blob: f1672b15c0f3837d2674f6cc00bf8ced0b6efd9e [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 Hedberg4bc58f52014-05-20 09:45:47 +030032#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020033#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070034
35#include "smp.h"
Johan Hedberg03811012010-12-08 00:21:06 +020036
Johan Hedberg2da9c552012-02-17 14:39:28 +020037#define MGMT_VERSION 1
Marcel Holtmann730f0912014-06-28 12:36:10 +020038#define MGMT_REVISION 7
Johan Hedberg02d98122010-12-13 21:07:04 +020039
Johan Hedberge70bb2e2012-02-13 16:59:33 +020040static const u16 mgmt_commands[] = {
41 MGMT_OP_READ_INDEX_LIST,
42 MGMT_OP_READ_INFO,
43 MGMT_OP_SET_POWERED,
44 MGMT_OP_SET_DISCOVERABLE,
45 MGMT_OP_SET_CONNECTABLE,
46 MGMT_OP_SET_FAST_CONNECTABLE,
47 MGMT_OP_SET_PAIRABLE,
48 MGMT_OP_SET_LINK_SECURITY,
49 MGMT_OP_SET_SSP,
50 MGMT_OP_SET_HS,
51 MGMT_OP_SET_LE,
52 MGMT_OP_SET_DEV_CLASS,
53 MGMT_OP_SET_LOCAL_NAME,
54 MGMT_OP_ADD_UUID,
55 MGMT_OP_REMOVE_UUID,
56 MGMT_OP_LOAD_LINK_KEYS,
57 MGMT_OP_LOAD_LONG_TERM_KEYS,
58 MGMT_OP_DISCONNECT,
59 MGMT_OP_GET_CONNECTIONS,
60 MGMT_OP_PIN_CODE_REPLY,
61 MGMT_OP_PIN_CODE_NEG_REPLY,
62 MGMT_OP_SET_IO_CAPABILITY,
63 MGMT_OP_PAIR_DEVICE,
64 MGMT_OP_CANCEL_PAIR_DEVICE,
65 MGMT_OP_UNPAIR_DEVICE,
66 MGMT_OP_USER_CONFIRM_REPLY,
67 MGMT_OP_USER_CONFIRM_NEG_REPLY,
68 MGMT_OP_USER_PASSKEY_REPLY,
69 MGMT_OP_USER_PASSKEY_NEG_REPLY,
70 MGMT_OP_READ_LOCAL_OOB_DATA,
71 MGMT_OP_ADD_REMOTE_OOB_DATA,
72 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
73 MGMT_OP_START_DISCOVERY,
74 MGMT_OP_STOP_DISCOVERY,
75 MGMT_OP_CONFIRM_NAME,
76 MGMT_OP_BLOCK_DEVICE,
77 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070078 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030079 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030080 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070081 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070082 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080083 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080084 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020085 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020086 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020087 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030088 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020089 MGMT_OP_ADD_DEVICE,
90 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030091 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020092 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020093 MGMT_OP_READ_CONFIG_INFO,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020094};
95
96static const u16 mgmt_events[] = {
97 MGMT_EV_CONTROLLER_ERROR,
98 MGMT_EV_INDEX_ADDED,
99 MGMT_EV_INDEX_REMOVED,
100 MGMT_EV_NEW_SETTINGS,
101 MGMT_EV_CLASS_OF_DEV_CHANGED,
102 MGMT_EV_LOCAL_NAME_CHANGED,
103 MGMT_EV_NEW_LINK_KEY,
104 MGMT_EV_NEW_LONG_TERM_KEY,
105 MGMT_EV_DEVICE_CONNECTED,
106 MGMT_EV_DEVICE_DISCONNECTED,
107 MGMT_EV_CONNECT_FAILED,
108 MGMT_EV_PIN_CODE_REQUEST,
109 MGMT_EV_USER_CONFIRM_REQUEST,
110 MGMT_EV_USER_PASSKEY_REQUEST,
111 MGMT_EV_AUTH_FAILED,
112 MGMT_EV_DEVICE_FOUND,
113 MGMT_EV_DISCOVERING,
114 MGMT_EV_DEVICE_BLOCKED,
115 MGMT_EV_DEVICE_UNBLOCKED,
116 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300117 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800118 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700119 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200120 MGMT_EV_DEVICE_ADDED,
121 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300122 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200123 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200124 MGMT_EV_UNCONF_INDEX_REMOVED,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200125};
126
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800127#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200128
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200129#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
130 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
131
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200132struct pending_cmd {
133 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200134 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200135 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100136 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200137 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300138 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200139};
140
Johan Hedbergca69b792011-11-11 18:10:00 +0200141/* HCI to MGMT error code conversion table */
142static u8 mgmt_status_table[] = {
143 MGMT_STATUS_SUCCESS,
144 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
145 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
146 MGMT_STATUS_FAILED, /* Hardware Failure */
147 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
148 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200149 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200150 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
151 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
152 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
153 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
154 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
155 MGMT_STATUS_BUSY, /* Command Disallowed */
156 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
157 MGMT_STATUS_REJECTED, /* Rejected Security */
158 MGMT_STATUS_REJECTED, /* Rejected Personal */
159 MGMT_STATUS_TIMEOUT, /* Host Timeout */
160 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
161 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
162 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
163 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
164 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
165 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
166 MGMT_STATUS_BUSY, /* Repeated Attempts */
167 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
168 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
169 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
170 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
171 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
172 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
173 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
174 MGMT_STATUS_FAILED, /* Unspecified Error */
175 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
176 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
177 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
178 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
179 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
180 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
181 MGMT_STATUS_FAILED, /* Unit Link Key Used */
182 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
183 MGMT_STATUS_TIMEOUT, /* Instant Passed */
184 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
185 MGMT_STATUS_FAILED, /* Transaction Collision */
186 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
187 MGMT_STATUS_REJECTED, /* QoS Rejected */
188 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
189 MGMT_STATUS_REJECTED, /* Insufficient Security */
190 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
191 MGMT_STATUS_BUSY, /* Role Switch Pending */
192 MGMT_STATUS_FAILED, /* Slot Violation */
193 MGMT_STATUS_FAILED, /* Role Switch Failed */
194 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
195 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
196 MGMT_STATUS_BUSY, /* Host Busy Pairing */
197 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
198 MGMT_STATUS_BUSY, /* Controller Busy */
199 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
200 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
201 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
202 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
203 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
204};
205
206static u8 mgmt_status(u8 hci_status)
207{
208 if (hci_status < ARRAY_SIZE(mgmt_status_table))
209 return mgmt_status_table[hci_status];
210
211 return MGMT_STATUS_FAILED;
212}
213
Szymon Janc4e51eae2011-02-25 19:05:48 +0100214static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200215{
216 struct sk_buff *skb;
217 struct mgmt_hdr *hdr;
218 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300219 int err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200220
Szymon Janc34eb5252011-02-28 14:10:08 +0100221 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200222
Andre Guedes790eff42012-06-07 19:05:46 -0300223 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200224 if (!skb)
225 return -ENOMEM;
226
227 hdr = (void *) skb_put(skb, sizeof(*hdr));
228
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700229 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100230 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200231 hdr->len = cpu_to_le16(sizeof(*ev));
232
233 ev = (void *) skb_put(skb, sizeof(*ev));
234 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200235 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200236
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300237 err = sock_queue_rcv_skb(sk, skb);
238 if (err < 0)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200239 kfree_skb(skb);
240
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300241 return err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200242}
243
Johan Hedbergaee9b212012-02-18 15:07:59 +0200244static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300245 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200246{
247 struct sk_buff *skb;
248 struct mgmt_hdr *hdr;
249 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300250 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200251
252 BT_DBG("sock %p", sk);
253
Andre Guedes790eff42012-06-07 19:05:46 -0300254 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200255 if (!skb)
256 return -ENOMEM;
257
258 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200259
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700260 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100261 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200262 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200263
Johan Hedberga38528f2011-01-22 06:46:43 +0200264 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200265 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b212012-02-18 15:07:59 +0200266 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100267
268 if (rp)
269 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200270
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300271 err = sock_queue_rcv_skb(sk, skb);
272 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200273 kfree_skb(skb);
274
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100275 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200276}
277
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300278static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
279 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200280{
281 struct mgmt_rp_read_version rp;
282
283 BT_DBG("sock %p", sk);
284
285 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700286 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200287
Johan Hedbergaee9b212012-02-18 15:07:59 +0200288 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300289 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200290}
291
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300292static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
293 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200294{
295 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200296 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
297 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200298 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200299 size_t rp_size;
300 int i, err;
301
302 BT_DBG("sock %p", sk);
303
304 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
305
306 rp = kmalloc(rp_size, GFP_KERNEL);
307 if (!rp)
308 return -ENOMEM;
309
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700310 rp->num_commands = cpu_to_le16(num_commands);
311 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200312
313 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
314 put_unaligned_le16(mgmt_commands[i], opcode);
315
316 for (i = 0; i < num_events; i++, opcode++)
317 put_unaligned_le16(mgmt_events[i], opcode);
318
Johan Hedbergaee9b212012-02-18 15:07:59 +0200319 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300320 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200321 kfree(rp);
322
323 return err;
324}
325
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300326static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
327 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200328{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200329 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200330 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200331 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200332 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300333 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200334
335 BT_DBG("sock %p", sk);
336
337 read_lock(&hci_dev_list_lock);
338
339 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300340 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200341 if (d->dev_type == HCI_BREDR &&
342 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700343 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200344 }
345
Johan Hedberga38528f2011-01-22 06:46:43 +0200346 rp_len = sizeof(*rp) + (2 * count);
347 rp = kmalloc(rp_len, GFP_ATOMIC);
348 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100349 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200350 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100351 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200352
Johan Hedberg476e44c2012-10-19 20:10:46 +0300353 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200354 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200355 if (test_bit(HCI_SETUP, &d->dev_flags) ||
356 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200357 continue;
358
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200359 /* Devices marked as raw-only are neither configured
360 * nor unconfigured controllers.
361 */
362 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700363 continue;
364
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200365 if (d->dev_type == HCI_BREDR &&
366 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700367 rp->index[count++] = cpu_to_le16(d->id);
368 BT_DBG("Added hci%u", d->id);
369 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200370 }
371
Johan Hedberg476e44c2012-10-19 20:10:46 +0300372 rp->num_controllers = cpu_to_le16(count);
373 rp_len = sizeof(*rp) + (2 * count);
374
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200375 read_unlock(&hci_dev_list_lock);
376
Johan Hedbergaee9b212012-02-18 15:07:59 +0200377 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300378 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200379
Johan Hedberga38528f2011-01-22 06:46:43 +0200380 kfree(rp);
381
382 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200383}
384
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200385static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
386 void *data, u16 data_len)
387{
388 struct mgmt_rp_read_unconf_index_list *rp;
389 struct hci_dev *d;
390 size_t rp_len;
391 u16 count;
392 int err;
393
394 BT_DBG("sock %p", sk);
395
396 read_lock(&hci_dev_list_lock);
397
398 count = 0;
399 list_for_each_entry(d, &hci_dev_list, list) {
400 if (d->dev_type == HCI_BREDR &&
401 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
402 count++;
403 }
404
405 rp_len = sizeof(*rp) + (2 * count);
406 rp = kmalloc(rp_len, GFP_ATOMIC);
407 if (!rp) {
408 read_unlock(&hci_dev_list_lock);
409 return -ENOMEM;
410 }
411
412 count = 0;
413 list_for_each_entry(d, &hci_dev_list, list) {
414 if (test_bit(HCI_SETUP, &d->dev_flags) ||
415 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
416 continue;
417
418 /* Devices marked as raw-only are neither configured
419 * nor unconfigured controllers.
420 */
421 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
422 continue;
423
424 if (d->dev_type == HCI_BREDR &&
425 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
426 rp->index[count++] = cpu_to_le16(d->id);
427 BT_DBG("Added hci%u", d->id);
428 }
429 }
430
431 rp->num_controllers = cpu_to_le16(count);
432 rp_len = sizeof(*rp) + (2 * count);
433
434 read_unlock(&hci_dev_list_lock);
435
436 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
437 0, rp, rp_len);
438
439 kfree(rp);
440
441 return err;
442}
443
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200444static int read_config_info(struct sock *sk, struct hci_dev *hdev,
445 void *data, u16 data_len)
446{
447 struct mgmt_rp_read_config_info rp;
448
449 BT_DBG("sock %p %s", sk, hdev->name);
450
451 hci_dev_lock(hdev);
452
453 memset(&rp, 0, sizeof(rp));
454 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
455 if (hdev->set_bdaddr)
456 rp.supported_options = cpu_to_le32(MGMT_OPTION_PUBLIC_ADDRESS);
457 else
458 rp.supported_options = cpu_to_le32(0);
459 rp.missing_options = cpu_to_le32(0);
460
461 hci_dev_unlock(hdev);
462
463 return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp,
464 sizeof(rp));
465}
466
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200467static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200468{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200469 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200470
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200471 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200472 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800473 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg03811012010-12-08 00:21:06 +0200474
Andre Guedesed3fa312012-07-24 15:03:46 -0300475 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300476 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500477 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
478 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300479 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200480 settings |= MGMT_SETTING_BREDR;
481 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700482
483 if (lmp_ssp_capable(hdev)) {
484 settings |= MGMT_SETTING_SSP;
485 settings |= MGMT_SETTING_HS;
486 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800487
Marcel Holtmann5afeac12014-01-10 02:07:27 -0800488 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200489 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800490 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700491 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100492
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300493 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200494 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300495 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200496 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300497 }
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200498
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200499 if (hdev->set_bdaddr)
500 settings |= MGMT_SETTING_CONFIGURATION;
501
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200502 return settings;
503}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200504
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200505static u32 get_current_settings(struct hci_dev *hdev)
506{
507 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200508
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200509 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100510 settings |= MGMT_SETTING_POWERED;
511
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200512 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200513 settings |= MGMT_SETTING_CONNECTABLE;
514
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500515 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
516 settings |= MGMT_SETTING_FAST_CONNECTABLE;
517
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200518 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200519 settings |= MGMT_SETTING_DISCOVERABLE;
520
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200521 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200522 settings |= MGMT_SETTING_PAIRABLE;
523
Johan Hedberg56f87902013-10-02 13:43:13 +0300524 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200525 settings |= MGMT_SETTING_BREDR;
526
Johan Hedberg06199cf2012-02-22 16:37:11 +0200527 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200528 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200529
Johan Hedberg47990ea2012-02-22 11:58:37 +0200530 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200531 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200532
Johan Hedberg84bde9d6c2012-01-25 14:21:06 +0200533 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200534 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200535
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200536 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
537 settings |= MGMT_SETTING_HS;
538
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200539 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300540 settings |= MGMT_SETTING_ADVERTISING;
541
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800542 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
543 settings |= MGMT_SETTING_SECURE_CONN;
544
Johan Hedberg0663b292014-06-24 13:15:50 +0300545 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800546 settings |= MGMT_SETTING_DEBUG_KEYS;
547
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200548 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
549 settings |= MGMT_SETTING_PRIVACY;
550
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200551 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200552}
553
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300554#define PNP_INFO_SVCLASS_ID 0x1200
555
Johan Hedberg213202e2013-01-27 00:31:33 +0200556static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
557{
558 u8 *ptr = data, *uuids_start = NULL;
559 struct bt_uuid *uuid;
560
561 if (len < 4)
562 return ptr;
563
564 list_for_each_entry(uuid, &hdev->uuids, list) {
565 u16 uuid16;
566
567 if (uuid->size != 16)
568 continue;
569
570 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
571 if (uuid16 < 0x1100)
572 continue;
573
574 if (uuid16 == PNP_INFO_SVCLASS_ID)
575 continue;
576
577 if (!uuids_start) {
578 uuids_start = ptr;
579 uuids_start[0] = 1;
580 uuids_start[1] = EIR_UUID16_ALL;
581 ptr += 2;
582 }
583
584 /* Stop if not enough space to put next UUID */
585 if ((ptr - data) + sizeof(u16) > len) {
586 uuids_start[1] = EIR_UUID16_SOME;
587 break;
588 }
589
590 *ptr++ = (uuid16 & 0x00ff);
591 *ptr++ = (uuid16 & 0xff00) >> 8;
592 uuids_start[0] += sizeof(uuid16);
593 }
594
595 return ptr;
596}
597
Johan Hedbergcdf19632013-01-27 00:31:34 +0200598static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
599{
600 u8 *ptr = data, *uuids_start = NULL;
601 struct bt_uuid *uuid;
602
603 if (len < 6)
604 return ptr;
605
606 list_for_each_entry(uuid, &hdev->uuids, list) {
607 if (uuid->size != 32)
608 continue;
609
610 if (!uuids_start) {
611 uuids_start = ptr;
612 uuids_start[0] = 1;
613 uuids_start[1] = EIR_UUID32_ALL;
614 ptr += 2;
615 }
616
617 /* Stop if not enough space to put next UUID */
618 if ((ptr - data) + sizeof(u32) > len) {
619 uuids_start[1] = EIR_UUID32_SOME;
620 break;
621 }
622
623 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
624 ptr += sizeof(u32);
625 uuids_start[0] += sizeof(u32);
626 }
627
628 return ptr;
629}
630
Johan Hedbergc00d5752013-01-27 00:31:35 +0200631static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
632{
633 u8 *ptr = data, *uuids_start = NULL;
634 struct bt_uuid *uuid;
635
636 if (len < 18)
637 return ptr;
638
639 list_for_each_entry(uuid, &hdev->uuids, list) {
640 if (uuid->size != 128)
641 continue;
642
643 if (!uuids_start) {
644 uuids_start = ptr;
645 uuids_start[0] = 1;
646 uuids_start[1] = EIR_UUID128_ALL;
647 ptr += 2;
648 }
649
650 /* Stop if not enough space to put next UUID */
651 if ((ptr - data) + 16 > len) {
652 uuids_start[1] = EIR_UUID128_SOME;
653 break;
654 }
655
656 memcpy(ptr, uuid->uuid, 16);
657 ptr += 16;
658 uuids_start[0] += 16;
659 }
660
661 return ptr;
662}
663
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300664static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
665{
666 struct pending_cmd *cmd;
667
668 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
669 if (cmd->opcode == opcode)
670 return cmd;
671 }
672
673 return NULL;
674}
675
Johan Hedberg95868422014-06-28 17:54:07 +0300676static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
677 struct hci_dev *hdev,
678 const void *data)
679{
680 struct pending_cmd *cmd;
681
682 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
683 if (cmd->user_data != data)
684 continue;
685 if (cmd->opcode == opcode)
686 return cmd;
687 }
688
689 return NULL;
690}
691
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700692static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
693{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700694 u8 ad_len = 0;
695 size_t name_len;
696
697 name_len = strlen(hdev->dev_name);
698 if (name_len > 0) {
699 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
700
701 if (name_len > max_len) {
702 name_len = max_len;
703 ptr[1] = EIR_NAME_SHORT;
704 } else
705 ptr[1] = EIR_NAME_COMPLETE;
706
707 ptr[0] = name_len + 1;
708
709 memcpy(ptr + 2, hdev->dev_name, name_len);
710
711 ad_len += (name_len + 2);
712 ptr += (name_len + 2);
713 }
714
715 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700716}
717
718static void update_scan_rsp_data(struct hci_request *req)
719{
720 struct hci_dev *hdev = req->hdev;
721 struct hci_cp_le_set_scan_rsp_data cp;
722 u8 len;
723
Johan Hedberg7751ef12013-10-19 23:38:15 +0300724 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700725 return;
726
727 memset(&cp, 0, sizeof(cp));
728
729 len = create_scan_rsp_data(hdev, cp.data);
730
Johan Hedbergeb438b52013-10-16 15:31:07 +0300731 if (hdev->scan_rsp_data_len == len &&
732 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700733 return;
734
Johan Hedbergeb438b52013-10-16 15:31:07 +0300735 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
736 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700737
738 cp.length = len;
739
740 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
741}
742
Johan Hedberg9a43e252013-10-20 19:00:07 +0300743static u8 get_adv_discov_flags(struct hci_dev *hdev)
744{
745 struct pending_cmd *cmd;
746
747 /* If there's a pending mgmt command the flags will not yet have
748 * their final values, so check for this first.
749 */
750 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
751 if (cmd) {
752 struct mgmt_mode *cp = cmd->param;
753 if (cp->val == 0x01)
754 return LE_AD_GENERAL;
755 else if (cp->val == 0x02)
756 return LE_AD_LIMITED;
757 } else {
758 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
759 return LE_AD_LIMITED;
760 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
761 return LE_AD_GENERAL;
762 }
763
764 return 0;
765}
766
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700767static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700768{
769 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700770
Johan Hedberg9a43e252013-10-20 19:00:07 +0300771 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700772
Johan Hedberge8340042014-01-30 11:16:50 -0800773 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700774 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700775
776 if (flags) {
777 BT_DBG("adv flags 0x%02x", flags);
778
779 ptr[0] = 2;
780 ptr[1] = EIR_FLAGS;
781 ptr[2] = flags;
782
783 ad_len += 3;
784 ptr += 3;
785 }
786
787 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
788 ptr[0] = 2;
789 ptr[1] = EIR_TX_POWER;
790 ptr[2] = (u8) hdev->adv_tx_power;
791
792 ad_len += 3;
793 ptr += 3;
794 }
795
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700796 return ad_len;
797}
798
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700799static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700800{
801 struct hci_dev *hdev = req->hdev;
802 struct hci_cp_le_set_adv_data cp;
803 u8 len;
804
Johan Hedberg10994ce2013-10-19 23:38:16 +0300805 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700806 return;
807
808 memset(&cp, 0, sizeof(cp));
809
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700810 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700811
812 if (hdev->adv_data_len == len &&
813 memcmp(cp.data, hdev->adv_data, len) == 0)
814 return;
815
816 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
817 hdev->adv_data_len = len;
818
819 cp.length = len;
820
821 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
822}
823
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300824static void create_eir(struct hci_dev *hdev, u8 *data)
825{
826 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300827 size_t name_len;
828
829 name_len = strlen(hdev->dev_name);
830
831 if (name_len > 0) {
832 /* EIR Data type */
833 if (name_len > 48) {
834 name_len = 48;
835 ptr[1] = EIR_NAME_SHORT;
836 } else
837 ptr[1] = EIR_NAME_COMPLETE;
838
839 /* EIR Data length */
840 ptr[0] = name_len + 1;
841
842 memcpy(ptr + 2, hdev->dev_name, name_len);
843
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300844 ptr += (name_len + 2);
845 }
846
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100847 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700848 ptr[0] = 2;
849 ptr[1] = EIR_TX_POWER;
850 ptr[2] = (u8) hdev->inq_tx_power;
851
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700852 ptr += 3;
853 }
854
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700855 if (hdev->devid_source > 0) {
856 ptr[0] = 9;
857 ptr[1] = EIR_DEVICE_ID;
858
859 put_unaligned_le16(hdev->devid_source, ptr + 2);
860 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
861 put_unaligned_le16(hdev->devid_product, ptr + 6);
862 put_unaligned_le16(hdev->devid_version, ptr + 8);
863
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700864 ptr += 10;
865 }
866
Johan Hedberg213202e2013-01-27 00:31:33 +0200867 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200868 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200869 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300870}
871
Johan Hedberg890ea892013-03-15 17:06:52 -0500872static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300873{
Johan Hedberg890ea892013-03-15 17:06:52 -0500874 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300875 struct hci_cp_write_eir cp;
876
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200877 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500878 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200879
Johan Hedberg976eb202012-10-24 21:12:01 +0300880 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500881 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300882
Johan Hedberg84bde9d6c2012-01-25 14:21:06 +0200883 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500884 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300885
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200886 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500887 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300888
889 memset(&cp, 0, sizeof(cp));
890
891 create_eir(hdev, cp.data);
892
893 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500894 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300895
896 memcpy(hdev->eir, cp.data, sizeof(cp.data));
897
Johan Hedberg890ea892013-03-15 17:06:52 -0500898 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300899}
900
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200901static u8 get_service_classes(struct hci_dev *hdev)
902{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300903 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200904 u8 val = 0;
905
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300906 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200907 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200908
909 return val;
910}
911
Johan Hedberg890ea892013-03-15 17:06:52 -0500912static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200913{
Johan Hedberg890ea892013-03-15 17:06:52 -0500914 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200915 u8 cod[3];
916
917 BT_DBG("%s", hdev->name);
918
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200919 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500920 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200921
Johan Hedbergf87ea1d2013-10-19 23:38:17 +0300922 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
923 return;
924
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200925 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500926 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200927
928 cod[0] = hdev->minor_class;
929 cod[1] = hdev->major_class;
930 cod[2] = get_service_classes(hdev);
931
Marcel Holtmann6acd7db2013-10-15 06:33:53 -0700932 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
933 cod[1] |= 0x20;
934
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200935 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500936 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200937
Johan Hedberg890ea892013-03-15 17:06:52 -0500938 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200939}
940
Johan Hedberga4858cb2014-02-25 19:56:31 +0200941static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200942{
943 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200944
945 /* If there's a pending mgmt command the flag will not yet have
946 * it's final value, so check for this first.
947 */
948 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
949 if (cmd) {
950 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200951 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200952 }
953
Johan Hedberga4858cb2014-02-25 19:56:31 +0200954 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200955}
956
957static void enable_advertising(struct hci_request *req)
958{
959 struct hci_dev *hdev = req->hdev;
960 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200961 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200962 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200963
Johan Hedberg8d972502014-02-28 12:54:14 +0200964 /* Clear the HCI_ADVERTISING bit temporarily so that the
965 * hci_update_random_address knows that it's safe to go ahead
966 * and write a new random address. The flag will be set back on
967 * as soon as the SET_ADV_ENABLE HCI command completes.
968 */
969 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
970
Johan Hedberga4858cb2014-02-25 19:56:31 +0200971 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200972
Johan Hedberga4858cb2014-02-25 19:56:31 +0200973 /* Set require_privacy to true only when non-connectable
974 * advertising is used. In that case it is fine to use a
975 * non-resolvable private address.
976 */
977 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200978 return;
979
Marcel Holtmann41c90c12014-02-23 20:25:55 -0800980 memset(&cp, 0, sizeof(cp));
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700981 cp.min_interval = cpu_to_le16(0x0800);
982 cp.max_interval = cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +0200983 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200984 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200985 cp.channel_map = hdev->le_adv_channel_map;
986
987 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
988
989 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
990}
991
992static void disable_advertising(struct hci_request *req)
993{
994 u8 enable = 0x00;
995
996 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
997}
998
Johan Hedberg7d785252011-12-15 00:47:39 +0200999static void service_cache_off(struct work_struct *work)
1000{
1001 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001002 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001003 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001004
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001005 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001006 return;
1007
Johan Hedberg890ea892013-03-15 17:06:52 -05001008 hci_req_init(&req, hdev);
1009
Johan Hedberg7d785252011-12-15 00:47:39 +02001010 hci_dev_lock(hdev);
1011
Johan Hedberg890ea892013-03-15 17:06:52 -05001012 update_eir(&req);
1013 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001014
1015 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001016
1017 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001018}
1019
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001020static void rpa_expired(struct work_struct *work)
1021{
1022 struct hci_dev *hdev = container_of(work, struct hci_dev,
1023 rpa_expired.work);
1024 struct hci_request req;
1025
1026 BT_DBG("");
1027
1028 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1029
1030 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
1031 hci_conn_num(hdev, LE_LINK) > 0)
1032 return;
1033
1034 /* The generation of a new RPA and programming it into the
1035 * controller happens in the enable_advertising() function.
1036 */
1037
1038 hci_req_init(&req, hdev);
1039
1040 disable_advertising(&req);
1041 enable_advertising(&req);
1042
1043 hci_req_run(&req, NULL);
1044}
1045
Johan Hedberg6a919082012-02-28 06:17:26 +02001046static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001047{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001048 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001049 return;
1050
Johan Hedberg4f87da82012-03-02 19:55:56 +02001051 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001052 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001053
Johan Hedberg4f87da82012-03-02 19:55:56 +02001054 /* Non-mgmt controlled devices get this bit set
1055 * implicitly so that pairing works for them, however
1056 * for mgmt we require user-space to explicitly enable
1057 * it
1058 */
1059 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001060}
1061
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001062static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001063 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001064{
1065 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001066
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001067 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001068
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001069 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001070
Johan Hedberg03811012010-12-08 00:21:06 +02001071 memset(&rp, 0, sizeof(rp));
1072
Johan Hedberg03811012010-12-08 00:21:06 +02001073 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001074
1075 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001076 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001077
1078 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1079 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1080
1081 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001082
1083 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001084 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001085
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001086 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001087
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001088 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001089 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001090}
1091
1092static void mgmt_pending_free(struct pending_cmd *cmd)
1093{
1094 sock_put(cmd->sk);
1095 kfree(cmd->param);
1096 kfree(cmd);
1097}
1098
1099static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001100 struct hci_dev *hdev, void *data,
1101 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001102{
1103 struct pending_cmd *cmd;
1104
Johan Hedbergfca20012014-06-28 17:54:05 +03001105 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001106 if (!cmd)
1107 return NULL;
1108
1109 cmd->opcode = opcode;
1110 cmd->index = hdev->id;
1111
Andre Guedes12b94562012-06-07 19:05:45 -03001112 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001113 if (!cmd->param) {
1114 kfree(cmd);
1115 return NULL;
1116 }
1117
1118 if (data)
1119 memcpy(cmd->param, data, len);
1120
1121 cmd->sk = sk;
1122 sock_hold(sk);
1123
1124 list_add(&cmd->list, &hdev->mgmt_pending);
1125
1126 return cmd;
1127}
1128
1129static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001130 void (*cb)(struct pending_cmd *cmd,
1131 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001132 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001133{
Andre Guedesa3d09352013-02-01 11:21:30 -03001134 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001135
Andre Guedesa3d09352013-02-01 11:21:30 -03001136 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001137 if (opcode > 0 && cmd->opcode != opcode)
1138 continue;
1139
1140 cb(cmd, data);
1141 }
1142}
1143
Johan Hedberg03811012010-12-08 00:21:06 +02001144static void mgmt_pending_remove(struct pending_cmd *cmd)
1145{
1146 list_del(&cmd->list);
1147 mgmt_pending_free(cmd);
1148}
1149
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001150static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001151{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001152 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001153
Johan Hedbergaee9b212012-02-18 15:07:59 +02001154 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001155 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001156}
1157
Johan Hedberg8b064a32014-02-24 14:52:22 +02001158static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1159{
1160 BT_DBG("%s status 0x%02x", hdev->name, status);
1161
Johan Hedberga3172b72014-02-28 09:33:44 +02001162 if (hci_conn_count(hdev) == 0) {
1163 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001164 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001165 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001166}
1167
Johan Hedberg21a60d32014-06-10 14:05:58 +03001168static void hci_stop_discovery(struct hci_request *req)
1169{
1170 struct hci_dev *hdev = req->hdev;
1171 struct hci_cp_remote_name_req_cancel cp;
1172 struct inquiry_entry *e;
1173
1174 switch (hdev->discovery.state) {
1175 case DISCOVERY_FINDING:
1176 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1177 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1178 } else {
1179 cancel_delayed_work(&hdev->le_scan_disable);
1180 hci_req_add_le_scan_disable(req);
1181 }
1182
1183 break;
1184
1185 case DISCOVERY_RESOLVING:
1186 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1187 NAME_PENDING);
1188 if (!e)
1189 return;
1190
1191 bacpy(&cp.bdaddr, &e->data.bdaddr);
1192 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1193 &cp);
1194
1195 break;
1196
1197 default:
1198 /* Passive scanning */
1199 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
1200 hci_req_add_le_scan_disable(req);
1201 break;
1202 }
1203}
1204
Johan Hedberg8b064a32014-02-24 14:52:22 +02001205static int clean_up_hci_state(struct hci_dev *hdev)
1206{
1207 struct hci_request req;
1208 struct hci_conn *conn;
1209
1210 hci_req_init(&req, hdev);
1211
1212 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1213 test_bit(HCI_PSCAN, &hdev->flags)) {
1214 u8 scan = 0x00;
1215 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1216 }
1217
1218 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1219 disable_advertising(&req);
1220
Johan Hedbergf8680f12014-06-10 14:05:59 +03001221 hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001222
1223 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1224 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001225 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001226
Johan Hedbergc9910d02014-02-27 14:35:12 +02001227 switch (conn->state) {
1228 case BT_CONNECTED:
1229 case BT_CONFIG:
1230 dc.handle = cpu_to_le16(conn->handle);
1231 dc.reason = 0x15; /* Terminated due to Power Off */
1232 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1233 break;
1234 case BT_CONNECT:
1235 if (conn->type == LE_LINK)
1236 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1237 0, NULL);
1238 else if (conn->type == ACL_LINK)
1239 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1240 6, &conn->dst);
1241 break;
1242 case BT_CONNECT2:
1243 bacpy(&rej.bdaddr, &conn->dst);
1244 rej.reason = 0x15; /* Terminated due to Power Off */
1245 if (conn->type == ACL_LINK)
1246 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1247 sizeof(rej), &rej);
1248 else if (conn->type == SCO_LINK)
1249 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1250 sizeof(rej), &rej);
1251 break;
1252 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001253 }
1254
1255 return hci_req_run(&req, clean_up_hci_complete);
1256}
1257
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001258static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001259 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001260{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001261 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001262 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001263 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001264
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001265 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001266
Johan Hedberga7e80f22013-01-09 16:05:19 +02001267 if (cp->val != 0x00 && cp->val != 0x01)
1268 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1269 MGMT_STATUS_INVALID_PARAMS);
1270
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001271 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001272
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001273 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1274 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1275 MGMT_STATUS_BUSY);
1276 goto failed;
1277 }
1278
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001279 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1280 cancel_delayed_work(&hdev->power_off);
1281
1282 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001283 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1284 data, len);
1285 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001286 goto failed;
1287 }
1288 }
1289
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001290 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001291 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001292 goto failed;
1293 }
1294
Johan Hedberg03811012010-12-08 00:21:06 +02001295 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1296 if (!cmd) {
1297 err = -ENOMEM;
1298 goto failed;
1299 }
1300
Johan Hedberg8b064a32014-02-24 14:52:22 +02001301 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001302 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001303 err = 0;
1304 } else {
1305 /* Disconnect connections, stop scans, etc */
1306 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001307 if (!err)
1308 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1309 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001310
Johan Hedberg8b064a32014-02-24 14:52:22 +02001311 /* ENODATA means there were no HCI commands queued */
1312 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001313 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001314 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1315 err = 0;
1316 }
1317 }
Johan Hedberg03811012010-12-08 00:21:06 +02001318
1319failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001320 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001321 return err;
1322}
1323
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001324static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
1325 struct sock *skip_sk)
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001326{
1327 struct sk_buff *skb;
1328 struct mgmt_hdr *hdr;
1329
Andre Guedes790eff42012-06-07 19:05:46 -03001330 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001331 if (!skb)
1332 return -ENOMEM;
1333
1334 hdr = (void *) skb_put(skb, sizeof(*hdr));
1335 hdr->opcode = cpu_to_le16(event);
1336 if (hdev)
1337 hdr->index = cpu_to_le16(hdev->id);
1338 else
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001339 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001340 hdr->len = cpu_to_le16(data_len);
1341
1342 if (data)
1343 memcpy(skb_put(skb, data_len), data, data_len);
1344
Marcel Holtmann97e0bde2012-02-22 13:49:28 +01001345 /* Time stamp */
1346 __net_timestamp(skb);
1347
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001348 hci_send_to_control(skb, skip_sk);
1349 kfree_skb(skb);
1350
1351 return 0;
1352}
1353
1354static int new_settings(struct hci_dev *hdev, struct sock *skip)
1355{
1356 __le32 ev;
1357
1358 ev = cpu_to_le32(get_current_settings(hdev));
1359
1360 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1361}
1362
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001363struct cmd_lookup {
1364 struct sock *sk;
1365 struct hci_dev *hdev;
1366 u8 mgmt_status;
1367};
1368
1369static void settings_rsp(struct pending_cmd *cmd, void *data)
1370{
1371 struct cmd_lookup *match = data;
1372
1373 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1374
1375 list_del(&cmd->list);
1376
1377 if (match->sk == NULL) {
1378 match->sk = cmd->sk;
1379 sock_hold(match->sk);
1380 }
1381
1382 mgmt_pending_free(cmd);
1383}
1384
1385static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1386{
1387 u8 *status = data;
1388
1389 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1390 mgmt_pending_remove(cmd);
1391}
1392
Johan Hedberge6fe7982013-10-02 15:45:22 +03001393static u8 mgmt_bredr_support(struct hci_dev *hdev)
1394{
1395 if (!lmp_bredr_capable(hdev))
1396 return MGMT_STATUS_NOT_SUPPORTED;
1397 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1398 return MGMT_STATUS_REJECTED;
1399 else
1400 return MGMT_STATUS_SUCCESS;
1401}
1402
1403static u8 mgmt_le_support(struct hci_dev *hdev)
1404{
1405 if (!lmp_le_capable(hdev))
1406 return MGMT_STATUS_NOT_SUPPORTED;
1407 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1408 return MGMT_STATUS_REJECTED;
1409 else
1410 return MGMT_STATUS_SUCCESS;
1411}
1412
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001413static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1414{
1415 struct pending_cmd *cmd;
1416 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001417 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001418 bool changed;
1419
1420 BT_DBG("status 0x%02x", status);
1421
1422 hci_dev_lock(hdev);
1423
1424 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1425 if (!cmd)
1426 goto unlock;
1427
1428 if (status) {
1429 u8 mgmt_err = mgmt_status(status);
1430 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001431 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001432 goto remove_cmd;
1433 }
1434
1435 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001436 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001437 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1438 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001439
1440 if (hdev->discov_timeout > 0) {
1441 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1442 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1443 to);
1444 }
1445 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001446 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1447 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001448 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001449
1450 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1451
1452 if (changed)
1453 new_settings(hdev, cmd->sk);
1454
Marcel Holtmann970ba522013-10-15 06:33:57 -07001455 /* When the discoverable mode gets changed, make sure
1456 * that class of device has the limited discoverable
1457 * bit correctly set.
1458 */
1459 hci_req_init(&req, hdev);
1460 update_class(&req);
1461 hci_req_run(&req, NULL);
1462
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001463remove_cmd:
1464 mgmt_pending_remove(cmd);
1465
1466unlock:
1467 hci_dev_unlock(hdev);
1468}
1469
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001470static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001471 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001472{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001473 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001474 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001475 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001476 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001477 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001478 int err;
1479
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001480 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001481
Johan Hedberg9a43e252013-10-20 19:00:07 +03001482 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1483 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001484 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001485 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001486
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001487 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001488 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1489 MGMT_STATUS_INVALID_PARAMS);
1490
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001491 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001492
1493 /* Disabling discoverable requires that no timeout is set,
1494 * and enabling limited discoverable requires a timeout.
1495 */
1496 if ((cp->val == 0x00 && timeout > 0) ||
1497 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001498 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001499 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001500
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001501 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001502
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001503 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001504 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001505 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001506 goto failed;
1507 }
1508
1509 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001510 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001511 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001512 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001513 goto failed;
1514 }
1515
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001516 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001517 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001518 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001519 goto failed;
1520 }
1521
1522 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001523 bool changed = false;
1524
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001525 /* Setting limited discoverable when powered off is
1526 * not a valid operation since it requires a timeout
1527 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1528 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001529 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1530 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1531 changed = true;
1532 }
1533
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001534 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001535 if (err < 0)
1536 goto failed;
1537
1538 if (changed)
1539 err = new_settings(hdev, sk);
1540
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001541 goto failed;
1542 }
1543
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001544 /* If the current mode is the same, then just update the timeout
1545 * value with the new value. And if only the timeout gets updated,
1546 * then no need for any HCI transactions.
1547 */
1548 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1549 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1550 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001551 cancel_delayed_work(&hdev->discov_off);
1552 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001553
Marcel Holtmann36261542013-10-15 08:28:51 -07001554 if (cp->val && hdev->discov_timeout > 0) {
1555 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001556 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001557 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001558 }
1559
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001560 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001561 goto failed;
1562 }
1563
1564 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1565 if (!cmd) {
1566 err = -ENOMEM;
1567 goto failed;
1568 }
1569
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001570 /* Cancel any potential discoverable timeout that might be
1571 * still active and store new timeout value. The arming of
1572 * the timeout happens in the complete handler.
1573 */
1574 cancel_delayed_work(&hdev->discov_off);
1575 hdev->discov_timeout = timeout;
1576
Johan Hedbergb456f872013-10-19 23:38:22 +03001577 /* Limited discoverable mode */
1578 if (cp->val == 0x02)
1579 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1580 else
1581 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1582
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001583 hci_req_init(&req, hdev);
1584
Johan Hedberg9a43e252013-10-20 19:00:07 +03001585 /* The procedure for LE-only controllers is much simpler - just
1586 * update the advertising data.
1587 */
1588 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1589 goto update_ad;
1590
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001591 scan = SCAN_PAGE;
1592
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001593 if (cp->val) {
1594 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001595
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001596 if (cp->val == 0x02) {
1597 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001598 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001599 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1600 hci_cp.iac_lap[1] = 0x8b;
1601 hci_cp.iac_lap[2] = 0x9e;
1602 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1603 hci_cp.iac_lap[4] = 0x8b;
1604 hci_cp.iac_lap[5] = 0x9e;
1605 } else {
1606 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001607 hci_cp.num_iac = 1;
1608 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1609 hci_cp.iac_lap[1] = 0x8b;
1610 hci_cp.iac_lap[2] = 0x9e;
1611 }
1612
1613 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1614 (hci_cp.num_iac * 3) + 1, &hci_cp);
1615
1616 scan |= SCAN_INQUIRY;
1617 } else {
1618 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1619 }
1620
1621 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001622
Johan Hedberg9a43e252013-10-20 19:00:07 +03001623update_ad:
1624 update_adv_data(&req);
1625
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001626 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001627 if (err < 0)
1628 mgmt_pending_remove(cmd);
1629
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001630failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001631 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001632 return err;
1633}
1634
Johan Hedberg406d7802013-03-15 17:07:09 -05001635static void write_fast_connectable(struct hci_request *req, bool enable)
1636{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001637 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001638 struct hci_cp_write_page_scan_activity acp;
1639 u8 type;
1640
Johan Hedberg547003b2013-10-21 16:51:53 +03001641 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1642 return;
1643
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001644 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1645 return;
1646
Johan Hedberg406d7802013-03-15 17:07:09 -05001647 if (enable) {
1648 type = PAGE_SCAN_TYPE_INTERLACED;
1649
1650 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001651 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001652 } else {
1653 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1654
1655 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001656 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001657 }
1658
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001659 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001660
Johan Hedbergbd98b992013-03-15 17:07:13 -05001661 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1662 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1663 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1664 sizeof(acp), &acp);
1665
1666 if (hdev->page_scan_type != type)
1667 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001668}
1669
Johan Hedberg2b76f452013-03-15 17:07:04 -05001670static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1671{
1672 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001673 struct mgmt_mode *cp;
1674 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001675
1676 BT_DBG("status 0x%02x", status);
1677
1678 hci_dev_lock(hdev);
1679
1680 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1681 if (!cmd)
1682 goto unlock;
1683
Johan Hedberg37438c12013-10-14 16:20:05 +03001684 if (status) {
1685 u8 mgmt_err = mgmt_status(status);
1686 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1687 goto remove_cmd;
1688 }
1689
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001690 cp = cmd->param;
1691 if (cp->val)
1692 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1693 else
1694 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1695
Johan Hedberg2b76f452013-03-15 17:07:04 -05001696 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1697
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001698 if (changed)
1699 new_settings(hdev, cmd->sk);
1700
Johan Hedberg37438c12013-10-14 16:20:05 +03001701remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001702 mgmt_pending_remove(cmd);
1703
1704unlock:
1705 hci_dev_unlock(hdev);
1706}
1707
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001708static int set_connectable_update_settings(struct hci_dev *hdev,
1709 struct sock *sk, u8 val)
1710{
1711 bool changed = false;
1712 int err;
1713
1714 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1715 changed = true;
1716
1717 if (val) {
1718 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1719 } else {
1720 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1721 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1722 }
1723
1724 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1725 if (err < 0)
1726 return err;
1727
1728 if (changed)
1729 return new_settings(hdev, sk);
1730
1731 return 0;
1732}
1733
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001734static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001735 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001736{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001737 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001738 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001739 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001740 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001741 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001742
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001743 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001744
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001745 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1746 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001747 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001748 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001749
Johan Hedberga7e80f22013-01-09 16:05:19 +02001750 if (cp->val != 0x00 && cp->val != 0x01)
1751 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1752 MGMT_STATUS_INVALID_PARAMS);
1753
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001754 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001755
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001756 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001757 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001758 goto failed;
1759 }
1760
1761 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001762 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001763 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001764 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001765 goto failed;
1766 }
1767
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001768 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1769 if (!cmd) {
1770 err = -ENOMEM;
1771 goto failed;
1772 }
1773
Johan Hedberg2b76f452013-03-15 17:07:04 -05001774 hci_req_init(&req, hdev);
1775
Johan Hedberg9a43e252013-10-20 19:00:07 +03001776 /* If BR/EDR is not enabled and we disable advertising as a
1777 * by-product of disabling connectable, we need to update the
1778 * advertising flags.
1779 */
1780 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1781 if (!cp->val) {
1782 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1783 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1784 }
1785 update_adv_data(&req);
1786 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001787 if (cp->val) {
1788 scan = SCAN_PAGE;
1789 } else {
1790 scan = 0;
1791
1792 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001793 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001794 cancel_delayed_work(&hdev->discov_off);
1795 }
1796
1797 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1798 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001799
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001800 /* If we're going from non-connectable to connectable or
1801 * vice-versa when fast connectable is enabled ensure that fast
1802 * connectable gets disabled. write_fast_connectable won't do
1803 * anything if the page scan parameters are already what they
1804 * should be.
1805 */
1806 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001807 write_fast_connectable(&req, false);
1808
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001809 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1810 hci_conn_num(hdev, LE_LINK) == 0) {
1811 disable_advertising(&req);
1812 enable_advertising(&req);
1813 }
1814
Johan Hedberg2b76f452013-03-15 17:07:04 -05001815 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001816 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001817 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001818 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001819 err = set_connectable_update_settings(hdev, sk,
1820 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001821 goto failed;
1822 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001823
1824failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001825 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001826 return err;
1827}
1828
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001829static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001830 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001831{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001832 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001833 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001834 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001835
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001836 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001837
Johan Hedberga7e80f22013-01-09 16:05:19 +02001838 if (cp->val != 0x00 && cp->val != 0x01)
1839 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1840 MGMT_STATUS_INVALID_PARAMS);
1841
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001842 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001843
1844 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001845 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001846 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001847 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001848
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001849 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001850 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001851 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001852
Marcel Holtmann55594352013-10-06 16:11:57 -07001853 if (changed)
1854 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001855
Marcel Holtmann55594352013-10-06 16:11:57 -07001856unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001857 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001858 return err;
1859}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001860
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001861static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1862 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001863{
1864 struct mgmt_mode *cp = data;
1865 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001866 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001867 int err;
1868
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001869 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001870
Johan Hedberge6fe7982013-10-02 15:45:22 +03001871 status = mgmt_bredr_support(hdev);
1872 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001873 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001874 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001875
Johan Hedberga7e80f22013-01-09 16:05:19 +02001876 if (cp->val != 0x00 && cp->val != 0x01)
1877 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1878 MGMT_STATUS_INVALID_PARAMS);
1879
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001880 hci_dev_lock(hdev);
1881
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001882 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001883 bool changed = false;
1884
1885 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001886 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001887 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1888 changed = true;
1889 }
1890
1891 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1892 if (err < 0)
1893 goto failed;
1894
1895 if (changed)
1896 err = new_settings(hdev, sk);
1897
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001898 goto failed;
1899 }
1900
1901 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001902 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001903 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001904 goto failed;
1905 }
1906
1907 val = !!cp->val;
1908
1909 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1910 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1911 goto failed;
1912 }
1913
1914 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1915 if (!cmd) {
1916 err = -ENOMEM;
1917 goto failed;
1918 }
1919
1920 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1921 if (err < 0) {
1922 mgmt_pending_remove(cmd);
1923 goto failed;
1924 }
1925
1926failed:
1927 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001928 return err;
1929}
1930
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001931static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001932{
1933 struct mgmt_mode *cp = data;
1934 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001935 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001936 int err;
1937
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001938 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001939
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001940 status = mgmt_bredr_support(hdev);
1941 if (status)
1942 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1943
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001944 if (!lmp_ssp_capable(hdev))
1945 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1946 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001947
Johan Hedberga7e80f22013-01-09 16:05:19 +02001948 if (cp->val != 0x00 && cp->val != 0x01)
1949 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1950 MGMT_STATUS_INVALID_PARAMS);
1951
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001952 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02001953
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001954 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001955 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001956
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001957 if (cp->val) {
1958 changed = !test_and_set_bit(HCI_SSP_ENABLED,
1959 &hdev->dev_flags);
1960 } else {
1961 changed = test_and_clear_bit(HCI_SSP_ENABLED,
1962 &hdev->dev_flags);
1963 if (!changed)
1964 changed = test_and_clear_bit(HCI_HS_ENABLED,
1965 &hdev->dev_flags);
1966 else
1967 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001968 }
1969
1970 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1971 if (err < 0)
1972 goto failed;
1973
1974 if (changed)
1975 err = new_settings(hdev, sk);
1976
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001977 goto failed;
1978 }
1979
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001980 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
1981 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01001982 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1983 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001984 goto failed;
1985 }
1986
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001987 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001988 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1989 goto failed;
1990 }
1991
1992 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
1993 if (!cmd) {
1994 err = -ENOMEM;
1995 goto failed;
1996 }
1997
Johan Hedberg37699722014-06-24 14:00:27 +03001998 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
1999 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2000 sizeof(cp->val), &cp->val);
2001
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002002 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002003 if (err < 0) {
2004 mgmt_pending_remove(cmd);
2005 goto failed;
2006 }
2007
2008failed:
2009 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002010 return err;
2011}
2012
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002013static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002014{
2015 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002016 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002017 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002018 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002019
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002020 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002021
Johan Hedberge6fe7982013-10-02 15:45:22 +03002022 status = mgmt_bredr_support(hdev);
2023 if (status)
2024 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002025
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002026 if (!lmp_ssp_capable(hdev))
2027 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2028 MGMT_STATUS_NOT_SUPPORTED);
2029
2030 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2031 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2032 MGMT_STATUS_REJECTED);
2033
Johan Hedberga7e80f22013-01-09 16:05:19 +02002034 if (cp->val != 0x00 && cp->val != 0x01)
2035 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2036 MGMT_STATUS_INVALID_PARAMS);
2037
Marcel Holtmannee392692013-10-01 22:59:23 -07002038 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002039
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002040 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002041 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002042 } else {
2043 if (hdev_is_powered(hdev)) {
2044 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2045 MGMT_STATUS_REJECTED);
2046 goto unlock;
2047 }
2048
Marcel Holtmannee392692013-10-01 22:59:23 -07002049 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002050 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002051
2052 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2053 if (err < 0)
2054 goto unlock;
2055
2056 if (changed)
2057 err = new_settings(hdev, sk);
2058
2059unlock:
2060 hci_dev_unlock(hdev);
2061 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002062}
2063
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002064static void le_enable_complete(struct hci_dev *hdev, u8 status)
2065{
2066 struct cmd_lookup match = { NULL, hdev };
2067
2068 if (status) {
2069 u8 mgmt_err = mgmt_status(status);
2070
2071 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2072 &mgmt_err);
2073 return;
2074 }
2075
2076 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2077
2078 new_settings(hdev, match.sk);
2079
2080 if (match.sk)
2081 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002082
2083 /* Make sure the controller has a good default for
2084 * advertising data. Restrict the update to when LE
2085 * has actually been enabled. During power on, the
2086 * update in powered_update_hci will take care of it.
2087 */
2088 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2089 struct hci_request req;
2090
2091 hci_dev_lock(hdev);
2092
2093 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002094 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002095 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002096 hci_req_run(&req, NULL);
2097
2098 hci_dev_unlock(hdev);
2099 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002100}
2101
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002102static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002103{
2104 struct mgmt_mode *cp = data;
2105 struct hci_cp_write_le_host_supported hci_cp;
2106 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002107 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002108 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002109 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002110
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002111 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002112
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002113 if (!lmp_le_capable(hdev))
2114 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2115 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002116
Johan Hedberga7e80f22013-01-09 16:05:19 +02002117 if (cp->val != 0x00 && cp->val != 0x01)
2118 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2119 MGMT_STATUS_INVALID_PARAMS);
2120
Johan Hedbergc73eee92013-04-19 18:35:21 +03002121 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002122 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002123 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2124 MGMT_STATUS_REJECTED);
2125
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002126 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002127
2128 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002129 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002130
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002131 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002132 bool changed = false;
2133
2134 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2135 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2136 changed = true;
2137 }
2138
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002139 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2140 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002141 changed = true;
2142 }
2143
Johan Hedberg06199cf2012-02-22 16:37:11 +02002144 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2145 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002146 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002147
2148 if (changed)
2149 err = new_settings(hdev, sk);
2150
Johan Hedberg1de028c2012-02-29 19:55:35 -08002151 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002152 }
2153
Johan Hedberg4375f102013-09-25 13:26:10 +03002154 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2155 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002156 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002157 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002158 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002159 }
2160
2161 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2162 if (!cmd) {
2163 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002164 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002165 }
2166
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002167 hci_req_init(&req, hdev);
2168
Johan Hedberg06199cf2012-02-22 16:37:11 +02002169 memset(&hci_cp, 0, sizeof(hci_cp));
2170
2171 if (val) {
2172 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002173 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002174 } else {
2175 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2176 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002177 }
2178
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002179 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2180 &hci_cp);
2181
2182 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302183 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002184 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002185
Johan Hedberg1de028c2012-02-29 19:55:35 -08002186unlock:
2187 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002188 return err;
2189}
2190
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002191/* This is a helper function to test for pending mgmt commands that can
2192 * cause CoD or EIR HCI commands. We can only allow one such pending
2193 * mgmt command at a time since otherwise we cannot easily track what
2194 * the current values are, will be, and based on that calculate if a new
2195 * HCI command needs to be sent and if yes with what value.
2196 */
2197static bool pending_eir_or_class(struct hci_dev *hdev)
2198{
2199 struct pending_cmd *cmd;
2200
2201 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2202 switch (cmd->opcode) {
2203 case MGMT_OP_ADD_UUID:
2204 case MGMT_OP_REMOVE_UUID:
2205 case MGMT_OP_SET_DEV_CLASS:
2206 case MGMT_OP_SET_POWERED:
2207 return true;
2208 }
2209 }
2210
2211 return false;
2212}
2213
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002214static const u8 bluetooth_base_uuid[] = {
2215 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2216 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2217};
2218
2219static u8 get_uuid_size(const u8 *uuid)
2220{
2221 u32 val;
2222
2223 if (memcmp(uuid, bluetooth_base_uuid, 12))
2224 return 128;
2225
2226 val = get_unaligned_le32(&uuid[12]);
2227 if (val > 0xffff)
2228 return 32;
2229
2230 return 16;
2231}
2232
Johan Hedberg92da6092013-03-15 17:06:55 -05002233static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2234{
2235 struct pending_cmd *cmd;
2236
2237 hci_dev_lock(hdev);
2238
2239 cmd = mgmt_pending_find(mgmt_op, hdev);
2240 if (!cmd)
2241 goto unlock;
2242
2243 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2244 hdev->dev_class, 3);
2245
2246 mgmt_pending_remove(cmd);
2247
2248unlock:
2249 hci_dev_unlock(hdev);
2250}
2251
2252static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2253{
2254 BT_DBG("status 0x%02x", status);
2255
2256 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2257}
2258
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002259static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002260{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002261 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002262 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002263 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002264 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002265 int err;
2266
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002267 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002268
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002269 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002270
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002271 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002272 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002273 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002274 goto failed;
2275 }
2276
Andre Guedes92c4c202012-06-07 19:05:44 -03002277 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002278 if (!uuid) {
2279 err = -ENOMEM;
2280 goto failed;
2281 }
2282
2283 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002284 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002285 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002286
Johan Hedbergde66aa62013-01-27 00:31:27 +02002287 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002288
Johan Hedberg890ea892013-03-15 17:06:52 -05002289 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002290
Johan Hedberg890ea892013-03-15 17:06:52 -05002291 update_class(&req);
2292 update_eir(&req);
2293
Johan Hedberg92da6092013-03-15 17:06:55 -05002294 err = hci_req_run(&req, add_uuid_complete);
2295 if (err < 0) {
2296 if (err != -ENODATA)
2297 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002298
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002299 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002300 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002301 goto failed;
2302 }
2303
2304 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002305 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002306 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002307 goto failed;
2308 }
2309
2310 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002311
2312failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002313 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002314 return err;
2315}
2316
Johan Hedberg24b78d02012-02-23 23:24:30 +02002317static bool enable_service_cache(struct hci_dev *hdev)
2318{
2319 if (!hdev_is_powered(hdev))
2320 return false;
2321
2322 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002323 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2324 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002325 return true;
2326 }
2327
2328 return false;
2329}
2330
Johan Hedberg92da6092013-03-15 17:06:55 -05002331static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2332{
2333 BT_DBG("status 0x%02x", status);
2334
2335 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2336}
2337
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002338static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002339 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002340{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002341 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002342 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002343 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002344 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 -05002345 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002346 int err, found;
2347
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002348 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002349
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002350 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002351
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002352 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002353 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002354 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002355 goto unlock;
2356 }
2357
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002358 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002359 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002360
Johan Hedberg24b78d02012-02-23 23:24:30 +02002361 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002362 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002363 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002364 goto unlock;
2365 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002366
Johan Hedberg9246a862012-02-23 21:33:16 +02002367 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002368 }
2369
2370 found = 0;
2371
Johan Hedberg056341c2013-01-27 00:31:30 +02002372 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002373 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2374 continue;
2375
2376 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002377 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002378 found++;
2379 }
2380
2381 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002382 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002383 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002384 goto unlock;
2385 }
2386
Johan Hedberg9246a862012-02-23 21:33:16 +02002387update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002388 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002389
Johan Hedberg890ea892013-03-15 17:06:52 -05002390 update_class(&req);
2391 update_eir(&req);
2392
Johan Hedberg92da6092013-03-15 17:06:55 -05002393 err = hci_req_run(&req, remove_uuid_complete);
2394 if (err < 0) {
2395 if (err != -ENODATA)
2396 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002397
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002398 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002399 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002400 goto unlock;
2401 }
2402
2403 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002404 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002405 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002406 goto unlock;
2407 }
2408
2409 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002410
2411unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002412 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002413 return err;
2414}
2415
Johan Hedberg92da6092013-03-15 17:06:55 -05002416static void set_class_complete(struct hci_dev *hdev, u8 status)
2417{
2418 BT_DBG("status 0x%02x", status);
2419
2420 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2421}
2422
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002423static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002424 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002425{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002426 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002427 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002428 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002429 int err;
2430
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002431 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002432
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002433 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002434 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2435 MGMT_STATUS_NOT_SUPPORTED);
2436
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002437 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002438
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002439 if (pending_eir_or_class(hdev)) {
2440 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2441 MGMT_STATUS_BUSY);
2442 goto unlock;
2443 }
2444
2445 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2446 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2447 MGMT_STATUS_INVALID_PARAMS);
2448 goto unlock;
2449 }
2450
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002451 hdev->major_class = cp->major;
2452 hdev->minor_class = cp->minor;
2453
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002454 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002455 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002456 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002457 goto unlock;
2458 }
2459
Johan Hedberg890ea892013-03-15 17:06:52 -05002460 hci_req_init(&req, hdev);
2461
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002462 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002463 hci_dev_unlock(hdev);
2464 cancel_delayed_work_sync(&hdev->service_cache);
2465 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002466 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002467 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002468
Johan Hedberg890ea892013-03-15 17:06:52 -05002469 update_class(&req);
2470
Johan Hedberg92da6092013-03-15 17:06:55 -05002471 err = hci_req_run(&req, set_class_complete);
2472 if (err < 0) {
2473 if (err != -ENODATA)
2474 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002475
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002476 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002477 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002478 goto unlock;
2479 }
2480
2481 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002482 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002483 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002484 goto unlock;
2485 }
2486
2487 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002488
Johan Hedbergb5235a62012-02-21 14:32:24 +02002489unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002490 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002491 return err;
2492}
2493
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002494static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002495 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002496{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002497 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002498 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2499 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002500 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002501 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002502 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002503
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002504 BT_DBG("request for %s", hdev->name);
2505
2506 if (!lmp_bredr_capable(hdev))
2507 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2508 MGMT_STATUS_NOT_SUPPORTED);
2509
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002510 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002511 if (key_count > max_key_count) {
2512 BT_ERR("load_link_keys: too big key_count value %u",
2513 key_count);
2514 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2515 MGMT_STATUS_INVALID_PARAMS);
2516 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002517
Johan Hedberg86742e12011-11-07 23:13:38 +02002518 expected_len = sizeof(*cp) + key_count *
2519 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002520 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002521 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002522 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002523 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002524 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002525 }
2526
Johan Hedberg4ae14302013-01-20 14:27:13 +02002527 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2528 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2529 MGMT_STATUS_INVALID_PARAMS);
2530
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002531 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002532 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002533
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002534 for (i = 0; i < key_count; i++) {
2535 struct mgmt_link_key_info *key = &cp->keys[i];
2536
Marcel Holtmann8e991132014-01-10 02:07:25 -08002537 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002538 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2539 MGMT_STATUS_INVALID_PARAMS);
2540 }
2541
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002542 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002543
2544 hci_link_keys_clear(hdev);
2545
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002546 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002547 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2548 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002549 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002550 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2551 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002552
2553 if (changed)
2554 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002555
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002556 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002557 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002558
Johan Hedberg58e92932014-06-24 14:00:26 +03002559 /* Always ignore debug keys and require a new pairing if
2560 * the user wants to use them.
2561 */
2562 if (key->type == HCI_LK_DEBUG_COMBINATION)
2563 continue;
2564
Johan Hedberg7652ff62014-06-24 13:15:49 +03002565 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2566 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002567 }
2568
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002569 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002570
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002571 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002572
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002573 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002574}
2575
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002576static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002577 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002578{
2579 struct mgmt_ev_device_unpaired ev;
2580
2581 bacpy(&ev.addr.bdaddr, bdaddr);
2582 ev.addr.type = addr_type;
2583
2584 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002585 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002586}
2587
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002588static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002589 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002590{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002591 struct mgmt_cp_unpair_device *cp = data;
2592 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002593 struct hci_cp_disconnect dc;
2594 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002595 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002596 int err;
2597
Johan Hedberga8a1d192011-11-10 15:54:38 +02002598 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002599 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2600 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002601
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002602 if (!bdaddr_type_is_valid(cp->addr.type))
2603 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2604 MGMT_STATUS_INVALID_PARAMS,
2605 &rp, sizeof(rp));
2606
Johan Hedberg118da702013-01-20 14:27:20 +02002607 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2608 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2609 MGMT_STATUS_INVALID_PARAMS,
2610 &rp, sizeof(rp));
2611
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002612 hci_dev_lock(hdev);
2613
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002614 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002615 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002616 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002617 goto unlock;
2618 }
2619
Johan Hedberge0b2b272014-02-18 17:14:31 +02002620 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002621 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002622 } else {
2623 u8 addr_type;
2624
2625 if (cp->addr.type == BDADDR_LE_PUBLIC)
2626 addr_type = ADDR_LE_DEV_PUBLIC;
2627 else
2628 addr_type = ADDR_LE_DEV_RANDOM;
2629
Johan Hedberga7ec7332014-02-18 17:14:35 +02002630 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2631
Andre Guedesa9b0a042014-02-26 20:21:52 -03002632 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2633
Johan Hedberge0b2b272014-02-18 17:14:31 +02002634 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2635 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002636
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002637 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002638 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002639 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002640 goto unlock;
2641 }
2642
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002643 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002644 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002645 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002646 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002647 else
2648 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002649 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002650 } else {
2651 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002652 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002653
Johan Hedberga8a1d192011-11-10 15:54:38 +02002654 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002655 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002656 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002657 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002658 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002659 }
2660
Johan Hedberg124f6e32012-02-09 13:50:12 +02002661 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002662 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002663 if (!cmd) {
2664 err = -ENOMEM;
2665 goto unlock;
2666 }
2667
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002668 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002669 dc.reason = 0x13; /* Remote User Terminated Connection */
2670 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2671 if (err < 0)
2672 mgmt_pending_remove(cmd);
2673
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002674unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002675 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002676 return err;
2677}
2678
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002679static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002680 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002681{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002682 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002683 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002684 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002685 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002686 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002687 int err;
2688
2689 BT_DBG("");
2690
Johan Hedberg06a63b12013-01-20 14:27:21 +02002691 memset(&rp, 0, sizeof(rp));
2692 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2693 rp.addr.type = cp->addr.type;
2694
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002695 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002696 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2697 MGMT_STATUS_INVALID_PARAMS,
2698 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002699
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002700 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002701
2702 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002703 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2704 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002705 goto failed;
2706 }
2707
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002708 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002709 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2710 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002711 goto failed;
2712 }
2713
Andre Guedes591f47f2012-04-24 21:02:49 -03002714 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002715 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2716 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002717 else
2718 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002719
Vishal Agarwalf9607272012-06-13 05:32:43 +05302720 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002721 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2722 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002723 goto failed;
2724 }
2725
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002726 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002727 if (!cmd) {
2728 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002729 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002730 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002731
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002732 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002733 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002734
2735 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2736 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002737 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002738
2739failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002740 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002741 return err;
2742}
2743
Andre Guedes57c14772012-04-24 21:02:50 -03002744static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002745{
2746 switch (link_type) {
2747 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002748 switch (addr_type) {
2749 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002750 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002751
Johan Hedberg48264f02011-11-09 13:58:58 +02002752 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002753 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002754 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002755 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002756
Johan Hedberg4c659c32011-11-07 23:13:39 +02002757 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002758 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002759 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002760 }
2761}
2762
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002763static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2764 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002765{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002766 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002767 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002768 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002769 int err;
2770 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002771
2772 BT_DBG("");
2773
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002774 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002775
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002776 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002777 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002778 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002779 goto unlock;
2780 }
2781
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002782 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002783 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2784 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002785 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002786 }
2787
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002788 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002789 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002790 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002791 err = -ENOMEM;
2792 goto unlock;
2793 }
2794
Johan Hedberg2784eb42011-01-21 13:56:35 +02002795 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002796 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002797 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2798 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002799 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002800 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002801 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002802 continue;
2803 i++;
2804 }
2805
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002806 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002807
Johan Hedberg4c659c32011-11-07 23:13:39 +02002808 /* Recalculate length in case of filtered SCO connections, etc */
2809 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002810
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002811 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002812 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002813
Johan Hedberga38528f2011-01-22 06:46:43 +02002814 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002815
2816unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002817 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002818 return err;
2819}
2820
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002821static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002822 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002823{
2824 struct pending_cmd *cmd;
2825 int err;
2826
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002827 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002828 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002829 if (!cmd)
2830 return -ENOMEM;
2831
Johan Hedbergd8457692012-02-17 14:24:57 +02002832 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002833 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002834 if (err < 0)
2835 mgmt_pending_remove(cmd);
2836
2837 return err;
2838}
2839
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002840static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002841 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002842{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002843 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002844 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002845 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002846 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002847 int err;
2848
2849 BT_DBG("");
2850
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002851 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002852
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002853 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002854 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002855 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002856 goto failed;
2857 }
2858
Johan Hedbergd8457692012-02-17 14:24:57 +02002859 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002860 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002861 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002862 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002863 goto failed;
2864 }
2865
2866 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002867 struct mgmt_cp_pin_code_neg_reply ncp;
2868
2869 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002870
2871 BT_ERR("PIN code is not 16 bytes long");
2872
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002873 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002874 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002875 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002876 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002877
2878 goto failed;
2879 }
2880
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002881 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002882 if (!cmd) {
2883 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002884 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002885 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002886
Johan Hedbergd8457692012-02-17 14:24:57 +02002887 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002888 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002889 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002890
2891 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2892 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002893 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002894
2895failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002896 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002897 return err;
2898}
2899
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002900static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2901 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002902{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002903 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002904
2905 BT_DBG("");
2906
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002907 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2908 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2909 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2910
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002911 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002912
2913 hdev->io_capability = cp->io_capability;
2914
2915 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002916 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002917
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002918 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002919
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002920 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2921 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002922}
2923
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002924static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002925{
2926 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002927 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002928
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002929 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002930 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2931 continue;
2932
Johan Hedberge9a416b2011-02-19 12:05:56 -03002933 if (cmd->user_data != conn)
2934 continue;
2935
2936 return cmd;
2937 }
2938
2939 return NULL;
2940}
2941
2942static void pairing_complete(struct pending_cmd *cmd, u8 status)
2943{
2944 struct mgmt_rp_pair_device rp;
2945 struct hci_conn *conn = cmd->user_data;
2946
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02002947 bacpy(&rp.addr.bdaddr, &conn->dst);
2948 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002949
Johan Hedbergaee9b212012-02-18 15:07:59 +02002950 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002951 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002952
2953 /* So we don't get further callbacks for this connection */
2954 conn->connect_cfm_cb = NULL;
2955 conn->security_cfm_cb = NULL;
2956 conn->disconn_cfm_cb = NULL;
2957
David Herrmann76a68ba2013-04-06 20:28:37 +02002958 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002959
Johan Hedberga664b5b2011-02-19 12:06:02 -03002960 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002961}
2962
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002963void mgmt_smp_complete(struct hci_conn *conn, bool complete)
2964{
2965 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
2966 struct pending_cmd *cmd;
2967
2968 cmd = find_pairing(conn);
2969 if (cmd)
2970 pairing_complete(cmd, status);
2971}
2972
Johan Hedberge9a416b2011-02-19 12:05:56 -03002973static void pairing_complete_cb(struct hci_conn *conn, u8 status)
2974{
2975 struct pending_cmd *cmd;
2976
2977 BT_DBG("status %u", status);
2978
Johan Hedberg56e5cb82011-11-08 20:40:16 +02002979 cmd = find_pairing(conn);
2980 if (!cmd)
2981 BT_DBG("Unable to find a pending command");
2982 else
Johan Hedberge2113262012-02-18 15:20:03 +02002983 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002984}
2985
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002986static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05302987{
2988 struct pending_cmd *cmd;
2989
2990 BT_DBG("status %u", status);
2991
2992 if (!status)
2993 return;
2994
2995 cmd = find_pairing(conn);
2996 if (!cmd)
2997 BT_DBG("Unable to find a pending command");
2998 else
2999 pairing_complete(cmd, mgmt_status(status));
3000}
3001
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003002static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003003 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003004{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003005 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003006 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003007 struct pending_cmd *cmd;
3008 u8 sec_level, auth_type;
3009 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003010 int err;
3011
3012 BT_DBG("");
3013
Szymon Jancf950a30e2013-01-18 12:48:07 +01003014 memset(&rp, 0, sizeof(rp));
3015 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3016 rp.addr.type = cp->addr.type;
3017
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003018 if (!bdaddr_type_is_valid(cp->addr.type))
3019 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3020 MGMT_STATUS_INVALID_PARAMS,
3021 &rp, sizeof(rp));
3022
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003023 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3024 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3025 MGMT_STATUS_INVALID_PARAMS,
3026 &rp, sizeof(rp));
3027
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003028 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003029
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003030 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003031 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3032 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003033 goto unlock;
3034 }
3035
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003036 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003037 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003038
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003039 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003040 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3041 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003042 } else {
3043 u8 addr_type;
3044
3045 /* Convert from L2CAP channel address type to HCI address type
3046 */
3047 if (cp->addr.type == BDADDR_LE_PUBLIC)
3048 addr_type = ADDR_LE_DEV_PUBLIC;
3049 else
3050 addr_type = ADDR_LE_DEV_RANDOM;
3051
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003052 /* When pairing a new device, it is expected to remember
3053 * this device for future connections. Adding the connection
3054 * parameter information ahead of time allows tracking
3055 * of the slave preferred values and will speed up any
3056 * further connection establishment.
3057 *
3058 * If connection parameters already exist, then they
3059 * will be kept and this function does nothing.
3060 */
3061 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3062
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003063 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03003064 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003065 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003066
Ville Tervo30e76272011-02-22 16:10:53 -03003067 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003068 int status;
3069
3070 if (PTR_ERR(conn) == -EBUSY)
3071 status = MGMT_STATUS_BUSY;
3072 else
3073 status = MGMT_STATUS_CONNECT_FAILED;
3074
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003075 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003076 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003077 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003078 goto unlock;
3079 }
3080
3081 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003082 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003083 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003084 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003085 goto unlock;
3086 }
3087
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003088 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003089 if (!cmd) {
3090 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003091 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003092 goto unlock;
3093 }
3094
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003095 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003096 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003097 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003098 conn->security_cfm_cb = pairing_complete_cb;
3099 conn->disconn_cfm_cb = pairing_complete_cb;
3100 } else {
3101 conn->connect_cfm_cb = le_pairing_complete_cb;
3102 conn->security_cfm_cb = le_pairing_complete_cb;
3103 conn->disconn_cfm_cb = le_pairing_complete_cb;
3104 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003105
Johan Hedberge9a416b2011-02-19 12:05:56 -03003106 conn->io_capability = cp->io_cap;
3107 cmd->user_data = conn;
3108
3109 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003110 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003111 pairing_complete(cmd, 0);
3112
3113 err = 0;
3114
3115unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003116 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003117 return err;
3118}
3119
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003120static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3121 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003122{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003123 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003124 struct pending_cmd *cmd;
3125 struct hci_conn *conn;
3126 int err;
3127
3128 BT_DBG("");
3129
Johan Hedberg28424702012-02-02 04:02:29 +02003130 hci_dev_lock(hdev);
3131
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003132 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003133 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003134 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003135 goto unlock;
3136 }
3137
Johan Hedberg28424702012-02-02 04:02:29 +02003138 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3139 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003140 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003141 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003142 goto unlock;
3143 }
3144
3145 conn = cmd->user_data;
3146
3147 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003148 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003149 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003150 goto unlock;
3151 }
3152
3153 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3154
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003155 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003156 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003157unlock:
3158 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003159 return err;
3160}
3161
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003162static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003163 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003164 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003165{
Johan Hedberga5c29682011-02-19 12:05:57 -03003166 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003167 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003168 int err;
3169
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003170 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003171
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003172 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003173 err = cmd_complete(sk, hdev->id, mgmt_op,
3174 MGMT_STATUS_NOT_POWERED, addr,
3175 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003176 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003177 }
3178
Johan Hedberg1707c602013-03-15 17:07:15 -05003179 if (addr->type == BDADDR_BREDR)
3180 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003181 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003182 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003183
Johan Hedberg272d90d2012-02-09 15:26:12 +02003184 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003185 err = cmd_complete(sk, hdev->id, mgmt_op,
3186 MGMT_STATUS_NOT_CONNECTED, addr,
3187 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003188 goto done;
3189 }
3190
Johan Hedberg1707c602013-03-15 17:07:15 -05003191 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003192 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003193 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003194 err = cmd_complete(sk, hdev->id, mgmt_op,
3195 MGMT_STATUS_SUCCESS, addr,
3196 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003197 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003198 err = cmd_complete(sk, hdev->id, mgmt_op,
3199 MGMT_STATUS_FAILED, addr,
3200 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003201
Brian Gix47c15e22011-11-16 13:53:14 -08003202 goto done;
3203 }
3204
Johan Hedberg1707c602013-03-15 17:07:15 -05003205 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003206 if (!cmd) {
3207 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003208 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003209 }
3210
Brian Gix0df4c182011-11-16 13:53:13 -08003211 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003212 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3213 struct hci_cp_user_passkey_reply cp;
3214
Johan Hedberg1707c602013-03-15 17:07:15 -05003215 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003216 cp.passkey = passkey;
3217 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3218 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003219 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3220 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003221
Johan Hedberga664b5b2011-02-19 12:06:02 -03003222 if (err < 0)
3223 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003224
Brian Gix0df4c182011-11-16 13:53:13 -08003225done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003226 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003227 return err;
3228}
3229
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303230static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3231 void *data, u16 len)
3232{
3233 struct mgmt_cp_pin_code_neg_reply *cp = data;
3234
3235 BT_DBG("");
3236
Johan Hedberg1707c602013-03-15 17:07:15 -05003237 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303238 MGMT_OP_PIN_CODE_NEG_REPLY,
3239 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3240}
3241
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003242static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3243 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003244{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003245 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003246
3247 BT_DBG("");
3248
3249 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003250 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003251 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003252
Johan Hedberg1707c602013-03-15 17:07:15 -05003253 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003254 MGMT_OP_USER_CONFIRM_REPLY,
3255 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003256}
3257
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003258static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003259 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003260{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003261 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003262
3263 BT_DBG("");
3264
Johan Hedberg1707c602013-03-15 17:07:15 -05003265 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003266 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3267 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003268}
3269
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003270static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3271 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003272{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003273 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003274
3275 BT_DBG("");
3276
Johan Hedberg1707c602013-03-15 17:07:15 -05003277 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003278 MGMT_OP_USER_PASSKEY_REPLY,
3279 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003280}
3281
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003282static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003283 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003284{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003285 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003286
3287 BT_DBG("");
3288
Johan Hedberg1707c602013-03-15 17:07:15 -05003289 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003290 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3291 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003292}
3293
Johan Hedberg13928972013-03-15 17:07:00 -05003294static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003295{
Johan Hedberg13928972013-03-15 17:07:00 -05003296 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003297 struct hci_cp_write_local_name cp;
3298
Johan Hedberg13928972013-03-15 17:07:00 -05003299 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003300
Johan Hedberg890ea892013-03-15 17:06:52 -05003301 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003302}
3303
Johan Hedberg13928972013-03-15 17:07:00 -05003304static void set_name_complete(struct hci_dev *hdev, u8 status)
3305{
3306 struct mgmt_cp_set_local_name *cp;
3307 struct pending_cmd *cmd;
3308
3309 BT_DBG("status 0x%02x", status);
3310
3311 hci_dev_lock(hdev);
3312
3313 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3314 if (!cmd)
3315 goto unlock;
3316
3317 cp = cmd->param;
3318
3319 if (status)
3320 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3321 mgmt_status(status));
3322 else
3323 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3324 cp, sizeof(*cp));
3325
3326 mgmt_pending_remove(cmd);
3327
3328unlock:
3329 hci_dev_unlock(hdev);
3330}
3331
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003332static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003333 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003334{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003335 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003336 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003337 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003338 int err;
3339
3340 BT_DBG("");
3341
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003342 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003343
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003344 /* If the old values are the same as the new ones just return a
3345 * direct command complete event.
3346 */
3347 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3348 !memcmp(hdev->short_name, cp->short_name,
3349 sizeof(hdev->short_name))) {
3350 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3351 data, len);
3352 goto failed;
3353 }
3354
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003355 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003356
Johan Hedbergb5235a62012-02-21 14:32:24 +02003357 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003358 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003359
3360 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003361 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003362 if (err < 0)
3363 goto failed;
3364
3365 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003366 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003367
Johan Hedbergb5235a62012-02-21 14:32:24 +02003368 goto failed;
3369 }
3370
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003371 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003372 if (!cmd) {
3373 err = -ENOMEM;
3374 goto failed;
3375 }
3376
Johan Hedberg13928972013-03-15 17:07:00 -05003377 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3378
Johan Hedberg890ea892013-03-15 17:06:52 -05003379 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003380
3381 if (lmp_bredr_capable(hdev)) {
3382 update_name(&req);
3383 update_eir(&req);
3384 }
3385
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003386 /* The name is stored in the scan response data and so
3387 * no need to udpate the advertising data here.
3388 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003389 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003390 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003391
Johan Hedberg13928972013-03-15 17:07:00 -05003392 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003393 if (err < 0)
3394 mgmt_pending_remove(cmd);
3395
3396failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003397 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003398 return err;
3399}
3400
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003401static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003402 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003403{
Szymon Jancc35938b2011-03-22 13:12:21 +01003404 struct pending_cmd *cmd;
3405 int err;
3406
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003407 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003408
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003409 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003410
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003411 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003412 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003413 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003414 goto unlock;
3415 }
3416
Andre Guedes9a1a1992012-07-24 15:03:48 -03003417 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003418 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003419 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003420 goto unlock;
3421 }
3422
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003423 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003424 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003425 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003426 goto unlock;
3427 }
3428
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003429 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003430 if (!cmd) {
3431 err = -ENOMEM;
3432 goto unlock;
3433 }
3434
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003435 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3436 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3437 0, NULL);
3438 else
3439 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3440
Szymon Jancc35938b2011-03-22 13:12:21 +01003441 if (err < 0)
3442 mgmt_pending_remove(cmd);
3443
3444unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003445 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003446 return err;
3447}
3448
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003449static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003450 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003451{
Szymon Janc2763eda2011-03-22 13:12:22 +01003452 int err;
3453
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003454 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003455
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003456 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003457
Marcel Holtmannec109112014-01-10 02:07:30 -08003458 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3459 struct mgmt_cp_add_remote_oob_data *cp = data;
3460 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003461
Marcel Holtmannec109112014-01-10 02:07:30 -08003462 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3463 cp->hash, cp->randomizer);
3464 if (err < 0)
3465 status = MGMT_STATUS_FAILED;
3466 else
3467 status = MGMT_STATUS_SUCCESS;
3468
3469 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3470 status, &cp->addr, sizeof(cp->addr));
3471 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3472 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3473 u8 status;
3474
3475 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3476 cp->hash192,
3477 cp->randomizer192,
3478 cp->hash256,
3479 cp->randomizer256);
3480 if (err < 0)
3481 status = MGMT_STATUS_FAILED;
3482 else
3483 status = MGMT_STATUS_SUCCESS;
3484
3485 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3486 status, &cp->addr, sizeof(cp->addr));
3487 } else {
3488 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3489 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3490 MGMT_STATUS_INVALID_PARAMS);
3491 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003492
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003493 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003494 return err;
3495}
3496
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003497static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003498 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003499{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003500 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003501 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003502 int err;
3503
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003504 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003505
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003506 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003507
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003508 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003509 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003510 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003511 else
Szymon Janca6785be2012-12-13 15:11:21 +01003512 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003513
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003514 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003515 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003516
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003517 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003518 return err;
3519}
3520
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003521static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3522{
3523 struct pending_cmd *cmd;
3524 u8 type;
3525 int err;
3526
3527 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3528
3529 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3530 if (!cmd)
3531 return -ENOENT;
3532
3533 type = hdev->discovery.type;
3534
3535 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3536 &type, sizeof(type));
3537 mgmt_pending_remove(cmd);
3538
3539 return err;
3540}
3541
Andre Guedes7c307722013-04-30 15:29:28 -03003542static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3543{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003544 unsigned long timeout = 0;
3545
Andre Guedes7c307722013-04-30 15:29:28 -03003546 BT_DBG("status %d", status);
3547
3548 if (status) {
3549 hci_dev_lock(hdev);
3550 mgmt_start_discovery_failed(hdev, status);
3551 hci_dev_unlock(hdev);
3552 return;
3553 }
3554
3555 hci_dev_lock(hdev);
3556 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3557 hci_dev_unlock(hdev);
3558
3559 switch (hdev->discovery.type) {
3560 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003561 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003562 break;
3563
3564 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003565 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003566 break;
3567
3568 case DISCOV_TYPE_BREDR:
3569 break;
3570
3571 default:
3572 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3573 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003574
3575 if (!timeout)
3576 return;
3577
3578 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003579}
3580
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003581static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003582 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003583{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003584 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003585 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003586 struct hci_cp_le_set_scan_param param_cp;
3587 struct hci_cp_le_set_scan_enable enable_cp;
3588 struct hci_cp_inquiry inq_cp;
3589 struct hci_request req;
3590 /* General inquiry access code (GIAC) */
3591 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003592 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003593 int err;
3594
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003595 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003596
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003597 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003598
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003599 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003600 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003601 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003602 goto failed;
3603 }
3604
Andre Guedes642be6c2012-03-21 00:03:37 -03003605 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3606 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3607 MGMT_STATUS_BUSY);
3608 goto failed;
3609 }
3610
Johan Hedbergff9ef572012-01-04 14:23:45 +02003611 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003612 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003613 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003614 goto failed;
3615 }
3616
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003617 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003618 if (!cmd) {
3619 err = -ENOMEM;
3620 goto failed;
3621 }
3622
Andre Guedes4aab14e2012-02-17 20:39:36 -03003623 hdev->discovery.type = cp->type;
3624
Andre Guedes7c307722013-04-30 15:29:28 -03003625 hci_req_init(&req, hdev);
3626
Andre Guedes4aab14e2012-02-17 20:39:36 -03003627 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003628 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003629 status = mgmt_bredr_support(hdev);
3630 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003631 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003632 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003633 mgmt_pending_remove(cmd);
3634 goto failed;
3635 }
3636
Andre Guedes7c307722013-04-30 15:29:28 -03003637 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3638 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3639 MGMT_STATUS_BUSY);
3640 mgmt_pending_remove(cmd);
3641 goto failed;
3642 }
3643
3644 hci_inquiry_cache_flush(hdev);
3645
3646 memset(&inq_cp, 0, sizeof(inq_cp));
3647 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003648 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003649 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003650 break;
3651
3652 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003653 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003654 status = mgmt_le_support(hdev);
3655 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003656 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003657 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003658 mgmt_pending_remove(cmd);
3659 goto failed;
3660 }
3661
Andre Guedes7c307722013-04-30 15:29:28 -03003662 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003663 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003664 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3665 MGMT_STATUS_NOT_SUPPORTED);
3666 mgmt_pending_remove(cmd);
3667 goto failed;
3668 }
3669
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003670 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003671 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3672 MGMT_STATUS_REJECTED);
3673 mgmt_pending_remove(cmd);
3674 goto failed;
3675 }
3676
Andre Guedesc54c3862014-02-26 20:21:50 -03003677 /* If controller is scanning, it means the background scanning
3678 * is running. Thus, we should temporarily stop it in order to
3679 * set the discovery scanning parameters.
3680 */
3681 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3682 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003683
3684 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003685
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003686 /* All active scans will be done with either a resolvable
3687 * private address (when privacy feature has been enabled)
3688 * or unresolvable private address.
3689 */
3690 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003691 if (err < 0) {
3692 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3693 MGMT_STATUS_FAILED);
3694 mgmt_pending_remove(cmd);
3695 goto failed;
3696 }
3697
Andre Guedes7c307722013-04-30 15:29:28 -03003698 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003699 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3700 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003701 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003702 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3703 &param_cp);
3704
3705 memset(&enable_cp, 0, sizeof(enable_cp));
3706 enable_cp.enable = LE_SCAN_ENABLE;
3707 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3708 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3709 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003710 break;
3711
Andre Guedesf39799f2012-02-17 20:39:35 -03003712 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003713 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3714 MGMT_STATUS_INVALID_PARAMS);
3715 mgmt_pending_remove(cmd);
3716 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003717 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003718
Andre Guedes7c307722013-04-30 15:29:28 -03003719 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003720 if (err < 0)
3721 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003722 else
3723 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003724
3725failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003726 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003727 return err;
3728}
3729
Andre Guedes1183fdc2013-04-30 15:29:35 -03003730static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3731{
3732 struct pending_cmd *cmd;
3733 int err;
3734
3735 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3736 if (!cmd)
3737 return -ENOENT;
3738
3739 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3740 &hdev->discovery.type, sizeof(hdev->discovery.type));
3741 mgmt_pending_remove(cmd);
3742
3743 return err;
3744}
3745
Andre Guedes0e05bba2013-04-30 15:29:33 -03003746static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3747{
3748 BT_DBG("status %d", status);
3749
3750 hci_dev_lock(hdev);
3751
3752 if (status) {
3753 mgmt_stop_discovery_failed(hdev, status);
3754 goto unlock;
3755 }
3756
3757 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3758
3759unlock:
3760 hci_dev_unlock(hdev);
3761}
3762
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003763static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003764 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003765{
Johan Hedbergd9306502012-02-20 23:25:18 +02003766 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003767 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003768 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003769 int err;
3770
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003771 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003772
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003773 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003774
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003775 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003776 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003777 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3778 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003779 goto unlock;
3780 }
3781
3782 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003783 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003784 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3785 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003786 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003787 }
3788
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003789 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003790 if (!cmd) {
3791 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003792 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003793 }
3794
Andre Guedes0e05bba2013-04-30 15:29:33 -03003795 hci_req_init(&req, hdev);
3796
Johan Hedberg21a60d32014-06-10 14:05:58 +03003797 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003798
Johan Hedberg21a60d32014-06-10 14:05:58 +03003799 err = hci_req_run(&req, stop_discovery_complete);
3800 if (!err) {
3801 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003802 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003803 }
3804
Johan Hedberg21a60d32014-06-10 14:05:58 +03003805 mgmt_pending_remove(cmd);
3806
3807 /* If no HCI commands were sent we're done */
3808 if (err == -ENODATA) {
3809 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3810 &mgmt_cp->type, sizeof(mgmt_cp->type));
3811 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3812 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003813
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003814unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003815 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003816 return err;
3817}
3818
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003819static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003820 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003821{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003822 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003823 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003824 int err;
3825
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003826 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003827
Johan Hedberg561aafb2012-01-04 13:31:59 +02003828 hci_dev_lock(hdev);
3829
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003830 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003831 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3832 MGMT_STATUS_FAILED, &cp->addr,
3833 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003834 goto failed;
3835 }
3836
Johan Hedberga198e7b2012-02-17 14:27:06 +02003837 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003838 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003839 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3840 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3841 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003842 goto failed;
3843 }
3844
3845 if (cp->name_known) {
3846 e->name_state = NAME_KNOWN;
3847 list_del(&e->list);
3848 } else {
3849 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003850 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003851 }
3852
Johan Hedberge3846622013-01-09 15:29:33 +02003853 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3854 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003855
3856failed:
3857 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003858 return err;
3859}
3860
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003861static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003862 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003863{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003864 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003865 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003866 int err;
3867
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003868 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003869
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003870 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003871 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3872 MGMT_STATUS_INVALID_PARAMS,
3873 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003874
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003875 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003876
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003877 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003878 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003879 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003880 goto done;
3881 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003882
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003883 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3884 sk);
3885 status = MGMT_STATUS_SUCCESS;
3886
3887done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003888 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003889 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003890
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003891 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003892
3893 return err;
3894}
3895
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003896static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003897 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003898{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003899 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003900 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003901 int err;
3902
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003903 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003904
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003905 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003906 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3907 MGMT_STATUS_INVALID_PARAMS,
3908 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003909
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003910 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003911
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003912 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003913 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003914 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003915 goto done;
3916 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003917
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003918 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3919 sk);
3920 status = MGMT_STATUS_SUCCESS;
3921
3922done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003923 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003924 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003925
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003926 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003927
3928 return err;
3929}
3930
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003931static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3932 u16 len)
3933{
3934 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003935 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003936 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003937 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003938
3939 BT_DBG("%s", hdev->name);
3940
Szymon Jancc72d4b82012-03-16 16:02:57 +01003941 source = __le16_to_cpu(cp->source);
3942
3943 if (source > 0x0002)
3944 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3945 MGMT_STATUS_INVALID_PARAMS);
3946
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003947 hci_dev_lock(hdev);
3948
Szymon Jancc72d4b82012-03-16 16:02:57 +01003949 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003950 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3951 hdev->devid_product = __le16_to_cpu(cp->product);
3952 hdev->devid_version = __le16_to_cpu(cp->version);
3953
3954 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3955
Johan Hedberg890ea892013-03-15 17:06:52 -05003956 hci_req_init(&req, hdev);
3957 update_eir(&req);
3958 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003959
3960 hci_dev_unlock(hdev);
3961
3962 return err;
3963}
3964
Johan Hedberg4375f102013-09-25 13:26:10 +03003965static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3966{
3967 struct cmd_lookup match = { NULL, hdev };
3968
3969 if (status) {
3970 u8 mgmt_err = mgmt_status(status);
3971
3972 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3973 cmd_status_rsp, &mgmt_err);
3974 return;
3975 }
3976
3977 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3978 &match);
3979
3980 new_settings(hdev, match.sk);
3981
3982 if (match.sk)
3983 sock_put(match.sk);
3984}
3985
Marcel Holtmann21b51872013-10-10 09:47:53 -07003986static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3987 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003988{
3989 struct mgmt_mode *cp = data;
3990 struct pending_cmd *cmd;
3991 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003992 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003993 int err;
3994
3995 BT_DBG("request for %s", hdev->name);
3996
Johan Hedberge6fe7982013-10-02 15:45:22 +03003997 status = mgmt_le_support(hdev);
3998 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003999 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004000 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004001
4002 if (cp->val != 0x00 && cp->val != 0x01)
4003 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4004 MGMT_STATUS_INVALID_PARAMS);
4005
4006 hci_dev_lock(hdev);
4007
4008 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004009 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004010
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004011 /* The following conditions are ones which mean that we should
4012 * not do any HCI communication but directly send a mgmt
4013 * response to user space (after toggling the flag if
4014 * necessary).
4015 */
4016 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07004017 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004018 bool changed = false;
4019
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004020 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4021 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004022 changed = true;
4023 }
4024
4025 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4026 if (err < 0)
4027 goto unlock;
4028
4029 if (changed)
4030 err = new_settings(hdev, sk);
4031
4032 goto unlock;
4033 }
4034
4035 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4036 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4037 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4038 MGMT_STATUS_BUSY);
4039 goto unlock;
4040 }
4041
4042 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4043 if (!cmd) {
4044 err = -ENOMEM;
4045 goto unlock;
4046 }
4047
4048 hci_req_init(&req, hdev);
4049
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004050 if (val)
4051 enable_advertising(&req);
4052 else
4053 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004054
4055 err = hci_req_run(&req, set_advertising_complete);
4056 if (err < 0)
4057 mgmt_pending_remove(cmd);
4058
4059unlock:
4060 hci_dev_unlock(hdev);
4061 return err;
4062}
4063
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004064static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4065 void *data, u16 len)
4066{
4067 struct mgmt_cp_set_static_address *cp = data;
4068 int err;
4069
4070 BT_DBG("%s", hdev->name);
4071
Marcel Holtmann62af4442013-10-02 22:10:32 -07004072 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004073 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004074 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004075
4076 if (hdev_is_powered(hdev))
4077 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4078 MGMT_STATUS_REJECTED);
4079
4080 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4081 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4082 return cmd_status(sk, hdev->id,
4083 MGMT_OP_SET_STATIC_ADDRESS,
4084 MGMT_STATUS_INVALID_PARAMS);
4085
4086 /* Two most significant bits shall be set */
4087 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4088 return cmd_status(sk, hdev->id,
4089 MGMT_OP_SET_STATIC_ADDRESS,
4090 MGMT_STATUS_INVALID_PARAMS);
4091 }
4092
4093 hci_dev_lock(hdev);
4094
4095 bacpy(&hdev->static_addr, &cp->bdaddr);
4096
4097 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4098
4099 hci_dev_unlock(hdev);
4100
4101 return err;
4102}
4103
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004104static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4105 void *data, u16 len)
4106{
4107 struct mgmt_cp_set_scan_params *cp = data;
4108 __u16 interval, window;
4109 int err;
4110
4111 BT_DBG("%s", hdev->name);
4112
4113 if (!lmp_le_capable(hdev))
4114 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4115 MGMT_STATUS_NOT_SUPPORTED);
4116
4117 interval = __le16_to_cpu(cp->interval);
4118
4119 if (interval < 0x0004 || interval > 0x4000)
4120 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4121 MGMT_STATUS_INVALID_PARAMS);
4122
4123 window = __le16_to_cpu(cp->window);
4124
4125 if (window < 0x0004 || window > 0x4000)
4126 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4127 MGMT_STATUS_INVALID_PARAMS);
4128
Marcel Holtmann899e1072013-10-14 09:55:32 -07004129 if (window > interval)
4130 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4131 MGMT_STATUS_INVALID_PARAMS);
4132
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004133 hci_dev_lock(hdev);
4134
4135 hdev->le_scan_interval = interval;
4136 hdev->le_scan_window = window;
4137
4138 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4139
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004140 /* If background scan is running, restart it so new parameters are
4141 * loaded.
4142 */
4143 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4144 hdev->discovery.state == DISCOVERY_STOPPED) {
4145 struct hci_request req;
4146
4147 hci_req_init(&req, hdev);
4148
4149 hci_req_add_le_scan_disable(&req);
4150 hci_req_add_le_passive_scan(&req);
4151
4152 hci_req_run(&req, NULL);
4153 }
4154
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004155 hci_dev_unlock(hdev);
4156
4157 return err;
4158}
4159
Johan Hedberg33e38b32013-03-15 17:07:05 -05004160static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4161{
4162 struct pending_cmd *cmd;
4163
4164 BT_DBG("status 0x%02x", status);
4165
4166 hci_dev_lock(hdev);
4167
4168 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4169 if (!cmd)
4170 goto unlock;
4171
4172 if (status) {
4173 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4174 mgmt_status(status));
4175 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004176 struct mgmt_mode *cp = cmd->param;
4177
4178 if (cp->val)
4179 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4180 else
4181 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4182
Johan Hedberg33e38b32013-03-15 17:07:05 -05004183 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4184 new_settings(hdev, cmd->sk);
4185 }
4186
4187 mgmt_pending_remove(cmd);
4188
4189unlock:
4190 hci_dev_unlock(hdev);
4191}
4192
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004193static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004194 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004195{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004196 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004197 struct pending_cmd *cmd;
4198 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004199 int err;
4200
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004201 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004202
Johan Hedberg56f87902013-10-02 13:43:13 +03004203 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4204 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004205 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4206 MGMT_STATUS_NOT_SUPPORTED);
4207
Johan Hedberga7e80f22013-01-09 16:05:19 +02004208 if (cp->val != 0x00 && cp->val != 0x01)
4209 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4210 MGMT_STATUS_INVALID_PARAMS);
4211
Johan Hedberg5400c042012-02-21 16:40:33 +02004212 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004213 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004214 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004215
4216 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004217 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004218 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004219
4220 hci_dev_lock(hdev);
4221
Johan Hedberg05cbf292013-03-15 17:07:07 -05004222 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4223 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4224 MGMT_STATUS_BUSY);
4225 goto unlock;
4226 }
4227
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004228 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4229 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4230 hdev);
4231 goto unlock;
4232 }
4233
Johan Hedberg33e38b32013-03-15 17:07:05 -05004234 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4235 data, len);
4236 if (!cmd) {
4237 err = -ENOMEM;
4238 goto unlock;
4239 }
4240
4241 hci_req_init(&req, hdev);
4242
Johan Hedberg406d7802013-03-15 17:07:09 -05004243 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004244
4245 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004246 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004247 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004248 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004249 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004250 }
4251
Johan Hedberg33e38b32013-03-15 17:07:05 -05004252unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004253 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004254
Antti Julkuf6422ec2011-06-22 13:11:56 +03004255 return err;
4256}
4257
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004258static void set_bredr_scan(struct hci_request *req)
4259{
4260 struct hci_dev *hdev = req->hdev;
4261 u8 scan = 0;
4262
4263 /* Ensure that fast connectable is disabled. This function will
4264 * not do anything if the page scan parameters are already what
4265 * they should be.
4266 */
4267 write_fast_connectable(req, false);
4268
4269 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4270 scan |= SCAN_PAGE;
4271 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4272 scan |= SCAN_INQUIRY;
4273
4274 if (scan)
4275 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4276}
4277
Johan Hedberg0663ca22013-10-02 13:43:14 +03004278static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4279{
4280 struct pending_cmd *cmd;
4281
4282 BT_DBG("status 0x%02x", status);
4283
4284 hci_dev_lock(hdev);
4285
4286 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4287 if (!cmd)
4288 goto unlock;
4289
4290 if (status) {
4291 u8 mgmt_err = mgmt_status(status);
4292
4293 /* We need to restore the flag if related HCI commands
4294 * failed.
4295 */
4296 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4297
4298 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4299 } else {
4300 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4301 new_settings(hdev, cmd->sk);
4302 }
4303
4304 mgmt_pending_remove(cmd);
4305
4306unlock:
4307 hci_dev_unlock(hdev);
4308}
4309
4310static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4311{
4312 struct mgmt_mode *cp = data;
4313 struct pending_cmd *cmd;
4314 struct hci_request req;
4315 int err;
4316
4317 BT_DBG("request for %s", hdev->name);
4318
4319 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4320 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4321 MGMT_STATUS_NOT_SUPPORTED);
4322
4323 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4324 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4325 MGMT_STATUS_REJECTED);
4326
4327 if (cp->val != 0x00 && cp->val != 0x01)
4328 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4329 MGMT_STATUS_INVALID_PARAMS);
4330
4331 hci_dev_lock(hdev);
4332
4333 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4334 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4335 goto unlock;
4336 }
4337
4338 if (!hdev_is_powered(hdev)) {
4339 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004340 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4341 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4342 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4343 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4344 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4345 }
4346
4347 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4348
4349 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4350 if (err < 0)
4351 goto unlock;
4352
4353 err = new_settings(hdev, sk);
4354 goto unlock;
4355 }
4356
4357 /* Reject disabling when powered on */
4358 if (!cp->val) {
4359 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4360 MGMT_STATUS_REJECTED);
4361 goto unlock;
4362 }
4363
4364 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4365 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4366 MGMT_STATUS_BUSY);
4367 goto unlock;
4368 }
4369
4370 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4371 if (!cmd) {
4372 err = -ENOMEM;
4373 goto unlock;
4374 }
4375
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004376 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004377 * generates the correct flags.
4378 */
4379 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4380
4381 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004382
4383 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4384 set_bredr_scan(&req);
4385
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004386 /* Since only the advertising data flags will change, there
4387 * is no need to update the scan response data.
4388 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004389 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004390
Johan Hedberg0663ca22013-10-02 13:43:14 +03004391 err = hci_req_run(&req, set_bredr_complete);
4392 if (err < 0)
4393 mgmt_pending_remove(cmd);
4394
4395unlock:
4396 hci_dev_unlock(hdev);
4397 return err;
4398}
4399
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004400static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4401 void *data, u16 len)
4402{
4403 struct mgmt_mode *cp = data;
4404 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004405 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004406 int err;
4407
4408 BT_DBG("request for %s", hdev->name);
4409
4410 status = mgmt_bredr_support(hdev);
4411 if (status)
4412 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4413 status);
4414
Marcel Holtmann5afeac12014-01-10 02:07:27 -08004415 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004416 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004417 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4418 MGMT_STATUS_NOT_SUPPORTED);
4419
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004420 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004421 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4422 MGMT_STATUS_INVALID_PARAMS);
4423
4424 hci_dev_lock(hdev);
4425
4426 if (!hdev_is_powered(hdev)) {
4427 bool changed;
4428
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004429 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004430 changed = !test_and_set_bit(HCI_SC_ENABLED,
4431 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004432 if (cp->val == 0x02)
4433 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4434 else
4435 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4436 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004437 changed = test_and_clear_bit(HCI_SC_ENABLED,
4438 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004439 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4440 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004441
4442 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4443 if (err < 0)
4444 goto failed;
4445
4446 if (changed)
4447 err = new_settings(hdev, sk);
4448
4449 goto failed;
4450 }
4451
4452 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4453 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4454 MGMT_STATUS_BUSY);
4455 goto failed;
4456 }
4457
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004458 val = !!cp->val;
4459
4460 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4461 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004462 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4463 goto failed;
4464 }
4465
4466 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4467 if (!cmd) {
4468 err = -ENOMEM;
4469 goto failed;
4470 }
4471
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004472 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004473 if (err < 0) {
4474 mgmt_pending_remove(cmd);
4475 goto failed;
4476 }
4477
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004478 if (cp->val == 0x02)
4479 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4480 else
4481 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4482
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004483failed:
4484 hci_dev_unlock(hdev);
4485 return err;
4486}
4487
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004488static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4489 void *data, u16 len)
4490{
4491 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004492 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004493 int err;
4494
4495 BT_DBG("request for %s", hdev->name);
4496
Johan Hedbergb97109792014-06-24 14:00:28 +03004497 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004498 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4499 MGMT_STATUS_INVALID_PARAMS);
4500
4501 hci_dev_lock(hdev);
4502
4503 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004504 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4505 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004506 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004507 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4508 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004509
Johan Hedbergb97109792014-06-24 14:00:28 +03004510 if (cp->val == 0x02)
4511 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4512 &hdev->dev_flags);
4513 else
4514 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4515 &hdev->dev_flags);
4516
4517 if (hdev_is_powered(hdev) && use_changed &&
4518 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4519 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4520 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4521 sizeof(mode), &mode);
4522 }
4523
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004524 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4525 if (err < 0)
4526 goto unlock;
4527
4528 if (changed)
4529 err = new_settings(hdev, sk);
4530
4531unlock:
4532 hci_dev_unlock(hdev);
4533 return err;
4534}
4535
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004536static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4537 u16 len)
4538{
4539 struct mgmt_cp_set_privacy *cp = cp_data;
4540 bool changed;
4541 int err;
4542
4543 BT_DBG("request for %s", hdev->name);
4544
4545 if (!lmp_le_capable(hdev))
4546 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4547 MGMT_STATUS_NOT_SUPPORTED);
4548
4549 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4550 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4551 MGMT_STATUS_INVALID_PARAMS);
4552
4553 if (hdev_is_powered(hdev))
4554 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4555 MGMT_STATUS_REJECTED);
4556
4557 hci_dev_lock(hdev);
4558
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004559 /* If user space supports this command it is also expected to
4560 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4561 */
4562 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4563
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004564 if (cp->privacy) {
4565 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4566 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4567 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4568 } else {
4569 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4570 memset(hdev->irk, 0, sizeof(hdev->irk));
4571 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4572 }
4573
4574 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4575 if (err < 0)
4576 goto unlock;
4577
4578 if (changed)
4579 err = new_settings(hdev, sk);
4580
4581unlock:
4582 hci_dev_unlock(hdev);
4583 return err;
4584}
4585
Johan Hedberg41edf162014-02-18 10:19:35 +02004586static bool irk_is_valid(struct mgmt_irk_info *irk)
4587{
4588 switch (irk->addr.type) {
4589 case BDADDR_LE_PUBLIC:
4590 return true;
4591
4592 case BDADDR_LE_RANDOM:
4593 /* Two most significant bits shall be set */
4594 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4595 return false;
4596 return true;
4597 }
4598
4599 return false;
4600}
4601
4602static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4603 u16 len)
4604{
4605 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004606 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4607 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004608 u16 irk_count, expected_len;
4609 int i, err;
4610
4611 BT_DBG("request for %s", hdev->name);
4612
4613 if (!lmp_le_capable(hdev))
4614 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4615 MGMT_STATUS_NOT_SUPPORTED);
4616
4617 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004618 if (irk_count > max_irk_count) {
4619 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4620 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4621 MGMT_STATUS_INVALID_PARAMS);
4622 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004623
4624 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4625 if (expected_len != len) {
4626 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004627 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004628 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4629 MGMT_STATUS_INVALID_PARAMS);
4630 }
4631
4632 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4633
4634 for (i = 0; i < irk_count; i++) {
4635 struct mgmt_irk_info *key = &cp->irks[i];
4636
4637 if (!irk_is_valid(key))
4638 return cmd_status(sk, hdev->id,
4639 MGMT_OP_LOAD_IRKS,
4640 MGMT_STATUS_INVALID_PARAMS);
4641 }
4642
4643 hci_dev_lock(hdev);
4644
4645 hci_smp_irks_clear(hdev);
4646
4647 for (i = 0; i < irk_count; i++) {
4648 struct mgmt_irk_info *irk = &cp->irks[i];
4649 u8 addr_type;
4650
4651 if (irk->addr.type == BDADDR_LE_PUBLIC)
4652 addr_type = ADDR_LE_DEV_PUBLIC;
4653 else
4654 addr_type = ADDR_LE_DEV_RANDOM;
4655
4656 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4657 BDADDR_ANY);
4658 }
4659
4660 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4661
4662 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4663
4664 hci_dev_unlock(hdev);
4665
4666 return err;
4667}
4668
Johan Hedberg3f706b72013-01-20 14:27:16 +02004669static bool ltk_is_valid(struct mgmt_ltk_info *key)
4670{
4671 if (key->master != 0x00 && key->master != 0x01)
4672 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004673
4674 switch (key->addr.type) {
4675 case BDADDR_LE_PUBLIC:
4676 return true;
4677
4678 case BDADDR_LE_RANDOM:
4679 /* Two most significant bits shall be set */
4680 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4681 return false;
4682 return true;
4683 }
4684
4685 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004686}
4687
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004688static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004689 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004690{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004691 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004692 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4693 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004694 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004695 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004696
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004697 BT_DBG("request for %s", hdev->name);
4698
4699 if (!lmp_le_capable(hdev))
4700 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4701 MGMT_STATUS_NOT_SUPPORTED);
4702
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004703 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004704 if (key_count > max_key_count) {
4705 BT_ERR("load_ltks: too big key_count value %u", key_count);
4706 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4707 MGMT_STATUS_INVALID_PARAMS);
4708 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004709
4710 expected_len = sizeof(*cp) + key_count *
4711 sizeof(struct mgmt_ltk_info);
4712 if (expected_len != len) {
4713 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004714 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004715 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004716 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004717 }
4718
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004719 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004720
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004721 for (i = 0; i < key_count; i++) {
4722 struct mgmt_ltk_info *key = &cp->keys[i];
4723
Johan Hedberg3f706b72013-01-20 14:27:16 +02004724 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004725 return cmd_status(sk, hdev->id,
4726 MGMT_OP_LOAD_LONG_TERM_KEYS,
4727 MGMT_STATUS_INVALID_PARAMS);
4728 }
4729
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004730 hci_dev_lock(hdev);
4731
4732 hci_smp_ltks_clear(hdev);
4733
4734 for (i = 0; i < key_count; i++) {
4735 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004736 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004737
4738 if (key->addr.type == BDADDR_LE_PUBLIC)
4739 addr_type = ADDR_LE_DEV_PUBLIC;
4740 else
4741 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004742
4743 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004744 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004745 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004746 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004747
Johan Hedberg61b43352014-05-29 19:36:53 +03004748 switch (key->type) {
4749 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004750 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004751 break;
4752 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004753 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004754 break;
4755 default:
4756 continue;
4757 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004758
Johan Hedberg35d70272014-02-19 14:57:47 +02004759 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004760 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004761 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004762 }
4763
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004764 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4765 NULL, 0);
4766
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004767 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004768
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004769 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004770}
4771
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004772struct cmd_conn_lookup {
4773 struct hci_conn *conn;
4774 bool valid_tx_power;
4775 u8 mgmt_status;
4776};
4777
4778static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4779{
4780 struct cmd_conn_lookup *match = data;
4781 struct mgmt_cp_get_conn_info *cp;
4782 struct mgmt_rp_get_conn_info rp;
4783 struct hci_conn *conn = cmd->user_data;
4784
4785 if (conn != match->conn)
4786 return;
4787
4788 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4789
4790 memset(&rp, 0, sizeof(rp));
4791 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4792 rp.addr.type = cp->addr.type;
4793
4794 if (!match->mgmt_status) {
4795 rp.rssi = conn->rssi;
4796
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004797 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004798 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004799 rp.max_tx_power = conn->max_tx_power;
4800 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004801 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004802 rp.max_tx_power = HCI_TX_POWER_INVALID;
4803 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004804 }
4805
4806 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4807 match->mgmt_status, &rp, sizeof(rp));
4808
4809 hci_conn_drop(conn);
4810
4811 mgmt_pending_remove(cmd);
4812}
4813
4814static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4815{
4816 struct hci_cp_read_rssi *cp;
4817 struct hci_conn *conn;
4818 struct cmd_conn_lookup match;
4819 u16 handle;
4820
4821 BT_DBG("status 0x%02x", status);
4822
4823 hci_dev_lock(hdev);
4824
4825 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004826 * otherwise we assume it's not valid. At the moment we assume that
4827 * either both or none of current and max values are valid to keep code
4828 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004829 */
4830 match.valid_tx_power = !status;
4831
4832 /* Commands sent in request are either Read RSSI or Read Transmit Power
4833 * Level so we check which one was last sent to retrieve connection
4834 * handle. Both commands have handle as first parameter so it's safe to
4835 * cast data on the same command struct.
4836 *
4837 * First command sent is always Read RSSI and we fail only if it fails.
4838 * In other case we simply override error to indicate success as we
4839 * already remembered if TX power value is actually valid.
4840 */
4841 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4842 if (!cp) {
4843 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4844 status = 0;
4845 }
4846
4847 if (!cp) {
4848 BT_ERR("invalid sent_cmd in response");
4849 goto unlock;
4850 }
4851
4852 handle = __le16_to_cpu(cp->handle);
4853 conn = hci_conn_hash_lookup_handle(hdev, handle);
4854 if (!conn) {
4855 BT_ERR("unknown handle (%d) in response", handle);
4856 goto unlock;
4857 }
4858
4859 match.conn = conn;
4860 match.mgmt_status = mgmt_status(status);
4861
4862 /* Cache refresh is complete, now reply for mgmt request for given
4863 * connection only.
4864 */
4865 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4866 get_conn_info_complete, &match);
4867
4868unlock:
4869 hci_dev_unlock(hdev);
4870}
4871
4872static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4873 u16 len)
4874{
4875 struct mgmt_cp_get_conn_info *cp = data;
4876 struct mgmt_rp_get_conn_info rp;
4877 struct hci_conn *conn;
4878 unsigned long conn_info_age;
4879 int err = 0;
4880
4881 BT_DBG("%s", hdev->name);
4882
4883 memset(&rp, 0, sizeof(rp));
4884 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4885 rp.addr.type = cp->addr.type;
4886
4887 if (!bdaddr_type_is_valid(cp->addr.type))
4888 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4889 MGMT_STATUS_INVALID_PARAMS,
4890 &rp, sizeof(rp));
4891
4892 hci_dev_lock(hdev);
4893
4894 if (!hdev_is_powered(hdev)) {
4895 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4896 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4897 goto unlock;
4898 }
4899
4900 if (cp->addr.type == BDADDR_BREDR)
4901 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4902 &cp->addr.bdaddr);
4903 else
4904 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4905
4906 if (!conn || conn->state != BT_CONNECTED) {
4907 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4908 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4909 goto unlock;
4910 }
4911
4912 /* To avoid client trying to guess when to poll again for information we
4913 * calculate conn info age as random value between min/max set in hdev.
4914 */
4915 conn_info_age = hdev->conn_info_min_age +
4916 prandom_u32_max(hdev->conn_info_max_age -
4917 hdev->conn_info_min_age);
4918
4919 /* Query controller to refresh cached values if they are too old or were
4920 * never read.
4921 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004922 if (time_after(jiffies, conn->conn_info_timestamp +
4923 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004924 !conn->conn_info_timestamp) {
4925 struct hci_request req;
4926 struct hci_cp_read_tx_power req_txp_cp;
4927 struct hci_cp_read_rssi req_rssi_cp;
4928 struct pending_cmd *cmd;
4929
4930 hci_req_init(&req, hdev);
4931 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4932 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4933 &req_rssi_cp);
4934
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004935 /* For LE links TX power does not change thus we don't need to
4936 * query for it once value is known.
4937 */
4938 if (!bdaddr_type_is_le(cp->addr.type) ||
4939 conn->tx_power == HCI_TX_POWER_INVALID) {
4940 req_txp_cp.handle = cpu_to_le16(conn->handle);
4941 req_txp_cp.type = 0x00;
4942 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4943 sizeof(req_txp_cp), &req_txp_cp);
4944 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004945
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004946 /* Max TX power needs to be read only once per connection */
4947 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
4948 req_txp_cp.handle = cpu_to_le16(conn->handle);
4949 req_txp_cp.type = 0x01;
4950 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4951 sizeof(req_txp_cp), &req_txp_cp);
4952 }
4953
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004954 err = hci_req_run(&req, conn_info_refresh_complete);
4955 if (err < 0)
4956 goto unlock;
4957
4958 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
4959 data, len);
4960 if (!cmd) {
4961 err = -ENOMEM;
4962 goto unlock;
4963 }
4964
4965 hci_conn_hold(conn);
4966 cmd->user_data = conn;
4967
4968 conn->conn_info_timestamp = jiffies;
4969 } else {
4970 /* Cache is valid, just reply with values cached in hci_conn */
4971 rp.rssi = conn->rssi;
4972 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004973 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004974
4975 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4976 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
4977 }
4978
4979unlock:
4980 hci_dev_unlock(hdev);
4981 return err;
4982}
4983
Johan Hedberg95868422014-06-28 17:54:07 +03004984static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
4985{
4986 struct mgmt_cp_get_clock_info *cp;
4987 struct mgmt_rp_get_clock_info rp;
4988 struct hci_cp_read_clock *hci_cp;
4989 struct pending_cmd *cmd;
4990 struct hci_conn *conn;
4991
4992 BT_DBG("%s status %u", hdev->name, status);
4993
4994 hci_dev_lock(hdev);
4995
4996 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
4997 if (!hci_cp)
4998 goto unlock;
4999
5000 if (hci_cp->which) {
5001 u16 handle = __le16_to_cpu(hci_cp->handle);
5002 conn = hci_conn_hash_lookup_handle(hdev, handle);
5003 } else {
5004 conn = NULL;
5005 }
5006
5007 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5008 if (!cmd)
5009 goto unlock;
5010
5011 cp = cmd->param;
5012
5013 memset(&rp, 0, sizeof(rp));
5014 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
5015
5016 if (status)
5017 goto send_rsp;
5018
5019 rp.local_clock = cpu_to_le32(hdev->clock);
5020
5021 if (conn) {
5022 rp.piconet_clock = cpu_to_le32(conn->clock);
5023 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5024 }
5025
5026send_rsp:
5027 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
5028 &rp, sizeof(rp));
5029 mgmt_pending_remove(cmd);
5030 if (conn)
5031 hci_conn_drop(conn);
5032
5033unlock:
5034 hci_dev_unlock(hdev);
5035}
5036
5037static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5038 u16 len)
5039{
5040 struct mgmt_cp_get_clock_info *cp = data;
5041 struct mgmt_rp_get_clock_info rp;
5042 struct hci_cp_read_clock hci_cp;
5043 struct pending_cmd *cmd;
5044 struct hci_request req;
5045 struct hci_conn *conn;
5046 int err;
5047
5048 BT_DBG("%s", hdev->name);
5049
5050 memset(&rp, 0, sizeof(rp));
5051 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5052 rp.addr.type = cp->addr.type;
5053
5054 if (cp->addr.type != BDADDR_BREDR)
5055 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5056 MGMT_STATUS_INVALID_PARAMS,
5057 &rp, sizeof(rp));
5058
5059 hci_dev_lock(hdev);
5060
5061 if (!hdev_is_powered(hdev)) {
5062 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5063 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5064 goto unlock;
5065 }
5066
5067 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5068 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5069 &cp->addr.bdaddr);
5070 if (!conn || conn->state != BT_CONNECTED) {
5071 err = cmd_complete(sk, hdev->id,
5072 MGMT_OP_GET_CLOCK_INFO,
5073 MGMT_STATUS_NOT_CONNECTED,
5074 &rp, sizeof(rp));
5075 goto unlock;
5076 }
5077 } else {
5078 conn = NULL;
5079 }
5080
5081 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5082 if (!cmd) {
5083 err = -ENOMEM;
5084 goto unlock;
5085 }
5086
5087 hci_req_init(&req, hdev);
5088
5089 memset(&hci_cp, 0, sizeof(hci_cp));
5090 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5091
5092 if (conn) {
5093 hci_conn_hold(conn);
5094 cmd->user_data = conn;
5095
5096 hci_cp.handle = cpu_to_le16(conn->handle);
5097 hci_cp.which = 0x01; /* Piconet clock */
5098 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5099 }
5100
5101 err = hci_req_run(&req, get_clock_info_complete);
5102 if (err < 0)
5103 mgmt_pending_remove(cmd);
5104
5105unlock:
5106 hci_dev_unlock(hdev);
5107 return err;
5108}
5109
Marcel Holtmann8afef092014-06-29 22:28:34 +02005110static void device_added(struct sock *sk, struct hci_dev *hdev,
5111 bdaddr_t *bdaddr, u8 type, u8 action)
5112{
5113 struct mgmt_ev_device_added ev;
5114
5115 bacpy(&ev.addr.bdaddr, bdaddr);
5116 ev.addr.type = type;
5117 ev.action = action;
5118
5119 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5120}
5121
Marcel Holtmann2faade52014-06-29 19:44:03 +02005122static int add_device(struct sock *sk, struct hci_dev *hdev,
5123 void *data, u16 len)
5124{
5125 struct mgmt_cp_add_device *cp = data;
5126 u8 auto_conn, addr_type;
5127 int err;
5128
5129 BT_DBG("%s", hdev->name);
5130
5131 if (!bdaddr_type_is_le(cp->addr.type) ||
5132 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5133 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5134 MGMT_STATUS_INVALID_PARAMS,
5135 &cp->addr, sizeof(cp->addr));
5136
5137 if (cp->action != 0x00 && cp->action != 0x01)
5138 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5139 MGMT_STATUS_INVALID_PARAMS,
5140 &cp->addr, sizeof(cp->addr));
5141
5142 hci_dev_lock(hdev);
5143
5144 if (cp->addr.type == BDADDR_LE_PUBLIC)
5145 addr_type = ADDR_LE_DEV_PUBLIC;
5146 else
5147 addr_type = ADDR_LE_DEV_RANDOM;
5148
5149 if (cp->action)
5150 auto_conn = HCI_AUTO_CONN_ALWAYS;
5151 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005152 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005153
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005154 /* If the connection parameters don't exist for this device,
5155 * they will be created and configured with defaults.
5156 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005157 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5158 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005159 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5160 MGMT_STATUS_FAILED,
5161 &cp->addr, sizeof(cp->addr));
5162 goto unlock;
5163 }
5164
Marcel Holtmann8afef092014-06-29 22:28:34 +02005165 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5166
Marcel Holtmann2faade52014-06-29 19:44:03 +02005167 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5168 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5169
5170unlock:
5171 hci_dev_unlock(hdev);
5172 return err;
5173}
5174
Marcel Holtmann8afef092014-06-29 22:28:34 +02005175static void device_removed(struct sock *sk, struct hci_dev *hdev,
5176 bdaddr_t *bdaddr, u8 type)
5177{
5178 struct mgmt_ev_device_removed ev;
5179
5180 bacpy(&ev.addr.bdaddr, bdaddr);
5181 ev.addr.type = type;
5182
5183 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5184}
5185
Marcel Holtmann2faade52014-06-29 19:44:03 +02005186static int remove_device(struct sock *sk, struct hci_dev *hdev,
5187 void *data, u16 len)
5188{
5189 struct mgmt_cp_remove_device *cp = data;
5190 int err;
5191
5192 BT_DBG("%s", hdev->name);
5193
5194 hci_dev_lock(hdev);
5195
5196 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005197 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005198 u8 addr_type;
5199
5200 if (!bdaddr_type_is_le(cp->addr.type)) {
5201 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5202 MGMT_STATUS_INVALID_PARAMS,
5203 &cp->addr, sizeof(cp->addr));
5204 goto unlock;
5205 }
5206
5207 if (cp->addr.type == BDADDR_LE_PUBLIC)
5208 addr_type = ADDR_LE_DEV_PUBLIC;
5209 else
5210 addr_type = ADDR_LE_DEV_RANDOM;
5211
Johan Hedbergc71593d2014-07-02 17:37:28 +03005212 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5213 addr_type);
5214 if (!params) {
5215 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5216 MGMT_STATUS_INVALID_PARAMS,
5217 &cp->addr, sizeof(cp->addr));
5218 goto unlock;
5219 }
5220
5221 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5222 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5223 MGMT_STATUS_INVALID_PARAMS,
5224 &cp->addr, sizeof(cp->addr));
5225 goto unlock;
5226 }
5227
Johan Hedberg95305ba2014-07-04 12:37:21 +03005228 list_del_init(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005229 list_del(&params->list);
5230 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005231 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005232
5233 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005234 } else {
5235 if (cp->addr.type) {
5236 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5237 MGMT_STATUS_INVALID_PARAMS,
5238 &cp->addr, sizeof(cp->addr));
5239 goto unlock;
5240 }
5241
Johan Hedbergc71593d2014-07-02 17:37:28 +03005242 hci_conn_params_clear_enabled(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005243 }
5244
5245 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5246 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5247
5248unlock:
5249 hci_dev_unlock(hdev);
5250 return err;
5251}
5252
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005253static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5254 u16 len)
5255{
5256 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005257 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5258 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005259 u16 param_count, expected_len;
5260 int i;
5261
5262 if (!lmp_le_capable(hdev))
5263 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5264 MGMT_STATUS_NOT_SUPPORTED);
5265
5266 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005267 if (param_count > max_param_count) {
5268 BT_ERR("load_conn_param: too big param_count value %u",
5269 param_count);
5270 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5271 MGMT_STATUS_INVALID_PARAMS);
5272 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005273
5274 expected_len = sizeof(*cp) + param_count *
5275 sizeof(struct mgmt_conn_param);
5276 if (expected_len != len) {
5277 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5278 expected_len, len);
5279 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5280 MGMT_STATUS_INVALID_PARAMS);
5281 }
5282
5283 BT_DBG("%s param_count %u", hdev->name, param_count);
5284
5285 hci_dev_lock(hdev);
5286
5287 hci_conn_params_clear_disabled(hdev);
5288
5289 for (i = 0; i < param_count; i++) {
5290 struct mgmt_conn_param *param = &cp->params[i];
5291 struct hci_conn_params *hci_param;
5292 u16 min, max, latency, timeout;
5293 u8 addr_type;
5294
5295 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5296 param->addr.type);
5297
5298 if (param->addr.type == BDADDR_LE_PUBLIC) {
5299 addr_type = ADDR_LE_DEV_PUBLIC;
5300 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5301 addr_type = ADDR_LE_DEV_RANDOM;
5302 } else {
5303 BT_ERR("Ignoring invalid connection parameters");
5304 continue;
5305 }
5306
5307 min = le16_to_cpu(param->min_interval);
5308 max = le16_to_cpu(param->max_interval);
5309 latency = le16_to_cpu(param->latency);
5310 timeout = le16_to_cpu(param->timeout);
5311
5312 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5313 min, max, latency, timeout);
5314
5315 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5316 BT_ERR("Ignoring invalid connection parameters");
5317 continue;
5318 }
5319
5320 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5321 addr_type);
5322 if (!hci_param) {
5323 BT_ERR("Failed to add connection parameters");
5324 continue;
5325 }
5326
5327 hci_param->conn_min_interval = min;
5328 hci_param->conn_max_interval = max;
5329 hci_param->conn_latency = latency;
5330 hci_param->supervision_timeout = timeout;
5331 }
5332
5333 hci_dev_unlock(hdev);
5334
5335 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5336}
5337
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005338static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005339 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5340 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005341 bool var_len;
5342 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005343} mgmt_handlers[] = {
5344 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005345 { read_version, false, MGMT_READ_VERSION_SIZE },
5346 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5347 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5348 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5349 { set_powered, false, MGMT_SETTING_SIZE },
5350 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5351 { set_connectable, false, MGMT_SETTING_SIZE },
5352 { set_fast_connectable, false, MGMT_SETTING_SIZE },
5353 { set_pairable, false, MGMT_SETTING_SIZE },
5354 { set_link_security, false, MGMT_SETTING_SIZE },
5355 { set_ssp, false, MGMT_SETTING_SIZE },
5356 { set_hs, false, MGMT_SETTING_SIZE },
5357 { set_le, false, MGMT_SETTING_SIZE },
5358 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5359 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5360 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5361 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5362 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5363 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5364 { disconnect, false, MGMT_DISCONNECT_SIZE },
5365 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5366 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5367 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5368 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5369 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5370 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5371 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5372 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5373 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5374 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5375 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5376 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005377 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005378 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5379 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5380 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5381 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5382 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5383 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005384 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005385 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005386 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005387 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005388 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005389 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005390 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005391 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005392 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005393 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005394 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005395 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5396 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005397 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5398 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005399 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005400};
5401
Johan Hedberg03811012010-12-08 00:21:06 +02005402int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5403{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005404 void *buf;
5405 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005406 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005407 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005408 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005409 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005410 int err;
5411
5412 BT_DBG("got %zu bytes", msglen);
5413
5414 if (msglen < sizeof(*hdr))
5415 return -EINVAL;
5416
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005417 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005418 if (!buf)
5419 return -ENOMEM;
5420
5421 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5422 err = -EFAULT;
5423 goto done;
5424 }
5425
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005426 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005427 opcode = __le16_to_cpu(hdr->opcode);
5428 index = __le16_to_cpu(hdr->index);
5429 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005430
5431 if (len != msglen - sizeof(*hdr)) {
5432 err = -EINVAL;
5433 goto done;
5434 }
5435
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005436 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005437 hdev = hci_dev_get(index);
5438 if (!hdev) {
5439 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005440 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005441 goto done;
5442 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005443
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005444 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005445 test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) ||
5446 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005447 err = cmd_status(sk, index, opcode,
5448 MGMT_STATUS_INVALID_INDEX);
5449 goto done;
5450 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005451 }
5452
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005453 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005454 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005455 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005456 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005457 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005458 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005459 }
5460
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005461 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5462 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5463 err = cmd_status(sk, index, opcode,
5464 MGMT_STATUS_INVALID_INDEX);
5465 goto done;
5466 }
5467
5468 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5469 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005470 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005471 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005472 goto done;
5473 }
5474
Johan Hedbergbe22b542012-03-01 22:24:41 +02005475 handler = &mgmt_handlers[opcode];
5476
5477 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005478 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005479 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005480 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005481 goto done;
5482 }
5483
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005484 if (hdev)
5485 mgmt_init_hdev(sk, hdev);
5486
5487 cp = buf + sizeof(*hdr);
5488
Johan Hedbergbe22b542012-03-01 22:24:41 +02005489 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005490 if (err < 0)
5491 goto done;
5492
Johan Hedberg03811012010-12-08 00:21:06 +02005493 err = msglen;
5494
5495done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005496 if (hdev)
5497 hci_dev_put(hdev);
5498
Johan Hedberg03811012010-12-08 00:21:06 +02005499 kfree(buf);
5500 return err;
5501}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005502
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005503void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005504{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005505 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005506 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005507
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005508 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5509 return;
5510
5511 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5512 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5513 else
5514 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005515}
5516
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005517void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005518{
Johan Hedberg5f159032012-03-02 03:13:19 +02005519 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005520
Marcel Holtmann1514b892013-10-06 08:25:01 -07005521 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005522 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005523
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005524 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5525 return;
5526
Johan Hedberg744cf192011-11-08 20:40:14 +02005527 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005528
Marcel Holtmannedd38962014-07-02 21:30:55 +02005529 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5530 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
5531 else
5532 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005533}
5534
Andre Guedes6046dc32014-02-26 20:21:51 -03005535/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03005536static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03005537{
5538 struct hci_conn_params *p;
5539
5540 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03005541 /* Needed for AUTO_OFF case where might not "really"
5542 * have been powered off.
5543 */
5544 list_del_init(&p->action);
5545
5546 switch (p->auto_connect) {
5547 case HCI_AUTO_CONN_ALWAYS:
5548 list_add(&p->action, &hdev->pend_le_conns);
5549 break;
5550 case HCI_AUTO_CONN_REPORT:
5551 list_add(&p->action, &hdev->pend_le_reports);
5552 break;
5553 default:
5554 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005555 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005556 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005557
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005558 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005559}
5560
Johan Hedberg229ab392013-03-15 17:06:53 -05005561static void powered_complete(struct hci_dev *hdev, u8 status)
5562{
5563 struct cmd_lookup match = { NULL, hdev };
5564
5565 BT_DBG("status 0x%02x", status);
5566
5567 hci_dev_lock(hdev);
5568
Johan Hedbergd7347f32014-07-04 12:37:23 +03005569 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005570
Johan Hedberg229ab392013-03-15 17:06:53 -05005571 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5572
5573 new_settings(hdev, match.sk);
5574
5575 hci_dev_unlock(hdev);
5576
5577 if (match.sk)
5578 sock_put(match.sk);
5579}
5580
Johan Hedberg70da6242013-03-15 17:06:51 -05005581static int powered_update_hci(struct hci_dev *hdev)
5582{
Johan Hedberg890ea892013-03-15 17:06:52 -05005583 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005584 u8 link_sec;
5585
Johan Hedberg890ea892013-03-15 17:06:52 -05005586 hci_req_init(&req, hdev);
5587
Johan Hedberg70da6242013-03-15 17:06:51 -05005588 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5589 !lmp_host_ssp_capable(hdev)) {
5590 u8 ssp = 1;
5591
Johan Hedberg890ea892013-03-15 17:06:52 -05005592 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005593 }
5594
Johan Hedbergc73eee92013-04-19 18:35:21 +03005595 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5596 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005597 struct hci_cp_write_le_host_supported cp;
5598
5599 cp.le = 1;
5600 cp.simul = lmp_le_br_capable(hdev);
5601
5602 /* Check first if we already have the right
5603 * host state (host features set)
5604 */
5605 if (cp.le != lmp_host_le_capable(hdev) ||
5606 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005607 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5608 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005609 }
5610
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005611 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005612 /* Make sure the controller has a good default for
5613 * advertising data. This also applies to the case
5614 * where BR/EDR was toggled during the AUTO_OFF phase.
5615 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005616 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005617 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005618 update_scan_rsp_data(&req);
5619 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005620
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005621 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5622 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005623 }
5624
Johan Hedberg70da6242013-03-15 17:06:51 -05005625 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5626 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005627 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5628 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005629
5630 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005631 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5632 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005633 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005634 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005635 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005636 }
5637
Johan Hedberg229ab392013-03-15 17:06:53 -05005638 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005639}
5640
Johan Hedberg744cf192011-11-08 20:40:14 +02005641int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005642{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005643 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005644 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5645 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005646 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005647
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005648 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5649 return 0;
5650
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005651 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005652 if (powered_update_hci(hdev) == 0)
5653 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005654
Johan Hedberg229ab392013-03-15 17:06:53 -05005655 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5656 &match);
5657 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005658 }
5659
Johan Hedberg229ab392013-03-15 17:06:53 -05005660 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5661 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5662
5663 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5664 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5665 zero_cod, sizeof(zero_cod), NULL);
5666
5667new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005668 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005669
5670 if (match.sk)
5671 sock_put(match.sk);
5672
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005673 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005674}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005675
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005676void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005677{
5678 struct pending_cmd *cmd;
5679 u8 status;
5680
5681 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5682 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005683 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005684
5685 if (err == -ERFKILL)
5686 status = MGMT_STATUS_RFKILLED;
5687 else
5688 status = MGMT_STATUS_FAILED;
5689
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005690 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005691
5692 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005693}
5694
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005695void mgmt_discoverable_timeout(struct hci_dev *hdev)
5696{
5697 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005698
5699 hci_dev_lock(hdev);
5700
5701 /* When discoverable timeout triggers, then just make sure
5702 * the limited discoverable flag is cleared. Even in the case
5703 * of a timeout triggered from general discoverable, it is
5704 * safe to unconditionally clear the flag.
5705 */
5706 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005707 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005708
5709 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005710 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5711 u8 scan = SCAN_PAGE;
5712 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5713 sizeof(scan), &scan);
5714 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005715 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005716 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005717 hci_req_run(&req, NULL);
5718
5719 hdev->discov_timeout = 0;
5720
Johan Hedberg9a43e252013-10-20 19:00:07 +03005721 new_settings(hdev, NULL);
5722
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005723 hci_dev_unlock(hdev);
5724}
5725
Marcel Holtmann86a75642013-10-15 06:33:54 -07005726void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005727{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005728 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005729
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005730 /* Nothing needed here if there's a pending command since that
5731 * commands request completion callback takes care of everything
5732 * necessary.
5733 */
5734 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005735 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005736
Johan Hedbergbd107992014-02-24 14:52:19 +02005737 /* Powering off may clear the scan mode - don't let that interfere */
5738 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5739 return;
5740
Johan Hedberg9a43e252013-10-20 19:00:07 +03005741 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005742 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005743 } else {
5744 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005745 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005746 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005747
Johan Hedberg9a43e252013-10-20 19:00:07 +03005748 if (changed) {
5749 struct hci_request req;
5750
5751 /* In case this change in discoverable was triggered by
5752 * a disabling of connectable there could be a need to
5753 * update the advertising flags.
5754 */
5755 hci_req_init(&req, hdev);
5756 update_adv_data(&req);
5757 hci_req_run(&req, NULL);
5758
Marcel Holtmann86a75642013-10-15 06:33:54 -07005759 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005760 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005761}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005762
Marcel Holtmanna3309162013-10-15 06:33:55 -07005763void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005764{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005765 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005766
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005767 /* Nothing needed here if there's a pending command since that
5768 * commands request completion callback takes care of everything
5769 * necessary.
5770 */
5771 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005772 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005773
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005774 /* Powering off may clear the scan mode - don't let that interfere */
5775 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5776 return;
5777
Marcel Holtmanna3309162013-10-15 06:33:55 -07005778 if (connectable)
5779 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5780 else
5781 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005782
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005783 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005784 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005785}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005786
Johan Hedberg778b2352014-02-24 14:52:17 +02005787void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5788{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005789 /* Powering off may stop advertising - don't let that interfere */
5790 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5791 return;
5792
Johan Hedberg778b2352014-02-24 14:52:17 +02005793 if (advertising)
5794 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5795 else
5796 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5797}
5798
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005799void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005800{
Johan Hedbergca69b792011-11-11 18:10:00 +02005801 u8 mgmt_err = mgmt_status(status);
5802
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005803 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005804 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005805 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005806
5807 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005808 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005809 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005810}
5811
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005812void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5813 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005814{
Johan Hedberg86742e12011-11-07 23:13:38 +02005815 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005816
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005817 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005818
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005819 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02005820 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005821 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005822 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005823 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005824 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005825
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005826 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005827}
Johan Hedbergf7520542011-01-20 12:34:39 +02005828
Johan Hedbergd7b25452014-05-23 13:19:53 +03005829static u8 mgmt_ltk_type(struct smp_ltk *ltk)
5830{
5831 if (ltk->authenticated)
5832 return MGMT_LTK_AUTHENTICATED;
5833
5834 return MGMT_LTK_UNAUTHENTICATED;
5835}
5836
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005837void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005838{
5839 struct mgmt_ev_new_long_term_key ev;
5840
5841 memset(&ev, 0, sizeof(ev));
5842
Marcel Holtmann5192d302014-02-19 17:11:58 -08005843 /* Devices using resolvable or non-resolvable random addresses
5844 * without providing an indentity resolving key don't require
5845 * to store long term keys. Their addresses will change the
5846 * next time around.
5847 *
5848 * Only when a remote device provides an identity address
5849 * make sure the long term key is stored. If the remote
5850 * identity is known, the long term keys are internally
5851 * mapped to the identity address. So allow static random
5852 * and public addresses here.
5853 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005854 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5855 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5856 ev.store_hint = 0x00;
5857 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005858 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02005859
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005860 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005861 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03005862 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005863 ev.key.enc_size = key->enc_size;
5864 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005865 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005866
Johan Hedberg2ceba532014-06-16 19:25:16 +03005867 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005868 ev.key.master = 1;
5869
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005870 memcpy(ev.key.val, key->val, sizeof(key->val));
5871
Marcel Holtmann083368f2013-10-15 14:26:29 -07005872 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005873}
5874
Johan Hedberg95fbac82014-02-19 15:18:31 +02005875void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5876{
5877 struct mgmt_ev_new_irk ev;
5878
5879 memset(&ev, 0, sizeof(ev));
5880
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005881 /* For identity resolving keys from devices that are already
5882 * using a public address or static random address, do not
5883 * ask for storing this key. The identity resolving key really
5884 * is only mandatory for devices using resovlable random
5885 * addresses.
5886 *
5887 * Storing all identity resolving keys has the downside that
5888 * they will be also loaded on next boot of they system. More
5889 * identity resolving keys, means more time during scanning is
5890 * needed to actually resolve these addresses.
5891 */
5892 if (bacmp(&irk->rpa, BDADDR_ANY))
5893 ev.store_hint = 0x01;
5894 else
5895 ev.store_hint = 0x00;
5896
Johan Hedberg95fbac82014-02-19 15:18:31 +02005897 bacpy(&ev.rpa, &irk->rpa);
5898 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5899 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5900 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5901
5902 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5903}
5904
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005905void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
5906 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005907{
5908 struct mgmt_ev_new_csrk ev;
5909
5910 memset(&ev, 0, sizeof(ev));
5911
5912 /* Devices using resolvable or non-resolvable random addresses
5913 * without providing an indentity resolving key don't require
5914 * to store signature resolving keys. Their addresses will change
5915 * the next time around.
5916 *
5917 * Only when a remote device provides an identity address
5918 * make sure the signature resolving key is stored. So allow
5919 * static random and public addresses here.
5920 */
5921 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5922 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
5923 ev.store_hint = 0x00;
5924 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005925 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005926
5927 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
5928 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
5929 ev.key.master = csrk->master;
5930 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
5931
5932 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
5933}
5934
Andre Guedesffb5a8272014-07-01 18:10:11 -03005935void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03005936 u8 bdaddr_type, u8 store_hint, u16 min_interval,
5937 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03005938{
5939 struct mgmt_ev_new_conn_param ev;
5940
Johan Hedbergc103aea2014-07-02 17:37:34 +03005941 if (!hci_is_identity_address(bdaddr, bdaddr_type))
5942 return;
5943
Andre Guedesffb5a8272014-07-01 18:10:11 -03005944 memset(&ev, 0, sizeof(ev));
5945 bacpy(&ev.addr.bdaddr, bdaddr);
5946 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03005947 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03005948 ev.min_interval = cpu_to_le16(min_interval);
5949 ev.max_interval = cpu_to_le16(max_interval);
5950 ev.latency = cpu_to_le16(latency);
5951 ev.timeout = cpu_to_le16(timeout);
5952
5953 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
5954}
5955
Marcel Holtmann94933992013-10-15 10:26:39 -07005956static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5957 u8 data_len)
5958{
5959 eir[eir_len++] = sizeof(type) + data_len;
5960 eir[eir_len++] = type;
5961 memcpy(&eir[eir_len], data, data_len);
5962 eir_len += data_len;
5963
5964 return eir_len;
5965}
5966
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005967void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5968 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5969 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005970{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005971 char buf[512];
5972 struct mgmt_ev_device_connected *ev = (void *) buf;
5973 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005974
Johan Hedbergb644ba32012-01-17 21:48:47 +02005975 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005976 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005977
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005978 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005979
Johan Hedbergb644ba32012-01-17 21:48:47 +02005980 if (name_len > 0)
5981 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005982 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005983
5984 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005985 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005986 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005987
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005988 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005989
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005990 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
5991 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02005992}
5993
Johan Hedberg8962ee72011-01-20 12:40:27 +02005994static void disconnect_rsp(struct pending_cmd *cmd, void *data)
5995{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01005996 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005997 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02005998 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005999
Johan Hedberg88c3df12012-02-09 14:27:38 +02006000 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6001 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006002
Johan Hedbergaee9b212012-02-18 15:07:59 +02006003 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006004 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006005
6006 *sk = cmd->sk;
6007 sock_hold(*sk);
6008
Johan Hedberga664b5b2011-02-19 12:06:02 -03006009 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006010}
6011
Johan Hedberg124f6e32012-02-09 13:50:12 +02006012static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006013{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006014 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006015 struct mgmt_cp_unpair_device *cp = cmd->param;
6016 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006017
6018 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02006019 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6020 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006021
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006022 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6023
Johan Hedbergaee9b212012-02-18 15:07:59 +02006024 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02006025
6026 mgmt_pending_remove(cmd);
6027}
6028
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006029void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006030 u8 link_type, u8 addr_type, u8 reason,
6031 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006032{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006033 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02006034 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006035 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006036
Johan Hedberg8b064a32014-02-24 14:52:22 +02006037 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6038 if (power_off) {
6039 struct mgmt_mode *cp = power_off->param;
6040
6041 /* The connection is still in hci_conn_hash so test for 1
6042 * instead of 0 to know if this is the last one.
6043 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006044 if (!cp->val && hci_conn_count(hdev) == 1) {
6045 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006046 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006047 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02006048 }
6049
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006050 if (!mgmt_connected)
6051 return;
6052
Andre Guedes57eb7762013-10-30 19:01:41 -03006053 if (link_type != ACL_LINK && link_type != LE_LINK)
6054 return;
6055
Johan Hedberg744cf192011-11-08 20:40:14 +02006056 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006057
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006058 bacpy(&ev.addr.bdaddr, bdaddr);
6059 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6060 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006061
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006062 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006063
6064 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006065 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006066
Johan Hedberg124f6e32012-02-09 13:50:12 +02006067 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006068 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006069}
6070
Marcel Holtmann78929242013-10-06 23:55:47 -07006071void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6072 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006073{
Andre Guedes3655bba2013-10-30 19:01:40 -03006074 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6075 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02006076 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006077 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006078
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006079 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6080 hdev);
6081
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006082 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006083 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006084 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006085
Andre Guedes3655bba2013-10-30 19:01:40 -03006086 cp = cmd->param;
6087
6088 if (bacmp(bdaddr, &cp->addr.bdaddr))
6089 return;
6090
6091 if (cp->addr.type != bdaddr_type)
6092 return;
6093
Johan Hedberg88c3df12012-02-09 14:27:38 +02006094 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03006095 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02006096
Marcel Holtmann78929242013-10-06 23:55:47 -07006097 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
6098 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006099
Johan Hedberga664b5b2011-02-19 12:06:02 -03006100 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006101}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006102
Marcel Holtmann445608d2013-10-06 23:55:48 -07006103void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6104 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006105{
6106 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006107 struct pending_cmd *power_off;
6108
6109 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6110 if (power_off) {
6111 struct mgmt_mode *cp = power_off->param;
6112
6113 /* The connection is still in hci_conn_hash so test for 1
6114 * instead of 0 to know if this is the last one.
6115 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006116 if (!cp->val && hci_conn_count(hdev) == 1) {
6117 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006118 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006119 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02006120 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006121
Johan Hedberg4c659c32011-11-07 23:13:39 +02006122 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006123 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006124 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006125
Marcel Holtmann445608d2013-10-06 23:55:48 -07006126 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006127}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006128
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006129void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006130{
6131 struct mgmt_ev_pin_code_request ev;
6132
Johan Hedbergd8457692012-02-17 14:24:57 +02006133 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006134 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006135 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006136
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006137 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006138}
6139
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006140void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6141 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006142{
6143 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006144 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006145
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006146 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006147 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006148 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006149
Johan Hedbergd8457692012-02-17 14:24:57 +02006150 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006151 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006152
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006153 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6154 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006155
Johan Hedberga664b5b2011-02-19 12:06:02 -03006156 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006157}
6158
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006159void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6160 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006161{
6162 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006163 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006164
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006165 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006166 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006167 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006168
Johan Hedbergd8457692012-02-17 14:24:57 +02006169 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006170 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006171
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006172 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6173 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006174
Johan Hedberga664b5b2011-02-19 12:06:02 -03006175 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006176}
Johan Hedberga5c29682011-02-19 12:05:57 -03006177
Johan Hedberg744cf192011-11-08 20:40:14 +02006178int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006179 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006180 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006181{
6182 struct mgmt_ev_user_confirm_request ev;
6183
Johan Hedberg744cf192011-11-08 20:40:14 +02006184 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006185
Johan Hedberg272d90d2012-02-09 15:26:12 +02006186 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006187 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006188 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006189 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006190
Johan Hedberg744cf192011-11-08 20:40:14 +02006191 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006192 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006193}
6194
Johan Hedberg272d90d2012-02-09 15:26:12 +02006195int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006196 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006197{
6198 struct mgmt_ev_user_passkey_request ev;
6199
6200 BT_DBG("%s", hdev->name);
6201
Johan Hedberg272d90d2012-02-09 15:26:12 +02006202 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006203 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006204
6205 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006206 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006207}
6208
Brian Gix0df4c182011-11-16 13:53:13 -08006209static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006210 u8 link_type, u8 addr_type, u8 status,
6211 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006212{
6213 struct pending_cmd *cmd;
6214 struct mgmt_rp_user_confirm_reply rp;
6215 int err;
6216
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006217 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006218 if (!cmd)
6219 return -ENOENT;
6220
Johan Hedberg272d90d2012-02-09 15:26:12 +02006221 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006222 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b212012-02-18 15:07:59 +02006223 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006224 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006225
Johan Hedberga664b5b2011-02-19 12:06:02 -03006226 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006227
6228 return err;
6229}
6230
Johan Hedberg744cf192011-11-08 20:40:14 +02006231int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006232 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006233{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006234 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006235 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006236}
6237
Johan Hedberg272d90d2012-02-09 15:26:12 +02006238int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006239 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006240{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006241 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006242 status,
6243 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006244}
Johan Hedberg2a611692011-02-19 12:06:00 -03006245
Brian Gix604086b2011-11-23 08:28:33 -08006246int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006247 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006248{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006249 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006250 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006251}
6252
Johan Hedberg272d90d2012-02-09 15:26:12 +02006253int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006254 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006255{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006256 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006257 status,
6258 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006259}
6260
Johan Hedberg92a25252012-09-06 18:39:26 +03006261int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6262 u8 link_type, u8 addr_type, u32 passkey,
6263 u8 entered)
6264{
6265 struct mgmt_ev_passkey_notify ev;
6266
6267 BT_DBG("%s", hdev->name);
6268
6269 bacpy(&ev.addr.bdaddr, bdaddr);
6270 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6271 ev.passkey = __cpu_to_le32(passkey);
6272 ev.entered = entered;
6273
6274 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6275}
6276
Marcel Holtmanne5460992013-10-15 14:26:23 -07006277void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6278 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006279{
6280 struct mgmt_ev_auth_failed ev;
6281
Johan Hedbergbab73cb2012-02-09 16:07:29 +02006282 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006283 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006284 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006285
Marcel Holtmanne5460992013-10-15 14:26:23 -07006286 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03006287}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006288
Marcel Holtmann464996a2013-10-15 14:26:24 -07006289void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006290{
6291 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006292 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006293
6294 if (status) {
6295 u8 mgmt_err = mgmt_status(status);
6296 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006297 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006298 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006299 }
6300
Marcel Holtmann464996a2013-10-15 14:26:24 -07006301 if (test_bit(HCI_AUTH, &hdev->flags))
6302 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6303 &hdev->dev_flags);
6304 else
6305 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6306 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006307
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006308 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006309 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006310
Johan Hedberg47990ea2012-02-22 11:58:37 +02006311 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006312 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006313
6314 if (match.sk)
6315 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006316}
6317
Johan Hedberg890ea892013-03-15 17:06:52 -05006318static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006319{
Johan Hedberg890ea892013-03-15 17:06:52 -05006320 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006321 struct hci_cp_write_eir cp;
6322
Johan Hedberg976eb202012-10-24 21:12:01 +03006323 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006324 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006325
Johan Hedbergc80da272012-02-22 15:38:48 +02006326 memset(hdev->eir, 0, sizeof(hdev->eir));
6327
Johan Hedbergcacaf522012-02-21 00:52:42 +02006328 memset(&cp, 0, sizeof(cp));
6329
Johan Hedberg890ea892013-03-15 17:06:52 -05006330 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006331}
6332
Marcel Holtmann3e248562013-10-15 14:26:25 -07006333void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006334{
6335 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006336 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006337 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006338
6339 if (status) {
6340 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006341
6342 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006343 &hdev->dev_flags)) {
6344 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006345 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006346 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006347
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006348 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6349 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006350 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006351 }
6352
6353 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006354 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006355 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006356 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6357 if (!changed)
6358 changed = test_and_clear_bit(HCI_HS_ENABLED,
6359 &hdev->dev_flags);
6360 else
6361 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006362 }
6363
6364 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6365
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006366 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006367 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006368
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006369 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006370 sock_put(match.sk);
6371
Johan Hedberg890ea892013-03-15 17:06:52 -05006372 hci_req_init(&req, hdev);
6373
Johan Hedberg37699722014-06-24 14:00:27 +03006374 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6375 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6376 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6377 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006378 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006379 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006380 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006381 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006382
6383 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006384}
6385
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006386void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6387{
6388 struct cmd_lookup match = { NULL, hdev };
6389 bool changed = false;
6390
6391 if (status) {
6392 u8 mgmt_err = mgmt_status(status);
6393
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006394 if (enable) {
6395 if (test_and_clear_bit(HCI_SC_ENABLED,
6396 &hdev->dev_flags))
6397 new_settings(hdev, NULL);
6398 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6399 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006400
6401 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6402 cmd_status_rsp, &mgmt_err);
6403 return;
6404 }
6405
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006406 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006407 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006408 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006409 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006410 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6411 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006412
6413 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6414 settings_rsp, &match);
6415
6416 if (changed)
6417 new_settings(hdev, match.sk);
6418
6419 if (match.sk)
6420 sock_put(match.sk);
6421}
6422
Johan Hedberg92da6092013-03-15 17:06:55 -05006423static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006424{
6425 struct cmd_lookup *match = data;
6426
Johan Hedberg90e70452012-02-23 23:09:40 +02006427 if (match->sk == NULL) {
6428 match->sk = cmd->sk;
6429 sock_hold(match->sk);
6430 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006431}
6432
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006433void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6434 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006435{
Johan Hedberg90e70452012-02-23 23:09:40 +02006436 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006437
Johan Hedberg92da6092013-03-15 17:06:55 -05006438 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6439 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6440 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006441
6442 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006443 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6444 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006445
6446 if (match.sk)
6447 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006448}
6449
Marcel Holtmann7667da32013-10-15 14:26:27 -07006450void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006451{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006452 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006453 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006454
Johan Hedberg13928972013-03-15 17:07:00 -05006455 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006456 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006457
6458 memset(&ev, 0, sizeof(ev));
6459 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006460 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006461
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006462 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006463 if (!cmd) {
6464 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006465
Johan Hedberg13928972013-03-15 17:07:00 -05006466 /* If this is a HCI command related to powering on the
6467 * HCI dev don't send any mgmt signals.
6468 */
6469 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006470 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006471 }
6472
Marcel Holtmann7667da32013-10-15 14:26:27 -07006473 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6474 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006475}
Szymon Jancc35938b2011-03-22 13:12:21 +01006476
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006477void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6478 u8 *randomizer192, u8 *hash256,
6479 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006480{
6481 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006482
Johan Hedberg744cf192011-11-08 20:40:14 +02006483 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006484
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006485 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006486 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006487 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006488
6489 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006490 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6491 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006492 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006493 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6494 hash256 && randomizer256) {
6495 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006496
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006497 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6498 memcpy(rp.randomizer192, randomizer192,
6499 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006500
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006501 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6502 memcpy(rp.randomizer256, randomizer256,
6503 sizeof(rp.randomizer256));
6504
6505 cmd_complete(cmd->sk, hdev->id,
6506 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6507 &rp, sizeof(rp));
6508 } else {
6509 struct mgmt_rp_read_local_oob_data rp;
6510
6511 memcpy(rp.hash, hash192, sizeof(rp.hash));
6512 memcpy(rp.randomizer, randomizer192,
6513 sizeof(rp.randomizer));
6514
6515 cmd_complete(cmd->sk, hdev->id,
6516 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6517 &rp, sizeof(rp));
6518 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006519 }
6520
6521 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006522}
Johan Hedberge17acd42011-03-30 23:57:16 +03006523
Marcel Holtmann901801b2013-10-06 23:55:51 -07006524void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006525 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6526 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006527{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006528 char buf[512];
6529 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006530 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006531 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006532
Johan Hedberg75ce2082014-07-02 22:42:01 +03006533 /* Don't send events for a non-kernel initiated discovery. With
6534 * LE one exception is if we have pend_le_reports > 0 in which
6535 * case we're doing passive scanning and want these events.
6536 */
6537 if (!hci_discovery_active(hdev)) {
6538 if (link_type == ACL_LINK)
6539 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03006540 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03006541 return;
6542 }
Andre Guedes12602d02013-04-30 15:29:40 -03006543
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006544 /* Make sure that the buffer is big enough. The 5 extra bytes
6545 * are for the potential CoD field.
6546 */
6547 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006548 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006549
Johan Hedberg1dc06092012-01-15 21:01:23 +02006550 memset(buf, 0, sizeof(buf));
6551
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006552 irk = hci_get_irk(hdev, bdaddr, addr_type);
6553 if (irk) {
6554 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
6555 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
6556 } else {
6557 bacpy(&ev->addr.bdaddr, bdaddr);
6558 ev->addr.type = link_to_bdaddr(link_type, addr_type);
6559 }
6560
Johan Hedberge319d2e2012-01-15 19:51:59 +02006561 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006562 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006563
Johan Hedberg1dc06092012-01-15 21:01:23 +02006564 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006565 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006566
Johan Hedberg1dc06092012-01-15 21:01:23 +02006567 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6568 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006569 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006570
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006571 if (scan_rsp_len > 0)
6572 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6573
6574 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6575 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006576
Marcel Holtmann901801b2013-10-06 23:55:51 -07006577 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006578}
Johan Hedberga88a9652011-03-30 13:18:12 +03006579
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006580void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6581 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006582{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006583 struct mgmt_ev_device_found *ev;
6584 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6585 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006586
Johan Hedbergb644ba32012-01-17 21:48:47 +02006587 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006588
Johan Hedbergb644ba32012-01-17 21:48:47 +02006589 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006590
Johan Hedbergb644ba32012-01-17 21:48:47 +02006591 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006592 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006593 ev->rssi = rssi;
6594
6595 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006596 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006597
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006598 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006599
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006600 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006601}
Johan Hedberg314b2382011-04-27 10:29:57 -04006602
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006603void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006604{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006605 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006606 struct pending_cmd *cmd;
6607
Andre Guedes343fb142011-11-22 17:14:19 -03006608 BT_DBG("%s discovering %u", hdev->name, discovering);
6609
Johan Hedberg164a6e72011-11-01 17:06:44 +02006610 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006611 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006612 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006613 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006614
6615 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006616 u8 type = hdev->discovery.type;
6617
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006618 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6619 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006620 mgmt_pending_remove(cmd);
6621 }
6622
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006623 memset(&ev, 0, sizeof(ev));
6624 ev.type = hdev->discovery.type;
6625 ev.discovering = discovering;
6626
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006627 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006628}
Antti Julku5e762442011-08-25 16:48:02 +03006629
Marcel Holtmann5976e602013-10-06 04:08:14 -07006630static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6631{
6632 BT_DBG("%s status %u", hdev->name, status);
6633
6634 /* Clear the advertising mgmt setting if we failed to re-enable it */
6635 if (status) {
6636 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006637 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006638 }
6639}
6640
6641void mgmt_reenable_advertising(struct hci_dev *hdev)
6642{
6643 struct hci_request req;
6644
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006645 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006646 return;
6647
6648 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6649 return;
6650
6651 hci_req_init(&req, hdev);
6652 enable_advertising(&req);
6653
6654 /* If this fails we have no option but to let user space know
6655 * that we've disabled advertising.
6656 */
6657 if (hci_req_run(&req, adv_enable_complete) < 0) {
6658 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006659 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006660 }
6661}