Blame view

net/bluetooth/mgmt.c 186 KB
0381101fd   Johan Hedberg   Bluetooth: Add in...
1
2
  /*
     BlueZ - Bluetooth protocol stack for Linux
ea585ab51   Johan Hedberg   Bluetooth: Add In...
3

0381101fd   Johan Hedberg   Bluetooth: Add in...
4
     Copyright (C) 2010  Nokia Corporation
ea585ab51   Johan Hedberg   Bluetooth: Add In...
5
     Copyright (C) 2011-2012 Intel Corporation
0381101fd   Johan Hedberg   Bluetooth: Add in...
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License version 2 as
     published by the Free Software Foundation;
  
     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
     IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
     CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
     WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  
     ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
     COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
     SOFTWARE IS DISCLAIMED.
  */
  
  /* Bluetooth HCI Management interface */
3a9a231d9   Paul Gortmaker   net: Fix files ex...
26
  #include <linux/module.h>
0381101fd   Johan Hedberg   Bluetooth: Add in...
27
28
29
30
  #include <asm/unaligned.h>
  
  #include <net/bluetooth/bluetooth.h>
  #include <net/bluetooth/hci_core.h>
7129069e8   Johan Hedberg   Bluetooth: Rename...
31
  #include <net/bluetooth/hci_sock.h>
4bc58f51e   Johan Hedberg   Bluetooth: Make S...
32
  #include <net/bluetooth/l2cap.h>
0381101fd   Johan Hedberg   Bluetooth: Add in...
33
  #include <net/bluetooth/mgmt.h>
ac4b72366   Marcel Holtmann   Bluetooth: Move s...
34

0857dd3be   Johan Hedberg   Bluetooth: Split ...
35
  #include "hci_request.h"
ac4b72366   Marcel Holtmann   Bluetooth: Move s...
36
  #include "smp.h"
a380b6cff   Johan Hedberg   Bluetooth: Add ge...
37
  #include "mgmt_util.h"
0381101fd   Johan Hedberg   Bluetooth: Add in...
38

2da9c55c5   Johan Hedberg   Bluetooth: mgmt: ...
39
  #define MGMT_VERSION	1
3310230c5   Szymon Janc   Bluetooth: Increm...
40
  #define MGMT_REVISION	14
02d981292   Johan Hedberg   Bluetooth: Add re...
41

e70bb2e89   Johan Hedberg   Bluetooth: Implem...
42
43
44
45
46
47
48
  static const u16 mgmt_commands[] = {
  	MGMT_OP_READ_INDEX_LIST,
  	MGMT_OP_READ_INFO,
  	MGMT_OP_SET_POWERED,
  	MGMT_OP_SET_DISCOVERABLE,
  	MGMT_OP_SET_CONNECTABLE,
  	MGMT_OP_SET_FAST_CONNECTABLE,
b2939475e   Johan Hedberg   Bluetooth: Rename...
49
  	MGMT_OP_SET_BONDABLE,
e70bb2e89   Johan Hedberg   Bluetooth: Implem...
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
  	MGMT_OP_SET_LINK_SECURITY,
  	MGMT_OP_SET_SSP,
  	MGMT_OP_SET_HS,
  	MGMT_OP_SET_LE,
  	MGMT_OP_SET_DEV_CLASS,
  	MGMT_OP_SET_LOCAL_NAME,
  	MGMT_OP_ADD_UUID,
  	MGMT_OP_REMOVE_UUID,
  	MGMT_OP_LOAD_LINK_KEYS,
  	MGMT_OP_LOAD_LONG_TERM_KEYS,
  	MGMT_OP_DISCONNECT,
  	MGMT_OP_GET_CONNECTIONS,
  	MGMT_OP_PIN_CODE_REPLY,
  	MGMT_OP_PIN_CODE_NEG_REPLY,
  	MGMT_OP_SET_IO_CAPABILITY,
  	MGMT_OP_PAIR_DEVICE,
  	MGMT_OP_CANCEL_PAIR_DEVICE,
  	MGMT_OP_UNPAIR_DEVICE,
  	MGMT_OP_USER_CONFIRM_REPLY,
  	MGMT_OP_USER_CONFIRM_NEG_REPLY,
  	MGMT_OP_USER_PASSKEY_REPLY,
  	MGMT_OP_USER_PASSKEY_NEG_REPLY,
  	MGMT_OP_READ_LOCAL_OOB_DATA,
  	MGMT_OP_ADD_REMOTE_OOB_DATA,
  	MGMT_OP_REMOVE_REMOTE_OOB_DATA,
  	MGMT_OP_START_DISCOVERY,
  	MGMT_OP_STOP_DISCOVERY,
  	MGMT_OP_CONFIRM_NAME,
  	MGMT_OP_BLOCK_DEVICE,
  	MGMT_OP_UNBLOCK_DEVICE,
cdbaccca7   Marcel Holtmann   Bluetooth: Add ma...
80
  	MGMT_OP_SET_DEVICE_ID,
4375f1037   Johan Hedberg   Bluetooth: Add ne...
81
  	MGMT_OP_SET_ADVERTISING,
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
82
  	MGMT_OP_SET_BREDR,
d13eafce2   Marcel Holtmann   Bluetooth: Add ma...
83
  	MGMT_OP_SET_STATIC_ADDRESS,
7f72134e0   Marcel Holtmann   Bluetooth: Add MG...
84
  	MGMT_OP_SET_SCAN_PARAMS,
e98d2ce29   Marcel Holtmann   Bluetooth: Add fl...
85
  	MGMT_OP_SET_SECURE_CONN,
4e39ac813   Marcel Holtmann   Bluetooth: Add ma...
86
  	MGMT_OP_SET_DEBUG_KEYS,
62b04cd12   Johan Hedberg   Bluetooth: Add su...
87
  	MGMT_OP_SET_PRIVACY,
41edf1601   Johan Hedberg   Bluetooth: Implem...
88
  	MGMT_OP_LOAD_IRKS,
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
89
  	MGMT_OP_GET_CONN_INFO,
958684263   Johan Hedberg   Bluetooth: Add su...
90
  	MGMT_OP_GET_CLOCK_INFO,
2faade53e   Marcel Holtmann   Bluetooth: Add su...
91
92
  	MGMT_OP_ADD_DEVICE,
  	MGMT_OP_REMOVE_DEVICE,
a26f3dcff   Johan Hedberg   Bluetooth: Add Lo...
93
  	MGMT_OP_LOAD_CONN_PARAM,
73d1df2a7   Marcel Holtmann   Bluetooth: Add su...
94
  	MGMT_OP_READ_UNCONF_INDEX_LIST,
9fc3bfb68   Marcel Holtmann   Bluetooth: Add su...
95
  	MGMT_OP_READ_CONFIG_INFO,
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
96
  	MGMT_OP_SET_EXTERNAL_CONFIG,
9713c17b0   Marcel Holtmann   Bluetooth: Add su...
97
  	MGMT_OP_SET_PUBLIC_ADDRESS,
66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
98
  	MGMT_OP_START_SERVICE_DISCOVERY,
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
99
  	MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
96f1474af   Marcel Holtmann   Bluetooth: Add su...
100
  	MGMT_OP_READ_EXT_INDEX_LIST,
d3d5305bf   Marcel Holtmann   Bluetooth: Add si...
101
  	MGMT_OP_READ_ADV_FEATURES,
24b4f38fc   Arman Uguray   Bluetooth: Implem...
102
  	MGMT_OP_ADD_ADVERTISING,
da929335f   Arman Uguray   Bluetooth: Implem...
103
  	MGMT_OP_REMOVE_ADVERTISING,
40b25fe5d   Marcel Holtmann   Bluetooth: Add su...
104
  	MGMT_OP_GET_ADV_SIZE_INFO,
78b781ca0   Johan Hedberg   Bluetooth: Add su...
105
  	MGMT_OP_START_LIMITED_DISCOVERY,
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
106
  	MGMT_OP_READ_EXT_INFO,
c4960ecf2   MichaƂ Narajowski   Bluetooth: Add su...
107
  	MGMT_OP_SET_APPEARANCE,
e70bb2e89   Johan Hedberg   Bluetooth: Implem...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
  };
  
  static const u16 mgmt_events[] = {
  	MGMT_EV_CONTROLLER_ERROR,
  	MGMT_EV_INDEX_ADDED,
  	MGMT_EV_INDEX_REMOVED,
  	MGMT_EV_NEW_SETTINGS,
  	MGMT_EV_CLASS_OF_DEV_CHANGED,
  	MGMT_EV_LOCAL_NAME_CHANGED,
  	MGMT_EV_NEW_LINK_KEY,
  	MGMT_EV_NEW_LONG_TERM_KEY,
  	MGMT_EV_DEVICE_CONNECTED,
  	MGMT_EV_DEVICE_DISCONNECTED,
  	MGMT_EV_CONNECT_FAILED,
  	MGMT_EV_PIN_CODE_REQUEST,
  	MGMT_EV_USER_CONFIRM_REQUEST,
  	MGMT_EV_USER_PASSKEY_REQUEST,
  	MGMT_EV_AUTH_FAILED,
  	MGMT_EV_DEVICE_FOUND,
  	MGMT_EV_DISCOVERING,
  	MGMT_EV_DEVICE_BLOCKED,
  	MGMT_EV_DEVICE_UNBLOCKED,
  	MGMT_EV_DEVICE_UNPAIRED,
92a25256f   Johan Hedberg   Bluetooth: mgmt: ...
131
  	MGMT_EV_PASSKEY_NOTIFY,
1b60ef210   Marcel Holtmann   Bluetooth: Fix is...
132
  	MGMT_EV_NEW_IRK,
7ee4ea369   Marcel Holtmann   Bluetooth: Add su...
133
  	MGMT_EV_NEW_CSRK,
8afef092a   Marcel Holtmann   Bluetooth: Add De...
134
135
  	MGMT_EV_DEVICE_ADDED,
  	MGMT_EV_DEVICE_REMOVED,
ffb5a827d   Andre Guedes   Bluetooth: Introd...
136
  	MGMT_EV_NEW_CONN_PARAM,
0602a8adc   Marcel Holtmann   Bluetooth: Add su...
137
  	MGMT_EV_UNCONF_INDEX_ADDED,
edd3896bc   Marcel Holtmann   Bluetooth: Add su...
138
  	MGMT_EV_UNCONF_INDEX_REMOVED,
f4537c04d   Marcel Holtmann   Bluetooth: Add su...
139
  	MGMT_EV_NEW_CONFIG_OPTIONS,
ced85549c   Marcel Holtmann   Bluetooth: Add su...
140
141
  	MGMT_EV_EXT_INDEX_ADDED,
  	MGMT_EV_EXT_INDEX_REMOVED,
72000df2c   Marcel Holtmann   Bluetooth: Add su...
142
  	MGMT_EV_LOCAL_OOB_DATA_UPDATED,
24b4f38fc   Arman Uguray   Bluetooth: Implem...
143
144
  	MGMT_EV_ADVERTISING_ADDED,
  	MGMT_EV_ADVERTISING_REMOVED,
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
145
  	MGMT_EV_EXT_INFO_CHANGED,
e70bb2e89   Johan Hedberg   Bluetooth: Implem...
146
  };
99c679acc   Marcel Holtmann   Bluetooth: Filter...
147
148
149
150
151
152
  static const u16 mgmt_untrusted_commands[] = {
  	MGMT_OP_READ_INDEX_LIST,
  	MGMT_OP_READ_INFO,
  	MGMT_OP_READ_UNCONF_INDEX_LIST,
  	MGMT_OP_READ_CONFIG_INFO,
  	MGMT_OP_READ_EXT_INDEX_LIST,
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
153
  	MGMT_OP_READ_EXT_INFO,
99c679acc   Marcel Holtmann   Bluetooth: Filter...
154
155
156
157
158
159
160
161
162
163
164
165
166
  };
  
  static const u16 mgmt_untrusted_events[] = {
  	MGMT_EV_INDEX_ADDED,
  	MGMT_EV_INDEX_REMOVED,
  	MGMT_EV_NEW_SETTINGS,
  	MGMT_EV_CLASS_OF_DEV_CHANGED,
  	MGMT_EV_LOCAL_NAME_CHANGED,
  	MGMT_EV_UNCONF_INDEX_ADDED,
  	MGMT_EV_UNCONF_INDEX_REMOVED,
  	MGMT_EV_NEW_CONFIG_OPTIONS,
  	MGMT_EV_EXT_INDEX_ADDED,
  	MGMT_EV_EXT_INDEX_REMOVED,
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
167
  	MGMT_EV_EXT_INFO_CHANGED,
99c679acc   Marcel Holtmann   Bluetooth: Filter...
168
  };
17b02e625   Marcel Holtmann   Bluetooth: Update...
169
  #define CACHE_TIMEOUT	msecs_to_jiffies(2 * 1000)
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
170

d25b78e2e   Johan Hedberg   Bluetooth: Enforc...
171
172
  #define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
  		 "\x00\x00\x00\x00\x00\x00\x00\x00"
ca69b7957   Johan Hedberg   Bluetooth: Create...
173
174
175
176
177
178
179
180
  /* HCI to MGMT error code conversion table */
  static u8 mgmt_status_table[] = {
  	MGMT_STATUS_SUCCESS,
  	MGMT_STATUS_UNKNOWN_COMMAND,	/* Unknown Command */
  	MGMT_STATUS_NOT_CONNECTED,	/* No Connection */
  	MGMT_STATUS_FAILED,		/* Hardware Failure */
  	MGMT_STATUS_CONNECT_FAILED,	/* Page Timeout */
  	MGMT_STATUS_AUTH_FAILED,	/* Authentication Failed */
eadd663a6   Johan Hedberg   Bluetooth: Fix mg...
181
  	MGMT_STATUS_AUTH_FAILED,	/* PIN or Key Missing */
ca69b7957   Johan Hedberg   Bluetooth: Create...
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
  	MGMT_STATUS_NO_RESOURCES,	/* Memory Full */
  	MGMT_STATUS_TIMEOUT,		/* Connection Timeout */
  	MGMT_STATUS_NO_RESOURCES,	/* Max Number of Connections */
  	MGMT_STATUS_NO_RESOURCES,	/* Max Number of SCO Connections */
  	MGMT_STATUS_ALREADY_CONNECTED,	/* ACL Connection Exists */
  	MGMT_STATUS_BUSY,		/* Command Disallowed */
  	MGMT_STATUS_NO_RESOURCES,	/* Rejected Limited Resources */
  	MGMT_STATUS_REJECTED,		/* Rejected Security */
  	MGMT_STATUS_REJECTED,		/* Rejected Personal */
  	MGMT_STATUS_TIMEOUT,		/* Host Timeout */
  	MGMT_STATUS_NOT_SUPPORTED,	/* Unsupported Feature */
  	MGMT_STATUS_INVALID_PARAMS,	/* Invalid Parameters */
  	MGMT_STATUS_DISCONNECTED,	/* OE User Ended Connection */
  	MGMT_STATUS_NO_RESOURCES,	/* OE Low Resources */
  	MGMT_STATUS_DISCONNECTED,	/* OE Power Off */
  	MGMT_STATUS_DISCONNECTED,	/* Connection Terminated */
  	MGMT_STATUS_BUSY,		/* Repeated Attempts */
  	MGMT_STATUS_REJECTED,		/* Pairing Not Allowed */
  	MGMT_STATUS_FAILED,		/* Unknown LMP PDU */
  	MGMT_STATUS_NOT_SUPPORTED,	/* Unsupported Remote Feature */
  	MGMT_STATUS_REJECTED,		/* SCO Offset Rejected */
  	MGMT_STATUS_REJECTED,		/* SCO Interval Rejected */
  	MGMT_STATUS_REJECTED,		/* Air Mode Rejected */
  	MGMT_STATUS_INVALID_PARAMS,	/* Invalid LMP Parameters */
  	MGMT_STATUS_FAILED,		/* Unspecified Error */
  	MGMT_STATUS_NOT_SUPPORTED,	/* Unsupported LMP Parameter Value */
  	MGMT_STATUS_FAILED,		/* Role Change Not Allowed */
  	MGMT_STATUS_TIMEOUT,		/* LMP Response Timeout */
  	MGMT_STATUS_FAILED,		/* LMP Error Transaction Collision */
  	MGMT_STATUS_FAILED,		/* LMP PDU Not Allowed */
  	MGMT_STATUS_REJECTED,		/* Encryption Mode Not Accepted */
  	MGMT_STATUS_FAILED,		/* Unit Link Key Used */
  	MGMT_STATUS_NOT_SUPPORTED,	/* QoS Not Supported */
  	MGMT_STATUS_TIMEOUT,		/* Instant Passed */
  	MGMT_STATUS_NOT_SUPPORTED,	/* Pairing Not Supported */
  	MGMT_STATUS_FAILED,		/* Transaction Collision */
  	MGMT_STATUS_INVALID_PARAMS,	/* Unacceptable Parameter */
  	MGMT_STATUS_REJECTED,		/* QoS Rejected */
  	MGMT_STATUS_NOT_SUPPORTED,	/* Classification Not Supported */
  	MGMT_STATUS_REJECTED,		/* Insufficient Security */
  	MGMT_STATUS_INVALID_PARAMS,	/* Parameter Out Of Range */
  	MGMT_STATUS_BUSY,		/* Role Switch Pending */
  	MGMT_STATUS_FAILED,		/* Slot Violation */
  	MGMT_STATUS_FAILED,		/* Role Switch Failed */
  	MGMT_STATUS_INVALID_PARAMS,	/* EIR Too Large */
  	MGMT_STATUS_NOT_SUPPORTED,	/* Simple Pairing Not Supported */
  	MGMT_STATUS_BUSY,		/* Host Busy Pairing */
  	MGMT_STATUS_REJECTED,		/* Rejected, No Suitable Channel */
  	MGMT_STATUS_BUSY,		/* Controller Busy */
  	MGMT_STATUS_INVALID_PARAMS,	/* Unsuitable Connection Interval */
  	MGMT_STATUS_TIMEOUT,		/* Directed Advertising Timeout */
  	MGMT_STATUS_AUTH_FAILED,	/* Terminated Due to MIC Failure */
  	MGMT_STATUS_CONNECT_FAILED,	/* Connection Establishment Failed */
  	MGMT_STATUS_CONNECT_FAILED,	/* MAC Connection Failed */
  };
  
  static u8 mgmt_status(u8 hci_status)
  {
  	if (hci_status < ARRAY_SIZE(mgmt_status_table))
  		return mgmt_status_table[hci_status];
  
  	return MGMT_STATUS_FAILED;
  }
c08b1a1db   Marcel Holtmann   Bluetooth: Consol...
245
246
  static int mgmt_index_event(u16 event, struct hci_dev *hdev, void *data,
  			    u16 len, int flag)
f92073388   Marcel Holtmann   Bluetooth: Use sp...
247
  {
c08b1a1db   Marcel Holtmann   Bluetooth: Consol...
248
249
  	return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
  			       flag, NULL);
f92073388   Marcel Holtmann   Bluetooth: Use sp...
250
  }
72000df2c   Marcel Holtmann   Bluetooth: Add su...
251
252
253
254
255
256
  static int mgmt_limited_event(u16 event, struct hci_dev *hdev, void *data,
  			      u16 len, int flag, struct sock *skip_sk)
  {
  	return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
  			       flag, skip_sk);
  }
7a00ff445   Johan Hedberg   Bluetooth: Add mg...
257
258
259
260
  static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 len,
  		      struct sock *skip_sk)
  {
  	return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
c08b1a1db   Marcel Holtmann   Bluetooth: Consol...
261
  			       HCI_SOCK_TRUSTED, skip_sk);
7a00ff445   Johan Hedberg   Bluetooth: Add mg...
262
  }
85813a7ec   Johan Hedberg   Bluetooth: Add le...
263
264
265
266
267
268
269
  static u8 le_addr_type(u8 mgmt_addr_type)
  {
  	if (mgmt_addr_type == BDADDR_LE_PUBLIC)
  		return ADDR_LE_DEV_PUBLIC;
  	else
  		return ADDR_LE_DEV_RANDOM;
  }
03c979c47   Marcel Holtmann   Bluetooth: Introd...
270
271
272
273
274
275
276
  void mgmt_fill_version_info(void *ver)
  {
  	struct mgmt_rp_read_version *rp = ver;
  
  	rp->version = MGMT_VERSION;
  	rp->revision = cpu_to_le16(MGMT_REVISION);
  }
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
277
278
  static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
  			u16 data_len)
a38528f11   Johan Hedberg   Bluetooth: Create...
279
280
281
282
  {
  	struct mgmt_rp_read_version rp;
  
  	BT_DBG("sock %p", sk);
03c979c47   Marcel Holtmann   Bluetooth: Introd...
283
  	mgmt_fill_version_info(&rp);
a38528f11   Johan Hedberg   Bluetooth: Create...
284

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
285
286
  	return mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0,
  				 &rp, sizeof(rp));
a38528f11   Johan Hedberg   Bluetooth: Create...
287
  }
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
288
289
  static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
  			 u16 data_len)
e70bb2e89   Johan Hedberg   Bluetooth: Implem...
290
291
  {
  	struct mgmt_rp_read_commands *rp;
99c679acc   Marcel Holtmann   Bluetooth: Filter...
292
  	u16 num_commands, num_events;
e70bb2e89   Johan Hedberg   Bluetooth: Implem...
293
294
295
296
  	size_t rp_size;
  	int i, err;
  
  	BT_DBG("sock %p", sk);
99c679acc   Marcel Holtmann   Bluetooth: Filter...
297
298
299
300
301
302
303
  	if (hci_sock_test_flag(sk, HCI_SOCK_TRUSTED)) {
  		num_commands = ARRAY_SIZE(mgmt_commands);
  		num_events = ARRAY_SIZE(mgmt_events);
  	} else {
  		num_commands = ARRAY_SIZE(mgmt_untrusted_commands);
  		num_events = ARRAY_SIZE(mgmt_untrusted_events);
  	}
e70bb2e89   Johan Hedberg   Bluetooth: Implem...
304
305
306
307
308
  	rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
  
  	rp = kmalloc(rp_size, GFP_KERNEL);
  	if (!rp)
  		return -ENOMEM;
dcf4adbfd   Joe Perches   Bluetooth: Conver...
309
310
  	rp->num_commands = cpu_to_le16(num_commands);
  	rp->num_events = cpu_to_le16(num_events);
e70bb2e89   Johan Hedberg   Bluetooth: Implem...
311

99c679acc   Marcel Holtmann   Bluetooth: Filter...
312
313
314
315
316
  	if (hci_sock_test_flag(sk, HCI_SOCK_TRUSTED)) {
  		__le16 *opcode = rp->opcodes;
  
  		for (i = 0; i < num_commands; i++, opcode++)
  			put_unaligned_le16(mgmt_commands[i], opcode);
e70bb2e89   Johan Hedberg   Bluetooth: Implem...
317

99c679acc   Marcel Holtmann   Bluetooth: Filter...
318
319
320
321
322
323
324
325
326
327
328
  		for (i = 0; i < num_events; i++, opcode++)
  			put_unaligned_le16(mgmt_events[i], opcode);
  	} else {
  		__le16 *opcode = rp->opcodes;
  
  		for (i = 0; i < num_commands; i++, opcode++)
  			put_unaligned_le16(mgmt_untrusted_commands[i], opcode);
  
  		for (i = 0; i < num_events; i++, opcode++)
  			put_unaligned_le16(mgmt_untrusted_events[i], opcode);
  	}
e70bb2e89   Johan Hedberg   Bluetooth: Implem...
329

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
330
331
  	err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0,
  				rp, rp_size);
e70bb2e89   Johan Hedberg   Bluetooth: Implem...
332
333
334
335
  	kfree(rp);
  
  	return err;
  }
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
336
337
  static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
  			   u16 data_len)
faba42eb2   Johan Hedberg   Bluetooth: Add re...
338
  {
faba42eb2   Johan Hedberg   Bluetooth: Add re...
339
  	struct mgmt_rp_read_index_list *rp;
8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
340
  	struct hci_dev *d;
a38528f11   Johan Hedberg   Bluetooth: Create...
341
  	size_t rp_len;
faba42eb2   Johan Hedberg   Bluetooth: Add re...
342
  	u16 count;
476e44cb1   Johan Hedberg   Bluetooth: Fix ha...
343
  	int err;
faba42eb2   Johan Hedberg   Bluetooth: Add re...
344
345
346
347
348
349
  
  	BT_DBG("sock %p", sk);
  
  	read_lock(&hci_dev_list_lock);
  
  	count = 0;
bb4b2a9ae   Andrei Emeltchenko   Bluetooth: mgmt: ...
350
  	list_for_each_entry(d, &hci_dev_list, list) {
ca8bee5dd   Marcel Holtmann   Bluetooth: Rename...
351
  		if (d->dev_type == HCI_PRIMARY &&
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
352
  		    !hci_dev_test_flag(d, HCI_UNCONFIGURED))
1514b8928   Marcel Holtmann   Bluetooth: Remove...
353
  			count++;
faba42eb2   Johan Hedberg   Bluetooth: Add re...
354
  	}
a38528f11   Johan Hedberg   Bluetooth: Create...
355
356
357
  	rp_len = sizeof(*rp) + (2 * count);
  	rp = kmalloc(rp_len, GFP_ATOMIC);
  	if (!rp) {
b2c60d42d   Jesper Juhl   Bluetooth: Fix fa...
358
  		read_unlock(&hci_dev_list_lock);
faba42eb2   Johan Hedberg   Bluetooth: Add re...
359
  		return -ENOMEM;
b2c60d42d   Jesper Juhl   Bluetooth: Fix fa...
360
  	}
faba42eb2   Johan Hedberg   Bluetooth: Add re...
361

476e44cb1   Johan Hedberg   Bluetooth: Fix ha...
362
  	count = 0;
8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
363
  	list_for_each_entry(d, &hci_dev_list, list) {
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
364
365
366
  		if (hci_dev_test_flag(d, HCI_SETUP) ||
  		    hci_dev_test_flag(d, HCI_CONFIG) ||
  		    hci_dev_test_flag(d, HCI_USER_CHANNEL))
ab81cbf99   Johan Hedberg   Bluetooth: Implem...
367
  			continue;
73d1df2a7   Marcel Holtmann   Bluetooth: Add su...
368
369
370
371
  		/* Devices marked as raw-only are neither configured
  		 * nor unconfigured controllers.
  		 */
  		if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
fee746b0b   Marcel Holtmann   Bluetooth: Restri...
372
  			continue;
ca8bee5dd   Marcel Holtmann   Bluetooth: Rename...
373
  		if (d->dev_type == HCI_PRIMARY &&
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
374
  		    !hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
1514b8928   Marcel Holtmann   Bluetooth: Remove...
375
376
377
  			rp->index[count++] = cpu_to_le16(d->id);
  			BT_DBG("Added hci%u", d->id);
  		}
faba42eb2   Johan Hedberg   Bluetooth: Add re...
378
  	}
476e44cb1   Johan Hedberg   Bluetooth: Fix ha...
379
380
  	rp->num_controllers = cpu_to_le16(count);
  	rp_len = sizeof(*rp) + (2 * count);
faba42eb2   Johan Hedberg   Bluetooth: Add re...
381
  	read_unlock(&hci_dev_list_lock);
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
382
383
  	err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST,
  				0, rp, rp_len);
faba42eb2   Johan Hedberg   Bluetooth: Add re...
384

a38528f11   Johan Hedberg   Bluetooth: Create...
385
386
387
  	kfree(rp);
  
  	return err;
faba42eb2   Johan Hedberg   Bluetooth: Add re...
388
  }
73d1df2a7   Marcel Holtmann   Bluetooth: Add su...
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
  static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
  				  void *data, u16 data_len)
  {
  	struct mgmt_rp_read_unconf_index_list *rp;
  	struct hci_dev *d;
  	size_t rp_len;
  	u16 count;
  	int err;
  
  	BT_DBG("sock %p", sk);
  
  	read_lock(&hci_dev_list_lock);
  
  	count = 0;
  	list_for_each_entry(d, &hci_dev_list, list) {
ca8bee5dd   Marcel Holtmann   Bluetooth: Rename...
404
  		if (d->dev_type == HCI_PRIMARY &&
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
405
  		    hci_dev_test_flag(d, HCI_UNCONFIGURED))
73d1df2a7   Marcel Holtmann   Bluetooth: Add su...
406
407
408
409
410
411
412
413
414
415
416
417
  			count++;
  	}
  
  	rp_len = sizeof(*rp) + (2 * count);
  	rp = kmalloc(rp_len, GFP_ATOMIC);
  	if (!rp) {
  		read_unlock(&hci_dev_list_lock);
  		return -ENOMEM;
  	}
  
  	count = 0;
  	list_for_each_entry(d, &hci_dev_list, list) {
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
418
419
420
  		if (hci_dev_test_flag(d, HCI_SETUP) ||
  		    hci_dev_test_flag(d, HCI_CONFIG) ||
  		    hci_dev_test_flag(d, HCI_USER_CHANNEL))
73d1df2a7   Marcel Holtmann   Bluetooth: Add su...
421
422
423
424
425
426
427
  			continue;
  
  		/* Devices marked as raw-only are neither configured
  		 * nor unconfigured controllers.
  		 */
  		if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
  			continue;
ca8bee5dd   Marcel Holtmann   Bluetooth: Rename...
428
  		if (d->dev_type == HCI_PRIMARY &&
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
429
  		    hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
73d1df2a7   Marcel Holtmann   Bluetooth: Add su...
430
431
432
433
434
435
436
437
438
  			rp->index[count++] = cpu_to_le16(d->id);
  			BT_DBG("Added hci%u", d->id);
  		}
  	}
  
  	rp->num_controllers = cpu_to_le16(count);
  	rp_len = sizeof(*rp) + (2 * count);
  
  	read_unlock(&hci_dev_list_lock);
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
439
440
  	err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
  				MGMT_OP_READ_UNCONF_INDEX_LIST, 0, rp, rp_len);
73d1df2a7   Marcel Holtmann   Bluetooth: Add su...
441
442
443
444
445
  
  	kfree(rp);
  
  	return err;
  }
96f1474af   Marcel Holtmann   Bluetooth: Add su...
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
  static int read_ext_index_list(struct sock *sk, struct hci_dev *hdev,
  			       void *data, u16 data_len)
  {
  	struct mgmt_rp_read_ext_index_list *rp;
  	struct hci_dev *d;
  	size_t rp_len;
  	u16 count;
  	int err;
  
  	BT_DBG("sock %p", sk);
  
  	read_lock(&hci_dev_list_lock);
  
  	count = 0;
  	list_for_each_entry(d, &hci_dev_list, list) {
ca8bee5dd   Marcel Holtmann   Bluetooth: Rename...
461
  		if (d->dev_type == HCI_PRIMARY || d->dev_type == HCI_AMP)
96f1474af   Marcel Holtmann   Bluetooth: Add su...
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
  			count++;
  	}
  
  	rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count);
  	rp = kmalloc(rp_len, GFP_ATOMIC);
  	if (!rp) {
  		read_unlock(&hci_dev_list_lock);
  		return -ENOMEM;
  	}
  
  	count = 0;
  	list_for_each_entry(d, &hci_dev_list, list) {
  		if (hci_dev_test_flag(d, HCI_SETUP) ||
  		    hci_dev_test_flag(d, HCI_CONFIG) ||
  		    hci_dev_test_flag(d, HCI_USER_CHANNEL))
  			continue;
  
  		/* Devices marked as raw-only are neither configured
  		 * nor unconfigured controllers.
  		 */
  		if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
  			continue;
ca8bee5dd   Marcel Holtmann   Bluetooth: Rename...
484
  		if (d->dev_type == HCI_PRIMARY) {
96f1474af   Marcel Holtmann   Bluetooth: Add su...
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
  			if (hci_dev_test_flag(d, HCI_UNCONFIGURED))
  				rp->entry[count].type = 0x01;
  			else
  				rp->entry[count].type = 0x00;
  		} else if (d->dev_type == HCI_AMP) {
  			rp->entry[count].type = 0x02;
  		} else {
  			continue;
  		}
  
  		rp->entry[count].bus = d->bus;
  		rp->entry[count++].index = cpu_to_le16(d->id);
  		BT_DBG("Added hci%u", d->id);
  	}
  
  	rp->num_controllers = cpu_to_le16(count);
  	rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count);
  
  	read_unlock(&hci_dev_list_lock);
  
  	/* If this command is called at least once, then all the
  	 * default index and unconfigured index events are disabled
  	 * and from now on only extended index events are used.
  	 */
  	hci_sock_set_flag(sk, HCI_MGMT_EXT_INDEX_EVENTS);
  	hci_sock_clear_flag(sk, HCI_MGMT_INDEX_EVENTS);
  	hci_sock_clear_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS);
  
  	err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
  				MGMT_OP_READ_EXT_INDEX_LIST, 0, rp, rp_len);
  
  	kfree(rp);
  
  	return err;
  }
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
520
521
522
  static bool is_configured(struct hci_dev *hdev)
  {
  	if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
523
  	    !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
524
525
526
527
528
529
530
531
  		return false;
  
  	if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
  	    !bacmp(&hdev->public_addr, BDADDR_ANY))
  		return false;
  
  	return true;
  }
89bc22d23   Marcel Holtmann   Bluetooth: Add qu...
532
533
534
  static __le32 get_missing_options(struct hci_dev *hdev)
  {
  	u32 options = 0;
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
535
  	if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
536
  	    !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
eb1904f49   Marcel Holtmann   Bluetooth: Add qu...
537
  		options |= MGMT_OPTION_EXTERNAL_CONFIG;
89bc22d23   Marcel Holtmann   Bluetooth: Add qu...
538
539
540
541
542
543
  	if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
  	    !bacmp(&hdev->public_addr, BDADDR_ANY))
  		options |= MGMT_OPTION_PUBLIC_ADDRESS;
  
  	return cpu_to_le32(options);
  }
f4537c04d   Marcel Holtmann   Bluetooth: Add su...
544
545
546
  static int new_options(struct hci_dev *hdev, struct sock *skip)
  {
  	__le32 options = get_missing_options(hdev);
5504c3a31   Marcel Holtmann   Bluetooth: Use in...
547
548
  	return mgmt_limited_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
  				  sizeof(options), HCI_MGMT_OPTION_EVENTS, skip);
f4537c04d   Marcel Holtmann   Bluetooth: Add su...
549
  }
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
550
551
552
  static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
  {
  	__le32 options = get_missing_options(hdev);
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
553
554
  	return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &options,
  				 sizeof(options));
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
555
  }
9fc3bfb68   Marcel Holtmann   Bluetooth: Add su...
556
557
558
559
  static int read_config_info(struct sock *sk, struct hci_dev *hdev,
  			    void *data, u16 data_len)
  {
  	struct mgmt_rp_read_config_info rp;
89bc22d23   Marcel Holtmann   Bluetooth: Add qu...
560
  	u32 options = 0;
9fc3bfb68   Marcel Holtmann   Bluetooth: Add su...
561
562
563
564
565
566
567
  
  	BT_DBG("sock %p %s", sk, hdev->name);
  
  	hci_dev_lock(hdev);
  
  	memset(&rp, 0, sizeof(rp));
  	rp.manufacturer = cpu_to_le16(hdev->manufacturer);
89bc22d23   Marcel Holtmann   Bluetooth: Add qu...
568

eb1904f49   Marcel Holtmann   Bluetooth: Add qu...
569
570
  	if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
  		options |= MGMT_OPTION_EXTERNAL_CONFIG;
9fc3bfb68   Marcel Holtmann   Bluetooth: Add su...
571
  	if (hdev->set_bdaddr)
89bc22d23   Marcel Holtmann   Bluetooth: Add qu...
572
573
574
575
  		options |= MGMT_OPTION_PUBLIC_ADDRESS;
  
  	rp.supported_options = cpu_to_le32(options);
  	rp.missing_options = get_missing_options(hdev);
9fc3bfb68   Marcel Holtmann   Bluetooth: Add su...
576
577
  
  	hci_dev_unlock(hdev);
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
578
579
  	return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0,
  				 &rp, sizeof(rp));
9fc3bfb68   Marcel Holtmann   Bluetooth: Add su...
580
  }
69ab39ea5   Johan Hedberg   Bluetooth: Update...
581
582
583
584
585
  static u32 get_supported_settings(struct hci_dev *hdev)
  {
  	u32 settings = 0;
  
  	settings |= MGMT_SETTING_POWERED;
b2939475e   Johan Hedberg   Bluetooth: Rename...
586
  	settings |= MGMT_SETTING_BONDABLE;
b1de97d8c   Marcel Holtmann   Bluetooth: Add ma...
587
  	settings |= MGMT_SETTING_DEBUG_KEYS;
3742abfc4   Johan Hedberg   Bluetooth: Fix co...
588
589
  	settings |= MGMT_SETTING_CONNECTABLE;
  	settings |= MGMT_SETTING_DISCOVERABLE;
69ab39ea5   Johan Hedberg   Bluetooth: Update...
590

ed3fa31f3   Andre Guedes   Bluetooth: Use lm...
591
  	if (lmp_bredr_capable(hdev)) {
1a47aee85   Johan Hedberg   Bluetooth: Limit ...
592
593
  		if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
  			settings |= MGMT_SETTING_FAST_CONNECTABLE;
69ab39ea5   Johan Hedberg   Bluetooth: Update...
594
595
  		settings |= MGMT_SETTING_BREDR;
  		settings |= MGMT_SETTING_LINK_SECURITY;
a82974c9f   Marcel Holtmann   Bluetooth: Don't ...
596
597
598
599
600
  
  		if (lmp_ssp_capable(hdev)) {
  			settings |= MGMT_SETTING_SSP;
  			settings |= MGMT_SETTING_HS;
  		}
e98d2ce29   Marcel Holtmann   Bluetooth: Add fl...
601

05b3c3e79   Marcel Holtmann   Bluetooth: Remove...
602
  		if (lmp_sc_capable(hdev))
e98d2ce29   Marcel Holtmann   Bluetooth: Add fl...
603
  			settings |= MGMT_SETTING_SECURE_CONN;
848566b38   Marcel Holtmann   Bluetooth: Provid...
604
  	}
d7b7e7968   Marcel Holtmann   Bluetooth: Set su...
605

eeca6f891   Johan Hedberg   Bluetooth: Add ne...
606
  	if (lmp_le_capable(hdev)) {
9d42820f3   Marcel Holtmann   Bluetooth: Enable...
607
  		settings |= MGMT_SETTING_LE;
eeca6f891   Johan Hedberg   Bluetooth: Add ne...
608
  		settings |= MGMT_SETTING_ADVERTISING;
a3209694f   Johan Hedberg   Bluetooth: Add mg...
609
  		settings |= MGMT_SETTING_SECURE_CONN;
0f4bd942f   Johan Hedberg   Bluetooth: Add Pr...
610
  		settings |= MGMT_SETTING_PRIVACY;
93690c227   Marcel Holtmann   Bluetooth: Introd...
611
  		settings |= MGMT_SETTING_STATIC_ADDRESS;
eeca6f891   Johan Hedberg   Bluetooth: Add ne...
612
  	}
69ab39ea5   Johan Hedberg   Bluetooth: Update...
613

eb1904f49   Marcel Holtmann   Bluetooth: Add qu...
614
615
  	if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
  	    hdev->set_bdaddr)
9fc3bfb68   Marcel Holtmann   Bluetooth: Add su...
616
  		settings |= MGMT_SETTING_CONFIGURATION;
69ab39ea5   Johan Hedberg   Bluetooth: Update...
617
618
619
620
621
622
  	return settings;
  }
  
  static u32 get_current_settings(struct hci_dev *hdev)
  {
  	u32 settings = 0;
f1f0eb022   Johan Hedberg   Bluetooth: mgmt: ...
623
  	if (hdev_is_powered(hdev))
f0d4b78a6   Marcel Holtmann   Bluetooth: Only k...
624
  		settings |= MGMT_SETTING_POWERED;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
625
  	if (hci_dev_test_flag(hdev, HCI_CONNECTABLE))
69ab39ea5   Johan Hedberg   Bluetooth: Update...
626
  		settings |= MGMT_SETTING_CONNECTABLE;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
627
  	if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
1a4d3c4b3   Johan Hedberg   Bluetooth: Add pr...
628
  		settings |= MGMT_SETTING_FAST_CONNECTABLE;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
629
  	if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
69ab39ea5   Johan Hedberg   Bluetooth: Update...
630
  		settings |= MGMT_SETTING_DISCOVERABLE;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
631
  	if (hci_dev_test_flag(hdev, HCI_BONDABLE))
b2939475e   Johan Hedberg   Bluetooth: Rename...
632
  		settings |= MGMT_SETTING_BONDABLE;
69ab39ea5   Johan Hedberg   Bluetooth: Update...
633

d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
634
  	if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
69ab39ea5   Johan Hedberg   Bluetooth: Update...
635
  		settings |= MGMT_SETTING_BREDR;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
636
  	if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
69ab39ea5   Johan Hedberg   Bluetooth: Update...
637
  		settings |= MGMT_SETTING_LE;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
638
  	if (hci_dev_test_flag(hdev, HCI_LINK_SECURITY))
69ab39ea5   Johan Hedberg   Bluetooth: Update...
639
  		settings |= MGMT_SETTING_LINK_SECURITY;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
640
  	if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
69ab39ea5   Johan Hedberg   Bluetooth: Update...
641
  		settings |= MGMT_SETTING_SSP;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
642
  	if (hci_dev_test_flag(hdev, HCI_HS_ENABLED))
6d80dfd09   Johan Hedberg   Bluetooth: mgmt: ...
643
  		settings |= MGMT_SETTING_HS;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
644
  	if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
eeca6f891   Johan Hedberg   Bluetooth: Add ne...
645
  		settings |= MGMT_SETTING_ADVERTISING;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
646
  	if (hci_dev_test_flag(hdev, HCI_SC_ENABLED))
e98d2ce29   Marcel Holtmann   Bluetooth: Add fl...
647
  		settings |= MGMT_SETTING_SECURE_CONN;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
648
  	if (hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS))
b1de97d8c   Marcel Holtmann   Bluetooth: Add ma...
649
  		settings |= MGMT_SETTING_DEBUG_KEYS;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
650
  	if (hci_dev_test_flag(hdev, HCI_PRIVACY))
0f4bd942f   Johan Hedberg   Bluetooth: Add Pr...
651
  		settings |= MGMT_SETTING_PRIVACY;
93690c227   Marcel Holtmann   Bluetooth: Introd...
652
653
654
655
656
  	/* The current setting for static address has two purposes. The
  	 * first is to indicate if the static address will be used and
  	 * the second is to indicate if it is actually set.
  	 *
  	 * This means if the static address is not configured, this flag
08dc0e987   Marcel Holtmann   Bluetooth: Fix mi...
657
  	 * will never be set. If the address is configured, then if the
93690c227   Marcel Holtmann   Bluetooth: Introd...
658
659
660
661
662
663
  	 * address is actually used decides if the flag is set or not.
  	 *
  	 * For single mode LE only controllers and dual-mode controllers
  	 * with BR/EDR disabled, the existence of the static address will
  	 * be evaluated.
  	 */
b7cb93e52   Marcel Holtmann   Bluetooth: Merge ...
664
  	if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
665
  	    !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
93690c227   Marcel Holtmann   Bluetooth: Introd...
666
667
668
669
  	    !bacmp(&hdev->bdaddr, BDADDR_ANY)) {
  		if (bacmp(&hdev->static_addr, BDADDR_ANY))
  			settings |= MGMT_SETTING_STATIC_ADDRESS;
  	}
69ab39ea5   Johan Hedberg   Bluetooth: Update...
670
671
  	return settings;
  }
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
672
673
674
675
  static struct mgmt_pending_cmd *pending_find(u16 opcode, struct hci_dev *hdev)
  {
  	return mgmt_pending_find(HCI_CHANNEL_CONTROL, opcode, hdev);
  }
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
676
677
678
679
680
681
  static struct mgmt_pending_cmd *pending_find_data(u16 opcode,
  						  struct hci_dev *hdev,
  						  const void *data)
  {
  	return mgmt_pending_find_data(HCI_CHANNEL_CONTROL, opcode, hdev, data);
  }
f22525700   Johan Hedberg   Bluetooth: Move a...
682
  u8 mgmt_get_adv_discov_flags(struct hci_dev *hdev)
9a43e25ff   Johan Hedberg   Bluetooth: Update...
683
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
684
  	struct mgmt_pending_cmd *cmd;
9a43e25ff   Johan Hedberg   Bluetooth: Update...
685
686
687
688
  
  	/* If there's a pending mgmt command the flags will not yet have
  	 * their final values, so check for this first.
  	 */
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
689
  	cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
9a43e25ff   Johan Hedberg   Bluetooth: Update...
690
691
692
693
694
695
696
  	if (cmd) {
  		struct mgmt_mode *cp = cmd->param;
  		if (cp->val == 0x01)
  			return LE_AD_GENERAL;
  		else if (cp->val == 0x02)
  			return LE_AD_LIMITED;
  	} else {
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
697
  		if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
9a43e25ff   Johan Hedberg   Bluetooth: Update...
698
  			return LE_AD_LIMITED;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
699
  		else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
9a43e25ff   Johan Hedberg   Bluetooth: Update...
700
701
702
703
704
  			return LE_AD_GENERAL;
  	}
  
  	return 0;
  }
f22525700   Johan Hedberg   Bluetooth: Move a...
705
  bool mgmt_get_connectable(struct hci_dev *hdev)
fdf51784c   Arman Uguray   Bluetooth: Unify ...
706
707
  {
  	struct mgmt_pending_cmd *cmd;
441ad2d04   Marcel Holtmann   Bluetooth: Update...
708

fdf51784c   Arman Uguray   Bluetooth: Unify ...
709
710
711
712
713
714
  	/* If there's a pending mgmt command the flag will not yet have
  	 * it's final value, so check for this first.
  	 */
  	cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
  	if (cmd) {
  		struct mgmt_mode *cp = cmd->param;
441ad2d04   Marcel Holtmann   Bluetooth: Update...
715

fdf51784c   Arman Uguray   Bluetooth: Unify ...
716
  		return cp->val;
441ad2d04   Marcel Holtmann   Bluetooth: Update...
717
  	}
fdf51784c   Arman Uguray   Bluetooth: Unify ...
718
719
  	return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
  }
441ad2d04   Marcel Holtmann   Bluetooth: Update...
720

7d78525dc   Johan Hedberg   Bluetooth: Add ti...
721
722
723
  static void service_cache_off(struct work_struct *work)
  {
  	struct hci_dev *hdev = container_of(work, struct hci_dev,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
724
  					    service_cache.work);
890ea8988   Johan Hedberg   Bluetooth: Update...
725
  	struct hci_request req;
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
726

a69d89272   Marcel Holtmann   Bluetooth: Introd...
727
  	if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
728
  		return;
890ea8988   Johan Hedberg   Bluetooth: Update...
729
  	hci_req_init(&req, hdev);
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
730
  	hci_dev_lock(hdev);
b1a8917c9   Johan Hedberg   Bluetooth: Move E...
731
  	__hci_req_update_eir(&req);
14bf5eac7   Johan Hedberg   Bluetooth: Perfor...
732
  	__hci_req_update_class(&req);
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
733
734
  
  	hci_dev_unlock(hdev);
890ea8988   Johan Hedberg   Bluetooth: Update...
735
736
  
  	hci_req_run(&req, NULL);
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
737
  }
d6bfd59ca   Johan Hedberg   Bluetooth: Add ti...
738
739
740
741
742
743
744
  static void rpa_expired(struct work_struct *work)
  {
  	struct hci_dev *hdev = container_of(work, struct hci_dev,
  					    rpa_expired.work);
  	struct hci_request req;
  
  	BT_DBG("");
a1536da25   Marcel Holtmann   Bluetooth: Introd...
745
  	hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
d6bfd59ca   Johan Hedberg   Bluetooth: Add ti...
746

d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
747
  	if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
d6bfd59ca   Johan Hedberg   Bluetooth: Add ti...
748
749
750
  		return;
  
  	/* The generation of a new RPA and programming it into the
f22525700   Johan Hedberg   Bluetooth: Move a...
751
752
  	 * controller happens in the hci_req_enable_advertising()
  	 * function.
d6bfd59ca   Johan Hedberg   Bluetooth: Add ti...
753
  	 */
d6bfd59ca   Johan Hedberg   Bluetooth: Add ti...
754
  	hci_req_init(&req, hdev);
f22525700   Johan Hedberg   Bluetooth: Move a...
755
  	__hci_req_enable_advertising(&req);
d6bfd59ca   Johan Hedberg   Bluetooth: Add ti...
756
757
  	hci_req_run(&req, NULL);
  }
6a919082e   Johan Hedberg   Bluetooth: mgmt: ...
758
  static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
759
  {
238be788f   Marcel Holtmann   Bluetooth: Introd...
760
  	if (hci_dev_test_and_set_flag(hdev, HCI_MGMT))
6a919082e   Johan Hedberg   Bluetooth: mgmt: ...
761
  		return;
4f87da80a   Johan Hedberg   Bluetooth: Remove...
762
  	INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
d6bfd59ca   Johan Hedberg   Bluetooth: Add ti...
763
  	INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
764

4f87da80a   Johan Hedberg   Bluetooth: Remove...
765
766
767
768
769
  	/* Non-mgmt controlled devices get this bit set
  	 * implicitly so that pairing works for them, however
  	 * for mgmt we require user-space to explicitly enable
  	 * it
  	 */
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
770
  	hci_dev_clear_flag(hdev, HCI_BONDABLE);
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
771
  }
0f4e68cf6   Johan Hedberg   Bluetooth: mgmt: ...
772
  static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
773
  				void *data, u16 data_len)
0381101fd   Johan Hedberg   Bluetooth: Add in...
774
  {
a38528f11   Johan Hedberg   Bluetooth: Create...
775
  	struct mgmt_rp_read_info rp;
f7b64e69c   Johan Hedberg   Bluetooth: Add re...
776

bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
777
  	BT_DBG("sock %p %s", sk, hdev->name);
f7b64e69c   Johan Hedberg   Bluetooth: Add re...
778

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
779
  	hci_dev_lock(hdev);
f7b64e69c   Johan Hedberg   Bluetooth: Add re...
780

dc4fe30b8   Johan Hedberg   Bluetooth: mgmt: ...
781
  	memset(&rp, 0, sizeof(rp));
69ab39ea5   Johan Hedberg   Bluetooth: Update...
782
  	bacpy(&rp.bdaddr, &hdev->bdaddr);
f7b64e69c   Johan Hedberg   Bluetooth: Add re...
783

69ab39ea5   Johan Hedberg   Bluetooth: Update...
784
  	rp.version = hdev->hci_ver;
eb55ef07a   Marcel Holtmann   Bluetooth: Fix br...
785
  	rp.manufacturer = cpu_to_le16(hdev->manufacturer);
69ab39ea5   Johan Hedberg   Bluetooth: Update...
786
787
788
  
  	rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
  	rp.current_settings = cpu_to_le32(get_current_settings(hdev));
f7b64e69c   Johan Hedberg   Bluetooth: Add re...
789

a38528f11   Johan Hedberg   Bluetooth: Create...
790
  	memcpy(rp.dev_class, hdev->dev_class, 3);
f7b64e69c   Johan Hedberg   Bluetooth: Add re...
791

dc4fe30b8   Johan Hedberg   Bluetooth: mgmt: ...
792
  	memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
27fcc3622   Johan Hedberg   Bluetooth: mgmt: ...
793
  	memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
dc4fe30b8   Johan Hedberg   Bluetooth: mgmt: ...
794

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
795
  	hci_dev_unlock(hdev);
0381101fd   Johan Hedberg   Bluetooth: Add in...
796

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
797
798
  	return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
  				 sizeof(rp));
0381101fd   Johan Hedberg   Bluetooth: Add in...
799
  }
cde7a863d   MichaƂ Narajowski   Bluetooth: Factor...
800
801
802
803
804
805
806
807
  static u16 append_eir_data_to_buf(struct hci_dev *hdev, u8 *eir)
  {
  	u16 eir_len = 0;
  	size_t name_len;
  
  	if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
  		eir_len = eir_append_data(eir, eir_len, EIR_CLASS_OF_DEV,
  					  hdev->dev_class, 3);
6a9e90bff   Szymon Janc   Bluetooth: Add ap...
808
809
810
  	if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
  		eir_len = eir_append_le16(eir, eir_len, EIR_APPEARANCE,
  					  hdev->appearance);
cde7a863d   MichaƂ Narajowski   Bluetooth: Factor...
811
812
813
814
815
816
817
818
819
820
  	name_len = strlen(hdev->dev_name);
  	eir_len = eir_append_data(eir, eir_len, EIR_NAME_COMPLETE,
  				  hdev->dev_name, name_len);
  
  	name_len = strlen(hdev->short_name);
  	eir_len = eir_append_data(eir, eir_len, EIR_NAME_SHORT,
  				  hdev->short_name, name_len);
  
  	return eir_len;
  }
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
821
822
823
  static int read_ext_controller_info(struct sock *sk, struct hci_dev *hdev,
  				    void *data, u16 data_len)
  {
7d5c11da1   Szymon Janc   Bluetooth: Refact...
824
825
  	char buf[512];
  	struct mgmt_rp_read_ext_info *rp = (void *)buf;
cde7a863d   MichaƂ Narajowski   Bluetooth: Factor...
826
  	u16 eir_len;
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
827
828
  
  	BT_DBG("sock %p %s", sk, hdev->name);
7d5c11da1   Szymon Janc   Bluetooth: Refact...
829
  	memset(&buf, 0, sizeof(buf));
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
830
  	hci_dev_lock(hdev);
7d5c11da1   Szymon Janc   Bluetooth: Refact...
831
832
833
834
835
836
837
  	bacpy(&rp->bdaddr, &hdev->bdaddr);
  
  	rp->version = hdev->hci_ver;
  	rp->manufacturer = cpu_to_le16(hdev->manufacturer);
  
  	rp->supported_settings = cpu_to_le32(get_supported_settings(hdev));
  	rp->current_settings = cpu_to_le32(get_current_settings(hdev));
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
838

cde7a863d   MichaƂ Narajowski   Bluetooth: Factor...
839
  	eir_len = append_eir_data_to_buf(hdev, rp->eir);
8a0c9f490   MichaƂ Narajowski   Bluetooth: Append...
840
  	rp->eir_len = cpu_to_le16(eir_len);
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
841
842
843
844
845
846
847
848
849
850
851
  
  	hci_dev_unlock(hdev);
  
  	/* If this command is called at least once, then the events
  	 * for class of device and local name changes are disabled
  	 * and only the new extended controller information event
  	 * is used.
  	 */
  	hci_sock_set_flag(sk, HCI_MGMT_EXT_INFO_EVENTS);
  	hci_sock_clear_flag(sk, HCI_MGMT_DEV_CLASS_EVENTS);
  	hci_sock_clear_flag(sk, HCI_MGMT_LOCAL_NAME_EVENTS);
8a0c9f490   MichaƂ Narajowski   Bluetooth: Append...
852
853
  	return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_EXT_INFO, 0, rp,
  				 sizeof(*rp) + eir_len);
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
854
855
856
857
  }
  
  static int ext_info_changed(struct hci_dev *hdev, struct sock *skip)
  {
5e9fae48f   MichaƂ Narajowski   Bluetooth: Add su...
858
859
860
861
862
  	char buf[512];
  	struct mgmt_ev_ext_info_changed *ev = (void *)buf;
  	u16 eir_len;
  
  	memset(buf, 0, sizeof(buf));
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
863

5e9fae48f   MichaƂ Narajowski   Bluetooth: Add su...
864
865
  	eir_len = append_eir_data_to_buf(hdev, ev->eir);
  	ev->eir_len = cpu_to_le16(eir_len);
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
866

5e9fae48f   MichaƂ Narajowski   Bluetooth: Add su...
867
868
869
  	return mgmt_limited_event(MGMT_EV_EXT_INFO_CHANGED, hdev, ev,
  				  sizeof(*ev) + eir_len,
  				  HCI_MGMT_EXT_INFO_EVENTS, skip);
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
870
  }
69ab39ea5   Johan Hedberg   Bluetooth: Update...
871
  static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
8680570b0   Johan Hedberg   Bluetooth: Return...
872
  {
69ab39ea5   Johan Hedberg   Bluetooth: Update...
873
  	__le32 settings = cpu_to_le32(get_current_settings(hdev));
8680570b0   Johan Hedberg   Bluetooth: Return...
874

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
875
876
  	return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
  				 sizeof(settings));
8680570b0   Johan Hedberg   Bluetooth: Return...
877
  }
1904a853f   Marcel Holtmann   Bluetooth: Add op...
878
  static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
879
880
  {
  	BT_DBG("%s status 0x%02x", hdev->name, status);
a3172b7eb   Johan Hedberg   Bluetooth: Add ti...
881
882
  	if (hci_conn_count(hdev) == 0) {
  		cancel_delayed_work(&hdev->power_off);
8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
883
  		queue_work(hdev->req_workqueue, &hdev->power_off.work);
a3172b7eb   Johan Hedberg   Bluetooth: Add ti...
884
  	}
8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
885
  }
f22525700   Johan Hedberg   Bluetooth: Move a...
886
  void mgmt_advertising_added(struct sock *sk, struct hci_dev *hdev, u8 instance)
912098a63   Arman Uguray   Bluetooth: Add su...
887
888
889
890
891
892
893
  {
  	struct mgmt_ev_advertising_added ev;
  
  	ev.instance = instance;
  
  	mgmt_event(MGMT_EV_ADVERTISING_ADDED, hdev, &ev, sizeof(ev), sk);
  }
f22525700   Johan Hedberg   Bluetooth: Move a...
894
895
  void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev,
  			      u8 instance)
912098a63   Arman Uguray   Bluetooth: Add su...
896
897
898
899
900
901
902
  {
  	struct mgmt_ev_advertising_removed ev;
  
  	ev.instance = instance;
  
  	mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk);
  }
7816b8203   Florian Grandel   Bluetooth: mgmt: ...
903
904
905
906
907
908
909
  static void cancel_adv_timeout(struct hci_dev *hdev)
  {
  	if (hdev->adv_instance_timeout) {
  		hdev->adv_instance_timeout = 0;
  		cancel_delayed_work(&hdev->adv_instance_expire);
  	}
  }
8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
910
911
912
913
  static int clean_up_hci_state(struct hci_dev *hdev)
  {
  	struct hci_request req;
  	struct hci_conn *conn;
23a48093b   Johan Hedberg   Bluetooth: Fix se...
914
915
  	bool discov_stopped;
  	int err;
8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
916
917
918
919
920
921
922
923
  
  	hci_req_init(&req, hdev);
  
  	if (test_bit(HCI_ISCAN, &hdev->flags) ||
  	    test_bit(HCI_PSCAN, &hdev->flags)) {
  		u8 scan = 0x00;
  		hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
  	}
37d3a1fab   Johan Hedberg   Bluetooth: mgmt: ...
924
  	hci_req_clear_adv_instance(hdev, NULL, NULL, 0x00, false);
912098a63   Arman Uguray   Bluetooth: Add su...
925

d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
926
  	if (hci_dev_test_flag(hdev, HCI_LE_ADV))
f22525700   Johan Hedberg   Bluetooth: Move a...
927
  		__hci_req_disable_advertising(&req);
8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
928

2154d3f4f   Johan Hedberg   Bluetooth: Move S...
929
  	discov_stopped = hci_req_stop_discovery(&req);
8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
930
931
  
  	list_for_each_entry(conn, &hdev->conn_hash.list, list) {
89e0ccc88   Johan Hedberg   Bluetooth: Take a...
932
933
  		/* 0x15 == Terminated due to Power Off */
  		__hci_abort_conn(&req, conn, 0x15);
8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
934
  	}
23a48093b   Johan Hedberg   Bluetooth: Fix se...
935
936
937
938
939
  	err = hci_req_run(&req, clean_up_hci_complete);
  	if (!err && discov_stopped)
  		hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
  
  	return err;
8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
940
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
941
  static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
942
  		       u16 len)
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
943
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
944
  	struct mgmt_mode *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
945
  	struct mgmt_pending_cmd *cmd;
4b34ee782   Johan Hedberg   Bluetooth: mgmt: ...
946
  	int err;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
947

bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
948
  	BT_DBG("request for %s", hdev->name);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
949

a7e80f25a   Johan Hedberg   Bluetooth: Fix ch...
950
  	if (cp->val != 0x00 && cp->val != 0x01)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
951
952
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
  				       MGMT_STATUS_INVALID_PARAMS);
a7e80f25a   Johan Hedberg   Bluetooth: Fix ch...
953

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
954
  	hci_dev_lock(hdev);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
955

333ae95d0   Johan Hedberg   Bluetooth: Add ch...
956
  	if (pending_find(MGMT_OP_SET_POWERED, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
957
958
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
  				      MGMT_STATUS_BUSY);
87b95ba64   Johan Hedberg   Bluetooth: Fix bu...
959
960
  		goto failed;
  	}
4b34ee782   Johan Hedberg   Bluetooth: mgmt: ...
961
  	if (!!cp->val == hdev_is_powered(hdev)) {
69ab39ea5   Johan Hedberg   Bluetooth: Update...
962
  		err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
963
964
  		goto failed;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
965
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
366a03369   Johan Hedberg   Bluetooth: Make p...
966
967
  	if (!cmd) {
  		err = -ENOMEM;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
968
  		goto failed;
366a03369   Johan Hedberg   Bluetooth: Make p...
969
  	}
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
970

8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
971
  	if (cp->val) {
192025731   Johan Hedberg   Bluetooth: Use re...
972
  		queue_work(hdev->req_workqueue, &hdev->power_on);
8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
973
974
975
976
  		err = 0;
  	} else {
  		/* Disconnect connections, stop scans, etc */
  		err = clean_up_hci_state(hdev);
a3172b7eb   Johan Hedberg   Bluetooth: Add ti...
977
978
979
  		if (!err)
  			queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
  					   HCI_POWER_OFF_TIMEOUT);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
980

8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
981
982
  		/* ENODATA means there were no HCI commands queued */
  		if (err == -ENODATA) {
a3172b7eb   Johan Hedberg   Bluetooth: Add ti...
983
  			cancel_delayed_work(&hdev->power_off);
8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
984
985
986
987
  			queue_work(hdev->req_workqueue, &hdev->power_off.work);
  			err = 0;
  		}
  	}
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
988
989
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
990
  	hci_dev_unlock(hdev);
366a03369   Johan Hedberg   Bluetooth: Make p...
991
  	return err;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
992
  }
beadb2bdd   Johan Hedberg   Bluetooth: mgmt: ...
993
994
  static int new_settings(struct hci_dev *hdev, struct sock *skip)
  {
f6b7712eb   Marcel Holtmann   Bluetooth: Send g...
995
  	__le32 ev = cpu_to_le32(get_current_settings(hdev));
beadb2bdd   Johan Hedberg   Bluetooth: mgmt: ...
996

5504c3a31   Marcel Holtmann   Bluetooth: Use in...
997
998
  	return mgmt_limited_event(MGMT_EV_NEW_SETTINGS, hdev, &ev,
  				  sizeof(ev), HCI_MGMT_SETTING_EVENTS, skip);
beadb2bdd   Johan Hedberg   Bluetooth: mgmt: ...
999
  }
91a668b05   Johan Hedberg   Bluetooth: Fix se...
1000
1001
1002
1003
  int mgmt_new_settings(struct hci_dev *hdev)
  {
  	return new_settings(hdev, NULL);
  }
bd99abdd5   Johan Hedberg   Bluetooth: Move m...
1004
1005
1006
1007
1008
  struct cmd_lookup {
  	struct sock *sk;
  	struct hci_dev *hdev;
  	u8 mgmt_status;
  };
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1009
  static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
bd99abdd5   Johan Hedberg   Bluetooth: Move m...
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
  {
  	struct cmd_lookup *match = data;
  
  	send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
  
  	list_del(&cmd->list);
  
  	if (match->sk == NULL) {
  		match->sk = cmd->sk;
  		sock_hold(match->sk);
  	}
  
  	mgmt_pending_free(cmd);
  }
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1024
  static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
bd99abdd5   Johan Hedberg   Bluetooth: Move m...
1025
1026
  {
  	u8 *status = data;
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1027
  	mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
bd99abdd5   Johan Hedberg   Bluetooth: Move m...
1028
1029
  	mgmt_pending_remove(cmd);
  }
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1030
  static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
1b9b5ee53   Johan Hedberg   Bluetooth: Add ca...
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
  {
  	if (cmd->cmd_complete) {
  		u8 *status = data;
  
  		cmd->cmd_complete(cmd, *status);
  		mgmt_pending_remove(cmd);
  
  		return;
  	}
  
  	cmd_status_rsp(cmd, data);
  }
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1043
  static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
f5818c224   Johan Hedberg   Bluetooth: Conver...
1044
  {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
1045
1046
  	return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
  				 cmd->param, cmd->param_len);
f5818c224   Johan Hedberg   Bluetooth: Conver...
1047
  }
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1048
  static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
7776d1d80   Johan Hedberg   Bluetooth: Use cm...
1049
  {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
1050
1051
  	return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
  				 cmd->param, sizeof(struct mgmt_addr_info));
7776d1d80   Johan Hedberg   Bluetooth: Use cm...
1052
  }
e6fe79865   Johan Hedberg   Bluetooth: Fix RE...
1053
1054
1055
1056
  static u8 mgmt_bredr_support(struct hci_dev *hdev)
  {
  	if (!lmp_bredr_capable(hdev))
  		return MGMT_STATUS_NOT_SUPPORTED;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1057
  	else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
e6fe79865   Johan Hedberg   Bluetooth: Fix RE...
1058
1059
1060
1061
1062
1063
1064
1065
1066
  		return MGMT_STATUS_REJECTED;
  	else
  		return MGMT_STATUS_SUCCESS;
  }
  
  static u8 mgmt_le_support(struct hci_dev *hdev)
  {
  	if (!lmp_le_capable(hdev))
  		return MGMT_STATUS_NOT_SUPPORTED;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1067
  	else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
e6fe79865   Johan Hedberg   Bluetooth: Fix RE...
1068
1069
1070
1071
  		return MGMT_STATUS_REJECTED;
  	else
  		return MGMT_STATUS_SUCCESS;
  }
aed1a8851   Johan Hedberg   Bluetooth: Move d...
1072
  void mgmt_set_discoverable_complete(struct hci_dev *hdev, u8 status)
bfaf8c9ff   Johan Hedberg   Bluetooth: Conver...
1073
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1074
  	struct mgmt_pending_cmd *cmd;
bfaf8c9ff   Johan Hedberg   Bluetooth: Conver...
1075
1076
1077
1078
  
  	BT_DBG("status 0x%02x", status);
  
  	hci_dev_lock(hdev);
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
1079
  	cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
bfaf8c9ff   Johan Hedberg   Bluetooth: Conver...
1080
1081
1082
1083
1084
  	if (!cmd)
  		goto unlock;
  
  	if (status) {
  		u8 mgmt_err = mgmt_status(status);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1085
  		mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
1086
  		hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
bfaf8c9ff   Johan Hedberg   Bluetooth: Conver...
1087
1088
  		goto remove_cmd;
  	}
aed1a8851   Johan Hedberg   Bluetooth: Move d...
1089
1090
1091
1092
  	if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
  	    hdev->discov_timeout > 0) {
  		int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
  		queue_delayed_work(hdev->req_workqueue, &hdev->discov_off, to);
d4462a07d   Marcel Holtmann   Bluetooth: Move a...
1093
  	}
bfaf8c9ff   Johan Hedberg   Bluetooth: Conver...
1094
1095
  
  	send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
aed1a8851   Johan Hedberg   Bluetooth: Move d...
1096
  	new_settings(hdev, cmd->sk);
970ba5242   Marcel Holtmann   Bluetooth: Update...
1097

bfaf8c9ff   Johan Hedberg   Bluetooth: Conver...
1098
1099
1100
1101
1102
1103
  remove_cmd:
  	mgmt_pending_remove(cmd);
  
  unlock:
  	hci_dev_unlock(hdev);
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1104
  static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
1105
  			    u16 len)
73f22f623   Johan Hedberg   Bluetooth: Add su...
1106
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
1107
  	struct mgmt_cp_set_discoverable *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1108
  	struct mgmt_pending_cmd *cmd;
5e5282bbf   Johan Hedberg   Bluetooth: mgmt: ...
1109
  	u16 timeout;
73f22f623   Johan Hedberg   Bluetooth: Add su...
1110
  	int err;
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1111
  	BT_DBG("request for %s", hdev->name);
73f22f623   Johan Hedberg   Bluetooth: Add su...
1112

d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1113
1114
  	if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
  	    !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1115
1116
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
  				       MGMT_STATUS_REJECTED);
33c525c0a   Johan Hedberg   Bluetooth: mgmt: ...
1117

310a3d485   Marcel Holtmann   Bluetooth: Add su...
1118
  	if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1119
1120
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
  				       MGMT_STATUS_INVALID_PARAMS);
a7e80f25a   Johan Hedberg   Bluetooth: Fix ch...
1121

1f350c872   Marcel Holtmann   Bluetooth: Fix br...
1122
  	timeout = __le16_to_cpu(cp->timeout);
310a3d485   Marcel Holtmann   Bluetooth: Add su...
1123
1124
1125
1126
1127
1128
  
  	/* Disabling discoverable requires that no timeout is set,
  	 * and enabling limited discoverable requires a timeout.
  	 */
  	if ((cp->val == 0x00 && timeout > 0) ||
  	    (cp->val == 0x02 && timeout == 0))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1129
1130
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
  				       MGMT_STATUS_INVALID_PARAMS);
73f22f623   Johan Hedberg   Bluetooth: Add su...
1131

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1132
  	hci_dev_lock(hdev);
73f22f623   Johan Hedberg   Bluetooth: Add su...
1133

5e5282bbf   Johan Hedberg   Bluetooth: mgmt: ...
1134
  	if (!hdev_is_powered(hdev) && timeout > 0) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1135
1136
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
  				      MGMT_STATUS_NOT_POWERED);
73f22f623   Johan Hedberg   Bluetooth: Add su...
1137
1138
  		goto failed;
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
1139
1140
  	if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
  	    pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1141
1142
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
  				      MGMT_STATUS_BUSY);
73f22f623   Johan Hedberg   Bluetooth: Add su...
1143
1144
  		goto failed;
  	}
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1145
  	if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1146
1147
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
  				      MGMT_STATUS_REJECTED);
5e5282bbf   Johan Hedberg   Bluetooth: mgmt: ...
1148
1149
1150
1151
  		goto failed;
  	}
  
  	if (!hdev_is_powered(hdev)) {
0224d2faf   Johan Hedberg   Bluetooth: mgmt: ...
1152
  		bool changed = false;
310a3d485   Marcel Holtmann   Bluetooth: Add su...
1153
1154
1155
1156
  		/* Setting limited discoverable when powered off is
  		 * not a valid operation since it requires a timeout
  		 * and so no need to check HCI_LIMITED_DISCOVERABLE.
  		 */
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1157
  		if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
ce05d603a   Marcel Holtmann   Bluetooth: Introd...
1158
  			hci_dev_change_flag(hdev, HCI_DISCOVERABLE);
0224d2faf   Johan Hedberg   Bluetooth: mgmt: ...
1159
1160
  			changed = true;
  		}
5e5282bbf   Johan Hedberg   Bluetooth: mgmt: ...
1161
  		err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
0224d2faf   Johan Hedberg   Bluetooth: mgmt: ...
1162
1163
1164
1165
1166
  		if (err < 0)
  			goto failed;
  
  		if (changed)
  			err = new_settings(hdev, sk);
5e5282bbf   Johan Hedberg   Bluetooth: mgmt: ...
1167
1168
  		goto failed;
  	}
310a3d485   Marcel Holtmann   Bluetooth: Add su...
1169
1170
1171
1172
  	/* If the current mode is the same, then just update the timeout
  	 * value with the new value. And if only the timeout gets updated,
  	 * then no need for any HCI transactions.
  	 */
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1173
1174
1175
  	if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
  	    (cp->val == 0x02) == hci_dev_test_flag(hdev,
  						   HCI_LIMITED_DISCOVERABLE)) {
36261547c   Marcel Holtmann   Bluetooth: Simpli...
1176
1177
  		cancel_delayed_work(&hdev->discov_off);
  		hdev->discov_timeout = timeout;
955638ece   Marcel Holtmann   Bluetooth: Fix ha...
1178

36261547c   Marcel Holtmann   Bluetooth: Simpli...
1179
1180
  		if (cp->val && hdev->discov_timeout > 0) {
  			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
c366f555b   Johan Hedberg   Bluetooth: Move d...
1181
1182
  			queue_delayed_work(hdev->req_workqueue,
  					   &hdev->discov_off, to);
955638ece   Marcel Holtmann   Bluetooth: Fix ha...
1183
  		}
69ab39ea5   Johan Hedberg   Bluetooth: Update...
1184
  		err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
73f22f623   Johan Hedberg   Bluetooth: Add su...
1185
1186
  		goto failed;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
1187
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
366a03369   Johan Hedberg   Bluetooth: Make p...
1188
1189
  	if (!cmd) {
  		err = -ENOMEM;
73f22f623   Johan Hedberg   Bluetooth: Add su...
1190
  		goto failed;
366a03369   Johan Hedberg   Bluetooth: Make p...
1191
  	}
73f22f623   Johan Hedberg   Bluetooth: Add su...
1192

310a3d485   Marcel Holtmann   Bluetooth: Add su...
1193
1194
1195
1196
1197
1198
  	/* Cancel any potential discoverable timeout that might be
  	 * still active and store new timeout value. The arming of
  	 * the timeout happens in the complete handler.
  	 */
  	cancel_delayed_work(&hdev->discov_off);
  	hdev->discov_timeout = timeout;
aed1a8851   Johan Hedberg   Bluetooth: Move d...
1199
1200
1201
1202
  	if (cp->val)
  		hci_dev_set_flag(hdev, HCI_DISCOVERABLE);
  	else
  		hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
b456f87cb   Johan Hedberg   Bluetooth: Move H...
1203
1204
  	/* Limited discoverable mode */
  	if (cp->val == 0x02)
a1536da25   Marcel Holtmann   Bluetooth: Introd...
1205
  		hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
b456f87cb   Johan Hedberg   Bluetooth: Move H...
1206
  	else
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
1207
  		hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
b456f87cb   Johan Hedberg   Bluetooth: Move H...
1208

aed1a8851   Johan Hedberg   Bluetooth: Move d...
1209
1210
  	queue_work(hdev->req_workqueue, &hdev->discoverable_update);
  	err = 0;
73f22f623   Johan Hedberg   Bluetooth: Add su...
1211
1212
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1213
  	hci_dev_unlock(hdev);
73f22f623   Johan Hedberg   Bluetooth: Add su...
1214
1215
  	return err;
  }
53c0ba745   Johan Hedberg   Bluetooth: Move c...
1216
  void mgmt_set_connectable_complete(struct hci_dev *hdev, u8 status)
2b76f4539   Johan Hedberg   Bluetooth: Use an...
1217
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1218
  	struct mgmt_pending_cmd *cmd;
2b76f4539   Johan Hedberg   Bluetooth: Use an...
1219
1220
1221
1222
  
  	BT_DBG("status 0x%02x", status);
  
  	hci_dev_lock(hdev);
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
1223
  	cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
2b76f4539   Johan Hedberg   Bluetooth: Use an...
1224
1225
  	if (!cmd)
  		goto unlock;
37438c1f7   Johan Hedberg   Bluetooth: Add mi...
1226
1227
  	if (status) {
  		u8 mgmt_err = mgmt_status(status);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1228
  		mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
37438c1f7   Johan Hedberg   Bluetooth: Add mi...
1229
1230
  		goto remove_cmd;
  	}
2b76f4539   Johan Hedberg   Bluetooth: Use an...
1231
  	send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
53c0ba745   Johan Hedberg   Bluetooth: Move c...
1232
  	new_settings(hdev, cmd->sk);
d7b856f93   Johan Hedberg   Bluetooth: Move m...
1233

37438c1f7   Johan Hedberg   Bluetooth: Add mi...
1234
  remove_cmd:
2b76f4539   Johan Hedberg   Bluetooth: Use an...
1235
1236
1237
1238
1239
  	mgmt_pending_remove(cmd);
  
  unlock:
  	hci_dev_unlock(hdev);
  }
e8ba3a1f0   Johan Hedberg   Bluetooth: Refact...
1240
1241
1242
1243
1244
  static int set_connectable_update_settings(struct hci_dev *hdev,
  					   struct sock *sk, u8 val)
  {
  	bool changed = false;
  	int err;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1245
  	if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
e8ba3a1f0   Johan Hedberg   Bluetooth: Refact...
1246
1247
1248
  		changed = true;
  
  	if (val) {
a1536da25   Marcel Holtmann   Bluetooth: Introd...
1249
  		hci_dev_set_flag(hdev, HCI_CONNECTABLE);
e8ba3a1f0   Johan Hedberg   Bluetooth: Refact...
1250
  	} else {
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
1251
1252
  		hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
  		hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
e8ba3a1f0   Johan Hedberg   Bluetooth: Refact...
1253
1254
1255
1256
1257
  	}
  
  	err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
  	if (err < 0)
  		return err;
562064e65   Johan Hedberg   Bluetooth: Fix to...
1258
  	if (changed) {
01b1cb87d   Johan Hedberg   Bluetooth: Run pa...
1259
  		hci_req_update_scan(hdev);
562064e65   Johan Hedberg   Bluetooth: Fix to...
1260
  		hci_update_background_scan(hdev);
e8ba3a1f0   Johan Hedberg   Bluetooth: Refact...
1261
  		return new_settings(hdev, sk);
562064e65   Johan Hedberg   Bluetooth: Fix to...
1262
  	}
e8ba3a1f0   Johan Hedberg   Bluetooth: Refact...
1263
1264
1265
  
  	return 0;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1266
  static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
1267
  			   u16 len)
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
1268
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
1269
  	struct mgmt_mode *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1270
  	struct mgmt_pending_cmd *cmd;
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
1271
  	int err;
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1272
  	BT_DBG("request for %s", hdev->name);
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
1273

d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1274
1275
  	if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
  	    !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1276
1277
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
  				       MGMT_STATUS_REJECTED);
33c525c0a   Johan Hedberg   Bluetooth: mgmt: ...
1278

a7e80f25a   Johan Hedberg   Bluetooth: Fix ch...
1279
  	if (cp->val != 0x00 && cp->val != 0x01)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1280
1281
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
  				       MGMT_STATUS_INVALID_PARAMS);
a7e80f25a   Johan Hedberg   Bluetooth: Fix ch...
1282

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1283
  	hci_dev_lock(hdev);
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
1284

4b34ee782   Johan Hedberg   Bluetooth: mgmt: ...
1285
  	if (!hdev_is_powered(hdev)) {
e8ba3a1f0   Johan Hedberg   Bluetooth: Refact...
1286
  		err = set_connectable_update_settings(hdev, sk, cp->val);
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
1287
1288
  		goto failed;
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
1289
1290
  	if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
  	    pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1291
1292
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
  				      MGMT_STATUS_BUSY);
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
1293
1294
  		goto failed;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
1295
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
366a03369   Johan Hedberg   Bluetooth: Make p...
1296
1297
  	if (!cmd) {
  		err = -ENOMEM;
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
1298
  		goto failed;
366a03369   Johan Hedberg   Bluetooth: Make p...
1299
  	}
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
1300

53c0ba745   Johan Hedberg   Bluetooth: Move c...
1301
1302
1303
1304
1305
  	if (cp->val) {
  		hci_dev_set_flag(hdev, HCI_CONNECTABLE);
  	} else {
  		if (hdev->discov_timeout > 0)
  			cancel_delayed_work(&hdev->discov_off);
2b76f4539   Johan Hedberg   Bluetooth: Use an...
1306

53c0ba745   Johan Hedberg   Bluetooth: Move c...
1307
1308
1309
  		hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
  		hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
  		hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
9b74246f3   Johan Hedberg   Bluetooth: Reorga...
1310
  	}
2b76f4539   Johan Hedberg   Bluetooth: Use an...
1311

53c0ba745   Johan Hedberg   Bluetooth: Move c...
1312
1313
  	queue_work(hdev->req_workqueue, &hdev->connectable_update);
  	err = 0;
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
1314
1315
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1316
  	hci_dev_unlock(hdev);
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
1317
1318
  	return err;
  }
b2939475e   Johan Hedberg   Bluetooth: Rename...
1319
  static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
1320
  			u16 len)
c542a06c2   Johan Hedberg   Bluetooth: Implem...
1321
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
1322
  	struct mgmt_mode *cp = data;
555943565   Marcel Holtmann   Bluetooth: Send n...
1323
  	bool changed;
c542a06c2   Johan Hedberg   Bluetooth: Implem...
1324
  	int err;
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1325
  	BT_DBG("request for %s", hdev->name);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
1326

a7e80f25a   Johan Hedberg   Bluetooth: Fix ch...
1327
  	if (cp->val != 0x00 && cp->val != 0x01)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1328
1329
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
  				       MGMT_STATUS_INVALID_PARAMS);
a7e80f25a   Johan Hedberg   Bluetooth: Fix ch...
1330

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1331
  	hci_dev_lock(hdev);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
1332
1333
  
  	if (cp->val)
238be788f   Marcel Holtmann   Bluetooth: Introd...
1334
  		changed = !hci_dev_test_and_set_flag(hdev, HCI_BONDABLE);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
1335
  	else
a69d89272   Marcel Holtmann   Bluetooth: Introd...
1336
  		changed = hci_dev_test_and_clear_flag(hdev, HCI_BONDABLE);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
1337

b2939475e   Johan Hedberg   Bluetooth: Rename...
1338
  	err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
1339
  	if (err < 0)
555943565   Marcel Holtmann   Bluetooth: Send n...
1340
  		goto unlock;
c542a06c2   Johan Hedberg   Bluetooth: Implem...
1341

82a37adee   Johan Hedberg   Bluetooth: Add su...
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
  	if (changed) {
  		/* In limited privacy mode the change of bondable mode
  		 * may affect the local advertising address.
  		 */
  		if (hdev_is_powered(hdev) &&
  		    hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
  		    hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
  		    hci_dev_test_flag(hdev, HCI_LIMITED_PRIVACY))
  			queue_work(hdev->req_workqueue,
  				   &hdev->discoverable_update);
555943565   Marcel Holtmann   Bluetooth: Send n...
1352
  		err = new_settings(hdev, sk);
82a37adee   Johan Hedberg   Bluetooth: Add su...
1353
  	}
c542a06c2   Johan Hedberg   Bluetooth: Implem...
1354

555943565   Marcel Holtmann   Bluetooth: Send n...
1355
  unlock:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1356
  	hci_dev_unlock(hdev);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
1357
1358
  	return err;
  }
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
1359
1360
  static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
  			     u16 len)
33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
1361
1362
  {
  	struct mgmt_mode *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1363
  	struct mgmt_pending_cmd *cmd;
e6fe79865   Johan Hedberg   Bluetooth: Fix RE...
1364
  	u8 val, status;
33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
1365
  	int err;
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1366
  	BT_DBG("request for %s", hdev->name);
33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
1367

e6fe79865   Johan Hedberg   Bluetooth: Fix RE...
1368
1369
  	status = mgmt_bredr_support(hdev);
  	if (status)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1370
1371
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
  				       status);
33c525c0a   Johan Hedberg   Bluetooth: mgmt: ...
1372

a7e80f25a   Johan Hedberg   Bluetooth: Fix ch...
1373
  	if (cp->val != 0x00 && cp->val != 0x01)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1374
1375
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
  				       MGMT_STATUS_INVALID_PARAMS);
a7e80f25a   Johan Hedberg   Bluetooth: Fix ch...
1376

33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
1377
  	hci_dev_lock(hdev);
4b34ee782   Johan Hedberg   Bluetooth: mgmt: ...
1378
  	if (!hdev_is_powered(hdev)) {
47990ea09   Johan Hedberg   Bluetooth: mgmt: ...
1379
  		bool changed = false;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1380
  		if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
ce05d603a   Marcel Holtmann   Bluetooth: Introd...
1381
  			hci_dev_change_flag(hdev, HCI_LINK_SECURITY);
47990ea09   Johan Hedberg   Bluetooth: mgmt: ...
1382
1383
1384
1385
1386
1387
1388
1389
1390
  			changed = true;
  		}
  
  		err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
  		if (err < 0)
  			goto failed;
  
  		if (changed)
  			err = new_settings(hdev, sk);
33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
1391
1392
  		goto failed;
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
1393
  	if (pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1394
1395
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
  				      MGMT_STATUS_BUSY);
33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
  		goto failed;
  	}
  
  	val = !!cp->val;
  
  	if (test_bit(HCI_AUTH, &hdev->flags) == val) {
  		err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
  		goto failed;
  	}
  
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
  	if (!cmd) {
  		err = -ENOMEM;
  		goto failed;
  	}
  
  	err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
  	if (err < 0) {
  		mgmt_pending_remove(cmd);
  		goto failed;
  	}
  
  failed:
  	hci_dev_unlock(hdev);
33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
1420
1421
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1422
  static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
1423
1424
  {
  	struct mgmt_mode *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1425
  	struct mgmt_pending_cmd *cmd;
72ef0c1a9   Marcel Holtmann   Bluetooth: Remove...
1426
  	u8 status;
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
1427
  	int err;
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1428
  	BT_DBG("request for %s", hdev->name);
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
1429

cdba5281b   Marcel Holtmann   Bluetooth: Restri...
1430
1431
  	status = mgmt_bredr_support(hdev);
  	if (status)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1432
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
cdba5281b   Marcel Holtmann   Bluetooth: Restri...
1433

13ecd8b66   Johan Hedberg   Bluetooth: Move n...
1434
  	if (!lmp_ssp_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1435
1436
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
  				       MGMT_STATUS_NOT_SUPPORTED);
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
1437

a7e80f25a   Johan Hedberg   Bluetooth: Fix ch...
1438
  	if (cp->val != 0x00 && cp->val != 0x01)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1439
1440
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
  				       MGMT_STATUS_INVALID_PARAMS);
a7e80f25a   Johan Hedberg   Bluetooth: Fix ch...
1441

13ecd8b66   Johan Hedberg   Bluetooth: Move n...
1442
  	hci_dev_lock(hdev);
6c8f12c14   Johan Hedberg   Bluetooth: mgmt: ...
1443

4b34ee782   Johan Hedberg   Bluetooth: mgmt: ...
1444
  	if (!hdev_is_powered(hdev)) {
9ecb3e242   Marcel Holtmann   Bluetooth: Restri...
1445
  		bool changed;
c0ecddc25   Johan Hedberg   Bluetooth: mgmt: ...
1446

9ecb3e242   Marcel Holtmann   Bluetooth: Restri...
1447
  		if (cp->val) {
238be788f   Marcel Holtmann   Bluetooth: Introd...
1448
1449
  			changed = !hci_dev_test_and_set_flag(hdev,
  							     HCI_SSP_ENABLED);
9ecb3e242   Marcel Holtmann   Bluetooth: Restri...
1450
  		} else {
a69d89272   Marcel Holtmann   Bluetooth: Introd...
1451
1452
  			changed = hci_dev_test_and_clear_flag(hdev,
  							      HCI_SSP_ENABLED);
9ecb3e242   Marcel Holtmann   Bluetooth: Restri...
1453
  			if (!changed)
a69d89272   Marcel Holtmann   Bluetooth: Introd...
1454
1455
  				changed = hci_dev_test_and_clear_flag(hdev,
  								      HCI_HS_ENABLED);
9ecb3e242   Marcel Holtmann   Bluetooth: Restri...
1456
  			else
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
1457
  				hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
c0ecddc25   Johan Hedberg   Bluetooth: mgmt: ...
1458
1459
1460
1461
1462
1463
1464
1465
  		}
  
  		err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
  		if (err < 0)
  			goto failed;
  
  		if (changed)
  			err = new_settings(hdev, sk);
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
1466
1467
  		goto failed;
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
1468
  	if (pending_find(MGMT_OP_SET_SSP, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1469
1470
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
  				      MGMT_STATUS_BUSY);
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
1471
1472
  		goto failed;
  	}
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1473
  	if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
1474
1475
1476
1477
1478
1479
1480
1481
1482
  		err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
  		goto failed;
  	}
  
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
  	if (!cmd) {
  		err = -ENOMEM;
  		goto failed;
  	}
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1483
  	if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
3769972ba   Johan Hedberg   Bluetooth: Add a ...
1484
1485
  		hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
  			     sizeof(cp->val), &cp->val);
72ef0c1a9   Marcel Holtmann   Bluetooth: Remove...
1486
  	err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
1487
1488
1489
1490
1491
1492
1493
  	if (err < 0) {
  		mgmt_pending_remove(cmd);
  		goto failed;
  	}
  
  failed:
  	hci_dev_unlock(hdev);
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
1494
1495
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1496
  static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
6d80dfd09   Johan Hedberg   Bluetooth: mgmt: ...
1497
1498
  {
  	struct mgmt_mode *cp = data;
ee3926936   Marcel Holtmann   Bluetooth: Send n...
1499
  	bool changed;
e6fe79865   Johan Hedberg   Bluetooth: Fix RE...
1500
  	u8 status;
ee3926936   Marcel Holtmann   Bluetooth: Send n...
1501
  	int err;
6d80dfd09   Johan Hedberg   Bluetooth: mgmt: ...
1502

bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1503
  	BT_DBG("request for %s", hdev->name);
6d80dfd09   Johan Hedberg   Bluetooth: mgmt: ...
1504

e6fe79865   Johan Hedberg   Bluetooth: Fix RE...
1505
1506
  	status = mgmt_bredr_support(hdev);
  	if (status)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1507
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
6d80dfd09   Johan Hedberg   Bluetooth: mgmt: ...
1508

9ecb3e242   Marcel Holtmann   Bluetooth: Restri...
1509
  	if (!lmp_ssp_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1510
1511
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
  				       MGMT_STATUS_NOT_SUPPORTED);
9ecb3e242   Marcel Holtmann   Bluetooth: Restri...
1512

d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1513
  	if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1514
1515
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
  				       MGMT_STATUS_REJECTED);
9ecb3e242   Marcel Holtmann   Bluetooth: Restri...
1516

a7e80f25a   Johan Hedberg   Bluetooth: Fix ch...
1517
  	if (cp->val != 0x00 && cp->val != 0x01)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1518
1519
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
  				       MGMT_STATUS_INVALID_PARAMS);
a7e80f25a   Johan Hedberg   Bluetooth: Fix ch...
1520

ee3926936   Marcel Holtmann   Bluetooth: Send n...
1521
  	hci_dev_lock(hdev);
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
1522
  	if (pending_find(MGMT_OP_SET_SSP, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1523
1524
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
  				      MGMT_STATUS_BUSY);
a2cb01de1   Johan Hedberg   Bluetooth: Fix ch...
1525
1526
  		goto unlock;
  	}
a0cdf960b   Marcel Holtmann   Bluetooth: Restri...
1527
  	if (cp->val) {
238be788f   Marcel Holtmann   Bluetooth: Introd...
1528
  		changed = !hci_dev_test_and_set_flag(hdev, HCI_HS_ENABLED);
a0cdf960b   Marcel Holtmann   Bluetooth: Restri...
1529
1530
  	} else {
  		if (hdev_is_powered(hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1531
1532
  			err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
  					      MGMT_STATUS_REJECTED);
a0cdf960b   Marcel Holtmann   Bluetooth: Restri...
1533
1534
  			goto unlock;
  		}
a69d89272   Marcel Holtmann   Bluetooth: Introd...
1535
  		changed = hci_dev_test_and_clear_flag(hdev, HCI_HS_ENABLED);
a0cdf960b   Marcel Holtmann   Bluetooth: Restri...
1536
  	}
ee3926936   Marcel Holtmann   Bluetooth: Send n...
1537
1538
1539
1540
1541
1542
1543
  
  	err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
  	if (err < 0)
  		goto unlock;
  
  	if (changed)
  		err = new_settings(hdev, sk);
6d80dfd09   Johan Hedberg   Bluetooth: mgmt: ...
1544

ee3926936   Marcel Holtmann   Bluetooth: Send n...
1545
1546
1547
  unlock:
  	hci_dev_unlock(hdev);
  	return err;
6d80dfd09   Johan Hedberg   Bluetooth: mgmt: ...
1548
  }
1904a853f   Marcel Holtmann   Bluetooth: Add op...
1549
  static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
416a4ae56   Johan Hedberg   Bluetooth: Use as...
1550
1551
  {
  	struct cmd_lookup match = { NULL, hdev };
3ad675827   Jaganath Kanakkassery   Bluetooth: Fix mi...
1552
  	hci_dev_lock(hdev);
416a4ae56   Johan Hedberg   Bluetooth: Use as...
1553
1554
1555
1556
1557
  	if (status) {
  		u8 mgmt_err = mgmt_status(status);
  
  		mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
  				     &mgmt_err);
3ad675827   Jaganath Kanakkassery   Bluetooth: Fix mi...
1558
  		goto unlock;
416a4ae56   Johan Hedberg   Bluetooth: Use as...
1559
1560
1561
1562
1563
1564
1565
1566
  	}
  
  	mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
  
  	new_settings(hdev, match.sk);
  
  	if (match.sk)
  		sock_put(match.sk);
441ad2d04   Marcel Holtmann   Bluetooth: Update...
1567
1568
1569
1570
1571
1572
  
  	/* Make sure the controller has a good default for
  	 * advertising data. Restrict the update to when LE
  	 * has actually been enabled. During power on, the
  	 * update in powered_update_hci will take care of it.
  	 */
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1573
  	if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
441ad2d04   Marcel Holtmann   Bluetooth: Update...
1574
  		struct hci_request req;
441ad2d04   Marcel Holtmann   Bluetooth: Update...
1575
  		hci_req_init(&req, hdev);
cab054ab4   Johan Hedberg   Bluetooth: Clean ...
1576
1577
  		__hci_req_update_adv_data(&req, 0x00);
  		__hci_req_update_scan_rsp_data(&req, 0x00);
441ad2d04   Marcel Holtmann   Bluetooth: Update...
1578
  		hci_req_run(&req, NULL);
2e93e53b8   Johan Hedberg   Bluetooth: Run al...
1579
  		hci_update_background_scan(hdev);
441ad2d04   Marcel Holtmann   Bluetooth: Update...
1580
  	}
3ad675827   Jaganath Kanakkassery   Bluetooth: Fix mi...
1581
1582
1583
  
  unlock:
  	hci_dev_unlock(hdev);
416a4ae56   Johan Hedberg   Bluetooth: Use as...
1584
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1585
  static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1586
1587
1588
  {
  	struct mgmt_mode *cp = data;
  	struct hci_cp_write_le_host_supported hci_cp;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1589
  	struct mgmt_pending_cmd *cmd;
416a4ae56   Johan Hedberg   Bluetooth: Use as...
1590
  	struct hci_request req;
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1591
  	int err;
0b60eba1b   Johan Hedberg   Bluetooth: Don't ...
1592
  	u8 val, enabled;
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1593

bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1594
  	BT_DBG("request for %s", hdev->name);
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1595

13ecd8b66   Johan Hedberg   Bluetooth: Move n...
1596
  	if (!lmp_le_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1597
1598
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
  				       MGMT_STATUS_NOT_SUPPORTED);
1de028ceb   Johan Hedberg   Bluetooth: mgmt: ...
1599

a7e80f25a   Johan Hedberg   Bluetooth: Fix ch...
1600
  	if (cp->val != 0x00 && cp->val != 0x01)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1601
1602
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
  				       MGMT_STATUS_INVALID_PARAMS);
a7e80f25a   Johan Hedberg   Bluetooth: Fix ch...
1603

e7844ee59   Marcel Holtmann   Bluetooth: Gracef...
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
  	/* Bluetooth single mode LE only controllers or dual-mode
  	 * controllers configured as LE only devices, do not allow
  	 * switching LE off. These have either LE enabled explicitly
  	 * or BR/EDR has been previously switched off.
  	 *
  	 * When trying to enable an already enabled LE, then gracefully
  	 * send a positive response. Trying to disable it however will
  	 * result into rejection.
  	 */
  	if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
  		if (cp->val == 0x01)
  			return send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1616
1617
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
  				       MGMT_STATUS_REJECTED);
e7844ee59   Marcel Holtmann   Bluetooth: Gracef...
1618
  	}
c73eee917   Johan Hedberg   Bluetooth: Fix se...
1619

13ecd8b66   Johan Hedberg   Bluetooth: Move n...
1620
  	hci_dev_lock(hdev);
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1621
1622
  
  	val = !!cp->val;
ffa88e02b   Gustavo Padovan   Bluetooth: Move d...
1623
  	enabled = lmp_host_le_capable(hdev);
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1624

847818d9c   Florian Grandel   Bluetooth: mgmt: ...
1625
  	if (!val)
37d3a1fab   Johan Hedberg   Bluetooth: mgmt: ...
1626
  		hci_req_clear_adv_instance(hdev, NULL, NULL, 0x00, true);
847818d9c   Florian Grandel   Bluetooth: mgmt: ...
1627

0b60eba1b   Johan Hedberg   Bluetooth: Don't ...
1628
  	if (!hdev_is_powered(hdev) || val == enabled) {
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1629
  		bool changed = false;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1630
  		if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
ce05d603a   Marcel Holtmann   Bluetooth: Introd...
1631
  			hci_dev_change_flag(hdev, HCI_LE_ENABLED);
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1632
1633
  			changed = true;
  		}
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1634
  		if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
1635
  			hci_dev_clear_flag(hdev, HCI_ADVERTISING);
eeca6f891   Johan Hedberg   Bluetooth: Add ne...
1636
1637
  			changed = true;
  		}
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1638
1639
  		err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
  		if (err < 0)
1de028ceb   Johan Hedberg   Bluetooth: mgmt: ...
1640
  			goto unlock;
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1641
1642
1643
  
  		if (changed)
  			err = new_settings(hdev, sk);
1de028ceb   Johan Hedberg   Bluetooth: mgmt: ...
1644
  		goto unlock;
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1645
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
1646
1647
  	if (pending_find(MGMT_OP_SET_LE, hdev) ||
  	    pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1648
1649
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
  				      MGMT_STATUS_BUSY);
1de028ceb   Johan Hedberg   Bluetooth: mgmt: ...
1650
  		goto unlock;
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1651
1652
1653
1654
1655
  	}
  
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
  	if (!cmd) {
  		err = -ENOMEM;
1de028ceb   Johan Hedberg   Bluetooth: mgmt: ...
1656
  		goto unlock;
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1657
  	}
441ad2d04   Marcel Holtmann   Bluetooth: Update...
1658
  	hci_req_init(&req, hdev);
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1659
1660
1661
1662
  	memset(&hci_cp, 0, sizeof(hci_cp));
  
  	if (val) {
  		hci_cp.le = val;
32226e4f1   Marcel Holtmann   Bluetooth: Set Si...
1663
  		hci_cp.simul = 0x00;
441ad2d04   Marcel Holtmann   Bluetooth: Update...
1664
  	} else {
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1665
  		if (hci_dev_test_flag(hdev, HCI_LE_ADV))
f22525700   Johan Hedberg   Bluetooth: Move a...
1666
  			__hci_req_disable_advertising(&req);
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1667
  	}
416a4ae56   Johan Hedberg   Bluetooth: Use as...
1668
1669
1670
1671
  	hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
  		    &hci_cp);
  
  	err = hci_req_run(&req, le_enable_complete);
0c01bc486   Syam Sidhardhan   Bluetooth: mgmt: ...
1672
  	if (err < 0)
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1673
  		mgmt_pending_remove(cmd);
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1674

1de028ceb   Johan Hedberg   Bluetooth: mgmt: ...
1675
1676
  unlock:
  	hci_dev_unlock(hdev);
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1677
1678
  	return err;
  }
0cab9c80f   Johan Hedberg   Bluetooth: Fix bu...
1679
1680
1681
1682
1683
1684
1685
1686
  /* This is a helper function to test for pending mgmt commands that can
   * cause CoD or EIR HCI commands. We can only allow one such pending
   * mgmt command at a time since otherwise we cannot easily track what
   * the current values are, will be, and based on that calculate if a new
   * HCI command needs to be sent and if yes with what value.
   */
  static bool pending_eir_or_class(struct hci_dev *hdev)
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1687
  	struct mgmt_pending_cmd *cmd;
0cab9c80f   Johan Hedberg   Bluetooth: Fix bu...
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
  
  	list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
  		switch (cmd->opcode) {
  		case MGMT_OP_ADD_UUID:
  		case MGMT_OP_REMOVE_UUID:
  		case MGMT_OP_SET_DEV_CLASS:
  		case MGMT_OP_SET_POWERED:
  			return true;
  		}
  	}
  
  	return false;
  }
83be8eca2   Johan Hedberg   Bluetooth: Keep t...
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
  static const u8 bluetooth_base_uuid[] = {
  			0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
  			0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };
  
  static u8 get_uuid_size(const u8 *uuid)
  {
  	u32 val;
  
  	if (memcmp(uuid, bluetooth_base_uuid, 12))
  		return 128;
  
  	val = get_unaligned_le32(&uuid[12]);
  	if (val > 0xffff)
  		return 32;
  
  	return 16;
  }
92da60975   Johan Hedberg   Bluetooth: Fix UU...
1719
1720
  static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1721
  	struct mgmt_pending_cmd *cmd;
92da60975   Johan Hedberg   Bluetooth: Fix UU...
1722
1723
  
  	hci_dev_lock(hdev);
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
1724
  	cmd = pending_find(mgmt_op, hdev);
92da60975   Johan Hedberg   Bluetooth: Fix UU...
1725
1726
  	if (!cmd)
  		goto unlock;
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
1727
1728
  	mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
  			  mgmt_status(status), hdev->dev_class, 3);
92da60975   Johan Hedberg   Bluetooth: Fix UU...
1729
1730
1731
1732
1733
1734
  
  	mgmt_pending_remove(cmd);
  
  unlock:
  	hci_dev_unlock(hdev);
  }
1904a853f   Marcel Holtmann   Bluetooth: Add op...
1735
  static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
92da60975   Johan Hedberg   Bluetooth: Fix UU...
1736
1737
1738
1739
1740
  {
  	BT_DBG("status 0x%02x", status);
  
  	mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1741
  static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1742
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
1743
  	struct mgmt_cp_add_uuid *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1744
  	struct mgmt_pending_cmd *cmd;
890ea8988   Johan Hedberg   Bluetooth: Update...
1745
  	struct hci_request req;
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1746
  	struct bt_uuid *uuid;
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1747
  	int err;
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1748
  	BT_DBG("request for %s", hdev->name);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1749

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1750
  	hci_dev_lock(hdev);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1751

0cab9c80f   Johan Hedberg   Bluetooth: Fix bu...
1752
  	if (pending_eir_or_class(hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1753
1754
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
  				      MGMT_STATUS_BUSY);
c95f0ba76   Johan Hedberg   Bluetooth: mgmt: ...
1755
1756
  		goto failed;
  	}
92c4c2049   Andre Guedes   Bluetooth: Use GF...
1757
  	uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1758
1759
1760
1761
1762
1763
  	if (!uuid) {
  		err = -ENOMEM;
  		goto failed;
  	}
  
  	memcpy(uuid->uuid, cp->uuid, 16);
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
1764
  	uuid->svc_hint = cp->svc_hint;
83be8eca2   Johan Hedberg   Bluetooth: Keep t...
1765
  	uuid->size = get_uuid_size(cp->uuid);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1766

de66aa630   Johan Hedberg   Bluetooth: Store ...
1767
  	list_add_tail(&uuid->list, &hdev->uuids);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1768

890ea8988   Johan Hedberg   Bluetooth: Update...
1769
  	hci_req_init(&req, hdev);
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
1770

14bf5eac7   Johan Hedberg   Bluetooth: Perfor...
1771
  	__hci_req_update_class(&req);
b1a8917c9   Johan Hedberg   Bluetooth: Move E...
1772
  	__hci_req_update_eir(&req);
890ea8988   Johan Hedberg   Bluetooth: Update...
1773

92da60975   Johan Hedberg   Bluetooth: Fix UU...
1774
1775
1776
1777
  	err = hci_req_run(&req, add_uuid_complete);
  	if (err < 0) {
  		if (err != -ENODATA)
  			goto failed;
80a1e1dbf   Johan Hedberg   Bluetooth: Add lo...
1778

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
1779
1780
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
  					hdev->dev_class, 3);
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
1781
1782
1783
1784
  		goto failed;
  	}
  
  	cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
890ea8988   Johan Hedberg   Bluetooth: Update...
1785
  	if (!cmd) {
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
1786
  		err = -ENOMEM;
890ea8988   Johan Hedberg   Bluetooth: Update...
1787
1788
1789
1790
  		goto failed;
  	}
  
  	err = 0;
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1791
1792
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1793
  	hci_dev_unlock(hdev);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1794
1795
  	return err;
  }
24b78d0f4   Johan Hedberg   Bluetooth: mgmt: ...
1796
1797
1798
1799
  static bool enable_service_cache(struct hci_dev *hdev)
  {
  	if (!hdev_is_powered(hdev))
  		return false;
238be788f   Marcel Holtmann   Bluetooth: Introd...
1800
  	if (!hci_dev_test_and_set_flag(hdev, HCI_SERVICE_CACHE)) {
46818ed51   Johan Hedberg   Bluetooth: Fix us...
1801
1802
  		queue_delayed_work(hdev->workqueue, &hdev->service_cache,
  				   CACHE_TIMEOUT);
24b78d0f4   Johan Hedberg   Bluetooth: mgmt: ...
1803
1804
1805
1806
1807
  		return true;
  	}
  
  	return false;
  }
1904a853f   Marcel Holtmann   Bluetooth: Add op...
1808
  static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
92da60975   Johan Hedberg   Bluetooth: Fix UU...
1809
1810
1811
1812
1813
  {
  	BT_DBG("status 0x%02x", status);
  
  	mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1814
  static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
8ce8e2b56   Gustavo Padovan   Bluetooth: Fix co...
1815
  		       u16 len)
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1816
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
1817
  	struct mgmt_cp_remove_uuid *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1818
  	struct mgmt_pending_cmd *cmd;
056341c8c   Johan Hedberg   Bluetooth: Simpli...
1819
  	struct bt_uuid *match, *tmp;
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1820
  	u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
890ea8988   Johan Hedberg   Bluetooth: Update...
1821
  	struct hci_request req;
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1822
  	int err, found;
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1823
  	BT_DBG("request for %s", hdev->name);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1824

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1825
  	hci_dev_lock(hdev);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1826

0cab9c80f   Johan Hedberg   Bluetooth: Fix bu...
1827
  	if (pending_eir_or_class(hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1828
1829
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
  				      MGMT_STATUS_BUSY);
c95f0ba76   Johan Hedberg   Bluetooth: mgmt: ...
1830
1831
  		goto unlock;
  	}
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1832
  	if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
35f7498a8   Johan Hedberg   Bluetooth: Remove...
1833
  		hci_uuids_clear(hdev);
4004b6d96   Johan Hedberg   Bluetooth: mgmt: ...
1834

24b78d0f4   Johan Hedberg   Bluetooth: mgmt: ...
1835
  		if (enable_service_cache(hdev)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
1836
1837
1838
  			err = mgmt_cmd_complete(sk, hdev->id,
  						MGMT_OP_REMOVE_UUID,
  						0, hdev->dev_class, 3);
24b78d0f4   Johan Hedberg   Bluetooth: mgmt: ...
1839
1840
  			goto unlock;
  		}
4004b6d96   Johan Hedberg   Bluetooth: mgmt: ...
1841

9246a8693   Johan Hedberg   Bluetooth: mgmt: ...
1842
  		goto update_class;
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1843
1844
1845
  	}
  
  	found = 0;
056341c8c   Johan Hedberg   Bluetooth: Simpli...
1846
  	list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1847
1848
1849
1850
  		if (memcmp(match->uuid, cp->uuid, 16) != 0)
  			continue;
  
  		list_del(&match->list);
482049f75   Johan Hedberg   Bluetooth: Fix me...
1851
  		kfree(match);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1852
1853
1854
1855
  		found++;
  	}
  
  	if (found == 0) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1856
1857
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
  				      MGMT_STATUS_INVALID_PARAMS);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1858
1859
  		goto unlock;
  	}
9246a8693   Johan Hedberg   Bluetooth: mgmt: ...
1860
  update_class:
890ea8988   Johan Hedberg   Bluetooth: Update...
1861
  	hci_req_init(&req, hdev);
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
1862

14bf5eac7   Johan Hedberg   Bluetooth: Perfor...
1863
  	__hci_req_update_class(&req);
b1a8917c9   Johan Hedberg   Bluetooth: Move E...
1864
  	__hci_req_update_eir(&req);
890ea8988   Johan Hedberg   Bluetooth: Update...
1865

92da60975   Johan Hedberg   Bluetooth: Fix UU...
1866
1867
1868
1869
  	err = hci_req_run(&req, remove_uuid_complete);
  	if (err < 0) {
  		if (err != -ENODATA)
  			goto unlock;
80a1e1dbf   Johan Hedberg   Bluetooth: Add lo...
1870

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
1871
1872
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
  					hdev->dev_class, 3);
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
1873
1874
1875
1876
  		goto unlock;
  	}
  
  	cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
890ea8988   Johan Hedberg   Bluetooth: Update...
1877
  	if (!cmd) {
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
1878
  		err = -ENOMEM;
890ea8988   Johan Hedberg   Bluetooth: Update...
1879
1880
1881
1882
  		goto unlock;
  	}
  
  	err = 0;
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1883
1884
  
  unlock:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1885
  	hci_dev_unlock(hdev);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1886
1887
  	return err;
  }
1904a853f   Marcel Holtmann   Bluetooth: Add op...
1888
  static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
92da60975   Johan Hedberg   Bluetooth: Fix UU...
1889
1890
1891
1892
1893
  {
  	BT_DBG("status 0x%02x", status);
  
  	mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1894
  static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
1895
  			 u16 len)
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
1896
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
1897
  	struct mgmt_cp_set_dev_class *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1898
  	struct mgmt_pending_cmd *cmd;
890ea8988   Johan Hedberg   Bluetooth: Update...
1899
  	struct hci_request req;
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
1900
  	int err;
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1901
  	BT_DBG("request for %s", hdev->name);
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
1902

6203fc983   Marcel Holtmann   Bluetooth: Allow ...
1903
  	if (!lmp_bredr_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1904
1905
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
  				       MGMT_STATUS_NOT_SUPPORTED);
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
1906

0cab9c80f   Johan Hedberg   Bluetooth: Fix bu...
1907
  	hci_dev_lock(hdev);
ee98f4738   Johan Hedberg   Bluetooth: Fix ac...
1908

0cab9c80f   Johan Hedberg   Bluetooth: Fix bu...
1909
  	if (pending_eir_or_class(hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1910
1911
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
  				      MGMT_STATUS_BUSY);
0cab9c80f   Johan Hedberg   Bluetooth: Fix bu...
1912
1913
  		goto unlock;
  	}
c95f0ba76   Johan Hedberg   Bluetooth: mgmt: ...
1914

0cab9c80f   Johan Hedberg   Bluetooth: Fix bu...
1915
  	if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1916
1917
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
  				      MGMT_STATUS_INVALID_PARAMS);
0cab9c80f   Johan Hedberg   Bluetooth: Fix bu...
1918
1919
  		goto unlock;
  	}
575b3a02e   Johan Hedberg   Bluetooth: Fix ch...
1920

932f5ff5e   Johan Hedberg   Bluetooth: mgmt: ...
1921
1922
  	hdev->major_class = cp->major;
  	hdev->minor_class = cp->minor;
b5235a65a   Johan Hedberg   Bluetooth: mgmt: ...
1923
  	if (!hdev_is_powered(hdev)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
1924
1925
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
  					hdev->dev_class, 3);
b5235a65a   Johan Hedberg   Bluetooth: mgmt: ...
1926
1927
  		goto unlock;
  	}
890ea8988   Johan Hedberg   Bluetooth: Update...
1928
  	hci_req_init(&req, hdev);
a69d89272   Marcel Holtmann   Bluetooth: Introd...
1929
  	if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
1930
1931
1932
  		hci_dev_unlock(hdev);
  		cancel_delayed_work_sync(&hdev->service_cache);
  		hci_dev_lock(hdev);
b1a8917c9   Johan Hedberg   Bluetooth: Move E...
1933
  		__hci_req_update_eir(&req);
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
1934
  	}
14c0b6082   Johan Hedberg   Bluetooth: Remove...
1935

14bf5eac7   Johan Hedberg   Bluetooth: Perfor...
1936
  	__hci_req_update_class(&req);
890ea8988   Johan Hedberg   Bluetooth: Update...
1937

92da60975   Johan Hedberg   Bluetooth: Fix UU...
1938
1939
1940
1941
  	err = hci_req_run(&req, set_class_complete);
  	if (err < 0) {
  		if (err != -ENODATA)
  			goto unlock;
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
1942

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
1943
1944
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
  					hdev->dev_class, 3);
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
1945
1946
1947
1948
  		goto unlock;
  	}
  
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
890ea8988   Johan Hedberg   Bluetooth: Update...
1949
  	if (!cmd) {
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
1950
  		err = -ENOMEM;
890ea8988   Johan Hedberg   Bluetooth: Update...
1951
1952
1953
1954
  		goto unlock;
  	}
  
  	err = 0;
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
1955

b5235a65a   Johan Hedberg   Bluetooth: mgmt: ...
1956
  unlock:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1957
  	hci_dev_unlock(hdev);
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
1958
1959
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1960
  static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
8ce8e2b56   Gustavo Padovan   Bluetooth: Fix co...
1961
  			  u16 len)
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1962
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
1963
  	struct mgmt_cp_load_link_keys *cp = data;
ba1d6936f   Johan Hedberg   Bluetooth: Fix bu...
1964
1965
  	const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
  				   sizeof(struct mgmt_link_key_info));
4e51eae9c   Szymon Janc   Bluetooth: Move i...
1966
  	u16 key_count, expected_len;
b1de97d8c   Marcel Holtmann   Bluetooth: Add ma...
1967
  	bool changed;
a492cd52b   Vinicius Costa Gomes   Revert "Bluetooth...
1968
  	int i;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1969

9060d5cf5   Marcel Holtmann   Bluetooth: Restri...
1970
1971
1972
  	BT_DBG("request for %s", hdev->name);
  
  	if (!lmp_bredr_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1973
1974
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
  				       MGMT_STATUS_NOT_SUPPORTED);
9060d5cf5   Marcel Holtmann   Bluetooth: Restri...
1975

1f350c872   Marcel Holtmann   Bluetooth: Fix br...
1976
  	key_count = __le16_to_cpu(cp->key_count);
ba1d6936f   Johan Hedberg   Bluetooth: Fix bu...
1977
1978
1979
  	if (key_count > max_key_count) {
  		BT_ERR("load_link_keys: too big key_count value %u",
  		       key_count);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1980
1981
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
  				       MGMT_STATUS_INVALID_PARAMS);
ba1d6936f   Johan Hedberg   Bluetooth: Fix bu...
1982
  	}
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1983

86742e1ec   Johan Hedberg   Bluetooth: Update...
1984
1985
  	expected_len = sizeof(*cp) + key_count *
  					sizeof(struct mgmt_link_key_info);
a492cd52b   Vinicius Costa Gomes   Revert "Bluetooth...
1986
  	if (expected_len != len) {
86742e1ec   Johan Hedberg   Bluetooth: Update...
1987
  		BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
2606ecbc4   Johan Hedberg   Bluetooth: Fix ex...
1988
  		       expected_len, len);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1989
1990
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
  				       MGMT_STATUS_INVALID_PARAMS);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1991
  	}
4ae14301c   Johan Hedberg   Bluetooth: Fix ch...
1992
  	if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1993
1994
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
  				       MGMT_STATUS_INVALID_PARAMS);
4ae14301c   Johan Hedberg   Bluetooth: Fix ch...
1995

bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1996
  	BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
8ce8e2b56   Gustavo Padovan   Bluetooth: Fix co...
1997
  	       key_count);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1998

4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
1999
2000
  	for (i = 0; i < key_count; i++) {
  		struct mgmt_link_key_info *key = &cp->keys[i];
8e9911327   Marcel Holtmann   Bluetooth: Limit ...
2001
  		if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2002
2003
2004
  			return mgmt_cmd_status(sk, hdev->id,
  					       MGMT_OP_LOAD_LINK_KEYS,
  					       MGMT_STATUS_INVALID_PARAMS);
4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
2005
  	}
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2006
  	hci_dev_lock(hdev);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2007
2008
  
  	hci_link_keys_clear(hdev);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2009
  	if (cp->debug_keys)
238be788f   Marcel Holtmann   Bluetooth: Introd...
2010
  		changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2011
  	else
a69d89272   Marcel Holtmann   Bluetooth: Introd...
2012
2013
  		changed = hci_dev_test_and_clear_flag(hdev,
  						      HCI_KEEP_DEBUG_KEYS);
b1de97d8c   Marcel Holtmann   Bluetooth: Add ma...
2014
2015
2016
  
  	if (changed)
  		new_settings(hdev, NULL);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2017

a492cd52b   Vinicius Costa Gomes   Revert "Bluetooth...
2018
  	for (i = 0; i < key_count; i++) {
86742e1ec   Johan Hedberg   Bluetooth: Update...
2019
  		struct mgmt_link_key_info *key = &cp->keys[i];
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2020

58e9293c4   Johan Hedberg   Bluetooth: Fix ig...
2021
2022
2023
2024
2025
  		/* Always ignore debug keys and require a new pairing if
  		 * the user wants to use them.
  		 */
  		if (key->type == HCI_LK_DEBUG_COMBINATION)
  			continue;
7652ff6ae   Johan Hedberg   Bluetooth: Move m...
2026
2027
  		hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
  				 key->type, key->pin_len, NULL);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2028
  	}
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2029
  	mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
0e5f875a8   Johan Hedberg   Bluetooth: Add mi...
2030

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2031
  	hci_dev_unlock(hdev);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2032

a492cd52b   Vinicius Costa Gomes   Revert "Bluetooth...
2033
  	return 0;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2034
  }
b1078ad0b   Johan Hedberg   Bluetooth: Add De...
2035
  static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2036
  			   u8 addr_type, struct sock *skip_sk)
b1078ad0b   Johan Hedberg   Bluetooth: Add De...
2037
2038
2039
2040
2041
2042
2043
  {
  	struct mgmt_ev_device_unpaired ev;
  
  	bacpy(&ev.addr.bdaddr, bdaddr);
  	ev.addr.type = addr_type;
  
  	return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2044
  			  skip_sk);
b1078ad0b   Johan Hedberg   Bluetooth: Add De...
2045
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
2046
  static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2047
  			 u16 len)
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2048
  {
124f6e352   Johan Hedberg   Bluetooth: Update...
2049
2050
  	struct mgmt_cp_unpair_device *cp = data;
  	struct mgmt_rp_unpair_device rp;
fc64361ac   Johan Hedberg   Bluetooth: Disabl...
2051
  	struct hci_conn_params *params;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2052
  	struct mgmt_pending_cmd *cmd;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2053
  	struct hci_conn *conn;
ec182f039   Johan Hedberg   Bluetooth: Remove...
2054
  	u8 addr_type;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2055
  	int err;
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
2056
  	memset(&rp, 0, sizeof(rp));
124f6e352   Johan Hedberg   Bluetooth: Update...
2057
2058
  	bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
  	rp.addr.type = cp->addr.type;
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
2059

4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
2060
  	if (!bdaddr_type_is_valid(cp->addr.type))
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2061
2062
2063
  		return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
  					 MGMT_STATUS_INVALID_PARAMS,
  					 &rp, sizeof(rp));
4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
2064

118da70b7   Johan Hedberg   Bluetooth: Fix ch...
2065
  	if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2066
2067
2068
  		return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
  					 MGMT_STATUS_INVALID_PARAMS,
  					 &rp, sizeof(rp));
118da70b7   Johan Hedberg   Bluetooth: Fix ch...
2069

4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
2070
  	hci_dev_lock(hdev);
86a8cfc6d   Johan Hedberg   Bluetooth: mgmt: ...
2071
  	if (!hdev_is_powered(hdev)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2072
2073
2074
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
  					MGMT_STATUS_NOT_POWERED, &rp,
  					sizeof(rp));
86a8cfc6d   Johan Hedberg   Bluetooth: mgmt: ...
2075
2076
  		goto unlock;
  	}
e0b2b27e6   Johan Hedberg   Bluetooth: Fix mi...
2077
  	if (cp->addr.type == BDADDR_BREDR) {
89cbb0638   Alfonso Acosta   Bluetooth: Defer ...
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
  		/* If disconnection is requested, then look up the
  		 * connection. If the remote device is connected, it
  		 * will be later used to terminate the link.
  		 *
  		 * Setting it to NULL explicitly will cause no
  		 * termination of the link.
  		 */
  		if (cp->disconnect)
  			conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
  						       &cp->addr.bdaddr);
  		else
  			conn = NULL;
124f6e352   Johan Hedberg   Bluetooth: Update...
2090
  		err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
ec182f039   Johan Hedberg   Bluetooth: Remove...
2091
2092
2093
2094
2095
2096
  		if (err < 0) {
  			err = mgmt_cmd_complete(sk, hdev->id,
  						MGMT_OP_UNPAIR_DEVICE,
  						MGMT_STATUS_NOT_PAIRED, &rp,
  						sizeof(rp));
  			goto unlock;
89cbb0638   Alfonso Acosta   Bluetooth: Defer ...
2097
  		}
ec182f039   Johan Hedberg   Bluetooth: Remove...
2098
  		goto done;
e0b2b27e6   Johan Hedberg   Bluetooth: Fix mi...
2099
  	}
b0dbfb46b   Vinicius Costa Gomes   Bluetooth: Add su...
2100

ec182f039   Johan Hedberg   Bluetooth: Remove...
2101
2102
  	/* LE address type */
  	addr_type = le_addr_type(cp->addr.type);
0f8a689c6   Matias Karhumaa   Bluetooth: SMP: f...
2103
2104
  	/* Abort any ongoing SMP pairing. Removes ltk and irk if they exist. */
  	err = smp_cancel_and_remove_pairing(hdev, &cp->addr.bdaddr, addr_type);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2105
  	if (err < 0) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2106
2107
2108
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
  					MGMT_STATUS_NOT_PAIRED, &rp,
  					sizeof(rp));
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2109
2110
  		goto unlock;
  	}
ec182f039   Johan Hedberg   Bluetooth: Remove...
2111
2112
2113
2114
2115
  	conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr, addr_type);
  	if (!conn) {
  		hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
  		goto done;
  	}
c81d555a2   Johan Hedberg   Bluetooth: Fix cr...
2116

ec182f039   Johan Hedberg   Bluetooth: Remove...
2117
2118
2119
2120
  	/* Defer clearing up the connection parameters until closing to
  	 * give a chance of keeping them if a repairing happens.
  	 */
  	set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
fc64361ac   Johan Hedberg   Bluetooth: Disabl...
2121
2122
2123
2124
2125
2126
2127
2128
  	/* Disable auto-connection parameters if present */
  	params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr, addr_type);
  	if (params) {
  		if (params->explicit_connect)
  			params->auto_connect = HCI_AUTO_CONN_EXPLICIT;
  		else
  			params->auto_connect = HCI_AUTO_CONN_DISABLED;
  	}
ec182f039   Johan Hedberg   Bluetooth: Remove...
2129
2130
2131
2132
2133
2134
2135
  	/* If disconnection is not requested, then clear the connection
  	 * variable so that the link is not terminated.
  	 */
  	if (!cp->disconnect)
  		conn = NULL;
  
  done:
89cbb0638   Alfonso Acosta   Bluetooth: Defer ...
2136
2137
2138
  	/* If the connection variable is set, then termination of the
  	 * link is requested.
  	 */
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
2139
  	if (!conn) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2140
2141
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
  					&rp, sizeof(rp));
b1078ad0b   Johan Hedberg   Bluetooth: Add De...
2142
  		device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
2143
2144
  		goto unlock;
  	}
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2145

124f6e352   Johan Hedberg   Bluetooth: Update...
2146
  	cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2147
  			       sizeof(*cp));
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
2148
2149
2150
  	if (!cmd) {
  		err = -ENOMEM;
  		goto unlock;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2151
  	}
d8b7b1e49   Johan Hedberg   Bluetooth: Conver...
2152
  	cmd->cmd_complete = addr_cmd_complete;
89e0ccc88   Johan Hedberg   Bluetooth: Take a...
2153
  	err = hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM);
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
2154
2155
  	if (err < 0)
  		mgmt_pending_remove(cmd);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2156
  unlock:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2157
  	hci_dev_unlock(hdev);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2158
2159
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
2160
  static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2161
  		      u16 len)
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2162
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
2163
  	struct mgmt_cp_disconnect *cp = data;
06a63b19e   Johan Hedberg   Bluetooth: Fix re...
2164
  	struct mgmt_rp_disconnect rp;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2165
  	struct mgmt_pending_cmd *cmd;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2166
  	struct hci_conn *conn;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2167
2168
2169
  	int err;
  
  	BT_DBG("");
06a63b19e   Johan Hedberg   Bluetooth: Fix re...
2170
2171
2172
  	memset(&rp, 0, sizeof(rp));
  	bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
  	rp.addr.type = cp->addr.type;
4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
2173
  	if (!bdaddr_type_is_valid(cp->addr.type))
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2174
2175
2176
  		return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
  					 MGMT_STATUS_INVALID_PARAMS,
  					 &rp, sizeof(rp));
4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
2177

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2178
  	hci_dev_lock(hdev);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2179
2180
  
  	if (!test_bit(HCI_UP, &hdev->flags)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2181
2182
2183
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
  					MGMT_STATUS_NOT_POWERED, &rp,
  					sizeof(rp));
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2184
2185
  		goto failed;
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
2186
  	if (pending_find(MGMT_OP_DISCONNECT, hdev)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2187
2188
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
  					MGMT_STATUS_BUSY, &rp, sizeof(rp));
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2189
2190
  		goto failed;
  	}
591f47f31   Andre Guedes   Bluetooth: Move a...
2191
  	if (cp->addr.type == BDADDR_BREDR)
8fc9ced39   Gustavo Padovan   Bluetooth: Fix co...
2192
2193
  		conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
  					       &cp->addr.bdaddr);
88c3df13c   Johan Hedberg   Bluetooth: Update...
2194
  	else
9d4c1cc15   Johan Hedberg   Bluetooth: Use hc...
2195
2196
  		conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr,
  					       le_addr_type(cp->addr.type));
365227e5f   Vinicius Costa Gomes   Bluetooth: Add su...
2197

f960727e6   Vishal Agarwal   Bluetooth: Fix se...
2198
  	if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2199
2200
2201
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
  					MGMT_STATUS_NOT_CONNECTED, &rp,
  					sizeof(rp));
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2202
2203
  		goto failed;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
2204
  	cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
366a03369   Johan Hedberg   Bluetooth: Make p...
2205
2206
  	if (!cmd) {
  		err = -ENOMEM;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2207
  		goto failed;
366a03369   Johan Hedberg   Bluetooth: Make p...
2208
  	}
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2209

f5818c224   Johan Hedberg   Bluetooth: Conver...
2210
  	cmd->cmd_complete = generic_cmd_complete;
e3f2f92a0   Johan Hedberg   Bluetooth: Use hc...
2211
  	err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2212
  	if (err < 0)
a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
2213
  		mgmt_pending_remove(cmd);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2214
2215
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2216
  	hci_dev_unlock(hdev);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2217
2218
  	return err;
  }
57c1477c2   Andre Guedes   Bluetooth: Rename...
2219
  static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
4c659c397   Johan Hedberg   Bluetooth: Add ad...
2220
2221
2222
  {
  	switch (link_type) {
  	case LE_LINK:
48264f069   Johan Hedberg   Bluetooth: Add pu...
2223
2224
  		switch (addr_type) {
  		case ADDR_LE_DEV_PUBLIC:
591f47f31   Andre Guedes   Bluetooth: Move a...
2225
  			return BDADDR_LE_PUBLIC;
0ed09148f   Andre Guedes   Bluetooth: Remove...
2226

48264f069   Johan Hedberg   Bluetooth: Add pu...
2227
  		default:
0ed09148f   Andre Guedes   Bluetooth: Remove...
2228
  			/* Fallback to LE Random address type */
591f47f31   Andre Guedes   Bluetooth: Move a...
2229
  			return BDADDR_LE_RANDOM;
48264f069   Johan Hedberg   Bluetooth: Add pu...
2230
  		}
0ed09148f   Andre Guedes   Bluetooth: Remove...
2231

4c659c397   Johan Hedberg   Bluetooth: Add ad...
2232
  	default:
0ed09148f   Andre Guedes   Bluetooth: Remove...
2233
  		/* Fallback to BR/EDR type */
591f47f31   Andre Guedes   Bluetooth: Move a...
2234
  		return BDADDR_BREDR;
4c659c397   Johan Hedberg   Bluetooth: Add ad...
2235
2236
  	}
  }
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2237
2238
  static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
  			   u16 data_len)
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
2239
  {
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
2240
  	struct mgmt_rp_get_connections *rp;
8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
2241
  	struct hci_conn *c;
a38528f11   Johan Hedberg   Bluetooth: Create...
2242
  	size_t rp_len;
60fc5fb66   Johan Hedberg   Bluetooth: mgmt: ...
2243
2244
  	int err;
  	u16 i;
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
2245
2246
  
  	BT_DBG("");
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2247
  	hci_dev_lock(hdev);
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
2248

5f97c1df5   Johan Hedberg   Bluetooth: mgmt: ...
2249
  	if (!hdev_is_powered(hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2250
2251
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
  				      MGMT_STATUS_NOT_POWERED);
5f97c1df5   Johan Hedberg   Bluetooth: mgmt: ...
2252
2253
  		goto unlock;
  	}
60fc5fb66   Johan Hedberg   Bluetooth: mgmt: ...
2254
  	i = 0;
b644ba336   Johan Hedberg   Bluetooth: Update...
2255
2256
  	list_for_each_entry(c, &hdev->conn_hash.list, list) {
  		if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
60fc5fb66   Johan Hedberg   Bluetooth: mgmt: ...
2257
  			i++;
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
2258
  	}
60fc5fb66   Johan Hedberg   Bluetooth: mgmt: ...
2259
  	rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
92c4c2049   Andre Guedes   Bluetooth: Use GF...
2260
  	rp = kmalloc(rp_len, GFP_KERNEL);
a38528f11   Johan Hedberg   Bluetooth: Create...
2261
  	if (!rp) {
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
2262
2263
2264
  		err = -ENOMEM;
  		goto unlock;
  	}
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
2265
  	i = 0;
4c659c397   Johan Hedberg   Bluetooth: Add ad...
2266
  	list_for_each_entry(c, &hdev->conn_hash.list, list) {
b644ba336   Johan Hedberg   Bluetooth: Update...
2267
2268
  		if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
  			continue;
4c659c397   Johan Hedberg   Bluetooth: Add ad...
2269
  		bacpy(&rp->addr[i].bdaddr, &c->dst);
57c1477c2   Andre Guedes   Bluetooth: Rename...
2270
  		rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
0ed09148f   Andre Guedes   Bluetooth: Remove...
2271
  		if (c->type == SCO_LINK || c->type == ESCO_LINK)
4c659c397   Johan Hedberg   Bluetooth: Add ad...
2272
2273
2274
  			continue;
  		i++;
  	}
eb55ef07a   Marcel Holtmann   Bluetooth: Fix br...
2275
  	rp->conn_count = cpu_to_le16(i);
60fc5fb66   Johan Hedberg   Bluetooth: mgmt: ...
2276

4c659c397   Johan Hedberg   Bluetooth: Add ad...
2277
2278
  	/* Recalculate length in case of filtered SCO connections, etc */
  	rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
2279

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2280
2281
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
  				rp_len);
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
2282

a38528f11   Johan Hedberg   Bluetooth: Create...
2283
  	kfree(rp);
5f97c1df5   Johan Hedberg   Bluetooth: mgmt: ...
2284
2285
  
  unlock:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2286
  	hci_dev_unlock(hdev);
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
2287
2288
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
2289
  static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2290
  				   struct mgmt_cp_pin_code_neg_reply *cp)
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
2291
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2292
  	struct mgmt_pending_cmd *cmd;
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
2293
  	int err;
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
2294
  	cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2295
  			       sizeof(*cp));
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
2296
2297
  	if (!cmd)
  		return -ENOMEM;
dd7e39bbf   Arek Lichwa   Bluetooth: Fix NU...
2298
  	cmd->cmd_complete = addr_cmd_complete;
d8457698e   Johan Hedberg   Bluetooth: mgmt: ...
2299
  	err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2300
  			   sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
2301
2302
2303
2304
2305
  	if (err < 0)
  		mgmt_pending_remove(cmd);
  
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
2306
  static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2307
  			  u16 len)
980e1a537   Johan Hedberg   Bluetooth: Add su...
2308
  {
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
2309
  	struct hci_conn *conn;
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
2310
  	struct mgmt_cp_pin_code_reply *cp = data;
980e1a537   Johan Hedberg   Bluetooth: Add su...
2311
  	struct hci_cp_pin_code_reply reply;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2312
  	struct mgmt_pending_cmd *cmd;
980e1a537   Johan Hedberg   Bluetooth: Add su...
2313
2314
2315
  	int err;
  
  	BT_DBG("");
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2316
  	hci_dev_lock(hdev);
980e1a537   Johan Hedberg   Bluetooth: Add su...
2317

4b34ee782   Johan Hedberg   Bluetooth: mgmt: ...
2318
  	if (!hdev_is_powered(hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2319
2320
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
  				      MGMT_STATUS_NOT_POWERED);
980e1a537   Johan Hedberg   Bluetooth: Add su...
2321
2322
  		goto failed;
  	}
d8457698e   Johan Hedberg   Bluetooth: mgmt: ...
2323
  	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
2324
  	if (!conn) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2325
2326
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
  				      MGMT_STATUS_NOT_CONNECTED);
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
2327
2328
2329
2330
  		goto failed;
  	}
  
  	if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
d8457698e   Johan Hedberg   Bluetooth: mgmt: ...
2331
2332
2333
  		struct mgmt_cp_pin_code_neg_reply ncp;
  
  		memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
2334
2335
  
  		BT_ERR("PIN code is not 16 bytes long");
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
2336
  		err = send_pin_code_neg_reply(sk, hdev, &ncp);
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
2337
  		if (err >= 0)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2338
2339
  			err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
  					      MGMT_STATUS_INVALID_PARAMS);
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
2340
2341
2342
  
  		goto failed;
  	}
00abfe444   Gustavo F. Padovan   Bluetooth: Fix co...
2343
  	cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
366a03369   Johan Hedberg   Bluetooth: Make p...
2344
2345
  	if (!cmd) {
  		err = -ENOMEM;
980e1a537   Johan Hedberg   Bluetooth: Add su...
2346
  		goto failed;
366a03369   Johan Hedberg   Bluetooth: Make p...
2347
  	}
980e1a537   Johan Hedberg   Bluetooth: Add su...
2348

7776d1d80   Johan Hedberg   Bluetooth: Use cm...
2349
  	cmd->cmd_complete = addr_cmd_complete;
d8457698e   Johan Hedberg   Bluetooth: mgmt: ...
2350
  	bacpy(&reply.bdaddr, &cp->addr.bdaddr);
980e1a537   Johan Hedberg   Bluetooth: Add su...
2351
  	reply.pin_len = cp->pin_len;
24718ca5e   Waldemar Rymarkiewicz   Bluetooth: Remove...
2352
  	memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
980e1a537   Johan Hedberg   Bluetooth: Add su...
2353
2354
2355
  
  	err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
  	if (err < 0)
a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
2356
  		mgmt_pending_remove(cmd);
980e1a537   Johan Hedberg   Bluetooth: Add su...
2357
2358
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2359
  	hci_dev_unlock(hdev);
980e1a537   Johan Hedberg   Bluetooth: Add su...
2360
2361
  	return err;
  }
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2362
2363
  static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
  			     u16 len)
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
2364
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
2365
  	struct mgmt_cp_set_io_capability *cp = data;
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
2366
2367
  
  	BT_DBG("");
4ec86d4c8   Johan Hedberg   Bluetooth: Fix va...
2368
  	if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
9db5c6295   Marcel Holtmann   Bluetooth: Use co...
2369
2370
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
  				       MGMT_STATUS_INVALID_PARAMS);
4ec86d4c8   Johan Hedberg   Bluetooth: Fix va...
2371

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2372
  	hci_dev_lock(hdev);
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
2373
2374
2375
2376
  
  	hdev->io_capability = cp->io_capability;
  
  	BT_DBG("%s IO capability set to 0x%02x", hdev->name,
8ce8e2b56   Gustavo Padovan   Bluetooth: Fix co...
2377
  	       hdev->io_capability);
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
2378

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2379
  	hci_dev_unlock(hdev);
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
2380

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2381
2382
  	return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
  				 NULL, 0);
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
2383
  }
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2384
  static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2385
2386
  {
  	struct hci_dev *hdev = conn->hdev;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2387
  	struct mgmt_pending_cmd *cmd;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2388

2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
2389
  	list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2390
2391
  		if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
  			continue;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2392
2393
2394
2395
2396
2397
2398
2399
  		if (cmd->user_data != conn)
  			continue;
  
  		return cmd;
  	}
  
  	return NULL;
  }
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2400
  static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2401
2402
2403
  {
  	struct mgmt_rp_pair_device rp;
  	struct hci_conn *conn = cmd->user_data;
9df746535   Johan Hedberg   Bluetooth: Add re...
2404
  	int err;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2405

61b1a7fbd   Johan Hedberg   Bluetooth: Fix ad...
2406
2407
  	bacpy(&rp.addr.bdaddr, &conn->dst);
  	rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2408

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2409
2410
  	err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
  				status, &rp, sizeof(rp));
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2411
2412
2413
2414
2415
  
  	/* So we don't get further callbacks for this connection */
  	conn->connect_cfm_cb = NULL;
  	conn->security_cfm_cb = NULL;
  	conn->disconn_cfm_cb = NULL;
76a68ba0a   David Herrmann   Bluetooth: rename...
2416
  	hci_conn_drop(conn);
89cbb0638   Alfonso Acosta   Bluetooth: Defer ...
2417
2418
2419
2420
2421
  
  	/* The device is paired so there is no need to remove
  	 * its connection parameters anymore.
  	 */
  	clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
15013aeb6   Johan Hedberg   Bluetooth: Fix ca...
2422
2423
  
  	hci_conn_put(conn);
9df746535   Johan Hedberg   Bluetooth: Add re...
2424
2425
  
  	return err;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2426
  }
f4a407bef   Johan Hedberg   Bluetooth: Wait f...
2427
2428
2429
  void mgmt_smp_complete(struct hci_conn *conn, bool complete)
  {
  	u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2430
  	struct mgmt_pending_cmd *cmd;
f4a407bef   Johan Hedberg   Bluetooth: Wait f...
2431
2432
  
  	cmd = find_pairing(conn);
a511b35ba   Johan Hedberg   Bluetooth: Fix in...
2433
  	if (cmd) {
04ab2749e   Johan Hedberg   Bluetooth: Conver...
2434
  		cmd->cmd_complete(cmd, status);
a511b35ba   Johan Hedberg   Bluetooth: Fix in...
2435
2436
  		mgmt_pending_remove(cmd);
  	}
f4a407bef   Johan Hedberg   Bluetooth: Wait f...
2437
  }
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2438
2439
  static void pairing_complete_cb(struct hci_conn *conn, u8 status)
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2440
  	struct mgmt_pending_cmd *cmd;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2441
2442
2443
2444
  
  	BT_DBG("status %u", status);
  
  	cmd = find_pairing(conn);
a511b35ba   Johan Hedberg   Bluetooth: Fix in...
2445
  	if (!cmd) {
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2446
  		BT_DBG("Unable to find a pending command");
a511b35ba   Johan Hedberg   Bluetooth: Fix in...
2447
2448
2449
2450
2451
  		return;
  	}
  
  	cmd->cmd_complete(cmd, mgmt_status(status));
  	mgmt_pending_remove(cmd);
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2452
  }
f4a407bef   Johan Hedberg   Bluetooth: Wait f...
2453
  static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
4c47d7396   Vishal Agarwal   Bluetooth: Fix LE...
2454
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2455
  	struct mgmt_pending_cmd *cmd;
4c47d7396   Vishal Agarwal   Bluetooth: Fix LE...
2456
2457
2458
2459
2460
2461
2462
  
  	BT_DBG("status %u", status);
  
  	if (!status)
  		return;
  
  	cmd = find_pairing(conn);
a511b35ba   Johan Hedberg   Bluetooth: Fix in...
2463
  	if (!cmd) {
4c47d7396   Vishal Agarwal   Bluetooth: Fix LE...
2464
  		BT_DBG("Unable to find a pending command");
a511b35ba   Johan Hedberg   Bluetooth: Fix in...
2465
2466
2467
2468
2469
  		return;
  	}
  
  	cmd->cmd_complete(cmd, mgmt_status(status));
  	mgmt_pending_remove(cmd);
4c47d7396   Vishal Agarwal   Bluetooth: Fix LE...
2470
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
2471
  static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2472
  		       u16 len)
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2473
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
2474
  	struct mgmt_cp_pair_device *cp = data;
1425acb74   Johan Hedberg   Bluetooth: Fix mg...
2475
  	struct mgmt_rp_pair_device rp;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2476
  	struct mgmt_pending_cmd *cmd;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2477
2478
  	u8 sec_level, auth_type;
  	struct hci_conn *conn;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2479
2480
2481
  	int err;
  
  	BT_DBG("");
f950a30e2   Szymon Janc   Bluetooth: Fix pa...
2482
2483
2484
  	memset(&rp, 0, sizeof(rp));
  	bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
  	rp.addr.type = cp->addr.type;
4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
2485
  	if (!bdaddr_type_is_valid(cp->addr.type))
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2486
2487
2488
  		return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
  					 MGMT_STATUS_INVALID_PARAMS,
  					 &rp, sizeof(rp));
4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
2489

4ec86d4c8   Johan Hedberg   Bluetooth: Fix va...
2490
  	if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2491
2492
2493
  		return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
  					 MGMT_STATUS_INVALID_PARAMS,
  					 &rp, sizeof(rp));
4ec86d4c8   Johan Hedberg   Bluetooth: Fix va...
2494

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2495
  	hci_dev_lock(hdev);
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2496

5f97c1df5   Johan Hedberg   Bluetooth: mgmt: ...
2497
  	if (!hdev_is_powered(hdev)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2498
2499
2500
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
  					MGMT_STATUS_NOT_POWERED, &rp,
  					sizeof(rp));
5f97c1df5   Johan Hedberg   Bluetooth: mgmt: ...
2501
2502
  		goto unlock;
  	}
55e76b389   Johan Hedberg   Bluetooth: Add 'A...
2503
2504
2505
2506
2507
2508
  	if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
  					MGMT_STATUS_ALREADY_PAIRED, &rp,
  					sizeof(rp));
  		goto unlock;
  	}
c908df362   Vinicius Costa Gomes   Bluetooth: Use th...
2509
  	sec_level = BT_SECURITY_MEDIUM;
6fd6b915b   Mikel Astiz   Bluetooth: Refact...
2510
  	auth_type = HCI_AT_DEDICATED_BONDING;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2511

6f77d8c75   Andre Guedes   Bluetooth: Move a...
2512
  	if (cp->addr.type == BDADDR_BREDR) {
04a6c5898   Andre Guedes   Bluetooth: Refact...
2513
2514
  		conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
  				       auth_type);
6f77d8c75   Andre Guedes   Bluetooth: Move a...
2515
  	} else {
85813a7ec   Johan Hedberg   Bluetooth: Add le...
2516
  		u8 addr_type = le_addr_type(cp->addr.type);
5157b8a50   Jakub Pawlowski   Bluetooth: Fix in...
2517
  		struct hci_conn_params *p;
6f77d8c75   Andre Guedes   Bluetooth: Move a...
2518

7c264b100   Marcel Holtmann   Bluetooth: Add de...
2519
2520
2521
2522
2523
2524
2525
2526
2527
  		/* When pairing a new device, it is expected to remember
  		 * this device for future connections. Adding the connection
  		 * parameter information ahead of time allows tracking
  		 * of the slave preferred values and will speed up any
  		 * further connection establishment.
  		 *
  		 * If connection parameters already exist, then they
  		 * will be kept and this function does nothing.
  		 */
5157b8a50   Jakub Pawlowski   Bluetooth: Fix in...
2528
2529
2530
2531
  		p = hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
  
  		if (p->auto_connect == HCI_AUTO_CONN_EXPLICIT)
  			p->auto_connect = HCI_AUTO_CONN_DISABLED;
7c264b100   Marcel Holtmann   Bluetooth: Add de...
2532

fa1422207   Jakub Pawlowski   Bluetooth: Enable...
2533
2534
  		conn = hci_connect_le_scan(hdev, &cp->addr.bdaddr,
  					   addr_type, sec_level,
0ad06aa6a   Johan Hedberg   Bluetooth: Fix sp...
2535
  					   HCI_LE_CONN_TIMEOUT);
6f77d8c75   Andre Guedes   Bluetooth: Move a...
2536
  	}
7a512d017   Vinicius Costa Gomes   Bluetooth: Add su...
2537

30e762721   Ville Tervo   Bluetooth: Use ER...
2538
  	if (IS_ERR(conn)) {
489dc48e7   Andrzej Kaczmarek   Bluetooth: Return...
2539
2540
2541
2542
  		int status;
  
  		if (PTR_ERR(conn) == -EBUSY)
  			status = MGMT_STATUS_BUSY;
faa810303   Lukasz Rymanowski   Bluetooth: Enhanc...
2543
2544
2545
2546
  		else if (PTR_ERR(conn) == -EOPNOTSUPP)
  			status = MGMT_STATUS_NOT_SUPPORTED;
  		else if (PTR_ERR(conn) == -ECONNREFUSED)
  			status = MGMT_STATUS_REJECTED;
489dc48e7   Andrzej Kaczmarek   Bluetooth: Return...
2547
2548
  		else
  			status = MGMT_STATUS_CONNECT_FAILED;
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2549
2550
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
  					status, &rp, sizeof(rp));
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2551
2552
2553
2554
  		goto unlock;
  	}
  
  	if (conn->connect_cfm_cb) {
76a68ba0a   David Herrmann   Bluetooth: rename...
2555
  		hci_conn_drop(conn);
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2556
2557
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
  					MGMT_STATUS_BUSY, &rp, sizeof(rp));
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2558
2559
  		goto unlock;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
2560
  	cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2561
2562
  	if (!cmd) {
  		err = -ENOMEM;
76a68ba0a   David Herrmann   Bluetooth: rename...
2563
  		hci_conn_drop(conn);
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2564
2565
  		goto unlock;
  	}
04ab2749e   Johan Hedberg   Bluetooth: Conver...
2566
  	cmd->cmd_complete = pairing_complete;
7a512d017   Vinicius Costa Gomes   Bluetooth: Add su...
2567
  	/* For LE, just connecting isn't a proof that the pairing finished */
f4a407bef   Johan Hedberg   Bluetooth: Wait f...
2568
  	if (cp->addr.type == BDADDR_BREDR) {
7a512d017   Vinicius Costa Gomes   Bluetooth: Add su...
2569
  		conn->connect_cfm_cb = pairing_complete_cb;
f4a407bef   Johan Hedberg   Bluetooth: Wait f...
2570
2571
2572
2573
2574
2575
2576
  		conn->security_cfm_cb = pairing_complete_cb;
  		conn->disconn_cfm_cb = pairing_complete_cb;
  	} else {
  		conn->connect_cfm_cb = le_pairing_complete_cb;
  		conn->security_cfm_cb = le_pairing_complete_cb;
  		conn->disconn_cfm_cb = le_pairing_complete_cb;
  	}
7a512d017   Vinicius Costa Gomes   Bluetooth: Add su...
2577

e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2578
  	conn->io_capability = cp->io_cap;
f8aaf9b65   Johan Hedberg   Bluetooth: Fix us...
2579
  	cmd->user_data = hci_conn_get(conn);
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2580

6f78fd4bb   Johan Hedberg   Bluetooth: Fix ch...
2581
  	if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
a511b35ba   Johan Hedberg   Bluetooth: Fix in...
2582
2583
2584
2585
  	    hci_conn_security(conn, sec_level, auth_type, true)) {
  		cmd->cmd_complete(cmd, 0);
  		mgmt_pending_remove(cmd);
  	}
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2586
2587
2588
2589
  
  	err = 0;
  
  unlock:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2590
  	hci_dev_unlock(hdev);
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2591
2592
  	return err;
  }
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2593
2594
  static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
  			      u16 len)
28424707a   Johan Hedberg   Bluetooth: mgmt: ...
2595
  {
0f4e68cf6   Johan Hedberg   Bluetooth: mgmt: ...
2596
  	struct mgmt_addr_info *addr = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2597
  	struct mgmt_pending_cmd *cmd;
28424707a   Johan Hedberg   Bluetooth: mgmt: ...
2598
2599
2600
2601
  	struct hci_conn *conn;
  	int err;
  
  	BT_DBG("");
28424707a   Johan Hedberg   Bluetooth: mgmt: ...
2602
  	hci_dev_lock(hdev);
5f97c1df5   Johan Hedberg   Bluetooth: mgmt: ...
2603
  	if (!hdev_is_powered(hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2604
2605
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
  				      MGMT_STATUS_NOT_POWERED);
5f97c1df5   Johan Hedberg   Bluetooth: mgmt: ...
2606
2607
  		goto unlock;
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
2608
  	cmd = pending_find(MGMT_OP_PAIR_DEVICE, hdev);
28424707a   Johan Hedberg   Bluetooth: mgmt: ...
2609
  	if (!cmd) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2610
2611
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
  				      MGMT_STATUS_INVALID_PARAMS);
28424707a   Johan Hedberg   Bluetooth: mgmt: ...
2612
2613
2614
2615
2616
2617
  		goto unlock;
  	}
  
  	conn = cmd->user_data;
  
  	if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2618
2619
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
  				      MGMT_STATUS_INVALID_PARAMS);
28424707a   Johan Hedberg   Bluetooth: mgmt: ...
2620
2621
  		goto unlock;
  	}
a511b35ba   Johan Hedberg   Bluetooth: Fix in...
2622
2623
  	cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
  	mgmt_pending_remove(cmd);
28424707a   Johan Hedberg   Bluetooth: mgmt: ...
2624

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2625
2626
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
  				addr, sizeof(*addr));
28424707a   Johan Hedberg   Bluetooth: mgmt: ...
2627
2628
  unlock:
  	hci_dev_unlock(hdev);
28424707a   Johan Hedberg   Bluetooth: mgmt: ...
2629
2630
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
2631
  static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
1707c60e5   Johan Hedberg   Bluetooth: Simpli...
2632
  			     struct mgmt_addr_info *addr, u16 mgmt_op,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2633
  			     u16 hci_op, __le32 passkey)
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2634
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2635
  	struct mgmt_pending_cmd *cmd;
0df4c185e   Brian Gix   Bluetooth: User P...
2636
  	struct hci_conn *conn;
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2637
  	int err;
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2638
  	hci_dev_lock(hdev);
08ba53824   Johan Hedberg   Bluetooth: Fix mi...
2639

4b34ee782   Johan Hedberg   Bluetooth: mgmt: ...
2640
  	if (!hdev_is_powered(hdev)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2641
2642
2643
  		err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
  					MGMT_STATUS_NOT_POWERED, addr,
  					sizeof(*addr));
0df4c185e   Brian Gix   Bluetooth: User P...
2644
  		goto done;
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2645
  	}
1707c60e5   Johan Hedberg   Bluetooth: Simpli...
2646
2647
  	if (addr->type == BDADDR_BREDR)
  		conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
272d90df2   Johan Hedberg   Bluetooth: Add ad...
2648
  	else
9d4c1cc15   Johan Hedberg   Bluetooth: Use hc...
2649
2650
  		conn = hci_conn_hash_lookup_le(hdev, &addr->bdaddr,
  					       le_addr_type(addr->type));
272d90df2   Johan Hedberg   Bluetooth: Add ad...
2651
2652
  
  	if (!conn) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2653
2654
2655
  		err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
  					MGMT_STATUS_NOT_CONNECTED, addr,
  					sizeof(*addr));
272d90df2   Johan Hedberg   Bluetooth: Add ad...
2656
2657
  		goto done;
  	}
47c15e2b3   Brian Gix   Bluetooth: Differ...
2658

1707c60e5   Johan Hedberg   Bluetooth: Simpli...
2659
  	if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
5fe57d9e9   Brian Gix   Bluetooth: Add SM...
2660
  		err = smp_user_confirm_reply(conn, mgmt_op, passkey);
5fe57d9e9   Brian Gix   Bluetooth: Add SM...
2661
  		if (!err)
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2662
2663
2664
  			err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
  						MGMT_STATUS_SUCCESS, addr,
  						sizeof(*addr));
5fe57d9e9   Brian Gix   Bluetooth: Add SM...
2665
  		else
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2666
2667
2668
  			err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
  						MGMT_STATUS_FAILED, addr,
  						sizeof(*addr));
47c15e2b3   Brian Gix   Bluetooth: Differ...
2669

47c15e2b3   Brian Gix   Bluetooth: Differ...
2670
2671
  		goto done;
  	}
1707c60e5   Johan Hedberg   Bluetooth: Simpli...
2672
  	cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2673
2674
  	if (!cmd) {
  		err = -ENOMEM;
0df4c185e   Brian Gix   Bluetooth: User P...
2675
  		goto done;
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2676
  	}
7776d1d80   Johan Hedberg   Bluetooth: Use cm...
2677
  	cmd->cmd_complete = addr_cmd_complete;
0df4c185e   Brian Gix   Bluetooth: User P...
2678
  	/* Continue with pairing via HCI */
604086b73   Brian Gix   Bluetooth: Add Us...
2679
2680
  	if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
  		struct hci_cp_user_passkey_reply cp;
1707c60e5   Johan Hedberg   Bluetooth: Simpli...
2681
  		bacpy(&cp.bdaddr, &addr->bdaddr);
604086b73   Brian Gix   Bluetooth: Add Us...
2682
2683
2684
  		cp.passkey = passkey;
  		err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
  	} else
1707c60e5   Johan Hedberg   Bluetooth: Simpli...
2685
2686
  		err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
  				   &addr->bdaddr);
604086b73   Brian Gix   Bluetooth: Add Us...
2687

a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
2688
2689
  	if (err < 0)
  		mgmt_pending_remove(cmd);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2690

0df4c185e   Brian Gix   Bluetooth: User P...
2691
  done:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2692
  	hci_dev_unlock(hdev);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2693
2694
  	return err;
  }
afeb019d0   Jaganath Kanakkassery   Bluetooth: Refact...
2695
2696
2697
2698
2699
2700
  static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
  			      void *data, u16 len)
  {
  	struct mgmt_cp_pin_code_neg_reply *cp = data;
  
  	BT_DBG("");
1707c60e5   Johan Hedberg   Bluetooth: Simpli...
2701
  	return user_pairing_resp(sk, hdev, &cp->addr,
afeb019d0   Jaganath Kanakkassery   Bluetooth: Refact...
2702
2703
2704
  				MGMT_OP_PIN_CODE_NEG_REPLY,
  				HCI_OP_PIN_CODE_NEG_REPLY, 0);
  }
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2705
2706
  static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
  			      u16 len)
0df4c185e   Brian Gix   Bluetooth: User P...
2707
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
2708
  	struct mgmt_cp_user_confirm_reply *cp = data;
0df4c185e   Brian Gix   Bluetooth: User P...
2709
2710
2711
2712
  
  	BT_DBG("");
  
  	if (len != sizeof(*cp))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2713
2714
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
  				       MGMT_STATUS_INVALID_PARAMS);
0df4c185e   Brian Gix   Bluetooth: User P...
2715

1707c60e5   Johan Hedberg   Bluetooth: Simpli...
2716
  	return user_pairing_resp(sk, hdev, &cp->addr,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2717
2718
  				 MGMT_OP_USER_CONFIRM_REPLY,
  				 HCI_OP_USER_CONFIRM_REPLY, 0);
0df4c185e   Brian Gix   Bluetooth: User P...
2719
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
2720
  static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2721
  				  void *data, u16 len)
0df4c185e   Brian Gix   Bluetooth: User P...
2722
  {
c9c2659f1   Johan Hedberg   Bluetooth: Use co...
2723
  	struct mgmt_cp_user_confirm_neg_reply *cp = data;
0df4c185e   Brian Gix   Bluetooth: User P...
2724
2725
  
  	BT_DBG("");
1707c60e5   Johan Hedberg   Bluetooth: Simpli...
2726
  	return user_pairing_resp(sk, hdev, &cp->addr,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2727
2728
  				 MGMT_OP_USER_CONFIRM_NEG_REPLY,
  				 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
0df4c185e   Brian Gix   Bluetooth: User P...
2729
  }
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2730
2731
  static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
  			      u16 len)
604086b73   Brian Gix   Bluetooth: Add Us...
2732
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
2733
  	struct mgmt_cp_user_passkey_reply *cp = data;
604086b73   Brian Gix   Bluetooth: Add Us...
2734
2735
  
  	BT_DBG("");
1707c60e5   Johan Hedberg   Bluetooth: Simpli...
2736
  	return user_pairing_resp(sk, hdev, &cp->addr,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2737
2738
  				 MGMT_OP_USER_PASSKEY_REPLY,
  				 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
604086b73   Brian Gix   Bluetooth: Add Us...
2739
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
2740
  static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2741
  				  void *data, u16 len)
604086b73   Brian Gix   Bluetooth: Add Us...
2742
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
2743
  	struct mgmt_cp_user_passkey_neg_reply *cp = data;
604086b73   Brian Gix   Bluetooth: Add Us...
2744
2745
  
  	BT_DBG("");
1707c60e5   Johan Hedberg   Bluetooth: Simpli...
2746
  	return user_pairing_resp(sk, hdev, &cp->addr,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2747
2748
  				 MGMT_OP_USER_PASSKEY_NEG_REPLY,
  				 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
604086b73   Brian Gix   Bluetooth: Add Us...
2749
  }
7c295c480   MichaƂ Narajowski   Bluetooth: Add su...
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
  static void adv_expire(struct hci_dev *hdev, u32 flags)
  {
  	struct adv_info *adv_instance;
  	struct hci_request req;
  	int err;
  
  	adv_instance = hci_find_adv_instance(hdev, hdev->cur_adv_instance);
  	if (!adv_instance)
  		return;
  
  	/* stop if current instance doesn't need to be changed */
  	if (!(adv_instance->flags & flags))
  		return;
  
  	cancel_adv_timeout(hdev);
  
  	adv_instance = hci_get_next_instance(hdev, adv_instance->instance);
  	if (!adv_instance)
  		return;
  
  	hci_req_init(&req, hdev);
  	err = __hci_req_schedule_adv_instance(&req, adv_instance->instance,
  					      true);
  	if (err)
  		return;
  
  	hci_req_run(&req, NULL);
  }
1904a853f   Marcel Holtmann   Bluetooth: Add op...
2778
  static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
139289713   Johan Hedberg   Bluetooth: Fix wa...
2779
2780
  {
  	struct mgmt_cp_set_local_name *cp;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2781
  	struct mgmt_pending_cmd *cmd;
139289713   Johan Hedberg   Bluetooth: Fix wa...
2782
2783
2784
2785
  
  	BT_DBG("status 0x%02x", status);
  
  	hci_dev_lock(hdev);
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
2786
  	cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
139289713   Johan Hedberg   Bluetooth: Fix wa...
2787
2788
2789
2790
  	if (!cmd)
  		goto unlock;
  
  	cp = cmd->param;
7c295c480   MichaƂ Narajowski   Bluetooth: Add su...
2791
  	if (status) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2792
2793
  		mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
  			        mgmt_status(status));
7c295c480   MichaƂ Narajowski   Bluetooth: Add su...
2794
  	} else {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2795
2796
  		mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
  				  cp, sizeof(*cp));
139289713   Johan Hedberg   Bluetooth: Fix wa...
2797

7c295c480   MichaƂ Narajowski   Bluetooth: Add su...
2798
2799
2800
  		if (hci_dev_test_flag(hdev, HCI_LE_ADV))
  			adv_expire(hdev, MGMT_ADV_FLAG_LOCAL_NAME);
  	}
139289713   Johan Hedberg   Bluetooth: Fix wa...
2801
2802
2803
2804
2805
  	mgmt_pending_remove(cmd);
  
  unlock:
  	hci_dev_unlock(hdev);
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
2806
  static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2807
  			  u16 len)
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
2808
  {
2b4bf3974   Johan Hedberg   Bluetooth: mgmt: ...
2809
  	struct mgmt_cp_set_local_name *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2810
  	struct mgmt_pending_cmd *cmd;
890ea8988   Johan Hedberg   Bluetooth: Update...
2811
  	struct hci_request req;
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
2812
2813
2814
  	int err;
  
  	BT_DBG("");
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2815
  	hci_dev_lock(hdev);
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
2816

b3f2ca944   Johan Hedberg   Bluetooth: Fix se...
2817
2818
2819
2820
2821
2822
  	/* If the old values are the same as the new ones just return a
  	 * direct command complete event.
  	 */
  	if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
  	    !memcmp(hdev->short_name, cp->short_name,
  		    sizeof(hdev->short_name))) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2823
2824
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
  					data, len);
b3f2ca944   Johan Hedberg   Bluetooth: Fix se...
2825
2826
  		goto failed;
  	}
2b4bf3974   Johan Hedberg   Bluetooth: mgmt: ...
2827
  	memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
28cc7bde5   Johan Hedberg   Bluetooth: mgmt: ...
2828

b5235a65a   Johan Hedberg   Bluetooth: mgmt: ...
2829
  	if (!hdev_is_powered(hdev)) {
2b4bf3974   Johan Hedberg   Bluetooth: mgmt: ...
2830
  		memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
28cc7bde5   Johan Hedberg   Bluetooth: mgmt: ...
2831

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2832
2833
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
  					data, len);
28cc7bde5   Johan Hedberg   Bluetooth: mgmt: ...
2834
2835
  		if (err < 0)
  			goto failed;
5504c3a31   Marcel Holtmann   Bluetooth: Use in...
2836
2837
  		err = mgmt_limited_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data,
  					 len, HCI_MGMT_LOCAL_NAME_EVENTS, sk);
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
2838
  		ext_info_changed(hdev, sk);
28cc7bde5   Johan Hedberg   Bluetooth: mgmt: ...
2839

b5235a65a   Johan Hedberg   Bluetooth: mgmt: ...
2840
2841
  		goto failed;
  	}
28cc7bde5   Johan Hedberg   Bluetooth: mgmt: ...
2842
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
2843
2844
2845
2846
  	if (!cmd) {
  		err = -ENOMEM;
  		goto failed;
  	}
139289713   Johan Hedberg   Bluetooth: Fix wa...
2847
  	memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
890ea8988   Johan Hedberg   Bluetooth: Update...
2848
  	hci_req_init(&req, hdev);
3f985050f   Johan Hedberg   Bluetooth: Fix lo...
2849
2850
  
  	if (lmp_bredr_capable(hdev)) {
00cf5040b   Johan Hedberg   Bluetooth: HCI na...
2851
  		__hci_req_update_name(&req);
b1a8917c9   Johan Hedberg   Bluetooth: Move E...
2852
  		__hci_req_update_eir(&req);
3f985050f   Johan Hedberg   Bluetooth: Fix lo...
2853
  	}
7a5f4990a   Marcel Holtmann   Bluetooth: Store ...
2854
2855
2856
  	/* The name is stored in the scan response data and so
  	 * no need to udpate the advertising data here.
  	 */
7dc6f16c6   MichaƂ Narajowski   Bluetooth: Fix no...
2857
  	if (lmp_le_capable(hdev) && hci_dev_test_flag(hdev, HCI_ADVERTISING))
cab054ab4   Johan Hedberg   Bluetooth: Clean ...
2858
  		__hci_req_update_scan_rsp_data(&req, hdev->cur_adv_instance);
3f985050f   Johan Hedberg   Bluetooth: Fix lo...
2859

139289713   Johan Hedberg   Bluetooth: Fix wa...
2860
  	err = hci_req_run(&req, set_name_complete);
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
2861
2862
2863
2864
  	if (err < 0)
  		mgmt_pending_remove(cmd);
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2865
  	hci_dev_unlock(hdev);
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
2866
2867
  	return err;
  }
c4960ecf2   MichaƂ Narajowski   Bluetooth: Add su...
2868
2869
2870
2871
2872
2873
2874
2875
  static int set_appearance(struct sock *sk, struct hci_dev *hdev, void *data,
  			  u16 len)
  {
  	struct mgmt_cp_set_appearance *cp = data;
  	u16 apperance;
  	int err;
  
  	BT_DBG("");
af4168c5a   MichaƂ Narajowski   Bluetooth: Set ap...
2876
2877
2878
  	if (!lmp_le_capable(hdev))
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_APPEARANCE,
  				       MGMT_STATUS_NOT_SUPPORTED);
c4960ecf2   MichaƂ Narajowski   Bluetooth: Add su...
2879
2880
2881
2882
2883
2884
2885
2886
2887
  	apperance = le16_to_cpu(cp->appearance);
  
  	hci_dev_lock(hdev);
  
  	if (hdev->appearance != apperance) {
  		hdev->appearance = apperance;
  
  		if (hci_dev_test_flag(hdev, HCI_LE_ADV))
  			adv_expire(hdev, MGMT_ADV_FLAG_APPEARANCE);
e74317f43   MichaƂ Narajowski   Bluetooth: Fix mi...
2888
2889
  
  		ext_info_changed(hdev, sk);
c4960ecf2   MichaƂ Narajowski   Bluetooth: Add su...
2890
2891
2892
2893
2894
2895
2896
2897
2898
  	}
  
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_APPEARANCE, 0, NULL,
  				0);
  
  	hci_dev_unlock(hdev);
  
  	return err;
  }
1b9441f8e   Johan Hedberg   Bluetooth: Conver...
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
  static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
  				         u16 opcode, struct sk_buff *skb)
  {
  	struct mgmt_rp_read_local_oob_data mgmt_rp;
  	size_t rp_size = sizeof(mgmt_rp);
  	struct mgmt_pending_cmd *cmd;
  
  	BT_DBG("%s status %u", hdev->name, status);
  
  	cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
  	if (!cmd)
  		return;
  
  	if (status || !skb) {
  		mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
  				status ? mgmt_status(status) : MGMT_STATUS_FAILED);
  		goto remove;
  	}
  
  	memset(&mgmt_rp, 0, sizeof(mgmt_rp));
  
  	if (opcode == HCI_OP_READ_LOCAL_OOB_DATA) {
  		struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
  
  		if (skb->len < sizeof(*rp)) {
  			mgmt_cmd_status(cmd->sk, hdev->id,
  					MGMT_OP_READ_LOCAL_OOB_DATA,
  					MGMT_STATUS_FAILED);
  			goto remove;
  		}
  
  		memcpy(mgmt_rp.hash192, rp->hash, sizeof(rp->hash));
  		memcpy(mgmt_rp.rand192, rp->rand, sizeof(rp->rand));
  
  		rp_size -= sizeof(mgmt_rp.hash256) + sizeof(mgmt_rp.rand256);
  	} else {
  		struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data;
  
  		if (skb->len < sizeof(*rp)) {
  			mgmt_cmd_status(cmd->sk, hdev->id,
  					MGMT_OP_READ_LOCAL_OOB_DATA,
  					MGMT_STATUS_FAILED);
  			goto remove;
  		}
  
  		memcpy(mgmt_rp.hash192, rp->hash192, sizeof(rp->hash192));
  		memcpy(mgmt_rp.rand192, rp->rand192, sizeof(rp->rand192));
  
  		memcpy(mgmt_rp.hash256, rp->hash256, sizeof(rp->hash256));
  		memcpy(mgmt_rp.rand256, rp->rand256, sizeof(rp->rand256));
  	}
  
  	mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
  			  MGMT_STATUS_SUCCESS, &mgmt_rp, rp_size);
  
  remove:
  	mgmt_pending_remove(cmd);
  }
0f4e68cf6   Johan Hedberg   Bluetooth: mgmt: ...
2957
  static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2958
  			       void *data, u16 data_len)
c35938b2f   Szymon Janc   Bluetooth: Add re...
2959
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2960
  	struct mgmt_pending_cmd *cmd;
1b9441f8e   Johan Hedberg   Bluetooth: Conver...
2961
  	struct hci_request req;
c35938b2f   Szymon Janc   Bluetooth: Add re...
2962
  	int err;
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
2963
  	BT_DBG("%s", hdev->name);
c35938b2f   Szymon Janc   Bluetooth: Add re...
2964

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2965
  	hci_dev_lock(hdev);
c35938b2f   Szymon Janc   Bluetooth: Add re...
2966

4b34ee782   Johan Hedberg   Bluetooth: mgmt: ...
2967
  	if (!hdev_is_powered(hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2968
2969
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
  				      MGMT_STATUS_NOT_POWERED);
c35938b2f   Szymon Janc   Bluetooth: Add re...
2970
2971
  		goto unlock;
  	}
9a1a1996d   Andre Guedes   Bluetooth: Use lm...
2972
  	if (!lmp_ssp_capable(hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2973
2974
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
  				      MGMT_STATUS_NOT_SUPPORTED);
c35938b2f   Szymon Janc   Bluetooth: Add re...
2975
2976
  		goto unlock;
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
2977
  	if (pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2978
2979
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
  				      MGMT_STATUS_BUSY);
c35938b2f   Szymon Janc   Bluetooth: Add re...
2980
2981
  		goto unlock;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
2982
  	cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
c35938b2f   Szymon Janc   Bluetooth: Add re...
2983
2984
2985
2986
  	if (!cmd) {
  		err = -ENOMEM;
  		goto unlock;
  	}
1b9441f8e   Johan Hedberg   Bluetooth: Conver...
2987
  	hci_req_init(&req, hdev);
710f11c08   Johan Hedberg   Bluetooth: Use cu...
2988
  	if (bredr_sc_enabled(hdev))
1b9441f8e   Johan Hedberg   Bluetooth: Conver...
2989
  		hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_EXT_DATA, 0, NULL);
4d2d27962   Marcel Holtmann   Bluetooth: Add su...
2990
  	else
1b9441f8e   Johan Hedberg   Bluetooth: Conver...
2991
  		hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
4d2d27962   Marcel Holtmann   Bluetooth: Add su...
2992

1b9441f8e   Johan Hedberg   Bluetooth: Conver...
2993
  	err = hci_req_run_skb(&req, read_local_oob_data_complete);
c35938b2f   Szymon Janc   Bluetooth: Add re...
2994
2995
2996
2997
  	if (err < 0)
  		mgmt_pending_remove(cmd);
  
  unlock:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2998
  	hci_dev_unlock(hdev);
c35938b2f   Szymon Janc   Bluetooth: Add re...
2999
3000
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
3001
  static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
3002
  			       void *data, u16 len)
2763eda6c   Szymon Janc   Bluetooth: Add ad...
3003
  {
5d57e7964   Johan Hedberg   Bluetooth: Check ...
3004
  	struct mgmt_addr_info *addr = data;
2763eda6c   Szymon Janc   Bluetooth: Add ad...
3005
  	int err;
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
3006
  	BT_DBG("%s ", hdev->name);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
3007

5d57e7964   Johan Hedberg   Bluetooth: Check ...
3008
  	if (!bdaddr_type_is_valid(addr->type))
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3009
3010
3011
3012
  		return mgmt_cmd_complete(sk, hdev->id,
  					 MGMT_OP_ADD_REMOTE_OOB_DATA,
  					 MGMT_STATUS_INVALID_PARAMS,
  					 addr, sizeof(*addr));
5d57e7964   Johan Hedberg   Bluetooth: Check ...
3013

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
3014
  	hci_dev_lock(hdev);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
3015

ec1091131   Marcel Holtmann   Bluetooth: Add su...
3016
3017
3018
  	if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
  		struct mgmt_cp_add_remote_oob_data *cp = data;
  		u8 status;
bf1e3541f   Johan Hedberg   Bluetooth: mgmt: ...
3019

c19a495c8   Johan Hedberg   Bluetooth: Fix BR...
3020
  		if (cp->addr.type != BDADDR_BREDR) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3021
3022
3023
3024
  			err = mgmt_cmd_complete(sk, hdev->id,
  						MGMT_OP_ADD_REMOTE_OOB_DATA,
  						MGMT_STATUS_INVALID_PARAMS,
  						&cp->addr, sizeof(cp->addr));
c19a495c8   Johan Hedberg   Bluetooth: Fix BR...
3025
3026
  			goto unlock;
  		}
ec1091131   Marcel Holtmann   Bluetooth: Add su...
3027
  		err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
6928a9245   Johan Hedberg   Bluetooth: Store ...
3028
3029
  					      cp->addr.type, cp->hash,
  					      cp->rand, NULL, NULL);
ec1091131   Marcel Holtmann   Bluetooth: Add su...
3030
3031
3032
3033
  		if (err < 0)
  			status = MGMT_STATUS_FAILED;
  		else
  			status = MGMT_STATUS_SUCCESS;
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3034
3035
3036
  		err = mgmt_cmd_complete(sk, hdev->id,
  					MGMT_OP_ADD_REMOTE_OOB_DATA, status,
  					&cp->addr, sizeof(cp->addr));
ec1091131   Marcel Holtmann   Bluetooth: Add su...
3037
3038
  	} else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
  		struct mgmt_cp_add_remote_oob_ext_data *cp = data;
41bcfd50d   Marcel Holtmann   Bluetooth: Allow ...
3039
  		u8 *rand192, *hash192, *rand256, *hash256;
ec1091131   Marcel Holtmann   Bluetooth: Add su...
3040
  		u8 status;
86df9200c   Johan Hedberg   Bluetooth: Add su...
3041
  		if (bdaddr_type_is_le(cp->addr.type)) {
d25b78e2e   Johan Hedberg   Bluetooth: Enforc...
3042
3043
3044
3045
3046
  			/* Enforce zero-valued 192-bit parameters as
  			 * long as legacy SMP OOB isn't implemented.
  			 */
  			if (memcmp(cp->rand192, ZERO_KEY, 16) ||
  			    memcmp(cp->hash192, ZERO_KEY, 16)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3047
3048
3049
3050
  				err = mgmt_cmd_complete(sk, hdev->id,
  							MGMT_OP_ADD_REMOTE_OOB_DATA,
  							MGMT_STATUS_INVALID_PARAMS,
  							addr, sizeof(*addr));
d25b78e2e   Johan Hedberg   Bluetooth: Enforc...
3051
3052
  				goto unlock;
  			}
86df9200c   Johan Hedberg   Bluetooth: Add su...
3053
3054
3055
  			rand192 = NULL;
  			hash192 = NULL;
  		} else {
41bcfd50d   Marcel Holtmann   Bluetooth: Allow ...
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
  			/* In case one of the P-192 values is set to zero,
  			 * then just disable OOB data for P-192.
  			 */
  			if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
  			    !memcmp(cp->hash192, ZERO_KEY, 16)) {
  				rand192 = NULL;
  				hash192 = NULL;
  			} else {
  				rand192 = cp->rand192;
  				hash192 = cp->hash192;
  			}
  		}
  
  		/* In case one of the P-256 values is set to zero, then just
  		 * disable OOB data for P-256.
  		 */
  		if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
  		    !memcmp(cp->hash256, ZERO_KEY, 16)) {
  			rand256 = NULL;
  			hash256 = NULL;
  		} else {
  			rand256 = cp->rand256;
  			hash256 = cp->hash256;
86df9200c   Johan Hedberg   Bluetooth: Add su...
3079
  		}
81328d5cc   Johan Hedberg   Bluetooth: Unify ...
3080
  		err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
86df9200c   Johan Hedberg   Bluetooth: Add su...
3081
  					      cp->addr.type, hash192, rand192,
41bcfd50d   Marcel Holtmann   Bluetooth: Allow ...
3082
  					      hash256, rand256);
ec1091131   Marcel Holtmann   Bluetooth: Add su...
3083
3084
3085
3086
  		if (err < 0)
  			status = MGMT_STATUS_FAILED;
  		else
  			status = MGMT_STATUS_SUCCESS;
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3087
3088
3089
  		err = mgmt_cmd_complete(sk, hdev->id,
  					MGMT_OP_ADD_REMOTE_OOB_DATA,
  					status, &cp->addr, sizeof(cp->addr));
ec1091131   Marcel Holtmann   Bluetooth: Add su...
3090
3091
  	} else {
  		BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3092
3093
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
  				      MGMT_STATUS_INVALID_PARAMS);
ec1091131   Marcel Holtmann   Bluetooth: Add su...
3094
  	}
2763eda6c   Szymon Janc   Bluetooth: Add ad...
3095

c19a495c8   Johan Hedberg   Bluetooth: Fix BR...
3096
  unlock:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
3097
  	hci_dev_unlock(hdev);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
3098
3099
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
3100
  static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
8ce8e2b56   Gustavo Padovan   Bluetooth: Fix co...
3101
  				  void *data, u16 len)
2763eda6c   Szymon Janc   Bluetooth: Add ad...
3102
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
3103
  	struct mgmt_cp_remove_remote_oob_data *cp = data;
bf1e3541f   Johan Hedberg   Bluetooth: mgmt: ...
3104
  	u8 status;
2763eda6c   Szymon Janc   Bluetooth: Add ad...
3105
  	int err;
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
3106
  	BT_DBG("%s", hdev->name);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
3107

c19a495c8   Johan Hedberg   Bluetooth: Fix BR...
3108
  	if (cp->addr.type != BDADDR_BREDR)
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3109
3110
3111
3112
  		return mgmt_cmd_complete(sk, hdev->id,
  					 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
  					 MGMT_STATUS_INVALID_PARAMS,
  					 &cp->addr, sizeof(cp->addr));
c19a495c8   Johan Hedberg   Bluetooth: Fix BR...
3113

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
3114
  	hci_dev_lock(hdev);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
3115

eedbd5812   Johan Hedberg   Bluetooth: Fix cl...
3116
3117
3118
3119
3120
  	if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
  		hci_remote_oob_data_clear(hdev);
  		status = MGMT_STATUS_SUCCESS;
  		goto done;
  	}
6928a9245   Johan Hedberg   Bluetooth: Store ...
3121
  	err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
3122
  	if (err < 0)
bf1e3541f   Johan Hedberg   Bluetooth: mgmt: ...
3123
  		status = MGMT_STATUS_INVALID_PARAMS;
2763eda6c   Szymon Janc   Bluetooth: Add ad...
3124
  	else
a6785be2f   Szymon Janc   Bluetooth: mgmt: ...
3125
  		status = MGMT_STATUS_SUCCESS;
bf1e3541f   Johan Hedberg   Bluetooth: mgmt: ...
3126

eedbd5812   Johan Hedberg   Bluetooth: Fix cl...
3127
  done:
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3128
3129
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
  				status, &cp->addr, sizeof(cp->addr));
2763eda6c   Szymon Janc   Bluetooth: Add ad...
3130

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
3131
  	hci_dev_unlock(hdev);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
3132
3133
  	return err;
  }
e68f072b7   Johan Hedberg   Bluetooth: Move S...
3134
  void mgmt_start_discovery_complete(struct hci_dev *hdev, u8 status)
7c3077207   Andre Guedes   Bluetooth: Update...
3135
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
3136
  	struct mgmt_pending_cmd *cmd;
ae55f5982   Lukasz Rymanowski   Bluetooth: Keep m...
3137

7c3077207   Andre Guedes   Bluetooth: Update...
3138
  	BT_DBG("status %d", status);
11e6e25d0   Marcel Holtmann   Bluetooth: Use {s...
3139
  	hci_dev_lock(hdev);
41dc2bd6d   Andre Guedes   Bluetooth: Make m...
3140

333ae95d0   Johan Hedberg   Bluetooth: Add ch...
3141
  	cmd = pending_find(MGMT_OP_START_DISCOVERY, hdev);
66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
3142
  	if (!cmd)
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
3143
  		cmd = pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
3144

78b781ca0   Johan Hedberg   Bluetooth: Add su...
3145
3146
  	if (!cmd)
  		cmd = pending_find(MGMT_OP_START_LIMITED_DISCOVERY, hdev);
11e6e25d0   Marcel Holtmann   Bluetooth: Use {s...
3147
  	if (cmd) {
2922a94fc   Johan Hedberg   Bluetooth: Conver...
3148
  		cmd->cmd_complete(cmd, mgmt_status(status));
11e6e25d0   Marcel Holtmann   Bluetooth: Use {s...
3149
3150
  		mgmt_pending_remove(cmd);
  	}
7c3077207   Andre Guedes   Bluetooth: Update...
3151

11e6e25d0   Marcel Holtmann   Bluetooth: Use {s...
3152
  	hci_dev_unlock(hdev);
7c3077207   Andre Guedes   Bluetooth: Update...
3153
  }
591752afb   Johan Hedberg   Bluetooth: Add di...
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
  static bool discovery_type_is_valid(struct hci_dev *hdev, uint8_t type,
  				    uint8_t *mgmt_status)
  {
  	switch (type) {
  	case DISCOV_TYPE_LE:
  		*mgmt_status = mgmt_le_support(hdev);
  		if (*mgmt_status)
  			return false;
  		break;
  	case DISCOV_TYPE_INTERLEAVED:
  		*mgmt_status = mgmt_le_support(hdev);
  		if (*mgmt_status)
  			return false;
  		/* Intentional fall-through */
  	case DISCOV_TYPE_BREDR:
  		*mgmt_status = mgmt_bredr_support(hdev);
  		if (*mgmt_status)
  			return false;
  		break;
  	default:
  		*mgmt_status = MGMT_STATUS_INVALID_PARAMS;
  		return false;
  	}
  
  	return true;
  }
78b781ca0   Johan Hedberg   Bluetooth: Add su...
3180
3181
  static int start_discovery_internal(struct sock *sk, struct hci_dev *hdev,
  				    u16 op, void *data, u16 len)
14a536641   Johan Hedberg   Bluetooth: Add ba...
3182
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
3183
  	struct mgmt_cp_start_discovery *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
3184
  	struct mgmt_pending_cmd *cmd;
8019044dc   Marcel Holtmann   Bluetooth: Split ...
3185
  	u8 status;
14a536641   Johan Hedberg   Bluetooth: Add ba...
3186
  	int err;
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
3187
  	BT_DBG("%s", hdev->name);
14a536641   Johan Hedberg   Bluetooth: Add ba...
3188

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
3189
  	hci_dev_lock(hdev);
14a536641   Johan Hedberg   Bluetooth: Add ba...
3190

4b34ee782   Johan Hedberg   Bluetooth: mgmt: ...
3191
  	if (!hdev_is_powered(hdev)) {
78b781ca0   Johan Hedberg   Bluetooth: Add su...
3192
  		err = mgmt_cmd_complete(sk, hdev->id, op,
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3193
3194
  					MGMT_STATUS_NOT_POWERED,
  					&cp->type, sizeof(cp->type));
bd2d1334e   Johan Hedberg   Bluetooth: Fix re...
3195
3196
  		goto failed;
  	}
f5a969f23   Marcel Holtmann   Bluetooth: Simpli...
3197
  	if (hdev->discovery.state != DISCOVERY_STOPPED ||
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
3198
  	    hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
78b781ca0   Johan Hedberg   Bluetooth: Add su...
3199
3200
  		err = mgmt_cmd_complete(sk, hdev->id, op, MGMT_STATUS_BUSY,
  					&cp->type, sizeof(cp->type));
642be6c76   Andre Guedes   Bluetooth: Check ...
3201
3202
  		goto failed;
  	}
591752afb   Johan Hedberg   Bluetooth: Add di...
3203
  	if (!discovery_type_is_valid(hdev, cp->type, &status)) {
78b781ca0   Johan Hedberg   Bluetooth: Add su...
3204
3205
  		err = mgmt_cmd_complete(sk, hdev->id, op, status,
  					&cp->type, sizeof(cp->type));
591752afb   Johan Hedberg   Bluetooth: Add di...
3206
3207
  		goto failed;
  	}
22078800c   Marcel Holtmann   Bluetooth: Fix me...
3208
3209
3210
3211
  	/* Clear the discovery filter first to free any previously
  	 * allocated memory for the UUID list.
  	 */
  	hci_discovery_filter_clear(hdev);
4aab14e55   Andre Guedes   Bluetooth: Track ...
3212
  	hdev->discovery.type = cp->type;
da25cf6a9   Marcel Holtmann   Bluetooth: Report...
3213
  	hdev->discovery.report_invalid_rssi = false;
78b781ca0   Johan Hedberg   Bluetooth: Add su...
3214
3215
3216
3217
  	if (op == MGMT_OP_START_LIMITED_DISCOVERY)
  		hdev->discovery.limited = true;
  	else
  		hdev->discovery.limited = false;
4aab14e55   Andre Guedes   Bluetooth: Track ...
3218

78b781ca0   Johan Hedberg   Bluetooth: Add su...
3219
  	cmd = mgmt_pending_add(sk, op, hdev, data, len);
e68f072b7   Johan Hedberg   Bluetooth: Move S...
3220
3221
  	if (!cmd) {
  		err = -ENOMEM;
041067557   Johan Hedberg   Bluetooth: Fix re...
3222
  		goto failed;
f39799f50   Andre Guedes   Bluetooth: Prepar...
3223
  	}
041067557   Johan Hedberg   Bluetooth: Fix re...
3224

e68f072b7   Johan Hedberg   Bluetooth: Move S...
3225
  	cmd->cmd_complete = generic_cmd_complete;
7c3077207   Andre Guedes   Bluetooth: Update...
3226

f5a969f23   Marcel Holtmann   Bluetooth: Simpli...
3227
  	hci_discovery_set_state(hdev, DISCOVERY_STARTING);
e68f072b7   Johan Hedberg   Bluetooth: Move S...
3228
3229
  	queue_work(hdev->req_workqueue, &hdev->discov_update);
  	err = 0;
7c3077207   Andre Guedes   Bluetooth: Update...
3230

14a536641   Johan Hedberg   Bluetooth: Add ba...
3231
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
3232
  	hci_dev_unlock(hdev);
14a536641   Johan Hedberg   Bluetooth: Add ba...
3233
3234
  	return err;
  }
f39799f50   Andre Guedes   Bluetooth: Prepar...
3235

78b781ca0   Johan Hedberg   Bluetooth: Add su...
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
  static int start_discovery(struct sock *sk, struct hci_dev *hdev,
  			   void *data, u16 len)
  {
  	return start_discovery_internal(sk, hdev, MGMT_OP_START_DISCOVERY,
  					data, len);
  }
  
  static int start_limited_discovery(struct sock *sk, struct hci_dev *hdev,
  				   void *data, u16 len)
  {
  	return start_discovery_internal(sk, hdev,
  					MGMT_OP_START_LIMITED_DISCOVERY,
  					data, len);
  }
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
3250
3251
  static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
  					  u8 status)
2922a94fc   Johan Hedberg   Bluetooth: Conver...
3252
  {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3253
3254
  	return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
  				 cmd->param, 1);
2922a94fc   Johan Hedberg   Bluetooth: Conver...
3255
  }
041067557   Johan Hedberg   Bluetooth: Fix re...
3256

66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
3257
3258
3259
3260
  static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
  				   void *data, u16 len)
  {
  	struct mgmt_cp_start_service_discovery *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
3261
  	struct mgmt_pending_cmd *cmd;
66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
3262
3263
3264
3265
  	const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
  	u16 uuid_count, expected_len;
  	u8 status;
  	int err;
041067557   Johan Hedberg   Bluetooth: Fix re...
3266

66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
3267
  	BT_DBG("%s", hdev->name);
e8bb6b973   Johan Hedberg   Bluetooth: Fix ad...
3268

66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
3269
  	hci_dev_lock(hdev);
7c3077207   Andre Guedes   Bluetooth: Update...
3270

66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
3271
  	if (!hdev_is_powered(hdev)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3272
3273
3274
3275
  		err = mgmt_cmd_complete(sk, hdev->id,
  					MGMT_OP_START_SERVICE_DISCOVERY,
  					MGMT_STATUS_NOT_POWERED,
  					&cp->type, sizeof(cp->type));
66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
3276
3277
  		goto failed;
  	}
7c3077207   Andre Guedes   Bluetooth: Update...
3278

66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
3279
  	if (hdev->discovery.state != DISCOVERY_STOPPED ||
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
3280
  	    hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3281
3282
3283
3284
  		err = mgmt_cmd_complete(sk, hdev->id,
  					MGMT_OP_START_SERVICE_DISCOVERY,
  					MGMT_STATUS_BUSY, &cp->type,
  					sizeof(cp->type));
66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
3285
3286
  		goto failed;
  	}
d94839436   Johan Hedberg   Bluetooth: Use hc...
3287

66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
3288
3289
3290
3291
  	uuid_count = __le16_to_cpu(cp->uuid_count);
  	if (uuid_count > max_uuid_count) {
  		BT_ERR("service_discovery: too big uuid_count value %u",
  		       uuid_count);
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3292
3293
3294
3295
  		err = mgmt_cmd_complete(sk, hdev->id,
  					MGMT_OP_START_SERVICE_DISCOVERY,
  					MGMT_STATUS_INVALID_PARAMS, &cp->type,
  					sizeof(cp->type));
66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
3296
3297
3298
3299
3300
3301
3302
  		goto failed;
  	}
  
  	expected_len = sizeof(*cp) + uuid_count * 16;
  	if (expected_len != len) {
  		BT_ERR("service_discovery: expected %u bytes, got %u bytes",
  		       expected_len, len);
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3303
3304
3305
3306
  		err = mgmt_cmd_complete(sk, hdev->id,
  					MGMT_OP_START_SERVICE_DISCOVERY,
  					MGMT_STATUS_INVALID_PARAMS, &cp->type,
  					sizeof(cp->type));
66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
3307
3308
  		goto failed;
  	}
591752afb   Johan Hedberg   Bluetooth: Add di...
3309
3310
3311
3312
3313
3314
  	if (!discovery_type_is_valid(hdev, cp->type, &status)) {
  		err = mgmt_cmd_complete(sk, hdev->id,
  					MGMT_OP_START_SERVICE_DISCOVERY,
  					status, &cp->type, sizeof(cp->type));
  		goto failed;
  	}
66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
3315
  	cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
2922a94fc   Johan Hedberg   Bluetooth: Conver...
3316
  			       hdev, data, len);
66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
3317
3318
3319
3320
  	if (!cmd) {
  		err = -ENOMEM;
  		goto failed;
  	}
2922a94fc   Johan Hedberg   Bluetooth: Conver...
3321
  	cmd->cmd_complete = service_discovery_cmd_complete;
22078800c   Marcel Holtmann   Bluetooth: Fix me...
3322
3323
3324
3325
  	/* Clear the discovery filter first to free any previously
  	 * allocated memory for the UUID list.
  	 */
  	hci_discovery_filter_clear(hdev);
82f8b651a   Jakub Pawlowski   Bluetooth: fix se...
3326
  	hdev->discovery.result_filtering = true;
66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
3327
3328
3329
3330
3331
3332
3333
3334
  	hdev->discovery.type = cp->type;
  	hdev->discovery.rssi = cp->rssi;
  	hdev->discovery.uuid_count = uuid_count;
  
  	if (uuid_count > 0) {
  		hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
  						GFP_KERNEL);
  		if (!hdev->discovery.uuids) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3335
3336
3337
3338
  			err = mgmt_cmd_complete(sk, hdev->id,
  						MGMT_OP_START_SERVICE_DISCOVERY,
  						MGMT_STATUS_FAILED,
  						&cp->type, sizeof(cp->type));
d94839436   Johan Hedberg   Bluetooth: Use hc...
3339
3340
3341
  			mgmt_pending_remove(cmd);
  			goto failed;
  		}
66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
3342
  	}
d94839436   Johan Hedberg   Bluetooth: Use hc...
3343

66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
3344
  	hci_discovery_set_state(hdev, DISCOVERY_STARTING);
e68f072b7   Johan Hedberg   Bluetooth: Move S...
3345
3346
  	queue_work(hdev->req_workqueue, &hdev->discov_update);
  	err = 0;
14a536641   Johan Hedberg   Bluetooth: Add ba...
3347
3348
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
3349
  	hci_dev_unlock(hdev);
14a536641   Johan Hedberg   Bluetooth: Add ba...
3350
3351
  	return err;
  }
2154d3f4f   Johan Hedberg   Bluetooth: Move S...
3352
  void mgmt_stop_discovery_complete(struct hci_dev *hdev, u8 status)
1183fdcad   Andre Guedes   Bluetooth: Make m...
3353
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
3354
  	struct mgmt_pending_cmd *cmd;
1183fdcad   Andre Guedes   Bluetooth: Make m...
3355

0e05bba6f   Andre Guedes   Bluetooth: Update...
3356
3357
3358
  	BT_DBG("status %d", status);
  
  	hci_dev_lock(hdev);
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
3359
  	cmd = pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
11e6e25d0   Marcel Holtmann   Bluetooth: Use {s...
3360
  	if (cmd) {
2922a94fc   Johan Hedberg   Bluetooth: Conver...
3361
  		cmd->cmd_complete(cmd, mgmt_status(status));
11e6e25d0   Marcel Holtmann   Bluetooth: Use {s...
3362
  		mgmt_pending_remove(cmd);
0e05bba6f   Andre Guedes   Bluetooth: Update...
3363
  	}
0e05bba6f   Andre Guedes   Bluetooth: Update...
3364
3365
  	hci_dev_unlock(hdev);
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
3366
  static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
3367
  			  u16 len)
14a536641   Johan Hedberg   Bluetooth: Add ba...
3368
  {
d930650b5   Johan Hedberg   Bluetooth: mgmt: ...
3369
  	struct mgmt_cp_stop_discovery *mgmt_cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
3370
  	struct mgmt_pending_cmd *cmd;
14a536641   Johan Hedberg   Bluetooth: Add ba...
3371
  	int err;
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
3372
  	BT_DBG("%s", hdev->name);
14a536641   Johan Hedberg   Bluetooth: Add ba...
3373

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
3374
  	hci_dev_lock(hdev);
14a536641   Johan Hedberg   Bluetooth: Add ba...
3375

30dc78e1a   Johan Hedberg   Bluetooth: Add na...
3376
  	if (!hci_discovery_active(hdev)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3377
3378
3379
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
  					MGMT_STATUS_REJECTED, &mgmt_cp->type,
  					sizeof(mgmt_cp->type));
d930650b5   Johan Hedberg   Bluetooth: mgmt: ...
3380
3381
3382
3383
  		goto unlock;
  	}
  
  	if (hdev->discovery.type != mgmt_cp->type) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3384
3385
3386
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
  					MGMT_STATUS_INVALID_PARAMS,
  					&mgmt_cp->type, sizeof(mgmt_cp->type));
30dc78e1a   Johan Hedberg   Bluetooth: Add na...
3387
  		goto unlock;
ff9ef5787   Johan Hedberg   Bluetooth: Add di...
3388
  	}
2922a94fc   Johan Hedberg   Bluetooth: Conver...
3389
  	cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
14a536641   Johan Hedberg   Bluetooth: Add ba...
3390
3391
  	if (!cmd) {
  		err = -ENOMEM;
30dc78e1a   Johan Hedberg   Bluetooth: Add na...
3392
3393
  		goto unlock;
  	}
2922a94fc   Johan Hedberg   Bluetooth: Conver...
3394
  	cmd->cmd_complete = generic_cmd_complete;
2154d3f4f   Johan Hedberg   Bluetooth: Move S...
3395
3396
3397
  	hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
  	queue_work(hdev->req_workqueue, &hdev->discov_update);
  	err = 0;
14a536641   Johan Hedberg   Bluetooth: Add ba...
3398

30dc78e1a   Johan Hedberg   Bluetooth: Add na...
3399
  unlock:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
3400
  	hci_dev_unlock(hdev);
14a536641   Johan Hedberg   Bluetooth: Add ba...
3401
3402
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
3403
  static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
3404
  			u16 len)
561aafbcb   Johan Hedberg   Bluetooth: Add in...
3405
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
3406
  	struct mgmt_cp_confirm_name *cp = data;
561aafbcb   Johan Hedberg   Bluetooth: Add in...
3407
  	struct inquiry_entry *e;
561aafbcb   Johan Hedberg   Bluetooth: Add in...
3408
  	int err;
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
3409
  	BT_DBG("%s", hdev->name);
561aafbcb   Johan Hedberg   Bluetooth: Add in...
3410

561aafbcb   Johan Hedberg   Bluetooth: Add in...
3411
  	hci_dev_lock(hdev);
30dc78e1a   Johan Hedberg   Bluetooth: Add na...
3412
  	if (!hci_discovery_active(hdev)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3413
3414
3415
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
  					MGMT_STATUS_FAILED, &cp->addr,
  					sizeof(cp->addr));
30dc78e1a   Johan Hedberg   Bluetooth: Add na...
3416
3417
  		goto failed;
  	}
a198e7b10   Johan Hedberg   Bluetooth: mgmt: ...
3418
  	e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
561aafbcb   Johan Hedberg   Bluetooth: Add in...
3419
  	if (!e) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3420
3421
3422
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
  					MGMT_STATUS_INVALID_PARAMS, &cp->addr,
  					sizeof(cp->addr));
561aafbcb   Johan Hedberg   Bluetooth: Add in...
3423
3424
3425
3426
3427
3428
3429
3430
  		goto failed;
  	}
  
  	if (cp->name_known) {
  		e->name_state = NAME_KNOWN;
  		list_del(&e->list);
  	} else {
  		e->name_state = NAME_NEEDED;
a3d4e20a8   Johan Hedberg   Bluetooth: Sort t...
3431
  		hci_inquiry_cache_update_resolve(hdev, e);
561aafbcb   Johan Hedberg   Bluetooth: Add in...
3432
  	}
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3433
3434
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
  				&cp->addr, sizeof(cp->addr));
561aafbcb   Johan Hedberg   Bluetooth: Add in...
3435
3436
3437
  
  failed:
  	hci_dev_unlock(hdev);
561aafbcb   Johan Hedberg   Bluetooth: Add in...
3438
3439
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
3440
  static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
3441
  			u16 len)
7fbec224c   Antti Julku   Bluetooth: Add bl...
3442
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
3443
  	struct mgmt_cp_block_device *cp = data;
f0eeea8b6   Johan Hedberg   Bluetooth: mgmt: ...
3444
  	u8 status;
7fbec224c   Antti Julku   Bluetooth: Add bl...
3445
  	int err;
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
3446
  	BT_DBG("%s", hdev->name);
7fbec224c   Antti Julku   Bluetooth: Add bl...
3447

4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
3448
  	if (!bdaddr_type_is_valid(cp->addr.type))
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3449
3450
3451
  		return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
  					 MGMT_STATUS_INVALID_PARAMS,
  					 &cp->addr, sizeof(cp->addr));
4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
3452

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
3453
  	hci_dev_lock(hdev);
5e762444b   Antti Julku   Bluetooth: Add mg...
3454

dcc36c16c   Johan Hedberg   Bluetooth: Unify ...
3455
3456
  	err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
  				  cp->addr.type);
2a8357f23   Johan Hedberg   Bluetooth: Fix re...
3457
  	if (err < 0) {
f0eeea8b6   Johan Hedberg   Bluetooth: mgmt: ...
3458
  		status = MGMT_STATUS_FAILED;
2a8357f23   Johan Hedberg   Bluetooth: Fix re...
3459
3460
3461
3462
3463
3464
  		goto done;
  	}
  
  	mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
  		   sk);
  	status = MGMT_STATUS_SUCCESS;
f0eeea8b6   Johan Hedberg   Bluetooth: mgmt: ...
3465

2a8357f23   Johan Hedberg   Bluetooth: Fix re...
3466
  done:
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3467
3468
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
  				&cp->addr, sizeof(cp->addr));
5e762444b   Antti Julku   Bluetooth: Add mg...
3469

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
3470
  	hci_dev_unlock(hdev);
7fbec224c   Antti Julku   Bluetooth: Add bl...
3471
3472
3473
  
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
3474
  static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
3475
  			  u16 len)
7fbec224c   Antti Julku   Bluetooth: Add bl...
3476
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
3477
  	struct mgmt_cp_unblock_device *cp = data;
f0eeea8b6   Johan Hedberg   Bluetooth: mgmt: ...
3478
  	u8 status;
7fbec224c   Antti Julku   Bluetooth: Add bl...
3479
  	int err;
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
3480
  	BT_DBG("%s", hdev->name);
7fbec224c   Antti Julku   Bluetooth: Add bl...
3481

4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
3482
  	if (!bdaddr_type_is_valid(cp->addr.type))
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3483
3484
3485
  		return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
  					 MGMT_STATUS_INVALID_PARAMS,
  					 &cp->addr, sizeof(cp->addr));
4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
3486

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
3487
  	hci_dev_lock(hdev);
5e762444b   Antti Julku   Bluetooth: Add mg...
3488

dcc36c16c   Johan Hedberg   Bluetooth: Unify ...
3489
3490
  	err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
  				  cp->addr.type);
2a8357f23   Johan Hedberg   Bluetooth: Fix re...
3491
  	if (err < 0) {
f0eeea8b6   Johan Hedberg   Bluetooth: mgmt: ...
3492
  		status = MGMT_STATUS_INVALID_PARAMS;
2a8357f23   Johan Hedberg   Bluetooth: Fix re...
3493
3494
3495
3496
3497
3498
  		goto done;
  	}
  
  	mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
  		   sk);
  	status = MGMT_STATUS_SUCCESS;
f0eeea8b6   Johan Hedberg   Bluetooth: mgmt: ...
3499

2a8357f23   Johan Hedberg   Bluetooth: Fix re...
3500
  done:
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3501
3502
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
  				&cp->addr, sizeof(cp->addr));
5e762444b   Antti Julku   Bluetooth: Add mg...
3503

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
3504
  	hci_dev_unlock(hdev);
7fbec224c   Antti Julku   Bluetooth: Add bl...
3505
3506
3507
  
  	return err;
  }
cdbaccca7   Marcel Holtmann   Bluetooth: Add ma...
3508
3509
3510
3511
  static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
  			 u16 len)
  {
  	struct mgmt_cp_set_device_id *cp = data;
890ea8988   Johan Hedberg   Bluetooth: Update...
3512
  	struct hci_request req;
cdbaccca7   Marcel Holtmann   Bluetooth: Add ma...
3513
  	int err;
c72d4b8af   Szymon Janc   Bluetooth: mgmt: ...
3514
  	__u16 source;
cdbaccca7   Marcel Holtmann   Bluetooth: Add ma...
3515
3516
  
  	BT_DBG("%s", hdev->name);
c72d4b8af   Szymon Janc   Bluetooth: mgmt: ...
3517
3518
3519
  	source = __le16_to_cpu(cp->source);
  
  	if (source > 0x0002)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3520
3521
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
  				       MGMT_STATUS_INVALID_PARAMS);
c72d4b8af   Szymon Janc   Bluetooth: mgmt: ...
3522

cdbaccca7   Marcel Holtmann   Bluetooth: Add ma...
3523
  	hci_dev_lock(hdev);
c72d4b8af   Szymon Janc   Bluetooth: mgmt: ...
3524
  	hdev->devid_source = source;
cdbaccca7   Marcel Holtmann   Bluetooth: Add ma...
3525
3526
3527
  	hdev->devid_vendor = __le16_to_cpu(cp->vendor);
  	hdev->devid_product = __le16_to_cpu(cp->product);
  	hdev->devid_version = __le16_to_cpu(cp->version);
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3528
3529
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
  				NULL, 0);
cdbaccca7   Marcel Holtmann   Bluetooth: Add ma...
3530

890ea8988   Johan Hedberg   Bluetooth: Update...
3531
  	hci_req_init(&req, hdev);
b1a8917c9   Johan Hedberg   Bluetooth: Move E...
3532
  	__hci_req_update_eir(&req);
890ea8988   Johan Hedberg   Bluetooth: Update...
3533
  	hci_req_run(&req, NULL);
cdbaccca7   Marcel Holtmann   Bluetooth: Add ma...
3534
3535
3536
3537
3538
  
  	hci_dev_unlock(hdev);
  
  	return err;
  }
24b4f38fc   Arman Uguray   Bluetooth: Implem...
3539
3540
3541
3542
3543
  static void enable_advertising_instance(struct hci_dev *hdev, u8 status,
  					u16 opcode)
  {
  	BT_DBG("status %d", status);
  }
1904a853f   Marcel Holtmann   Bluetooth: Add op...
3544
3545
  static void set_advertising_complete(struct hci_dev *hdev, u8 status,
  				     u16 opcode)
4375f1037   Johan Hedberg   Bluetooth: Add ne...
3546
3547
  {
  	struct cmd_lookup match = { NULL, hdev };
24b4f38fc   Arman Uguray   Bluetooth: Implem...
3548
  	struct hci_request req;
7816b8203   Florian Grandel   Bluetooth: mgmt: ...
3549
3550
3551
  	u8 instance;
  	struct adv_info *adv_instance;
  	int err;
4375f1037   Johan Hedberg   Bluetooth: Add ne...
3552

3ad675827   Jaganath Kanakkassery   Bluetooth: Fix mi...
3553
  	hci_dev_lock(hdev);
4375f1037   Johan Hedberg   Bluetooth: Add ne...
3554
3555
3556
3557
3558
  	if (status) {
  		u8 mgmt_err = mgmt_status(status);
  
  		mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
  				     cmd_status_rsp, &mgmt_err);
3ad675827   Jaganath Kanakkassery   Bluetooth: Fix mi...
3559
  		goto unlock;
4375f1037   Johan Hedberg   Bluetooth: Add ne...
3560
  	}
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
3561
  	if (hci_dev_test_flag(hdev, HCI_LE_ADV))
a1536da25   Marcel Holtmann   Bluetooth: Introd...
3562
  		hci_dev_set_flag(hdev, HCI_ADVERTISING);
c93bd1503   Johan Hedberg   Bluetooth: Remove...
3563
  	else
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
3564
  		hci_dev_clear_flag(hdev, HCI_ADVERTISING);
c93bd1503   Johan Hedberg   Bluetooth: Remove...
3565

4375f1037   Johan Hedberg   Bluetooth: Add ne...
3566
3567
3568
3569
3570
3571
3572
  	mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
  			     &match);
  
  	new_settings(hdev, match.sk);
  
  	if (match.sk)
  		sock_put(match.sk);
3ad675827   Jaganath Kanakkassery   Bluetooth: Fix mi...
3573

24b4f38fc   Arman Uguray   Bluetooth: Implem...
3574
  	/* If "Set Advertising" was just disabled and instance advertising was
7816b8203   Florian Grandel   Bluetooth: mgmt: ...
3575
  	 * set up earlier, then re-enable multi-instance advertising.
24b4f38fc   Arman Uguray   Bluetooth: Implem...
3576
3577
  	 */
  	if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
7816b8203   Florian Grandel   Bluetooth: mgmt: ...
3578
  	    list_empty(&hdev->adv_instances))
24b4f38fc   Arman Uguray   Bluetooth: Implem...
3579
  		goto unlock;
7816b8203   Florian Grandel   Bluetooth: mgmt: ...
3580
3581
3582
3583
3584
3585
3586
3587
3588
  	instance = hdev->cur_adv_instance;
  	if (!instance) {
  		adv_instance = list_first_entry_or_null(&hdev->adv_instances,
  							struct adv_info, list);
  		if (!adv_instance)
  			goto unlock;
  
  		instance = adv_instance->instance;
  	}
24b4f38fc   Arman Uguray   Bluetooth: Implem...
3589
  	hci_req_init(&req, hdev);
f22525700   Johan Hedberg   Bluetooth: Move a...
3590
  	err = __hci_req_schedule_adv_instance(&req, instance, true);
7816b8203   Florian Grandel   Bluetooth: mgmt: ...
3591
3592
3593
  
  	if (!err)
  		err = hci_req_run(&req, enable_advertising_instance);
24b4f38fc   Arman Uguray   Bluetooth: Implem...
3594

7816b8203   Florian Grandel   Bluetooth: mgmt: ...
3595
  	if (err)
24b4f38fc   Arman Uguray   Bluetooth: Implem...
3596
  		BT_ERR("Failed to re-configure advertising");
3ad675827   Jaganath Kanakkassery   Bluetooth: Fix mi...
3597
3598
  unlock:
  	hci_dev_unlock(hdev);
4375f1037   Johan Hedberg   Bluetooth: Add ne...
3599
  }
21b5187f2   Marcel Holtmann   Bluetooth: Fix to...
3600
3601
  static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
  			   u16 len)
4375f1037   Johan Hedberg   Bluetooth: Add ne...
3602
3603
  {
  	struct mgmt_mode *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
3604
  	struct mgmt_pending_cmd *cmd;
4375f1037   Johan Hedberg   Bluetooth: Add ne...
3605
  	struct hci_request req;
cc91cb042   Marcel Holtmann   Bluetooth: Add su...
3606
  	u8 val, status;
4375f1037   Johan Hedberg   Bluetooth: Add ne...
3607
3608
3609
  	int err;
  
  	BT_DBG("request for %s", hdev->name);
e6fe79865   Johan Hedberg   Bluetooth: Fix RE...
3610
3611
  	status = mgmt_le_support(hdev);
  	if (status)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3612
3613
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
  				       status);
4375f1037   Johan Hedberg   Bluetooth: Add ne...
3614

cc91cb042   Marcel Holtmann   Bluetooth: Add su...
3615
  	if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3616
3617
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
  				       MGMT_STATUS_INVALID_PARAMS);
4375f1037   Johan Hedberg   Bluetooth: Add ne...
3618
3619
3620
3621
  
  	hci_dev_lock(hdev);
  
  	val = !!cp->val;
4375f1037   Johan Hedberg   Bluetooth: Add ne...
3622

f74ca9b80   Johan Hedberg   Bluetooth: Fix ch...
3623
3624
3625
3626
3627
  	/* The following conditions are ones which mean that we should
  	 * not do any HCI communication but directly send a mgmt
  	 * response to user space (after toggling the flag if
  	 * necessary).
  	 */
cc91cb042   Marcel Holtmann   Bluetooth: Add su...
3628
  	if (!hdev_is_powered(hdev) ||
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
3629
3630
  	    (val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
  	     (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
e8bb6b973   Johan Hedberg   Bluetooth: Fix ad...
3631
  	    hci_conn_num(hdev, LE_LINK) > 0 ||
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
3632
  	    (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
e8bb6b973   Johan Hedberg   Bluetooth: Fix ad...
3633
  	     hdev->le_scan_type == LE_SCAN_ACTIVE)) {
cc91cb042   Marcel Holtmann   Bluetooth: Add su...
3634
  		bool changed;
4375f1037   Johan Hedberg   Bluetooth: Add ne...
3635

cc91cb042   Marcel Holtmann   Bluetooth: Add su...
3636
  		if (cp->val) {
cab054ab4   Johan Hedberg   Bluetooth: Clean ...
3637
  			hdev->cur_adv_instance = 0x00;
238be788f   Marcel Holtmann   Bluetooth: Introd...
3638
  			changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING);
cc91cb042   Marcel Holtmann   Bluetooth: Add su...
3639
  			if (cp->val == 0x02)
a1536da25   Marcel Holtmann   Bluetooth: Introd...
3640
  				hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
cc91cb042   Marcel Holtmann   Bluetooth: Add su...
3641
  			else
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
3642
  				hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
cc91cb042   Marcel Holtmann   Bluetooth: Add su...
3643
  		} else {
a69d89272   Marcel Holtmann   Bluetooth: Introd...
3644
  			changed = hci_dev_test_and_clear_flag(hdev, HCI_ADVERTISING);
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
3645
  			hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
4375f1037   Johan Hedberg   Bluetooth: Add ne...
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
  		}
  
  		err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
  		if (err < 0)
  			goto unlock;
  
  		if (changed)
  			err = new_settings(hdev, sk);
  
  		goto unlock;
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
3657
3658
  	if (pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
  	    pending_find(MGMT_OP_SET_LE, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3659
3660
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
  				      MGMT_STATUS_BUSY);
4375f1037   Johan Hedberg   Bluetooth: Add ne...
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
  		goto unlock;
  	}
  
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
  	if (!cmd) {
  		err = -ENOMEM;
  		goto unlock;
  	}
  
  	hci_req_init(&req, hdev);
cc91cb042   Marcel Holtmann   Bluetooth: Add su...
3671
  	if (cp->val == 0x02)
a1536da25   Marcel Holtmann   Bluetooth: Introd...
3672
  		hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
cc91cb042   Marcel Holtmann   Bluetooth: Add su...
3673
  	else
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
3674
  		hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
cc91cb042   Marcel Holtmann   Bluetooth: Add su...
3675

7816b8203   Florian Grandel   Bluetooth: mgmt: ...
3676
  	cancel_adv_timeout(hdev);
24b4f38fc   Arman Uguray   Bluetooth: Implem...
3677
  	if (val) {
7816b8203   Florian Grandel   Bluetooth: mgmt: ...
3678
3679
3680
3681
  		/* Switch to instance "0" for the Set Advertising setting.
  		 * We cannot use update_[adv|scan_rsp]_data() here as the
  		 * HCI_ADVERTISING flag is not yet set.
  		 */
cab054ab4   Johan Hedberg   Bluetooth: Clean ...
3682
  		hdev->cur_adv_instance = 0x00;
f22525700   Johan Hedberg   Bluetooth: Move a...
3683
3684
3685
  		__hci_req_update_adv_data(&req, 0x00);
  		__hci_req_update_scan_rsp_data(&req, 0x00);
  		__hci_req_enable_advertising(&req);
24b4f38fc   Arman Uguray   Bluetooth: Implem...
3686
  	} else {
f22525700   Johan Hedberg   Bluetooth: Move a...
3687
  		__hci_req_disable_advertising(&req);
24b4f38fc   Arman Uguray   Bluetooth: Implem...
3688
  	}
4375f1037   Johan Hedberg   Bluetooth: Add ne...
3689
3690
3691
3692
3693
3694
3695
3696
3697
  
  	err = hci_req_run(&req, set_advertising_complete);
  	if (err < 0)
  		mgmt_pending_remove(cmd);
  
  unlock:
  	hci_dev_unlock(hdev);
  	return err;
  }
d13eafce2   Marcel Holtmann   Bluetooth: Add ma...
3698
3699
3700
3701
3702
3703
3704
  static int set_static_address(struct sock *sk, struct hci_dev *hdev,
  			      void *data, u16 len)
  {
  	struct mgmt_cp_set_static_address *cp = data;
  	int err;
  
  	BT_DBG("%s", hdev->name);
62af44431   Marcel Holtmann   Bluetooth: Allow ...
3705
  	if (!lmp_le_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3706
3707
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
  				       MGMT_STATUS_NOT_SUPPORTED);
d13eafce2   Marcel Holtmann   Bluetooth: Add ma...
3708
3709
  
  	if (hdev_is_powered(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3710
3711
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
  				       MGMT_STATUS_REJECTED);
d13eafce2   Marcel Holtmann   Bluetooth: Add ma...
3712
3713
3714
  
  	if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
  		if (!bacmp(&cp->bdaddr, BDADDR_NONE))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3715
3716
3717
  			return mgmt_cmd_status(sk, hdev->id,
  					       MGMT_OP_SET_STATIC_ADDRESS,
  					       MGMT_STATUS_INVALID_PARAMS);
d13eafce2   Marcel Holtmann   Bluetooth: Add ma...
3718
3719
3720
  
  		/* Two most significant bits shall be set */
  		if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3721
3722
3723
  			return mgmt_cmd_status(sk, hdev->id,
  					       MGMT_OP_SET_STATIC_ADDRESS,
  					       MGMT_STATUS_INVALID_PARAMS);
d13eafce2   Marcel Holtmann   Bluetooth: Add ma...
3724
3725
3726
3727
3728
  	}
  
  	hci_dev_lock(hdev);
  
  	bacpy(&hdev->static_addr, &cp->bdaddr);
93690c227   Marcel Holtmann   Bluetooth: Introd...
3729
3730
3731
3732
3733
  	err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
  	if (err < 0)
  		goto unlock;
  
  	err = new_settings(hdev, sk);
d13eafce2   Marcel Holtmann   Bluetooth: Add ma...
3734

93690c227   Marcel Holtmann   Bluetooth: Introd...
3735
  unlock:
d13eafce2   Marcel Holtmann   Bluetooth: Add ma...
3736
  	hci_dev_unlock(hdev);
d13eafce2   Marcel Holtmann   Bluetooth: Add ma...
3737
3738
  	return err;
  }
14b49b9a4   Marcel Holtmann   Bluetooth: Add ma...
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
  static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
  			   void *data, u16 len)
  {
  	struct mgmt_cp_set_scan_params *cp = data;
  	__u16 interval, window;
  	int err;
  
  	BT_DBG("%s", hdev->name);
  
  	if (!lmp_le_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3749
3750
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
  				       MGMT_STATUS_NOT_SUPPORTED);
14b49b9a4   Marcel Holtmann   Bluetooth: Add ma...
3751
3752
3753
3754
  
  	interval = __le16_to_cpu(cp->interval);
  
  	if (interval < 0x0004 || interval > 0x4000)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3755
3756
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
  				       MGMT_STATUS_INVALID_PARAMS);
14b49b9a4   Marcel Holtmann   Bluetooth: Add ma...
3757
3758
3759
3760
  
  	window = __le16_to_cpu(cp->window);
  
  	if (window < 0x0004 || window > 0x4000)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3761
3762
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
  				       MGMT_STATUS_INVALID_PARAMS);
14b49b9a4   Marcel Holtmann   Bluetooth: Add ma...
3763

899e10757   Marcel Holtmann   Bluetooth: Check ...
3764
  	if (window > interval)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3765
3766
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
  				       MGMT_STATUS_INVALID_PARAMS);
899e10757   Marcel Holtmann   Bluetooth: Check ...
3767

14b49b9a4   Marcel Holtmann   Bluetooth: Add ma...
3768
3769
3770
3771
  	hci_dev_lock(hdev);
  
  	hdev->le_scan_interval = interval;
  	hdev->le_scan_window = window;
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3772
3773
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
  				NULL, 0);
14b49b9a4   Marcel Holtmann   Bluetooth: Add ma...
3774

dd2ef8e27   Andre Guedes   Bluetooth: Update...
3775
3776
3777
  	/* If background scan is running, restart it so new parameters are
  	 * loaded.
  	 */
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
3778
  	if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
dd2ef8e27   Andre Guedes   Bluetooth: Update...
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
  	    hdev->discovery.state == DISCOVERY_STOPPED) {
  		struct hci_request req;
  
  		hci_req_init(&req, hdev);
  
  		hci_req_add_le_scan_disable(&req);
  		hci_req_add_le_passive_scan(&req);
  
  		hci_req_run(&req, NULL);
  	}
14b49b9a4   Marcel Holtmann   Bluetooth: Add ma...
3789
3790
3791
3792
  	hci_dev_unlock(hdev);
  
  	return err;
  }
1904a853f   Marcel Holtmann   Bluetooth: Add op...
3793
3794
  static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
  				      u16 opcode)
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
3795
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
3796
  	struct mgmt_pending_cmd *cmd;
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
3797
3798
3799
3800
  
  	BT_DBG("status 0x%02x", status);
  
  	hci_dev_lock(hdev);
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
3801
  	cmd = pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
3802
3803
3804
3805
  	if (!cmd)
  		goto unlock;
  
  	if (status) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3806
3807
  		mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
  			        mgmt_status(status));
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
3808
  	} else {
1a4d3c4b3   Johan Hedberg   Bluetooth: Add pr...
3809
3810
3811
  		struct mgmt_mode *cp = cmd->param;
  
  		if (cp->val)
a1536da25   Marcel Holtmann   Bluetooth: Introd...
3812
  			hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
1a4d3c4b3   Johan Hedberg   Bluetooth: Add pr...
3813
  		else
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
3814
  			hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
1a4d3c4b3   Johan Hedberg   Bluetooth: Add pr...
3815

33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
3816
3817
3818
3819
3820
3821
3822
3823
3824
  		send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
  		new_settings(hdev, cmd->sk);
  	}
  
  	mgmt_pending_remove(cmd);
  
  unlock:
  	hci_dev_unlock(hdev);
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
3825
  static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
3826
  				void *data, u16 len)
f6422ec62   Antti Julku   Bluetooth: Add mg...
3827
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
3828
  	struct mgmt_mode *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
3829
  	struct mgmt_pending_cmd *cmd;
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
3830
  	struct hci_request req;
f6422ec62   Antti Julku   Bluetooth: Add mg...
3831
  	int err;
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
3832
  	BT_DBG("%s", hdev->name);
f6422ec62   Antti Julku   Bluetooth: Add mg...
3833

d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
3834
  	if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
56f879010   Johan Hedberg   Bluetooth: Introd...
3835
  	    hdev->hci_ver < BLUETOOTH_VER_1_2)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3836
3837
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
  				       MGMT_STATUS_NOT_SUPPORTED);
33c525c0a   Johan Hedberg   Bluetooth: mgmt: ...
3838

a7e80f25a   Johan Hedberg   Bluetooth: Fix ch...
3839
  	if (cp->val != 0x00 && cp->val != 0x01)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3840
3841
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
  				       MGMT_STATUS_INVALID_PARAMS);
a7e80f25a   Johan Hedberg   Bluetooth: Fix ch...
3842

f6422ec62   Antti Julku   Bluetooth: Add mg...
3843
  	hci_dev_lock(hdev);
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
3844
  	if (pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3845
3846
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
  				      MGMT_STATUS_BUSY);
05cbf29f8   Johan Hedberg   Bluetooth: Fix er...
3847
3848
  		goto unlock;
  	}
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
3849
  	if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
1a4d3c4b3   Johan Hedberg   Bluetooth: Add pr...
3850
3851
3852
3853
  		err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
  					hdev);
  		goto unlock;
  	}
406ef2a67   Johan Hedberg   Bluetooth: Make F...
3854
  	if (!hdev_is_powered(hdev)) {
ce05d603a   Marcel Holtmann   Bluetooth: Introd...
3855
  		hci_dev_change_flag(hdev, HCI_FAST_CONNECTABLE);
406ef2a67   Johan Hedberg   Bluetooth: Make F...
3856
3857
3858
3859
3860
  		err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
  					hdev);
  		new_settings(hdev, sk);
  		goto unlock;
  	}
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
3861
3862
3863
3864
3865
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
  			       data, len);
  	if (!cmd) {
  		err = -ENOMEM;
  		goto unlock;
f6422ec62   Antti Julku   Bluetooth: Add mg...
3866
  	}
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
3867
  	hci_req_init(&req, hdev);
bf943cbf7   Johan Hedberg   Bluetooth: Move f...
3868
  	__hci_req_write_fast_connectable(&req, cp->val);
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
3869
3870
  
  	err = hci_req_run(&req, fast_connectable_complete);
f6422ec62   Antti Julku   Bluetooth: Add mg...
3871
  	if (err < 0) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3872
3873
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
  				      MGMT_STATUS_FAILED);
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
3874
  		mgmt_pending_remove(cmd);
f6422ec62   Antti Julku   Bluetooth: Add mg...
3875
  	}
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
3876
  unlock:
f6422ec62   Antti Julku   Bluetooth: Add mg...
3877
  	hci_dev_unlock(hdev);
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
3878

f6422ec62   Antti Julku   Bluetooth: Add mg...
3879
3880
  	return err;
  }
1904a853f   Marcel Holtmann   Bluetooth: Add op...
3881
  static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
3882
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
3883
  	struct mgmt_pending_cmd *cmd;
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
3884
3885
3886
3887
  
  	BT_DBG("status 0x%02x", status);
  
  	hci_dev_lock(hdev);
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
3888
  	cmd = pending_find(MGMT_OP_SET_BREDR, hdev);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
3889
3890
3891
3892
3893
3894
3895
3896
3897
  	if (!cmd)
  		goto unlock;
  
  	if (status) {
  		u8 mgmt_err = mgmt_status(status);
  
  		/* We need to restore the flag if related HCI commands
  		 * failed.
  		 */
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
3898
  		hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
3899

a69e8375a   Johan Hedberg   Bluetooth: Rename...
3900
  		mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
  	} else {
  		send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
  		new_settings(hdev, cmd->sk);
  	}
  
  	mgmt_pending_remove(cmd);
  
  unlock:
  	hci_dev_unlock(hdev);
  }
  
  static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
  {
  	struct mgmt_mode *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
3915
  	struct mgmt_pending_cmd *cmd;
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
3916
3917
3918
3919
3920
3921
  	struct hci_request req;
  	int err;
  
  	BT_DBG("request for %s", hdev->name);
  
  	if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3922
3923
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
  				       MGMT_STATUS_NOT_SUPPORTED);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
3924

d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
3925
  	if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3926
3927
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
  				       MGMT_STATUS_REJECTED);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
3928
3929
  
  	if (cp->val != 0x00 && cp->val != 0x01)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3930
3931
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
  				       MGMT_STATUS_INVALID_PARAMS);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
3932
3933
  
  	hci_dev_lock(hdev);
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
3934
  	if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
3935
3936
3937
3938
3939
3940
  		err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
  		goto unlock;
  	}
  
  	if (!hdev_is_powered(hdev)) {
  		if (!cp->val) {
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
3941
3942
3943
3944
3945
  			hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
  			hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
  			hci_dev_clear_flag(hdev, HCI_LINK_SECURITY);
  			hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
  			hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
3946
  		}
ce05d603a   Marcel Holtmann   Bluetooth: Introd...
3947
  		hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
  
  		err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
  		if (err < 0)
  			goto unlock;
  
  		err = new_settings(hdev, sk);
  		goto unlock;
  	}
  
  	/* Reject disabling when powered on */
  	if (!cp->val) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3959
3960
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
  				      MGMT_STATUS_REJECTED);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
3961
  		goto unlock;
111e4bccd   Marcel Holtmann   Bluetooth: Fix is...
3962
3963
3964
3965
3966
3967
3968
3969
  	} else {
  		/* When configuring a dual-mode controller to operate
  		 * with LE only and using a static address, then switching
  		 * BR/EDR back on is not allowed.
  		 *
  		 * Dual-mode controllers shall operate with the public
  		 * address as its identity address for BR/EDR and LE. So
  		 * reject the attempt to create an invalid configuration.
3a5486e1f   Marcel Holtmann   Bluetooth: Limit ...
3970
3971
3972
3973
3974
3975
  		 *
  		 * The same restrictions applies when secure connections
  		 * has been enabled. For BR/EDR this is a controller feature
  		 * while for LE it is a host stack feature. This means that
  		 * switching BR/EDR back on when secure connections has been
  		 * enabled is not a supported transaction.
111e4bccd   Marcel Holtmann   Bluetooth: Fix is...
3976
  		 */
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
3977
  		if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
3a5486e1f   Marcel Holtmann   Bluetooth: Limit ...
3978
  		    (bacmp(&hdev->static_addr, BDADDR_ANY) ||
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
3979
  		     hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3980
3981
  			err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
  					      MGMT_STATUS_REJECTED);
111e4bccd   Marcel Holtmann   Bluetooth: Fix is...
3982
3983
  			goto unlock;
  		}
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
3984
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
3985
  	if (pending_find(MGMT_OP_SET_BREDR, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
3986
3987
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
  				      MGMT_STATUS_BUSY);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
3988
3989
3990
3991
3992
3993
3994
3995
  		goto unlock;
  	}
  
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
  	if (!cmd) {
  		err = -ENOMEM;
  		goto unlock;
  	}
f22525700   Johan Hedberg   Bluetooth: Move a...
3996
3997
  	/* We need to flip the bit already here so that
  	 * hci_req_update_adv_data generates the correct flags.
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
3998
  	 */
a1536da25   Marcel Holtmann   Bluetooth: Introd...
3999
  	hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
4000
4001
  
  	hci_req_init(&req, hdev);
aa8af46e9   Johan Hedberg   Bluetooth: Fix up...
4002

bf943cbf7   Johan Hedberg   Bluetooth: Move f...
4003
  	__hci_req_write_fast_connectable(&req, false);
01b1cb87d   Johan Hedberg   Bluetooth: Run pa...
4004
  	__hci_req_update_scan(&req);
aa8af46e9   Johan Hedberg   Bluetooth: Fix up...
4005

f14d8f643   Marcel Holtmann   Bluetooth: Set th...
4006
4007
4008
  	/* Since only the advertising data flags will change, there
  	 * is no need to update the scan response data.
  	 */
cab054ab4   Johan Hedberg   Bluetooth: Clean ...
4009
  	__hci_req_update_adv_data(&req, hdev->cur_adv_instance);
aa8af46e9   Johan Hedberg   Bluetooth: Fix up...
4010

0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
4011
4012
4013
4014
4015
4016
4017
4018
  	err = hci_req_run(&req, set_bredr_complete);
  	if (err < 0)
  		mgmt_pending_remove(cmd);
  
  unlock:
  	hci_dev_unlock(hdev);
  	return err;
  }
a1443f5a2   Johan Hedberg   Bluetooth: Conver...
4019
4020
  static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
4021
  	struct mgmt_pending_cmd *cmd;
a1443f5a2   Johan Hedberg   Bluetooth: Conver...
4022
4023
4024
4025
4026
  	struct mgmt_mode *cp;
  
  	BT_DBG("%s status %u", hdev->name, status);
  
  	hci_dev_lock(hdev);
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
4027
  	cmd = pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
a1443f5a2   Johan Hedberg   Bluetooth: Conver...
4028
4029
4030
4031
  	if (!cmd)
  		goto unlock;
  
  	if (status) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4032
4033
  		mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
  			        mgmt_status(status));
a1443f5a2   Johan Hedberg   Bluetooth: Conver...
4034
4035
4036
4037
4038
4039
4040
  		goto remove;
  	}
  
  	cp = cmd->param;
  
  	switch (cp->val) {
  	case 0x00:
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
4041
4042
  		hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
  		hci_dev_clear_flag(hdev, HCI_SC_ONLY);
a1443f5a2   Johan Hedberg   Bluetooth: Conver...
4043
4044
  		break;
  	case 0x01:
a1536da25   Marcel Holtmann   Bluetooth: Introd...
4045
  		hci_dev_set_flag(hdev, HCI_SC_ENABLED);
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
4046
  		hci_dev_clear_flag(hdev, HCI_SC_ONLY);
a1443f5a2   Johan Hedberg   Bluetooth: Conver...
4047
4048
  		break;
  	case 0x02:
a1536da25   Marcel Holtmann   Bluetooth: Introd...
4049
4050
  		hci_dev_set_flag(hdev, HCI_SC_ENABLED);
  		hci_dev_set_flag(hdev, HCI_SC_ONLY);
a1443f5a2   Johan Hedberg   Bluetooth: Conver...
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
  		break;
  	}
  
  	send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
  	new_settings(hdev, cmd->sk);
  
  remove:
  	mgmt_pending_remove(cmd);
  unlock:
  	hci_dev_unlock(hdev);
  }
eac83dc63   Marcel Holtmann   Bluetooth: Add ma...
4062
4063
4064
4065
  static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
  			   void *data, u16 len)
  {
  	struct mgmt_mode *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
4066
  	struct mgmt_pending_cmd *cmd;
a1443f5a2   Johan Hedberg   Bluetooth: Conver...
4067
  	struct hci_request req;
a3209694f   Johan Hedberg   Bluetooth: Add mg...
4068
  	u8 val;
eac83dc63   Marcel Holtmann   Bluetooth: Add ma...
4069
4070
4071
  	int err;
  
  	BT_DBG("request for %s", hdev->name);
05b3c3e79   Marcel Holtmann   Bluetooth: Remove...
4072
  	if (!lmp_sc_capable(hdev) &&
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
4073
  	    !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4074
4075
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
  				       MGMT_STATUS_NOT_SUPPORTED);
eac83dc63   Marcel Holtmann   Bluetooth: Add ma...
4076

d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
4077
  	if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
592002863   Johan Hedberg   Bluetooth: Fix ch...
4078
  	    lmp_sc_capable(hdev) &&
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
4079
  	    !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4080
4081
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
  				       MGMT_STATUS_REJECTED);
ed93ec69c   Marcel Holtmann   Bluetooth: Requir...
4082

0ab04a9c0   Marcel Holtmann   Bluetooth: Add ma...
4083
  	if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4084
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
eac83dc63   Marcel Holtmann   Bluetooth: Add ma...
4085
4086
4087
  				  MGMT_STATUS_INVALID_PARAMS);
  
  	hci_dev_lock(hdev);
05b3c3e79   Marcel Holtmann   Bluetooth: Remove...
4088
  	if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
4089
  	    !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
eac83dc63   Marcel Holtmann   Bluetooth: Add ma...
4090
  		bool changed;
0ab04a9c0   Marcel Holtmann   Bluetooth: Add ma...
4091
  		if (cp->val) {
238be788f   Marcel Holtmann   Bluetooth: Introd...
4092
4093
  			changed = !hci_dev_test_and_set_flag(hdev,
  							     HCI_SC_ENABLED);
0ab04a9c0   Marcel Holtmann   Bluetooth: Add ma...
4094
  			if (cp->val == 0x02)
a1536da25   Marcel Holtmann   Bluetooth: Introd...
4095
  				hci_dev_set_flag(hdev, HCI_SC_ONLY);
0ab04a9c0   Marcel Holtmann   Bluetooth: Add ma...
4096
  			else
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
4097
  				hci_dev_clear_flag(hdev, HCI_SC_ONLY);
0ab04a9c0   Marcel Holtmann   Bluetooth: Add ma...
4098
  		} else {
a69d89272   Marcel Holtmann   Bluetooth: Introd...
4099
4100
  			changed = hci_dev_test_and_clear_flag(hdev,
  							      HCI_SC_ENABLED);
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
4101
  			hci_dev_clear_flag(hdev, HCI_SC_ONLY);
0ab04a9c0   Marcel Holtmann   Bluetooth: Add ma...
4102
  		}
eac83dc63   Marcel Holtmann   Bluetooth: Add ma...
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
  
  		err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
  		if (err < 0)
  			goto failed;
  
  		if (changed)
  			err = new_settings(hdev, sk);
  
  		goto failed;
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
4113
  	if (pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4114
4115
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
  				      MGMT_STATUS_BUSY);
eac83dc63   Marcel Holtmann   Bluetooth: Add ma...
4116
4117
  		goto failed;
  	}
0ab04a9c0   Marcel Holtmann   Bluetooth: Add ma...
4118
  	val = !!cp->val;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
4119
4120
  	if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
  	    (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
eac83dc63   Marcel Holtmann   Bluetooth: Add ma...
4121
4122
4123
4124
4125
4126
4127
4128
4129
  		err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
  		goto failed;
  	}
  
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
  	if (!cmd) {
  		err = -ENOMEM;
  		goto failed;
  	}
a1443f5a2   Johan Hedberg   Bluetooth: Conver...
4130
4131
4132
  	hci_req_init(&req, hdev);
  	hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
  	err = hci_req_run(&req, sc_enable_complete);
eac83dc63   Marcel Holtmann   Bluetooth: Add ma...
4133
4134
4135
4136
4137
4138
4139
4140
4141
  	if (err < 0) {
  		mgmt_pending_remove(cmd);
  		goto failed;
  	}
  
  failed:
  	hci_dev_unlock(hdev);
  	return err;
  }
4e39ac813   Marcel Holtmann   Bluetooth: Add ma...
4142
4143
4144
4145
  static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
  			  void *data, u16 len)
  {
  	struct mgmt_mode *cp = data;
b97109790   Johan Hedberg   Bluetooth: Add su...
4146
  	bool changed, use_changed;
4e39ac813   Marcel Holtmann   Bluetooth: Add ma...
4147
4148
4149
  	int err;
  
  	BT_DBG("request for %s", hdev->name);
b97109790   Johan Hedberg   Bluetooth: Add su...
4150
  	if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4151
4152
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
  				       MGMT_STATUS_INVALID_PARAMS);
4e39ac813   Marcel Holtmann   Bluetooth: Add ma...
4153
4154
4155
4156
  
  	hci_dev_lock(hdev);
  
  	if (cp->val)
238be788f   Marcel Holtmann   Bluetooth: Introd...
4157
  		changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
4e39ac813   Marcel Holtmann   Bluetooth: Add ma...
4158
  	else
a69d89272   Marcel Holtmann   Bluetooth: Introd...
4159
4160
  		changed = hci_dev_test_and_clear_flag(hdev,
  						      HCI_KEEP_DEBUG_KEYS);
4e39ac813   Marcel Holtmann   Bluetooth: Add ma...
4161

b97109790   Johan Hedberg   Bluetooth: Add su...
4162
  	if (cp->val == 0x02)
238be788f   Marcel Holtmann   Bluetooth: Introd...
4163
4164
  		use_changed = !hci_dev_test_and_set_flag(hdev,
  							 HCI_USE_DEBUG_KEYS);
b97109790   Johan Hedberg   Bluetooth: Add su...
4165
  	else
a69d89272   Marcel Holtmann   Bluetooth: Introd...
4166
4167
  		use_changed = hci_dev_test_and_clear_flag(hdev,
  							  HCI_USE_DEBUG_KEYS);
b97109790   Johan Hedberg   Bluetooth: Add su...
4168
4169
  
  	if (hdev_is_powered(hdev) && use_changed &&
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
4170
  	    hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
b97109790   Johan Hedberg   Bluetooth: Add su...
4171
4172
4173
4174
  		u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
  		hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
  			     sizeof(mode), &mode);
  	}
4e39ac813   Marcel Holtmann   Bluetooth: Add ma...
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
  	err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
  	if (err < 0)
  		goto unlock;
  
  	if (changed)
  		err = new_settings(hdev, sk);
  
  unlock:
  	hci_dev_unlock(hdev);
  	return err;
  }
62b04cd12   Johan Hedberg   Bluetooth: Add su...
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
  static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
  		       u16 len)
  {
  	struct mgmt_cp_set_privacy *cp = cp_data;
  	bool changed;
  	int err;
  
  	BT_DBG("request for %s", hdev->name);
  
  	if (!lmp_le_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4196
4197
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
  				       MGMT_STATUS_NOT_SUPPORTED);
62b04cd12   Johan Hedberg   Bluetooth: Add su...
4198

82a37adee   Johan Hedberg   Bluetooth: Add su...
4199
  	if (cp->privacy != 0x00 && cp->privacy != 0x01 && cp->privacy != 0x02)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4200
4201
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
  				       MGMT_STATUS_INVALID_PARAMS);
62b04cd12   Johan Hedberg   Bluetooth: Add su...
4202
4203
  
  	if (hdev_is_powered(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4204
4205
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
  				       MGMT_STATUS_REJECTED);
62b04cd12   Johan Hedberg   Bluetooth: Add su...
4206
4207
  
  	hci_dev_lock(hdev);
c21c0ea07   Johan Hedberg   Bluetooth: Enable...
4208
4209
4210
  	/* If user space supports this command it is also expected to
  	 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
  	 */
a1536da25   Marcel Holtmann   Bluetooth: Introd...
4211
  	hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
c21c0ea07   Johan Hedberg   Bluetooth: Enable...
4212

62b04cd12   Johan Hedberg   Bluetooth: Add su...
4213
  	if (cp->privacy) {
238be788f   Marcel Holtmann   Bluetooth: Introd...
4214
  		changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY);
62b04cd12   Johan Hedberg   Bluetooth: Add su...
4215
  		memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
a1536da25   Marcel Holtmann   Bluetooth: Introd...
4216
  		hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
82a37adee   Johan Hedberg   Bluetooth: Add su...
4217
4218
4219
4220
  		if (cp->privacy == 0x02)
  			hci_dev_set_flag(hdev, HCI_LIMITED_PRIVACY);
  		else
  			hci_dev_clear_flag(hdev, HCI_LIMITED_PRIVACY);
62b04cd12   Johan Hedberg   Bluetooth: Add su...
4221
  	} else {
a69d89272   Marcel Holtmann   Bluetooth: Introd...
4222
  		changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
62b04cd12   Johan Hedberg   Bluetooth: Add su...
4223
  		memset(hdev->irk, 0, sizeof(hdev->irk));
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
4224
  		hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
82a37adee   Johan Hedberg   Bluetooth: Add su...
4225
  		hci_dev_clear_flag(hdev, HCI_LIMITED_PRIVACY);
62b04cd12   Johan Hedberg   Bluetooth: Add su...
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
  	}
  
  	err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
  	if (err < 0)
  		goto unlock;
  
  	if (changed)
  		err = new_settings(hdev, sk);
  
  unlock:
  	hci_dev_unlock(hdev);
  	return err;
  }
41edf1601   Johan Hedberg   Bluetooth: Implem...
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
  static bool irk_is_valid(struct mgmt_irk_info *irk)
  {
  	switch (irk->addr.type) {
  	case BDADDR_LE_PUBLIC:
  		return true;
  
  	case BDADDR_LE_RANDOM:
  		/* Two most significant bits shall be set */
  		if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
  			return false;
  		return true;
  	}
  
  	return false;
  }
  
  static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
  		     u16 len)
  {
  	struct mgmt_cp_load_irks *cp = cp_data;
ba1d6936f   Johan Hedberg   Bluetooth: Fix bu...
4259
4260
  	const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
  				   sizeof(struct mgmt_irk_info));
41edf1601   Johan Hedberg   Bluetooth: Implem...
4261
4262
4263
4264
4265
4266
  	u16 irk_count, expected_len;
  	int i, err;
  
  	BT_DBG("request for %s", hdev->name);
  
  	if (!lmp_le_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4267
4268
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
  				       MGMT_STATUS_NOT_SUPPORTED);
41edf1601   Johan Hedberg   Bluetooth: Implem...
4269
4270
  
  	irk_count = __le16_to_cpu(cp->irk_count);
ba1d6936f   Johan Hedberg   Bluetooth: Fix bu...
4271
4272
  	if (irk_count > max_irk_count) {
  		BT_ERR("load_irks: too big irk_count value %u", irk_count);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4273
4274
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
  				       MGMT_STATUS_INVALID_PARAMS);
ba1d6936f   Johan Hedberg   Bluetooth: Fix bu...
4275
  	}
41edf1601   Johan Hedberg   Bluetooth: Implem...
4276
4277
4278
4279
  
  	expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
  	if (expected_len != len) {
  		BT_ERR("load_irks: expected %u bytes, got %u bytes",
2606ecbc4   Johan Hedberg   Bluetooth: Fix ex...
4280
  		       expected_len, len);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4281
4282
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
  				       MGMT_STATUS_INVALID_PARAMS);
41edf1601   Johan Hedberg   Bluetooth: Implem...
4283
4284
4285
4286
4287
4288
4289
4290
  	}
  
  	BT_DBG("%s irk_count %u", hdev->name, irk_count);
  
  	for (i = 0; i < irk_count; i++) {
  		struct mgmt_irk_info *key = &cp->irks[i];
  
  		if (!irk_is_valid(key))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4291
4292
4293
  			return mgmt_cmd_status(sk, hdev->id,
  					       MGMT_OP_LOAD_IRKS,
  					       MGMT_STATUS_INVALID_PARAMS);
41edf1601   Johan Hedberg   Bluetooth: Implem...
4294
4295
4296
4297
4298
4299
4300
4301
  	}
  
  	hci_dev_lock(hdev);
  
  	hci_smp_irks_clear(hdev);
  
  	for (i = 0; i < irk_count; i++) {
  		struct mgmt_irk_info *irk = &cp->irks[i];
41edf1601   Johan Hedberg   Bluetooth: Implem...
4302

85813a7ec   Johan Hedberg   Bluetooth: Add le...
4303
4304
  		hci_add_irk(hdev, &irk->addr.bdaddr,
  			    le_addr_type(irk->addr.type), irk->val,
41edf1601   Johan Hedberg   Bluetooth: Implem...
4305
4306
  			    BDADDR_ANY);
  	}
a1536da25   Marcel Holtmann   Bluetooth: Introd...
4307
  	hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
41edf1601   Johan Hedberg   Bluetooth: Implem...
4308

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4309
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
41edf1601   Johan Hedberg   Bluetooth: Implem...
4310
4311
4312
4313
4314
  
  	hci_dev_unlock(hdev);
  
  	return err;
  }
3f706b720   Johan Hedberg   Bluetooth: Refact...
4315
4316
4317
4318
  static bool ltk_is_valid(struct mgmt_ltk_info *key)
  {
  	if (key->master != 0x00 && key->master != 0x01)
  		return false;
490cb0b31   Marcel Holtmann   Bluetooth: Restri...
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
  
  	switch (key->addr.type) {
  	case BDADDR_LE_PUBLIC:
  		return true;
  
  	case BDADDR_LE_RANDOM:
  		/* Two most significant bits shall be set */
  		if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
  			return false;
  		return true;
  	}
  
  	return false;
3f706b720   Johan Hedberg   Bluetooth: Refact...
4332
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
4333
  static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
4334
  			       void *cp_data, u16 len)
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
4335
  {
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
4336
  	struct mgmt_cp_load_long_term_keys *cp = cp_data;
ba1d6936f   Johan Hedberg   Bluetooth: Fix bu...
4337
4338
  	const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
  				   sizeof(struct mgmt_ltk_info));
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
4339
  	u16 key_count, expected_len;
715a5bf2d   Johan Hedberg   Bluetooth: Fix mi...
4340
  	int i, err;
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
4341

cf99ba135   Marcel Holtmann   Bluetooth: Restri...
4342
4343
4344
  	BT_DBG("request for %s", hdev->name);
  
  	if (!lmp_le_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4345
4346
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
  				       MGMT_STATUS_NOT_SUPPORTED);
cf99ba135   Marcel Holtmann   Bluetooth: Restri...
4347

1f350c872   Marcel Holtmann   Bluetooth: Fix br...
4348
  	key_count = __le16_to_cpu(cp->key_count);
ba1d6936f   Johan Hedberg   Bluetooth: Fix bu...
4349
4350
  	if (key_count > max_key_count) {
  		BT_ERR("load_ltks: too big key_count value %u", key_count);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4351
4352
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
  				       MGMT_STATUS_INVALID_PARAMS);
ba1d6936f   Johan Hedberg   Bluetooth: Fix bu...
4353
  	}
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
4354
4355
4356
4357
4358
  
  	expected_len = sizeof(*cp) + key_count *
  					sizeof(struct mgmt_ltk_info);
  	if (expected_len != len) {
  		BT_ERR("load_keys: expected %u bytes, got %u bytes",
2606ecbc4   Johan Hedberg   Bluetooth: Fix ex...
4359
  		       expected_len, len);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4360
4361
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
  				       MGMT_STATUS_INVALID_PARAMS);
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
4362
  	}
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
4363
  	BT_DBG("%s key_count %u", hdev->name, key_count);
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
4364

54ad6d8a5   Johan Hedberg   Bluetooth: Fix ch...
4365
4366
  	for (i = 0; i < key_count; i++) {
  		struct mgmt_ltk_info *key = &cp->keys[i];
3f706b720   Johan Hedberg   Bluetooth: Refact...
4367
  		if (!ltk_is_valid(key))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4368
4369
4370
  			return mgmt_cmd_status(sk, hdev->id,
  					       MGMT_OP_LOAD_LONG_TERM_KEYS,
  					       MGMT_STATUS_INVALID_PARAMS);
54ad6d8a5   Johan Hedberg   Bluetooth: Fix ch...
4371
  	}
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
4372
4373
4374
4375
4376
4377
  	hci_dev_lock(hdev);
  
  	hci_smp_ltks_clear(hdev);
  
  	for (i = 0; i < key_count; i++) {
  		struct mgmt_ltk_info *key = &cp->keys[i];
85813a7ec   Johan Hedberg   Bluetooth: Add le...
4378
  		u8 type, authenticated;
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
4379

61b433579   Johan Hedberg   Bluetooth: Fix pr...
4380
4381
  		switch (key->type) {
  		case MGMT_LTK_UNAUTHENTICATED:
d7b254502   Johan Hedberg   Bluetooth: Clearl...
4382
  			authenticated = 0x00;
23fb8de37   Johan Hedberg   Bluetooth: Add mg...
4383
  			type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
61b433579   Johan Hedberg   Bluetooth: Fix pr...
4384
4385
  			break;
  		case MGMT_LTK_AUTHENTICATED:
d7b254502   Johan Hedberg   Bluetooth: Clearl...
4386
  			authenticated = 0x01;
23fb8de37   Johan Hedberg   Bluetooth: Add mg...
4387
4388
4389
4390
4391
  			type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
  			break;
  		case MGMT_LTK_P256_UNAUTH:
  			authenticated = 0x00;
  			type = SMP_LTK_P256;
61b433579   Johan Hedberg   Bluetooth: Fix pr...
4392
  			break;
23fb8de37   Johan Hedberg   Bluetooth: Add mg...
4393
4394
4395
  		case MGMT_LTK_P256_AUTH:
  			authenticated = 0x01;
  			type = SMP_LTK_P256;
61b433579   Johan Hedberg   Bluetooth: Fix pr...
4396
  			break;
23fb8de37   Johan Hedberg   Bluetooth: Add mg...
4397
4398
4399
  		case MGMT_LTK_P256_DEBUG:
  			authenticated = 0x00;
  			type = SMP_LTK_P256_DEBUG;
61b433579   Johan Hedberg   Bluetooth: Fix pr...
4400
4401
4402
  		default:
  			continue;
  		}
d7b254502   Johan Hedberg   Bluetooth: Clearl...
4403

85813a7ec   Johan Hedberg   Bluetooth: Add le...
4404
4405
4406
  		hci_add_ltk(hdev, &key->addr.bdaddr,
  			    le_addr_type(key->addr.type), type, authenticated,
  			    key->val, key->enc_size, key->ediv, key->rand);
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
4407
  	}
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4408
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
715a5bf2d   Johan Hedberg   Bluetooth: Fix mi...
4409
  			   NULL, 0);
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
4410
  	hci_dev_unlock(hdev);
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
4411

715a5bf2d   Johan Hedberg   Bluetooth: Fix mi...
4412
  	return err;
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
4413
  }
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
4414
  static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4415
  {
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4416
  	struct hci_conn *conn = cmd->user_data;
9981bdb05   Johan Hedberg   Bluetooth: Fix Ge...
4417
  	struct mgmt_rp_get_conn_info rp;
9df746535   Johan Hedberg   Bluetooth: Add re...
4418
  	int err;
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4419

9981bdb05   Johan Hedberg   Bluetooth: Fix Ge...
4420
  	memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4421

9981bdb05   Johan Hedberg   Bluetooth: Fix Ge...
4422
  	if (status == MGMT_STATUS_SUCCESS) {
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4423
  		rp.rssi = conn->rssi;
9981bdb05   Johan Hedberg   Bluetooth: Fix Ge...
4424
4425
4426
4427
4428
4429
  		rp.tx_power = conn->tx_power;
  		rp.max_tx_power = conn->max_tx_power;
  	} else {
  		rp.rssi = HCI_RSSI_INVALID;
  		rp.tx_power = HCI_TX_POWER_INVALID;
  		rp.max_tx_power = HCI_TX_POWER_INVALID;
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4430
  	}
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4431
4432
  	err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
  				status, &rp, sizeof(rp));
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4433
4434
  
  	hci_conn_drop(conn);
f8aaf9b65   Johan Hedberg   Bluetooth: Fix us...
4435
  	hci_conn_put(conn);
9df746535   Johan Hedberg   Bluetooth: Add re...
4436
4437
  
  	return err;
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4438
  }
1904a853f   Marcel Holtmann   Bluetooth: Add op...
4439
4440
  static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
  				       u16 opcode)
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4441
4442
  {
  	struct hci_cp_read_rssi *cp;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
4443
  	struct mgmt_pending_cmd *cmd;
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4444
  	struct hci_conn *conn;
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4445
  	u16 handle;
9981bdb05   Johan Hedberg   Bluetooth: Fix Ge...
4446
  	u8 status;
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4447

9981bdb05   Johan Hedberg   Bluetooth: Fix Ge...
4448
  	BT_DBG("status 0x%02x", hci_status);
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4449
4450
  
  	hci_dev_lock(hdev);
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
  	/* Commands sent in request are either Read RSSI or Read Transmit Power
  	 * Level so we check which one was last sent to retrieve connection
  	 * handle.  Both commands have handle as first parameter so it's safe to
  	 * cast data on the same command struct.
  	 *
  	 * First command sent is always Read RSSI and we fail only if it fails.
  	 * In other case we simply override error to indicate success as we
  	 * already remembered if TX power value is actually valid.
  	 */
  	cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
  	if (!cp) {
  		cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
9981bdb05   Johan Hedberg   Bluetooth: Fix Ge...
4463
4464
4465
  		status = MGMT_STATUS_SUCCESS;
  	} else {
  		status = mgmt_status(hci_status);
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4466
4467
4468
  	}
  
  	if (!cp) {
9981bdb05   Johan Hedberg   Bluetooth: Fix Ge...
4469
  		BT_ERR("invalid sent_cmd in conn_info response");
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4470
4471
4472
4473
4474
4475
  		goto unlock;
  	}
  
  	handle = __le16_to_cpu(cp->handle);
  	conn = hci_conn_hash_lookup_handle(hdev, handle);
  	if (!conn) {
9981bdb05   Johan Hedberg   Bluetooth: Fix Ge...
4476
  		BT_ERR("unknown handle (%d) in conn_info response", handle);
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4477
4478
  		goto unlock;
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
4479
  	cmd = pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
9981bdb05   Johan Hedberg   Bluetooth: Fix Ge...
4480
4481
  	if (!cmd)
  		goto unlock;
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4482

9981bdb05   Johan Hedberg   Bluetooth: Fix Ge...
4483
4484
  	cmd->cmd_complete(cmd, status);
  	mgmt_pending_remove(cmd);
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
  
  unlock:
  	hci_dev_unlock(hdev);
  }
  
  static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
  			 u16 len)
  {
  	struct mgmt_cp_get_conn_info *cp = data;
  	struct mgmt_rp_get_conn_info rp;
  	struct hci_conn *conn;
  	unsigned long conn_info_age;
  	int err = 0;
  
  	BT_DBG("%s", hdev->name);
  
  	memset(&rp, 0, sizeof(rp));
  	bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
  	rp.addr.type = cp->addr.type;
  
  	if (!bdaddr_type_is_valid(cp->addr.type))
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4506
4507
4508
  		return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
  					 MGMT_STATUS_INVALID_PARAMS,
  					 &rp, sizeof(rp));
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4509
4510
4511
4512
  
  	hci_dev_lock(hdev);
  
  	if (!hdev_is_powered(hdev)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4513
4514
4515
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
  					MGMT_STATUS_NOT_POWERED, &rp,
  					sizeof(rp));
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
  		goto unlock;
  	}
  
  	if (cp->addr.type == BDADDR_BREDR)
  		conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
  					       &cp->addr.bdaddr);
  	else
  		conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
  
  	if (!conn || conn->state != BT_CONNECTED) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4526
4527
4528
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
  					MGMT_STATUS_NOT_CONNECTED, &rp,
  					sizeof(rp));
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4529
4530
  		goto unlock;
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
4531
  	if (pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4532
4533
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
  					MGMT_STATUS_BUSY, &rp, sizeof(rp));
9981bdb05   Johan Hedberg   Bluetooth: Fix Ge...
4534
4535
  		goto unlock;
  	}
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
  	/* To avoid client trying to guess when to poll again for information we
  	 * calculate conn info age as random value between min/max set in hdev.
  	 */
  	conn_info_age = hdev->conn_info_min_age +
  			prandom_u32_max(hdev->conn_info_max_age -
  					hdev->conn_info_min_age);
  
  	/* Query controller to refresh cached values if they are too old or were
  	 * never read.
  	 */
f4e2dd53d   Andrzej Kaczmarek   Bluetooth: Add mi...
4546
4547
  	if (time_after(jiffies, conn->conn_info_timestamp +
  		       msecs_to_jiffies(conn_info_age)) ||
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4548
4549
4550
4551
  	    !conn->conn_info_timestamp) {
  		struct hci_request req;
  		struct hci_cp_read_tx_power req_txp_cp;
  		struct hci_cp_read_rssi req_rssi_cp;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
4552
  		struct mgmt_pending_cmd *cmd;
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4553
4554
4555
4556
4557
  
  		hci_req_init(&req, hdev);
  		req_rssi_cp.handle = cpu_to_le16(conn->handle);
  		hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
  			    &req_rssi_cp);
f7faab0c9   Andrzej Kaczmarek   Bluetooth: Avoid ...
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
  		/* For LE links TX power does not change thus we don't need to
  		 * query for it once value is known.
  		 */
  		if (!bdaddr_type_is_le(cp->addr.type) ||
  		    conn->tx_power == HCI_TX_POWER_INVALID) {
  			req_txp_cp.handle = cpu_to_le16(conn->handle);
  			req_txp_cp.type = 0x00;
  			hci_req_add(&req, HCI_OP_READ_TX_POWER,
  				    sizeof(req_txp_cp), &req_txp_cp);
  		}
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4568

eed5daf31   Andrzej Kaczmarek   Bluetooth: Add su...
4569
4570
4571
4572
4573
4574
4575
  		/* Max TX power needs to be read only once per connection */
  		if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
  			req_txp_cp.handle = cpu_to_le16(conn->handle);
  			req_txp_cp.type = 0x01;
  			hci_req_add(&req, HCI_OP_READ_TX_POWER,
  				    sizeof(req_txp_cp), &req_txp_cp);
  		}
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
  		err = hci_req_run(&req, conn_info_refresh_complete);
  		if (err < 0)
  			goto unlock;
  
  		cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
  				       data, len);
  		if (!cmd) {
  			err = -ENOMEM;
  			goto unlock;
  		}
  
  		hci_conn_hold(conn);
f8aaf9b65   Johan Hedberg   Bluetooth: Fix us...
4588
  		cmd->user_data = hci_conn_get(conn);
9981bdb05   Johan Hedberg   Bluetooth: Fix Ge...
4589
  		cmd->cmd_complete = conn_info_cmd_complete;
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4590
4591
4592
4593
4594
4595
  
  		conn->conn_info_timestamp = jiffies;
  	} else {
  		/* Cache is valid, just reply with values cached in hci_conn */
  		rp.rssi = conn->rssi;
  		rp.tx_power = conn->tx_power;
eed5daf31   Andrzej Kaczmarek   Bluetooth: Add su...
4596
  		rp.max_tx_power = conn->max_tx_power;
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4597

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4598
4599
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
  					MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
4600
4601
4602
4603
4604
4605
  	}
  
  unlock:
  	hci_dev_unlock(hdev);
  	return err;
  }
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
4606
  static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
958684263   Johan Hedberg   Bluetooth: Add su...
4607
  {
69487371d   Johan Hedberg   Bluetooth: Conver...
4608
  	struct hci_conn *conn = cmd->user_data;
958684263   Johan Hedberg   Bluetooth: Add su...
4609
  	struct mgmt_rp_get_clock_info rp;
69487371d   Johan Hedberg   Bluetooth: Conver...
4610
  	struct hci_dev *hdev;
9df746535   Johan Hedberg   Bluetooth: Add re...
4611
  	int err;
69487371d   Johan Hedberg   Bluetooth: Conver...
4612
4613
  
  	memset(&rp, 0, sizeof(rp));
56f787c50   Marcel Holtmann   Bluetooth: Fix wr...
4614
  	memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
69487371d   Johan Hedberg   Bluetooth: Conver...
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
  
  	if (status)
  		goto complete;
  
  	hdev = hci_dev_get(cmd->index);
  	if (hdev) {
  		rp.local_clock = cpu_to_le32(hdev->clock);
  		hci_dev_put(hdev);
  	}
  
  	if (conn) {
  		rp.piconet_clock = cpu_to_le32(conn->clock);
  		rp.accuracy = cpu_to_le16(conn->clock_accuracy);
  	}
  
  complete:
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4631
4632
  	err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
  				sizeof(rp));
69487371d   Johan Hedberg   Bluetooth: Conver...
4633
4634
4635
4636
4637
  
  	if (conn) {
  		hci_conn_drop(conn);
  		hci_conn_put(conn);
  	}
9df746535   Johan Hedberg   Bluetooth: Add re...
4638
4639
  
  	return err;
69487371d   Johan Hedberg   Bluetooth: Conver...
4640
  }
1904a853f   Marcel Holtmann   Bluetooth: Add op...
4641
  static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
69487371d   Johan Hedberg   Bluetooth: Conver...
4642
  {
958684263   Johan Hedberg   Bluetooth: Add su...
4643
  	struct hci_cp_read_clock *hci_cp;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
4644
  	struct mgmt_pending_cmd *cmd;
958684263   Johan Hedberg   Bluetooth: Add su...
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
  	struct hci_conn *conn;
  
  	BT_DBG("%s status %u", hdev->name, status);
  
  	hci_dev_lock(hdev);
  
  	hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
  	if (!hci_cp)
  		goto unlock;
  
  	if (hci_cp->which) {
  		u16 handle = __le16_to_cpu(hci_cp->handle);
  		conn = hci_conn_hash_lookup_handle(hdev, handle);
  	} else {
  		conn = NULL;
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
4661
  	cmd = pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
958684263   Johan Hedberg   Bluetooth: Add su...
4662
4663
  	if (!cmd)
  		goto unlock;
69487371d   Johan Hedberg   Bluetooth: Conver...
4664
  	cmd->cmd_complete(cmd, mgmt_status(status));
958684263   Johan Hedberg   Bluetooth: Add su...
4665
  	mgmt_pending_remove(cmd);
958684263   Johan Hedberg   Bluetooth: Add su...
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
  
  unlock:
  	hci_dev_unlock(hdev);
  }
  
  static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
  			 u16 len)
  {
  	struct mgmt_cp_get_clock_info *cp = data;
  	struct mgmt_rp_get_clock_info rp;
  	struct hci_cp_read_clock hci_cp;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
4677
  	struct mgmt_pending_cmd *cmd;
958684263   Johan Hedberg   Bluetooth: Add su...
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
  	struct hci_request req;
  	struct hci_conn *conn;
  	int err;
  
  	BT_DBG("%s", hdev->name);
  
  	memset(&rp, 0, sizeof(rp));
  	bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
  	rp.addr.type = cp->addr.type;
  
  	if (cp->addr.type != BDADDR_BREDR)
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4689
4690
4691
  		return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
  					 MGMT_STATUS_INVALID_PARAMS,
  					 &rp, sizeof(rp));
958684263   Johan Hedberg   Bluetooth: Add su...
4692
4693
4694
4695
  
  	hci_dev_lock(hdev);
  
  	if (!hdev_is_powered(hdev)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4696
4697
4698
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
  					MGMT_STATUS_NOT_POWERED, &rp,
  					sizeof(rp));
958684263   Johan Hedberg   Bluetooth: Add su...
4699
4700
4701
4702
4703
4704
4705
  		goto unlock;
  	}
  
  	if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
  		conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
  					       &cp->addr.bdaddr);
  		if (!conn || conn->state != BT_CONNECTED) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4706
4707
4708
4709
  			err = mgmt_cmd_complete(sk, hdev->id,
  						MGMT_OP_GET_CLOCK_INFO,
  						MGMT_STATUS_NOT_CONNECTED,
  						&rp, sizeof(rp));
958684263   Johan Hedberg   Bluetooth: Add su...
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
  			goto unlock;
  		}
  	} else {
  		conn = NULL;
  	}
  
  	cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
  	if (!cmd) {
  		err = -ENOMEM;
  		goto unlock;
  	}
69487371d   Johan Hedberg   Bluetooth: Conver...
4721
  	cmd->cmd_complete = clock_info_cmd_complete;
958684263   Johan Hedberg   Bluetooth: Add su...
4722
4723
4724
4725
4726
4727
4728
  	hci_req_init(&req, hdev);
  
  	memset(&hci_cp, 0, sizeof(hci_cp));
  	hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
  
  	if (conn) {
  		hci_conn_hold(conn);
f8aaf9b65   Johan Hedberg   Bluetooth: Fix us...
4729
  		cmd->user_data = hci_conn_get(conn);
958684263   Johan Hedberg   Bluetooth: Add su...
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
  
  		hci_cp.handle = cpu_to_le16(conn->handle);
  		hci_cp.which = 0x01; /* Piconet clock */
  		hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
  	}
  
  	err = hci_req_run(&req, get_clock_info_complete);
  	if (err < 0)
  		mgmt_pending_remove(cmd);
  
  unlock:
  	hci_dev_unlock(hdev);
  	return err;
  }
5a154e6f7   Johan Hedberg   Bluetooth: Fix Ad...
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
  static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
  {
  	struct hci_conn *conn;
  
  	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
  	if (!conn)
  		return false;
  
  	if (conn->dst_type != type)
  		return false;
  
  	if (conn->state != BT_CONNECTED)
  		return false;
  
  	return true;
  }
  
  /* This function requires the caller holds hdev->lock */
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
4762
  static int hci_conn_params_set(struct hci_dev *hdev, bdaddr_t *addr,
5a154e6f7   Johan Hedberg   Bluetooth: Fix Ad...
4763
4764
  			       u8 addr_type, u8 auto_connect)
  {
5a154e6f7   Johan Hedberg   Bluetooth: Fix Ad...
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
  	struct hci_conn_params *params;
  
  	params = hci_conn_params_add(hdev, addr, addr_type);
  	if (!params)
  		return -EIO;
  
  	if (params->auto_connect == auto_connect)
  		return 0;
  
  	list_del_init(&params->action);
  
  	switch (auto_connect) {
  	case HCI_AUTO_CONN_DISABLED:
  	case HCI_AUTO_CONN_LINK_LOSS:
28a667c9c   Jakub Pawlowski   Bluetooth: advert...
4779
4780
4781
4782
4783
  		/* If auto connect is being disabled when we're trying to
  		 * connect to device, keep connecting.
  		 */
  		if (params->explicit_connect)
  			list_add(&params->action, &hdev->pend_le_conns);
5a154e6f7   Johan Hedberg   Bluetooth: Fix Ad...
4784
4785
  		break;
  	case HCI_AUTO_CONN_REPORT:
49c509220   Johan Hedberg   Bluetooth: Fix LE...
4786
4787
4788
4789
  		if (params->explicit_connect)
  			list_add(&params->action, &hdev->pend_le_conns);
  		else
  			list_add(&params->action, &hdev->pend_le_reports);
5a154e6f7   Johan Hedberg   Bluetooth: Fix Ad...
4790
4791
4792
  		break;
  	case HCI_AUTO_CONN_DIRECT:
  	case HCI_AUTO_CONN_ALWAYS:
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
4793
  		if (!is_connected(hdev, addr, addr_type))
5a154e6f7   Johan Hedberg   Bluetooth: Fix Ad...
4794
  			list_add(&params->action, &hdev->pend_le_conns);
5a154e6f7   Johan Hedberg   Bluetooth: Fix Ad...
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
  		break;
  	}
  
  	params->auto_connect = auto_connect;
  
  	BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
  	       auto_connect);
  
  	return 0;
  }
8afef092a   Marcel Holtmann   Bluetooth: Add De...
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
  static void device_added(struct sock *sk, struct hci_dev *hdev,
  			 bdaddr_t *bdaddr, u8 type, u8 action)
  {
  	struct mgmt_ev_device_added ev;
  
  	bacpy(&ev.addr.bdaddr, bdaddr);
  	ev.addr.type = type;
  	ev.action = action;
  
  	mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
  }
2faade53e   Marcel Holtmann   Bluetooth: Add su...
4816
4817
4818
4819
4820
4821
4822
4823
  static int add_device(struct sock *sk, struct hci_dev *hdev,
  		      void *data, u16 len)
  {
  	struct mgmt_cp_add_device *cp = data;
  	u8 auto_conn, addr_type;
  	int err;
  
  	BT_DBG("%s", hdev->name);
6659358ef   Johan Hedberg   Bluetooth: Introd...
4824
  	if (!bdaddr_type_is_valid(cp->addr.type) ||
2faade53e   Marcel Holtmann   Bluetooth: Add su...
4825
  	    !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4826
4827
4828
  		return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
  					 MGMT_STATUS_INVALID_PARAMS,
  					 &cp->addr, sizeof(cp->addr));
2faade53e   Marcel Holtmann   Bluetooth: Add su...
4829

4b9e7e751   Marcel Holtmann   Bluetooth: Fix is...
4830
  	if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4831
4832
4833
  		return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
  					 MGMT_STATUS_INVALID_PARAMS,
  					 &cp->addr, sizeof(cp->addr));
2faade53e   Marcel Holtmann   Bluetooth: Add su...
4834
4835
  
  	hci_dev_lock(hdev);
6659358ef   Johan Hedberg   Bluetooth: Introd...
4836
  	if (cp->addr.type == BDADDR_BREDR) {
4b9e7e751   Marcel Holtmann   Bluetooth: Fix is...
4837
  		/* Only incoming connections action is supported for now */
6659358ef   Johan Hedberg   Bluetooth: Introd...
4838
  		if (cp->action != 0x01) {
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
4839
4840
4841
4842
  			err = mgmt_cmd_complete(sk, hdev->id,
  						MGMT_OP_ADD_DEVICE,
  						MGMT_STATUS_INVALID_PARAMS,
  						&cp->addr, sizeof(cp->addr));
6659358ef   Johan Hedberg   Bluetooth: Introd...
4843
4844
4845
4846
4847
4848
4849
  			goto unlock;
  		}
  
  		err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
  					  cp->addr.type);
  		if (err)
  			goto unlock;
a397407f2   Johan Hedberg   Bluetooth: Update...
4850

01b1cb87d   Johan Hedberg   Bluetooth: Run pa...
4851
  		hci_req_update_scan(hdev);
a397407f2   Johan Hedberg   Bluetooth: Update...
4852

6659358ef   Johan Hedberg   Bluetooth: Introd...
4853
4854
  		goto added;
  	}
85813a7ec   Johan Hedberg   Bluetooth: Add le...
4855
  	addr_type = le_addr_type(cp->addr.type);
2faade53e   Marcel Holtmann   Bluetooth: Add su...
4856

4b9e7e751   Marcel Holtmann   Bluetooth: Fix is...
4857
  	if (cp->action == 0x02)
2faade53e   Marcel Holtmann   Bluetooth: Add su...
4858
  		auto_conn = HCI_AUTO_CONN_ALWAYS;
4b9e7e751   Marcel Holtmann   Bluetooth: Fix is...
4859
4860
  	else if (cp->action == 0x01)
  		auto_conn = HCI_AUTO_CONN_DIRECT;
2faade53e   Marcel Holtmann   Bluetooth: Add su...
4861
  	else
a3451d279   Johan Hedberg   Bluetooth: Add ne...
4862
  		auto_conn = HCI_AUTO_CONN_REPORT;
2faade53e   Marcel Holtmann   Bluetooth: Add su...
4863

9a0a8a8e8   Jakub Pawlowski   Bluetooth: Move I...
4864
4865
4866
4867
4868
4869
  	/* Kernel internally uses conn_params with resolvable private
  	 * address, but Add Device allows only identity addresses.
  	 * Make sure it is enforced before calling
  	 * hci_conn_params_lookup.
  	 */
  	if (!hci_is_identity_address(&cp->addr.bdaddr, addr_type)) {
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
4870
4871
4872
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
  					MGMT_STATUS_INVALID_PARAMS,
  					&cp->addr, sizeof(cp->addr));
9a0a8a8e8   Jakub Pawlowski   Bluetooth: Move I...
4873
4874
  		goto unlock;
  	}
bf5b3c8be   Marcel Holtmann   Bluetooth: Provid...
4875
4876
4877
  	/* If the connection parameters don't exist for this device,
  	 * they will be created and configured with defaults.
  	 */
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
4878
  	if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
d06b50ce1   Marcel Holtmann   Bluetooth: Remove...
4879
  				auto_conn) < 0) {
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
4880
4881
4882
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
  					MGMT_STATUS_FAILED, &cp->addr,
  					sizeof(cp->addr));
2faade53e   Marcel Holtmann   Bluetooth: Add su...
4883
4884
  		goto unlock;
  	}
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
4885
  	hci_update_background_scan(hdev);
6659358ef   Johan Hedberg   Bluetooth: Introd...
4886
  added:
8afef092a   Marcel Holtmann   Bluetooth: Add De...
4887
  	device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
4888
4889
4890
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
  				MGMT_STATUS_SUCCESS, &cp->addr,
  				sizeof(cp->addr));
2faade53e   Marcel Holtmann   Bluetooth: Add su...
4891
4892
4893
4894
4895
  
  unlock:
  	hci_dev_unlock(hdev);
  	return err;
  }
8afef092a   Marcel Holtmann   Bluetooth: Add De...
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
  static void device_removed(struct sock *sk, struct hci_dev *hdev,
  			   bdaddr_t *bdaddr, u8 type)
  {
  	struct mgmt_ev_device_removed ev;
  
  	bacpy(&ev.addr.bdaddr, bdaddr);
  	ev.addr.type = type;
  
  	mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
  }
2faade53e   Marcel Holtmann   Bluetooth: Add su...
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
  static int remove_device(struct sock *sk, struct hci_dev *hdev,
  			 void *data, u16 len)
  {
  	struct mgmt_cp_remove_device *cp = data;
  	int err;
  
  	BT_DBG("%s", hdev->name);
  
  	hci_dev_lock(hdev);
  
  	if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
c71593dd3   Johan Hedberg   Bluetooth: Remove...
4917
  		struct hci_conn_params *params;
2faade53e   Marcel Holtmann   Bluetooth: Add su...
4918
  		u8 addr_type;
6659358ef   Johan Hedberg   Bluetooth: Introd...
4919
  		if (!bdaddr_type_is_valid(cp->addr.type)) {
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
4920
4921
4922
4923
  			err = mgmt_cmd_complete(sk, hdev->id,
  						MGMT_OP_REMOVE_DEVICE,
  						MGMT_STATUS_INVALID_PARAMS,
  						&cp->addr, sizeof(cp->addr));
2faade53e   Marcel Holtmann   Bluetooth: Add su...
4924
4925
  			goto unlock;
  		}
6659358ef   Johan Hedberg   Bluetooth: Introd...
4926
4927
4928
4929
4930
  		if (cp->addr.type == BDADDR_BREDR) {
  			err = hci_bdaddr_list_del(&hdev->whitelist,
  						  &cp->addr.bdaddr,
  						  cp->addr.type);
  			if (err) {
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
4931
4932
4933
4934
4935
  				err = mgmt_cmd_complete(sk, hdev->id,
  							MGMT_OP_REMOVE_DEVICE,
  							MGMT_STATUS_INVALID_PARAMS,
  							&cp->addr,
  							sizeof(cp->addr));
6659358ef   Johan Hedberg   Bluetooth: Introd...
4936
4937
  				goto unlock;
  			}
01b1cb87d   Johan Hedberg   Bluetooth: Run pa...
4938
  			hci_req_update_scan(hdev);
a397407f2   Johan Hedberg   Bluetooth: Update...
4939

6659358ef   Johan Hedberg   Bluetooth: Introd...
4940
4941
4942
4943
  			device_removed(sk, hdev, &cp->addr.bdaddr,
  				       cp->addr.type);
  			goto complete;
  		}
85813a7ec   Johan Hedberg   Bluetooth: Add le...
4944
  		addr_type = le_addr_type(cp->addr.type);
2faade53e   Marcel Holtmann   Bluetooth: Add su...
4945

9a0a8a8e8   Jakub Pawlowski   Bluetooth: Move I...
4946
4947
4948
4949
4950
4951
  		/* Kernel internally uses conn_params with resolvable private
  		 * address, but Remove Device allows only identity addresses.
  		 * Make sure it is enforced before calling
  		 * hci_conn_params_lookup.
  		 */
  		if (!hci_is_identity_address(&cp->addr.bdaddr, addr_type)) {
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
4952
4953
4954
4955
  			err = mgmt_cmd_complete(sk, hdev->id,
  						MGMT_OP_REMOVE_DEVICE,
  						MGMT_STATUS_INVALID_PARAMS,
  						&cp->addr, sizeof(cp->addr));
9a0a8a8e8   Jakub Pawlowski   Bluetooth: Move I...
4956
4957
  			goto unlock;
  		}
c71593dd3   Johan Hedberg   Bluetooth: Remove...
4958
4959
4960
  		params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
  						addr_type);
  		if (!params) {
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
4961
4962
4963
4964
  			err = mgmt_cmd_complete(sk, hdev->id,
  						MGMT_OP_REMOVE_DEVICE,
  						MGMT_STATUS_INVALID_PARAMS,
  						&cp->addr, sizeof(cp->addr));
c71593dd3   Johan Hedberg   Bluetooth: Remove...
4965
4966
  			goto unlock;
  		}
679d2b6f9   Johan Hedberg   Bluetooth: Fix re...
4967
4968
  		if (params->auto_connect == HCI_AUTO_CONN_DISABLED ||
  		    params->auto_connect == HCI_AUTO_CONN_EXPLICIT) {
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
4969
4970
4971
4972
  			err = mgmt_cmd_complete(sk, hdev->id,
  						MGMT_OP_REMOVE_DEVICE,
  						MGMT_STATUS_INVALID_PARAMS,
  						&cp->addr, sizeof(cp->addr));
c71593dd3   Johan Hedberg   Bluetooth: Remove...
4973
4974
  			goto unlock;
  		}
d1dbf12e3   Johan Hedberg   Bluetooth: Use li...
4975
  		list_del(&params->action);
c71593dd3   Johan Hedberg   Bluetooth: Remove...
4976
4977
  		list_del(&params->list);
  		kfree(params);
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
4978
  		hci_update_background_scan(hdev);
8afef092a   Marcel Holtmann   Bluetooth: Add De...
4979
4980
  
  		device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
2faade53e   Marcel Holtmann   Bluetooth: Add su...
4981
  	} else {
19de0825c   Johan Hedberg   Bluetooth: Fix se...
4982
  		struct hci_conn_params *p, *tmp;
6659358ef   Johan Hedberg   Bluetooth: Introd...
4983
  		struct bdaddr_list *b, *btmp;
19de0825c   Johan Hedberg   Bluetooth: Fix se...
4984

2faade53e   Marcel Holtmann   Bluetooth: Add su...
4985
  		if (cp->addr.type) {
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
4986
4987
4988
4989
  			err = mgmt_cmd_complete(sk, hdev->id,
  						MGMT_OP_REMOVE_DEVICE,
  						MGMT_STATUS_INVALID_PARAMS,
  						&cp->addr, sizeof(cp->addr));
2faade53e   Marcel Holtmann   Bluetooth: Add su...
4990
4991
  			goto unlock;
  		}
6659358ef   Johan Hedberg   Bluetooth: Introd...
4992
4993
4994
4995
4996
  		list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
  			device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
  			list_del(&b->list);
  			kfree(b);
  		}
01b1cb87d   Johan Hedberg   Bluetooth: Run pa...
4997
  		hci_req_update_scan(hdev);
a397407f2   Johan Hedberg   Bluetooth: Update...
4998

19de0825c   Johan Hedberg   Bluetooth: Fix se...
4999
5000
5001
5002
  		list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
  			if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
  				continue;
  			device_removed(sk, hdev, &p->addr, p->addr_type);
679d2b6f9   Johan Hedberg   Bluetooth: Fix re...
5003
5004
5005
5006
  			if (p->explicit_connect) {
  				p->auto_connect = HCI_AUTO_CONN_EXPLICIT;
  				continue;
  			}
19de0825c   Johan Hedberg   Bluetooth: Fix se...
5007
5008
5009
5010
5011
5012
  			list_del(&p->action);
  			list_del(&p->list);
  			kfree(p);
  		}
  
  		BT_DBG("All LE connection parameters were removed");
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
5013
  		hci_update_background_scan(hdev);
2faade53e   Marcel Holtmann   Bluetooth: Add su...
5014
  	}
6659358ef   Johan Hedberg   Bluetooth: Introd...
5015
  complete:
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
5016
5017
5018
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
  				MGMT_STATUS_SUCCESS, &cp->addr,
  				sizeof(cp->addr));
2faade53e   Marcel Holtmann   Bluetooth: Add su...
5019
5020
5021
5022
  unlock:
  	hci_dev_unlock(hdev);
  	return err;
  }
a26f3dcff   Johan Hedberg   Bluetooth: Add Lo...
5023
5024
5025
5026
  static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
  			   u16 len)
  {
  	struct mgmt_cp_load_conn_param *cp = data;
ba1d6936f   Johan Hedberg   Bluetooth: Fix bu...
5027
5028
  	const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
  				     sizeof(struct mgmt_conn_param));
a26f3dcff   Johan Hedberg   Bluetooth: Add Lo...
5029
5030
5031
5032
  	u16 param_count, expected_len;
  	int i;
  
  	if (!lmp_le_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5033
5034
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
  				       MGMT_STATUS_NOT_SUPPORTED);
a26f3dcff   Johan Hedberg   Bluetooth: Add Lo...
5035
5036
  
  	param_count = __le16_to_cpu(cp->param_count);
ba1d6936f   Johan Hedberg   Bluetooth: Fix bu...
5037
5038
5039
  	if (param_count > max_param_count) {
  		BT_ERR("load_conn_param: too big param_count value %u",
  		       param_count);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5040
5041
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
  				       MGMT_STATUS_INVALID_PARAMS);
ba1d6936f   Johan Hedberg   Bluetooth: Fix bu...
5042
  	}
a26f3dcff   Johan Hedberg   Bluetooth: Add Lo...
5043
5044
5045
5046
5047
5048
  
  	expected_len = sizeof(*cp) + param_count *
  					sizeof(struct mgmt_conn_param);
  	if (expected_len != len) {
  		BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
  		       expected_len, len);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5049
5050
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
  				       MGMT_STATUS_INVALID_PARAMS);
a26f3dcff   Johan Hedberg   Bluetooth: Add Lo...
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
  	}
  
  	BT_DBG("%s param_count %u", hdev->name, param_count);
  
  	hci_dev_lock(hdev);
  
  	hci_conn_params_clear_disabled(hdev);
  
  	for (i = 0; i < param_count; i++) {
  		struct mgmt_conn_param *param = &cp->params[i];
  		struct hci_conn_params *hci_param;
  		u16 min, max, latency, timeout;
  		u8 addr_type;
  
  		BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
  		       param->addr.type);
  
  		if (param->addr.type == BDADDR_LE_PUBLIC) {
  			addr_type = ADDR_LE_DEV_PUBLIC;
  		} else if (param->addr.type == BDADDR_LE_RANDOM) {
  			addr_type = ADDR_LE_DEV_RANDOM;
  		} else {
  			BT_ERR("Ignoring invalid connection parameters");
  			continue;
  		}
  
  		min = le16_to_cpu(param->min_interval);
  		max = le16_to_cpu(param->max_interval);
  		latency = le16_to_cpu(param->latency);
  		timeout = le16_to_cpu(param->timeout);
  
  		BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
  		       min, max, latency, timeout);
  
  		if (hci_check_conn_params(min, max, latency, timeout) < 0) {
  			BT_ERR("Ignoring invalid connection parameters");
  			continue;
  		}
  
  		hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
  						addr_type);
  		if (!hci_param) {
  			BT_ERR("Failed to add connection parameters");
  			continue;
  		}
  
  		hci_param->conn_min_interval = min;
  		hci_param->conn_max_interval = max;
  		hci_param->conn_latency = latency;
  		hci_param->supervision_timeout = timeout;
  	}
  
  	hci_dev_unlock(hdev);
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
5104
5105
  	return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
  				 NULL, 0);
a26f3dcff   Johan Hedberg   Bluetooth: Add Lo...
5106
  }
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
  static int set_external_config(struct sock *sk, struct hci_dev *hdev,
  			       void *data, u16 len)
  {
  	struct mgmt_cp_set_external_config *cp = data;
  	bool changed;
  	int err;
  
  	BT_DBG("%s", hdev->name);
  
  	if (hdev_is_powered(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5117
5118
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
  				       MGMT_STATUS_REJECTED);
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
5119
5120
  
  	if (cp->config != 0x00 && cp->config != 0x01)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5121
5122
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
  				         MGMT_STATUS_INVALID_PARAMS);
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
5123
5124
  
  	if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5125
5126
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
  				       MGMT_STATUS_NOT_SUPPORTED);
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
5127
5128
5129
5130
  
  	hci_dev_lock(hdev);
  
  	if (cp->config)
238be788f   Marcel Holtmann   Bluetooth: Introd...
5131
  		changed = !hci_dev_test_and_set_flag(hdev, HCI_EXT_CONFIGURED);
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
5132
  	else
a69d89272   Marcel Holtmann   Bluetooth: Introd...
5133
  		changed = hci_dev_test_and_clear_flag(hdev, HCI_EXT_CONFIGURED);
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
5134
5135
5136
5137
5138
5139
5140
  
  	err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
  	if (err < 0)
  		goto unlock;
  
  	if (!changed)
  		goto unlock;
f4537c04d   Marcel Holtmann   Bluetooth: Add su...
5141
  	err = new_options(hdev, sk);
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
5142
  	if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
5143
  		mgmt_index_removed(hdev);
d603b76b0   Marcel Holtmann   Bluetooth: Run co...
5144

516018a9c   Marcel Holtmann   Bluetooth: Introd...
5145
  		if (hci_dev_test_and_change_flag(hdev, HCI_UNCONFIGURED)) {
a1536da25   Marcel Holtmann   Bluetooth: Introd...
5146
5147
  			hci_dev_set_flag(hdev, HCI_CONFIG);
  			hci_dev_set_flag(hdev, HCI_AUTO_OFF);
d603b76b0   Marcel Holtmann   Bluetooth: Run co...
5148
5149
5150
  
  			queue_work(hdev->req_workqueue, &hdev->power_on);
  		} else {
5ea234d3e   Marcel Holtmann   Bluetooth: Clear ...
5151
  			set_bit(HCI_RAW, &hdev->flags);
d603b76b0   Marcel Holtmann   Bluetooth: Run co...
5152
5153
  			mgmt_index_added(hdev);
  		}
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
5154
5155
5156
5157
5158
5159
  	}
  
  unlock:
  	hci_dev_unlock(hdev);
  	return err;
  }
9713c17b0   Marcel Holtmann   Bluetooth: Add su...
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
  static int set_public_address(struct sock *sk, struct hci_dev *hdev,
  			      void *data, u16 len)
  {
  	struct mgmt_cp_set_public_address *cp = data;
  	bool changed;
  	int err;
  
  	BT_DBG("%s", hdev->name);
  
  	if (hdev_is_powered(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5170
5171
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
  				       MGMT_STATUS_REJECTED);
9713c17b0   Marcel Holtmann   Bluetooth: Add su...
5172
5173
  
  	if (!bacmp(&cp->bdaddr, BDADDR_ANY))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5174
5175
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
  				       MGMT_STATUS_INVALID_PARAMS);
9713c17b0   Marcel Holtmann   Bluetooth: Add su...
5176
5177
  
  	if (!hdev->set_bdaddr)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5178
5179
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
  				       MGMT_STATUS_NOT_SUPPORTED);
9713c17b0   Marcel Holtmann   Bluetooth: Add su...
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
  
  	hci_dev_lock(hdev);
  
  	changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
  	bacpy(&hdev->public_addr, &cp->bdaddr);
  
  	err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
  	if (err < 0)
  		goto unlock;
  
  	if (!changed)
  		goto unlock;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
5192
  	if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
9713c17b0   Marcel Holtmann   Bluetooth: Add su...
5193
5194
5195
5196
  		err = new_options(hdev, sk);
  
  	if (is_configured(hdev)) {
  		mgmt_index_removed(hdev);
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
5197
  		hci_dev_clear_flag(hdev, HCI_UNCONFIGURED);
9713c17b0   Marcel Holtmann   Bluetooth: Add su...
5198

a1536da25   Marcel Holtmann   Bluetooth: Introd...
5199
5200
  		hci_dev_set_flag(hdev, HCI_CONFIG);
  		hci_dev_set_flag(hdev, HCI_AUTO_OFF);
9713c17b0   Marcel Holtmann   Bluetooth: Add su...
5201
5202
5203
5204
5205
5206
5207
5208
  
  		queue_work(hdev->req_workqueue, &hdev->power_on);
  	}
  
  unlock:
  	hci_dev_unlock(hdev);
  	return err;
  }
40f66c05c   Johan Hedberg   Bluetooth: Add lo...
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
  static void read_local_oob_ext_data_complete(struct hci_dev *hdev, u8 status,
  					     u16 opcode, struct sk_buff *skb)
  {
  	const struct mgmt_cp_read_local_oob_ext_data *mgmt_cp;
  	struct mgmt_rp_read_local_oob_ext_data *mgmt_rp;
  	u8 *h192, *r192, *h256, *r256;
  	struct mgmt_pending_cmd *cmd;
  	u16 eir_len;
  	int err;
  
  	BT_DBG("%s status %u", hdev->name, status);
  
  	cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev);
  	if (!cmd)
  		return;
  
  	mgmt_cp = cmd->param;
  
  	if (status) {
  		status = mgmt_status(status);
  		eir_len = 0;
  
  		h192 = NULL;
  		r192 = NULL;
  		h256 = NULL;
  		r256 = NULL;
  	} else if (opcode == HCI_OP_READ_LOCAL_OOB_DATA) {
  		struct hci_rp_read_local_oob_data *rp;
  
  		if (skb->len != sizeof(*rp)) {
  			status = MGMT_STATUS_FAILED;
  			eir_len = 0;
  		} else {
  			status = MGMT_STATUS_SUCCESS;
  			rp = (void *)skb->data;
  
  			eir_len = 5 + 18 + 18;
  			h192 = rp->hash;
  			r192 = rp->rand;
  			h256 = NULL;
  			r256 = NULL;
  		}
  	} else {
  		struct hci_rp_read_local_oob_ext_data *rp;
  
  		if (skb->len != sizeof(*rp)) {
  			status = MGMT_STATUS_FAILED;
  			eir_len = 0;
  		} else {
  			status = MGMT_STATUS_SUCCESS;
  			rp = (void *)skb->data;
  
  			if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
  				eir_len = 5 + 18 + 18;
  				h192 = NULL;
  				r192 = NULL;
  			} else {
  				eir_len = 5 + 18 + 18 + 18 + 18;
  				h192 = rp->hash192;
  				r192 = rp->rand192;
  			}
  
  			h256 = rp->hash256;
  			r256 = rp->rand256;
  		}
  	}
  
  	mgmt_rp = kmalloc(sizeof(*mgmt_rp) + eir_len, GFP_KERNEL);
  	if (!mgmt_rp)
  		goto done;
  
  	if (status)
  		goto send_rsp;
  
  	eir_len = eir_append_data(mgmt_rp->eir, 0, EIR_CLASS_OF_DEV,
  				  hdev->dev_class, 3);
  
  	if (h192 && r192) {
  		eir_len = eir_append_data(mgmt_rp->eir, eir_len,
  					  EIR_SSP_HASH_C192, h192, 16);
  		eir_len = eir_append_data(mgmt_rp->eir, eir_len,
  					  EIR_SSP_RAND_R192, r192, 16);
  	}
  
  	if (h256 && r256) {
  		eir_len = eir_append_data(mgmt_rp->eir, eir_len,
  					  EIR_SSP_HASH_C256, h256, 16);
  		eir_len = eir_append_data(mgmt_rp->eir, eir_len,
  					  EIR_SSP_RAND_R256, r256, 16);
  	}
  
  send_rsp:
  	mgmt_rp->type = mgmt_cp->type;
  	mgmt_rp->eir_len = cpu_to_le16(eir_len);
  
  	err = mgmt_cmd_complete(cmd->sk, hdev->id,
  				MGMT_OP_READ_LOCAL_OOB_EXT_DATA, status,
  				mgmt_rp, sizeof(*mgmt_rp) + eir_len);
  	if (err < 0 || status)
  		goto done;
  
  	hci_sock_set_flag(cmd->sk, HCI_MGMT_OOB_DATA_EVENTS);
  
  	err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
  				 mgmt_rp, sizeof(*mgmt_rp) + eir_len,
  				 HCI_MGMT_OOB_DATA_EVENTS, cmd->sk);
  done:
  	kfree(mgmt_rp);
  	mgmt_pending_remove(cmd);
  }
  
  static int read_local_ssp_oob_req(struct hci_dev *hdev, struct sock *sk,
  				  struct mgmt_cp_read_local_oob_ext_data *cp)
  {
  	struct mgmt_pending_cmd *cmd;
  	struct hci_request req;
  	int err;
  
  	cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev,
  			       cp, sizeof(*cp));
  	if (!cmd)
  		return -ENOMEM;
  
  	hci_req_init(&req, hdev);
  
  	if (bredr_sc_enabled(hdev))
  		hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_EXT_DATA, 0, NULL);
  	else
  		hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
  
  	err = hci_req_run_skb(&req, read_local_oob_ext_data_complete);
  	if (err < 0) {
  		mgmt_pending_remove(cmd);
  		return err;
  	}
  
  	return 0;
  }
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
5347
5348
5349
5350
5351
5352
5353
  static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev,
  				   void *data, u16 data_len)
  {
  	struct mgmt_cp_read_local_oob_ext_data *cp = data;
  	struct mgmt_rp_read_local_oob_ext_data *rp;
  	size_t rp_len;
  	u16 eir_len;
0821a2c5a   Marcel Holtmann   Bluetooth: Return...
5354
  	u8 status, flags, role, addr[7], hash[16], rand[16];
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
5355
5356
5357
  	int err;
  
  	BT_DBG("%s", hdev->name);
57b0d3e8e   Marcel Holtmann   Bluetooth: Fix er...
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
  	if (hdev_is_powered(hdev)) {
  		switch (cp->type) {
  		case BIT(BDADDR_BREDR):
  			status = mgmt_bredr_support(hdev);
  			if (status)
  				eir_len = 0;
  			else
  				eir_len = 5;
  			break;
  		case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
  			status = mgmt_le_support(hdev);
  			if (status)
  				eir_len = 0;
  			else
  				eir_len = 9 + 3 + 18 + 18 + 3;
  			break;
  		default:
  			status = MGMT_STATUS_INVALID_PARAMS;
  			eir_len = 0;
  			break;
  		}
  	} else {
  		status = MGMT_STATUS_NOT_POWERED;
  		eir_len = 0;
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
5382
  	}
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
5383
5384
  	rp_len = sizeof(*rp) + eir_len;
  	rp = kmalloc(rp_len, GFP_ATOMIC);
efcd8c98e   Marcel Holtmann   Bluetooth: Move m...
5385
  	if (!rp)
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
5386
  		return -ENOMEM;
efcd8c98e   Marcel Holtmann   Bluetooth: Move m...
5387

57b0d3e8e   Marcel Holtmann   Bluetooth: Fix er...
5388
5389
  	if (status)
  		goto complete;
efcd8c98e   Marcel Holtmann   Bluetooth: Move m...
5390
  	hci_dev_lock(hdev);
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
5391
5392
5393
5394
  
  	eir_len = 0;
  	switch (cp->type) {
  	case BIT(BDADDR_BREDR):
40f66c05c   Johan Hedberg   Bluetooth: Add lo...
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
  		if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
  			err = read_local_ssp_oob_req(hdev, sk, cp);
  			hci_dev_unlock(hdev);
  			if (!err)
  				goto done;
  
  			status = MGMT_STATUS_FAILED;
  			goto complete;
  		} else {
  			eir_len = eir_append_data(rp->eir, eir_len,
  						  EIR_CLASS_OF_DEV,
  						  hdev->dev_class, 3);
  		}
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
5408
5409
  		break;
  	case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
5082a5996   Marcel Holtmann   Bluetooth: Do not...
5410
5411
  		if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
  		    smp_generate_oob(hdev, hash, rand) < 0) {
0821a2c5a   Marcel Holtmann   Bluetooth: Return...
5412
  			hci_dev_unlock(hdev);
57b0d3e8e   Marcel Holtmann   Bluetooth: Fix er...
5413
5414
  			status = MGMT_STATUS_FAILED;
  			goto complete;
0821a2c5a   Marcel Holtmann   Bluetooth: Return...
5415
  		}
e213568ad   Marcel Holtmann   Bluetooth: Disall...
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
  		/* This should return the active RPA, but since the RPA
  		 * is only programmed on demand, it is really hard to fill
  		 * this in at the moment. For now disallow retrieving
  		 * local out-of-band data when privacy is in use.
  		 *
  		 * Returning the identity address will not help here since
  		 * pairing happens before the identity resolving key is
  		 * known and thus the connection establishment happens
  		 * based on the RPA and not the identity address.
  		 */
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
5426
  		if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
e213568ad   Marcel Holtmann   Bluetooth: Disall...
5427
5428
5429
5430
5431
5432
5433
5434
5435
  			hci_dev_unlock(hdev);
  			status = MGMT_STATUS_REJECTED;
  			goto complete;
  		}
  
  		if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
  		   !bacmp(&hdev->bdaddr, BDADDR_ANY) ||
  		   (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
  		    bacmp(&hdev->static_addr, BDADDR_ANY))) {
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
  			memcpy(addr, &hdev->static_addr, 6);
  			addr[6] = 0x01;
  		} else {
  			memcpy(addr, &hdev->bdaddr, 6);
  			addr[6] = 0x00;
  		}
  
  		eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_BDADDR,
  					  addr, sizeof(addr));
  
  		if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
  			role = 0x02;
  		else
  			role = 0x01;
  
  		eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_ROLE,
  					  &role, sizeof(role));
5082a5996   Marcel Holtmann   Bluetooth: Do not...
5453
5454
5455
5456
  		if (hci_dev_test_flag(hdev, HCI_SC_ENABLED)) {
  			eir_len = eir_append_data(rp->eir, eir_len,
  						  EIR_LE_SC_CONFIRM,
  						  hash, sizeof(hash));
0821a2c5a   Marcel Holtmann   Bluetooth: Return...
5457

5082a5996   Marcel Holtmann   Bluetooth: Do not...
5458
5459
5460
5461
  			eir_len = eir_append_data(rp->eir, eir_len,
  						  EIR_LE_SC_RANDOM,
  						  rand, sizeof(rand));
  		}
0821a2c5a   Marcel Holtmann   Bluetooth: Return...
5462

f22525700   Johan Hedberg   Bluetooth: Move a...
5463
  		flags = mgmt_get_adv_discov_flags(hdev);
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
5464
5465
5466
5467
5468
5469
5470
5471
  
  		if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
  			flags |= LE_AD_NO_BREDR;
  
  		eir_len = eir_append_data(rp->eir, eir_len, EIR_FLAGS,
  					  &flags, sizeof(flags));
  		break;
  	}
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
5472
  	hci_dev_unlock(hdev);
72000df2c   Marcel Holtmann   Bluetooth: Add su...
5473
  	hci_sock_set_flag(sk, HCI_MGMT_OOB_DATA_EVENTS);
57b0d3e8e   Marcel Holtmann   Bluetooth: Fix er...
5474
5475
5476
  	status = MGMT_STATUS_SUCCESS;
  
  complete:
efcd8c98e   Marcel Holtmann   Bluetooth: Move m...
5477
5478
  	rp->type = cp->type;
  	rp->eir_len = cpu_to_le16(eir_len);
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
5479
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
57b0d3e8e   Marcel Holtmann   Bluetooth: Fix er...
5480
5481
  				status, rp, sizeof(*rp) + eir_len);
  	if (err < 0 || status)
72000df2c   Marcel Holtmann   Bluetooth: Add su...
5482
5483
5484
5485
5486
  		goto done;
  
  	err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
  				 rp, sizeof(*rp) + eir_len,
  				 HCI_MGMT_OOB_DATA_EVENTS, sk);
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
5487

0821a2c5a   Marcel Holtmann   Bluetooth: Return...
5488
  done:
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
5489
5490
5491
5492
  	kfree(rp);
  
  	return err;
  }
089fa8c09   Arman Uguray   Bluetooth: Update...
5493
5494
5495
5496
5497
5498
5499
5500
  static u32 get_supported_adv_flags(struct hci_dev *hdev)
  {
  	u32 flags = 0;
  
  	flags |= MGMT_ADV_FLAG_CONNECTABLE;
  	flags |= MGMT_ADV_FLAG_DISCOV;
  	flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
  	flags |= MGMT_ADV_FLAG_MANAGED_FLAGS;
c4960ecf2   MichaƂ Narajowski   Bluetooth: Add su...
5501
  	flags |= MGMT_ADV_FLAG_APPEARANCE;
7c295c480   MichaƂ Narajowski   Bluetooth: Add su...
5502
  	flags |= MGMT_ADV_FLAG_LOCAL_NAME;
089fa8c09   Arman Uguray   Bluetooth: Update...
5503
5504
5505
5506
5507
5508
  
  	if (hdev->adv_tx_power != HCI_TX_POWER_INVALID)
  		flags |= MGMT_ADV_FLAG_TX_POWER;
  
  	return flags;
  }
d3d5305bf   Marcel Holtmann   Bluetooth: Add si...
5509
5510
5511
5512
5513
  static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
  			     void *data, u16 data_len)
  {
  	struct mgmt_rp_read_adv_features *rp;
  	size_t rp_len;
02c04afea   Johan Hedberg   Bluetooth: Simpli...
5514
  	int err;
286e0c83d   Florian Grandel   Bluetooth: mgmt: ...
5515
  	struct adv_info *adv_instance;
089fa8c09   Arman Uguray   Bluetooth: Update...
5516
  	u32 supported_flags;
02c04afea   Johan Hedberg   Bluetooth: Simpli...
5517
  	u8 *instance;
d3d5305bf   Marcel Holtmann   Bluetooth: Add si...
5518
5519
  
  	BT_DBG("%s", hdev->name);
089fa8c09   Arman Uguray   Bluetooth: Update...
5520
5521
5522
  	if (!lmp_le_capable(hdev))
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
  				       MGMT_STATUS_REJECTED);
d3d5305bf   Marcel Holtmann   Bluetooth: Add si...
5523
  	hci_dev_lock(hdev);
02c04afea   Johan Hedberg   Bluetooth: Simpli...
5524
  	rp_len = sizeof(*rp) + hdev->adv_instance_cnt;
d3d5305bf   Marcel Holtmann   Bluetooth: Add si...
5525
5526
5527
5528
5529
  	rp = kmalloc(rp_len, GFP_ATOMIC);
  	if (!rp) {
  		hci_dev_unlock(hdev);
  		return -ENOMEM;
  	}
089fa8c09   Arman Uguray   Bluetooth: Update...
5530
5531
5532
  	supported_flags = get_supported_adv_flags(hdev);
  
  	rp->supported_flags = cpu_to_le32(supported_flags);
dc5d82a9f   Marcel Holtmann   Bluetooth: Use HC...
5533
5534
  	rp->max_adv_data_len = HCI_MAX_AD_LENGTH;
  	rp->max_scan_rsp_len = HCI_MAX_AD_LENGTH;
d2609b345   Florian Grandel   Bluetooth: hci_co...
5535
  	rp->max_instances = HCI_MAX_ADV_INSTANCES;
02c04afea   Johan Hedberg   Bluetooth: Simpli...
5536
  	rp->num_instances = hdev->adv_instance_cnt;
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5537

02c04afea   Johan Hedberg   Bluetooth: Simpli...
5538
5539
5540
5541
  	instance = rp->instance;
  	list_for_each_entry(adv_instance, &hdev->adv_instances, list) {
  		*instance = adv_instance->instance;
  		instance++;
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5542
  	}
d3d5305bf   Marcel Holtmann   Bluetooth: Add si...
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
  
  	hci_dev_unlock(hdev);
  
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
  				MGMT_STATUS_SUCCESS, rp, rp_len);
  
  	kfree(rp);
  
  	return err;
  }
f61851f64   MichaƂ Narajowski   Bluetooth: Fix ap...
5553
5554
5555
5556
5557
5558
5559
5560
5561
  static u8 calculate_name_len(struct hci_dev *hdev)
  {
  	u8 buf[HCI_MAX_SHORT_NAME_LENGTH + 3];
  
  	return append_local_name(hdev, buf, 0);
  }
  
  static u8 tlv_data_max_len(struct hci_dev *hdev, u32 adv_flags,
  			   bool is_adv_data)
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5562
  {
4117ed70a   Arman Uguray   Bluetooth: Add su...
5563
  	u8 max_len = HCI_MAX_AD_LENGTH;
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5564

31a3248dd   Marcel Holtmann   Bluetooth: Simpli...
5565
5566
5567
  	if (is_adv_data) {
  		if (adv_flags & (MGMT_ADV_FLAG_DISCOV |
  				 MGMT_ADV_FLAG_LIMITED_DISCOV |
2bb36870e   Szymon Janc   Bluetooth: Unify ...
5568
  				 MGMT_ADV_FLAG_MANAGED_FLAGS))
31a3248dd   Marcel Holtmann   Bluetooth: Simpli...
5569
  			max_len -= 3;
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5570

2bb36870e   Szymon Janc   Bluetooth: Unify ...
5571
  		if (adv_flags & MGMT_ADV_FLAG_TX_POWER)
31a3248dd   Marcel Holtmann   Bluetooth: Simpli...
5572
  			max_len -= 3;
7c295c480   MichaƂ Narajowski   Bluetooth: Add su...
5573
  	} else {
7c295c480   MichaƂ Narajowski   Bluetooth: Add su...
5574
  		if (adv_flags & MGMT_ADV_FLAG_LOCAL_NAME)
f61851f64   MichaƂ Narajowski   Bluetooth: Fix ap...
5575
  			max_len -= calculate_name_len(hdev);
c4960ecf2   MichaƂ Narajowski   Bluetooth: Add su...
5576

2bb36870e   Szymon Janc   Bluetooth: Unify ...
5577
  		if (adv_flags & (MGMT_ADV_FLAG_APPEARANCE))
c4960ecf2   MichaƂ Narajowski   Bluetooth: Add su...
5578
  			max_len -= 4;
5507e3581   Arman Uguray   Bluetooth: Suppor...
5579
  	}
2bb36870e   Szymon Janc   Bluetooth: Unify ...
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
  	return max_len;
  }
  
  static bool flags_managed(u32 adv_flags)
  {
  	return adv_flags & (MGMT_ADV_FLAG_DISCOV |
  			    MGMT_ADV_FLAG_LIMITED_DISCOV |
  			    MGMT_ADV_FLAG_MANAGED_FLAGS);
  }
  
  static bool tx_power_managed(u32 adv_flags)
  {
  	return adv_flags & MGMT_ADV_FLAG_TX_POWER;
  }
  
  static bool name_managed(u32 adv_flags)
  {
  	return adv_flags & MGMT_ADV_FLAG_LOCAL_NAME;
  }
  
  static bool appearance_managed(u32 adv_flags)
  {
  	return adv_flags & MGMT_ADV_FLAG_APPEARANCE;
  }
f61851f64   MichaƂ Narajowski   Bluetooth: Fix ap...
5604
5605
  static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
  			      u8 len, bool is_adv_data)
2bb36870e   Szymon Janc   Bluetooth: Unify ...
5606
5607
5608
  {
  	int i, cur_len;
  	u8 max_len;
f61851f64   MichaƂ Narajowski   Bluetooth: Fix ap...
5609
  	max_len = tlv_data_max_len(hdev, adv_flags, is_adv_data);
2bb36870e   Szymon Janc   Bluetooth: Unify ...
5610

4117ed70a   Arman Uguray   Bluetooth: Add su...
5611
  	if (len > max_len)
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5612
  		return false;
4117ed70a   Arman Uguray   Bluetooth: Add su...
5613
5614
5615
  	/* Make sure that the data is correctly formatted. */
  	for (i = 0, cur_len = 0; i < len; i += (cur_len + 1)) {
  		cur_len = data[i];
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5616

9c9db78dc   Szymon Janc   Bluetooth: Fix ad...
5617
5618
  		if (data[i + 1] == EIR_FLAGS &&
  		    (!is_adv_data || flags_managed(adv_flags)))
2bb36870e   Szymon Janc   Bluetooth: Unify ...
5619
5620
5621
5622
5623
5624
5625
5626
5627
  			return false;
  
  		if (data[i + 1] == EIR_TX_POWER && tx_power_managed(adv_flags))
  			return false;
  
  		if (data[i + 1] == EIR_NAME_COMPLETE && name_managed(adv_flags))
  			return false;
  
  		if (data[i + 1] == EIR_NAME_SHORT && name_managed(adv_flags))
b44133ff0   Arman Uguray   Bluetooth: Suppor...
5628
  			return false;
2bb36870e   Szymon Janc   Bluetooth: Unify ...
5629
5630
  		if (data[i + 1] == EIR_APPEARANCE &&
  		    appearance_managed(adv_flags))
5507e3581   Arman Uguray   Bluetooth: Suppor...
5631
  			return false;
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5632
5633
5634
  		/* If the current field length would exceed the total data
  		 * length, then it's invalid.
  		 */
4117ed70a   Arman Uguray   Bluetooth: Add su...
5635
  		if (i + cur_len >= len)
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5636
5637
5638
5639
5640
  			return false;
  	}
  
  	return true;
  }
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5641
5642
5643
5644
  static void add_advertising_complete(struct hci_dev *hdev, u8 status,
  				     u16 opcode)
  {
  	struct mgmt_pending_cmd *cmd;
fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
5645
  	struct mgmt_cp_add_advertising *cp;
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5646
  	struct mgmt_rp_add_advertising rp;
fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
5647
5648
  	struct adv_info *adv_instance, *n;
  	u8 instance;
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5649
5650
5651
5652
5653
5654
  
  	BT_DBG("status %d", status);
  
  	hci_dev_lock(hdev);
  
  	cmd = pending_find(MGMT_OP_ADD_ADVERTISING, hdev);
fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
  	list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances, list) {
  		if (!adv_instance->pending)
  			continue;
  
  		if (!status) {
  			adv_instance->pending = false;
  			continue;
  		}
  
  		instance = adv_instance->instance;
  
  		if (hdev->cur_adv_instance == instance)
  			cancel_adv_timeout(hdev);
  
  		hci_remove_adv_instance(hdev, instance);
f22525700   Johan Hedberg   Bluetooth: Move a...
5670
  		mgmt_advertising_removed(cmd ? cmd->sk : NULL, hdev, instance);
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5671
5672
5673
5674
  	}
  
  	if (!cmd)
  		goto unlock;
fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
5675
5676
  	cp = cmd->param;
  	rp.instance = cp->instance;
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
  
  	if (status)
  		mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
  				mgmt_status(status));
  	else
  		mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
  				  mgmt_status(status), &rp, sizeof(rp));
  
  	mgmt_pending_remove(cmd);
  
  unlock:
  	hci_dev_unlock(hdev);
  }
  
  static int add_advertising(struct sock *sk, struct hci_dev *hdev,
  			   void *data, u16 data_len)
  {
  	struct mgmt_cp_add_advertising *cp = data;
  	struct mgmt_rp_add_advertising rp;
  	u32 flags;
089fa8c09   Arman Uguray   Bluetooth: Update...
5697
  	u32 supported_flags;
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5698
  	u8 status;
fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
5699
5700
5701
5702
  	u16 timeout, duration;
  	unsigned int prev_instance_cnt = hdev->adv_instance_cnt;
  	u8 schedule_instance = 0;
  	struct adv_info *next_instance;
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
  	int err;
  	struct mgmt_pending_cmd *cmd;
  	struct hci_request req;
  
  	BT_DBG("%s", hdev->name);
  
  	status = mgmt_le_support(hdev);
  	if (status)
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
  				       status);
ceff86af5   Marcel Holtmann   Bluetooth: Add in...
5713
5714
  	if (cp->instance < 1 || cp->instance > HCI_MAX_ADV_INSTANCES)
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6a0e78072   Johan Hedberg   Bluetooth: Fix po...
5715
5716
5717
5718
  				       MGMT_STATUS_INVALID_PARAMS);
  
  	if (data_len != sizeof(*cp) + cp->adv_data_len + cp->scan_rsp_len)
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
ceff86af5   Marcel Holtmann   Bluetooth: Add in...
5719
  				       MGMT_STATUS_INVALID_PARAMS);
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5720
  	flags = __le32_to_cpu(cp->flags);
912098a63   Arman Uguray   Bluetooth: Add su...
5721
  	timeout = __le16_to_cpu(cp->timeout);
fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
5722
  	duration = __le16_to_cpu(cp->duration);
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5723

fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
5724
5725
  	/* The current implementation only supports a subset of the specified
  	 * flags.
089fa8c09   Arman Uguray   Bluetooth: Update...
5726
5727
  	 */
  	supported_flags = get_supported_adv_flags(hdev);
fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
5728
  	if (flags & ~supported_flags)
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5729
5730
5731
5732
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
  				       MGMT_STATUS_INVALID_PARAMS);
  
  	hci_dev_lock(hdev);
912098a63   Arman Uguray   Bluetooth: Add su...
5733
5734
5735
5736
5737
  	if (timeout && !hdev_is_powered(hdev)) {
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
  				      MGMT_STATUS_REJECTED);
  		goto unlock;
  	}
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5738
  	if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
da929335f   Arman Uguray   Bluetooth: Implem...
5739
  	    pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5740
5741
5742
5743
5744
  	    pending_find(MGMT_OP_SET_LE, hdev)) {
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
  				      MGMT_STATUS_BUSY);
  		goto unlock;
  	}
f61851f64   MichaƂ Narajowski   Bluetooth: Fix ap...
5745
5746
  	if (!tlv_data_is_valid(hdev, flags, cp->data, cp->adv_data_len, true) ||
  	    !tlv_data_is_valid(hdev, flags, cp->data + cp->adv_data_len,
b44133ff0   Arman Uguray   Bluetooth: Suppor...
5747
  			       cp->scan_rsp_len, false)) {
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5748
5749
5750
5751
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
  				      MGMT_STATUS_INVALID_PARAMS);
  		goto unlock;
  	}
fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
  	err = hci_add_adv_instance(hdev, cp->instance, flags,
  				   cp->adv_data_len, cp->data,
  				   cp->scan_rsp_len,
  				   cp->data + cp->adv_data_len,
  				   timeout, duration);
  	if (err < 0) {
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
  				      MGMT_STATUS_FAILED);
  		goto unlock;
  	}
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5762

fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
5763
5764
5765
5766
  	/* Only trigger an advertising added event if a new instance was
  	 * actually added.
  	 */
  	if (hdev->adv_instance_cnt > prev_instance_cnt)
f22525700   Johan Hedberg   Bluetooth: Move a...
5767
  		mgmt_advertising_added(sk, hdev, cp->instance);
912098a63   Arman Uguray   Bluetooth: Add su...
5768

fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
5769
5770
5771
5772
5773
5774
5775
  	if (hdev->cur_adv_instance == cp->instance) {
  		/* If the currently advertised instance is being changed then
  		 * cancel the current advertising and schedule the next
  		 * instance. If there is only one instance then the overridden
  		 * advertising data will be visible right away.
  		 */
  		cancel_adv_timeout(hdev);
912098a63   Arman Uguray   Bluetooth: Add su...
5776

fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
5777
5778
5779
5780
5781
5782
5783
5784
5785
  		next_instance = hci_get_next_instance(hdev, cp->instance);
  		if (next_instance)
  			schedule_instance = next_instance->instance;
  	} else if (!hdev->adv_instance_timeout) {
  		/* Immediately advertise the new instance if no other
  		 * instance is currently being advertised.
  		 */
  		schedule_instance = cp->instance;
  	}
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5786

fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
5787
5788
5789
  	/* If the HCI_ADVERTISING flag is set or the device isn't powered or
  	 * there is no instance to be advertised then we have no HCI
  	 * communication to make. Simply return.
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5790
5791
  	 */
  	if (!hdev_is_powered(hdev) ||
fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
5792
5793
5794
  	    hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
  	    !schedule_instance) {
  		rp.instance = cp->instance;
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
  					MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
  		goto unlock;
  	}
  
  	/* We're good to go, update advertising data, parameters, and start
  	 * advertising.
  	 */
  	cmd = mgmt_pending_add(sk, MGMT_OP_ADD_ADVERTISING, hdev, data,
  			       data_len);
  	if (!cmd) {
  		err = -ENOMEM;
  		goto unlock;
  	}
  
  	hci_req_init(&req, hdev);
f22525700   Johan Hedberg   Bluetooth: Move a...
5811
  	err = __hci_req_schedule_adv_instance(&req, schedule_instance, true);
fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
5812
5813
5814
  
  	if (!err)
  		err = hci_req_run(&req, add_advertising_complete);
24b4f38fc   Arman Uguray   Bluetooth: Implem...
5815

24b4f38fc   Arman Uguray   Bluetooth: Implem...
5816
5817
5818
5819
5820
5821
5822
5823
  	if (err < 0)
  		mgmt_pending_remove(cmd);
  
  unlock:
  	hci_dev_unlock(hdev);
  
  	return err;
  }
da929335f   Arman Uguray   Bluetooth: Implem...
5824
5825
5826
5827
  static void remove_advertising_complete(struct hci_dev *hdev, u8 status,
  					u16 opcode)
  {
  	struct mgmt_pending_cmd *cmd;
01948331a   Florian Grandel   Bluetooth: mgmt: ...
5828
  	struct mgmt_cp_remove_advertising *cp;
da929335f   Arman Uguray   Bluetooth: Implem...
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
  	struct mgmt_rp_remove_advertising rp;
  
  	BT_DBG("status %d", status);
  
  	hci_dev_lock(hdev);
  
  	/* A failure status here only means that we failed to disable
  	 * advertising. Otherwise, the advertising instance has been removed,
  	 * so report success.
  	 */
  	cmd = pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev);
  	if (!cmd)
  		goto unlock;
01948331a   Florian Grandel   Bluetooth: mgmt: ...
5842
5843
  	cp = cmd->param;
  	rp.instance = cp->instance;
da929335f   Arman Uguray   Bluetooth: Implem...
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
  
  	mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, MGMT_STATUS_SUCCESS,
  			  &rp, sizeof(rp));
  	mgmt_pending_remove(cmd);
  
  unlock:
  	hci_dev_unlock(hdev);
  }
  
  static int remove_advertising(struct sock *sk, struct hci_dev *hdev,
  			      void *data, u16 data_len)
  {
  	struct mgmt_cp_remove_advertising *cp = data;
  	struct mgmt_rp_remove_advertising rp;
da929335f   Arman Uguray   Bluetooth: Implem...
5858
5859
  	struct mgmt_pending_cmd *cmd;
  	struct hci_request req;
952497b15   Johan Hedberg   Bluetooth: Fix wa...
5860
  	int err;
da929335f   Arman Uguray   Bluetooth: Implem...
5861
5862
  
  	BT_DBG("%s", hdev->name);
da929335f   Arman Uguray   Bluetooth: Implem...
5863
  	hci_dev_lock(hdev);
952497b15   Johan Hedberg   Bluetooth: Fix wa...
5864
  	if (cp->instance && !hci_find_adv_instance(hdev, cp->instance)) {
01948331a   Florian Grandel   Bluetooth: mgmt: ...
5865
5866
5867
5868
5869
  		err = mgmt_cmd_status(sk, hdev->id,
  				      MGMT_OP_REMOVE_ADVERTISING,
  				      MGMT_STATUS_INVALID_PARAMS);
  		goto unlock;
  	}
da929335f   Arman Uguray   Bluetooth: Implem...
5870
5871
5872
5873
5874
5875
5876
  	if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
  	    pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
  	    pending_find(MGMT_OP_SET_LE, hdev)) {
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
  				      MGMT_STATUS_BUSY);
  		goto unlock;
  	}
17fd08ffb   Johan Hedberg   Bluetooth: Remove...
5877
  	if (list_empty(&hdev->adv_instances)) {
da929335f   Arman Uguray   Bluetooth: Implem...
5878
5879
5880
5881
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
  				      MGMT_STATUS_INVALID_PARAMS);
  		goto unlock;
  	}
01948331a   Florian Grandel   Bluetooth: mgmt: ...
5882
  	hci_req_init(&req, hdev);
da929335f   Arman Uguray   Bluetooth: Implem...
5883

37d3a1fab   Johan Hedberg   Bluetooth: mgmt: ...
5884
  	hci_req_clear_adv_instance(hdev, sk, &req, cp->instance, true);
da929335f   Arman Uguray   Bluetooth: Implem...
5885

01948331a   Florian Grandel   Bluetooth: mgmt: ...
5886
  	if (list_empty(&hdev->adv_instances))
f22525700   Johan Hedberg   Bluetooth: Move a...
5887
  		__hci_req_disable_advertising(&req);
da929335f   Arman Uguray   Bluetooth: Implem...
5888

01948331a   Florian Grandel   Bluetooth: mgmt: ...
5889
5890
5891
  	/* If no HCI commands have been collected so far or the HCI_ADVERTISING
  	 * flag is set or the device isn't powered then we have no HCI
  	 * communication to make. Simply return.
da929335f   Arman Uguray   Bluetooth: Implem...
5892
  	 */
01948331a   Florian Grandel   Bluetooth: mgmt: ...
5893
5894
  	if (skb_queue_empty(&req.cmd_q) ||
  	    !hdev_is_powered(hdev) ||
da929335f   Arman Uguray   Bluetooth: Implem...
5895
  	    hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
01948331a   Florian Grandel   Bluetooth: mgmt: ...
5896
  		rp.instance = cp->instance;
da929335f   Arman Uguray   Bluetooth: Implem...
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
  		err = mgmt_cmd_complete(sk, hdev->id,
  					MGMT_OP_REMOVE_ADVERTISING,
  					MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
  		goto unlock;
  	}
  
  	cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_ADVERTISING, hdev, data,
  			       data_len);
  	if (!cmd) {
  		err = -ENOMEM;
  		goto unlock;
  	}
da929335f   Arman Uguray   Bluetooth: Implem...
5909
5910
5911
5912
5913
5914
5915
5916
5917
  	err = hci_req_run(&req, remove_advertising_complete);
  	if (err < 0)
  		mgmt_pending_remove(cmd);
  
  unlock:
  	hci_dev_unlock(hdev);
  
  	return err;
  }
40b25fe5d   Marcel Holtmann   Bluetooth: Add su...
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
  static int get_adv_size_info(struct sock *sk, struct hci_dev *hdev,
  			     void *data, u16 data_len)
  {
  	struct mgmt_cp_get_adv_size_info *cp = data;
  	struct mgmt_rp_get_adv_size_info rp;
  	u32 flags, supported_flags;
  	int err;
  
  	BT_DBG("%s", hdev->name);
  
  	if (!lmp_le_capable(hdev))
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_ADV_SIZE_INFO,
  				       MGMT_STATUS_REJECTED);
  
  	if (cp->instance < 1 || cp->instance > HCI_MAX_ADV_INSTANCES)
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_ADV_SIZE_INFO,
  				       MGMT_STATUS_INVALID_PARAMS);
  
  	flags = __le32_to_cpu(cp->flags);
  
  	/* The current implementation only supports a subset of the specified
  	 * flags.
  	 */
  	supported_flags = get_supported_adv_flags(hdev);
  	if (flags & ~supported_flags)
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_ADV_SIZE_INFO,
  				       MGMT_STATUS_INVALID_PARAMS);
  
  	rp.instance = cp->instance;
  	rp.flags = cp->flags;
f61851f64   MichaƂ Narajowski   Bluetooth: Fix ap...
5948
5949
  	rp.max_adv_data_len = tlv_data_max_len(hdev, flags, true);
  	rp.max_scan_rsp_len = tlv_data_max_len(hdev, flags, false);
40b25fe5d   Marcel Holtmann   Bluetooth: Add su...
5950
5951
5952
5953
5954
5955
  
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_ADV_SIZE_INFO,
  				MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
  
  	return err;
  }
6d785aa34   Johan Hedberg   Bluetooth: Conver...
5956
  static const struct hci_mgmt_handler mgmt_handlers[] = {
0f4e68cf6   Johan Hedberg   Bluetooth: mgmt: ...
5957
  	{ NULL }, /* 0x0000 (no command) */
b9a245fb1   Johan Hedberg   Bluetooth: Move a...
5958
  	{ read_version,            MGMT_READ_VERSION_SIZE,
c91041dc4   Marcel Holtmann   Bluetooth: Add su...
5959
5960
  						HCI_MGMT_NO_HDEV |
  						HCI_MGMT_UNTRUSTED },
b9a245fb1   Johan Hedberg   Bluetooth: Move a...
5961
  	{ read_commands,           MGMT_READ_COMMANDS_SIZE,
c91041dc4   Marcel Holtmann   Bluetooth: Add su...
5962
5963
  						HCI_MGMT_NO_HDEV |
  						HCI_MGMT_UNTRUSTED },
b9a245fb1   Johan Hedberg   Bluetooth: Move a...
5964
  	{ read_index_list,         MGMT_READ_INDEX_LIST_SIZE,
c91041dc4   Marcel Holtmann   Bluetooth: Add su...
5965
5966
5967
5968
  						HCI_MGMT_NO_HDEV |
  						HCI_MGMT_UNTRUSTED },
  	{ read_controller_info,    MGMT_READ_INFO_SIZE,
  						HCI_MGMT_UNTRUSTED },
7aea8616c   Marcel Holtmann   Bluetooth: Remove...
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
  	{ set_powered,             MGMT_SETTING_SIZE },
  	{ set_discoverable,        MGMT_SET_DISCOVERABLE_SIZE },
  	{ set_connectable,         MGMT_SETTING_SIZE },
  	{ set_fast_connectable,    MGMT_SETTING_SIZE },
  	{ set_bondable,            MGMT_SETTING_SIZE },
  	{ set_link_security,       MGMT_SETTING_SIZE },
  	{ set_ssp,                 MGMT_SETTING_SIZE },
  	{ set_hs,                  MGMT_SETTING_SIZE },
  	{ set_le,                  MGMT_SETTING_SIZE },
  	{ set_dev_class,           MGMT_SET_DEV_CLASS_SIZE },
  	{ set_local_name,          MGMT_SET_LOCAL_NAME_SIZE },
  	{ add_uuid,                MGMT_ADD_UUID_SIZE },
  	{ remove_uuid,             MGMT_REMOVE_UUID_SIZE },
b9a245fb1   Johan Hedberg   Bluetooth: Move a...
5982
5983
5984
5985
  	{ load_link_keys,          MGMT_LOAD_LINK_KEYS_SIZE,
  						HCI_MGMT_VAR_LEN },
  	{ load_long_term_keys,     MGMT_LOAD_LONG_TERM_KEYS_SIZE,
  						HCI_MGMT_VAR_LEN },
7aea8616c   Marcel Holtmann   Bluetooth: Remove...
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
  	{ disconnect,              MGMT_DISCONNECT_SIZE },
  	{ get_connections,         MGMT_GET_CONNECTIONS_SIZE },
  	{ pin_code_reply,          MGMT_PIN_CODE_REPLY_SIZE },
  	{ pin_code_neg_reply,      MGMT_PIN_CODE_NEG_REPLY_SIZE },
  	{ set_io_capability,       MGMT_SET_IO_CAPABILITY_SIZE },
  	{ pair_device,             MGMT_PAIR_DEVICE_SIZE },
  	{ cancel_pair_device,      MGMT_CANCEL_PAIR_DEVICE_SIZE },
  	{ unpair_device,           MGMT_UNPAIR_DEVICE_SIZE },
  	{ user_confirm_reply,      MGMT_USER_CONFIRM_REPLY_SIZE },
  	{ user_confirm_neg_reply,  MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
  	{ user_passkey_reply,      MGMT_USER_PASSKEY_REPLY_SIZE },
  	{ user_passkey_neg_reply,  MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
b9a245fb1   Johan Hedberg   Bluetooth: Move a...
5998
5999
6000
  	{ read_local_oob_data,     MGMT_READ_LOCAL_OOB_DATA_SIZE },
  	{ add_remote_oob_data,     MGMT_ADD_REMOTE_OOB_DATA_SIZE,
  						HCI_MGMT_VAR_LEN },
7aea8616c   Marcel Holtmann   Bluetooth: Remove...
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
  	{ remove_remote_oob_data,  MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
  	{ start_discovery,         MGMT_START_DISCOVERY_SIZE },
  	{ stop_discovery,          MGMT_STOP_DISCOVERY_SIZE },
  	{ confirm_name,            MGMT_CONFIRM_NAME_SIZE },
  	{ block_device,            MGMT_BLOCK_DEVICE_SIZE },
  	{ unblock_device,          MGMT_UNBLOCK_DEVICE_SIZE },
  	{ set_device_id,           MGMT_SET_DEVICE_ID_SIZE },
  	{ set_advertising,         MGMT_SETTING_SIZE },
  	{ set_bredr,               MGMT_SETTING_SIZE },
  	{ set_static_address,      MGMT_SET_STATIC_ADDRESS_SIZE },
  	{ set_scan_params,         MGMT_SET_SCAN_PARAMS_SIZE },
  	{ set_secure_conn,         MGMT_SETTING_SIZE },
  	{ set_debug_keys,          MGMT_SETTING_SIZE },
  	{ set_privacy,             MGMT_SET_PRIVACY_SIZE },
b9a245fb1   Johan Hedberg   Bluetooth: Move a...
6015
6016
  	{ load_irks,               MGMT_LOAD_IRKS_SIZE,
  						HCI_MGMT_VAR_LEN },
7aea8616c   Marcel Holtmann   Bluetooth: Remove...
6017
6018
6019
6020
  	{ get_conn_info,           MGMT_GET_CONN_INFO_SIZE },
  	{ get_clock_info,          MGMT_GET_CLOCK_INFO_SIZE },
  	{ add_device,              MGMT_ADD_DEVICE_SIZE },
  	{ remove_device,           MGMT_REMOVE_DEVICE_SIZE },
b9a245fb1   Johan Hedberg   Bluetooth: Move a...
6021
6022
6023
  	{ load_conn_param,         MGMT_LOAD_CONN_PARAM_SIZE,
  						HCI_MGMT_VAR_LEN },
  	{ read_unconf_index_list,  MGMT_READ_UNCONF_INDEX_LIST_SIZE,
c91041dc4   Marcel Holtmann   Bluetooth: Add su...
6024
6025
  						HCI_MGMT_NO_HDEV |
  						HCI_MGMT_UNTRUSTED },
b9a245fb1   Johan Hedberg   Bluetooth: Move a...
6026
  	{ read_config_info,        MGMT_READ_CONFIG_INFO_SIZE,
c91041dc4   Marcel Holtmann   Bluetooth: Add su...
6027
6028
  						HCI_MGMT_UNCONFIGURED |
  						HCI_MGMT_UNTRUSTED },
b9a245fb1   Johan Hedberg   Bluetooth: Move a...
6029
6030
6031
6032
6033
6034
  	{ set_external_config,     MGMT_SET_EXTERNAL_CONFIG_SIZE,
  						HCI_MGMT_UNCONFIGURED },
  	{ set_public_address,      MGMT_SET_PUBLIC_ADDRESS_SIZE,
  						HCI_MGMT_UNCONFIGURED },
  	{ start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
  						HCI_MGMT_VAR_LEN },
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
6035
  	{ read_local_oob_ext_data, MGMT_READ_LOCAL_OOB_EXT_DATA_SIZE },
96f1474af   Marcel Holtmann   Bluetooth: Add su...
6036
  	{ read_ext_index_list,     MGMT_READ_EXT_INDEX_LIST_SIZE,
c91041dc4   Marcel Holtmann   Bluetooth: Add su...
6037
6038
  						HCI_MGMT_NO_HDEV |
  						HCI_MGMT_UNTRUSTED },
d3d5305bf   Marcel Holtmann   Bluetooth: Add si...
6039
  	{ read_adv_features,       MGMT_READ_ADV_FEATURES_SIZE },
24b4f38fc   Arman Uguray   Bluetooth: Implem...
6040
6041
  	{ add_advertising,	   MGMT_ADD_ADVERTISING_SIZE,
  						HCI_MGMT_VAR_LEN },
da929335f   Arman Uguray   Bluetooth: Implem...
6042
  	{ remove_advertising,	   MGMT_REMOVE_ADVERTISING_SIZE },
40b25fe5d   Marcel Holtmann   Bluetooth: Add su...
6043
  	{ get_adv_size_info,       MGMT_GET_ADV_SIZE_INFO_SIZE },
78b781ca0   Johan Hedberg   Bluetooth: Add su...
6044
  	{ start_limited_discovery, MGMT_START_DISCOVERY_SIZE },
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
6045
6046
  	{ read_ext_controller_info,MGMT_READ_EXT_INFO_SIZE,
  						HCI_MGMT_UNTRUSTED },
c4960ecf2   MichaƂ Narajowski   Bluetooth: Add su...
6047
  	{ set_appearance,	   MGMT_SET_APPEARANCE_SIZE },
0f4e68cf6   Johan Hedberg   Bluetooth: mgmt: ...
6048
  };
bf6b56db0   Marcel Holtmann   Bluetooth: Make m...
6049
  void mgmt_index_added(struct hci_dev *hdev)
c71e97bfa   Johan Hedberg   Bluetooth: Add ma...
6050
  {
ced85549c   Marcel Holtmann   Bluetooth: Add su...
6051
  	struct mgmt_ev_ext_index ev;
bb4b2a9ae   Andrei Emeltchenko   Bluetooth: mgmt: ...
6052

0602a8adc   Marcel Holtmann   Bluetooth: Add su...
6053
6054
  	if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
  		return;
f92073388   Marcel Holtmann   Bluetooth: Use sp...
6055
  	switch (hdev->dev_type) {
ca8bee5dd   Marcel Holtmann   Bluetooth: Rename...
6056
  	case HCI_PRIMARY:
f92073388   Marcel Holtmann   Bluetooth: Use sp...
6057
6058
6059
  		if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
  			mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev,
  					 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
ced85549c   Marcel Holtmann   Bluetooth: Add su...
6060
  			ev.type = 0x01;
f92073388   Marcel Holtmann   Bluetooth: Use sp...
6061
6062
6063
  		} else {
  			mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
  					 HCI_MGMT_INDEX_EVENTS);
ced85549c   Marcel Holtmann   Bluetooth: Add su...
6064
  			ev.type = 0x00;
f92073388   Marcel Holtmann   Bluetooth: Use sp...
6065
6066
  		}
  		break;
ced85549c   Marcel Holtmann   Bluetooth: Add su...
6067
6068
6069
6070
6071
  	case HCI_AMP:
  		ev.type = 0x02;
  		break;
  	default:
  		return;
f92073388   Marcel Holtmann   Bluetooth: Use sp...
6072
  	}
ced85549c   Marcel Holtmann   Bluetooth: Add su...
6073
6074
6075
6076
6077
  
  	ev.bus = hdev->bus;
  
  	mgmt_index_event(MGMT_EV_EXT_INDEX_ADDED, hdev, &ev, sizeof(ev),
  			 HCI_MGMT_EXT_INDEX_EVENTS);
c71e97bfa   Johan Hedberg   Bluetooth: Add ma...
6078
  }
bf6b56db0   Marcel Holtmann   Bluetooth: Make m...
6079
  void mgmt_index_removed(struct hci_dev *hdev)
c71e97bfa   Johan Hedberg   Bluetooth: Add ma...
6080
  {
ced85549c   Marcel Holtmann   Bluetooth: Add su...
6081
  	struct mgmt_ev_ext_index ev;
5f1590327   Johan Hedberg   Bluetooth: mgmt: ...
6082
  	u8 status = MGMT_STATUS_INVALID_INDEX;
b24752fe6   Johan Hedberg   Bluetooth: Fix mg...
6083

0602a8adc   Marcel Holtmann   Bluetooth: Add su...
6084
6085
  	if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
  		return;
f92073388   Marcel Holtmann   Bluetooth: Use sp...
6086
  	switch (hdev->dev_type) {
ca8bee5dd   Marcel Holtmann   Bluetooth: Rename...
6087
  	case HCI_PRIMARY:
f92073388   Marcel Holtmann   Bluetooth: Use sp...
6088
  		mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
b24752fe6   Johan Hedberg   Bluetooth: Fix mg...
6089

f92073388   Marcel Holtmann   Bluetooth: Use sp...
6090
6091
6092
  		if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
  			mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev,
  					 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
ced85549c   Marcel Holtmann   Bluetooth: Add su...
6093
  			ev.type = 0x01;
f92073388   Marcel Holtmann   Bluetooth: Use sp...
6094
6095
6096
  		} else {
  			mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
  					 HCI_MGMT_INDEX_EVENTS);
ced85549c   Marcel Holtmann   Bluetooth: Add su...
6097
  			ev.type = 0x00;
f92073388   Marcel Holtmann   Bluetooth: Use sp...
6098
6099
  		}
  		break;
ced85549c   Marcel Holtmann   Bluetooth: Add su...
6100
6101
6102
6103
6104
  	case HCI_AMP:
  		ev.type = 0x02;
  		break;
  	default:
  		return;
f92073388   Marcel Holtmann   Bluetooth: Use sp...
6105
  	}
ced85549c   Marcel Holtmann   Bluetooth: Add su...
6106
6107
6108
6109
6110
  
  	ev.bus = hdev->bus;
  
  	mgmt_index_event(MGMT_EV_EXT_INDEX_REMOVED, hdev, &ev, sizeof(ev),
  			 HCI_MGMT_EXT_INDEX_EVENTS);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
6111
  }
6046dc3e0   Andre Guedes   Bluetooth: Auto c...
6112
  /* This function requires the caller holds hdev->lock */
af02dd446   Johan Hedberg   Bluetooth: Use re...
6113
  static void restart_le_actions(struct hci_dev *hdev)
6046dc3e0   Andre Guedes   Bluetooth: Auto c...
6114
6115
6116
6117
  {
  	struct hci_conn_params *p;
  
  	list_for_each_entry(p, &hdev->le_conn_params, list) {
d7347f3cc   Johan Hedberg   Bluetooth: Fix cl...
6118
6119
6120
6121
6122
6123
  		/* Needed for AUTO_OFF case where might not "really"
  		 * have been powered off.
  		 */
  		list_del_init(&p->action);
  
  		switch (p->auto_connect) {
4b9e7e751   Marcel Holtmann   Bluetooth: Fix is...
6124
  		case HCI_AUTO_CONN_DIRECT:
d7347f3cc   Johan Hedberg   Bluetooth: Fix cl...
6125
6126
6127
6128
6129
6130
6131
6132
  		case HCI_AUTO_CONN_ALWAYS:
  			list_add(&p->action, &hdev->pend_le_conns);
  			break;
  		case HCI_AUTO_CONN_REPORT:
  			list_add(&p->action, &hdev->pend_le_reports);
  			break;
  		default:
  			break;
c83ed19d2   Marcel Holtmann   Bluetooth: Ensure...
6133
  		}
6046dc3e0   Andre Guedes   Bluetooth: Auto c...
6134
6135
  	}
  }
2ff13894c   Johan Hedberg   Bluetooth: Perfor...
6136
  void mgmt_power_on(struct hci_dev *hdev, int err)
229ab39ca   Johan Hedberg   Bluetooth: Wait f...
6137
6138
  {
  	struct cmd_lookup match = { NULL, hdev };
2ff13894c   Johan Hedberg   Bluetooth: Perfor...
6139
  	BT_DBG("err %d", err);
229ab39ca   Johan Hedberg   Bluetooth: Wait f...
6140

2ff13894c   Johan Hedberg   Bluetooth: Perfor...
6141
6142
6143
  	hci_dev_lock(hdev);
  
  	if (!err) {
af02dd446   Johan Hedberg   Bluetooth: Use re...
6144
6145
  		restart_le_actions(hdev);
  		hci_update_background_scan(hdev);
162a3bac8   Marcel Holtmann   Bluetooth: Bind t...
6146
  	}
229ab39ca   Johan Hedberg   Bluetooth: Wait f...
6147
6148
6149
  	mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
  
  	new_settings(hdev, match.sk);
229ab39ca   Johan Hedberg   Bluetooth: Wait f...
6150
6151
  	if (match.sk)
  		sock_put(match.sk);
229ab39ca   Johan Hedberg   Bluetooth: Wait f...
6152

2ff13894c   Johan Hedberg   Bluetooth: Perfor...
6153
  	hci_dev_unlock(hdev);
70da62437   Johan Hedberg   Bluetooth: Move p...
6154
  }
562fcc246   Andrzej Kaczmarek   Bluetooth: mgmt: ...
6155

2ff13894c   Johan Hedberg   Bluetooth: Perfor...
6156
  void __mgmt_power_off(struct hci_dev *hdev)
70da62437   Johan Hedberg   Bluetooth: Move p...
6157
6158
  {
  	struct cmd_lookup match = { NULL, hdev };
9845904fd   Johan Hedberg   Bluetooth: Fix mg...
6159
  	u8 status, zero_cod[] = { 0, 0, 0 };
b24752fe6   Johan Hedberg   Bluetooth: Fix mg...
6160

229ab39ca   Johan Hedberg   Bluetooth: Wait f...
6161
  	mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
9845904fd   Johan Hedberg   Bluetooth: Fix mg...
6162
6163
6164
6165
6166
6167
6168
6169
  
  	/* If the power off is because of hdev unregistration let
  	 * use the appropriate INVALID_INDEX status. Otherwise use
  	 * NOT_POWERED. We cover both scenarios here since later in
  	 * mgmt_index_removed() any hci_conn callbacks will have already
  	 * been triggered, potentially causing misleading DISCONNECTED
  	 * status responses.
  	 */
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
6170
  	if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
9845904fd   Johan Hedberg   Bluetooth: Fix mg...
6171
6172
6173
6174
6175
  		status = MGMT_STATUS_INVALID_INDEX;
  	else
  		status = MGMT_STATUS_NOT_POWERED;
  
  	mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
229ab39ca   Johan Hedberg   Bluetooth: Wait f...
6176

321c6feed   Marcel Holtmann   Bluetooth: Add fr...
6177
  	if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) {
5504c3a31   Marcel Holtmann   Bluetooth: Use in...
6178
6179
6180
  		mgmt_limited_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
  				   zero_cod, sizeof(zero_cod),
  				   HCI_MGMT_DEV_CLASS_EVENTS, NULL);
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
6181
6182
  		ext_info_changed(hdev, NULL);
  	}
229ab39ca   Johan Hedberg   Bluetooth: Wait f...
6183

2ff13894c   Johan Hedberg   Bluetooth: Perfor...
6184
  	new_settings(hdev, match.sk);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
6185
6186
6187
  
  	if (match.sk)
  		sock_put(match.sk);
5add6af8f   Johan Hedberg   Bluetooth: Add su...
6188
  }
73f22f623   Johan Hedberg   Bluetooth: Add su...
6189

3eec705e4   Marcel Holtmann   Bluetooth: Make m...
6190
  void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
96570ffcc   Johan Hedberg   Bluetooth: Fix mg...
6191
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
6192
  	struct mgmt_pending_cmd *cmd;
96570ffcc   Johan Hedberg   Bluetooth: Fix mg...
6193
  	u8 status;
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
6194
  	cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
96570ffcc   Johan Hedberg   Bluetooth: Fix mg...
6195
  	if (!cmd)
3eec705e4   Marcel Holtmann   Bluetooth: Make m...
6196
  		return;
96570ffcc   Johan Hedberg   Bluetooth: Fix mg...
6197
6198
6199
6200
6201
  
  	if (err == -ERFKILL)
  		status = MGMT_STATUS_RFKILLED;
  	else
  		status = MGMT_STATUS_FAILED;
a69e8375a   Johan Hedberg   Bluetooth: Rename...
6202
  	mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
96570ffcc   Johan Hedberg   Bluetooth: Fix mg...
6203
6204
  
  	mgmt_pending_remove(cmd);
96570ffcc   Johan Hedberg   Bluetooth: Fix mg...
6205
  }
dc4a5ee2a   Marcel Holtmann   Bluetooth: Make m...
6206
6207
  void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
  		       bool persistent)
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
6208
  {
86742e1ec   Johan Hedberg   Bluetooth: Update...
6209
  	struct mgmt_ev_new_link_key ev;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
6210

a492cd52b   Vinicius Costa Gomes   Revert "Bluetooth...
6211
  	memset(&ev, 0, sizeof(ev));
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
6212

a492cd52b   Vinicius Costa Gomes   Revert "Bluetooth...
6213
  	ev.store_hint = persistent;
d753fdc40   Johan Hedberg   Bluetooth: mgmt: ...
6214
  	bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
591f47f31   Andre Guedes   Bluetooth: Move a...
6215
  	ev.key.addr.type = BDADDR_BREDR;
a492cd52b   Vinicius Costa Gomes   Revert "Bluetooth...
6216
  	ev.key.type = key->type;
9b3b44604   Andrei Emeltchenko   Bluetooth: Use de...
6217
  	memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
a492cd52b   Vinicius Costa Gomes   Revert "Bluetooth...
6218
  	ev.key.pin_len = key->pin_len;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
6219

dc4a5ee2a   Marcel Holtmann   Bluetooth: Make m...
6220
  	mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
6221
  }
f7520543a   Johan Hedberg   Bluetooth: Add co...
6222

d7b254502   Johan Hedberg   Bluetooth: Clearl...
6223
6224
  static u8 mgmt_ltk_type(struct smp_ltk *ltk)
  {
23fb8de37   Johan Hedberg   Bluetooth: Add mg...
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
  	switch (ltk->type) {
  	case SMP_LTK:
  	case SMP_LTK_SLAVE:
  		if (ltk->authenticated)
  			return MGMT_LTK_AUTHENTICATED;
  		return MGMT_LTK_UNAUTHENTICATED;
  	case SMP_LTK_P256:
  		if (ltk->authenticated)
  			return MGMT_LTK_P256_AUTH;
  		return MGMT_LTK_P256_UNAUTH;
  	case SMP_LTK_P256_DEBUG:
  		return MGMT_LTK_P256_DEBUG;
  	}
d7b254502   Johan Hedberg   Bluetooth: Clearl...
6238
6239
6240
  
  	return MGMT_LTK_UNAUTHENTICATED;
  }
53ac6ab61   Marcel Holtmann   Bluetooth: Make L...
6241
  void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
6242
6243
6244
6245
  {
  	struct mgmt_ev_new_long_term_key ev;
  
  	memset(&ev, 0, sizeof(ev));
5192d3011   Marcel Holtmann   Bluetooth: Add co...
6246
  	/* Devices using resolvable or non-resolvable random addresses
f72186d22   Florian Grandel   Bluetooth: mgmt: ...
6247
  	 * without providing an identity resolving key don't require
5192d3011   Marcel Holtmann   Bluetooth: Add co...
6248
6249
6250
6251
6252
6253
6254
6255
6256
  	 * to store long term keys. Their addresses will change the
  	 * next time around.
  	 *
  	 * Only when a remote device provides an identity address
  	 * make sure the long term key is stored. If the remote
  	 * identity is known, the long term keys are internally
  	 * mapped to the identity address. So allow static random
  	 * and public addresses here.
  	 */
ba74b666b   Johan Hedberg   Bluetooth: Move N...
6257
6258
6259
6260
  	if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
  	    (key->bdaddr.b[5] & 0xc0) != 0xc0)
  		ev.store_hint = 0x00;
  	else
53ac6ab61   Marcel Holtmann   Bluetooth: Make L...
6261
  		ev.store_hint = persistent;
ba74b666b   Johan Hedberg   Bluetooth: Move N...
6262

346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
6263
  	bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
57c1477c2   Andre Guedes   Bluetooth: Rename...
6264
  	ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
d7b254502   Johan Hedberg   Bluetooth: Clearl...
6265
  	ev.key.type = mgmt_ltk_type(key);
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
6266
6267
  	ev.key.enc_size = key->enc_size;
  	ev.key.ediv = key->ediv;
fe39c7b2d   Marcel Holtmann   Bluetooth: Use __...
6268
  	ev.key.rand = key->rand;
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
6269

2ceba5393   Johan Hedberg   Bluetooth: Remove...
6270
  	if (key->type == SMP_LTK)
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
6271
  		ev.key.master = 1;
1fc62c526   Johan Hedberg   Bluetooth: Fix ex...
6272
6273
6274
  	/* Make sure we copy only the significant bytes based on the
  	 * encryption key size, and set the rest of the value to zeroes.
  	 */
cb92205ba   Jakub Pawlowski   Bluetooth: fix MG...
6275
  	memcpy(ev.key.val, key->val, key->enc_size);
1fc62c526   Johan Hedberg   Bluetooth: Fix ex...
6276
6277
  	memset(ev.key.val + key->enc_size, 0,
  	       sizeof(ev.key.val) - key->enc_size);
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
6278

083368f7b   Marcel Holtmann   Bluetooth: Make m...
6279
  	mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
6280
  }
cad20c278   Johan Hedberg   Bluetooth: Don't ...
6281
  void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk, bool persistent)
95fbac8a8   Johan Hedberg   Bluetooth: Add su...
6282
6283
6284
6285
  {
  	struct mgmt_ev_new_irk ev;
  
  	memset(&ev, 0, sizeof(ev));
cad20c278   Johan Hedberg   Bluetooth: Don't ...
6286
  	ev.store_hint = persistent;
bab6d1e59   Marcel Holtmann   Bluetooth: Don't ...
6287

95fbac8a8   Johan Hedberg   Bluetooth: Add su...
6288
6289
6290
6291
6292
6293
6294
  	bacpy(&ev.rpa, &irk->rpa);
  	bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
  	ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
  	memcpy(ev.irk.val, irk->val, sizeof(irk->val));
  
  	mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
  }
53ac6ab61   Marcel Holtmann   Bluetooth: Make L...
6295
6296
  void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
  		   bool persistent)
7ee4ea369   Marcel Holtmann   Bluetooth: Add su...
6297
6298
6299
6300
6301
6302
  {
  	struct mgmt_ev_new_csrk ev;
  
  	memset(&ev, 0, sizeof(ev));
  
  	/* Devices using resolvable or non-resolvable random addresses
f72186d22   Florian Grandel   Bluetooth: mgmt: ...
6303
  	 * without providing an identity resolving key don't require
7ee4ea369   Marcel Holtmann   Bluetooth: Add su...
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
  	 * to store signature resolving keys. Their addresses will change
  	 * the next time around.
  	 *
  	 * Only when a remote device provides an identity address
  	 * make sure the signature resolving key is stored. So allow
  	 * static random and public addresses here.
  	 */
  	if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
  	    (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
  		ev.store_hint = 0x00;
  	else
53ac6ab61   Marcel Holtmann   Bluetooth: Make L...
6315
  		ev.store_hint = persistent;
7ee4ea369   Marcel Holtmann   Bluetooth: Add su...
6316
6317
6318
  
  	bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
  	ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
4cd3928a8   Johan Hedberg   Bluetooth: Update...
6319
  	ev.key.type = csrk->type;
7ee4ea369   Marcel Holtmann   Bluetooth: Add su...
6320
6321
6322
6323
  	memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
  
  	mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
  }
ffb5a827d   Andre Guedes   Bluetooth: Introd...
6324
  void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
f4869e2ad   Johan Hedberg   Bluetooth: Pass s...
6325
6326
  			 u8 bdaddr_type, u8 store_hint, u16 min_interval,
  			 u16 max_interval, u16 latency, u16 timeout)
ffb5a827d   Andre Guedes   Bluetooth: Introd...
6327
6328
  {
  	struct mgmt_ev_new_conn_param ev;
c103aea6f   Johan Hedberg   Bluetooth: Don't ...
6329
6330
  	if (!hci_is_identity_address(bdaddr, bdaddr_type))
  		return;
ffb5a827d   Andre Guedes   Bluetooth: Introd...
6331
6332
6333
  	memset(&ev, 0, sizeof(ev));
  	bacpy(&ev.addr.bdaddr, bdaddr);
  	ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
f4869e2ad   Johan Hedberg   Bluetooth: Pass s...
6334
  	ev.store_hint = store_hint;
ffb5a827d   Andre Guedes   Bluetooth: Introd...
6335
6336
6337
6338
6339
6340
6341
  	ev.min_interval = cpu_to_le16(min_interval);
  	ev.max_interval = cpu_to_le16(max_interval);
  	ev.latency = cpu_to_le16(latency);
  	ev.timeout = cpu_to_le16(timeout);
  
  	mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
  }
48ec92fa4   Alfonso Acosta   Bluetooth: Refact...
6342
6343
  void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
  			   u32 flags, u8 *name, u8 name_len)
f7520543a   Johan Hedberg   Bluetooth: Add co...
6344
  {
b644ba336   Johan Hedberg   Bluetooth: Update...
6345
6346
6347
  	char buf[512];
  	struct mgmt_ev_device_connected *ev = (void *) buf;
  	u16 eir_len = 0;
f7520543a   Johan Hedberg   Bluetooth: Add co...
6348

48ec92fa4   Alfonso Acosta   Bluetooth: Refact...
6349
6350
  	bacpy(&ev->addr.bdaddr, &conn->dst);
  	ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
f7520543a   Johan Hedberg   Bluetooth: Add co...
6351

c95f0ba76   Johan Hedberg   Bluetooth: mgmt: ...
6352
  	ev->flags = __cpu_to_le32(flags);
08c79b613   Johan Hedberg   Bluetooth: mgmt: ...
6353

fd45ada91   Alfonso Acosta   Bluetooth: Includ...
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
  	/* We must ensure that the EIR Data fields are ordered and
  	 * unique. Keep it simple for now and avoid the problem by not
  	 * adding any BR/EDR data to the LE adv.
  	 */
  	if (conn->le_adv_data_len > 0) {
  		memcpy(&ev->eir[eir_len],
  		       conn->le_adv_data, conn->le_adv_data_len);
  		eir_len = conn->le_adv_data_len;
  	} else {
  		if (name_len > 0)
  			eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
  						  name, name_len);
b644ba336   Johan Hedberg   Bluetooth: Update...
6366

ddbea5cff   Alfonso Acosta   Bluetooth: Remove...
6367
  		if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
fd45ada91   Alfonso Acosta   Bluetooth: Includ...
6368
6369
6370
6371
  			eir_len = eir_append_data(ev->eir, eir_len,
  						  EIR_CLASS_OF_DEV,
  						  conn->dev_class, 3);
  	}
b644ba336   Johan Hedberg   Bluetooth: Update...
6372

eb55ef07a   Marcel Holtmann   Bluetooth: Fix br...
6373
  	ev->eir_len = cpu_to_le16(eir_len);
b644ba336   Johan Hedberg   Bluetooth: Update...
6374

ecd90ae7f   Marcel Holtmann   Bluetooth: Make m...
6375
6376
  	mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
  		    sizeof(*ev) + eir_len, NULL);
f7520543a   Johan Hedberg   Bluetooth: Add co...
6377
  }
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
6378
  static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
8962ee74b   Johan Hedberg   Bluetooth: Add di...
6379
  {
8962ee74b   Johan Hedberg   Bluetooth: Add di...
6380
  	struct sock **sk = data;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
6381

f5818c224   Johan Hedberg   Bluetooth: Conver...
6382
  	cmd->cmd_complete(cmd, 0);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
6383
6384
6385
  
  	*sk = cmd->sk;
  	sock_hold(*sk);
a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
6386
  	mgmt_pending_remove(cmd);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
6387
  }
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
6388
  static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
6389
  {
b1078ad0b   Johan Hedberg   Bluetooth: Add De...
6390
  	struct hci_dev *hdev = data;
124f6e352   Johan Hedberg   Bluetooth: Update...
6391
  	struct mgmt_cp_unpair_device *cp = cmd->param;
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
6392

b1078ad0b   Johan Hedberg   Bluetooth: Add De...
6393
  	device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
d8b7b1e49   Johan Hedberg   Bluetooth: Conver...
6394
  	cmd->cmd_complete(cmd, 0);
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
6395
6396
  	mgmt_pending_remove(cmd);
  }
84c61d92b   Johan Hedberg   Bluetooth: Add co...
6397
6398
  bool mgmt_powering_down(struct hci_dev *hdev)
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
6399
  	struct mgmt_pending_cmd *cmd;
84c61d92b   Johan Hedberg   Bluetooth: Add co...
6400
  	struct mgmt_mode *cp;
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
6401
  	cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
84c61d92b   Johan Hedberg   Bluetooth: Add co...
6402
6403
6404
6405
6406
6407
6408
6409
6410
  	if (!cmd)
  		return false;
  
  	cp = cmd->param;
  	if (!cp->val)
  		return true;
  
  	return false;
  }
9b80ec5e8   Marcel Holtmann   Bluetooth: Make m...
6411
  void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
12d4a3b2c   Johan Hedberg   Bluetooth: Move c...
6412
6413
  			      u8 link_type, u8 addr_type, u8 reason,
  			      bool mgmt_connected)
f7520543a   Johan Hedberg   Bluetooth: Add co...
6414
  {
f0d6a0ea3   Mikel Astiz   Bluetooth: mgmt: ...
6415
  	struct mgmt_ev_device_disconnected ev;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
6416
  	struct sock *sk = NULL;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
6417

84c61d92b   Johan Hedberg   Bluetooth: Add co...
6418
6419
6420
6421
6422
6423
  	/* The connection is still in hci_conn_hash so test for 1
  	 * instead of 0 to know if this is the last one.
  	 */
  	if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
  		cancel_delayed_work(&hdev->power_off);
  		queue_work(hdev->req_workqueue, &hdev->power_off.work);
8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
6424
  	}
12d4a3b2c   Johan Hedberg   Bluetooth: Move c...
6425
6426
  	if (!mgmt_connected)
  		return;
57eb776fe   Andre Guedes   Bluetooth: Add an...
6427
6428
  	if (link_type != ACL_LINK && link_type != LE_LINK)
  		return;
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
6429
  	mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
f7520543a   Johan Hedberg   Bluetooth: Add co...
6430

f0d6a0ea3   Mikel Astiz   Bluetooth: mgmt: ...
6431
6432
6433
  	bacpy(&ev.addr.bdaddr, bdaddr);
  	ev.addr.type = link_to_bdaddr(link_type, addr_type);
  	ev.reason = reason;
f7520543a   Johan Hedberg   Bluetooth: Add co...
6434

9b80ec5e8   Marcel Holtmann   Bluetooth: Make m...
6435
  	mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
6436
6437
  
  	if (sk)
d97dcb660   Szymon Janc   Bluetooth: mgmt: ...
6438
  		sock_put(sk);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
6439

124f6e352   Johan Hedberg   Bluetooth: Update...
6440
  	mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
6441
  			     hdev);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
6442
  }
7892924c7   Marcel Holtmann   Bluetooth: Make m...
6443
6444
  void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
  			    u8 link_type, u8 addr_type, u8 status)
8962ee74b   Johan Hedberg   Bluetooth: Add di...
6445
  {
3655bba8f   Andre Guedes   Bluetooth: Check ...
6446
6447
  	u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
  	struct mgmt_cp_disconnect *cp;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
6448
  	struct mgmt_pending_cmd *cmd;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
6449

36a75f1b3   Jefferson Delfes   Bluetooth: Force ...
6450
6451
  	mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
  			     hdev);
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
6452
  	cmd = pending_find(MGMT_OP_DISCONNECT, hdev);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
6453
  	if (!cmd)
7892924c7   Marcel Holtmann   Bluetooth: Make m...
6454
  		return;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
6455

3655bba8f   Andre Guedes   Bluetooth: Check ...
6456
6457
6458
6459
6460
6461
6462
  	cp = cmd->param;
  
  	if (bacmp(bdaddr, &cp->addr.bdaddr))
  		return;
  
  	if (cp->addr.type != bdaddr_type)
  		return;
f5818c224   Johan Hedberg   Bluetooth: Conver...
6463
  	cmd->cmd_complete(cmd, mgmt_status(status));
a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
6464
  	mgmt_pending_remove(cmd);
f7520543a   Johan Hedberg   Bluetooth: Add co...
6465
  }
17d5c04cb   Johan Hedberg   Bluetooth: Add su...
6466

445608d07   Marcel Holtmann   Bluetooth: Make m...
6467
6468
  void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
  			 u8 addr_type, u8 status)
17d5c04cb   Johan Hedberg   Bluetooth: Add su...
6469
6470
  {
  	struct mgmt_ev_connect_failed ev;
c9910d0fb   Johan Hedberg   Bluetooth: Fix di...
6471

84c61d92b   Johan Hedberg   Bluetooth: Add co...
6472
6473
6474
6475
6476
6477
  	/* The connection is still in hci_conn_hash so test for 1
  	 * instead of 0 to know if this is the last one.
  	 */
  	if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
  		cancel_delayed_work(&hdev->power_off);
  		queue_work(hdev->req_workqueue, &hdev->power_off.work);
c9910d0fb   Johan Hedberg   Bluetooth: Fix di...
6478
  	}
17d5c04cb   Johan Hedberg   Bluetooth: Add su...
6479

4c659c397   Johan Hedberg   Bluetooth: Add ad...
6480
  	bacpy(&ev.addr.bdaddr, bdaddr);
57c1477c2   Andre Guedes   Bluetooth: Rename...
6481
  	ev.addr.type = link_to_bdaddr(link_type, addr_type);
ca69b7957   Johan Hedberg   Bluetooth: Create...
6482
  	ev.status = mgmt_status(status);
17d5c04cb   Johan Hedberg   Bluetooth: Add su...
6483

445608d07   Marcel Holtmann   Bluetooth: Make m...
6484
  	mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
17d5c04cb   Johan Hedberg   Bluetooth: Add su...
6485
  }
980e1a537   Johan Hedberg   Bluetooth: Add su...
6486

ce0e4a0d7   Marcel Holtmann   Bluetooth: Make m...
6487
  void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
980e1a537   Johan Hedberg   Bluetooth: Add su...
6488
6489
  {
  	struct mgmt_ev_pin_code_request ev;
d8457698e   Johan Hedberg   Bluetooth: mgmt: ...
6490
  	bacpy(&ev.addr.bdaddr, bdaddr);
591f47f31   Andre Guedes   Bluetooth: Move a...
6491
  	ev.addr.type = BDADDR_BREDR;
a770bb5ae   Waldemar Rymarkiewicz   Bluetooth: Add se...
6492
  	ev.secure = secure;
980e1a537   Johan Hedberg   Bluetooth: Add su...
6493

ce0e4a0d7   Marcel Holtmann   Bluetooth: Make m...
6494
  	mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
980e1a537   Johan Hedberg   Bluetooth: Add su...
6495
  }
e669cf803   Marcel Holtmann   Bluetooth: Make m...
6496
6497
  void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
  				  u8 status)
980e1a537   Johan Hedberg   Bluetooth: Add su...
6498
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
6499
  	struct mgmt_pending_cmd *cmd;
980e1a537   Johan Hedberg   Bluetooth: Add su...
6500

333ae95d0   Johan Hedberg   Bluetooth: Add ch...
6501
  	cmd = pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
980e1a537   Johan Hedberg   Bluetooth: Add su...
6502
  	if (!cmd)
e669cf803   Marcel Holtmann   Bluetooth: Make m...
6503
  		return;
980e1a537   Johan Hedberg   Bluetooth: Add su...
6504

7776d1d80   Johan Hedberg   Bluetooth: Use cm...
6505
  	cmd->cmd_complete(cmd, mgmt_status(status));
a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
6506
  	mgmt_pending_remove(cmd);
980e1a537   Johan Hedberg   Bluetooth: Add su...
6507
  }
3eb385289   Marcel Holtmann   Bluetooth: Make m...
6508
6509
  void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
  				      u8 status)
980e1a537   Johan Hedberg   Bluetooth: Add su...
6510
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
6511
  	struct mgmt_pending_cmd *cmd;
980e1a537   Johan Hedberg   Bluetooth: Add su...
6512

333ae95d0   Johan Hedberg   Bluetooth: Add ch...
6513
  	cmd = pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
980e1a537   Johan Hedberg   Bluetooth: Add su...
6514
  	if (!cmd)
3eb385289   Marcel Holtmann   Bluetooth: Make m...
6515
  		return;
980e1a537   Johan Hedberg   Bluetooth: Add su...
6516

7776d1d80   Johan Hedberg   Bluetooth: Use cm...
6517
  	cmd->cmd_complete(cmd, mgmt_status(status));
a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
6518
  	mgmt_pending_remove(cmd);
980e1a537   Johan Hedberg   Bluetooth: Add su...
6519
  }
a5c296832   Johan Hedberg   Bluetooth: Add ma...
6520

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
6521
  int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
39adbffe4   Johan Hedberg   Bluetooth: Fix pa...
6522
  			      u8 link_type, u8 addr_type, u32 value,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
6523
  			      u8 confirm_hint)
a5c296832   Johan Hedberg   Bluetooth: Add ma...
6524
6525
  {
  	struct mgmt_ev_user_confirm_request ev;
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
6526
  	BT_DBG("%s", hdev->name);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
6527

272d90df2   Johan Hedberg   Bluetooth: Add ad...
6528
  	bacpy(&ev.addr.bdaddr, bdaddr);
57c1477c2   Andre Guedes   Bluetooth: Rename...
6529
  	ev.addr.type = link_to_bdaddr(link_type, addr_type);
55bc1a378   Johan Hedberg   Bluetooth: Add co...
6530
  	ev.confirm_hint = confirm_hint;
39adbffe4   Johan Hedberg   Bluetooth: Fix pa...
6531
  	ev.value = cpu_to_le32(value);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
6532

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
6533
  	return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
6534
  			  NULL);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
6535
  }
272d90df2   Johan Hedberg   Bluetooth: Add ad...
6536
  int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
8ce8e2b56   Gustavo Padovan   Bluetooth: Fix co...
6537
  			      u8 link_type, u8 addr_type)
604086b73   Brian Gix   Bluetooth: Add Us...
6538
6539
6540
6541
  {
  	struct mgmt_ev_user_passkey_request ev;
  
  	BT_DBG("%s", hdev->name);
272d90df2   Johan Hedberg   Bluetooth: Add ad...
6542
  	bacpy(&ev.addr.bdaddr, bdaddr);
57c1477c2   Andre Guedes   Bluetooth: Rename...
6543
  	ev.addr.type = link_to_bdaddr(link_type, addr_type);
604086b73   Brian Gix   Bluetooth: Add Us...
6544
6545
  
  	return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
6546
  			  NULL);
604086b73   Brian Gix   Bluetooth: Add Us...
6547
  }
0df4c185e   Brian Gix   Bluetooth: User P...
6548
  static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
8ce8e2b56   Gustavo Padovan   Bluetooth: Fix co...
6549
6550
  				      u8 link_type, u8 addr_type, u8 status,
  				      u8 opcode)
a5c296832   Johan Hedberg   Bluetooth: Add ma...
6551
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
6552
  	struct mgmt_pending_cmd *cmd;
a5c296832   Johan Hedberg   Bluetooth: Add ma...
6553

333ae95d0   Johan Hedberg   Bluetooth: Add ch...
6554
  	cmd = pending_find(opcode, hdev);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
6555
6556
  	if (!cmd)
  		return -ENOENT;
7776d1d80   Johan Hedberg   Bluetooth: Use cm...
6557
  	cmd->cmd_complete(cmd, mgmt_status(status));
a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
6558
  	mgmt_pending_remove(cmd);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
6559

7776d1d80   Johan Hedberg   Bluetooth: Use cm...
6560
  	return 0;
a5c296832   Johan Hedberg   Bluetooth: Add ma...
6561
  }
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
6562
  int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
6563
  				     u8 link_type, u8 addr_type, u8 status)
a5c296832   Johan Hedberg   Bluetooth: Add ma...
6564
  {
272d90df2   Johan Hedberg   Bluetooth: Add ad...
6565
  	return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
6566
  					  status, MGMT_OP_USER_CONFIRM_REPLY);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
6567
  }
272d90df2   Johan Hedberg   Bluetooth: Add ad...
6568
  int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
6569
  					 u8 link_type, u8 addr_type, u8 status)
a5c296832   Johan Hedberg   Bluetooth: Add ma...
6570
  {
272d90df2   Johan Hedberg   Bluetooth: Add ad...
6571
  	return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
8fc9ced39   Gustavo Padovan   Bluetooth: Fix co...
6572
6573
  					  status,
  					  MGMT_OP_USER_CONFIRM_NEG_REPLY);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
6574
  }
2a6116920   Johan Hedberg   Bluetooth: Add mg...
6575

604086b73   Brian Gix   Bluetooth: Add Us...
6576
  int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
6577
  				     u8 link_type, u8 addr_type, u8 status)
604086b73   Brian Gix   Bluetooth: Add Us...
6578
  {
272d90df2   Johan Hedberg   Bluetooth: Add ad...
6579
  	return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
6580
  					  status, MGMT_OP_USER_PASSKEY_REPLY);
604086b73   Brian Gix   Bluetooth: Add Us...
6581
  }
272d90df2   Johan Hedberg   Bluetooth: Add ad...
6582
  int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
6583
  					 u8 link_type, u8 addr_type, u8 status)
604086b73   Brian Gix   Bluetooth: Add Us...
6584
  {
272d90df2   Johan Hedberg   Bluetooth: Add ad...
6585
  	return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
8fc9ced39   Gustavo Padovan   Bluetooth: Fix co...
6586
6587
  					  status,
  					  MGMT_OP_USER_PASSKEY_NEG_REPLY);
604086b73   Brian Gix   Bluetooth: Add Us...
6588
  }
92a25256f   Johan Hedberg   Bluetooth: mgmt: ...
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
  int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
  			     u8 link_type, u8 addr_type, u32 passkey,
  			     u8 entered)
  {
  	struct mgmt_ev_passkey_notify ev;
  
  	BT_DBG("%s", hdev->name);
  
  	bacpy(&ev.addr.bdaddr, bdaddr);
  	ev.addr.type = link_to_bdaddr(link_type, addr_type);
  	ev.passkey = __cpu_to_le32(passkey);
  	ev.entered = entered;
  
  	return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
  }
e1e930f59   Johan Hedberg   Bluetooth: Fix mg...
6604
  void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
2a6116920   Johan Hedberg   Bluetooth: Add mg...
6605
6606
  {
  	struct mgmt_ev_auth_failed ev;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
6607
  	struct mgmt_pending_cmd *cmd;
e1e930f59   Johan Hedberg   Bluetooth: Fix mg...
6608
  	u8 status = mgmt_status(hci_status);
2a6116920   Johan Hedberg   Bluetooth: Add mg...
6609

e1e930f59   Johan Hedberg   Bluetooth: Fix mg...
6610
6611
6612
  	bacpy(&ev.addr.bdaddr, &conn->dst);
  	ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
  	ev.status = status;
2a6116920   Johan Hedberg   Bluetooth: Add mg...
6613

e1e930f59   Johan Hedberg   Bluetooth: Fix mg...
6614
6615
6616
6617
  	cmd = find_pairing(conn);
  
  	mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
  		    cmd ? cmd->sk : NULL);
a511b35ba   Johan Hedberg   Bluetooth: Fix in...
6618
6619
6620
6621
  	if (cmd) {
  		cmd->cmd_complete(cmd, status);
  		mgmt_pending_remove(cmd);
  	}
2a6116920   Johan Hedberg   Bluetooth: Add mg...
6622
  }
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
6623

464996aea   Marcel Holtmann   Bluetooth: Make m...
6624
  void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
6625
6626
  {
  	struct cmd_lookup match = { NULL, hdev };
464996aea   Marcel Holtmann   Bluetooth: Make m...
6627
  	bool changed;
33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
6628
6629
6630
6631
  
  	if (status) {
  		u8 mgmt_err = mgmt_status(status);
  		mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
6632
  				     cmd_status_rsp, &mgmt_err);
464996aea   Marcel Holtmann   Bluetooth: Make m...
6633
  		return;
33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
6634
  	}
464996aea   Marcel Holtmann   Bluetooth: Make m...
6635
  	if (test_bit(HCI_AUTH, &hdev->flags))
238be788f   Marcel Holtmann   Bluetooth: Introd...
6636
  		changed = !hci_dev_test_and_set_flag(hdev, HCI_LINK_SECURITY);
464996aea   Marcel Holtmann   Bluetooth: Make m...
6637
  	else
a69d89272   Marcel Holtmann   Bluetooth: Introd...
6638
  		changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
47990ea09   Johan Hedberg   Bluetooth: mgmt: ...
6639

33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
6640
  	mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
6641
  			     &match);
33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
6642

47990ea09   Johan Hedberg   Bluetooth: mgmt: ...
6643
  	if (changed)
464996aea   Marcel Holtmann   Bluetooth: Make m...
6644
  		new_settings(hdev, match.sk);
33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
6645
6646
6647
  
  	if (match.sk)
  		sock_put(match.sk);
33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
6648
  }
890ea8988   Johan Hedberg   Bluetooth: Update...
6649
  static void clear_eir(struct hci_request *req)
cacaf52f5   Johan Hedberg   Bluetooth: mgmt: ...
6650
  {
890ea8988   Johan Hedberg   Bluetooth: Update...
6651
  	struct hci_dev *hdev = req->hdev;
cacaf52f5   Johan Hedberg   Bluetooth: mgmt: ...
6652
  	struct hci_cp_write_eir cp;
976eb20e6   Johan Hedberg   Bluetooth: Make u...
6653
  	if (!lmp_ext_inq_capable(hdev))
890ea8988   Johan Hedberg   Bluetooth: Update...
6654
  		return;
cacaf52f5   Johan Hedberg   Bluetooth: mgmt: ...
6655

c80da27e8   Johan Hedberg   Bluetooth: mgmt: ...
6656
  	memset(hdev->eir, 0, sizeof(hdev->eir));
cacaf52f5   Johan Hedberg   Bluetooth: mgmt: ...
6657
  	memset(&cp, 0, sizeof(cp));
890ea8988   Johan Hedberg   Bluetooth: Update...
6658
  	hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
cacaf52f5   Johan Hedberg   Bluetooth: mgmt: ...
6659
  }
3e248560d   Marcel Holtmann   Bluetooth: Make m...
6660
  void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
6661
6662
  {
  	struct cmd_lookup match = { NULL, hdev };
890ea8988   Johan Hedberg   Bluetooth: Update...
6663
  	struct hci_request req;
c0ecddc25   Johan Hedberg   Bluetooth: mgmt: ...
6664
  	bool changed = false;
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
6665
6666
6667
  
  	if (status) {
  		u8 mgmt_err = mgmt_status(status);
c0ecddc25   Johan Hedberg   Bluetooth: mgmt: ...
6668

a69d89272   Marcel Holtmann   Bluetooth: Introd...
6669
6670
  		if (enable && hci_dev_test_and_clear_flag(hdev,
  							  HCI_SSP_ENABLED)) {
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
6671
  			hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
3e248560d   Marcel Holtmann   Bluetooth: Make m...
6672
  			new_settings(hdev, NULL);
9ecb3e242   Marcel Holtmann   Bluetooth: Restri...
6673
  		}
c0ecddc25   Johan Hedberg   Bluetooth: mgmt: ...
6674

04124681f   Gustavo F. Padovan   Bluetooth: fix co...
6675
6676
  		mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
  				     &mgmt_err);
3e248560d   Marcel Holtmann   Bluetooth: Make m...
6677
  		return;
c0ecddc25   Johan Hedberg   Bluetooth: mgmt: ...
6678
6679
6680
  	}
  
  	if (enable) {
238be788f   Marcel Holtmann   Bluetooth: Introd...
6681
  		changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
c0ecddc25   Johan Hedberg   Bluetooth: mgmt: ...
6682
  	} else {
a69d89272   Marcel Holtmann   Bluetooth: Introd...
6683
  		changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
9ecb3e242   Marcel Holtmann   Bluetooth: Restri...
6684
  		if (!changed)
a69d89272   Marcel Holtmann   Bluetooth: Introd...
6685
6686
  			changed = hci_dev_test_and_clear_flag(hdev,
  							      HCI_HS_ENABLED);
9ecb3e242   Marcel Holtmann   Bluetooth: Restri...
6687
  		else
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
6688
  			hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
6689
6690
6691
  	}
  
  	mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
c0ecddc25   Johan Hedberg   Bluetooth: mgmt: ...
6692
  	if (changed)
3e248560d   Marcel Holtmann   Bluetooth: Make m...
6693
  		new_settings(hdev, match.sk);
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
6694

5fc6ebb10   Johan Hedberg   Bluetooth: mgmt: ...
6695
  	if (match.sk)
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
6696
  		sock_put(match.sk);
890ea8988   Johan Hedberg   Bluetooth: Update...
6697
  	hci_req_init(&req, hdev);
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
6698
6699
  	if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
  		if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
3769972ba   Johan Hedberg   Bluetooth: Add a ...
6700
6701
  			hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
  				    sizeof(enable), &enable);
b1a8917c9   Johan Hedberg   Bluetooth: Move E...
6702
  		__hci_req_update_eir(&req);
3769972ba   Johan Hedberg   Bluetooth: Add a ...
6703
  	} else {
890ea8988   Johan Hedberg   Bluetooth: Update...
6704
  		clear_eir(&req);
3769972ba   Johan Hedberg   Bluetooth: Add a ...
6705
  	}
890ea8988   Johan Hedberg   Bluetooth: Update...
6706
6707
  
  	hci_req_run(&req, NULL);
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
6708
  }
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
6709
  static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
6710
6711
  {
  	struct cmd_lookup *match = data;
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
6712
6713
6714
6715
  	if (match->sk == NULL) {
  		match->sk = cmd->sk;
  		sock_hold(match->sk);
  	}
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
6716
  }
4e1b0245f   Marcel Holtmann   Bluetooth: Make m...
6717
6718
  void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
  				    u8 status)
7f9a903c5   Marcel Holtmann   Bluetooth: Send m...
6719
  {
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
6720
  	struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
7f9a903c5   Marcel Holtmann   Bluetooth: Send m...
6721

92da60975   Johan Hedberg   Bluetooth: Fix UU...
6722
6723
6724
  	mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
  	mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
  	mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
6725

321c6feed   Marcel Holtmann   Bluetooth: Add fr...
6726
  	if (!status) {
5504c3a31   Marcel Holtmann   Bluetooth: Use in...
6727
6728
  		mgmt_limited_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class,
  				   3, HCI_MGMT_DEV_CLASS_EVENTS, NULL);
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
6729
6730
  		ext_info_changed(hdev, NULL);
  	}
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
6731
6732
6733
  
  	if (match.sk)
  		sock_put(match.sk);
7f9a903c5   Marcel Holtmann   Bluetooth: Send m...
6734
  }
7667da342   Marcel Holtmann   Bluetooth: Make m...
6735
  void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
6736
  {
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
6737
  	struct mgmt_cp_set_local_name ev;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
6738
  	struct mgmt_pending_cmd *cmd;
28cc7bde5   Johan Hedberg   Bluetooth: mgmt: ...
6739

139289713   Johan Hedberg   Bluetooth: Fix wa...
6740
  	if (status)
7667da342   Marcel Holtmann   Bluetooth: Make m...
6741
  		return;
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
6742
6743
6744
  
  	memset(&ev, 0, sizeof(ev));
  	memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
28cc7bde5   Johan Hedberg   Bluetooth: mgmt: ...
6745
  	memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
6746

333ae95d0   Johan Hedberg   Bluetooth: Add ch...
6747
  	cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
139289713   Johan Hedberg   Bluetooth: Fix wa...
6748
6749
  	if (!cmd) {
  		memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
28cc7bde5   Johan Hedberg   Bluetooth: mgmt: ...
6750

139289713   Johan Hedberg   Bluetooth: Fix wa...
6751
6752
6753
  		/* If this is a HCI command related to powering on the
  		 * HCI dev don't send any mgmt signals.
  		 */
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
6754
  		if (pending_find(MGMT_OP_SET_POWERED, hdev))
7667da342   Marcel Holtmann   Bluetooth: Make m...
6755
  			return;
890ea8988   Johan Hedberg   Bluetooth: Update...
6756
  	}
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
6757

5504c3a31   Marcel Holtmann   Bluetooth: Use in...
6758
6759
  	mgmt_limited_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
  			   HCI_MGMT_LOCAL_NAME_EVENTS, cmd ? cmd->sk : NULL);
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
6760
  	ext_info_changed(hdev, cmd ? cmd->sk : NULL);
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
6761
  }
c35938b2f   Szymon Janc   Bluetooth: Add re...
6762

799ce93df   Jakub Pawlowski   Bluetooth: Add lo...
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
  static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
  {
  	int i;
  
  	for (i = 0; i < uuid_count; i++) {
  		if (!memcmp(uuid, uuids[i], 16))
  			return true;
  	}
  
  	return false;
  }
b487b9ce9   Marcel Holtmann   Bluetooth: Add fr...
6774
6775
  static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
  {
799ce93df   Jakub Pawlowski   Bluetooth: Add lo...
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
  	u16 parsed = 0;
  
  	while (parsed < eir_len) {
  		u8 field_len = eir[0];
  		u8 uuid[16];
  		int i;
  
  		if (field_len == 0)
  			break;
  
  		if (eir_len - parsed < field_len + 1)
  			break;
  
  		switch (eir[1]) {
  		case EIR_UUID16_ALL:
  		case EIR_UUID16_SOME:
  			for (i = 0; i + 3 <= field_len; i += 2) {
189f6ad21   Johan Hedberg   Bluetooth: Remove...
6793
  				memcpy(uuid, bluetooth_base_uuid, 16);
799ce93df   Jakub Pawlowski   Bluetooth: Add lo...
6794
6795
6796
6797
6798
6799
6800
6801
6802
  				uuid[13] = eir[i + 3];
  				uuid[12] = eir[i + 2];
  				if (has_uuid(uuid, uuid_count, uuids))
  					return true;
  			}
  			break;
  		case EIR_UUID32_ALL:
  		case EIR_UUID32_SOME:
  			for (i = 0; i + 5 <= field_len; i += 4) {
189f6ad21   Johan Hedberg   Bluetooth: Remove...
6803
  				memcpy(uuid, bluetooth_base_uuid, 16);
799ce93df   Jakub Pawlowski   Bluetooth: Add lo...
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
  				uuid[15] = eir[i + 5];
  				uuid[14] = eir[i + 4];
  				uuid[13] = eir[i + 3];
  				uuid[12] = eir[i + 2];
  				if (has_uuid(uuid, uuid_count, uuids))
  					return true;
  			}
  			break;
  		case EIR_UUID128_ALL:
  		case EIR_UUID128_SOME:
  			for (i = 0; i + 17 <= field_len; i += 16) {
  				memcpy(uuid, eir + i + 2, 16);
  				if (has_uuid(uuid, uuid_count, uuids))
  					return true;
  			}
  			break;
  		}
  
  		parsed += field_len + 1;
  		eir += field_len + 1;
  	}
b487b9ce9   Marcel Holtmann   Bluetooth: Add fr...
6825
6826
  	return false;
  }
4b0e0cedd   Jakub Pawlowski   Bluetooth: Add re...
6827
6828
6829
  static void restart_le_scan(struct hci_dev *hdev)
  {
  	/* If controller is not scanning we are done. */
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
6830
  	if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
4b0e0cedd   Jakub Pawlowski   Bluetooth: Add re...
6831
6832
6833
6834
6835
6836
  		return;
  
  	if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
  		       hdev->discovery.scan_start +
  		       hdev->discovery.scan_duration))
  		return;
7c1fbed23   Johan Hedberg   Bluetooth: Move L...
6837
  	queue_delayed_work(hdev->req_workqueue, &hdev->le_scan_restart,
4b0e0cedd   Jakub Pawlowski   Bluetooth: Add re...
6838
6839
  			   DISCOV_LE_RESTART_DELAY);
  }
48f86b7f2   Jakub Pawlowski   Bluetooth: Move S...
6840
6841
  static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
  			    u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
e17acd40f   Johan Hedberg   Bluetooth: Add mg...
6842
  {
48f86b7f2   Jakub Pawlowski   Bluetooth: Move S...
6843
6844
6845
6846
6847
  	/* If a RSSI threshold has been specified, and
  	 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
  	 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
  	 * is set, let it through for further processing, as we might need to
  	 * restart the scan.
efb2513fd   Marcel Holtmann   Bluetooth: Fix di...
6848
6849
6850
  	 *
  	 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
  	 * the results are also dropped.
bda157a40   Marcel Holtmann   Bluetooth: Filter...
6851
6852
  	 */
  	if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
4b0e0cedd   Jakub Pawlowski   Bluetooth: Add re...
6853
6854
6855
  	    (rssi == HCI_RSSI_INVALID ||
  	    (rssi < hdev->discovery.rssi &&
  	     !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
48f86b7f2   Jakub Pawlowski   Bluetooth: Move S...
6856
  		return  false;
efb2513fd   Marcel Holtmann   Bluetooth: Fix di...
6857

2976cdeb2   Jakub Pawlowski   Bluetooth: Refact...
6858
6859
6860
  	if (hdev->discovery.uuid_count != 0) {
  		/* If a list of UUIDs is provided in filter, results with no
  		 * matching UUID should be dropped.
b487b9ce9   Marcel Holtmann   Bluetooth: Add fr...
6861
  		 */
2976cdeb2   Jakub Pawlowski   Bluetooth: Refact...
6862
6863
6864
6865
6866
6867
  		if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
  				   hdev->discovery.uuids) &&
  		    !eir_has_uuids(scan_rsp, scan_rsp_len,
  				   hdev->discovery.uuid_count,
  				   hdev->discovery.uuids))
  			return false;
b487b9ce9   Marcel Holtmann   Bluetooth: Add fr...
6868
  	}
5d2e9fadf   Johan Hedberg   Bluetooth: Add sc...
6869

2976cdeb2   Jakub Pawlowski   Bluetooth: Refact...
6870
6871
  	/* If duplicate filtering does not report RSSI changes, then restart
  	 * scanning to ensure updated result with updated RSSI values.
4b0e0cedd   Jakub Pawlowski   Bluetooth: Add re...
6872
  	 */
2976cdeb2   Jakub Pawlowski   Bluetooth: Refact...
6873
6874
6875
6876
6877
6878
6879
6880
  	if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
  		restart_le_scan(hdev);
  
  		/* Validate RSSI value against the RSSI threshold once more. */
  		if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
  		    rssi < hdev->discovery.rssi)
  			return false;
  	}
48f86b7f2   Jakub Pawlowski   Bluetooth: Move S...
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
  
  	return true;
  }
  
  void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
  		       u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
  		       u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
  {
  	char buf[512];
  	struct mgmt_ev_device_found *ev = (void *)buf;
  	size_t ev_size;
  
  	/* Don't send events for a non-kernel initiated discovery. With
  	 * LE one exception is if we have pend_le_reports > 0 in which
  	 * case we're doing passive scanning and want these events.
  	 */
  	if (!hci_discovery_active(hdev)) {
  		if (link_type == ACL_LINK)
  			return;
  		if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
  			return;
  	}
82f8b651a   Jakub Pawlowski   Bluetooth: fix se...
6903
  	if (hdev->discovery.result_filtering) {
48f86b7f2   Jakub Pawlowski   Bluetooth: Move S...
6904
6905
6906
6907
6908
  		/* We are using service discovery */
  		if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
  				     scan_rsp_len))
  			return;
  	}
78b781ca0   Johan Hedberg   Bluetooth: Add su...
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
  	if (hdev->discovery.limited) {
  		/* Check for limited discoverable bit */
  		if (dev_class) {
  			if (!(dev_class[1] & 0x20))
  				return;
  		} else {
  			u8 *flags = eir_get_data(eir, eir_len, EIR_FLAGS, NULL);
  			if (!flags || !(flags[0] & LE_AD_LIMITED))
  				return;
  		}
  	}
48f86b7f2   Jakub Pawlowski   Bluetooth: Move S...
6920
6921
6922
6923
  	/* Make sure that the buffer is big enough. The 5 extra bytes
  	 * are for the potential CoD field.
  	 */
  	if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
4b0e0cedd   Jakub Pawlowski   Bluetooth: Add re...
6924
  		return;
48f86b7f2   Jakub Pawlowski   Bluetooth: Move S...
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
  	memset(buf, 0, sizeof(buf));
  
  	/* In case of device discovery with BR/EDR devices (pre 1.2), the
  	 * RSSI value was reported as 0 when not available. This behavior
  	 * is kept when using device discovery. This is required for full
  	 * backwards compatibility with the API.
  	 *
  	 * However when using service discovery, the value 127 will be
  	 * returned when the RSSI is not available.
  	 */
  	if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
  	    link_type == ACL_LINK)
  		rssi = 0;
  
  	bacpy(&ev->addr.bdaddr, bdaddr);
  	ev->addr.type = link_to_bdaddr(link_type, addr_type);
  	ev->rssi = rssi;
  	ev->flags = cpu_to_le32(flags);
  
  	if (eir_len > 0)
  		/* Copy EIR or advertising data into event */
  		memcpy(ev->eir, eir, eir_len);
0d3b7f64c   Johan Hedberg   Bluetooth: Change...
6947
6948
  	if (dev_class && !eir_get_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
  				       NULL))
48f86b7f2   Jakub Pawlowski   Bluetooth: Move S...
6949
6950
6951
6952
6953
6954
  		eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
  					  dev_class, 3);
  
  	if (scan_rsp_len > 0)
  		/* Append scan response data to event */
  		memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
5d2e9fadf   Johan Hedberg   Bluetooth: Add sc...
6955
6956
  	ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
  	ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
f8523598e   Andre Guedes   Bluetooth: Check ...
6957

901801b9a   Marcel Holtmann   Bluetooth: Make m...
6958
  	mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
e17acd40f   Johan Hedberg   Bluetooth: Add mg...
6959
  }
a88a9652d   Johan Hedberg   Bluetooth: Add mg...
6960

9cf12aee8   Marcel Holtmann   Bluetooth: Make m...
6961
6962
  void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
  		      u8 addr_type, s8 rssi, u8 *name, u8 name_len)
a88a9652d   Johan Hedberg   Bluetooth: Add mg...
6963
  {
b644ba336   Johan Hedberg   Bluetooth: Update...
6964
6965
6966
  	struct mgmt_ev_device_found *ev;
  	char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
  	u16 eir_len;
a88a9652d   Johan Hedberg   Bluetooth: Add mg...
6967

b644ba336   Johan Hedberg   Bluetooth: Update...
6968
  	ev = (struct mgmt_ev_device_found *) buf;
a88a9652d   Johan Hedberg   Bluetooth: Add mg...
6969

b644ba336   Johan Hedberg   Bluetooth: Update...
6970
6971
6972
  	memset(buf, 0, sizeof(buf));
  
  	bacpy(&ev->addr.bdaddr, bdaddr);
57c1477c2   Andre Guedes   Bluetooth: Rename...
6973
  	ev->addr.type = link_to_bdaddr(link_type, addr_type);
b644ba336   Johan Hedberg   Bluetooth: Update...
6974
6975
6976
  	ev->rssi = rssi;
  
  	eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
6977
  				  name_len);
b644ba336   Johan Hedberg   Bluetooth: Update...
6978

eb55ef07a   Marcel Holtmann   Bluetooth: Fix br...
6979
  	ev->eir_len = cpu_to_le16(eir_len);
a88a9652d   Johan Hedberg   Bluetooth: Add mg...
6980

9cf12aee8   Marcel Holtmann   Bluetooth: Make m...
6981
  	mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
a88a9652d   Johan Hedberg   Bluetooth: Add mg...
6982
  }
314b2381a   Johan Hedberg   Bluetooth: Add di...
6983

2f1e063bc   Marcel Holtmann   Bluetooth: Make m...
6984
  void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
314b2381a   Johan Hedberg   Bluetooth: Add di...
6985
  {
f963e8e9d   Johan Hedberg   Bluetooth: mgmt: ...
6986
  	struct mgmt_ev_discovering ev;
164a6e789   Johan Hedberg   Bluetooth: Fix co...
6987

343fb1454   Andre Guedes   Bluetooth: Add BT...
6988
  	BT_DBG("%s discovering %u", hdev->name, discovering);
f963e8e9d   Johan Hedberg   Bluetooth: mgmt: ...
6989
6990
6991
  	memset(&ev, 0, sizeof(ev));
  	ev.type = hdev->discovery.type;
  	ev.discovering = discovering;
2f1e063bc   Marcel Holtmann   Bluetooth: Make m...
6992
  	mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
314b2381a   Johan Hedberg   Bluetooth: Add di...
6993
  }
5e762444b   Antti Julku   Bluetooth: Add mg...
6994

6d785aa34   Johan Hedberg   Bluetooth: Conver...
6995
6996
6997
6998
  static struct hci_mgmt_chan chan = {
  	.channel	= HCI_CHANNEL_CONTROL,
  	.handler_count	= ARRAY_SIZE(mgmt_handlers),
  	.handlers	= mgmt_handlers,
88b94ce92   Johan Hedberg   Bluetooth: Add hd...
6999
  	.hdev_init	= mgmt_init_hdev,
6d785aa34   Johan Hedberg   Bluetooth: Conver...
7000
7001
7002
7003
7004
7005
7006
7007
7008
7009
7010
  };
  
  int mgmt_init(void)
  {
  	return hci_mgmt_chan_register(&chan);
  }
  
  void mgmt_exit(void)
  {
  	hci_mgmt_chan_unregister(&chan);
  }