blob: 1a78d26b00498da685614823719e3431bfb4ba89 [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,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020092};
93
94static const u16 mgmt_events[] = {
95 MGMT_EV_CONTROLLER_ERROR,
96 MGMT_EV_INDEX_ADDED,
97 MGMT_EV_INDEX_REMOVED,
98 MGMT_EV_NEW_SETTINGS,
99 MGMT_EV_CLASS_OF_DEV_CHANGED,
100 MGMT_EV_LOCAL_NAME_CHANGED,
101 MGMT_EV_NEW_LINK_KEY,
102 MGMT_EV_NEW_LONG_TERM_KEY,
103 MGMT_EV_DEVICE_CONNECTED,
104 MGMT_EV_DEVICE_DISCONNECTED,
105 MGMT_EV_CONNECT_FAILED,
106 MGMT_EV_PIN_CODE_REQUEST,
107 MGMT_EV_USER_CONFIRM_REQUEST,
108 MGMT_EV_USER_PASSKEY_REQUEST,
109 MGMT_EV_AUTH_FAILED,
110 MGMT_EV_DEVICE_FOUND,
111 MGMT_EV_DISCOVERING,
112 MGMT_EV_DEVICE_BLOCKED,
113 MGMT_EV_DEVICE_UNBLOCKED,
114 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300115 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800116 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700117 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200118 MGMT_EV_DEVICE_ADDED,
119 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300120 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200121 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200122 MGMT_EV_UNCONF_INDEX_REMOVED,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200123};
124
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800125#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200126
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200127#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
128 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
129
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200130struct pending_cmd {
131 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200132 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200133 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100134 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200135 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300136 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200137};
138
Johan Hedbergca69b792011-11-11 18:10:00 +0200139/* HCI to MGMT error code conversion table */
140static u8 mgmt_status_table[] = {
141 MGMT_STATUS_SUCCESS,
142 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
143 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
144 MGMT_STATUS_FAILED, /* Hardware Failure */
145 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
146 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200147 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200148 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
149 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
150 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
151 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
152 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
153 MGMT_STATUS_BUSY, /* Command Disallowed */
154 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
155 MGMT_STATUS_REJECTED, /* Rejected Security */
156 MGMT_STATUS_REJECTED, /* Rejected Personal */
157 MGMT_STATUS_TIMEOUT, /* Host Timeout */
158 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
159 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
160 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
161 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
162 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
163 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
164 MGMT_STATUS_BUSY, /* Repeated Attempts */
165 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
166 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
167 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
168 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
169 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
170 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
171 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
172 MGMT_STATUS_FAILED, /* Unspecified Error */
173 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
174 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
175 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
176 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
177 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
178 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
179 MGMT_STATUS_FAILED, /* Unit Link Key Used */
180 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
181 MGMT_STATUS_TIMEOUT, /* Instant Passed */
182 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
183 MGMT_STATUS_FAILED, /* Transaction Collision */
184 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
185 MGMT_STATUS_REJECTED, /* QoS Rejected */
186 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
187 MGMT_STATUS_REJECTED, /* Insufficient Security */
188 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
189 MGMT_STATUS_BUSY, /* Role Switch Pending */
190 MGMT_STATUS_FAILED, /* Slot Violation */
191 MGMT_STATUS_FAILED, /* Role Switch Failed */
192 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
193 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
194 MGMT_STATUS_BUSY, /* Host Busy Pairing */
195 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
196 MGMT_STATUS_BUSY, /* Controller Busy */
197 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
198 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
199 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
200 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
201 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
202};
203
204static u8 mgmt_status(u8 hci_status)
205{
206 if (hci_status < ARRAY_SIZE(mgmt_status_table))
207 return mgmt_status_table[hci_status];
208
209 return MGMT_STATUS_FAILED;
210}
211
Szymon Janc4e51eae2011-02-25 19:05:48 +0100212static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200213{
214 struct sk_buff *skb;
215 struct mgmt_hdr *hdr;
216 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300217 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200218
Szymon Janc34eb5252011-02-28 14:10:08 +0100219 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200220
Andre Guedes790eff42012-06-07 19:05:46 -0300221 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200222 if (!skb)
223 return -ENOMEM;
224
225 hdr = (void *) skb_put(skb, sizeof(*hdr));
226
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700227 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100228 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200229 hdr->len = cpu_to_le16(sizeof(*ev));
230
231 ev = (void *) skb_put(skb, sizeof(*ev));
232 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200233 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200234
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300235 err = sock_queue_rcv_skb(sk, skb);
236 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200237 kfree_skb(skb);
238
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300239 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200240}
241
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200242static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300243 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200244{
245 struct sk_buff *skb;
246 struct mgmt_hdr *hdr;
247 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300248 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200249
250 BT_DBG("sock %p", sk);
251
Andre Guedes790eff42012-06-07 19:05:46 -0300252 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200253 if (!skb)
254 return -ENOMEM;
255
256 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200257
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700258 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100259 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200260 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200261
Johan Hedberga38528f2011-01-22 06:46:43 +0200262 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200263 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200264 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100265
266 if (rp)
267 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200268
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300269 err = sock_queue_rcv_skb(sk, skb);
270 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200271 kfree_skb(skb);
272
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100273 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200274}
275
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300276static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
277 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200278{
279 struct mgmt_rp_read_version rp;
280
281 BT_DBG("sock %p", sk);
282
283 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700284 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200285
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200286 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300287 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200288}
289
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300290static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
291 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200292{
293 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200294 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
295 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200296 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200297 size_t rp_size;
298 int i, err;
299
300 BT_DBG("sock %p", sk);
301
302 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
303
304 rp = kmalloc(rp_size, GFP_KERNEL);
305 if (!rp)
306 return -ENOMEM;
307
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700308 rp->num_commands = cpu_to_le16(num_commands);
309 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200310
311 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
312 put_unaligned_le16(mgmt_commands[i], opcode);
313
314 for (i = 0; i < num_events; i++, opcode++)
315 put_unaligned_le16(mgmt_events[i], opcode);
316
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200317 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300318 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200319 kfree(rp);
320
321 return err;
322}
323
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300324static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
325 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200326{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200327 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200328 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200329 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200330 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300331 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200332
333 BT_DBG("sock %p", sk);
334
335 read_lock(&hci_dev_list_lock);
336
337 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300338 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700339 if (d->dev_type == HCI_BREDR)
340 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200341 }
342
Johan Hedberga38528f2011-01-22 06:46:43 +0200343 rp_len = sizeof(*rp) + (2 * count);
344 rp = kmalloc(rp_len, GFP_ATOMIC);
345 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100346 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200347 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100348 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200349
Johan Hedberg476e44c2012-10-19 20:10:46 +0300350 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200351 list_for_each_entry(d, &hci_dev_list, list) {
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200352 if (test_bit(HCI_SETUP, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200353 continue;
354
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700355 if (test_bit(HCI_USER_CHANNEL, &d->dev_flags))
356 continue;
357
Marcel Holtmann4a964402014-07-02 19:10:33 +0200358 if (test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmannfee746b2014-06-29 12:13:05 +0200359 continue;
360
Marcel Holtmann1514b892013-10-06 08:25:01 -0700361 if (d->dev_type == HCI_BREDR) {
362 rp->index[count++] = cpu_to_le16(d->id);
363 BT_DBG("Added hci%u", d->id);
364 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200365 }
366
Johan Hedberg476e44c2012-10-19 20:10:46 +0300367 rp->num_controllers = cpu_to_le16(count);
368 rp_len = sizeof(*rp) + (2 * count);
369
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200370 read_unlock(&hci_dev_list_lock);
371
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200372 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300373 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200374
Johan Hedberga38528f2011-01-22 06:46:43 +0200375 kfree(rp);
376
377 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200378}
379
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200380static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200381{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200382 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200383
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200384 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200385 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800386 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg03811012010-12-08 00:21:06 +0200387
Andre Guedesed3fa312012-07-24 15:03:46 -0300388 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300389 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500390 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
391 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300392 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200393 settings |= MGMT_SETTING_BREDR;
394 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700395
396 if (lmp_ssp_capable(hdev)) {
397 settings |= MGMT_SETTING_SSP;
398 settings |= MGMT_SETTING_HS;
399 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800400
Marcel Holtmann5afeac142014-01-10 02:07:27 -0800401 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200402 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800403 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700404 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100405
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300406 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200407 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300408 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200409 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300410 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200411
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200412 return settings;
413}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200414
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200415static u32 get_current_settings(struct hci_dev *hdev)
416{
417 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200418
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200419 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100420 settings |= MGMT_SETTING_POWERED;
421
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200422 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200423 settings |= MGMT_SETTING_CONNECTABLE;
424
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500425 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
426 settings |= MGMT_SETTING_FAST_CONNECTABLE;
427
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200428 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200429 settings |= MGMT_SETTING_DISCOVERABLE;
430
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200431 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200432 settings |= MGMT_SETTING_PAIRABLE;
433
Johan Hedberg56f87902013-10-02 13:43:13 +0300434 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200435 settings |= MGMT_SETTING_BREDR;
436
Johan Hedberg06199cf2012-02-22 16:37:11 +0200437 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200438 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200439
Johan Hedberg47990ea2012-02-22 11:58:37 +0200440 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200441 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200442
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200443 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200444 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200445
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200446 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
447 settings |= MGMT_SETTING_HS;
448
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200449 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300450 settings |= MGMT_SETTING_ADVERTISING;
451
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800452 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
453 settings |= MGMT_SETTING_SECURE_CONN;
454
Johan Hedberg0663b292014-06-24 13:15:50 +0300455 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800456 settings |= MGMT_SETTING_DEBUG_KEYS;
457
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200458 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
459 settings |= MGMT_SETTING_PRIVACY;
460
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200461 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200462}
463
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300464#define PNP_INFO_SVCLASS_ID 0x1200
465
Johan Hedberg213202e2013-01-27 00:31:33 +0200466static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
467{
468 u8 *ptr = data, *uuids_start = NULL;
469 struct bt_uuid *uuid;
470
471 if (len < 4)
472 return ptr;
473
474 list_for_each_entry(uuid, &hdev->uuids, list) {
475 u16 uuid16;
476
477 if (uuid->size != 16)
478 continue;
479
480 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
481 if (uuid16 < 0x1100)
482 continue;
483
484 if (uuid16 == PNP_INFO_SVCLASS_ID)
485 continue;
486
487 if (!uuids_start) {
488 uuids_start = ptr;
489 uuids_start[0] = 1;
490 uuids_start[1] = EIR_UUID16_ALL;
491 ptr += 2;
492 }
493
494 /* Stop if not enough space to put next UUID */
495 if ((ptr - data) + sizeof(u16) > len) {
496 uuids_start[1] = EIR_UUID16_SOME;
497 break;
498 }
499
500 *ptr++ = (uuid16 & 0x00ff);
501 *ptr++ = (uuid16 & 0xff00) >> 8;
502 uuids_start[0] += sizeof(uuid16);
503 }
504
505 return ptr;
506}
507
Johan Hedbergcdf19632013-01-27 00:31:34 +0200508static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
509{
510 u8 *ptr = data, *uuids_start = NULL;
511 struct bt_uuid *uuid;
512
513 if (len < 6)
514 return ptr;
515
516 list_for_each_entry(uuid, &hdev->uuids, list) {
517 if (uuid->size != 32)
518 continue;
519
520 if (!uuids_start) {
521 uuids_start = ptr;
522 uuids_start[0] = 1;
523 uuids_start[1] = EIR_UUID32_ALL;
524 ptr += 2;
525 }
526
527 /* Stop if not enough space to put next UUID */
528 if ((ptr - data) + sizeof(u32) > len) {
529 uuids_start[1] = EIR_UUID32_SOME;
530 break;
531 }
532
533 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
534 ptr += sizeof(u32);
535 uuids_start[0] += sizeof(u32);
536 }
537
538 return ptr;
539}
540
Johan Hedbergc00d5752013-01-27 00:31:35 +0200541static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
542{
543 u8 *ptr = data, *uuids_start = NULL;
544 struct bt_uuid *uuid;
545
546 if (len < 18)
547 return ptr;
548
549 list_for_each_entry(uuid, &hdev->uuids, list) {
550 if (uuid->size != 128)
551 continue;
552
553 if (!uuids_start) {
554 uuids_start = ptr;
555 uuids_start[0] = 1;
556 uuids_start[1] = EIR_UUID128_ALL;
557 ptr += 2;
558 }
559
560 /* Stop if not enough space to put next UUID */
561 if ((ptr - data) + 16 > len) {
562 uuids_start[1] = EIR_UUID128_SOME;
563 break;
564 }
565
566 memcpy(ptr, uuid->uuid, 16);
567 ptr += 16;
568 uuids_start[0] += 16;
569 }
570
571 return ptr;
572}
573
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300574static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
575{
576 struct pending_cmd *cmd;
577
578 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
579 if (cmd->opcode == opcode)
580 return cmd;
581 }
582
583 return NULL;
584}
585
Johan Hedberg95868422014-06-28 17:54:07 +0300586static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
587 struct hci_dev *hdev,
588 const void *data)
589{
590 struct pending_cmd *cmd;
591
592 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
593 if (cmd->user_data != data)
594 continue;
595 if (cmd->opcode == opcode)
596 return cmd;
597 }
598
599 return NULL;
600}
601
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700602static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
603{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700604 u8 ad_len = 0;
605 size_t name_len;
606
607 name_len = strlen(hdev->dev_name);
608 if (name_len > 0) {
609 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
610
611 if (name_len > max_len) {
612 name_len = max_len;
613 ptr[1] = EIR_NAME_SHORT;
614 } else
615 ptr[1] = EIR_NAME_COMPLETE;
616
617 ptr[0] = name_len + 1;
618
619 memcpy(ptr + 2, hdev->dev_name, name_len);
620
621 ad_len += (name_len + 2);
622 ptr += (name_len + 2);
623 }
624
625 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700626}
627
628static void update_scan_rsp_data(struct hci_request *req)
629{
630 struct hci_dev *hdev = req->hdev;
631 struct hci_cp_le_set_scan_rsp_data cp;
632 u8 len;
633
Johan Hedberg7751ef12013-10-19 23:38:15 +0300634 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700635 return;
636
637 memset(&cp, 0, sizeof(cp));
638
639 len = create_scan_rsp_data(hdev, cp.data);
640
Johan Hedbergeb438b52013-10-16 15:31:07 +0300641 if (hdev->scan_rsp_data_len == len &&
642 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700643 return;
644
Johan Hedbergeb438b52013-10-16 15:31:07 +0300645 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
646 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700647
648 cp.length = len;
649
650 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
651}
652
Johan Hedberg9a43e252013-10-20 19:00:07 +0300653static u8 get_adv_discov_flags(struct hci_dev *hdev)
654{
655 struct pending_cmd *cmd;
656
657 /* If there's a pending mgmt command the flags will not yet have
658 * their final values, so check for this first.
659 */
660 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
661 if (cmd) {
662 struct mgmt_mode *cp = cmd->param;
663 if (cp->val == 0x01)
664 return LE_AD_GENERAL;
665 else if (cp->val == 0x02)
666 return LE_AD_LIMITED;
667 } else {
668 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
669 return LE_AD_LIMITED;
670 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
671 return LE_AD_GENERAL;
672 }
673
674 return 0;
675}
676
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700677static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700678{
679 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700680
Johan Hedberg9a43e252013-10-20 19:00:07 +0300681 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700682
Johan Hedberge8340042014-01-30 11:16:50 -0800683 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700684 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700685
686 if (flags) {
687 BT_DBG("adv flags 0x%02x", flags);
688
689 ptr[0] = 2;
690 ptr[1] = EIR_FLAGS;
691 ptr[2] = flags;
692
693 ad_len += 3;
694 ptr += 3;
695 }
696
697 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
698 ptr[0] = 2;
699 ptr[1] = EIR_TX_POWER;
700 ptr[2] = (u8) hdev->adv_tx_power;
701
702 ad_len += 3;
703 ptr += 3;
704 }
705
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700706 return ad_len;
707}
708
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700709static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700710{
711 struct hci_dev *hdev = req->hdev;
712 struct hci_cp_le_set_adv_data cp;
713 u8 len;
714
Johan Hedberg10994ce2013-10-19 23:38:16 +0300715 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700716 return;
717
718 memset(&cp, 0, sizeof(cp));
719
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700720 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700721
722 if (hdev->adv_data_len == len &&
723 memcmp(cp.data, hdev->adv_data, len) == 0)
724 return;
725
726 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
727 hdev->adv_data_len = len;
728
729 cp.length = len;
730
731 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
732}
733
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300734static void create_eir(struct hci_dev *hdev, u8 *data)
735{
736 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300737 size_t name_len;
738
739 name_len = strlen(hdev->dev_name);
740
741 if (name_len > 0) {
742 /* EIR Data type */
743 if (name_len > 48) {
744 name_len = 48;
745 ptr[1] = EIR_NAME_SHORT;
746 } else
747 ptr[1] = EIR_NAME_COMPLETE;
748
749 /* EIR Data length */
750 ptr[0] = name_len + 1;
751
752 memcpy(ptr + 2, hdev->dev_name, name_len);
753
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300754 ptr += (name_len + 2);
755 }
756
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100757 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700758 ptr[0] = 2;
759 ptr[1] = EIR_TX_POWER;
760 ptr[2] = (u8) hdev->inq_tx_power;
761
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700762 ptr += 3;
763 }
764
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700765 if (hdev->devid_source > 0) {
766 ptr[0] = 9;
767 ptr[1] = EIR_DEVICE_ID;
768
769 put_unaligned_le16(hdev->devid_source, ptr + 2);
770 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
771 put_unaligned_le16(hdev->devid_product, ptr + 6);
772 put_unaligned_le16(hdev->devid_version, ptr + 8);
773
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700774 ptr += 10;
775 }
776
Johan Hedberg213202e2013-01-27 00:31:33 +0200777 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200778 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200779 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300780}
781
Johan Hedberg890ea892013-03-15 17:06:52 -0500782static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300783{
Johan Hedberg890ea892013-03-15 17:06:52 -0500784 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300785 struct hci_cp_write_eir cp;
786
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200787 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500788 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200789
Johan Hedberg976eb202012-10-24 21:12:01 +0300790 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500791 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300792
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200793 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500794 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300795
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200796 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500797 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300798
799 memset(&cp, 0, sizeof(cp));
800
801 create_eir(hdev, cp.data);
802
803 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500804 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300805
806 memcpy(hdev->eir, cp.data, sizeof(cp.data));
807
Johan Hedberg890ea892013-03-15 17:06:52 -0500808 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300809}
810
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200811static u8 get_service_classes(struct hci_dev *hdev)
812{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300813 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200814 u8 val = 0;
815
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300816 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200817 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200818
819 return val;
820}
821
Johan Hedberg890ea892013-03-15 17:06:52 -0500822static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200823{
Johan Hedberg890ea892013-03-15 17:06:52 -0500824 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200825 u8 cod[3];
826
827 BT_DBG("%s", hdev->name);
828
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200829 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500830 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200831
Johan Hedbergf87ea1d2013-10-19 23:38:17 +0300832 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
833 return;
834
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200835 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500836 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200837
838 cod[0] = hdev->minor_class;
839 cod[1] = hdev->major_class;
840 cod[2] = get_service_classes(hdev);
841
Marcel Holtmann6acd7db2013-10-15 06:33:53 -0700842 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
843 cod[1] |= 0x20;
844
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200845 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500846 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200847
Johan Hedberg890ea892013-03-15 17:06:52 -0500848 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200849}
850
Johan Hedberga4858cb2014-02-25 19:56:31 +0200851static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200852{
853 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200854
855 /* If there's a pending mgmt command the flag will not yet have
856 * it's final value, so check for this first.
857 */
858 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
859 if (cmd) {
860 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200861 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200862 }
863
Johan Hedberga4858cb2014-02-25 19:56:31 +0200864 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200865}
866
867static void enable_advertising(struct hci_request *req)
868{
869 struct hci_dev *hdev = req->hdev;
870 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200871 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200872 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200873
Johan Hedberg8d972502014-02-28 12:54:14 +0200874 /* Clear the HCI_ADVERTISING bit temporarily so that the
875 * hci_update_random_address knows that it's safe to go ahead
876 * and write a new random address. The flag will be set back on
877 * as soon as the SET_ADV_ENABLE HCI command completes.
878 */
879 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
880
Johan Hedberga4858cb2014-02-25 19:56:31 +0200881 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200882
Johan Hedberga4858cb2014-02-25 19:56:31 +0200883 /* Set require_privacy to true only when non-connectable
884 * advertising is used. In that case it is fine to use a
885 * non-resolvable private address.
886 */
887 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200888 return;
889
Marcel Holtmann41c90c12014-02-23 20:25:55 -0800890 memset(&cp, 0, sizeof(cp));
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700891 cp.min_interval = cpu_to_le16(0x0800);
892 cp.max_interval = cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +0200893 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200894 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200895 cp.channel_map = hdev->le_adv_channel_map;
896
897 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
898
899 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
900}
901
902static void disable_advertising(struct hci_request *req)
903{
904 u8 enable = 0x00;
905
906 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
907}
908
Johan Hedberg7d785252011-12-15 00:47:39 +0200909static void service_cache_off(struct work_struct *work)
910{
911 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300912 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -0500913 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +0200914
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200915 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +0200916 return;
917
Johan Hedberg890ea892013-03-15 17:06:52 -0500918 hci_req_init(&req, hdev);
919
Johan Hedberg7d785252011-12-15 00:47:39 +0200920 hci_dev_lock(hdev);
921
Johan Hedberg890ea892013-03-15 17:06:52 -0500922 update_eir(&req);
923 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +0200924
925 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -0500926
927 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +0200928}
929
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200930static void rpa_expired(struct work_struct *work)
931{
932 struct hci_dev *hdev = container_of(work, struct hci_dev,
933 rpa_expired.work);
934 struct hci_request req;
935
936 BT_DBG("");
937
938 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
939
940 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
941 hci_conn_num(hdev, LE_LINK) > 0)
942 return;
943
944 /* The generation of a new RPA and programming it into the
945 * controller happens in the enable_advertising() function.
946 */
947
948 hci_req_init(&req, hdev);
949
950 disable_advertising(&req);
951 enable_advertising(&req);
952
953 hci_req_run(&req, NULL);
954}
955
Johan Hedberg6a919082012-02-28 06:17:26 +0200956static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +0200957{
Johan Hedberg4f87da82012-03-02 19:55:56 +0200958 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +0200959 return;
960
Johan Hedberg4f87da82012-03-02 19:55:56 +0200961 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200962 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +0200963
Johan Hedberg4f87da82012-03-02 19:55:56 +0200964 /* Non-mgmt controlled devices get this bit set
965 * implicitly so that pairing works for them, however
966 * for mgmt we require user-space to explicitly enable
967 * it
968 */
969 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +0200970}
971
Johan Hedberg0f4e68c2012-02-28 17:18:30 +0200972static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300973 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +0200974{
975 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +0200976
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200977 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +0200978
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300979 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200980
Johan Hedberg03811012010-12-08 00:21:06 +0200981 memset(&rp, 0, sizeof(rp));
982
Johan Hedberg03811012010-12-08 00:21:06 +0200983 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200984
985 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200986 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200987
988 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
989 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
990
991 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +0200992
993 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +0200994 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +0200995
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300996 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200997
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200998 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300999 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001000}
1001
1002static void mgmt_pending_free(struct pending_cmd *cmd)
1003{
1004 sock_put(cmd->sk);
1005 kfree(cmd->param);
1006 kfree(cmd);
1007}
1008
1009static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001010 struct hci_dev *hdev, void *data,
1011 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001012{
1013 struct pending_cmd *cmd;
1014
Johan Hedbergfca20012014-06-28 17:54:05 +03001015 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001016 if (!cmd)
1017 return NULL;
1018
1019 cmd->opcode = opcode;
1020 cmd->index = hdev->id;
1021
Andre Guedes12b94562012-06-07 19:05:45 -03001022 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001023 if (!cmd->param) {
1024 kfree(cmd);
1025 return NULL;
1026 }
1027
1028 if (data)
1029 memcpy(cmd->param, data, len);
1030
1031 cmd->sk = sk;
1032 sock_hold(sk);
1033
1034 list_add(&cmd->list, &hdev->mgmt_pending);
1035
1036 return cmd;
1037}
1038
1039static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001040 void (*cb)(struct pending_cmd *cmd,
1041 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001042 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001043{
Andre Guedesa3d09352013-02-01 11:21:30 -03001044 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001045
Andre Guedesa3d09352013-02-01 11:21:30 -03001046 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001047 if (opcode > 0 && cmd->opcode != opcode)
1048 continue;
1049
1050 cb(cmd, data);
1051 }
1052}
1053
Johan Hedberg03811012010-12-08 00:21:06 +02001054static void mgmt_pending_remove(struct pending_cmd *cmd)
1055{
1056 list_del(&cmd->list);
1057 mgmt_pending_free(cmd);
1058}
1059
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001060static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001061{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001062 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001063
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001064 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001065 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001066}
1067
Johan Hedberg8b064a32014-02-24 14:52:22 +02001068static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1069{
1070 BT_DBG("%s status 0x%02x", hdev->name, status);
1071
Johan Hedberga3172b72014-02-28 09:33:44 +02001072 if (hci_conn_count(hdev) == 0) {
1073 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001074 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001075 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001076}
1077
Johan Hedberg21a60d32014-06-10 14:05:58 +03001078static void hci_stop_discovery(struct hci_request *req)
1079{
1080 struct hci_dev *hdev = req->hdev;
1081 struct hci_cp_remote_name_req_cancel cp;
1082 struct inquiry_entry *e;
1083
1084 switch (hdev->discovery.state) {
1085 case DISCOVERY_FINDING:
1086 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1087 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1088 } else {
1089 cancel_delayed_work(&hdev->le_scan_disable);
1090 hci_req_add_le_scan_disable(req);
1091 }
1092
1093 break;
1094
1095 case DISCOVERY_RESOLVING:
1096 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1097 NAME_PENDING);
1098 if (!e)
1099 return;
1100
1101 bacpy(&cp.bdaddr, &e->data.bdaddr);
1102 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1103 &cp);
1104
1105 break;
1106
1107 default:
1108 /* Passive scanning */
1109 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
1110 hci_req_add_le_scan_disable(req);
1111 break;
1112 }
1113}
1114
Johan Hedberg8b064a32014-02-24 14:52:22 +02001115static int clean_up_hci_state(struct hci_dev *hdev)
1116{
1117 struct hci_request req;
1118 struct hci_conn *conn;
1119
1120 hci_req_init(&req, hdev);
1121
1122 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1123 test_bit(HCI_PSCAN, &hdev->flags)) {
1124 u8 scan = 0x00;
1125 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1126 }
1127
1128 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1129 disable_advertising(&req);
1130
Johan Hedbergf8680f12014-06-10 14:05:59 +03001131 hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001132
1133 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1134 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001135 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001136
Johan Hedbergc9910d02014-02-27 14:35:12 +02001137 switch (conn->state) {
1138 case BT_CONNECTED:
1139 case BT_CONFIG:
1140 dc.handle = cpu_to_le16(conn->handle);
1141 dc.reason = 0x15; /* Terminated due to Power Off */
1142 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1143 break;
1144 case BT_CONNECT:
1145 if (conn->type == LE_LINK)
1146 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1147 0, NULL);
1148 else if (conn->type == ACL_LINK)
1149 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1150 6, &conn->dst);
1151 break;
1152 case BT_CONNECT2:
1153 bacpy(&rej.bdaddr, &conn->dst);
1154 rej.reason = 0x15; /* Terminated due to Power Off */
1155 if (conn->type == ACL_LINK)
1156 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1157 sizeof(rej), &rej);
1158 else if (conn->type == SCO_LINK)
1159 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1160 sizeof(rej), &rej);
1161 break;
1162 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001163 }
1164
1165 return hci_req_run(&req, clean_up_hci_complete);
1166}
1167
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001168static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001169 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001170{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001171 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001172 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001173 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001174
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001175 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001176
Johan Hedberga7e80f22013-01-09 16:05:19 +02001177 if (cp->val != 0x00 && cp->val != 0x01)
1178 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1179 MGMT_STATUS_INVALID_PARAMS);
1180
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001181 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001182
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001183 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1184 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1185 MGMT_STATUS_BUSY);
1186 goto failed;
1187 }
1188
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001189 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1190 cancel_delayed_work(&hdev->power_off);
1191
1192 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001193 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1194 data, len);
1195 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001196 goto failed;
1197 }
1198 }
1199
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001200 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001201 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001202 goto failed;
1203 }
1204
Johan Hedberg03811012010-12-08 00:21:06 +02001205 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1206 if (!cmd) {
1207 err = -ENOMEM;
1208 goto failed;
1209 }
1210
Johan Hedberg8b064a32014-02-24 14:52:22 +02001211 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001212 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001213 err = 0;
1214 } else {
1215 /* Disconnect connections, stop scans, etc */
1216 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001217 if (!err)
1218 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1219 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001220
Johan Hedberg8b064a32014-02-24 14:52:22 +02001221 /* ENODATA means there were no HCI commands queued */
1222 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001223 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001224 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1225 err = 0;
1226 }
1227 }
Johan Hedberg03811012010-12-08 00:21:06 +02001228
1229failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001230 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001231 return err;
1232}
1233
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001234static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
1235 struct sock *skip_sk)
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001236{
1237 struct sk_buff *skb;
1238 struct mgmt_hdr *hdr;
1239
Andre Guedes790eff42012-06-07 19:05:46 -03001240 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001241 if (!skb)
1242 return -ENOMEM;
1243
1244 hdr = (void *) skb_put(skb, sizeof(*hdr));
1245 hdr->opcode = cpu_to_le16(event);
1246 if (hdev)
1247 hdr->index = cpu_to_le16(hdev->id);
1248 else
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001249 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001250 hdr->len = cpu_to_le16(data_len);
1251
1252 if (data)
1253 memcpy(skb_put(skb, data_len), data, data_len);
1254
Marcel Holtmann97e0bde2012-02-22 13:49:28 +01001255 /* Time stamp */
1256 __net_timestamp(skb);
1257
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001258 hci_send_to_control(skb, skip_sk);
1259 kfree_skb(skb);
1260
1261 return 0;
1262}
1263
1264static int new_settings(struct hci_dev *hdev, struct sock *skip)
1265{
1266 __le32 ev;
1267
1268 ev = cpu_to_le32(get_current_settings(hdev));
1269
1270 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1271}
1272
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001273struct cmd_lookup {
1274 struct sock *sk;
1275 struct hci_dev *hdev;
1276 u8 mgmt_status;
1277};
1278
1279static void settings_rsp(struct pending_cmd *cmd, void *data)
1280{
1281 struct cmd_lookup *match = data;
1282
1283 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1284
1285 list_del(&cmd->list);
1286
1287 if (match->sk == NULL) {
1288 match->sk = cmd->sk;
1289 sock_hold(match->sk);
1290 }
1291
1292 mgmt_pending_free(cmd);
1293}
1294
1295static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1296{
1297 u8 *status = data;
1298
1299 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1300 mgmt_pending_remove(cmd);
1301}
1302
Johan Hedberge6fe7982013-10-02 15:45:22 +03001303static u8 mgmt_bredr_support(struct hci_dev *hdev)
1304{
1305 if (!lmp_bredr_capable(hdev))
1306 return MGMT_STATUS_NOT_SUPPORTED;
1307 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1308 return MGMT_STATUS_REJECTED;
1309 else
1310 return MGMT_STATUS_SUCCESS;
1311}
1312
1313static u8 mgmt_le_support(struct hci_dev *hdev)
1314{
1315 if (!lmp_le_capable(hdev))
1316 return MGMT_STATUS_NOT_SUPPORTED;
1317 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1318 return MGMT_STATUS_REJECTED;
1319 else
1320 return MGMT_STATUS_SUCCESS;
1321}
1322
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001323static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1324{
1325 struct pending_cmd *cmd;
1326 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001327 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001328 bool changed;
1329
1330 BT_DBG("status 0x%02x", status);
1331
1332 hci_dev_lock(hdev);
1333
1334 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1335 if (!cmd)
1336 goto unlock;
1337
1338 if (status) {
1339 u8 mgmt_err = mgmt_status(status);
1340 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001341 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001342 goto remove_cmd;
1343 }
1344
1345 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001346 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001347 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1348 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001349
1350 if (hdev->discov_timeout > 0) {
1351 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1352 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1353 to);
1354 }
1355 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001356 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1357 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001358 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001359
1360 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1361
1362 if (changed)
1363 new_settings(hdev, cmd->sk);
1364
Marcel Holtmann970ba522013-10-15 06:33:57 -07001365 /* When the discoverable mode gets changed, make sure
1366 * that class of device has the limited discoverable
1367 * bit correctly set.
1368 */
1369 hci_req_init(&req, hdev);
1370 update_class(&req);
1371 hci_req_run(&req, NULL);
1372
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001373remove_cmd:
1374 mgmt_pending_remove(cmd);
1375
1376unlock:
1377 hci_dev_unlock(hdev);
1378}
1379
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001380static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001381 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001382{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001383 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001384 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001385 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001386 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001387 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001388 int err;
1389
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001390 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001391
Johan Hedberg9a43e252013-10-20 19:00:07 +03001392 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1393 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001394 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001395 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001396
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001397 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001398 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1399 MGMT_STATUS_INVALID_PARAMS);
1400
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001401 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001402
1403 /* Disabling discoverable requires that no timeout is set,
1404 * and enabling limited discoverable requires a timeout.
1405 */
1406 if ((cp->val == 0x00 && timeout > 0) ||
1407 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001408 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001409 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001410
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001411 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001412
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001413 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001414 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001415 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001416 goto failed;
1417 }
1418
1419 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001420 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001421 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001422 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001423 goto failed;
1424 }
1425
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001426 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001427 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001428 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001429 goto failed;
1430 }
1431
1432 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001433 bool changed = false;
1434
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001435 /* Setting limited discoverable when powered off is
1436 * not a valid operation since it requires a timeout
1437 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1438 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001439 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1440 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1441 changed = true;
1442 }
1443
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001444 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001445 if (err < 0)
1446 goto failed;
1447
1448 if (changed)
1449 err = new_settings(hdev, sk);
1450
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001451 goto failed;
1452 }
1453
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001454 /* If the current mode is the same, then just update the timeout
1455 * value with the new value. And if only the timeout gets updated,
1456 * then no need for any HCI transactions.
1457 */
1458 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1459 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1460 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001461 cancel_delayed_work(&hdev->discov_off);
1462 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001463
Marcel Holtmann36261542013-10-15 08:28:51 -07001464 if (cp->val && hdev->discov_timeout > 0) {
1465 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001466 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001467 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001468 }
1469
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001470 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001471 goto failed;
1472 }
1473
1474 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1475 if (!cmd) {
1476 err = -ENOMEM;
1477 goto failed;
1478 }
1479
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001480 /* Cancel any potential discoverable timeout that might be
1481 * still active and store new timeout value. The arming of
1482 * the timeout happens in the complete handler.
1483 */
1484 cancel_delayed_work(&hdev->discov_off);
1485 hdev->discov_timeout = timeout;
1486
Johan Hedbergb456f872013-10-19 23:38:22 +03001487 /* Limited discoverable mode */
1488 if (cp->val == 0x02)
1489 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1490 else
1491 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1492
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001493 hci_req_init(&req, hdev);
1494
Johan Hedberg9a43e252013-10-20 19:00:07 +03001495 /* The procedure for LE-only controllers is much simpler - just
1496 * update the advertising data.
1497 */
1498 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1499 goto update_ad;
1500
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001501 scan = SCAN_PAGE;
1502
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001503 if (cp->val) {
1504 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001505
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001506 if (cp->val == 0x02) {
1507 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001508 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001509 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1510 hci_cp.iac_lap[1] = 0x8b;
1511 hci_cp.iac_lap[2] = 0x9e;
1512 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1513 hci_cp.iac_lap[4] = 0x8b;
1514 hci_cp.iac_lap[5] = 0x9e;
1515 } else {
1516 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001517 hci_cp.num_iac = 1;
1518 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1519 hci_cp.iac_lap[1] = 0x8b;
1520 hci_cp.iac_lap[2] = 0x9e;
1521 }
1522
1523 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1524 (hci_cp.num_iac * 3) + 1, &hci_cp);
1525
1526 scan |= SCAN_INQUIRY;
1527 } else {
1528 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1529 }
1530
1531 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001532
Johan Hedberg9a43e252013-10-20 19:00:07 +03001533update_ad:
1534 update_adv_data(&req);
1535
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001536 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001537 if (err < 0)
1538 mgmt_pending_remove(cmd);
1539
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001540failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001541 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001542 return err;
1543}
1544
Johan Hedberg406d7802013-03-15 17:07:09 -05001545static void write_fast_connectable(struct hci_request *req, bool enable)
1546{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001547 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001548 struct hci_cp_write_page_scan_activity acp;
1549 u8 type;
1550
Johan Hedberg547003b2013-10-21 16:51:53 +03001551 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1552 return;
1553
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001554 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1555 return;
1556
Johan Hedberg406d7802013-03-15 17:07:09 -05001557 if (enable) {
1558 type = PAGE_SCAN_TYPE_INTERLACED;
1559
1560 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001561 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001562 } else {
1563 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1564
1565 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001566 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001567 }
1568
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001569 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001570
Johan Hedbergbd98b992013-03-15 17:07:13 -05001571 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1572 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1573 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1574 sizeof(acp), &acp);
1575
1576 if (hdev->page_scan_type != type)
1577 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001578}
1579
Johan Hedberg2b76f452013-03-15 17:07:04 -05001580static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1581{
1582 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001583 struct mgmt_mode *cp;
1584 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001585
1586 BT_DBG("status 0x%02x", status);
1587
1588 hci_dev_lock(hdev);
1589
1590 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1591 if (!cmd)
1592 goto unlock;
1593
Johan Hedberg37438c12013-10-14 16:20:05 +03001594 if (status) {
1595 u8 mgmt_err = mgmt_status(status);
1596 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1597 goto remove_cmd;
1598 }
1599
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001600 cp = cmd->param;
1601 if (cp->val)
1602 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1603 else
1604 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1605
Johan Hedberg2b76f452013-03-15 17:07:04 -05001606 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1607
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001608 if (changed)
1609 new_settings(hdev, cmd->sk);
1610
Johan Hedberg37438c12013-10-14 16:20:05 +03001611remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001612 mgmt_pending_remove(cmd);
1613
1614unlock:
1615 hci_dev_unlock(hdev);
1616}
1617
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001618static int set_connectable_update_settings(struct hci_dev *hdev,
1619 struct sock *sk, u8 val)
1620{
1621 bool changed = false;
1622 int err;
1623
1624 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1625 changed = true;
1626
1627 if (val) {
1628 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1629 } else {
1630 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1631 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1632 }
1633
1634 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1635 if (err < 0)
1636 return err;
1637
1638 if (changed)
1639 return new_settings(hdev, sk);
1640
1641 return 0;
1642}
1643
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001644static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001645 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001646{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001647 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001648 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001649 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001650 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001651 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001652
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001653 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001654
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001655 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1656 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001657 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001658 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001659
Johan Hedberga7e80f22013-01-09 16:05:19 +02001660 if (cp->val != 0x00 && cp->val != 0x01)
1661 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1662 MGMT_STATUS_INVALID_PARAMS);
1663
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001664 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001665
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001666 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001667 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001668 goto failed;
1669 }
1670
1671 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001672 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001673 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001674 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001675 goto failed;
1676 }
1677
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001678 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1679 if (!cmd) {
1680 err = -ENOMEM;
1681 goto failed;
1682 }
1683
Johan Hedberg2b76f452013-03-15 17:07:04 -05001684 hci_req_init(&req, hdev);
1685
Johan Hedberg9a43e252013-10-20 19:00:07 +03001686 /* If BR/EDR is not enabled and we disable advertising as a
1687 * by-product of disabling connectable, we need to update the
1688 * advertising flags.
1689 */
1690 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1691 if (!cp->val) {
1692 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1693 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1694 }
1695 update_adv_data(&req);
1696 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001697 if (cp->val) {
1698 scan = SCAN_PAGE;
1699 } else {
1700 scan = 0;
1701
1702 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001703 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001704 cancel_delayed_work(&hdev->discov_off);
1705 }
1706
1707 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1708 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001709
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001710 /* If we're going from non-connectable to connectable or
1711 * vice-versa when fast connectable is enabled ensure that fast
1712 * connectable gets disabled. write_fast_connectable won't do
1713 * anything if the page scan parameters are already what they
1714 * should be.
1715 */
1716 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001717 write_fast_connectable(&req, false);
1718
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001719 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1720 hci_conn_num(hdev, LE_LINK) == 0) {
1721 disable_advertising(&req);
1722 enable_advertising(&req);
1723 }
1724
Johan Hedberg2b76f452013-03-15 17:07:04 -05001725 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001726 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001727 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001728 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001729 err = set_connectable_update_settings(hdev, sk,
1730 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001731 goto failed;
1732 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001733
1734failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001735 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001736 return err;
1737}
1738
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001739static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001740 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001741{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001742 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001743 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001744 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001745
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001746 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001747
Johan Hedberga7e80f22013-01-09 16:05:19 +02001748 if (cp->val != 0x00 && cp->val != 0x01)
1749 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1750 MGMT_STATUS_INVALID_PARAMS);
1751
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001752 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001753
1754 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001755 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001756 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001757 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001758
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001759 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001760 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001761 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001762
Marcel Holtmann55594352013-10-06 16:11:57 -07001763 if (changed)
1764 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001765
Marcel Holtmann55594352013-10-06 16:11:57 -07001766unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001767 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001768 return err;
1769}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001770
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001771static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1772 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001773{
1774 struct mgmt_mode *cp = data;
1775 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001776 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001777 int err;
1778
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001779 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001780
Johan Hedberge6fe7982013-10-02 15:45:22 +03001781 status = mgmt_bredr_support(hdev);
1782 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001783 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001784 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001785
Johan Hedberga7e80f22013-01-09 16:05:19 +02001786 if (cp->val != 0x00 && cp->val != 0x01)
1787 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1788 MGMT_STATUS_INVALID_PARAMS);
1789
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001790 hci_dev_lock(hdev);
1791
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001792 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001793 bool changed = false;
1794
1795 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001796 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001797 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1798 changed = true;
1799 }
1800
1801 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1802 if (err < 0)
1803 goto failed;
1804
1805 if (changed)
1806 err = new_settings(hdev, sk);
1807
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001808 goto failed;
1809 }
1810
1811 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001812 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001813 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001814 goto failed;
1815 }
1816
1817 val = !!cp->val;
1818
1819 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1820 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1821 goto failed;
1822 }
1823
1824 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1825 if (!cmd) {
1826 err = -ENOMEM;
1827 goto failed;
1828 }
1829
1830 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1831 if (err < 0) {
1832 mgmt_pending_remove(cmd);
1833 goto failed;
1834 }
1835
1836failed:
1837 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001838 return err;
1839}
1840
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001841static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001842{
1843 struct mgmt_mode *cp = data;
1844 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001845 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001846 int err;
1847
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001848 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001849
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001850 status = mgmt_bredr_support(hdev);
1851 if (status)
1852 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1853
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001854 if (!lmp_ssp_capable(hdev))
1855 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1856 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001857
Johan Hedberga7e80f22013-01-09 16:05:19 +02001858 if (cp->val != 0x00 && cp->val != 0x01)
1859 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1860 MGMT_STATUS_INVALID_PARAMS);
1861
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001862 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02001863
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001864 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001865 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001866
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001867 if (cp->val) {
1868 changed = !test_and_set_bit(HCI_SSP_ENABLED,
1869 &hdev->dev_flags);
1870 } else {
1871 changed = test_and_clear_bit(HCI_SSP_ENABLED,
1872 &hdev->dev_flags);
1873 if (!changed)
1874 changed = test_and_clear_bit(HCI_HS_ENABLED,
1875 &hdev->dev_flags);
1876 else
1877 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001878 }
1879
1880 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1881 if (err < 0)
1882 goto failed;
1883
1884 if (changed)
1885 err = new_settings(hdev, sk);
1886
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001887 goto failed;
1888 }
1889
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001890 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
1891 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01001892 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1893 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001894 goto failed;
1895 }
1896
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001897 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001898 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1899 goto failed;
1900 }
1901
1902 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
1903 if (!cmd) {
1904 err = -ENOMEM;
1905 goto failed;
1906 }
1907
Johan Hedberg37699722014-06-24 14:00:27 +03001908 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
1909 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
1910 sizeof(cp->val), &cp->val);
1911
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001912 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001913 if (err < 0) {
1914 mgmt_pending_remove(cmd);
1915 goto failed;
1916 }
1917
1918failed:
1919 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001920 return err;
1921}
1922
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001923static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001924{
1925 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07001926 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001927 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07001928 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001929
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001930 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001931
Johan Hedberge6fe7982013-10-02 15:45:22 +03001932 status = mgmt_bredr_support(hdev);
1933 if (status)
1934 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001935
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001936 if (!lmp_ssp_capable(hdev))
1937 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1938 MGMT_STATUS_NOT_SUPPORTED);
1939
1940 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
1941 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1942 MGMT_STATUS_REJECTED);
1943
Johan Hedberga7e80f22013-01-09 16:05:19 +02001944 if (cp->val != 0x00 && cp->val != 0x01)
1945 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1946 MGMT_STATUS_INVALID_PARAMS);
1947
Marcel Holtmannee392692013-10-01 22:59:23 -07001948 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001949
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001950 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07001951 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001952 } else {
1953 if (hdev_is_powered(hdev)) {
1954 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1955 MGMT_STATUS_REJECTED);
1956 goto unlock;
1957 }
1958
Marcel Holtmannee392692013-10-01 22:59:23 -07001959 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001960 }
Marcel Holtmannee392692013-10-01 22:59:23 -07001961
1962 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
1963 if (err < 0)
1964 goto unlock;
1965
1966 if (changed)
1967 err = new_settings(hdev, sk);
1968
1969unlock:
1970 hci_dev_unlock(hdev);
1971 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001972}
1973
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001974static void le_enable_complete(struct hci_dev *hdev, u8 status)
1975{
1976 struct cmd_lookup match = { NULL, hdev };
1977
1978 if (status) {
1979 u8 mgmt_err = mgmt_status(status);
1980
1981 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
1982 &mgmt_err);
1983 return;
1984 }
1985
1986 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
1987
1988 new_settings(hdev, match.sk);
1989
1990 if (match.sk)
1991 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001992
1993 /* Make sure the controller has a good default for
1994 * advertising data. Restrict the update to when LE
1995 * has actually been enabled. During power on, the
1996 * update in powered_update_hci will take care of it.
1997 */
1998 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1999 struct hci_request req;
2000
2001 hci_dev_lock(hdev);
2002
2003 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002004 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002005 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002006 hci_req_run(&req, NULL);
2007
2008 hci_dev_unlock(hdev);
2009 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002010}
2011
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002012static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002013{
2014 struct mgmt_mode *cp = data;
2015 struct hci_cp_write_le_host_supported hci_cp;
2016 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002017 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002018 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002019 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002020
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002021 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002022
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002023 if (!lmp_le_capable(hdev))
2024 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2025 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002026
Johan Hedberga7e80f22013-01-09 16:05:19 +02002027 if (cp->val != 0x00 && cp->val != 0x01)
2028 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2029 MGMT_STATUS_INVALID_PARAMS);
2030
Johan Hedbergc73eee92013-04-19 18:35:21 +03002031 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002032 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002033 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2034 MGMT_STATUS_REJECTED);
2035
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002036 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002037
2038 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002039 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002040
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002041 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002042 bool changed = false;
2043
2044 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2045 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2046 changed = true;
2047 }
2048
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002049 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2050 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002051 changed = true;
2052 }
2053
Johan Hedberg06199cf2012-02-22 16:37:11 +02002054 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2055 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002056 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002057
2058 if (changed)
2059 err = new_settings(hdev, sk);
2060
Johan Hedberg1de028c2012-02-29 19:55:35 -08002061 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002062 }
2063
Johan Hedberg4375f102013-09-25 13:26:10 +03002064 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2065 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002066 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002067 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002068 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002069 }
2070
2071 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2072 if (!cmd) {
2073 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002074 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002075 }
2076
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002077 hci_req_init(&req, hdev);
2078
Johan Hedberg06199cf2012-02-22 16:37:11 +02002079 memset(&hci_cp, 0, sizeof(hci_cp));
2080
2081 if (val) {
2082 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002083 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002084 } else {
2085 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2086 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002087 }
2088
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002089 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2090 &hci_cp);
2091
2092 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302093 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002094 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002095
Johan Hedberg1de028c2012-02-29 19:55:35 -08002096unlock:
2097 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002098 return err;
2099}
2100
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002101/* This is a helper function to test for pending mgmt commands that can
2102 * cause CoD or EIR HCI commands. We can only allow one such pending
2103 * mgmt command at a time since otherwise we cannot easily track what
2104 * the current values are, will be, and based on that calculate if a new
2105 * HCI command needs to be sent and if yes with what value.
2106 */
2107static bool pending_eir_or_class(struct hci_dev *hdev)
2108{
2109 struct pending_cmd *cmd;
2110
2111 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2112 switch (cmd->opcode) {
2113 case MGMT_OP_ADD_UUID:
2114 case MGMT_OP_REMOVE_UUID:
2115 case MGMT_OP_SET_DEV_CLASS:
2116 case MGMT_OP_SET_POWERED:
2117 return true;
2118 }
2119 }
2120
2121 return false;
2122}
2123
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002124static const u8 bluetooth_base_uuid[] = {
2125 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2126 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2127};
2128
2129static u8 get_uuid_size(const u8 *uuid)
2130{
2131 u32 val;
2132
2133 if (memcmp(uuid, bluetooth_base_uuid, 12))
2134 return 128;
2135
2136 val = get_unaligned_le32(&uuid[12]);
2137 if (val > 0xffff)
2138 return 32;
2139
2140 return 16;
2141}
2142
Johan Hedberg92da6092013-03-15 17:06:55 -05002143static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2144{
2145 struct pending_cmd *cmd;
2146
2147 hci_dev_lock(hdev);
2148
2149 cmd = mgmt_pending_find(mgmt_op, hdev);
2150 if (!cmd)
2151 goto unlock;
2152
2153 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2154 hdev->dev_class, 3);
2155
2156 mgmt_pending_remove(cmd);
2157
2158unlock:
2159 hci_dev_unlock(hdev);
2160}
2161
2162static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2163{
2164 BT_DBG("status 0x%02x", status);
2165
2166 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2167}
2168
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002169static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002170{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002171 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002172 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002173 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002174 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002175 int err;
2176
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002177 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002178
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002179 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002180
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002181 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002182 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002183 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002184 goto failed;
2185 }
2186
Andre Guedes92c4c202012-06-07 19:05:44 -03002187 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002188 if (!uuid) {
2189 err = -ENOMEM;
2190 goto failed;
2191 }
2192
2193 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002194 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002195 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002196
Johan Hedbergde66aa62013-01-27 00:31:27 +02002197 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002198
Johan Hedberg890ea892013-03-15 17:06:52 -05002199 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002200
Johan Hedberg890ea892013-03-15 17:06:52 -05002201 update_class(&req);
2202 update_eir(&req);
2203
Johan Hedberg92da6092013-03-15 17:06:55 -05002204 err = hci_req_run(&req, add_uuid_complete);
2205 if (err < 0) {
2206 if (err != -ENODATA)
2207 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002208
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002209 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002210 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002211 goto failed;
2212 }
2213
2214 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002215 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002216 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002217 goto failed;
2218 }
2219
2220 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002221
2222failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002223 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002224 return err;
2225}
2226
Johan Hedberg24b78d02012-02-23 23:24:30 +02002227static bool enable_service_cache(struct hci_dev *hdev)
2228{
2229 if (!hdev_is_powered(hdev))
2230 return false;
2231
2232 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002233 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2234 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002235 return true;
2236 }
2237
2238 return false;
2239}
2240
Johan Hedberg92da6092013-03-15 17:06:55 -05002241static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2242{
2243 BT_DBG("status 0x%02x", status);
2244
2245 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2246}
2247
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002248static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002249 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002250{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002251 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002252 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002253 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002254 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 -05002255 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002256 int err, found;
2257
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002258 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002259
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002260 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002261
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002262 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002263 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002264 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002265 goto unlock;
2266 }
2267
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002268 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002269 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002270
Johan Hedberg24b78d02012-02-23 23:24:30 +02002271 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002272 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002273 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002274 goto unlock;
2275 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002276
Johan Hedberg9246a862012-02-23 21:33:16 +02002277 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002278 }
2279
2280 found = 0;
2281
Johan Hedberg056341c2013-01-27 00:31:30 +02002282 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002283 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2284 continue;
2285
2286 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002287 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002288 found++;
2289 }
2290
2291 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002292 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002293 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002294 goto unlock;
2295 }
2296
Johan Hedberg9246a862012-02-23 21:33:16 +02002297update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002298 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002299
Johan Hedberg890ea892013-03-15 17:06:52 -05002300 update_class(&req);
2301 update_eir(&req);
2302
Johan Hedberg92da6092013-03-15 17:06:55 -05002303 err = hci_req_run(&req, remove_uuid_complete);
2304 if (err < 0) {
2305 if (err != -ENODATA)
2306 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002307
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002308 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002309 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002310 goto unlock;
2311 }
2312
2313 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002314 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002315 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002316 goto unlock;
2317 }
2318
2319 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002320
2321unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002322 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002323 return err;
2324}
2325
Johan Hedberg92da6092013-03-15 17:06:55 -05002326static void set_class_complete(struct hci_dev *hdev, u8 status)
2327{
2328 BT_DBG("status 0x%02x", status);
2329
2330 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2331}
2332
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002333static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002334 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002335{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002336 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002337 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002338 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002339 int err;
2340
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002341 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002342
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002343 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002344 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2345 MGMT_STATUS_NOT_SUPPORTED);
2346
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002347 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002348
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002349 if (pending_eir_or_class(hdev)) {
2350 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2351 MGMT_STATUS_BUSY);
2352 goto unlock;
2353 }
2354
2355 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2356 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2357 MGMT_STATUS_INVALID_PARAMS);
2358 goto unlock;
2359 }
2360
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002361 hdev->major_class = cp->major;
2362 hdev->minor_class = cp->minor;
2363
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002364 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002365 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002366 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002367 goto unlock;
2368 }
2369
Johan Hedberg890ea892013-03-15 17:06:52 -05002370 hci_req_init(&req, hdev);
2371
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002372 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002373 hci_dev_unlock(hdev);
2374 cancel_delayed_work_sync(&hdev->service_cache);
2375 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002376 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002377 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002378
Johan Hedberg890ea892013-03-15 17:06:52 -05002379 update_class(&req);
2380
Johan Hedberg92da6092013-03-15 17:06:55 -05002381 err = hci_req_run(&req, set_class_complete);
2382 if (err < 0) {
2383 if (err != -ENODATA)
2384 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002385
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002386 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002387 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002388 goto unlock;
2389 }
2390
2391 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002392 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002393 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002394 goto unlock;
2395 }
2396
2397 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002398
Johan Hedbergb5235a62012-02-21 14:32:24 +02002399unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002400 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002401 return err;
2402}
2403
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002404static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002405 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002406{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002407 struct mgmt_cp_load_link_keys *cp = data;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002408 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002409 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002410 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002411
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002412 BT_DBG("request for %s", hdev->name);
2413
2414 if (!lmp_bredr_capable(hdev))
2415 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2416 MGMT_STATUS_NOT_SUPPORTED);
2417
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002418 key_count = __le16_to_cpu(cp->key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002419
Johan Hedberg86742e12011-11-07 23:13:38 +02002420 expected_len = sizeof(*cp) + key_count *
2421 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002422 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002423 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002424 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002425 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002426 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002427 }
2428
Johan Hedberg4ae14302013-01-20 14:27:13 +02002429 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2430 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2431 MGMT_STATUS_INVALID_PARAMS);
2432
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002433 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002434 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002435
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002436 for (i = 0; i < key_count; i++) {
2437 struct mgmt_link_key_info *key = &cp->keys[i];
2438
Marcel Holtmann8e991132014-01-10 02:07:25 -08002439 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002440 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2441 MGMT_STATUS_INVALID_PARAMS);
2442 }
2443
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002444 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002445
2446 hci_link_keys_clear(hdev);
2447
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002448 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002449 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2450 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002451 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002452 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2453 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002454
2455 if (changed)
2456 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002457
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002458 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002459 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002460
Johan Hedberg58e92932014-06-24 14:00:26 +03002461 /* Always ignore debug keys and require a new pairing if
2462 * the user wants to use them.
2463 */
2464 if (key->type == HCI_LK_DEBUG_COMBINATION)
2465 continue;
2466
Johan Hedberg7652ff62014-06-24 13:15:49 +03002467 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2468 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002469 }
2470
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002471 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002472
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002473 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002474
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002475 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002476}
2477
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002478static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002479 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002480{
2481 struct mgmt_ev_device_unpaired ev;
2482
2483 bacpy(&ev.addr.bdaddr, bdaddr);
2484 ev.addr.type = addr_type;
2485
2486 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002487 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002488}
2489
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002490static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002491 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002492{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002493 struct mgmt_cp_unpair_device *cp = data;
2494 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002495 struct hci_cp_disconnect dc;
2496 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002497 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002498 int err;
2499
Johan Hedberga8a1d192011-11-10 15:54:38 +02002500 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002501 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2502 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002503
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002504 if (!bdaddr_type_is_valid(cp->addr.type))
2505 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2506 MGMT_STATUS_INVALID_PARAMS,
2507 &rp, sizeof(rp));
2508
Johan Hedberg118da702013-01-20 14:27:20 +02002509 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2510 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2511 MGMT_STATUS_INVALID_PARAMS,
2512 &rp, sizeof(rp));
2513
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002514 hci_dev_lock(hdev);
2515
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002516 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002517 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002518 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002519 goto unlock;
2520 }
2521
Johan Hedberge0b2b272014-02-18 17:14:31 +02002522 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002523 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002524 } else {
2525 u8 addr_type;
2526
2527 if (cp->addr.type == BDADDR_LE_PUBLIC)
2528 addr_type = ADDR_LE_DEV_PUBLIC;
2529 else
2530 addr_type = ADDR_LE_DEV_RANDOM;
2531
Johan Hedberga7ec7332014-02-18 17:14:35 +02002532 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2533
Andre Guedesa9b0a042014-02-26 20:21:52 -03002534 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2535
Johan Hedberge0b2b272014-02-18 17:14:31 +02002536 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2537 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002538
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002539 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002540 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002541 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002542 goto unlock;
2543 }
2544
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002545 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002546 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002547 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002548 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002549 else
2550 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002551 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002552 } else {
2553 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002554 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002555
Johan Hedberga8a1d192011-11-10 15:54:38 +02002556 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002557 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002558 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002559 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002560 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002561 }
2562
Johan Hedberg124f6e32012-02-09 13:50:12 +02002563 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002564 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002565 if (!cmd) {
2566 err = -ENOMEM;
2567 goto unlock;
2568 }
2569
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002570 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002571 dc.reason = 0x13; /* Remote User Terminated Connection */
2572 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2573 if (err < 0)
2574 mgmt_pending_remove(cmd);
2575
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002576unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002577 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002578 return err;
2579}
2580
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002581static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002582 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002583{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002584 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002585 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002586 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002587 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002588 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002589 int err;
2590
2591 BT_DBG("");
2592
Johan Hedberg06a63b12013-01-20 14:27:21 +02002593 memset(&rp, 0, sizeof(rp));
2594 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2595 rp.addr.type = cp->addr.type;
2596
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002597 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002598 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2599 MGMT_STATUS_INVALID_PARAMS,
2600 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002601
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002602 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002603
2604 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002605 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2606 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002607 goto failed;
2608 }
2609
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002610 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002611 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2612 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002613 goto failed;
2614 }
2615
Andre Guedes591f47f2012-04-24 21:02:49 -03002616 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002617 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2618 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002619 else
2620 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002621
Vishal Agarwalf9607272012-06-13 05:32:43 +05302622 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002623 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2624 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002625 goto failed;
2626 }
2627
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002628 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002629 if (!cmd) {
2630 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002631 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002632 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002633
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002634 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002635 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002636
2637 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2638 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002639 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002640
2641failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002642 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002643 return err;
2644}
2645
Andre Guedes57c14772012-04-24 21:02:50 -03002646static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002647{
2648 switch (link_type) {
2649 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002650 switch (addr_type) {
2651 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002652 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002653
Johan Hedberg48264f02011-11-09 13:58:58 +02002654 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002655 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002656 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002657 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002658
Johan Hedberg4c659c32011-11-07 23:13:39 +02002659 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002660 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002661 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002662 }
2663}
2664
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002665static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2666 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002667{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002668 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002669 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002670 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002671 int err;
2672 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002673
2674 BT_DBG("");
2675
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002676 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002677
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002678 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002679 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002680 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002681 goto unlock;
2682 }
2683
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002684 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002685 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2686 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002687 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002688 }
2689
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002690 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002691 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002692 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002693 err = -ENOMEM;
2694 goto unlock;
2695 }
2696
Johan Hedberg2784eb42011-01-21 13:56:35 +02002697 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002698 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002699 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2700 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002701 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002702 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002703 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002704 continue;
2705 i++;
2706 }
2707
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002708 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002709
Johan Hedberg4c659c32011-11-07 23:13:39 +02002710 /* Recalculate length in case of filtered SCO connections, etc */
2711 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002712
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002713 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002714 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002715
Johan Hedberga38528f2011-01-22 06:46:43 +02002716 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002717
2718unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002719 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002720 return err;
2721}
2722
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002723static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002724 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002725{
2726 struct pending_cmd *cmd;
2727 int err;
2728
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002729 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002730 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002731 if (!cmd)
2732 return -ENOMEM;
2733
Johan Hedbergd8457692012-02-17 14:24:57 +02002734 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002735 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002736 if (err < 0)
2737 mgmt_pending_remove(cmd);
2738
2739 return err;
2740}
2741
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002742static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002743 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002744{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002745 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002746 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002747 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002748 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002749 int err;
2750
2751 BT_DBG("");
2752
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002753 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002754
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002755 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002756 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002757 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002758 goto failed;
2759 }
2760
Johan Hedbergd8457692012-02-17 14:24:57 +02002761 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002762 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002763 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002764 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002765 goto failed;
2766 }
2767
2768 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002769 struct mgmt_cp_pin_code_neg_reply ncp;
2770
2771 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002772
2773 BT_ERR("PIN code is not 16 bytes long");
2774
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002775 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002776 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002777 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002778 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002779
2780 goto failed;
2781 }
2782
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002783 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002784 if (!cmd) {
2785 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002786 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002787 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002788
Johan Hedbergd8457692012-02-17 14:24:57 +02002789 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002790 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002791 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002792
2793 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2794 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002795 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002796
2797failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002798 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002799 return err;
2800}
2801
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002802static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2803 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002804{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002805 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002806
2807 BT_DBG("");
2808
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002809 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2810 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2811 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2812
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002813 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002814
2815 hdev->io_capability = cp->io_capability;
2816
2817 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002818 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002819
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002820 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002821
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002822 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2823 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002824}
2825
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002826static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002827{
2828 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002829 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002830
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002831 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002832 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2833 continue;
2834
Johan Hedberge9a416b2011-02-19 12:05:56 -03002835 if (cmd->user_data != conn)
2836 continue;
2837
2838 return cmd;
2839 }
2840
2841 return NULL;
2842}
2843
2844static void pairing_complete(struct pending_cmd *cmd, u8 status)
2845{
2846 struct mgmt_rp_pair_device rp;
2847 struct hci_conn *conn = cmd->user_data;
2848
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02002849 bacpy(&rp.addr.bdaddr, &conn->dst);
2850 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002851
Johan Hedbergaee9b2182012-02-18 15:07:59 +02002852 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002853 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002854
2855 /* So we don't get further callbacks for this connection */
2856 conn->connect_cfm_cb = NULL;
2857 conn->security_cfm_cb = NULL;
2858 conn->disconn_cfm_cb = NULL;
2859
David Herrmann76a68ba2013-04-06 20:28:37 +02002860 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002861
Johan Hedberga664b5b2011-02-19 12:06:02 -03002862 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002863}
2864
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002865void mgmt_smp_complete(struct hci_conn *conn, bool complete)
2866{
2867 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
2868 struct pending_cmd *cmd;
2869
2870 cmd = find_pairing(conn);
2871 if (cmd)
2872 pairing_complete(cmd, status);
2873}
2874
Johan Hedberge9a416b2011-02-19 12:05:56 -03002875static void pairing_complete_cb(struct hci_conn *conn, u8 status)
2876{
2877 struct pending_cmd *cmd;
2878
2879 BT_DBG("status %u", status);
2880
Johan Hedberg56e5cb82011-11-08 20:40:16 +02002881 cmd = find_pairing(conn);
2882 if (!cmd)
2883 BT_DBG("Unable to find a pending command");
2884 else
Johan Hedberge2113262012-02-18 15:20:03 +02002885 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002886}
2887
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002888static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05302889{
2890 struct pending_cmd *cmd;
2891
2892 BT_DBG("status %u", status);
2893
2894 if (!status)
2895 return;
2896
2897 cmd = find_pairing(conn);
2898 if (!cmd)
2899 BT_DBG("Unable to find a pending command");
2900 else
2901 pairing_complete(cmd, mgmt_status(status));
2902}
2903
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002904static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002905 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002906{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002907 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02002908 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002909 struct pending_cmd *cmd;
2910 u8 sec_level, auth_type;
2911 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002912 int err;
2913
2914 BT_DBG("");
2915
Szymon Jancf950a30e2013-01-18 12:48:07 +01002916 memset(&rp, 0, sizeof(rp));
2917 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2918 rp.addr.type = cp->addr.type;
2919
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002920 if (!bdaddr_type_is_valid(cp->addr.type))
2921 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2922 MGMT_STATUS_INVALID_PARAMS,
2923 &rp, sizeof(rp));
2924
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002925 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
2926 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2927 MGMT_STATUS_INVALID_PARAMS,
2928 &rp, sizeof(rp));
2929
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002930 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002931
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002932 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01002933 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2934 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002935 goto unlock;
2936 }
2937
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002938 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02002939 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002940
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002941 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03002942 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
2943 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002944 } else {
2945 u8 addr_type;
2946
2947 /* Convert from L2CAP channel address type to HCI address type
2948 */
2949 if (cp->addr.type == BDADDR_LE_PUBLIC)
2950 addr_type = ADDR_LE_DEV_PUBLIC;
2951 else
2952 addr_type = ADDR_LE_DEV_RANDOM;
2953
Marcel Holtmann7c264b12014-06-30 12:34:40 +02002954 /* When pairing a new device, it is expected to remember
2955 * this device for future connections. Adding the connection
2956 * parameter information ahead of time allows tracking
2957 * of the slave preferred values and will speed up any
2958 * further connection establishment.
2959 *
2960 * If connection parameters already exist, then they
2961 * will be kept and this function does nothing.
2962 */
2963 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
2964
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002965 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03002966 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002967 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002968
Ville Tervo30e76272011-02-22 16:10:53 -03002969 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002970 int status;
2971
2972 if (PTR_ERR(conn) == -EBUSY)
2973 status = MGMT_STATUS_BUSY;
2974 else
2975 status = MGMT_STATUS_CONNECT_FAILED;
2976
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002977 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002978 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002979 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002980 goto unlock;
2981 }
2982
2983 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02002984 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002985 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002986 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002987 goto unlock;
2988 }
2989
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002990 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002991 if (!cmd) {
2992 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02002993 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002994 goto unlock;
2995 }
2996
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002997 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002998 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002999 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003000 conn->security_cfm_cb = pairing_complete_cb;
3001 conn->disconn_cfm_cb = pairing_complete_cb;
3002 } else {
3003 conn->connect_cfm_cb = le_pairing_complete_cb;
3004 conn->security_cfm_cb = le_pairing_complete_cb;
3005 conn->disconn_cfm_cb = le_pairing_complete_cb;
3006 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003007
Johan Hedberge9a416b2011-02-19 12:05:56 -03003008 conn->io_capability = cp->io_cap;
3009 cmd->user_data = conn;
3010
3011 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003012 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003013 pairing_complete(cmd, 0);
3014
3015 err = 0;
3016
3017unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003018 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003019 return err;
3020}
3021
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003022static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3023 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003024{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003025 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003026 struct pending_cmd *cmd;
3027 struct hci_conn *conn;
3028 int err;
3029
3030 BT_DBG("");
3031
Johan Hedberg28424702012-02-02 04:02:29 +02003032 hci_dev_lock(hdev);
3033
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003034 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003035 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003036 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003037 goto unlock;
3038 }
3039
Johan Hedberg28424702012-02-02 04:02:29 +02003040 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3041 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003042 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003043 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003044 goto unlock;
3045 }
3046
3047 conn = cmd->user_data;
3048
3049 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003050 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003051 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003052 goto unlock;
3053 }
3054
3055 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3056
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003057 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003058 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003059unlock:
3060 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003061 return err;
3062}
3063
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003064static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003065 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003066 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003067{
Johan Hedberga5c29682011-02-19 12:05:57 -03003068 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003069 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003070 int err;
3071
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003072 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003073
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003074 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003075 err = cmd_complete(sk, hdev->id, mgmt_op,
3076 MGMT_STATUS_NOT_POWERED, addr,
3077 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003078 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003079 }
3080
Johan Hedberg1707c602013-03-15 17:07:15 -05003081 if (addr->type == BDADDR_BREDR)
3082 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003083 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003084 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003085
Johan Hedberg272d90d2012-02-09 15:26:12 +02003086 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003087 err = cmd_complete(sk, hdev->id, mgmt_op,
3088 MGMT_STATUS_NOT_CONNECTED, addr,
3089 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003090 goto done;
3091 }
3092
Johan Hedberg1707c602013-03-15 17:07:15 -05003093 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003094 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003095 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003096 err = cmd_complete(sk, hdev->id, mgmt_op,
3097 MGMT_STATUS_SUCCESS, addr,
3098 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003099 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003100 err = cmd_complete(sk, hdev->id, mgmt_op,
3101 MGMT_STATUS_FAILED, addr,
3102 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003103
Brian Gix47c15e22011-11-16 13:53:14 -08003104 goto done;
3105 }
3106
Johan Hedberg1707c602013-03-15 17:07:15 -05003107 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003108 if (!cmd) {
3109 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003110 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003111 }
3112
Brian Gix0df4c182011-11-16 13:53:13 -08003113 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003114 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3115 struct hci_cp_user_passkey_reply cp;
3116
Johan Hedberg1707c602013-03-15 17:07:15 -05003117 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003118 cp.passkey = passkey;
3119 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3120 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003121 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3122 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003123
Johan Hedberga664b5b2011-02-19 12:06:02 -03003124 if (err < 0)
3125 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003126
Brian Gix0df4c182011-11-16 13:53:13 -08003127done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003128 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003129 return err;
3130}
3131
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303132static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3133 void *data, u16 len)
3134{
3135 struct mgmt_cp_pin_code_neg_reply *cp = data;
3136
3137 BT_DBG("");
3138
Johan Hedberg1707c602013-03-15 17:07:15 -05003139 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303140 MGMT_OP_PIN_CODE_NEG_REPLY,
3141 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3142}
3143
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003144static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3145 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003146{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003147 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003148
3149 BT_DBG("");
3150
3151 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003152 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003153 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003154
Johan Hedberg1707c602013-03-15 17:07:15 -05003155 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003156 MGMT_OP_USER_CONFIRM_REPLY,
3157 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003158}
3159
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003160static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003161 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003162{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003163 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003164
3165 BT_DBG("");
3166
Johan Hedberg1707c602013-03-15 17:07:15 -05003167 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003168 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3169 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003170}
3171
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003172static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3173 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003174{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003175 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003176
3177 BT_DBG("");
3178
Johan Hedberg1707c602013-03-15 17:07:15 -05003179 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003180 MGMT_OP_USER_PASSKEY_REPLY,
3181 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003182}
3183
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003184static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003185 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003186{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003187 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003188
3189 BT_DBG("");
3190
Johan Hedberg1707c602013-03-15 17:07:15 -05003191 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003192 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3193 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003194}
3195
Johan Hedberg13928972013-03-15 17:07:00 -05003196static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003197{
Johan Hedberg13928972013-03-15 17:07:00 -05003198 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003199 struct hci_cp_write_local_name cp;
3200
Johan Hedberg13928972013-03-15 17:07:00 -05003201 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003202
Johan Hedberg890ea892013-03-15 17:06:52 -05003203 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003204}
3205
Johan Hedberg13928972013-03-15 17:07:00 -05003206static void set_name_complete(struct hci_dev *hdev, u8 status)
3207{
3208 struct mgmt_cp_set_local_name *cp;
3209 struct pending_cmd *cmd;
3210
3211 BT_DBG("status 0x%02x", status);
3212
3213 hci_dev_lock(hdev);
3214
3215 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3216 if (!cmd)
3217 goto unlock;
3218
3219 cp = cmd->param;
3220
3221 if (status)
3222 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3223 mgmt_status(status));
3224 else
3225 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3226 cp, sizeof(*cp));
3227
3228 mgmt_pending_remove(cmd);
3229
3230unlock:
3231 hci_dev_unlock(hdev);
3232}
3233
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003234static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003235 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003236{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003237 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003238 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003239 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003240 int err;
3241
3242 BT_DBG("");
3243
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003244 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003245
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003246 /* If the old values are the same as the new ones just return a
3247 * direct command complete event.
3248 */
3249 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3250 !memcmp(hdev->short_name, cp->short_name,
3251 sizeof(hdev->short_name))) {
3252 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3253 data, len);
3254 goto failed;
3255 }
3256
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003257 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003258
Johan Hedbergb5235a62012-02-21 14:32:24 +02003259 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003260 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003261
3262 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003263 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003264 if (err < 0)
3265 goto failed;
3266
3267 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003268 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003269
Johan Hedbergb5235a62012-02-21 14:32:24 +02003270 goto failed;
3271 }
3272
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003273 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003274 if (!cmd) {
3275 err = -ENOMEM;
3276 goto failed;
3277 }
3278
Johan Hedberg13928972013-03-15 17:07:00 -05003279 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3280
Johan Hedberg890ea892013-03-15 17:06:52 -05003281 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003282
3283 if (lmp_bredr_capable(hdev)) {
3284 update_name(&req);
3285 update_eir(&req);
3286 }
3287
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003288 /* The name is stored in the scan response data and so
3289 * no need to udpate the advertising data here.
3290 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003291 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003292 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003293
Johan Hedberg13928972013-03-15 17:07:00 -05003294 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003295 if (err < 0)
3296 mgmt_pending_remove(cmd);
3297
3298failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003299 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003300 return err;
3301}
3302
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003303static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003304 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003305{
Szymon Jancc35938b2011-03-22 13:12:21 +01003306 struct pending_cmd *cmd;
3307 int err;
3308
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003309 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003310
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003311 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003312
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003313 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003314 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003315 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003316 goto unlock;
3317 }
3318
Andre Guedes9a1a1992012-07-24 15:03:48 -03003319 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003320 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003321 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003322 goto unlock;
3323 }
3324
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003325 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003326 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003327 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003328 goto unlock;
3329 }
3330
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003331 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003332 if (!cmd) {
3333 err = -ENOMEM;
3334 goto unlock;
3335 }
3336
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003337 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3338 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3339 0, NULL);
3340 else
3341 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3342
Szymon Jancc35938b2011-03-22 13:12:21 +01003343 if (err < 0)
3344 mgmt_pending_remove(cmd);
3345
3346unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003347 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003348 return err;
3349}
3350
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003351static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003352 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003353{
Szymon Janc2763eda2011-03-22 13:12:22 +01003354 int err;
3355
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003356 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003357
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003358 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003359
Marcel Holtmannec109112014-01-10 02:07:30 -08003360 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3361 struct mgmt_cp_add_remote_oob_data *cp = data;
3362 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003363
Marcel Holtmannec109112014-01-10 02:07:30 -08003364 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3365 cp->hash, cp->randomizer);
3366 if (err < 0)
3367 status = MGMT_STATUS_FAILED;
3368 else
3369 status = MGMT_STATUS_SUCCESS;
3370
3371 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3372 status, &cp->addr, sizeof(cp->addr));
3373 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3374 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3375 u8 status;
3376
3377 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3378 cp->hash192,
3379 cp->randomizer192,
3380 cp->hash256,
3381 cp->randomizer256);
3382 if (err < 0)
3383 status = MGMT_STATUS_FAILED;
3384 else
3385 status = MGMT_STATUS_SUCCESS;
3386
3387 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3388 status, &cp->addr, sizeof(cp->addr));
3389 } else {
3390 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3391 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3392 MGMT_STATUS_INVALID_PARAMS);
3393 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003394
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003395 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003396 return err;
3397}
3398
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003399static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003400 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003401{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003402 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003403 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003404 int err;
3405
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003406 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003407
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003408 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003409
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003410 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003411 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003412 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003413 else
Szymon Janca6785be2012-12-13 15:11:21 +01003414 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003415
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003416 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003417 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003418
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003419 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003420 return err;
3421}
3422
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003423static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3424{
3425 struct pending_cmd *cmd;
3426 u8 type;
3427 int err;
3428
3429 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3430
3431 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3432 if (!cmd)
3433 return -ENOENT;
3434
3435 type = hdev->discovery.type;
3436
3437 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3438 &type, sizeof(type));
3439 mgmt_pending_remove(cmd);
3440
3441 return err;
3442}
3443
Andre Guedes7c307722013-04-30 15:29:28 -03003444static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3445{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003446 unsigned long timeout = 0;
3447
Andre Guedes7c307722013-04-30 15:29:28 -03003448 BT_DBG("status %d", status);
3449
3450 if (status) {
3451 hci_dev_lock(hdev);
3452 mgmt_start_discovery_failed(hdev, status);
3453 hci_dev_unlock(hdev);
3454 return;
3455 }
3456
3457 hci_dev_lock(hdev);
3458 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3459 hci_dev_unlock(hdev);
3460
3461 switch (hdev->discovery.type) {
3462 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003463 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003464 break;
3465
3466 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003467 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003468 break;
3469
3470 case DISCOV_TYPE_BREDR:
3471 break;
3472
3473 default:
3474 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3475 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003476
3477 if (!timeout)
3478 return;
3479
3480 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003481}
3482
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003483static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003484 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003485{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003486 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003487 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003488 struct hci_cp_le_set_scan_param param_cp;
3489 struct hci_cp_le_set_scan_enable enable_cp;
3490 struct hci_cp_inquiry inq_cp;
3491 struct hci_request req;
3492 /* General inquiry access code (GIAC) */
3493 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003494 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003495 int err;
3496
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003497 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003498
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003499 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003500
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003501 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003502 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003503 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003504 goto failed;
3505 }
3506
Andre Guedes642be6c2012-03-21 00:03:37 -03003507 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3508 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3509 MGMT_STATUS_BUSY);
3510 goto failed;
3511 }
3512
Johan Hedbergff9ef572012-01-04 14:23:45 +02003513 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003514 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003515 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003516 goto failed;
3517 }
3518
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003519 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003520 if (!cmd) {
3521 err = -ENOMEM;
3522 goto failed;
3523 }
3524
Andre Guedes4aab14e2012-02-17 20:39:36 -03003525 hdev->discovery.type = cp->type;
3526
Andre Guedes7c307722013-04-30 15:29:28 -03003527 hci_req_init(&req, hdev);
3528
Andre Guedes4aab14e2012-02-17 20:39:36 -03003529 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003530 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003531 status = mgmt_bredr_support(hdev);
3532 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003533 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003534 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003535 mgmt_pending_remove(cmd);
3536 goto failed;
3537 }
3538
Andre Guedes7c307722013-04-30 15:29:28 -03003539 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3540 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3541 MGMT_STATUS_BUSY);
3542 mgmt_pending_remove(cmd);
3543 goto failed;
3544 }
3545
3546 hci_inquiry_cache_flush(hdev);
3547
3548 memset(&inq_cp, 0, sizeof(inq_cp));
3549 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003550 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003551 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003552 break;
3553
3554 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003555 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003556 status = mgmt_le_support(hdev);
3557 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003558 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003559 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003560 mgmt_pending_remove(cmd);
3561 goto failed;
3562 }
3563
Andre Guedes7c307722013-04-30 15:29:28 -03003564 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003565 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003566 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3567 MGMT_STATUS_NOT_SUPPORTED);
3568 mgmt_pending_remove(cmd);
3569 goto failed;
3570 }
3571
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003572 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003573 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3574 MGMT_STATUS_REJECTED);
3575 mgmt_pending_remove(cmd);
3576 goto failed;
3577 }
3578
Andre Guedesc54c3862014-02-26 20:21:50 -03003579 /* If controller is scanning, it means the background scanning
3580 * is running. Thus, we should temporarily stop it in order to
3581 * set the discovery scanning parameters.
3582 */
3583 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3584 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003585
3586 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003587
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003588 /* All active scans will be done with either a resolvable
3589 * private address (when privacy feature has been enabled)
3590 * or unresolvable private address.
3591 */
3592 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003593 if (err < 0) {
3594 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3595 MGMT_STATUS_FAILED);
3596 mgmt_pending_remove(cmd);
3597 goto failed;
3598 }
3599
Andre Guedes7c307722013-04-30 15:29:28 -03003600 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003601 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3602 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003603 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003604 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3605 &param_cp);
3606
3607 memset(&enable_cp, 0, sizeof(enable_cp));
3608 enable_cp.enable = LE_SCAN_ENABLE;
3609 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3610 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3611 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003612 break;
3613
Andre Guedesf39799f2012-02-17 20:39:35 -03003614 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003615 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3616 MGMT_STATUS_INVALID_PARAMS);
3617 mgmt_pending_remove(cmd);
3618 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003619 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003620
Andre Guedes7c307722013-04-30 15:29:28 -03003621 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003622 if (err < 0)
3623 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003624 else
3625 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003626
3627failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003628 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003629 return err;
3630}
3631
Andre Guedes1183fdc2013-04-30 15:29:35 -03003632static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3633{
3634 struct pending_cmd *cmd;
3635 int err;
3636
3637 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3638 if (!cmd)
3639 return -ENOENT;
3640
3641 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3642 &hdev->discovery.type, sizeof(hdev->discovery.type));
3643 mgmt_pending_remove(cmd);
3644
3645 return err;
3646}
3647
Andre Guedes0e05bba2013-04-30 15:29:33 -03003648static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3649{
3650 BT_DBG("status %d", status);
3651
3652 hci_dev_lock(hdev);
3653
3654 if (status) {
3655 mgmt_stop_discovery_failed(hdev, status);
3656 goto unlock;
3657 }
3658
3659 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3660
3661unlock:
3662 hci_dev_unlock(hdev);
3663}
3664
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003665static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003666 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003667{
Johan Hedbergd9306502012-02-20 23:25:18 +02003668 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003669 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003670 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003671 int err;
3672
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003673 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003674
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003675 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003676
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003677 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003678 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003679 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3680 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003681 goto unlock;
3682 }
3683
3684 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003685 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003686 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3687 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003688 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003689 }
3690
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003691 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003692 if (!cmd) {
3693 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003694 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003695 }
3696
Andre Guedes0e05bba2013-04-30 15:29:33 -03003697 hci_req_init(&req, hdev);
3698
Johan Hedberg21a60d32014-06-10 14:05:58 +03003699 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003700
Johan Hedberg21a60d32014-06-10 14:05:58 +03003701 err = hci_req_run(&req, stop_discovery_complete);
3702 if (!err) {
3703 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003704 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003705 }
3706
Johan Hedberg21a60d32014-06-10 14:05:58 +03003707 mgmt_pending_remove(cmd);
3708
3709 /* If no HCI commands were sent we're done */
3710 if (err == -ENODATA) {
3711 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3712 &mgmt_cp->type, sizeof(mgmt_cp->type));
3713 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3714 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003715
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003716unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003717 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003718 return err;
3719}
3720
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003721static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003722 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003723{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003724 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003725 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003726 int err;
3727
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003728 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003729
Johan Hedberg561aafb2012-01-04 13:31:59 +02003730 hci_dev_lock(hdev);
3731
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003732 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003733 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3734 MGMT_STATUS_FAILED, &cp->addr,
3735 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003736 goto failed;
3737 }
3738
Johan Hedberga198e7b2012-02-17 14:27:06 +02003739 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003740 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003741 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3742 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3743 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003744 goto failed;
3745 }
3746
3747 if (cp->name_known) {
3748 e->name_state = NAME_KNOWN;
3749 list_del(&e->list);
3750 } else {
3751 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003752 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003753 }
3754
Johan Hedberge3846622013-01-09 15:29:33 +02003755 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3756 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003757
3758failed:
3759 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003760 return err;
3761}
3762
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003763static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003764 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003765{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003766 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003767 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003768 int err;
3769
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003770 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003771
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003772 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003773 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3774 MGMT_STATUS_INVALID_PARAMS,
3775 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003776
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003777 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003778
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003779 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003780 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003781 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003782 goto done;
3783 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003784
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003785 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3786 sk);
3787 status = MGMT_STATUS_SUCCESS;
3788
3789done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003790 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003791 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003792
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003793 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003794
3795 return err;
3796}
3797
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003798static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003799 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003800{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003801 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003802 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003803 int err;
3804
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003805 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003806
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003807 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003808 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3809 MGMT_STATUS_INVALID_PARAMS,
3810 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003811
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003812 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003813
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003814 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003815 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003816 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003817 goto done;
3818 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003819
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003820 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3821 sk);
3822 status = MGMT_STATUS_SUCCESS;
3823
3824done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003825 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003826 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003827
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003828 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003829
3830 return err;
3831}
3832
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003833static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3834 u16 len)
3835{
3836 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003837 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003838 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003839 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003840
3841 BT_DBG("%s", hdev->name);
3842
Szymon Jancc72d4b82012-03-16 16:02:57 +01003843 source = __le16_to_cpu(cp->source);
3844
3845 if (source > 0x0002)
3846 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3847 MGMT_STATUS_INVALID_PARAMS);
3848
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003849 hci_dev_lock(hdev);
3850
Szymon Jancc72d4b82012-03-16 16:02:57 +01003851 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003852 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3853 hdev->devid_product = __le16_to_cpu(cp->product);
3854 hdev->devid_version = __le16_to_cpu(cp->version);
3855
3856 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3857
Johan Hedberg890ea892013-03-15 17:06:52 -05003858 hci_req_init(&req, hdev);
3859 update_eir(&req);
3860 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003861
3862 hci_dev_unlock(hdev);
3863
3864 return err;
3865}
3866
Johan Hedberg4375f102013-09-25 13:26:10 +03003867static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3868{
3869 struct cmd_lookup match = { NULL, hdev };
3870
3871 if (status) {
3872 u8 mgmt_err = mgmt_status(status);
3873
3874 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3875 cmd_status_rsp, &mgmt_err);
3876 return;
3877 }
3878
3879 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3880 &match);
3881
3882 new_settings(hdev, match.sk);
3883
3884 if (match.sk)
3885 sock_put(match.sk);
3886}
3887
Marcel Holtmann21b51872013-10-10 09:47:53 -07003888static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3889 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003890{
3891 struct mgmt_mode *cp = data;
3892 struct pending_cmd *cmd;
3893 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003894 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003895 int err;
3896
3897 BT_DBG("request for %s", hdev->name);
3898
Johan Hedberge6fe7982013-10-02 15:45:22 +03003899 status = mgmt_le_support(hdev);
3900 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003901 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003902 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03003903
3904 if (cp->val != 0x00 && cp->val != 0x01)
3905 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3906 MGMT_STATUS_INVALID_PARAMS);
3907
3908 hci_dev_lock(hdev);
3909
3910 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003911 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003912
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02003913 /* The following conditions are ones which mean that we should
3914 * not do any HCI communication but directly send a mgmt
3915 * response to user space (after toggling the flag if
3916 * necessary).
3917 */
3918 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07003919 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03003920 bool changed = false;
3921
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003922 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
3923 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003924 changed = true;
3925 }
3926
3927 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
3928 if (err < 0)
3929 goto unlock;
3930
3931 if (changed)
3932 err = new_settings(hdev, sk);
3933
3934 goto unlock;
3935 }
3936
3937 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
3938 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
3939 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3940 MGMT_STATUS_BUSY);
3941 goto unlock;
3942 }
3943
3944 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
3945 if (!cmd) {
3946 err = -ENOMEM;
3947 goto unlock;
3948 }
3949
3950 hci_req_init(&req, hdev);
3951
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07003952 if (val)
3953 enable_advertising(&req);
3954 else
3955 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03003956
3957 err = hci_req_run(&req, set_advertising_complete);
3958 if (err < 0)
3959 mgmt_pending_remove(cmd);
3960
3961unlock:
3962 hci_dev_unlock(hdev);
3963 return err;
3964}
3965
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003966static int set_static_address(struct sock *sk, struct hci_dev *hdev,
3967 void *data, u16 len)
3968{
3969 struct mgmt_cp_set_static_address *cp = data;
3970 int err;
3971
3972 BT_DBG("%s", hdev->name);
3973
Marcel Holtmann62af4442013-10-02 22:10:32 -07003974 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003975 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07003976 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003977
3978 if (hdev_is_powered(hdev))
3979 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
3980 MGMT_STATUS_REJECTED);
3981
3982 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
3983 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
3984 return cmd_status(sk, hdev->id,
3985 MGMT_OP_SET_STATIC_ADDRESS,
3986 MGMT_STATUS_INVALID_PARAMS);
3987
3988 /* Two most significant bits shall be set */
3989 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
3990 return cmd_status(sk, hdev->id,
3991 MGMT_OP_SET_STATIC_ADDRESS,
3992 MGMT_STATUS_INVALID_PARAMS);
3993 }
3994
3995 hci_dev_lock(hdev);
3996
3997 bacpy(&hdev->static_addr, &cp->bdaddr);
3998
3999 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4000
4001 hci_dev_unlock(hdev);
4002
4003 return err;
4004}
4005
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004006static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4007 void *data, u16 len)
4008{
4009 struct mgmt_cp_set_scan_params *cp = data;
4010 __u16 interval, window;
4011 int err;
4012
4013 BT_DBG("%s", hdev->name);
4014
4015 if (!lmp_le_capable(hdev))
4016 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4017 MGMT_STATUS_NOT_SUPPORTED);
4018
4019 interval = __le16_to_cpu(cp->interval);
4020
4021 if (interval < 0x0004 || interval > 0x4000)
4022 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4023 MGMT_STATUS_INVALID_PARAMS);
4024
4025 window = __le16_to_cpu(cp->window);
4026
4027 if (window < 0x0004 || window > 0x4000)
4028 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4029 MGMT_STATUS_INVALID_PARAMS);
4030
Marcel Holtmann899e1072013-10-14 09:55:32 -07004031 if (window > interval)
4032 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4033 MGMT_STATUS_INVALID_PARAMS);
4034
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004035 hci_dev_lock(hdev);
4036
4037 hdev->le_scan_interval = interval;
4038 hdev->le_scan_window = window;
4039
4040 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4041
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004042 /* If background scan is running, restart it so new parameters are
4043 * loaded.
4044 */
4045 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4046 hdev->discovery.state == DISCOVERY_STOPPED) {
4047 struct hci_request req;
4048
4049 hci_req_init(&req, hdev);
4050
4051 hci_req_add_le_scan_disable(&req);
4052 hci_req_add_le_passive_scan(&req);
4053
4054 hci_req_run(&req, NULL);
4055 }
4056
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004057 hci_dev_unlock(hdev);
4058
4059 return err;
4060}
4061
Johan Hedberg33e38b32013-03-15 17:07:05 -05004062static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4063{
4064 struct pending_cmd *cmd;
4065
4066 BT_DBG("status 0x%02x", status);
4067
4068 hci_dev_lock(hdev);
4069
4070 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4071 if (!cmd)
4072 goto unlock;
4073
4074 if (status) {
4075 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4076 mgmt_status(status));
4077 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004078 struct mgmt_mode *cp = cmd->param;
4079
4080 if (cp->val)
4081 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4082 else
4083 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4084
Johan Hedberg33e38b32013-03-15 17:07:05 -05004085 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4086 new_settings(hdev, cmd->sk);
4087 }
4088
4089 mgmt_pending_remove(cmd);
4090
4091unlock:
4092 hci_dev_unlock(hdev);
4093}
4094
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004095static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004096 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004097{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004098 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004099 struct pending_cmd *cmd;
4100 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004101 int err;
4102
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004103 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004104
Johan Hedberg56f87902013-10-02 13:43:13 +03004105 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4106 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004107 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4108 MGMT_STATUS_NOT_SUPPORTED);
4109
Johan Hedberga7e80f22013-01-09 16:05:19 +02004110 if (cp->val != 0x00 && cp->val != 0x01)
4111 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4112 MGMT_STATUS_INVALID_PARAMS);
4113
Johan Hedberg5400c042012-02-21 16:40:33 +02004114 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004115 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004116 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004117
4118 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004119 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004120 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004121
4122 hci_dev_lock(hdev);
4123
Johan Hedberg05cbf292013-03-15 17:07:07 -05004124 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4125 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4126 MGMT_STATUS_BUSY);
4127 goto unlock;
4128 }
4129
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004130 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4131 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4132 hdev);
4133 goto unlock;
4134 }
4135
Johan Hedberg33e38b32013-03-15 17:07:05 -05004136 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4137 data, len);
4138 if (!cmd) {
4139 err = -ENOMEM;
4140 goto unlock;
4141 }
4142
4143 hci_req_init(&req, hdev);
4144
Johan Hedberg406d7802013-03-15 17:07:09 -05004145 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004146
4147 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004148 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004149 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004150 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004151 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004152 }
4153
Johan Hedberg33e38b32013-03-15 17:07:05 -05004154unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004155 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004156
Antti Julkuf6422ec2011-06-22 13:11:56 +03004157 return err;
4158}
4159
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004160static void set_bredr_scan(struct hci_request *req)
4161{
4162 struct hci_dev *hdev = req->hdev;
4163 u8 scan = 0;
4164
4165 /* Ensure that fast connectable is disabled. This function will
4166 * not do anything if the page scan parameters are already what
4167 * they should be.
4168 */
4169 write_fast_connectable(req, false);
4170
4171 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4172 scan |= SCAN_PAGE;
4173 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4174 scan |= SCAN_INQUIRY;
4175
4176 if (scan)
4177 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4178}
4179
Johan Hedberg0663ca22013-10-02 13:43:14 +03004180static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4181{
4182 struct pending_cmd *cmd;
4183
4184 BT_DBG("status 0x%02x", status);
4185
4186 hci_dev_lock(hdev);
4187
4188 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4189 if (!cmd)
4190 goto unlock;
4191
4192 if (status) {
4193 u8 mgmt_err = mgmt_status(status);
4194
4195 /* We need to restore the flag if related HCI commands
4196 * failed.
4197 */
4198 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4199
4200 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4201 } else {
4202 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4203 new_settings(hdev, cmd->sk);
4204 }
4205
4206 mgmt_pending_remove(cmd);
4207
4208unlock:
4209 hci_dev_unlock(hdev);
4210}
4211
4212static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4213{
4214 struct mgmt_mode *cp = data;
4215 struct pending_cmd *cmd;
4216 struct hci_request req;
4217 int err;
4218
4219 BT_DBG("request for %s", hdev->name);
4220
4221 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4222 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4223 MGMT_STATUS_NOT_SUPPORTED);
4224
4225 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4226 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4227 MGMT_STATUS_REJECTED);
4228
4229 if (cp->val != 0x00 && cp->val != 0x01)
4230 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4231 MGMT_STATUS_INVALID_PARAMS);
4232
4233 hci_dev_lock(hdev);
4234
4235 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4236 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4237 goto unlock;
4238 }
4239
4240 if (!hdev_is_powered(hdev)) {
4241 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004242 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4243 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4244 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4245 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4246 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4247 }
4248
4249 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4250
4251 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4252 if (err < 0)
4253 goto unlock;
4254
4255 err = new_settings(hdev, sk);
4256 goto unlock;
4257 }
4258
4259 /* Reject disabling when powered on */
4260 if (!cp->val) {
4261 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4262 MGMT_STATUS_REJECTED);
4263 goto unlock;
4264 }
4265
4266 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4267 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4268 MGMT_STATUS_BUSY);
4269 goto unlock;
4270 }
4271
4272 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4273 if (!cmd) {
4274 err = -ENOMEM;
4275 goto unlock;
4276 }
4277
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004278 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004279 * generates the correct flags.
4280 */
4281 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4282
4283 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004284
4285 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4286 set_bredr_scan(&req);
4287
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004288 /* Since only the advertising data flags will change, there
4289 * is no need to update the scan response data.
4290 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004291 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004292
Johan Hedberg0663ca22013-10-02 13:43:14 +03004293 err = hci_req_run(&req, set_bredr_complete);
4294 if (err < 0)
4295 mgmt_pending_remove(cmd);
4296
4297unlock:
4298 hci_dev_unlock(hdev);
4299 return err;
4300}
4301
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004302static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4303 void *data, u16 len)
4304{
4305 struct mgmt_mode *cp = data;
4306 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004307 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004308 int err;
4309
4310 BT_DBG("request for %s", hdev->name);
4311
4312 status = mgmt_bredr_support(hdev);
4313 if (status)
4314 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4315 status);
4316
Marcel Holtmann5afeac142014-01-10 02:07:27 -08004317 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004318 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004319 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4320 MGMT_STATUS_NOT_SUPPORTED);
4321
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004322 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004323 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4324 MGMT_STATUS_INVALID_PARAMS);
4325
4326 hci_dev_lock(hdev);
4327
4328 if (!hdev_is_powered(hdev)) {
4329 bool changed;
4330
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004331 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004332 changed = !test_and_set_bit(HCI_SC_ENABLED,
4333 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004334 if (cp->val == 0x02)
4335 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4336 else
4337 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4338 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004339 changed = test_and_clear_bit(HCI_SC_ENABLED,
4340 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004341 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4342 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004343
4344 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4345 if (err < 0)
4346 goto failed;
4347
4348 if (changed)
4349 err = new_settings(hdev, sk);
4350
4351 goto failed;
4352 }
4353
4354 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4355 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4356 MGMT_STATUS_BUSY);
4357 goto failed;
4358 }
4359
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004360 val = !!cp->val;
4361
4362 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4363 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004364 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4365 goto failed;
4366 }
4367
4368 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4369 if (!cmd) {
4370 err = -ENOMEM;
4371 goto failed;
4372 }
4373
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004374 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004375 if (err < 0) {
4376 mgmt_pending_remove(cmd);
4377 goto failed;
4378 }
4379
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004380 if (cp->val == 0x02)
4381 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4382 else
4383 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4384
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004385failed:
4386 hci_dev_unlock(hdev);
4387 return err;
4388}
4389
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004390static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4391 void *data, u16 len)
4392{
4393 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004394 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004395 int err;
4396
4397 BT_DBG("request for %s", hdev->name);
4398
Johan Hedbergb97109792014-06-24 14:00:28 +03004399 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004400 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4401 MGMT_STATUS_INVALID_PARAMS);
4402
4403 hci_dev_lock(hdev);
4404
4405 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004406 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4407 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004408 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004409 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4410 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004411
Johan Hedbergb97109792014-06-24 14:00:28 +03004412 if (cp->val == 0x02)
4413 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4414 &hdev->dev_flags);
4415 else
4416 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4417 &hdev->dev_flags);
4418
4419 if (hdev_is_powered(hdev) && use_changed &&
4420 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4421 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4422 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4423 sizeof(mode), &mode);
4424 }
4425
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004426 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4427 if (err < 0)
4428 goto unlock;
4429
4430 if (changed)
4431 err = new_settings(hdev, sk);
4432
4433unlock:
4434 hci_dev_unlock(hdev);
4435 return err;
4436}
4437
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004438static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4439 u16 len)
4440{
4441 struct mgmt_cp_set_privacy *cp = cp_data;
4442 bool changed;
4443 int err;
4444
4445 BT_DBG("request for %s", hdev->name);
4446
4447 if (!lmp_le_capable(hdev))
4448 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4449 MGMT_STATUS_NOT_SUPPORTED);
4450
4451 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4452 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4453 MGMT_STATUS_INVALID_PARAMS);
4454
4455 if (hdev_is_powered(hdev))
4456 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4457 MGMT_STATUS_REJECTED);
4458
4459 hci_dev_lock(hdev);
4460
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004461 /* If user space supports this command it is also expected to
4462 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4463 */
4464 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4465
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004466 if (cp->privacy) {
4467 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4468 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4469 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4470 } else {
4471 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4472 memset(hdev->irk, 0, sizeof(hdev->irk));
4473 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4474 }
4475
4476 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4477 if (err < 0)
4478 goto unlock;
4479
4480 if (changed)
4481 err = new_settings(hdev, sk);
4482
4483unlock:
4484 hci_dev_unlock(hdev);
4485 return err;
4486}
4487
Johan Hedberg41edf162014-02-18 10:19:35 +02004488static bool irk_is_valid(struct mgmt_irk_info *irk)
4489{
4490 switch (irk->addr.type) {
4491 case BDADDR_LE_PUBLIC:
4492 return true;
4493
4494 case BDADDR_LE_RANDOM:
4495 /* Two most significant bits shall be set */
4496 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4497 return false;
4498 return true;
4499 }
4500
4501 return false;
4502}
4503
4504static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4505 u16 len)
4506{
4507 struct mgmt_cp_load_irks *cp = cp_data;
4508 u16 irk_count, expected_len;
4509 int i, err;
4510
4511 BT_DBG("request for %s", hdev->name);
4512
4513 if (!lmp_le_capable(hdev))
4514 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4515 MGMT_STATUS_NOT_SUPPORTED);
4516
4517 irk_count = __le16_to_cpu(cp->irk_count);
4518
4519 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4520 if (expected_len != len) {
4521 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004522 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004523 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4524 MGMT_STATUS_INVALID_PARAMS);
4525 }
4526
4527 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4528
4529 for (i = 0; i < irk_count; i++) {
4530 struct mgmt_irk_info *key = &cp->irks[i];
4531
4532 if (!irk_is_valid(key))
4533 return cmd_status(sk, hdev->id,
4534 MGMT_OP_LOAD_IRKS,
4535 MGMT_STATUS_INVALID_PARAMS);
4536 }
4537
4538 hci_dev_lock(hdev);
4539
4540 hci_smp_irks_clear(hdev);
4541
4542 for (i = 0; i < irk_count; i++) {
4543 struct mgmt_irk_info *irk = &cp->irks[i];
4544 u8 addr_type;
4545
4546 if (irk->addr.type == BDADDR_LE_PUBLIC)
4547 addr_type = ADDR_LE_DEV_PUBLIC;
4548 else
4549 addr_type = ADDR_LE_DEV_RANDOM;
4550
4551 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4552 BDADDR_ANY);
4553 }
4554
4555 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4556
4557 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4558
4559 hci_dev_unlock(hdev);
4560
4561 return err;
4562}
4563
Johan Hedberg3f706b72013-01-20 14:27:16 +02004564static bool ltk_is_valid(struct mgmt_ltk_info *key)
4565{
4566 if (key->master != 0x00 && key->master != 0x01)
4567 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004568
4569 switch (key->addr.type) {
4570 case BDADDR_LE_PUBLIC:
4571 return true;
4572
4573 case BDADDR_LE_RANDOM:
4574 /* Two most significant bits shall be set */
4575 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4576 return false;
4577 return true;
4578 }
4579
4580 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004581}
4582
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004583static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004584 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004585{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004586 struct mgmt_cp_load_long_term_keys *cp = cp_data;
4587 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004588 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004589
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004590 BT_DBG("request for %s", hdev->name);
4591
4592 if (!lmp_le_capable(hdev))
4593 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4594 MGMT_STATUS_NOT_SUPPORTED);
4595
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004596 key_count = __le16_to_cpu(cp->key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004597
4598 expected_len = sizeof(*cp) + key_count *
4599 sizeof(struct mgmt_ltk_info);
4600 if (expected_len != len) {
4601 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004602 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004603 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004604 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004605 }
4606
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004607 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004608
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004609 for (i = 0; i < key_count; i++) {
4610 struct mgmt_ltk_info *key = &cp->keys[i];
4611
Johan Hedberg3f706b72013-01-20 14:27:16 +02004612 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004613 return cmd_status(sk, hdev->id,
4614 MGMT_OP_LOAD_LONG_TERM_KEYS,
4615 MGMT_STATUS_INVALID_PARAMS);
4616 }
4617
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004618 hci_dev_lock(hdev);
4619
4620 hci_smp_ltks_clear(hdev);
4621
4622 for (i = 0; i < key_count; i++) {
4623 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004624 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004625
4626 if (key->addr.type == BDADDR_LE_PUBLIC)
4627 addr_type = ADDR_LE_DEV_PUBLIC;
4628 else
4629 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004630
4631 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004632 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004633 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004634 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004635
Johan Hedberg61b43352014-05-29 19:36:53 +03004636 switch (key->type) {
4637 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004638 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004639 break;
4640 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004641 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004642 break;
4643 default:
4644 continue;
4645 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004646
Johan Hedberg35d70272014-02-19 14:57:47 +02004647 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004648 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004649 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004650 }
4651
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004652 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4653 NULL, 0);
4654
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004655 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004656
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004657 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004658}
4659
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004660struct cmd_conn_lookup {
4661 struct hci_conn *conn;
4662 bool valid_tx_power;
4663 u8 mgmt_status;
4664};
4665
4666static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4667{
4668 struct cmd_conn_lookup *match = data;
4669 struct mgmt_cp_get_conn_info *cp;
4670 struct mgmt_rp_get_conn_info rp;
4671 struct hci_conn *conn = cmd->user_data;
4672
4673 if (conn != match->conn)
4674 return;
4675
4676 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4677
4678 memset(&rp, 0, sizeof(rp));
4679 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4680 rp.addr.type = cp->addr.type;
4681
4682 if (!match->mgmt_status) {
4683 rp.rssi = conn->rssi;
4684
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004685 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004686 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004687 rp.max_tx_power = conn->max_tx_power;
4688 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004689 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004690 rp.max_tx_power = HCI_TX_POWER_INVALID;
4691 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004692 }
4693
4694 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4695 match->mgmt_status, &rp, sizeof(rp));
4696
4697 hci_conn_drop(conn);
4698
4699 mgmt_pending_remove(cmd);
4700}
4701
4702static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4703{
4704 struct hci_cp_read_rssi *cp;
4705 struct hci_conn *conn;
4706 struct cmd_conn_lookup match;
4707 u16 handle;
4708
4709 BT_DBG("status 0x%02x", status);
4710
4711 hci_dev_lock(hdev);
4712
4713 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004714 * otherwise we assume it's not valid. At the moment we assume that
4715 * either both or none of current and max values are valid to keep code
4716 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004717 */
4718 match.valid_tx_power = !status;
4719
4720 /* Commands sent in request are either Read RSSI or Read Transmit Power
4721 * Level so we check which one was last sent to retrieve connection
4722 * handle. Both commands have handle as first parameter so it's safe to
4723 * cast data on the same command struct.
4724 *
4725 * First command sent is always Read RSSI and we fail only if it fails.
4726 * In other case we simply override error to indicate success as we
4727 * already remembered if TX power value is actually valid.
4728 */
4729 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4730 if (!cp) {
4731 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4732 status = 0;
4733 }
4734
4735 if (!cp) {
4736 BT_ERR("invalid sent_cmd in response");
4737 goto unlock;
4738 }
4739
4740 handle = __le16_to_cpu(cp->handle);
4741 conn = hci_conn_hash_lookup_handle(hdev, handle);
4742 if (!conn) {
4743 BT_ERR("unknown handle (%d) in response", handle);
4744 goto unlock;
4745 }
4746
4747 match.conn = conn;
4748 match.mgmt_status = mgmt_status(status);
4749
4750 /* Cache refresh is complete, now reply for mgmt request for given
4751 * connection only.
4752 */
4753 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4754 get_conn_info_complete, &match);
4755
4756unlock:
4757 hci_dev_unlock(hdev);
4758}
4759
4760static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4761 u16 len)
4762{
4763 struct mgmt_cp_get_conn_info *cp = data;
4764 struct mgmt_rp_get_conn_info rp;
4765 struct hci_conn *conn;
4766 unsigned long conn_info_age;
4767 int err = 0;
4768
4769 BT_DBG("%s", hdev->name);
4770
4771 memset(&rp, 0, sizeof(rp));
4772 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4773 rp.addr.type = cp->addr.type;
4774
4775 if (!bdaddr_type_is_valid(cp->addr.type))
4776 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4777 MGMT_STATUS_INVALID_PARAMS,
4778 &rp, sizeof(rp));
4779
4780 hci_dev_lock(hdev);
4781
4782 if (!hdev_is_powered(hdev)) {
4783 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4784 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4785 goto unlock;
4786 }
4787
4788 if (cp->addr.type == BDADDR_BREDR)
4789 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4790 &cp->addr.bdaddr);
4791 else
4792 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4793
4794 if (!conn || conn->state != BT_CONNECTED) {
4795 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4796 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4797 goto unlock;
4798 }
4799
4800 /* To avoid client trying to guess when to poll again for information we
4801 * calculate conn info age as random value between min/max set in hdev.
4802 */
4803 conn_info_age = hdev->conn_info_min_age +
4804 prandom_u32_max(hdev->conn_info_max_age -
4805 hdev->conn_info_min_age);
4806
4807 /* Query controller to refresh cached values if they are too old or were
4808 * never read.
4809 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004810 if (time_after(jiffies, conn->conn_info_timestamp +
4811 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004812 !conn->conn_info_timestamp) {
4813 struct hci_request req;
4814 struct hci_cp_read_tx_power req_txp_cp;
4815 struct hci_cp_read_rssi req_rssi_cp;
4816 struct pending_cmd *cmd;
4817
4818 hci_req_init(&req, hdev);
4819 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4820 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4821 &req_rssi_cp);
4822
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004823 /* For LE links TX power does not change thus we don't need to
4824 * query for it once value is known.
4825 */
4826 if (!bdaddr_type_is_le(cp->addr.type) ||
4827 conn->tx_power == HCI_TX_POWER_INVALID) {
4828 req_txp_cp.handle = cpu_to_le16(conn->handle);
4829 req_txp_cp.type = 0x00;
4830 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4831 sizeof(req_txp_cp), &req_txp_cp);
4832 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004833
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004834 /* Max TX power needs to be read only once per connection */
4835 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
4836 req_txp_cp.handle = cpu_to_le16(conn->handle);
4837 req_txp_cp.type = 0x01;
4838 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4839 sizeof(req_txp_cp), &req_txp_cp);
4840 }
4841
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004842 err = hci_req_run(&req, conn_info_refresh_complete);
4843 if (err < 0)
4844 goto unlock;
4845
4846 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
4847 data, len);
4848 if (!cmd) {
4849 err = -ENOMEM;
4850 goto unlock;
4851 }
4852
4853 hci_conn_hold(conn);
4854 cmd->user_data = conn;
4855
4856 conn->conn_info_timestamp = jiffies;
4857 } else {
4858 /* Cache is valid, just reply with values cached in hci_conn */
4859 rp.rssi = conn->rssi;
4860 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004861 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004862
4863 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4864 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
4865 }
4866
4867unlock:
4868 hci_dev_unlock(hdev);
4869 return err;
4870}
4871
Johan Hedberg95868422014-06-28 17:54:07 +03004872static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
4873{
4874 struct mgmt_cp_get_clock_info *cp;
4875 struct mgmt_rp_get_clock_info rp;
4876 struct hci_cp_read_clock *hci_cp;
4877 struct pending_cmd *cmd;
4878 struct hci_conn *conn;
4879
4880 BT_DBG("%s status %u", hdev->name, status);
4881
4882 hci_dev_lock(hdev);
4883
4884 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
4885 if (!hci_cp)
4886 goto unlock;
4887
4888 if (hci_cp->which) {
4889 u16 handle = __le16_to_cpu(hci_cp->handle);
4890 conn = hci_conn_hash_lookup_handle(hdev, handle);
4891 } else {
4892 conn = NULL;
4893 }
4894
4895 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
4896 if (!cmd)
4897 goto unlock;
4898
4899 cp = cmd->param;
4900
4901 memset(&rp, 0, sizeof(rp));
4902 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
4903
4904 if (status)
4905 goto send_rsp;
4906
4907 rp.local_clock = cpu_to_le32(hdev->clock);
4908
4909 if (conn) {
4910 rp.piconet_clock = cpu_to_le32(conn->clock);
4911 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
4912 }
4913
4914send_rsp:
4915 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
4916 &rp, sizeof(rp));
4917 mgmt_pending_remove(cmd);
4918 if (conn)
4919 hci_conn_drop(conn);
4920
4921unlock:
4922 hci_dev_unlock(hdev);
4923}
4924
4925static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
4926 u16 len)
4927{
4928 struct mgmt_cp_get_clock_info *cp = data;
4929 struct mgmt_rp_get_clock_info rp;
4930 struct hci_cp_read_clock hci_cp;
4931 struct pending_cmd *cmd;
4932 struct hci_request req;
4933 struct hci_conn *conn;
4934 int err;
4935
4936 BT_DBG("%s", hdev->name);
4937
4938 memset(&rp, 0, sizeof(rp));
4939 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4940 rp.addr.type = cp->addr.type;
4941
4942 if (cp->addr.type != BDADDR_BREDR)
4943 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
4944 MGMT_STATUS_INVALID_PARAMS,
4945 &rp, sizeof(rp));
4946
4947 hci_dev_lock(hdev);
4948
4949 if (!hdev_is_powered(hdev)) {
4950 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
4951 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4952 goto unlock;
4953 }
4954
4955 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
4956 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4957 &cp->addr.bdaddr);
4958 if (!conn || conn->state != BT_CONNECTED) {
4959 err = cmd_complete(sk, hdev->id,
4960 MGMT_OP_GET_CLOCK_INFO,
4961 MGMT_STATUS_NOT_CONNECTED,
4962 &rp, sizeof(rp));
4963 goto unlock;
4964 }
4965 } else {
4966 conn = NULL;
4967 }
4968
4969 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
4970 if (!cmd) {
4971 err = -ENOMEM;
4972 goto unlock;
4973 }
4974
4975 hci_req_init(&req, hdev);
4976
4977 memset(&hci_cp, 0, sizeof(hci_cp));
4978 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
4979
4980 if (conn) {
4981 hci_conn_hold(conn);
4982 cmd->user_data = conn;
4983
4984 hci_cp.handle = cpu_to_le16(conn->handle);
4985 hci_cp.which = 0x01; /* Piconet clock */
4986 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
4987 }
4988
4989 err = hci_req_run(&req, get_clock_info_complete);
4990 if (err < 0)
4991 mgmt_pending_remove(cmd);
4992
4993unlock:
4994 hci_dev_unlock(hdev);
4995 return err;
4996}
4997
Marcel Holtmann8afef092014-06-29 22:28:34 +02004998static void device_added(struct sock *sk, struct hci_dev *hdev,
4999 bdaddr_t *bdaddr, u8 type, u8 action)
5000{
5001 struct mgmt_ev_device_added ev;
5002
5003 bacpy(&ev.addr.bdaddr, bdaddr);
5004 ev.addr.type = type;
5005 ev.action = action;
5006
5007 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5008}
5009
Marcel Holtmann2faade52014-06-29 19:44:03 +02005010static int add_device(struct sock *sk, struct hci_dev *hdev,
5011 void *data, u16 len)
5012{
5013 struct mgmt_cp_add_device *cp = data;
5014 u8 auto_conn, addr_type;
5015 int err;
5016
5017 BT_DBG("%s", hdev->name);
5018
5019 if (!bdaddr_type_is_le(cp->addr.type) ||
5020 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5021 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5022 MGMT_STATUS_INVALID_PARAMS,
5023 &cp->addr, sizeof(cp->addr));
5024
5025 if (cp->action != 0x00 && cp->action != 0x01)
5026 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5027 MGMT_STATUS_INVALID_PARAMS,
5028 &cp->addr, sizeof(cp->addr));
5029
5030 hci_dev_lock(hdev);
5031
5032 if (cp->addr.type == BDADDR_LE_PUBLIC)
5033 addr_type = ADDR_LE_DEV_PUBLIC;
5034 else
5035 addr_type = ADDR_LE_DEV_RANDOM;
5036
5037 if (cp->action)
5038 auto_conn = HCI_AUTO_CONN_ALWAYS;
5039 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005040 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005041
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005042 /* If the connection parameters don't exist for this device,
5043 * they will be created and configured with defaults.
5044 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005045 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5046 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005047 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5048 MGMT_STATUS_FAILED,
5049 &cp->addr, sizeof(cp->addr));
5050 goto unlock;
5051 }
5052
Marcel Holtmann8afef092014-06-29 22:28:34 +02005053 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5054
Marcel Holtmann2faade52014-06-29 19:44:03 +02005055 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5056 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5057
5058unlock:
5059 hci_dev_unlock(hdev);
5060 return err;
5061}
5062
Marcel Holtmann8afef092014-06-29 22:28:34 +02005063static void device_removed(struct sock *sk, struct hci_dev *hdev,
5064 bdaddr_t *bdaddr, u8 type)
5065{
5066 struct mgmt_ev_device_removed ev;
5067
5068 bacpy(&ev.addr.bdaddr, bdaddr);
5069 ev.addr.type = type;
5070
5071 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5072}
5073
Marcel Holtmann2faade52014-06-29 19:44:03 +02005074static int remove_device(struct sock *sk, struct hci_dev *hdev,
5075 void *data, u16 len)
5076{
5077 struct mgmt_cp_remove_device *cp = data;
5078 int err;
5079
5080 BT_DBG("%s", hdev->name);
5081
5082 hci_dev_lock(hdev);
5083
5084 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005085 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005086 u8 addr_type;
5087
5088 if (!bdaddr_type_is_le(cp->addr.type)) {
5089 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5090 MGMT_STATUS_INVALID_PARAMS,
5091 &cp->addr, sizeof(cp->addr));
5092 goto unlock;
5093 }
5094
5095 if (cp->addr.type == BDADDR_LE_PUBLIC)
5096 addr_type = ADDR_LE_DEV_PUBLIC;
5097 else
5098 addr_type = ADDR_LE_DEV_RANDOM;
5099
Johan Hedbergc71593d2014-07-02 17:37:28 +03005100 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5101 addr_type);
5102 if (!params) {
5103 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5104 MGMT_STATUS_INVALID_PARAMS,
5105 &cp->addr, sizeof(cp->addr));
5106 goto unlock;
5107 }
5108
5109 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5110 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5111 MGMT_STATUS_INVALID_PARAMS,
5112 &cp->addr, sizeof(cp->addr));
5113 goto unlock;
5114 }
5115
5116 hci_pend_le_conn_del(hdev, &cp->addr.bdaddr, addr_type);
5117 list_del(&params->list);
5118 kfree(params);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005119
5120 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005121 } else {
5122 if (cp->addr.type) {
5123 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5124 MGMT_STATUS_INVALID_PARAMS,
5125 &cp->addr, sizeof(cp->addr));
5126 goto unlock;
5127 }
5128
Johan Hedbergc71593d2014-07-02 17:37:28 +03005129 hci_conn_params_clear_enabled(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005130 }
5131
5132 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5133 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5134
5135unlock:
5136 hci_dev_unlock(hdev);
5137 return err;
5138}
5139
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005140static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5141 u16 len)
5142{
5143 struct mgmt_cp_load_conn_param *cp = data;
5144 u16 param_count, expected_len;
5145 int i;
5146
5147 if (!lmp_le_capable(hdev))
5148 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5149 MGMT_STATUS_NOT_SUPPORTED);
5150
5151 param_count = __le16_to_cpu(cp->param_count);
5152
5153 expected_len = sizeof(*cp) + param_count *
5154 sizeof(struct mgmt_conn_param);
5155 if (expected_len != len) {
5156 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5157 expected_len, len);
5158 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5159 MGMT_STATUS_INVALID_PARAMS);
5160 }
5161
5162 BT_DBG("%s param_count %u", hdev->name, param_count);
5163
5164 hci_dev_lock(hdev);
5165
5166 hci_conn_params_clear_disabled(hdev);
5167
5168 for (i = 0; i < param_count; i++) {
5169 struct mgmt_conn_param *param = &cp->params[i];
5170 struct hci_conn_params *hci_param;
5171 u16 min, max, latency, timeout;
5172 u8 addr_type;
5173
5174 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5175 param->addr.type);
5176
5177 if (param->addr.type == BDADDR_LE_PUBLIC) {
5178 addr_type = ADDR_LE_DEV_PUBLIC;
5179 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5180 addr_type = ADDR_LE_DEV_RANDOM;
5181 } else {
5182 BT_ERR("Ignoring invalid connection parameters");
5183 continue;
5184 }
5185
5186 min = le16_to_cpu(param->min_interval);
5187 max = le16_to_cpu(param->max_interval);
5188 latency = le16_to_cpu(param->latency);
5189 timeout = le16_to_cpu(param->timeout);
5190
5191 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5192 min, max, latency, timeout);
5193
5194 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5195 BT_ERR("Ignoring invalid connection parameters");
5196 continue;
5197 }
5198
5199 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5200 addr_type);
5201 if (!hci_param) {
5202 BT_ERR("Failed to add connection parameters");
5203 continue;
5204 }
5205
5206 hci_param->conn_min_interval = min;
5207 hci_param->conn_max_interval = max;
5208 hci_param->conn_latency = latency;
5209 hci_param->supervision_timeout = timeout;
5210 }
5211
5212 hci_dev_unlock(hdev);
5213
5214 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5215}
5216
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005217static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005218 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5219 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005220 bool var_len;
5221 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005222} mgmt_handlers[] = {
5223 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005224 { read_version, false, MGMT_READ_VERSION_SIZE },
5225 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5226 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5227 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5228 { set_powered, false, MGMT_SETTING_SIZE },
5229 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5230 { set_connectable, false, MGMT_SETTING_SIZE },
5231 { set_fast_connectable, false, MGMT_SETTING_SIZE },
5232 { set_pairable, false, MGMT_SETTING_SIZE },
5233 { set_link_security, false, MGMT_SETTING_SIZE },
5234 { set_ssp, false, MGMT_SETTING_SIZE },
5235 { set_hs, false, MGMT_SETTING_SIZE },
5236 { set_le, false, MGMT_SETTING_SIZE },
5237 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5238 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5239 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5240 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5241 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5242 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5243 { disconnect, false, MGMT_DISCONNECT_SIZE },
5244 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5245 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5246 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5247 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5248 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5249 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5250 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5251 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5252 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5253 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5254 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5255 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005256 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005257 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5258 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5259 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5260 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5261 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5262 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005263 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005264 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005265 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005266 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005267 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005268 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005269 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005270 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005271 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005272 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005273 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005274 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5275 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005276 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005277};
5278
Johan Hedberg03811012010-12-08 00:21:06 +02005279int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5280{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005281 void *buf;
5282 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005283 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005284 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005285 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005286 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005287 int err;
5288
5289 BT_DBG("got %zu bytes", msglen);
5290
5291 if (msglen < sizeof(*hdr))
5292 return -EINVAL;
5293
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005294 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005295 if (!buf)
5296 return -ENOMEM;
5297
5298 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5299 err = -EFAULT;
5300 goto done;
5301 }
5302
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005303 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005304 opcode = __le16_to_cpu(hdr->opcode);
5305 index = __le16_to_cpu(hdr->index);
5306 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005307
5308 if (len != msglen - sizeof(*hdr)) {
5309 err = -EINVAL;
5310 goto done;
5311 }
5312
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005313 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005314 hdev = hci_dev_get(index);
5315 if (!hdev) {
5316 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005317 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005318 goto done;
5319 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005320
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005321 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005322 test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) ||
5323 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005324 err = cmd_status(sk, index, opcode,
5325 MGMT_STATUS_INVALID_INDEX);
5326 goto done;
5327 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005328 }
5329
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005330 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005331 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005332 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005333 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005334 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005335 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005336 }
5337
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005338 if ((hdev && opcode < MGMT_OP_READ_INFO) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005339 (!hdev && opcode >= MGMT_OP_READ_INFO)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005340 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005341 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005342 goto done;
5343 }
5344
Johan Hedbergbe22b542012-03-01 22:24:41 +02005345 handler = &mgmt_handlers[opcode];
5346
5347 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005348 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005349 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005350 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005351 goto done;
5352 }
5353
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005354 if (hdev)
5355 mgmt_init_hdev(sk, hdev);
5356
5357 cp = buf + sizeof(*hdr);
5358
Johan Hedbergbe22b542012-03-01 22:24:41 +02005359 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005360 if (err < 0)
5361 goto done;
5362
Johan Hedberg03811012010-12-08 00:21:06 +02005363 err = msglen;
5364
5365done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005366 if (hdev)
5367 hci_dev_put(hdev);
5368
Johan Hedberg03811012010-12-08 00:21:06 +02005369 kfree(buf);
5370 return err;
5371}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005372
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005373void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005374{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005375 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005376 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005377
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005378 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5379 return;
5380
5381 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5382 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5383 else
5384 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005385}
5386
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005387void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005388{
Johan Hedberg5f159032012-03-02 03:13:19 +02005389 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005390
Marcel Holtmann1514b892013-10-06 08:25:01 -07005391 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005392 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005393
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005394 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5395 return;
5396
Johan Hedberg744cf192011-11-08 20:40:14 +02005397 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005398
Marcel Holtmannedd38962014-07-02 21:30:55 +02005399 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5400 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
5401 else
5402 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005403}
5404
Andre Guedes6046dc32014-02-26 20:21:51 -03005405/* This function requires the caller holds hdev->lock */
5406static void restart_le_auto_conns(struct hci_dev *hdev)
5407{
5408 struct hci_conn_params *p;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005409 bool added = false;
Andre Guedes6046dc32014-02-26 20:21:51 -03005410
5411 list_for_each_entry(p, &hdev->le_conn_params, list) {
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005412 if (p->auto_connect == HCI_AUTO_CONN_ALWAYS) {
Andre Guedes6046dc32014-02-26 20:21:51 -03005413 hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005414 added = true;
5415 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005416 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005417
5418 /* Calling hci_pend_le_conn_add will actually already trigger
5419 * background scanning when needed. So no need to trigger it
5420 * just another time.
5421 *
5422 * This check is here to avoid an unneeded restart of the
5423 * passive scanning. Since this is during the controller
5424 * power up phase the duplicate filtering is not an issue.
5425 */
5426 if (added)
5427 return;
5428
5429 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005430}
5431
Johan Hedberg229ab392013-03-15 17:06:53 -05005432static void powered_complete(struct hci_dev *hdev, u8 status)
5433{
5434 struct cmd_lookup match = { NULL, hdev };
5435
5436 BT_DBG("status 0x%02x", status);
5437
5438 hci_dev_lock(hdev);
5439
Andre Guedes6046dc32014-02-26 20:21:51 -03005440 restart_le_auto_conns(hdev);
5441
Johan Hedberg229ab392013-03-15 17:06:53 -05005442 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5443
5444 new_settings(hdev, match.sk);
5445
5446 hci_dev_unlock(hdev);
5447
5448 if (match.sk)
5449 sock_put(match.sk);
5450}
5451
Johan Hedberg70da6242013-03-15 17:06:51 -05005452static int powered_update_hci(struct hci_dev *hdev)
5453{
Johan Hedberg890ea892013-03-15 17:06:52 -05005454 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005455 u8 link_sec;
5456
Johan Hedberg890ea892013-03-15 17:06:52 -05005457 hci_req_init(&req, hdev);
5458
Johan Hedberg70da6242013-03-15 17:06:51 -05005459 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5460 !lmp_host_ssp_capable(hdev)) {
5461 u8 ssp = 1;
5462
Johan Hedberg890ea892013-03-15 17:06:52 -05005463 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005464 }
5465
Johan Hedbergc73eee92013-04-19 18:35:21 +03005466 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5467 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005468 struct hci_cp_write_le_host_supported cp;
5469
5470 cp.le = 1;
5471 cp.simul = lmp_le_br_capable(hdev);
5472
5473 /* Check first if we already have the right
5474 * host state (host features set)
5475 */
5476 if (cp.le != lmp_host_le_capable(hdev) ||
5477 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005478 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5479 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005480 }
5481
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005482 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005483 /* Make sure the controller has a good default for
5484 * advertising data. This also applies to the case
5485 * where BR/EDR was toggled during the AUTO_OFF phase.
5486 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005487 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005488 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005489 update_scan_rsp_data(&req);
5490 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005491
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005492 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5493 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005494 }
5495
Johan Hedberg70da6242013-03-15 17:06:51 -05005496 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5497 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005498 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5499 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005500
5501 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005502 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5503 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005504 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005505 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005506 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005507 }
5508
Johan Hedberg229ab392013-03-15 17:06:53 -05005509 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005510}
5511
Johan Hedberg744cf192011-11-08 20:40:14 +02005512int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005513{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005514 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005515 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5516 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005517 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005518
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005519 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5520 return 0;
5521
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005522 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005523 if (powered_update_hci(hdev) == 0)
5524 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005525
Johan Hedberg229ab392013-03-15 17:06:53 -05005526 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5527 &match);
5528 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005529 }
5530
Johan Hedberg229ab392013-03-15 17:06:53 -05005531 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5532 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5533
5534 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5535 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5536 zero_cod, sizeof(zero_cod), NULL);
5537
5538new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005539 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005540
5541 if (match.sk)
5542 sock_put(match.sk);
5543
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005544 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005545}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005546
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005547void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005548{
5549 struct pending_cmd *cmd;
5550 u8 status;
5551
5552 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5553 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005554 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005555
5556 if (err == -ERFKILL)
5557 status = MGMT_STATUS_RFKILLED;
5558 else
5559 status = MGMT_STATUS_FAILED;
5560
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005561 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005562
5563 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005564}
5565
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005566void mgmt_discoverable_timeout(struct hci_dev *hdev)
5567{
5568 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005569
5570 hci_dev_lock(hdev);
5571
5572 /* When discoverable timeout triggers, then just make sure
5573 * the limited discoverable flag is cleared. Even in the case
5574 * of a timeout triggered from general discoverable, it is
5575 * safe to unconditionally clear the flag.
5576 */
5577 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005578 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005579
5580 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005581 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5582 u8 scan = SCAN_PAGE;
5583 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5584 sizeof(scan), &scan);
5585 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005586 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005587 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005588 hci_req_run(&req, NULL);
5589
5590 hdev->discov_timeout = 0;
5591
Johan Hedberg9a43e252013-10-20 19:00:07 +03005592 new_settings(hdev, NULL);
5593
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005594 hci_dev_unlock(hdev);
5595}
5596
Marcel Holtmann86a75642013-10-15 06:33:54 -07005597void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005598{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005599 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005600
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005601 /* Nothing needed here if there's a pending command since that
5602 * commands request completion callback takes care of everything
5603 * necessary.
5604 */
5605 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005606 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005607
Johan Hedbergbd107992014-02-24 14:52:19 +02005608 /* Powering off may clear the scan mode - don't let that interfere */
5609 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5610 return;
5611
Johan Hedberg9a43e252013-10-20 19:00:07 +03005612 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005613 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005614 } else {
5615 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005616 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005617 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005618
Johan Hedberg9a43e252013-10-20 19:00:07 +03005619 if (changed) {
5620 struct hci_request req;
5621
5622 /* In case this change in discoverable was triggered by
5623 * a disabling of connectable there could be a need to
5624 * update the advertising flags.
5625 */
5626 hci_req_init(&req, hdev);
5627 update_adv_data(&req);
5628 hci_req_run(&req, NULL);
5629
Marcel Holtmann86a75642013-10-15 06:33:54 -07005630 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005631 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005632}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005633
Marcel Holtmanna3309162013-10-15 06:33:55 -07005634void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005635{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005636 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005637
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005638 /* Nothing needed here if there's a pending command since that
5639 * commands request completion callback takes care of everything
5640 * necessary.
5641 */
5642 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005643 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005644
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005645 /* Powering off may clear the scan mode - don't let that interfere */
5646 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5647 return;
5648
Marcel Holtmanna3309162013-10-15 06:33:55 -07005649 if (connectable)
5650 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5651 else
5652 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005653
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005654 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005655 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005656}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005657
Johan Hedberg778b2352014-02-24 14:52:17 +02005658void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5659{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005660 /* Powering off may stop advertising - don't let that interfere */
5661 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5662 return;
5663
Johan Hedberg778b2352014-02-24 14:52:17 +02005664 if (advertising)
5665 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5666 else
5667 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5668}
5669
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005670void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005671{
Johan Hedbergca69b792011-11-11 18:10:00 +02005672 u8 mgmt_err = mgmt_status(status);
5673
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005674 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005675 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005676 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005677
5678 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005679 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005680 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005681}
5682
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005683void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5684 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005685{
Johan Hedberg86742e12011-11-07 23:13:38 +02005686 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005687
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005688 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005689
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005690 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02005691 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005692 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005693 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005694 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005695 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005696
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005697 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005698}
Johan Hedbergf7520542011-01-20 12:34:39 +02005699
Johan Hedbergd7b25452014-05-23 13:19:53 +03005700static u8 mgmt_ltk_type(struct smp_ltk *ltk)
5701{
5702 if (ltk->authenticated)
5703 return MGMT_LTK_AUTHENTICATED;
5704
5705 return MGMT_LTK_UNAUTHENTICATED;
5706}
5707
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005708void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005709{
5710 struct mgmt_ev_new_long_term_key ev;
5711
5712 memset(&ev, 0, sizeof(ev));
5713
Marcel Holtmann5192d302014-02-19 17:11:58 -08005714 /* Devices using resolvable or non-resolvable random addresses
5715 * without providing an indentity resolving key don't require
5716 * to store long term keys. Their addresses will change the
5717 * next time around.
5718 *
5719 * Only when a remote device provides an identity address
5720 * make sure the long term key is stored. If the remote
5721 * identity is known, the long term keys are internally
5722 * mapped to the identity address. So allow static random
5723 * and public addresses here.
5724 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005725 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5726 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5727 ev.store_hint = 0x00;
5728 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005729 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02005730
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005731 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005732 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03005733 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005734 ev.key.enc_size = key->enc_size;
5735 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005736 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005737
Johan Hedberg2ceba532014-06-16 19:25:16 +03005738 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005739 ev.key.master = 1;
5740
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005741 memcpy(ev.key.val, key->val, sizeof(key->val));
5742
Marcel Holtmann083368f2013-10-15 14:26:29 -07005743 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005744}
5745
Johan Hedberg95fbac82014-02-19 15:18:31 +02005746void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5747{
5748 struct mgmt_ev_new_irk ev;
5749
5750 memset(&ev, 0, sizeof(ev));
5751
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005752 /* For identity resolving keys from devices that are already
5753 * using a public address or static random address, do not
5754 * ask for storing this key. The identity resolving key really
5755 * is only mandatory for devices using resovlable random
5756 * addresses.
5757 *
5758 * Storing all identity resolving keys has the downside that
5759 * they will be also loaded on next boot of they system. More
5760 * identity resolving keys, means more time during scanning is
5761 * needed to actually resolve these addresses.
5762 */
5763 if (bacmp(&irk->rpa, BDADDR_ANY))
5764 ev.store_hint = 0x01;
5765 else
5766 ev.store_hint = 0x00;
5767
Johan Hedberg95fbac82014-02-19 15:18:31 +02005768 bacpy(&ev.rpa, &irk->rpa);
5769 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5770 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5771 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5772
5773 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5774}
5775
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005776void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
5777 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005778{
5779 struct mgmt_ev_new_csrk ev;
5780
5781 memset(&ev, 0, sizeof(ev));
5782
5783 /* Devices using resolvable or non-resolvable random addresses
5784 * without providing an indentity resolving key don't require
5785 * to store signature resolving keys. Their addresses will change
5786 * the next time around.
5787 *
5788 * Only when a remote device provides an identity address
5789 * make sure the signature resolving key is stored. So allow
5790 * static random and public addresses here.
5791 */
5792 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5793 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
5794 ev.store_hint = 0x00;
5795 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005796 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005797
5798 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
5799 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
5800 ev.key.master = csrk->master;
5801 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
5802
5803 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
5804}
5805
Andre Guedesffb5a8272014-07-01 18:10:11 -03005806void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03005807 u8 bdaddr_type, u8 store_hint, u16 min_interval,
5808 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03005809{
5810 struct mgmt_ev_new_conn_param ev;
5811
Johan Hedbergc103aea2014-07-02 17:37:34 +03005812 if (!hci_is_identity_address(bdaddr, bdaddr_type))
5813 return;
5814
Andre Guedesffb5a8272014-07-01 18:10:11 -03005815 memset(&ev, 0, sizeof(ev));
5816 bacpy(&ev.addr.bdaddr, bdaddr);
5817 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03005818 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03005819 ev.min_interval = cpu_to_le16(min_interval);
5820 ev.max_interval = cpu_to_le16(max_interval);
5821 ev.latency = cpu_to_le16(latency);
5822 ev.timeout = cpu_to_le16(timeout);
5823
5824 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
5825}
5826
Marcel Holtmann94933992013-10-15 10:26:39 -07005827static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5828 u8 data_len)
5829{
5830 eir[eir_len++] = sizeof(type) + data_len;
5831 eir[eir_len++] = type;
5832 memcpy(&eir[eir_len], data, data_len);
5833 eir_len += data_len;
5834
5835 return eir_len;
5836}
5837
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005838void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5839 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5840 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005841{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005842 char buf[512];
5843 struct mgmt_ev_device_connected *ev = (void *) buf;
5844 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005845
Johan Hedbergb644ba32012-01-17 21:48:47 +02005846 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005847 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005848
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005849 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005850
Johan Hedbergb644ba32012-01-17 21:48:47 +02005851 if (name_len > 0)
5852 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005853 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005854
5855 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005856 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005857 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005858
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005859 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005860
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005861 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
5862 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02005863}
5864
Johan Hedberg8962ee72011-01-20 12:40:27 +02005865static void disconnect_rsp(struct pending_cmd *cmd, void *data)
5866{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01005867 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005868 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02005869 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005870
Johan Hedberg88c3df12012-02-09 14:27:38 +02005871 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5872 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005873
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005874 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005875 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005876
5877 *sk = cmd->sk;
5878 sock_hold(*sk);
5879
Johan Hedberga664b5b2011-02-19 12:06:02 -03005880 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005881}
5882
Johan Hedberg124f6e32012-02-09 13:50:12 +02005883static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02005884{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005885 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02005886 struct mgmt_cp_unpair_device *cp = cmd->param;
5887 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005888
5889 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02005890 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5891 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005892
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005893 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
5894
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005895 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02005896
5897 mgmt_pending_remove(cmd);
5898}
5899
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005900void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005901 u8 link_type, u8 addr_type, u8 reason,
5902 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02005903{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005904 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02005905 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005906 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005907
Johan Hedberg8b064a32014-02-24 14:52:22 +02005908 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5909 if (power_off) {
5910 struct mgmt_mode *cp = power_off->param;
5911
5912 /* The connection is still in hci_conn_hash so test for 1
5913 * instead of 0 to know if this is the last one.
5914 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005915 if (!cp->val && hci_conn_count(hdev) == 1) {
5916 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02005917 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005918 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02005919 }
5920
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005921 if (!mgmt_connected)
5922 return;
5923
Andre Guedes57eb7762013-10-30 19:01:41 -03005924 if (link_type != ACL_LINK && link_type != LE_LINK)
5925 return;
5926
Johan Hedberg744cf192011-11-08 20:40:14 +02005927 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02005928
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005929 bacpy(&ev.addr.bdaddr, bdaddr);
5930 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5931 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02005932
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005933 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005934
5935 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01005936 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005937
Johan Hedberg124f6e32012-02-09 13:50:12 +02005938 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005939 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005940}
5941
Marcel Holtmann78929242013-10-06 23:55:47 -07005942void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
5943 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02005944{
Andre Guedes3655bba2013-10-30 19:01:40 -03005945 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
5946 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02005947 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005948 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005949
Jefferson Delfes36a75f12012-09-18 13:36:54 -04005950 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
5951 hdev);
5952
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005953 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005954 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07005955 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005956
Andre Guedes3655bba2013-10-30 19:01:40 -03005957 cp = cmd->param;
5958
5959 if (bacmp(bdaddr, &cp->addr.bdaddr))
5960 return;
5961
5962 if (cp->addr.type != bdaddr_type)
5963 return;
5964
Johan Hedberg88c3df12012-02-09 14:27:38 +02005965 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03005966 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02005967
Marcel Holtmann78929242013-10-06 23:55:47 -07005968 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
5969 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005970
Johan Hedberga664b5b2011-02-19 12:06:02 -03005971 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02005972}
Johan Hedberg17d5c042011-01-22 06:09:08 +02005973
Marcel Holtmann445608d2013-10-06 23:55:48 -07005974void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5975 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02005976{
5977 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02005978 struct pending_cmd *power_off;
5979
5980 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5981 if (power_off) {
5982 struct mgmt_mode *cp = power_off->param;
5983
5984 /* The connection is still in hci_conn_hash so test for 1
5985 * instead of 0 to know if this is the last one.
5986 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005987 if (!cp->val && hci_conn_count(hdev) == 1) {
5988 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02005989 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005990 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02005991 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02005992
Johan Hedberg4c659c32011-11-07 23:13:39 +02005993 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005994 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005995 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005996
Marcel Holtmann445608d2013-10-06 23:55:48 -07005997 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005998}
Johan Hedberg980e1a52011-01-22 06:10:07 +02005999
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006000void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006001{
6002 struct mgmt_ev_pin_code_request ev;
6003
Johan Hedbergd8457692012-02-17 14:24:57 +02006004 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006005 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006006 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006007
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006008 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006009}
6010
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006011void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6012 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006013{
6014 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006015 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006016
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006017 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006018 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006019 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006020
Johan Hedbergd8457692012-02-17 14:24:57 +02006021 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006022 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006023
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006024 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6025 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006026
Johan Hedberga664b5b2011-02-19 12:06:02 -03006027 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006028}
6029
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006030void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6031 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006032{
6033 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006034 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006035
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006036 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006037 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006038 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006039
Johan Hedbergd8457692012-02-17 14:24:57 +02006040 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006041 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006042
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006043 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6044 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006045
Johan Hedberga664b5b2011-02-19 12:06:02 -03006046 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006047}
Johan Hedberga5c29682011-02-19 12:05:57 -03006048
Johan Hedberg744cf192011-11-08 20:40:14 +02006049int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006050 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006051 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006052{
6053 struct mgmt_ev_user_confirm_request ev;
6054
Johan Hedberg744cf192011-11-08 20:40:14 +02006055 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006056
Johan Hedberg272d90d2012-02-09 15:26:12 +02006057 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006058 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006059 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006060 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006061
Johan Hedberg744cf192011-11-08 20:40:14 +02006062 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006063 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006064}
6065
Johan Hedberg272d90d2012-02-09 15:26:12 +02006066int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006067 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006068{
6069 struct mgmt_ev_user_passkey_request ev;
6070
6071 BT_DBG("%s", hdev->name);
6072
Johan Hedberg272d90d2012-02-09 15:26:12 +02006073 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006074 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006075
6076 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006077 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006078}
6079
Brian Gix0df4c182011-11-16 13:53:13 -08006080static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006081 u8 link_type, u8 addr_type, u8 status,
6082 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006083{
6084 struct pending_cmd *cmd;
6085 struct mgmt_rp_user_confirm_reply rp;
6086 int err;
6087
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006088 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006089 if (!cmd)
6090 return -ENOENT;
6091
Johan Hedberg272d90d2012-02-09 15:26:12 +02006092 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006093 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006094 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006095 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006096
Johan Hedberga664b5b2011-02-19 12:06:02 -03006097 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006098
6099 return err;
6100}
6101
Johan Hedberg744cf192011-11-08 20:40:14 +02006102int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006103 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006104{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006105 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006106 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006107}
6108
Johan Hedberg272d90d2012-02-09 15:26:12 +02006109int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006110 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006111{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006112 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006113 status,
6114 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006115}
Johan Hedberg2a611692011-02-19 12:06:00 -03006116
Brian Gix604086b2011-11-23 08:28:33 -08006117int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006118 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006119{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006120 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006121 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006122}
6123
Johan Hedberg272d90d2012-02-09 15:26:12 +02006124int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006125 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006126{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006127 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006128 status,
6129 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006130}
6131
Johan Hedberg92a25252012-09-06 18:39:26 +03006132int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6133 u8 link_type, u8 addr_type, u32 passkey,
6134 u8 entered)
6135{
6136 struct mgmt_ev_passkey_notify ev;
6137
6138 BT_DBG("%s", hdev->name);
6139
6140 bacpy(&ev.addr.bdaddr, bdaddr);
6141 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6142 ev.passkey = __cpu_to_le32(passkey);
6143 ev.entered = entered;
6144
6145 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6146}
6147
Marcel Holtmanne5460992013-10-15 14:26:23 -07006148void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6149 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006150{
6151 struct mgmt_ev_auth_failed ev;
6152
Johan Hedbergbab73cb2012-02-09 16:07:29 +02006153 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006154 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006155 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006156
Marcel Holtmanne5460992013-10-15 14:26:23 -07006157 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03006158}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006159
Marcel Holtmann464996a2013-10-15 14:26:24 -07006160void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006161{
6162 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006163 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006164
6165 if (status) {
6166 u8 mgmt_err = mgmt_status(status);
6167 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006168 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006169 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006170 }
6171
Marcel Holtmann464996a2013-10-15 14:26:24 -07006172 if (test_bit(HCI_AUTH, &hdev->flags))
6173 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6174 &hdev->dev_flags);
6175 else
6176 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6177 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006178
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006179 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006180 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006181
Johan Hedberg47990ea2012-02-22 11:58:37 +02006182 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006183 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006184
6185 if (match.sk)
6186 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006187}
6188
Johan Hedberg890ea892013-03-15 17:06:52 -05006189static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006190{
Johan Hedberg890ea892013-03-15 17:06:52 -05006191 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006192 struct hci_cp_write_eir cp;
6193
Johan Hedberg976eb202012-10-24 21:12:01 +03006194 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006195 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006196
Johan Hedbergc80da272012-02-22 15:38:48 +02006197 memset(hdev->eir, 0, sizeof(hdev->eir));
6198
Johan Hedbergcacaf522012-02-21 00:52:42 +02006199 memset(&cp, 0, sizeof(cp));
6200
Johan Hedberg890ea892013-03-15 17:06:52 -05006201 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006202}
6203
Marcel Holtmann3e248562013-10-15 14:26:25 -07006204void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006205{
6206 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006207 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006208 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006209
6210 if (status) {
6211 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006212
6213 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006214 &hdev->dev_flags)) {
6215 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006216 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006217 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006218
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006219 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6220 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006221 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006222 }
6223
6224 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006225 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006226 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006227 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6228 if (!changed)
6229 changed = test_and_clear_bit(HCI_HS_ENABLED,
6230 &hdev->dev_flags);
6231 else
6232 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006233 }
6234
6235 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6236
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006237 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006238 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006239
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006240 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006241 sock_put(match.sk);
6242
Johan Hedberg890ea892013-03-15 17:06:52 -05006243 hci_req_init(&req, hdev);
6244
Johan Hedberg37699722014-06-24 14:00:27 +03006245 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6246 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6247 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6248 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006249 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006250 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006251 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006252 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006253
6254 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006255}
6256
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006257void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6258{
6259 struct cmd_lookup match = { NULL, hdev };
6260 bool changed = false;
6261
6262 if (status) {
6263 u8 mgmt_err = mgmt_status(status);
6264
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006265 if (enable) {
6266 if (test_and_clear_bit(HCI_SC_ENABLED,
6267 &hdev->dev_flags))
6268 new_settings(hdev, NULL);
6269 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6270 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006271
6272 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6273 cmd_status_rsp, &mgmt_err);
6274 return;
6275 }
6276
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006277 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006278 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006279 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006280 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006281 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6282 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006283
6284 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6285 settings_rsp, &match);
6286
6287 if (changed)
6288 new_settings(hdev, match.sk);
6289
6290 if (match.sk)
6291 sock_put(match.sk);
6292}
6293
Johan Hedberg92da6092013-03-15 17:06:55 -05006294static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006295{
6296 struct cmd_lookup *match = data;
6297
Johan Hedberg90e70452012-02-23 23:09:40 +02006298 if (match->sk == NULL) {
6299 match->sk = cmd->sk;
6300 sock_hold(match->sk);
6301 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006302}
6303
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006304void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6305 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006306{
Johan Hedberg90e70452012-02-23 23:09:40 +02006307 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006308
Johan Hedberg92da6092013-03-15 17:06:55 -05006309 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6310 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6311 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006312
6313 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006314 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6315 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006316
6317 if (match.sk)
6318 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006319}
6320
Marcel Holtmann7667da32013-10-15 14:26:27 -07006321void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006322{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006323 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006324 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006325
Johan Hedberg13928972013-03-15 17:07:00 -05006326 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006327 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006328
6329 memset(&ev, 0, sizeof(ev));
6330 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006331 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006332
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006333 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006334 if (!cmd) {
6335 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006336
Johan Hedberg13928972013-03-15 17:07:00 -05006337 /* If this is a HCI command related to powering on the
6338 * HCI dev don't send any mgmt signals.
6339 */
6340 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006341 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006342 }
6343
Marcel Holtmann7667da32013-10-15 14:26:27 -07006344 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6345 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006346}
Szymon Jancc35938b2011-03-22 13:12:21 +01006347
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006348void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6349 u8 *randomizer192, u8 *hash256,
6350 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006351{
6352 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006353
Johan Hedberg744cf192011-11-08 20:40:14 +02006354 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006355
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006356 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006357 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006358 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006359
6360 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006361 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6362 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006363 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006364 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6365 hash256 && randomizer256) {
6366 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006367
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006368 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6369 memcpy(rp.randomizer192, randomizer192,
6370 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006371
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006372 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6373 memcpy(rp.randomizer256, randomizer256,
6374 sizeof(rp.randomizer256));
6375
6376 cmd_complete(cmd->sk, hdev->id,
6377 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6378 &rp, sizeof(rp));
6379 } else {
6380 struct mgmt_rp_read_local_oob_data rp;
6381
6382 memcpy(rp.hash, hash192, sizeof(rp.hash));
6383 memcpy(rp.randomizer, randomizer192,
6384 sizeof(rp.randomizer));
6385
6386 cmd_complete(cmd->sk, hdev->id,
6387 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6388 &rp, sizeof(rp));
6389 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006390 }
6391
6392 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006393}
Johan Hedberge17acd42011-03-30 23:57:16 +03006394
Marcel Holtmann901801b2013-10-06 23:55:51 -07006395void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006396 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6397 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006398{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006399 char buf[512];
6400 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006401 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006402 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006403
Andre Guedes12602d02013-04-30 15:29:40 -03006404 if (!hci_discovery_active(hdev))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006405 return;
Andre Guedes12602d02013-04-30 15:29:40 -03006406
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006407 /* Make sure that the buffer is big enough. The 5 extra bytes
6408 * are for the potential CoD field.
6409 */
6410 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006411 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006412
Johan Hedberg1dc06092012-01-15 21:01:23 +02006413 memset(buf, 0, sizeof(buf));
6414
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006415 irk = hci_get_irk(hdev, bdaddr, addr_type);
6416 if (irk) {
6417 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
6418 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
6419 } else {
6420 bacpy(&ev->addr.bdaddr, bdaddr);
6421 ev->addr.type = link_to_bdaddr(link_type, addr_type);
6422 }
6423
Johan Hedberge319d2e2012-01-15 19:51:59 +02006424 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006425 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006426
Johan Hedberg1dc06092012-01-15 21:01:23 +02006427 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006428 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006429
Johan Hedberg1dc06092012-01-15 21:01:23 +02006430 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6431 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006432 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006433
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006434 if (scan_rsp_len > 0)
6435 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6436
6437 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6438 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006439
Marcel Holtmann901801b2013-10-06 23:55:51 -07006440 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006441}
Johan Hedberga88a9652011-03-30 13:18:12 +03006442
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006443void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6444 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006445{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006446 struct mgmt_ev_device_found *ev;
6447 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6448 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006449
Johan Hedbergb644ba32012-01-17 21:48:47 +02006450 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006451
Johan Hedbergb644ba32012-01-17 21:48:47 +02006452 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006453
Johan Hedbergb644ba32012-01-17 21:48:47 +02006454 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006455 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006456 ev->rssi = rssi;
6457
6458 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006459 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006460
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006461 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006462
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006463 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006464}
Johan Hedberg314b2382011-04-27 10:29:57 -04006465
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006466void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006467{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006468 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006469 struct pending_cmd *cmd;
6470
Andre Guedes343fb142011-11-22 17:14:19 -03006471 BT_DBG("%s discovering %u", hdev->name, discovering);
6472
Johan Hedberg164a6e72011-11-01 17:06:44 +02006473 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006474 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006475 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006476 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006477
6478 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006479 u8 type = hdev->discovery.type;
6480
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006481 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6482 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006483 mgmt_pending_remove(cmd);
6484 }
6485
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006486 memset(&ev, 0, sizeof(ev));
6487 ev.type = hdev->discovery.type;
6488 ev.discovering = discovering;
6489
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006490 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006491}
Antti Julku5e762442011-08-25 16:48:02 +03006492
Marcel Holtmann5976e602013-10-06 04:08:14 -07006493static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6494{
6495 BT_DBG("%s status %u", hdev->name, status);
6496
6497 /* Clear the advertising mgmt setting if we failed to re-enable it */
6498 if (status) {
6499 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006500 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006501 }
6502}
6503
6504void mgmt_reenable_advertising(struct hci_dev *hdev)
6505{
6506 struct hci_request req;
6507
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006508 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006509 return;
6510
6511 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6512 return;
6513
6514 hci_req_init(&req, hdev);
6515 enable_advertising(&req);
6516
6517 /* If this fails we have no option but to let user space know
6518 * that we've disabled advertising.
6519 */
6520 if (hci_req_run(&req, adv_enable_complete) < 0) {
6521 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006522 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006523 }
6524}