blob: 07c75a04829ac7b697349a3ee335986af514ea4c [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 Holtmann96f14742015-03-14 19:27:57 -070099 MGMT_OP_READ_EXT_INDEX_LIST,
Marcel Holtmannd3d53052015-03-14 20:53:25 -0700100 MGMT_OP_READ_ADV_FEATURES,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200101};
102
103static const u16 mgmt_events[] = {
104 MGMT_EV_CONTROLLER_ERROR,
105 MGMT_EV_INDEX_ADDED,
106 MGMT_EV_INDEX_REMOVED,
107 MGMT_EV_NEW_SETTINGS,
108 MGMT_EV_CLASS_OF_DEV_CHANGED,
109 MGMT_EV_LOCAL_NAME_CHANGED,
110 MGMT_EV_NEW_LINK_KEY,
111 MGMT_EV_NEW_LONG_TERM_KEY,
112 MGMT_EV_DEVICE_CONNECTED,
113 MGMT_EV_DEVICE_DISCONNECTED,
114 MGMT_EV_CONNECT_FAILED,
115 MGMT_EV_PIN_CODE_REQUEST,
116 MGMT_EV_USER_CONFIRM_REQUEST,
117 MGMT_EV_USER_PASSKEY_REQUEST,
118 MGMT_EV_AUTH_FAILED,
119 MGMT_EV_DEVICE_FOUND,
120 MGMT_EV_DISCOVERING,
121 MGMT_EV_DEVICE_BLOCKED,
122 MGMT_EV_DEVICE_UNBLOCKED,
123 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300124 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800125 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700126 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200127 MGMT_EV_DEVICE_ADDED,
128 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300129 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200130 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd3896b2014-07-02 21:30:55 +0200131 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200132 MGMT_EV_NEW_CONFIG_OPTIONS,
Marcel Holtmannced85542015-03-14 19:27:56 -0700133 MGMT_EV_EXT_INDEX_ADDED,
134 MGMT_EV_EXT_INDEX_REMOVED,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200135};
136
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800137#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200138
Johan Hedbergd25b78e2015-01-27 12:55:52 +0200139#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
140 "\x00\x00\x00\x00\x00\x00\x00\x00"
141
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200142struct mgmt_pending_cmd {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200143 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200144 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200145 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100146 void *param;
Johan Hedberg323b0b82014-12-05 13:36:01 +0200147 size_t param_len;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200148 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300149 void *user_data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200150 int (*cmd_complete)(struct mgmt_pending_cmd *cmd, u8 status);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200151};
152
Johan Hedbergca69b792011-11-11 18:10:00 +0200153/* HCI to MGMT error code conversion table */
154static u8 mgmt_status_table[] = {
155 MGMT_STATUS_SUCCESS,
156 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
157 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
158 MGMT_STATUS_FAILED, /* Hardware Failure */
159 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
160 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200161 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200162 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
163 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
164 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
165 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
166 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
167 MGMT_STATUS_BUSY, /* Command Disallowed */
168 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
169 MGMT_STATUS_REJECTED, /* Rejected Security */
170 MGMT_STATUS_REJECTED, /* Rejected Personal */
171 MGMT_STATUS_TIMEOUT, /* Host Timeout */
172 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
173 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
174 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
175 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
176 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
177 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
178 MGMT_STATUS_BUSY, /* Repeated Attempts */
179 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
180 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
181 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
182 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
183 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
184 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
185 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
186 MGMT_STATUS_FAILED, /* Unspecified Error */
187 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
188 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
189 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
190 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
191 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
192 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
193 MGMT_STATUS_FAILED, /* Unit Link Key Used */
194 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
195 MGMT_STATUS_TIMEOUT, /* Instant Passed */
196 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
197 MGMT_STATUS_FAILED, /* Transaction Collision */
198 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
199 MGMT_STATUS_REJECTED, /* QoS Rejected */
200 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
201 MGMT_STATUS_REJECTED, /* Insufficient Security */
202 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
203 MGMT_STATUS_BUSY, /* Role Switch Pending */
204 MGMT_STATUS_FAILED, /* Slot Violation */
205 MGMT_STATUS_FAILED, /* Role Switch Failed */
206 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
207 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
208 MGMT_STATUS_BUSY, /* Host Busy Pairing */
209 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
210 MGMT_STATUS_BUSY, /* Controller Busy */
211 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
212 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
213 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
214 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
215 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
216};
217
218static u8 mgmt_status(u8 hci_status)
219{
220 if (hci_status < ARRAY_SIZE(mgmt_status_table))
221 return mgmt_status_table[hci_status];
222
223 return MGMT_STATUS_FAILED;
224}
225
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200226static int mgmt_send_event(u16 event, struct hci_dev *hdev,
227 unsigned short channel, void *data, u16 data_len,
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700228 int flag, struct sock *skip_sk)
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200229{
230 struct sk_buff *skb;
231 struct mgmt_hdr *hdr;
232
233 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
234 if (!skb)
235 return -ENOMEM;
236
237 hdr = (void *) skb_put(skb, sizeof(*hdr));
238 hdr->opcode = cpu_to_le16(event);
239 if (hdev)
240 hdr->index = cpu_to_le16(hdev->id);
241 else
242 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
243 hdr->len = cpu_to_le16(data_len);
244
245 if (data)
246 memcpy(skb_put(skb, data_len), data, data_len);
247
248 /* Time stamp */
249 __net_timestamp(skb);
250
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700251 hci_send_to_channel(channel, skb, flag, skip_sk);
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200252 kfree_skb(skb);
253
254 return 0;
255}
256
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700257static int mgmt_index_event(u16 event, struct hci_dev *hdev, void *data,
258 u16 len, int flag)
Marcel Holtmannf9207332015-03-14 19:27:55 -0700259{
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700260 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
261 flag, NULL);
Marcel Holtmannf9207332015-03-14 19:27:55 -0700262}
263
Marcel Holtmannf6b77122015-03-14 19:28:05 -0700264static int mgmt_generic_event(u16 event, struct hci_dev *hdev, void *data,
265 u16 len, struct sock *skip_sk)
266{
267 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
268 HCI_MGMT_GENERIC_EVENTS, skip_sk);
269}
270
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200271static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 len,
272 struct sock *skip_sk)
273{
274 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700275 HCI_SOCK_TRUSTED, skip_sk);
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200276}
277
Johan Hedberga69e8372015-03-06 21:08:53 +0200278static int mgmt_cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200279{
280 struct sk_buff *skb;
281 struct mgmt_hdr *hdr;
282 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300283 int err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200284
Szymon Janc34eb5252011-02-28 14:10:08 +0100285 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200286
Andre Guedes790eff42012-06-07 19:05:46 -0300287 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200288 if (!skb)
289 return -ENOMEM;
290
291 hdr = (void *) skb_put(skb, sizeof(*hdr));
292
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700293 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100294 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200295 hdr->len = cpu_to_le16(sizeof(*ev));
296
297 ev = (void *) skb_put(skb, sizeof(*ev));
298 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200299 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200300
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300301 err = sock_queue_rcv_skb(sk, skb);
302 if (err < 0)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200303 kfree_skb(skb);
304
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300305 return err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200306}
307
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200308static int mgmt_cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
309 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200310{
311 struct sk_buff *skb;
312 struct mgmt_hdr *hdr;
313 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300314 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200315
316 BT_DBG("sock %p", sk);
317
Andre Guedes790eff42012-06-07 19:05:46 -0300318 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200319 if (!skb)
320 return -ENOMEM;
321
322 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200323
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700324 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100325 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200326 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200327
Johan Hedberga38528f2011-01-22 06:46:43 +0200328 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200329 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b212012-02-18 15:07:59 +0200330 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100331
332 if (rp)
333 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200334
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300335 err = sock_queue_rcv_skb(sk, skb);
336 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200337 kfree_skb(skb);
338
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100339 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200340}
341
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300342static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
343 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200344{
345 struct mgmt_rp_read_version rp;
346
347 BT_DBG("sock %p", sk);
348
349 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700350 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200351
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200352 return mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0,
353 &rp, sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200354}
355
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300356static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
357 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200358{
359 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200360 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
361 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200362 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200363 size_t rp_size;
364 int i, err;
365
366 BT_DBG("sock %p", sk);
367
368 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
369
370 rp = kmalloc(rp_size, GFP_KERNEL);
371 if (!rp)
372 return -ENOMEM;
373
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700374 rp->num_commands = cpu_to_le16(num_commands);
375 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200376
377 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
378 put_unaligned_le16(mgmt_commands[i], opcode);
379
380 for (i = 0; i < num_events; i++, opcode++)
381 put_unaligned_le16(mgmt_events[i], opcode);
382
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200383 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0,
384 rp, rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200385 kfree(rp);
386
387 return err;
388}
389
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300390static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
391 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200392{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200393 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200394 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200395 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200396 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300397 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200398
399 BT_DBG("sock %p", sk);
400
401 read_lock(&hci_dev_list_lock);
402
403 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300404 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200405 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700406 !hci_dev_test_flag(d, HCI_UNCONFIGURED))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700407 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200408 }
409
Johan Hedberga38528f2011-01-22 06:46:43 +0200410 rp_len = sizeof(*rp) + (2 * count);
411 rp = kmalloc(rp_len, GFP_ATOMIC);
412 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100413 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200414 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100415 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200416
Johan Hedberg476e44c2012-10-19 20:10:46 +0300417 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200418 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700419 if (hci_dev_test_flag(d, HCI_SETUP) ||
420 hci_dev_test_flag(d, HCI_CONFIG) ||
421 hci_dev_test_flag(d, HCI_USER_CHANNEL))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200422 continue;
423
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200424 /* Devices marked as raw-only are neither configured
425 * nor unconfigured controllers.
426 */
427 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700428 continue;
429
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200430 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700431 !hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700432 rp->index[count++] = cpu_to_le16(d->id);
433 BT_DBG("Added hci%u", d->id);
434 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200435 }
436
Johan Hedberg476e44c2012-10-19 20:10:46 +0300437 rp->num_controllers = cpu_to_le16(count);
438 rp_len = sizeof(*rp) + (2 * count);
439
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200440 read_unlock(&hci_dev_list_lock);
441
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200442 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST,
443 0, rp, rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200444
Johan Hedberga38528f2011-01-22 06:46:43 +0200445 kfree(rp);
446
447 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200448}
449
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200450static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
451 void *data, u16 data_len)
452{
453 struct mgmt_rp_read_unconf_index_list *rp;
454 struct hci_dev *d;
455 size_t rp_len;
456 u16 count;
457 int err;
458
459 BT_DBG("sock %p", sk);
460
461 read_lock(&hci_dev_list_lock);
462
463 count = 0;
464 list_for_each_entry(d, &hci_dev_list, list) {
465 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700466 hci_dev_test_flag(d, HCI_UNCONFIGURED))
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200467 count++;
468 }
469
470 rp_len = sizeof(*rp) + (2 * count);
471 rp = kmalloc(rp_len, GFP_ATOMIC);
472 if (!rp) {
473 read_unlock(&hci_dev_list_lock);
474 return -ENOMEM;
475 }
476
477 count = 0;
478 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700479 if (hci_dev_test_flag(d, HCI_SETUP) ||
480 hci_dev_test_flag(d, HCI_CONFIG) ||
481 hci_dev_test_flag(d, HCI_USER_CHANNEL))
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200482 continue;
483
484 /* Devices marked as raw-only are neither configured
485 * nor unconfigured controllers.
486 */
487 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
488 continue;
489
490 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700491 hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200492 rp->index[count++] = cpu_to_le16(d->id);
493 BT_DBG("Added hci%u", d->id);
494 }
495 }
496
497 rp->num_controllers = cpu_to_le16(count);
498 rp_len = sizeof(*rp) + (2 * count);
499
500 read_unlock(&hci_dev_list_lock);
501
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200502 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
503 MGMT_OP_READ_UNCONF_INDEX_LIST, 0, rp, rp_len);
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200504
505 kfree(rp);
506
507 return err;
508}
509
Marcel Holtmann96f14742015-03-14 19:27:57 -0700510static int read_ext_index_list(struct sock *sk, struct hci_dev *hdev,
511 void *data, u16 data_len)
512{
513 struct mgmt_rp_read_ext_index_list *rp;
514 struct hci_dev *d;
515 size_t rp_len;
516 u16 count;
517 int err;
518
519 BT_DBG("sock %p", sk);
520
521 read_lock(&hci_dev_list_lock);
522
523 count = 0;
524 list_for_each_entry(d, &hci_dev_list, list) {
525 if (d->dev_type == HCI_BREDR || d->dev_type == HCI_AMP)
526 count++;
527 }
528
529 rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count);
530 rp = kmalloc(rp_len, GFP_ATOMIC);
531 if (!rp) {
532 read_unlock(&hci_dev_list_lock);
533 return -ENOMEM;
534 }
535
536 count = 0;
537 list_for_each_entry(d, &hci_dev_list, list) {
538 if (hci_dev_test_flag(d, HCI_SETUP) ||
539 hci_dev_test_flag(d, HCI_CONFIG) ||
540 hci_dev_test_flag(d, HCI_USER_CHANNEL))
541 continue;
542
543 /* Devices marked as raw-only are neither configured
544 * nor unconfigured controllers.
545 */
546 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
547 continue;
548
549 if (d->dev_type == HCI_BREDR) {
550 if (hci_dev_test_flag(d, HCI_UNCONFIGURED))
551 rp->entry[count].type = 0x01;
552 else
553 rp->entry[count].type = 0x00;
554 } else if (d->dev_type == HCI_AMP) {
555 rp->entry[count].type = 0x02;
556 } else {
557 continue;
558 }
559
560 rp->entry[count].bus = d->bus;
561 rp->entry[count++].index = cpu_to_le16(d->id);
562 BT_DBG("Added hci%u", d->id);
563 }
564
565 rp->num_controllers = cpu_to_le16(count);
566 rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count);
567
568 read_unlock(&hci_dev_list_lock);
569
570 /* If this command is called at least once, then all the
571 * default index and unconfigured index events are disabled
572 * and from now on only extended index events are used.
573 */
574 hci_sock_set_flag(sk, HCI_MGMT_EXT_INDEX_EVENTS);
575 hci_sock_clear_flag(sk, HCI_MGMT_INDEX_EVENTS);
576 hci_sock_clear_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS);
577
578 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
579 MGMT_OP_READ_EXT_INDEX_LIST, 0, rp, rp_len);
580
581 kfree(rp);
582
583 return err;
584}
585
Marcel Holtmanndbece372014-07-04 18:11:55 +0200586static bool is_configured(struct hci_dev *hdev)
587{
588 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700589 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanndbece372014-07-04 18:11:55 +0200590 return false;
591
592 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
593 !bacmp(&hdev->public_addr, BDADDR_ANY))
594 return false;
595
596 return true;
597}
598
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200599static __le32 get_missing_options(struct hci_dev *hdev)
600{
601 u32 options = 0;
602
Marcel Holtmanndbece372014-07-04 18:11:55 +0200603 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700604 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200605 options |= MGMT_OPTION_EXTERNAL_CONFIG;
606
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200607 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
608 !bacmp(&hdev->public_addr, BDADDR_ANY))
609 options |= MGMT_OPTION_PUBLIC_ADDRESS;
610
611 return cpu_to_le32(options);
612}
613
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200614static int new_options(struct hci_dev *hdev, struct sock *skip)
615{
616 __le32 options = get_missing_options(hdev);
617
Marcel Holtmannf6b77122015-03-14 19:28:05 -0700618 return mgmt_generic_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
619 sizeof(options), skip);
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200620}
621
Marcel Holtmanndbece372014-07-04 18:11:55 +0200622static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
623{
624 __le32 options = get_missing_options(hdev);
625
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200626 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &options,
627 sizeof(options));
Marcel Holtmanndbece372014-07-04 18:11:55 +0200628}
629
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200630static int read_config_info(struct sock *sk, struct hci_dev *hdev,
631 void *data, u16 data_len)
632{
633 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200634 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200635
636 BT_DBG("sock %p %s", sk, hdev->name);
637
638 hci_dev_lock(hdev);
639
640 memset(&rp, 0, sizeof(rp));
641 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200642
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200643 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
644 options |= MGMT_OPTION_EXTERNAL_CONFIG;
645
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200646 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200647 options |= MGMT_OPTION_PUBLIC_ADDRESS;
648
649 rp.supported_options = cpu_to_le32(options);
650 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200651
652 hci_dev_unlock(hdev);
653
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200654 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0,
655 &rp, sizeof(rp));
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200656}
657
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200658static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200659{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200660 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200661
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200662 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300663 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800664 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300665 settings |= MGMT_SETTING_CONNECTABLE;
666 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200667
Andre Guedesed3fa312012-07-24 15:03:46 -0300668 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500669 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
670 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200671 settings |= MGMT_SETTING_BREDR;
672 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700673
674 if (lmp_ssp_capable(hdev)) {
675 settings |= MGMT_SETTING_SSP;
676 settings |= MGMT_SETTING_HS;
677 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800678
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -0800679 if (lmp_sc_capable(hdev))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800680 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700681 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100682
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300683 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200684 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300685 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300686 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200687 settings |= MGMT_SETTING_PRIVACY;
Marcel Holtmann93690c22015-03-06 10:11:21 -0800688 settings |= MGMT_SETTING_STATIC_ADDRESS;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300689 }
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200690
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200691 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
692 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200693 settings |= MGMT_SETTING_CONFIGURATION;
694
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200695 return settings;
696}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200697
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200698static u32 get_current_settings(struct hci_dev *hdev)
699{
700 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200701
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200702 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100703 settings |= MGMT_SETTING_POWERED;
704
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700705 if (hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200706 settings |= MGMT_SETTING_CONNECTABLE;
707
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700708 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500709 settings |= MGMT_SETTING_FAST_CONNECTABLE;
710
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700711 if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200712 settings |= MGMT_SETTING_DISCOVERABLE;
713
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700714 if (hci_dev_test_flag(hdev, HCI_BONDABLE))
Johan Hedbergb2939472014-07-30 09:22:23 +0300715 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200716
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700717 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200718 settings |= MGMT_SETTING_BREDR;
719
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700720 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200721 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200722
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700723 if (hci_dev_test_flag(hdev, HCI_LINK_SECURITY))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200724 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200725
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700726 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200727 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200728
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700729 if (hci_dev_test_flag(hdev, HCI_HS_ENABLED))
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200730 settings |= MGMT_SETTING_HS;
731
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700732 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300733 settings |= MGMT_SETTING_ADVERTISING;
734
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700735 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800736 settings |= MGMT_SETTING_SECURE_CONN;
737
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700738 if (hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800739 settings |= MGMT_SETTING_DEBUG_KEYS;
740
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700741 if (hci_dev_test_flag(hdev, HCI_PRIVACY))
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200742 settings |= MGMT_SETTING_PRIVACY;
743
Marcel Holtmann93690c22015-03-06 10:11:21 -0800744 /* The current setting for static address has two purposes. The
745 * first is to indicate if the static address will be used and
746 * the second is to indicate if it is actually set.
747 *
748 * This means if the static address is not configured, this flag
749 * will never bet set. If the address is configured, then if the
750 * address is actually used decides if the flag is set or not.
751 *
752 * For single mode LE only controllers and dual-mode controllers
753 * with BR/EDR disabled, the existence of the static address will
754 * be evaluated.
755 */
Marcel Holtmannb7cb93e2015-03-13 10:20:35 -0700756 if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700757 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Marcel Holtmann93690c22015-03-06 10:11:21 -0800758 !bacmp(&hdev->bdaddr, BDADDR_ANY)) {
759 if (bacmp(&hdev->static_addr, BDADDR_ANY))
760 settings |= MGMT_SETTING_STATIC_ADDRESS;
761 }
762
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200763 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200764}
765
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300766#define PNP_INFO_SVCLASS_ID 0x1200
767
Johan Hedberg213202e2013-01-27 00:31:33 +0200768static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
769{
770 u8 *ptr = data, *uuids_start = NULL;
771 struct bt_uuid *uuid;
772
773 if (len < 4)
774 return ptr;
775
776 list_for_each_entry(uuid, &hdev->uuids, list) {
777 u16 uuid16;
778
779 if (uuid->size != 16)
780 continue;
781
782 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
783 if (uuid16 < 0x1100)
784 continue;
785
786 if (uuid16 == PNP_INFO_SVCLASS_ID)
787 continue;
788
789 if (!uuids_start) {
790 uuids_start = ptr;
791 uuids_start[0] = 1;
792 uuids_start[1] = EIR_UUID16_ALL;
793 ptr += 2;
794 }
795
796 /* Stop if not enough space to put next UUID */
797 if ((ptr - data) + sizeof(u16) > len) {
798 uuids_start[1] = EIR_UUID16_SOME;
799 break;
800 }
801
802 *ptr++ = (uuid16 & 0x00ff);
803 *ptr++ = (uuid16 & 0xff00) >> 8;
804 uuids_start[0] += sizeof(uuid16);
805 }
806
807 return ptr;
808}
809
Johan Hedbergcdf19632013-01-27 00:31:34 +0200810static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
811{
812 u8 *ptr = data, *uuids_start = NULL;
813 struct bt_uuid *uuid;
814
815 if (len < 6)
816 return ptr;
817
818 list_for_each_entry(uuid, &hdev->uuids, list) {
819 if (uuid->size != 32)
820 continue;
821
822 if (!uuids_start) {
823 uuids_start = ptr;
824 uuids_start[0] = 1;
825 uuids_start[1] = EIR_UUID32_ALL;
826 ptr += 2;
827 }
828
829 /* Stop if not enough space to put next UUID */
830 if ((ptr - data) + sizeof(u32) > len) {
831 uuids_start[1] = EIR_UUID32_SOME;
832 break;
833 }
834
835 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
836 ptr += sizeof(u32);
837 uuids_start[0] += sizeof(u32);
838 }
839
840 return ptr;
841}
842
Johan Hedbergc00d5752013-01-27 00:31:35 +0200843static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
844{
845 u8 *ptr = data, *uuids_start = NULL;
846 struct bt_uuid *uuid;
847
848 if (len < 18)
849 return ptr;
850
851 list_for_each_entry(uuid, &hdev->uuids, list) {
852 if (uuid->size != 128)
853 continue;
854
855 if (!uuids_start) {
856 uuids_start = ptr;
857 uuids_start[0] = 1;
858 uuids_start[1] = EIR_UUID128_ALL;
859 ptr += 2;
860 }
861
862 /* Stop if not enough space to put next UUID */
863 if ((ptr - data) + 16 > len) {
864 uuids_start[1] = EIR_UUID128_SOME;
865 break;
866 }
867
868 memcpy(ptr, uuid->uuid, 16);
869 ptr += 16;
870 uuids_start[0] += 16;
871 }
872
873 return ptr;
874}
875
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200876static struct mgmt_pending_cmd *mgmt_pending_find(u16 opcode,
877 struct hci_dev *hdev)
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300878{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200879 struct mgmt_pending_cmd *cmd;
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300880
881 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
882 if (cmd->opcode == opcode)
883 return cmd;
884 }
885
886 return NULL;
887}
888
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200889static struct mgmt_pending_cmd *mgmt_pending_find_data(u16 opcode,
890 struct hci_dev *hdev,
891 const void *data)
Johan Hedberg95868422014-06-28 17:54:07 +0300892{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200893 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +0300894
895 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
896 if (cmd->user_data != data)
897 continue;
898 if (cmd->opcode == opcode)
899 return cmd;
900 }
901
902 return NULL;
903}
904
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700905static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
906{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700907 u8 ad_len = 0;
908 size_t name_len;
909
910 name_len = strlen(hdev->dev_name);
911 if (name_len > 0) {
912 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
913
914 if (name_len > max_len) {
915 name_len = max_len;
916 ptr[1] = EIR_NAME_SHORT;
917 } else
918 ptr[1] = EIR_NAME_COMPLETE;
919
920 ptr[0] = name_len + 1;
921
922 memcpy(ptr + 2, hdev->dev_name, name_len);
923
924 ad_len += (name_len + 2);
925 ptr += (name_len + 2);
926 }
927
928 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700929}
930
931static void update_scan_rsp_data(struct hci_request *req)
932{
933 struct hci_dev *hdev = req->hdev;
934 struct hci_cp_le_set_scan_rsp_data cp;
935 u8 len;
936
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700937 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700938 return;
939
940 memset(&cp, 0, sizeof(cp));
941
942 len = create_scan_rsp_data(hdev, cp.data);
943
Johan Hedbergeb438b52013-10-16 15:31:07 +0300944 if (hdev->scan_rsp_data_len == len &&
945 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700946 return;
947
Johan Hedbergeb438b52013-10-16 15:31:07 +0300948 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
949 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700950
951 cp.length = len;
952
953 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
954}
955
Johan Hedberg9a43e252013-10-20 19:00:07 +0300956static u8 get_adv_discov_flags(struct hci_dev *hdev)
957{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200958 struct mgmt_pending_cmd *cmd;
Johan Hedberg9a43e252013-10-20 19:00:07 +0300959
960 /* If there's a pending mgmt command the flags will not yet have
961 * their final values, so check for this first.
962 */
963 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
964 if (cmd) {
965 struct mgmt_mode *cp = cmd->param;
966 if (cp->val == 0x01)
967 return LE_AD_GENERAL;
968 else if (cp->val == 0x02)
969 return LE_AD_LIMITED;
970 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700971 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300972 return LE_AD_LIMITED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700973 else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300974 return LE_AD_GENERAL;
975 }
976
977 return 0;
978}
979
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700980static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700981{
982 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700983
Johan Hedberg9a43e252013-10-20 19:00:07 +0300984 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700985
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700986 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700987 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700988
989 if (flags) {
990 BT_DBG("adv flags 0x%02x", flags);
991
992 ptr[0] = 2;
993 ptr[1] = EIR_FLAGS;
994 ptr[2] = flags;
995
996 ad_len += 3;
997 ptr += 3;
998 }
999
1000 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
1001 ptr[0] = 2;
1002 ptr[1] = EIR_TX_POWER;
1003 ptr[2] = (u8) hdev->adv_tx_power;
1004
1005 ad_len += 3;
1006 ptr += 3;
1007 }
1008
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001009 return ad_len;
1010}
1011
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07001012static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001013{
1014 struct hci_dev *hdev = req->hdev;
1015 struct hci_cp_le_set_adv_data cp;
1016 u8 len;
1017
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001018 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001019 return;
1020
1021 memset(&cp, 0, sizeof(cp));
1022
Marcel Holtmann46cad2e2013-10-16 00:16:46 -07001023 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001024
1025 if (hdev->adv_data_len == len &&
1026 memcmp(cp.data, hdev->adv_data, len) == 0)
1027 return;
1028
1029 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
1030 hdev->adv_data_len = len;
1031
1032 cp.length = len;
1033
1034 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
1035}
1036
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001037int mgmt_update_adv_data(struct hci_dev *hdev)
1038{
1039 struct hci_request req;
1040
1041 hci_req_init(&req, hdev);
1042 update_adv_data(&req);
1043
1044 return hci_req_run(&req, NULL);
1045}
1046
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001047static void create_eir(struct hci_dev *hdev, u8 *data)
1048{
1049 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001050 size_t name_len;
1051
1052 name_len = strlen(hdev->dev_name);
1053
1054 if (name_len > 0) {
1055 /* EIR Data type */
1056 if (name_len > 48) {
1057 name_len = 48;
1058 ptr[1] = EIR_NAME_SHORT;
1059 } else
1060 ptr[1] = EIR_NAME_COMPLETE;
1061
1062 /* EIR Data length */
1063 ptr[0] = name_len + 1;
1064
1065 memcpy(ptr + 2, hdev->dev_name, name_len);
1066
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001067 ptr += (name_len + 2);
1068 }
1069
Johan Hedbergbbaf4442012-11-08 01:22:59 +01001070 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001071 ptr[0] = 2;
1072 ptr[1] = EIR_TX_POWER;
1073 ptr[2] = (u8) hdev->inq_tx_power;
1074
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001075 ptr += 3;
1076 }
1077
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001078 if (hdev->devid_source > 0) {
1079 ptr[0] = 9;
1080 ptr[1] = EIR_DEVICE_ID;
1081
1082 put_unaligned_le16(hdev->devid_source, ptr + 2);
1083 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
1084 put_unaligned_le16(hdev->devid_product, ptr + 6);
1085 put_unaligned_le16(hdev->devid_version, ptr + 8);
1086
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001087 ptr += 10;
1088 }
1089
Johan Hedberg213202e2013-01-27 00:31:33 +02001090 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +02001091 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +02001092 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001093}
1094
Johan Hedberg890ea892013-03-15 17:06:52 -05001095static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001096{
Johan Hedberg890ea892013-03-15 17:06:52 -05001097 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001098 struct hci_cp_write_eir cp;
1099
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001100 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001101 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001102
Johan Hedberg976eb202012-10-24 21:12:01 +03001103 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001104 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001105
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001106 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg890ea892013-03-15 17:06:52 -05001107 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001108
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001109 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001110 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001111
1112 memset(&cp, 0, sizeof(cp));
1113
1114 create_eir(hdev, cp.data);
1115
1116 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001117 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001118
1119 memcpy(hdev->eir, cp.data, sizeof(cp.data));
1120
Johan Hedberg890ea892013-03-15 17:06:52 -05001121 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001122}
1123
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001124static u8 get_service_classes(struct hci_dev *hdev)
1125{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001126 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001127 u8 val = 0;
1128
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001129 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001130 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001131
1132 return val;
1133}
1134
Johan Hedberg890ea892013-03-15 17:06:52 -05001135static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001136{
Johan Hedberg890ea892013-03-15 17:06:52 -05001137 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001138 u8 cod[3];
1139
1140 BT_DBG("%s", hdev->name);
1141
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001142 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001143 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001144
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001145 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001146 return;
1147
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001148 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001149 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001150
1151 cod[0] = hdev->minor_class;
1152 cod[1] = hdev->major_class;
1153 cod[2] = get_service_classes(hdev);
1154
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001155 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001156 cod[1] |= 0x20;
1157
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001158 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001159 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001160
Johan Hedberg890ea892013-03-15 17:06:52 -05001161 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001162}
1163
Johan Hedberga4858cb2014-02-25 19:56:31 +02001164static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001165{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001166 struct mgmt_pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001167
1168 /* If there's a pending mgmt command the flag will not yet have
1169 * it's final value, so check for this first.
1170 */
1171 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1172 if (cmd) {
1173 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001174 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001175 }
1176
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001177 return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001178}
1179
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001180static void disable_advertising(struct hci_request *req)
1181{
1182 u8 enable = 0x00;
1183
1184 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1185}
1186
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001187static void enable_advertising(struct hci_request *req)
1188{
1189 struct hci_dev *hdev = req->hdev;
1190 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001191 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001192 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001193
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001194 if (hci_conn_num(hdev, LE_LINK) > 0)
1195 return;
1196
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001197 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001198 disable_advertising(req);
1199
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001200 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001201 * hci_update_random_address knows that it's safe to go ahead
1202 * and write a new random address. The flag will be set back on
1203 * as soon as the SET_ADV_ENABLE HCI command completes.
1204 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001205 hci_dev_clear_flag(hdev, HCI_LE_ADV);
Johan Hedberg8d972502014-02-28 12:54:14 +02001206
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001207 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE))
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07001208 connectable = true;
1209 else
1210 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001211
Johan Hedberga4858cb2014-02-25 19:56:31 +02001212 /* Set require_privacy to true only when non-connectable
1213 * advertising is used. In that case it is fine to use a
1214 * non-resolvable private address.
1215 */
1216 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001217 return;
1218
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001219 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001220 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1221 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001222 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001223 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001224 cp.channel_map = hdev->le_adv_channel_map;
1225
1226 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1227
1228 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1229}
1230
Johan Hedberg7d785252011-12-15 00:47:39 +02001231static void service_cache_off(struct work_struct *work)
1232{
1233 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001234 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001235 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001236
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001237 if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg7d785252011-12-15 00:47:39 +02001238 return;
1239
Johan Hedberg890ea892013-03-15 17:06:52 -05001240 hci_req_init(&req, hdev);
1241
Johan Hedberg7d785252011-12-15 00:47:39 +02001242 hci_dev_lock(hdev);
1243
Johan Hedberg890ea892013-03-15 17:06:52 -05001244 update_eir(&req);
1245 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001246
1247 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001248
1249 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001250}
1251
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001252static void rpa_expired(struct work_struct *work)
1253{
1254 struct hci_dev *hdev = container_of(work, struct hci_dev,
1255 rpa_expired.work);
1256 struct hci_request req;
1257
1258 BT_DBG("");
1259
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001260 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001261
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001262 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001263 return;
1264
1265 /* The generation of a new RPA and programming it into the
1266 * controller happens in the enable_advertising() function.
1267 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001268 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001269 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001270 hci_req_run(&req, NULL);
1271}
1272
Johan Hedberg6a919082012-02-28 06:17:26 +02001273static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001274{
Marcel Holtmann238be782015-03-13 02:11:06 -07001275 if (hci_dev_test_and_set_flag(hdev, HCI_MGMT))
Johan Hedberg6a919082012-02-28 06:17:26 +02001276 return;
1277
Johan Hedberg4f87da82012-03-02 19:55:56 +02001278 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001279 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001280
Johan Hedberg4f87da82012-03-02 19:55:56 +02001281 /* Non-mgmt controlled devices get this bit set
1282 * implicitly so that pairing works for them, however
1283 * for mgmt we require user-space to explicitly enable
1284 * it
1285 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001286 hci_dev_clear_flag(hdev, HCI_BONDABLE);
Johan Hedberg7d785252011-12-15 00:47:39 +02001287}
1288
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001289static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001290 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001291{
1292 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001293
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001294 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001295
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001296 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001297
Johan Hedberg03811012010-12-08 00:21:06 +02001298 memset(&rp, 0, sizeof(rp));
1299
Johan Hedberg03811012010-12-08 00:21:06 +02001300 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001301
1302 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001303 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001304
1305 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1306 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1307
1308 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001309
1310 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001311 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001312
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001313 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001314
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001315 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
1316 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001317}
1318
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001319static void mgmt_pending_free(struct mgmt_pending_cmd *cmd)
Johan Hedberg03811012010-12-08 00:21:06 +02001320{
1321 sock_put(cmd->sk);
1322 kfree(cmd->param);
1323 kfree(cmd);
1324}
1325
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001326static struct mgmt_pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
1327 struct hci_dev *hdev,
1328 void *data, u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001329{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001330 struct mgmt_pending_cmd *cmd;
Johan Hedberg03811012010-12-08 00:21:06 +02001331
Johan Hedbergfca20012014-06-28 17:54:05 +03001332 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001333 if (!cmd)
1334 return NULL;
1335
1336 cmd->opcode = opcode;
1337 cmd->index = hdev->id;
1338
Johan Hedberg323b0b82014-12-05 13:36:01 +02001339 cmd->param = kmemdup(data, len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001340 if (!cmd->param) {
1341 kfree(cmd);
1342 return NULL;
1343 }
1344
Johan Hedberg323b0b82014-12-05 13:36:01 +02001345 cmd->param_len = len;
Johan Hedberg03811012010-12-08 00:21:06 +02001346
1347 cmd->sk = sk;
1348 sock_hold(sk);
1349
1350 list_add(&cmd->list, &hdev->mgmt_pending);
1351
1352 return cmd;
1353}
1354
1355static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001356 void (*cb)(struct mgmt_pending_cmd *cmd,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001357 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001358 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001359{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001360 struct mgmt_pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001361
Andre Guedesa3d09352013-02-01 11:21:30 -03001362 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001363 if (opcode > 0 && cmd->opcode != opcode)
1364 continue;
1365
1366 cb(cmd, data);
1367 }
1368}
1369
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001370static void mgmt_pending_remove(struct mgmt_pending_cmd *cmd)
Johan Hedberg03811012010-12-08 00:21:06 +02001371{
1372 list_del(&cmd->list);
1373 mgmt_pending_free(cmd);
1374}
1375
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001376static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001377{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001378 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001379
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001380 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
1381 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001382}
1383
Marcel Holtmann1904a852015-01-11 13:50:44 -08001384static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001385{
1386 BT_DBG("%s status 0x%02x", hdev->name, status);
1387
Johan Hedberga3172b72014-02-28 09:33:44 +02001388 if (hci_conn_count(hdev) == 0) {
1389 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001390 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001391 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001392}
1393
Johan Hedberg23a48092014-07-08 16:05:06 +03001394static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001395{
1396 struct hci_dev *hdev = req->hdev;
1397 struct hci_cp_remote_name_req_cancel cp;
1398 struct inquiry_entry *e;
1399
1400 switch (hdev->discovery.state) {
1401 case DISCOVERY_FINDING:
1402 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1403 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1404 } else {
1405 cancel_delayed_work(&hdev->le_scan_disable);
1406 hci_req_add_le_scan_disable(req);
1407 }
1408
Johan Hedberg23a48092014-07-08 16:05:06 +03001409 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001410
1411 case DISCOVERY_RESOLVING:
1412 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1413 NAME_PENDING);
1414 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001415 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001416
1417 bacpy(&cp.bdaddr, &e->data.bdaddr);
1418 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1419 &cp);
1420
Johan Hedberg23a48092014-07-08 16:05:06 +03001421 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001422
1423 default:
1424 /* Passive scanning */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001425 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001426 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001427 return true;
1428 }
1429
Johan Hedberg21a60d32014-06-10 14:05:58 +03001430 break;
1431 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001432
1433 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001434}
1435
Johan Hedberg8b064a32014-02-24 14:52:22 +02001436static int clean_up_hci_state(struct hci_dev *hdev)
1437{
1438 struct hci_request req;
1439 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001440 bool discov_stopped;
1441 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001442
1443 hci_req_init(&req, hdev);
1444
1445 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1446 test_bit(HCI_PSCAN, &hdev->flags)) {
1447 u8 scan = 0x00;
1448 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1449 }
1450
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001451 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001452 disable_advertising(&req);
1453
Johan Hedberg23a48092014-07-08 16:05:06 +03001454 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001455
1456 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1457 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001458 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001459
Johan Hedbergc9910d02014-02-27 14:35:12 +02001460 switch (conn->state) {
1461 case BT_CONNECTED:
1462 case BT_CONFIG:
1463 dc.handle = cpu_to_le16(conn->handle);
1464 dc.reason = 0x15; /* Terminated due to Power Off */
1465 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1466 break;
1467 case BT_CONNECT:
1468 if (conn->type == LE_LINK)
1469 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1470 0, NULL);
1471 else if (conn->type == ACL_LINK)
1472 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1473 6, &conn->dst);
1474 break;
1475 case BT_CONNECT2:
1476 bacpy(&rej.bdaddr, &conn->dst);
1477 rej.reason = 0x15; /* Terminated due to Power Off */
1478 if (conn->type == ACL_LINK)
1479 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1480 sizeof(rej), &rej);
1481 else if (conn->type == SCO_LINK)
1482 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1483 sizeof(rej), &rej);
1484 break;
1485 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001486 }
1487
Johan Hedberg23a48092014-07-08 16:05:06 +03001488 err = hci_req_run(&req, clean_up_hci_complete);
1489 if (!err && discov_stopped)
1490 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1491
1492 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001493}
1494
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001495static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001496 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001497{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001498 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001499 struct mgmt_pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001500 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001501
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001502 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001503
Johan Hedberga7e80f22013-01-09 16:05:19 +02001504 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001505 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1506 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001507
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001508 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001509
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001510 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001511 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1512 MGMT_STATUS_BUSY);
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001513 goto failed;
1514 }
1515
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001516 if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001517 cancel_delayed_work(&hdev->power_off);
1518
1519 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001520 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1521 data, len);
1522 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001523 goto failed;
1524 }
1525 }
1526
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001527 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001528 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001529 goto failed;
1530 }
1531
Johan Hedberg03811012010-12-08 00:21:06 +02001532 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1533 if (!cmd) {
1534 err = -ENOMEM;
1535 goto failed;
1536 }
1537
Johan Hedberg8b064a32014-02-24 14:52:22 +02001538 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001539 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001540 err = 0;
1541 } else {
1542 /* Disconnect connections, stop scans, etc */
1543 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001544 if (!err)
1545 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1546 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001547
Johan Hedberg8b064a32014-02-24 14:52:22 +02001548 /* ENODATA means there were no HCI commands queued */
1549 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001550 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001551 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1552 err = 0;
1553 }
1554 }
Johan Hedberg03811012010-12-08 00:21:06 +02001555
1556failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001557 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001558 return err;
1559}
1560
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001561static int new_settings(struct hci_dev *hdev, struct sock *skip)
1562{
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001563 __le32 ev = cpu_to_le32(get_current_settings(hdev));
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001564
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001565 return mgmt_generic_event(MGMT_EV_NEW_SETTINGS, hdev, &ev,
1566 sizeof(ev), skip);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001567}
1568
Johan Hedberg91a668b2014-07-09 13:28:26 +03001569int mgmt_new_settings(struct hci_dev *hdev)
1570{
1571 return new_settings(hdev, NULL);
1572}
1573
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001574struct cmd_lookup {
1575 struct sock *sk;
1576 struct hci_dev *hdev;
1577 u8 mgmt_status;
1578};
1579
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001580static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001581{
1582 struct cmd_lookup *match = data;
1583
1584 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1585
1586 list_del(&cmd->list);
1587
1588 if (match->sk == NULL) {
1589 match->sk = cmd->sk;
1590 sock_hold(match->sk);
1591 }
1592
1593 mgmt_pending_free(cmd);
1594}
1595
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001596static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001597{
1598 u8 *status = data;
1599
Johan Hedberga69e8372015-03-06 21:08:53 +02001600 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001601 mgmt_pending_remove(cmd);
1602}
1603
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001604static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001605{
1606 if (cmd->cmd_complete) {
1607 u8 *status = data;
1608
1609 cmd->cmd_complete(cmd, *status);
1610 mgmt_pending_remove(cmd);
1611
1612 return;
1613 }
1614
1615 cmd_status_rsp(cmd, data);
1616}
1617
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001618static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001619{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001620 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1621 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001622}
1623
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001624static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001625{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001626 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1627 cmd->param, sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001628}
1629
Johan Hedberge6fe7982013-10-02 15:45:22 +03001630static u8 mgmt_bredr_support(struct hci_dev *hdev)
1631{
1632 if (!lmp_bredr_capable(hdev))
1633 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001634 else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001635 return MGMT_STATUS_REJECTED;
1636 else
1637 return MGMT_STATUS_SUCCESS;
1638}
1639
1640static u8 mgmt_le_support(struct hci_dev *hdev)
1641{
1642 if (!lmp_le_capable(hdev))
1643 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001644 else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001645 return MGMT_STATUS_REJECTED;
1646 else
1647 return MGMT_STATUS_SUCCESS;
1648}
1649
Marcel Holtmann1904a852015-01-11 13:50:44 -08001650static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1651 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001652{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001653 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001654 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001655 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001656 bool changed;
1657
1658 BT_DBG("status 0x%02x", status);
1659
1660 hci_dev_lock(hdev);
1661
1662 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1663 if (!cmd)
1664 goto unlock;
1665
1666 if (status) {
1667 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001668 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001669 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001670 goto remove_cmd;
1671 }
1672
1673 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001674 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001675 changed = !hci_dev_test_and_set_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001676
1677 if (hdev->discov_timeout > 0) {
1678 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1679 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1680 to);
1681 }
1682 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001683 changed = hci_dev_test_and_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001684 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001685
1686 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1687
1688 if (changed)
1689 new_settings(hdev, cmd->sk);
1690
Marcel Holtmann970ba522013-10-15 06:33:57 -07001691 /* When the discoverable mode gets changed, make sure
1692 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001693 * bit correctly set. Also update page scan based on whitelist
1694 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001695 */
1696 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001697 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001698 update_class(&req);
1699 hci_req_run(&req, NULL);
1700
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001701remove_cmd:
1702 mgmt_pending_remove(cmd);
1703
1704unlock:
1705 hci_dev_unlock(hdev);
1706}
1707
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001708static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001709 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001710{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001711 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001712 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001713 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001714 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001715 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001716 int err;
Johan Hedberge41d8b42010-12-13 21:07:03 +02001717
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001718 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001719
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001720 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1721 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001722 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1723 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001724
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001725 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02001726 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1727 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001728
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001729 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001730
1731 /* Disabling discoverable requires that no timeout is set,
1732 * and enabling limited discoverable requires a timeout.
1733 */
1734 if ((cp->val == 0x00 && timeout > 0) ||
1735 (cp->val == 0x02 && timeout == 0))
Johan Hedberga69e8372015-03-06 21:08:53 +02001736 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1737 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001738
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001739 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001740
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001741 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001742 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1743 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001744 goto failed;
1745 }
1746
1747 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001748 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001749 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1750 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001751 goto failed;
1752 }
1753
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001754 if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001755 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1756 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001757 goto failed;
1758 }
1759
1760 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001761 bool changed = false;
1762
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001763 /* Setting limited discoverable when powered off is
1764 * not a valid operation since it requires a timeout
1765 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1766 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001767 if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07001768 hci_dev_change_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001769 changed = true;
1770 }
1771
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001772 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001773 if (err < 0)
1774 goto failed;
1775
1776 if (changed)
1777 err = new_settings(hdev, sk);
1778
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001779 goto failed;
1780 }
1781
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001782 /* If the current mode is the same, then just update the timeout
1783 * value with the new value. And if only the timeout gets updated,
1784 * then no need for any HCI transactions.
1785 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001786 if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
1787 (cp->val == 0x02) == hci_dev_test_flag(hdev,
1788 HCI_LIMITED_DISCOVERABLE)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001789 cancel_delayed_work(&hdev->discov_off);
1790 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001791
Marcel Holtmann36261542013-10-15 08:28:51 -07001792 if (cp->val && hdev->discov_timeout > 0) {
1793 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001794 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001795 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001796 }
1797
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001798 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001799 goto failed;
1800 }
1801
1802 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1803 if (!cmd) {
1804 err = -ENOMEM;
1805 goto failed;
1806 }
1807
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001808 /* Cancel any potential discoverable timeout that might be
1809 * still active and store new timeout value. The arming of
1810 * the timeout happens in the complete handler.
1811 */
1812 cancel_delayed_work(&hdev->discov_off);
1813 hdev->discov_timeout = timeout;
1814
Johan Hedbergb456f872013-10-19 23:38:22 +03001815 /* Limited discoverable mode */
1816 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001817 hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001818 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001819 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001820
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001821 hci_req_init(&req, hdev);
1822
Johan Hedberg9a43e252013-10-20 19:00:07 +03001823 /* The procedure for LE-only controllers is much simpler - just
1824 * update the advertising data.
1825 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001826 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg9a43e252013-10-20 19:00:07 +03001827 goto update_ad;
1828
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001829 scan = SCAN_PAGE;
1830
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001831 if (cp->val) {
1832 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001833
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001834 if (cp->val == 0x02) {
1835 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001836 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001837 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1838 hci_cp.iac_lap[1] = 0x8b;
1839 hci_cp.iac_lap[2] = 0x9e;
1840 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1841 hci_cp.iac_lap[4] = 0x8b;
1842 hci_cp.iac_lap[5] = 0x9e;
1843 } else {
1844 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001845 hci_cp.num_iac = 1;
1846 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1847 hci_cp.iac_lap[1] = 0x8b;
1848 hci_cp.iac_lap[2] = 0x9e;
1849 }
1850
1851 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1852 (hci_cp.num_iac * 3) + 1, &hci_cp);
1853
1854 scan |= SCAN_INQUIRY;
1855 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001856 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001857 }
1858
1859 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001860
Johan Hedberg9a43e252013-10-20 19:00:07 +03001861update_ad:
1862 update_adv_data(&req);
1863
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001864 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001865 if (err < 0)
1866 mgmt_pending_remove(cmd);
1867
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001868failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001869 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001870 return err;
1871}
1872
Johan Hedberg406d7802013-03-15 17:07:09 -05001873static void write_fast_connectable(struct hci_request *req, bool enable)
1874{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001875 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001876 struct hci_cp_write_page_scan_activity acp;
1877 u8 type;
1878
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001879 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg547003b2013-10-21 16:51:53 +03001880 return;
1881
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001882 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1883 return;
1884
Johan Hedberg406d7802013-03-15 17:07:09 -05001885 if (enable) {
1886 type = PAGE_SCAN_TYPE_INTERLACED;
1887
1888 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001889 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001890 } else {
1891 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1892
1893 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001894 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001895 }
1896
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001897 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001898
Johan Hedbergbd98b992013-03-15 17:07:13 -05001899 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1900 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1901 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1902 sizeof(acp), &acp);
1903
1904 if (hdev->page_scan_type != type)
1905 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001906}
1907
Marcel Holtmann1904a852015-01-11 13:50:44 -08001908static void set_connectable_complete(struct hci_dev *hdev, u8 status,
1909 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05001910{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001911 struct mgmt_pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001912 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001913 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001914
1915 BT_DBG("status 0x%02x", status);
1916
1917 hci_dev_lock(hdev);
1918
1919 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1920 if (!cmd)
1921 goto unlock;
1922
Johan Hedberg37438c12013-10-14 16:20:05 +03001923 if (status) {
1924 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001925 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg37438c12013-10-14 16:20:05 +03001926 goto remove_cmd;
1927 }
1928
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001929 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001930 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001931 conn_changed = !hci_dev_test_and_set_flag(hdev,
1932 HCI_CONNECTABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001933 discov_changed = false;
1934 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001935 conn_changed = hci_dev_test_and_clear_flag(hdev,
1936 HCI_CONNECTABLE);
1937 discov_changed = hci_dev_test_and_clear_flag(hdev,
1938 HCI_DISCOVERABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001939 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001940
Johan Hedberg2b76f452013-03-15 17:07:04 -05001941 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1942
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001943 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001944 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001945 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001946 if (discov_changed)
1947 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001948 hci_update_background_scan(hdev);
1949 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001950
Johan Hedberg37438c12013-10-14 16:20:05 +03001951remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001952 mgmt_pending_remove(cmd);
1953
1954unlock:
1955 hci_dev_unlock(hdev);
1956}
1957
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001958static int set_connectable_update_settings(struct hci_dev *hdev,
1959 struct sock *sk, u8 val)
1960{
1961 bool changed = false;
1962 int err;
1963
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001964 if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001965 changed = true;
1966
1967 if (val) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001968 hci_dev_set_flag(hdev, HCI_CONNECTABLE);
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001969 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001970 hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
1971 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001972 }
1973
1974 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1975 if (err < 0)
1976 return err;
1977
Johan Hedberg562064e2014-07-08 16:35:34 +03001978 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001979 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03001980 hci_update_background_scan(hdev);
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001981 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001982 }
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001983
1984 return 0;
1985}
1986
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001987static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001988 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001989{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001990 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001991 struct mgmt_pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001992 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001993 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001994 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001995
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001996 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001997
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001998 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1999 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002000 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2001 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002002
Johan Hedberga7e80f22013-01-09 16:05:19 +02002003 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002004 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2005 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002006
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002007 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002008
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002009 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03002010 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002011 goto failed;
2012 }
2013
2014 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002015 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002016 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2017 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002018 goto failed;
2019 }
2020
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002021 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
2022 if (!cmd) {
2023 err = -ENOMEM;
2024 goto failed;
2025 }
2026
Johan Hedberg2b76f452013-03-15 17:07:04 -05002027 hci_req_init(&req, hdev);
2028
Johan Hedberg9a43e252013-10-20 19:00:07 +03002029 /* If BR/EDR is not enabled and we disable advertising as a
2030 * by-product of disabling connectable, we need to update the
2031 * advertising flags.
2032 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002033 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg9a43e252013-10-20 19:00:07 +03002034 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002035 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
2036 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg9a43e252013-10-20 19:00:07 +03002037 }
2038 update_adv_data(&req);
2039 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03002040 if (cp->val) {
2041 scan = SCAN_PAGE;
2042 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03002043 /* If we don't have any whitelist entries just
2044 * disable all scanning. If there are entries
2045 * and we had both page and inquiry scanning
2046 * enabled then fall back to only page scanning.
2047 * Otherwise no changes are needed.
2048 */
2049 if (list_empty(&hdev->whitelist))
2050 scan = SCAN_DISABLED;
2051 else if (test_bit(HCI_ISCAN, &hdev->flags))
2052 scan = SCAN_PAGE;
2053 else
2054 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03002055
2056 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07002057 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03002058 cancel_delayed_work(&hdev->discov_off);
2059 }
2060
2061 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
2062 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05002063
Johan Hedberg3bd27242014-07-28 20:53:58 +03002064no_scan_update:
Johan Hedberge8b12022014-07-10 10:51:27 +03002065 /* Update the advertising parameters if necessary */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002066 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002067 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002068
Johan Hedberg2b76f452013-03-15 17:07:04 -05002069 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03002070 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002071 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03002072 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03002073 err = set_connectable_update_settings(hdev, sk,
2074 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03002075 goto failed;
2076 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002077
2078failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002079 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002080 return err;
2081}
2082
Johan Hedbergb2939472014-07-30 09:22:23 +03002083static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002084 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02002085{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002086 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07002087 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002088 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002089
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002090 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002091
Johan Hedberga7e80f22013-01-09 16:05:19 +02002092 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002093 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2094 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002095
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002096 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002097
2098 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07002099 changed = !hci_dev_test_and_set_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002100 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002101 changed = hci_dev_test_and_clear_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002102
Johan Hedbergb2939472014-07-30 09:22:23 +03002103 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002104 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002105 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002106
Marcel Holtmann55594352013-10-06 16:11:57 -07002107 if (changed)
2108 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002109
Marcel Holtmann55594352013-10-06 16:11:57 -07002110unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002111 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002112 return err;
2113}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002114
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002115static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2116 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002117{
2118 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002119 struct mgmt_pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002120 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002121 int err;
2122
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002123 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002124
Johan Hedberge6fe7982013-10-02 15:45:22 +03002125 status = mgmt_bredr_support(hdev);
2126 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002127 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2128 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002129
Johan Hedberga7e80f22013-01-09 16:05:19 +02002130 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002131 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2132 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002133
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002134 hci_dev_lock(hdev);
2135
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002136 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002137 bool changed = false;
2138
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002139 if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002140 hci_dev_change_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02002141 changed = true;
2142 }
2143
2144 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2145 if (err < 0)
2146 goto failed;
2147
2148 if (changed)
2149 err = new_settings(hdev, sk);
2150
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002151 goto failed;
2152 }
2153
2154 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002155 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2156 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002157 goto failed;
2158 }
2159
2160 val = !!cp->val;
2161
2162 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2163 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2164 goto failed;
2165 }
2166
2167 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2168 if (!cmd) {
2169 err = -ENOMEM;
2170 goto failed;
2171 }
2172
2173 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2174 if (err < 0) {
2175 mgmt_pending_remove(cmd);
2176 goto failed;
2177 }
2178
2179failed:
2180 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002181 return err;
2182}
2183
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002184static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002185{
2186 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002187 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002188 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002189 int err;
2190
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002191 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002192
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002193 status = mgmt_bredr_support(hdev);
2194 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002195 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002196
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002197 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002198 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2199 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002200
Johan Hedberga7e80f22013-01-09 16:05:19 +02002201 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002202 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2203 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002204
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002205 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002206
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002207 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002208 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002209
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002210 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002211 changed = !hci_dev_test_and_set_flag(hdev,
2212 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002213 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002214 changed = hci_dev_test_and_clear_flag(hdev,
2215 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002216 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002217 changed = hci_dev_test_and_clear_flag(hdev,
2218 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002219 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002220 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002221 }
2222
2223 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2224 if (err < 0)
2225 goto failed;
2226
2227 if (changed)
2228 err = new_settings(hdev, sk);
2229
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002230 goto failed;
2231 }
2232
Johan Hedberg94d52da2015-02-19 17:38:06 +02002233 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002234 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2235 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002236 goto failed;
2237 }
2238
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002239 if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002240 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2241 goto failed;
2242 }
2243
2244 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2245 if (!cmd) {
2246 err = -ENOMEM;
2247 goto failed;
2248 }
2249
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002250 if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03002251 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2252 sizeof(cp->val), &cp->val);
2253
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002254 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002255 if (err < 0) {
2256 mgmt_pending_remove(cmd);
2257 goto failed;
2258 }
2259
2260failed:
2261 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002262 return err;
2263}
2264
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002265static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002266{
2267 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002268 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002269 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002270 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002271
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002272 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002273
Johan Hedberge6fe7982013-10-02 15:45:22 +03002274 status = mgmt_bredr_support(hdev);
2275 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002276 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002277
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002278 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002279 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2280 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002281
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002282 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002283 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2284 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002285
Johan Hedberga7e80f22013-01-09 16:05:19 +02002286 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002287 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2288 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002289
Marcel Holtmannee392692013-10-01 22:59:23 -07002290 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002291
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002292 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002293 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2294 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002295 goto unlock;
2296 }
2297
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002298 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002299 changed = !hci_dev_test_and_set_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002300 } else {
2301 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002302 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2303 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002304 goto unlock;
2305 }
2306
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002307 changed = hci_dev_test_and_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002308 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002309
2310 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2311 if (err < 0)
2312 goto unlock;
2313
2314 if (changed)
2315 err = new_settings(hdev, sk);
2316
2317unlock:
2318 hci_dev_unlock(hdev);
2319 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002320}
2321
Marcel Holtmann1904a852015-01-11 13:50:44 -08002322static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002323{
2324 struct cmd_lookup match = { NULL, hdev };
2325
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302326 hci_dev_lock(hdev);
2327
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002328 if (status) {
2329 u8 mgmt_err = mgmt_status(status);
2330
2331 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2332 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302333 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002334 }
2335
2336 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2337
2338 new_settings(hdev, match.sk);
2339
2340 if (match.sk)
2341 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002342
2343 /* Make sure the controller has a good default for
2344 * advertising data. Restrict the update to when LE
2345 * has actually been enabled. During power on, the
2346 * update in powered_update_hci will take care of it.
2347 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002348 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002349 struct hci_request req;
2350
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002351 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002352 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002353 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002354 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002355 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002356 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302357
2358unlock:
2359 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002360}
2361
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002362static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002363{
2364 struct mgmt_mode *cp = data;
2365 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002366 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002367 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002368 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002369 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002370
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002371 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002372
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002373 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002374 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2375 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002376
Johan Hedberga7e80f22013-01-09 16:05:19 +02002377 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002378 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2379 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002380
Johan Hedbergc73eee92013-04-19 18:35:21 +03002381 /* LE-only devices do not allow toggling LE on/off */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002382 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002383 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2384 MGMT_STATUS_REJECTED);
Johan Hedbergc73eee92013-04-19 18:35:21 +03002385
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002386 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002387
2388 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002389 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002390
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002391 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002392 bool changed = false;
2393
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002394 if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002395 hci_dev_change_flag(hdev, HCI_LE_ENABLED);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002396 changed = true;
2397 }
2398
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002399 if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002400 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002401 changed = true;
2402 }
2403
Johan Hedberg06199cf2012-02-22 16:37:11 +02002404 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2405 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002406 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002407
2408 if (changed)
2409 err = new_settings(hdev, sk);
2410
Johan Hedberg1de028c2012-02-29 19:55:35 -08002411 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002412 }
2413
Johan Hedberg4375f102013-09-25 13:26:10 +03002414 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2415 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002416 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2417 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002418 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002419 }
2420
2421 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2422 if (!cmd) {
2423 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002424 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002425 }
2426
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002427 hci_req_init(&req, hdev);
2428
Johan Hedberg06199cf2012-02-22 16:37:11 +02002429 memset(&hci_cp, 0, sizeof(hci_cp));
2430
2431 if (val) {
2432 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002433 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002434 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002435 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002436 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002437 }
2438
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002439 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2440 &hci_cp);
2441
2442 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302443 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002444 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002445
Johan Hedberg1de028c2012-02-29 19:55:35 -08002446unlock:
2447 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002448 return err;
2449}
2450
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002451/* This is a helper function to test for pending mgmt commands that can
2452 * cause CoD or EIR HCI commands. We can only allow one such pending
2453 * mgmt command at a time since otherwise we cannot easily track what
2454 * the current values are, will be, and based on that calculate if a new
2455 * HCI command needs to be sent and if yes with what value.
2456 */
2457static bool pending_eir_or_class(struct hci_dev *hdev)
2458{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002459 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002460
2461 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2462 switch (cmd->opcode) {
2463 case MGMT_OP_ADD_UUID:
2464 case MGMT_OP_REMOVE_UUID:
2465 case MGMT_OP_SET_DEV_CLASS:
2466 case MGMT_OP_SET_POWERED:
2467 return true;
2468 }
2469 }
2470
2471 return false;
2472}
2473
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002474static const u8 bluetooth_base_uuid[] = {
2475 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2476 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2477};
2478
2479static u8 get_uuid_size(const u8 *uuid)
2480{
2481 u32 val;
2482
2483 if (memcmp(uuid, bluetooth_base_uuid, 12))
2484 return 128;
2485
2486 val = get_unaligned_le32(&uuid[12]);
2487 if (val > 0xffff)
2488 return 32;
2489
2490 return 16;
2491}
2492
Johan Hedberg92da6092013-03-15 17:06:55 -05002493static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2494{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002495 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002496
2497 hci_dev_lock(hdev);
2498
2499 cmd = mgmt_pending_find(mgmt_op, hdev);
2500 if (!cmd)
2501 goto unlock;
2502
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002503 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2504 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002505
2506 mgmt_pending_remove(cmd);
2507
2508unlock:
2509 hci_dev_unlock(hdev);
2510}
2511
Marcel Holtmann1904a852015-01-11 13:50:44 -08002512static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002513{
2514 BT_DBG("status 0x%02x", status);
2515
2516 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2517}
2518
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002519static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002520{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002521 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002522 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002523 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002524 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002525 int err;
2526
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002527 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002528
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002529 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002530
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002531 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002532 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2533 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002534 goto failed;
2535 }
2536
Andre Guedes92c4c202012-06-07 19:05:44 -03002537 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002538 if (!uuid) {
2539 err = -ENOMEM;
2540 goto failed;
2541 }
2542
2543 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002544 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002545 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002546
Johan Hedbergde66aa62013-01-27 00:31:27 +02002547 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002548
Johan Hedberg890ea892013-03-15 17:06:52 -05002549 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002550
Johan Hedberg890ea892013-03-15 17:06:52 -05002551 update_class(&req);
2552 update_eir(&req);
2553
Johan Hedberg92da6092013-03-15 17:06:55 -05002554 err = hci_req_run(&req, add_uuid_complete);
2555 if (err < 0) {
2556 if (err != -ENODATA)
2557 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002558
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002559 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2560 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002561 goto failed;
2562 }
2563
2564 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002565 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002566 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002567 goto failed;
2568 }
2569
2570 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002571
2572failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002573 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002574 return err;
2575}
2576
Johan Hedberg24b78d02012-02-23 23:24:30 +02002577static bool enable_service_cache(struct hci_dev *hdev)
2578{
2579 if (!hdev_is_powered(hdev))
2580 return false;
2581
Marcel Holtmann238be782015-03-13 02:11:06 -07002582 if (!hci_dev_test_and_set_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002583 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2584 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002585 return true;
2586 }
2587
2588 return false;
2589}
2590
Marcel Holtmann1904a852015-01-11 13:50:44 -08002591static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002592{
2593 BT_DBG("status 0x%02x", status);
2594
2595 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2596}
2597
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002598static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002599 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002600{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002601 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002602 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002603 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002604 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 -05002605 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002606 int err, found;
2607
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002608 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002609
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002610 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002611
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002612 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002613 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2614 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002615 goto unlock;
2616 }
2617
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002618 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002619 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002620
Johan Hedberg24b78d02012-02-23 23:24:30 +02002621 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002622 err = mgmt_cmd_complete(sk, hdev->id,
2623 MGMT_OP_REMOVE_UUID,
2624 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002625 goto unlock;
2626 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002627
Johan Hedberg9246a862012-02-23 21:33:16 +02002628 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002629 }
2630
2631 found = 0;
2632
Johan Hedberg056341c2013-01-27 00:31:30 +02002633 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002634 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2635 continue;
2636
2637 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002638 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002639 found++;
2640 }
2641
2642 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002643 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2644 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002645 goto unlock;
2646 }
2647
Johan Hedberg9246a862012-02-23 21:33:16 +02002648update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002649 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002650
Johan Hedberg890ea892013-03-15 17:06:52 -05002651 update_class(&req);
2652 update_eir(&req);
2653
Johan Hedberg92da6092013-03-15 17:06:55 -05002654 err = hci_req_run(&req, remove_uuid_complete);
2655 if (err < 0) {
2656 if (err != -ENODATA)
2657 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002658
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002659 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2660 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002661 goto unlock;
2662 }
2663
2664 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002665 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002666 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002667 goto unlock;
2668 }
2669
2670 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002671
2672unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002673 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002674 return err;
2675}
2676
Marcel Holtmann1904a852015-01-11 13:50:44 -08002677static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002678{
2679 BT_DBG("status 0x%02x", status);
2680
2681 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2682}
2683
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002684static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002685 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002686{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002687 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002688 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002689 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002690 int err;
2691
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002692 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002693
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002694 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002695 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2696 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002697
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002698 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002699
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002700 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002701 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2702 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002703 goto unlock;
2704 }
2705
2706 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002707 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2708 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002709 goto unlock;
2710 }
2711
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002712 hdev->major_class = cp->major;
2713 hdev->minor_class = cp->minor;
2714
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002715 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002716 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2717 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002718 goto unlock;
2719 }
2720
Johan Hedberg890ea892013-03-15 17:06:52 -05002721 hci_req_init(&req, hdev);
2722
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002723 if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002724 hci_dev_unlock(hdev);
2725 cancel_delayed_work_sync(&hdev->service_cache);
2726 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002727 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002728 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002729
Johan Hedberg890ea892013-03-15 17:06:52 -05002730 update_class(&req);
2731
Johan Hedberg92da6092013-03-15 17:06:55 -05002732 err = hci_req_run(&req, set_class_complete);
2733 if (err < 0) {
2734 if (err != -ENODATA)
2735 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002736
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002737 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2738 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002739 goto unlock;
2740 }
2741
2742 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002743 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002744 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002745 goto unlock;
2746 }
2747
2748 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002749
Johan Hedbergb5235a62012-02-21 14:32:24 +02002750unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002751 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002752 return err;
2753}
2754
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002755static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002756 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002757{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002758 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002759 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2760 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002761 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002762 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002763 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002764
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002765 BT_DBG("request for %s", hdev->name);
2766
2767 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002768 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2769 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002770
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002771 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002772 if (key_count > max_key_count) {
2773 BT_ERR("load_link_keys: too big key_count value %u",
2774 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002775 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2776 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002777 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002778
Johan Hedberg86742e12011-11-07 23:13:38 +02002779 expected_len = sizeof(*cp) + key_count *
2780 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002781 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002782 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002783 expected_len, len);
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 Hedberg55ed8ca12011-01-17 14:41:05 +02002786 }
2787
Johan Hedberg4ae14302013-01-20 14:27:13 +02002788 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002789 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2790 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae14302013-01-20 14:27:13 +02002791
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002792 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002793 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002794
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002795 for (i = 0; i < key_count; i++) {
2796 struct mgmt_link_key_info *key = &cp->keys[i];
2797
Marcel Holtmann8e991132014-01-10 02:07:25 -08002798 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002799 return mgmt_cmd_status(sk, hdev->id,
2800 MGMT_OP_LOAD_LINK_KEYS,
2801 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002802 }
2803
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002804 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002805
2806 hci_link_keys_clear(hdev);
2807
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002808 if (cp->debug_keys)
Marcel Holtmann238be782015-03-13 02:11:06 -07002809 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002810 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002811 changed = hci_dev_test_and_clear_flag(hdev,
2812 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002813
2814 if (changed)
2815 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002816
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002817 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002818 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002819
Johan Hedberg58e92932014-06-24 14:00:26 +03002820 /* Always ignore debug keys and require a new pairing if
2821 * the user wants to use them.
2822 */
2823 if (key->type == HCI_LK_DEBUG_COMBINATION)
2824 continue;
2825
Johan Hedberg7652ff62014-06-24 13:15:49 +03002826 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2827 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002828 }
2829
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002830 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002831
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002832 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002833
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002834 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002835}
2836
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002837static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002838 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002839{
2840 struct mgmt_ev_device_unpaired ev;
2841
2842 bacpy(&ev.addr.bdaddr, bdaddr);
2843 ev.addr.type = addr_type;
2844
2845 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002846 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002847}
2848
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002849static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002850 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002851{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002852 struct mgmt_cp_unpair_device *cp = data;
2853 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002854 struct hci_cp_disconnect dc;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002855 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002856 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002857 int err;
2858
Johan Hedberga8a1d192011-11-10 15:54:38 +02002859 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002860 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2861 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002862
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002863 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002864 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2865 MGMT_STATUS_INVALID_PARAMS,
2866 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002867
Johan Hedberg118da702013-01-20 14:27:20 +02002868 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002869 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2870 MGMT_STATUS_INVALID_PARAMS,
2871 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02002872
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002873 hci_dev_lock(hdev);
2874
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002875 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002876 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2877 MGMT_STATUS_NOT_POWERED, &rp,
2878 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002879 goto unlock;
2880 }
2881
Johan Hedberge0b2b272014-02-18 17:14:31 +02002882 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002883 /* If disconnection is requested, then look up the
2884 * connection. If the remote device is connected, it
2885 * will be later used to terminate the link.
2886 *
2887 * Setting it to NULL explicitly will cause no
2888 * termination of the link.
2889 */
2890 if (cp->disconnect)
2891 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2892 &cp->addr.bdaddr);
2893 else
2894 conn = NULL;
2895
Johan Hedberg124f6e32012-02-09 13:50:12 +02002896 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002897 } else {
2898 u8 addr_type;
2899
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002900 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2901 &cp->addr.bdaddr);
2902 if (conn) {
2903 /* Defer clearing up the connection parameters
2904 * until closing to give a chance of keeping
2905 * them if a repairing happens.
2906 */
2907 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2908
2909 /* If disconnection is not requested, then
2910 * clear the connection variable so that the
2911 * link is not terminated.
2912 */
2913 if (!cp->disconnect)
2914 conn = NULL;
2915 }
2916
Johan Hedberge0b2b272014-02-18 17:14:31 +02002917 if (cp->addr.type == BDADDR_LE_PUBLIC)
2918 addr_type = ADDR_LE_DEV_PUBLIC;
2919 else
2920 addr_type = ADDR_LE_DEV_RANDOM;
2921
Johan Hedberga7ec7332014-02-18 17:14:35 +02002922 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2923
Johan Hedberge0b2b272014-02-18 17:14:31 +02002924 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2925 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002926
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002927 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002928 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2929 MGMT_STATUS_NOT_PAIRED, &rp,
2930 sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002931 goto unlock;
2932 }
2933
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002934 /* If the connection variable is set, then termination of the
2935 * link is requested.
2936 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002937 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002938 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
2939 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002940 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002941 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002942 }
2943
Johan Hedberg124f6e32012-02-09 13:50:12 +02002944 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002945 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002946 if (!cmd) {
2947 err = -ENOMEM;
2948 goto unlock;
2949 }
2950
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02002951 cmd->cmd_complete = addr_cmd_complete;
2952
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002953 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002954 dc.reason = 0x13; /* Remote User Terminated Connection */
2955 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2956 if (err < 0)
2957 mgmt_pending_remove(cmd);
2958
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002959unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002960 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002961 return err;
2962}
2963
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002964static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002965 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002966{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002967 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002968 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002969 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002970 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002971 int err;
2972
2973 BT_DBG("");
2974
Johan Hedberg06a63b12013-01-20 14:27:21 +02002975 memset(&rp, 0, sizeof(rp));
2976 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2977 rp.addr.type = cp->addr.type;
2978
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002979 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002980 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2981 MGMT_STATUS_INVALID_PARAMS,
2982 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002983
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002984 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002985
2986 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002987 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2988 MGMT_STATUS_NOT_POWERED, &rp,
2989 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002990 goto failed;
2991 }
2992
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002993 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002994 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2995 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002996 goto failed;
2997 }
2998
Andre Guedes591f47f2012-04-24 21:02:49 -03002999 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003000 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
3001 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02003002 else
3003 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03003004
Vishal Agarwalf9607272012-06-13 05:32:43 +05303005 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003006 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3007 MGMT_STATUS_NOT_CONNECTED, &rp,
3008 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003009 goto failed;
3010 }
3011
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003012 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003013 if (!cmd) {
3014 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003015 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003016 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02003017
Johan Hedbergf5818c22014-12-05 13:36:02 +02003018 cmd->cmd_complete = generic_cmd_complete;
3019
Johan Hedberge3f2f922014-08-18 20:33:33 +03003020 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003021 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003022 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003023
3024failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003025 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003026 return err;
3027}
3028
Andre Guedes57c14772012-04-24 21:02:50 -03003029static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003030{
3031 switch (link_type) {
3032 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02003033 switch (addr_type) {
3034 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03003035 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03003036
Johan Hedberg48264f02011-11-09 13:58:58 +02003037 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003038 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003039 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02003040 }
Andre Guedes0ed09142012-04-03 08:46:54 -03003041
Johan Hedberg4c659c32011-11-07 23:13:39 +02003042 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003043 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003044 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003045 }
3046}
3047
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003048static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
3049 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02003050{
Johan Hedberg2784eb42011-01-21 13:56:35 +02003051 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003052 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02003053 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003054 int err;
3055 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003056
3057 BT_DBG("");
3058
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003059 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003060
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003061 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003062 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
3063 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003064 goto unlock;
3065 }
3066
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003067 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02003068 list_for_each_entry(c, &hdev->conn_hash.list, list) {
3069 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003070 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003071 }
3072
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003073 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03003074 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02003075 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02003076 err = -ENOMEM;
3077 goto unlock;
3078 }
3079
Johan Hedberg2784eb42011-01-21 13:56:35 +02003080 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003081 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02003082 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
3083 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003084 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03003085 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03003086 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003087 continue;
3088 i++;
3089 }
3090
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003091 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003092
Johan Hedberg4c659c32011-11-07 23:13:39 +02003093 /* Recalculate length in case of filtered SCO connections, etc */
3094 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003095
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003096 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3097 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003098
Johan Hedberga38528f2011-01-22 06:46:43 +02003099 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003100
3101unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003102 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003103 return err;
3104}
3105
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003106static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003107 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003108{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003109 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003110 int err;
3111
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003112 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003113 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003114 if (!cmd)
3115 return -ENOMEM;
3116
Johan Hedbergd8457692012-02-17 14:24:57 +02003117 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003118 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003119 if (err < 0)
3120 mgmt_pending_remove(cmd);
3121
3122 return err;
3123}
3124
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003125static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003126 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003127{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003128 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003129 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003130 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003131 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003132 int err;
3133
3134 BT_DBG("");
3135
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003136 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003137
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003138 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003139 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3140 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003141 goto failed;
3142 }
3143
Johan Hedbergd8457692012-02-17 14:24:57 +02003144 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003145 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003146 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3147 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003148 goto failed;
3149 }
3150
3151 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003152 struct mgmt_cp_pin_code_neg_reply ncp;
3153
3154 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003155
3156 BT_ERR("PIN code is not 16 bytes long");
3157
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003158 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003159 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003160 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3161 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003162
3163 goto failed;
3164 }
3165
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003166 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003167 if (!cmd) {
3168 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003169 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003170 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003171
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003172 cmd->cmd_complete = addr_cmd_complete;
3173
Johan Hedbergd8457692012-02-17 14:24:57 +02003174 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003175 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003176 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003177
3178 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3179 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003180 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003181
3182failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003183 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003184 return err;
3185}
3186
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003187static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3188 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003189{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003190 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003191
3192 BT_DBG("");
3193
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003194 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003195 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3196 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003197
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003198 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003199
3200 hdev->io_capability = cp->io_capability;
3201
3202 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003203 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003204
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003205 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003206
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003207 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3208 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003209}
3210
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003211static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003212{
3213 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003214 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003215
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003216 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003217 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3218 continue;
3219
Johan Hedberge9a416b2011-02-19 12:05:56 -03003220 if (cmd->user_data != conn)
3221 continue;
3222
3223 return cmd;
3224 }
3225
3226 return NULL;
3227}
3228
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003229static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003230{
3231 struct mgmt_rp_pair_device rp;
3232 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003233 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003234
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003235 bacpy(&rp.addr.bdaddr, &conn->dst);
3236 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003237
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003238 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3239 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003240
3241 /* So we don't get further callbacks for this connection */
3242 conn->connect_cfm_cb = NULL;
3243 conn->security_cfm_cb = NULL;
3244 conn->disconn_cfm_cb = NULL;
3245
David Herrmann76a68ba2013-04-06 20:28:37 +02003246 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003247
3248 /* The device is paired so there is no need to remove
3249 * its connection parameters anymore.
3250 */
3251 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003252
3253 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003254
3255 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003256}
3257
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003258void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3259{
3260 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003261 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003262
3263 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003264 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003265 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003266 mgmt_pending_remove(cmd);
3267 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003268}
3269
Johan Hedberge9a416b2011-02-19 12:05:56 -03003270static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3271{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003272 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003273
3274 BT_DBG("status %u", status);
3275
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003276 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003277 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003278 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003279 return;
3280 }
3281
3282 cmd->cmd_complete(cmd, mgmt_status(status));
3283 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003284}
3285
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003286static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303287{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003288 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303289
3290 BT_DBG("status %u", status);
3291
3292 if (!status)
3293 return;
3294
3295 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003296 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303297 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003298 return;
3299 }
3300
3301 cmd->cmd_complete(cmd, mgmt_status(status));
3302 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303303}
3304
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003305static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003306 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003307{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003308 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003309 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003310 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003311 u8 sec_level, auth_type;
3312 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003313 int err;
3314
3315 BT_DBG("");
3316
Szymon Jancf950a30e2013-01-18 12:48:07 +01003317 memset(&rp, 0, sizeof(rp));
3318 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3319 rp.addr.type = cp->addr.type;
3320
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003321 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003322 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3323 MGMT_STATUS_INVALID_PARAMS,
3324 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003325
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003326 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003327 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3328 MGMT_STATUS_INVALID_PARAMS,
3329 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003330
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003331 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003332
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003333 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003334 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3335 MGMT_STATUS_NOT_POWERED, &rp,
3336 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003337 goto unlock;
3338 }
3339
Johan Hedberg55e76b32015-03-10 22:34:40 +02003340 if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
3341 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3342 MGMT_STATUS_ALREADY_PAIRED, &rp,
3343 sizeof(rp));
3344 goto unlock;
3345 }
3346
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003347 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003348 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003349
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003350 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003351 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3352 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003353 } else {
3354 u8 addr_type;
3355
3356 /* Convert from L2CAP channel address type to HCI address type
3357 */
3358 if (cp->addr.type == BDADDR_LE_PUBLIC)
3359 addr_type = ADDR_LE_DEV_PUBLIC;
3360 else
3361 addr_type = ADDR_LE_DEV_RANDOM;
3362
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003363 /* When pairing a new device, it is expected to remember
3364 * this device for future connections. Adding the connection
3365 * parameter information ahead of time allows tracking
3366 * of the slave preferred values and will speed up any
3367 * further connection establishment.
3368 *
3369 * If connection parameters already exist, then they
3370 * will be kept and this function does nothing.
3371 */
3372 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3373
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003374 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003375 sec_level, HCI_LE_CONN_TIMEOUT,
3376 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003377 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003378
Ville Tervo30e76272011-02-22 16:10:53 -03003379 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003380 int status;
3381
3382 if (PTR_ERR(conn) == -EBUSY)
3383 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003384 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3385 status = MGMT_STATUS_NOT_SUPPORTED;
3386 else if (PTR_ERR(conn) == -ECONNREFUSED)
3387 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003388 else
3389 status = MGMT_STATUS_CONNECT_FAILED;
3390
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003391 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3392 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003393 goto unlock;
3394 }
3395
3396 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003397 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003398 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3399 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003400 goto unlock;
3401 }
3402
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003403 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003404 if (!cmd) {
3405 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003406 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003407 goto unlock;
3408 }
3409
Johan Hedberg04ab2742014-12-05 13:36:04 +02003410 cmd->cmd_complete = pairing_complete;
3411
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003412 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003413 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003414 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003415 conn->security_cfm_cb = pairing_complete_cb;
3416 conn->disconn_cfm_cb = pairing_complete_cb;
3417 } else {
3418 conn->connect_cfm_cb = le_pairing_complete_cb;
3419 conn->security_cfm_cb = le_pairing_complete_cb;
3420 conn->disconn_cfm_cb = le_pairing_complete_cb;
3421 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003422
Johan Hedberge9a416b2011-02-19 12:05:56 -03003423 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003424 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003425
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003426 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003427 hci_conn_security(conn, sec_level, auth_type, true)) {
3428 cmd->cmd_complete(cmd, 0);
3429 mgmt_pending_remove(cmd);
3430 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003431
3432 err = 0;
3433
3434unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003435 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003436 return err;
3437}
3438
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003439static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3440 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003441{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003442 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003443 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003444 struct hci_conn *conn;
3445 int err;
3446
3447 BT_DBG("");
3448
Johan Hedberg28424702012-02-02 04:02:29 +02003449 hci_dev_lock(hdev);
3450
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003451 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003452 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3453 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003454 goto unlock;
3455 }
3456
Johan Hedberg28424702012-02-02 04:02:29 +02003457 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3458 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003459 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3460 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003461 goto unlock;
3462 }
3463
3464 conn = cmd->user_data;
3465
3466 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003467 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3468 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003469 goto unlock;
3470 }
3471
Johan Hedberga511b352014-12-11 21:45:45 +02003472 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3473 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003474
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003475 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3476 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003477unlock:
3478 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003479 return err;
3480}
3481
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003482static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003483 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003484 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003485{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003486 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003487 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003488 int err;
3489
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003490 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003491
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003492 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003493 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3494 MGMT_STATUS_NOT_POWERED, addr,
3495 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003496 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003497 }
3498
Johan Hedberg1707c602013-03-15 17:07:15 -05003499 if (addr->type == BDADDR_BREDR)
3500 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003501 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003502 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003503
Johan Hedberg272d90d2012-02-09 15:26:12 +02003504 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003505 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3506 MGMT_STATUS_NOT_CONNECTED, addr,
3507 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003508 goto done;
3509 }
3510
Johan Hedberg1707c602013-03-15 17:07:15 -05003511 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003512 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003513 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003514 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3515 MGMT_STATUS_SUCCESS, addr,
3516 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003517 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003518 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3519 MGMT_STATUS_FAILED, addr,
3520 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003521
Brian Gix47c15e22011-11-16 13:53:14 -08003522 goto done;
3523 }
3524
Johan Hedberg1707c602013-03-15 17:07:15 -05003525 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003526 if (!cmd) {
3527 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003528 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003529 }
3530
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003531 cmd->cmd_complete = addr_cmd_complete;
3532
Brian Gix0df4c182011-11-16 13:53:13 -08003533 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003534 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3535 struct hci_cp_user_passkey_reply cp;
3536
Johan Hedberg1707c602013-03-15 17:07:15 -05003537 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003538 cp.passkey = passkey;
3539 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3540 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003541 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3542 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003543
Johan Hedberga664b5b2011-02-19 12:06:02 -03003544 if (err < 0)
3545 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003546
Brian Gix0df4c182011-11-16 13:53:13 -08003547done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003548 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003549 return err;
3550}
3551
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303552static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3553 void *data, u16 len)
3554{
3555 struct mgmt_cp_pin_code_neg_reply *cp = data;
3556
3557 BT_DBG("");
3558
Johan Hedberg1707c602013-03-15 17:07:15 -05003559 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303560 MGMT_OP_PIN_CODE_NEG_REPLY,
3561 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3562}
3563
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003564static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3565 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003566{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003567 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003568
3569 BT_DBG("");
3570
3571 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003572 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3573 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003574
Johan Hedberg1707c602013-03-15 17:07:15 -05003575 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003576 MGMT_OP_USER_CONFIRM_REPLY,
3577 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003578}
3579
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003580static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003581 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003582{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003583 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003584
3585 BT_DBG("");
3586
Johan Hedberg1707c602013-03-15 17:07:15 -05003587 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003588 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3589 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003590}
3591
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003592static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3593 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003594{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003595 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003596
3597 BT_DBG("");
3598
Johan Hedberg1707c602013-03-15 17:07:15 -05003599 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003600 MGMT_OP_USER_PASSKEY_REPLY,
3601 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003602}
3603
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003604static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003605 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003606{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003607 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003608
3609 BT_DBG("");
3610
Johan Hedberg1707c602013-03-15 17:07:15 -05003611 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003612 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3613 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003614}
3615
Johan Hedberg13928972013-03-15 17:07:00 -05003616static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003617{
Johan Hedberg13928972013-03-15 17:07:00 -05003618 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003619 struct hci_cp_write_local_name cp;
3620
Johan Hedberg13928972013-03-15 17:07:00 -05003621 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003622
Johan Hedberg890ea892013-03-15 17:06:52 -05003623 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003624}
3625
Marcel Holtmann1904a852015-01-11 13:50:44 -08003626static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003627{
3628 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003629 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003630
3631 BT_DBG("status 0x%02x", status);
3632
3633 hci_dev_lock(hdev);
3634
3635 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3636 if (!cmd)
3637 goto unlock;
3638
3639 cp = cmd->param;
3640
3641 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003642 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3643 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003644 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003645 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3646 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003647
3648 mgmt_pending_remove(cmd);
3649
3650unlock:
3651 hci_dev_unlock(hdev);
3652}
3653
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003654static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003655 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003656{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003657 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003658 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003659 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003660 int err;
3661
3662 BT_DBG("");
3663
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003664 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003665
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003666 /* If the old values are the same as the new ones just return a
3667 * direct command complete event.
3668 */
3669 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3670 !memcmp(hdev->short_name, cp->short_name,
3671 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003672 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3673 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003674 goto failed;
3675 }
3676
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003677 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003678
Johan Hedbergb5235a62012-02-21 14:32:24 +02003679 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003680 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003681
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003682 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3683 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003684 if (err < 0)
3685 goto failed;
3686
Marcel Holtmannf6b77122015-03-14 19:28:05 -07003687 err = mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev,
3688 data, len, sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003689
Johan Hedbergb5235a62012-02-21 14:32:24 +02003690 goto failed;
3691 }
3692
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003693 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003694 if (!cmd) {
3695 err = -ENOMEM;
3696 goto failed;
3697 }
3698
Johan Hedberg13928972013-03-15 17:07:00 -05003699 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3700
Johan Hedberg890ea892013-03-15 17:06:52 -05003701 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003702
3703 if (lmp_bredr_capable(hdev)) {
3704 update_name(&req);
3705 update_eir(&req);
3706 }
3707
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003708 /* The name is stored in the scan response data and so
3709 * no need to udpate the advertising data here.
3710 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003711 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003712 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003713
Johan Hedberg13928972013-03-15 17:07:00 -05003714 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003715 if (err < 0)
3716 mgmt_pending_remove(cmd);
3717
3718failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003719 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003720 return err;
3721}
3722
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003723static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003724 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003725{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003726 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01003727 int err;
3728
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003729 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003730
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003731 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003732
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003733 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003734 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3735 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003736 goto unlock;
3737 }
3738
Andre Guedes9a1a1992012-07-24 15:03:48 -03003739 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003740 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3741 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003742 goto unlock;
3743 }
3744
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003745 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003746 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3747 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003748 goto unlock;
3749 }
3750
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003751 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003752 if (!cmd) {
3753 err = -ENOMEM;
3754 goto unlock;
3755 }
3756
Johan Hedberg710f11c2014-05-26 11:21:22 +03003757 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003758 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3759 0, NULL);
3760 else
3761 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3762
Szymon Jancc35938b2011-03-22 13:12:21 +01003763 if (err < 0)
3764 mgmt_pending_remove(cmd);
3765
3766unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003767 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003768 return err;
3769}
3770
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003771static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003772 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003773{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003774 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003775 int err;
3776
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003777 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003778
Johan Hedberg5d57e792015-01-23 10:10:38 +02003779 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003780 return mgmt_cmd_complete(sk, hdev->id,
3781 MGMT_OP_ADD_REMOTE_OOB_DATA,
3782 MGMT_STATUS_INVALID_PARAMS,
3783 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003784
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003785 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003786
Marcel Holtmannec109112014-01-10 02:07:30 -08003787 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3788 struct mgmt_cp_add_remote_oob_data *cp = data;
3789 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003790
Johan Hedbergc19a4952014-11-17 20:52:19 +02003791 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003792 err = mgmt_cmd_complete(sk, hdev->id,
3793 MGMT_OP_ADD_REMOTE_OOB_DATA,
3794 MGMT_STATUS_INVALID_PARAMS,
3795 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003796 goto unlock;
3797 }
3798
Marcel Holtmannec109112014-01-10 02:07:30 -08003799 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003800 cp->addr.type, cp->hash,
3801 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003802 if (err < 0)
3803 status = MGMT_STATUS_FAILED;
3804 else
3805 status = MGMT_STATUS_SUCCESS;
3806
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003807 err = mgmt_cmd_complete(sk, hdev->id,
3808 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
3809 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003810 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3811 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003812 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003813 u8 status;
3814
Johan Hedberg86df9202014-10-26 20:52:27 +01003815 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003816 /* Enforce zero-valued 192-bit parameters as
3817 * long as legacy SMP OOB isn't implemented.
3818 */
3819 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3820 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003821 err = mgmt_cmd_complete(sk, hdev->id,
3822 MGMT_OP_ADD_REMOTE_OOB_DATA,
3823 MGMT_STATUS_INVALID_PARAMS,
3824 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003825 goto unlock;
3826 }
3827
Johan Hedberg86df9202014-10-26 20:52:27 +01003828 rand192 = NULL;
3829 hash192 = NULL;
3830 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003831 /* In case one of the P-192 values is set to zero,
3832 * then just disable OOB data for P-192.
3833 */
3834 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3835 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3836 rand192 = NULL;
3837 hash192 = NULL;
3838 } else {
3839 rand192 = cp->rand192;
3840 hash192 = cp->hash192;
3841 }
3842 }
3843
3844 /* In case one of the P-256 values is set to zero, then just
3845 * disable OOB data for P-256.
3846 */
3847 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3848 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3849 rand256 = NULL;
3850 hash256 = NULL;
3851 } else {
3852 rand256 = cp->rand256;
3853 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003854 }
3855
Johan Hedberg81328d5c2014-10-26 20:33:47 +01003856 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003857 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003858 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003859 if (err < 0)
3860 status = MGMT_STATUS_FAILED;
3861 else
3862 status = MGMT_STATUS_SUCCESS;
3863
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003864 err = mgmt_cmd_complete(sk, hdev->id,
3865 MGMT_OP_ADD_REMOTE_OOB_DATA,
3866 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003867 } else {
3868 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02003869 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3870 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08003871 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003872
Johan Hedbergc19a4952014-11-17 20:52:19 +02003873unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003874 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003875 return err;
3876}
3877
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003878static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003879 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003880{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003881 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003882 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003883 int err;
3884
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003885 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003886
Johan Hedbergc19a4952014-11-17 20:52:19 +02003887 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003888 return mgmt_cmd_complete(sk, hdev->id,
3889 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3890 MGMT_STATUS_INVALID_PARAMS,
3891 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003892
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003893 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003894
Johan Hedbergeedbd582014-11-15 09:34:23 +02003895 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3896 hci_remote_oob_data_clear(hdev);
3897 status = MGMT_STATUS_SUCCESS;
3898 goto done;
3899 }
3900
Johan Hedberg6928a922014-10-26 20:46:09 +01003901 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003902 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003903 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003904 else
Szymon Janca6785be2012-12-13 15:11:21 +01003905 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003906
Johan Hedbergeedbd582014-11-15 09:34:23 +02003907done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003908 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3909 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003910
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003911 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003912 return err;
3913}
3914
Marcel Holtmann80190442014-12-04 11:36:36 +01003915static bool trigger_discovery(struct hci_request *req, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003916{
Marcel Holtmann80190442014-12-04 11:36:36 +01003917 struct hci_dev *hdev = req->hdev;
3918 struct hci_cp_le_set_scan_param param_cp;
3919 struct hci_cp_le_set_scan_enable enable_cp;
3920 struct hci_cp_inquiry inq_cp;
3921 /* General inquiry access code (GIAC) */
3922 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3923 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003924 int err;
3925
Marcel Holtmann80190442014-12-04 11:36:36 +01003926 switch (hdev->discovery.type) {
3927 case DISCOV_TYPE_BREDR:
3928 *status = mgmt_bredr_support(hdev);
3929 if (*status)
3930 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003931
Marcel Holtmann80190442014-12-04 11:36:36 +01003932 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3933 *status = MGMT_STATUS_BUSY;
3934 return false;
3935 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003936
Marcel Holtmann80190442014-12-04 11:36:36 +01003937 hci_inquiry_cache_flush(hdev);
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003938
Marcel Holtmann80190442014-12-04 11:36:36 +01003939 memset(&inq_cp, 0, sizeof(inq_cp));
3940 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3941 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3942 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3943 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003944
Marcel Holtmann80190442014-12-04 11:36:36 +01003945 case DISCOV_TYPE_LE:
3946 case DISCOV_TYPE_INTERLEAVED:
3947 *status = mgmt_le_support(hdev);
3948 if (*status)
3949 return false;
3950
3951 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07003952 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01003953 *status = MGMT_STATUS_NOT_SUPPORTED;
3954 return false;
3955 }
3956
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07003957 if (hci_dev_test_flag(hdev, HCI_LE_ADV)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01003958 /* Don't let discovery abort an outgoing
3959 * connection attempt that's using directed
3960 * advertising.
3961 */
3962 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3963 BT_CONNECT)) {
3964 *status = MGMT_STATUS_REJECTED;
3965 return false;
3966 }
3967
3968 disable_advertising(req);
3969 }
3970
3971 /* If controller is scanning, it means the background scanning
3972 * is running. Thus, we should temporarily stop it in order to
3973 * set the discovery scanning parameters.
3974 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07003975 if (hci_dev_test_flag(hdev, HCI_LE_SCAN))
Marcel Holtmann80190442014-12-04 11:36:36 +01003976 hci_req_add_le_scan_disable(req);
3977
3978 memset(&param_cp, 0, sizeof(param_cp));
3979
3980 /* All active scans will be done with either a resolvable
3981 * private address (when privacy feature has been enabled)
Marcel Holtmann9437d2e2014-12-07 20:13:17 +01003982 * or non-resolvable private address.
Marcel Holtmann80190442014-12-04 11:36:36 +01003983 */
3984 err = hci_update_random_address(req, true, &own_addr_type);
3985 if (err < 0) {
3986 *status = MGMT_STATUS_FAILED;
3987 return false;
3988 }
3989
3990 param_cp.type = LE_SCAN_ACTIVE;
3991 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3992 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3993 param_cp.own_address_type = own_addr_type;
3994 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3995 &param_cp);
3996
3997 memset(&enable_cp, 0, sizeof(enable_cp));
3998 enable_cp.enable = LE_SCAN_ENABLE;
3999 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
4000 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
4001 &enable_cp);
4002 break;
4003
4004 default:
4005 *status = MGMT_STATUS_INVALID_PARAMS;
4006 return false;
4007 }
4008
4009 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004010}
4011
Marcel Holtmann1904a852015-01-11 13:50:44 -08004012static void start_discovery_complete(struct hci_dev *hdev, u8 status,
4013 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03004014{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004015 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004016 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004017
Andre Guedes7c307722013-04-30 15:29:28 -03004018 BT_DBG("status %d", status);
4019
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004020 hci_dev_lock(hdev);
4021
4022 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004023 if (!cmd)
4024 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
4025
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004026 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004027 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004028 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03004029 }
4030
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004031 if (status) {
4032 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4033 goto unlock;
4034 }
4035
Andre Guedes7c307722013-04-30 15:29:28 -03004036 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03004037
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004038 /* If the scan involves LE scan, pick proper timeout to schedule
4039 * hdev->le_scan_disable that will stop it.
4040 */
Andre Guedes7c307722013-04-30 15:29:28 -03004041 switch (hdev->discovery.type) {
4042 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01004043 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03004044 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004045 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01004046 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03004047 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004048 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004049 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03004050 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004051 default:
4052 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004053 timeout = 0;
4054 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004055 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004056
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004057 if (timeout) {
4058 /* When service discovery is used and the controller has
4059 * a strict duplicate filter, it is important to remember
4060 * the start and duration of the scan. This is required
4061 * for restarting scanning during the discovery phase.
4062 */
4063 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
4064 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004065 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004066 hdev->discovery.scan_start = jiffies;
4067 hdev->discovery.scan_duration = timeout;
4068 }
4069
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004070 queue_delayed_work(hdev->workqueue,
4071 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004072 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004073
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004074unlock:
4075 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03004076}
4077
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004078static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004079 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004080{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004081 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004082 struct mgmt_pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03004083 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01004084 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04004085 int err;
4086
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004087 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004088
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004089 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004090
Johan Hedberg4b34ee782012-02-21 14:13:02 +02004091 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004092 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4093 MGMT_STATUS_NOT_POWERED,
4094 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004095 goto failed;
4096 }
4097
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004098 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004099 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004100 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4101 MGMT_STATUS_BUSY, &cp->type,
4102 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004103 goto failed;
4104 }
4105
Johan Hedberg2922a942014-12-05 13:36:06 +02004106 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004107 if (!cmd) {
4108 err = -ENOMEM;
4109 goto failed;
4110 }
4111
Johan Hedberg2922a942014-12-05 13:36:06 +02004112 cmd->cmd_complete = generic_cmd_complete;
4113
Marcel Holtmann22078802014-12-05 11:45:22 +01004114 /* Clear the discovery filter first to free any previously
4115 * allocated memory for the UUID list.
4116 */
4117 hci_discovery_filter_clear(hdev);
4118
Andre Guedes4aab14e2012-02-17 20:39:36 -03004119 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004120 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004121
Andre Guedes7c307722013-04-30 15:29:28 -03004122 hci_req_init(&req, hdev);
4123
Marcel Holtmann80190442014-12-04 11:36:36 +01004124 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004125 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4126 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004127 mgmt_pending_remove(cmd);
4128 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004129 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004130
Andre Guedes7c307722013-04-30 15:29:28 -03004131 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004132 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004133 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004134 goto failed;
4135 }
4136
4137 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004138
4139failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004140 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004141 return err;
4142}
4143
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004144static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4145 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004146{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004147 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4148 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004149}
4150
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004151static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4152 void *data, u16 len)
4153{
4154 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004155 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004156 struct hci_request req;
4157 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4158 u16 uuid_count, expected_len;
4159 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004160 int err;
4161
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004162 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004163
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004164 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004165
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004166 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004167 err = mgmt_cmd_complete(sk, hdev->id,
4168 MGMT_OP_START_SERVICE_DISCOVERY,
4169 MGMT_STATUS_NOT_POWERED,
4170 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004171 goto failed;
4172 }
4173
4174 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004175 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004176 err = mgmt_cmd_complete(sk, hdev->id,
4177 MGMT_OP_START_SERVICE_DISCOVERY,
4178 MGMT_STATUS_BUSY, &cp->type,
4179 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004180 goto failed;
4181 }
4182
4183 uuid_count = __le16_to_cpu(cp->uuid_count);
4184 if (uuid_count > max_uuid_count) {
4185 BT_ERR("service_discovery: too big uuid_count value %u",
4186 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004187 err = mgmt_cmd_complete(sk, hdev->id,
4188 MGMT_OP_START_SERVICE_DISCOVERY,
4189 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4190 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004191 goto failed;
4192 }
4193
4194 expected_len = sizeof(*cp) + uuid_count * 16;
4195 if (expected_len != len) {
4196 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4197 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004198 err = mgmt_cmd_complete(sk, hdev->id,
4199 MGMT_OP_START_SERVICE_DISCOVERY,
4200 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4201 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004202 goto failed;
4203 }
4204
4205 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004206 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004207 if (!cmd) {
4208 err = -ENOMEM;
4209 goto failed;
4210 }
4211
Johan Hedberg2922a942014-12-05 13:36:06 +02004212 cmd->cmd_complete = service_discovery_cmd_complete;
4213
Marcel Holtmann22078802014-12-05 11:45:22 +01004214 /* Clear the discovery filter first to free any previously
4215 * allocated memory for the UUID list.
4216 */
4217 hci_discovery_filter_clear(hdev);
4218
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004219 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004220 hdev->discovery.type = cp->type;
4221 hdev->discovery.rssi = cp->rssi;
4222 hdev->discovery.uuid_count = uuid_count;
4223
4224 if (uuid_count > 0) {
4225 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4226 GFP_KERNEL);
4227 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004228 err = mgmt_cmd_complete(sk, hdev->id,
4229 MGMT_OP_START_SERVICE_DISCOVERY,
4230 MGMT_STATUS_FAILED,
4231 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004232 mgmt_pending_remove(cmd);
4233 goto failed;
4234 }
4235 }
4236
4237 hci_req_init(&req, hdev);
4238
4239 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004240 err = mgmt_cmd_complete(sk, hdev->id,
4241 MGMT_OP_START_SERVICE_DISCOVERY,
4242 status, &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004243 mgmt_pending_remove(cmd);
4244 goto failed;
4245 }
4246
4247 err = hci_req_run(&req, start_discovery_complete);
4248 if (err < 0) {
4249 mgmt_pending_remove(cmd);
4250 goto failed;
4251 }
4252
4253 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4254
4255failed:
4256 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004257 return err;
4258}
4259
Marcel Holtmann1904a852015-01-11 13:50:44 -08004260static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004261{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004262 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004263
Andre Guedes0e05bba2013-04-30 15:29:33 -03004264 BT_DBG("status %d", status);
4265
4266 hci_dev_lock(hdev);
4267
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004268 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4269 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004270 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004271 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004272 }
4273
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004274 if (!status)
4275 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004276
Andre Guedes0e05bba2013-04-30 15:29:33 -03004277 hci_dev_unlock(hdev);
4278}
4279
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004280static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004281 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004282{
Johan Hedbergd9306502012-02-20 23:25:18 +02004283 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004284 struct mgmt_pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004285 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004286 int err;
4287
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004288 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004289
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004290 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004291
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004292 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004293 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4294 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4295 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004296 goto unlock;
4297 }
4298
4299 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004300 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4301 MGMT_STATUS_INVALID_PARAMS,
4302 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004303 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004304 }
4305
Johan Hedberg2922a942014-12-05 13:36:06 +02004306 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004307 if (!cmd) {
4308 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004309 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004310 }
4311
Johan Hedberg2922a942014-12-05 13:36:06 +02004312 cmd->cmd_complete = generic_cmd_complete;
4313
Andre Guedes0e05bba2013-04-30 15:29:33 -03004314 hci_req_init(&req, hdev);
4315
Johan Hedberg21a60d32014-06-10 14:05:58 +03004316 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004317
Johan Hedberg21a60d32014-06-10 14:05:58 +03004318 err = hci_req_run(&req, stop_discovery_complete);
4319 if (!err) {
4320 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004321 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004322 }
4323
Johan Hedberg21a60d32014-06-10 14:05:58 +03004324 mgmt_pending_remove(cmd);
4325
4326 /* If no HCI commands were sent we're done */
4327 if (err == -ENODATA) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004328 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4329 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg21a60d32014-06-10 14:05:58 +03004330 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4331 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004332
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004333unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004334 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004335 return err;
4336}
4337
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004338static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004339 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004340{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004341 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004342 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004343 int err;
4344
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004345 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004346
Johan Hedberg561aafb2012-01-04 13:31:59 +02004347 hci_dev_lock(hdev);
4348
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004349 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004350 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4351 MGMT_STATUS_FAILED, &cp->addr,
4352 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004353 goto failed;
4354 }
4355
Johan Hedberga198e7b2012-02-17 14:27:06 +02004356 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004357 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004358 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4359 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4360 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004361 goto failed;
4362 }
4363
4364 if (cp->name_known) {
4365 e->name_state = NAME_KNOWN;
4366 list_del(&e->list);
4367 } else {
4368 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e20a2012-01-09 00:53:02 +02004369 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004370 }
4371
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004372 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4373 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004374
4375failed:
4376 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004377 return err;
4378}
4379
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004380static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004381 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004382{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004383 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004384 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004385 int err;
4386
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004387 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004388
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004389 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004390 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4391 MGMT_STATUS_INVALID_PARAMS,
4392 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004393
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004394 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004395
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004396 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4397 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004398 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004399 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004400 goto done;
4401 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004402
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004403 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4404 sk);
4405 status = MGMT_STATUS_SUCCESS;
4406
4407done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004408 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4409 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004410
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004411 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004412
4413 return err;
4414}
4415
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004416static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004417 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004418{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004419 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004420 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004421 int err;
4422
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004423 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004424
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004425 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004426 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4427 MGMT_STATUS_INVALID_PARAMS,
4428 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004429
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004430 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004431
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004432 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4433 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004434 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004435 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004436 goto done;
4437 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004438
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004439 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4440 sk);
4441 status = MGMT_STATUS_SUCCESS;
4442
4443done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004444 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4445 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004446
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004447 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004448
4449 return err;
4450}
4451
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004452static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4453 u16 len)
4454{
4455 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004456 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004457 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004458 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004459
4460 BT_DBG("%s", hdev->name);
4461
Szymon Jancc72d4b82012-03-16 16:02:57 +01004462 source = __le16_to_cpu(cp->source);
4463
4464 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004465 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4466 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004467
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004468 hci_dev_lock(hdev);
4469
Szymon Jancc72d4b82012-03-16 16:02:57 +01004470 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004471 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4472 hdev->devid_product = __le16_to_cpu(cp->product);
4473 hdev->devid_version = __le16_to_cpu(cp->version);
4474
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004475 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4476 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004477
Johan Hedberg890ea892013-03-15 17:06:52 -05004478 hci_req_init(&req, hdev);
4479 update_eir(&req);
4480 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004481
4482 hci_dev_unlock(hdev);
4483
4484 return err;
4485}
4486
Marcel Holtmann1904a852015-01-11 13:50:44 -08004487static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4488 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004489{
4490 struct cmd_lookup match = { NULL, hdev };
4491
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304492 hci_dev_lock(hdev);
4493
Johan Hedberg4375f102013-09-25 13:26:10 +03004494 if (status) {
4495 u8 mgmt_err = mgmt_status(status);
4496
4497 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4498 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304499 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004500 }
4501
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004502 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004503 hci_dev_set_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004504 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004505 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004506
Johan Hedberg4375f102013-09-25 13:26:10 +03004507 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4508 &match);
4509
4510 new_settings(hdev, match.sk);
4511
4512 if (match.sk)
4513 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304514
4515unlock:
4516 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004517}
4518
Marcel Holtmann21b51872013-10-10 09:47:53 -07004519static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4520 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004521{
4522 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004523 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004524 struct hci_request req;
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004525 u8 val, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004526 int err;
4527
4528 BT_DBG("request for %s", hdev->name);
4529
Johan Hedberge6fe7982013-10-02 15:45:22 +03004530 status = mgmt_le_support(hdev);
4531 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004532 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4533 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004534
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004535 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004536 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4537 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004538
4539 hci_dev_lock(hdev);
4540
4541 val = !!cp->val;
Johan Hedberg4375f102013-09-25 13:26:10 +03004542
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004543 /* The following conditions are ones which mean that we should
4544 * not do any HCI communication but directly send a mgmt
4545 * response to user space (after toggling the flag if
4546 * necessary).
4547 */
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004548 if (!hdev_is_powered(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004549 (val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
4550 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004551 hci_conn_num(hdev, LE_LINK) > 0 ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004552 (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004553 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004554 bool changed;
Johan Hedberg4375f102013-09-25 13:26:10 +03004555
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004556 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07004557 changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004558 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004559 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004560 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004561 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004562 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07004563 changed = hci_dev_test_and_clear_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004564 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Johan Hedberg4375f102013-09-25 13:26:10 +03004565 }
4566
4567 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4568 if (err < 0)
4569 goto unlock;
4570
4571 if (changed)
4572 err = new_settings(hdev, sk);
4573
4574 goto unlock;
4575 }
4576
4577 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4578 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004579 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4580 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004581 goto unlock;
4582 }
4583
4584 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4585 if (!cmd) {
4586 err = -ENOMEM;
4587 goto unlock;
4588 }
4589
4590 hci_req_init(&req, hdev);
4591
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004592 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004593 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004594 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004595 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004596
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004597 if (val)
4598 enable_advertising(&req);
4599 else
4600 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004601
4602 err = hci_req_run(&req, set_advertising_complete);
4603 if (err < 0)
4604 mgmt_pending_remove(cmd);
4605
4606unlock:
4607 hci_dev_unlock(hdev);
4608 return err;
4609}
4610
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004611static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4612 void *data, u16 len)
4613{
4614 struct mgmt_cp_set_static_address *cp = data;
4615 int err;
4616
4617 BT_DBG("%s", hdev->name);
4618
Marcel Holtmann62af4442013-10-02 22:10:32 -07004619 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004620 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4621 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004622
4623 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004624 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4625 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004626
4627 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4628 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004629 return mgmt_cmd_status(sk, hdev->id,
4630 MGMT_OP_SET_STATIC_ADDRESS,
4631 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004632
4633 /* Two most significant bits shall be set */
4634 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004635 return mgmt_cmd_status(sk, hdev->id,
4636 MGMT_OP_SET_STATIC_ADDRESS,
4637 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004638 }
4639
4640 hci_dev_lock(hdev);
4641
4642 bacpy(&hdev->static_addr, &cp->bdaddr);
4643
Marcel Holtmann93690c22015-03-06 10:11:21 -08004644 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4645 if (err < 0)
4646 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004647
Marcel Holtmann93690c22015-03-06 10:11:21 -08004648 err = new_settings(hdev, sk);
4649
4650unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004651 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004652 return err;
4653}
4654
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004655static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4656 void *data, u16 len)
4657{
4658 struct mgmt_cp_set_scan_params *cp = data;
4659 __u16 interval, window;
4660 int err;
4661
4662 BT_DBG("%s", hdev->name);
4663
4664 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004665 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4666 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004667
4668 interval = __le16_to_cpu(cp->interval);
4669
4670 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004671 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4672 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004673
4674 window = __le16_to_cpu(cp->window);
4675
4676 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004677 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4678 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004679
Marcel Holtmann899e1072013-10-14 09:55:32 -07004680 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004681 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4682 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004683
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004684 hci_dev_lock(hdev);
4685
4686 hdev->le_scan_interval = interval;
4687 hdev->le_scan_window = window;
4688
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004689 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4690 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004691
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004692 /* If background scan is running, restart it so new parameters are
4693 * loaded.
4694 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004695 if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004696 hdev->discovery.state == DISCOVERY_STOPPED) {
4697 struct hci_request req;
4698
4699 hci_req_init(&req, hdev);
4700
4701 hci_req_add_le_scan_disable(&req);
4702 hci_req_add_le_passive_scan(&req);
4703
4704 hci_req_run(&req, NULL);
4705 }
4706
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004707 hci_dev_unlock(hdev);
4708
4709 return err;
4710}
4711
Marcel Holtmann1904a852015-01-11 13:50:44 -08004712static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4713 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004714{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004715 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004716
4717 BT_DBG("status 0x%02x", status);
4718
4719 hci_dev_lock(hdev);
4720
4721 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4722 if (!cmd)
4723 goto unlock;
4724
4725 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004726 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4727 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004728 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004729 struct mgmt_mode *cp = cmd->param;
4730
4731 if (cp->val)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004732 hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004733 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004734 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004735
Johan Hedberg33e38b32013-03-15 17:07:05 -05004736 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4737 new_settings(hdev, cmd->sk);
4738 }
4739
4740 mgmt_pending_remove(cmd);
4741
4742unlock:
4743 hci_dev_unlock(hdev);
4744}
4745
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004746static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004747 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004748{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004749 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004750 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004751 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004752 int err;
4753
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004754 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004755
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004756 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Johan Hedberg56f87902013-10-02 13:43:13 +03004757 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004758 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4759 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004760
Johan Hedberga7e80f22013-01-09 16:05:19 +02004761 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004762 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4763 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004764
Antti Julkuf6422ec2011-06-22 13:11:56 +03004765 hci_dev_lock(hdev);
4766
Johan Hedberg05cbf292013-03-15 17:07:07 -05004767 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004768 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4769 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004770 goto unlock;
4771 }
4772
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004773 if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004774 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4775 hdev);
4776 goto unlock;
4777 }
4778
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004779 if (!hdev_is_powered(hdev)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07004780 hci_dev_change_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004781 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4782 hdev);
4783 new_settings(hdev, sk);
4784 goto unlock;
4785 }
4786
Johan Hedberg33e38b32013-03-15 17:07:05 -05004787 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4788 data, len);
4789 if (!cmd) {
4790 err = -ENOMEM;
4791 goto unlock;
4792 }
4793
4794 hci_req_init(&req, hdev);
4795
Johan Hedberg406d7802013-03-15 17:07:09 -05004796 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004797
4798 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004799 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004800 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4801 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004802 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004803 }
4804
Johan Hedberg33e38b32013-03-15 17:07:05 -05004805unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004806 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004807
Antti Julkuf6422ec2011-06-22 13:11:56 +03004808 return err;
4809}
4810
Marcel Holtmann1904a852015-01-11 13:50:44 -08004811static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004812{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004813 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004814
4815 BT_DBG("status 0x%02x", status);
4816
4817 hci_dev_lock(hdev);
4818
4819 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4820 if (!cmd)
4821 goto unlock;
4822
4823 if (status) {
4824 u8 mgmt_err = mgmt_status(status);
4825
4826 /* We need to restore the flag if related HCI commands
4827 * failed.
4828 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004829 hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004830
Johan Hedberga69e8372015-03-06 21:08:53 +02004831 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004832 } else {
4833 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4834 new_settings(hdev, cmd->sk);
4835 }
4836
4837 mgmt_pending_remove(cmd);
4838
4839unlock:
4840 hci_dev_unlock(hdev);
4841}
4842
4843static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4844{
4845 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004846 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004847 struct hci_request req;
4848 int err;
4849
4850 BT_DBG("request for %s", hdev->name);
4851
4852 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004853 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4854 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004855
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004856 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004857 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4858 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004859
4860 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004861 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4862 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004863
4864 hci_dev_lock(hdev);
4865
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004866 if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004867 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4868 goto unlock;
4869 }
4870
4871 if (!hdev_is_powered(hdev)) {
4872 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004873 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
4874 hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
4875 hci_dev_clear_flag(hdev, HCI_LINK_SECURITY);
4876 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
4877 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004878 }
4879
Marcel Holtmannce05d602015-03-13 02:11:03 -07004880 hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004881
4882 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4883 if (err < 0)
4884 goto unlock;
4885
4886 err = new_settings(hdev, sk);
4887 goto unlock;
4888 }
4889
4890 /* Reject disabling when powered on */
4891 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004892 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4893 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004894 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004895 } else {
4896 /* When configuring a dual-mode controller to operate
4897 * with LE only and using a static address, then switching
4898 * BR/EDR back on is not allowed.
4899 *
4900 * Dual-mode controllers shall operate with the public
4901 * address as its identity address for BR/EDR and LE. So
4902 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004903 *
4904 * The same restrictions applies when secure connections
4905 * has been enabled. For BR/EDR this is a controller feature
4906 * while for LE it is a host stack feature. This means that
4907 * switching BR/EDR back on when secure connections has been
4908 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004909 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004910 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004911 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004912 hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004913 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4914 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004915 goto unlock;
4916 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03004917 }
4918
4919 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004920 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4921 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004922 goto unlock;
4923 }
4924
4925 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4926 if (!cmd) {
4927 err = -ENOMEM;
4928 goto unlock;
4929 }
4930
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004931 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004932 * generates the correct flags.
4933 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004934 hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004935
4936 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004937
Johan Hedberg432df052014-08-01 11:13:31 +03004938 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02004939 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004940
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004941 /* Since only the advertising data flags will change, there
4942 * is no need to update the scan response data.
4943 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004944 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004945
Johan Hedberg0663ca22013-10-02 13:43:14 +03004946 err = hci_req_run(&req, set_bredr_complete);
4947 if (err < 0)
4948 mgmt_pending_remove(cmd);
4949
4950unlock:
4951 hci_dev_unlock(hdev);
4952 return err;
4953}
4954
Johan Hedberga1443f52015-01-23 15:42:46 +02004955static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
4956{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004957 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02004958 struct mgmt_mode *cp;
4959
4960 BT_DBG("%s status %u", hdev->name, status);
4961
4962 hci_dev_lock(hdev);
4963
4964 cmd = mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
4965 if (!cmd)
4966 goto unlock;
4967
4968 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004969 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
4970 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02004971 goto remove;
4972 }
4973
4974 cp = cmd->param;
4975
4976 switch (cp->val) {
4977 case 0x00:
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004978 hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
4979 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02004980 break;
4981 case 0x01:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004982 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004983 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02004984 break;
4985 case 0x02:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004986 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
4987 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02004988 break;
4989 }
4990
4991 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
4992 new_settings(hdev, cmd->sk);
4993
4994remove:
4995 mgmt_pending_remove(cmd);
4996unlock:
4997 hci_dev_unlock(hdev);
4998}
4999
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005000static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
5001 void *data, u16 len)
5002{
5003 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005004 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005005 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03005006 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005007 int err;
5008
5009 BT_DBG("request for %s", hdev->name);
5010
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005011 if (!lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005012 !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005013 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5014 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005015
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005016 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Johan Hedberg59200282015-01-28 19:56:00 +02005017 lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005018 !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005019 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5020 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08005021
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005022 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005023 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005024 MGMT_STATUS_INVALID_PARAMS);
5025
5026 hci_dev_lock(hdev);
5027
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005028 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005029 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005030 bool changed;
5031
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005032 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005033 changed = !hci_dev_test_and_set_flag(hdev,
5034 HCI_SC_ENABLED);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005035 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005036 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005037 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005038 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005039 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005040 changed = hci_dev_test_and_clear_flag(hdev,
5041 HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005042 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005043 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005044
5045 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5046 if (err < 0)
5047 goto failed;
5048
5049 if (changed)
5050 err = new_settings(hdev, sk);
5051
5052 goto failed;
5053 }
5054
5055 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005056 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5057 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005058 goto failed;
5059 }
5060
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005061 val = !!cp->val;
5062
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005063 if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
5064 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005065 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5066 goto failed;
5067 }
5068
5069 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
5070 if (!cmd) {
5071 err = -ENOMEM;
5072 goto failed;
5073 }
5074
Johan Hedberga1443f52015-01-23 15:42:46 +02005075 hci_req_init(&req, hdev);
5076 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
5077 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005078 if (err < 0) {
5079 mgmt_pending_remove(cmd);
5080 goto failed;
5081 }
5082
5083failed:
5084 hci_dev_unlock(hdev);
5085 return err;
5086}
5087
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005088static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
5089 void *data, u16 len)
5090{
5091 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03005092 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005093 int err;
5094
5095 BT_DBG("request for %s", hdev->name);
5096
Johan Hedbergb97109792014-06-24 14:00:28 +03005097 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005098 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
5099 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005100
5101 hci_dev_lock(hdev);
5102
5103 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07005104 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005105 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005106 changed = hci_dev_test_and_clear_flag(hdev,
5107 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005108
Johan Hedbergb97109792014-06-24 14:00:28 +03005109 if (cp->val == 0x02)
Marcel Holtmann238be782015-03-13 02:11:06 -07005110 use_changed = !hci_dev_test_and_set_flag(hdev,
5111 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005112 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005113 use_changed = hci_dev_test_and_clear_flag(hdev,
5114 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005115
5116 if (hdev_is_powered(hdev) && use_changed &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005117 hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedbergb97109792014-06-24 14:00:28 +03005118 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5119 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5120 sizeof(mode), &mode);
5121 }
5122
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005123 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5124 if (err < 0)
5125 goto unlock;
5126
5127 if (changed)
5128 err = new_settings(hdev, sk);
5129
5130unlock:
5131 hci_dev_unlock(hdev);
5132 return err;
5133}
5134
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005135static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5136 u16 len)
5137{
5138 struct mgmt_cp_set_privacy *cp = cp_data;
5139 bool changed;
5140 int err;
5141
5142 BT_DBG("request for %s", hdev->name);
5143
5144 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005145 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5146 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005147
5148 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005149 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5150 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005151
5152 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005153 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5154 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005155
5156 hci_dev_lock(hdev);
5157
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005158 /* If user space supports this command it is also expected to
5159 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5160 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005161 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005162
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005163 if (cp->privacy) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005164 changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005165 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005166 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005167 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005168 changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005169 memset(hdev->irk, 0, sizeof(hdev->irk));
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005170 hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005171 }
5172
5173 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5174 if (err < 0)
5175 goto unlock;
5176
5177 if (changed)
5178 err = new_settings(hdev, sk);
5179
5180unlock:
5181 hci_dev_unlock(hdev);
5182 return err;
5183}
5184
Johan Hedberg41edf162014-02-18 10:19:35 +02005185static bool irk_is_valid(struct mgmt_irk_info *irk)
5186{
5187 switch (irk->addr.type) {
5188 case BDADDR_LE_PUBLIC:
5189 return true;
5190
5191 case BDADDR_LE_RANDOM:
5192 /* Two most significant bits shall be set */
5193 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5194 return false;
5195 return true;
5196 }
5197
5198 return false;
5199}
5200
5201static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5202 u16 len)
5203{
5204 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005205 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5206 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005207 u16 irk_count, expected_len;
5208 int i, err;
5209
5210 BT_DBG("request for %s", hdev->name);
5211
5212 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005213 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5214 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005215
5216 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005217 if (irk_count > max_irk_count) {
5218 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005219 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5220 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005221 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005222
5223 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5224 if (expected_len != len) {
5225 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005226 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005227 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5228 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005229 }
5230
5231 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5232
5233 for (i = 0; i < irk_count; i++) {
5234 struct mgmt_irk_info *key = &cp->irks[i];
5235
5236 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005237 return mgmt_cmd_status(sk, hdev->id,
5238 MGMT_OP_LOAD_IRKS,
5239 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005240 }
5241
5242 hci_dev_lock(hdev);
5243
5244 hci_smp_irks_clear(hdev);
5245
5246 for (i = 0; i < irk_count; i++) {
5247 struct mgmt_irk_info *irk = &cp->irks[i];
5248 u8 addr_type;
5249
5250 if (irk->addr.type == BDADDR_LE_PUBLIC)
5251 addr_type = ADDR_LE_DEV_PUBLIC;
5252 else
5253 addr_type = ADDR_LE_DEV_RANDOM;
5254
5255 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5256 BDADDR_ANY);
5257 }
5258
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005259 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedberg41edf162014-02-18 10:19:35 +02005260
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005261 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005262
5263 hci_dev_unlock(hdev);
5264
5265 return err;
5266}
5267
Johan Hedberg3f706b72013-01-20 14:27:16 +02005268static bool ltk_is_valid(struct mgmt_ltk_info *key)
5269{
5270 if (key->master != 0x00 && key->master != 0x01)
5271 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005272
5273 switch (key->addr.type) {
5274 case BDADDR_LE_PUBLIC:
5275 return true;
5276
5277 case BDADDR_LE_RANDOM:
5278 /* Two most significant bits shall be set */
5279 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5280 return false;
5281 return true;
5282 }
5283
5284 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005285}
5286
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005287static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005288 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005289{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005290 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005291 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5292 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005293 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005294 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005295
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005296 BT_DBG("request for %s", hdev->name);
5297
5298 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005299 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5300 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005301
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005302 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005303 if (key_count > max_key_count) {
5304 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005305 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5306 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005307 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005308
5309 expected_len = sizeof(*cp) + key_count *
5310 sizeof(struct mgmt_ltk_info);
5311 if (expected_len != len) {
5312 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005313 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005314 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5315 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005316 }
5317
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005318 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005319
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005320 for (i = 0; i < key_count; i++) {
5321 struct mgmt_ltk_info *key = &cp->keys[i];
5322
Johan Hedberg3f706b72013-01-20 14:27:16 +02005323 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005324 return mgmt_cmd_status(sk, hdev->id,
5325 MGMT_OP_LOAD_LONG_TERM_KEYS,
5326 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005327 }
5328
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005329 hci_dev_lock(hdev);
5330
5331 hci_smp_ltks_clear(hdev);
5332
5333 for (i = 0; i < key_count; i++) {
5334 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005335 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005336
5337 if (key->addr.type == BDADDR_LE_PUBLIC)
5338 addr_type = ADDR_LE_DEV_PUBLIC;
5339 else
5340 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005341
Johan Hedberg61b43352014-05-29 19:36:53 +03005342 switch (key->type) {
5343 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005344 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005345 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005346 break;
5347 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005348 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005349 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005350 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005351 case MGMT_LTK_P256_UNAUTH:
5352 authenticated = 0x00;
5353 type = SMP_LTK_P256;
5354 break;
5355 case MGMT_LTK_P256_AUTH:
5356 authenticated = 0x01;
5357 type = SMP_LTK_P256;
5358 break;
5359 case MGMT_LTK_P256_DEBUG:
5360 authenticated = 0x00;
5361 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005362 default:
5363 continue;
5364 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005365
Johan Hedberg35d70272014-02-19 14:57:47 +02005366 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005367 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005368 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005369 }
5370
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005371 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005372 NULL, 0);
5373
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005374 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005375
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005376 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005377}
5378
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005379static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005380{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005381 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005382 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005383 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005384
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005385 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005386
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005387 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005388 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005389 rp.tx_power = conn->tx_power;
5390 rp.max_tx_power = conn->max_tx_power;
5391 } else {
5392 rp.rssi = HCI_RSSI_INVALID;
5393 rp.tx_power = HCI_TX_POWER_INVALID;
5394 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005395 }
5396
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005397 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5398 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005399
5400 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005401 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005402
5403 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005404}
5405
Marcel Holtmann1904a852015-01-11 13:50:44 -08005406static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5407 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005408{
5409 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005410 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005411 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005412 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005413 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005414
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005415 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005416
5417 hci_dev_lock(hdev);
5418
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005419 /* Commands sent in request are either Read RSSI or Read Transmit Power
5420 * Level so we check which one was last sent to retrieve connection
5421 * handle. Both commands have handle as first parameter so it's safe to
5422 * cast data on the same command struct.
5423 *
5424 * First command sent is always Read RSSI and we fail only if it fails.
5425 * In other case we simply override error to indicate success as we
5426 * already remembered if TX power value is actually valid.
5427 */
5428 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5429 if (!cp) {
5430 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005431 status = MGMT_STATUS_SUCCESS;
5432 } else {
5433 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005434 }
5435
5436 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005437 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005438 goto unlock;
5439 }
5440
5441 handle = __le16_to_cpu(cp->handle);
5442 conn = hci_conn_hash_lookup_handle(hdev, handle);
5443 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005444 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005445 goto unlock;
5446 }
5447
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005448 cmd = mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
5449 if (!cmd)
5450 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005451
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005452 cmd->cmd_complete(cmd, status);
5453 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005454
5455unlock:
5456 hci_dev_unlock(hdev);
5457}
5458
5459static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5460 u16 len)
5461{
5462 struct mgmt_cp_get_conn_info *cp = data;
5463 struct mgmt_rp_get_conn_info rp;
5464 struct hci_conn *conn;
5465 unsigned long conn_info_age;
5466 int err = 0;
5467
5468 BT_DBG("%s", hdev->name);
5469
5470 memset(&rp, 0, sizeof(rp));
5471 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5472 rp.addr.type = cp->addr.type;
5473
5474 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005475 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5476 MGMT_STATUS_INVALID_PARAMS,
5477 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005478
5479 hci_dev_lock(hdev);
5480
5481 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005482 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5483 MGMT_STATUS_NOT_POWERED, &rp,
5484 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005485 goto unlock;
5486 }
5487
5488 if (cp->addr.type == BDADDR_BREDR)
5489 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5490 &cp->addr.bdaddr);
5491 else
5492 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5493
5494 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005495 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5496 MGMT_STATUS_NOT_CONNECTED, &rp,
5497 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005498 goto unlock;
5499 }
5500
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005501 if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005502 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5503 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005504 goto unlock;
5505 }
5506
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005507 /* To avoid client trying to guess when to poll again for information we
5508 * calculate conn info age as random value between min/max set in hdev.
5509 */
5510 conn_info_age = hdev->conn_info_min_age +
5511 prandom_u32_max(hdev->conn_info_max_age -
5512 hdev->conn_info_min_age);
5513
5514 /* Query controller to refresh cached values if they are too old or were
5515 * never read.
5516 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005517 if (time_after(jiffies, conn->conn_info_timestamp +
5518 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005519 !conn->conn_info_timestamp) {
5520 struct hci_request req;
5521 struct hci_cp_read_tx_power req_txp_cp;
5522 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005523 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005524
5525 hci_req_init(&req, hdev);
5526 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5527 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5528 &req_rssi_cp);
5529
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005530 /* For LE links TX power does not change thus we don't need to
5531 * query for it once value is known.
5532 */
5533 if (!bdaddr_type_is_le(cp->addr.type) ||
5534 conn->tx_power == HCI_TX_POWER_INVALID) {
5535 req_txp_cp.handle = cpu_to_le16(conn->handle);
5536 req_txp_cp.type = 0x00;
5537 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5538 sizeof(req_txp_cp), &req_txp_cp);
5539 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005540
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005541 /* Max TX power needs to be read only once per connection */
5542 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5543 req_txp_cp.handle = cpu_to_le16(conn->handle);
5544 req_txp_cp.type = 0x01;
5545 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5546 sizeof(req_txp_cp), &req_txp_cp);
5547 }
5548
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005549 err = hci_req_run(&req, conn_info_refresh_complete);
5550 if (err < 0)
5551 goto unlock;
5552
5553 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5554 data, len);
5555 if (!cmd) {
5556 err = -ENOMEM;
5557 goto unlock;
5558 }
5559
5560 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005561 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005562 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005563
5564 conn->conn_info_timestamp = jiffies;
5565 } else {
5566 /* Cache is valid, just reply with values cached in hci_conn */
5567 rp.rssi = conn->rssi;
5568 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005569 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005570
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005571 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5572 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005573 }
5574
5575unlock:
5576 hci_dev_unlock(hdev);
5577 return err;
5578}
5579
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005580static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005581{
5582 struct hci_conn *conn = cmd->user_data;
5583 struct mgmt_rp_get_clock_info rp;
5584 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005585 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005586
5587 memset(&rp, 0, sizeof(rp));
5588 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5589
5590 if (status)
5591 goto complete;
5592
5593 hdev = hci_dev_get(cmd->index);
5594 if (hdev) {
5595 rp.local_clock = cpu_to_le32(hdev->clock);
5596 hci_dev_put(hdev);
5597 }
5598
5599 if (conn) {
5600 rp.piconet_clock = cpu_to_le32(conn->clock);
5601 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5602 }
5603
5604complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005605 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5606 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005607
5608 if (conn) {
5609 hci_conn_drop(conn);
5610 hci_conn_put(conn);
5611 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005612
5613 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005614}
5615
Marcel Holtmann1904a852015-01-11 13:50:44 -08005616static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005617{
Johan Hedberg95868422014-06-28 17:54:07 +03005618 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005619 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005620 struct hci_conn *conn;
5621
5622 BT_DBG("%s status %u", hdev->name, status);
5623
5624 hci_dev_lock(hdev);
5625
5626 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5627 if (!hci_cp)
5628 goto unlock;
5629
5630 if (hci_cp->which) {
5631 u16 handle = __le16_to_cpu(hci_cp->handle);
5632 conn = hci_conn_hash_lookup_handle(hdev, handle);
5633 } else {
5634 conn = NULL;
5635 }
5636
5637 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5638 if (!cmd)
5639 goto unlock;
5640
Johan Hedberg69487372014-12-05 13:36:07 +02005641 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005642 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005643
5644unlock:
5645 hci_dev_unlock(hdev);
5646}
5647
5648static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5649 u16 len)
5650{
5651 struct mgmt_cp_get_clock_info *cp = data;
5652 struct mgmt_rp_get_clock_info rp;
5653 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005654 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005655 struct hci_request req;
5656 struct hci_conn *conn;
5657 int err;
5658
5659 BT_DBG("%s", hdev->name);
5660
5661 memset(&rp, 0, sizeof(rp));
5662 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5663 rp.addr.type = cp->addr.type;
5664
5665 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005666 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5667 MGMT_STATUS_INVALID_PARAMS,
5668 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005669
5670 hci_dev_lock(hdev);
5671
5672 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005673 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5674 MGMT_STATUS_NOT_POWERED, &rp,
5675 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005676 goto unlock;
5677 }
5678
5679 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5680 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5681 &cp->addr.bdaddr);
5682 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005683 err = mgmt_cmd_complete(sk, hdev->id,
5684 MGMT_OP_GET_CLOCK_INFO,
5685 MGMT_STATUS_NOT_CONNECTED,
5686 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005687 goto unlock;
5688 }
5689 } else {
5690 conn = NULL;
5691 }
5692
5693 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5694 if (!cmd) {
5695 err = -ENOMEM;
5696 goto unlock;
5697 }
5698
Johan Hedberg69487372014-12-05 13:36:07 +02005699 cmd->cmd_complete = clock_info_cmd_complete;
5700
Johan Hedberg95868422014-06-28 17:54:07 +03005701 hci_req_init(&req, hdev);
5702
5703 memset(&hci_cp, 0, sizeof(hci_cp));
5704 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5705
5706 if (conn) {
5707 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005708 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005709
5710 hci_cp.handle = cpu_to_le16(conn->handle);
5711 hci_cp.which = 0x01; /* Piconet clock */
5712 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5713 }
5714
5715 err = hci_req_run(&req, get_clock_info_complete);
5716 if (err < 0)
5717 mgmt_pending_remove(cmd);
5718
5719unlock:
5720 hci_dev_unlock(hdev);
5721 return err;
5722}
5723
Johan Hedberg5a154e62014-12-19 22:26:02 +02005724static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5725{
5726 struct hci_conn *conn;
5727
5728 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5729 if (!conn)
5730 return false;
5731
5732 if (conn->dst_type != type)
5733 return false;
5734
5735 if (conn->state != BT_CONNECTED)
5736 return false;
5737
5738 return true;
5739}
5740
5741/* This function requires the caller holds hdev->lock */
5742static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5743 u8 addr_type, u8 auto_connect)
5744{
5745 struct hci_dev *hdev = req->hdev;
5746 struct hci_conn_params *params;
5747
5748 params = hci_conn_params_add(hdev, addr, addr_type);
5749 if (!params)
5750 return -EIO;
5751
5752 if (params->auto_connect == auto_connect)
5753 return 0;
5754
5755 list_del_init(&params->action);
5756
5757 switch (auto_connect) {
5758 case HCI_AUTO_CONN_DISABLED:
5759 case HCI_AUTO_CONN_LINK_LOSS:
5760 __hci_update_background_scan(req);
5761 break;
5762 case HCI_AUTO_CONN_REPORT:
5763 list_add(&params->action, &hdev->pend_le_reports);
5764 __hci_update_background_scan(req);
5765 break;
5766 case HCI_AUTO_CONN_DIRECT:
5767 case HCI_AUTO_CONN_ALWAYS:
5768 if (!is_connected(hdev, addr, addr_type)) {
5769 list_add(&params->action, &hdev->pend_le_conns);
5770 __hci_update_background_scan(req);
5771 }
5772 break;
5773 }
5774
5775 params->auto_connect = auto_connect;
5776
5777 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5778 auto_connect);
5779
5780 return 0;
5781}
5782
Marcel Holtmann8afef092014-06-29 22:28:34 +02005783static void device_added(struct sock *sk, struct hci_dev *hdev,
5784 bdaddr_t *bdaddr, u8 type, u8 action)
5785{
5786 struct mgmt_ev_device_added ev;
5787
5788 bacpy(&ev.addr.bdaddr, bdaddr);
5789 ev.addr.type = type;
5790 ev.action = action;
5791
5792 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5793}
5794
Marcel Holtmann1904a852015-01-11 13:50:44 -08005795static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005796{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005797 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005798
5799 BT_DBG("status 0x%02x", status);
5800
5801 hci_dev_lock(hdev);
5802
5803 cmd = mgmt_pending_find(MGMT_OP_ADD_DEVICE, hdev);
5804 if (!cmd)
5805 goto unlock;
5806
5807 cmd->cmd_complete(cmd, mgmt_status(status));
5808 mgmt_pending_remove(cmd);
5809
5810unlock:
5811 hci_dev_unlock(hdev);
5812}
5813
Marcel Holtmann2faade52014-06-29 19:44:03 +02005814static int add_device(struct sock *sk, struct hci_dev *hdev,
5815 void *data, u16 len)
5816{
5817 struct mgmt_cp_add_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005818 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005819 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005820 u8 auto_conn, addr_type;
5821 int err;
5822
5823 BT_DBG("%s", hdev->name);
5824
Johan Hedberg66593582014-07-09 12:59:14 +03005825 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005826 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005827 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5828 MGMT_STATUS_INVALID_PARAMS,
5829 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005830
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005831 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005832 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5833 MGMT_STATUS_INVALID_PARAMS,
5834 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005835
Johan Hedberg5a154e62014-12-19 22:26:02 +02005836 hci_req_init(&req, hdev);
5837
Marcel Holtmann2faade52014-06-29 19:44:03 +02005838 hci_dev_lock(hdev);
5839
Johan Hedberg5a154e62014-12-19 22:26:02 +02005840 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5841 if (!cmd) {
5842 err = -ENOMEM;
5843 goto unlock;
5844 }
5845
5846 cmd->cmd_complete = addr_cmd_complete;
5847
Johan Hedberg66593582014-07-09 12:59:14 +03005848 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005849 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005850 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005851 err = cmd->cmd_complete(cmd,
5852 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005853 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005854 goto unlock;
5855 }
5856
5857 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5858 cp->addr.type);
5859 if (err)
5860 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005861
Johan Hedberg5a154e62014-12-19 22:26:02 +02005862 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005863
Johan Hedberg66593582014-07-09 12:59:14 +03005864 goto added;
5865 }
5866
Marcel Holtmann2faade52014-06-29 19:44:03 +02005867 if (cp->addr.type == BDADDR_LE_PUBLIC)
5868 addr_type = ADDR_LE_DEV_PUBLIC;
5869 else
5870 addr_type = ADDR_LE_DEV_RANDOM;
5871
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005872 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005873 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005874 else if (cp->action == 0x01)
5875 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005876 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005877 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005878
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005879 /* If the connection parameters don't exist for this device,
5880 * they will be created and configured with defaults.
5881 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02005882 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005883 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005884 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005885 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005886 goto unlock;
5887 }
5888
Johan Hedberg66593582014-07-09 12:59:14 +03005889added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005890 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5891
Johan Hedberg5a154e62014-12-19 22:26:02 +02005892 err = hci_req_run(&req, add_device_complete);
5893 if (err < 0) {
5894 /* ENODATA means no HCI commands were needed (e.g. if
5895 * the adapter is powered off).
5896 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005897 if (err == -ENODATA)
5898 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005899 mgmt_pending_remove(cmd);
5900 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005901
5902unlock:
5903 hci_dev_unlock(hdev);
5904 return err;
5905}
5906
Marcel Holtmann8afef092014-06-29 22:28:34 +02005907static void device_removed(struct sock *sk, struct hci_dev *hdev,
5908 bdaddr_t *bdaddr, u8 type)
5909{
5910 struct mgmt_ev_device_removed ev;
5911
5912 bacpy(&ev.addr.bdaddr, bdaddr);
5913 ev.addr.type = type;
5914
5915 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5916}
5917
Marcel Holtmann1904a852015-01-11 13:50:44 -08005918static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005919{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005920 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005921
5922 BT_DBG("status 0x%02x", status);
5923
5924 hci_dev_lock(hdev);
5925
5926 cmd = mgmt_pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
5927 if (!cmd)
5928 goto unlock;
5929
5930 cmd->cmd_complete(cmd, mgmt_status(status));
5931 mgmt_pending_remove(cmd);
5932
5933unlock:
5934 hci_dev_unlock(hdev);
5935}
5936
Marcel Holtmann2faade52014-06-29 19:44:03 +02005937static int remove_device(struct sock *sk, struct hci_dev *hdev,
5938 void *data, u16 len)
5939{
5940 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005941 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005942 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005943 int err;
5944
5945 BT_DBG("%s", hdev->name);
5946
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005947 hci_req_init(&req, hdev);
5948
Marcel Holtmann2faade52014-06-29 19:44:03 +02005949 hci_dev_lock(hdev);
5950
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005951 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
5952 if (!cmd) {
5953 err = -ENOMEM;
5954 goto unlock;
5955 }
5956
5957 cmd->cmd_complete = addr_cmd_complete;
5958
Marcel Holtmann2faade52014-06-29 19:44:03 +02005959 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005960 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005961 u8 addr_type;
5962
Johan Hedberg66593582014-07-09 12:59:14 +03005963 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005964 err = cmd->cmd_complete(cmd,
5965 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005966 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005967 goto unlock;
5968 }
5969
Johan Hedberg66593582014-07-09 12:59:14 +03005970 if (cp->addr.type == BDADDR_BREDR) {
5971 err = hci_bdaddr_list_del(&hdev->whitelist,
5972 &cp->addr.bdaddr,
5973 cp->addr.type);
5974 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005975 err = cmd->cmd_complete(cmd,
5976 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005977 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005978 goto unlock;
5979 }
5980
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005981 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005982
Johan Hedberg66593582014-07-09 12:59:14 +03005983 device_removed(sk, hdev, &cp->addr.bdaddr,
5984 cp->addr.type);
5985 goto complete;
5986 }
5987
Marcel Holtmann2faade52014-06-29 19:44:03 +02005988 if (cp->addr.type == BDADDR_LE_PUBLIC)
5989 addr_type = ADDR_LE_DEV_PUBLIC;
5990 else
5991 addr_type = ADDR_LE_DEV_RANDOM;
5992
Johan Hedbergc71593d2014-07-02 17:37:28 +03005993 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5994 addr_type);
5995 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005996 err = cmd->cmd_complete(cmd,
5997 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005998 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005999 goto unlock;
6000 }
6001
6002 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006003 err = cmd->cmd_complete(cmd,
6004 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006005 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006006 goto unlock;
6007 }
6008
Johan Hedbergd1dbf122014-07-04 16:17:23 +03006009 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006010 list_del(&params->list);
6011 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006012 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02006013
6014 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006015 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03006016 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03006017 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03006018
Marcel Holtmann2faade52014-06-29 19:44:03 +02006019 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006020 err = cmd->cmd_complete(cmd,
6021 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006022 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006023 goto unlock;
6024 }
6025
Johan Hedberg66593582014-07-09 12:59:14 +03006026 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
6027 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
6028 list_del(&b->list);
6029 kfree(b);
6030 }
6031
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006032 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006033
Johan Hedberg19de0822014-07-06 13:06:51 +03006034 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
6035 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
6036 continue;
6037 device_removed(sk, hdev, &p->addr, p->addr_type);
6038 list_del(&p->action);
6039 list_del(&p->list);
6040 kfree(p);
6041 }
6042
6043 BT_DBG("All LE connection parameters were removed");
6044
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006045 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006046 }
6047
Johan Hedberg66593582014-07-09 12:59:14 +03006048complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006049 err = hci_req_run(&req, remove_device_complete);
6050 if (err < 0) {
6051 /* ENODATA means no HCI commands were needed (e.g. if
6052 * the adapter is powered off).
6053 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006054 if (err == -ENODATA)
6055 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006056 mgmt_pending_remove(cmd);
6057 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006058
6059unlock:
6060 hci_dev_unlock(hdev);
6061 return err;
6062}
6063
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006064static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
6065 u16 len)
6066{
6067 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03006068 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
6069 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006070 u16 param_count, expected_len;
6071 int i;
6072
6073 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006074 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6075 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006076
6077 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006078 if (param_count > max_param_count) {
6079 BT_ERR("load_conn_param: too big param_count value %u",
6080 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02006081 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6082 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006083 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006084
6085 expected_len = sizeof(*cp) + param_count *
6086 sizeof(struct mgmt_conn_param);
6087 if (expected_len != len) {
6088 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
6089 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02006090 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6091 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006092 }
6093
6094 BT_DBG("%s param_count %u", hdev->name, param_count);
6095
6096 hci_dev_lock(hdev);
6097
6098 hci_conn_params_clear_disabled(hdev);
6099
6100 for (i = 0; i < param_count; i++) {
6101 struct mgmt_conn_param *param = &cp->params[i];
6102 struct hci_conn_params *hci_param;
6103 u16 min, max, latency, timeout;
6104 u8 addr_type;
6105
6106 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6107 param->addr.type);
6108
6109 if (param->addr.type == BDADDR_LE_PUBLIC) {
6110 addr_type = ADDR_LE_DEV_PUBLIC;
6111 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6112 addr_type = ADDR_LE_DEV_RANDOM;
6113 } else {
6114 BT_ERR("Ignoring invalid connection parameters");
6115 continue;
6116 }
6117
6118 min = le16_to_cpu(param->min_interval);
6119 max = le16_to_cpu(param->max_interval);
6120 latency = le16_to_cpu(param->latency);
6121 timeout = le16_to_cpu(param->timeout);
6122
6123 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6124 min, max, latency, timeout);
6125
6126 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6127 BT_ERR("Ignoring invalid connection parameters");
6128 continue;
6129 }
6130
6131 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6132 addr_type);
6133 if (!hci_param) {
6134 BT_ERR("Failed to add connection parameters");
6135 continue;
6136 }
6137
6138 hci_param->conn_min_interval = min;
6139 hci_param->conn_max_interval = max;
6140 hci_param->conn_latency = latency;
6141 hci_param->supervision_timeout = timeout;
6142 }
6143
6144 hci_dev_unlock(hdev);
6145
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006146 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6147 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006148}
6149
Marcel Holtmanndbece372014-07-04 18:11:55 +02006150static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6151 void *data, u16 len)
6152{
6153 struct mgmt_cp_set_external_config *cp = data;
6154 bool changed;
6155 int err;
6156
6157 BT_DBG("%s", hdev->name);
6158
6159 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006160 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6161 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006162
6163 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006164 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6165 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006166
6167 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006168 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6169 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006170
6171 hci_dev_lock(hdev);
6172
6173 if (cp->config)
Marcel Holtmann238be782015-03-13 02:11:06 -07006174 changed = !hci_dev_test_and_set_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006175 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07006176 changed = hci_dev_test_and_clear_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006177
6178 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6179 if (err < 0)
6180 goto unlock;
6181
6182 if (!changed)
6183 goto unlock;
6184
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006185 err = new_options(hdev, sk);
6186
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006187 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
Marcel Holtmanndbece372014-07-04 18:11:55 +02006188 mgmt_index_removed(hdev);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006189
Marcel Holtmann516018a2015-03-13 02:11:04 -07006190 if (hci_dev_test_and_change_flag(hdev, HCI_UNCONFIGURED)) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006191 hci_dev_set_flag(hdev, HCI_CONFIG);
6192 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006193
6194 queue_work(hdev->req_workqueue, &hdev->power_on);
6195 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006196 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006197 mgmt_index_added(hdev);
6198 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006199 }
6200
6201unlock:
6202 hci_dev_unlock(hdev);
6203 return err;
6204}
6205
Marcel Holtmann9713c172014-07-06 12:11:15 +02006206static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6207 void *data, u16 len)
6208{
6209 struct mgmt_cp_set_public_address *cp = data;
6210 bool changed;
6211 int err;
6212
6213 BT_DBG("%s", hdev->name);
6214
6215 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006216 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6217 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006218
6219 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006220 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6221 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006222
6223 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006224 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6225 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006226
6227 hci_dev_lock(hdev);
6228
6229 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6230 bacpy(&hdev->public_addr, &cp->bdaddr);
6231
6232 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6233 if (err < 0)
6234 goto unlock;
6235
6236 if (!changed)
6237 goto unlock;
6238
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006239 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann9713c172014-07-06 12:11:15 +02006240 err = new_options(hdev, sk);
6241
6242 if (is_configured(hdev)) {
6243 mgmt_index_removed(hdev);
6244
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006245 hci_dev_clear_flag(hdev, HCI_UNCONFIGURED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006246
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006247 hci_dev_set_flag(hdev, HCI_CONFIG);
6248 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006249
6250 queue_work(hdev->req_workqueue, &hdev->power_on);
6251 }
6252
6253unlock:
6254 hci_dev_unlock(hdev);
6255 return err;
6256}
6257
Marcel Holtmannbea41602015-03-14 22:43:17 -07006258static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6259 u8 data_len)
6260{
6261 eir[eir_len++] = sizeof(type) + data_len;
6262 eir[eir_len++] = type;
6263 memcpy(&eir[eir_len], data, data_len);
6264 eir_len += data_len;
6265
6266 return eir_len;
6267}
6268
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006269static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
6270 void *data, u16 data_len)
6271{
6272 struct mgmt_rp_read_adv_features *rp;
6273 size_t rp_len;
6274 int err;
6275
6276 BT_DBG("%s", hdev->name);
6277
6278 hci_dev_lock(hdev);
6279
6280 rp_len = sizeof(*rp);
6281 rp = kmalloc(rp_len, GFP_ATOMIC);
6282 if (!rp) {
6283 hci_dev_unlock(hdev);
6284 return -ENOMEM;
6285 }
6286
6287 rp->supported_flags = cpu_to_le32(0);
6288 rp->max_adv_data_len = 31;
6289 rp->max_scan_rsp_len = 31;
6290 rp->max_instances = 0;
6291 rp->num_instances = 0;
6292
6293 hci_dev_unlock(hdev);
6294
6295 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6296 MGMT_STATUS_SUCCESS, rp, rp_len);
6297
6298 kfree(rp);
6299
6300 return err;
6301}
6302
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006303static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006304 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006305 { read_version, MGMT_READ_VERSION_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006306 HCI_MGMT_NO_HDEV |
6307 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006308 { read_commands, MGMT_READ_COMMANDS_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006309 HCI_MGMT_NO_HDEV |
6310 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006311 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006312 HCI_MGMT_NO_HDEV |
6313 HCI_MGMT_UNTRUSTED },
6314 { read_controller_info, MGMT_READ_INFO_SIZE,
6315 HCI_MGMT_UNTRUSTED },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006316 { set_powered, MGMT_SETTING_SIZE },
6317 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE },
6318 { set_connectable, MGMT_SETTING_SIZE },
6319 { set_fast_connectable, MGMT_SETTING_SIZE },
6320 { set_bondable, MGMT_SETTING_SIZE },
6321 { set_link_security, MGMT_SETTING_SIZE },
6322 { set_ssp, MGMT_SETTING_SIZE },
6323 { set_hs, MGMT_SETTING_SIZE },
6324 { set_le, MGMT_SETTING_SIZE },
6325 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE },
6326 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE },
6327 { add_uuid, MGMT_ADD_UUID_SIZE },
6328 { remove_uuid, MGMT_REMOVE_UUID_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006329 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
6330 HCI_MGMT_VAR_LEN },
6331 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
6332 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006333 { disconnect, MGMT_DISCONNECT_SIZE },
6334 { get_connections, MGMT_GET_CONNECTIONS_SIZE },
6335 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE },
6336 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE },
6337 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE },
6338 { pair_device, MGMT_PAIR_DEVICE_SIZE },
6339 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE },
6340 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE },
6341 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE },
6342 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
6343 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE },
6344 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006345 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
6346 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
6347 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006348 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
6349 { start_discovery, MGMT_START_DISCOVERY_SIZE },
6350 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE },
6351 { confirm_name, MGMT_CONFIRM_NAME_SIZE },
6352 { block_device, MGMT_BLOCK_DEVICE_SIZE },
6353 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE },
6354 { set_device_id, MGMT_SET_DEVICE_ID_SIZE },
6355 { set_advertising, MGMT_SETTING_SIZE },
6356 { set_bredr, MGMT_SETTING_SIZE },
6357 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE },
6358 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE },
6359 { set_secure_conn, MGMT_SETTING_SIZE },
6360 { set_debug_keys, MGMT_SETTING_SIZE },
6361 { set_privacy, MGMT_SET_PRIVACY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006362 { load_irks, MGMT_LOAD_IRKS_SIZE,
6363 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006364 { get_conn_info, MGMT_GET_CONN_INFO_SIZE },
6365 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE },
6366 { add_device, MGMT_ADD_DEVICE_SIZE },
6367 { remove_device, MGMT_REMOVE_DEVICE_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006368 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
6369 HCI_MGMT_VAR_LEN },
6370 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006371 HCI_MGMT_NO_HDEV |
6372 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006373 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006374 HCI_MGMT_UNCONFIGURED |
6375 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006376 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
6377 HCI_MGMT_UNCONFIGURED },
6378 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
6379 HCI_MGMT_UNCONFIGURED },
6380 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
6381 HCI_MGMT_VAR_LEN },
Marcel Holtmann96f14742015-03-14 19:27:57 -07006382 { NULL },
6383 { read_ext_index_list, MGMT_READ_EXT_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006384 HCI_MGMT_NO_HDEV |
6385 HCI_MGMT_UNTRUSTED },
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006386 { read_adv_features, MGMT_READ_ADV_FEATURES_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006387};
6388
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006389int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk,
6390 struct msghdr *msg, size_t msglen)
Johan Hedberg03811012010-12-08 00:21:06 +02006391{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006392 void *buf;
6393 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02006394 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01006395 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006396 struct hci_dev *hdev = NULL;
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006397 const struct hci_mgmt_handler *handler;
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006398 bool var_len, no_hdev;
Johan Hedberg03811012010-12-08 00:21:06 +02006399 int err;
6400
6401 BT_DBG("got %zu bytes", msglen);
6402
6403 if (msglen < sizeof(*hdr))
6404 return -EINVAL;
6405
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03006406 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02006407 if (!buf)
6408 return -ENOMEM;
6409
Al Viro6ce8e9c2014-04-06 21:25:44 -04006410 if (memcpy_from_msg(buf, msg, msglen)) {
Johan Hedberg03811012010-12-08 00:21:06 +02006411 err = -EFAULT;
6412 goto done;
6413 }
6414
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006415 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07006416 opcode = __le16_to_cpu(hdr->opcode);
6417 index = __le16_to_cpu(hdr->index);
6418 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02006419
6420 if (len != msglen - sizeof(*hdr)) {
6421 err = -EINVAL;
6422 goto done;
6423 }
6424
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006425 if (opcode >= chan->handler_count ||
6426 chan->handlers[opcode].func == NULL) {
6427 BT_DBG("Unknown op %u", opcode);
Johan Hedberga69e8372015-03-06 21:08:53 +02006428 err = mgmt_cmd_status(sk, index, opcode,
6429 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006430 goto done;
6431 }
6432
6433 handler = &chan->handlers[opcode];
6434
Marcel Holtmannc927a102015-03-14 19:28:03 -07006435 if (!hci_sock_test_flag(sk, HCI_SOCK_TRUSTED) &&
6436 !(handler->flags & HCI_MGMT_UNTRUSTED)) {
6437 err = mgmt_cmd_status(sk, index, opcode,
6438 MGMT_STATUS_PERMISSION_DENIED);
6439 goto done;
6440 }
6441
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006442 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006443 hdev = hci_dev_get(index);
6444 if (!hdev) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006445 err = mgmt_cmd_status(sk, index, opcode,
6446 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006447 goto done;
6448 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006449
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006450 if (hci_dev_test_flag(hdev, HCI_SETUP) ||
6451 hci_dev_test_flag(hdev, HCI_CONFIG) ||
6452 hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006453 err = mgmt_cmd_status(sk, index, opcode,
6454 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006455 goto done;
6456 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006457
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006458 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006459 !(handler->flags & HCI_MGMT_UNCONFIGURED)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006460 err = mgmt_cmd_status(sk, index, opcode,
6461 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006462 goto done;
6463 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006464 }
6465
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006466 no_hdev = (handler->flags & HCI_MGMT_NO_HDEV);
6467 if (no_hdev != !hdev) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006468 err = mgmt_cmd_status(sk, index, opcode,
6469 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006470 goto done;
6471 }
6472
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006473 var_len = (handler->flags & HCI_MGMT_VAR_LEN);
6474 if ((var_len && len < handler->data_len) ||
6475 (!var_len && len != handler->data_len)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006476 err = mgmt_cmd_status(sk, index, opcode,
6477 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02006478 goto done;
6479 }
6480
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006481 if (hdev)
6482 mgmt_init_hdev(sk, hdev);
6483
6484 cp = buf + sizeof(*hdr);
6485
Johan Hedbergbe22b542012-03-01 22:24:41 +02006486 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02006487 if (err < 0)
6488 goto done;
6489
Johan Hedberg03811012010-12-08 00:21:06 +02006490 err = msglen;
6491
6492done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006493 if (hdev)
6494 hci_dev_put(hdev);
6495
Johan Hedberg03811012010-12-08 00:21:06 +02006496 kfree(buf);
6497 return err;
6498}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006499
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006500void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006501{
Marcel Holtmannced85542015-03-14 19:27:56 -07006502 struct mgmt_ev_ext_index ev;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006503
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006504 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6505 return;
6506
Marcel Holtmannf9207332015-03-14 19:27:55 -07006507 switch (hdev->dev_type) {
6508 case HCI_BREDR:
6509 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
6510 mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev,
6511 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07006512 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006513 } else {
6514 mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
6515 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07006516 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006517 }
6518 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07006519 case HCI_AMP:
6520 ev.type = 0x02;
6521 break;
6522 default:
6523 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006524 }
Marcel Holtmannced85542015-03-14 19:27:56 -07006525
6526 ev.bus = hdev->bus;
6527
6528 mgmt_index_event(MGMT_EV_EXT_INDEX_ADDED, hdev, &ev, sizeof(ev),
6529 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006530}
6531
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006532void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006533{
Marcel Holtmannced85542015-03-14 19:27:56 -07006534 struct mgmt_ev_ext_index ev;
Johan Hedberg5f159032012-03-02 03:13:19 +02006535 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006536
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006537 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6538 return;
6539
Marcel Holtmannf9207332015-03-14 19:27:55 -07006540 switch (hdev->dev_type) {
6541 case HCI_BREDR:
6542 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006543
Marcel Holtmannf9207332015-03-14 19:27:55 -07006544 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
6545 mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev,
6546 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07006547 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006548 } else {
6549 mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
6550 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07006551 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006552 }
6553 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07006554 case HCI_AMP:
6555 ev.type = 0x02;
6556 break;
6557 default:
6558 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006559 }
Marcel Holtmannced85542015-03-14 19:27:56 -07006560
6561 ev.bus = hdev->bus;
6562
6563 mgmt_index_event(MGMT_EV_EXT_INDEX_REMOVED, hdev, &ev, sizeof(ev),
6564 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006565}
6566
Andre Guedes6046dc32014-02-26 20:21:51 -03006567/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02006568static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03006569{
Johan Hedberg2cf22212014-12-19 22:26:00 +02006570 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03006571 struct hci_conn_params *p;
6572
6573 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006574 /* Needed for AUTO_OFF case where might not "really"
6575 * have been powered off.
6576 */
6577 list_del_init(&p->action);
6578
6579 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006580 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006581 case HCI_AUTO_CONN_ALWAYS:
6582 list_add(&p->action, &hdev->pend_le_conns);
6583 break;
6584 case HCI_AUTO_CONN_REPORT:
6585 list_add(&p->action, &hdev->pend_le_reports);
6586 break;
6587 default:
6588 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006589 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006590 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006591
Johan Hedberg2cf22212014-12-19 22:26:00 +02006592 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03006593}
6594
Marcel Holtmann1904a852015-01-11 13:50:44 -08006595static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05006596{
6597 struct cmd_lookup match = { NULL, hdev };
6598
6599 BT_DBG("status 0x%02x", status);
6600
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08006601 if (!status) {
6602 /* Register the available SMP channels (BR/EDR and LE) only
6603 * when successfully powering on the controller. This late
6604 * registration is required so that LE SMP can clearly
6605 * decide if the public address or static address is used.
6606 */
6607 smp_register(hdev);
6608 }
6609
Johan Hedberg229ab392013-03-15 17:06:53 -05006610 hci_dev_lock(hdev);
6611
6612 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6613
6614 new_settings(hdev, match.sk);
6615
6616 hci_dev_unlock(hdev);
6617
6618 if (match.sk)
6619 sock_put(match.sk);
6620}
6621
Johan Hedberg70da6242013-03-15 17:06:51 -05006622static int powered_update_hci(struct hci_dev *hdev)
6623{
Johan Hedberg890ea892013-03-15 17:06:52 -05006624 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006625 u8 link_sec;
6626
Johan Hedberg890ea892013-03-15 17:06:52 -05006627 hci_req_init(&req, hdev);
6628
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006629 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
Johan Hedberg70da6242013-03-15 17:06:51 -05006630 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006631 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05006632
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006633 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05006634
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006635 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
6636 u8 support = 0x01;
6637
6638 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
6639 sizeof(support), &support);
6640 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02006641 }
6642
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006643 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
Johan Hedbergc73eee92013-04-19 18:35:21 +03006644 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006645 struct hci_cp_write_le_host_supported cp;
6646
Marcel Holtmann32226e42014-07-24 20:04:16 +02006647 cp.le = 0x01;
6648 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006649
6650 /* Check first if we already have the right
6651 * host state (host features set)
6652 */
6653 if (cp.le != lmp_host_le_capable(hdev) ||
6654 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006655 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6656 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006657 }
6658
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006659 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006660 /* Make sure the controller has a good default for
6661 * advertising data. This also applies to the case
6662 * where BR/EDR was toggled during the AUTO_OFF phase.
6663 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006664 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006665 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006666 update_scan_rsp_data(&req);
6667 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006668
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006669 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006670 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02006671
6672 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006673 }
6674
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006675 link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg70da6242013-03-15 17:06:51 -05006676 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006677 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6678 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006679
6680 if (lmp_bredr_capable(hdev)) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006681 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg406ef2a2015-03-10 20:14:27 +02006682 write_fast_connectable(&req, true);
6683 else
6684 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02006685 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006686 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006687 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006688 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006689 }
6690
Johan Hedberg229ab392013-03-15 17:06:53 -05006691 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006692}
6693
Johan Hedberg744cf192011-11-08 20:40:14 +02006694int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006695{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006696 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02006697 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006698 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006699
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006700 if (!hci_dev_test_flag(hdev, HCI_MGMT))
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006701 return 0;
6702
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006703 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006704 if (powered_update_hci(hdev) == 0)
6705 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006706
Johan Hedberg229ab392013-03-15 17:06:53 -05006707 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6708 &match);
6709 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006710 }
6711
Johan Hedberg229ab392013-03-15 17:06:53 -05006712 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02006713
6714 /* If the power off is because of hdev unregistration let
6715 * use the appropriate INVALID_INDEX status. Otherwise use
6716 * NOT_POWERED. We cover both scenarios here since later in
6717 * mgmt_index_removed() any hci_conn callbacks will have already
6718 * been triggered, potentially causing misleading DISCONNECTED
6719 * status responses.
6720 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006721 if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
Johan Hedberg98459042014-12-12 11:15:21 +02006722 status = MGMT_STATUS_INVALID_INDEX;
6723 else
6724 status = MGMT_STATUS_NOT_POWERED;
6725
6726 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05006727
6728 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07006729 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6730 zero_cod, sizeof(zero_cod), NULL);
Johan Hedberg229ab392013-03-15 17:06:53 -05006731
6732new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006733 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006734
6735 if (match.sk)
6736 sock_put(match.sk);
6737
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006738 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006739}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006740
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006741void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006742{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006743 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006744 u8 status;
6745
6746 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6747 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006748 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006749
6750 if (err == -ERFKILL)
6751 status = MGMT_STATUS_RFKILLED;
6752 else
6753 status = MGMT_STATUS_FAILED;
6754
Johan Hedberga69e8372015-03-06 21:08:53 +02006755 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006756
6757 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006758}
6759
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006760void mgmt_discoverable_timeout(struct hci_dev *hdev)
6761{
6762 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006763
6764 hci_dev_lock(hdev);
6765
6766 /* When discoverable timeout triggers, then just make sure
6767 * the limited discoverable flag is cleared. Even in the case
6768 * of a timeout triggered from general discoverable, it is
6769 * safe to unconditionally clear the flag.
6770 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006771 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
6772 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006773
6774 hci_req_init(&req, hdev);
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006775 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg4b580612013-10-19 23:38:21 +03006776 u8 scan = SCAN_PAGE;
6777 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6778 sizeof(scan), &scan);
6779 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006780 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006781 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006782 hci_req_run(&req, NULL);
6783
6784 hdev->discov_timeout = 0;
6785
Johan Hedberg9a43e252013-10-20 19:00:07 +03006786 new_settings(hdev, NULL);
6787
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006788 hci_dev_unlock(hdev);
6789}
6790
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006791void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6792 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006793{
Johan Hedberg86742e12011-11-07 23:13:38 +02006794 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006795
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006796 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006797
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006798 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006799 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006800 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006801 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006802 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006803 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006804
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006805 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006806}
Johan Hedbergf7520542011-01-20 12:34:39 +02006807
Johan Hedbergd7b25452014-05-23 13:19:53 +03006808static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6809{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006810 switch (ltk->type) {
6811 case SMP_LTK:
6812 case SMP_LTK_SLAVE:
6813 if (ltk->authenticated)
6814 return MGMT_LTK_AUTHENTICATED;
6815 return MGMT_LTK_UNAUTHENTICATED;
6816 case SMP_LTK_P256:
6817 if (ltk->authenticated)
6818 return MGMT_LTK_P256_AUTH;
6819 return MGMT_LTK_P256_UNAUTH;
6820 case SMP_LTK_P256_DEBUG:
6821 return MGMT_LTK_P256_DEBUG;
6822 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006823
6824 return MGMT_LTK_UNAUTHENTICATED;
6825}
6826
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006827void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006828{
6829 struct mgmt_ev_new_long_term_key ev;
6830
6831 memset(&ev, 0, sizeof(ev));
6832
Marcel Holtmann5192d302014-02-19 17:11:58 -08006833 /* Devices using resolvable or non-resolvable random addresses
6834 * without providing an indentity resolving key don't require
6835 * to store long term keys. Their addresses will change the
6836 * next time around.
6837 *
6838 * Only when a remote device provides an identity address
6839 * make sure the long term key is stored. If the remote
6840 * identity is known, the long term keys are internally
6841 * mapped to the identity address. So allow static random
6842 * and public addresses here.
6843 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006844 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6845 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6846 ev.store_hint = 0x00;
6847 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006848 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006849
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006850 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006851 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006852 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006853 ev.key.enc_size = key->enc_size;
6854 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006855 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006856
Johan Hedberg2ceba532014-06-16 19:25:16 +03006857 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006858 ev.key.master = 1;
6859
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006860 memcpy(ev.key.val, key->val, sizeof(key->val));
6861
Marcel Holtmann083368f2013-10-15 14:26:29 -07006862 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006863}
6864
Johan Hedberg95fbac82014-02-19 15:18:31 +02006865void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6866{
6867 struct mgmt_ev_new_irk ev;
6868
6869 memset(&ev, 0, sizeof(ev));
6870
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006871 /* For identity resolving keys from devices that are already
6872 * using a public address or static random address, do not
6873 * ask for storing this key. The identity resolving key really
6874 * is only mandatory for devices using resovlable random
6875 * addresses.
6876 *
6877 * Storing all identity resolving keys has the downside that
6878 * they will be also loaded on next boot of they system. More
6879 * identity resolving keys, means more time during scanning is
6880 * needed to actually resolve these addresses.
6881 */
6882 if (bacmp(&irk->rpa, BDADDR_ANY))
6883 ev.store_hint = 0x01;
6884 else
6885 ev.store_hint = 0x00;
6886
Johan Hedberg95fbac82014-02-19 15:18:31 +02006887 bacpy(&ev.rpa, &irk->rpa);
6888 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6889 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6890 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6891
6892 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6893}
6894
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006895void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6896 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006897{
6898 struct mgmt_ev_new_csrk ev;
6899
6900 memset(&ev, 0, sizeof(ev));
6901
6902 /* Devices using resolvable or non-resolvable random addresses
6903 * without providing an indentity resolving key don't require
6904 * to store signature resolving keys. Their addresses will change
6905 * the next time around.
6906 *
6907 * Only when a remote device provides an identity address
6908 * make sure the signature resolving key is stored. So allow
6909 * static random and public addresses here.
6910 */
6911 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6912 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6913 ev.store_hint = 0x00;
6914 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006915 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006916
6917 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6918 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02006919 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006920 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6921
6922 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6923}
6924
Andre Guedesffb5a8272014-07-01 18:10:11 -03006925void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006926 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6927 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006928{
6929 struct mgmt_ev_new_conn_param ev;
6930
Johan Hedbergc103aea2014-07-02 17:37:34 +03006931 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6932 return;
6933
Andre Guedesffb5a8272014-07-01 18:10:11 -03006934 memset(&ev, 0, sizeof(ev));
6935 bacpy(&ev.addr.bdaddr, bdaddr);
6936 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006937 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006938 ev.min_interval = cpu_to_le16(min_interval);
6939 ev.max_interval = cpu_to_le16(max_interval);
6940 ev.latency = cpu_to_le16(latency);
6941 ev.timeout = cpu_to_le16(timeout);
6942
6943 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6944}
6945
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006946void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6947 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006948{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006949 char buf[512];
6950 struct mgmt_ev_device_connected *ev = (void *) buf;
6951 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006952
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006953 bacpy(&ev->addr.bdaddr, &conn->dst);
6954 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006955
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006956 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006957
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006958 /* We must ensure that the EIR Data fields are ordered and
6959 * unique. Keep it simple for now and avoid the problem by not
6960 * adding any BR/EDR data to the LE adv.
6961 */
6962 if (conn->le_adv_data_len > 0) {
6963 memcpy(&ev->eir[eir_len],
6964 conn->le_adv_data, conn->le_adv_data_len);
6965 eir_len = conn->le_adv_data_len;
6966 } else {
6967 if (name_len > 0)
6968 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6969 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006970
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006971 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006972 eir_len = eir_append_data(ev->eir, eir_len,
6973 EIR_CLASS_OF_DEV,
6974 conn->dev_class, 3);
6975 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006976
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006977 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006978
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006979 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6980 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006981}
6982
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006983static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006984{
Johan Hedberg8962ee72011-01-20 12:40:27 +02006985 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006986
Johan Hedbergf5818c22014-12-05 13:36:02 +02006987 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006988
6989 *sk = cmd->sk;
6990 sock_hold(*sk);
6991
Johan Hedberga664b5b2011-02-19 12:06:02 -03006992 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006993}
6994
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006995static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006996{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006997 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006998 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006999
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007000 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
7001
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02007002 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02007003 mgmt_pending_remove(cmd);
7004}
7005
Johan Hedberg84c61d92014-08-01 11:13:30 +03007006bool mgmt_powering_down(struct hci_dev *hdev)
7007{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007008 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03007009 struct mgmt_mode *cp;
7010
7011 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
7012 if (!cmd)
7013 return false;
7014
7015 cp = cmd->param;
7016 if (!cp->val)
7017 return true;
7018
7019 return false;
7020}
7021
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007022void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007023 u8 link_type, u8 addr_type, u8 reason,
7024 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02007025{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007026 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007027 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007028
Johan Hedberg84c61d92014-08-01 11:13:30 +03007029 /* The connection is still in hci_conn_hash so test for 1
7030 * instead of 0 to know if this is the last one.
7031 */
7032 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7033 cancel_delayed_work(&hdev->power_off);
7034 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02007035 }
7036
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007037 if (!mgmt_connected)
7038 return;
7039
Andre Guedes57eb7762013-10-30 19:01:41 -03007040 if (link_type != ACL_LINK && link_type != LE_LINK)
7041 return;
7042
Johan Hedberg744cf192011-11-08 20:40:14 +02007043 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02007044
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007045 bacpy(&ev.addr.bdaddr, bdaddr);
7046 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7047 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02007048
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007049 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007050
7051 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01007052 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007053
Johan Hedberg124f6e32012-02-09 13:50:12 +02007054 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007055 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007056}
7057
Marcel Holtmann78929242013-10-06 23:55:47 -07007058void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
7059 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007060{
Andre Guedes3655bba2013-10-30 19:01:40 -03007061 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
7062 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007063 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007064
Jefferson Delfes36a75f12012-09-18 13:36:54 -04007065 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
7066 hdev);
7067
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007068 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007069 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07007070 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007071
Andre Guedes3655bba2013-10-30 19:01:40 -03007072 cp = cmd->param;
7073
7074 if (bacmp(bdaddr, &cp->addr.bdaddr))
7075 return;
7076
7077 if (cp->addr.type != bdaddr_type)
7078 return;
7079
Johan Hedbergf5818c22014-12-05 13:36:02 +02007080 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007081 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02007082}
Johan Hedberg17d5c042011-01-22 06:09:08 +02007083
Marcel Holtmann445608d2013-10-06 23:55:48 -07007084void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7085 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02007086{
7087 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02007088
Johan Hedberg84c61d92014-08-01 11:13:30 +03007089 /* The connection is still in hci_conn_hash so test for 1
7090 * instead of 0 to know if this is the last one.
7091 */
7092 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7093 cancel_delayed_work(&hdev->power_off);
7094 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02007095 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02007096
Johan Hedberg4c659c32011-11-07 23:13:39 +02007097 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007098 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02007099 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007100
Marcel Holtmann445608d2013-10-06 23:55:48 -07007101 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007102}
Johan Hedberg980e1a52011-01-22 06:10:07 +02007103
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007104void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007105{
7106 struct mgmt_ev_pin_code_request ev;
7107
Johan Hedbergd8457692012-02-17 14:24:57 +02007108 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007109 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02007110 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007111
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007112 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007113}
7114
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007115void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7116 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007117{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007118 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007119
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007120 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007121 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007122 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007123
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007124 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007125 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007126}
7127
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007128void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7129 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007130{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007131 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007132
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007133 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007134 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007135 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007136
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007137 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007138 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007139}
Johan Hedberga5c29682011-02-19 12:05:57 -03007140
Johan Hedberg744cf192011-11-08 20:40:14 +02007141int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02007142 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007143 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03007144{
7145 struct mgmt_ev_user_confirm_request ev;
7146
Johan Hedberg744cf192011-11-08 20:40:14 +02007147 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03007148
Johan Hedberg272d90d2012-02-09 15:26:12 +02007149 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007150 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07007151 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02007152 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03007153
Johan Hedberg744cf192011-11-08 20:40:14 +02007154 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007155 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03007156}
7157
Johan Hedberg272d90d2012-02-09 15:26:12 +02007158int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007159 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08007160{
7161 struct mgmt_ev_user_passkey_request ev;
7162
7163 BT_DBG("%s", hdev->name);
7164
Johan Hedberg272d90d2012-02-09 15:26:12 +02007165 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007166 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08007167
7168 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007169 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08007170}
7171
Brian Gix0df4c182011-11-16 13:53:13 -08007172static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007173 u8 link_type, u8 addr_type, u8 status,
7174 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03007175{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007176 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03007177
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007178 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03007179 if (!cmd)
7180 return -ENOENT;
7181
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007182 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007183 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03007184
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007185 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03007186}
7187
Johan Hedberg744cf192011-11-08 20:40:14 +02007188int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007189 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007190{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007191 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007192 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007193}
7194
Johan Hedberg272d90d2012-02-09 15:26:12 +02007195int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007196 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007197{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007198 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007199 status,
7200 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007201}
Johan Hedberg2a611692011-02-19 12:06:00 -03007202
Brian Gix604086b2011-11-23 08:28:33 -08007203int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007204 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007205{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007206 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007207 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007208}
7209
Johan Hedberg272d90d2012-02-09 15:26:12 +02007210int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007211 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007212{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007213 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007214 status,
7215 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007216}
7217
Johan Hedberg92a25252012-09-06 18:39:26 +03007218int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7219 u8 link_type, u8 addr_type, u32 passkey,
7220 u8 entered)
7221{
7222 struct mgmt_ev_passkey_notify ev;
7223
7224 BT_DBG("%s", hdev->name);
7225
7226 bacpy(&ev.addr.bdaddr, bdaddr);
7227 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7228 ev.passkey = __cpu_to_le32(passkey);
7229 ev.entered = entered;
7230
7231 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7232}
7233
Johan Hedberge1e930f2014-09-08 17:09:49 -07007234void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007235{
7236 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007237 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007238 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007239
Johan Hedberge1e930f2014-09-08 17:09:49 -07007240 bacpy(&ev.addr.bdaddr, &conn->dst);
7241 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7242 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007243
Johan Hedberge1e930f2014-09-08 17:09:49 -07007244 cmd = find_pairing(conn);
7245
7246 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7247 cmd ? cmd->sk : NULL);
7248
Johan Hedberga511b352014-12-11 21:45:45 +02007249 if (cmd) {
7250 cmd->cmd_complete(cmd, status);
7251 mgmt_pending_remove(cmd);
7252 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007253}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007254
Marcel Holtmann464996a2013-10-15 14:26:24 -07007255void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007256{
7257 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007258 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007259
7260 if (status) {
7261 u8 mgmt_err = mgmt_status(status);
7262 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007263 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007264 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007265 }
7266
Marcel Holtmann464996a2013-10-15 14:26:24 -07007267 if (test_bit(HCI_AUTH, &hdev->flags))
Marcel Holtmann238be782015-03-13 02:11:06 -07007268 changed = !hci_dev_test_and_set_flag(hdev, HCI_LINK_SECURITY);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007269 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007270 changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02007271
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007272 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007273 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007274
Johan Hedberg47990ea2012-02-22 11:58:37 +02007275 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07007276 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007277
7278 if (match.sk)
7279 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007280}
7281
Johan Hedberg890ea892013-03-15 17:06:52 -05007282static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02007283{
Johan Hedberg890ea892013-03-15 17:06:52 -05007284 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007285 struct hci_cp_write_eir cp;
7286
Johan Hedberg976eb202012-10-24 21:12:01 +03007287 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007288 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007289
Johan Hedbergc80da272012-02-22 15:38:48 +02007290 memset(hdev->eir, 0, sizeof(hdev->eir));
7291
Johan Hedbergcacaf522012-02-21 00:52:42 +02007292 memset(&cp, 0, sizeof(cp));
7293
Johan Hedberg890ea892013-03-15 17:06:52 -05007294 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02007295}
7296
Marcel Holtmann3e248562013-10-15 14:26:25 -07007297void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007298{
7299 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05007300 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007301 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007302
7303 if (status) {
7304 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007305
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007306 if (enable && hci_dev_test_and_clear_flag(hdev,
7307 HCI_SSP_ENABLED)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007308 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007309 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007310 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007311
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007312 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
7313 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007314 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007315 }
7316
7317 if (enable) {
Marcel Holtmann238be782015-03-13 02:11:06 -07007318 changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007319 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007320 changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007321 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007322 changed = hci_dev_test_and_clear_flag(hdev,
7323 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007324 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007325 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007326 }
7327
7328 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
7329
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007330 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07007331 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007332
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02007333 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007334 sock_put(match.sk);
7335
Johan Hedberg890ea892013-03-15 17:06:52 -05007336 hci_req_init(&req, hdev);
7337
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007338 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
7339 if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03007340 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
7341 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05007342 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007343 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05007344 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007345 }
Johan Hedberg890ea892013-03-15 17:06:52 -05007346
7347 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007348}
7349
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007350static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02007351{
7352 struct cmd_lookup *match = data;
7353
Johan Hedberg90e70452012-02-23 23:09:40 +02007354 if (match->sk == NULL) {
7355 match->sk = cmd->sk;
7356 sock_hold(match->sk);
7357 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007358}
7359
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007360void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7361 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007362{
Johan Hedberg90e70452012-02-23 23:09:40 +02007363 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007364
Johan Hedberg92da6092013-03-15 17:06:55 -05007365 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7366 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7367 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007368
7369 if (!status)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007370 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
7371 dev_class, 3, NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007372
7373 if (match.sk)
7374 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007375}
7376
Marcel Holtmann7667da32013-10-15 14:26:27 -07007377void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007378{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007379 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007380 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007381
Johan Hedberg13928972013-03-15 17:07:00 -05007382 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007383 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007384
7385 memset(&ev, 0, sizeof(ev));
7386 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007387 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007388
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007389 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007390 if (!cmd) {
7391 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007392
Johan Hedberg13928972013-03-15 17:07:00 -05007393 /* If this is a HCI command related to powering on the
7394 * HCI dev don't send any mgmt signals.
7395 */
7396 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007397 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007398 }
7399
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007400 mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7401 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007402}
Szymon Jancc35938b2011-03-22 13:12:21 +01007403
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007404void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02007405 u8 *rand192, u8 *hash256, u8 *rand256,
7406 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01007407{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007408 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01007409
Johan Hedberg744cf192011-11-08 20:40:14 +02007410 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01007411
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007412 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01007413 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007414 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01007415
7416 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02007417 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
7418 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01007419 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007420 struct mgmt_rp_read_local_oob_data rp;
7421 size_t rp_size = sizeof(rp);
7422
7423 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
7424 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
7425
Johan Hedberg710f11c2014-05-26 11:21:22 +03007426 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007427 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02007428 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007429 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007430 rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007431 }
Johan Hedberg66f096f2015-02-02 13:23:42 +02007432
Johan Hedberg2a1afb52015-03-06 21:08:54 +02007433 mgmt_cmd_complete(cmd->sk, hdev->id,
7434 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7435 &rp, rp_size);
Szymon Jancc35938b2011-03-22 13:12:21 +01007436 }
7437
7438 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01007439}
Johan Hedberge17acd42011-03-30 23:57:16 +03007440
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007441static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7442{
7443 int i;
7444
7445 for (i = 0; i < uuid_count; i++) {
7446 if (!memcmp(uuid, uuids[i], 16))
7447 return true;
7448 }
7449
7450 return false;
7451}
7452
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007453static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7454{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007455 u16 parsed = 0;
7456
7457 while (parsed < eir_len) {
7458 u8 field_len = eir[0];
7459 u8 uuid[16];
7460 int i;
7461
7462 if (field_len == 0)
7463 break;
7464
7465 if (eir_len - parsed < field_len + 1)
7466 break;
7467
7468 switch (eir[1]) {
7469 case EIR_UUID16_ALL:
7470 case EIR_UUID16_SOME:
7471 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007472 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007473 uuid[13] = eir[i + 3];
7474 uuid[12] = eir[i + 2];
7475 if (has_uuid(uuid, uuid_count, uuids))
7476 return true;
7477 }
7478 break;
7479 case EIR_UUID32_ALL:
7480 case EIR_UUID32_SOME:
7481 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007482 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007483 uuid[15] = eir[i + 5];
7484 uuid[14] = eir[i + 4];
7485 uuid[13] = eir[i + 3];
7486 uuid[12] = eir[i + 2];
7487 if (has_uuid(uuid, uuid_count, uuids))
7488 return true;
7489 }
7490 break;
7491 case EIR_UUID128_ALL:
7492 case EIR_UUID128_SOME:
7493 for (i = 0; i + 17 <= field_len; i += 16) {
7494 memcpy(uuid, eir + i + 2, 16);
7495 if (has_uuid(uuid, uuid_count, uuids))
7496 return true;
7497 }
7498 break;
7499 }
7500
7501 parsed += field_len + 1;
7502 eir += field_len + 1;
7503 }
7504
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007505 return false;
7506}
7507
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007508static void restart_le_scan(struct hci_dev *hdev)
7509{
7510 /* If controller is not scanning we are done. */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007511 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007512 return;
7513
7514 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
7515 hdev->discovery.scan_start +
7516 hdev->discovery.scan_duration))
7517 return;
7518
7519 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
7520 DISCOV_LE_RESTART_DELAY);
7521}
7522
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007523static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
7524 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
7525{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007526 /* If a RSSI threshold has been specified, and
7527 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
7528 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
7529 * is set, let it through for further processing, as we might need to
7530 * restart the scan.
7531 *
7532 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
7533 * the results are also dropped.
7534 */
7535 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7536 (rssi == HCI_RSSI_INVALID ||
7537 (rssi < hdev->discovery.rssi &&
7538 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
7539 return false;
7540
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007541 if (hdev->discovery.uuid_count != 0) {
7542 /* If a list of UUIDs is provided in filter, results with no
7543 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007544 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007545 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
7546 hdev->discovery.uuids) &&
7547 !eir_has_uuids(scan_rsp, scan_rsp_len,
7548 hdev->discovery.uuid_count,
7549 hdev->discovery.uuids))
7550 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007551 }
7552
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007553 /* If duplicate filtering does not report RSSI changes, then restart
7554 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007555 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007556 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
7557 restart_le_scan(hdev);
7558
7559 /* Validate RSSI value against the RSSI threshold once more. */
7560 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7561 rssi < hdev->discovery.rssi)
7562 return false;
7563 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007564
7565 return true;
7566}
7567
Marcel Holtmann901801b2013-10-06 23:55:51 -07007568void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02007569 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7570 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007571{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007572 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007573 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007574 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03007575
Johan Hedberg75ce2082014-07-02 22:42:01 +03007576 /* Don't send events for a non-kernel initiated discovery. With
7577 * LE one exception is if we have pend_le_reports > 0 in which
7578 * case we're doing passive scanning and want these events.
7579 */
7580 if (!hci_discovery_active(hdev)) {
7581 if (link_type == ACL_LINK)
7582 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007583 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007584 return;
7585 }
Andre Guedes12602d02013-04-30 15:29:40 -03007586
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08007587 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007588 /* We are using service discovery */
7589 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
7590 scan_rsp_len))
7591 return;
7592 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007593
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007594 /* Make sure that the buffer is big enough. The 5 extra bytes
7595 * are for the potential CoD field.
7596 */
7597 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007598 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007599
Johan Hedberg1dc06092012-01-15 21:01:23 +02007600 memset(buf, 0, sizeof(buf));
7601
Marcel Holtmannda25cf62014-12-05 13:03:35 +01007602 /* In case of device discovery with BR/EDR devices (pre 1.2), the
7603 * RSSI value was reported as 0 when not available. This behavior
7604 * is kept when using device discovery. This is required for full
7605 * backwards compatibility with the API.
7606 *
7607 * However when using service discovery, the value 127 will be
7608 * returned when the RSSI is not available.
7609 */
Szymon Janc91200e92015-01-22 16:57:05 +01007610 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
7611 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01007612 rssi = 0;
7613
Johan Hedberg841c5642014-07-07 12:45:54 +03007614 bacpy(&ev->addr.bdaddr, bdaddr);
7615 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007616 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007617 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007618
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007619 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007620 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007621 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03007622
Johan Hedberg1dc06092012-01-15 21:01:23 +02007623 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7624 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007625 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007626
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007627 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007628 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007629 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007630
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007631 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7632 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007633
Marcel Holtmann901801b2013-10-06 23:55:51 -07007634 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007635}
Johan Hedberga88a9652011-03-30 13:18:12 +03007636
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007637void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7638 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007639{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007640 struct mgmt_ev_device_found *ev;
7641 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7642 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007643
Johan Hedbergb644ba32012-01-17 21:48:47 +02007644 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007645
Johan Hedbergb644ba32012-01-17 21:48:47 +02007646 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007647
Johan Hedbergb644ba32012-01-17 21:48:47 +02007648 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007649 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007650 ev->rssi = rssi;
7651
7652 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007653 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007654
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007655 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007656
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007657 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007658}
Johan Hedberg314b2382011-04-27 10:29:57 -04007659
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007660void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007661{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007662 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007663
Andre Guedes343fb142011-11-22 17:14:19 -03007664 BT_DBG("%s discovering %u", hdev->name, discovering);
7665
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007666 memset(&ev, 0, sizeof(ev));
7667 ev.type = hdev->discovery.type;
7668 ev.discovering = discovering;
7669
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007670 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007671}
Antti Julku5e762442011-08-25 16:48:02 +03007672
Marcel Holtmann1904a852015-01-11 13:50:44 -08007673static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07007674{
7675 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007676}
7677
7678void mgmt_reenable_advertising(struct hci_dev *hdev)
7679{
7680 struct hci_request req;
7681
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007682 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Marcel Holtmann5976e602013-10-06 04:08:14 -07007683 return;
7684
7685 hci_req_init(&req, hdev);
7686 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007687 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007688}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02007689
7690static struct hci_mgmt_chan chan = {
7691 .channel = HCI_CHANNEL_CONTROL,
7692 .handler_count = ARRAY_SIZE(mgmt_handlers),
7693 .handlers = mgmt_handlers,
7694};
7695
7696int mgmt_init(void)
7697{
7698 return hci_mgmt_chan_register(&chan);
7699}
7700
7701void mgmt_exit(void)
7702{
7703 hci_mgmt_chan_unregister(&chan);
7704}