blob: c6e9b551242ba12eff76e86254bec121fe90605c [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 Hedberg84bde9d6c2012-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 Hedberg84bde9d6c2012-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 Hedberg4ae14302013-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
Marcel Holtmann7c264b12014-06-30 12:34:40 +02002950 /* When pairing a new device, it is expected to remember
2951 * this device for future connections. Adding the connection
2952 * parameter information ahead of time allows tracking
2953 * of the slave preferred values and will speed up any
2954 * further connection establishment.
2955 *
2956 * If connection parameters already exist, then they
2957 * will be kept and this function does nothing.
2958 */
2959 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
2960
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002961 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03002962 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002963 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002964
Ville Tervo30e76272011-02-22 16:10:53 -03002965 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002966 int status;
2967
2968 if (PTR_ERR(conn) == -EBUSY)
2969 status = MGMT_STATUS_BUSY;
2970 else
2971 status = MGMT_STATUS_CONNECT_FAILED;
2972
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002973 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002974 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002975 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002976 goto unlock;
2977 }
2978
2979 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02002980 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002981 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002982 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002983 goto unlock;
2984 }
2985
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002986 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002987 if (!cmd) {
2988 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02002989 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002990 goto unlock;
2991 }
2992
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002993 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002994 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002995 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002996 conn->security_cfm_cb = pairing_complete_cb;
2997 conn->disconn_cfm_cb = pairing_complete_cb;
2998 } else {
2999 conn->connect_cfm_cb = le_pairing_complete_cb;
3000 conn->security_cfm_cb = le_pairing_complete_cb;
3001 conn->disconn_cfm_cb = le_pairing_complete_cb;
3002 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003003
Johan Hedberge9a416b2011-02-19 12:05:56 -03003004 conn->io_capability = cp->io_cap;
3005 cmd->user_data = conn;
3006
3007 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003008 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003009 pairing_complete(cmd, 0);
3010
3011 err = 0;
3012
3013unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003014 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003015 return err;
3016}
3017
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003018static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3019 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003020{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003021 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003022 struct pending_cmd *cmd;
3023 struct hci_conn *conn;
3024 int err;
3025
3026 BT_DBG("");
3027
Johan Hedberg28424702012-02-02 04:02:29 +02003028 hci_dev_lock(hdev);
3029
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003030 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003031 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003032 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003033 goto unlock;
3034 }
3035
Johan Hedberg28424702012-02-02 04:02:29 +02003036 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3037 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003038 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003039 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003040 goto unlock;
3041 }
3042
3043 conn = cmd->user_data;
3044
3045 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003046 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003047 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003048 goto unlock;
3049 }
3050
3051 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3052
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003053 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003054 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003055unlock:
3056 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003057 return err;
3058}
3059
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003060static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003061 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003062 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003063{
Johan Hedberga5c29682011-02-19 12:05:57 -03003064 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003065 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003066 int err;
3067
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003068 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003069
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003070 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003071 err = cmd_complete(sk, hdev->id, mgmt_op,
3072 MGMT_STATUS_NOT_POWERED, addr,
3073 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003074 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003075 }
3076
Johan Hedberg1707c602013-03-15 17:07:15 -05003077 if (addr->type == BDADDR_BREDR)
3078 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003079 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003080 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003081
Johan Hedberg272d90d2012-02-09 15:26:12 +02003082 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003083 err = cmd_complete(sk, hdev->id, mgmt_op,
3084 MGMT_STATUS_NOT_CONNECTED, addr,
3085 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003086 goto done;
3087 }
3088
Johan Hedberg1707c602013-03-15 17:07:15 -05003089 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003090 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003091 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003092 err = cmd_complete(sk, hdev->id, mgmt_op,
3093 MGMT_STATUS_SUCCESS, addr,
3094 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003095 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003096 err = cmd_complete(sk, hdev->id, mgmt_op,
3097 MGMT_STATUS_FAILED, addr,
3098 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003099
Brian Gix47c15e22011-11-16 13:53:14 -08003100 goto done;
3101 }
3102
Johan Hedberg1707c602013-03-15 17:07:15 -05003103 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003104 if (!cmd) {
3105 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003106 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003107 }
3108
Brian Gix0df4c182011-11-16 13:53:13 -08003109 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003110 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3111 struct hci_cp_user_passkey_reply cp;
3112
Johan Hedberg1707c602013-03-15 17:07:15 -05003113 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003114 cp.passkey = passkey;
3115 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3116 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003117 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3118 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003119
Johan Hedberga664b5b2011-02-19 12:06:02 -03003120 if (err < 0)
3121 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003122
Brian Gix0df4c182011-11-16 13:53:13 -08003123done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003124 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003125 return err;
3126}
3127
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303128static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3129 void *data, u16 len)
3130{
3131 struct mgmt_cp_pin_code_neg_reply *cp = data;
3132
3133 BT_DBG("");
3134
Johan Hedberg1707c602013-03-15 17:07:15 -05003135 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303136 MGMT_OP_PIN_CODE_NEG_REPLY,
3137 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3138}
3139
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003140static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3141 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003142{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003143 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003144
3145 BT_DBG("");
3146
3147 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003148 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003149 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003150
Johan Hedberg1707c602013-03-15 17:07:15 -05003151 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003152 MGMT_OP_USER_CONFIRM_REPLY,
3153 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003154}
3155
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003156static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003157 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003158{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003159 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003160
3161 BT_DBG("");
3162
Johan Hedberg1707c602013-03-15 17:07:15 -05003163 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003164 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3165 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003166}
3167
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003168static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3169 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003170{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003171 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003172
3173 BT_DBG("");
3174
Johan Hedberg1707c602013-03-15 17:07:15 -05003175 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003176 MGMT_OP_USER_PASSKEY_REPLY,
3177 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003178}
3179
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003180static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003181 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003182{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003183 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003184
3185 BT_DBG("");
3186
Johan Hedberg1707c602013-03-15 17:07:15 -05003187 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003188 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3189 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003190}
3191
Johan Hedberg13928972013-03-15 17:07:00 -05003192static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003193{
Johan Hedberg13928972013-03-15 17:07:00 -05003194 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003195 struct hci_cp_write_local_name cp;
3196
Johan Hedberg13928972013-03-15 17:07:00 -05003197 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003198
Johan Hedberg890ea892013-03-15 17:06:52 -05003199 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003200}
3201
Johan Hedberg13928972013-03-15 17:07:00 -05003202static void set_name_complete(struct hci_dev *hdev, u8 status)
3203{
3204 struct mgmt_cp_set_local_name *cp;
3205 struct pending_cmd *cmd;
3206
3207 BT_DBG("status 0x%02x", status);
3208
3209 hci_dev_lock(hdev);
3210
3211 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3212 if (!cmd)
3213 goto unlock;
3214
3215 cp = cmd->param;
3216
3217 if (status)
3218 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3219 mgmt_status(status));
3220 else
3221 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3222 cp, sizeof(*cp));
3223
3224 mgmt_pending_remove(cmd);
3225
3226unlock:
3227 hci_dev_unlock(hdev);
3228}
3229
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003230static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003231 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003232{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003233 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003234 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003235 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003236 int err;
3237
3238 BT_DBG("");
3239
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003240 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003241
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003242 /* If the old values are the same as the new ones just return a
3243 * direct command complete event.
3244 */
3245 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3246 !memcmp(hdev->short_name, cp->short_name,
3247 sizeof(hdev->short_name))) {
3248 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3249 data, len);
3250 goto failed;
3251 }
3252
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003253 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003254
Johan Hedbergb5235a62012-02-21 14:32:24 +02003255 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003256 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003257
3258 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003259 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003260 if (err < 0)
3261 goto failed;
3262
3263 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003264 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003265
Johan Hedbergb5235a62012-02-21 14:32:24 +02003266 goto failed;
3267 }
3268
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003269 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003270 if (!cmd) {
3271 err = -ENOMEM;
3272 goto failed;
3273 }
3274
Johan Hedberg13928972013-03-15 17:07:00 -05003275 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3276
Johan Hedberg890ea892013-03-15 17:06:52 -05003277 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003278
3279 if (lmp_bredr_capable(hdev)) {
3280 update_name(&req);
3281 update_eir(&req);
3282 }
3283
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003284 /* The name is stored in the scan response data and so
3285 * no need to udpate the advertising data here.
3286 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003287 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003288 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003289
Johan Hedberg13928972013-03-15 17:07:00 -05003290 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003291 if (err < 0)
3292 mgmt_pending_remove(cmd);
3293
3294failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003295 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003296 return err;
3297}
3298
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003299static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003300 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003301{
Szymon Jancc35938b2011-03-22 13:12:21 +01003302 struct pending_cmd *cmd;
3303 int err;
3304
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003305 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003306
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003307 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003308
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003309 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003310 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003311 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003312 goto unlock;
3313 }
3314
Andre Guedes9a1a1992012-07-24 15:03:48 -03003315 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003316 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003317 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003318 goto unlock;
3319 }
3320
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003321 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003322 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003323 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003324 goto unlock;
3325 }
3326
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003327 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003328 if (!cmd) {
3329 err = -ENOMEM;
3330 goto unlock;
3331 }
3332
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003333 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3334 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3335 0, NULL);
3336 else
3337 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3338
Szymon Jancc35938b2011-03-22 13:12:21 +01003339 if (err < 0)
3340 mgmt_pending_remove(cmd);
3341
3342unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003343 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003344 return err;
3345}
3346
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003347static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003348 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003349{
Szymon Janc2763eda2011-03-22 13:12:22 +01003350 int err;
3351
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003352 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003353
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003354 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003355
Marcel Holtmannec109112014-01-10 02:07:30 -08003356 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3357 struct mgmt_cp_add_remote_oob_data *cp = data;
3358 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003359
Marcel Holtmannec109112014-01-10 02:07:30 -08003360 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3361 cp->hash, cp->randomizer);
3362 if (err < 0)
3363 status = MGMT_STATUS_FAILED;
3364 else
3365 status = MGMT_STATUS_SUCCESS;
3366
3367 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3368 status, &cp->addr, sizeof(cp->addr));
3369 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3370 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3371 u8 status;
3372
3373 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3374 cp->hash192,
3375 cp->randomizer192,
3376 cp->hash256,
3377 cp->randomizer256);
3378 if (err < 0)
3379 status = MGMT_STATUS_FAILED;
3380 else
3381 status = MGMT_STATUS_SUCCESS;
3382
3383 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3384 status, &cp->addr, sizeof(cp->addr));
3385 } else {
3386 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3387 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3388 MGMT_STATUS_INVALID_PARAMS);
3389 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003390
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003391 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003392 return err;
3393}
3394
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003395static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003396 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003397{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003398 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003399 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003400 int err;
3401
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003402 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003403
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003404 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003405
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003406 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003407 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003408 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003409 else
Szymon Janca6785be2012-12-13 15:11:21 +01003410 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003411
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003412 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003413 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003414
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003415 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003416 return err;
3417}
3418
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003419static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3420{
3421 struct pending_cmd *cmd;
3422 u8 type;
3423 int err;
3424
3425 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3426
3427 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3428 if (!cmd)
3429 return -ENOENT;
3430
3431 type = hdev->discovery.type;
3432
3433 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3434 &type, sizeof(type));
3435 mgmt_pending_remove(cmd);
3436
3437 return err;
3438}
3439
Andre Guedes7c307722013-04-30 15:29:28 -03003440static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3441{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003442 unsigned long timeout = 0;
3443
Andre Guedes7c307722013-04-30 15:29:28 -03003444 BT_DBG("status %d", status);
3445
3446 if (status) {
3447 hci_dev_lock(hdev);
3448 mgmt_start_discovery_failed(hdev, status);
3449 hci_dev_unlock(hdev);
3450 return;
3451 }
3452
3453 hci_dev_lock(hdev);
3454 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3455 hci_dev_unlock(hdev);
3456
3457 switch (hdev->discovery.type) {
3458 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003459 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003460 break;
3461
3462 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003463 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003464 break;
3465
3466 case DISCOV_TYPE_BREDR:
3467 break;
3468
3469 default:
3470 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3471 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003472
3473 if (!timeout)
3474 return;
3475
3476 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003477}
3478
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003479static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003480 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003481{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003482 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003483 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003484 struct hci_cp_le_set_scan_param param_cp;
3485 struct hci_cp_le_set_scan_enable enable_cp;
3486 struct hci_cp_inquiry inq_cp;
3487 struct hci_request req;
3488 /* General inquiry access code (GIAC) */
3489 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003490 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003491 int err;
3492
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003493 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003494
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003495 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003496
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003497 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003498 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003499 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003500 goto failed;
3501 }
3502
Andre Guedes642be6c2012-03-21 00:03:37 -03003503 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3504 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3505 MGMT_STATUS_BUSY);
3506 goto failed;
3507 }
3508
Johan Hedbergff9ef572012-01-04 14:23:45 +02003509 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003510 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003511 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003512 goto failed;
3513 }
3514
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003515 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003516 if (!cmd) {
3517 err = -ENOMEM;
3518 goto failed;
3519 }
3520
Andre Guedes4aab14e2012-02-17 20:39:36 -03003521 hdev->discovery.type = cp->type;
3522
Andre Guedes7c307722013-04-30 15:29:28 -03003523 hci_req_init(&req, hdev);
3524
Andre Guedes4aab14e2012-02-17 20:39:36 -03003525 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003526 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003527 status = mgmt_bredr_support(hdev);
3528 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003529 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003530 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003531 mgmt_pending_remove(cmd);
3532 goto failed;
3533 }
3534
Andre Guedes7c307722013-04-30 15:29:28 -03003535 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3536 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3537 MGMT_STATUS_BUSY);
3538 mgmt_pending_remove(cmd);
3539 goto failed;
3540 }
3541
3542 hci_inquiry_cache_flush(hdev);
3543
3544 memset(&inq_cp, 0, sizeof(inq_cp));
3545 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003546 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003547 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003548 break;
3549
3550 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003551 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003552 status = mgmt_le_support(hdev);
3553 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003554 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003555 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003556 mgmt_pending_remove(cmd);
3557 goto failed;
3558 }
3559
Andre Guedes7c307722013-04-30 15:29:28 -03003560 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003561 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003562 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3563 MGMT_STATUS_NOT_SUPPORTED);
3564 mgmt_pending_remove(cmd);
3565 goto failed;
3566 }
3567
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003568 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003569 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3570 MGMT_STATUS_REJECTED);
3571 mgmt_pending_remove(cmd);
3572 goto failed;
3573 }
3574
Andre Guedesc54c3862014-02-26 20:21:50 -03003575 /* If controller is scanning, it means the background scanning
3576 * is running. Thus, we should temporarily stop it in order to
3577 * set the discovery scanning parameters.
3578 */
3579 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3580 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003581
3582 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003583
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003584 /* All active scans will be done with either a resolvable
3585 * private address (when privacy feature has been enabled)
3586 * or unresolvable private address.
3587 */
3588 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003589 if (err < 0) {
3590 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3591 MGMT_STATUS_FAILED);
3592 mgmt_pending_remove(cmd);
3593 goto failed;
3594 }
3595
Andre Guedes7c307722013-04-30 15:29:28 -03003596 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003597 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3598 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003599 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003600 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3601 &param_cp);
3602
3603 memset(&enable_cp, 0, sizeof(enable_cp));
3604 enable_cp.enable = LE_SCAN_ENABLE;
3605 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3606 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3607 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003608 break;
3609
Andre Guedesf39799f2012-02-17 20:39:35 -03003610 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003611 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3612 MGMT_STATUS_INVALID_PARAMS);
3613 mgmt_pending_remove(cmd);
3614 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003615 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003616
Andre Guedes7c307722013-04-30 15:29:28 -03003617 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003618 if (err < 0)
3619 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003620 else
3621 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003622
3623failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003624 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003625 return err;
3626}
3627
Andre Guedes1183fdc2013-04-30 15:29:35 -03003628static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3629{
3630 struct pending_cmd *cmd;
3631 int err;
3632
3633 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3634 if (!cmd)
3635 return -ENOENT;
3636
3637 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3638 &hdev->discovery.type, sizeof(hdev->discovery.type));
3639 mgmt_pending_remove(cmd);
3640
3641 return err;
3642}
3643
Andre Guedes0e05bba2013-04-30 15:29:33 -03003644static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3645{
3646 BT_DBG("status %d", status);
3647
3648 hci_dev_lock(hdev);
3649
3650 if (status) {
3651 mgmt_stop_discovery_failed(hdev, status);
3652 goto unlock;
3653 }
3654
3655 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3656
3657unlock:
3658 hci_dev_unlock(hdev);
3659}
3660
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003661static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003662 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003663{
Johan Hedbergd9306502012-02-20 23:25:18 +02003664 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003665 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003666 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003667 int err;
3668
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003669 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003670
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003671 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003672
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003673 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003674 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003675 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3676 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003677 goto unlock;
3678 }
3679
3680 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003681 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003682 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3683 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003684 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003685 }
3686
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003687 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003688 if (!cmd) {
3689 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003690 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003691 }
3692
Andre Guedes0e05bba2013-04-30 15:29:33 -03003693 hci_req_init(&req, hdev);
3694
Johan Hedberg21a60d32014-06-10 14:05:58 +03003695 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003696
Johan Hedberg21a60d32014-06-10 14:05:58 +03003697 err = hci_req_run(&req, stop_discovery_complete);
3698 if (!err) {
3699 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003700 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003701 }
3702
Johan Hedberg21a60d32014-06-10 14:05:58 +03003703 mgmt_pending_remove(cmd);
3704
3705 /* If no HCI commands were sent we're done */
3706 if (err == -ENODATA) {
3707 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3708 &mgmt_cp->type, sizeof(mgmt_cp->type));
3709 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3710 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003711
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003712unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003713 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003714 return err;
3715}
3716
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003717static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003718 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003719{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003720 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003721 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003722 int err;
3723
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003724 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003725
Johan Hedberg561aafb2012-01-04 13:31:59 +02003726 hci_dev_lock(hdev);
3727
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003728 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003729 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3730 MGMT_STATUS_FAILED, &cp->addr,
3731 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003732 goto failed;
3733 }
3734
Johan Hedberga198e7b2012-02-17 14:27:06 +02003735 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003736 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003737 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3738 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3739 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003740 goto failed;
3741 }
3742
3743 if (cp->name_known) {
3744 e->name_state = NAME_KNOWN;
3745 list_del(&e->list);
3746 } else {
3747 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003748 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003749 }
3750
Johan Hedberge3846622013-01-09 15:29:33 +02003751 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3752 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003753
3754failed:
3755 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003756 return err;
3757}
3758
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003759static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003760 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003761{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003762 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003763 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003764 int err;
3765
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003766 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003767
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003768 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003769 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3770 MGMT_STATUS_INVALID_PARAMS,
3771 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003772
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003773 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003774
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003775 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003776 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003777 status = MGMT_STATUS_FAILED;
Antti Julku7fbec222011-06-15 12:01:15 +03003778 else
Szymon Janca6785be2012-12-13 15:11:21 +01003779 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003780
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003781 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003782 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003783
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003784 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003785
3786 return err;
3787}
3788
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003789static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003790 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003791{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003792 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003793 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003794 int err;
3795
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003796 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003797
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003798 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003799 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3800 MGMT_STATUS_INVALID_PARAMS,
3801 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003802
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003803 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003804
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003805 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003806 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003807 status = MGMT_STATUS_INVALID_PARAMS;
Antti Julku7fbec222011-06-15 12:01:15 +03003808 else
Szymon Janca6785be2012-12-13 15:11:21 +01003809 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003810
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003811 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003812 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003813
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003814 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003815
3816 return err;
3817}
3818
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003819static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3820 u16 len)
3821{
3822 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003823 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003824 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003825 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003826
3827 BT_DBG("%s", hdev->name);
3828
Szymon Jancc72d4b82012-03-16 16:02:57 +01003829 source = __le16_to_cpu(cp->source);
3830
3831 if (source > 0x0002)
3832 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3833 MGMT_STATUS_INVALID_PARAMS);
3834
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003835 hci_dev_lock(hdev);
3836
Szymon Jancc72d4b82012-03-16 16:02:57 +01003837 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003838 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3839 hdev->devid_product = __le16_to_cpu(cp->product);
3840 hdev->devid_version = __le16_to_cpu(cp->version);
3841
3842 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3843
Johan Hedberg890ea892013-03-15 17:06:52 -05003844 hci_req_init(&req, hdev);
3845 update_eir(&req);
3846 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003847
3848 hci_dev_unlock(hdev);
3849
3850 return err;
3851}
3852
Johan Hedberg4375f102013-09-25 13:26:10 +03003853static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3854{
3855 struct cmd_lookup match = { NULL, hdev };
3856
3857 if (status) {
3858 u8 mgmt_err = mgmt_status(status);
3859
3860 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3861 cmd_status_rsp, &mgmt_err);
3862 return;
3863 }
3864
3865 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3866 &match);
3867
3868 new_settings(hdev, match.sk);
3869
3870 if (match.sk)
3871 sock_put(match.sk);
3872}
3873
Marcel Holtmann21b51872013-10-10 09:47:53 -07003874static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3875 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003876{
3877 struct mgmt_mode *cp = data;
3878 struct pending_cmd *cmd;
3879 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003880 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003881 int err;
3882
3883 BT_DBG("request for %s", hdev->name);
3884
Johan Hedberge6fe7982013-10-02 15:45:22 +03003885 status = mgmt_le_support(hdev);
3886 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003887 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003888 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03003889
3890 if (cp->val != 0x00 && cp->val != 0x01)
3891 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3892 MGMT_STATUS_INVALID_PARAMS);
3893
3894 hci_dev_lock(hdev);
3895
3896 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003897 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003898
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02003899 /* The following conditions are ones which mean that we should
3900 * not do any HCI communication but directly send a mgmt
3901 * response to user space (after toggling the flag if
3902 * necessary).
3903 */
3904 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07003905 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03003906 bool changed = false;
3907
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003908 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
3909 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003910 changed = true;
3911 }
3912
3913 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
3914 if (err < 0)
3915 goto unlock;
3916
3917 if (changed)
3918 err = new_settings(hdev, sk);
3919
3920 goto unlock;
3921 }
3922
3923 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
3924 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
3925 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3926 MGMT_STATUS_BUSY);
3927 goto unlock;
3928 }
3929
3930 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
3931 if (!cmd) {
3932 err = -ENOMEM;
3933 goto unlock;
3934 }
3935
3936 hci_req_init(&req, hdev);
3937
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07003938 if (val)
3939 enable_advertising(&req);
3940 else
3941 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03003942
3943 err = hci_req_run(&req, set_advertising_complete);
3944 if (err < 0)
3945 mgmt_pending_remove(cmd);
3946
3947unlock:
3948 hci_dev_unlock(hdev);
3949 return err;
3950}
3951
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003952static int set_static_address(struct sock *sk, struct hci_dev *hdev,
3953 void *data, u16 len)
3954{
3955 struct mgmt_cp_set_static_address *cp = data;
3956 int err;
3957
3958 BT_DBG("%s", hdev->name);
3959
Marcel Holtmann62af4442013-10-02 22:10:32 -07003960 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003961 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07003962 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003963
3964 if (hdev_is_powered(hdev))
3965 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
3966 MGMT_STATUS_REJECTED);
3967
3968 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
3969 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
3970 return cmd_status(sk, hdev->id,
3971 MGMT_OP_SET_STATIC_ADDRESS,
3972 MGMT_STATUS_INVALID_PARAMS);
3973
3974 /* Two most significant bits shall be set */
3975 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
3976 return cmd_status(sk, hdev->id,
3977 MGMT_OP_SET_STATIC_ADDRESS,
3978 MGMT_STATUS_INVALID_PARAMS);
3979 }
3980
3981 hci_dev_lock(hdev);
3982
3983 bacpy(&hdev->static_addr, &cp->bdaddr);
3984
3985 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
3986
3987 hci_dev_unlock(hdev);
3988
3989 return err;
3990}
3991
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003992static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
3993 void *data, u16 len)
3994{
3995 struct mgmt_cp_set_scan_params *cp = data;
3996 __u16 interval, window;
3997 int err;
3998
3999 BT_DBG("%s", hdev->name);
4000
4001 if (!lmp_le_capable(hdev))
4002 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4003 MGMT_STATUS_NOT_SUPPORTED);
4004
4005 interval = __le16_to_cpu(cp->interval);
4006
4007 if (interval < 0x0004 || interval > 0x4000)
4008 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4009 MGMT_STATUS_INVALID_PARAMS);
4010
4011 window = __le16_to_cpu(cp->window);
4012
4013 if (window < 0x0004 || window > 0x4000)
4014 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4015 MGMT_STATUS_INVALID_PARAMS);
4016
Marcel Holtmann899e1072013-10-14 09:55:32 -07004017 if (window > interval)
4018 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4019 MGMT_STATUS_INVALID_PARAMS);
4020
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004021 hci_dev_lock(hdev);
4022
4023 hdev->le_scan_interval = interval;
4024 hdev->le_scan_window = window;
4025
4026 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4027
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004028 /* If background scan is running, restart it so new parameters are
4029 * loaded.
4030 */
4031 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4032 hdev->discovery.state == DISCOVERY_STOPPED) {
4033 struct hci_request req;
4034
4035 hci_req_init(&req, hdev);
4036
4037 hci_req_add_le_scan_disable(&req);
4038 hci_req_add_le_passive_scan(&req);
4039
4040 hci_req_run(&req, NULL);
4041 }
4042
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004043 hci_dev_unlock(hdev);
4044
4045 return err;
4046}
4047
Johan Hedberg33e38b32013-03-15 17:07:05 -05004048static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4049{
4050 struct pending_cmd *cmd;
4051
4052 BT_DBG("status 0x%02x", status);
4053
4054 hci_dev_lock(hdev);
4055
4056 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4057 if (!cmd)
4058 goto unlock;
4059
4060 if (status) {
4061 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4062 mgmt_status(status));
4063 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004064 struct mgmt_mode *cp = cmd->param;
4065
4066 if (cp->val)
4067 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4068 else
4069 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4070
Johan Hedberg33e38b32013-03-15 17:07:05 -05004071 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4072 new_settings(hdev, cmd->sk);
4073 }
4074
4075 mgmt_pending_remove(cmd);
4076
4077unlock:
4078 hci_dev_unlock(hdev);
4079}
4080
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004081static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004082 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004083{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004084 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004085 struct pending_cmd *cmd;
4086 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004087 int err;
4088
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004089 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004090
Johan Hedberg56f87902013-10-02 13:43:13 +03004091 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4092 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004093 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4094 MGMT_STATUS_NOT_SUPPORTED);
4095
Johan Hedberga7e80f22013-01-09 16:05:19 +02004096 if (cp->val != 0x00 && cp->val != 0x01)
4097 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4098 MGMT_STATUS_INVALID_PARAMS);
4099
Johan Hedberg5400c042012-02-21 16:40:33 +02004100 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004101 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004102 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004103
4104 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004105 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004106 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004107
4108 hci_dev_lock(hdev);
4109
Johan Hedberg05cbf292013-03-15 17:07:07 -05004110 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4111 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4112 MGMT_STATUS_BUSY);
4113 goto unlock;
4114 }
4115
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004116 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4117 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4118 hdev);
4119 goto unlock;
4120 }
4121
Johan Hedberg33e38b32013-03-15 17:07:05 -05004122 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4123 data, len);
4124 if (!cmd) {
4125 err = -ENOMEM;
4126 goto unlock;
4127 }
4128
4129 hci_req_init(&req, hdev);
4130
Johan Hedberg406d7802013-03-15 17:07:09 -05004131 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004132
4133 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004134 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004135 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004136 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004137 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004138 }
4139
Johan Hedberg33e38b32013-03-15 17:07:05 -05004140unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004141 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004142
Antti Julkuf6422ec2011-06-22 13:11:56 +03004143 return err;
4144}
4145
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004146static void set_bredr_scan(struct hci_request *req)
4147{
4148 struct hci_dev *hdev = req->hdev;
4149 u8 scan = 0;
4150
4151 /* Ensure that fast connectable is disabled. This function will
4152 * not do anything if the page scan parameters are already what
4153 * they should be.
4154 */
4155 write_fast_connectable(req, false);
4156
4157 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4158 scan |= SCAN_PAGE;
4159 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4160 scan |= SCAN_INQUIRY;
4161
4162 if (scan)
4163 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4164}
4165
Johan Hedberg0663ca22013-10-02 13:43:14 +03004166static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4167{
4168 struct pending_cmd *cmd;
4169
4170 BT_DBG("status 0x%02x", status);
4171
4172 hci_dev_lock(hdev);
4173
4174 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4175 if (!cmd)
4176 goto unlock;
4177
4178 if (status) {
4179 u8 mgmt_err = mgmt_status(status);
4180
4181 /* We need to restore the flag if related HCI commands
4182 * failed.
4183 */
4184 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4185
4186 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4187 } else {
4188 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4189 new_settings(hdev, cmd->sk);
4190 }
4191
4192 mgmt_pending_remove(cmd);
4193
4194unlock:
4195 hci_dev_unlock(hdev);
4196}
4197
4198static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4199{
4200 struct mgmt_mode *cp = data;
4201 struct pending_cmd *cmd;
4202 struct hci_request req;
4203 int err;
4204
4205 BT_DBG("request for %s", hdev->name);
4206
4207 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4208 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4209 MGMT_STATUS_NOT_SUPPORTED);
4210
4211 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4212 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4213 MGMT_STATUS_REJECTED);
4214
4215 if (cp->val != 0x00 && cp->val != 0x01)
4216 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4217 MGMT_STATUS_INVALID_PARAMS);
4218
4219 hci_dev_lock(hdev);
4220
4221 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4222 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4223 goto unlock;
4224 }
4225
4226 if (!hdev_is_powered(hdev)) {
4227 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004228 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4229 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4230 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4231 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4232 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4233 }
4234
4235 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4236
4237 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4238 if (err < 0)
4239 goto unlock;
4240
4241 err = new_settings(hdev, sk);
4242 goto unlock;
4243 }
4244
4245 /* Reject disabling when powered on */
4246 if (!cp->val) {
4247 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4248 MGMT_STATUS_REJECTED);
4249 goto unlock;
4250 }
4251
4252 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4253 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4254 MGMT_STATUS_BUSY);
4255 goto unlock;
4256 }
4257
4258 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4259 if (!cmd) {
4260 err = -ENOMEM;
4261 goto unlock;
4262 }
4263
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004264 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004265 * generates the correct flags.
4266 */
4267 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4268
4269 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004270
4271 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4272 set_bredr_scan(&req);
4273
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004274 /* Since only the advertising data flags will change, there
4275 * is no need to update the scan response data.
4276 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004277 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004278
Johan Hedberg0663ca22013-10-02 13:43:14 +03004279 err = hci_req_run(&req, set_bredr_complete);
4280 if (err < 0)
4281 mgmt_pending_remove(cmd);
4282
4283unlock:
4284 hci_dev_unlock(hdev);
4285 return err;
4286}
4287
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004288static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4289 void *data, u16 len)
4290{
4291 struct mgmt_mode *cp = data;
4292 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004293 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004294 int err;
4295
4296 BT_DBG("request for %s", hdev->name);
4297
4298 status = mgmt_bredr_support(hdev);
4299 if (status)
4300 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4301 status);
4302
Marcel Holtmann5afeac12014-01-10 02:07:27 -08004303 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004304 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004305 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4306 MGMT_STATUS_NOT_SUPPORTED);
4307
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004308 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004309 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4310 MGMT_STATUS_INVALID_PARAMS);
4311
4312 hci_dev_lock(hdev);
4313
4314 if (!hdev_is_powered(hdev)) {
4315 bool changed;
4316
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004317 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004318 changed = !test_and_set_bit(HCI_SC_ENABLED,
4319 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004320 if (cp->val == 0x02)
4321 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4322 else
4323 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4324 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004325 changed = test_and_clear_bit(HCI_SC_ENABLED,
4326 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004327 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4328 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004329
4330 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4331 if (err < 0)
4332 goto failed;
4333
4334 if (changed)
4335 err = new_settings(hdev, sk);
4336
4337 goto failed;
4338 }
4339
4340 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4341 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4342 MGMT_STATUS_BUSY);
4343 goto failed;
4344 }
4345
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004346 val = !!cp->val;
4347
4348 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4349 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004350 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4351 goto failed;
4352 }
4353
4354 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4355 if (!cmd) {
4356 err = -ENOMEM;
4357 goto failed;
4358 }
4359
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004360 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004361 if (err < 0) {
4362 mgmt_pending_remove(cmd);
4363 goto failed;
4364 }
4365
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004366 if (cp->val == 0x02)
4367 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4368 else
4369 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4370
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004371failed:
4372 hci_dev_unlock(hdev);
4373 return err;
4374}
4375
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004376static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4377 void *data, u16 len)
4378{
4379 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004380 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004381 int err;
4382
4383 BT_DBG("request for %s", hdev->name);
4384
Johan Hedbergb97109792014-06-24 14:00:28 +03004385 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004386 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4387 MGMT_STATUS_INVALID_PARAMS);
4388
4389 hci_dev_lock(hdev);
4390
4391 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004392 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4393 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004394 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004395 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4396 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004397
Johan Hedbergb97109792014-06-24 14:00:28 +03004398 if (cp->val == 0x02)
4399 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4400 &hdev->dev_flags);
4401 else
4402 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4403 &hdev->dev_flags);
4404
4405 if (hdev_is_powered(hdev) && use_changed &&
4406 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4407 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4408 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4409 sizeof(mode), &mode);
4410 }
4411
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004412 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4413 if (err < 0)
4414 goto unlock;
4415
4416 if (changed)
4417 err = new_settings(hdev, sk);
4418
4419unlock:
4420 hci_dev_unlock(hdev);
4421 return err;
4422}
4423
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004424static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4425 u16 len)
4426{
4427 struct mgmt_cp_set_privacy *cp = cp_data;
4428 bool changed;
4429 int err;
4430
4431 BT_DBG("request for %s", hdev->name);
4432
4433 if (!lmp_le_capable(hdev))
4434 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4435 MGMT_STATUS_NOT_SUPPORTED);
4436
4437 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4438 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4439 MGMT_STATUS_INVALID_PARAMS);
4440
4441 if (hdev_is_powered(hdev))
4442 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4443 MGMT_STATUS_REJECTED);
4444
4445 hci_dev_lock(hdev);
4446
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004447 /* If user space supports this command it is also expected to
4448 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4449 */
4450 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4451
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004452 if (cp->privacy) {
4453 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4454 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4455 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4456 } else {
4457 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4458 memset(hdev->irk, 0, sizeof(hdev->irk));
4459 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4460 }
4461
4462 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4463 if (err < 0)
4464 goto unlock;
4465
4466 if (changed)
4467 err = new_settings(hdev, sk);
4468
4469unlock:
4470 hci_dev_unlock(hdev);
4471 return err;
4472}
4473
Johan Hedberg41edf162014-02-18 10:19:35 +02004474static bool irk_is_valid(struct mgmt_irk_info *irk)
4475{
4476 switch (irk->addr.type) {
4477 case BDADDR_LE_PUBLIC:
4478 return true;
4479
4480 case BDADDR_LE_RANDOM:
4481 /* Two most significant bits shall be set */
4482 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4483 return false;
4484 return true;
4485 }
4486
4487 return false;
4488}
4489
4490static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4491 u16 len)
4492{
4493 struct mgmt_cp_load_irks *cp = cp_data;
4494 u16 irk_count, expected_len;
4495 int i, err;
4496
4497 BT_DBG("request for %s", hdev->name);
4498
4499 if (!lmp_le_capable(hdev))
4500 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4501 MGMT_STATUS_NOT_SUPPORTED);
4502
4503 irk_count = __le16_to_cpu(cp->irk_count);
4504
4505 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4506 if (expected_len != len) {
4507 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004508 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004509 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4510 MGMT_STATUS_INVALID_PARAMS);
4511 }
4512
4513 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4514
4515 for (i = 0; i < irk_count; i++) {
4516 struct mgmt_irk_info *key = &cp->irks[i];
4517
4518 if (!irk_is_valid(key))
4519 return cmd_status(sk, hdev->id,
4520 MGMT_OP_LOAD_IRKS,
4521 MGMT_STATUS_INVALID_PARAMS);
4522 }
4523
4524 hci_dev_lock(hdev);
4525
4526 hci_smp_irks_clear(hdev);
4527
4528 for (i = 0; i < irk_count; i++) {
4529 struct mgmt_irk_info *irk = &cp->irks[i];
4530 u8 addr_type;
4531
4532 if (irk->addr.type == BDADDR_LE_PUBLIC)
4533 addr_type = ADDR_LE_DEV_PUBLIC;
4534 else
4535 addr_type = ADDR_LE_DEV_RANDOM;
4536
4537 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4538 BDADDR_ANY);
4539 }
4540
4541 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4542
4543 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4544
4545 hci_dev_unlock(hdev);
4546
4547 return err;
4548}
4549
Johan Hedberg3f706b72013-01-20 14:27:16 +02004550static bool ltk_is_valid(struct mgmt_ltk_info *key)
4551{
4552 if (key->master != 0x00 && key->master != 0x01)
4553 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004554
4555 switch (key->addr.type) {
4556 case BDADDR_LE_PUBLIC:
4557 return true;
4558
4559 case BDADDR_LE_RANDOM:
4560 /* Two most significant bits shall be set */
4561 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4562 return false;
4563 return true;
4564 }
4565
4566 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004567}
4568
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004569static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004570 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004571{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004572 struct mgmt_cp_load_long_term_keys *cp = cp_data;
4573 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004574 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004575
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004576 BT_DBG("request for %s", hdev->name);
4577
4578 if (!lmp_le_capable(hdev))
4579 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4580 MGMT_STATUS_NOT_SUPPORTED);
4581
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004582 key_count = __le16_to_cpu(cp->key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004583
4584 expected_len = sizeof(*cp) + key_count *
4585 sizeof(struct mgmt_ltk_info);
4586 if (expected_len != len) {
4587 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004588 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004589 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004590 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004591 }
4592
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004593 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004594
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004595 for (i = 0; i < key_count; i++) {
4596 struct mgmt_ltk_info *key = &cp->keys[i];
4597
Johan Hedberg3f706b72013-01-20 14:27:16 +02004598 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004599 return cmd_status(sk, hdev->id,
4600 MGMT_OP_LOAD_LONG_TERM_KEYS,
4601 MGMT_STATUS_INVALID_PARAMS);
4602 }
4603
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004604 hci_dev_lock(hdev);
4605
4606 hci_smp_ltks_clear(hdev);
4607
4608 for (i = 0; i < key_count; i++) {
4609 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004610 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004611
4612 if (key->addr.type == BDADDR_LE_PUBLIC)
4613 addr_type = ADDR_LE_DEV_PUBLIC;
4614 else
4615 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004616
4617 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004618 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004619 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004620 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004621
Johan Hedberg61b43352014-05-29 19:36:53 +03004622 switch (key->type) {
4623 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004624 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004625 break;
4626 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004627 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004628 break;
4629 default:
4630 continue;
4631 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004632
Johan Hedberg35d70272014-02-19 14:57:47 +02004633 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004634 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004635 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004636 }
4637
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004638 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4639 NULL, 0);
4640
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004641 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004642
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004643 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004644}
4645
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004646struct cmd_conn_lookup {
4647 struct hci_conn *conn;
4648 bool valid_tx_power;
4649 u8 mgmt_status;
4650};
4651
4652static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4653{
4654 struct cmd_conn_lookup *match = data;
4655 struct mgmt_cp_get_conn_info *cp;
4656 struct mgmt_rp_get_conn_info rp;
4657 struct hci_conn *conn = cmd->user_data;
4658
4659 if (conn != match->conn)
4660 return;
4661
4662 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4663
4664 memset(&rp, 0, sizeof(rp));
4665 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4666 rp.addr.type = cp->addr.type;
4667
4668 if (!match->mgmt_status) {
4669 rp.rssi = conn->rssi;
4670
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004671 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004672 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004673 rp.max_tx_power = conn->max_tx_power;
4674 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004675 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004676 rp.max_tx_power = HCI_TX_POWER_INVALID;
4677 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004678 }
4679
4680 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4681 match->mgmt_status, &rp, sizeof(rp));
4682
4683 hci_conn_drop(conn);
4684
4685 mgmt_pending_remove(cmd);
4686}
4687
4688static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4689{
4690 struct hci_cp_read_rssi *cp;
4691 struct hci_conn *conn;
4692 struct cmd_conn_lookup match;
4693 u16 handle;
4694
4695 BT_DBG("status 0x%02x", status);
4696
4697 hci_dev_lock(hdev);
4698
4699 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004700 * otherwise we assume it's not valid. At the moment we assume that
4701 * either both or none of current and max values are valid to keep code
4702 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004703 */
4704 match.valid_tx_power = !status;
4705
4706 /* Commands sent in request are either Read RSSI or Read Transmit Power
4707 * Level so we check which one was last sent to retrieve connection
4708 * handle. Both commands have handle as first parameter so it's safe to
4709 * cast data on the same command struct.
4710 *
4711 * First command sent is always Read RSSI and we fail only if it fails.
4712 * In other case we simply override error to indicate success as we
4713 * already remembered if TX power value is actually valid.
4714 */
4715 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4716 if (!cp) {
4717 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4718 status = 0;
4719 }
4720
4721 if (!cp) {
4722 BT_ERR("invalid sent_cmd in response");
4723 goto unlock;
4724 }
4725
4726 handle = __le16_to_cpu(cp->handle);
4727 conn = hci_conn_hash_lookup_handle(hdev, handle);
4728 if (!conn) {
4729 BT_ERR("unknown handle (%d) in response", handle);
4730 goto unlock;
4731 }
4732
4733 match.conn = conn;
4734 match.mgmt_status = mgmt_status(status);
4735
4736 /* Cache refresh is complete, now reply for mgmt request for given
4737 * connection only.
4738 */
4739 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4740 get_conn_info_complete, &match);
4741
4742unlock:
4743 hci_dev_unlock(hdev);
4744}
4745
4746static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4747 u16 len)
4748{
4749 struct mgmt_cp_get_conn_info *cp = data;
4750 struct mgmt_rp_get_conn_info rp;
4751 struct hci_conn *conn;
4752 unsigned long conn_info_age;
4753 int err = 0;
4754
4755 BT_DBG("%s", hdev->name);
4756
4757 memset(&rp, 0, sizeof(rp));
4758 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4759 rp.addr.type = cp->addr.type;
4760
4761 if (!bdaddr_type_is_valid(cp->addr.type))
4762 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4763 MGMT_STATUS_INVALID_PARAMS,
4764 &rp, sizeof(rp));
4765
4766 hci_dev_lock(hdev);
4767
4768 if (!hdev_is_powered(hdev)) {
4769 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4770 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4771 goto unlock;
4772 }
4773
4774 if (cp->addr.type == BDADDR_BREDR)
4775 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4776 &cp->addr.bdaddr);
4777 else
4778 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4779
4780 if (!conn || conn->state != BT_CONNECTED) {
4781 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4782 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4783 goto unlock;
4784 }
4785
4786 /* To avoid client trying to guess when to poll again for information we
4787 * calculate conn info age as random value between min/max set in hdev.
4788 */
4789 conn_info_age = hdev->conn_info_min_age +
4790 prandom_u32_max(hdev->conn_info_max_age -
4791 hdev->conn_info_min_age);
4792
4793 /* Query controller to refresh cached values if they are too old or were
4794 * never read.
4795 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004796 if (time_after(jiffies, conn->conn_info_timestamp +
4797 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004798 !conn->conn_info_timestamp) {
4799 struct hci_request req;
4800 struct hci_cp_read_tx_power req_txp_cp;
4801 struct hci_cp_read_rssi req_rssi_cp;
4802 struct pending_cmd *cmd;
4803
4804 hci_req_init(&req, hdev);
4805 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4806 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4807 &req_rssi_cp);
4808
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004809 /* For LE links TX power does not change thus we don't need to
4810 * query for it once value is known.
4811 */
4812 if (!bdaddr_type_is_le(cp->addr.type) ||
4813 conn->tx_power == HCI_TX_POWER_INVALID) {
4814 req_txp_cp.handle = cpu_to_le16(conn->handle);
4815 req_txp_cp.type = 0x00;
4816 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4817 sizeof(req_txp_cp), &req_txp_cp);
4818 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004819
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004820 /* Max TX power needs to be read only once per connection */
4821 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
4822 req_txp_cp.handle = cpu_to_le16(conn->handle);
4823 req_txp_cp.type = 0x01;
4824 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4825 sizeof(req_txp_cp), &req_txp_cp);
4826 }
4827
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004828 err = hci_req_run(&req, conn_info_refresh_complete);
4829 if (err < 0)
4830 goto unlock;
4831
4832 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
4833 data, len);
4834 if (!cmd) {
4835 err = -ENOMEM;
4836 goto unlock;
4837 }
4838
4839 hci_conn_hold(conn);
4840 cmd->user_data = conn;
4841
4842 conn->conn_info_timestamp = jiffies;
4843 } else {
4844 /* Cache is valid, just reply with values cached in hci_conn */
4845 rp.rssi = conn->rssi;
4846 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004847 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004848
4849 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4850 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
4851 }
4852
4853unlock:
4854 hci_dev_unlock(hdev);
4855 return err;
4856}
4857
Johan Hedberg95868422014-06-28 17:54:07 +03004858static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
4859{
4860 struct mgmt_cp_get_clock_info *cp;
4861 struct mgmt_rp_get_clock_info rp;
4862 struct hci_cp_read_clock *hci_cp;
4863 struct pending_cmd *cmd;
4864 struct hci_conn *conn;
4865
4866 BT_DBG("%s status %u", hdev->name, status);
4867
4868 hci_dev_lock(hdev);
4869
4870 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
4871 if (!hci_cp)
4872 goto unlock;
4873
4874 if (hci_cp->which) {
4875 u16 handle = __le16_to_cpu(hci_cp->handle);
4876 conn = hci_conn_hash_lookup_handle(hdev, handle);
4877 } else {
4878 conn = NULL;
4879 }
4880
4881 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
4882 if (!cmd)
4883 goto unlock;
4884
4885 cp = cmd->param;
4886
4887 memset(&rp, 0, sizeof(rp));
4888 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
4889
4890 if (status)
4891 goto send_rsp;
4892
4893 rp.local_clock = cpu_to_le32(hdev->clock);
4894
4895 if (conn) {
4896 rp.piconet_clock = cpu_to_le32(conn->clock);
4897 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
4898 }
4899
4900send_rsp:
4901 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
4902 &rp, sizeof(rp));
4903 mgmt_pending_remove(cmd);
4904 if (conn)
4905 hci_conn_drop(conn);
4906
4907unlock:
4908 hci_dev_unlock(hdev);
4909}
4910
4911static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
4912 u16 len)
4913{
4914 struct mgmt_cp_get_clock_info *cp = data;
4915 struct mgmt_rp_get_clock_info rp;
4916 struct hci_cp_read_clock hci_cp;
4917 struct pending_cmd *cmd;
4918 struct hci_request req;
4919 struct hci_conn *conn;
4920 int err;
4921
4922 BT_DBG("%s", hdev->name);
4923
4924 memset(&rp, 0, sizeof(rp));
4925 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4926 rp.addr.type = cp->addr.type;
4927
4928 if (cp->addr.type != BDADDR_BREDR)
4929 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
4930 MGMT_STATUS_INVALID_PARAMS,
4931 &rp, sizeof(rp));
4932
4933 hci_dev_lock(hdev);
4934
4935 if (!hdev_is_powered(hdev)) {
4936 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
4937 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4938 goto unlock;
4939 }
4940
4941 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
4942 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4943 &cp->addr.bdaddr);
4944 if (!conn || conn->state != BT_CONNECTED) {
4945 err = cmd_complete(sk, hdev->id,
4946 MGMT_OP_GET_CLOCK_INFO,
4947 MGMT_STATUS_NOT_CONNECTED,
4948 &rp, sizeof(rp));
4949 goto unlock;
4950 }
4951 } else {
4952 conn = NULL;
4953 }
4954
4955 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
4956 if (!cmd) {
4957 err = -ENOMEM;
4958 goto unlock;
4959 }
4960
4961 hci_req_init(&req, hdev);
4962
4963 memset(&hci_cp, 0, sizeof(hci_cp));
4964 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
4965
4966 if (conn) {
4967 hci_conn_hold(conn);
4968 cmd->user_data = conn;
4969
4970 hci_cp.handle = cpu_to_le16(conn->handle);
4971 hci_cp.which = 0x01; /* Piconet clock */
4972 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
4973 }
4974
4975 err = hci_req_run(&req, get_clock_info_complete);
4976 if (err < 0)
4977 mgmt_pending_remove(cmd);
4978
4979unlock:
4980 hci_dev_unlock(hdev);
4981 return err;
4982}
4983
Marcel Holtmann8afef092014-06-29 22:28:34 +02004984static void device_added(struct sock *sk, struct hci_dev *hdev,
4985 bdaddr_t *bdaddr, u8 type, u8 action)
4986{
4987 struct mgmt_ev_device_added ev;
4988
4989 bacpy(&ev.addr.bdaddr, bdaddr);
4990 ev.addr.type = type;
4991 ev.action = action;
4992
4993 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
4994}
4995
Marcel Holtmann2faade52014-06-29 19:44:03 +02004996static int add_device(struct sock *sk, struct hci_dev *hdev,
4997 void *data, u16 len)
4998{
4999 struct mgmt_cp_add_device *cp = data;
5000 u8 auto_conn, addr_type;
5001 int err;
5002
5003 BT_DBG("%s", hdev->name);
5004
5005 if (!bdaddr_type_is_le(cp->addr.type) ||
5006 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5007 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5008 MGMT_STATUS_INVALID_PARAMS,
5009 &cp->addr, sizeof(cp->addr));
5010
5011 if (cp->action != 0x00 && cp->action != 0x01)
5012 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5013 MGMT_STATUS_INVALID_PARAMS,
5014 &cp->addr, sizeof(cp->addr));
5015
5016 hci_dev_lock(hdev);
5017
5018 if (cp->addr.type == BDADDR_LE_PUBLIC)
5019 addr_type = ADDR_LE_DEV_PUBLIC;
5020 else
5021 addr_type = ADDR_LE_DEV_RANDOM;
5022
5023 if (cp->action)
5024 auto_conn = HCI_AUTO_CONN_ALWAYS;
5025 else
5026 auto_conn = HCI_AUTO_CONN_DISABLED;
5027
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005028 /* If the connection parameters don't exist for this device,
5029 * they will be created and configured with defaults.
5030 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005031 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5032 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005033 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5034 MGMT_STATUS_FAILED,
5035 &cp->addr, sizeof(cp->addr));
5036 goto unlock;
5037 }
5038
Marcel Holtmann8afef092014-06-29 22:28:34 +02005039 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5040
Marcel Holtmann2faade52014-06-29 19:44:03 +02005041 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5042 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5043
5044unlock:
5045 hci_dev_unlock(hdev);
5046 return err;
5047}
5048
Marcel Holtmann8afef092014-06-29 22:28:34 +02005049static void device_removed(struct sock *sk, struct hci_dev *hdev,
5050 bdaddr_t *bdaddr, u8 type)
5051{
5052 struct mgmt_ev_device_removed ev;
5053
5054 bacpy(&ev.addr.bdaddr, bdaddr);
5055 ev.addr.type = type;
5056
5057 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5058}
5059
Marcel Holtmann2faade52014-06-29 19:44:03 +02005060static int remove_device(struct sock *sk, struct hci_dev *hdev,
5061 void *data, u16 len)
5062{
5063 struct mgmt_cp_remove_device *cp = data;
5064 int err;
5065
5066 BT_DBG("%s", hdev->name);
5067
5068 hci_dev_lock(hdev);
5069
5070 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5071 u8 addr_type;
5072
5073 if (!bdaddr_type_is_le(cp->addr.type)) {
5074 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5075 MGMT_STATUS_INVALID_PARAMS,
5076 &cp->addr, sizeof(cp->addr));
5077 goto unlock;
5078 }
5079
5080 if (cp->addr.type == BDADDR_LE_PUBLIC)
5081 addr_type = ADDR_LE_DEV_PUBLIC;
5082 else
5083 addr_type = ADDR_LE_DEV_RANDOM;
5084
5085 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005086
5087 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005088 } else {
5089 if (cp->addr.type) {
5090 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5091 MGMT_STATUS_INVALID_PARAMS,
5092 &cp->addr, sizeof(cp->addr));
5093 goto unlock;
5094 }
5095
5096 hci_conn_params_clear(hdev);
5097 }
5098
5099 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5100 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5101
5102unlock:
5103 hci_dev_unlock(hdev);
5104 return err;
5105}
5106
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005107static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005108 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5109 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005110 bool var_len;
5111 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005112} mgmt_handlers[] = {
5113 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005114 { read_version, false, MGMT_READ_VERSION_SIZE },
5115 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5116 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5117 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5118 { set_powered, false, MGMT_SETTING_SIZE },
5119 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5120 { set_connectable, false, MGMT_SETTING_SIZE },
5121 { set_fast_connectable, false, MGMT_SETTING_SIZE },
5122 { set_pairable, false, MGMT_SETTING_SIZE },
5123 { set_link_security, false, MGMT_SETTING_SIZE },
5124 { set_ssp, false, MGMT_SETTING_SIZE },
5125 { set_hs, false, MGMT_SETTING_SIZE },
5126 { set_le, false, MGMT_SETTING_SIZE },
5127 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5128 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5129 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5130 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5131 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5132 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5133 { disconnect, false, MGMT_DISCONNECT_SIZE },
5134 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5135 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5136 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5137 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5138 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5139 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5140 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5141 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5142 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5143 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5144 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5145 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005146 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005147 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5148 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5149 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5150 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5151 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5152 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005153 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005154 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005155 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005156 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005157 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005158 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005159 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005160 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005161 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005162 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005163 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005164 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5165 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005166};
5167
Johan Hedberg03811012010-12-08 00:21:06 +02005168int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5169{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005170 void *buf;
5171 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005172 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005173 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005174 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005175 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005176 int err;
5177
5178 BT_DBG("got %zu bytes", msglen);
5179
5180 if (msglen < sizeof(*hdr))
5181 return -EINVAL;
5182
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005183 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005184 if (!buf)
5185 return -ENOMEM;
5186
5187 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5188 err = -EFAULT;
5189 goto done;
5190 }
5191
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005192 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005193 opcode = __le16_to_cpu(hdr->opcode);
5194 index = __le16_to_cpu(hdr->index);
5195 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005196
5197 if (len != msglen - sizeof(*hdr)) {
5198 err = -EINVAL;
5199 goto done;
5200 }
5201
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005202 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005203 hdev = hci_dev_get(index);
5204 if (!hdev) {
5205 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005206 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005207 goto done;
5208 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005209
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005210 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannfee746b2014-06-29 12:13:05 +02005211 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) ||
5212 test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005213 err = cmd_status(sk, index, opcode,
5214 MGMT_STATUS_INVALID_INDEX);
5215 goto done;
5216 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005217 }
5218
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005219 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005220 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005221 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005222 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005223 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005224 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005225 }
5226
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005227 if ((hdev && opcode < MGMT_OP_READ_INFO) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005228 (!hdev && opcode >= MGMT_OP_READ_INFO)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005229 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005230 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005231 goto done;
5232 }
5233
Johan Hedbergbe22b542012-03-01 22:24:41 +02005234 handler = &mgmt_handlers[opcode];
5235
5236 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005237 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005238 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005239 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005240 goto done;
5241 }
5242
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005243 if (hdev)
5244 mgmt_init_hdev(sk, hdev);
5245
5246 cp = buf + sizeof(*hdr);
5247
Johan Hedbergbe22b542012-03-01 22:24:41 +02005248 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005249 if (err < 0)
5250 goto done;
5251
Johan Hedberg03811012010-12-08 00:21:06 +02005252 err = msglen;
5253
5254done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005255 if (hdev)
5256 hci_dev_put(hdev);
5257
Johan Hedberg03811012010-12-08 00:21:06 +02005258 kfree(buf);
5259 return err;
5260}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005261
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005262void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005263{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005264 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005265 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005266
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005267 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005268}
5269
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005270void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005271{
Johan Hedberg5f159032012-03-02 03:13:19 +02005272 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005273
Marcel Holtmann1514b892013-10-06 08:25:01 -07005274 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005275 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005276
Johan Hedberg744cf192011-11-08 20:40:14 +02005277 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005278
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005279 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005280}
5281
Andre Guedes6046dc32014-02-26 20:21:51 -03005282/* This function requires the caller holds hdev->lock */
5283static void restart_le_auto_conns(struct hci_dev *hdev)
5284{
5285 struct hci_conn_params *p;
5286
5287 list_for_each_entry(p, &hdev->le_conn_params, list) {
5288 if (p->auto_connect == HCI_AUTO_CONN_ALWAYS)
5289 hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
5290 }
5291}
5292
Johan Hedberg229ab392013-03-15 17:06:53 -05005293static void powered_complete(struct hci_dev *hdev, u8 status)
5294{
5295 struct cmd_lookup match = { NULL, hdev };
5296
5297 BT_DBG("status 0x%02x", status);
5298
5299 hci_dev_lock(hdev);
5300
Andre Guedes6046dc32014-02-26 20:21:51 -03005301 restart_le_auto_conns(hdev);
5302
Johan Hedberg229ab392013-03-15 17:06:53 -05005303 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5304
5305 new_settings(hdev, match.sk);
5306
5307 hci_dev_unlock(hdev);
5308
5309 if (match.sk)
5310 sock_put(match.sk);
5311}
5312
Johan Hedberg70da6242013-03-15 17:06:51 -05005313static int powered_update_hci(struct hci_dev *hdev)
5314{
Johan Hedberg890ea892013-03-15 17:06:52 -05005315 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005316 u8 link_sec;
5317
Johan Hedberg890ea892013-03-15 17:06:52 -05005318 hci_req_init(&req, hdev);
5319
Johan Hedberg70da6242013-03-15 17:06:51 -05005320 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5321 !lmp_host_ssp_capable(hdev)) {
5322 u8 ssp = 1;
5323
Johan Hedberg890ea892013-03-15 17:06:52 -05005324 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005325 }
5326
Johan Hedbergc73eee92013-04-19 18:35:21 +03005327 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5328 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005329 struct hci_cp_write_le_host_supported cp;
5330
5331 cp.le = 1;
5332 cp.simul = lmp_le_br_capable(hdev);
5333
5334 /* Check first if we already have the right
5335 * host state (host features set)
5336 */
5337 if (cp.le != lmp_host_le_capable(hdev) ||
5338 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005339 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5340 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005341 }
5342
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005343 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005344 /* Make sure the controller has a good default for
5345 * advertising data. This also applies to the case
5346 * where BR/EDR was toggled during the AUTO_OFF phase.
5347 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005348 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005349 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005350 update_scan_rsp_data(&req);
5351 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005352
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005353 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5354 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005355 }
5356
Johan Hedberg70da6242013-03-15 17:06:51 -05005357 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5358 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005359 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5360 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005361
5362 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005363 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5364 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005365 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005366 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005367 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005368 }
5369
Johan Hedberg229ab392013-03-15 17:06:53 -05005370 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005371}
5372
Johan Hedberg744cf192011-11-08 20:40:14 +02005373int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005374{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005375 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005376 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5377 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005378 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005379
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005380 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5381 return 0;
5382
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005383 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005384 if (powered_update_hci(hdev) == 0)
5385 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005386
Johan Hedberg229ab392013-03-15 17:06:53 -05005387 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5388 &match);
5389 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005390 }
5391
Johan Hedberg229ab392013-03-15 17:06:53 -05005392 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5393 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5394
5395 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5396 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5397 zero_cod, sizeof(zero_cod), NULL);
5398
5399new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005400 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005401
5402 if (match.sk)
5403 sock_put(match.sk);
5404
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005405 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005406}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005407
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005408void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005409{
5410 struct pending_cmd *cmd;
5411 u8 status;
5412
5413 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5414 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005415 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005416
5417 if (err == -ERFKILL)
5418 status = MGMT_STATUS_RFKILLED;
5419 else
5420 status = MGMT_STATUS_FAILED;
5421
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005422 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005423
5424 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005425}
5426
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005427void mgmt_discoverable_timeout(struct hci_dev *hdev)
5428{
5429 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005430
5431 hci_dev_lock(hdev);
5432
5433 /* When discoverable timeout triggers, then just make sure
5434 * the limited discoverable flag is cleared. Even in the case
5435 * of a timeout triggered from general discoverable, it is
5436 * safe to unconditionally clear the flag.
5437 */
5438 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005439 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005440
5441 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005442 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5443 u8 scan = SCAN_PAGE;
5444 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5445 sizeof(scan), &scan);
5446 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005447 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005448 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005449 hci_req_run(&req, NULL);
5450
5451 hdev->discov_timeout = 0;
5452
Johan Hedberg9a43e252013-10-20 19:00:07 +03005453 new_settings(hdev, NULL);
5454
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005455 hci_dev_unlock(hdev);
5456}
5457
Marcel Holtmann86a75642013-10-15 06:33:54 -07005458void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005459{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005460 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005461
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005462 /* Nothing needed here if there's a pending command since that
5463 * commands request completion callback takes care of everything
5464 * necessary.
5465 */
5466 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005467 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005468
Johan Hedbergbd107992014-02-24 14:52:19 +02005469 /* Powering off may clear the scan mode - don't let that interfere */
5470 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5471 return;
5472
Johan Hedberg9a43e252013-10-20 19:00:07 +03005473 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005474 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005475 } else {
5476 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005477 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005478 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005479
Johan Hedberg9a43e252013-10-20 19:00:07 +03005480 if (changed) {
5481 struct hci_request req;
5482
5483 /* In case this change in discoverable was triggered by
5484 * a disabling of connectable there could be a need to
5485 * update the advertising flags.
5486 */
5487 hci_req_init(&req, hdev);
5488 update_adv_data(&req);
5489 hci_req_run(&req, NULL);
5490
Marcel Holtmann86a75642013-10-15 06:33:54 -07005491 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005492 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005493}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005494
Marcel Holtmanna3309162013-10-15 06:33:55 -07005495void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005496{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005497 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005498
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005499 /* Nothing needed here if there's a pending command since that
5500 * commands request completion callback takes care of everything
5501 * necessary.
5502 */
5503 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005504 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005505
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005506 /* Powering off may clear the scan mode - don't let that interfere */
5507 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5508 return;
5509
Marcel Holtmanna3309162013-10-15 06:33:55 -07005510 if (connectable)
5511 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5512 else
5513 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005514
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005515 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005516 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005517}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005518
Johan Hedberg778b2352014-02-24 14:52:17 +02005519void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5520{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005521 /* Powering off may stop advertising - don't let that interfere */
5522 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5523 return;
5524
Johan Hedberg778b2352014-02-24 14:52:17 +02005525 if (advertising)
5526 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5527 else
5528 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5529}
5530
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005531void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005532{
Johan Hedbergca69b792011-11-11 18:10:00 +02005533 u8 mgmt_err = mgmt_status(status);
5534
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005535 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005536 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005537 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005538
5539 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005540 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005541 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005542}
5543
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005544void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5545 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005546{
Johan Hedberg86742e12011-11-07 23:13:38 +02005547 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005548
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005549 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005550
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005551 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02005552 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005553 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005554 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005555 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005556 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005557
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005558 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005559}
Johan Hedbergf7520542011-01-20 12:34:39 +02005560
Johan Hedbergd7b25452014-05-23 13:19:53 +03005561static u8 mgmt_ltk_type(struct smp_ltk *ltk)
5562{
5563 if (ltk->authenticated)
5564 return MGMT_LTK_AUTHENTICATED;
5565
5566 return MGMT_LTK_UNAUTHENTICATED;
5567}
5568
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005569void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005570{
5571 struct mgmt_ev_new_long_term_key ev;
5572
5573 memset(&ev, 0, sizeof(ev));
5574
Marcel Holtmann5192d302014-02-19 17:11:58 -08005575 /* Devices using resolvable or non-resolvable random addresses
5576 * without providing an indentity resolving key don't require
5577 * to store long term keys. Their addresses will change the
5578 * next time around.
5579 *
5580 * Only when a remote device provides an identity address
5581 * make sure the long term key is stored. If the remote
5582 * identity is known, the long term keys are internally
5583 * mapped to the identity address. So allow static random
5584 * and public addresses here.
5585 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005586 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5587 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5588 ev.store_hint = 0x00;
5589 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005590 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02005591
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005592 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005593 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03005594 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005595 ev.key.enc_size = key->enc_size;
5596 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005597 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005598
Johan Hedberg2ceba532014-06-16 19:25:16 +03005599 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005600 ev.key.master = 1;
5601
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005602 memcpy(ev.key.val, key->val, sizeof(key->val));
5603
Marcel Holtmann083368f2013-10-15 14:26:29 -07005604 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005605}
5606
Johan Hedberg95fbac82014-02-19 15:18:31 +02005607void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5608{
5609 struct mgmt_ev_new_irk ev;
5610
5611 memset(&ev, 0, sizeof(ev));
5612
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005613 /* For identity resolving keys from devices that are already
5614 * using a public address or static random address, do not
5615 * ask for storing this key. The identity resolving key really
5616 * is only mandatory for devices using resovlable random
5617 * addresses.
5618 *
5619 * Storing all identity resolving keys has the downside that
5620 * they will be also loaded on next boot of they system. More
5621 * identity resolving keys, means more time during scanning is
5622 * needed to actually resolve these addresses.
5623 */
5624 if (bacmp(&irk->rpa, BDADDR_ANY))
5625 ev.store_hint = 0x01;
5626 else
5627 ev.store_hint = 0x00;
5628
Johan Hedberg95fbac82014-02-19 15:18:31 +02005629 bacpy(&ev.rpa, &irk->rpa);
5630 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5631 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5632 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5633
5634 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5635}
5636
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005637void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
5638 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005639{
5640 struct mgmt_ev_new_csrk ev;
5641
5642 memset(&ev, 0, sizeof(ev));
5643
5644 /* Devices using resolvable or non-resolvable random addresses
5645 * without providing an indentity resolving key don't require
5646 * to store signature resolving keys. Their addresses will change
5647 * the next time around.
5648 *
5649 * Only when a remote device provides an identity address
5650 * make sure the signature resolving key is stored. So allow
5651 * static random and public addresses here.
5652 */
5653 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5654 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
5655 ev.store_hint = 0x00;
5656 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005657 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005658
5659 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
5660 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
5661 ev.key.master = csrk->master;
5662 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
5663
5664 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
5665}
5666
Marcel Holtmann94933992013-10-15 10:26:39 -07005667static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5668 u8 data_len)
5669{
5670 eir[eir_len++] = sizeof(type) + data_len;
5671 eir[eir_len++] = type;
5672 memcpy(&eir[eir_len], data, data_len);
5673 eir_len += data_len;
5674
5675 return eir_len;
5676}
5677
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005678void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5679 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5680 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005681{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005682 char buf[512];
5683 struct mgmt_ev_device_connected *ev = (void *) buf;
5684 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005685
Johan Hedbergb644ba32012-01-17 21:48:47 +02005686 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005687 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005688
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005689 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005690
Johan Hedbergb644ba32012-01-17 21:48:47 +02005691 if (name_len > 0)
5692 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005693 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005694
5695 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005696 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005697 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005698
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005699 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005700
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005701 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
5702 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02005703}
5704
Johan Hedberg8962ee72011-01-20 12:40:27 +02005705static void disconnect_rsp(struct pending_cmd *cmd, void *data)
5706{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01005707 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005708 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02005709 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005710
Johan Hedberg88c3df12012-02-09 14:27:38 +02005711 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5712 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005713
Johan Hedbergaee9b212012-02-18 15:07:59 +02005714 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005715 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005716
5717 *sk = cmd->sk;
5718 sock_hold(*sk);
5719
Johan Hedberga664b5b2011-02-19 12:06:02 -03005720 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005721}
5722
Johan Hedberg124f6e32012-02-09 13:50:12 +02005723static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02005724{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005725 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02005726 struct mgmt_cp_unpair_device *cp = cmd->param;
5727 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005728
5729 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02005730 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5731 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005732
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005733 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
5734
Johan Hedbergaee9b212012-02-18 15:07:59 +02005735 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02005736
5737 mgmt_pending_remove(cmd);
5738}
5739
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005740void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005741 u8 link_type, u8 addr_type, u8 reason,
5742 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02005743{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005744 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02005745 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005746 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005747
Johan Hedberg8b064a32014-02-24 14:52:22 +02005748 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5749 if (power_off) {
5750 struct mgmt_mode *cp = power_off->param;
5751
5752 /* The connection is still in hci_conn_hash so test for 1
5753 * instead of 0 to know if this is the last one.
5754 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005755 if (!cp->val && hci_conn_count(hdev) == 1) {
5756 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02005757 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005758 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02005759 }
5760
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005761 if (!mgmt_connected)
5762 return;
5763
Andre Guedes57eb7762013-10-30 19:01:41 -03005764 if (link_type != ACL_LINK && link_type != LE_LINK)
5765 return;
5766
Johan Hedberg744cf192011-11-08 20:40:14 +02005767 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02005768
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005769 bacpy(&ev.addr.bdaddr, bdaddr);
5770 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5771 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02005772
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005773 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005774
5775 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01005776 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005777
Johan Hedberg124f6e32012-02-09 13:50:12 +02005778 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005779 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005780}
5781
Marcel Holtmann78929242013-10-06 23:55:47 -07005782void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
5783 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02005784{
Andre Guedes3655bba2013-10-30 19:01:40 -03005785 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
5786 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02005787 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005788 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005789
Jefferson Delfes36a75f12012-09-18 13:36:54 -04005790 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
5791 hdev);
5792
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005793 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005794 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07005795 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005796
Andre Guedes3655bba2013-10-30 19:01:40 -03005797 cp = cmd->param;
5798
5799 if (bacmp(bdaddr, &cp->addr.bdaddr))
5800 return;
5801
5802 if (cp->addr.type != bdaddr_type)
5803 return;
5804
Johan Hedberg88c3df12012-02-09 14:27:38 +02005805 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03005806 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02005807
Marcel Holtmann78929242013-10-06 23:55:47 -07005808 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
5809 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005810
Johan Hedberga664b5b2011-02-19 12:06:02 -03005811 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02005812}
Johan Hedberg17d5c042011-01-22 06:09:08 +02005813
Marcel Holtmann445608d2013-10-06 23:55:48 -07005814void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5815 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02005816{
5817 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02005818 struct pending_cmd *power_off;
5819
5820 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5821 if (power_off) {
5822 struct mgmt_mode *cp = power_off->param;
5823
5824 /* The connection is still in hci_conn_hash so test for 1
5825 * instead of 0 to know if this is the last one.
5826 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005827 if (!cp->val && hci_conn_count(hdev) == 1) {
5828 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02005829 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005830 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02005831 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02005832
Johan Hedberg4c659c32011-11-07 23:13:39 +02005833 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005834 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005835 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005836
Marcel Holtmann445608d2013-10-06 23:55:48 -07005837 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005838}
Johan Hedberg980e1a52011-01-22 06:10:07 +02005839
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005840void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005841{
5842 struct mgmt_ev_pin_code_request ev;
5843
Johan Hedbergd8457692012-02-17 14:24:57 +02005844 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005845 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02005846 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005847
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005848 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005849}
5850
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005851void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5852 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005853{
5854 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005855 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005856
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005857 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005858 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005859 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005860
Johan Hedbergd8457692012-02-17 14:24:57 +02005861 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005862 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005863
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005864 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
5865 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005866
Johan Hedberga664b5b2011-02-19 12:06:02 -03005867 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005868}
5869
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005870void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5871 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005872{
5873 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005874 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005875
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005876 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005877 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005878 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005879
Johan Hedbergd8457692012-02-17 14:24:57 +02005880 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005881 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005882
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005883 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
5884 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005885
Johan Hedberga664b5b2011-02-19 12:06:02 -03005886 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005887}
Johan Hedberga5c29682011-02-19 12:05:57 -03005888
Johan Hedberg744cf192011-11-08 20:40:14 +02005889int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02005890 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005891 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03005892{
5893 struct mgmt_ev_user_confirm_request ev;
5894
Johan Hedberg744cf192011-11-08 20:40:14 +02005895 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03005896
Johan Hedberg272d90d2012-02-09 15:26:12 +02005897 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005898 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07005899 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02005900 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03005901
Johan Hedberg744cf192011-11-08 20:40:14 +02005902 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005903 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03005904}
5905
Johan Hedberg272d90d2012-02-09 15:26:12 +02005906int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005907 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08005908{
5909 struct mgmt_ev_user_passkey_request ev;
5910
5911 BT_DBG("%s", hdev->name);
5912
Johan Hedberg272d90d2012-02-09 15:26:12 +02005913 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005914 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08005915
5916 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005917 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08005918}
5919
Brian Gix0df4c182011-11-16 13:53:13 -08005920static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005921 u8 link_type, u8 addr_type, u8 status,
5922 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03005923{
5924 struct pending_cmd *cmd;
5925 struct mgmt_rp_user_confirm_reply rp;
5926 int err;
5927
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005928 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03005929 if (!cmd)
5930 return -ENOENT;
5931
Johan Hedberg272d90d2012-02-09 15:26:12 +02005932 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005933 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b212012-02-18 15:07:59 +02005934 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005935 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03005936
Johan Hedberga664b5b2011-02-19 12:06:02 -03005937 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03005938
5939 return err;
5940}
5941
Johan Hedberg744cf192011-11-08 20:40:14 +02005942int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005943 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005944{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005945 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005946 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005947}
5948
Johan Hedberg272d90d2012-02-09 15:26:12 +02005949int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005950 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005951{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005952 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005953 status,
5954 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005955}
Johan Hedberg2a611692011-02-19 12:06:00 -03005956
Brian Gix604086b2011-11-23 08:28:33 -08005957int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005958 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005959{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005960 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005961 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005962}
5963
Johan Hedberg272d90d2012-02-09 15:26:12 +02005964int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005965 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005966{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005967 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005968 status,
5969 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005970}
5971
Johan Hedberg92a25252012-09-06 18:39:26 +03005972int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
5973 u8 link_type, u8 addr_type, u32 passkey,
5974 u8 entered)
5975{
5976 struct mgmt_ev_passkey_notify ev;
5977
5978 BT_DBG("%s", hdev->name);
5979
5980 bacpy(&ev.addr.bdaddr, bdaddr);
5981 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5982 ev.passkey = __cpu_to_le32(passkey);
5983 ev.entered = entered;
5984
5985 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
5986}
5987
Marcel Holtmanne5460992013-10-15 14:26:23 -07005988void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5989 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03005990{
5991 struct mgmt_ev_auth_failed ev;
5992
Johan Hedbergbab73cb2012-02-09 16:07:29 +02005993 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005994 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005995 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03005996
Marcel Holtmanne5460992013-10-15 14:26:23 -07005997 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03005998}
Johan Hedbergb312b1612011-03-16 14:29:37 +02005999
Marcel Holtmann464996a2013-10-15 14:26:24 -07006000void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006001{
6002 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006003 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006004
6005 if (status) {
6006 u8 mgmt_err = mgmt_status(status);
6007 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006008 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006009 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006010 }
6011
Marcel Holtmann464996a2013-10-15 14:26:24 -07006012 if (test_bit(HCI_AUTH, &hdev->flags))
6013 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6014 &hdev->dev_flags);
6015 else
6016 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6017 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006018
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006019 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006020 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006021
Johan Hedberg47990ea2012-02-22 11:58:37 +02006022 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006023 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006024
6025 if (match.sk)
6026 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006027}
6028
Johan Hedberg890ea892013-03-15 17:06:52 -05006029static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006030{
Johan Hedberg890ea892013-03-15 17:06:52 -05006031 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006032 struct hci_cp_write_eir cp;
6033
Johan Hedberg976eb202012-10-24 21:12:01 +03006034 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006035 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006036
Johan Hedbergc80da272012-02-22 15:38:48 +02006037 memset(hdev->eir, 0, sizeof(hdev->eir));
6038
Johan Hedbergcacaf522012-02-21 00:52:42 +02006039 memset(&cp, 0, sizeof(cp));
6040
Johan Hedberg890ea892013-03-15 17:06:52 -05006041 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006042}
6043
Marcel Holtmann3e248562013-10-15 14:26:25 -07006044void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006045{
6046 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006047 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006048 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006049
6050 if (status) {
6051 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006052
6053 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006054 &hdev->dev_flags)) {
6055 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006056 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006057 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006058
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006059 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6060 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006061 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006062 }
6063
6064 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006065 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006066 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006067 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6068 if (!changed)
6069 changed = test_and_clear_bit(HCI_HS_ENABLED,
6070 &hdev->dev_flags);
6071 else
6072 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006073 }
6074
6075 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6076
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006077 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006078 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006079
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006080 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006081 sock_put(match.sk);
6082
Johan Hedberg890ea892013-03-15 17:06:52 -05006083 hci_req_init(&req, hdev);
6084
Johan Hedberg37699722014-06-24 14:00:27 +03006085 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6086 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6087 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6088 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006089 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006090 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006091 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006092 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006093
6094 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006095}
6096
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006097void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6098{
6099 struct cmd_lookup match = { NULL, hdev };
6100 bool changed = false;
6101
6102 if (status) {
6103 u8 mgmt_err = mgmt_status(status);
6104
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006105 if (enable) {
6106 if (test_and_clear_bit(HCI_SC_ENABLED,
6107 &hdev->dev_flags))
6108 new_settings(hdev, NULL);
6109 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6110 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006111
6112 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6113 cmd_status_rsp, &mgmt_err);
6114 return;
6115 }
6116
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006117 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006118 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006119 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006120 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006121 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6122 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006123
6124 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6125 settings_rsp, &match);
6126
6127 if (changed)
6128 new_settings(hdev, match.sk);
6129
6130 if (match.sk)
6131 sock_put(match.sk);
6132}
6133
Johan Hedberg92da6092013-03-15 17:06:55 -05006134static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006135{
6136 struct cmd_lookup *match = data;
6137
Johan Hedberg90e70452012-02-23 23:09:40 +02006138 if (match->sk == NULL) {
6139 match->sk = cmd->sk;
6140 sock_hold(match->sk);
6141 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006142}
6143
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006144void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6145 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006146{
Johan Hedberg90e70452012-02-23 23:09:40 +02006147 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006148
Johan Hedberg92da6092013-03-15 17:06:55 -05006149 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6150 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6151 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006152
6153 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006154 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6155 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006156
6157 if (match.sk)
6158 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006159}
6160
Marcel Holtmann7667da32013-10-15 14:26:27 -07006161void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006162{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006163 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006164 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006165
Johan Hedberg13928972013-03-15 17:07:00 -05006166 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006167 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006168
6169 memset(&ev, 0, sizeof(ev));
6170 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006171 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006172
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006173 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006174 if (!cmd) {
6175 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006176
Johan Hedberg13928972013-03-15 17:07:00 -05006177 /* If this is a HCI command related to powering on the
6178 * HCI dev don't send any mgmt signals.
6179 */
6180 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006181 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006182 }
6183
Marcel Holtmann7667da32013-10-15 14:26:27 -07006184 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6185 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006186}
Szymon Jancc35938b2011-03-22 13:12:21 +01006187
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006188void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6189 u8 *randomizer192, u8 *hash256,
6190 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006191{
6192 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006193
Johan Hedberg744cf192011-11-08 20:40:14 +02006194 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006195
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006196 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006197 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006198 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006199
6200 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006201 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6202 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006203 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006204 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6205 hash256 && randomizer256) {
6206 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006207
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006208 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6209 memcpy(rp.randomizer192, randomizer192,
6210 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006211
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006212 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6213 memcpy(rp.randomizer256, randomizer256,
6214 sizeof(rp.randomizer256));
6215
6216 cmd_complete(cmd->sk, hdev->id,
6217 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6218 &rp, sizeof(rp));
6219 } else {
6220 struct mgmt_rp_read_local_oob_data rp;
6221
6222 memcpy(rp.hash, hash192, sizeof(rp.hash));
6223 memcpy(rp.randomizer, randomizer192,
6224 sizeof(rp.randomizer));
6225
6226 cmd_complete(cmd->sk, hdev->id,
6227 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6228 &rp, sizeof(rp));
6229 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006230 }
6231
6232 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006233}
Johan Hedberge17acd42011-03-30 23:57:16 +03006234
Marcel Holtmann901801b2013-10-06 23:55:51 -07006235void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Johan Hedberg73cf71d2014-03-25 12:06:19 +02006236 u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name,
6237 u8 ssp, u8 *eir, u16 eir_len, u8 *scan_rsp,
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006238 u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006239{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006240 char buf[512];
6241 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006242 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006243 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006244
Andre Guedes12602d02013-04-30 15:29:40 -03006245 if (!hci_discovery_active(hdev))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006246 return;
Andre Guedes12602d02013-04-30 15:29:40 -03006247
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006248 /* Make sure that the buffer is big enough. The 5 extra bytes
6249 * are for the potential CoD field.
6250 */
6251 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006252 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006253
Johan Hedberg1dc06092012-01-15 21:01:23 +02006254 memset(buf, 0, sizeof(buf));
6255
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006256 irk = hci_get_irk(hdev, bdaddr, addr_type);
6257 if (irk) {
6258 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
6259 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
6260 } else {
6261 bacpy(&ev->addr.bdaddr, bdaddr);
6262 ev->addr.type = link_to_bdaddr(link_type, addr_type);
6263 }
6264
Johan Hedberge319d2e2012-01-15 19:51:59 +02006265 ev->rssi = rssi;
Johan Hedberg9a395a82012-02-23 00:00:32 +02006266 if (cfm_name)
Joe Perchesdcf4adb2014-03-12 10:52:35 -07006267 ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02006268 if (!ssp)
Joe Perchesdcf4adb2014-03-12 10:52:35 -07006269 ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING);
Johan Hedberge17acd42011-03-30 23:57:16 +03006270
Johan Hedberg1dc06092012-01-15 21:01:23 +02006271 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006272 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006273
Johan Hedberg1dc06092012-01-15 21:01:23 +02006274 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6275 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006276 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006277
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006278 if (scan_rsp_len > 0)
6279 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6280
6281 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6282 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006283
Marcel Holtmann901801b2013-10-06 23:55:51 -07006284 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006285}
Johan Hedberga88a9652011-03-30 13:18:12 +03006286
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006287void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6288 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006289{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006290 struct mgmt_ev_device_found *ev;
6291 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6292 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006293
Johan Hedbergb644ba32012-01-17 21:48:47 +02006294 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006295
Johan Hedbergb644ba32012-01-17 21:48:47 +02006296 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006297
Johan Hedbergb644ba32012-01-17 21:48:47 +02006298 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006299 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006300 ev->rssi = rssi;
6301
6302 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006303 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006304
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006305 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006306
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006307 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006308}
Johan Hedberg314b2382011-04-27 10:29:57 -04006309
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006310void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006311{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006312 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006313 struct pending_cmd *cmd;
6314
Andre Guedes343fb142011-11-22 17:14:19 -03006315 BT_DBG("%s discovering %u", hdev->name, discovering);
6316
Johan Hedberg164a6e72011-11-01 17:06:44 +02006317 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006318 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006319 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006320 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006321
6322 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006323 u8 type = hdev->discovery.type;
6324
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006325 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6326 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006327 mgmt_pending_remove(cmd);
6328 }
6329
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006330 memset(&ev, 0, sizeof(ev));
6331 ev.type = hdev->discovery.type;
6332 ev.discovering = discovering;
6333
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006334 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006335}
Antti Julku5e762442011-08-25 16:48:02 +03006336
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006337int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03006338{
6339 struct pending_cmd *cmd;
6340 struct mgmt_ev_device_blocked ev;
6341
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006342 cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03006343
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006344 bacpy(&ev.addr.bdaddr, bdaddr);
6345 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03006346
Johan Hedberg744cf192011-11-08 20:40:14 +02006347 return mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006348 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03006349}
6350
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006351int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03006352{
6353 struct pending_cmd *cmd;
6354 struct mgmt_ev_device_unblocked ev;
6355
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006356 cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03006357
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006358 bacpy(&ev.addr.bdaddr, bdaddr);
6359 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03006360
Johan Hedberg744cf192011-11-08 20:40:14 +02006361 return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006362 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03006363}
Marcel Holtmann5976e602013-10-06 04:08:14 -07006364
6365static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6366{
6367 BT_DBG("%s status %u", hdev->name, status);
6368
6369 /* Clear the advertising mgmt setting if we failed to re-enable it */
6370 if (status) {
6371 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006372 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006373 }
6374}
6375
6376void mgmt_reenable_advertising(struct hci_dev *hdev)
6377{
6378 struct hci_request req;
6379
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006380 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006381 return;
6382
6383 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6384 return;
6385
6386 hci_req_init(&req, hdev);
6387 enable_advertising(&req);
6388
6389 /* If this fails we have no option but to let user space know
6390 * that we've disabled advertising.
6391 */
6392 if (hci_req_run(&req, adv_enable_complete) < 0) {
6393 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006394 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006395 }
6396}