blob: ba5e215a7561a23ac08b4708d1b4b09cfb58c861 [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);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003776 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003777 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003778 goto done;
3779 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003780
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003781 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3782 sk);
3783 status = MGMT_STATUS_SUCCESS;
3784
3785done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003786 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003787 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003788
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003789 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003790
3791 return err;
3792}
3793
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003794static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003795 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003796{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003797 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003798 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003799 int err;
3800
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003801 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003802
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003803 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003804 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3805 MGMT_STATUS_INVALID_PARAMS,
3806 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003807
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003808 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003809
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003810 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003811 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003812 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003813 goto done;
3814 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003815
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003816 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3817 sk);
3818 status = MGMT_STATUS_SUCCESS;
3819
3820done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003821 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003822 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003823
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003824 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003825
3826 return err;
3827}
3828
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003829static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3830 u16 len)
3831{
3832 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003833 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003834 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003835 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003836
3837 BT_DBG("%s", hdev->name);
3838
Szymon Jancc72d4b82012-03-16 16:02:57 +01003839 source = __le16_to_cpu(cp->source);
3840
3841 if (source > 0x0002)
3842 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3843 MGMT_STATUS_INVALID_PARAMS);
3844
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003845 hci_dev_lock(hdev);
3846
Szymon Jancc72d4b82012-03-16 16:02:57 +01003847 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003848 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3849 hdev->devid_product = __le16_to_cpu(cp->product);
3850 hdev->devid_version = __le16_to_cpu(cp->version);
3851
3852 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3853
Johan Hedberg890ea892013-03-15 17:06:52 -05003854 hci_req_init(&req, hdev);
3855 update_eir(&req);
3856 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003857
3858 hci_dev_unlock(hdev);
3859
3860 return err;
3861}
3862
Johan Hedberg4375f102013-09-25 13:26:10 +03003863static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3864{
3865 struct cmd_lookup match = { NULL, hdev };
3866
3867 if (status) {
3868 u8 mgmt_err = mgmt_status(status);
3869
3870 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3871 cmd_status_rsp, &mgmt_err);
3872 return;
3873 }
3874
3875 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3876 &match);
3877
3878 new_settings(hdev, match.sk);
3879
3880 if (match.sk)
3881 sock_put(match.sk);
3882}
3883
Marcel Holtmann21b51872013-10-10 09:47:53 -07003884static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3885 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003886{
3887 struct mgmt_mode *cp = data;
3888 struct pending_cmd *cmd;
3889 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003890 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003891 int err;
3892
3893 BT_DBG("request for %s", hdev->name);
3894
Johan Hedberge6fe7982013-10-02 15:45:22 +03003895 status = mgmt_le_support(hdev);
3896 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003897 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003898 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03003899
3900 if (cp->val != 0x00 && cp->val != 0x01)
3901 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3902 MGMT_STATUS_INVALID_PARAMS);
3903
3904 hci_dev_lock(hdev);
3905
3906 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003907 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003908
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02003909 /* The following conditions are ones which mean that we should
3910 * not do any HCI communication but directly send a mgmt
3911 * response to user space (after toggling the flag if
3912 * necessary).
3913 */
3914 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07003915 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03003916 bool changed = false;
3917
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003918 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
3919 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003920 changed = true;
3921 }
3922
3923 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
3924 if (err < 0)
3925 goto unlock;
3926
3927 if (changed)
3928 err = new_settings(hdev, sk);
3929
3930 goto unlock;
3931 }
3932
3933 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
3934 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
3935 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3936 MGMT_STATUS_BUSY);
3937 goto unlock;
3938 }
3939
3940 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
3941 if (!cmd) {
3942 err = -ENOMEM;
3943 goto unlock;
3944 }
3945
3946 hci_req_init(&req, hdev);
3947
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07003948 if (val)
3949 enable_advertising(&req);
3950 else
3951 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03003952
3953 err = hci_req_run(&req, set_advertising_complete);
3954 if (err < 0)
3955 mgmt_pending_remove(cmd);
3956
3957unlock:
3958 hci_dev_unlock(hdev);
3959 return err;
3960}
3961
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003962static int set_static_address(struct sock *sk, struct hci_dev *hdev,
3963 void *data, u16 len)
3964{
3965 struct mgmt_cp_set_static_address *cp = data;
3966 int err;
3967
3968 BT_DBG("%s", hdev->name);
3969
Marcel Holtmann62af4442013-10-02 22:10:32 -07003970 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003971 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07003972 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003973
3974 if (hdev_is_powered(hdev))
3975 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
3976 MGMT_STATUS_REJECTED);
3977
3978 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
3979 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
3980 return cmd_status(sk, hdev->id,
3981 MGMT_OP_SET_STATIC_ADDRESS,
3982 MGMT_STATUS_INVALID_PARAMS);
3983
3984 /* Two most significant bits shall be set */
3985 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
3986 return cmd_status(sk, hdev->id,
3987 MGMT_OP_SET_STATIC_ADDRESS,
3988 MGMT_STATUS_INVALID_PARAMS);
3989 }
3990
3991 hci_dev_lock(hdev);
3992
3993 bacpy(&hdev->static_addr, &cp->bdaddr);
3994
3995 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
3996
3997 hci_dev_unlock(hdev);
3998
3999 return err;
4000}
4001
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004002static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4003 void *data, u16 len)
4004{
4005 struct mgmt_cp_set_scan_params *cp = data;
4006 __u16 interval, window;
4007 int err;
4008
4009 BT_DBG("%s", hdev->name);
4010
4011 if (!lmp_le_capable(hdev))
4012 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4013 MGMT_STATUS_NOT_SUPPORTED);
4014
4015 interval = __le16_to_cpu(cp->interval);
4016
4017 if (interval < 0x0004 || interval > 0x4000)
4018 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4019 MGMT_STATUS_INVALID_PARAMS);
4020
4021 window = __le16_to_cpu(cp->window);
4022
4023 if (window < 0x0004 || window > 0x4000)
4024 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4025 MGMT_STATUS_INVALID_PARAMS);
4026
Marcel Holtmann899e1072013-10-14 09:55:32 -07004027 if (window > interval)
4028 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4029 MGMT_STATUS_INVALID_PARAMS);
4030
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004031 hci_dev_lock(hdev);
4032
4033 hdev->le_scan_interval = interval;
4034 hdev->le_scan_window = window;
4035
4036 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4037
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004038 /* If background scan is running, restart it so new parameters are
4039 * loaded.
4040 */
4041 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4042 hdev->discovery.state == DISCOVERY_STOPPED) {
4043 struct hci_request req;
4044
4045 hci_req_init(&req, hdev);
4046
4047 hci_req_add_le_scan_disable(&req);
4048 hci_req_add_le_passive_scan(&req);
4049
4050 hci_req_run(&req, NULL);
4051 }
4052
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004053 hci_dev_unlock(hdev);
4054
4055 return err;
4056}
4057
Johan Hedberg33e38b32013-03-15 17:07:05 -05004058static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4059{
4060 struct pending_cmd *cmd;
4061
4062 BT_DBG("status 0x%02x", status);
4063
4064 hci_dev_lock(hdev);
4065
4066 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4067 if (!cmd)
4068 goto unlock;
4069
4070 if (status) {
4071 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4072 mgmt_status(status));
4073 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004074 struct mgmt_mode *cp = cmd->param;
4075
4076 if (cp->val)
4077 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4078 else
4079 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4080
Johan Hedberg33e38b32013-03-15 17:07:05 -05004081 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4082 new_settings(hdev, cmd->sk);
4083 }
4084
4085 mgmt_pending_remove(cmd);
4086
4087unlock:
4088 hci_dev_unlock(hdev);
4089}
4090
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004091static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004092 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004093{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004094 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004095 struct pending_cmd *cmd;
4096 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004097 int err;
4098
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004099 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004100
Johan Hedberg56f87902013-10-02 13:43:13 +03004101 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4102 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004103 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4104 MGMT_STATUS_NOT_SUPPORTED);
4105
Johan Hedberga7e80f22013-01-09 16:05:19 +02004106 if (cp->val != 0x00 && cp->val != 0x01)
4107 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4108 MGMT_STATUS_INVALID_PARAMS);
4109
Johan Hedberg5400c042012-02-21 16:40:33 +02004110 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004111 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004112 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004113
4114 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004115 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004116 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004117
4118 hci_dev_lock(hdev);
4119
Johan Hedberg05cbf292013-03-15 17:07:07 -05004120 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4121 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4122 MGMT_STATUS_BUSY);
4123 goto unlock;
4124 }
4125
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004126 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4127 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4128 hdev);
4129 goto unlock;
4130 }
4131
Johan Hedberg33e38b32013-03-15 17:07:05 -05004132 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4133 data, len);
4134 if (!cmd) {
4135 err = -ENOMEM;
4136 goto unlock;
4137 }
4138
4139 hci_req_init(&req, hdev);
4140
Johan Hedberg406d7802013-03-15 17:07:09 -05004141 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004142
4143 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004144 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004145 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004146 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004147 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004148 }
4149
Johan Hedberg33e38b32013-03-15 17:07:05 -05004150unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004151 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004152
Antti Julkuf6422ec2011-06-22 13:11:56 +03004153 return err;
4154}
4155
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004156static void set_bredr_scan(struct hci_request *req)
4157{
4158 struct hci_dev *hdev = req->hdev;
4159 u8 scan = 0;
4160
4161 /* Ensure that fast connectable is disabled. This function will
4162 * not do anything if the page scan parameters are already what
4163 * they should be.
4164 */
4165 write_fast_connectable(req, false);
4166
4167 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4168 scan |= SCAN_PAGE;
4169 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4170 scan |= SCAN_INQUIRY;
4171
4172 if (scan)
4173 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4174}
4175
Johan Hedberg0663ca22013-10-02 13:43:14 +03004176static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4177{
4178 struct pending_cmd *cmd;
4179
4180 BT_DBG("status 0x%02x", status);
4181
4182 hci_dev_lock(hdev);
4183
4184 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4185 if (!cmd)
4186 goto unlock;
4187
4188 if (status) {
4189 u8 mgmt_err = mgmt_status(status);
4190
4191 /* We need to restore the flag if related HCI commands
4192 * failed.
4193 */
4194 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4195
4196 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4197 } else {
4198 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4199 new_settings(hdev, cmd->sk);
4200 }
4201
4202 mgmt_pending_remove(cmd);
4203
4204unlock:
4205 hci_dev_unlock(hdev);
4206}
4207
4208static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4209{
4210 struct mgmt_mode *cp = data;
4211 struct pending_cmd *cmd;
4212 struct hci_request req;
4213 int err;
4214
4215 BT_DBG("request for %s", hdev->name);
4216
4217 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4218 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4219 MGMT_STATUS_NOT_SUPPORTED);
4220
4221 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4222 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4223 MGMT_STATUS_REJECTED);
4224
4225 if (cp->val != 0x00 && cp->val != 0x01)
4226 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4227 MGMT_STATUS_INVALID_PARAMS);
4228
4229 hci_dev_lock(hdev);
4230
4231 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4232 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4233 goto unlock;
4234 }
4235
4236 if (!hdev_is_powered(hdev)) {
4237 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004238 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4239 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4240 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4241 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4242 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4243 }
4244
4245 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4246
4247 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4248 if (err < 0)
4249 goto unlock;
4250
4251 err = new_settings(hdev, sk);
4252 goto unlock;
4253 }
4254
4255 /* Reject disabling when powered on */
4256 if (!cp->val) {
4257 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4258 MGMT_STATUS_REJECTED);
4259 goto unlock;
4260 }
4261
4262 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4263 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4264 MGMT_STATUS_BUSY);
4265 goto unlock;
4266 }
4267
4268 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4269 if (!cmd) {
4270 err = -ENOMEM;
4271 goto unlock;
4272 }
4273
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004274 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004275 * generates the correct flags.
4276 */
4277 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4278
4279 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004280
4281 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4282 set_bredr_scan(&req);
4283
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004284 /* Since only the advertising data flags will change, there
4285 * is no need to update the scan response data.
4286 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004287 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004288
Johan Hedberg0663ca22013-10-02 13:43:14 +03004289 err = hci_req_run(&req, set_bredr_complete);
4290 if (err < 0)
4291 mgmt_pending_remove(cmd);
4292
4293unlock:
4294 hci_dev_unlock(hdev);
4295 return err;
4296}
4297
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004298static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4299 void *data, u16 len)
4300{
4301 struct mgmt_mode *cp = data;
4302 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004303 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004304 int err;
4305
4306 BT_DBG("request for %s", hdev->name);
4307
4308 status = mgmt_bredr_support(hdev);
4309 if (status)
4310 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4311 status);
4312
Marcel Holtmann5afeac12014-01-10 02:07:27 -08004313 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004314 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004315 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4316 MGMT_STATUS_NOT_SUPPORTED);
4317
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004318 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004319 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4320 MGMT_STATUS_INVALID_PARAMS);
4321
4322 hci_dev_lock(hdev);
4323
4324 if (!hdev_is_powered(hdev)) {
4325 bool changed;
4326
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004327 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004328 changed = !test_and_set_bit(HCI_SC_ENABLED,
4329 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004330 if (cp->val == 0x02)
4331 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4332 else
4333 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4334 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004335 changed = test_and_clear_bit(HCI_SC_ENABLED,
4336 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004337 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4338 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004339
4340 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4341 if (err < 0)
4342 goto failed;
4343
4344 if (changed)
4345 err = new_settings(hdev, sk);
4346
4347 goto failed;
4348 }
4349
4350 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4351 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4352 MGMT_STATUS_BUSY);
4353 goto failed;
4354 }
4355
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004356 val = !!cp->val;
4357
4358 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4359 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004360 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4361 goto failed;
4362 }
4363
4364 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4365 if (!cmd) {
4366 err = -ENOMEM;
4367 goto failed;
4368 }
4369
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004370 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004371 if (err < 0) {
4372 mgmt_pending_remove(cmd);
4373 goto failed;
4374 }
4375
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004376 if (cp->val == 0x02)
4377 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4378 else
4379 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4380
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004381failed:
4382 hci_dev_unlock(hdev);
4383 return err;
4384}
4385
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004386static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4387 void *data, u16 len)
4388{
4389 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004390 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004391 int err;
4392
4393 BT_DBG("request for %s", hdev->name);
4394
Johan Hedbergb97109792014-06-24 14:00:28 +03004395 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004396 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4397 MGMT_STATUS_INVALID_PARAMS);
4398
4399 hci_dev_lock(hdev);
4400
4401 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004402 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4403 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004404 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004405 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4406 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004407
Johan Hedbergb97109792014-06-24 14:00:28 +03004408 if (cp->val == 0x02)
4409 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4410 &hdev->dev_flags);
4411 else
4412 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4413 &hdev->dev_flags);
4414
4415 if (hdev_is_powered(hdev) && use_changed &&
4416 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4417 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4418 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4419 sizeof(mode), &mode);
4420 }
4421
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004422 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4423 if (err < 0)
4424 goto unlock;
4425
4426 if (changed)
4427 err = new_settings(hdev, sk);
4428
4429unlock:
4430 hci_dev_unlock(hdev);
4431 return err;
4432}
4433
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004434static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4435 u16 len)
4436{
4437 struct mgmt_cp_set_privacy *cp = cp_data;
4438 bool changed;
4439 int err;
4440
4441 BT_DBG("request for %s", hdev->name);
4442
4443 if (!lmp_le_capable(hdev))
4444 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4445 MGMT_STATUS_NOT_SUPPORTED);
4446
4447 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4448 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4449 MGMT_STATUS_INVALID_PARAMS);
4450
4451 if (hdev_is_powered(hdev))
4452 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4453 MGMT_STATUS_REJECTED);
4454
4455 hci_dev_lock(hdev);
4456
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004457 /* If user space supports this command it is also expected to
4458 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4459 */
4460 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4461
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004462 if (cp->privacy) {
4463 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4464 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4465 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4466 } else {
4467 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4468 memset(hdev->irk, 0, sizeof(hdev->irk));
4469 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4470 }
4471
4472 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4473 if (err < 0)
4474 goto unlock;
4475
4476 if (changed)
4477 err = new_settings(hdev, sk);
4478
4479unlock:
4480 hci_dev_unlock(hdev);
4481 return err;
4482}
4483
Johan Hedberg41edf162014-02-18 10:19:35 +02004484static bool irk_is_valid(struct mgmt_irk_info *irk)
4485{
4486 switch (irk->addr.type) {
4487 case BDADDR_LE_PUBLIC:
4488 return true;
4489
4490 case BDADDR_LE_RANDOM:
4491 /* Two most significant bits shall be set */
4492 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4493 return false;
4494 return true;
4495 }
4496
4497 return false;
4498}
4499
4500static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4501 u16 len)
4502{
4503 struct mgmt_cp_load_irks *cp = cp_data;
4504 u16 irk_count, expected_len;
4505 int i, err;
4506
4507 BT_DBG("request for %s", hdev->name);
4508
4509 if (!lmp_le_capable(hdev))
4510 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4511 MGMT_STATUS_NOT_SUPPORTED);
4512
4513 irk_count = __le16_to_cpu(cp->irk_count);
4514
4515 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4516 if (expected_len != len) {
4517 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004518 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004519 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4520 MGMT_STATUS_INVALID_PARAMS);
4521 }
4522
4523 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4524
4525 for (i = 0; i < irk_count; i++) {
4526 struct mgmt_irk_info *key = &cp->irks[i];
4527
4528 if (!irk_is_valid(key))
4529 return cmd_status(sk, hdev->id,
4530 MGMT_OP_LOAD_IRKS,
4531 MGMT_STATUS_INVALID_PARAMS);
4532 }
4533
4534 hci_dev_lock(hdev);
4535
4536 hci_smp_irks_clear(hdev);
4537
4538 for (i = 0; i < irk_count; i++) {
4539 struct mgmt_irk_info *irk = &cp->irks[i];
4540 u8 addr_type;
4541
4542 if (irk->addr.type == BDADDR_LE_PUBLIC)
4543 addr_type = ADDR_LE_DEV_PUBLIC;
4544 else
4545 addr_type = ADDR_LE_DEV_RANDOM;
4546
4547 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4548 BDADDR_ANY);
4549 }
4550
4551 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4552
4553 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4554
4555 hci_dev_unlock(hdev);
4556
4557 return err;
4558}
4559
Johan Hedberg3f706b72013-01-20 14:27:16 +02004560static bool ltk_is_valid(struct mgmt_ltk_info *key)
4561{
4562 if (key->master != 0x00 && key->master != 0x01)
4563 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004564
4565 switch (key->addr.type) {
4566 case BDADDR_LE_PUBLIC:
4567 return true;
4568
4569 case BDADDR_LE_RANDOM:
4570 /* Two most significant bits shall be set */
4571 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4572 return false;
4573 return true;
4574 }
4575
4576 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004577}
4578
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004579static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004580 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004581{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004582 struct mgmt_cp_load_long_term_keys *cp = cp_data;
4583 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004584 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004585
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004586 BT_DBG("request for %s", hdev->name);
4587
4588 if (!lmp_le_capable(hdev))
4589 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4590 MGMT_STATUS_NOT_SUPPORTED);
4591
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004592 key_count = __le16_to_cpu(cp->key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004593
4594 expected_len = sizeof(*cp) + key_count *
4595 sizeof(struct mgmt_ltk_info);
4596 if (expected_len != len) {
4597 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004598 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004599 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004600 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004601 }
4602
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004603 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004604
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004605 for (i = 0; i < key_count; i++) {
4606 struct mgmt_ltk_info *key = &cp->keys[i];
4607
Johan Hedberg3f706b72013-01-20 14:27:16 +02004608 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004609 return cmd_status(sk, hdev->id,
4610 MGMT_OP_LOAD_LONG_TERM_KEYS,
4611 MGMT_STATUS_INVALID_PARAMS);
4612 }
4613
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004614 hci_dev_lock(hdev);
4615
4616 hci_smp_ltks_clear(hdev);
4617
4618 for (i = 0; i < key_count; i++) {
4619 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004620 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004621
4622 if (key->addr.type == BDADDR_LE_PUBLIC)
4623 addr_type = ADDR_LE_DEV_PUBLIC;
4624 else
4625 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004626
4627 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004628 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004629 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004630 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004631
Johan Hedberg61b43352014-05-29 19:36:53 +03004632 switch (key->type) {
4633 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004634 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004635 break;
4636 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004637 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004638 break;
4639 default:
4640 continue;
4641 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004642
Johan Hedberg35d70272014-02-19 14:57:47 +02004643 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004644 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004645 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004646 }
4647
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004648 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4649 NULL, 0);
4650
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004651 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004652
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004653 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004654}
4655
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004656struct cmd_conn_lookup {
4657 struct hci_conn *conn;
4658 bool valid_tx_power;
4659 u8 mgmt_status;
4660};
4661
4662static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4663{
4664 struct cmd_conn_lookup *match = data;
4665 struct mgmt_cp_get_conn_info *cp;
4666 struct mgmt_rp_get_conn_info rp;
4667 struct hci_conn *conn = cmd->user_data;
4668
4669 if (conn != match->conn)
4670 return;
4671
4672 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4673
4674 memset(&rp, 0, sizeof(rp));
4675 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4676 rp.addr.type = cp->addr.type;
4677
4678 if (!match->mgmt_status) {
4679 rp.rssi = conn->rssi;
4680
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004681 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004682 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004683 rp.max_tx_power = conn->max_tx_power;
4684 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004685 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004686 rp.max_tx_power = HCI_TX_POWER_INVALID;
4687 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004688 }
4689
4690 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4691 match->mgmt_status, &rp, sizeof(rp));
4692
4693 hci_conn_drop(conn);
4694
4695 mgmt_pending_remove(cmd);
4696}
4697
4698static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4699{
4700 struct hci_cp_read_rssi *cp;
4701 struct hci_conn *conn;
4702 struct cmd_conn_lookup match;
4703 u16 handle;
4704
4705 BT_DBG("status 0x%02x", status);
4706
4707 hci_dev_lock(hdev);
4708
4709 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004710 * otherwise we assume it's not valid. At the moment we assume that
4711 * either both or none of current and max values are valid to keep code
4712 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004713 */
4714 match.valid_tx_power = !status;
4715
4716 /* Commands sent in request are either Read RSSI or Read Transmit Power
4717 * Level so we check which one was last sent to retrieve connection
4718 * handle. Both commands have handle as first parameter so it's safe to
4719 * cast data on the same command struct.
4720 *
4721 * First command sent is always Read RSSI and we fail only if it fails.
4722 * In other case we simply override error to indicate success as we
4723 * already remembered if TX power value is actually valid.
4724 */
4725 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4726 if (!cp) {
4727 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4728 status = 0;
4729 }
4730
4731 if (!cp) {
4732 BT_ERR("invalid sent_cmd in response");
4733 goto unlock;
4734 }
4735
4736 handle = __le16_to_cpu(cp->handle);
4737 conn = hci_conn_hash_lookup_handle(hdev, handle);
4738 if (!conn) {
4739 BT_ERR("unknown handle (%d) in response", handle);
4740 goto unlock;
4741 }
4742
4743 match.conn = conn;
4744 match.mgmt_status = mgmt_status(status);
4745
4746 /* Cache refresh is complete, now reply for mgmt request for given
4747 * connection only.
4748 */
4749 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4750 get_conn_info_complete, &match);
4751
4752unlock:
4753 hci_dev_unlock(hdev);
4754}
4755
4756static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4757 u16 len)
4758{
4759 struct mgmt_cp_get_conn_info *cp = data;
4760 struct mgmt_rp_get_conn_info rp;
4761 struct hci_conn *conn;
4762 unsigned long conn_info_age;
4763 int err = 0;
4764
4765 BT_DBG("%s", hdev->name);
4766
4767 memset(&rp, 0, sizeof(rp));
4768 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4769 rp.addr.type = cp->addr.type;
4770
4771 if (!bdaddr_type_is_valid(cp->addr.type))
4772 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4773 MGMT_STATUS_INVALID_PARAMS,
4774 &rp, sizeof(rp));
4775
4776 hci_dev_lock(hdev);
4777
4778 if (!hdev_is_powered(hdev)) {
4779 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4780 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4781 goto unlock;
4782 }
4783
4784 if (cp->addr.type == BDADDR_BREDR)
4785 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4786 &cp->addr.bdaddr);
4787 else
4788 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4789
4790 if (!conn || conn->state != BT_CONNECTED) {
4791 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4792 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4793 goto unlock;
4794 }
4795
4796 /* To avoid client trying to guess when to poll again for information we
4797 * calculate conn info age as random value between min/max set in hdev.
4798 */
4799 conn_info_age = hdev->conn_info_min_age +
4800 prandom_u32_max(hdev->conn_info_max_age -
4801 hdev->conn_info_min_age);
4802
4803 /* Query controller to refresh cached values if they are too old or were
4804 * never read.
4805 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004806 if (time_after(jiffies, conn->conn_info_timestamp +
4807 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004808 !conn->conn_info_timestamp) {
4809 struct hci_request req;
4810 struct hci_cp_read_tx_power req_txp_cp;
4811 struct hci_cp_read_rssi req_rssi_cp;
4812 struct pending_cmd *cmd;
4813
4814 hci_req_init(&req, hdev);
4815 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4816 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4817 &req_rssi_cp);
4818
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004819 /* For LE links TX power does not change thus we don't need to
4820 * query for it once value is known.
4821 */
4822 if (!bdaddr_type_is_le(cp->addr.type) ||
4823 conn->tx_power == HCI_TX_POWER_INVALID) {
4824 req_txp_cp.handle = cpu_to_le16(conn->handle);
4825 req_txp_cp.type = 0x00;
4826 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4827 sizeof(req_txp_cp), &req_txp_cp);
4828 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004829
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004830 /* Max TX power needs to be read only once per connection */
4831 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
4832 req_txp_cp.handle = cpu_to_le16(conn->handle);
4833 req_txp_cp.type = 0x01;
4834 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4835 sizeof(req_txp_cp), &req_txp_cp);
4836 }
4837
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004838 err = hci_req_run(&req, conn_info_refresh_complete);
4839 if (err < 0)
4840 goto unlock;
4841
4842 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
4843 data, len);
4844 if (!cmd) {
4845 err = -ENOMEM;
4846 goto unlock;
4847 }
4848
4849 hci_conn_hold(conn);
4850 cmd->user_data = conn;
4851
4852 conn->conn_info_timestamp = jiffies;
4853 } else {
4854 /* Cache is valid, just reply with values cached in hci_conn */
4855 rp.rssi = conn->rssi;
4856 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004857 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004858
4859 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4860 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
4861 }
4862
4863unlock:
4864 hci_dev_unlock(hdev);
4865 return err;
4866}
4867
Johan Hedberg95868422014-06-28 17:54:07 +03004868static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
4869{
4870 struct mgmt_cp_get_clock_info *cp;
4871 struct mgmt_rp_get_clock_info rp;
4872 struct hci_cp_read_clock *hci_cp;
4873 struct pending_cmd *cmd;
4874 struct hci_conn *conn;
4875
4876 BT_DBG("%s status %u", hdev->name, status);
4877
4878 hci_dev_lock(hdev);
4879
4880 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
4881 if (!hci_cp)
4882 goto unlock;
4883
4884 if (hci_cp->which) {
4885 u16 handle = __le16_to_cpu(hci_cp->handle);
4886 conn = hci_conn_hash_lookup_handle(hdev, handle);
4887 } else {
4888 conn = NULL;
4889 }
4890
4891 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
4892 if (!cmd)
4893 goto unlock;
4894
4895 cp = cmd->param;
4896
4897 memset(&rp, 0, sizeof(rp));
4898 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
4899
4900 if (status)
4901 goto send_rsp;
4902
4903 rp.local_clock = cpu_to_le32(hdev->clock);
4904
4905 if (conn) {
4906 rp.piconet_clock = cpu_to_le32(conn->clock);
4907 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
4908 }
4909
4910send_rsp:
4911 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
4912 &rp, sizeof(rp));
4913 mgmt_pending_remove(cmd);
4914 if (conn)
4915 hci_conn_drop(conn);
4916
4917unlock:
4918 hci_dev_unlock(hdev);
4919}
4920
4921static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
4922 u16 len)
4923{
4924 struct mgmt_cp_get_clock_info *cp = data;
4925 struct mgmt_rp_get_clock_info rp;
4926 struct hci_cp_read_clock hci_cp;
4927 struct pending_cmd *cmd;
4928 struct hci_request req;
4929 struct hci_conn *conn;
4930 int err;
4931
4932 BT_DBG("%s", hdev->name);
4933
4934 memset(&rp, 0, sizeof(rp));
4935 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4936 rp.addr.type = cp->addr.type;
4937
4938 if (cp->addr.type != BDADDR_BREDR)
4939 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
4940 MGMT_STATUS_INVALID_PARAMS,
4941 &rp, sizeof(rp));
4942
4943 hci_dev_lock(hdev);
4944
4945 if (!hdev_is_powered(hdev)) {
4946 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
4947 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4948 goto unlock;
4949 }
4950
4951 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
4952 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4953 &cp->addr.bdaddr);
4954 if (!conn || conn->state != BT_CONNECTED) {
4955 err = cmd_complete(sk, hdev->id,
4956 MGMT_OP_GET_CLOCK_INFO,
4957 MGMT_STATUS_NOT_CONNECTED,
4958 &rp, sizeof(rp));
4959 goto unlock;
4960 }
4961 } else {
4962 conn = NULL;
4963 }
4964
4965 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
4966 if (!cmd) {
4967 err = -ENOMEM;
4968 goto unlock;
4969 }
4970
4971 hci_req_init(&req, hdev);
4972
4973 memset(&hci_cp, 0, sizeof(hci_cp));
4974 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
4975
4976 if (conn) {
4977 hci_conn_hold(conn);
4978 cmd->user_data = conn;
4979
4980 hci_cp.handle = cpu_to_le16(conn->handle);
4981 hci_cp.which = 0x01; /* Piconet clock */
4982 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
4983 }
4984
4985 err = hci_req_run(&req, get_clock_info_complete);
4986 if (err < 0)
4987 mgmt_pending_remove(cmd);
4988
4989unlock:
4990 hci_dev_unlock(hdev);
4991 return err;
4992}
4993
Marcel Holtmann8afef092014-06-29 22:28:34 +02004994static void device_added(struct sock *sk, struct hci_dev *hdev,
4995 bdaddr_t *bdaddr, u8 type, u8 action)
4996{
4997 struct mgmt_ev_device_added ev;
4998
4999 bacpy(&ev.addr.bdaddr, bdaddr);
5000 ev.addr.type = type;
5001 ev.action = action;
5002
5003 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5004}
5005
Marcel Holtmann2faade52014-06-29 19:44:03 +02005006static int add_device(struct sock *sk, struct hci_dev *hdev,
5007 void *data, u16 len)
5008{
5009 struct mgmt_cp_add_device *cp = data;
5010 u8 auto_conn, addr_type;
5011 int err;
5012
5013 BT_DBG("%s", hdev->name);
5014
5015 if (!bdaddr_type_is_le(cp->addr.type) ||
5016 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5017 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5018 MGMT_STATUS_INVALID_PARAMS,
5019 &cp->addr, sizeof(cp->addr));
5020
5021 if (cp->action != 0x00 && cp->action != 0x01)
5022 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5023 MGMT_STATUS_INVALID_PARAMS,
5024 &cp->addr, sizeof(cp->addr));
5025
5026 hci_dev_lock(hdev);
5027
5028 if (cp->addr.type == BDADDR_LE_PUBLIC)
5029 addr_type = ADDR_LE_DEV_PUBLIC;
5030 else
5031 addr_type = ADDR_LE_DEV_RANDOM;
5032
5033 if (cp->action)
5034 auto_conn = HCI_AUTO_CONN_ALWAYS;
5035 else
5036 auto_conn = HCI_AUTO_CONN_DISABLED;
5037
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005038 /* If the connection parameters don't exist for this device,
5039 * they will be created and configured with defaults.
5040 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005041 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5042 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005043 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5044 MGMT_STATUS_FAILED,
5045 &cp->addr, sizeof(cp->addr));
5046 goto unlock;
5047 }
5048
Marcel Holtmann8afef092014-06-29 22:28:34 +02005049 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5050
Marcel Holtmann2faade52014-06-29 19:44:03 +02005051 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5052 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5053
5054unlock:
5055 hci_dev_unlock(hdev);
5056 return err;
5057}
5058
Marcel Holtmann8afef092014-06-29 22:28:34 +02005059static void device_removed(struct sock *sk, struct hci_dev *hdev,
5060 bdaddr_t *bdaddr, u8 type)
5061{
5062 struct mgmt_ev_device_removed ev;
5063
5064 bacpy(&ev.addr.bdaddr, bdaddr);
5065 ev.addr.type = type;
5066
5067 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5068}
5069
Marcel Holtmann2faade52014-06-29 19:44:03 +02005070static int remove_device(struct sock *sk, struct hci_dev *hdev,
5071 void *data, u16 len)
5072{
5073 struct mgmt_cp_remove_device *cp = data;
5074 int err;
5075
5076 BT_DBG("%s", hdev->name);
5077
5078 hci_dev_lock(hdev);
5079
5080 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5081 u8 addr_type;
5082
5083 if (!bdaddr_type_is_le(cp->addr.type)) {
5084 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5085 MGMT_STATUS_INVALID_PARAMS,
5086 &cp->addr, sizeof(cp->addr));
5087 goto unlock;
5088 }
5089
5090 if (cp->addr.type == BDADDR_LE_PUBLIC)
5091 addr_type = ADDR_LE_DEV_PUBLIC;
5092 else
5093 addr_type = ADDR_LE_DEV_RANDOM;
5094
5095 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005096
5097 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005098 } else {
5099 if (cp->addr.type) {
5100 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5101 MGMT_STATUS_INVALID_PARAMS,
5102 &cp->addr, sizeof(cp->addr));
5103 goto unlock;
5104 }
5105
5106 hci_conn_params_clear(hdev);
5107 }
5108
5109 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5110 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5111
5112unlock:
5113 hci_dev_unlock(hdev);
5114 return err;
5115}
5116
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005117static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005118 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5119 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005120 bool var_len;
5121 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005122} mgmt_handlers[] = {
5123 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005124 { read_version, false, MGMT_READ_VERSION_SIZE },
5125 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5126 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5127 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5128 { set_powered, false, MGMT_SETTING_SIZE },
5129 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5130 { set_connectable, false, MGMT_SETTING_SIZE },
5131 { set_fast_connectable, false, MGMT_SETTING_SIZE },
5132 { set_pairable, false, MGMT_SETTING_SIZE },
5133 { set_link_security, false, MGMT_SETTING_SIZE },
5134 { set_ssp, false, MGMT_SETTING_SIZE },
5135 { set_hs, false, MGMT_SETTING_SIZE },
5136 { set_le, false, MGMT_SETTING_SIZE },
5137 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5138 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5139 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5140 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5141 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5142 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5143 { disconnect, false, MGMT_DISCONNECT_SIZE },
5144 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5145 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5146 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5147 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5148 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5149 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5150 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5151 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5152 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5153 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5154 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5155 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005156 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005157 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5158 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5159 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5160 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5161 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5162 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005163 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005164 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005165 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005166 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005167 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005168 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005169 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005170 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005171 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005172 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005173 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005174 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5175 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005176};
5177
Johan Hedberg03811012010-12-08 00:21:06 +02005178int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5179{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005180 void *buf;
5181 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005182 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005183 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005184 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005185 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005186 int err;
5187
5188 BT_DBG("got %zu bytes", msglen);
5189
5190 if (msglen < sizeof(*hdr))
5191 return -EINVAL;
5192
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005193 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005194 if (!buf)
5195 return -ENOMEM;
5196
5197 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5198 err = -EFAULT;
5199 goto done;
5200 }
5201
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005202 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005203 opcode = __le16_to_cpu(hdr->opcode);
5204 index = __le16_to_cpu(hdr->index);
5205 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005206
5207 if (len != msglen - sizeof(*hdr)) {
5208 err = -EINVAL;
5209 goto done;
5210 }
5211
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005212 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005213 hdev = hci_dev_get(index);
5214 if (!hdev) {
5215 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005216 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005217 goto done;
5218 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005219
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005220 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannfee746b2014-06-29 12:13:05 +02005221 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) ||
5222 test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005223 err = cmd_status(sk, index, opcode,
5224 MGMT_STATUS_INVALID_INDEX);
5225 goto done;
5226 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005227 }
5228
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005229 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005230 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005231 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005232 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005233 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005234 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005235 }
5236
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005237 if ((hdev && opcode < MGMT_OP_READ_INFO) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005238 (!hdev && opcode >= MGMT_OP_READ_INFO)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005239 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005240 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005241 goto done;
5242 }
5243
Johan Hedbergbe22b542012-03-01 22:24:41 +02005244 handler = &mgmt_handlers[opcode];
5245
5246 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005247 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005248 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005249 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005250 goto done;
5251 }
5252
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005253 if (hdev)
5254 mgmt_init_hdev(sk, hdev);
5255
5256 cp = buf + sizeof(*hdr);
5257
Johan Hedbergbe22b542012-03-01 22:24:41 +02005258 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005259 if (err < 0)
5260 goto done;
5261
Johan Hedberg03811012010-12-08 00:21:06 +02005262 err = msglen;
5263
5264done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005265 if (hdev)
5266 hci_dev_put(hdev);
5267
Johan Hedberg03811012010-12-08 00:21:06 +02005268 kfree(buf);
5269 return err;
5270}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005271
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005272void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +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
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005277 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005278}
5279
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005280void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005281{
Johan Hedberg5f159032012-03-02 03:13:19 +02005282 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005283
Marcel Holtmann1514b892013-10-06 08:25:01 -07005284 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005285 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005286
Johan Hedberg744cf192011-11-08 20:40:14 +02005287 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005288
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005289 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005290}
5291
Andre Guedes6046dc32014-02-26 20:21:51 -03005292/* This function requires the caller holds hdev->lock */
5293static void restart_le_auto_conns(struct hci_dev *hdev)
5294{
5295 struct hci_conn_params *p;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005296 bool added = false;
Andre Guedes6046dc32014-02-26 20:21:51 -03005297
5298 list_for_each_entry(p, &hdev->le_conn_params, list) {
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005299 if (p->auto_connect == HCI_AUTO_CONN_ALWAYS) {
Andre Guedes6046dc32014-02-26 20:21:51 -03005300 hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005301 added = true;
5302 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005303 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005304
5305 /* Calling hci_pend_le_conn_add will actually already trigger
5306 * background scanning when needed. So no need to trigger it
5307 * just another time.
5308 *
5309 * This check is here to avoid an unneeded restart of the
5310 * passive scanning. Since this is during the controller
5311 * power up phase the duplicate filtering is not an issue.
5312 */
5313 if (added)
5314 return;
5315
5316 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005317}
5318
Johan Hedberg229ab392013-03-15 17:06:53 -05005319static void powered_complete(struct hci_dev *hdev, u8 status)
5320{
5321 struct cmd_lookup match = { NULL, hdev };
5322
5323 BT_DBG("status 0x%02x", status);
5324
5325 hci_dev_lock(hdev);
5326
Andre Guedes6046dc32014-02-26 20:21:51 -03005327 restart_le_auto_conns(hdev);
5328
Johan Hedberg229ab392013-03-15 17:06:53 -05005329 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5330
5331 new_settings(hdev, match.sk);
5332
5333 hci_dev_unlock(hdev);
5334
5335 if (match.sk)
5336 sock_put(match.sk);
5337}
5338
Johan Hedberg70da6242013-03-15 17:06:51 -05005339static int powered_update_hci(struct hci_dev *hdev)
5340{
Johan Hedberg890ea892013-03-15 17:06:52 -05005341 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005342 u8 link_sec;
5343
Johan Hedberg890ea892013-03-15 17:06:52 -05005344 hci_req_init(&req, hdev);
5345
Johan Hedberg70da6242013-03-15 17:06:51 -05005346 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5347 !lmp_host_ssp_capable(hdev)) {
5348 u8 ssp = 1;
5349
Johan Hedberg890ea892013-03-15 17:06:52 -05005350 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005351 }
5352
Johan Hedbergc73eee92013-04-19 18:35:21 +03005353 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5354 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005355 struct hci_cp_write_le_host_supported cp;
5356
5357 cp.le = 1;
5358 cp.simul = lmp_le_br_capable(hdev);
5359
5360 /* Check first if we already have the right
5361 * host state (host features set)
5362 */
5363 if (cp.le != lmp_host_le_capable(hdev) ||
5364 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005365 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5366 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005367 }
5368
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005369 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005370 /* Make sure the controller has a good default for
5371 * advertising data. This also applies to the case
5372 * where BR/EDR was toggled during the AUTO_OFF phase.
5373 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005374 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005375 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005376 update_scan_rsp_data(&req);
5377 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005378
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005379 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5380 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005381 }
5382
Johan Hedberg70da6242013-03-15 17:06:51 -05005383 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5384 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005385 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5386 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005387
5388 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005389 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5390 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005391 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005392 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005393 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005394 }
5395
Johan Hedberg229ab392013-03-15 17:06:53 -05005396 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005397}
5398
Johan Hedberg744cf192011-11-08 20:40:14 +02005399int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005400{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005401 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005402 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5403 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005404 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005405
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005406 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5407 return 0;
5408
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005409 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005410 if (powered_update_hci(hdev) == 0)
5411 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005412
Johan Hedberg229ab392013-03-15 17:06:53 -05005413 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5414 &match);
5415 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005416 }
5417
Johan Hedberg229ab392013-03-15 17:06:53 -05005418 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5419 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5420
5421 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5422 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5423 zero_cod, sizeof(zero_cod), NULL);
5424
5425new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005426 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005427
5428 if (match.sk)
5429 sock_put(match.sk);
5430
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005431 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005432}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005433
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005434void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005435{
5436 struct pending_cmd *cmd;
5437 u8 status;
5438
5439 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5440 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005441 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005442
5443 if (err == -ERFKILL)
5444 status = MGMT_STATUS_RFKILLED;
5445 else
5446 status = MGMT_STATUS_FAILED;
5447
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005448 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005449
5450 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005451}
5452
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005453void mgmt_discoverable_timeout(struct hci_dev *hdev)
5454{
5455 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005456
5457 hci_dev_lock(hdev);
5458
5459 /* When discoverable timeout triggers, then just make sure
5460 * the limited discoverable flag is cleared. Even in the case
5461 * of a timeout triggered from general discoverable, it is
5462 * safe to unconditionally clear the flag.
5463 */
5464 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005465 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005466
5467 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005468 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5469 u8 scan = SCAN_PAGE;
5470 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5471 sizeof(scan), &scan);
5472 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005473 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005474 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005475 hci_req_run(&req, NULL);
5476
5477 hdev->discov_timeout = 0;
5478
Johan Hedberg9a43e252013-10-20 19:00:07 +03005479 new_settings(hdev, NULL);
5480
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005481 hci_dev_unlock(hdev);
5482}
5483
Marcel Holtmann86a75642013-10-15 06:33:54 -07005484void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005485{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005486 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005487
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005488 /* Nothing needed here if there's a pending command since that
5489 * commands request completion callback takes care of everything
5490 * necessary.
5491 */
5492 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005493 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005494
Johan Hedbergbd107992014-02-24 14:52:19 +02005495 /* Powering off may clear the scan mode - don't let that interfere */
5496 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5497 return;
5498
Johan Hedberg9a43e252013-10-20 19:00:07 +03005499 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005500 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005501 } else {
5502 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005503 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005504 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005505
Johan Hedberg9a43e252013-10-20 19:00:07 +03005506 if (changed) {
5507 struct hci_request req;
5508
5509 /* In case this change in discoverable was triggered by
5510 * a disabling of connectable there could be a need to
5511 * update the advertising flags.
5512 */
5513 hci_req_init(&req, hdev);
5514 update_adv_data(&req);
5515 hci_req_run(&req, NULL);
5516
Marcel Holtmann86a75642013-10-15 06:33:54 -07005517 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005518 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005519}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005520
Marcel Holtmanna3309162013-10-15 06:33:55 -07005521void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005522{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005523 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005524
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005525 /* Nothing needed here if there's a pending command since that
5526 * commands request completion callback takes care of everything
5527 * necessary.
5528 */
5529 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005530 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005531
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005532 /* Powering off may clear the scan mode - don't let that interfere */
5533 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5534 return;
5535
Marcel Holtmanna3309162013-10-15 06:33:55 -07005536 if (connectable)
5537 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5538 else
5539 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005540
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005541 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005542 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005543}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005544
Johan Hedberg778b2352014-02-24 14:52:17 +02005545void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5546{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005547 /* Powering off may stop advertising - don't let that interfere */
5548 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5549 return;
5550
Johan Hedberg778b2352014-02-24 14:52:17 +02005551 if (advertising)
5552 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5553 else
5554 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5555}
5556
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005557void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005558{
Johan Hedbergca69b792011-11-11 18:10:00 +02005559 u8 mgmt_err = mgmt_status(status);
5560
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005561 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005562 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005563 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005564
5565 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005566 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005567 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005568}
5569
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005570void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5571 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005572{
Johan Hedberg86742e12011-11-07 23:13:38 +02005573 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005574
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005575 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005576
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005577 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02005578 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005579 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005580 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005581 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005582 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005583
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005584 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005585}
Johan Hedbergf7520542011-01-20 12:34:39 +02005586
Johan Hedbergd7b25452014-05-23 13:19:53 +03005587static u8 mgmt_ltk_type(struct smp_ltk *ltk)
5588{
5589 if (ltk->authenticated)
5590 return MGMT_LTK_AUTHENTICATED;
5591
5592 return MGMT_LTK_UNAUTHENTICATED;
5593}
5594
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005595void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005596{
5597 struct mgmt_ev_new_long_term_key ev;
5598
5599 memset(&ev, 0, sizeof(ev));
5600
Marcel Holtmann5192d302014-02-19 17:11:58 -08005601 /* Devices using resolvable or non-resolvable random addresses
5602 * without providing an indentity resolving key don't require
5603 * to store long term keys. Their addresses will change the
5604 * next time around.
5605 *
5606 * Only when a remote device provides an identity address
5607 * make sure the long term key is stored. If the remote
5608 * identity is known, the long term keys are internally
5609 * mapped to the identity address. So allow static random
5610 * and public addresses here.
5611 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005612 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5613 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5614 ev.store_hint = 0x00;
5615 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005616 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02005617
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005618 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005619 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03005620 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005621 ev.key.enc_size = key->enc_size;
5622 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005623 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005624
Johan Hedberg2ceba532014-06-16 19:25:16 +03005625 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005626 ev.key.master = 1;
5627
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005628 memcpy(ev.key.val, key->val, sizeof(key->val));
5629
Marcel Holtmann083368f2013-10-15 14:26:29 -07005630 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005631}
5632
Johan Hedberg95fbac82014-02-19 15:18:31 +02005633void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5634{
5635 struct mgmt_ev_new_irk ev;
5636
5637 memset(&ev, 0, sizeof(ev));
5638
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005639 /* For identity resolving keys from devices that are already
5640 * using a public address or static random address, do not
5641 * ask for storing this key. The identity resolving key really
5642 * is only mandatory for devices using resovlable random
5643 * addresses.
5644 *
5645 * Storing all identity resolving keys has the downside that
5646 * they will be also loaded on next boot of they system. More
5647 * identity resolving keys, means more time during scanning is
5648 * needed to actually resolve these addresses.
5649 */
5650 if (bacmp(&irk->rpa, BDADDR_ANY))
5651 ev.store_hint = 0x01;
5652 else
5653 ev.store_hint = 0x00;
5654
Johan Hedberg95fbac82014-02-19 15:18:31 +02005655 bacpy(&ev.rpa, &irk->rpa);
5656 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5657 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5658 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5659
5660 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5661}
5662
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005663void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
5664 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005665{
5666 struct mgmt_ev_new_csrk ev;
5667
5668 memset(&ev, 0, sizeof(ev));
5669
5670 /* Devices using resolvable or non-resolvable random addresses
5671 * without providing an indentity resolving key don't require
5672 * to store signature resolving keys. Their addresses will change
5673 * the next time around.
5674 *
5675 * Only when a remote device provides an identity address
5676 * make sure the signature resolving key is stored. So allow
5677 * static random and public addresses here.
5678 */
5679 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5680 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
5681 ev.store_hint = 0x00;
5682 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005683 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005684
5685 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
5686 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
5687 ev.key.master = csrk->master;
5688 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
5689
5690 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
5691}
5692
Marcel Holtmann94933992013-10-15 10:26:39 -07005693static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5694 u8 data_len)
5695{
5696 eir[eir_len++] = sizeof(type) + data_len;
5697 eir[eir_len++] = type;
5698 memcpy(&eir[eir_len], data, data_len);
5699 eir_len += data_len;
5700
5701 return eir_len;
5702}
5703
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005704void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5705 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5706 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005707{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005708 char buf[512];
5709 struct mgmt_ev_device_connected *ev = (void *) buf;
5710 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005711
Johan Hedbergb644ba32012-01-17 21:48:47 +02005712 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005713 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005714
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005715 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005716
Johan Hedbergb644ba32012-01-17 21:48:47 +02005717 if (name_len > 0)
5718 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005719 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005720
5721 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005722 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005723 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005724
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005725 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005726
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005727 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
5728 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02005729}
5730
Johan Hedberg8962ee72011-01-20 12:40:27 +02005731static void disconnect_rsp(struct pending_cmd *cmd, void *data)
5732{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01005733 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005734 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02005735 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005736
Johan Hedberg88c3df12012-02-09 14:27:38 +02005737 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5738 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005739
Johan Hedbergaee9b212012-02-18 15:07:59 +02005740 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005741 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005742
5743 *sk = cmd->sk;
5744 sock_hold(*sk);
5745
Johan Hedberga664b5b2011-02-19 12:06:02 -03005746 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005747}
5748
Johan Hedberg124f6e32012-02-09 13:50:12 +02005749static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02005750{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005751 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02005752 struct mgmt_cp_unpair_device *cp = cmd->param;
5753 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005754
5755 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02005756 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5757 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005758
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005759 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
5760
Johan Hedbergaee9b212012-02-18 15:07:59 +02005761 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02005762
5763 mgmt_pending_remove(cmd);
5764}
5765
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005766void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005767 u8 link_type, u8 addr_type, u8 reason,
5768 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02005769{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005770 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02005771 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005772 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005773
Johan Hedberg8b064a32014-02-24 14:52:22 +02005774 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5775 if (power_off) {
5776 struct mgmt_mode *cp = power_off->param;
5777
5778 /* The connection is still in hci_conn_hash so test for 1
5779 * instead of 0 to know if this is the last one.
5780 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005781 if (!cp->val && hci_conn_count(hdev) == 1) {
5782 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02005783 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005784 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02005785 }
5786
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005787 if (!mgmt_connected)
5788 return;
5789
Andre Guedes57eb7762013-10-30 19:01:41 -03005790 if (link_type != ACL_LINK && link_type != LE_LINK)
5791 return;
5792
Johan Hedberg744cf192011-11-08 20:40:14 +02005793 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02005794
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005795 bacpy(&ev.addr.bdaddr, bdaddr);
5796 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5797 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02005798
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005799 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005800
5801 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01005802 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005803
Johan Hedberg124f6e32012-02-09 13:50:12 +02005804 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005805 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005806}
5807
Marcel Holtmann78929242013-10-06 23:55:47 -07005808void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
5809 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02005810{
Andre Guedes3655bba2013-10-30 19:01:40 -03005811 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
5812 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02005813 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005814 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005815
Jefferson Delfes36a75f12012-09-18 13:36:54 -04005816 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
5817 hdev);
5818
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005819 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005820 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07005821 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005822
Andre Guedes3655bba2013-10-30 19:01:40 -03005823 cp = cmd->param;
5824
5825 if (bacmp(bdaddr, &cp->addr.bdaddr))
5826 return;
5827
5828 if (cp->addr.type != bdaddr_type)
5829 return;
5830
Johan Hedberg88c3df12012-02-09 14:27:38 +02005831 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03005832 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02005833
Marcel Holtmann78929242013-10-06 23:55:47 -07005834 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
5835 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005836
Johan Hedberga664b5b2011-02-19 12:06:02 -03005837 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02005838}
Johan Hedberg17d5c042011-01-22 06:09:08 +02005839
Marcel Holtmann445608d2013-10-06 23:55:48 -07005840void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5841 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02005842{
5843 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02005844 struct pending_cmd *power_off;
5845
5846 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5847 if (power_off) {
5848 struct mgmt_mode *cp = power_off->param;
5849
5850 /* The connection is still in hci_conn_hash so test for 1
5851 * instead of 0 to know if this is the last one.
5852 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005853 if (!cp->val && hci_conn_count(hdev) == 1) {
5854 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02005855 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005856 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02005857 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02005858
Johan Hedberg4c659c32011-11-07 23:13:39 +02005859 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005860 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005861 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005862
Marcel Holtmann445608d2013-10-06 23:55:48 -07005863 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005864}
Johan Hedberg980e1a52011-01-22 06:10:07 +02005865
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005866void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005867{
5868 struct mgmt_ev_pin_code_request ev;
5869
Johan Hedbergd8457692012-02-17 14:24:57 +02005870 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005871 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02005872 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005873
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005874 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005875}
5876
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005877void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5878 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005879{
5880 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005881 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005882
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005883 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005884 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005885 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005886
Johan Hedbergd8457692012-02-17 14:24:57 +02005887 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005888 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005889
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005890 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
5891 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005892
Johan Hedberga664b5b2011-02-19 12:06:02 -03005893 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005894}
5895
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005896void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5897 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005898{
5899 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005900 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005901
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005902 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005903 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005904 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005905
Johan Hedbergd8457692012-02-17 14:24:57 +02005906 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005907 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005908
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005909 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
5910 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005911
Johan Hedberga664b5b2011-02-19 12:06:02 -03005912 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005913}
Johan Hedberga5c29682011-02-19 12:05:57 -03005914
Johan Hedberg744cf192011-11-08 20:40:14 +02005915int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02005916 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005917 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03005918{
5919 struct mgmt_ev_user_confirm_request ev;
5920
Johan Hedberg744cf192011-11-08 20:40:14 +02005921 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03005922
Johan Hedberg272d90d2012-02-09 15:26:12 +02005923 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005924 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07005925 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02005926 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03005927
Johan Hedberg744cf192011-11-08 20:40:14 +02005928 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005929 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03005930}
5931
Johan Hedberg272d90d2012-02-09 15:26:12 +02005932int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005933 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08005934{
5935 struct mgmt_ev_user_passkey_request ev;
5936
5937 BT_DBG("%s", hdev->name);
5938
Johan Hedberg272d90d2012-02-09 15:26:12 +02005939 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005940 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08005941
5942 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005943 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08005944}
5945
Brian Gix0df4c182011-11-16 13:53:13 -08005946static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005947 u8 link_type, u8 addr_type, u8 status,
5948 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03005949{
5950 struct pending_cmd *cmd;
5951 struct mgmt_rp_user_confirm_reply rp;
5952 int err;
5953
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005954 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03005955 if (!cmd)
5956 return -ENOENT;
5957
Johan Hedberg272d90d2012-02-09 15:26:12 +02005958 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005959 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b212012-02-18 15:07:59 +02005960 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005961 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03005962
Johan Hedberga664b5b2011-02-19 12:06:02 -03005963 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03005964
5965 return err;
5966}
5967
Johan Hedberg744cf192011-11-08 20:40:14 +02005968int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005969 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005970{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005971 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005972 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005973}
5974
Johan Hedberg272d90d2012-02-09 15:26:12 +02005975int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005976 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005977{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005978 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005979 status,
5980 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005981}
Johan Hedberg2a611692011-02-19 12:06:00 -03005982
Brian Gix604086b2011-11-23 08:28:33 -08005983int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005984 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005985{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005986 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005987 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005988}
5989
Johan Hedberg272d90d2012-02-09 15:26:12 +02005990int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005991 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005992{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005993 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005994 status,
5995 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005996}
5997
Johan Hedberg92a25252012-09-06 18:39:26 +03005998int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
5999 u8 link_type, u8 addr_type, u32 passkey,
6000 u8 entered)
6001{
6002 struct mgmt_ev_passkey_notify ev;
6003
6004 BT_DBG("%s", hdev->name);
6005
6006 bacpy(&ev.addr.bdaddr, bdaddr);
6007 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6008 ev.passkey = __cpu_to_le32(passkey);
6009 ev.entered = entered;
6010
6011 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6012}
6013
Marcel Holtmanne5460992013-10-15 14:26:23 -07006014void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6015 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006016{
6017 struct mgmt_ev_auth_failed ev;
6018
Johan Hedbergbab73cb2012-02-09 16:07:29 +02006019 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006020 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006021 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006022
Marcel Holtmanne5460992013-10-15 14:26:23 -07006023 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03006024}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006025
Marcel Holtmann464996a2013-10-15 14:26:24 -07006026void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006027{
6028 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006029 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006030
6031 if (status) {
6032 u8 mgmt_err = mgmt_status(status);
6033 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006034 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006035 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006036 }
6037
Marcel Holtmann464996a2013-10-15 14:26:24 -07006038 if (test_bit(HCI_AUTH, &hdev->flags))
6039 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6040 &hdev->dev_flags);
6041 else
6042 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6043 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006044
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006045 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006046 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006047
Johan Hedberg47990ea2012-02-22 11:58:37 +02006048 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006049 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006050
6051 if (match.sk)
6052 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006053}
6054
Johan Hedberg890ea892013-03-15 17:06:52 -05006055static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006056{
Johan Hedberg890ea892013-03-15 17:06:52 -05006057 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006058 struct hci_cp_write_eir cp;
6059
Johan Hedberg976eb202012-10-24 21:12:01 +03006060 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006061 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006062
Johan Hedbergc80da272012-02-22 15:38:48 +02006063 memset(hdev->eir, 0, sizeof(hdev->eir));
6064
Johan Hedbergcacaf522012-02-21 00:52:42 +02006065 memset(&cp, 0, sizeof(cp));
6066
Johan Hedberg890ea892013-03-15 17:06:52 -05006067 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006068}
6069
Marcel Holtmann3e248562013-10-15 14:26:25 -07006070void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006071{
6072 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006073 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006074 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006075
6076 if (status) {
6077 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006078
6079 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006080 &hdev->dev_flags)) {
6081 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006082 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006083 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006084
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006085 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6086 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006087 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006088 }
6089
6090 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006091 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006092 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006093 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6094 if (!changed)
6095 changed = test_and_clear_bit(HCI_HS_ENABLED,
6096 &hdev->dev_flags);
6097 else
6098 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006099 }
6100
6101 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6102
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006103 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006104 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006105
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006106 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006107 sock_put(match.sk);
6108
Johan Hedberg890ea892013-03-15 17:06:52 -05006109 hci_req_init(&req, hdev);
6110
Johan Hedberg37699722014-06-24 14:00:27 +03006111 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6112 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6113 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6114 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006115 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006116 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006117 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006118 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006119
6120 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006121}
6122
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006123void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6124{
6125 struct cmd_lookup match = { NULL, hdev };
6126 bool changed = false;
6127
6128 if (status) {
6129 u8 mgmt_err = mgmt_status(status);
6130
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006131 if (enable) {
6132 if (test_and_clear_bit(HCI_SC_ENABLED,
6133 &hdev->dev_flags))
6134 new_settings(hdev, NULL);
6135 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6136 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006137
6138 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6139 cmd_status_rsp, &mgmt_err);
6140 return;
6141 }
6142
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006143 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006144 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006145 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006146 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006147 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6148 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006149
6150 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6151 settings_rsp, &match);
6152
6153 if (changed)
6154 new_settings(hdev, match.sk);
6155
6156 if (match.sk)
6157 sock_put(match.sk);
6158}
6159
Johan Hedberg92da6092013-03-15 17:06:55 -05006160static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006161{
6162 struct cmd_lookup *match = data;
6163
Johan Hedberg90e70452012-02-23 23:09:40 +02006164 if (match->sk == NULL) {
6165 match->sk = cmd->sk;
6166 sock_hold(match->sk);
6167 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006168}
6169
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006170void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6171 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006172{
Johan Hedberg90e70452012-02-23 23:09:40 +02006173 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006174
Johan Hedberg92da6092013-03-15 17:06:55 -05006175 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6176 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6177 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006178
6179 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006180 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6181 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006182
6183 if (match.sk)
6184 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006185}
6186
Marcel Holtmann7667da32013-10-15 14:26:27 -07006187void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006188{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006189 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006190 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006191
Johan Hedberg13928972013-03-15 17:07:00 -05006192 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006193 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006194
6195 memset(&ev, 0, sizeof(ev));
6196 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006197 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006198
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006199 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006200 if (!cmd) {
6201 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006202
Johan Hedberg13928972013-03-15 17:07:00 -05006203 /* If this is a HCI command related to powering on the
6204 * HCI dev don't send any mgmt signals.
6205 */
6206 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006207 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006208 }
6209
Marcel Holtmann7667da32013-10-15 14:26:27 -07006210 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6211 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006212}
Szymon Jancc35938b2011-03-22 13:12:21 +01006213
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006214void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6215 u8 *randomizer192, u8 *hash256,
6216 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006217{
6218 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006219
Johan Hedberg744cf192011-11-08 20:40:14 +02006220 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006221
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006222 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006223 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006224 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006225
6226 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006227 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6228 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006229 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006230 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6231 hash256 && randomizer256) {
6232 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006233
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006234 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6235 memcpy(rp.randomizer192, randomizer192,
6236 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006237
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006238 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6239 memcpy(rp.randomizer256, randomizer256,
6240 sizeof(rp.randomizer256));
6241
6242 cmd_complete(cmd->sk, hdev->id,
6243 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6244 &rp, sizeof(rp));
6245 } else {
6246 struct mgmt_rp_read_local_oob_data rp;
6247
6248 memcpy(rp.hash, hash192, sizeof(rp.hash));
6249 memcpy(rp.randomizer, randomizer192,
6250 sizeof(rp.randomizer));
6251
6252 cmd_complete(cmd->sk, hdev->id,
6253 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6254 &rp, sizeof(rp));
6255 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006256 }
6257
6258 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006259}
Johan Hedberge17acd42011-03-30 23:57:16 +03006260
Marcel Holtmann901801b2013-10-06 23:55:51 -07006261void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006262 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6263 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006264{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006265 char buf[512];
6266 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006267 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006268 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006269
Andre Guedes12602d02013-04-30 15:29:40 -03006270 if (!hci_discovery_active(hdev))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006271 return;
Andre Guedes12602d02013-04-30 15:29:40 -03006272
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006273 /* Make sure that the buffer is big enough. The 5 extra bytes
6274 * are for the potential CoD field.
6275 */
6276 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006277 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006278
Johan Hedberg1dc06092012-01-15 21:01:23 +02006279 memset(buf, 0, sizeof(buf));
6280
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006281 irk = hci_get_irk(hdev, bdaddr, addr_type);
6282 if (irk) {
6283 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
6284 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
6285 } else {
6286 bacpy(&ev->addr.bdaddr, bdaddr);
6287 ev->addr.type = link_to_bdaddr(link_type, addr_type);
6288 }
6289
Johan Hedberge319d2e2012-01-15 19:51:59 +02006290 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006291 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006292
Johan Hedberg1dc06092012-01-15 21:01:23 +02006293 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006294 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006295
Johan Hedberg1dc06092012-01-15 21:01:23 +02006296 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6297 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006298 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006299
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006300 if (scan_rsp_len > 0)
6301 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6302
6303 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6304 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006305
Marcel Holtmann901801b2013-10-06 23:55:51 -07006306 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006307}
Johan Hedberga88a9652011-03-30 13:18:12 +03006308
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006309void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6310 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006311{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006312 struct mgmt_ev_device_found *ev;
6313 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6314 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006315
Johan Hedbergb644ba32012-01-17 21:48:47 +02006316 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006317
Johan Hedbergb644ba32012-01-17 21:48:47 +02006318 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006319
Johan Hedbergb644ba32012-01-17 21:48:47 +02006320 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006321 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006322 ev->rssi = rssi;
6323
6324 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006325 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006326
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006327 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006328
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006329 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006330}
Johan Hedberg314b2382011-04-27 10:29:57 -04006331
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006332void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006333{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006334 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006335 struct pending_cmd *cmd;
6336
Andre Guedes343fb142011-11-22 17:14:19 -03006337 BT_DBG("%s discovering %u", hdev->name, discovering);
6338
Johan Hedberg164a6e72011-11-01 17:06:44 +02006339 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006340 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006341 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006342 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006343
6344 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006345 u8 type = hdev->discovery.type;
6346
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006347 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6348 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006349 mgmt_pending_remove(cmd);
6350 }
6351
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006352 memset(&ev, 0, sizeof(ev));
6353 ev.type = hdev->discovery.type;
6354 ev.discovering = discovering;
6355
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006356 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006357}
Antti Julku5e762442011-08-25 16:48:02 +03006358
Marcel Holtmann5976e602013-10-06 04:08:14 -07006359static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6360{
6361 BT_DBG("%s status %u", hdev->name, status);
6362
6363 /* Clear the advertising mgmt setting if we failed to re-enable it */
6364 if (status) {
6365 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006366 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006367 }
6368}
6369
6370void mgmt_reenable_advertising(struct hci_dev *hdev)
6371{
6372 struct hci_request req;
6373
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006374 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006375 return;
6376
6377 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6378 return;
6379
6380 hci_req_init(&req, hdev);
6381 enable_advertising(&req);
6382
6383 /* If this fails we have no option but to let user space know
6384 * that we've disabled advertising.
6385 */
6386 if (hci_req_run(&req, adv_enable_complete) < 0) {
6387 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006388 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006389 }
6390}