blob: 967f07fdbbbe8f37c0f3b9405f4b3dd63e7c14b5 [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 Holtmann854bda12014-12-03 19:52:43 +010040#define MGMT_REVISION 8
Johan Hedberg02d98122010-12-13 21:07:04 +020041
Johan Hedberge70bb2e2012-02-13 16:59:33 +020042static const u16 mgmt_commands[] = {
43 MGMT_OP_READ_INDEX_LIST,
44 MGMT_OP_READ_INFO,
45 MGMT_OP_SET_POWERED,
46 MGMT_OP_SET_DISCOVERABLE,
47 MGMT_OP_SET_CONNECTABLE,
48 MGMT_OP_SET_FAST_CONNECTABLE,
Johan Hedbergb2939472014-07-30 09:22:23 +030049 MGMT_OP_SET_BONDABLE,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020050 MGMT_OP_SET_LINK_SECURITY,
51 MGMT_OP_SET_SSP,
52 MGMT_OP_SET_HS,
53 MGMT_OP_SET_LE,
54 MGMT_OP_SET_DEV_CLASS,
55 MGMT_OP_SET_LOCAL_NAME,
56 MGMT_OP_ADD_UUID,
57 MGMT_OP_REMOVE_UUID,
58 MGMT_OP_LOAD_LINK_KEYS,
59 MGMT_OP_LOAD_LONG_TERM_KEYS,
60 MGMT_OP_DISCONNECT,
61 MGMT_OP_GET_CONNECTIONS,
62 MGMT_OP_PIN_CODE_REPLY,
63 MGMT_OP_PIN_CODE_NEG_REPLY,
64 MGMT_OP_SET_IO_CAPABILITY,
65 MGMT_OP_PAIR_DEVICE,
66 MGMT_OP_CANCEL_PAIR_DEVICE,
67 MGMT_OP_UNPAIR_DEVICE,
68 MGMT_OP_USER_CONFIRM_REPLY,
69 MGMT_OP_USER_CONFIRM_NEG_REPLY,
70 MGMT_OP_USER_PASSKEY_REPLY,
71 MGMT_OP_USER_PASSKEY_NEG_REPLY,
72 MGMT_OP_READ_LOCAL_OOB_DATA,
73 MGMT_OP_ADD_REMOTE_OOB_DATA,
74 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
75 MGMT_OP_START_DISCOVERY,
76 MGMT_OP_STOP_DISCOVERY,
77 MGMT_OP_CONFIRM_NAME,
78 MGMT_OP_BLOCK_DEVICE,
79 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070080 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030081 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030082 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070083 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070084 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080085 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080086 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020087 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020088 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020089 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030090 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020091 MGMT_OP_ADD_DEVICE,
92 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030093 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020094 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020095 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020096 MGMT_OP_SET_EXTERNAL_CONFIG,
Marcel Holtmann9713c172014-07-06 12:11:15 +020097 MGMT_OP_SET_PUBLIC_ADDRESS,
Jakub Pawlowski66ea9422014-12-05 10:55:59 +010098 MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020099};
100
101static const u16 mgmt_events[] = {
102 MGMT_EV_CONTROLLER_ERROR,
103 MGMT_EV_INDEX_ADDED,
104 MGMT_EV_INDEX_REMOVED,
105 MGMT_EV_NEW_SETTINGS,
106 MGMT_EV_CLASS_OF_DEV_CHANGED,
107 MGMT_EV_LOCAL_NAME_CHANGED,
108 MGMT_EV_NEW_LINK_KEY,
109 MGMT_EV_NEW_LONG_TERM_KEY,
110 MGMT_EV_DEVICE_CONNECTED,
111 MGMT_EV_DEVICE_DISCONNECTED,
112 MGMT_EV_CONNECT_FAILED,
113 MGMT_EV_PIN_CODE_REQUEST,
114 MGMT_EV_USER_CONFIRM_REQUEST,
115 MGMT_EV_USER_PASSKEY_REQUEST,
116 MGMT_EV_AUTH_FAILED,
117 MGMT_EV_DEVICE_FOUND,
118 MGMT_EV_DISCOVERING,
119 MGMT_EV_DEVICE_BLOCKED,
120 MGMT_EV_DEVICE_UNBLOCKED,
121 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300122 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800123 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700124 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200125 MGMT_EV_DEVICE_ADDED,
126 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300127 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200128 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd3896b2014-07-02 21:30:55 +0200129 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200130 MGMT_EV_NEW_CONFIG_OPTIONS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200131};
132
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800133#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200134
Johan Hedbergd25b78e2015-01-27 12:55:52 +0200135#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
136 "\x00\x00\x00\x00\x00\x00\x00\x00"
137
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200138struct pending_cmd {
139 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200140 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200141 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100142 void *param;
Johan Hedberg323b0b82014-12-05 13:36:01 +0200143 size_t param_len;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200144 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300145 void *user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +0200146 int (*cmd_complete)(struct pending_cmd *cmd, u8 status);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200147};
148
Johan Hedbergca69b792011-11-11 18:10:00 +0200149/* HCI to MGMT error code conversion table */
150static u8 mgmt_status_table[] = {
151 MGMT_STATUS_SUCCESS,
152 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
153 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
154 MGMT_STATUS_FAILED, /* Hardware Failure */
155 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
156 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200157 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200158 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
159 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
160 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
161 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
162 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
163 MGMT_STATUS_BUSY, /* Command Disallowed */
164 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
165 MGMT_STATUS_REJECTED, /* Rejected Security */
166 MGMT_STATUS_REJECTED, /* Rejected Personal */
167 MGMT_STATUS_TIMEOUT, /* Host Timeout */
168 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
169 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
170 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
171 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
172 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
173 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
174 MGMT_STATUS_BUSY, /* Repeated Attempts */
175 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
176 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
177 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
178 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
179 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
180 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
181 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
182 MGMT_STATUS_FAILED, /* Unspecified Error */
183 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
184 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
185 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
186 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
187 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
188 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
189 MGMT_STATUS_FAILED, /* Unit Link Key Used */
190 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
191 MGMT_STATUS_TIMEOUT, /* Instant Passed */
192 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
193 MGMT_STATUS_FAILED, /* Transaction Collision */
194 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
195 MGMT_STATUS_REJECTED, /* QoS Rejected */
196 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
197 MGMT_STATUS_REJECTED, /* Insufficient Security */
198 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
199 MGMT_STATUS_BUSY, /* Role Switch Pending */
200 MGMT_STATUS_FAILED, /* Slot Violation */
201 MGMT_STATUS_FAILED, /* Role Switch Failed */
202 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
203 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
204 MGMT_STATUS_BUSY, /* Host Busy Pairing */
205 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
206 MGMT_STATUS_BUSY, /* Controller Busy */
207 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
208 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
209 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
210 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
211 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
212};
213
214static u8 mgmt_status(u8 hci_status)
215{
216 if (hci_status < ARRAY_SIZE(mgmt_status_table))
217 return mgmt_status_table[hci_status];
218
219 return MGMT_STATUS_FAILED;
220}
221
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200222static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
223 struct sock *skip_sk)
224{
225 struct sk_buff *skb;
226 struct mgmt_hdr *hdr;
227
228 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
229 if (!skb)
230 return -ENOMEM;
231
232 hdr = (void *) skb_put(skb, sizeof(*hdr));
233 hdr->opcode = cpu_to_le16(event);
234 if (hdev)
235 hdr->index = cpu_to_le16(hdev->id);
236 else
237 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
238 hdr->len = cpu_to_le16(data_len);
239
240 if (data)
241 memcpy(skb_put(skb, data_len), data, data_len);
242
243 /* Time stamp */
244 __net_timestamp(skb);
245
Johan Hedberg71290692015-02-20 13:26:23 +0200246 hci_send_to_channel(HCI_CHANNEL_CONTROL, skb, skip_sk);
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200247 kfree_skb(skb);
248
249 return 0;
250}
251
Szymon Janc4e51eae2011-02-25 19:05:48 +0100252static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200253{
254 struct sk_buff *skb;
255 struct mgmt_hdr *hdr;
256 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300257 int err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200258
Szymon Janc34eb5252011-02-28 14:10:08 +0100259 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200260
Andre Guedes790eff42012-06-07 19:05:46 -0300261 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200262 if (!skb)
263 return -ENOMEM;
264
265 hdr = (void *) skb_put(skb, sizeof(*hdr));
266
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700267 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100268 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200269 hdr->len = cpu_to_le16(sizeof(*ev));
270
271 ev = (void *) skb_put(skb, sizeof(*ev));
272 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200273 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200274
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300275 err = sock_queue_rcv_skb(sk, skb);
276 if (err < 0)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200277 kfree_skb(skb);
278
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300279 return err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200280}
281
Johan Hedbergaee9b212012-02-18 15:07:59 +0200282static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300283 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200284{
285 struct sk_buff *skb;
286 struct mgmt_hdr *hdr;
287 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300288 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200289
290 BT_DBG("sock %p", sk);
291
Andre Guedes790eff42012-06-07 19:05:46 -0300292 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200293 if (!skb)
294 return -ENOMEM;
295
296 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200297
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700298 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100299 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200300 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200301
Johan Hedberga38528f2011-01-22 06:46:43 +0200302 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200303 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b212012-02-18 15:07:59 +0200304 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100305
306 if (rp)
307 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200308
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300309 err = sock_queue_rcv_skb(sk, skb);
310 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200311 kfree_skb(skb);
312
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100313 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200314}
315
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300316static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
317 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200318{
319 struct mgmt_rp_read_version rp;
320
321 BT_DBG("sock %p", sk);
322
323 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700324 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200325
Johan Hedbergaee9b212012-02-18 15:07:59 +0200326 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300327 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200328}
329
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300330static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
331 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200332{
333 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200334 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
335 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200336 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200337 size_t rp_size;
338 int i, err;
339
340 BT_DBG("sock %p", sk);
341
342 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
343
344 rp = kmalloc(rp_size, GFP_KERNEL);
345 if (!rp)
346 return -ENOMEM;
347
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700348 rp->num_commands = cpu_to_le16(num_commands);
349 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200350
351 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
352 put_unaligned_le16(mgmt_commands[i], opcode);
353
354 for (i = 0; i < num_events; i++, opcode++)
355 put_unaligned_le16(mgmt_events[i], opcode);
356
Johan Hedbergaee9b212012-02-18 15:07:59 +0200357 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300358 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200359 kfree(rp);
360
361 return err;
362}
363
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300364static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
365 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200366{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200367 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200368 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200369 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200370 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300371 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200372
373 BT_DBG("sock %p", sk);
374
375 read_lock(&hci_dev_list_lock);
376
377 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300378 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200379 if (d->dev_type == HCI_BREDR &&
380 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700381 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200382 }
383
Johan Hedberga38528f2011-01-22 06:46:43 +0200384 rp_len = sizeof(*rp) + (2 * count);
385 rp = kmalloc(rp_len, GFP_ATOMIC);
386 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100387 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200388 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100389 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200390
Johan Hedberg476e44c2012-10-19 20:10:46 +0300391 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200392 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200393 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b76b2014-07-06 12:11:14 +0200394 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200395 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200396 continue;
397
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200398 /* Devices marked as raw-only are neither configured
399 * nor unconfigured controllers.
400 */
401 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700402 continue;
403
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200404 if (d->dev_type == HCI_BREDR &&
405 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700406 rp->index[count++] = cpu_to_le16(d->id);
407 BT_DBG("Added hci%u", d->id);
408 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200409 }
410
Johan Hedberg476e44c2012-10-19 20:10:46 +0300411 rp->num_controllers = cpu_to_le16(count);
412 rp_len = sizeof(*rp) + (2 * count);
413
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200414 read_unlock(&hci_dev_list_lock);
415
Johan Hedbergaee9b212012-02-18 15:07:59 +0200416 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300417 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200418
Johan Hedberga38528f2011-01-22 06:46:43 +0200419 kfree(rp);
420
421 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200422}
423
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200424static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
425 void *data, u16 data_len)
426{
427 struct mgmt_rp_read_unconf_index_list *rp;
428 struct hci_dev *d;
429 size_t rp_len;
430 u16 count;
431 int err;
432
433 BT_DBG("sock %p", sk);
434
435 read_lock(&hci_dev_list_lock);
436
437 count = 0;
438 list_for_each_entry(d, &hci_dev_list, list) {
439 if (d->dev_type == HCI_BREDR &&
440 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
441 count++;
442 }
443
444 rp_len = sizeof(*rp) + (2 * count);
445 rp = kmalloc(rp_len, GFP_ATOMIC);
446 if (!rp) {
447 read_unlock(&hci_dev_list_lock);
448 return -ENOMEM;
449 }
450
451 count = 0;
452 list_for_each_entry(d, &hci_dev_list, list) {
453 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b76b2014-07-06 12:11:14 +0200454 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200455 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
456 continue;
457
458 /* Devices marked as raw-only are neither configured
459 * nor unconfigured controllers.
460 */
461 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
462 continue;
463
464 if (d->dev_type == HCI_BREDR &&
465 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
466 rp->index[count++] = cpu_to_le16(d->id);
467 BT_DBG("Added hci%u", d->id);
468 }
469 }
470
471 rp->num_controllers = cpu_to_le16(count);
472 rp_len = sizeof(*rp) + (2 * count);
473
474 read_unlock(&hci_dev_list_lock);
475
476 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
477 0, rp, rp_len);
478
479 kfree(rp);
480
481 return err;
482}
483
Marcel Holtmanndbece372014-07-04 18:11:55 +0200484static bool is_configured(struct hci_dev *hdev)
485{
486 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
487 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
488 return false;
489
490 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
491 !bacmp(&hdev->public_addr, BDADDR_ANY))
492 return false;
493
494 return true;
495}
496
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200497static __le32 get_missing_options(struct hci_dev *hdev)
498{
499 u32 options = 0;
500
Marcel Holtmanndbece372014-07-04 18:11:55 +0200501 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
502 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200503 options |= MGMT_OPTION_EXTERNAL_CONFIG;
504
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200505 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
506 !bacmp(&hdev->public_addr, BDADDR_ANY))
507 options |= MGMT_OPTION_PUBLIC_ADDRESS;
508
509 return cpu_to_le32(options);
510}
511
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200512static int new_options(struct hci_dev *hdev, struct sock *skip)
513{
514 __le32 options = get_missing_options(hdev);
515
516 return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
517 sizeof(options), skip);
518}
519
Marcel Holtmanndbece372014-07-04 18:11:55 +0200520static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
521{
522 __le32 options = get_missing_options(hdev);
523
524 return cmd_complete(sk, hdev->id, opcode, 0, &options,
525 sizeof(options));
526}
527
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200528static int read_config_info(struct sock *sk, struct hci_dev *hdev,
529 void *data, u16 data_len)
530{
531 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200532 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200533
534 BT_DBG("sock %p %s", sk, hdev->name);
535
536 hci_dev_lock(hdev);
537
538 memset(&rp, 0, sizeof(rp));
539 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200540
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200541 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
542 options |= MGMT_OPTION_EXTERNAL_CONFIG;
543
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200544 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200545 options |= MGMT_OPTION_PUBLIC_ADDRESS;
546
547 rp.supported_options = cpu_to_le32(options);
548 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200549
550 hci_dev_unlock(hdev);
551
552 return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp,
553 sizeof(rp));
554}
555
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200556static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200557{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200558 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200559
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200560 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300561 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800562 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300563 settings |= MGMT_SETTING_CONNECTABLE;
564 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200565
Andre Guedesed3fa312012-07-24 15:03:46 -0300566 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500567 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
568 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200569 settings |= MGMT_SETTING_BREDR;
570 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700571
572 if (lmp_ssp_capable(hdev)) {
573 settings |= MGMT_SETTING_SSP;
574 settings |= MGMT_SETTING_HS;
575 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800576
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -0800577 if (lmp_sc_capable(hdev))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800578 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700579 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100580
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300581 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200582 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300583 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300584 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200585 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300586 }
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200587
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200588 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
589 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200590 settings |= MGMT_SETTING_CONFIGURATION;
591
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200592 return settings;
593}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200594
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200595static u32 get_current_settings(struct hci_dev *hdev)
596{
597 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200598
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200599 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100600 settings |= MGMT_SETTING_POWERED;
601
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200602 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200603 settings |= MGMT_SETTING_CONNECTABLE;
604
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500605 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
606 settings |= MGMT_SETTING_FAST_CONNECTABLE;
607
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200608 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200609 settings |= MGMT_SETTING_DISCOVERABLE;
610
Johan Hedbergb6ae8452014-07-30 09:22:22 +0300611 if (test_bit(HCI_BONDABLE, &hdev->dev_flags))
Johan Hedbergb2939472014-07-30 09:22:23 +0300612 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200613
Johan Hedberg56f87902013-10-02 13:43:13 +0300614 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200615 settings |= MGMT_SETTING_BREDR;
616
Johan Hedberg06199cf2012-02-22 16:37:11 +0200617 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200618 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200619
Johan Hedberg47990ea2012-02-22 11:58:37 +0200620 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200621 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200622
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200623 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200624 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200625
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200626 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
627 settings |= MGMT_SETTING_HS;
628
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200629 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300630 settings |= MGMT_SETTING_ADVERTISING;
631
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800632 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
633 settings |= MGMT_SETTING_SECURE_CONN;
634
Johan Hedberg0663b292014-06-24 13:15:50 +0300635 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800636 settings |= MGMT_SETTING_DEBUG_KEYS;
637
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200638 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
639 settings |= MGMT_SETTING_PRIVACY;
640
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200641 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200642}
643
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300644#define PNP_INFO_SVCLASS_ID 0x1200
645
Johan Hedberg213202e2013-01-27 00:31:33 +0200646static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
647{
648 u8 *ptr = data, *uuids_start = NULL;
649 struct bt_uuid *uuid;
650
651 if (len < 4)
652 return ptr;
653
654 list_for_each_entry(uuid, &hdev->uuids, list) {
655 u16 uuid16;
656
657 if (uuid->size != 16)
658 continue;
659
660 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
661 if (uuid16 < 0x1100)
662 continue;
663
664 if (uuid16 == PNP_INFO_SVCLASS_ID)
665 continue;
666
667 if (!uuids_start) {
668 uuids_start = ptr;
669 uuids_start[0] = 1;
670 uuids_start[1] = EIR_UUID16_ALL;
671 ptr += 2;
672 }
673
674 /* Stop if not enough space to put next UUID */
675 if ((ptr - data) + sizeof(u16) > len) {
676 uuids_start[1] = EIR_UUID16_SOME;
677 break;
678 }
679
680 *ptr++ = (uuid16 & 0x00ff);
681 *ptr++ = (uuid16 & 0xff00) >> 8;
682 uuids_start[0] += sizeof(uuid16);
683 }
684
685 return ptr;
686}
687
Johan Hedbergcdf19632013-01-27 00:31:34 +0200688static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
689{
690 u8 *ptr = data, *uuids_start = NULL;
691 struct bt_uuid *uuid;
692
693 if (len < 6)
694 return ptr;
695
696 list_for_each_entry(uuid, &hdev->uuids, list) {
697 if (uuid->size != 32)
698 continue;
699
700 if (!uuids_start) {
701 uuids_start = ptr;
702 uuids_start[0] = 1;
703 uuids_start[1] = EIR_UUID32_ALL;
704 ptr += 2;
705 }
706
707 /* Stop if not enough space to put next UUID */
708 if ((ptr - data) + sizeof(u32) > len) {
709 uuids_start[1] = EIR_UUID32_SOME;
710 break;
711 }
712
713 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
714 ptr += sizeof(u32);
715 uuids_start[0] += sizeof(u32);
716 }
717
718 return ptr;
719}
720
Johan Hedbergc00d5752013-01-27 00:31:35 +0200721static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
722{
723 u8 *ptr = data, *uuids_start = NULL;
724 struct bt_uuid *uuid;
725
726 if (len < 18)
727 return ptr;
728
729 list_for_each_entry(uuid, &hdev->uuids, list) {
730 if (uuid->size != 128)
731 continue;
732
733 if (!uuids_start) {
734 uuids_start = ptr;
735 uuids_start[0] = 1;
736 uuids_start[1] = EIR_UUID128_ALL;
737 ptr += 2;
738 }
739
740 /* Stop if not enough space to put next UUID */
741 if ((ptr - data) + 16 > len) {
742 uuids_start[1] = EIR_UUID128_SOME;
743 break;
744 }
745
746 memcpy(ptr, uuid->uuid, 16);
747 ptr += 16;
748 uuids_start[0] += 16;
749 }
750
751 return ptr;
752}
753
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300754static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
755{
756 struct pending_cmd *cmd;
757
758 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
759 if (cmd->opcode == opcode)
760 return cmd;
761 }
762
763 return NULL;
764}
765
Johan Hedberg95868422014-06-28 17:54:07 +0300766static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
767 struct hci_dev *hdev,
768 const void *data)
769{
770 struct pending_cmd *cmd;
771
772 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
773 if (cmd->user_data != data)
774 continue;
775 if (cmd->opcode == opcode)
776 return cmd;
777 }
778
779 return NULL;
780}
781
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700782static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
783{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700784 u8 ad_len = 0;
785 size_t name_len;
786
787 name_len = strlen(hdev->dev_name);
788 if (name_len > 0) {
789 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
790
791 if (name_len > max_len) {
792 name_len = max_len;
793 ptr[1] = EIR_NAME_SHORT;
794 } else
795 ptr[1] = EIR_NAME_COMPLETE;
796
797 ptr[0] = name_len + 1;
798
799 memcpy(ptr + 2, hdev->dev_name, name_len);
800
801 ad_len += (name_len + 2);
802 ptr += (name_len + 2);
803 }
804
805 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700806}
807
808static void update_scan_rsp_data(struct hci_request *req)
809{
810 struct hci_dev *hdev = req->hdev;
811 struct hci_cp_le_set_scan_rsp_data cp;
812 u8 len;
813
Johan Hedberg7751ef12013-10-19 23:38:15 +0300814 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700815 return;
816
817 memset(&cp, 0, sizeof(cp));
818
819 len = create_scan_rsp_data(hdev, cp.data);
820
Johan Hedbergeb438b52013-10-16 15:31:07 +0300821 if (hdev->scan_rsp_data_len == len &&
822 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700823 return;
824
Johan Hedbergeb438b52013-10-16 15:31:07 +0300825 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
826 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700827
828 cp.length = len;
829
830 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
831}
832
Johan Hedberg9a43e252013-10-20 19:00:07 +0300833static u8 get_adv_discov_flags(struct hci_dev *hdev)
834{
835 struct pending_cmd *cmd;
836
837 /* If there's a pending mgmt command the flags will not yet have
838 * their final values, so check for this first.
839 */
840 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
841 if (cmd) {
842 struct mgmt_mode *cp = cmd->param;
843 if (cp->val == 0x01)
844 return LE_AD_GENERAL;
845 else if (cp->val == 0x02)
846 return LE_AD_LIMITED;
847 } else {
848 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
849 return LE_AD_LIMITED;
850 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
851 return LE_AD_GENERAL;
852 }
853
854 return 0;
855}
856
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700857static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700858{
859 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700860
Johan Hedberg9a43e252013-10-20 19:00:07 +0300861 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700862
Johan Hedberge8340042014-01-30 11:16:50 -0800863 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700864 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700865
866 if (flags) {
867 BT_DBG("adv flags 0x%02x", flags);
868
869 ptr[0] = 2;
870 ptr[1] = EIR_FLAGS;
871 ptr[2] = flags;
872
873 ad_len += 3;
874 ptr += 3;
875 }
876
877 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
878 ptr[0] = 2;
879 ptr[1] = EIR_TX_POWER;
880 ptr[2] = (u8) hdev->adv_tx_power;
881
882 ad_len += 3;
883 ptr += 3;
884 }
885
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700886 return ad_len;
887}
888
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700889static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700890{
891 struct hci_dev *hdev = req->hdev;
892 struct hci_cp_le_set_adv_data cp;
893 u8 len;
894
Johan Hedberg10994ce2013-10-19 23:38:16 +0300895 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700896 return;
897
898 memset(&cp, 0, sizeof(cp));
899
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700900 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700901
902 if (hdev->adv_data_len == len &&
903 memcmp(cp.data, hdev->adv_data, len) == 0)
904 return;
905
906 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
907 hdev->adv_data_len = len;
908
909 cp.length = len;
910
911 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
912}
913
Johan Hedbergbc6d2d02014-07-10 12:09:08 +0300914int mgmt_update_adv_data(struct hci_dev *hdev)
915{
916 struct hci_request req;
917
918 hci_req_init(&req, hdev);
919 update_adv_data(&req);
920
921 return hci_req_run(&req, NULL);
922}
923
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300924static void create_eir(struct hci_dev *hdev, u8 *data)
925{
926 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300927 size_t name_len;
928
929 name_len = strlen(hdev->dev_name);
930
931 if (name_len > 0) {
932 /* EIR Data type */
933 if (name_len > 48) {
934 name_len = 48;
935 ptr[1] = EIR_NAME_SHORT;
936 } else
937 ptr[1] = EIR_NAME_COMPLETE;
938
939 /* EIR Data length */
940 ptr[0] = name_len + 1;
941
942 memcpy(ptr + 2, hdev->dev_name, name_len);
943
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300944 ptr += (name_len + 2);
945 }
946
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100947 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700948 ptr[0] = 2;
949 ptr[1] = EIR_TX_POWER;
950 ptr[2] = (u8) hdev->inq_tx_power;
951
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700952 ptr += 3;
953 }
954
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700955 if (hdev->devid_source > 0) {
956 ptr[0] = 9;
957 ptr[1] = EIR_DEVICE_ID;
958
959 put_unaligned_le16(hdev->devid_source, ptr + 2);
960 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
961 put_unaligned_le16(hdev->devid_product, ptr + 6);
962 put_unaligned_le16(hdev->devid_version, ptr + 8);
963
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700964 ptr += 10;
965 }
966
Johan Hedberg213202e2013-01-27 00:31:33 +0200967 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200968 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200969 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300970}
971
Johan Hedberg890ea892013-03-15 17:06:52 -0500972static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300973{
Johan Hedberg890ea892013-03-15 17:06:52 -0500974 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300975 struct hci_cp_write_eir cp;
976
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200977 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500978 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200979
Johan Hedberg976eb202012-10-24 21:12:01 +0300980 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500981 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300982
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200983 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500984 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300985
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200986 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500987 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300988
989 memset(&cp, 0, sizeof(cp));
990
991 create_eir(hdev, cp.data);
992
993 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500994 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300995
996 memcpy(hdev->eir, cp.data, sizeof(cp.data));
997
Johan Hedberg890ea892013-03-15 17:06:52 -0500998 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300999}
1000
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001001static u8 get_service_classes(struct hci_dev *hdev)
1002{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001003 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001004 u8 val = 0;
1005
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001006 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001007 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001008
1009 return val;
1010}
1011
Johan Hedberg890ea892013-03-15 17:06:52 -05001012static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001013{
Johan Hedberg890ea892013-03-15 17:06:52 -05001014 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001015 u8 cod[3];
1016
1017 BT_DBG("%s", hdev->name);
1018
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001019 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001020 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001021
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001022 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1023 return;
1024
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001025 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001026 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001027
1028 cod[0] = hdev->minor_class;
1029 cod[1] = hdev->major_class;
1030 cod[2] = get_service_classes(hdev);
1031
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001032 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
1033 cod[1] |= 0x20;
1034
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001035 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001036 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001037
Johan Hedberg890ea892013-03-15 17:06:52 -05001038 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001039}
1040
Johan Hedberga4858cb2014-02-25 19:56:31 +02001041static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001042{
1043 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001044
1045 /* If there's a pending mgmt command the flag will not yet have
1046 * it's final value, so check for this first.
1047 */
1048 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1049 if (cmd) {
1050 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001051 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001052 }
1053
Johan Hedberga4858cb2014-02-25 19:56:31 +02001054 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001055}
1056
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001057static void disable_advertising(struct hci_request *req)
1058{
1059 u8 enable = 0x00;
1060
1061 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1062}
1063
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001064static void enable_advertising(struct hci_request *req)
1065{
1066 struct hci_dev *hdev = req->hdev;
1067 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001068 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001069 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001070
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001071 if (hci_conn_num(hdev, LE_LINK) > 0)
1072 return;
1073
1074 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
1075 disable_advertising(req);
1076
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001077 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001078 * hci_update_random_address knows that it's safe to go ahead
1079 * and write a new random address. The flag will be set back on
1080 * as soon as the SET_ADV_ENABLE HCI command completes.
1081 */
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001082 clear_bit(HCI_LE_ADV, &hdev->dev_flags);
Johan Hedberg8d972502014-02-28 12:54:14 +02001083
Johan Hedberga4858cb2014-02-25 19:56:31 +02001084 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001085
Johan Hedberga4858cb2014-02-25 19:56:31 +02001086 /* Set require_privacy to true only when non-connectable
1087 * advertising is used. In that case it is fine to use a
1088 * non-resolvable private address.
1089 */
1090 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001091 return;
1092
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001093 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001094 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1095 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001096 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001097 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001098 cp.channel_map = hdev->le_adv_channel_map;
1099
1100 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1101
1102 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1103}
1104
Johan Hedberg7d785252011-12-15 00:47:39 +02001105static void service_cache_off(struct work_struct *work)
1106{
1107 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001108 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001109 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001110
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001111 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001112 return;
1113
Johan Hedberg890ea892013-03-15 17:06:52 -05001114 hci_req_init(&req, hdev);
1115
Johan Hedberg7d785252011-12-15 00:47:39 +02001116 hci_dev_lock(hdev);
1117
Johan Hedberg890ea892013-03-15 17:06:52 -05001118 update_eir(&req);
1119 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001120
1121 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001122
1123 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001124}
1125
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001126static void rpa_expired(struct work_struct *work)
1127{
1128 struct hci_dev *hdev = container_of(work, struct hci_dev,
1129 rpa_expired.work);
1130 struct hci_request req;
1131
1132 BT_DBG("");
1133
1134 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1135
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001136 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001137 return;
1138
1139 /* The generation of a new RPA and programming it into the
1140 * controller happens in the enable_advertising() function.
1141 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001142 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001143 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001144 hci_req_run(&req, NULL);
1145}
1146
Johan Hedberg6a919082012-02-28 06:17:26 +02001147static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001148{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001149 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001150 return;
1151
Johan Hedberg4f87da82012-03-02 19:55:56 +02001152 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001153 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001154
Johan Hedberg4f87da82012-03-02 19:55:56 +02001155 /* Non-mgmt controlled devices get this bit set
1156 * implicitly so that pairing works for them, however
1157 * for mgmt we require user-space to explicitly enable
1158 * it
1159 */
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001160 clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001161}
1162
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001163static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001164 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001165{
1166 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001167
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001168 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001169
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001170 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001171
Johan Hedberg03811012010-12-08 00:21:06 +02001172 memset(&rp, 0, sizeof(rp));
1173
Johan Hedberg03811012010-12-08 00:21:06 +02001174 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001175
1176 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001177 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001178
1179 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1180 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1181
1182 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001183
1184 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001185 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001186
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001187 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001188
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001189 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001190 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001191}
1192
1193static void mgmt_pending_free(struct pending_cmd *cmd)
1194{
1195 sock_put(cmd->sk);
1196 kfree(cmd->param);
1197 kfree(cmd);
1198}
1199
1200static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001201 struct hci_dev *hdev, void *data,
1202 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001203{
1204 struct pending_cmd *cmd;
1205
Johan Hedbergfca20012014-06-28 17:54:05 +03001206 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001207 if (!cmd)
1208 return NULL;
1209
1210 cmd->opcode = opcode;
1211 cmd->index = hdev->id;
1212
Johan Hedberg323b0b82014-12-05 13:36:01 +02001213 cmd->param = kmemdup(data, len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001214 if (!cmd->param) {
1215 kfree(cmd);
1216 return NULL;
1217 }
1218
Johan Hedberg323b0b82014-12-05 13:36:01 +02001219 cmd->param_len = len;
Johan Hedberg03811012010-12-08 00:21:06 +02001220
1221 cmd->sk = sk;
1222 sock_hold(sk);
1223
1224 list_add(&cmd->list, &hdev->mgmt_pending);
1225
1226 return cmd;
1227}
1228
1229static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001230 void (*cb)(struct pending_cmd *cmd,
1231 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001232 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001233{
Andre Guedesa3d09352013-02-01 11:21:30 -03001234 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001235
Andre Guedesa3d09352013-02-01 11:21:30 -03001236 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001237 if (opcode > 0 && cmd->opcode != opcode)
1238 continue;
1239
1240 cb(cmd, data);
1241 }
1242}
1243
Johan Hedberg03811012010-12-08 00:21:06 +02001244static void mgmt_pending_remove(struct pending_cmd *cmd)
1245{
1246 list_del(&cmd->list);
1247 mgmt_pending_free(cmd);
1248}
1249
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001250static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001251{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001252 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001253
Johan Hedbergaee9b212012-02-18 15:07:59 +02001254 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001255 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001256}
1257
Marcel Holtmann1904a852015-01-11 13:50:44 -08001258static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001259{
1260 BT_DBG("%s status 0x%02x", hdev->name, status);
1261
Johan Hedberga3172b72014-02-28 09:33:44 +02001262 if (hci_conn_count(hdev) == 0) {
1263 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001264 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001265 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001266}
1267
Johan Hedberg23a48092014-07-08 16:05:06 +03001268static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001269{
1270 struct hci_dev *hdev = req->hdev;
1271 struct hci_cp_remote_name_req_cancel cp;
1272 struct inquiry_entry *e;
1273
1274 switch (hdev->discovery.state) {
1275 case DISCOVERY_FINDING:
1276 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1277 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1278 } else {
1279 cancel_delayed_work(&hdev->le_scan_disable);
1280 hci_req_add_le_scan_disable(req);
1281 }
1282
Johan Hedberg23a48092014-07-08 16:05:06 +03001283 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001284
1285 case DISCOVERY_RESOLVING:
1286 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1287 NAME_PENDING);
1288 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001289 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001290
1291 bacpy(&cp.bdaddr, &e->data.bdaddr);
1292 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1293 &cp);
1294
Johan Hedberg23a48092014-07-08 16:05:06 +03001295 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001296
1297 default:
1298 /* Passive scanning */
Johan Hedberg23a48092014-07-08 16:05:06 +03001299 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001300 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001301 return true;
1302 }
1303
Johan Hedberg21a60d32014-06-10 14:05:58 +03001304 break;
1305 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001306
1307 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001308}
1309
Johan Hedberg8b064a32014-02-24 14:52:22 +02001310static int clean_up_hci_state(struct hci_dev *hdev)
1311{
1312 struct hci_request req;
1313 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001314 bool discov_stopped;
1315 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001316
1317 hci_req_init(&req, hdev);
1318
1319 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1320 test_bit(HCI_PSCAN, &hdev->flags)) {
1321 u8 scan = 0x00;
1322 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1323 }
1324
Johan Hedberg73e082f2014-07-08 15:07:51 +03001325 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001326 disable_advertising(&req);
1327
Johan Hedberg23a48092014-07-08 16:05:06 +03001328 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001329
1330 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1331 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001332 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001333
Johan Hedbergc9910d02014-02-27 14:35:12 +02001334 switch (conn->state) {
1335 case BT_CONNECTED:
1336 case BT_CONFIG:
1337 dc.handle = cpu_to_le16(conn->handle);
1338 dc.reason = 0x15; /* Terminated due to Power Off */
1339 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1340 break;
1341 case BT_CONNECT:
1342 if (conn->type == LE_LINK)
1343 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1344 0, NULL);
1345 else if (conn->type == ACL_LINK)
1346 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1347 6, &conn->dst);
1348 break;
1349 case BT_CONNECT2:
1350 bacpy(&rej.bdaddr, &conn->dst);
1351 rej.reason = 0x15; /* Terminated due to Power Off */
1352 if (conn->type == ACL_LINK)
1353 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1354 sizeof(rej), &rej);
1355 else if (conn->type == SCO_LINK)
1356 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1357 sizeof(rej), &rej);
1358 break;
1359 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001360 }
1361
Johan Hedberg23a48092014-07-08 16:05:06 +03001362 err = hci_req_run(&req, clean_up_hci_complete);
1363 if (!err && discov_stopped)
1364 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1365
1366 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001367}
1368
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001369static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001370 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001371{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001372 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001373 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001374 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001375
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001376 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001377
Johan Hedberga7e80f22013-01-09 16:05:19 +02001378 if (cp->val != 0x00 && cp->val != 0x01)
1379 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1380 MGMT_STATUS_INVALID_PARAMS);
1381
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001382 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001383
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001384 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1385 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1386 MGMT_STATUS_BUSY);
1387 goto failed;
1388 }
1389
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001390 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1391 cancel_delayed_work(&hdev->power_off);
1392
1393 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001394 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1395 data, len);
1396 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001397 goto failed;
1398 }
1399 }
1400
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001401 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001402 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001403 goto failed;
1404 }
1405
Johan Hedberg03811012010-12-08 00:21:06 +02001406 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1407 if (!cmd) {
1408 err = -ENOMEM;
1409 goto failed;
1410 }
1411
Johan Hedberg8b064a32014-02-24 14:52:22 +02001412 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001413 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001414 err = 0;
1415 } else {
1416 /* Disconnect connections, stop scans, etc */
1417 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001418 if (!err)
1419 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1420 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001421
Johan Hedberg8b064a32014-02-24 14:52:22 +02001422 /* ENODATA means there were no HCI commands queued */
1423 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001424 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001425 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1426 err = 0;
1427 }
1428 }
Johan Hedberg03811012010-12-08 00:21:06 +02001429
1430failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001431 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001432 return err;
1433}
1434
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001435static int new_settings(struct hci_dev *hdev, struct sock *skip)
1436{
1437 __le32 ev;
1438
1439 ev = cpu_to_le32(get_current_settings(hdev));
1440
1441 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1442}
1443
Johan Hedberg91a668b2014-07-09 13:28:26 +03001444int mgmt_new_settings(struct hci_dev *hdev)
1445{
1446 return new_settings(hdev, NULL);
1447}
1448
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001449struct cmd_lookup {
1450 struct sock *sk;
1451 struct hci_dev *hdev;
1452 u8 mgmt_status;
1453};
1454
1455static void settings_rsp(struct pending_cmd *cmd, void *data)
1456{
1457 struct cmd_lookup *match = data;
1458
1459 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1460
1461 list_del(&cmd->list);
1462
1463 if (match->sk == NULL) {
1464 match->sk = cmd->sk;
1465 sock_hold(match->sk);
1466 }
1467
1468 mgmt_pending_free(cmd);
1469}
1470
1471static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1472{
1473 u8 *status = data;
1474
1475 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1476 mgmt_pending_remove(cmd);
1477}
1478
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001479static void cmd_complete_rsp(struct pending_cmd *cmd, void *data)
1480{
1481 if (cmd->cmd_complete) {
1482 u8 *status = data;
1483
1484 cmd->cmd_complete(cmd, *status);
1485 mgmt_pending_remove(cmd);
1486
1487 return;
1488 }
1489
1490 cmd_status_rsp(cmd, data);
1491}
1492
Johan Hedberg9df74652014-12-19 22:26:03 +02001493static int generic_cmd_complete(struct pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001494{
Johan Hedberg9df74652014-12-19 22:26:03 +02001495 return cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1496 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001497}
1498
Johan Hedberg9df74652014-12-19 22:26:03 +02001499static int addr_cmd_complete(struct pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001500{
Johan Hedberg9df74652014-12-19 22:26:03 +02001501 return cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param,
1502 sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001503}
1504
Johan Hedberge6fe7982013-10-02 15:45:22 +03001505static u8 mgmt_bredr_support(struct hci_dev *hdev)
1506{
1507 if (!lmp_bredr_capable(hdev))
1508 return MGMT_STATUS_NOT_SUPPORTED;
1509 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1510 return MGMT_STATUS_REJECTED;
1511 else
1512 return MGMT_STATUS_SUCCESS;
1513}
1514
1515static u8 mgmt_le_support(struct hci_dev *hdev)
1516{
1517 if (!lmp_le_capable(hdev))
1518 return MGMT_STATUS_NOT_SUPPORTED;
1519 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1520 return MGMT_STATUS_REJECTED;
1521 else
1522 return MGMT_STATUS_SUCCESS;
1523}
1524
Marcel Holtmann1904a852015-01-11 13:50:44 -08001525static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1526 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001527{
1528 struct pending_cmd *cmd;
1529 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001530 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001531 bool changed;
1532
1533 BT_DBG("status 0x%02x", status);
1534
1535 hci_dev_lock(hdev);
1536
1537 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1538 if (!cmd)
1539 goto unlock;
1540
1541 if (status) {
1542 u8 mgmt_err = mgmt_status(status);
1543 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001544 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001545 goto remove_cmd;
1546 }
1547
1548 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001549 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001550 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1551 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001552
1553 if (hdev->discov_timeout > 0) {
1554 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1555 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1556 to);
1557 }
1558 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001559 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1560 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001561 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001562
1563 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1564
1565 if (changed)
1566 new_settings(hdev, cmd->sk);
1567
Marcel Holtmann970ba522013-10-15 06:33:57 -07001568 /* When the discoverable mode gets changed, make sure
1569 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001570 * bit correctly set. Also update page scan based on whitelist
1571 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001572 */
1573 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001574 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001575 update_class(&req);
1576 hci_req_run(&req, NULL);
1577
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001578remove_cmd:
1579 mgmt_pending_remove(cmd);
1580
1581unlock:
1582 hci_dev_unlock(hdev);
1583}
1584
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001585static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001586 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001587{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001588 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001589 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001590 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001591 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001592 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001593 int err;
1594
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001595 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001596
Johan Hedberg9a43e252013-10-20 19:00:07 +03001597 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1598 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001599 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001600 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001601
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001602 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001603 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1604 MGMT_STATUS_INVALID_PARAMS);
1605
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001606 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001607
1608 /* Disabling discoverable requires that no timeout is set,
1609 * and enabling limited discoverable requires a timeout.
1610 */
1611 if ((cp->val == 0x00 && timeout > 0) ||
1612 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001613 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001614 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001615
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001616 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001617
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001618 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001619 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001620 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001621 goto failed;
1622 }
1623
1624 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001625 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001626 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001627 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001628 goto failed;
1629 }
1630
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001631 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001632 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001633 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001634 goto failed;
1635 }
1636
1637 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001638 bool changed = false;
1639
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001640 /* Setting limited discoverable when powered off is
1641 * not a valid operation since it requires a timeout
1642 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1643 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001644 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1645 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1646 changed = true;
1647 }
1648
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001649 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001650 if (err < 0)
1651 goto failed;
1652
1653 if (changed)
1654 err = new_settings(hdev, sk);
1655
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001656 goto failed;
1657 }
1658
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001659 /* If the current mode is the same, then just update the timeout
1660 * value with the new value. And if only the timeout gets updated,
1661 * then no need for any HCI transactions.
1662 */
1663 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1664 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1665 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001666 cancel_delayed_work(&hdev->discov_off);
1667 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001668
Marcel Holtmann36261542013-10-15 08:28:51 -07001669 if (cp->val && hdev->discov_timeout > 0) {
1670 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001671 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001672 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001673 }
1674
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001675 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001676 goto failed;
1677 }
1678
1679 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1680 if (!cmd) {
1681 err = -ENOMEM;
1682 goto failed;
1683 }
1684
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001685 /* Cancel any potential discoverable timeout that might be
1686 * still active and store new timeout value. The arming of
1687 * the timeout happens in the complete handler.
1688 */
1689 cancel_delayed_work(&hdev->discov_off);
1690 hdev->discov_timeout = timeout;
1691
Johan Hedbergb456f872013-10-19 23:38:22 +03001692 /* Limited discoverable mode */
1693 if (cp->val == 0x02)
1694 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1695 else
1696 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1697
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001698 hci_req_init(&req, hdev);
1699
Johan Hedberg9a43e252013-10-20 19:00:07 +03001700 /* The procedure for LE-only controllers is much simpler - just
1701 * update the advertising data.
1702 */
1703 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1704 goto update_ad;
1705
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001706 scan = SCAN_PAGE;
1707
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001708 if (cp->val) {
1709 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001710
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001711 if (cp->val == 0x02) {
1712 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001713 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001714 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1715 hci_cp.iac_lap[1] = 0x8b;
1716 hci_cp.iac_lap[2] = 0x9e;
1717 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1718 hci_cp.iac_lap[4] = 0x8b;
1719 hci_cp.iac_lap[5] = 0x9e;
1720 } else {
1721 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001722 hci_cp.num_iac = 1;
1723 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1724 hci_cp.iac_lap[1] = 0x8b;
1725 hci_cp.iac_lap[2] = 0x9e;
1726 }
1727
1728 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1729 (hci_cp.num_iac * 3) + 1, &hci_cp);
1730
1731 scan |= SCAN_INQUIRY;
1732 } else {
1733 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1734 }
1735
1736 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001737
Johan Hedberg9a43e252013-10-20 19:00:07 +03001738update_ad:
1739 update_adv_data(&req);
1740
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001741 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001742 if (err < 0)
1743 mgmt_pending_remove(cmd);
1744
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001745failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001746 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001747 return err;
1748}
1749
Johan Hedberg406d7802013-03-15 17:07:09 -05001750static void write_fast_connectable(struct hci_request *req, bool enable)
1751{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001752 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001753 struct hci_cp_write_page_scan_activity acp;
1754 u8 type;
1755
Johan Hedberg547003b2013-10-21 16:51:53 +03001756 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1757 return;
1758
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001759 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1760 return;
1761
Johan Hedberg406d7802013-03-15 17:07:09 -05001762 if (enable) {
1763 type = PAGE_SCAN_TYPE_INTERLACED;
1764
1765 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001766 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001767 } else {
1768 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1769
1770 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001771 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001772 }
1773
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001774 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001775
Johan Hedbergbd98b992013-03-15 17:07:13 -05001776 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1777 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1778 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1779 sizeof(acp), &acp);
1780
1781 if (hdev->page_scan_type != type)
1782 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001783}
1784
Marcel Holtmann1904a852015-01-11 13:50:44 -08001785static void set_connectable_complete(struct hci_dev *hdev, u8 status,
1786 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05001787{
1788 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001789 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001790 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001791
1792 BT_DBG("status 0x%02x", status);
1793
1794 hci_dev_lock(hdev);
1795
1796 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1797 if (!cmd)
1798 goto unlock;
1799
Johan Hedberg37438c12013-10-14 16:20:05 +03001800 if (status) {
1801 u8 mgmt_err = mgmt_status(status);
1802 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1803 goto remove_cmd;
1804 }
1805
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001806 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001807 if (cp->val) {
1808 conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
1809 &hdev->dev_flags);
1810 discov_changed = false;
1811 } else {
1812 conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
1813 &hdev->dev_flags);
1814 discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
1815 &hdev->dev_flags);
1816 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001817
Johan Hedberg2b76f452013-03-15 17:07:04 -05001818 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1819
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001820 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001821 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001822 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001823 if (discov_changed)
1824 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001825 hci_update_background_scan(hdev);
1826 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001827
Johan Hedberg37438c12013-10-14 16:20:05 +03001828remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001829 mgmt_pending_remove(cmd);
1830
1831unlock:
1832 hci_dev_unlock(hdev);
1833}
1834
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001835static int set_connectable_update_settings(struct hci_dev *hdev,
1836 struct sock *sk, u8 val)
1837{
1838 bool changed = false;
1839 int err;
1840
1841 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1842 changed = true;
1843
1844 if (val) {
1845 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1846 } else {
1847 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1848 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1849 }
1850
1851 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1852 if (err < 0)
1853 return err;
1854
Johan Hedberg562064e2014-07-08 16:35:34 +03001855 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001856 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03001857 hci_update_background_scan(hdev);
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001858 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001859 }
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001860
1861 return 0;
1862}
1863
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001864static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001865 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001866{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001867 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001868 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001869 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001870 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001871 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001872
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001873 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001874
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001875 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1876 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001877 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001878 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001879
Johan Hedberga7e80f22013-01-09 16:05:19 +02001880 if (cp->val != 0x00 && cp->val != 0x01)
1881 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1882 MGMT_STATUS_INVALID_PARAMS);
1883
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001884 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001885
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001886 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001887 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001888 goto failed;
1889 }
1890
1891 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001892 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001893 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001894 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001895 goto failed;
1896 }
1897
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001898 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1899 if (!cmd) {
1900 err = -ENOMEM;
1901 goto failed;
1902 }
1903
Johan Hedberg2b76f452013-03-15 17:07:04 -05001904 hci_req_init(&req, hdev);
1905
Johan Hedberg9a43e252013-10-20 19:00:07 +03001906 /* If BR/EDR is not enabled and we disable advertising as a
1907 * by-product of disabling connectable, we need to update the
1908 * advertising flags.
1909 */
1910 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1911 if (!cp->val) {
1912 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1913 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1914 }
1915 update_adv_data(&req);
1916 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001917 if (cp->val) {
1918 scan = SCAN_PAGE;
1919 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001920 /* If we don't have any whitelist entries just
1921 * disable all scanning. If there are entries
1922 * and we had both page and inquiry scanning
1923 * enabled then fall back to only page scanning.
1924 * Otherwise no changes are needed.
1925 */
1926 if (list_empty(&hdev->whitelist))
1927 scan = SCAN_DISABLED;
1928 else if (test_bit(HCI_ISCAN, &hdev->flags))
1929 scan = SCAN_PAGE;
1930 else
1931 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001932
1933 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001934 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001935 cancel_delayed_work(&hdev->discov_off);
1936 }
1937
1938 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1939 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001940
Johan Hedberg3bd27242014-07-28 20:53:58 +03001941no_scan_update:
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001942 /* If we're going from non-connectable to connectable or
1943 * vice-versa when fast connectable is enabled ensure that fast
1944 * connectable gets disabled. write_fast_connectable won't do
1945 * anything if the page scan parameters are already what they
1946 * should be.
1947 */
1948 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001949 write_fast_connectable(&req, false);
1950
Johan Hedberge8b12022014-07-10 10:51:27 +03001951 /* Update the advertising parameters if necessary */
1952 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001953 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001954
Johan Hedberg2b76f452013-03-15 17:07:04 -05001955 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001956 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001957 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001958 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001959 err = set_connectable_update_settings(hdev, sk,
1960 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001961 goto failed;
1962 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001963
1964failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001965 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001966 return err;
1967}
1968
Johan Hedbergb2939472014-07-30 09:22:23 +03001969static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001970 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001971{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001972 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001973 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001974 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001975
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001976 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001977
Johan Hedberga7e80f22013-01-09 16:05:19 +02001978 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedbergb2939472014-07-30 09:22:23 +03001979 return cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
Johan Hedberga7e80f22013-01-09 16:05:19 +02001980 MGMT_STATUS_INVALID_PARAMS);
1981
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001982 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001983
1984 if (cp->val)
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001985 changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001986 else
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001987 changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001988
Johan Hedbergb2939472014-07-30 09:22:23 +03001989 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001990 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001991 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001992
Marcel Holtmann55594352013-10-06 16:11:57 -07001993 if (changed)
1994 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001995
Marcel Holtmann55594352013-10-06 16:11:57 -07001996unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001997 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001998 return err;
1999}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002000
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002001static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2002 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002003{
2004 struct mgmt_mode *cp = data;
2005 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002006 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002007 int err;
2008
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002009 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002010
Johan Hedberge6fe7982013-10-02 15:45:22 +03002011 status = mgmt_bredr_support(hdev);
2012 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03002013 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03002014 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002015
Johan Hedberga7e80f22013-01-09 16:05:19 +02002016 if (cp->val != 0x00 && cp->val != 0x01)
2017 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2018 MGMT_STATUS_INVALID_PARAMS);
2019
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002020 hci_dev_lock(hdev);
2021
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002022 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002023 bool changed = false;
2024
2025 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002026 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002027 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
2028 changed = true;
2029 }
2030
2031 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2032 if (err < 0)
2033 goto failed;
2034
2035 if (changed)
2036 err = new_settings(hdev, sk);
2037
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002038 goto failed;
2039 }
2040
2041 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002042 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002043 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002044 goto failed;
2045 }
2046
2047 val = !!cp->val;
2048
2049 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2050 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2051 goto failed;
2052 }
2053
2054 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2055 if (!cmd) {
2056 err = -ENOMEM;
2057 goto failed;
2058 }
2059
2060 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2061 if (err < 0) {
2062 mgmt_pending_remove(cmd);
2063 goto failed;
2064 }
2065
2066failed:
2067 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002068 return err;
2069}
2070
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002071static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002072{
2073 struct mgmt_mode *cp = data;
2074 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002075 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002076 int err;
2077
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002078 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002079
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002080 status = mgmt_bredr_support(hdev);
2081 if (status)
2082 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2083
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002084 if (!lmp_ssp_capable(hdev))
2085 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2086 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002087
Johan Hedberga7e80f22013-01-09 16:05:19 +02002088 if (cp->val != 0x00 && cp->val != 0x01)
2089 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2090 MGMT_STATUS_INVALID_PARAMS);
2091
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002092 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002093
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002094 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002095 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002096
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002097 if (cp->val) {
2098 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2099 &hdev->dev_flags);
2100 } else {
2101 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2102 &hdev->dev_flags);
2103 if (!changed)
2104 changed = test_and_clear_bit(HCI_HS_ENABLED,
2105 &hdev->dev_flags);
2106 else
2107 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002108 }
2109
2110 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2111 if (err < 0)
2112 goto failed;
2113
2114 if (changed)
2115 err = new_settings(hdev, sk);
2116
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002117 goto failed;
2118 }
2119
Johan Hedberg94d52da2015-02-19 17:38:06 +02002120 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002121 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2122 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002123 goto failed;
2124 }
2125
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002126 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002127 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2128 goto failed;
2129 }
2130
2131 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2132 if (!cmd) {
2133 err = -ENOMEM;
2134 goto failed;
2135 }
2136
Johan Hedberg37699722014-06-24 14:00:27 +03002137 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2138 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2139 sizeof(cp->val), &cp->val);
2140
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002141 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002142 if (err < 0) {
2143 mgmt_pending_remove(cmd);
2144 goto failed;
2145 }
2146
2147failed:
2148 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002149 return err;
2150}
2151
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002152static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002153{
2154 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002155 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002156 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002157 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002158
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002159 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002160
Johan Hedberge6fe7982013-10-02 15:45:22 +03002161 status = mgmt_bredr_support(hdev);
2162 if (status)
2163 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002164
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002165 if (!lmp_ssp_capable(hdev))
2166 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2167 MGMT_STATUS_NOT_SUPPORTED);
2168
2169 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2170 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2171 MGMT_STATUS_REJECTED);
2172
Johan Hedberga7e80f22013-01-09 16:05:19 +02002173 if (cp->val != 0x00 && cp->val != 0x01)
2174 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2175 MGMT_STATUS_INVALID_PARAMS);
2176
Marcel Holtmannee392692013-10-01 22:59:23 -07002177 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002178
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002179 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
2180 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2181 MGMT_STATUS_BUSY);
2182 goto unlock;
2183 }
2184
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002185 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002186 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002187 } else {
2188 if (hdev_is_powered(hdev)) {
2189 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2190 MGMT_STATUS_REJECTED);
2191 goto unlock;
2192 }
2193
Marcel Holtmannee392692013-10-01 22:59:23 -07002194 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002195 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002196
2197 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2198 if (err < 0)
2199 goto unlock;
2200
2201 if (changed)
2202 err = new_settings(hdev, sk);
2203
2204unlock:
2205 hci_dev_unlock(hdev);
2206 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002207}
2208
Marcel Holtmann1904a852015-01-11 13:50:44 -08002209static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002210{
2211 struct cmd_lookup match = { NULL, hdev };
2212
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302213 hci_dev_lock(hdev);
2214
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002215 if (status) {
2216 u8 mgmt_err = mgmt_status(status);
2217
2218 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2219 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302220 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002221 }
2222
2223 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2224
2225 new_settings(hdev, match.sk);
2226
2227 if (match.sk)
2228 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002229
2230 /* Make sure the controller has a good default for
2231 * advertising data. Restrict the update to when LE
2232 * has actually been enabled. During power on, the
2233 * update in powered_update_hci will take care of it.
2234 */
2235 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2236 struct hci_request req;
2237
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002238 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002239 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002240 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002241 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002242 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002243 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302244
2245unlock:
2246 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002247}
2248
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002249static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002250{
2251 struct mgmt_mode *cp = data;
2252 struct hci_cp_write_le_host_supported hci_cp;
2253 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002254 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002255 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002256 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002257
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002258 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002259
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002260 if (!lmp_le_capable(hdev))
2261 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2262 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002263
Johan Hedberga7e80f22013-01-09 16:05:19 +02002264 if (cp->val != 0x00 && cp->val != 0x01)
2265 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2266 MGMT_STATUS_INVALID_PARAMS);
2267
Johan Hedbergc73eee92013-04-19 18:35:21 +03002268 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002269 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002270 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2271 MGMT_STATUS_REJECTED);
2272
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002273 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002274
2275 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002276 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002277
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002278 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002279 bool changed = false;
2280
2281 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2282 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2283 changed = true;
2284 }
2285
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002286 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2287 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002288 changed = true;
2289 }
2290
Johan Hedberg06199cf2012-02-22 16:37:11 +02002291 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2292 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002293 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002294
2295 if (changed)
2296 err = new_settings(hdev, sk);
2297
Johan Hedberg1de028c2012-02-29 19:55:35 -08002298 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002299 }
2300
Johan Hedberg4375f102013-09-25 13:26:10 +03002301 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2302 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002303 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002304 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002305 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002306 }
2307
2308 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2309 if (!cmd) {
2310 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002311 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002312 }
2313
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002314 hci_req_init(&req, hdev);
2315
Johan Hedberg06199cf2012-02-22 16:37:11 +02002316 memset(&hci_cp, 0, sizeof(hci_cp));
2317
2318 if (val) {
2319 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002320 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002321 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002322 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002323 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002324 }
2325
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002326 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2327 &hci_cp);
2328
2329 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302330 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002331 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002332
Johan Hedberg1de028c2012-02-29 19:55:35 -08002333unlock:
2334 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002335 return err;
2336}
2337
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002338/* This is a helper function to test for pending mgmt commands that can
2339 * cause CoD or EIR HCI commands. We can only allow one such pending
2340 * mgmt command at a time since otherwise we cannot easily track what
2341 * the current values are, will be, and based on that calculate if a new
2342 * HCI command needs to be sent and if yes with what value.
2343 */
2344static bool pending_eir_or_class(struct hci_dev *hdev)
2345{
2346 struct pending_cmd *cmd;
2347
2348 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2349 switch (cmd->opcode) {
2350 case MGMT_OP_ADD_UUID:
2351 case MGMT_OP_REMOVE_UUID:
2352 case MGMT_OP_SET_DEV_CLASS:
2353 case MGMT_OP_SET_POWERED:
2354 return true;
2355 }
2356 }
2357
2358 return false;
2359}
2360
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002361static const u8 bluetooth_base_uuid[] = {
2362 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2363 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2364};
2365
2366static u8 get_uuid_size(const u8 *uuid)
2367{
2368 u32 val;
2369
2370 if (memcmp(uuid, bluetooth_base_uuid, 12))
2371 return 128;
2372
2373 val = get_unaligned_le32(&uuid[12]);
2374 if (val > 0xffff)
2375 return 32;
2376
2377 return 16;
2378}
2379
Johan Hedberg92da6092013-03-15 17:06:55 -05002380static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2381{
2382 struct pending_cmd *cmd;
2383
2384 hci_dev_lock(hdev);
2385
2386 cmd = mgmt_pending_find(mgmt_op, hdev);
2387 if (!cmd)
2388 goto unlock;
2389
2390 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2391 hdev->dev_class, 3);
2392
2393 mgmt_pending_remove(cmd);
2394
2395unlock:
2396 hci_dev_unlock(hdev);
2397}
2398
Marcel Holtmann1904a852015-01-11 13:50:44 -08002399static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002400{
2401 BT_DBG("status 0x%02x", status);
2402
2403 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2404}
2405
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002406static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002407{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002408 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002409 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002410 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002411 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002412 int err;
2413
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002414 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002415
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002416 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002417
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002418 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002419 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002420 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002421 goto failed;
2422 }
2423
Andre Guedes92c4c202012-06-07 19:05:44 -03002424 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002425 if (!uuid) {
2426 err = -ENOMEM;
2427 goto failed;
2428 }
2429
2430 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002431 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002432 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002433
Johan Hedbergde66aa62013-01-27 00:31:27 +02002434 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002435
Johan Hedberg890ea892013-03-15 17:06:52 -05002436 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002437
Johan Hedberg890ea892013-03-15 17:06:52 -05002438 update_class(&req);
2439 update_eir(&req);
2440
Johan Hedberg92da6092013-03-15 17:06:55 -05002441 err = hci_req_run(&req, add_uuid_complete);
2442 if (err < 0) {
2443 if (err != -ENODATA)
2444 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002445
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002446 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002447 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002448 goto failed;
2449 }
2450
2451 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002452 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002453 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002454 goto failed;
2455 }
2456
2457 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002458
2459failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002460 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002461 return err;
2462}
2463
Johan Hedberg24b78d02012-02-23 23:24:30 +02002464static bool enable_service_cache(struct hci_dev *hdev)
2465{
2466 if (!hdev_is_powered(hdev))
2467 return false;
2468
2469 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002470 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2471 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002472 return true;
2473 }
2474
2475 return false;
2476}
2477
Marcel Holtmann1904a852015-01-11 13:50:44 -08002478static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002479{
2480 BT_DBG("status 0x%02x", status);
2481
2482 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2483}
2484
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002485static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002486 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002487{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002488 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002489 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002490 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002491 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 -05002492 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002493 int err, found;
2494
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002495 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002496
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002497 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002498
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002499 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002500 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002501 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002502 goto unlock;
2503 }
2504
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002505 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002506 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002507
Johan Hedberg24b78d02012-02-23 23:24:30 +02002508 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002509 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002510 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002511 goto unlock;
2512 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002513
Johan Hedberg9246a862012-02-23 21:33:16 +02002514 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002515 }
2516
2517 found = 0;
2518
Johan Hedberg056341c2013-01-27 00:31:30 +02002519 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002520 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2521 continue;
2522
2523 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002524 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002525 found++;
2526 }
2527
2528 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002529 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002530 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002531 goto unlock;
2532 }
2533
Johan Hedberg9246a862012-02-23 21:33:16 +02002534update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002535 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002536
Johan Hedberg890ea892013-03-15 17:06:52 -05002537 update_class(&req);
2538 update_eir(&req);
2539
Johan Hedberg92da6092013-03-15 17:06:55 -05002540 err = hci_req_run(&req, remove_uuid_complete);
2541 if (err < 0) {
2542 if (err != -ENODATA)
2543 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002544
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002545 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002546 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002547 goto unlock;
2548 }
2549
2550 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002551 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002552 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002553 goto unlock;
2554 }
2555
2556 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002557
2558unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002559 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002560 return err;
2561}
2562
Marcel Holtmann1904a852015-01-11 13:50:44 -08002563static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002564{
2565 BT_DBG("status 0x%02x", status);
2566
2567 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2568}
2569
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002570static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002571 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002572{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002573 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002574 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002575 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002576 int err;
2577
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002578 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002579
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002580 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002581 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2582 MGMT_STATUS_NOT_SUPPORTED);
2583
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002584 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002585
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002586 if (pending_eir_or_class(hdev)) {
2587 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2588 MGMT_STATUS_BUSY);
2589 goto unlock;
2590 }
2591
2592 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2593 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2594 MGMT_STATUS_INVALID_PARAMS);
2595 goto unlock;
2596 }
2597
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002598 hdev->major_class = cp->major;
2599 hdev->minor_class = cp->minor;
2600
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002601 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002602 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002603 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002604 goto unlock;
2605 }
2606
Johan Hedberg890ea892013-03-15 17:06:52 -05002607 hci_req_init(&req, hdev);
2608
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002609 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002610 hci_dev_unlock(hdev);
2611 cancel_delayed_work_sync(&hdev->service_cache);
2612 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002613 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002614 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002615
Johan Hedberg890ea892013-03-15 17:06:52 -05002616 update_class(&req);
2617
Johan Hedberg92da6092013-03-15 17:06:55 -05002618 err = hci_req_run(&req, set_class_complete);
2619 if (err < 0) {
2620 if (err != -ENODATA)
2621 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002622
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002623 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002624 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002625 goto unlock;
2626 }
2627
2628 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002629 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002630 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002631 goto unlock;
2632 }
2633
2634 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002635
Johan Hedbergb5235a62012-02-21 14:32:24 +02002636unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002637 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002638 return err;
2639}
2640
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002641static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002642 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002643{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002644 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002645 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2646 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002647 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002648 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002649 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002650
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002651 BT_DBG("request for %s", hdev->name);
2652
2653 if (!lmp_bredr_capable(hdev))
2654 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2655 MGMT_STATUS_NOT_SUPPORTED);
2656
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002657 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002658 if (key_count > max_key_count) {
2659 BT_ERR("load_link_keys: too big key_count value %u",
2660 key_count);
2661 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2662 MGMT_STATUS_INVALID_PARAMS);
2663 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002664
Johan Hedberg86742e12011-11-07 23:13:38 +02002665 expected_len = sizeof(*cp) + key_count *
2666 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002667 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002668 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002669 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002670 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002671 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002672 }
2673
Johan Hedberg4ae143012013-01-20 14:27:13 +02002674 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2675 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2676 MGMT_STATUS_INVALID_PARAMS);
2677
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002678 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002679 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002680
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002681 for (i = 0; i < key_count; i++) {
2682 struct mgmt_link_key_info *key = &cp->keys[i];
2683
Marcel Holtmann8e991132014-01-10 02:07:25 -08002684 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002685 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2686 MGMT_STATUS_INVALID_PARAMS);
2687 }
2688
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002689 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002690
2691 hci_link_keys_clear(hdev);
2692
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002693 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002694 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2695 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002696 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002697 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2698 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002699
2700 if (changed)
2701 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002702
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002703 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002704 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002705
Johan Hedberg58e92932014-06-24 14:00:26 +03002706 /* Always ignore debug keys and require a new pairing if
2707 * the user wants to use them.
2708 */
2709 if (key->type == HCI_LK_DEBUG_COMBINATION)
2710 continue;
2711
Johan Hedberg7652ff62014-06-24 13:15:49 +03002712 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2713 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002714 }
2715
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002716 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002717
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002718 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002719
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002720 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002721}
2722
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002723static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002724 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002725{
2726 struct mgmt_ev_device_unpaired ev;
2727
2728 bacpy(&ev.addr.bdaddr, bdaddr);
2729 ev.addr.type = addr_type;
2730
2731 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002732 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002733}
2734
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002735static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002736 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002737{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002738 struct mgmt_cp_unpair_device *cp = data;
2739 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002740 struct hci_cp_disconnect dc;
2741 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002742 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002743 int err;
2744
Johan Hedberga8a1d192011-11-10 15:54:38 +02002745 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002746 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2747 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002748
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002749 if (!bdaddr_type_is_valid(cp->addr.type))
2750 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2751 MGMT_STATUS_INVALID_PARAMS,
2752 &rp, sizeof(rp));
2753
Johan Hedberg118da702013-01-20 14:27:20 +02002754 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2755 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2756 MGMT_STATUS_INVALID_PARAMS,
2757 &rp, sizeof(rp));
2758
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002759 hci_dev_lock(hdev);
2760
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002761 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002762 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002763 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002764 goto unlock;
2765 }
2766
Johan Hedberge0b2b272014-02-18 17:14:31 +02002767 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002768 /* If disconnection is requested, then look up the
2769 * connection. If the remote device is connected, it
2770 * will be later used to terminate the link.
2771 *
2772 * Setting it to NULL explicitly will cause no
2773 * termination of the link.
2774 */
2775 if (cp->disconnect)
2776 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2777 &cp->addr.bdaddr);
2778 else
2779 conn = NULL;
2780
Johan Hedberg124f6e32012-02-09 13:50:12 +02002781 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002782 } else {
2783 u8 addr_type;
2784
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002785 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2786 &cp->addr.bdaddr);
2787 if (conn) {
2788 /* Defer clearing up the connection parameters
2789 * until closing to give a chance of keeping
2790 * them if a repairing happens.
2791 */
2792 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2793
2794 /* If disconnection is not requested, then
2795 * clear the connection variable so that the
2796 * link is not terminated.
2797 */
2798 if (!cp->disconnect)
2799 conn = NULL;
2800 }
2801
Johan Hedberge0b2b272014-02-18 17:14:31 +02002802 if (cp->addr.type == BDADDR_LE_PUBLIC)
2803 addr_type = ADDR_LE_DEV_PUBLIC;
2804 else
2805 addr_type = ADDR_LE_DEV_RANDOM;
2806
Johan Hedberga7ec7332014-02-18 17:14:35 +02002807 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2808
Johan Hedberge0b2b272014-02-18 17:14:31 +02002809 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2810 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002811
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002812 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002813 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002814 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002815 goto unlock;
2816 }
2817
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002818 /* If the connection variable is set, then termination of the
2819 * link is requested.
2820 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002821 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002822 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002823 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002824 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002825 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002826 }
2827
Johan Hedberg124f6e32012-02-09 13:50:12 +02002828 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002829 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002830 if (!cmd) {
2831 err = -ENOMEM;
2832 goto unlock;
2833 }
2834
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02002835 cmd->cmd_complete = addr_cmd_complete;
2836
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002837 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002838 dc.reason = 0x13; /* Remote User Terminated Connection */
2839 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2840 if (err < 0)
2841 mgmt_pending_remove(cmd);
2842
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002843unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002844 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002845 return err;
2846}
2847
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002848static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002849 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002850{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002851 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002852 struct mgmt_rp_disconnect rp;
Johan Hedberg366a0332011-02-19 12:05:55 -03002853 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002854 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002855 int err;
2856
2857 BT_DBG("");
2858
Johan Hedberg06a63b12013-01-20 14:27:21 +02002859 memset(&rp, 0, sizeof(rp));
2860 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2861 rp.addr.type = cp->addr.type;
2862
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002863 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002864 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2865 MGMT_STATUS_INVALID_PARAMS,
2866 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002867
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002868 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002869
2870 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002871 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2872 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002873 goto failed;
2874 }
2875
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002876 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002877 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2878 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002879 goto failed;
2880 }
2881
Andre Guedes591f47f2012-04-24 21:02:49 -03002882 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002883 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2884 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002885 else
2886 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002887
Vishal Agarwalf9607272012-06-13 05:32:43 +05302888 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002889 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2890 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002891 goto failed;
2892 }
2893
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002894 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002895 if (!cmd) {
2896 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002897 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002898 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002899
Johan Hedbergf5818c22014-12-05 13:36:02 +02002900 cmd->cmd_complete = generic_cmd_complete;
2901
Johan Hedberge3f2f922014-08-18 20:33:33 +03002902 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002903 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002904 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002905
2906failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002907 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002908 return err;
2909}
2910
Andre Guedes57c14772012-04-24 21:02:50 -03002911static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002912{
2913 switch (link_type) {
2914 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002915 switch (addr_type) {
2916 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002917 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002918
Johan Hedberg48264f02011-11-09 13:58:58 +02002919 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002920 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002921 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002922 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002923
Johan Hedberg4c659c32011-11-07 23:13:39 +02002924 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002925 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002926 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002927 }
2928}
2929
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002930static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2931 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002932{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002933 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002934 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002935 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002936 int err;
2937 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002938
2939 BT_DBG("");
2940
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002941 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002942
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002943 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002944 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002945 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002946 goto unlock;
2947 }
2948
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002949 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002950 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2951 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002952 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002953 }
2954
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002955 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002956 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002957 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002958 err = -ENOMEM;
2959 goto unlock;
2960 }
2961
Johan Hedberg2784eb42011-01-21 13:56:35 +02002962 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002963 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002964 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2965 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002966 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002967 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002968 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002969 continue;
2970 i++;
2971 }
2972
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002973 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002974
Johan Hedberg4c659c32011-11-07 23:13:39 +02002975 /* Recalculate length in case of filtered SCO connections, etc */
2976 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002977
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002978 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002979 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002980
Johan Hedberga38528f2011-01-22 06:46:43 +02002981 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002982
2983unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002984 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002985 return err;
2986}
2987
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002988static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002989 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002990{
2991 struct pending_cmd *cmd;
2992 int err;
2993
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002994 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002995 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002996 if (!cmd)
2997 return -ENOMEM;
2998
Johan Hedbergd8457692012-02-17 14:24:57 +02002999 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003000 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003001 if (err < 0)
3002 mgmt_pending_remove(cmd);
3003
3004 return err;
3005}
3006
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003007static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003008 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003009{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003010 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003011 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003012 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03003013 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003014 int err;
3015
3016 BT_DBG("");
3017
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003018 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003019
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003020 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003021 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003022 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003023 goto failed;
3024 }
3025
Johan Hedbergd8457692012-02-17 14:24:57 +02003026 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003027 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003028 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003029 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003030 goto failed;
3031 }
3032
3033 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003034 struct mgmt_cp_pin_code_neg_reply ncp;
3035
3036 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003037
3038 BT_ERR("PIN code is not 16 bytes long");
3039
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003040 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003041 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003042 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003043 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003044
3045 goto failed;
3046 }
3047
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003048 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003049 if (!cmd) {
3050 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003051 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003052 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003053
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003054 cmd->cmd_complete = addr_cmd_complete;
3055
Johan Hedbergd8457692012-02-17 14:24:57 +02003056 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003057 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003058 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003059
3060 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3061 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003062 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003063
3064failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003065 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003066 return err;
3067}
3068
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003069static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3070 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003071{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003072 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003073
3074 BT_DBG("");
3075
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003076 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
3077 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3078 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
3079
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003080 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003081
3082 hdev->io_capability = cp->io_capability;
3083
3084 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003085 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003086
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003087 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003088
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003089 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
3090 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003091}
3092
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003093static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003094{
3095 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003096 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003097
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003098 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003099 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3100 continue;
3101
Johan Hedberge9a416b2011-02-19 12:05:56 -03003102 if (cmd->user_data != conn)
3103 continue;
3104
3105 return cmd;
3106 }
3107
3108 return NULL;
3109}
3110
Johan Hedberg9df74652014-12-19 22:26:03 +02003111static int pairing_complete(struct pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003112{
3113 struct mgmt_rp_pair_device rp;
3114 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003115 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003116
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003117 bacpy(&rp.addr.bdaddr, &conn->dst);
3118 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003119
Johan Hedberg9df74652014-12-19 22:26:03 +02003120 err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
3121 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003122
3123 /* So we don't get further callbacks for this connection */
3124 conn->connect_cfm_cb = NULL;
3125 conn->security_cfm_cb = NULL;
3126 conn->disconn_cfm_cb = NULL;
3127
David Herrmann76a68ba2013-04-06 20:28:37 +02003128 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003129
3130 /* The device is paired so there is no need to remove
3131 * its connection parameters anymore.
3132 */
3133 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003134
3135 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003136
3137 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003138}
3139
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003140void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3141{
3142 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3143 struct pending_cmd *cmd;
3144
3145 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003146 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003147 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003148 mgmt_pending_remove(cmd);
3149 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003150}
3151
Johan Hedberge9a416b2011-02-19 12:05:56 -03003152static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3153{
3154 struct pending_cmd *cmd;
3155
3156 BT_DBG("status %u", status);
3157
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003158 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003159 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003160 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003161 return;
3162 }
3163
3164 cmd->cmd_complete(cmd, mgmt_status(status));
3165 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003166}
3167
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003168static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303169{
3170 struct pending_cmd *cmd;
3171
3172 BT_DBG("status %u", status);
3173
3174 if (!status)
3175 return;
3176
3177 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003178 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303179 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003180 return;
3181 }
3182
3183 cmd->cmd_complete(cmd, mgmt_status(status));
3184 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303185}
3186
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003187static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003188 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003189{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003190 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003191 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003192 struct pending_cmd *cmd;
3193 u8 sec_level, auth_type;
3194 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003195 int err;
3196
3197 BT_DBG("");
3198
Szymon Jancf950a30e2013-01-18 12:48:07 +01003199 memset(&rp, 0, sizeof(rp));
3200 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3201 rp.addr.type = cp->addr.type;
3202
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003203 if (!bdaddr_type_is_valid(cp->addr.type))
3204 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3205 MGMT_STATUS_INVALID_PARAMS,
3206 &rp, sizeof(rp));
3207
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003208 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3209 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3210 MGMT_STATUS_INVALID_PARAMS,
3211 &rp, sizeof(rp));
3212
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003213 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003214
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003215 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003216 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3217 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003218 goto unlock;
3219 }
3220
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003221 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003222 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003223
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003224 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003225 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3226 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003227 } else {
3228 u8 addr_type;
3229
3230 /* Convert from L2CAP channel address type to HCI address type
3231 */
3232 if (cp->addr.type == BDADDR_LE_PUBLIC)
3233 addr_type = ADDR_LE_DEV_PUBLIC;
3234 else
3235 addr_type = ADDR_LE_DEV_RANDOM;
3236
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003237 /* When pairing a new device, it is expected to remember
3238 * this device for future connections. Adding the connection
3239 * parameter information ahead of time allows tracking
3240 * of the slave preferred values and will speed up any
3241 * further connection establishment.
3242 *
3243 * If connection parameters already exist, then they
3244 * will be kept and this function does nothing.
3245 */
3246 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3247
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003248 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003249 sec_level, HCI_LE_CONN_TIMEOUT,
3250 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003251 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003252
Ville Tervo30e76272011-02-22 16:10:53 -03003253 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003254 int status;
3255
3256 if (PTR_ERR(conn) == -EBUSY)
3257 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003258 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3259 status = MGMT_STATUS_NOT_SUPPORTED;
3260 else if (PTR_ERR(conn) == -ECONNREFUSED)
3261 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003262 else
3263 status = MGMT_STATUS_CONNECT_FAILED;
3264
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003265 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003266 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003267 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003268 goto unlock;
3269 }
3270
3271 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003272 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003273 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003274 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003275 goto unlock;
3276 }
3277
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003278 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003279 if (!cmd) {
3280 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003281 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003282 goto unlock;
3283 }
3284
Johan Hedberg04ab2742014-12-05 13:36:04 +02003285 cmd->cmd_complete = pairing_complete;
3286
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003287 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003288 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003289 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003290 conn->security_cfm_cb = pairing_complete_cb;
3291 conn->disconn_cfm_cb = pairing_complete_cb;
3292 } else {
3293 conn->connect_cfm_cb = le_pairing_complete_cb;
3294 conn->security_cfm_cb = le_pairing_complete_cb;
3295 conn->disconn_cfm_cb = le_pairing_complete_cb;
3296 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003297
Johan Hedberge9a416b2011-02-19 12:05:56 -03003298 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003299 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003300
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003301 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003302 hci_conn_security(conn, sec_level, auth_type, true)) {
3303 cmd->cmd_complete(cmd, 0);
3304 mgmt_pending_remove(cmd);
3305 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003306
3307 err = 0;
3308
3309unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003310 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003311 return err;
3312}
3313
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003314static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3315 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003316{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003317 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003318 struct pending_cmd *cmd;
3319 struct hci_conn *conn;
3320 int err;
3321
3322 BT_DBG("");
3323
Johan Hedberg28424702012-02-02 04:02:29 +02003324 hci_dev_lock(hdev);
3325
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003326 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003327 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003328 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003329 goto unlock;
3330 }
3331
Johan Hedberg28424702012-02-02 04:02:29 +02003332 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3333 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003334 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003335 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003336 goto unlock;
3337 }
3338
3339 conn = cmd->user_data;
3340
3341 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003342 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003343 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003344 goto unlock;
3345 }
3346
Johan Hedberga511b352014-12-11 21:45:45 +02003347 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3348 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003349
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003350 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003351 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003352unlock:
3353 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003354 return err;
3355}
3356
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003357static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003358 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003359 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003360{
Johan Hedberga5c29682011-02-19 12:05:57 -03003361 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003362 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003363 int err;
3364
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003365 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003366
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003367 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003368 err = cmd_complete(sk, hdev->id, mgmt_op,
3369 MGMT_STATUS_NOT_POWERED, addr,
3370 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003371 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003372 }
3373
Johan Hedberg1707c602013-03-15 17:07:15 -05003374 if (addr->type == BDADDR_BREDR)
3375 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003376 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003377 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003378
Johan Hedberg272d90d2012-02-09 15:26:12 +02003379 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003380 err = cmd_complete(sk, hdev->id, mgmt_op,
3381 MGMT_STATUS_NOT_CONNECTED, addr,
3382 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003383 goto done;
3384 }
3385
Johan Hedberg1707c602013-03-15 17:07:15 -05003386 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003387 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003388 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003389 err = cmd_complete(sk, hdev->id, mgmt_op,
3390 MGMT_STATUS_SUCCESS, addr,
3391 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003392 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003393 err = cmd_complete(sk, hdev->id, mgmt_op,
3394 MGMT_STATUS_FAILED, addr,
3395 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003396
Brian Gix47c15e22011-11-16 13:53:14 -08003397 goto done;
3398 }
3399
Johan Hedberg1707c602013-03-15 17:07:15 -05003400 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003401 if (!cmd) {
3402 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003403 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003404 }
3405
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003406 cmd->cmd_complete = addr_cmd_complete;
3407
Brian Gix0df4c182011-11-16 13:53:13 -08003408 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003409 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3410 struct hci_cp_user_passkey_reply cp;
3411
Johan Hedberg1707c602013-03-15 17:07:15 -05003412 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003413 cp.passkey = passkey;
3414 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3415 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003416 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3417 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003418
Johan Hedberga664b5b2011-02-19 12:06:02 -03003419 if (err < 0)
3420 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003421
Brian Gix0df4c182011-11-16 13:53:13 -08003422done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003423 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003424 return err;
3425}
3426
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303427static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3428 void *data, u16 len)
3429{
3430 struct mgmt_cp_pin_code_neg_reply *cp = data;
3431
3432 BT_DBG("");
3433
Johan Hedberg1707c602013-03-15 17:07:15 -05003434 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303435 MGMT_OP_PIN_CODE_NEG_REPLY,
3436 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3437}
3438
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003439static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3440 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003441{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003442 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003443
3444 BT_DBG("");
3445
3446 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003447 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003448 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003449
Johan Hedberg1707c602013-03-15 17:07:15 -05003450 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003451 MGMT_OP_USER_CONFIRM_REPLY,
3452 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003453}
3454
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003455static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003456 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003457{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003458 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003459
3460 BT_DBG("");
3461
Johan Hedberg1707c602013-03-15 17:07:15 -05003462 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003463 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3464 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003465}
3466
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003467static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3468 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003469{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003470 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003471
3472 BT_DBG("");
3473
Johan Hedberg1707c602013-03-15 17:07:15 -05003474 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003475 MGMT_OP_USER_PASSKEY_REPLY,
3476 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003477}
3478
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003479static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003480 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003481{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003482 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003483
3484 BT_DBG("");
3485
Johan Hedberg1707c602013-03-15 17:07:15 -05003486 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003487 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3488 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003489}
3490
Johan Hedberg13928972013-03-15 17:07:00 -05003491static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003492{
Johan Hedberg13928972013-03-15 17:07:00 -05003493 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003494 struct hci_cp_write_local_name cp;
3495
Johan Hedberg13928972013-03-15 17:07:00 -05003496 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003497
Johan Hedberg890ea892013-03-15 17:06:52 -05003498 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003499}
3500
Marcel Holtmann1904a852015-01-11 13:50:44 -08003501static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003502{
3503 struct mgmt_cp_set_local_name *cp;
3504 struct pending_cmd *cmd;
3505
3506 BT_DBG("status 0x%02x", status);
3507
3508 hci_dev_lock(hdev);
3509
3510 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3511 if (!cmd)
3512 goto unlock;
3513
3514 cp = cmd->param;
3515
3516 if (status)
3517 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3518 mgmt_status(status));
3519 else
3520 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3521 cp, sizeof(*cp));
3522
3523 mgmt_pending_remove(cmd);
3524
3525unlock:
3526 hci_dev_unlock(hdev);
3527}
3528
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003529static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003530 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003531{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003532 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003533 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003534 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003535 int err;
3536
3537 BT_DBG("");
3538
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003539 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003540
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003541 /* If the old values are the same as the new ones just return a
3542 * direct command complete event.
3543 */
3544 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3545 !memcmp(hdev->short_name, cp->short_name,
3546 sizeof(hdev->short_name))) {
3547 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3548 data, len);
3549 goto failed;
3550 }
3551
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003552 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003553
Johan Hedbergb5235a62012-02-21 14:32:24 +02003554 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003555 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003556
3557 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003558 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003559 if (err < 0)
3560 goto failed;
3561
3562 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003563 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003564
Johan Hedbergb5235a62012-02-21 14:32:24 +02003565 goto failed;
3566 }
3567
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003568 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003569 if (!cmd) {
3570 err = -ENOMEM;
3571 goto failed;
3572 }
3573
Johan Hedberg13928972013-03-15 17:07:00 -05003574 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3575
Johan Hedberg890ea892013-03-15 17:06:52 -05003576 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003577
3578 if (lmp_bredr_capable(hdev)) {
3579 update_name(&req);
3580 update_eir(&req);
3581 }
3582
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003583 /* The name is stored in the scan response data and so
3584 * no need to udpate the advertising data here.
3585 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003586 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003587 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003588
Johan Hedberg13928972013-03-15 17:07:00 -05003589 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003590 if (err < 0)
3591 mgmt_pending_remove(cmd);
3592
3593failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003594 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003595 return err;
3596}
3597
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003598static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003599 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003600{
Szymon Jancc35938b2011-03-22 13:12:21 +01003601 struct pending_cmd *cmd;
3602 int err;
3603
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003604 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003605
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003606 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003607
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003608 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003609 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003610 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003611 goto unlock;
3612 }
3613
Andre Guedes9a1a1992012-07-24 15:03:48 -03003614 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003615 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003616 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003617 goto unlock;
3618 }
3619
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003620 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003621 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003622 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003623 goto unlock;
3624 }
3625
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003626 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003627 if (!cmd) {
3628 err = -ENOMEM;
3629 goto unlock;
3630 }
3631
Johan Hedberg710f11c2014-05-26 11:21:22 +03003632 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003633 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3634 0, NULL);
3635 else
3636 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3637
Szymon Jancc35938b2011-03-22 13:12:21 +01003638 if (err < 0)
3639 mgmt_pending_remove(cmd);
3640
3641unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003642 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003643 return err;
3644}
3645
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003646static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003647 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003648{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003649 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003650 int err;
3651
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003652 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003653
Johan Hedberg5d57e792015-01-23 10:10:38 +02003654 if (!bdaddr_type_is_valid(addr->type))
3655 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3656 MGMT_STATUS_INVALID_PARAMS, addr,
3657 sizeof(*addr));
3658
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003659 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003660
Marcel Holtmannec109112014-01-10 02:07:30 -08003661 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3662 struct mgmt_cp_add_remote_oob_data *cp = data;
3663 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003664
Johan Hedbergc19a4952014-11-17 20:52:19 +02003665 if (cp->addr.type != BDADDR_BREDR) {
3666 err = cmd_complete(sk, hdev->id,
3667 MGMT_OP_ADD_REMOTE_OOB_DATA,
3668 MGMT_STATUS_INVALID_PARAMS,
3669 &cp->addr, sizeof(cp->addr));
3670 goto unlock;
3671 }
3672
Marcel Holtmannec109112014-01-10 02:07:30 -08003673 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003674 cp->addr.type, cp->hash,
3675 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003676 if (err < 0)
3677 status = MGMT_STATUS_FAILED;
3678 else
3679 status = MGMT_STATUS_SUCCESS;
3680
3681 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3682 status, &cp->addr, sizeof(cp->addr));
3683 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3684 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003685 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003686 u8 status;
3687
Johan Hedberg86df9202014-10-26 20:52:27 +01003688 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003689 /* Enforce zero-valued 192-bit parameters as
3690 * long as legacy SMP OOB isn't implemented.
3691 */
3692 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3693 memcmp(cp->hash192, ZERO_KEY, 16)) {
3694 err = cmd_complete(sk, hdev->id,
3695 MGMT_OP_ADD_REMOTE_OOB_DATA,
3696 MGMT_STATUS_INVALID_PARAMS,
3697 addr, sizeof(*addr));
3698 goto unlock;
3699 }
3700
Johan Hedberg86df9202014-10-26 20:52:27 +01003701 rand192 = NULL;
3702 hash192 = NULL;
3703 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003704 /* In case one of the P-192 values is set to zero,
3705 * then just disable OOB data for P-192.
3706 */
3707 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3708 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3709 rand192 = NULL;
3710 hash192 = NULL;
3711 } else {
3712 rand192 = cp->rand192;
3713 hash192 = cp->hash192;
3714 }
3715 }
3716
3717 /* In case one of the P-256 values is set to zero, then just
3718 * disable OOB data for P-256.
3719 */
3720 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3721 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3722 rand256 = NULL;
3723 hash256 = NULL;
3724 } else {
3725 rand256 = cp->rand256;
3726 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003727 }
3728
Johan Hedberg81328d5c2014-10-26 20:33:47 +01003729 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003730 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003731 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003732 if (err < 0)
3733 status = MGMT_STATUS_FAILED;
3734 else
3735 status = MGMT_STATUS_SUCCESS;
3736
3737 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3738 status, &cp->addr, sizeof(cp->addr));
3739 } else {
3740 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3741 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3742 MGMT_STATUS_INVALID_PARAMS);
3743 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003744
Johan Hedbergc19a4952014-11-17 20:52:19 +02003745unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003746 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003747 return err;
3748}
3749
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003750static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003751 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003752{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003753 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003754 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003755 int err;
3756
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003757 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003758
Johan Hedbergc19a4952014-11-17 20:52:19 +02003759 if (cp->addr.type != BDADDR_BREDR)
3760 return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3761 MGMT_STATUS_INVALID_PARAMS,
3762 &cp->addr, sizeof(cp->addr));
3763
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003764 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003765
Johan Hedbergeedbd582014-11-15 09:34:23 +02003766 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3767 hci_remote_oob_data_clear(hdev);
3768 status = MGMT_STATUS_SUCCESS;
3769 goto done;
3770 }
3771
Johan Hedberg6928a922014-10-26 20:46:09 +01003772 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003773 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003774 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003775 else
Szymon Janca6785be2012-12-13 15:11:21 +01003776 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003777
Johan Hedbergeedbd582014-11-15 09:34:23 +02003778done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003779 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003780 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003781
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003782 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003783 return err;
3784}
3785
Marcel Holtmann80190442014-12-04 11:36:36 +01003786static bool trigger_discovery(struct hci_request *req, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003787{
Marcel Holtmann80190442014-12-04 11:36:36 +01003788 struct hci_dev *hdev = req->hdev;
3789 struct hci_cp_le_set_scan_param param_cp;
3790 struct hci_cp_le_set_scan_enable enable_cp;
3791 struct hci_cp_inquiry inq_cp;
3792 /* General inquiry access code (GIAC) */
3793 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3794 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003795 int err;
3796
Marcel Holtmann80190442014-12-04 11:36:36 +01003797 switch (hdev->discovery.type) {
3798 case DISCOV_TYPE_BREDR:
3799 *status = mgmt_bredr_support(hdev);
3800 if (*status)
3801 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003802
Marcel Holtmann80190442014-12-04 11:36:36 +01003803 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3804 *status = MGMT_STATUS_BUSY;
3805 return false;
3806 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003807
Marcel Holtmann80190442014-12-04 11:36:36 +01003808 hci_inquiry_cache_flush(hdev);
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003809
Marcel Holtmann80190442014-12-04 11:36:36 +01003810 memset(&inq_cp, 0, sizeof(inq_cp));
3811 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3812 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3813 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3814 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003815
Marcel Holtmann80190442014-12-04 11:36:36 +01003816 case DISCOV_TYPE_LE:
3817 case DISCOV_TYPE_INTERLEAVED:
3818 *status = mgmt_le_support(hdev);
3819 if (*status)
3820 return false;
3821
3822 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
3823 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
3824 *status = MGMT_STATUS_NOT_SUPPORTED;
3825 return false;
3826 }
3827
3828 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3829 /* Don't let discovery abort an outgoing
3830 * connection attempt that's using directed
3831 * advertising.
3832 */
3833 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3834 BT_CONNECT)) {
3835 *status = MGMT_STATUS_REJECTED;
3836 return false;
3837 }
3838
3839 disable_advertising(req);
3840 }
3841
3842 /* If controller is scanning, it means the background scanning
3843 * is running. Thus, we should temporarily stop it in order to
3844 * set the discovery scanning parameters.
3845 */
3846 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3847 hci_req_add_le_scan_disable(req);
3848
3849 memset(&param_cp, 0, sizeof(param_cp));
3850
3851 /* All active scans will be done with either a resolvable
3852 * private address (when privacy feature has been enabled)
Marcel Holtmann9437d2e2014-12-07 20:13:17 +01003853 * or non-resolvable private address.
Marcel Holtmann80190442014-12-04 11:36:36 +01003854 */
3855 err = hci_update_random_address(req, true, &own_addr_type);
3856 if (err < 0) {
3857 *status = MGMT_STATUS_FAILED;
3858 return false;
3859 }
3860
3861 param_cp.type = LE_SCAN_ACTIVE;
3862 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3863 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3864 param_cp.own_address_type = own_addr_type;
3865 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3866 &param_cp);
3867
3868 memset(&enable_cp, 0, sizeof(enable_cp));
3869 enable_cp.enable = LE_SCAN_ENABLE;
3870 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3871 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3872 &enable_cp);
3873 break;
3874
3875 default:
3876 *status = MGMT_STATUS_INVALID_PARAMS;
3877 return false;
3878 }
3879
3880 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003881}
3882
Marcel Holtmann1904a852015-01-11 13:50:44 -08003883static void start_discovery_complete(struct hci_dev *hdev, u8 status,
3884 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03003885{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003886 struct pending_cmd *cmd;
3887 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003888
Andre Guedes7c307722013-04-30 15:29:28 -03003889 BT_DBG("status %d", status);
3890
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003891 hci_dev_lock(hdev);
3892
3893 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003894 if (!cmd)
3895 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3896
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003897 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02003898 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003899 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03003900 }
3901
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003902 if (status) {
3903 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3904 goto unlock;
3905 }
3906
Andre Guedes7c307722013-04-30 15:29:28 -03003907 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03003908
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003909 /* If the scan involves LE scan, pick proper timeout to schedule
3910 * hdev->le_scan_disable that will stop it.
3911 */
Andre Guedes7c307722013-04-30 15:29:28 -03003912 switch (hdev->discovery.type) {
3913 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003914 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003915 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003916 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003917 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003918 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003919 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003920 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03003921 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003922 default:
3923 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003924 timeout = 0;
3925 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003926 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003927
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003928 if (timeout) {
3929 /* When service discovery is used and the controller has
3930 * a strict duplicate filter, it is important to remember
3931 * the start and duration of the scan. This is required
3932 * for restarting scanning during the discovery phase.
3933 */
3934 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
3935 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08003936 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003937 hdev->discovery.scan_start = jiffies;
3938 hdev->discovery.scan_duration = timeout;
3939 }
3940
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003941 queue_delayed_work(hdev->workqueue,
3942 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003943 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003944
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003945unlock:
3946 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03003947}
3948
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003949static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003950 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003951{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003952 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003953 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003954 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01003955 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04003956 int err;
3957
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003958 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003959
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003960 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003961
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003962 if (!hdev_is_powered(hdev)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003963 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3964 MGMT_STATUS_NOT_POWERED,
3965 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003966 goto failed;
3967 }
3968
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003969 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3970 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003971 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3972 MGMT_STATUS_BUSY, &cp->type,
3973 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03003974 goto failed;
3975 }
3976
Johan Hedberg2922a942014-12-05 13:36:06 +02003977 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04003978 if (!cmd) {
3979 err = -ENOMEM;
3980 goto failed;
3981 }
3982
Johan Hedberg2922a942014-12-05 13:36:06 +02003983 cmd->cmd_complete = generic_cmd_complete;
3984
Marcel Holtmann22078802014-12-05 11:45:22 +01003985 /* Clear the discovery filter first to free any previously
3986 * allocated memory for the UUID list.
3987 */
3988 hci_discovery_filter_clear(hdev);
3989
Andre Guedes4aab14e2012-02-17 20:39:36 -03003990 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01003991 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03003992
Andre Guedes7c307722013-04-30 15:29:28 -03003993 hci_req_init(&req, hdev);
3994
Marcel Holtmann80190442014-12-04 11:36:36 +01003995 if (!trigger_discovery(&req, &status)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003996 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Marcel Holtmann80190442014-12-04 11:36:36 +01003997 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02003998 mgmt_pending_remove(cmd);
3999 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004000 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004001
Andre Guedes7c307722013-04-30 15:29:28 -03004002 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004003 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004004 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004005 goto failed;
4006 }
4007
4008 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004009
4010failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004011 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004012 return err;
4013}
4014
Johan Hedberg9df74652014-12-19 22:26:03 +02004015static int service_discovery_cmd_complete(struct pending_cmd *cmd, u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004016{
Johan Hedberg9df74652014-12-19 22:26:03 +02004017 return cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4018 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004019}
4020
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004021static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4022 void *data, u16 len)
4023{
4024 struct mgmt_cp_start_service_discovery *cp = data;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004025 struct pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004026 struct hci_request req;
4027 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4028 u16 uuid_count, expected_len;
4029 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004030 int err;
4031
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004032 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004033
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004034 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004035
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004036 if (!hdev_is_powered(hdev)) {
4037 err = cmd_complete(sk, hdev->id,
4038 MGMT_OP_START_SERVICE_DISCOVERY,
4039 MGMT_STATUS_NOT_POWERED,
4040 &cp->type, sizeof(cp->type));
4041 goto failed;
4042 }
4043
4044 if (hdev->discovery.state != DISCOVERY_STOPPED ||
4045 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
4046 err = cmd_complete(sk, hdev->id,
4047 MGMT_OP_START_SERVICE_DISCOVERY,
4048 MGMT_STATUS_BUSY, &cp->type,
4049 sizeof(cp->type));
4050 goto failed;
4051 }
4052
4053 uuid_count = __le16_to_cpu(cp->uuid_count);
4054 if (uuid_count > max_uuid_count) {
4055 BT_ERR("service_discovery: too big uuid_count value %u",
4056 uuid_count);
4057 err = cmd_complete(sk, hdev->id,
4058 MGMT_OP_START_SERVICE_DISCOVERY,
4059 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4060 sizeof(cp->type));
4061 goto failed;
4062 }
4063
4064 expected_len = sizeof(*cp) + uuid_count * 16;
4065 if (expected_len != len) {
4066 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4067 expected_len, len);
4068 err = cmd_complete(sk, hdev->id,
4069 MGMT_OP_START_SERVICE_DISCOVERY,
4070 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4071 sizeof(cp->type));
4072 goto failed;
4073 }
4074
4075 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004076 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004077 if (!cmd) {
4078 err = -ENOMEM;
4079 goto failed;
4080 }
4081
Johan Hedberg2922a942014-12-05 13:36:06 +02004082 cmd->cmd_complete = service_discovery_cmd_complete;
4083
Marcel Holtmann22078802014-12-05 11:45:22 +01004084 /* Clear the discovery filter first to free any previously
4085 * allocated memory for the UUID list.
4086 */
4087 hci_discovery_filter_clear(hdev);
4088
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004089 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004090 hdev->discovery.type = cp->type;
4091 hdev->discovery.rssi = cp->rssi;
4092 hdev->discovery.uuid_count = uuid_count;
4093
4094 if (uuid_count > 0) {
4095 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4096 GFP_KERNEL);
4097 if (!hdev->discovery.uuids) {
4098 err = cmd_complete(sk, hdev->id,
4099 MGMT_OP_START_SERVICE_DISCOVERY,
4100 MGMT_STATUS_FAILED,
4101 &cp->type, sizeof(cp->type));
4102 mgmt_pending_remove(cmd);
4103 goto failed;
4104 }
4105 }
4106
4107 hci_req_init(&req, hdev);
4108
4109 if (!trigger_discovery(&req, &status)) {
4110 err = cmd_complete(sk, hdev->id,
4111 MGMT_OP_START_SERVICE_DISCOVERY,
4112 status, &cp->type, sizeof(cp->type));
4113 mgmt_pending_remove(cmd);
4114 goto failed;
4115 }
4116
4117 err = hci_req_run(&req, start_discovery_complete);
4118 if (err < 0) {
4119 mgmt_pending_remove(cmd);
4120 goto failed;
4121 }
4122
4123 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4124
4125failed:
4126 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004127 return err;
4128}
4129
Marcel Holtmann1904a852015-01-11 13:50:44 -08004130static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004131{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004132 struct pending_cmd *cmd;
4133
Andre Guedes0e05bba2013-04-30 15:29:33 -03004134 BT_DBG("status %d", status);
4135
4136 hci_dev_lock(hdev);
4137
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004138 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4139 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004140 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004141 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004142 }
4143
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004144 if (!status)
4145 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004146
Andre Guedes0e05bba2013-04-30 15:29:33 -03004147 hci_dev_unlock(hdev);
4148}
4149
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004150static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004151 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004152{
Johan Hedbergd9306502012-02-20 23:25:18 +02004153 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04004154 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004155 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004156 int err;
4157
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004158 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004159
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004160 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004161
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004162 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004163 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004164 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4165 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004166 goto unlock;
4167 }
4168
4169 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004170 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004171 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
4172 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004173 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004174 }
4175
Johan Hedberg2922a942014-12-05 13:36:06 +02004176 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004177 if (!cmd) {
4178 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004179 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004180 }
4181
Johan Hedberg2922a942014-12-05 13:36:06 +02004182 cmd->cmd_complete = generic_cmd_complete;
4183
Andre Guedes0e05bba2013-04-30 15:29:33 -03004184 hci_req_init(&req, hdev);
4185
Johan Hedberg21a60d32014-06-10 14:05:58 +03004186 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004187
Johan Hedberg21a60d32014-06-10 14:05:58 +03004188 err = hci_req_run(&req, stop_discovery_complete);
4189 if (!err) {
4190 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004191 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004192 }
4193
Johan Hedberg21a60d32014-06-10 14:05:58 +03004194 mgmt_pending_remove(cmd);
4195
4196 /* If no HCI commands were sent we're done */
4197 if (err == -ENODATA) {
4198 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4199 &mgmt_cp->type, sizeof(mgmt_cp->type));
4200 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4201 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004202
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004203unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004204 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004205 return err;
4206}
4207
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004208static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004209 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004210{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004211 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004212 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004213 int err;
4214
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004215 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004216
Johan Hedberg561aafb2012-01-04 13:31:59 +02004217 hci_dev_lock(hdev);
4218
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004219 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004220 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4221 MGMT_STATUS_FAILED, &cp->addr,
4222 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004223 goto failed;
4224 }
4225
Johan Hedberga198e7b2012-02-17 14:27:06 +02004226 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004227 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004228 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4229 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4230 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004231 goto failed;
4232 }
4233
4234 if (cp->name_known) {
4235 e->name_state = NAME_KNOWN;
4236 list_del(&e->list);
4237 } else {
4238 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e20a2012-01-09 00:53:02 +02004239 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004240 }
4241
Johan Hedberge3846622013-01-09 15:29:33 +02004242 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
4243 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004244
4245failed:
4246 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004247 return err;
4248}
4249
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004250static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004251 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004252{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004253 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004254 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004255 int err;
4256
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004257 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004258
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004259 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004260 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4261 MGMT_STATUS_INVALID_PARAMS,
4262 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004263
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004264 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004265
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004266 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4267 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004268 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004269 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004270 goto done;
4271 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004272
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004273 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4274 sk);
4275 status = MGMT_STATUS_SUCCESS;
4276
4277done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004278 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004279 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004280
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004281 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004282
4283 return err;
4284}
4285
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004286static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004287 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004288{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004289 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004290 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004291 int err;
4292
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004293 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004294
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004295 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004296 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4297 MGMT_STATUS_INVALID_PARAMS,
4298 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004299
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004300 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004301
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004302 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4303 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004304 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004305 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004306 goto done;
4307 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004308
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004309 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4310 sk);
4311 status = MGMT_STATUS_SUCCESS;
4312
4313done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004314 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004315 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004316
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004317 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004318
4319 return err;
4320}
4321
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004322static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4323 u16 len)
4324{
4325 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004326 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004327 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004328 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004329
4330 BT_DBG("%s", hdev->name);
4331
Szymon Jancc72d4b82012-03-16 16:02:57 +01004332 source = __le16_to_cpu(cp->source);
4333
4334 if (source > 0x0002)
4335 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4336 MGMT_STATUS_INVALID_PARAMS);
4337
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004338 hci_dev_lock(hdev);
4339
Szymon Jancc72d4b82012-03-16 16:02:57 +01004340 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004341 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4342 hdev->devid_product = __le16_to_cpu(cp->product);
4343 hdev->devid_version = __le16_to_cpu(cp->version);
4344
4345 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4346
Johan Hedberg890ea892013-03-15 17:06:52 -05004347 hci_req_init(&req, hdev);
4348 update_eir(&req);
4349 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004350
4351 hci_dev_unlock(hdev);
4352
4353 return err;
4354}
4355
Marcel Holtmann1904a852015-01-11 13:50:44 -08004356static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4357 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004358{
4359 struct cmd_lookup match = { NULL, hdev };
4360
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304361 hci_dev_lock(hdev);
4362
Johan Hedberg4375f102013-09-25 13:26:10 +03004363 if (status) {
4364 u8 mgmt_err = mgmt_status(status);
4365
4366 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4367 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304368 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004369 }
4370
Johan Hedbergc93bd152014-07-08 15:07:48 +03004371 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4372 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4373 else
4374 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4375
Johan Hedberg4375f102013-09-25 13:26:10 +03004376 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4377 &match);
4378
4379 new_settings(hdev, match.sk);
4380
4381 if (match.sk)
4382 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304383
4384unlock:
4385 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004386}
4387
Marcel Holtmann21b51872013-10-10 09:47:53 -07004388static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4389 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004390{
4391 struct mgmt_mode *cp = data;
4392 struct pending_cmd *cmd;
4393 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004394 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004395 int err;
4396
4397 BT_DBG("request for %s", hdev->name);
4398
Johan Hedberge6fe7982013-10-02 15:45:22 +03004399 status = mgmt_le_support(hdev);
4400 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004401 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004402 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004403
4404 if (cp->val != 0x00 && cp->val != 0x01)
4405 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4406 MGMT_STATUS_INVALID_PARAMS);
4407
4408 hci_dev_lock(hdev);
4409
4410 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004411 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004412
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004413 /* The following conditions are ones which mean that we should
4414 * not do any HCI communication but directly send a mgmt
4415 * response to user space (after toggling the flag if
4416 * necessary).
4417 */
4418 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004419 hci_conn_num(hdev, LE_LINK) > 0 ||
4420 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4421 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004422 bool changed = false;
4423
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004424 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4425 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004426 changed = true;
4427 }
4428
4429 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4430 if (err < 0)
4431 goto unlock;
4432
4433 if (changed)
4434 err = new_settings(hdev, sk);
4435
4436 goto unlock;
4437 }
4438
4439 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4440 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4441 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4442 MGMT_STATUS_BUSY);
4443 goto unlock;
4444 }
4445
4446 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4447 if (!cmd) {
4448 err = -ENOMEM;
4449 goto unlock;
4450 }
4451
4452 hci_req_init(&req, hdev);
4453
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004454 if (val)
4455 enable_advertising(&req);
4456 else
4457 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004458
4459 err = hci_req_run(&req, set_advertising_complete);
4460 if (err < 0)
4461 mgmt_pending_remove(cmd);
4462
4463unlock:
4464 hci_dev_unlock(hdev);
4465 return err;
4466}
4467
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004468static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4469 void *data, u16 len)
4470{
4471 struct mgmt_cp_set_static_address *cp = data;
4472 int err;
4473
4474 BT_DBG("%s", hdev->name);
4475
Marcel Holtmann62af4442013-10-02 22:10:32 -07004476 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004477 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004478 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004479
4480 if (hdev_is_powered(hdev))
4481 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4482 MGMT_STATUS_REJECTED);
4483
4484 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4485 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4486 return cmd_status(sk, hdev->id,
4487 MGMT_OP_SET_STATIC_ADDRESS,
4488 MGMT_STATUS_INVALID_PARAMS);
4489
4490 /* Two most significant bits shall be set */
4491 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4492 return cmd_status(sk, hdev->id,
4493 MGMT_OP_SET_STATIC_ADDRESS,
4494 MGMT_STATUS_INVALID_PARAMS);
4495 }
4496
4497 hci_dev_lock(hdev);
4498
4499 bacpy(&hdev->static_addr, &cp->bdaddr);
4500
4501 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4502
4503 hci_dev_unlock(hdev);
4504
4505 return err;
4506}
4507
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004508static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4509 void *data, u16 len)
4510{
4511 struct mgmt_cp_set_scan_params *cp = data;
4512 __u16 interval, window;
4513 int err;
4514
4515 BT_DBG("%s", hdev->name);
4516
4517 if (!lmp_le_capable(hdev))
4518 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4519 MGMT_STATUS_NOT_SUPPORTED);
4520
4521 interval = __le16_to_cpu(cp->interval);
4522
4523 if (interval < 0x0004 || interval > 0x4000)
4524 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4525 MGMT_STATUS_INVALID_PARAMS);
4526
4527 window = __le16_to_cpu(cp->window);
4528
4529 if (window < 0x0004 || window > 0x4000)
4530 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4531 MGMT_STATUS_INVALID_PARAMS);
4532
Marcel Holtmann899e1072013-10-14 09:55:32 -07004533 if (window > interval)
4534 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4535 MGMT_STATUS_INVALID_PARAMS);
4536
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004537 hci_dev_lock(hdev);
4538
4539 hdev->le_scan_interval = interval;
4540 hdev->le_scan_window = window;
4541
4542 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4543
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004544 /* If background scan is running, restart it so new parameters are
4545 * loaded.
4546 */
4547 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4548 hdev->discovery.state == DISCOVERY_STOPPED) {
4549 struct hci_request req;
4550
4551 hci_req_init(&req, hdev);
4552
4553 hci_req_add_le_scan_disable(&req);
4554 hci_req_add_le_passive_scan(&req);
4555
4556 hci_req_run(&req, NULL);
4557 }
4558
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004559 hci_dev_unlock(hdev);
4560
4561 return err;
4562}
4563
Marcel Holtmann1904a852015-01-11 13:50:44 -08004564static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4565 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004566{
4567 struct pending_cmd *cmd;
4568
4569 BT_DBG("status 0x%02x", status);
4570
4571 hci_dev_lock(hdev);
4572
4573 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4574 if (!cmd)
4575 goto unlock;
4576
4577 if (status) {
4578 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4579 mgmt_status(status));
4580 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004581 struct mgmt_mode *cp = cmd->param;
4582
4583 if (cp->val)
4584 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4585 else
4586 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4587
Johan Hedberg33e38b32013-03-15 17:07:05 -05004588 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4589 new_settings(hdev, cmd->sk);
4590 }
4591
4592 mgmt_pending_remove(cmd);
4593
4594unlock:
4595 hci_dev_unlock(hdev);
4596}
4597
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004598static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004599 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004600{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004601 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004602 struct pending_cmd *cmd;
4603 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004604 int err;
4605
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004606 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004607
Johan Hedberg56f87902013-10-02 13:43:13 +03004608 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4609 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004610 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4611 MGMT_STATUS_NOT_SUPPORTED);
4612
Johan Hedberga7e80f22013-01-09 16:05:19 +02004613 if (cp->val != 0x00 && cp->val != 0x01)
4614 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4615 MGMT_STATUS_INVALID_PARAMS);
4616
Johan Hedberg5400c042012-02-21 16:40:33 +02004617 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004618 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004619 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004620
4621 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004622 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004623 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004624
4625 hci_dev_lock(hdev);
4626
Johan Hedberg05cbf292013-03-15 17:07:07 -05004627 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4628 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4629 MGMT_STATUS_BUSY);
4630 goto unlock;
4631 }
4632
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004633 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4634 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4635 hdev);
4636 goto unlock;
4637 }
4638
Johan Hedberg33e38b32013-03-15 17:07:05 -05004639 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4640 data, len);
4641 if (!cmd) {
4642 err = -ENOMEM;
4643 goto unlock;
4644 }
4645
4646 hci_req_init(&req, hdev);
4647
Johan Hedberg406d7802013-03-15 17:07:09 -05004648 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004649
4650 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004651 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004652 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004653 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004654 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004655 }
4656
Johan Hedberg33e38b32013-03-15 17:07:05 -05004657unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004658 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004659
Antti Julkuf6422ec2011-06-22 13:11:56 +03004660 return err;
4661}
4662
Marcel Holtmann1904a852015-01-11 13:50:44 -08004663static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004664{
4665 struct pending_cmd *cmd;
4666
4667 BT_DBG("status 0x%02x", status);
4668
4669 hci_dev_lock(hdev);
4670
4671 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4672 if (!cmd)
4673 goto unlock;
4674
4675 if (status) {
4676 u8 mgmt_err = mgmt_status(status);
4677
4678 /* We need to restore the flag if related HCI commands
4679 * failed.
4680 */
4681 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4682
4683 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4684 } else {
4685 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4686 new_settings(hdev, cmd->sk);
4687 }
4688
4689 mgmt_pending_remove(cmd);
4690
4691unlock:
4692 hci_dev_unlock(hdev);
4693}
4694
4695static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4696{
4697 struct mgmt_mode *cp = data;
4698 struct pending_cmd *cmd;
4699 struct hci_request req;
4700 int err;
4701
4702 BT_DBG("request for %s", hdev->name);
4703
4704 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4705 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4706 MGMT_STATUS_NOT_SUPPORTED);
4707
4708 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4709 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4710 MGMT_STATUS_REJECTED);
4711
4712 if (cp->val != 0x00 && cp->val != 0x01)
4713 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4714 MGMT_STATUS_INVALID_PARAMS);
4715
4716 hci_dev_lock(hdev);
4717
4718 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4719 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4720 goto unlock;
4721 }
4722
4723 if (!hdev_is_powered(hdev)) {
4724 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004725 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4726 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4727 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4728 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4729 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4730 }
4731
4732 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4733
4734 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4735 if (err < 0)
4736 goto unlock;
4737
4738 err = new_settings(hdev, sk);
4739 goto unlock;
4740 }
4741
4742 /* Reject disabling when powered on */
4743 if (!cp->val) {
4744 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4745 MGMT_STATUS_REJECTED);
4746 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004747 } else {
4748 /* When configuring a dual-mode controller to operate
4749 * with LE only and using a static address, then switching
4750 * BR/EDR back on is not allowed.
4751 *
4752 * Dual-mode controllers shall operate with the public
4753 * address as its identity address for BR/EDR and LE. So
4754 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004755 *
4756 * The same restrictions applies when secure connections
4757 * has been enabled. For BR/EDR this is a controller feature
4758 * while for LE it is a host stack feature. This means that
4759 * switching BR/EDR back on when secure connections has been
4760 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004761 */
4762 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004763 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
4764 test_bit(HCI_SC_ENABLED, &hdev->dev_flags))) {
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004765 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4766 MGMT_STATUS_REJECTED);
4767 goto unlock;
4768 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03004769 }
4770
4771 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4772 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4773 MGMT_STATUS_BUSY);
4774 goto unlock;
4775 }
4776
4777 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4778 if (!cmd) {
4779 err = -ENOMEM;
4780 goto unlock;
4781 }
4782
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004783 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004784 * generates the correct flags.
4785 */
4786 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4787
4788 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004789
Johan Hedberg432df052014-08-01 11:13:31 +03004790 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02004791 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004792
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004793 /* Since only the advertising data flags will change, there
4794 * is no need to update the scan response data.
4795 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004796 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004797
Johan Hedberg0663ca22013-10-02 13:43:14 +03004798 err = hci_req_run(&req, set_bredr_complete);
4799 if (err < 0)
4800 mgmt_pending_remove(cmd);
4801
4802unlock:
4803 hci_dev_unlock(hdev);
4804 return err;
4805}
4806
Johan Hedberga1443f52015-01-23 15:42:46 +02004807static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
4808{
4809 struct pending_cmd *cmd;
4810 struct mgmt_mode *cp;
4811
4812 BT_DBG("%s status %u", hdev->name, status);
4813
4814 hci_dev_lock(hdev);
4815
4816 cmd = mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
4817 if (!cmd)
4818 goto unlock;
4819
4820 if (status) {
4821 cmd_status(cmd->sk, cmd->index, cmd->opcode,
4822 mgmt_status(status));
4823 goto remove;
4824 }
4825
4826 cp = cmd->param;
4827
4828 switch (cp->val) {
4829 case 0x00:
4830 clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4831 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4832 break;
4833 case 0x01:
4834 set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4835 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4836 break;
4837 case 0x02:
4838 set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
4839 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4840 break;
4841 }
4842
4843 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
4844 new_settings(hdev, cmd->sk);
4845
4846remove:
4847 mgmt_pending_remove(cmd);
4848unlock:
4849 hci_dev_unlock(hdev);
4850}
4851
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004852static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4853 void *data, u16 len)
4854{
4855 struct mgmt_mode *cp = data;
4856 struct pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02004857 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03004858 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004859 int err;
4860
4861 BT_DBG("request for %s", hdev->name);
4862
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004863 if (!lmp_sc_capable(hdev) &&
4864 !test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004865 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4866 MGMT_STATUS_NOT_SUPPORTED);
4867
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004868 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) &&
Johan Hedberg59200282015-01-28 19:56:00 +02004869 lmp_sc_capable(hdev) &&
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004870 !test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
4871 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4872 MGMT_STATUS_REJECTED);
4873
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004874 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004875 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4876 MGMT_STATUS_INVALID_PARAMS);
4877
4878 hci_dev_lock(hdev);
4879
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004880 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Johan Hedberga3209692014-05-26 11:23:35 +03004881 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004882 bool changed;
4883
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004884 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004885 changed = !test_and_set_bit(HCI_SC_ENABLED,
4886 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004887 if (cp->val == 0x02)
4888 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4889 else
4890 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4891 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004892 changed = test_and_clear_bit(HCI_SC_ENABLED,
4893 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004894 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4895 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004896
4897 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4898 if (err < 0)
4899 goto failed;
4900
4901 if (changed)
4902 err = new_settings(hdev, sk);
4903
4904 goto failed;
4905 }
4906
4907 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4908 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4909 MGMT_STATUS_BUSY);
4910 goto failed;
4911 }
4912
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004913 val = !!cp->val;
4914
4915 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4916 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004917 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4918 goto failed;
4919 }
4920
4921 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4922 if (!cmd) {
4923 err = -ENOMEM;
4924 goto failed;
4925 }
4926
Johan Hedberga1443f52015-01-23 15:42:46 +02004927 hci_req_init(&req, hdev);
4928 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
4929 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004930 if (err < 0) {
4931 mgmt_pending_remove(cmd);
4932 goto failed;
4933 }
4934
4935failed:
4936 hci_dev_unlock(hdev);
4937 return err;
4938}
4939
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004940static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4941 void *data, u16 len)
4942{
4943 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004944 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004945 int err;
4946
4947 BT_DBG("request for %s", hdev->name);
4948
Johan Hedbergb97109792014-06-24 14:00:28 +03004949 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004950 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4951 MGMT_STATUS_INVALID_PARAMS);
4952
4953 hci_dev_lock(hdev);
4954
4955 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004956 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4957 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004958 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004959 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4960 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004961
Johan Hedbergb97109792014-06-24 14:00:28 +03004962 if (cp->val == 0x02)
4963 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4964 &hdev->dev_flags);
4965 else
4966 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4967 &hdev->dev_flags);
4968
4969 if (hdev_is_powered(hdev) && use_changed &&
4970 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4971 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4972 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4973 sizeof(mode), &mode);
4974 }
4975
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004976 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4977 if (err < 0)
4978 goto unlock;
4979
4980 if (changed)
4981 err = new_settings(hdev, sk);
4982
4983unlock:
4984 hci_dev_unlock(hdev);
4985 return err;
4986}
4987
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004988static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4989 u16 len)
4990{
4991 struct mgmt_cp_set_privacy *cp = cp_data;
4992 bool changed;
4993 int err;
4994
4995 BT_DBG("request for %s", hdev->name);
4996
4997 if (!lmp_le_capable(hdev))
4998 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4999 MGMT_STATUS_NOT_SUPPORTED);
5000
5001 if (cp->privacy != 0x00 && cp->privacy != 0x01)
5002 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5003 MGMT_STATUS_INVALID_PARAMS);
5004
5005 if (hdev_is_powered(hdev))
5006 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5007 MGMT_STATUS_REJECTED);
5008
5009 hci_dev_lock(hdev);
5010
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005011 /* If user space supports this command it is also expected to
5012 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5013 */
5014 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
5015
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005016 if (cp->privacy) {
5017 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
5018 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
5019 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
5020 } else {
5021 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
5022 memset(hdev->irk, 0, sizeof(hdev->irk));
5023 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
5024 }
5025
5026 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5027 if (err < 0)
5028 goto unlock;
5029
5030 if (changed)
5031 err = new_settings(hdev, sk);
5032
5033unlock:
5034 hci_dev_unlock(hdev);
5035 return err;
5036}
5037
Johan Hedberg41edf162014-02-18 10:19:35 +02005038static bool irk_is_valid(struct mgmt_irk_info *irk)
5039{
5040 switch (irk->addr.type) {
5041 case BDADDR_LE_PUBLIC:
5042 return true;
5043
5044 case BDADDR_LE_RANDOM:
5045 /* Two most significant bits shall be set */
5046 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5047 return false;
5048 return true;
5049 }
5050
5051 return false;
5052}
5053
5054static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5055 u16 len)
5056{
5057 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005058 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5059 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005060 u16 irk_count, expected_len;
5061 int i, err;
5062
5063 BT_DBG("request for %s", hdev->name);
5064
5065 if (!lmp_le_capable(hdev))
5066 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5067 MGMT_STATUS_NOT_SUPPORTED);
5068
5069 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005070 if (irk_count > max_irk_count) {
5071 BT_ERR("load_irks: too big irk_count value %u", irk_count);
5072 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5073 MGMT_STATUS_INVALID_PARAMS);
5074 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005075
5076 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5077 if (expected_len != len) {
5078 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005079 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02005080 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5081 MGMT_STATUS_INVALID_PARAMS);
5082 }
5083
5084 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5085
5086 for (i = 0; i < irk_count; i++) {
5087 struct mgmt_irk_info *key = &cp->irks[i];
5088
5089 if (!irk_is_valid(key))
5090 return cmd_status(sk, hdev->id,
5091 MGMT_OP_LOAD_IRKS,
5092 MGMT_STATUS_INVALID_PARAMS);
5093 }
5094
5095 hci_dev_lock(hdev);
5096
5097 hci_smp_irks_clear(hdev);
5098
5099 for (i = 0; i < irk_count; i++) {
5100 struct mgmt_irk_info *irk = &cp->irks[i];
5101 u8 addr_type;
5102
5103 if (irk->addr.type == BDADDR_LE_PUBLIC)
5104 addr_type = ADDR_LE_DEV_PUBLIC;
5105 else
5106 addr_type = ADDR_LE_DEV_RANDOM;
5107
5108 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5109 BDADDR_ANY);
5110 }
5111
5112 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
5113
5114 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
5115
5116 hci_dev_unlock(hdev);
5117
5118 return err;
5119}
5120
Johan Hedberg3f706b72013-01-20 14:27:16 +02005121static bool ltk_is_valid(struct mgmt_ltk_info *key)
5122{
5123 if (key->master != 0x00 && key->master != 0x01)
5124 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005125
5126 switch (key->addr.type) {
5127 case BDADDR_LE_PUBLIC:
5128 return true;
5129
5130 case BDADDR_LE_RANDOM:
5131 /* Two most significant bits shall be set */
5132 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5133 return false;
5134 return true;
5135 }
5136
5137 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005138}
5139
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005140static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005141 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005142{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005143 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005144 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5145 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005146 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005147 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005148
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005149 BT_DBG("request for %s", hdev->name);
5150
5151 if (!lmp_le_capable(hdev))
5152 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5153 MGMT_STATUS_NOT_SUPPORTED);
5154
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005155 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005156 if (key_count > max_key_count) {
5157 BT_ERR("load_ltks: too big key_count value %u", key_count);
5158 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5159 MGMT_STATUS_INVALID_PARAMS);
5160 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005161
5162 expected_len = sizeof(*cp) + key_count *
5163 sizeof(struct mgmt_ltk_info);
5164 if (expected_len != len) {
5165 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005166 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005167 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02005168 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005169 }
5170
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005171 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005172
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005173 for (i = 0; i < key_count; i++) {
5174 struct mgmt_ltk_info *key = &cp->keys[i];
5175
Johan Hedberg3f706b72013-01-20 14:27:16 +02005176 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005177 return cmd_status(sk, hdev->id,
5178 MGMT_OP_LOAD_LONG_TERM_KEYS,
5179 MGMT_STATUS_INVALID_PARAMS);
5180 }
5181
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005182 hci_dev_lock(hdev);
5183
5184 hci_smp_ltks_clear(hdev);
5185
5186 for (i = 0; i < key_count; i++) {
5187 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005188 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005189
5190 if (key->addr.type == BDADDR_LE_PUBLIC)
5191 addr_type = ADDR_LE_DEV_PUBLIC;
5192 else
5193 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005194
Johan Hedberg61b43352014-05-29 19:36:53 +03005195 switch (key->type) {
5196 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005197 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005198 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005199 break;
5200 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005201 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005202 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005203 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005204 case MGMT_LTK_P256_UNAUTH:
5205 authenticated = 0x00;
5206 type = SMP_LTK_P256;
5207 break;
5208 case MGMT_LTK_P256_AUTH:
5209 authenticated = 0x01;
5210 type = SMP_LTK_P256;
5211 break;
5212 case MGMT_LTK_P256_DEBUG:
5213 authenticated = 0x00;
5214 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005215 default:
5216 continue;
5217 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005218
Johan Hedberg35d70272014-02-19 14:57:47 +02005219 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005220 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005221 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005222 }
5223
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005224 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
5225 NULL, 0);
5226
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005227 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005228
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005229 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005230}
5231
Johan Hedberg9df74652014-12-19 22:26:03 +02005232static int conn_info_cmd_complete(struct pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005233{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005234 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005235 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005236 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005237
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005238 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005239
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005240 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005241 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005242 rp.tx_power = conn->tx_power;
5243 rp.max_tx_power = conn->max_tx_power;
5244 } else {
5245 rp.rssi = HCI_RSSI_INVALID;
5246 rp.tx_power = HCI_TX_POWER_INVALID;
5247 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005248 }
5249
Johan Hedberg9df74652014-12-19 22:26:03 +02005250 err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO, status,
5251 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005252
5253 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005254 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005255
5256 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005257}
5258
Marcel Holtmann1904a852015-01-11 13:50:44 -08005259static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5260 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005261{
5262 struct hci_cp_read_rssi *cp;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005263 struct pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005264 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005265 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005266 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005267
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005268 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005269
5270 hci_dev_lock(hdev);
5271
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005272 /* Commands sent in request are either Read RSSI or Read Transmit Power
5273 * Level so we check which one was last sent to retrieve connection
5274 * handle. Both commands have handle as first parameter so it's safe to
5275 * cast data on the same command struct.
5276 *
5277 * First command sent is always Read RSSI and we fail only if it fails.
5278 * In other case we simply override error to indicate success as we
5279 * already remembered if TX power value is actually valid.
5280 */
5281 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5282 if (!cp) {
5283 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005284 status = MGMT_STATUS_SUCCESS;
5285 } else {
5286 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005287 }
5288
5289 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005290 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005291 goto unlock;
5292 }
5293
5294 handle = __le16_to_cpu(cp->handle);
5295 conn = hci_conn_hash_lookup_handle(hdev, handle);
5296 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005297 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005298 goto unlock;
5299 }
5300
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005301 cmd = mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
5302 if (!cmd)
5303 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005304
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005305 cmd->cmd_complete(cmd, status);
5306 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005307
5308unlock:
5309 hci_dev_unlock(hdev);
5310}
5311
5312static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5313 u16 len)
5314{
5315 struct mgmt_cp_get_conn_info *cp = data;
5316 struct mgmt_rp_get_conn_info rp;
5317 struct hci_conn *conn;
5318 unsigned long conn_info_age;
5319 int err = 0;
5320
5321 BT_DBG("%s", hdev->name);
5322
5323 memset(&rp, 0, sizeof(rp));
5324 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5325 rp.addr.type = cp->addr.type;
5326
5327 if (!bdaddr_type_is_valid(cp->addr.type))
5328 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5329 MGMT_STATUS_INVALID_PARAMS,
5330 &rp, sizeof(rp));
5331
5332 hci_dev_lock(hdev);
5333
5334 if (!hdev_is_powered(hdev)) {
5335 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5336 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5337 goto unlock;
5338 }
5339
5340 if (cp->addr.type == BDADDR_BREDR)
5341 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5342 &cp->addr.bdaddr);
5343 else
5344 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5345
5346 if (!conn || conn->state != BT_CONNECTED) {
5347 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5348 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
5349 goto unlock;
5350 }
5351
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005352 if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
5353 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5354 MGMT_STATUS_BUSY, &rp, sizeof(rp));
5355 goto unlock;
5356 }
5357
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005358 /* To avoid client trying to guess when to poll again for information we
5359 * calculate conn info age as random value between min/max set in hdev.
5360 */
5361 conn_info_age = hdev->conn_info_min_age +
5362 prandom_u32_max(hdev->conn_info_max_age -
5363 hdev->conn_info_min_age);
5364
5365 /* Query controller to refresh cached values if they are too old or were
5366 * never read.
5367 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005368 if (time_after(jiffies, conn->conn_info_timestamp +
5369 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005370 !conn->conn_info_timestamp) {
5371 struct hci_request req;
5372 struct hci_cp_read_tx_power req_txp_cp;
5373 struct hci_cp_read_rssi req_rssi_cp;
5374 struct pending_cmd *cmd;
5375
5376 hci_req_init(&req, hdev);
5377 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5378 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5379 &req_rssi_cp);
5380
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005381 /* For LE links TX power does not change thus we don't need to
5382 * query for it once value is known.
5383 */
5384 if (!bdaddr_type_is_le(cp->addr.type) ||
5385 conn->tx_power == HCI_TX_POWER_INVALID) {
5386 req_txp_cp.handle = cpu_to_le16(conn->handle);
5387 req_txp_cp.type = 0x00;
5388 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5389 sizeof(req_txp_cp), &req_txp_cp);
5390 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005391
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005392 /* Max TX power needs to be read only once per connection */
5393 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5394 req_txp_cp.handle = cpu_to_le16(conn->handle);
5395 req_txp_cp.type = 0x01;
5396 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5397 sizeof(req_txp_cp), &req_txp_cp);
5398 }
5399
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005400 err = hci_req_run(&req, conn_info_refresh_complete);
5401 if (err < 0)
5402 goto unlock;
5403
5404 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5405 data, len);
5406 if (!cmd) {
5407 err = -ENOMEM;
5408 goto unlock;
5409 }
5410
5411 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005412 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005413 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005414
5415 conn->conn_info_timestamp = jiffies;
5416 } else {
5417 /* Cache is valid, just reply with values cached in hci_conn */
5418 rp.rssi = conn->rssi;
5419 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005420 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005421
5422 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5423 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5424 }
5425
5426unlock:
5427 hci_dev_unlock(hdev);
5428 return err;
5429}
5430
Johan Hedberg9df74652014-12-19 22:26:03 +02005431static int clock_info_cmd_complete(struct pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005432{
5433 struct hci_conn *conn = cmd->user_data;
5434 struct mgmt_rp_get_clock_info rp;
5435 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005436 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005437
5438 memset(&rp, 0, sizeof(rp));
5439 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5440
5441 if (status)
5442 goto complete;
5443
5444 hdev = hci_dev_get(cmd->index);
5445 if (hdev) {
5446 rp.local_clock = cpu_to_le32(hdev->clock);
5447 hci_dev_put(hdev);
5448 }
5449
5450 if (conn) {
5451 rp.piconet_clock = cpu_to_le32(conn->clock);
5452 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5453 }
5454
5455complete:
Johan Hedberg9df74652014-12-19 22:26:03 +02005456 err = cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5457 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005458
5459 if (conn) {
5460 hci_conn_drop(conn);
5461 hci_conn_put(conn);
5462 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005463
5464 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005465}
5466
Marcel Holtmann1904a852015-01-11 13:50:44 -08005467static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005468{
Johan Hedberg95868422014-06-28 17:54:07 +03005469 struct hci_cp_read_clock *hci_cp;
5470 struct pending_cmd *cmd;
5471 struct hci_conn *conn;
5472
5473 BT_DBG("%s status %u", hdev->name, status);
5474
5475 hci_dev_lock(hdev);
5476
5477 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5478 if (!hci_cp)
5479 goto unlock;
5480
5481 if (hci_cp->which) {
5482 u16 handle = __le16_to_cpu(hci_cp->handle);
5483 conn = hci_conn_hash_lookup_handle(hdev, handle);
5484 } else {
5485 conn = NULL;
5486 }
5487
5488 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5489 if (!cmd)
5490 goto unlock;
5491
Johan Hedberg69487372014-12-05 13:36:07 +02005492 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005493 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005494
5495unlock:
5496 hci_dev_unlock(hdev);
5497}
5498
5499static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5500 u16 len)
5501{
5502 struct mgmt_cp_get_clock_info *cp = data;
5503 struct mgmt_rp_get_clock_info rp;
5504 struct hci_cp_read_clock hci_cp;
5505 struct pending_cmd *cmd;
5506 struct hci_request req;
5507 struct hci_conn *conn;
5508 int err;
5509
5510 BT_DBG("%s", hdev->name);
5511
5512 memset(&rp, 0, sizeof(rp));
5513 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5514 rp.addr.type = cp->addr.type;
5515
5516 if (cp->addr.type != BDADDR_BREDR)
5517 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5518 MGMT_STATUS_INVALID_PARAMS,
5519 &rp, sizeof(rp));
5520
5521 hci_dev_lock(hdev);
5522
5523 if (!hdev_is_powered(hdev)) {
5524 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5525 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5526 goto unlock;
5527 }
5528
5529 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5530 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5531 &cp->addr.bdaddr);
5532 if (!conn || conn->state != BT_CONNECTED) {
5533 err = cmd_complete(sk, hdev->id,
5534 MGMT_OP_GET_CLOCK_INFO,
5535 MGMT_STATUS_NOT_CONNECTED,
5536 &rp, sizeof(rp));
5537 goto unlock;
5538 }
5539 } else {
5540 conn = NULL;
5541 }
5542
5543 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5544 if (!cmd) {
5545 err = -ENOMEM;
5546 goto unlock;
5547 }
5548
Johan Hedberg69487372014-12-05 13:36:07 +02005549 cmd->cmd_complete = clock_info_cmd_complete;
5550
Johan Hedberg95868422014-06-28 17:54:07 +03005551 hci_req_init(&req, hdev);
5552
5553 memset(&hci_cp, 0, sizeof(hci_cp));
5554 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5555
5556 if (conn) {
5557 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005558 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005559
5560 hci_cp.handle = cpu_to_le16(conn->handle);
5561 hci_cp.which = 0x01; /* Piconet clock */
5562 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5563 }
5564
5565 err = hci_req_run(&req, get_clock_info_complete);
5566 if (err < 0)
5567 mgmt_pending_remove(cmd);
5568
5569unlock:
5570 hci_dev_unlock(hdev);
5571 return err;
5572}
5573
Johan Hedberg5a154e62014-12-19 22:26:02 +02005574static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5575{
5576 struct hci_conn *conn;
5577
5578 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5579 if (!conn)
5580 return false;
5581
5582 if (conn->dst_type != type)
5583 return false;
5584
5585 if (conn->state != BT_CONNECTED)
5586 return false;
5587
5588 return true;
5589}
5590
5591/* This function requires the caller holds hdev->lock */
5592static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5593 u8 addr_type, u8 auto_connect)
5594{
5595 struct hci_dev *hdev = req->hdev;
5596 struct hci_conn_params *params;
5597
5598 params = hci_conn_params_add(hdev, addr, addr_type);
5599 if (!params)
5600 return -EIO;
5601
5602 if (params->auto_connect == auto_connect)
5603 return 0;
5604
5605 list_del_init(&params->action);
5606
5607 switch (auto_connect) {
5608 case HCI_AUTO_CONN_DISABLED:
5609 case HCI_AUTO_CONN_LINK_LOSS:
5610 __hci_update_background_scan(req);
5611 break;
5612 case HCI_AUTO_CONN_REPORT:
5613 list_add(&params->action, &hdev->pend_le_reports);
5614 __hci_update_background_scan(req);
5615 break;
5616 case HCI_AUTO_CONN_DIRECT:
5617 case HCI_AUTO_CONN_ALWAYS:
5618 if (!is_connected(hdev, addr, addr_type)) {
5619 list_add(&params->action, &hdev->pend_le_conns);
5620 __hci_update_background_scan(req);
5621 }
5622 break;
5623 }
5624
5625 params->auto_connect = auto_connect;
5626
5627 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5628 auto_connect);
5629
5630 return 0;
5631}
5632
Marcel Holtmann8afef092014-06-29 22:28:34 +02005633static void device_added(struct sock *sk, struct hci_dev *hdev,
5634 bdaddr_t *bdaddr, u8 type, u8 action)
5635{
5636 struct mgmt_ev_device_added ev;
5637
5638 bacpy(&ev.addr.bdaddr, bdaddr);
5639 ev.addr.type = type;
5640 ev.action = action;
5641
5642 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5643}
5644
Marcel Holtmann1904a852015-01-11 13:50:44 -08005645static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005646{
5647 struct pending_cmd *cmd;
5648
5649 BT_DBG("status 0x%02x", status);
5650
5651 hci_dev_lock(hdev);
5652
5653 cmd = mgmt_pending_find(MGMT_OP_ADD_DEVICE, hdev);
5654 if (!cmd)
5655 goto unlock;
5656
5657 cmd->cmd_complete(cmd, mgmt_status(status));
5658 mgmt_pending_remove(cmd);
5659
5660unlock:
5661 hci_dev_unlock(hdev);
5662}
5663
Marcel Holtmann2faade52014-06-29 19:44:03 +02005664static int add_device(struct sock *sk, struct hci_dev *hdev,
5665 void *data, u16 len)
5666{
5667 struct mgmt_cp_add_device *cp = data;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005668 struct pending_cmd *cmd;
5669 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005670 u8 auto_conn, addr_type;
5671 int err;
5672
5673 BT_DBG("%s", hdev->name);
5674
Johan Hedberg66593582014-07-09 12:59:14 +03005675 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005676 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5677 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5678 MGMT_STATUS_INVALID_PARAMS,
5679 &cp->addr, sizeof(cp->addr));
5680
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005681 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005682 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5683 MGMT_STATUS_INVALID_PARAMS,
5684 &cp->addr, sizeof(cp->addr));
5685
Johan Hedberg5a154e62014-12-19 22:26:02 +02005686 hci_req_init(&req, hdev);
5687
Marcel Holtmann2faade52014-06-29 19:44:03 +02005688 hci_dev_lock(hdev);
5689
Johan Hedberg5a154e62014-12-19 22:26:02 +02005690 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5691 if (!cmd) {
5692 err = -ENOMEM;
5693 goto unlock;
5694 }
5695
5696 cmd->cmd_complete = addr_cmd_complete;
5697
Johan Hedberg66593582014-07-09 12:59:14 +03005698 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005699 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005700 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005701 err = cmd->cmd_complete(cmd,
5702 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005703 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005704 goto unlock;
5705 }
5706
5707 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5708 cp->addr.type);
5709 if (err)
5710 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005711
Johan Hedberg5a154e62014-12-19 22:26:02 +02005712 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005713
Johan Hedberg66593582014-07-09 12:59:14 +03005714 goto added;
5715 }
5716
Marcel Holtmann2faade52014-06-29 19:44:03 +02005717 if (cp->addr.type == BDADDR_LE_PUBLIC)
5718 addr_type = ADDR_LE_DEV_PUBLIC;
5719 else
5720 addr_type = ADDR_LE_DEV_RANDOM;
5721
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005722 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005723 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005724 else if (cp->action == 0x01)
5725 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005726 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005727 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005728
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005729 /* If the connection parameters don't exist for this device,
5730 * they will be created and configured with defaults.
5731 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02005732 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005733 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005734 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005735 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005736 goto unlock;
5737 }
5738
Johan Hedberg66593582014-07-09 12:59:14 +03005739added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005740 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5741
Johan Hedberg5a154e62014-12-19 22:26:02 +02005742 err = hci_req_run(&req, add_device_complete);
5743 if (err < 0) {
5744 /* ENODATA means no HCI commands were needed (e.g. if
5745 * the adapter is powered off).
5746 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005747 if (err == -ENODATA)
5748 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005749 mgmt_pending_remove(cmd);
5750 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005751
5752unlock:
5753 hci_dev_unlock(hdev);
5754 return err;
5755}
5756
Marcel Holtmann8afef092014-06-29 22:28:34 +02005757static void device_removed(struct sock *sk, struct hci_dev *hdev,
5758 bdaddr_t *bdaddr, u8 type)
5759{
5760 struct mgmt_ev_device_removed ev;
5761
5762 bacpy(&ev.addr.bdaddr, bdaddr);
5763 ev.addr.type = type;
5764
5765 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5766}
5767
Marcel Holtmann1904a852015-01-11 13:50:44 -08005768static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005769{
5770 struct pending_cmd *cmd;
5771
5772 BT_DBG("status 0x%02x", status);
5773
5774 hci_dev_lock(hdev);
5775
5776 cmd = mgmt_pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
5777 if (!cmd)
5778 goto unlock;
5779
5780 cmd->cmd_complete(cmd, mgmt_status(status));
5781 mgmt_pending_remove(cmd);
5782
5783unlock:
5784 hci_dev_unlock(hdev);
5785}
5786
Marcel Holtmann2faade52014-06-29 19:44:03 +02005787static int remove_device(struct sock *sk, struct hci_dev *hdev,
5788 void *data, u16 len)
5789{
5790 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005791 struct pending_cmd *cmd;
5792 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005793 int err;
5794
5795 BT_DBG("%s", hdev->name);
5796
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005797 hci_req_init(&req, hdev);
5798
Marcel Holtmann2faade52014-06-29 19:44:03 +02005799 hci_dev_lock(hdev);
5800
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005801 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
5802 if (!cmd) {
5803 err = -ENOMEM;
5804 goto unlock;
5805 }
5806
5807 cmd->cmd_complete = addr_cmd_complete;
5808
Marcel Holtmann2faade52014-06-29 19:44:03 +02005809 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005810 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005811 u8 addr_type;
5812
Johan Hedberg66593582014-07-09 12:59:14 +03005813 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005814 err = cmd->cmd_complete(cmd,
5815 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005816 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005817 goto unlock;
5818 }
5819
Johan Hedberg66593582014-07-09 12:59:14 +03005820 if (cp->addr.type == BDADDR_BREDR) {
5821 err = hci_bdaddr_list_del(&hdev->whitelist,
5822 &cp->addr.bdaddr,
5823 cp->addr.type);
5824 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005825 err = cmd->cmd_complete(cmd,
5826 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005827 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005828 goto unlock;
5829 }
5830
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005831 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005832
Johan Hedberg66593582014-07-09 12:59:14 +03005833 device_removed(sk, hdev, &cp->addr.bdaddr,
5834 cp->addr.type);
5835 goto complete;
5836 }
5837
Marcel Holtmann2faade52014-06-29 19:44:03 +02005838 if (cp->addr.type == BDADDR_LE_PUBLIC)
5839 addr_type = ADDR_LE_DEV_PUBLIC;
5840 else
5841 addr_type = ADDR_LE_DEV_RANDOM;
5842
Johan Hedbergc71593d2014-07-02 17:37:28 +03005843 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5844 addr_type);
5845 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005846 err = cmd->cmd_complete(cmd,
5847 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005848 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005849 goto unlock;
5850 }
5851
5852 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005853 err = cmd->cmd_complete(cmd,
5854 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005855 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005856 goto unlock;
5857 }
5858
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005859 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005860 list_del(&params->list);
5861 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005862 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005863
5864 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005865 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005866 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005867 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005868
Marcel Holtmann2faade52014-06-29 19:44:03 +02005869 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005870 err = cmd->cmd_complete(cmd,
5871 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005872 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005873 goto unlock;
5874 }
5875
Johan Hedberg66593582014-07-09 12:59:14 +03005876 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5877 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5878 list_del(&b->list);
5879 kfree(b);
5880 }
5881
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005882 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005883
Johan Hedberg19de0822014-07-06 13:06:51 +03005884 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5885 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5886 continue;
5887 device_removed(sk, hdev, &p->addr, p->addr_type);
5888 list_del(&p->action);
5889 list_del(&p->list);
5890 kfree(p);
5891 }
5892
5893 BT_DBG("All LE connection parameters were removed");
5894
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005895 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005896 }
5897
Johan Hedberg66593582014-07-09 12:59:14 +03005898complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005899 err = hci_req_run(&req, remove_device_complete);
5900 if (err < 0) {
5901 /* ENODATA means no HCI commands were needed (e.g. if
5902 * the adapter is powered off).
5903 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005904 if (err == -ENODATA)
5905 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005906 mgmt_pending_remove(cmd);
5907 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005908
5909unlock:
5910 hci_dev_unlock(hdev);
5911 return err;
5912}
5913
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005914static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5915 u16 len)
5916{
5917 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005918 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5919 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005920 u16 param_count, expected_len;
5921 int i;
5922
5923 if (!lmp_le_capable(hdev))
5924 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5925 MGMT_STATUS_NOT_SUPPORTED);
5926
5927 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005928 if (param_count > max_param_count) {
5929 BT_ERR("load_conn_param: too big param_count value %u",
5930 param_count);
5931 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5932 MGMT_STATUS_INVALID_PARAMS);
5933 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005934
5935 expected_len = sizeof(*cp) + param_count *
5936 sizeof(struct mgmt_conn_param);
5937 if (expected_len != len) {
5938 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5939 expected_len, len);
5940 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5941 MGMT_STATUS_INVALID_PARAMS);
5942 }
5943
5944 BT_DBG("%s param_count %u", hdev->name, param_count);
5945
5946 hci_dev_lock(hdev);
5947
5948 hci_conn_params_clear_disabled(hdev);
5949
5950 for (i = 0; i < param_count; i++) {
5951 struct mgmt_conn_param *param = &cp->params[i];
5952 struct hci_conn_params *hci_param;
5953 u16 min, max, latency, timeout;
5954 u8 addr_type;
5955
5956 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5957 param->addr.type);
5958
5959 if (param->addr.type == BDADDR_LE_PUBLIC) {
5960 addr_type = ADDR_LE_DEV_PUBLIC;
5961 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5962 addr_type = ADDR_LE_DEV_RANDOM;
5963 } else {
5964 BT_ERR("Ignoring invalid connection parameters");
5965 continue;
5966 }
5967
5968 min = le16_to_cpu(param->min_interval);
5969 max = le16_to_cpu(param->max_interval);
5970 latency = le16_to_cpu(param->latency);
5971 timeout = le16_to_cpu(param->timeout);
5972
5973 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5974 min, max, latency, timeout);
5975
5976 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5977 BT_ERR("Ignoring invalid connection parameters");
5978 continue;
5979 }
5980
5981 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5982 addr_type);
5983 if (!hci_param) {
5984 BT_ERR("Failed to add connection parameters");
5985 continue;
5986 }
5987
5988 hci_param->conn_min_interval = min;
5989 hci_param->conn_max_interval = max;
5990 hci_param->conn_latency = latency;
5991 hci_param->supervision_timeout = timeout;
5992 }
5993
5994 hci_dev_unlock(hdev);
5995
5996 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5997}
5998
Marcel Holtmanndbece372014-07-04 18:11:55 +02005999static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6000 void *data, u16 len)
6001{
6002 struct mgmt_cp_set_external_config *cp = data;
6003 bool changed;
6004 int err;
6005
6006 BT_DBG("%s", hdev->name);
6007
6008 if (hdev_is_powered(hdev))
6009 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6010 MGMT_STATUS_REJECTED);
6011
6012 if (cp->config != 0x00 && cp->config != 0x01)
6013 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6014 MGMT_STATUS_INVALID_PARAMS);
6015
6016 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
6017 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6018 MGMT_STATUS_NOT_SUPPORTED);
6019
6020 hci_dev_lock(hdev);
6021
6022 if (cp->config)
6023 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
6024 &hdev->dev_flags);
6025 else
6026 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
6027 &hdev->dev_flags);
6028
6029 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6030 if (err < 0)
6031 goto unlock;
6032
6033 if (!changed)
6034 goto unlock;
6035
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006036 err = new_options(hdev, sk);
6037
Marcel Holtmanndbece372014-07-04 18:11:55 +02006038 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
6039 mgmt_index_removed(hdev);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006040
6041 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
6042 set_bit(HCI_CONFIG, &hdev->dev_flags);
6043 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
6044
6045 queue_work(hdev->req_workqueue, &hdev->power_on);
6046 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006047 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006048 mgmt_index_added(hdev);
6049 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006050 }
6051
6052unlock:
6053 hci_dev_unlock(hdev);
6054 return err;
6055}
6056
Marcel Holtmann9713c172014-07-06 12:11:15 +02006057static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6058 void *data, u16 len)
6059{
6060 struct mgmt_cp_set_public_address *cp = data;
6061 bool changed;
6062 int err;
6063
6064 BT_DBG("%s", hdev->name);
6065
6066 if (hdev_is_powered(hdev))
6067 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6068 MGMT_STATUS_REJECTED);
6069
6070 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
6071 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6072 MGMT_STATUS_INVALID_PARAMS);
6073
6074 if (!hdev->set_bdaddr)
6075 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6076 MGMT_STATUS_NOT_SUPPORTED);
6077
6078 hci_dev_lock(hdev);
6079
6080 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6081 bacpy(&hdev->public_addr, &cp->bdaddr);
6082
6083 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6084 if (err < 0)
6085 goto unlock;
6086
6087 if (!changed)
6088 goto unlock;
6089
6090 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6091 err = new_options(hdev, sk);
6092
6093 if (is_configured(hdev)) {
6094 mgmt_index_removed(hdev);
6095
6096 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
6097
6098 set_bit(HCI_CONFIG, &hdev->dev_flags);
6099 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
6100
6101 queue_work(hdev->req_workqueue, &hdev->power_on);
6102 }
6103
6104unlock:
6105 hci_dev_unlock(hdev);
6106 return err;
6107}
6108
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02006109static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006110 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
6111 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02006112 bool var_len;
6113 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006114} mgmt_handlers[] = {
6115 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02006116 { read_version, false, MGMT_READ_VERSION_SIZE },
6117 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
6118 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
6119 { read_controller_info, false, MGMT_READ_INFO_SIZE },
6120 { set_powered, false, MGMT_SETTING_SIZE },
6121 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
6122 { set_connectable, false, MGMT_SETTING_SIZE },
6123 { set_fast_connectable, false, MGMT_SETTING_SIZE },
Johan Hedbergb2939472014-07-30 09:22:23 +03006124 { set_bondable, false, MGMT_SETTING_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02006125 { set_link_security, false, MGMT_SETTING_SIZE },
6126 { set_ssp, false, MGMT_SETTING_SIZE },
6127 { set_hs, false, MGMT_SETTING_SIZE },
6128 { set_le, false, MGMT_SETTING_SIZE },
6129 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
6130 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
6131 { add_uuid, false, MGMT_ADD_UUID_SIZE },
6132 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
6133 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
6134 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
6135 { disconnect, false, MGMT_DISCONNECT_SIZE },
6136 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
6137 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
6138 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
6139 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
6140 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
6141 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
6142 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
6143 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
6144 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
6145 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
6146 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
6147 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08006148 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02006149 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
6150 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
6151 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
6152 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
6153 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
6154 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07006155 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03006156 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03006157 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006158 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07006159 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006160 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08006161 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02006162 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02006163 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02006164 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03006165 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02006166 { add_device, false, MGMT_ADD_DEVICE_SIZE },
6167 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006168 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
6169 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02006170 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02006171 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02006172 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01006173 { start_service_discovery,true, MGMT_START_SERVICE_DISCOVERY_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006174};
6175
Johan Hedberg03811012010-12-08 00:21:06 +02006176int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
6177{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006178 void *buf;
6179 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02006180 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01006181 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006182 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02006183 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02006184 int err;
6185
6186 BT_DBG("got %zu bytes", msglen);
6187
6188 if (msglen < sizeof(*hdr))
6189 return -EINVAL;
6190
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03006191 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02006192 if (!buf)
6193 return -ENOMEM;
6194
Al Viro6ce8e9c2014-04-06 21:25:44 -04006195 if (memcpy_from_msg(buf, msg, msglen)) {
Johan Hedberg03811012010-12-08 00:21:06 +02006196 err = -EFAULT;
6197 goto done;
6198 }
6199
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006200 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07006201 opcode = __le16_to_cpu(hdr->opcode);
6202 index = __le16_to_cpu(hdr->index);
6203 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02006204
6205 if (len != msglen - sizeof(*hdr)) {
6206 err = -EINVAL;
6207 goto done;
6208 }
6209
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006210 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006211 hdev = hci_dev_get(index);
6212 if (!hdev) {
6213 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006214 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006215 goto done;
6216 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006217
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02006218 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006219 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02006220 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006221 err = cmd_status(sk, index, opcode,
6222 MGMT_STATUS_INVALID_INDEX);
6223 goto done;
6224 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006225
6226 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02006227 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02006228 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
6229 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006230 err = cmd_status(sk, index, opcode,
6231 MGMT_STATUS_INVALID_INDEX);
6232 goto done;
6233 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006234 }
6235
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006236 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006237 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02006238 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02006239 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006240 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006241 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02006242 }
6243
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006244 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
6245 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
6246 err = cmd_status(sk, index, opcode,
6247 MGMT_STATUS_INVALID_INDEX);
6248 goto done;
6249 }
6250
6251 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
6252 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006253 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006254 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006255 goto done;
6256 }
6257
Johan Hedbergbe22b542012-03-01 22:24:41 +02006258 handler = &mgmt_handlers[opcode];
6259
6260 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006261 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02006262 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006263 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02006264 goto done;
6265 }
6266
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006267 if (hdev)
6268 mgmt_init_hdev(sk, hdev);
6269
6270 cp = buf + sizeof(*hdr);
6271
Johan Hedbergbe22b542012-03-01 22:24:41 +02006272 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02006273 if (err < 0)
6274 goto done;
6275
Johan Hedberg03811012010-12-08 00:21:06 +02006276 err = msglen;
6277
6278done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006279 if (hdev)
6280 hci_dev_put(hdev);
6281
Johan Hedberg03811012010-12-08 00:21:06 +02006282 kfree(buf);
6283 return err;
6284}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006285
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006286void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006287{
Marcel Holtmann1514b892013-10-06 08:25:01 -07006288 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006289 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006290
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006291 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6292 return;
6293
6294 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6295 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
6296 else
6297 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006298}
6299
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006300void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006301{
Johan Hedberg5f159032012-03-02 03:13:19 +02006302 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006303
Marcel Holtmann1514b892013-10-06 08:25:01 -07006304 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006305 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006306
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006307 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6308 return;
6309
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006310 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006311
Marcel Holtmannedd3896b2014-07-02 21:30:55 +02006312 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6313 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
6314 else
6315 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006316}
6317
Andre Guedes6046dc32014-02-26 20:21:51 -03006318/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02006319static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03006320{
Johan Hedberg2cf22212014-12-19 22:26:00 +02006321 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03006322 struct hci_conn_params *p;
6323
6324 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006325 /* Needed for AUTO_OFF case where might not "really"
6326 * have been powered off.
6327 */
6328 list_del_init(&p->action);
6329
6330 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006331 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006332 case HCI_AUTO_CONN_ALWAYS:
6333 list_add(&p->action, &hdev->pend_le_conns);
6334 break;
6335 case HCI_AUTO_CONN_REPORT:
6336 list_add(&p->action, &hdev->pend_le_reports);
6337 break;
6338 default:
6339 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006340 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006341 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006342
Johan Hedberg2cf22212014-12-19 22:26:00 +02006343 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03006344}
6345
Marcel Holtmann1904a852015-01-11 13:50:44 -08006346static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05006347{
6348 struct cmd_lookup match = { NULL, hdev };
6349
6350 BT_DBG("status 0x%02x", status);
6351
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08006352 if (!status) {
6353 /* Register the available SMP channels (BR/EDR and LE) only
6354 * when successfully powering on the controller. This late
6355 * registration is required so that LE SMP can clearly
6356 * decide if the public address or static address is used.
6357 */
6358 smp_register(hdev);
6359 }
6360
Johan Hedberg229ab392013-03-15 17:06:53 -05006361 hci_dev_lock(hdev);
6362
6363 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6364
6365 new_settings(hdev, match.sk);
6366
6367 hci_dev_unlock(hdev);
6368
6369 if (match.sk)
6370 sock_put(match.sk);
6371}
6372
Johan Hedberg70da6242013-03-15 17:06:51 -05006373static int powered_update_hci(struct hci_dev *hdev)
6374{
Johan Hedberg890ea892013-03-15 17:06:52 -05006375 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006376 u8 link_sec;
6377
Johan Hedberg890ea892013-03-15 17:06:52 -05006378 hci_req_init(&req, hdev);
6379
Johan Hedberg70da6242013-03-15 17:06:51 -05006380 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
6381 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006382 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05006383
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006384 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05006385
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006386 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
6387 u8 support = 0x01;
6388
6389 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
6390 sizeof(support), &support);
6391 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02006392 }
6393
Johan Hedbergc73eee92013-04-19 18:35:21 +03006394 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
6395 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006396 struct hci_cp_write_le_host_supported cp;
6397
Marcel Holtmann32226e42014-07-24 20:04:16 +02006398 cp.le = 0x01;
6399 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006400
6401 /* Check first if we already have the right
6402 * host state (host features set)
6403 */
6404 if (cp.le != lmp_host_le_capable(hdev) ||
6405 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006406 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6407 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006408 }
6409
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006410 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006411 /* Make sure the controller has a good default for
6412 * advertising data. This also applies to the case
6413 * where BR/EDR was toggled during the AUTO_OFF phase.
6414 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006415 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006416 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006417 update_scan_rsp_data(&req);
6418 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006419
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006420 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6421 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02006422
6423 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006424 }
6425
Johan Hedberg70da6242013-03-15 17:06:51 -05006426 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
6427 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006428 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6429 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006430
6431 if (lmp_bredr_capable(hdev)) {
Johan Hedberg432df052014-08-01 11:13:31 +03006432 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02006433 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006434 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006435 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006436 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006437 }
6438
Johan Hedberg229ab392013-03-15 17:06:53 -05006439 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006440}
6441
Johan Hedberg744cf192011-11-08 20:40:14 +02006442int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006443{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006444 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02006445 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006446 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006447
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006448 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
6449 return 0;
6450
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006451 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006452 if (powered_update_hci(hdev) == 0)
6453 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006454
Johan Hedberg229ab392013-03-15 17:06:53 -05006455 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6456 &match);
6457 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006458 }
6459
Johan Hedberg229ab392013-03-15 17:06:53 -05006460 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02006461
6462 /* If the power off is because of hdev unregistration let
6463 * use the appropriate INVALID_INDEX status. Otherwise use
6464 * NOT_POWERED. We cover both scenarios here since later in
6465 * mgmt_index_removed() any hci_conn callbacks will have already
6466 * been triggered, potentially causing misleading DISCONNECTED
6467 * status responses.
6468 */
6469 if (test_bit(HCI_UNREGISTER, &hdev->dev_flags))
6470 status = MGMT_STATUS_INVALID_INDEX;
6471 else
6472 status = MGMT_STATUS_NOT_POWERED;
6473
6474 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05006475
6476 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6477 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6478 zero_cod, sizeof(zero_cod), NULL);
6479
6480new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006481 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006482
6483 if (match.sk)
6484 sock_put(match.sk);
6485
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006486 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006487}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006488
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006489void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006490{
6491 struct pending_cmd *cmd;
6492 u8 status;
6493
6494 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6495 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006496 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006497
6498 if (err == -ERFKILL)
6499 status = MGMT_STATUS_RFKILLED;
6500 else
6501 status = MGMT_STATUS_FAILED;
6502
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006503 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006504
6505 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006506}
6507
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006508void mgmt_discoverable_timeout(struct hci_dev *hdev)
6509{
6510 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006511
6512 hci_dev_lock(hdev);
6513
6514 /* When discoverable timeout triggers, then just make sure
6515 * the limited discoverable flag is cleared. Even in the case
6516 * of a timeout triggered from general discoverable, it is
6517 * safe to unconditionally clear the flag.
6518 */
6519 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006520 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006521
6522 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006523 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6524 u8 scan = SCAN_PAGE;
6525 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6526 sizeof(scan), &scan);
6527 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006528 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006529 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006530 hci_req_run(&req, NULL);
6531
6532 hdev->discov_timeout = 0;
6533
Johan Hedberg9a43e252013-10-20 19:00:07 +03006534 new_settings(hdev, NULL);
6535
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006536 hci_dev_unlock(hdev);
6537}
6538
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006539void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6540 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006541{
Johan Hedberg86742e12011-11-07 23:13:38 +02006542 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006543
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006544 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006545
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006546 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006547 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006548 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006549 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006550 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006551 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006552
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006553 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006554}
Johan Hedbergf7520542011-01-20 12:34:39 +02006555
Johan Hedbergd7b25452014-05-23 13:19:53 +03006556static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6557{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006558 switch (ltk->type) {
6559 case SMP_LTK:
6560 case SMP_LTK_SLAVE:
6561 if (ltk->authenticated)
6562 return MGMT_LTK_AUTHENTICATED;
6563 return MGMT_LTK_UNAUTHENTICATED;
6564 case SMP_LTK_P256:
6565 if (ltk->authenticated)
6566 return MGMT_LTK_P256_AUTH;
6567 return MGMT_LTK_P256_UNAUTH;
6568 case SMP_LTK_P256_DEBUG:
6569 return MGMT_LTK_P256_DEBUG;
6570 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006571
6572 return MGMT_LTK_UNAUTHENTICATED;
6573}
6574
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006575void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006576{
6577 struct mgmt_ev_new_long_term_key ev;
6578
6579 memset(&ev, 0, sizeof(ev));
6580
Marcel Holtmann5192d302014-02-19 17:11:58 -08006581 /* Devices using resolvable or non-resolvable random addresses
6582 * without providing an indentity resolving key don't require
6583 * to store long term keys. Their addresses will change the
6584 * next time around.
6585 *
6586 * Only when a remote device provides an identity address
6587 * make sure the long term key is stored. If the remote
6588 * identity is known, the long term keys are internally
6589 * mapped to the identity address. So allow static random
6590 * and public addresses here.
6591 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006592 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6593 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6594 ev.store_hint = 0x00;
6595 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006596 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006597
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006598 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006599 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006600 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006601 ev.key.enc_size = key->enc_size;
6602 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006603 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006604
Johan Hedberg2ceba532014-06-16 19:25:16 +03006605 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006606 ev.key.master = 1;
6607
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006608 memcpy(ev.key.val, key->val, sizeof(key->val));
6609
Marcel Holtmann083368f2013-10-15 14:26:29 -07006610 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006611}
6612
Johan Hedberg95fbac82014-02-19 15:18:31 +02006613void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6614{
6615 struct mgmt_ev_new_irk ev;
6616
6617 memset(&ev, 0, sizeof(ev));
6618
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006619 /* For identity resolving keys from devices that are already
6620 * using a public address or static random address, do not
6621 * ask for storing this key. The identity resolving key really
6622 * is only mandatory for devices using resovlable random
6623 * addresses.
6624 *
6625 * Storing all identity resolving keys has the downside that
6626 * they will be also loaded on next boot of they system. More
6627 * identity resolving keys, means more time during scanning is
6628 * needed to actually resolve these addresses.
6629 */
6630 if (bacmp(&irk->rpa, BDADDR_ANY))
6631 ev.store_hint = 0x01;
6632 else
6633 ev.store_hint = 0x00;
6634
Johan Hedberg95fbac82014-02-19 15:18:31 +02006635 bacpy(&ev.rpa, &irk->rpa);
6636 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6637 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6638 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6639
6640 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6641}
6642
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006643void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6644 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006645{
6646 struct mgmt_ev_new_csrk ev;
6647
6648 memset(&ev, 0, sizeof(ev));
6649
6650 /* Devices using resolvable or non-resolvable random addresses
6651 * without providing an indentity resolving key don't require
6652 * to store signature resolving keys. Their addresses will change
6653 * the next time around.
6654 *
6655 * Only when a remote device provides an identity address
6656 * make sure the signature resolving key is stored. So allow
6657 * static random and public addresses here.
6658 */
6659 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6660 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6661 ev.store_hint = 0x00;
6662 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006663 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006664
6665 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6666 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02006667 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006668 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6669
6670 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6671}
6672
Andre Guedesffb5a8272014-07-01 18:10:11 -03006673void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006674 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6675 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006676{
6677 struct mgmt_ev_new_conn_param ev;
6678
Johan Hedbergc103aea2014-07-02 17:37:34 +03006679 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6680 return;
6681
Andre Guedesffb5a8272014-07-01 18:10:11 -03006682 memset(&ev, 0, sizeof(ev));
6683 bacpy(&ev.addr.bdaddr, bdaddr);
6684 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006685 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006686 ev.min_interval = cpu_to_le16(min_interval);
6687 ev.max_interval = cpu_to_le16(max_interval);
6688 ev.latency = cpu_to_le16(latency);
6689 ev.timeout = cpu_to_le16(timeout);
6690
6691 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6692}
6693
Marcel Holtmann94933992013-10-15 10:26:39 -07006694static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6695 u8 data_len)
6696{
6697 eir[eir_len++] = sizeof(type) + data_len;
6698 eir[eir_len++] = type;
6699 memcpy(&eir[eir_len], data, data_len);
6700 eir_len += data_len;
6701
6702 return eir_len;
6703}
6704
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006705void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6706 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006707{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006708 char buf[512];
6709 struct mgmt_ev_device_connected *ev = (void *) buf;
6710 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006711
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006712 bacpy(&ev->addr.bdaddr, &conn->dst);
6713 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006714
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006715 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006716
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006717 /* We must ensure that the EIR Data fields are ordered and
6718 * unique. Keep it simple for now and avoid the problem by not
6719 * adding any BR/EDR data to the LE adv.
6720 */
6721 if (conn->le_adv_data_len > 0) {
6722 memcpy(&ev->eir[eir_len],
6723 conn->le_adv_data, conn->le_adv_data_len);
6724 eir_len = conn->le_adv_data_len;
6725 } else {
6726 if (name_len > 0)
6727 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6728 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006729
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006730 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006731 eir_len = eir_append_data(ev->eir, eir_len,
6732 EIR_CLASS_OF_DEV,
6733 conn->dev_class, 3);
6734 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006735
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006736 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006737
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006738 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6739 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006740}
6741
Johan Hedberg8962ee72011-01-20 12:40:27 +02006742static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6743{
Johan Hedberg8962ee72011-01-20 12:40:27 +02006744 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006745
Johan Hedbergf5818c22014-12-05 13:36:02 +02006746 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006747
6748 *sk = cmd->sk;
6749 sock_hold(*sk);
6750
Johan Hedberga664b5b2011-02-19 12:06:02 -03006751 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006752}
6753
Johan Hedberg124f6e32012-02-09 13:50:12 +02006754static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006755{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006756 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006757 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006758
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006759 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6760
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02006761 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02006762 mgmt_pending_remove(cmd);
6763}
6764
Johan Hedberg84c61d92014-08-01 11:13:30 +03006765bool mgmt_powering_down(struct hci_dev *hdev)
6766{
6767 struct pending_cmd *cmd;
6768 struct mgmt_mode *cp;
6769
6770 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6771 if (!cmd)
6772 return false;
6773
6774 cp = cmd->param;
6775 if (!cp->val)
6776 return true;
6777
6778 return false;
6779}
6780
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006781void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006782 u8 link_type, u8 addr_type, u8 reason,
6783 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006784{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006785 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006786 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006787
Johan Hedberg84c61d92014-08-01 11:13:30 +03006788 /* The connection is still in hci_conn_hash so test for 1
6789 * instead of 0 to know if this is the last one.
6790 */
6791 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6792 cancel_delayed_work(&hdev->power_off);
6793 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006794 }
6795
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006796 if (!mgmt_connected)
6797 return;
6798
Andre Guedes57eb7762013-10-30 19:01:41 -03006799 if (link_type != ACL_LINK && link_type != LE_LINK)
6800 return;
6801
Johan Hedberg744cf192011-11-08 20:40:14 +02006802 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006803
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006804 bacpy(&ev.addr.bdaddr, bdaddr);
6805 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6806 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006807
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006808 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006809
6810 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006811 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006812
Johan Hedberg124f6e32012-02-09 13:50:12 +02006813 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006814 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006815}
6816
Marcel Holtmann78929242013-10-06 23:55:47 -07006817void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6818 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006819{
Andre Guedes3655bba2013-10-30 19:01:40 -03006820 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6821 struct mgmt_cp_disconnect *cp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006822 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006823
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006824 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6825 hdev);
6826
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006827 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006828 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006829 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006830
Andre Guedes3655bba2013-10-30 19:01:40 -03006831 cp = cmd->param;
6832
6833 if (bacmp(bdaddr, &cp->addr.bdaddr))
6834 return;
6835
6836 if (cp->addr.type != bdaddr_type)
6837 return;
6838
Johan Hedbergf5818c22014-12-05 13:36:02 +02006839 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006840 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006841}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006842
Marcel Holtmann445608d2013-10-06 23:55:48 -07006843void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6844 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006845{
6846 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006847
Johan Hedberg84c61d92014-08-01 11:13:30 +03006848 /* The connection is still in hci_conn_hash so test for 1
6849 * instead of 0 to know if this is the last one.
6850 */
6851 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6852 cancel_delayed_work(&hdev->power_off);
6853 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006854 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006855
Johan Hedberg4c659c32011-11-07 23:13:39 +02006856 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006857 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006858 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006859
Marcel Holtmann445608d2013-10-06 23:55:48 -07006860 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006861}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006862
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006863void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006864{
6865 struct mgmt_ev_pin_code_request ev;
6866
Johan Hedbergd8457692012-02-17 14:24:57 +02006867 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006868 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006869 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006870
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006871 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006872}
6873
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006874void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6875 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006876{
6877 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006878
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006879 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006880 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006881 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006882
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006883 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006884 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006885}
6886
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006887void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6888 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006889{
6890 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006891
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006892 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006893 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006894 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006895
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006896 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006897 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006898}
Johan Hedberga5c29682011-02-19 12:05:57 -03006899
Johan Hedberg744cf192011-11-08 20:40:14 +02006900int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006901 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006902 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006903{
6904 struct mgmt_ev_user_confirm_request ev;
6905
Johan Hedberg744cf192011-11-08 20:40:14 +02006906 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006907
Johan Hedberg272d90d2012-02-09 15:26:12 +02006908 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006909 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006910 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006911 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006912
Johan Hedberg744cf192011-11-08 20:40:14 +02006913 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006914 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006915}
6916
Johan Hedberg272d90d2012-02-09 15:26:12 +02006917int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006918 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006919{
6920 struct mgmt_ev_user_passkey_request ev;
6921
6922 BT_DBG("%s", hdev->name);
6923
Johan Hedberg272d90d2012-02-09 15:26:12 +02006924 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006925 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006926
6927 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006928 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006929}
6930
Brian Gix0df4c182011-11-16 13:53:13 -08006931static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006932 u8 link_type, u8 addr_type, u8 status,
6933 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006934{
6935 struct pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03006936
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006937 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006938 if (!cmd)
6939 return -ENOENT;
6940
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006941 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006942 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006943
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006944 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03006945}
6946
Johan Hedberg744cf192011-11-08 20:40:14 +02006947int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006948 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006949{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006950 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006951 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006952}
6953
Johan Hedberg272d90d2012-02-09 15:26:12 +02006954int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006955 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006956{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006957 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006958 status,
6959 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006960}
Johan Hedberg2a611692011-02-19 12:06:00 -03006961
Brian Gix604086b2011-11-23 08:28:33 -08006962int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006963 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006964{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006965 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006966 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006967}
6968
Johan Hedberg272d90d2012-02-09 15:26:12 +02006969int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006970 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006971{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006972 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006973 status,
6974 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006975}
6976
Johan Hedberg92a25252012-09-06 18:39:26 +03006977int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6978 u8 link_type, u8 addr_type, u32 passkey,
6979 u8 entered)
6980{
6981 struct mgmt_ev_passkey_notify ev;
6982
6983 BT_DBG("%s", hdev->name);
6984
6985 bacpy(&ev.addr.bdaddr, bdaddr);
6986 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6987 ev.passkey = __cpu_to_le32(passkey);
6988 ev.entered = entered;
6989
6990 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6991}
6992
Johan Hedberge1e930f2014-09-08 17:09:49 -07006993void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006994{
6995 struct mgmt_ev_auth_failed ev;
Johan Hedberge1e930f2014-09-08 17:09:49 -07006996 struct pending_cmd *cmd;
6997 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006998
Johan Hedberge1e930f2014-09-08 17:09:49 -07006999 bacpy(&ev.addr.bdaddr, &conn->dst);
7000 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7001 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007002
Johan Hedberge1e930f2014-09-08 17:09:49 -07007003 cmd = find_pairing(conn);
7004
7005 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7006 cmd ? cmd->sk : NULL);
7007
Johan Hedberga511b352014-12-11 21:45:45 +02007008 if (cmd) {
7009 cmd->cmd_complete(cmd, status);
7010 mgmt_pending_remove(cmd);
7011 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007012}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007013
Marcel Holtmann464996a2013-10-15 14:26:24 -07007014void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007015{
7016 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007017 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007018
7019 if (status) {
7020 u8 mgmt_err = mgmt_status(status);
7021 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007022 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007023 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007024 }
7025
Marcel Holtmann464996a2013-10-15 14:26:24 -07007026 if (test_bit(HCI_AUTH, &hdev->flags))
7027 changed = !test_and_set_bit(HCI_LINK_SECURITY,
7028 &hdev->dev_flags);
7029 else
7030 changed = test_and_clear_bit(HCI_LINK_SECURITY,
7031 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02007032
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007033 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007034 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007035
Johan Hedberg47990ea2012-02-22 11:58:37 +02007036 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07007037 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007038
7039 if (match.sk)
7040 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007041}
7042
Johan Hedberg890ea892013-03-15 17:06:52 -05007043static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02007044{
Johan Hedberg890ea892013-03-15 17:06:52 -05007045 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007046 struct hci_cp_write_eir cp;
7047
Johan Hedberg976eb202012-10-24 21:12:01 +03007048 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007049 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007050
Johan Hedbergc80da272012-02-22 15:38:48 +02007051 memset(hdev->eir, 0, sizeof(hdev->eir));
7052
Johan Hedbergcacaf522012-02-21 00:52:42 +02007053 memset(&cp, 0, sizeof(cp));
7054
Johan Hedberg890ea892013-03-15 17:06:52 -05007055 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02007056}
7057
Marcel Holtmann3e248562013-10-15 14:26:25 -07007058void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007059{
7060 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05007061 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007062 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007063
7064 if (status) {
7065 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007066
7067 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007068 &hdev->dev_flags)) {
7069 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007070 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007071 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007072
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007073 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
7074 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007075 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007076 }
7077
7078 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007079 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007080 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007081 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
7082 if (!changed)
7083 changed = test_and_clear_bit(HCI_HS_ENABLED,
7084 &hdev->dev_flags);
7085 else
7086 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007087 }
7088
7089 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
7090
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007091 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07007092 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007093
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02007094 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007095 sock_put(match.sk);
7096
Johan Hedberg890ea892013-03-15 17:06:52 -05007097 hci_req_init(&req, hdev);
7098
Johan Hedberg37699722014-06-24 14:00:27 +03007099 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
7100 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
7101 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
7102 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05007103 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007104 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05007105 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007106 }
Johan Hedberg890ea892013-03-15 17:06:52 -05007107
7108 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007109}
7110
Johan Hedberg92da6092013-03-15 17:06:55 -05007111static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02007112{
7113 struct cmd_lookup *match = data;
7114
Johan Hedberg90e70452012-02-23 23:09:40 +02007115 if (match->sk == NULL) {
7116 match->sk = cmd->sk;
7117 sock_hold(match->sk);
7118 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007119}
7120
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007121void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7122 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007123{
Johan Hedberg90e70452012-02-23 23:09:40 +02007124 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007125
Johan Hedberg92da6092013-03-15 17:06:55 -05007126 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7127 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7128 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007129
7130 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007131 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
7132 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007133
7134 if (match.sk)
7135 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007136}
7137
Marcel Holtmann7667da32013-10-15 14:26:27 -07007138void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007139{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007140 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05007141 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007142
Johan Hedberg13928972013-03-15 17:07:00 -05007143 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007144 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007145
7146 memset(&ev, 0, sizeof(ev));
7147 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007148 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007149
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007150 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007151 if (!cmd) {
7152 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007153
Johan Hedberg13928972013-03-15 17:07:00 -05007154 /* If this is a HCI command related to powering on the
7155 * HCI dev don't send any mgmt signals.
7156 */
7157 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007158 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007159 }
7160
Marcel Holtmann7667da32013-10-15 14:26:27 -07007161 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7162 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007163}
Szymon Jancc35938b2011-03-22 13:12:21 +01007164
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007165void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02007166 u8 *rand192, u8 *hash256, u8 *rand256,
7167 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01007168{
7169 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01007170
Johan Hedberg744cf192011-11-08 20:40:14 +02007171 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01007172
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007173 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01007174 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007175 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01007176
7177 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007178 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
7179 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01007180 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007181 struct mgmt_rp_read_local_oob_data rp;
7182 size_t rp_size = sizeof(rp);
7183
7184 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
7185 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
7186
Johan Hedberg710f11c2014-05-26 11:21:22 +03007187 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007188 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02007189 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007190 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007191 rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007192 }
Johan Hedberg66f096f2015-02-02 13:23:42 +02007193
7194 cmd_complete(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7195 &rp, rp_size);
Szymon Jancc35938b2011-03-22 13:12:21 +01007196 }
7197
7198 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01007199}
Johan Hedberge17acd42011-03-30 23:57:16 +03007200
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007201static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7202{
7203 int i;
7204
7205 for (i = 0; i < uuid_count; i++) {
7206 if (!memcmp(uuid, uuids[i], 16))
7207 return true;
7208 }
7209
7210 return false;
7211}
7212
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007213static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7214{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007215 u16 parsed = 0;
7216
7217 while (parsed < eir_len) {
7218 u8 field_len = eir[0];
7219 u8 uuid[16];
7220 int i;
7221
7222 if (field_len == 0)
7223 break;
7224
7225 if (eir_len - parsed < field_len + 1)
7226 break;
7227
7228 switch (eir[1]) {
7229 case EIR_UUID16_ALL:
7230 case EIR_UUID16_SOME:
7231 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007232 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007233 uuid[13] = eir[i + 3];
7234 uuid[12] = eir[i + 2];
7235 if (has_uuid(uuid, uuid_count, uuids))
7236 return true;
7237 }
7238 break;
7239 case EIR_UUID32_ALL:
7240 case EIR_UUID32_SOME:
7241 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007242 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007243 uuid[15] = eir[i + 5];
7244 uuid[14] = eir[i + 4];
7245 uuid[13] = eir[i + 3];
7246 uuid[12] = eir[i + 2];
7247 if (has_uuid(uuid, uuid_count, uuids))
7248 return true;
7249 }
7250 break;
7251 case EIR_UUID128_ALL:
7252 case EIR_UUID128_SOME:
7253 for (i = 0; i + 17 <= field_len; i += 16) {
7254 memcpy(uuid, eir + i + 2, 16);
7255 if (has_uuid(uuid, uuid_count, uuids))
7256 return true;
7257 }
7258 break;
7259 }
7260
7261 parsed += field_len + 1;
7262 eir += field_len + 1;
7263 }
7264
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007265 return false;
7266}
7267
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007268static void restart_le_scan(struct hci_dev *hdev)
7269{
7270 /* If controller is not scanning we are done. */
7271 if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
7272 return;
7273
7274 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
7275 hdev->discovery.scan_start +
7276 hdev->discovery.scan_duration))
7277 return;
7278
7279 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
7280 DISCOV_LE_RESTART_DELAY);
7281}
7282
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007283static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
7284 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
7285{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007286 /* If a RSSI threshold has been specified, and
7287 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
7288 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
7289 * is set, let it through for further processing, as we might need to
7290 * restart the scan.
7291 *
7292 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
7293 * the results are also dropped.
7294 */
7295 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7296 (rssi == HCI_RSSI_INVALID ||
7297 (rssi < hdev->discovery.rssi &&
7298 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
7299 return false;
7300
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007301 if (hdev->discovery.uuid_count != 0) {
7302 /* If a list of UUIDs is provided in filter, results with no
7303 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007304 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007305 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
7306 hdev->discovery.uuids) &&
7307 !eir_has_uuids(scan_rsp, scan_rsp_len,
7308 hdev->discovery.uuid_count,
7309 hdev->discovery.uuids))
7310 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007311 }
7312
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007313 /* If duplicate filtering does not report RSSI changes, then restart
7314 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007315 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007316 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
7317 restart_le_scan(hdev);
7318
7319 /* Validate RSSI value against the RSSI threshold once more. */
7320 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7321 rssi < hdev->discovery.rssi)
7322 return false;
7323 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007324
7325 return true;
7326}
7327
Marcel Holtmann901801b2013-10-06 23:55:51 -07007328void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02007329 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7330 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007331{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007332 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007333 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007334 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03007335
Johan Hedberg75ce2082014-07-02 22:42:01 +03007336 /* Don't send events for a non-kernel initiated discovery. With
7337 * LE one exception is if we have pend_le_reports > 0 in which
7338 * case we're doing passive scanning and want these events.
7339 */
7340 if (!hci_discovery_active(hdev)) {
7341 if (link_type == ACL_LINK)
7342 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007343 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007344 return;
7345 }
Andre Guedes12602d02013-04-30 15:29:40 -03007346
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08007347 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007348 /* We are using service discovery */
7349 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
7350 scan_rsp_len))
7351 return;
7352 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007353
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007354 /* Make sure that the buffer is big enough. The 5 extra bytes
7355 * are for the potential CoD field.
7356 */
7357 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007358 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007359
Johan Hedberg1dc06092012-01-15 21:01:23 +02007360 memset(buf, 0, sizeof(buf));
7361
Marcel Holtmannda25cf62014-12-05 13:03:35 +01007362 /* In case of device discovery with BR/EDR devices (pre 1.2), the
7363 * RSSI value was reported as 0 when not available. This behavior
7364 * is kept when using device discovery. This is required for full
7365 * backwards compatibility with the API.
7366 *
7367 * However when using service discovery, the value 127 will be
7368 * returned when the RSSI is not available.
7369 */
Szymon Janc91200e92015-01-22 16:57:05 +01007370 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
7371 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01007372 rssi = 0;
7373
Johan Hedberg841c5642014-07-07 12:45:54 +03007374 bacpy(&ev->addr.bdaddr, bdaddr);
7375 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007376 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007377 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007378
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007379 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007380 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007381 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03007382
Johan Hedberg1dc06092012-01-15 21:01:23 +02007383 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7384 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007385 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007386
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007387 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007388 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007389 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007390
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007391 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7392 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007393
Marcel Holtmann901801b2013-10-06 23:55:51 -07007394 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007395}
Johan Hedberga88a9652011-03-30 13:18:12 +03007396
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007397void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7398 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007399{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007400 struct mgmt_ev_device_found *ev;
7401 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7402 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007403
Johan Hedbergb644ba32012-01-17 21:48:47 +02007404 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007405
Johan Hedbergb644ba32012-01-17 21:48:47 +02007406 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007407
Johan Hedbergb644ba32012-01-17 21:48:47 +02007408 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007409 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007410 ev->rssi = rssi;
7411
7412 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007413 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007414
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007415 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007416
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007417 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007418}
Johan Hedberg314b2382011-04-27 10:29:57 -04007419
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007420void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007421{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007422 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007423
Andre Guedes343fb142011-11-22 17:14:19 -03007424 BT_DBG("%s discovering %u", hdev->name, discovering);
7425
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007426 memset(&ev, 0, sizeof(ev));
7427 ev.type = hdev->discovery.type;
7428 ev.discovering = discovering;
7429
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007430 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007431}
Antti Julku5e762442011-08-25 16:48:02 +03007432
Marcel Holtmann1904a852015-01-11 13:50:44 -08007433static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07007434{
7435 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007436}
7437
7438void mgmt_reenable_advertising(struct hci_dev *hdev)
7439{
7440 struct hci_request req;
7441
Marcel Holtmann5976e602013-10-06 04:08:14 -07007442 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
7443 return;
7444
7445 hci_req_init(&req, hdev);
7446 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007447 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007448}