blob: d83197f9e72718c49bee994b3a21fa2f29a3dfa5 [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 Hedberge70bb2e2012-02-13 16:59:33 +020091};
92
93static const u16 mgmt_events[] = {
94 MGMT_EV_CONTROLLER_ERROR,
95 MGMT_EV_INDEX_ADDED,
96 MGMT_EV_INDEX_REMOVED,
97 MGMT_EV_NEW_SETTINGS,
98 MGMT_EV_CLASS_OF_DEV_CHANGED,
99 MGMT_EV_LOCAL_NAME_CHANGED,
100 MGMT_EV_NEW_LINK_KEY,
101 MGMT_EV_NEW_LONG_TERM_KEY,
102 MGMT_EV_DEVICE_CONNECTED,
103 MGMT_EV_DEVICE_DISCONNECTED,
104 MGMT_EV_CONNECT_FAILED,
105 MGMT_EV_PIN_CODE_REQUEST,
106 MGMT_EV_USER_CONFIRM_REQUEST,
107 MGMT_EV_USER_PASSKEY_REQUEST,
108 MGMT_EV_AUTH_FAILED,
109 MGMT_EV_DEVICE_FOUND,
110 MGMT_EV_DISCOVERING,
111 MGMT_EV_DEVICE_BLOCKED,
112 MGMT_EV_DEVICE_UNBLOCKED,
113 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300114 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800115 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700116 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200117 MGMT_EV_DEVICE_ADDED,
118 MGMT_EV_DEVICE_REMOVED,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200119};
120
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800121#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200122
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200123#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
124 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
125
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200126struct pending_cmd {
127 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200128 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200129 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100130 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200131 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300132 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200133};
134
Johan Hedbergca69b792011-11-11 18:10:00 +0200135/* HCI to MGMT error code conversion table */
136static u8 mgmt_status_table[] = {
137 MGMT_STATUS_SUCCESS,
138 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
139 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
140 MGMT_STATUS_FAILED, /* Hardware Failure */
141 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
142 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200143 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200144 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
145 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
146 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
147 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
148 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
149 MGMT_STATUS_BUSY, /* Command Disallowed */
150 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
151 MGMT_STATUS_REJECTED, /* Rejected Security */
152 MGMT_STATUS_REJECTED, /* Rejected Personal */
153 MGMT_STATUS_TIMEOUT, /* Host Timeout */
154 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
155 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
156 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
157 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
158 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
159 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
160 MGMT_STATUS_BUSY, /* Repeated Attempts */
161 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
162 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
163 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
164 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
165 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
166 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
167 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
168 MGMT_STATUS_FAILED, /* Unspecified Error */
169 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
170 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
171 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
172 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
173 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
174 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
175 MGMT_STATUS_FAILED, /* Unit Link Key Used */
176 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
177 MGMT_STATUS_TIMEOUT, /* Instant Passed */
178 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
179 MGMT_STATUS_FAILED, /* Transaction Collision */
180 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
181 MGMT_STATUS_REJECTED, /* QoS Rejected */
182 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
183 MGMT_STATUS_REJECTED, /* Insufficient Security */
184 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
185 MGMT_STATUS_BUSY, /* Role Switch Pending */
186 MGMT_STATUS_FAILED, /* Slot Violation */
187 MGMT_STATUS_FAILED, /* Role Switch Failed */
188 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
189 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
190 MGMT_STATUS_BUSY, /* Host Busy Pairing */
191 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
192 MGMT_STATUS_BUSY, /* Controller Busy */
193 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
194 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
195 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
196 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
197 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
198};
199
200static u8 mgmt_status(u8 hci_status)
201{
202 if (hci_status < ARRAY_SIZE(mgmt_status_table))
203 return mgmt_status_table[hci_status];
204
205 return MGMT_STATUS_FAILED;
206}
207
Szymon Janc4e51eae2011-02-25 19:05:48 +0100208static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200209{
210 struct sk_buff *skb;
211 struct mgmt_hdr *hdr;
212 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300213 int err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200214
Szymon Janc34eb5252011-02-28 14:10:08 +0100215 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200216
Andre Guedes790eff42012-06-07 19:05:46 -0300217 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200218 if (!skb)
219 return -ENOMEM;
220
221 hdr = (void *) skb_put(skb, sizeof(*hdr));
222
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700223 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100224 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200225 hdr->len = cpu_to_le16(sizeof(*ev));
226
227 ev = (void *) skb_put(skb, sizeof(*ev));
228 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200229 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200230
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300231 err = sock_queue_rcv_skb(sk, skb);
232 if (err < 0)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200233 kfree_skb(skb);
234
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300235 return err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200236}
237
Johan Hedbergaee9b212012-02-18 15:07:59 +0200238static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300239 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200240{
241 struct sk_buff *skb;
242 struct mgmt_hdr *hdr;
243 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300244 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200245
246 BT_DBG("sock %p", sk);
247
Andre Guedes790eff42012-06-07 19:05:46 -0300248 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200249 if (!skb)
250 return -ENOMEM;
251
252 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200253
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700254 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100255 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200256 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200257
Johan Hedberga38528f2011-01-22 06:46:43 +0200258 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200259 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b212012-02-18 15:07:59 +0200260 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100261
262 if (rp)
263 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200264
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300265 err = sock_queue_rcv_skb(sk, skb);
266 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200267 kfree_skb(skb);
268
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100269 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200270}
271
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300272static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
273 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200274{
275 struct mgmt_rp_read_version rp;
276
277 BT_DBG("sock %p", sk);
278
279 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700280 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200281
Johan Hedbergaee9b212012-02-18 15:07:59 +0200282 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300283 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200284}
285
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300286static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
287 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200288{
289 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200290 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
291 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200292 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200293 size_t rp_size;
294 int i, err;
295
296 BT_DBG("sock %p", sk);
297
298 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
299
300 rp = kmalloc(rp_size, GFP_KERNEL);
301 if (!rp)
302 return -ENOMEM;
303
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700304 rp->num_commands = cpu_to_le16(num_commands);
305 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200306
307 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
308 put_unaligned_le16(mgmt_commands[i], opcode);
309
310 for (i = 0; i < num_events; i++, opcode++)
311 put_unaligned_le16(mgmt_events[i], opcode);
312
Johan Hedbergaee9b212012-02-18 15:07:59 +0200313 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300314 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200315 kfree(rp);
316
317 return err;
318}
319
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300320static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
321 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200322{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200323 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200324 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200325 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200326 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300327 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200328
329 BT_DBG("sock %p", sk);
330
331 read_lock(&hci_dev_list_lock);
332
333 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300334 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700335 if (d->dev_type == HCI_BREDR)
336 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200337 }
338
Johan Hedberga38528f2011-01-22 06:46:43 +0200339 rp_len = sizeof(*rp) + (2 * count);
340 rp = kmalloc(rp_len, GFP_ATOMIC);
341 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100342 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200343 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100344 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200345
Johan Hedberg476e44c2012-10-19 20:10:46 +0300346 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200347 list_for_each_entry(d, &hci_dev_list, list) {
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200348 if (test_bit(HCI_SETUP, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200349 continue;
350
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700351 if (test_bit(HCI_USER_CHANNEL, &d->dev_flags))
352 continue;
353
Marcel Holtmannfee746b2014-06-29 12:13:05 +0200354 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
355 continue;
356
Marcel Holtmann1514b892013-10-06 08:25:01 -0700357 if (d->dev_type == HCI_BREDR) {
358 rp->index[count++] = cpu_to_le16(d->id);
359 BT_DBG("Added hci%u", d->id);
360 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200361 }
362
Johan Hedberg476e44c2012-10-19 20:10:46 +0300363 rp->num_controllers = cpu_to_le16(count);
364 rp_len = sizeof(*rp) + (2 * count);
365
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200366 read_unlock(&hci_dev_list_lock);
367
Johan Hedbergaee9b212012-02-18 15:07:59 +0200368 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300369 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200370
Johan Hedberga38528f2011-01-22 06:46:43 +0200371 kfree(rp);
372
373 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200374}
375
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200376static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200377{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200378 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200379
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200380 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200381 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800382 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg03811012010-12-08 00:21:06 +0200383
Andre Guedesed3fa312012-07-24 15:03:46 -0300384 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300385 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500386 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
387 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300388 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200389 settings |= MGMT_SETTING_BREDR;
390 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700391
392 if (lmp_ssp_capable(hdev)) {
393 settings |= MGMT_SETTING_SSP;
394 settings |= MGMT_SETTING_HS;
395 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800396
Marcel Holtmann5afeac12014-01-10 02:07:27 -0800397 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200398 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800399 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700400 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100401
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300402 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200403 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300404 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200405 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300406 }
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200407
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200408 return settings;
409}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200410
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200411static u32 get_current_settings(struct hci_dev *hdev)
412{
413 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200414
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200415 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100416 settings |= MGMT_SETTING_POWERED;
417
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200418 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200419 settings |= MGMT_SETTING_CONNECTABLE;
420
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500421 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
422 settings |= MGMT_SETTING_FAST_CONNECTABLE;
423
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200424 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200425 settings |= MGMT_SETTING_DISCOVERABLE;
426
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200427 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200428 settings |= MGMT_SETTING_PAIRABLE;
429
Johan Hedberg56f87902013-10-02 13:43:13 +0300430 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200431 settings |= MGMT_SETTING_BREDR;
432
Johan Hedberg06199cf2012-02-22 16:37:11 +0200433 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200434 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200435
Johan Hedberg47990ea2012-02-22 11:58:37 +0200436 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200437 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200438
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200439 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200440 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200441
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200442 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
443 settings |= MGMT_SETTING_HS;
444
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200445 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300446 settings |= MGMT_SETTING_ADVERTISING;
447
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800448 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
449 settings |= MGMT_SETTING_SECURE_CONN;
450
Johan Hedberg0663b292014-06-24 13:15:50 +0300451 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800452 settings |= MGMT_SETTING_DEBUG_KEYS;
453
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200454 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
455 settings |= MGMT_SETTING_PRIVACY;
456
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200457 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200458}
459
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300460#define PNP_INFO_SVCLASS_ID 0x1200
461
Johan Hedberg213202e2013-01-27 00:31:33 +0200462static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
463{
464 u8 *ptr = data, *uuids_start = NULL;
465 struct bt_uuid *uuid;
466
467 if (len < 4)
468 return ptr;
469
470 list_for_each_entry(uuid, &hdev->uuids, list) {
471 u16 uuid16;
472
473 if (uuid->size != 16)
474 continue;
475
476 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
477 if (uuid16 < 0x1100)
478 continue;
479
480 if (uuid16 == PNP_INFO_SVCLASS_ID)
481 continue;
482
483 if (!uuids_start) {
484 uuids_start = ptr;
485 uuids_start[0] = 1;
486 uuids_start[1] = EIR_UUID16_ALL;
487 ptr += 2;
488 }
489
490 /* Stop if not enough space to put next UUID */
491 if ((ptr - data) + sizeof(u16) > len) {
492 uuids_start[1] = EIR_UUID16_SOME;
493 break;
494 }
495
496 *ptr++ = (uuid16 & 0x00ff);
497 *ptr++ = (uuid16 & 0xff00) >> 8;
498 uuids_start[0] += sizeof(uuid16);
499 }
500
501 return ptr;
502}
503
Johan Hedbergcdf19632013-01-27 00:31:34 +0200504static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
505{
506 u8 *ptr = data, *uuids_start = NULL;
507 struct bt_uuid *uuid;
508
509 if (len < 6)
510 return ptr;
511
512 list_for_each_entry(uuid, &hdev->uuids, list) {
513 if (uuid->size != 32)
514 continue;
515
516 if (!uuids_start) {
517 uuids_start = ptr;
518 uuids_start[0] = 1;
519 uuids_start[1] = EIR_UUID32_ALL;
520 ptr += 2;
521 }
522
523 /* Stop if not enough space to put next UUID */
524 if ((ptr - data) + sizeof(u32) > len) {
525 uuids_start[1] = EIR_UUID32_SOME;
526 break;
527 }
528
529 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
530 ptr += sizeof(u32);
531 uuids_start[0] += sizeof(u32);
532 }
533
534 return ptr;
535}
536
Johan Hedbergc00d5752013-01-27 00:31:35 +0200537static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
538{
539 u8 *ptr = data, *uuids_start = NULL;
540 struct bt_uuid *uuid;
541
542 if (len < 18)
543 return ptr;
544
545 list_for_each_entry(uuid, &hdev->uuids, list) {
546 if (uuid->size != 128)
547 continue;
548
549 if (!uuids_start) {
550 uuids_start = ptr;
551 uuids_start[0] = 1;
552 uuids_start[1] = EIR_UUID128_ALL;
553 ptr += 2;
554 }
555
556 /* Stop if not enough space to put next UUID */
557 if ((ptr - data) + 16 > len) {
558 uuids_start[1] = EIR_UUID128_SOME;
559 break;
560 }
561
562 memcpy(ptr, uuid->uuid, 16);
563 ptr += 16;
564 uuids_start[0] += 16;
565 }
566
567 return ptr;
568}
569
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300570static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
571{
572 struct pending_cmd *cmd;
573
574 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
575 if (cmd->opcode == opcode)
576 return cmd;
577 }
578
579 return NULL;
580}
581
Johan Hedberg95868422014-06-28 17:54:07 +0300582static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
583 struct hci_dev *hdev,
584 const void *data)
585{
586 struct pending_cmd *cmd;
587
588 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
589 if (cmd->user_data != data)
590 continue;
591 if (cmd->opcode == opcode)
592 return cmd;
593 }
594
595 return NULL;
596}
597
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700598static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
599{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700600 u8 ad_len = 0;
601 size_t name_len;
602
603 name_len = strlen(hdev->dev_name);
604 if (name_len > 0) {
605 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
606
607 if (name_len > max_len) {
608 name_len = max_len;
609 ptr[1] = EIR_NAME_SHORT;
610 } else
611 ptr[1] = EIR_NAME_COMPLETE;
612
613 ptr[0] = name_len + 1;
614
615 memcpy(ptr + 2, hdev->dev_name, name_len);
616
617 ad_len += (name_len + 2);
618 ptr += (name_len + 2);
619 }
620
621 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700622}
623
624static void update_scan_rsp_data(struct hci_request *req)
625{
626 struct hci_dev *hdev = req->hdev;
627 struct hci_cp_le_set_scan_rsp_data cp;
628 u8 len;
629
Johan Hedberg7751ef12013-10-19 23:38:15 +0300630 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700631 return;
632
633 memset(&cp, 0, sizeof(cp));
634
635 len = create_scan_rsp_data(hdev, cp.data);
636
Johan Hedbergeb438b52013-10-16 15:31:07 +0300637 if (hdev->scan_rsp_data_len == len &&
638 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700639 return;
640
Johan Hedbergeb438b52013-10-16 15:31:07 +0300641 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
642 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700643
644 cp.length = len;
645
646 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
647}
648
Johan Hedberg9a43e252013-10-20 19:00:07 +0300649static u8 get_adv_discov_flags(struct hci_dev *hdev)
650{
651 struct pending_cmd *cmd;
652
653 /* If there's a pending mgmt command the flags will not yet have
654 * their final values, so check for this first.
655 */
656 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
657 if (cmd) {
658 struct mgmt_mode *cp = cmd->param;
659 if (cp->val == 0x01)
660 return LE_AD_GENERAL;
661 else if (cp->val == 0x02)
662 return LE_AD_LIMITED;
663 } else {
664 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
665 return LE_AD_LIMITED;
666 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
667 return LE_AD_GENERAL;
668 }
669
670 return 0;
671}
672
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700673static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700674{
675 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700676
Johan Hedberg9a43e252013-10-20 19:00:07 +0300677 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700678
Johan Hedberge8340042014-01-30 11:16:50 -0800679 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700680 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700681
682 if (flags) {
683 BT_DBG("adv flags 0x%02x", flags);
684
685 ptr[0] = 2;
686 ptr[1] = EIR_FLAGS;
687 ptr[2] = flags;
688
689 ad_len += 3;
690 ptr += 3;
691 }
692
693 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
694 ptr[0] = 2;
695 ptr[1] = EIR_TX_POWER;
696 ptr[2] = (u8) hdev->adv_tx_power;
697
698 ad_len += 3;
699 ptr += 3;
700 }
701
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700702 return ad_len;
703}
704
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700705static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700706{
707 struct hci_dev *hdev = req->hdev;
708 struct hci_cp_le_set_adv_data cp;
709 u8 len;
710
Johan Hedberg10994ce2013-10-19 23:38:16 +0300711 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700712 return;
713
714 memset(&cp, 0, sizeof(cp));
715
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700716 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700717
718 if (hdev->adv_data_len == len &&
719 memcmp(cp.data, hdev->adv_data, len) == 0)
720 return;
721
722 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
723 hdev->adv_data_len = len;
724
725 cp.length = len;
726
727 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
728}
729
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300730static void create_eir(struct hci_dev *hdev, u8 *data)
731{
732 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300733 size_t name_len;
734
735 name_len = strlen(hdev->dev_name);
736
737 if (name_len > 0) {
738 /* EIR Data type */
739 if (name_len > 48) {
740 name_len = 48;
741 ptr[1] = EIR_NAME_SHORT;
742 } else
743 ptr[1] = EIR_NAME_COMPLETE;
744
745 /* EIR Data length */
746 ptr[0] = name_len + 1;
747
748 memcpy(ptr + 2, hdev->dev_name, name_len);
749
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300750 ptr += (name_len + 2);
751 }
752
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100753 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700754 ptr[0] = 2;
755 ptr[1] = EIR_TX_POWER;
756 ptr[2] = (u8) hdev->inq_tx_power;
757
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700758 ptr += 3;
759 }
760
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700761 if (hdev->devid_source > 0) {
762 ptr[0] = 9;
763 ptr[1] = EIR_DEVICE_ID;
764
765 put_unaligned_le16(hdev->devid_source, ptr + 2);
766 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
767 put_unaligned_le16(hdev->devid_product, ptr + 6);
768 put_unaligned_le16(hdev->devid_version, ptr + 8);
769
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700770 ptr += 10;
771 }
772
Johan Hedberg213202e2013-01-27 00:31:33 +0200773 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200774 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200775 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300776}
777
Johan Hedberg890ea892013-03-15 17:06:52 -0500778static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300779{
Johan Hedberg890ea892013-03-15 17:06:52 -0500780 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300781 struct hci_cp_write_eir cp;
782
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200783 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500784 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200785
Johan Hedberg976eb202012-10-24 21:12:01 +0300786 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500787 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300788
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200789 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500790 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300791
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200792 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500793 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300794
795 memset(&cp, 0, sizeof(cp));
796
797 create_eir(hdev, cp.data);
798
799 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500800 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300801
802 memcpy(hdev->eir, cp.data, sizeof(cp.data));
803
Johan Hedberg890ea892013-03-15 17:06:52 -0500804 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300805}
806
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200807static u8 get_service_classes(struct hci_dev *hdev)
808{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300809 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200810 u8 val = 0;
811
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300812 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200813 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200814
815 return val;
816}
817
Johan Hedberg890ea892013-03-15 17:06:52 -0500818static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200819{
Johan Hedberg890ea892013-03-15 17:06:52 -0500820 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200821 u8 cod[3];
822
823 BT_DBG("%s", hdev->name);
824
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200825 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500826 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200827
Johan Hedbergf87ea1d2013-10-19 23:38:17 +0300828 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
829 return;
830
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200831 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500832 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200833
834 cod[0] = hdev->minor_class;
835 cod[1] = hdev->major_class;
836 cod[2] = get_service_classes(hdev);
837
Marcel Holtmann6acd7db2013-10-15 06:33:53 -0700838 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
839 cod[1] |= 0x20;
840
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200841 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500842 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200843
Johan Hedberg890ea892013-03-15 17:06:52 -0500844 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200845}
846
Johan Hedberga4858cb2014-02-25 19:56:31 +0200847static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200848{
849 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200850
851 /* If there's a pending mgmt command the flag will not yet have
852 * it's final value, so check for this first.
853 */
854 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
855 if (cmd) {
856 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200857 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200858 }
859
Johan Hedberga4858cb2014-02-25 19:56:31 +0200860 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200861}
862
863static void enable_advertising(struct hci_request *req)
864{
865 struct hci_dev *hdev = req->hdev;
866 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200867 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200868 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200869
Johan Hedberg8d972502014-02-28 12:54:14 +0200870 /* Clear the HCI_ADVERTISING bit temporarily so that the
871 * hci_update_random_address knows that it's safe to go ahead
872 * and write a new random address. The flag will be set back on
873 * as soon as the SET_ADV_ENABLE HCI command completes.
874 */
875 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
876
Johan Hedberga4858cb2014-02-25 19:56:31 +0200877 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200878
Johan Hedberga4858cb2014-02-25 19:56:31 +0200879 /* Set require_privacy to true only when non-connectable
880 * advertising is used. In that case it is fine to use a
881 * non-resolvable private address.
882 */
883 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200884 return;
885
Marcel Holtmann41c90c12014-02-23 20:25:55 -0800886 memset(&cp, 0, sizeof(cp));
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700887 cp.min_interval = cpu_to_le16(0x0800);
888 cp.max_interval = cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +0200889 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200890 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200891 cp.channel_map = hdev->le_adv_channel_map;
892
893 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
894
895 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
896}
897
898static void disable_advertising(struct hci_request *req)
899{
900 u8 enable = 0x00;
901
902 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
903}
904
Johan Hedberg7d785252011-12-15 00:47:39 +0200905static void service_cache_off(struct work_struct *work)
906{
907 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300908 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -0500909 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +0200910
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200911 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +0200912 return;
913
Johan Hedberg890ea892013-03-15 17:06:52 -0500914 hci_req_init(&req, hdev);
915
Johan Hedberg7d785252011-12-15 00:47:39 +0200916 hci_dev_lock(hdev);
917
Johan Hedberg890ea892013-03-15 17:06:52 -0500918 update_eir(&req);
919 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +0200920
921 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -0500922
923 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +0200924}
925
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200926static void rpa_expired(struct work_struct *work)
927{
928 struct hci_dev *hdev = container_of(work, struct hci_dev,
929 rpa_expired.work);
930 struct hci_request req;
931
932 BT_DBG("");
933
934 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
935
936 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
937 hci_conn_num(hdev, LE_LINK) > 0)
938 return;
939
940 /* The generation of a new RPA and programming it into the
941 * controller happens in the enable_advertising() function.
942 */
943
944 hci_req_init(&req, hdev);
945
946 disable_advertising(&req);
947 enable_advertising(&req);
948
949 hci_req_run(&req, NULL);
950}
951
Johan Hedberg6a919082012-02-28 06:17:26 +0200952static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +0200953{
Johan Hedberg4f87da82012-03-02 19:55:56 +0200954 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +0200955 return;
956
Johan Hedberg4f87da82012-03-02 19:55:56 +0200957 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200958 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +0200959
Johan Hedberg4f87da82012-03-02 19:55:56 +0200960 /* Non-mgmt controlled devices get this bit set
961 * implicitly so that pairing works for them, however
962 * for mgmt we require user-space to explicitly enable
963 * it
964 */
965 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +0200966}
967
Johan Hedberg0f4e68c2012-02-28 17:18:30 +0200968static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300969 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +0200970{
971 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +0200972
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200973 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +0200974
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300975 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200976
Johan Hedberg03811012010-12-08 00:21:06 +0200977 memset(&rp, 0, sizeof(rp));
978
Johan Hedberg03811012010-12-08 00:21:06 +0200979 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200980
981 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200982 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200983
984 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
985 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
986
987 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +0200988
989 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +0200990 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +0200991
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300992 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200993
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200994 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300995 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +0200996}
997
998static void mgmt_pending_free(struct pending_cmd *cmd)
999{
1000 sock_put(cmd->sk);
1001 kfree(cmd->param);
1002 kfree(cmd);
1003}
1004
1005static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001006 struct hci_dev *hdev, void *data,
1007 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001008{
1009 struct pending_cmd *cmd;
1010
Johan Hedbergfca20012014-06-28 17:54:05 +03001011 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001012 if (!cmd)
1013 return NULL;
1014
1015 cmd->opcode = opcode;
1016 cmd->index = hdev->id;
1017
Andre Guedes12b94562012-06-07 19:05:45 -03001018 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001019 if (!cmd->param) {
1020 kfree(cmd);
1021 return NULL;
1022 }
1023
1024 if (data)
1025 memcpy(cmd->param, data, len);
1026
1027 cmd->sk = sk;
1028 sock_hold(sk);
1029
1030 list_add(&cmd->list, &hdev->mgmt_pending);
1031
1032 return cmd;
1033}
1034
1035static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001036 void (*cb)(struct pending_cmd *cmd,
1037 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001038 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001039{
Andre Guedesa3d09352013-02-01 11:21:30 -03001040 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001041
Andre Guedesa3d09352013-02-01 11:21:30 -03001042 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001043 if (opcode > 0 && cmd->opcode != opcode)
1044 continue;
1045
1046 cb(cmd, data);
1047 }
1048}
1049
Johan Hedberg03811012010-12-08 00:21:06 +02001050static void mgmt_pending_remove(struct pending_cmd *cmd)
1051{
1052 list_del(&cmd->list);
1053 mgmt_pending_free(cmd);
1054}
1055
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001056static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001057{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001058 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001059
Johan Hedbergaee9b212012-02-18 15:07:59 +02001060 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001061 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001062}
1063
Johan Hedberg8b064a32014-02-24 14:52:22 +02001064static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1065{
1066 BT_DBG("%s status 0x%02x", hdev->name, status);
1067
Johan Hedberga3172b72014-02-28 09:33:44 +02001068 if (hci_conn_count(hdev) == 0) {
1069 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001070 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001071 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001072}
1073
Johan Hedberg21a60d32014-06-10 14:05:58 +03001074static void hci_stop_discovery(struct hci_request *req)
1075{
1076 struct hci_dev *hdev = req->hdev;
1077 struct hci_cp_remote_name_req_cancel cp;
1078 struct inquiry_entry *e;
1079
1080 switch (hdev->discovery.state) {
1081 case DISCOVERY_FINDING:
1082 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1083 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1084 } else {
1085 cancel_delayed_work(&hdev->le_scan_disable);
1086 hci_req_add_le_scan_disable(req);
1087 }
1088
1089 break;
1090
1091 case DISCOVERY_RESOLVING:
1092 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1093 NAME_PENDING);
1094 if (!e)
1095 return;
1096
1097 bacpy(&cp.bdaddr, &e->data.bdaddr);
1098 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1099 &cp);
1100
1101 break;
1102
1103 default:
1104 /* Passive scanning */
1105 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
1106 hci_req_add_le_scan_disable(req);
1107 break;
1108 }
1109}
1110
Johan Hedberg8b064a32014-02-24 14:52:22 +02001111static int clean_up_hci_state(struct hci_dev *hdev)
1112{
1113 struct hci_request req;
1114 struct hci_conn *conn;
1115
1116 hci_req_init(&req, hdev);
1117
1118 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1119 test_bit(HCI_PSCAN, &hdev->flags)) {
1120 u8 scan = 0x00;
1121 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1122 }
1123
1124 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1125 disable_advertising(&req);
1126
Johan Hedbergf8680f12014-06-10 14:05:59 +03001127 hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001128
1129 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1130 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001131 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001132
Johan Hedbergc9910d02014-02-27 14:35:12 +02001133 switch (conn->state) {
1134 case BT_CONNECTED:
1135 case BT_CONFIG:
1136 dc.handle = cpu_to_le16(conn->handle);
1137 dc.reason = 0x15; /* Terminated due to Power Off */
1138 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1139 break;
1140 case BT_CONNECT:
1141 if (conn->type == LE_LINK)
1142 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1143 0, NULL);
1144 else if (conn->type == ACL_LINK)
1145 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1146 6, &conn->dst);
1147 break;
1148 case BT_CONNECT2:
1149 bacpy(&rej.bdaddr, &conn->dst);
1150 rej.reason = 0x15; /* Terminated due to Power Off */
1151 if (conn->type == ACL_LINK)
1152 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1153 sizeof(rej), &rej);
1154 else if (conn->type == SCO_LINK)
1155 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1156 sizeof(rej), &rej);
1157 break;
1158 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001159 }
1160
1161 return hci_req_run(&req, clean_up_hci_complete);
1162}
1163
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001164static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001165 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001166{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001167 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001168 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001169 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001170
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001171 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001172
Johan Hedberga7e80f22013-01-09 16:05:19 +02001173 if (cp->val != 0x00 && cp->val != 0x01)
1174 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1175 MGMT_STATUS_INVALID_PARAMS);
1176
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001177 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001178
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001179 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1180 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1181 MGMT_STATUS_BUSY);
1182 goto failed;
1183 }
1184
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001185 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1186 cancel_delayed_work(&hdev->power_off);
1187
1188 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001189 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1190 data, len);
1191 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001192 goto failed;
1193 }
1194 }
1195
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001196 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001197 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001198 goto failed;
1199 }
1200
Johan Hedberg03811012010-12-08 00:21:06 +02001201 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1202 if (!cmd) {
1203 err = -ENOMEM;
1204 goto failed;
1205 }
1206
Johan Hedberg8b064a32014-02-24 14:52:22 +02001207 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001208 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001209 err = 0;
1210 } else {
1211 /* Disconnect connections, stop scans, etc */
1212 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001213 if (!err)
1214 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1215 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001216
Johan Hedberg8b064a32014-02-24 14:52:22 +02001217 /* ENODATA means there were no HCI commands queued */
1218 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001219 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001220 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1221 err = 0;
1222 }
1223 }
Johan Hedberg03811012010-12-08 00:21:06 +02001224
1225failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001226 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001227 return err;
1228}
1229
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001230static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
1231 struct sock *skip_sk)
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001232{
1233 struct sk_buff *skb;
1234 struct mgmt_hdr *hdr;
1235
Andre Guedes790eff42012-06-07 19:05:46 -03001236 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001237 if (!skb)
1238 return -ENOMEM;
1239
1240 hdr = (void *) skb_put(skb, sizeof(*hdr));
1241 hdr->opcode = cpu_to_le16(event);
1242 if (hdev)
1243 hdr->index = cpu_to_le16(hdev->id);
1244 else
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001245 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001246 hdr->len = cpu_to_le16(data_len);
1247
1248 if (data)
1249 memcpy(skb_put(skb, data_len), data, data_len);
1250
Marcel Holtmann97e0bde2012-02-22 13:49:28 +01001251 /* Time stamp */
1252 __net_timestamp(skb);
1253
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001254 hci_send_to_control(skb, skip_sk);
1255 kfree_skb(skb);
1256
1257 return 0;
1258}
1259
1260static int new_settings(struct hci_dev *hdev, struct sock *skip)
1261{
1262 __le32 ev;
1263
1264 ev = cpu_to_le32(get_current_settings(hdev));
1265
1266 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1267}
1268
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001269struct cmd_lookup {
1270 struct sock *sk;
1271 struct hci_dev *hdev;
1272 u8 mgmt_status;
1273};
1274
1275static void settings_rsp(struct pending_cmd *cmd, void *data)
1276{
1277 struct cmd_lookup *match = data;
1278
1279 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1280
1281 list_del(&cmd->list);
1282
1283 if (match->sk == NULL) {
1284 match->sk = cmd->sk;
1285 sock_hold(match->sk);
1286 }
1287
1288 mgmt_pending_free(cmd);
1289}
1290
1291static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1292{
1293 u8 *status = data;
1294
1295 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1296 mgmt_pending_remove(cmd);
1297}
1298
Johan Hedberge6fe7982013-10-02 15:45:22 +03001299static u8 mgmt_bredr_support(struct hci_dev *hdev)
1300{
1301 if (!lmp_bredr_capable(hdev))
1302 return MGMT_STATUS_NOT_SUPPORTED;
1303 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1304 return MGMT_STATUS_REJECTED;
1305 else
1306 return MGMT_STATUS_SUCCESS;
1307}
1308
1309static u8 mgmt_le_support(struct hci_dev *hdev)
1310{
1311 if (!lmp_le_capable(hdev))
1312 return MGMT_STATUS_NOT_SUPPORTED;
1313 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1314 return MGMT_STATUS_REJECTED;
1315 else
1316 return MGMT_STATUS_SUCCESS;
1317}
1318
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001319static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1320{
1321 struct pending_cmd *cmd;
1322 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001323 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001324 bool changed;
1325
1326 BT_DBG("status 0x%02x", status);
1327
1328 hci_dev_lock(hdev);
1329
1330 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1331 if (!cmd)
1332 goto unlock;
1333
1334 if (status) {
1335 u8 mgmt_err = mgmt_status(status);
1336 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001337 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001338 goto remove_cmd;
1339 }
1340
1341 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001342 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001343 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1344 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001345
1346 if (hdev->discov_timeout > 0) {
1347 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1348 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1349 to);
1350 }
1351 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001352 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1353 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001354 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001355
1356 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1357
1358 if (changed)
1359 new_settings(hdev, cmd->sk);
1360
Marcel Holtmann970ba522013-10-15 06:33:57 -07001361 /* When the discoverable mode gets changed, make sure
1362 * that class of device has the limited discoverable
1363 * bit correctly set.
1364 */
1365 hci_req_init(&req, hdev);
1366 update_class(&req);
1367 hci_req_run(&req, NULL);
1368
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001369remove_cmd:
1370 mgmt_pending_remove(cmd);
1371
1372unlock:
1373 hci_dev_unlock(hdev);
1374}
1375
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001376static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001377 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001378{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001379 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001380 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001381 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001382 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001383 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001384 int err;
1385
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001386 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001387
Johan Hedberg9a43e252013-10-20 19:00:07 +03001388 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1389 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001390 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001391 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001392
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001393 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001394 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1395 MGMT_STATUS_INVALID_PARAMS);
1396
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001397 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001398
1399 /* Disabling discoverable requires that no timeout is set,
1400 * and enabling limited discoverable requires a timeout.
1401 */
1402 if ((cp->val == 0x00 && timeout > 0) ||
1403 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001404 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001405 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001406
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001407 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001408
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001409 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001410 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001411 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001412 goto failed;
1413 }
1414
1415 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001416 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001417 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001418 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001419 goto failed;
1420 }
1421
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001422 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001423 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001424 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001425 goto failed;
1426 }
1427
1428 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001429 bool changed = false;
1430
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001431 /* Setting limited discoverable when powered off is
1432 * not a valid operation since it requires a timeout
1433 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1434 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001435 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1436 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1437 changed = true;
1438 }
1439
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001440 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001441 if (err < 0)
1442 goto failed;
1443
1444 if (changed)
1445 err = new_settings(hdev, sk);
1446
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001447 goto failed;
1448 }
1449
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001450 /* If the current mode is the same, then just update the timeout
1451 * value with the new value. And if only the timeout gets updated,
1452 * then no need for any HCI transactions.
1453 */
1454 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1455 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1456 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001457 cancel_delayed_work(&hdev->discov_off);
1458 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001459
Marcel Holtmann36261542013-10-15 08:28:51 -07001460 if (cp->val && hdev->discov_timeout > 0) {
1461 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001462 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001463 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001464 }
1465
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001466 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001467 goto failed;
1468 }
1469
1470 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1471 if (!cmd) {
1472 err = -ENOMEM;
1473 goto failed;
1474 }
1475
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001476 /* Cancel any potential discoverable timeout that might be
1477 * still active and store new timeout value. The arming of
1478 * the timeout happens in the complete handler.
1479 */
1480 cancel_delayed_work(&hdev->discov_off);
1481 hdev->discov_timeout = timeout;
1482
Johan Hedbergb456f872013-10-19 23:38:22 +03001483 /* Limited discoverable mode */
1484 if (cp->val == 0x02)
1485 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1486 else
1487 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1488
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001489 hci_req_init(&req, hdev);
1490
Johan Hedberg9a43e252013-10-20 19:00:07 +03001491 /* The procedure for LE-only controllers is much simpler - just
1492 * update the advertising data.
1493 */
1494 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1495 goto update_ad;
1496
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001497 scan = SCAN_PAGE;
1498
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001499 if (cp->val) {
1500 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001501
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001502 if (cp->val == 0x02) {
1503 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001504 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001505 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1506 hci_cp.iac_lap[1] = 0x8b;
1507 hci_cp.iac_lap[2] = 0x9e;
1508 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1509 hci_cp.iac_lap[4] = 0x8b;
1510 hci_cp.iac_lap[5] = 0x9e;
1511 } else {
1512 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001513 hci_cp.num_iac = 1;
1514 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1515 hci_cp.iac_lap[1] = 0x8b;
1516 hci_cp.iac_lap[2] = 0x9e;
1517 }
1518
1519 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1520 (hci_cp.num_iac * 3) + 1, &hci_cp);
1521
1522 scan |= SCAN_INQUIRY;
1523 } else {
1524 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1525 }
1526
1527 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001528
Johan Hedberg9a43e252013-10-20 19:00:07 +03001529update_ad:
1530 update_adv_data(&req);
1531
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001532 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001533 if (err < 0)
1534 mgmt_pending_remove(cmd);
1535
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001536failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001537 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001538 return err;
1539}
1540
Johan Hedberg406d7802013-03-15 17:07:09 -05001541static void write_fast_connectable(struct hci_request *req, bool enable)
1542{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001543 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001544 struct hci_cp_write_page_scan_activity acp;
1545 u8 type;
1546
Johan Hedberg547003b2013-10-21 16:51:53 +03001547 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1548 return;
1549
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001550 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1551 return;
1552
Johan Hedberg406d7802013-03-15 17:07:09 -05001553 if (enable) {
1554 type = PAGE_SCAN_TYPE_INTERLACED;
1555
1556 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001557 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001558 } else {
1559 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1560
1561 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001562 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001563 }
1564
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001565 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001566
Johan Hedbergbd98b992013-03-15 17:07:13 -05001567 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1568 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1569 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1570 sizeof(acp), &acp);
1571
1572 if (hdev->page_scan_type != type)
1573 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001574}
1575
Johan Hedberg2b76f452013-03-15 17:07:04 -05001576static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1577{
1578 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001579 struct mgmt_mode *cp;
1580 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001581
1582 BT_DBG("status 0x%02x", status);
1583
1584 hci_dev_lock(hdev);
1585
1586 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1587 if (!cmd)
1588 goto unlock;
1589
Johan Hedberg37438c12013-10-14 16:20:05 +03001590 if (status) {
1591 u8 mgmt_err = mgmt_status(status);
1592 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1593 goto remove_cmd;
1594 }
1595
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001596 cp = cmd->param;
1597 if (cp->val)
1598 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1599 else
1600 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1601
Johan Hedberg2b76f452013-03-15 17:07:04 -05001602 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1603
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001604 if (changed)
1605 new_settings(hdev, cmd->sk);
1606
Johan Hedberg37438c12013-10-14 16:20:05 +03001607remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001608 mgmt_pending_remove(cmd);
1609
1610unlock:
1611 hci_dev_unlock(hdev);
1612}
1613
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001614static int set_connectable_update_settings(struct hci_dev *hdev,
1615 struct sock *sk, u8 val)
1616{
1617 bool changed = false;
1618 int err;
1619
1620 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1621 changed = true;
1622
1623 if (val) {
1624 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1625 } else {
1626 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1627 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1628 }
1629
1630 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1631 if (err < 0)
1632 return err;
1633
1634 if (changed)
1635 return new_settings(hdev, sk);
1636
1637 return 0;
1638}
1639
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001640static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001641 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001642{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001643 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001644 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001645 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001646 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001647 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001648
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001649 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001650
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001651 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1652 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001653 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001654 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001655
Johan Hedberga7e80f22013-01-09 16:05:19 +02001656 if (cp->val != 0x00 && cp->val != 0x01)
1657 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1658 MGMT_STATUS_INVALID_PARAMS);
1659
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001660 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001661
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001662 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001663 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001664 goto failed;
1665 }
1666
1667 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001668 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001669 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001670 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001671 goto failed;
1672 }
1673
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001674 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1675 if (!cmd) {
1676 err = -ENOMEM;
1677 goto failed;
1678 }
1679
Johan Hedberg2b76f452013-03-15 17:07:04 -05001680 hci_req_init(&req, hdev);
1681
Johan Hedberg9a43e252013-10-20 19:00:07 +03001682 /* If BR/EDR is not enabled and we disable advertising as a
1683 * by-product of disabling connectable, we need to update the
1684 * advertising flags.
1685 */
1686 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1687 if (!cp->val) {
1688 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1689 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1690 }
1691 update_adv_data(&req);
1692 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001693 if (cp->val) {
1694 scan = SCAN_PAGE;
1695 } else {
1696 scan = 0;
1697
1698 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001699 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001700 cancel_delayed_work(&hdev->discov_off);
1701 }
1702
1703 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1704 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001705
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001706 /* If we're going from non-connectable to connectable or
1707 * vice-versa when fast connectable is enabled ensure that fast
1708 * connectable gets disabled. write_fast_connectable won't do
1709 * anything if the page scan parameters are already what they
1710 * should be.
1711 */
1712 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001713 write_fast_connectable(&req, false);
1714
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001715 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1716 hci_conn_num(hdev, LE_LINK) == 0) {
1717 disable_advertising(&req);
1718 enable_advertising(&req);
1719 }
1720
Johan Hedberg2b76f452013-03-15 17:07:04 -05001721 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001722 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001723 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001724 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001725 err = set_connectable_update_settings(hdev, sk,
1726 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001727 goto failed;
1728 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001729
1730failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001731 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001732 return err;
1733}
1734
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001735static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001736 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001737{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001738 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001739 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001740 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001741
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001742 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001743
Johan Hedberga7e80f22013-01-09 16:05:19 +02001744 if (cp->val != 0x00 && cp->val != 0x01)
1745 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1746 MGMT_STATUS_INVALID_PARAMS);
1747
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001748 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001749
1750 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001751 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001752 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001753 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001754
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001755 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001756 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001757 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001758
Marcel Holtmann55594352013-10-06 16:11:57 -07001759 if (changed)
1760 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001761
Marcel Holtmann55594352013-10-06 16:11:57 -07001762unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001763 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001764 return err;
1765}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001766
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001767static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1768 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001769{
1770 struct mgmt_mode *cp = data;
1771 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001772 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001773 int err;
1774
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001775 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001776
Johan Hedberge6fe7982013-10-02 15:45:22 +03001777 status = mgmt_bredr_support(hdev);
1778 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001779 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001780 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001781
Johan Hedberga7e80f22013-01-09 16:05:19 +02001782 if (cp->val != 0x00 && cp->val != 0x01)
1783 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1784 MGMT_STATUS_INVALID_PARAMS);
1785
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001786 hci_dev_lock(hdev);
1787
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001788 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001789 bool changed = false;
1790
1791 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001792 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001793 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1794 changed = true;
1795 }
1796
1797 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1798 if (err < 0)
1799 goto failed;
1800
1801 if (changed)
1802 err = new_settings(hdev, sk);
1803
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001804 goto failed;
1805 }
1806
1807 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001808 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001809 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001810 goto failed;
1811 }
1812
1813 val = !!cp->val;
1814
1815 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1816 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1817 goto failed;
1818 }
1819
1820 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1821 if (!cmd) {
1822 err = -ENOMEM;
1823 goto failed;
1824 }
1825
1826 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1827 if (err < 0) {
1828 mgmt_pending_remove(cmd);
1829 goto failed;
1830 }
1831
1832failed:
1833 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001834 return err;
1835}
1836
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001837static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001838{
1839 struct mgmt_mode *cp = data;
1840 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001841 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001842 int err;
1843
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001844 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001845
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001846 status = mgmt_bredr_support(hdev);
1847 if (status)
1848 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1849
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001850 if (!lmp_ssp_capable(hdev))
1851 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1852 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001853
Johan Hedberga7e80f22013-01-09 16:05:19 +02001854 if (cp->val != 0x00 && cp->val != 0x01)
1855 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1856 MGMT_STATUS_INVALID_PARAMS);
1857
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001858 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02001859
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001860 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001861 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001862
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001863 if (cp->val) {
1864 changed = !test_and_set_bit(HCI_SSP_ENABLED,
1865 &hdev->dev_flags);
1866 } else {
1867 changed = test_and_clear_bit(HCI_SSP_ENABLED,
1868 &hdev->dev_flags);
1869 if (!changed)
1870 changed = test_and_clear_bit(HCI_HS_ENABLED,
1871 &hdev->dev_flags);
1872 else
1873 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001874 }
1875
1876 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1877 if (err < 0)
1878 goto failed;
1879
1880 if (changed)
1881 err = new_settings(hdev, sk);
1882
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001883 goto failed;
1884 }
1885
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001886 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
1887 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01001888 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1889 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001890 goto failed;
1891 }
1892
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001893 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001894 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1895 goto failed;
1896 }
1897
1898 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
1899 if (!cmd) {
1900 err = -ENOMEM;
1901 goto failed;
1902 }
1903
Johan Hedberg37699722014-06-24 14:00:27 +03001904 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
1905 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
1906 sizeof(cp->val), &cp->val);
1907
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001908 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001909 if (err < 0) {
1910 mgmt_pending_remove(cmd);
1911 goto failed;
1912 }
1913
1914failed:
1915 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001916 return err;
1917}
1918
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001919static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001920{
1921 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07001922 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001923 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07001924 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001925
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001926 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001927
Johan Hedberge6fe7982013-10-02 15:45:22 +03001928 status = mgmt_bredr_support(hdev);
1929 if (status)
1930 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001931
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001932 if (!lmp_ssp_capable(hdev))
1933 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1934 MGMT_STATUS_NOT_SUPPORTED);
1935
1936 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
1937 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1938 MGMT_STATUS_REJECTED);
1939
Johan Hedberga7e80f22013-01-09 16:05:19 +02001940 if (cp->val != 0x00 && cp->val != 0x01)
1941 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1942 MGMT_STATUS_INVALID_PARAMS);
1943
Marcel Holtmannee392692013-10-01 22:59:23 -07001944 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001945
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001946 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07001947 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001948 } else {
1949 if (hdev_is_powered(hdev)) {
1950 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1951 MGMT_STATUS_REJECTED);
1952 goto unlock;
1953 }
1954
Marcel Holtmannee392692013-10-01 22:59:23 -07001955 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001956 }
Marcel Holtmannee392692013-10-01 22:59:23 -07001957
1958 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
1959 if (err < 0)
1960 goto unlock;
1961
1962 if (changed)
1963 err = new_settings(hdev, sk);
1964
1965unlock:
1966 hci_dev_unlock(hdev);
1967 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001968}
1969
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001970static void le_enable_complete(struct hci_dev *hdev, u8 status)
1971{
1972 struct cmd_lookup match = { NULL, hdev };
1973
1974 if (status) {
1975 u8 mgmt_err = mgmt_status(status);
1976
1977 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
1978 &mgmt_err);
1979 return;
1980 }
1981
1982 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
1983
1984 new_settings(hdev, match.sk);
1985
1986 if (match.sk)
1987 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001988
1989 /* Make sure the controller has a good default for
1990 * advertising data. Restrict the update to when LE
1991 * has actually been enabled. During power on, the
1992 * update in powered_update_hci will take care of it.
1993 */
1994 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1995 struct hci_request req;
1996
1997 hci_dev_lock(hdev);
1998
1999 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002000 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002001 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002002 hci_req_run(&req, NULL);
2003
2004 hci_dev_unlock(hdev);
2005 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002006}
2007
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002008static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002009{
2010 struct mgmt_mode *cp = data;
2011 struct hci_cp_write_le_host_supported hci_cp;
2012 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002013 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002014 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002015 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002016
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002017 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002018
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002019 if (!lmp_le_capable(hdev))
2020 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2021 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002022
Johan Hedberga7e80f22013-01-09 16:05:19 +02002023 if (cp->val != 0x00 && cp->val != 0x01)
2024 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2025 MGMT_STATUS_INVALID_PARAMS);
2026
Johan Hedbergc73eee92013-04-19 18:35:21 +03002027 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002028 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002029 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2030 MGMT_STATUS_REJECTED);
2031
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002032 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002033
2034 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002035 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002036
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002037 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002038 bool changed = false;
2039
2040 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2041 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2042 changed = true;
2043 }
2044
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002045 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2046 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002047 changed = true;
2048 }
2049
Johan Hedberg06199cf2012-02-22 16:37:11 +02002050 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2051 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002052 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002053
2054 if (changed)
2055 err = new_settings(hdev, sk);
2056
Johan Hedberg1de028c2012-02-29 19:55:35 -08002057 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002058 }
2059
Johan Hedberg4375f102013-09-25 13:26:10 +03002060 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2061 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002062 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002063 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002064 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002065 }
2066
2067 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2068 if (!cmd) {
2069 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002070 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002071 }
2072
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002073 hci_req_init(&req, hdev);
2074
Johan Hedberg06199cf2012-02-22 16:37:11 +02002075 memset(&hci_cp, 0, sizeof(hci_cp));
2076
2077 if (val) {
2078 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002079 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002080 } else {
2081 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2082 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002083 }
2084
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002085 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2086 &hci_cp);
2087
2088 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302089 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002090 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002091
Johan Hedberg1de028c2012-02-29 19:55:35 -08002092unlock:
2093 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002094 return err;
2095}
2096
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002097/* This is a helper function to test for pending mgmt commands that can
2098 * cause CoD or EIR HCI commands. We can only allow one such pending
2099 * mgmt command at a time since otherwise we cannot easily track what
2100 * the current values are, will be, and based on that calculate if a new
2101 * HCI command needs to be sent and if yes with what value.
2102 */
2103static bool pending_eir_or_class(struct hci_dev *hdev)
2104{
2105 struct pending_cmd *cmd;
2106
2107 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2108 switch (cmd->opcode) {
2109 case MGMT_OP_ADD_UUID:
2110 case MGMT_OP_REMOVE_UUID:
2111 case MGMT_OP_SET_DEV_CLASS:
2112 case MGMT_OP_SET_POWERED:
2113 return true;
2114 }
2115 }
2116
2117 return false;
2118}
2119
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002120static const u8 bluetooth_base_uuid[] = {
2121 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2122 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2123};
2124
2125static u8 get_uuid_size(const u8 *uuid)
2126{
2127 u32 val;
2128
2129 if (memcmp(uuid, bluetooth_base_uuid, 12))
2130 return 128;
2131
2132 val = get_unaligned_le32(&uuid[12]);
2133 if (val > 0xffff)
2134 return 32;
2135
2136 return 16;
2137}
2138
Johan Hedberg92da6092013-03-15 17:06:55 -05002139static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2140{
2141 struct pending_cmd *cmd;
2142
2143 hci_dev_lock(hdev);
2144
2145 cmd = mgmt_pending_find(mgmt_op, hdev);
2146 if (!cmd)
2147 goto unlock;
2148
2149 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2150 hdev->dev_class, 3);
2151
2152 mgmt_pending_remove(cmd);
2153
2154unlock:
2155 hci_dev_unlock(hdev);
2156}
2157
2158static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2159{
2160 BT_DBG("status 0x%02x", status);
2161
2162 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2163}
2164
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002165static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002166{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002167 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002168 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002169 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002170 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002171 int err;
2172
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002173 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002174
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002175 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002176
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002177 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002178 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002179 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002180 goto failed;
2181 }
2182
Andre Guedes92c4c202012-06-07 19:05:44 -03002183 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002184 if (!uuid) {
2185 err = -ENOMEM;
2186 goto failed;
2187 }
2188
2189 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002190 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002191 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002192
Johan Hedbergde66aa62013-01-27 00:31:27 +02002193 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002194
Johan Hedberg890ea892013-03-15 17:06:52 -05002195 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002196
Johan Hedberg890ea892013-03-15 17:06:52 -05002197 update_class(&req);
2198 update_eir(&req);
2199
Johan Hedberg92da6092013-03-15 17:06:55 -05002200 err = hci_req_run(&req, add_uuid_complete);
2201 if (err < 0) {
2202 if (err != -ENODATA)
2203 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002204
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002205 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002206 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002207 goto failed;
2208 }
2209
2210 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002211 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002212 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002213 goto failed;
2214 }
2215
2216 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002217
2218failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002219 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002220 return err;
2221}
2222
Johan Hedberg24b78d02012-02-23 23:24:30 +02002223static bool enable_service_cache(struct hci_dev *hdev)
2224{
2225 if (!hdev_is_powered(hdev))
2226 return false;
2227
2228 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002229 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2230 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002231 return true;
2232 }
2233
2234 return false;
2235}
2236
Johan Hedberg92da6092013-03-15 17:06:55 -05002237static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2238{
2239 BT_DBG("status 0x%02x", status);
2240
2241 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2242}
2243
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002244static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002245 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002246{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002247 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002248 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002249 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002250 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 -05002251 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002252 int err, found;
2253
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002254 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002255
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002256 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002257
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002258 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002259 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002260 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002261 goto unlock;
2262 }
2263
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002264 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002265 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002266
Johan Hedberg24b78d02012-02-23 23:24:30 +02002267 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002268 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002269 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002270 goto unlock;
2271 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002272
Johan Hedberg9246a862012-02-23 21:33:16 +02002273 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002274 }
2275
2276 found = 0;
2277
Johan Hedberg056341c2013-01-27 00:31:30 +02002278 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002279 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2280 continue;
2281
2282 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002283 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002284 found++;
2285 }
2286
2287 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002288 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002289 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002290 goto unlock;
2291 }
2292
Johan Hedberg9246a862012-02-23 21:33:16 +02002293update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002294 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002295
Johan Hedberg890ea892013-03-15 17:06:52 -05002296 update_class(&req);
2297 update_eir(&req);
2298
Johan Hedberg92da6092013-03-15 17:06:55 -05002299 err = hci_req_run(&req, remove_uuid_complete);
2300 if (err < 0) {
2301 if (err != -ENODATA)
2302 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002303
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002304 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002305 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002306 goto unlock;
2307 }
2308
2309 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002310 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002311 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002312 goto unlock;
2313 }
2314
2315 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002316
2317unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002318 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002319 return err;
2320}
2321
Johan Hedberg92da6092013-03-15 17:06:55 -05002322static void set_class_complete(struct hci_dev *hdev, u8 status)
2323{
2324 BT_DBG("status 0x%02x", status);
2325
2326 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2327}
2328
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002329static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002330 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002331{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002332 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002333 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002334 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002335 int err;
2336
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002337 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002338
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002339 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002340 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2341 MGMT_STATUS_NOT_SUPPORTED);
2342
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002343 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002344
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002345 if (pending_eir_or_class(hdev)) {
2346 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2347 MGMT_STATUS_BUSY);
2348 goto unlock;
2349 }
2350
2351 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2352 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2353 MGMT_STATUS_INVALID_PARAMS);
2354 goto unlock;
2355 }
2356
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002357 hdev->major_class = cp->major;
2358 hdev->minor_class = cp->minor;
2359
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002360 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002361 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002362 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002363 goto unlock;
2364 }
2365
Johan Hedberg890ea892013-03-15 17:06:52 -05002366 hci_req_init(&req, hdev);
2367
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002368 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002369 hci_dev_unlock(hdev);
2370 cancel_delayed_work_sync(&hdev->service_cache);
2371 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002372 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002373 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002374
Johan Hedberg890ea892013-03-15 17:06:52 -05002375 update_class(&req);
2376
Johan Hedberg92da6092013-03-15 17:06:55 -05002377 err = hci_req_run(&req, set_class_complete);
2378 if (err < 0) {
2379 if (err != -ENODATA)
2380 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002381
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002382 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002383 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002384 goto unlock;
2385 }
2386
2387 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002388 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002389 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002390 goto unlock;
2391 }
2392
2393 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002394
Johan Hedbergb5235a62012-02-21 14:32:24 +02002395unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002396 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002397 return err;
2398}
2399
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002400static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002401 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002402{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002403 struct mgmt_cp_load_link_keys *cp = data;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002404 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002405 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002406 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002407
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002408 BT_DBG("request for %s", hdev->name);
2409
2410 if (!lmp_bredr_capable(hdev))
2411 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2412 MGMT_STATUS_NOT_SUPPORTED);
2413
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002414 key_count = __le16_to_cpu(cp->key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002415
Johan Hedberg86742e12011-11-07 23:13:38 +02002416 expected_len = sizeof(*cp) + key_count *
2417 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002418 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002419 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002420 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002421 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002422 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002423 }
2424
Johan Hedberg4ae143012013-01-20 14:27:13 +02002425 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2426 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2427 MGMT_STATUS_INVALID_PARAMS);
2428
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002429 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002430 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002431
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002432 for (i = 0; i < key_count; i++) {
2433 struct mgmt_link_key_info *key = &cp->keys[i];
2434
Marcel Holtmann8e991132014-01-10 02:07:25 -08002435 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002436 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2437 MGMT_STATUS_INVALID_PARAMS);
2438 }
2439
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002440 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002441
2442 hci_link_keys_clear(hdev);
2443
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002444 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002445 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2446 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002447 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002448 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2449 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002450
2451 if (changed)
2452 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002453
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002454 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002455 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002456
Johan Hedberg58e92932014-06-24 14:00:26 +03002457 /* Always ignore debug keys and require a new pairing if
2458 * the user wants to use them.
2459 */
2460 if (key->type == HCI_LK_DEBUG_COMBINATION)
2461 continue;
2462
Johan Hedberg7652ff62014-06-24 13:15:49 +03002463 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2464 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002465 }
2466
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002467 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002468
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002469 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002470
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002471 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002472}
2473
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002474static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002475 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002476{
2477 struct mgmt_ev_device_unpaired ev;
2478
2479 bacpy(&ev.addr.bdaddr, bdaddr);
2480 ev.addr.type = addr_type;
2481
2482 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002483 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002484}
2485
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002486static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002487 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002488{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002489 struct mgmt_cp_unpair_device *cp = data;
2490 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002491 struct hci_cp_disconnect dc;
2492 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002493 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002494 int err;
2495
Johan Hedberga8a1d192011-11-10 15:54:38 +02002496 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002497 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2498 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002499
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002500 if (!bdaddr_type_is_valid(cp->addr.type))
2501 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2502 MGMT_STATUS_INVALID_PARAMS,
2503 &rp, sizeof(rp));
2504
Johan Hedberg118da702013-01-20 14:27:20 +02002505 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2506 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2507 MGMT_STATUS_INVALID_PARAMS,
2508 &rp, sizeof(rp));
2509
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002510 hci_dev_lock(hdev);
2511
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002512 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002513 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002514 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002515 goto unlock;
2516 }
2517
Johan Hedberge0b2b272014-02-18 17:14:31 +02002518 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002519 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002520 } else {
2521 u8 addr_type;
2522
2523 if (cp->addr.type == BDADDR_LE_PUBLIC)
2524 addr_type = ADDR_LE_DEV_PUBLIC;
2525 else
2526 addr_type = ADDR_LE_DEV_RANDOM;
2527
Johan Hedberga7ec7332014-02-18 17:14:35 +02002528 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2529
Andre Guedesa9b0a042014-02-26 20:21:52 -03002530 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2531
Johan Hedberge0b2b272014-02-18 17:14:31 +02002532 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2533 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002534
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002535 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002536 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002537 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002538 goto unlock;
2539 }
2540
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002541 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002542 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002543 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002544 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002545 else
2546 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002547 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002548 } else {
2549 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002550 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002551
Johan Hedberga8a1d192011-11-10 15:54:38 +02002552 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002553 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002554 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002555 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002556 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002557 }
2558
Johan Hedberg124f6e32012-02-09 13:50:12 +02002559 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002560 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002561 if (!cmd) {
2562 err = -ENOMEM;
2563 goto unlock;
2564 }
2565
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002566 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002567 dc.reason = 0x13; /* Remote User Terminated Connection */
2568 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2569 if (err < 0)
2570 mgmt_pending_remove(cmd);
2571
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002572unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002573 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002574 return err;
2575}
2576
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002577static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002578 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002579{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002580 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002581 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002582 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002583 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002584 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002585 int err;
2586
2587 BT_DBG("");
2588
Johan Hedberg06a63b12013-01-20 14:27:21 +02002589 memset(&rp, 0, sizeof(rp));
2590 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2591 rp.addr.type = cp->addr.type;
2592
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002593 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002594 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2595 MGMT_STATUS_INVALID_PARAMS,
2596 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002597
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002598 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002599
2600 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002601 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2602 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002603 goto failed;
2604 }
2605
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002606 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002607 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2608 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002609 goto failed;
2610 }
2611
Andre Guedes591f47f2012-04-24 21:02:49 -03002612 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002613 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2614 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002615 else
2616 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002617
Vishal Agarwalf9607272012-06-13 05:32:43 +05302618 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002619 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2620 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002621 goto failed;
2622 }
2623
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002624 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002625 if (!cmd) {
2626 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002627 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002628 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002629
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002630 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002631 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002632
2633 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2634 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002635 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002636
2637failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002638 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002639 return err;
2640}
2641
Andre Guedes57c14772012-04-24 21:02:50 -03002642static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002643{
2644 switch (link_type) {
2645 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002646 switch (addr_type) {
2647 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002648 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002649
Johan Hedberg48264f02011-11-09 13:58:58 +02002650 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002651 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002652 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002653 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002654
Johan Hedberg4c659c32011-11-07 23:13:39 +02002655 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002656 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002657 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002658 }
2659}
2660
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002661static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2662 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002663{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002664 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002665 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002666 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002667 int err;
2668 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002669
2670 BT_DBG("");
2671
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002672 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002673
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002674 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002675 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002676 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002677 goto unlock;
2678 }
2679
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002680 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002681 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2682 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002683 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002684 }
2685
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002686 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002687 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002688 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002689 err = -ENOMEM;
2690 goto unlock;
2691 }
2692
Johan Hedberg2784eb42011-01-21 13:56:35 +02002693 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002694 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002695 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2696 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002697 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002698 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002699 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002700 continue;
2701 i++;
2702 }
2703
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002704 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002705
Johan Hedberg4c659c32011-11-07 23:13:39 +02002706 /* Recalculate length in case of filtered SCO connections, etc */
2707 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002708
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002709 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002710 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002711
Johan Hedberga38528f2011-01-22 06:46:43 +02002712 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002713
2714unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002715 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002716 return err;
2717}
2718
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002719static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002720 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002721{
2722 struct pending_cmd *cmd;
2723 int err;
2724
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002725 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002726 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002727 if (!cmd)
2728 return -ENOMEM;
2729
Johan Hedbergd8457692012-02-17 14:24:57 +02002730 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002731 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002732 if (err < 0)
2733 mgmt_pending_remove(cmd);
2734
2735 return err;
2736}
2737
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002738static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002739 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002740{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002741 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002742 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002743 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002744 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002745 int err;
2746
2747 BT_DBG("");
2748
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002749 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002750
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002751 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002752 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002753 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002754 goto failed;
2755 }
2756
Johan Hedbergd8457692012-02-17 14:24:57 +02002757 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002758 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002759 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002760 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002761 goto failed;
2762 }
2763
2764 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002765 struct mgmt_cp_pin_code_neg_reply ncp;
2766
2767 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002768
2769 BT_ERR("PIN code is not 16 bytes long");
2770
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002771 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002772 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002773 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002774 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002775
2776 goto failed;
2777 }
2778
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002779 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002780 if (!cmd) {
2781 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002782 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002783 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002784
Johan Hedbergd8457692012-02-17 14:24:57 +02002785 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002786 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002787 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002788
2789 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2790 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002791 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002792
2793failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002794 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002795 return err;
2796}
2797
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002798static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2799 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002800{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002801 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002802
2803 BT_DBG("");
2804
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002805 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2806 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2807 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2808
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002809 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002810
2811 hdev->io_capability = cp->io_capability;
2812
2813 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002814 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002815
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002816 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002817
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002818 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2819 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002820}
2821
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002822static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002823{
2824 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002825 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002826
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002827 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002828 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2829 continue;
2830
Johan Hedberge9a416b2011-02-19 12:05:56 -03002831 if (cmd->user_data != conn)
2832 continue;
2833
2834 return cmd;
2835 }
2836
2837 return NULL;
2838}
2839
2840static void pairing_complete(struct pending_cmd *cmd, u8 status)
2841{
2842 struct mgmt_rp_pair_device rp;
2843 struct hci_conn *conn = cmd->user_data;
2844
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02002845 bacpy(&rp.addr.bdaddr, &conn->dst);
2846 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002847
Johan Hedbergaee9b212012-02-18 15:07:59 +02002848 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002849 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002850
2851 /* So we don't get further callbacks for this connection */
2852 conn->connect_cfm_cb = NULL;
2853 conn->security_cfm_cb = NULL;
2854 conn->disconn_cfm_cb = NULL;
2855
David Herrmann76a68ba2013-04-06 20:28:37 +02002856 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002857
Johan Hedberga664b5b2011-02-19 12:06:02 -03002858 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002859}
2860
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002861void mgmt_smp_complete(struct hci_conn *conn, bool complete)
2862{
2863 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
2864 struct pending_cmd *cmd;
2865
2866 cmd = find_pairing(conn);
2867 if (cmd)
2868 pairing_complete(cmd, status);
2869}
2870
Johan Hedberge9a416b2011-02-19 12:05:56 -03002871static void pairing_complete_cb(struct hci_conn *conn, u8 status)
2872{
2873 struct pending_cmd *cmd;
2874
2875 BT_DBG("status %u", status);
2876
Johan Hedberg56e5cb82011-11-08 20:40:16 +02002877 cmd = find_pairing(conn);
2878 if (!cmd)
2879 BT_DBG("Unable to find a pending command");
2880 else
Johan Hedberge2113262012-02-18 15:20:03 +02002881 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002882}
2883
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002884static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05302885{
2886 struct pending_cmd *cmd;
2887
2888 BT_DBG("status %u", status);
2889
2890 if (!status)
2891 return;
2892
2893 cmd = find_pairing(conn);
2894 if (!cmd)
2895 BT_DBG("Unable to find a pending command");
2896 else
2897 pairing_complete(cmd, mgmt_status(status));
2898}
2899
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002900static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002901 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002902{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002903 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02002904 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002905 struct pending_cmd *cmd;
2906 u8 sec_level, auth_type;
2907 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002908 int err;
2909
2910 BT_DBG("");
2911
Szymon Jancf950a30e2013-01-18 12:48:07 +01002912 memset(&rp, 0, sizeof(rp));
2913 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2914 rp.addr.type = cp->addr.type;
2915
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002916 if (!bdaddr_type_is_valid(cp->addr.type))
2917 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2918 MGMT_STATUS_INVALID_PARAMS,
2919 &rp, sizeof(rp));
2920
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002921 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
2922 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2923 MGMT_STATUS_INVALID_PARAMS,
2924 &rp, sizeof(rp));
2925
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002926 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002927
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002928 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01002929 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2930 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002931 goto unlock;
2932 }
2933
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002934 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02002935 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002936
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002937 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03002938 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
2939 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002940 } else {
2941 u8 addr_type;
2942
2943 /* Convert from L2CAP channel address type to HCI address type
2944 */
2945 if (cp->addr.type == BDADDR_LE_PUBLIC)
2946 addr_type = ADDR_LE_DEV_PUBLIC;
2947 else
2948 addr_type = ADDR_LE_DEV_RANDOM;
2949
2950 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03002951 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002952 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002953
Ville Tervo30e76272011-02-22 16:10:53 -03002954 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002955 int status;
2956
2957 if (PTR_ERR(conn) == -EBUSY)
2958 status = MGMT_STATUS_BUSY;
2959 else
2960 status = MGMT_STATUS_CONNECT_FAILED;
2961
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002962 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002963 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002964 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002965 goto unlock;
2966 }
2967
2968 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02002969 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002970 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002971 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002972 goto unlock;
2973 }
2974
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002975 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002976 if (!cmd) {
2977 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02002978 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002979 goto unlock;
2980 }
2981
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002982 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002983 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002984 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002985 conn->security_cfm_cb = pairing_complete_cb;
2986 conn->disconn_cfm_cb = pairing_complete_cb;
2987 } else {
2988 conn->connect_cfm_cb = le_pairing_complete_cb;
2989 conn->security_cfm_cb = le_pairing_complete_cb;
2990 conn->disconn_cfm_cb = le_pairing_complete_cb;
2991 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002992
Johan Hedberge9a416b2011-02-19 12:05:56 -03002993 conn->io_capability = cp->io_cap;
2994 cmd->user_data = conn;
2995
2996 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002997 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03002998 pairing_complete(cmd, 0);
2999
3000 err = 0;
3001
3002unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003003 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003004 return err;
3005}
3006
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003007static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3008 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003009{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003010 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003011 struct pending_cmd *cmd;
3012 struct hci_conn *conn;
3013 int err;
3014
3015 BT_DBG("");
3016
Johan Hedberg28424702012-02-02 04:02:29 +02003017 hci_dev_lock(hdev);
3018
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003019 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003020 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003021 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003022 goto unlock;
3023 }
3024
Johan Hedberg28424702012-02-02 04:02:29 +02003025 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3026 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003027 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003028 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003029 goto unlock;
3030 }
3031
3032 conn = cmd->user_data;
3033
3034 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
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_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003037 goto unlock;
3038 }
3039
3040 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3041
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003042 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003043 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003044unlock:
3045 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003046 return err;
3047}
3048
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003049static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003050 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003051 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003052{
Johan Hedberga5c29682011-02-19 12:05:57 -03003053 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003054 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003055 int err;
3056
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003057 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003058
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003059 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003060 err = cmd_complete(sk, hdev->id, mgmt_op,
3061 MGMT_STATUS_NOT_POWERED, addr,
3062 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003063 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003064 }
3065
Johan Hedberg1707c602013-03-15 17:07:15 -05003066 if (addr->type == BDADDR_BREDR)
3067 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003068 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003069 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003070
Johan Hedberg272d90d2012-02-09 15:26:12 +02003071 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003072 err = cmd_complete(sk, hdev->id, mgmt_op,
3073 MGMT_STATUS_NOT_CONNECTED, addr,
3074 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003075 goto done;
3076 }
3077
Johan Hedberg1707c602013-03-15 17:07:15 -05003078 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003079 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003080 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003081 err = cmd_complete(sk, hdev->id, mgmt_op,
3082 MGMT_STATUS_SUCCESS, addr,
3083 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003084 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003085 err = cmd_complete(sk, hdev->id, mgmt_op,
3086 MGMT_STATUS_FAILED, addr,
3087 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003088
Brian Gix47c15e22011-11-16 13:53:14 -08003089 goto done;
3090 }
3091
Johan Hedberg1707c602013-03-15 17:07:15 -05003092 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003093 if (!cmd) {
3094 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003095 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003096 }
3097
Brian Gix0df4c182011-11-16 13:53:13 -08003098 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003099 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3100 struct hci_cp_user_passkey_reply cp;
3101
Johan Hedberg1707c602013-03-15 17:07:15 -05003102 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003103 cp.passkey = passkey;
3104 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3105 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003106 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3107 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003108
Johan Hedberga664b5b2011-02-19 12:06:02 -03003109 if (err < 0)
3110 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003111
Brian Gix0df4c182011-11-16 13:53:13 -08003112done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003113 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003114 return err;
3115}
3116
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303117static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3118 void *data, u16 len)
3119{
3120 struct mgmt_cp_pin_code_neg_reply *cp = data;
3121
3122 BT_DBG("");
3123
Johan Hedberg1707c602013-03-15 17:07:15 -05003124 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303125 MGMT_OP_PIN_CODE_NEG_REPLY,
3126 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3127}
3128
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003129static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3130 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003131{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003132 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003133
3134 BT_DBG("");
3135
3136 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003137 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003138 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003139
Johan Hedberg1707c602013-03-15 17:07:15 -05003140 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003141 MGMT_OP_USER_CONFIRM_REPLY,
3142 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003143}
3144
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003145static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003146 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003147{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003148 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003149
3150 BT_DBG("");
3151
Johan Hedberg1707c602013-03-15 17:07:15 -05003152 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003153 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3154 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003155}
3156
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003157static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3158 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003159{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003160 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003161
3162 BT_DBG("");
3163
Johan Hedberg1707c602013-03-15 17:07:15 -05003164 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003165 MGMT_OP_USER_PASSKEY_REPLY,
3166 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003167}
3168
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003169static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003170 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003171{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003172 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003173
3174 BT_DBG("");
3175
Johan Hedberg1707c602013-03-15 17:07:15 -05003176 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003177 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3178 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003179}
3180
Johan Hedberg13928972013-03-15 17:07:00 -05003181static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003182{
Johan Hedberg13928972013-03-15 17:07:00 -05003183 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003184 struct hci_cp_write_local_name cp;
3185
Johan Hedberg13928972013-03-15 17:07:00 -05003186 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003187
Johan Hedberg890ea892013-03-15 17:06:52 -05003188 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003189}
3190
Johan Hedberg13928972013-03-15 17:07:00 -05003191static void set_name_complete(struct hci_dev *hdev, u8 status)
3192{
3193 struct mgmt_cp_set_local_name *cp;
3194 struct pending_cmd *cmd;
3195
3196 BT_DBG("status 0x%02x", status);
3197
3198 hci_dev_lock(hdev);
3199
3200 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3201 if (!cmd)
3202 goto unlock;
3203
3204 cp = cmd->param;
3205
3206 if (status)
3207 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3208 mgmt_status(status));
3209 else
3210 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3211 cp, sizeof(*cp));
3212
3213 mgmt_pending_remove(cmd);
3214
3215unlock:
3216 hci_dev_unlock(hdev);
3217}
3218
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003219static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003220 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003221{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003222 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003223 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003224 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003225 int err;
3226
3227 BT_DBG("");
3228
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003229 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003230
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003231 /* If the old values are the same as the new ones just return a
3232 * direct command complete event.
3233 */
3234 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3235 !memcmp(hdev->short_name, cp->short_name,
3236 sizeof(hdev->short_name))) {
3237 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3238 data, len);
3239 goto failed;
3240 }
3241
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003242 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003243
Johan Hedbergb5235a62012-02-21 14:32:24 +02003244 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003245 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003246
3247 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003248 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003249 if (err < 0)
3250 goto failed;
3251
3252 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003253 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003254
Johan Hedbergb5235a62012-02-21 14:32:24 +02003255 goto failed;
3256 }
3257
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003258 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003259 if (!cmd) {
3260 err = -ENOMEM;
3261 goto failed;
3262 }
3263
Johan Hedberg13928972013-03-15 17:07:00 -05003264 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3265
Johan Hedberg890ea892013-03-15 17:06:52 -05003266 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003267
3268 if (lmp_bredr_capable(hdev)) {
3269 update_name(&req);
3270 update_eir(&req);
3271 }
3272
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003273 /* The name is stored in the scan response data and so
3274 * no need to udpate the advertising data here.
3275 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003276 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003277 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003278
Johan Hedberg13928972013-03-15 17:07:00 -05003279 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003280 if (err < 0)
3281 mgmt_pending_remove(cmd);
3282
3283failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003284 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003285 return err;
3286}
3287
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003288static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003289 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003290{
Szymon Jancc35938b2011-03-22 13:12:21 +01003291 struct pending_cmd *cmd;
3292 int err;
3293
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003294 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003295
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003296 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003297
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003298 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003299 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003300 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003301 goto unlock;
3302 }
3303
Andre Guedes9a1a1992012-07-24 15:03:48 -03003304 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003305 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003306 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003307 goto unlock;
3308 }
3309
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003310 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003311 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003312 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003313 goto unlock;
3314 }
3315
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003316 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003317 if (!cmd) {
3318 err = -ENOMEM;
3319 goto unlock;
3320 }
3321
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003322 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3323 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3324 0, NULL);
3325 else
3326 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3327
Szymon Jancc35938b2011-03-22 13:12:21 +01003328 if (err < 0)
3329 mgmt_pending_remove(cmd);
3330
3331unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003332 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003333 return err;
3334}
3335
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003336static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003337 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003338{
Szymon Janc2763eda2011-03-22 13:12:22 +01003339 int err;
3340
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003341 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003342
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003343 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003344
Marcel Holtmannec109112014-01-10 02:07:30 -08003345 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3346 struct mgmt_cp_add_remote_oob_data *cp = data;
3347 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003348
Marcel Holtmannec109112014-01-10 02:07:30 -08003349 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3350 cp->hash, cp->randomizer);
3351 if (err < 0)
3352 status = MGMT_STATUS_FAILED;
3353 else
3354 status = MGMT_STATUS_SUCCESS;
3355
3356 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3357 status, &cp->addr, sizeof(cp->addr));
3358 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3359 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3360 u8 status;
3361
3362 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3363 cp->hash192,
3364 cp->randomizer192,
3365 cp->hash256,
3366 cp->randomizer256);
3367 if (err < 0)
3368 status = MGMT_STATUS_FAILED;
3369 else
3370 status = MGMT_STATUS_SUCCESS;
3371
3372 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3373 status, &cp->addr, sizeof(cp->addr));
3374 } else {
3375 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3376 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3377 MGMT_STATUS_INVALID_PARAMS);
3378 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003379
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003380 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003381 return err;
3382}
3383
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003384static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003385 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003386{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003387 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003388 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003389 int err;
3390
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003391 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003392
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003393 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003394
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003395 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003396 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003397 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003398 else
Szymon Janca6785be2012-12-13 15:11:21 +01003399 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003400
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003401 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003402 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003403
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003404 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003405 return err;
3406}
3407
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003408static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3409{
3410 struct pending_cmd *cmd;
3411 u8 type;
3412 int err;
3413
3414 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3415
3416 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3417 if (!cmd)
3418 return -ENOENT;
3419
3420 type = hdev->discovery.type;
3421
3422 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3423 &type, sizeof(type));
3424 mgmt_pending_remove(cmd);
3425
3426 return err;
3427}
3428
Andre Guedes7c307722013-04-30 15:29:28 -03003429static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3430{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003431 unsigned long timeout = 0;
3432
Andre Guedes7c307722013-04-30 15:29:28 -03003433 BT_DBG("status %d", status);
3434
3435 if (status) {
3436 hci_dev_lock(hdev);
3437 mgmt_start_discovery_failed(hdev, status);
3438 hci_dev_unlock(hdev);
3439 return;
3440 }
3441
3442 hci_dev_lock(hdev);
3443 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3444 hci_dev_unlock(hdev);
3445
3446 switch (hdev->discovery.type) {
3447 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003448 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003449 break;
3450
3451 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003452 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003453 break;
3454
3455 case DISCOV_TYPE_BREDR:
3456 break;
3457
3458 default:
3459 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3460 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003461
3462 if (!timeout)
3463 return;
3464
3465 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003466}
3467
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003468static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003469 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003470{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003471 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003472 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003473 struct hci_cp_le_set_scan_param param_cp;
3474 struct hci_cp_le_set_scan_enable enable_cp;
3475 struct hci_cp_inquiry inq_cp;
3476 struct hci_request req;
3477 /* General inquiry access code (GIAC) */
3478 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003479 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003480 int err;
3481
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003482 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003483
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003484 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003485
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003486 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003487 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003488 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003489 goto failed;
3490 }
3491
Andre Guedes642be6c2012-03-21 00:03:37 -03003492 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3493 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3494 MGMT_STATUS_BUSY);
3495 goto failed;
3496 }
3497
Johan Hedbergff9ef572012-01-04 14:23:45 +02003498 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003499 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003500 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003501 goto failed;
3502 }
3503
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003504 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003505 if (!cmd) {
3506 err = -ENOMEM;
3507 goto failed;
3508 }
3509
Andre Guedes4aab14e2012-02-17 20:39:36 -03003510 hdev->discovery.type = cp->type;
3511
Andre Guedes7c307722013-04-30 15:29:28 -03003512 hci_req_init(&req, hdev);
3513
Andre Guedes4aab14e2012-02-17 20:39:36 -03003514 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003515 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003516 status = mgmt_bredr_support(hdev);
3517 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003518 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003519 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003520 mgmt_pending_remove(cmd);
3521 goto failed;
3522 }
3523
Andre Guedes7c307722013-04-30 15:29:28 -03003524 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3525 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3526 MGMT_STATUS_BUSY);
3527 mgmt_pending_remove(cmd);
3528 goto failed;
3529 }
3530
3531 hci_inquiry_cache_flush(hdev);
3532
3533 memset(&inq_cp, 0, sizeof(inq_cp));
3534 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003535 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003536 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003537 break;
3538
3539 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003540 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003541 status = mgmt_le_support(hdev);
3542 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003543 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003544 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003545 mgmt_pending_remove(cmd);
3546 goto failed;
3547 }
3548
Andre Guedes7c307722013-04-30 15:29:28 -03003549 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003550 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003551 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3552 MGMT_STATUS_NOT_SUPPORTED);
3553 mgmt_pending_remove(cmd);
3554 goto failed;
3555 }
3556
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003557 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003558 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3559 MGMT_STATUS_REJECTED);
3560 mgmt_pending_remove(cmd);
3561 goto failed;
3562 }
3563
Andre Guedesc54c3862014-02-26 20:21:50 -03003564 /* If controller is scanning, it means the background scanning
3565 * is running. Thus, we should temporarily stop it in order to
3566 * set the discovery scanning parameters.
3567 */
3568 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3569 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003570
3571 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003572
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003573 /* All active scans will be done with either a resolvable
3574 * private address (when privacy feature has been enabled)
3575 * or unresolvable private address.
3576 */
3577 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003578 if (err < 0) {
3579 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3580 MGMT_STATUS_FAILED);
3581 mgmt_pending_remove(cmd);
3582 goto failed;
3583 }
3584
Andre Guedes7c307722013-04-30 15:29:28 -03003585 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003586 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3587 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003588 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003589 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3590 &param_cp);
3591
3592 memset(&enable_cp, 0, sizeof(enable_cp));
3593 enable_cp.enable = LE_SCAN_ENABLE;
3594 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3595 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3596 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003597 break;
3598
Andre Guedesf39799f2012-02-17 20:39:35 -03003599 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003600 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3601 MGMT_STATUS_INVALID_PARAMS);
3602 mgmt_pending_remove(cmd);
3603 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003604 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003605
Andre Guedes7c307722013-04-30 15:29:28 -03003606 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003607 if (err < 0)
3608 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003609 else
3610 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003611
3612failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003613 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003614 return err;
3615}
3616
Andre Guedes1183fdc2013-04-30 15:29:35 -03003617static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3618{
3619 struct pending_cmd *cmd;
3620 int err;
3621
3622 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3623 if (!cmd)
3624 return -ENOENT;
3625
3626 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3627 &hdev->discovery.type, sizeof(hdev->discovery.type));
3628 mgmt_pending_remove(cmd);
3629
3630 return err;
3631}
3632
Andre Guedes0e05bba2013-04-30 15:29:33 -03003633static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3634{
3635 BT_DBG("status %d", status);
3636
3637 hci_dev_lock(hdev);
3638
3639 if (status) {
3640 mgmt_stop_discovery_failed(hdev, status);
3641 goto unlock;
3642 }
3643
3644 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3645
3646unlock:
3647 hci_dev_unlock(hdev);
3648}
3649
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003650static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003651 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003652{
Johan Hedbergd9306502012-02-20 23:25:18 +02003653 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003654 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003655 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003656 int err;
3657
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003658 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003659
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003660 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003661
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003662 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003663 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003664 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3665 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003666 goto unlock;
3667 }
3668
3669 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003670 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003671 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3672 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003673 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003674 }
3675
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003676 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003677 if (!cmd) {
3678 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003679 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003680 }
3681
Andre Guedes0e05bba2013-04-30 15:29:33 -03003682 hci_req_init(&req, hdev);
3683
Johan Hedberg21a60d32014-06-10 14:05:58 +03003684 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003685
Johan Hedberg21a60d32014-06-10 14:05:58 +03003686 err = hci_req_run(&req, stop_discovery_complete);
3687 if (!err) {
3688 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003689 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003690 }
3691
Johan Hedberg21a60d32014-06-10 14:05:58 +03003692 mgmt_pending_remove(cmd);
3693
3694 /* If no HCI commands were sent we're done */
3695 if (err == -ENODATA) {
3696 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3697 &mgmt_cp->type, sizeof(mgmt_cp->type));
3698 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3699 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003700
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003701unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003702 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003703 return err;
3704}
3705
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003706static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003707 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003708{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003709 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003710 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003711 int err;
3712
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003713 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003714
Johan Hedberg561aafb2012-01-04 13:31:59 +02003715 hci_dev_lock(hdev);
3716
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003717 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003718 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3719 MGMT_STATUS_FAILED, &cp->addr,
3720 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003721 goto failed;
3722 }
3723
Johan Hedberga198e7b2012-02-17 14:27:06 +02003724 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003725 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003726 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3727 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3728 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003729 goto failed;
3730 }
3731
3732 if (cp->name_known) {
3733 e->name_state = NAME_KNOWN;
3734 list_del(&e->list);
3735 } else {
3736 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e20a2012-01-09 00:53:02 +02003737 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003738 }
3739
Johan Hedberge3846622013-01-09 15:29:33 +02003740 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3741 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003742
3743failed:
3744 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003745 return err;
3746}
3747
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003748static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003749 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003750{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003751 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003752 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003753 int err;
3754
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003755 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003756
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003757 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003758 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3759 MGMT_STATUS_INVALID_PARAMS,
3760 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003761
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003762 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003763
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003764 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003765 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003766 status = MGMT_STATUS_FAILED;
Antti Julku7fbec222011-06-15 12:01:15 +03003767 else
Szymon Janca6785be2012-12-13 15:11:21 +01003768 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003769
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003770 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003771 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003772
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003773 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003774
3775 return err;
3776}
3777
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003778static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003779 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003780{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003781 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003782 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003783 int err;
3784
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003785 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003786
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003787 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003788 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3789 MGMT_STATUS_INVALID_PARAMS,
3790 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003791
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003792 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003793
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003794 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003795 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003796 status = MGMT_STATUS_INVALID_PARAMS;
Antti Julku7fbec222011-06-15 12:01:15 +03003797 else
Szymon Janca6785be2012-12-13 15:11:21 +01003798 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003799
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003800 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003801 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003802
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003803 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003804
3805 return err;
3806}
3807
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003808static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3809 u16 len)
3810{
3811 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003812 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003813 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003814 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003815
3816 BT_DBG("%s", hdev->name);
3817
Szymon Jancc72d4b82012-03-16 16:02:57 +01003818 source = __le16_to_cpu(cp->source);
3819
3820 if (source > 0x0002)
3821 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3822 MGMT_STATUS_INVALID_PARAMS);
3823
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003824 hci_dev_lock(hdev);
3825
Szymon Jancc72d4b82012-03-16 16:02:57 +01003826 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003827 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3828 hdev->devid_product = __le16_to_cpu(cp->product);
3829 hdev->devid_version = __le16_to_cpu(cp->version);
3830
3831 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3832
Johan Hedberg890ea892013-03-15 17:06:52 -05003833 hci_req_init(&req, hdev);
3834 update_eir(&req);
3835 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003836
3837 hci_dev_unlock(hdev);
3838
3839 return err;
3840}
3841
Johan Hedberg4375f102013-09-25 13:26:10 +03003842static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3843{
3844 struct cmd_lookup match = { NULL, hdev };
3845
3846 if (status) {
3847 u8 mgmt_err = mgmt_status(status);
3848
3849 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3850 cmd_status_rsp, &mgmt_err);
3851 return;
3852 }
3853
3854 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3855 &match);
3856
3857 new_settings(hdev, match.sk);
3858
3859 if (match.sk)
3860 sock_put(match.sk);
3861}
3862
Marcel Holtmann21b51872013-10-10 09:47:53 -07003863static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3864 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003865{
3866 struct mgmt_mode *cp = data;
3867 struct pending_cmd *cmd;
3868 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003869 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003870 int err;
3871
3872 BT_DBG("request for %s", hdev->name);
3873
Johan Hedberge6fe7982013-10-02 15:45:22 +03003874 status = mgmt_le_support(hdev);
3875 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003876 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003877 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03003878
3879 if (cp->val != 0x00 && cp->val != 0x01)
3880 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3881 MGMT_STATUS_INVALID_PARAMS);
3882
3883 hci_dev_lock(hdev);
3884
3885 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003886 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003887
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02003888 /* The following conditions are ones which mean that we should
3889 * not do any HCI communication but directly send a mgmt
3890 * response to user space (after toggling the flag if
3891 * necessary).
3892 */
3893 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07003894 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03003895 bool changed = false;
3896
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003897 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
3898 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003899 changed = true;
3900 }
3901
3902 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
3903 if (err < 0)
3904 goto unlock;
3905
3906 if (changed)
3907 err = new_settings(hdev, sk);
3908
3909 goto unlock;
3910 }
3911
3912 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
3913 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
3914 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3915 MGMT_STATUS_BUSY);
3916 goto unlock;
3917 }
3918
3919 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
3920 if (!cmd) {
3921 err = -ENOMEM;
3922 goto unlock;
3923 }
3924
3925 hci_req_init(&req, hdev);
3926
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07003927 if (val)
3928 enable_advertising(&req);
3929 else
3930 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03003931
3932 err = hci_req_run(&req, set_advertising_complete);
3933 if (err < 0)
3934 mgmt_pending_remove(cmd);
3935
3936unlock:
3937 hci_dev_unlock(hdev);
3938 return err;
3939}
3940
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003941static int set_static_address(struct sock *sk, struct hci_dev *hdev,
3942 void *data, u16 len)
3943{
3944 struct mgmt_cp_set_static_address *cp = data;
3945 int err;
3946
3947 BT_DBG("%s", hdev->name);
3948
Marcel Holtmann62af4442013-10-02 22:10:32 -07003949 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003950 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07003951 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003952
3953 if (hdev_is_powered(hdev))
3954 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
3955 MGMT_STATUS_REJECTED);
3956
3957 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
3958 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
3959 return cmd_status(sk, hdev->id,
3960 MGMT_OP_SET_STATIC_ADDRESS,
3961 MGMT_STATUS_INVALID_PARAMS);
3962
3963 /* Two most significant bits shall be set */
3964 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
3965 return cmd_status(sk, hdev->id,
3966 MGMT_OP_SET_STATIC_ADDRESS,
3967 MGMT_STATUS_INVALID_PARAMS);
3968 }
3969
3970 hci_dev_lock(hdev);
3971
3972 bacpy(&hdev->static_addr, &cp->bdaddr);
3973
3974 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
3975
3976 hci_dev_unlock(hdev);
3977
3978 return err;
3979}
3980
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003981static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
3982 void *data, u16 len)
3983{
3984 struct mgmt_cp_set_scan_params *cp = data;
3985 __u16 interval, window;
3986 int err;
3987
3988 BT_DBG("%s", hdev->name);
3989
3990 if (!lmp_le_capable(hdev))
3991 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3992 MGMT_STATUS_NOT_SUPPORTED);
3993
3994 interval = __le16_to_cpu(cp->interval);
3995
3996 if (interval < 0x0004 || interval > 0x4000)
3997 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3998 MGMT_STATUS_INVALID_PARAMS);
3999
4000 window = __le16_to_cpu(cp->window);
4001
4002 if (window < 0x0004 || window > 0x4000)
4003 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4004 MGMT_STATUS_INVALID_PARAMS);
4005
Marcel Holtmann899e1072013-10-14 09:55:32 -07004006 if (window > interval)
4007 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4008 MGMT_STATUS_INVALID_PARAMS);
4009
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004010 hci_dev_lock(hdev);
4011
4012 hdev->le_scan_interval = interval;
4013 hdev->le_scan_window = window;
4014
4015 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4016
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004017 /* If background scan is running, restart it so new parameters are
4018 * loaded.
4019 */
4020 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4021 hdev->discovery.state == DISCOVERY_STOPPED) {
4022 struct hci_request req;
4023
4024 hci_req_init(&req, hdev);
4025
4026 hci_req_add_le_scan_disable(&req);
4027 hci_req_add_le_passive_scan(&req);
4028
4029 hci_req_run(&req, NULL);
4030 }
4031
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004032 hci_dev_unlock(hdev);
4033
4034 return err;
4035}
4036
Johan Hedberg33e38b32013-03-15 17:07:05 -05004037static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4038{
4039 struct pending_cmd *cmd;
4040
4041 BT_DBG("status 0x%02x", status);
4042
4043 hci_dev_lock(hdev);
4044
4045 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4046 if (!cmd)
4047 goto unlock;
4048
4049 if (status) {
4050 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4051 mgmt_status(status));
4052 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004053 struct mgmt_mode *cp = cmd->param;
4054
4055 if (cp->val)
4056 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4057 else
4058 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4059
Johan Hedberg33e38b32013-03-15 17:07:05 -05004060 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4061 new_settings(hdev, cmd->sk);
4062 }
4063
4064 mgmt_pending_remove(cmd);
4065
4066unlock:
4067 hci_dev_unlock(hdev);
4068}
4069
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004070static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004071 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004072{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004073 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004074 struct pending_cmd *cmd;
4075 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004076 int err;
4077
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004078 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004079
Johan Hedberg56f87902013-10-02 13:43:13 +03004080 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4081 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004082 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4083 MGMT_STATUS_NOT_SUPPORTED);
4084
Johan Hedberga7e80f22013-01-09 16:05:19 +02004085 if (cp->val != 0x00 && cp->val != 0x01)
4086 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4087 MGMT_STATUS_INVALID_PARAMS);
4088
Johan Hedberg5400c042012-02-21 16:40:33 +02004089 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004090 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004091 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004092
4093 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004094 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004095 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004096
4097 hci_dev_lock(hdev);
4098
Johan Hedberg05cbf292013-03-15 17:07:07 -05004099 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4100 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4101 MGMT_STATUS_BUSY);
4102 goto unlock;
4103 }
4104
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004105 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4106 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4107 hdev);
4108 goto unlock;
4109 }
4110
Johan Hedberg33e38b32013-03-15 17:07:05 -05004111 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4112 data, len);
4113 if (!cmd) {
4114 err = -ENOMEM;
4115 goto unlock;
4116 }
4117
4118 hci_req_init(&req, hdev);
4119
Johan Hedberg406d7802013-03-15 17:07:09 -05004120 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004121
4122 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004123 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004124 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004125 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004126 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004127 }
4128
Johan Hedberg33e38b32013-03-15 17:07:05 -05004129unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004130 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004131
Antti Julkuf6422ec2011-06-22 13:11:56 +03004132 return err;
4133}
4134
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004135static void set_bredr_scan(struct hci_request *req)
4136{
4137 struct hci_dev *hdev = req->hdev;
4138 u8 scan = 0;
4139
4140 /* Ensure that fast connectable is disabled. This function will
4141 * not do anything if the page scan parameters are already what
4142 * they should be.
4143 */
4144 write_fast_connectable(req, false);
4145
4146 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4147 scan |= SCAN_PAGE;
4148 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4149 scan |= SCAN_INQUIRY;
4150
4151 if (scan)
4152 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4153}
4154
Johan Hedberg0663ca22013-10-02 13:43:14 +03004155static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4156{
4157 struct pending_cmd *cmd;
4158
4159 BT_DBG("status 0x%02x", status);
4160
4161 hci_dev_lock(hdev);
4162
4163 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4164 if (!cmd)
4165 goto unlock;
4166
4167 if (status) {
4168 u8 mgmt_err = mgmt_status(status);
4169
4170 /* We need to restore the flag if related HCI commands
4171 * failed.
4172 */
4173 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4174
4175 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4176 } else {
4177 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4178 new_settings(hdev, cmd->sk);
4179 }
4180
4181 mgmt_pending_remove(cmd);
4182
4183unlock:
4184 hci_dev_unlock(hdev);
4185}
4186
4187static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4188{
4189 struct mgmt_mode *cp = data;
4190 struct pending_cmd *cmd;
4191 struct hci_request req;
4192 int err;
4193
4194 BT_DBG("request for %s", hdev->name);
4195
4196 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4197 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4198 MGMT_STATUS_NOT_SUPPORTED);
4199
4200 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4201 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4202 MGMT_STATUS_REJECTED);
4203
4204 if (cp->val != 0x00 && cp->val != 0x01)
4205 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4206 MGMT_STATUS_INVALID_PARAMS);
4207
4208 hci_dev_lock(hdev);
4209
4210 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4211 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4212 goto unlock;
4213 }
4214
4215 if (!hdev_is_powered(hdev)) {
4216 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004217 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4218 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4219 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4220 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4221 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4222 }
4223
4224 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4225
4226 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4227 if (err < 0)
4228 goto unlock;
4229
4230 err = new_settings(hdev, sk);
4231 goto unlock;
4232 }
4233
4234 /* Reject disabling when powered on */
4235 if (!cp->val) {
4236 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4237 MGMT_STATUS_REJECTED);
4238 goto unlock;
4239 }
4240
4241 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4242 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4243 MGMT_STATUS_BUSY);
4244 goto unlock;
4245 }
4246
4247 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4248 if (!cmd) {
4249 err = -ENOMEM;
4250 goto unlock;
4251 }
4252
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004253 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004254 * generates the correct flags.
4255 */
4256 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4257
4258 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004259
4260 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4261 set_bredr_scan(&req);
4262
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004263 /* Since only the advertising data flags will change, there
4264 * is no need to update the scan response data.
4265 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004266 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004267
Johan Hedberg0663ca22013-10-02 13:43:14 +03004268 err = hci_req_run(&req, set_bredr_complete);
4269 if (err < 0)
4270 mgmt_pending_remove(cmd);
4271
4272unlock:
4273 hci_dev_unlock(hdev);
4274 return err;
4275}
4276
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004277static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4278 void *data, u16 len)
4279{
4280 struct mgmt_mode *cp = data;
4281 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004282 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004283 int err;
4284
4285 BT_DBG("request for %s", hdev->name);
4286
4287 status = mgmt_bredr_support(hdev);
4288 if (status)
4289 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4290 status);
4291
Marcel Holtmann5afeac12014-01-10 02:07:27 -08004292 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004293 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004294 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4295 MGMT_STATUS_NOT_SUPPORTED);
4296
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004297 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004298 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4299 MGMT_STATUS_INVALID_PARAMS);
4300
4301 hci_dev_lock(hdev);
4302
4303 if (!hdev_is_powered(hdev)) {
4304 bool changed;
4305
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004306 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004307 changed = !test_and_set_bit(HCI_SC_ENABLED,
4308 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004309 if (cp->val == 0x02)
4310 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4311 else
4312 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4313 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004314 changed = test_and_clear_bit(HCI_SC_ENABLED,
4315 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004316 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4317 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004318
4319 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4320 if (err < 0)
4321 goto failed;
4322
4323 if (changed)
4324 err = new_settings(hdev, sk);
4325
4326 goto failed;
4327 }
4328
4329 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4330 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4331 MGMT_STATUS_BUSY);
4332 goto failed;
4333 }
4334
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004335 val = !!cp->val;
4336
4337 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4338 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004339 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4340 goto failed;
4341 }
4342
4343 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4344 if (!cmd) {
4345 err = -ENOMEM;
4346 goto failed;
4347 }
4348
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004349 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004350 if (err < 0) {
4351 mgmt_pending_remove(cmd);
4352 goto failed;
4353 }
4354
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004355 if (cp->val == 0x02)
4356 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4357 else
4358 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4359
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004360failed:
4361 hci_dev_unlock(hdev);
4362 return err;
4363}
4364
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004365static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4366 void *data, u16 len)
4367{
4368 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004369 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004370 int err;
4371
4372 BT_DBG("request for %s", hdev->name);
4373
Johan Hedbergb97109792014-06-24 14:00:28 +03004374 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004375 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4376 MGMT_STATUS_INVALID_PARAMS);
4377
4378 hci_dev_lock(hdev);
4379
4380 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004381 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4382 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004383 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004384 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4385 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004386
Johan Hedbergb97109792014-06-24 14:00:28 +03004387 if (cp->val == 0x02)
4388 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4389 &hdev->dev_flags);
4390 else
4391 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4392 &hdev->dev_flags);
4393
4394 if (hdev_is_powered(hdev) && use_changed &&
4395 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4396 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4397 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4398 sizeof(mode), &mode);
4399 }
4400
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004401 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4402 if (err < 0)
4403 goto unlock;
4404
4405 if (changed)
4406 err = new_settings(hdev, sk);
4407
4408unlock:
4409 hci_dev_unlock(hdev);
4410 return err;
4411}
4412
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004413static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4414 u16 len)
4415{
4416 struct mgmt_cp_set_privacy *cp = cp_data;
4417 bool changed;
4418 int err;
4419
4420 BT_DBG("request for %s", hdev->name);
4421
4422 if (!lmp_le_capable(hdev))
4423 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4424 MGMT_STATUS_NOT_SUPPORTED);
4425
4426 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4427 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4428 MGMT_STATUS_INVALID_PARAMS);
4429
4430 if (hdev_is_powered(hdev))
4431 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4432 MGMT_STATUS_REJECTED);
4433
4434 hci_dev_lock(hdev);
4435
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004436 /* If user space supports this command it is also expected to
4437 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4438 */
4439 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4440
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004441 if (cp->privacy) {
4442 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4443 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4444 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4445 } else {
4446 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4447 memset(hdev->irk, 0, sizeof(hdev->irk));
4448 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4449 }
4450
4451 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4452 if (err < 0)
4453 goto unlock;
4454
4455 if (changed)
4456 err = new_settings(hdev, sk);
4457
4458unlock:
4459 hci_dev_unlock(hdev);
4460 return err;
4461}
4462
Johan Hedberg41edf162014-02-18 10:19:35 +02004463static bool irk_is_valid(struct mgmt_irk_info *irk)
4464{
4465 switch (irk->addr.type) {
4466 case BDADDR_LE_PUBLIC:
4467 return true;
4468
4469 case BDADDR_LE_RANDOM:
4470 /* Two most significant bits shall be set */
4471 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4472 return false;
4473 return true;
4474 }
4475
4476 return false;
4477}
4478
4479static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4480 u16 len)
4481{
4482 struct mgmt_cp_load_irks *cp = cp_data;
4483 u16 irk_count, expected_len;
4484 int i, err;
4485
4486 BT_DBG("request for %s", hdev->name);
4487
4488 if (!lmp_le_capable(hdev))
4489 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4490 MGMT_STATUS_NOT_SUPPORTED);
4491
4492 irk_count = __le16_to_cpu(cp->irk_count);
4493
4494 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4495 if (expected_len != len) {
4496 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004497 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004498 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4499 MGMT_STATUS_INVALID_PARAMS);
4500 }
4501
4502 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4503
4504 for (i = 0; i < irk_count; i++) {
4505 struct mgmt_irk_info *key = &cp->irks[i];
4506
4507 if (!irk_is_valid(key))
4508 return cmd_status(sk, hdev->id,
4509 MGMT_OP_LOAD_IRKS,
4510 MGMT_STATUS_INVALID_PARAMS);
4511 }
4512
4513 hci_dev_lock(hdev);
4514
4515 hci_smp_irks_clear(hdev);
4516
4517 for (i = 0; i < irk_count; i++) {
4518 struct mgmt_irk_info *irk = &cp->irks[i];
4519 u8 addr_type;
4520
4521 if (irk->addr.type == BDADDR_LE_PUBLIC)
4522 addr_type = ADDR_LE_DEV_PUBLIC;
4523 else
4524 addr_type = ADDR_LE_DEV_RANDOM;
4525
4526 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4527 BDADDR_ANY);
4528 }
4529
4530 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4531
4532 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4533
4534 hci_dev_unlock(hdev);
4535
4536 return err;
4537}
4538
Johan Hedberg3f706b72013-01-20 14:27:16 +02004539static bool ltk_is_valid(struct mgmt_ltk_info *key)
4540{
4541 if (key->master != 0x00 && key->master != 0x01)
4542 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004543
4544 switch (key->addr.type) {
4545 case BDADDR_LE_PUBLIC:
4546 return true;
4547
4548 case BDADDR_LE_RANDOM:
4549 /* Two most significant bits shall be set */
4550 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4551 return false;
4552 return true;
4553 }
4554
4555 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004556}
4557
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004558static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004559 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004560{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004561 struct mgmt_cp_load_long_term_keys *cp = cp_data;
4562 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004563 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004564
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004565 BT_DBG("request for %s", hdev->name);
4566
4567 if (!lmp_le_capable(hdev))
4568 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4569 MGMT_STATUS_NOT_SUPPORTED);
4570
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004571 key_count = __le16_to_cpu(cp->key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004572
4573 expected_len = sizeof(*cp) + key_count *
4574 sizeof(struct mgmt_ltk_info);
4575 if (expected_len != len) {
4576 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004577 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004578 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004579 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004580 }
4581
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004582 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004583
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004584 for (i = 0; i < key_count; i++) {
4585 struct mgmt_ltk_info *key = &cp->keys[i];
4586
Johan Hedberg3f706b72013-01-20 14:27:16 +02004587 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004588 return cmd_status(sk, hdev->id,
4589 MGMT_OP_LOAD_LONG_TERM_KEYS,
4590 MGMT_STATUS_INVALID_PARAMS);
4591 }
4592
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004593 hci_dev_lock(hdev);
4594
4595 hci_smp_ltks_clear(hdev);
4596
4597 for (i = 0; i < key_count; i++) {
4598 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004599 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004600
4601 if (key->addr.type == BDADDR_LE_PUBLIC)
4602 addr_type = ADDR_LE_DEV_PUBLIC;
4603 else
4604 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004605
4606 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004607 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004608 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004609 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004610
Johan Hedberg61b43352014-05-29 19:36:53 +03004611 switch (key->type) {
4612 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004613 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004614 break;
4615 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004616 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004617 break;
4618 default:
4619 continue;
4620 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004621
Johan Hedberg35d70272014-02-19 14:57:47 +02004622 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004623 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004624 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004625 }
4626
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004627 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4628 NULL, 0);
4629
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004630 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004631
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004632 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004633}
4634
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004635struct cmd_conn_lookup {
4636 struct hci_conn *conn;
4637 bool valid_tx_power;
4638 u8 mgmt_status;
4639};
4640
4641static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4642{
4643 struct cmd_conn_lookup *match = data;
4644 struct mgmt_cp_get_conn_info *cp;
4645 struct mgmt_rp_get_conn_info rp;
4646 struct hci_conn *conn = cmd->user_data;
4647
4648 if (conn != match->conn)
4649 return;
4650
4651 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4652
4653 memset(&rp, 0, sizeof(rp));
4654 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4655 rp.addr.type = cp->addr.type;
4656
4657 if (!match->mgmt_status) {
4658 rp.rssi = conn->rssi;
4659
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004660 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004661 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004662 rp.max_tx_power = conn->max_tx_power;
4663 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004664 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004665 rp.max_tx_power = HCI_TX_POWER_INVALID;
4666 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004667 }
4668
4669 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4670 match->mgmt_status, &rp, sizeof(rp));
4671
4672 hci_conn_drop(conn);
4673
4674 mgmt_pending_remove(cmd);
4675}
4676
4677static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4678{
4679 struct hci_cp_read_rssi *cp;
4680 struct hci_conn *conn;
4681 struct cmd_conn_lookup match;
4682 u16 handle;
4683
4684 BT_DBG("status 0x%02x", status);
4685
4686 hci_dev_lock(hdev);
4687
4688 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004689 * otherwise we assume it's not valid. At the moment we assume that
4690 * either both or none of current and max values are valid to keep code
4691 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004692 */
4693 match.valid_tx_power = !status;
4694
4695 /* Commands sent in request are either Read RSSI or Read Transmit Power
4696 * Level so we check which one was last sent to retrieve connection
4697 * handle. Both commands have handle as first parameter so it's safe to
4698 * cast data on the same command struct.
4699 *
4700 * First command sent is always Read RSSI and we fail only if it fails.
4701 * In other case we simply override error to indicate success as we
4702 * already remembered if TX power value is actually valid.
4703 */
4704 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4705 if (!cp) {
4706 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4707 status = 0;
4708 }
4709
4710 if (!cp) {
4711 BT_ERR("invalid sent_cmd in response");
4712 goto unlock;
4713 }
4714
4715 handle = __le16_to_cpu(cp->handle);
4716 conn = hci_conn_hash_lookup_handle(hdev, handle);
4717 if (!conn) {
4718 BT_ERR("unknown handle (%d) in response", handle);
4719 goto unlock;
4720 }
4721
4722 match.conn = conn;
4723 match.mgmt_status = mgmt_status(status);
4724
4725 /* Cache refresh is complete, now reply for mgmt request for given
4726 * connection only.
4727 */
4728 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4729 get_conn_info_complete, &match);
4730
4731unlock:
4732 hci_dev_unlock(hdev);
4733}
4734
4735static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4736 u16 len)
4737{
4738 struct mgmt_cp_get_conn_info *cp = data;
4739 struct mgmt_rp_get_conn_info rp;
4740 struct hci_conn *conn;
4741 unsigned long conn_info_age;
4742 int err = 0;
4743
4744 BT_DBG("%s", hdev->name);
4745
4746 memset(&rp, 0, sizeof(rp));
4747 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4748 rp.addr.type = cp->addr.type;
4749
4750 if (!bdaddr_type_is_valid(cp->addr.type))
4751 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4752 MGMT_STATUS_INVALID_PARAMS,
4753 &rp, sizeof(rp));
4754
4755 hci_dev_lock(hdev);
4756
4757 if (!hdev_is_powered(hdev)) {
4758 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4759 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4760 goto unlock;
4761 }
4762
4763 if (cp->addr.type == BDADDR_BREDR)
4764 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4765 &cp->addr.bdaddr);
4766 else
4767 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4768
4769 if (!conn || conn->state != BT_CONNECTED) {
4770 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4771 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4772 goto unlock;
4773 }
4774
4775 /* To avoid client trying to guess when to poll again for information we
4776 * calculate conn info age as random value between min/max set in hdev.
4777 */
4778 conn_info_age = hdev->conn_info_min_age +
4779 prandom_u32_max(hdev->conn_info_max_age -
4780 hdev->conn_info_min_age);
4781
4782 /* Query controller to refresh cached values if they are too old or were
4783 * never read.
4784 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004785 if (time_after(jiffies, conn->conn_info_timestamp +
4786 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004787 !conn->conn_info_timestamp) {
4788 struct hci_request req;
4789 struct hci_cp_read_tx_power req_txp_cp;
4790 struct hci_cp_read_rssi req_rssi_cp;
4791 struct pending_cmd *cmd;
4792
4793 hci_req_init(&req, hdev);
4794 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4795 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4796 &req_rssi_cp);
4797
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004798 /* For LE links TX power does not change thus we don't need to
4799 * query for it once value is known.
4800 */
4801 if (!bdaddr_type_is_le(cp->addr.type) ||
4802 conn->tx_power == HCI_TX_POWER_INVALID) {
4803 req_txp_cp.handle = cpu_to_le16(conn->handle);
4804 req_txp_cp.type = 0x00;
4805 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4806 sizeof(req_txp_cp), &req_txp_cp);
4807 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004808
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004809 /* Max TX power needs to be read only once per connection */
4810 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
4811 req_txp_cp.handle = cpu_to_le16(conn->handle);
4812 req_txp_cp.type = 0x01;
4813 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4814 sizeof(req_txp_cp), &req_txp_cp);
4815 }
4816
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004817 err = hci_req_run(&req, conn_info_refresh_complete);
4818 if (err < 0)
4819 goto unlock;
4820
4821 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
4822 data, len);
4823 if (!cmd) {
4824 err = -ENOMEM;
4825 goto unlock;
4826 }
4827
4828 hci_conn_hold(conn);
4829 cmd->user_data = conn;
4830
4831 conn->conn_info_timestamp = jiffies;
4832 } else {
4833 /* Cache is valid, just reply with values cached in hci_conn */
4834 rp.rssi = conn->rssi;
4835 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004836 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004837
4838 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4839 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
4840 }
4841
4842unlock:
4843 hci_dev_unlock(hdev);
4844 return err;
4845}
4846
Johan Hedberg95868422014-06-28 17:54:07 +03004847static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
4848{
4849 struct mgmt_cp_get_clock_info *cp;
4850 struct mgmt_rp_get_clock_info rp;
4851 struct hci_cp_read_clock *hci_cp;
4852 struct pending_cmd *cmd;
4853 struct hci_conn *conn;
4854
4855 BT_DBG("%s status %u", hdev->name, status);
4856
4857 hci_dev_lock(hdev);
4858
4859 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
4860 if (!hci_cp)
4861 goto unlock;
4862
4863 if (hci_cp->which) {
4864 u16 handle = __le16_to_cpu(hci_cp->handle);
4865 conn = hci_conn_hash_lookup_handle(hdev, handle);
4866 } else {
4867 conn = NULL;
4868 }
4869
4870 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
4871 if (!cmd)
4872 goto unlock;
4873
4874 cp = cmd->param;
4875
4876 memset(&rp, 0, sizeof(rp));
4877 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
4878
4879 if (status)
4880 goto send_rsp;
4881
4882 rp.local_clock = cpu_to_le32(hdev->clock);
4883
4884 if (conn) {
4885 rp.piconet_clock = cpu_to_le32(conn->clock);
4886 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
4887 }
4888
4889send_rsp:
4890 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
4891 &rp, sizeof(rp));
4892 mgmt_pending_remove(cmd);
4893 if (conn)
4894 hci_conn_drop(conn);
4895
4896unlock:
4897 hci_dev_unlock(hdev);
4898}
4899
4900static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
4901 u16 len)
4902{
4903 struct mgmt_cp_get_clock_info *cp = data;
4904 struct mgmt_rp_get_clock_info rp;
4905 struct hci_cp_read_clock hci_cp;
4906 struct pending_cmd *cmd;
4907 struct hci_request req;
4908 struct hci_conn *conn;
4909 int err;
4910
4911 BT_DBG("%s", hdev->name);
4912
4913 memset(&rp, 0, sizeof(rp));
4914 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4915 rp.addr.type = cp->addr.type;
4916
4917 if (cp->addr.type != BDADDR_BREDR)
4918 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
4919 MGMT_STATUS_INVALID_PARAMS,
4920 &rp, sizeof(rp));
4921
4922 hci_dev_lock(hdev);
4923
4924 if (!hdev_is_powered(hdev)) {
4925 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
4926 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4927 goto unlock;
4928 }
4929
4930 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
4931 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4932 &cp->addr.bdaddr);
4933 if (!conn || conn->state != BT_CONNECTED) {
4934 err = cmd_complete(sk, hdev->id,
4935 MGMT_OP_GET_CLOCK_INFO,
4936 MGMT_STATUS_NOT_CONNECTED,
4937 &rp, sizeof(rp));
4938 goto unlock;
4939 }
4940 } else {
4941 conn = NULL;
4942 }
4943
4944 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
4945 if (!cmd) {
4946 err = -ENOMEM;
4947 goto unlock;
4948 }
4949
4950 hci_req_init(&req, hdev);
4951
4952 memset(&hci_cp, 0, sizeof(hci_cp));
4953 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
4954
4955 if (conn) {
4956 hci_conn_hold(conn);
4957 cmd->user_data = conn;
4958
4959 hci_cp.handle = cpu_to_le16(conn->handle);
4960 hci_cp.which = 0x01; /* Piconet clock */
4961 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
4962 }
4963
4964 err = hci_req_run(&req, get_clock_info_complete);
4965 if (err < 0)
4966 mgmt_pending_remove(cmd);
4967
4968unlock:
4969 hci_dev_unlock(hdev);
4970 return err;
4971}
4972
Marcel Holtmann8afef092014-06-29 22:28:34 +02004973static void device_added(struct sock *sk, struct hci_dev *hdev,
4974 bdaddr_t *bdaddr, u8 type, u8 action)
4975{
4976 struct mgmt_ev_device_added ev;
4977
4978 bacpy(&ev.addr.bdaddr, bdaddr);
4979 ev.addr.type = type;
4980 ev.action = action;
4981
4982 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
4983}
4984
Marcel Holtmann2faade52014-06-29 19:44:03 +02004985static int add_device(struct sock *sk, struct hci_dev *hdev,
4986 void *data, u16 len)
4987{
4988 struct mgmt_cp_add_device *cp = data;
4989 u8 auto_conn, addr_type;
4990 int err;
4991
4992 BT_DBG("%s", hdev->name);
4993
4994 if (!bdaddr_type_is_le(cp->addr.type) ||
4995 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
4996 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
4997 MGMT_STATUS_INVALID_PARAMS,
4998 &cp->addr, sizeof(cp->addr));
4999
5000 if (cp->action != 0x00 && cp->action != 0x01)
5001 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5002 MGMT_STATUS_INVALID_PARAMS,
5003 &cp->addr, sizeof(cp->addr));
5004
5005 hci_dev_lock(hdev);
5006
5007 if (cp->addr.type == BDADDR_LE_PUBLIC)
5008 addr_type = ADDR_LE_DEV_PUBLIC;
5009 else
5010 addr_type = ADDR_LE_DEV_RANDOM;
5011
5012 if (cp->action)
5013 auto_conn = HCI_AUTO_CONN_ALWAYS;
5014 else
5015 auto_conn = HCI_AUTO_CONN_DISABLED;
5016
5017 if (hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type, auto_conn,
5018 hdev->le_conn_min_interval,
5019 hdev->le_conn_max_interval) < 0) {
5020 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5021 MGMT_STATUS_FAILED,
5022 &cp->addr, sizeof(cp->addr));
5023 goto unlock;
5024 }
5025
Marcel Holtmann8afef092014-06-29 22:28:34 +02005026 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5027
Marcel Holtmann2faade52014-06-29 19:44:03 +02005028 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5029 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5030
5031unlock:
5032 hci_dev_unlock(hdev);
5033 return err;
5034}
5035
Marcel Holtmann8afef092014-06-29 22:28:34 +02005036static void device_removed(struct sock *sk, struct hci_dev *hdev,
5037 bdaddr_t *bdaddr, u8 type)
5038{
5039 struct mgmt_ev_device_removed ev;
5040
5041 bacpy(&ev.addr.bdaddr, bdaddr);
5042 ev.addr.type = type;
5043
5044 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5045}
5046
Marcel Holtmann2faade52014-06-29 19:44:03 +02005047static int remove_device(struct sock *sk, struct hci_dev *hdev,
5048 void *data, u16 len)
5049{
5050 struct mgmt_cp_remove_device *cp = data;
5051 int err;
5052
5053 BT_DBG("%s", hdev->name);
5054
5055 hci_dev_lock(hdev);
5056
5057 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5058 u8 addr_type;
5059
5060 if (!bdaddr_type_is_le(cp->addr.type)) {
5061 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5062 MGMT_STATUS_INVALID_PARAMS,
5063 &cp->addr, sizeof(cp->addr));
5064 goto unlock;
5065 }
5066
5067 if (cp->addr.type == BDADDR_LE_PUBLIC)
5068 addr_type = ADDR_LE_DEV_PUBLIC;
5069 else
5070 addr_type = ADDR_LE_DEV_RANDOM;
5071
5072 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005073
5074 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005075 } else {
5076 if (cp->addr.type) {
5077 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5078 MGMT_STATUS_INVALID_PARAMS,
5079 &cp->addr, sizeof(cp->addr));
5080 goto unlock;
5081 }
5082
5083 hci_conn_params_clear(hdev);
5084 }
5085
5086 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5087 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5088
5089unlock:
5090 hci_dev_unlock(hdev);
5091 return err;
5092}
5093
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005094static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005095 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5096 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005097 bool var_len;
5098 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005099} mgmt_handlers[] = {
5100 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005101 { read_version, false, MGMT_READ_VERSION_SIZE },
5102 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5103 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5104 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5105 { set_powered, false, MGMT_SETTING_SIZE },
5106 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5107 { set_connectable, false, MGMT_SETTING_SIZE },
5108 { set_fast_connectable, false, MGMT_SETTING_SIZE },
5109 { set_pairable, false, MGMT_SETTING_SIZE },
5110 { set_link_security, false, MGMT_SETTING_SIZE },
5111 { set_ssp, false, MGMT_SETTING_SIZE },
5112 { set_hs, false, MGMT_SETTING_SIZE },
5113 { set_le, false, MGMT_SETTING_SIZE },
5114 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5115 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5116 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5117 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5118 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5119 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5120 { disconnect, false, MGMT_DISCONNECT_SIZE },
5121 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5122 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5123 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5124 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5125 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5126 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5127 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5128 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5129 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5130 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5131 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5132 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005133 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005134 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5135 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5136 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5137 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5138 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5139 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005140 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005141 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005142 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005143 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005144 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005145 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005146 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005147 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005148 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005149 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005150 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005151 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5152 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005153};
5154
Johan Hedberg03811012010-12-08 00:21:06 +02005155int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5156{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005157 void *buf;
5158 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005159 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005160 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005161 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005162 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005163 int err;
5164
5165 BT_DBG("got %zu bytes", msglen);
5166
5167 if (msglen < sizeof(*hdr))
5168 return -EINVAL;
5169
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005170 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005171 if (!buf)
5172 return -ENOMEM;
5173
5174 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5175 err = -EFAULT;
5176 goto done;
5177 }
5178
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005179 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005180 opcode = __le16_to_cpu(hdr->opcode);
5181 index = __le16_to_cpu(hdr->index);
5182 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005183
5184 if (len != msglen - sizeof(*hdr)) {
5185 err = -EINVAL;
5186 goto done;
5187 }
5188
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005189 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005190 hdev = hci_dev_get(index);
5191 if (!hdev) {
5192 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005193 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005194 goto done;
5195 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005196
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005197 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannfee746b2014-06-29 12:13:05 +02005198 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) ||
5199 test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005200 err = cmd_status(sk, index, opcode,
5201 MGMT_STATUS_INVALID_INDEX);
5202 goto done;
5203 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005204 }
5205
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005206 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005207 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005208 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005209 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005210 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005211 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005212 }
5213
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005214 if ((hdev && opcode < MGMT_OP_READ_INFO) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005215 (!hdev && opcode >= MGMT_OP_READ_INFO)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005216 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005217 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005218 goto done;
5219 }
5220
Johan Hedbergbe22b542012-03-01 22:24:41 +02005221 handler = &mgmt_handlers[opcode];
5222
5223 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005224 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005225 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005226 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005227 goto done;
5228 }
5229
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005230 if (hdev)
5231 mgmt_init_hdev(sk, hdev);
5232
5233 cp = buf + sizeof(*hdr);
5234
Johan Hedbergbe22b542012-03-01 22:24:41 +02005235 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005236 if (err < 0)
5237 goto done;
5238
Johan Hedberg03811012010-12-08 00:21:06 +02005239 err = msglen;
5240
5241done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005242 if (hdev)
5243 hci_dev_put(hdev);
5244
Johan Hedberg03811012010-12-08 00:21:06 +02005245 kfree(buf);
5246 return err;
5247}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005248
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005249void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005250{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005251 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005252 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005253
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005254 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005255}
5256
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005257void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005258{
Johan Hedberg5f159032012-03-02 03:13:19 +02005259 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005260
Marcel Holtmann1514b892013-10-06 08:25:01 -07005261 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005262 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005263
Johan Hedberg744cf192011-11-08 20:40:14 +02005264 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005265
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005266 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005267}
5268
Andre Guedes6046dc32014-02-26 20:21:51 -03005269/* This function requires the caller holds hdev->lock */
5270static void restart_le_auto_conns(struct hci_dev *hdev)
5271{
5272 struct hci_conn_params *p;
5273
5274 list_for_each_entry(p, &hdev->le_conn_params, list) {
5275 if (p->auto_connect == HCI_AUTO_CONN_ALWAYS)
5276 hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
5277 }
5278}
5279
Johan Hedberg229ab392013-03-15 17:06:53 -05005280static void powered_complete(struct hci_dev *hdev, u8 status)
5281{
5282 struct cmd_lookup match = { NULL, hdev };
5283
5284 BT_DBG("status 0x%02x", status);
5285
5286 hci_dev_lock(hdev);
5287
Andre Guedes6046dc32014-02-26 20:21:51 -03005288 restart_le_auto_conns(hdev);
5289
Johan Hedberg229ab392013-03-15 17:06:53 -05005290 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5291
5292 new_settings(hdev, match.sk);
5293
5294 hci_dev_unlock(hdev);
5295
5296 if (match.sk)
5297 sock_put(match.sk);
5298}
5299
Johan Hedberg70da6242013-03-15 17:06:51 -05005300static int powered_update_hci(struct hci_dev *hdev)
5301{
Johan Hedberg890ea892013-03-15 17:06:52 -05005302 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005303 u8 link_sec;
5304
Johan Hedberg890ea892013-03-15 17:06:52 -05005305 hci_req_init(&req, hdev);
5306
Johan Hedberg70da6242013-03-15 17:06:51 -05005307 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5308 !lmp_host_ssp_capable(hdev)) {
5309 u8 ssp = 1;
5310
Johan Hedberg890ea892013-03-15 17:06:52 -05005311 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005312 }
5313
Johan Hedbergc73eee92013-04-19 18:35:21 +03005314 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5315 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005316 struct hci_cp_write_le_host_supported cp;
5317
5318 cp.le = 1;
5319 cp.simul = lmp_le_br_capable(hdev);
5320
5321 /* Check first if we already have the right
5322 * host state (host features set)
5323 */
5324 if (cp.le != lmp_host_le_capable(hdev) ||
5325 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005326 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5327 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005328 }
5329
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005330 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005331 /* Make sure the controller has a good default for
5332 * advertising data. This also applies to the case
5333 * where BR/EDR was toggled during the AUTO_OFF phase.
5334 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005335 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005336 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005337 update_scan_rsp_data(&req);
5338 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005339
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005340 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5341 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005342 }
5343
Johan Hedberg70da6242013-03-15 17:06:51 -05005344 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5345 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005346 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5347 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005348
5349 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005350 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5351 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005352 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005353 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005354 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005355 }
5356
Johan Hedberg229ab392013-03-15 17:06:53 -05005357 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005358}
5359
Johan Hedberg744cf192011-11-08 20:40:14 +02005360int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005361{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005362 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005363 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5364 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005365 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005366
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005367 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5368 return 0;
5369
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005370 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005371 if (powered_update_hci(hdev) == 0)
5372 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005373
Johan Hedberg229ab392013-03-15 17:06:53 -05005374 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5375 &match);
5376 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005377 }
5378
Johan Hedberg229ab392013-03-15 17:06:53 -05005379 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5380 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5381
5382 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5383 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5384 zero_cod, sizeof(zero_cod), NULL);
5385
5386new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005387 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005388
5389 if (match.sk)
5390 sock_put(match.sk);
5391
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005392 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005393}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005394
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005395void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005396{
5397 struct pending_cmd *cmd;
5398 u8 status;
5399
5400 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5401 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005402 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005403
5404 if (err == -ERFKILL)
5405 status = MGMT_STATUS_RFKILLED;
5406 else
5407 status = MGMT_STATUS_FAILED;
5408
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005409 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005410
5411 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005412}
5413
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005414void mgmt_discoverable_timeout(struct hci_dev *hdev)
5415{
5416 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005417
5418 hci_dev_lock(hdev);
5419
5420 /* When discoverable timeout triggers, then just make sure
5421 * the limited discoverable flag is cleared. Even in the case
5422 * of a timeout triggered from general discoverable, it is
5423 * safe to unconditionally clear the flag.
5424 */
5425 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005426 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005427
5428 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005429 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5430 u8 scan = SCAN_PAGE;
5431 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5432 sizeof(scan), &scan);
5433 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005434 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005435 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005436 hci_req_run(&req, NULL);
5437
5438 hdev->discov_timeout = 0;
5439
Johan Hedberg9a43e252013-10-20 19:00:07 +03005440 new_settings(hdev, NULL);
5441
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005442 hci_dev_unlock(hdev);
5443}
5444
Marcel Holtmann86a75642013-10-15 06:33:54 -07005445void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005446{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005447 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005448
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005449 /* Nothing needed here if there's a pending command since that
5450 * commands request completion callback takes care of everything
5451 * necessary.
5452 */
5453 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005454 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005455
Johan Hedbergbd107992014-02-24 14:52:19 +02005456 /* Powering off may clear the scan mode - don't let that interfere */
5457 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5458 return;
5459
Johan Hedberg9a43e252013-10-20 19:00:07 +03005460 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005461 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005462 } else {
5463 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005464 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005465 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005466
Johan Hedberg9a43e252013-10-20 19:00:07 +03005467 if (changed) {
5468 struct hci_request req;
5469
5470 /* In case this change in discoverable was triggered by
5471 * a disabling of connectable there could be a need to
5472 * update the advertising flags.
5473 */
5474 hci_req_init(&req, hdev);
5475 update_adv_data(&req);
5476 hci_req_run(&req, NULL);
5477
Marcel Holtmann86a75642013-10-15 06:33:54 -07005478 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005479 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005480}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005481
Marcel Holtmanna3309162013-10-15 06:33:55 -07005482void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005483{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005484 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005485
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005486 /* Nothing needed here if there's a pending command since that
5487 * commands request completion callback takes care of everything
5488 * necessary.
5489 */
5490 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005491 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005492
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005493 /* Powering off may clear the scan mode - don't let that interfere */
5494 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5495 return;
5496
Marcel Holtmanna3309162013-10-15 06:33:55 -07005497 if (connectable)
5498 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5499 else
5500 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005501
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005502 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005503 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005504}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005505
Johan Hedberg778b2352014-02-24 14:52:17 +02005506void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5507{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005508 /* Powering off may stop advertising - don't let that interfere */
5509 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5510 return;
5511
Johan Hedberg778b2352014-02-24 14:52:17 +02005512 if (advertising)
5513 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5514 else
5515 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5516}
5517
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005518void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005519{
Johan Hedbergca69b792011-11-11 18:10:00 +02005520 u8 mgmt_err = mgmt_status(status);
5521
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005522 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005523 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005524 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005525
5526 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005527 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005528 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005529}
5530
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005531void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5532 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005533{
Johan Hedberg86742e12011-11-07 23:13:38 +02005534 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005535
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005536 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005537
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005538 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02005539 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005540 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005541 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005542 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005543 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005544
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005545 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005546}
Johan Hedbergf7520542011-01-20 12:34:39 +02005547
Johan Hedbergd7b25452014-05-23 13:19:53 +03005548static u8 mgmt_ltk_type(struct smp_ltk *ltk)
5549{
5550 if (ltk->authenticated)
5551 return MGMT_LTK_AUTHENTICATED;
5552
5553 return MGMT_LTK_UNAUTHENTICATED;
5554}
5555
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005556void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005557{
5558 struct mgmt_ev_new_long_term_key ev;
5559
5560 memset(&ev, 0, sizeof(ev));
5561
Marcel Holtmann5192d302014-02-19 17:11:58 -08005562 /* Devices using resolvable or non-resolvable random addresses
5563 * without providing an indentity resolving key don't require
5564 * to store long term keys. Their addresses will change the
5565 * next time around.
5566 *
5567 * Only when a remote device provides an identity address
5568 * make sure the long term key is stored. If the remote
5569 * identity is known, the long term keys are internally
5570 * mapped to the identity address. So allow static random
5571 * and public addresses here.
5572 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005573 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5574 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5575 ev.store_hint = 0x00;
5576 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005577 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02005578
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005579 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005580 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03005581 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005582 ev.key.enc_size = key->enc_size;
5583 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005584 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005585
Johan Hedberg2ceba532014-06-16 19:25:16 +03005586 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005587 ev.key.master = 1;
5588
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005589 memcpy(ev.key.val, key->val, sizeof(key->val));
5590
Marcel Holtmann083368f2013-10-15 14:26:29 -07005591 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005592}
5593
Johan Hedberg95fbac82014-02-19 15:18:31 +02005594void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5595{
5596 struct mgmt_ev_new_irk ev;
5597
5598 memset(&ev, 0, sizeof(ev));
5599
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005600 /* For identity resolving keys from devices that are already
5601 * using a public address or static random address, do not
5602 * ask for storing this key. The identity resolving key really
5603 * is only mandatory for devices using resovlable random
5604 * addresses.
5605 *
5606 * Storing all identity resolving keys has the downside that
5607 * they will be also loaded on next boot of they system. More
5608 * identity resolving keys, means more time during scanning is
5609 * needed to actually resolve these addresses.
5610 */
5611 if (bacmp(&irk->rpa, BDADDR_ANY))
5612 ev.store_hint = 0x01;
5613 else
5614 ev.store_hint = 0x00;
5615
Johan Hedberg95fbac82014-02-19 15:18:31 +02005616 bacpy(&ev.rpa, &irk->rpa);
5617 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5618 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5619 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5620
5621 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5622}
5623
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005624void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
5625 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005626{
5627 struct mgmt_ev_new_csrk ev;
5628
5629 memset(&ev, 0, sizeof(ev));
5630
5631 /* Devices using resolvable or non-resolvable random addresses
5632 * without providing an indentity resolving key don't require
5633 * to store signature resolving keys. Their addresses will change
5634 * the next time around.
5635 *
5636 * Only when a remote device provides an identity address
5637 * make sure the signature resolving key is stored. So allow
5638 * static random and public addresses here.
5639 */
5640 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5641 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
5642 ev.store_hint = 0x00;
5643 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005644 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005645
5646 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
5647 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
5648 ev.key.master = csrk->master;
5649 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
5650
5651 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
5652}
5653
Marcel Holtmann94933992013-10-15 10:26:39 -07005654static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5655 u8 data_len)
5656{
5657 eir[eir_len++] = sizeof(type) + data_len;
5658 eir[eir_len++] = type;
5659 memcpy(&eir[eir_len], data, data_len);
5660 eir_len += data_len;
5661
5662 return eir_len;
5663}
5664
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005665void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5666 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5667 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005668{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005669 char buf[512];
5670 struct mgmt_ev_device_connected *ev = (void *) buf;
5671 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005672
Johan Hedbergb644ba32012-01-17 21:48:47 +02005673 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005674 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005675
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005676 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005677
Johan Hedbergb644ba32012-01-17 21:48:47 +02005678 if (name_len > 0)
5679 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005680 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005681
5682 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005683 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005684 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005685
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005686 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005687
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005688 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
5689 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02005690}
5691
Johan Hedberg8962ee72011-01-20 12:40:27 +02005692static void disconnect_rsp(struct pending_cmd *cmd, void *data)
5693{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01005694 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005695 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02005696 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005697
Johan Hedberg88c3df12012-02-09 14:27:38 +02005698 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5699 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005700
Johan Hedbergaee9b212012-02-18 15:07:59 +02005701 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005702 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005703
5704 *sk = cmd->sk;
5705 sock_hold(*sk);
5706
Johan Hedberga664b5b2011-02-19 12:06:02 -03005707 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005708}
5709
Johan Hedberg124f6e32012-02-09 13:50:12 +02005710static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02005711{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005712 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02005713 struct mgmt_cp_unpair_device *cp = cmd->param;
5714 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005715
5716 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02005717 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5718 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005719
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005720 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
5721
Johan Hedbergaee9b212012-02-18 15:07:59 +02005722 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02005723
5724 mgmt_pending_remove(cmd);
5725}
5726
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005727void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005728 u8 link_type, u8 addr_type, u8 reason,
5729 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02005730{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005731 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02005732 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005733 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005734
Johan Hedberg8b064a32014-02-24 14:52:22 +02005735 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5736 if (power_off) {
5737 struct mgmt_mode *cp = power_off->param;
5738
5739 /* The connection is still in hci_conn_hash so test for 1
5740 * instead of 0 to know if this is the last one.
5741 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005742 if (!cp->val && hci_conn_count(hdev) == 1) {
5743 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02005744 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005745 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02005746 }
5747
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005748 if (!mgmt_connected)
5749 return;
5750
Andre Guedes57eb7762013-10-30 19:01:41 -03005751 if (link_type != ACL_LINK && link_type != LE_LINK)
5752 return;
5753
Johan Hedberg744cf192011-11-08 20:40:14 +02005754 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02005755
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005756 bacpy(&ev.addr.bdaddr, bdaddr);
5757 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5758 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02005759
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005760 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005761
5762 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01005763 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005764
Johan Hedberg124f6e32012-02-09 13:50:12 +02005765 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005766 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005767}
5768
Marcel Holtmann78929242013-10-06 23:55:47 -07005769void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
5770 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02005771{
Andre Guedes3655bba2013-10-30 19:01:40 -03005772 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
5773 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02005774 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005775 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005776
Jefferson Delfes36a75f12012-09-18 13:36:54 -04005777 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
5778 hdev);
5779
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005780 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005781 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07005782 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005783
Andre Guedes3655bba2013-10-30 19:01:40 -03005784 cp = cmd->param;
5785
5786 if (bacmp(bdaddr, &cp->addr.bdaddr))
5787 return;
5788
5789 if (cp->addr.type != bdaddr_type)
5790 return;
5791
Johan Hedberg88c3df12012-02-09 14:27:38 +02005792 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03005793 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02005794
Marcel Holtmann78929242013-10-06 23:55:47 -07005795 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
5796 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005797
Johan Hedberga664b5b2011-02-19 12:06:02 -03005798 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02005799}
Johan Hedberg17d5c042011-01-22 06:09:08 +02005800
Marcel Holtmann445608d2013-10-06 23:55:48 -07005801void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5802 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02005803{
5804 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02005805 struct pending_cmd *power_off;
5806
5807 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5808 if (power_off) {
5809 struct mgmt_mode *cp = power_off->param;
5810
5811 /* The connection is still in hci_conn_hash so test for 1
5812 * instead of 0 to know if this is the last one.
5813 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005814 if (!cp->val && hci_conn_count(hdev) == 1) {
5815 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02005816 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005817 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02005818 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02005819
Johan Hedberg4c659c32011-11-07 23:13:39 +02005820 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005821 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005822 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005823
Marcel Holtmann445608d2013-10-06 23:55:48 -07005824 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005825}
Johan Hedberg980e1a52011-01-22 06:10:07 +02005826
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005827void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005828{
5829 struct mgmt_ev_pin_code_request ev;
5830
Johan Hedbergd8457692012-02-17 14:24:57 +02005831 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005832 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02005833 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005834
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005835 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005836}
5837
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005838void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5839 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005840{
5841 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005842 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005843
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005844 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005845 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005846 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005847
Johan Hedbergd8457692012-02-17 14:24:57 +02005848 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005849 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005850
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005851 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
5852 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005853
Johan Hedberga664b5b2011-02-19 12:06:02 -03005854 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005855}
5856
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005857void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5858 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005859{
5860 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005861 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005862
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005863 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005864 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005865 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005866
Johan Hedbergd8457692012-02-17 14:24:57 +02005867 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005868 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005869
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005870 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
5871 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005872
Johan Hedberga664b5b2011-02-19 12:06:02 -03005873 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005874}
Johan Hedberga5c29682011-02-19 12:05:57 -03005875
Johan Hedberg744cf192011-11-08 20:40:14 +02005876int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02005877 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005878 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03005879{
5880 struct mgmt_ev_user_confirm_request ev;
5881
Johan Hedberg744cf192011-11-08 20:40:14 +02005882 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03005883
Johan Hedberg272d90d2012-02-09 15:26:12 +02005884 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005885 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07005886 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02005887 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03005888
Johan Hedberg744cf192011-11-08 20:40:14 +02005889 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005890 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03005891}
5892
Johan Hedberg272d90d2012-02-09 15:26:12 +02005893int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005894 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08005895{
5896 struct mgmt_ev_user_passkey_request ev;
5897
5898 BT_DBG("%s", hdev->name);
5899
Johan Hedberg272d90d2012-02-09 15:26:12 +02005900 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005901 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08005902
5903 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005904 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08005905}
5906
Brian Gix0df4c182011-11-16 13:53:13 -08005907static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005908 u8 link_type, u8 addr_type, u8 status,
5909 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03005910{
5911 struct pending_cmd *cmd;
5912 struct mgmt_rp_user_confirm_reply rp;
5913 int err;
5914
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005915 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03005916 if (!cmd)
5917 return -ENOENT;
5918
Johan Hedberg272d90d2012-02-09 15:26:12 +02005919 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005920 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b212012-02-18 15:07:59 +02005921 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005922 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03005923
Johan Hedberga664b5b2011-02-19 12:06:02 -03005924 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03005925
5926 return err;
5927}
5928
Johan Hedberg744cf192011-11-08 20:40:14 +02005929int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005930 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005931{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005932 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005933 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005934}
5935
Johan Hedberg272d90d2012-02-09 15:26:12 +02005936int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005937 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005938{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005939 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005940 status,
5941 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005942}
Johan Hedberg2a611692011-02-19 12:06:00 -03005943
Brian Gix604086b2011-11-23 08:28:33 -08005944int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005945 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005946{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005947 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005948 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005949}
5950
Johan Hedberg272d90d2012-02-09 15:26:12 +02005951int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005952 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005953{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005954 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005955 status,
5956 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005957}
5958
Johan Hedberg92a25252012-09-06 18:39:26 +03005959int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
5960 u8 link_type, u8 addr_type, u32 passkey,
5961 u8 entered)
5962{
5963 struct mgmt_ev_passkey_notify ev;
5964
5965 BT_DBG("%s", hdev->name);
5966
5967 bacpy(&ev.addr.bdaddr, bdaddr);
5968 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5969 ev.passkey = __cpu_to_le32(passkey);
5970 ev.entered = entered;
5971
5972 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
5973}
5974
Marcel Holtmanne5460992013-10-15 14:26:23 -07005975void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5976 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03005977{
5978 struct mgmt_ev_auth_failed ev;
5979
Johan Hedbergbab73cb2012-02-09 16:07:29 +02005980 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005981 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005982 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03005983
Marcel Holtmanne5460992013-10-15 14:26:23 -07005984 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03005985}
Johan Hedbergb312b1612011-03-16 14:29:37 +02005986
Marcel Holtmann464996a2013-10-15 14:26:24 -07005987void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005988{
5989 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07005990 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005991
5992 if (status) {
5993 u8 mgmt_err = mgmt_status(status);
5994 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005995 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07005996 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005997 }
5998
Marcel Holtmann464996a2013-10-15 14:26:24 -07005999 if (test_bit(HCI_AUTH, &hdev->flags))
6000 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6001 &hdev->dev_flags);
6002 else
6003 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6004 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006005
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006006 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006007 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006008
Johan Hedberg47990ea2012-02-22 11:58:37 +02006009 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006010 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006011
6012 if (match.sk)
6013 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006014}
6015
Johan Hedberg890ea892013-03-15 17:06:52 -05006016static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006017{
Johan Hedberg890ea892013-03-15 17:06:52 -05006018 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006019 struct hci_cp_write_eir cp;
6020
Johan Hedberg976eb202012-10-24 21:12:01 +03006021 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006022 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006023
Johan Hedbergc80da272012-02-22 15:38:48 +02006024 memset(hdev->eir, 0, sizeof(hdev->eir));
6025
Johan Hedbergcacaf522012-02-21 00:52:42 +02006026 memset(&cp, 0, sizeof(cp));
6027
Johan Hedberg890ea892013-03-15 17:06:52 -05006028 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006029}
6030
Marcel Holtmann3e248562013-10-15 14:26:25 -07006031void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006032{
6033 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006034 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006035 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006036
6037 if (status) {
6038 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006039
6040 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006041 &hdev->dev_flags)) {
6042 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006043 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006044 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006045
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006046 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6047 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006048 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006049 }
6050
6051 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006052 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006053 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006054 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6055 if (!changed)
6056 changed = test_and_clear_bit(HCI_HS_ENABLED,
6057 &hdev->dev_flags);
6058 else
6059 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006060 }
6061
6062 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6063
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006064 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006065 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006066
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006067 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006068 sock_put(match.sk);
6069
Johan Hedberg890ea892013-03-15 17:06:52 -05006070 hci_req_init(&req, hdev);
6071
Johan Hedberg37699722014-06-24 14:00:27 +03006072 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6073 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6074 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6075 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006076 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006077 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006078 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006079 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006080
6081 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006082}
6083
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006084void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6085{
6086 struct cmd_lookup match = { NULL, hdev };
6087 bool changed = false;
6088
6089 if (status) {
6090 u8 mgmt_err = mgmt_status(status);
6091
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006092 if (enable) {
6093 if (test_and_clear_bit(HCI_SC_ENABLED,
6094 &hdev->dev_flags))
6095 new_settings(hdev, NULL);
6096 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6097 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006098
6099 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6100 cmd_status_rsp, &mgmt_err);
6101 return;
6102 }
6103
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006104 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006105 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006106 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006107 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006108 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6109 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006110
6111 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6112 settings_rsp, &match);
6113
6114 if (changed)
6115 new_settings(hdev, match.sk);
6116
6117 if (match.sk)
6118 sock_put(match.sk);
6119}
6120
Johan Hedberg92da6092013-03-15 17:06:55 -05006121static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006122{
6123 struct cmd_lookup *match = data;
6124
Johan Hedberg90e70452012-02-23 23:09:40 +02006125 if (match->sk == NULL) {
6126 match->sk = cmd->sk;
6127 sock_hold(match->sk);
6128 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006129}
6130
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006131void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6132 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006133{
Johan Hedberg90e70452012-02-23 23:09:40 +02006134 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006135
Johan Hedberg92da6092013-03-15 17:06:55 -05006136 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6137 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6138 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006139
6140 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006141 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6142 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006143
6144 if (match.sk)
6145 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006146}
6147
Marcel Holtmann7667da32013-10-15 14:26:27 -07006148void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006149{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006150 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006151 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006152
Johan Hedberg13928972013-03-15 17:07:00 -05006153 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006154 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006155
6156 memset(&ev, 0, sizeof(ev));
6157 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006158 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006159
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006160 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006161 if (!cmd) {
6162 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006163
Johan Hedberg13928972013-03-15 17:07:00 -05006164 /* If this is a HCI command related to powering on the
6165 * HCI dev don't send any mgmt signals.
6166 */
6167 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006168 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006169 }
6170
Marcel Holtmann7667da32013-10-15 14:26:27 -07006171 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6172 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006173}
Szymon Jancc35938b2011-03-22 13:12:21 +01006174
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006175void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6176 u8 *randomizer192, u8 *hash256,
6177 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006178{
6179 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006180
Johan Hedberg744cf192011-11-08 20:40:14 +02006181 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006182
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006183 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006184 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006185 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006186
6187 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006188 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6189 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006190 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006191 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6192 hash256 && randomizer256) {
6193 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006194
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006195 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6196 memcpy(rp.randomizer192, randomizer192,
6197 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006198
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006199 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6200 memcpy(rp.randomizer256, randomizer256,
6201 sizeof(rp.randomizer256));
6202
6203 cmd_complete(cmd->sk, hdev->id,
6204 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6205 &rp, sizeof(rp));
6206 } else {
6207 struct mgmt_rp_read_local_oob_data rp;
6208
6209 memcpy(rp.hash, hash192, sizeof(rp.hash));
6210 memcpy(rp.randomizer, randomizer192,
6211 sizeof(rp.randomizer));
6212
6213 cmd_complete(cmd->sk, hdev->id,
6214 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6215 &rp, sizeof(rp));
6216 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006217 }
6218
6219 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006220}
Johan Hedberge17acd42011-03-30 23:57:16 +03006221
Marcel Holtmann901801b2013-10-06 23:55:51 -07006222void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Johan Hedberg73cf71d2014-03-25 12:06:19 +02006223 u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name,
6224 u8 ssp, u8 *eir, u16 eir_len, u8 *scan_rsp,
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006225 u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006226{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006227 char buf[512];
6228 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006229 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006230 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006231
Andre Guedes12602d02013-04-30 15:29:40 -03006232 if (!hci_discovery_active(hdev))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006233 return;
Andre Guedes12602d02013-04-30 15:29:40 -03006234
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006235 /* Make sure that the buffer is big enough. The 5 extra bytes
6236 * are for the potential CoD field.
6237 */
6238 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006239 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006240
Johan Hedberg1dc06092012-01-15 21:01:23 +02006241 memset(buf, 0, sizeof(buf));
6242
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006243 irk = hci_get_irk(hdev, bdaddr, addr_type);
6244 if (irk) {
6245 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
6246 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
6247 } else {
6248 bacpy(&ev->addr.bdaddr, bdaddr);
6249 ev->addr.type = link_to_bdaddr(link_type, addr_type);
6250 }
6251
Johan Hedberge319d2e2012-01-15 19:51:59 +02006252 ev->rssi = rssi;
Johan Hedberg9a395a82012-02-23 00:00:32 +02006253 if (cfm_name)
Joe Perchesdcf4adb2014-03-12 10:52:35 -07006254 ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02006255 if (!ssp)
Joe Perchesdcf4adb2014-03-12 10:52:35 -07006256 ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING);
Johan Hedberge17acd42011-03-30 23:57:16 +03006257
Johan Hedberg1dc06092012-01-15 21:01:23 +02006258 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006259 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006260
Johan Hedberg1dc06092012-01-15 21:01:23 +02006261 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6262 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006263 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006264
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006265 if (scan_rsp_len > 0)
6266 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6267
6268 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6269 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006270
Marcel Holtmann901801b2013-10-06 23:55:51 -07006271 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006272}
Johan Hedberga88a9652011-03-30 13:18:12 +03006273
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006274void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6275 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006276{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006277 struct mgmt_ev_device_found *ev;
6278 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6279 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006280
Johan Hedbergb644ba32012-01-17 21:48:47 +02006281 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006282
Johan Hedbergb644ba32012-01-17 21:48:47 +02006283 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006284
Johan Hedbergb644ba32012-01-17 21:48:47 +02006285 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006286 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006287 ev->rssi = rssi;
6288
6289 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006290 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006291
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006292 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006293
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006294 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006295}
Johan Hedberg314b2382011-04-27 10:29:57 -04006296
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006297void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006298{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006299 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006300 struct pending_cmd *cmd;
6301
Andre Guedes343fb142011-11-22 17:14:19 -03006302 BT_DBG("%s discovering %u", hdev->name, discovering);
6303
Johan Hedberg164a6e72011-11-01 17:06:44 +02006304 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006305 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006306 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006307 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006308
6309 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006310 u8 type = hdev->discovery.type;
6311
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006312 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6313 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006314 mgmt_pending_remove(cmd);
6315 }
6316
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006317 memset(&ev, 0, sizeof(ev));
6318 ev.type = hdev->discovery.type;
6319 ev.discovering = discovering;
6320
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006321 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006322}
Antti Julku5e762442011-08-25 16:48:02 +03006323
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006324int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03006325{
6326 struct pending_cmd *cmd;
6327 struct mgmt_ev_device_blocked ev;
6328
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006329 cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03006330
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006331 bacpy(&ev.addr.bdaddr, bdaddr);
6332 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03006333
Johan Hedberg744cf192011-11-08 20:40:14 +02006334 return mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006335 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03006336}
6337
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006338int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03006339{
6340 struct pending_cmd *cmd;
6341 struct mgmt_ev_device_unblocked ev;
6342
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006343 cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03006344
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006345 bacpy(&ev.addr.bdaddr, bdaddr);
6346 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03006347
Johan Hedberg744cf192011-11-08 20:40:14 +02006348 return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006349 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03006350}
Marcel Holtmann5976e602013-10-06 04:08:14 -07006351
6352static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6353{
6354 BT_DBG("%s status %u", hdev->name, status);
6355
6356 /* Clear the advertising mgmt setting if we failed to re-enable it */
6357 if (status) {
6358 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006359 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006360 }
6361}
6362
6363void mgmt_reenable_advertising(struct hci_dev *hdev)
6364{
6365 struct hci_request req;
6366
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006367 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006368 return;
6369
6370 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6371 return;
6372
6373 hci_req_init(&req, hdev);
6374 enable_advertising(&req);
6375
6376 /* If this fails we have no option but to let user space know
6377 * that we've disabled advertising.
6378 */
6379 if (hci_req_run(&req, adv_enable_complete) < 0) {
6380 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006381 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006382 }
6383}