Blame view

net/bluetooth/mgmt.c 222 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"
17896406f   Alain Michaud   Bluetooth: implem...
38
  #include "mgmt_config.h"
e5e1e7fd4   Miao-chen Chou   Bluetooth: Add ha...
39
  #include "msft.h"
0381101fd   Johan Hedberg   Bluetooth: Add in...
40

2da9c55c5   Johan Hedberg   Bluetooth: mgmt: ...
41
  #define MGMT_VERSION	1
79bf11895   Marcel Holtmann   Bluetooth: Increm...
42
  #define MGMT_REVISION	18
02d981292   Johan Hedberg   Bluetooth: Add re...
43

e70bb2e89   Johan Hedberg   Bluetooth: Implem...
44
45
46
47
48
49
50
  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...
51
  	MGMT_OP_SET_BONDABLE,
e70bb2e89   Johan Hedberg   Bluetooth: Implem...
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
80
81
  	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...
82
  	MGMT_OP_SET_DEVICE_ID,
4375f1037   Johan Hedberg   Bluetooth: Add ne...
83
  	MGMT_OP_SET_ADVERTISING,
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
84
  	MGMT_OP_SET_BREDR,
d13eafce2   Marcel Holtmann   Bluetooth: Add ma...
85
  	MGMT_OP_SET_STATIC_ADDRESS,
7f72134e0   Marcel Holtmann   Bluetooth: Add MG...
86
  	MGMT_OP_SET_SCAN_PARAMS,
e98d2ce29   Marcel Holtmann   Bluetooth: Add fl...
87
  	MGMT_OP_SET_SECURE_CONN,
4e39ac813   Marcel Holtmann   Bluetooth: Add ma...
88
  	MGMT_OP_SET_DEBUG_KEYS,
62b04cd12   Johan Hedberg   Bluetooth: Add su...
89
  	MGMT_OP_SET_PRIVACY,
41edf1601   Johan Hedberg   Bluetooth: Implem...
90
  	MGMT_OP_LOAD_IRKS,
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
91
  	MGMT_OP_GET_CONN_INFO,
958684263   Johan Hedberg   Bluetooth: Add su...
92
  	MGMT_OP_GET_CLOCK_INFO,
2faade53e   Marcel Holtmann   Bluetooth: Add su...
93
94
  	MGMT_OP_ADD_DEVICE,
  	MGMT_OP_REMOVE_DEVICE,
a26f3dcff   Johan Hedberg   Bluetooth: Add Lo...
95
  	MGMT_OP_LOAD_CONN_PARAM,
73d1df2a7   Marcel Holtmann   Bluetooth: Add su...
96
  	MGMT_OP_READ_UNCONF_INDEX_LIST,
9fc3bfb68   Marcel Holtmann   Bluetooth: Add su...
97
  	MGMT_OP_READ_CONFIG_INFO,
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
98
  	MGMT_OP_SET_EXTERNAL_CONFIG,
9713c17b0   Marcel Holtmann   Bluetooth: Add su...
99
  	MGMT_OP_SET_PUBLIC_ADDRESS,
66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
100
  	MGMT_OP_START_SERVICE_DISCOVERY,
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
101
  	MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
96f1474af   Marcel Holtmann   Bluetooth: Add su...
102
  	MGMT_OP_READ_EXT_INDEX_LIST,
d3d5305bf   Marcel Holtmann   Bluetooth: Add si...
103
  	MGMT_OP_READ_ADV_FEATURES,
24b4f38fc   Arman Uguray   Bluetooth: Implem...
104
  	MGMT_OP_ADD_ADVERTISING,
da929335f   Arman Uguray   Bluetooth: Implem...
105
  	MGMT_OP_REMOVE_ADVERTISING,
40b25fe5d   Marcel Holtmann   Bluetooth: Add su...
106
  	MGMT_OP_GET_ADV_SIZE_INFO,
78b781ca0   Johan Hedberg   Bluetooth: Add su...
107
  	MGMT_OP_START_LIMITED_DISCOVERY,
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
108
  	MGMT_OP_READ_EXT_INFO,
c4960ecf2   MichaƂ Narajowski   Bluetooth: Add su...
109
  	MGMT_OP_SET_APPEARANCE,
600a87490   Alain Michaud   Bluetooth: Implem...
110
  	MGMT_OP_SET_BLOCKED_KEYS,
00bce3fb0   Alain Michaud   Bluetooth: Enable...
111
  	MGMT_OP_SET_WIDEBAND_SPEECH,
bc292258c   Marcel Holtmann   Bluetooth: Add su...
112
  	MGMT_OP_READ_SECURITY_INFO,
a10c907ce   Marcel Holtmann   Bluetooth: Add su...
113
114
  	MGMT_OP_READ_EXP_FEATURES_INFO,
  	MGMT_OP_SET_EXP_FEATURE,
17896406f   Alain Michaud   Bluetooth: implem...
115
116
  	MGMT_OP_READ_DEF_SYSTEM_CONFIG,
  	MGMT_OP_SET_DEF_SYSTEM_CONFIG,
aececa645   Marcel Holtmann   Bluetooth: mgmt: ...
117
118
  	MGMT_OP_READ_DEF_RUNTIME_CONFIG,
  	MGMT_OP_SET_DEF_RUNTIME_CONFIG,
4c54bf2b0   Abhishek Pandit-Subedi   Bluetooth: Add ge...
119
120
  	MGMT_OP_GET_DEVICE_FLAGS,
  	MGMT_OP_SET_DEVICE_FLAGS,
e5e1e7fd4   Miao-chen Chou   Bluetooth: Add ha...
121
  	MGMT_OP_READ_ADV_MONITOR_FEATURES,
b139553db   Miao-chen Chou   Bluetooth: Add ha...
122
  	MGMT_OP_ADD_ADV_PATTERNS_MONITOR,
bd2fbc6cb   Miao-chen Chou   Bluetooth: Add ha...
123
  	MGMT_OP_REMOVE_ADV_MONITOR,
e70bb2e89   Johan Hedberg   Bluetooth: Implem...
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
  };
  
  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: ...
147
  	MGMT_EV_PASSKEY_NOTIFY,
1b60ef210   Marcel Holtmann   Bluetooth: Fix is...
148
  	MGMT_EV_NEW_IRK,
7ee4ea369   Marcel Holtmann   Bluetooth: Add su...
149
  	MGMT_EV_NEW_CSRK,
8afef092a   Marcel Holtmann   Bluetooth: Add De...
150
151
  	MGMT_EV_DEVICE_ADDED,
  	MGMT_EV_DEVICE_REMOVED,
ffb5a827d   Andre Guedes   Bluetooth: Introd...
152
  	MGMT_EV_NEW_CONN_PARAM,
0602a8adc   Marcel Holtmann   Bluetooth: Add su...
153
  	MGMT_EV_UNCONF_INDEX_ADDED,
edd3896bc   Marcel Holtmann   Bluetooth: Add su...
154
  	MGMT_EV_UNCONF_INDEX_REMOVED,
f4537c04d   Marcel Holtmann   Bluetooth: Add su...
155
  	MGMT_EV_NEW_CONFIG_OPTIONS,
ced85549c   Marcel Holtmann   Bluetooth: Add su...
156
157
  	MGMT_EV_EXT_INDEX_ADDED,
  	MGMT_EV_EXT_INDEX_REMOVED,
72000df2c   Marcel Holtmann   Bluetooth: Add su...
158
  	MGMT_EV_LOCAL_OOB_DATA_UPDATED,
24b4f38fc   Arman Uguray   Bluetooth: Implem...
159
160
  	MGMT_EV_ADVERTISING_ADDED,
  	MGMT_EV_ADVERTISING_REMOVED,
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
161
  	MGMT_EV_EXT_INFO_CHANGED,
5f4b91728   Marcel Holtmann   Bluetooth: Add MG...
162
  	MGMT_EV_PHY_CONFIGURATION_CHANGED,
a10c907ce   Marcel Holtmann   Bluetooth: Add su...
163
  	MGMT_EV_EXP_FEATURE_CHANGED,
4c54bf2b0   Abhishek Pandit-Subedi   Bluetooth: Add ge...
164
  	MGMT_EV_DEVICE_FLAGS_CHANGED,
346ce5b7d   Abhishek Pandit-Subedi   Bluetooth: Add mg...
165
166
  	MGMT_EV_CONTROLLER_SUSPEND,
  	MGMT_EV_CONTROLLER_RESUME,
e70bb2e89   Johan Hedberg   Bluetooth: Implem...
167
  };
99c679acc   Marcel Holtmann   Bluetooth: Filter...
168
169
170
171
172
173
  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...
174
  	MGMT_OP_READ_EXT_INFO,
bc292258c   Marcel Holtmann   Bluetooth: Add su...
175
  	MGMT_OP_READ_SECURITY_INFO,
a10c907ce   Marcel Holtmann   Bluetooth: Add su...
176
  	MGMT_OP_READ_EXP_FEATURES_INFO,
17896406f   Alain Michaud   Bluetooth: implem...
177
  	MGMT_OP_READ_DEF_SYSTEM_CONFIG,
aececa645   Marcel Holtmann   Bluetooth: mgmt: ...
178
  	MGMT_OP_READ_DEF_RUNTIME_CONFIG,
99c679acc   Marcel Holtmann   Bluetooth: Filter...
179
180
181
182
183
184
185
186
187
188
189
190
191
  };
  
  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...
192
  	MGMT_EV_EXT_INFO_CHANGED,
a10c907ce   Marcel Holtmann   Bluetooth: Add su...
193
  	MGMT_EV_EXP_FEATURE_CHANGED,
b52729f27   Miao-chen Chou   Bluetooth: Notify...
194
  	MGMT_EV_ADV_MONITOR_ADDED,
cdde92e23   Miao-chen Chou   Bluetooth: Notify...
195
  	MGMT_EV_ADV_MONITOR_REMOVED,
99c679acc   Marcel Holtmann   Bluetooth: Filter...
196
  };
17b02e625   Marcel Holtmann   Bluetooth: Update...
197
  #define CACHE_TIMEOUT	msecs_to_jiffies(2 * 1000)
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
198

d25b78e2e   Johan Hedberg   Bluetooth: Enforc...
199
200
  #define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
  		 "\x00\x00\x00\x00\x00\x00\x00\x00"
ca69b7957   Johan Hedberg   Bluetooth: Create...
201
  /* HCI to MGMT error code conversion table */
bdf2aca70   Alain Michaud   Bluetooth: adding...
202
  static const u8 mgmt_status_table[] = {
ca69b7957   Johan Hedberg   Bluetooth: Create...
203
204
205
206
207
208
  	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...
209
  	MGMT_STATUS_AUTH_FAILED,	/* PIN or Key Missing */
ca69b7957   Johan Hedberg   Bluetooth: Create...
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
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
  	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...
273
274
  static int mgmt_index_event(u16 event, struct hci_dev *hdev, void *data,
  			    u16 len, int flag)
f92073388   Marcel Holtmann   Bluetooth: Use sp...
275
  {
c08b1a1db   Marcel Holtmann   Bluetooth: Consol...
276
277
  	return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
  			       flag, NULL);
f92073388   Marcel Holtmann   Bluetooth: Use sp...
278
  }
72000df2c   Marcel Holtmann   Bluetooth: Add su...
279
280
281
282
283
284
  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...
285
286
287
288
  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...
289
  			       HCI_SOCK_TRUSTED, skip_sk);
7a00ff445   Johan Hedberg   Bluetooth: Add mg...
290
  }
85813a7ec   Johan Hedberg   Bluetooth: Add le...
291
292
293
294
295
296
297
  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...
298
299
300
301
302
303
304
  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...
305
306
  static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
  			u16 data_len)
a38528f11   Johan Hedberg   Bluetooth: Create...
307
308
  {
  	struct mgmt_rp_read_version rp;
181d69535   Marcel Holtmann   Bluetooth: Replac...
309
  	bt_dev_dbg(hdev, "sock %p", sk);
a38528f11   Johan Hedberg   Bluetooth: Create...
310

03c979c47   Marcel Holtmann   Bluetooth: Introd...
311
  	mgmt_fill_version_info(&rp);
a38528f11   Johan Hedberg   Bluetooth: Create...
312

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
313
314
  	return mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0,
  				 &rp, sizeof(rp));
a38528f11   Johan Hedberg   Bluetooth: Create...
315
  }
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
316
317
  static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
  			 u16 data_len)
e70bb2e89   Johan Hedberg   Bluetooth: Implem...
318
319
  {
  	struct mgmt_rp_read_commands *rp;
99c679acc   Marcel Holtmann   Bluetooth: Filter...
320
  	u16 num_commands, num_events;
e70bb2e89   Johan Hedberg   Bluetooth: Implem...
321
322
  	size_t rp_size;
  	int i, err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
323
  	bt_dev_dbg(hdev, "sock %p", sk);
e70bb2e89   Johan Hedberg   Bluetooth: Implem...
324

99c679acc   Marcel Holtmann   Bluetooth: Filter...
325
326
327
328
329
330
331
  	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...
332
333
334
335
336
  	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...
337
338
  	rp->num_commands = cpu_to_le16(num_commands);
  	rp->num_events = cpu_to_le16(num_events);
e70bb2e89   Johan Hedberg   Bluetooth: Implem...
339

99c679acc   Marcel Holtmann   Bluetooth: Filter...
340
341
342
343
344
  	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...
345

99c679acc   Marcel Holtmann   Bluetooth: Filter...
346
347
348
349
350
351
352
353
354
355
356
  		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...
357

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
358
359
  	err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0,
  				rp, rp_size);
e70bb2e89   Johan Hedberg   Bluetooth: Implem...
360
361
362
363
  	kfree(rp);
  
  	return err;
  }
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
364
365
  static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
  			   u16 data_len)
faba42eb2   Johan Hedberg   Bluetooth: Add re...
366
  {
faba42eb2   Johan Hedberg   Bluetooth: Add re...
367
  	struct mgmt_rp_read_index_list *rp;
8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
368
  	struct hci_dev *d;
a38528f11   Johan Hedberg   Bluetooth: Create...
369
  	size_t rp_len;
faba42eb2   Johan Hedberg   Bluetooth: Add re...
370
  	u16 count;
476e44cb1   Johan Hedberg   Bluetooth: Fix ha...
371
  	int err;
faba42eb2   Johan Hedberg   Bluetooth: Add re...
372

181d69535   Marcel Holtmann   Bluetooth: Replac...
373
  	bt_dev_dbg(hdev, "sock %p", sk);
faba42eb2   Johan Hedberg   Bluetooth: Add re...
374
375
376
377
  
  	read_lock(&hci_dev_list_lock);
  
  	count = 0;
bb4b2a9ae   Andrei Emeltchenko   Bluetooth: mgmt: ...
378
  	list_for_each_entry(d, &hci_dev_list, list) {
ca8bee5dd   Marcel Holtmann   Bluetooth: Rename...
379
  		if (d->dev_type == HCI_PRIMARY &&
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
380
  		    !hci_dev_test_flag(d, HCI_UNCONFIGURED))
1514b8928   Marcel Holtmann   Bluetooth: Remove...
381
  			count++;
faba42eb2   Johan Hedberg   Bluetooth: Add re...
382
  	}
a38528f11   Johan Hedberg   Bluetooth: Create...
383
384
385
  	rp_len = sizeof(*rp) + (2 * count);
  	rp = kmalloc(rp_len, GFP_ATOMIC);
  	if (!rp) {
b2c60d42d   Jesper Juhl   Bluetooth: Fix fa...
386
  		read_unlock(&hci_dev_list_lock);
faba42eb2   Johan Hedberg   Bluetooth: Add re...
387
  		return -ENOMEM;
b2c60d42d   Jesper Juhl   Bluetooth: Fix fa...
388
  	}
faba42eb2   Johan Hedberg   Bluetooth: Add re...
389

476e44cb1   Johan Hedberg   Bluetooth: Fix ha...
390
  	count = 0;
8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
391
  	list_for_each_entry(d, &hci_dev_list, list) {
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
392
393
394
  		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...
395
  			continue;
73d1df2a7   Marcel Holtmann   Bluetooth: Add su...
396
397
398
399
  		/* 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...
400
  			continue;
ca8bee5dd   Marcel Holtmann   Bluetooth: Rename...
401
  		if (d->dev_type == HCI_PRIMARY &&
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
402
  		    !hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
1514b8928   Marcel Holtmann   Bluetooth: Remove...
403
  			rp->index[count++] = cpu_to_le16(d->id);
181d69535   Marcel Holtmann   Bluetooth: Replac...
404
  			bt_dev_dbg(hdev, "Added hci%u", d->id);
1514b8928   Marcel Holtmann   Bluetooth: Remove...
405
  		}
faba42eb2   Johan Hedberg   Bluetooth: Add re...
406
  	}
476e44cb1   Johan Hedberg   Bluetooth: Fix ha...
407
408
  	rp->num_controllers = cpu_to_le16(count);
  	rp_len = sizeof(*rp) + (2 * count);
faba42eb2   Johan Hedberg   Bluetooth: Add re...
409
  	read_unlock(&hci_dev_list_lock);
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
410
411
  	err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST,
  				0, rp, rp_len);
faba42eb2   Johan Hedberg   Bluetooth: Add re...
412

a38528f11   Johan Hedberg   Bluetooth: Create...
413
414
415
  	kfree(rp);
  
  	return err;
faba42eb2   Johan Hedberg   Bluetooth: Add re...
416
  }
73d1df2a7   Marcel Holtmann   Bluetooth: Add su...
417
418
419
420
421
422
423
424
  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;
181d69535   Marcel Holtmann   Bluetooth: Replac...
425
  	bt_dev_dbg(hdev, "sock %p", sk);
73d1df2a7   Marcel Holtmann   Bluetooth: Add su...
426
427
428
429
430
  
  	read_lock(&hci_dev_list_lock);
  
  	count = 0;
  	list_for_each_entry(d, &hci_dev_list, list) {
ca8bee5dd   Marcel Holtmann   Bluetooth: Rename...
431
  		if (d->dev_type == HCI_PRIMARY &&
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
432
  		    hci_dev_test_flag(d, HCI_UNCONFIGURED))
73d1df2a7   Marcel Holtmann   Bluetooth: Add su...
433
434
435
436
437
438
439
440
441
442
443
444
  			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...
445
446
447
  		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...
448
449
450
451
452
453
454
  			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...
455
  		if (d->dev_type == HCI_PRIMARY &&
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
456
  		    hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
73d1df2a7   Marcel Holtmann   Bluetooth: Add su...
457
  			rp->index[count++] = cpu_to_le16(d->id);
181d69535   Marcel Holtmann   Bluetooth: Replac...
458
  			bt_dev_dbg(hdev, "Added hci%u", d->id);
73d1df2a7   Marcel Holtmann   Bluetooth: Add su...
459
460
461
462
463
464
465
  		}
  	}
  
  	rp->num_controllers = cpu_to_le16(count);
  	rp_len = sizeof(*rp) + (2 * count);
  
  	read_unlock(&hci_dev_list_lock);
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
466
467
  	err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
  				MGMT_OP_READ_UNCONF_INDEX_LIST, 0, rp, rp_len);
73d1df2a7   Marcel Holtmann   Bluetooth: Add su...
468
469
470
471
472
  
  	kfree(rp);
  
  	return err;
  }
96f1474af   Marcel Holtmann   Bluetooth: Add su...
473
474
475
476
477
  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;
96f1474af   Marcel Holtmann   Bluetooth: Add su...
478
479
  	u16 count;
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
480
  	bt_dev_dbg(hdev, "sock %p", sk);
96f1474af   Marcel Holtmann   Bluetooth: Add su...
481
482
483
484
485
  
  	read_lock(&hci_dev_list_lock);
  
  	count = 0;
  	list_for_each_entry(d, &hci_dev_list, list) {
ca8bee5dd   Marcel Holtmann   Bluetooth: Rename...
486
  		if (d->dev_type == HCI_PRIMARY || d->dev_type == HCI_AMP)
96f1474af   Marcel Holtmann   Bluetooth: Add su...
487
488
  			count++;
  	}
4a67e5d4a   Gustavo A. R. Silva   Bluetooth: mgmt: ...
489
  	rp = kmalloc(struct_size(rp, entry, count), GFP_ATOMIC);
96f1474af   Marcel Holtmann   Bluetooth: Add su...
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
  	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...
507
  		if (d->dev_type == HCI_PRIMARY) {
96f1474af   Marcel Holtmann   Bluetooth: Add su...
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);
181d69535   Marcel Holtmann   Bluetooth: Replac...
520
  		bt_dev_dbg(hdev, "Added hci%u", d->id);
96f1474af   Marcel Holtmann   Bluetooth: Add su...
521
522
523
  	}
  
  	rp->num_controllers = cpu_to_le16(count);
96f1474af   Marcel Holtmann   Bluetooth: Add su...
524
525
526
527
528
529
530
531
532
533
534
535
  
  	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,
4a67e5d4a   Gustavo A. R. Silva   Bluetooth: mgmt: ...
536
537
  				MGMT_OP_READ_EXT_INDEX_LIST, 0, rp,
  				struct_size(rp, entry, count));
96f1474af   Marcel Holtmann   Bluetooth: Add su...
538
539
540
541
542
  
  	kfree(rp);
  
  	return err;
  }
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
543
544
545
  static bool is_configured(struct hci_dev *hdev)
  {
  	if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
546
  	    !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
547
  		return false;
7a0e5b15c   Matthias Kaehlcke   Bluetooth: Add qu...
548
549
  	if ((test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) ||
  	     test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks)) &&
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
550
551
552
553
554
  	    !bacmp(&hdev->public_addr, BDADDR_ANY))
  		return false;
  
  	return true;
  }
89bc22d23   Marcel Holtmann   Bluetooth: Add qu...
555
556
557
  static __le32 get_missing_options(struct hci_dev *hdev)
  {
  	u32 options = 0;
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
558
  	if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
559
  	    !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
eb1904f49   Marcel Holtmann   Bluetooth: Add qu...
560
  		options |= MGMT_OPTION_EXTERNAL_CONFIG;
7a0e5b15c   Matthias Kaehlcke   Bluetooth: Add qu...
561
562
  	if ((test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) ||
  	     test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks)) &&
89bc22d23   Marcel Holtmann   Bluetooth: Add qu...
563
564
565
566
567
  	    !bacmp(&hdev->public_addr, BDADDR_ANY))
  		options |= MGMT_OPTION_PUBLIC_ADDRESS;
  
  	return cpu_to_le32(options);
  }
f4537c04d   Marcel Holtmann   Bluetooth: Add su...
568
569
570
  static int new_options(struct hci_dev *hdev, struct sock *skip)
  {
  	__le32 options = get_missing_options(hdev);
5504c3a31   Marcel Holtmann   Bluetooth: Use in...
571
572
  	return mgmt_limited_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
  				  sizeof(options), HCI_MGMT_OPTION_EVENTS, skip);
f4537c04d   Marcel Holtmann   Bluetooth: Add su...
573
  }
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
574
575
576
  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...
577
578
  	return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &options,
  				 sizeof(options));
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
579
  }
9fc3bfb68   Marcel Holtmann   Bluetooth: Add su...
580
581
582
583
  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...
584
  	u32 options = 0;
9fc3bfb68   Marcel Holtmann   Bluetooth: Add su...
585

181d69535   Marcel Holtmann   Bluetooth: Replac...
586
  	bt_dev_dbg(hdev, "sock %p", sk);
9fc3bfb68   Marcel Holtmann   Bluetooth: Add su...
587
588
589
590
591
  
  	hci_dev_lock(hdev);
  
  	memset(&rp, 0, sizeof(rp));
  	rp.manufacturer = cpu_to_le16(hdev->manufacturer);
89bc22d23   Marcel Holtmann   Bluetooth: Add qu...
592

eb1904f49   Marcel Holtmann   Bluetooth: Add qu...
593
594
  	if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
  		options |= MGMT_OPTION_EXTERNAL_CONFIG;
9fc3bfb68   Marcel Holtmann   Bluetooth: Add su...
595
  	if (hdev->set_bdaddr)
89bc22d23   Marcel Holtmann   Bluetooth: Add qu...
596
597
598
599
  		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...
600
601
  
  	hci_dev_unlock(hdev);
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
602
603
  	return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0,
  				 &rp, sizeof(rp));
9fc3bfb68   Marcel Holtmann   Bluetooth: Add su...
604
  }
6244691fe   Jaganath Kanakkassery   Bluetooth: Implem...
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
  static u32 get_supported_phys(struct hci_dev *hdev)
  {
  	u32 supported_phys = 0;
  
  	if (lmp_bredr_capable(hdev)) {
  		supported_phys |= MGMT_PHY_BR_1M_1SLOT;
  
  		if (hdev->features[0][0] & LMP_3SLOT)
  			supported_phys |= MGMT_PHY_BR_1M_3SLOT;
  
  		if (hdev->features[0][0] & LMP_5SLOT)
  			supported_phys |= MGMT_PHY_BR_1M_5SLOT;
  
  		if (lmp_edr_2m_capable(hdev)) {
  			supported_phys |= MGMT_PHY_EDR_2M_1SLOT;
  
  			if (lmp_edr_3slot_capable(hdev))
  				supported_phys |= MGMT_PHY_EDR_2M_3SLOT;
  
  			if (lmp_edr_5slot_capable(hdev))
  				supported_phys |= MGMT_PHY_EDR_2M_5SLOT;
  
  			if (lmp_edr_3m_capable(hdev)) {
  				supported_phys |= MGMT_PHY_EDR_3M_1SLOT;
  
  				if (lmp_edr_3slot_capable(hdev))
  					supported_phys |= MGMT_PHY_EDR_3M_3SLOT;
  
  				if (lmp_edr_5slot_capable(hdev))
  					supported_phys |= MGMT_PHY_EDR_3M_5SLOT;
  			}
  		}
  	}
  
  	if (lmp_le_capable(hdev)) {
  		supported_phys |= MGMT_PHY_LE_1M_TX;
  		supported_phys |= MGMT_PHY_LE_1M_RX;
  
  		if (hdev->le_features[1] & HCI_LE_PHY_2M) {
  			supported_phys |= MGMT_PHY_LE_2M_TX;
  			supported_phys |= MGMT_PHY_LE_2M_RX;
  		}
  
  		if (hdev->le_features[1] & HCI_LE_PHY_CODED) {
  			supported_phys |= MGMT_PHY_LE_CODED_TX;
  			supported_phys |= MGMT_PHY_LE_CODED_RX;
  		}
  	}
  
  	return supported_phys;
  }
  
  static u32 get_selected_phys(struct hci_dev *hdev)
  {
  	u32 selected_phys = 0;
  
  	if (lmp_bredr_capable(hdev)) {
  		selected_phys |= MGMT_PHY_BR_1M_1SLOT;
  
  		if (hdev->pkt_type & (HCI_DM3 | HCI_DH3))
  			selected_phys |= MGMT_PHY_BR_1M_3SLOT;
  
  		if (hdev->pkt_type & (HCI_DM5 | HCI_DH5))
  			selected_phys |= MGMT_PHY_BR_1M_5SLOT;
  
  		if (lmp_edr_2m_capable(hdev)) {
  			if (!(hdev->pkt_type & HCI_2DH1))
  				selected_phys |= MGMT_PHY_EDR_2M_1SLOT;
  
  			if (lmp_edr_3slot_capable(hdev) &&
  			    !(hdev->pkt_type & HCI_2DH3))
  				selected_phys |= MGMT_PHY_EDR_2M_3SLOT;
  
  			if (lmp_edr_5slot_capable(hdev) &&
  			    !(hdev->pkt_type & HCI_2DH5))
  				selected_phys |= MGMT_PHY_EDR_2M_5SLOT;
  
  			if (lmp_edr_3m_capable(hdev)) {
  				if (!(hdev->pkt_type & HCI_3DH1))
  					selected_phys |= MGMT_PHY_EDR_3M_1SLOT;
  
  				if (lmp_edr_3slot_capable(hdev) &&
  				    !(hdev->pkt_type & HCI_3DH3))
  					selected_phys |= MGMT_PHY_EDR_3M_3SLOT;
  
  				if (lmp_edr_5slot_capable(hdev) &&
  				    !(hdev->pkt_type & HCI_3DH5))
  					selected_phys |= MGMT_PHY_EDR_3M_5SLOT;
  			}
  		}
  	}
  
  	if (lmp_le_capable(hdev)) {
  		if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_1M)
  			selected_phys |= MGMT_PHY_LE_1M_TX;
  
  		if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_1M)
  			selected_phys |= MGMT_PHY_LE_1M_RX;
  
  		if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_2M)
  			selected_phys |= MGMT_PHY_LE_2M_TX;
  
  		if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_2M)
  			selected_phys |= MGMT_PHY_LE_2M_RX;
  
  		if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_CODED)
  			selected_phys |= MGMT_PHY_LE_CODED_TX;
  
  		if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_CODED)
  			selected_phys |= MGMT_PHY_LE_CODED_RX;
  	}
  
  	return selected_phys;
  }
  
  static u32 get_configurable_phys(struct hci_dev *hdev)
  {
  	return (get_supported_phys(hdev) & ~MGMT_PHY_BR_1M_1SLOT &
  		~MGMT_PHY_LE_1M_TX & ~MGMT_PHY_LE_1M_RX);
  }
69ab39ea5   Johan Hedberg   Bluetooth: Update...
725
726
727
728
729
  static u32 get_supported_settings(struct hci_dev *hdev)
  {
  	u32 settings = 0;
  
  	settings |= MGMT_SETTING_POWERED;
b2939475e   Johan Hedberg   Bluetooth: Rename...
730
  	settings |= MGMT_SETTING_BONDABLE;
b1de97d8c   Marcel Holtmann   Bluetooth: Add ma...
731
  	settings |= MGMT_SETTING_DEBUG_KEYS;
3742abfc4   Johan Hedberg   Bluetooth: Fix co...
732
733
  	settings |= MGMT_SETTING_CONNECTABLE;
  	settings |= MGMT_SETTING_DISCOVERABLE;
69ab39ea5   Johan Hedberg   Bluetooth: Update...
734

ed3fa31f3   Andre Guedes   Bluetooth: Use lm...
735
  	if (lmp_bredr_capable(hdev)) {
1a47aee85   Johan Hedberg   Bluetooth: Limit ...
736
737
  		if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
  			settings |= MGMT_SETTING_FAST_CONNECTABLE;
69ab39ea5   Johan Hedberg   Bluetooth: Update...
738
739
  		settings |= MGMT_SETTING_BREDR;
  		settings |= MGMT_SETTING_LINK_SECURITY;
a82974c9f   Marcel Holtmann   Bluetooth: Don't ...
740
741
742
  
  		if (lmp_ssp_capable(hdev)) {
  			settings |= MGMT_SETTING_SSP;
b560a208c   Luiz Augusto von Dentz   Bluetooth: MGMT: ...
743
744
  			if (IS_ENABLED(CONFIG_BT_HS))
  				settings |= MGMT_SETTING_HS;
a82974c9f   Marcel Holtmann   Bluetooth: Don't ...
745
  		}
e98d2ce29   Marcel Holtmann   Bluetooth: Add fl...
746

05b3c3e79   Marcel Holtmann   Bluetooth: Remove...
747
  		if (lmp_sc_capable(hdev))
e98d2ce29   Marcel Holtmann   Bluetooth: Add fl...
748
  			settings |= MGMT_SETTING_SECURE_CONN;
4b127bd5f   Alain Michaud   Bluetooth: Suppor...
749

00bce3fb0   Alain Michaud   Bluetooth: Enable...
750
  		if (test_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED,
4b127bd5f   Alain Michaud   Bluetooth: Suppor...
751
  			     &hdev->quirks))
00bce3fb0   Alain Michaud   Bluetooth: Enable...
752
  			settings |= MGMT_SETTING_WIDEBAND_SPEECH;
848566b38   Marcel Holtmann   Bluetooth: Provid...
753
  	}
d7b7e7968   Marcel Holtmann   Bluetooth: Set su...
754

eeca6f891   Johan Hedberg   Bluetooth: Add ne...
755
  	if (lmp_le_capable(hdev)) {
9d42820f3   Marcel Holtmann   Bluetooth: Enable...
756
  		settings |= MGMT_SETTING_LE;
a3209694f   Johan Hedberg   Bluetooth: Add mg...
757
  		settings |= MGMT_SETTING_SECURE_CONN;
0f4bd942f   Johan Hedberg   Bluetooth: Add Pr...
758
  		settings |= MGMT_SETTING_PRIVACY;
93690c227   Marcel Holtmann   Bluetooth: Introd...
759
  		settings |= MGMT_SETTING_STATIC_ADDRESS;
cbbdfa6f3   Sathish Narasimman   Bluetooth: Enable...
760
761
762
763
764
765
  
  		/* When the experimental feature for LL Privacy support is
  		 * enabled, then advertising is no longer supported.
  		 */
  		if (!hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
  			settings |= MGMT_SETTING_ADVERTISING;
eeca6f891   Johan Hedberg   Bluetooth: Add ne...
766
  	}
69ab39ea5   Johan Hedberg   Bluetooth: Update...
767

eb1904f49   Marcel Holtmann   Bluetooth: Add qu...
768
769
  	if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
  	    hdev->set_bdaddr)
9fc3bfb68   Marcel Holtmann   Bluetooth: Add su...
770
  		settings |= MGMT_SETTING_CONFIGURATION;
6244691fe   Jaganath Kanakkassery   Bluetooth: Implem...
771
  	settings |= MGMT_SETTING_PHY_CONFIGURATION;
69ab39ea5   Johan Hedberg   Bluetooth: Update...
772
773
774
775
776
777
  	return settings;
  }
  
  static u32 get_current_settings(struct hci_dev *hdev)
  {
  	u32 settings = 0;
f1f0eb022   Johan Hedberg   Bluetooth: mgmt: ...
778
  	if (hdev_is_powered(hdev))
f0d4b78a6   Marcel Holtmann   Bluetooth: Only k...
779
  		settings |= MGMT_SETTING_POWERED;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
780
  	if (hci_dev_test_flag(hdev, HCI_CONNECTABLE))
69ab39ea5   Johan Hedberg   Bluetooth: Update...
781
  		settings |= MGMT_SETTING_CONNECTABLE;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
782
  	if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
1a4d3c4b3   Johan Hedberg   Bluetooth: Add pr...
783
  		settings |= MGMT_SETTING_FAST_CONNECTABLE;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
784
  	if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
69ab39ea5   Johan Hedberg   Bluetooth: Update...
785
  		settings |= MGMT_SETTING_DISCOVERABLE;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
786
  	if (hci_dev_test_flag(hdev, HCI_BONDABLE))
b2939475e   Johan Hedberg   Bluetooth: Rename...
787
  		settings |= MGMT_SETTING_BONDABLE;
69ab39ea5   Johan Hedberg   Bluetooth: Update...
788

d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
789
  	if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
69ab39ea5   Johan Hedberg   Bluetooth: Update...
790
  		settings |= MGMT_SETTING_BREDR;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
791
  	if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
69ab39ea5   Johan Hedberg   Bluetooth: Update...
792
  		settings |= MGMT_SETTING_LE;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
793
  	if (hci_dev_test_flag(hdev, HCI_LINK_SECURITY))
69ab39ea5   Johan Hedberg   Bluetooth: Update...
794
  		settings |= MGMT_SETTING_LINK_SECURITY;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
795
  	if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
69ab39ea5   Johan Hedberg   Bluetooth: Update...
796
  		settings |= MGMT_SETTING_SSP;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
797
  	if (hci_dev_test_flag(hdev, HCI_HS_ENABLED))
6d80dfd09   Johan Hedberg   Bluetooth: mgmt: ...
798
  		settings |= MGMT_SETTING_HS;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
799
  	if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
eeca6f891   Johan Hedberg   Bluetooth: Add ne...
800
  		settings |= MGMT_SETTING_ADVERTISING;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
801
  	if (hci_dev_test_flag(hdev, HCI_SC_ENABLED))
e98d2ce29   Marcel Holtmann   Bluetooth: Add fl...
802
  		settings |= MGMT_SETTING_SECURE_CONN;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
803
  	if (hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS))
b1de97d8c   Marcel Holtmann   Bluetooth: Add ma...
804
  		settings |= MGMT_SETTING_DEBUG_KEYS;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
805
  	if (hci_dev_test_flag(hdev, HCI_PRIVACY))
0f4bd942f   Johan Hedberg   Bluetooth: Add Pr...
806
  		settings |= MGMT_SETTING_PRIVACY;
93690c227   Marcel Holtmann   Bluetooth: Introd...
807
808
809
810
811
  	/* 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...
812
  	 * will never be set. If the address is configured, then if the
93690c227   Marcel Holtmann   Bluetooth: Introd...
813
814
815
816
817
818
  	 * 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 ...
819
  	if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
820
  	    !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
93690c227   Marcel Holtmann   Bluetooth: Introd...
821
822
823
824
  	    !bacmp(&hdev->bdaddr, BDADDR_ANY)) {
  		if (bacmp(&hdev->static_addr, BDADDR_ANY))
  			settings |= MGMT_SETTING_STATIC_ADDRESS;
  	}
00bce3fb0   Alain Michaud   Bluetooth: Enable...
825
826
  	if (hci_dev_test_flag(hdev, HCI_WIDEBAND_SPEECH_ENABLED))
  		settings |= MGMT_SETTING_WIDEBAND_SPEECH;
69ab39ea5   Johan Hedberg   Bluetooth: Update...
827
828
  	return settings;
  }
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
829
830
831
832
  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...
833
834
835
836
837
838
  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...
839
  u8 mgmt_get_adv_discov_flags(struct hci_dev *hdev)
9a43e25ff   Johan Hedberg   Bluetooth: Update...
840
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
841
  	struct mgmt_pending_cmd *cmd;
9a43e25ff   Johan Hedberg   Bluetooth: Update...
842
843
844
845
  
  	/* 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...
846
  	cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
9a43e25ff   Johan Hedberg   Bluetooth: Update...
847
848
849
850
851
852
853
  	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...
854
  		if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
9a43e25ff   Johan Hedberg   Bluetooth: Update...
855
  			return LE_AD_LIMITED;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
856
  		else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
9a43e25ff   Johan Hedberg   Bluetooth: Update...
857
858
859
860
861
  			return LE_AD_GENERAL;
  	}
  
  	return 0;
  }
f22525700   Johan Hedberg   Bluetooth: Move a...
862
  bool mgmt_get_connectable(struct hci_dev *hdev)
fdf51784c   Arman Uguray   Bluetooth: Unify ...
863
864
  {
  	struct mgmt_pending_cmd *cmd;
441ad2d04   Marcel Holtmann   Bluetooth: Update...
865

fdf51784c   Arman Uguray   Bluetooth: Unify ...
866
867
868
869
870
871
  	/* 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...
872

fdf51784c   Arman Uguray   Bluetooth: Unify ...
873
  		return cp->val;
441ad2d04   Marcel Holtmann   Bluetooth: Update...
874
  	}
fdf51784c   Arman Uguray   Bluetooth: Unify ...
875
876
  	return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
  }
441ad2d04   Marcel Holtmann   Bluetooth: Update...
877

7d78525dc   Johan Hedberg   Bluetooth: Add ti...
878
879
880
  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...
881
  					    service_cache.work);
890ea8988   Johan Hedberg   Bluetooth: Update...
882
  	struct hci_request req;
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
883

a69d89272   Marcel Holtmann   Bluetooth: Introd...
884
  	if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
885
  		return;
890ea8988   Johan Hedberg   Bluetooth: Update...
886
  	hci_req_init(&req, hdev);
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
887
  	hci_dev_lock(hdev);
b1a8917c9   Johan Hedberg   Bluetooth: Move E...
888
  	__hci_req_update_eir(&req);
14bf5eac7   Johan Hedberg   Bluetooth: Perfor...
889
  	__hci_req_update_class(&req);
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
890
891
  
  	hci_dev_unlock(hdev);
890ea8988   Johan Hedberg   Bluetooth: Update...
892
893
  
  	hci_req_run(&req, NULL);
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
894
  }
d6bfd59ca   Johan Hedberg   Bluetooth: Add ti...
895
896
897
898
899
  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;
181d69535   Marcel Holtmann   Bluetooth: Replac...
900
  	bt_dev_dbg(hdev, "");
d6bfd59ca   Johan Hedberg   Bluetooth: Add ti...
901

a1536da25   Marcel Holtmann   Bluetooth: Introd...
902
  	hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
d6bfd59ca   Johan Hedberg   Bluetooth: Add ti...
903

d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
904
  	if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
d6bfd59ca   Johan Hedberg   Bluetooth: Add ti...
905
906
907
  		return;
  
  	/* The generation of a new RPA and programming it into the
f22525700   Johan Hedberg   Bluetooth: Move a...
908
909
  	 * controller happens in the hci_req_enable_advertising()
  	 * function.
d6bfd59ca   Johan Hedberg   Bluetooth: Add ti...
910
  	 */
d6bfd59ca   Johan Hedberg   Bluetooth: Add ti...
911
  	hci_req_init(&req, hdev);
de181e887   Jaganath Kanakkassery   Bluetooth: Impmle...
912
913
914
915
  	if (ext_adv_capable(hdev))
  		__hci_req_start_ext_adv(&req, hdev->cur_adv_instance);
  	else
  		__hci_req_enable_advertising(&req);
d6bfd59ca   Johan Hedberg   Bluetooth: Add ti...
916
917
  	hci_req_run(&req, NULL);
  }
6a919082e   Johan Hedberg   Bluetooth: mgmt: ...
918
  static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
919
  {
238be788f   Marcel Holtmann   Bluetooth: Introd...
920
  	if (hci_dev_test_and_set_flag(hdev, HCI_MGMT))
6a919082e   Johan Hedberg   Bluetooth: mgmt: ...
921
  		return;
4f87da80a   Johan Hedberg   Bluetooth: Remove...
922
  	INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
d6bfd59ca   Johan Hedberg   Bluetooth: Add ti...
923
  	INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
924

4f87da80a   Johan Hedberg   Bluetooth: Remove...
925
926
927
928
929
  	/* 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...
930
  	hci_dev_clear_flag(hdev, HCI_BONDABLE);
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
931
  }
0f4e68cf6   Johan Hedberg   Bluetooth: mgmt: ...
932
  static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
933
  				void *data, u16 data_len)
0381101fd   Johan Hedberg   Bluetooth: Add in...
934
  {
a38528f11   Johan Hedberg   Bluetooth: Create...
935
  	struct mgmt_rp_read_info rp;
f7b64e69c   Johan Hedberg   Bluetooth: Add re...
936

181d69535   Marcel Holtmann   Bluetooth: Replac...
937
  	bt_dev_dbg(hdev, "sock %p", sk);
f7b64e69c   Johan Hedberg   Bluetooth: Add re...
938

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

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

69ab39ea5   Johan Hedberg   Bluetooth: Update...
944
  	rp.version = hdev->hci_ver;
eb55ef07a   Marcel Holtmann   Bluetooth: Fix br...
945
  	rp.manufacturer = cpu_to_le16(hdev->manufacturer);
69ab39ea5   Johan Hedberg   Bluetooth: Update...
946
947
948
  
  	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...
949

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

dc4fe30b8   Johan Hedberg   Bluetooth: mgmt: ...
952
  	memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
27fcc3622   Johan Hedberg   Bluetooth: mgmt: ...
953
  	memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
dc4fe30b8   Johan Hedberg   Bluetooth: mgmt: ...
954

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

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
957
958
  	return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
  				 sizeof(rp));
0381101fd   Johan Hedberg   Bluetooth: Add in...
959
  }
cde7a863d   MichaƂ Narajowski   Bluetooth: Factor...
960
961
962
963
964
965
966
967
  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...
968
969
970
  	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...
971
972
973
974
975
976
977
978
979
980
  	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...
981
982
983
  static int read_ext_controller_info(struct sock *sk, struct hci_dev *hdev,
  				    void *data, u16 data_len)
  {
7d5c11da1   Szymon Janc   Bluetooth: Refact...
984
985
  	char buf[512];
  	struct mgmt_rp_read_ext_info *rp = (void *)buf;
cde7a863d   MichaƂ Narajowski   Bluetooth: Factor...
986
  	u16 eir_len;
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
987

181d69535   Marcel Holtmann   Bluetooth: Replac...
988
  	bt_dev_dbg(hdev, "sock %p", sk);
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
989

7d5c11da1   Szymon Janc   Bluetooth: Refact...
990
  	memset(&buf, 0, sizeof(buf));
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
991
  	hci_dev_lock(hdev);
7d5c11da1   Szymon Janc   Bluetooth: Refact...
992
993
994
995
996
997
998
  	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...
999

cde7a863d   MichaƂ Narajowski   Bluetooth: Factor...
1000
  	eir_len = append_eir_data_to_buf(hdev, rp->eir);
8a0c9f490   MichaƂ Narajowski   Bluetooth: Append...
1001
  	rp->eir_len = cpu_to_le16(eir_len);
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
  
  	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...
1013
1014
  	return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_EXT_INFO, 0, rp,
  				 sizeof(*rp) + eir_len);
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
1015
1016
1017
1018
  }
  
  static int ext_info_changed(struct hci_dev *hdev, struct sock *skip)
  {
5e9fae48f   MichaƂ Narajowski   Bluetooth: Add su...
1019
1020
1021
1022
1023
  	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...
1024

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

5e9fae48f   MichaƂ Narajowski   Bluetooth: Add su...
1028
1029
1030
  	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...
1031
  }
69ab39ea5   Johan Hedberg   Bluetooth: Update...
1032
  static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
8680570b0   Johan Hedberg   Bluetooth: Return...
1033
  {
69ab39ea5   Johan Hedberg   Bluetooth: Update...
1034
  	__le32 settings = cpu_to_le32(get_current_settings(hdev));
8680570b0   Johan Hedberg   Bluetooth: Return...
1035

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
1036
1037
  	return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
  				 sizeof(settings));
8680570b0   Johan Hedberg   Bluetooth: Return...
1038
  }
1904a853f   Marcel Holtmann   Bluetooth: Add op...
1039
  static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
1040
  {
181d69535   Marcel Holtmann   Bluetooth: Replac...
1041
  	bt_dev_dbg(hdev, "status 0x%02x", status);
8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
1042

a3172b7eb   Johan Hedberg   Bluetooth: Add ti...
1043
1044
  	if (hci_conn_count(hdev) == 0) {
  		cancel_delayed_work(&hdev->power_off);
8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
1045
  		queue_work(hdev->req_workqueue, &hdev->power_off.work);
a3172b7eb   Johan Hedberg   Bluetooth: Add ti...
1046
  	}
8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
1047
  }
f22525700   Johan Hedberg   Bluetooth: Move a...
1048
  void mgmt_advertising_added(struct sock *sk, struct hci_dev *hdev, u8 instance)
912098a63   Arman Uguray   Bluetooth: Add su...
1049
1050
1051
1052
1053
1054
1055
  {
  	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...
1056
1057
  void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev,
  			      u8 instance)
912098a63   Arman Uguray   Bluetooth: Add su...
1058
1059
1060
1061
1062
1063
1064
  {
  	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: ...
1065
1066
1067
1068
1069
1070
1071
  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 ...
1072
1073
1074
1075
  static int clean_up_hci_state(struct hci_dev *hdev)
  {
  	struct hci_request req;
  	struct hci_conn *conn;
23a48093b   Johan Hedberg   Bluetooth: Fix se...
1076
1077
  	bool discov_stopped;
  	int err;
8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
1078
1079
1080
1081
1082
1083
1084
1085
  
  	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: ...
1086
  	hci_req_clear_adv_instance(hdev, NULL, NULL, 0x00, false);
912098a63   Arman Uguray   Bluetooth: Add su...
1087

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

2154d3f4f   Johan Hedberg   Bluetooth: Move S...
1091
  	discov_stopped = hci_req_stop_discovery(&req);
8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
1092
1093
  
  	list_for_each_entry(conn, &hdev->conn_hash.list, list) {
89e0ccc88   Johan Hedberg   Bluetooth: Take a...
1094
1095
  		/* 0x15 == Terminated due to Power Off */
  		__hci_abort_conn(&req, conn, 0x15);
8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
1096
  	}
23a48093b   Johan Hedberg   Bluetooth: Fix se...
1097
1098
1099
1100
1101
  	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 ...
1102
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1103
  static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
1104
  		       u16 len)
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
1105
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
1106
  	struct mgmt_mode *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1107
  	struct mgmt_pending_cmd *cmd;
4b34ee782   Johan Hedberg   Bluetooth: mgmt: ...
1108
  	int err;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
1109

181d69535   Marcel Holtmann   Bluetooth: Replac...
1110
  	bt_dev_dbg(hdev, "sock %p", sk);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
1111

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

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

333ae95d0   Johan Hedberg   Bluetooth: Add ch...
1118
  	if (pending_find(MGMT_OP_SET_POWERED, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1119
1120
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
  				      MGMT_STATUS_BUSY);
87b95ba64   Johan Hedberg   Bluetooth: Fix bu...
1121
1122
  		goto failed;
  	}
4b34ee782   Johan Hedberg   Bluetooth: mgmt: ...
1123
  	if (!!cp->val == hdev_is_powered(hdev)) {
69ab39ea5   Johan Hedberg   Bluetooth: Update...
1124
  		err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
1125
1126
  		goto failed;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
1127
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
366a03369   Johan Hedberg   Bluetooth: Make p...
1128
1129
  	if (!cmd) {
  		err = -ENOMEM;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
1130
  		goto failed;
366a03369   Johan Hedberg   Bluetooth: Make p...
1131
  	}
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
1132

8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
1133
  	if (cp->val) {
192025731   Johan Hedberg   Bluetooth: Use re...
1134
  		queue_work(hdev->req_workqueue, &hdev->power_on);
8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
1135
1136
1137
1138
  		err = 0;
  	} else {
  		/* Disconnect connections, stop scans, etc */
  		err = clean_up_hci_state(hdev);
a3172b7eb   Johan Hedberg   Bluetooth: Add ti...
1139
1140
1141
  		if (!err)
  			queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
  					   HCI_POWER_OFF_TIMEOUT);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
1142

8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
1143
1144
  		/* ENODATA means there were no HCI commands queued */
  		if (err == -ENODATA) {
a3172b7eb   Johan Hedberg   Bluetooth: Add ti...
1145
  			cancel_delayed_work(&hdev->power_off);
8b064a3ad   Johan Hedberg   Bluetooth: Clean ...
1146
1147
1148
1149
  			queue_work(hdev->req_workqueue, &hdev->power_off.work);
  			err = 0;
  		}
  	}
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
1150
1151
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1152
  	hci_dev_unlock(hdev);
366a03369   Johan Hedberg   Bluetooth: Make p...
1153
  	return err;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
1154
  }
beadb2bdd   Johan Hedberg   Bluetooth: mgmt: ...
1155
1156
  static int new_settings(struct hci_dev *hdev, struct sock *skip)
  {
f6b7712eb   Marcel Holtmann   Bluetooth: Send g...
1157
  	__le32 ev = cpu_to_le32(get_current_settings(hdev));
beadb2bdd   Johan Hedberg   Bluetooth: mgmt: ...
1158

5504c3a31   Marcel Holtmann   Bluetooth: Use in...
1159
1160
  	return mgmt_limited_event(MGMT_EV_NEW_SETTINGS, hdev, &ev,
  				  sizeof(ev), HCI_MGMT_SETTING_EVENTS, skip);
beadb2bdd   Johan Hedberg   Bluetooth: mgmt: ...
1161
  }
91a668b05   Johan Hedberg   Bluetooth: Fix se...
1162
1163
1164
1165
  int mgmt_new_settings(struct hci_dev *hdev)
  {
  	return new_settings(hdev, NULL);
  }
bd99abdd5   Johan Hedberg   Bluetooth: Move m...
1166
1167
1168
1169
1170
  struct cmd_lookup {
  	struct sock *sk;
  	struct hci_dev *hdev;
  	u8 mgmt_status;
  };
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1171
  static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
bd99abdd5   Johan Hedberg   Bluetooth: Move m...
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
  {
  	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...
1186
  static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
bd99abdd5   Johan Hedberg   Bluetooth: Move m...
1187
1188
  {
  	u8 *status = data;
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1189
  	mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
bd99abdd5   Johan Hedberg   Bluetooth: Move m...
1190
1191
  	mgmt_pending_remove(cmd);
  }
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1192
  static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
1b9b5ee53   Johan Hedberg   Bluetooth: Add ca...
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
  {
  	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...
1205
  static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
f5818c224   Johan Hedberg   Bluetooth: Conver...
1206
  {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
1207
1208
  	return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
  				 cmd->param, cmd->param_len);
f5818c224   Johan Hedberg   Bluetooth: Conver...
1209
  }
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1210
  static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
7776d1d80   Johan Hedberg   Bluetooth: Use cm...
1211
  {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
1212
1213
  	return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
  				 cmd->param, sizeof(struct mgmt_addr_info));
7776d1d80   Johan Hedberg   Bluetooth: Use cm...
1214
  }
e6fe79865   Johan Hedberg   Bluetooth: Fix RE...
1215
1216
1217
1218
  static u8 mgmt_bredr_support(struct hci_dev *hdev)
  {
  	if (!lmp_bredr_capable(hdev))
  		return MGMT_STATUS_NOT_SUPPORTED;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1219
  	else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
e6fe79865   Johan Hedberg   Bluetooth: Fix RE...
1220
1221
1222
1223
1224
1225
1226
1227
1228
  		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...
1229
  	else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
e6fe79865   Johan Hedberg   Bluetooth: Fix RE...
1230
1231
1232
1233
  		return MGMT_STATUS_REJECTED;
  	else
  		return MGMT_STATUS_SUCCESS;
  }
aed1a8851   Johan Hedberg   Bluetooth: Move d...
1234
  void mgmt_set_discoverable_complete(struct hci_dev *hdev, u8 status)
bfaf8c9ff   Johan Hedberg   Bluetooth: Conver...
1235
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1236
  	struct mgmt_pending_cmd *cmd;
bfaf8c9ff   Johan Hedberg   Bluetooth: Conver...
1237

181d69535   Marcel Holtmann   Bluetooth: Replac...
1238
  	bt_dev_dbg(hdev, "status 0x%02x", status);
bfaf8c9ff   Johan Hedberg   Bluetooth: Conver...
1239
1240
  
  	hci_dev_lock(hdev);
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
1241
  	cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
bfaf8c9ff   Johan Hedberg   Bluetooth: Conver...
1242
1243
1244
1245
1246
  	if (!cmd)
  		goto unlock;
  
  	if (status) {
  		u8 mgmt_err = mgmt_status(status);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1247
  		mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
1248
  		hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
bfaf8c9ff   Johan Hedberg   Bluetooth: Conver...
1249
1250
  		goto remove_cmd;
  	}
aed1a8851   Johan Hedberg   Bluetooth: Move d...
1251
1252
1253
1254
  	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...
1255
  	}
bfaf8c9ff   Johan Hedberg   Bluetooth: Conver...
1256
1257
  
  	send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
aed1a8851   Johan Hedberg   Bluetooth: Move d...
1258
  	new_settings(hdev, cmd->sk);
970ba5242   Marcel Holtmann   Bluetooth: Update...
1259

bfaf8c9ff   Johan Hedberg   Bluetooth: Conver...
1260
1261
1262
1263
1264
1265
  remove_cmd:
  	mgmt_pending_remove(cmd);
  
  unlock:
  	hci_dev_unlock(hdev);
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1266
  static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
1267
  			    u16 len)
73f22f623   Johan Hedberg   Bluetooth: Add su...
1268
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
1269
  	struct mgmt_cp_set_discoverable *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1270
  	struct mgmt_pending_cmd *cmd;
5e5282bbf   Johan Hedberg   Bluetooth: mgmt: ...
1271
  	u16 timeout;
73f22f623   Johan Hedberg   Bluetooth: Add su...
1272
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
1273
  	bt_dev_dbg(hdev, "sock %p", sk);
73f22f623   Johan Hedberg   Bluetooth: Add su...
1274

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

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

1f350c872   Marcel Holtmann   Bluetooth: Fix br...
1284
  	timeout = __le16_to_cpu(cp->timeout);
310a3d485   Marcel Holtmann   Bluetooth: Add su...
1285
1286
1287
1288
1289
1290
  
  	/* 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...
1291
1292
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
  				       MGMT_STATUS_INVALID_PARAMS);
73f22f623   Johan Hedberg   Bluetooth: Add su...
1293

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

5e5282bbf   Johan Hedberg   Bluetooth: mgmt: ...
1296
  	if (!hdev_is_powered(hdev) && timeout > 0) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1297
1298
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
  				      MGMT_STATUS_NOT_POWERED);
73f22f623   Johan Hedberg   Bluetooth: Add su...
1299
1300
  		goto failed;
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
1301
1302
  	if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
  	    pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1303
1304
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
  				      MGMT_STATUS_BUSY);
73f22f623   Johan Hedberg   Bluetooth: Add su...
1305
1306
  		goto failed;
  	}
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1307
  	if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1308
1309
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
  				      MGMT_STATUS_REJECTED);
5e5282bbf   Johan Hedberg   Bluetooth: mgmt: ...
1310
1311
  		goto failed;
  	}
4867bd007   Abhishek Pandit-Subedi   Bluetooth: Pause ...
1312
1313
1314
1315
1316
  	if (hdev->advertising_paused) {
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
  				      MGMT_STATUS_BUSY);
  		goto failed;
  	}
5e5282bbf   Johan Hedberg   Bluetooth: mgmt: ...
1317
  	if (!hdev_is_powered(hdev)) {
0224d2faf   Johan Hedberg   Bluetooth: mgmt: ...
1318
  		bool changed = false;
310a3d485   Marcel Holtmann   Bluetooth: Add su...
1319
1320
1321
1322
  		/* 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...
1323
  		if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
ce05d603a   Marcel Holtmann   Bluetooth: Introd...
1324
  			hci_dev_change_flag(hdev, HCI_DISCOVERABLE);
0224d2faf   Johan Hedberg   Bluetooth: mgmt: ...
1325
1326
  			changed = true;
  		}
5e5282bbf   Johan Hedberg   Bluetooth: mgmt: ...
1327
  		err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
0224d2faf   Johan Hedberg   Bluetooth: mgmt: ...
1328
1329
1330
1331
1332
  		if (err < 0)
  			goto failed;
  
  		if (changed)
  			err = new_settings(hdev, sk);
5e5282bbf   Johan Hedberg   Bluetooth: mgmt: ...
1333
1334
  		goto failed;
  	}
310a3d485   Marcel Holtmann   Bluetooth: Add su...
1335
1336
1337
1338
  	/* 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...
1339
1340
1341
  	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...
1342
1343
  		cancel_delayed_work(&hdev->discov_off);
  		hdev->discov_timeout = timeout;
955638ece   Marcel Holtmann   Bluetooth: Fix ha...
1344

36261547c   Marcel Holtmann   Bluetooth: Simpli...
1345
1346
  		if (cp->val && hdev->discov_timeout > 0) {
  			int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
c366f555b   Johan Hedberg   Bluetooth: Move d...
1347
1348
  			queue_delayed_work(hdev->req_workqueue,
  					   &hdev->discov_off, to);
955638ece   Marcel Holtmann   Bluetooth: Fix ha...
1349
  		}
69ab39ea5   Johan Hedberg   Bluetooth: Update...
1350
  		err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
73f22f623   Johan Hedberg   Bluetooth: Add su...
1351
1352
  		goto failed;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
1353
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
366a03369   Johan Hedberg   Bluetooth: Make p...
1354
1355
  	if (!cmd) {
  		err = -ENOMEM;
73f22f623   Johan Hedberg   Bluetooth: Add su...
1356
  		goto failed;
366a03369   Johan Hedberg   Bluetooth: Make p...
1357
  	}
73f22f623   Johan Hedberg   Bluetooth: Add su...
1358

310a3d485   Marcel Holtmann   Bluetooth: Add su...
1359
1360
1361
1362
1363
1364
  	/* 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...
1365
1366
1367
1368
  	if (cp->val)
  		hci_dev_set_flag(hdev, HCI_DISCOVERABLE);
  	else
  		hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
b456f87cb   Johan Hedberg   Bluetooth: Move H...
1369
1370
  	/* Limited discoverable mode */
  	if (cp->val == 0x02)
a1536da25   Marcel Holtmann   Bluetooth: Introd...
1371
  		hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
b456f87cb   Johan Hedberg   Bluetooth: Move H...
1372
  	else
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
1373
  		hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
b456f87cb   Johan Hedberg   Bluetooth: Move H...
1374

aed1a8851   Johan Hedberg   Bluetooth: Move d...
1375
1376
  	queue_work(hdev->req_workqueue, &hdev->discoverable_update);
  	err = 0;
73f22f623   Johan Hedberg   Bluetooth: Add su...
1377
1378
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1379
  	hci_dev_unlock(hdev);
73f22f623   Johan Hedberg   Bluetooth: Add su...
1380
1381
  	return err;
  }
53c0ba745   Johan Hedberg   Bluetooth: Move c...
1382
  void mgmt_set_connectable_complete(struct hci_dev *hdev, u8 status)
2b76f4539   Johan Hedberg   Bluetooth: Use an...
1383
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1384
  	struct mgmt_pending_cmd *cmd;
2b76f4539   Johan Hedberg   Bluetooth: Use an...
1385

181d69535   Marcel Holtmann   Bluetooth: Replac...
1386
  	bt_dev_dbg(hdev, "status 0x%02x", status);
2b76f4539   Johan Hedberg   Bluetooth: Use an...
1387
1388
  
  	hci_dev_lock(hdev);
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
1389
  	cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
2b76f4539   Johan Hedberg   Bluetooth: Use an...
1390
1391
  	if (!cmd)
  		goto unlock;
37438c1f7   Johan Hedberg   Bluetooth: Add mi...
1392
1393
  	if (status) {
  		u8 mgmt_err = mgmt_status(status);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1394
  		mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
37438c1f7   Johan Hedberg   Bluetooth: Add mi...
1395
1396
  		goto remove_cmd;
  	}
2b76f4539   Johan Hedberg   Bluetooth: Use an...
1397
  	send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
53c0ba745   Johan Hedberg   Bluetooth: Move c...
1398
  	new_settings(hdev, cmd->sk);
d7b856f93   Johan Hedberg   Bluetooth: Move m...
1399

37438c1f7   Johan Hedberg   Bluetooth: Add mi...
1400
  remove_cmd:
2b76f4539   Johan Hedberg   Bluetooth: Use an...
1401
1402
1403
1404
1405
  	mgmt_pending_remove(cmd);
  
  unlock:
  	hci_dev_unlock(hdev);
  }
e8ba3a1f0   Johan Hedberg   Bluetooth: Refact...
1406
1407
1408
1409
1410
  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...
1411
  	if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
e8ba3a1f0   Johan Hedberg   Bluetooth: Refact...
1412
1413
1414
  		changed = true;
  
  	if (val) {
a1536da25   Marcel Holtmann   Bluetooth: Introd...
1415
  		hci_dev_set_flag(hdev, HCI_CONNECTABLE);
e8ba3a1f0   Johan Hedberg   Bluetooth: Refact...
1416
  	} else {
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
1417
1418
  		hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
  		hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
e8ba3a1f0   Johan Hedberg   Bluetooth: Refact...
1419
1420
1421
1422
1423
  	}
  
  	err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
  	if (err < 0)
  		return err;
562064e65   Johan Hedberg   Bluetooth: Fix to...
1424
  	if (changed) {
01b1cb87d   Johan Hedberg   Bluetooth: Run pa...
1425
  		hci_req_update_scan(hdev);
562064e65   Johan Hedberg   Bluetooth: Fix to...
1426
  		hci_update_background_scan(hdev);
e8ba3a1f0   Johan Hedberg   Bluetooth: Refact...
1427
  		return new_settings(hdev, sk);
562064e65   Johan Hedberg   Bluetooth: Fix to...
1428
  	}
e8ba3a1f0   Johan Hedberg   Bluetooth: Refact...
1429
1430
1431
  
  	return 0;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1432
  static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
1433
  			   u16 len)
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
1434
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
1435
  	struct mgmt_mode *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1436
  	struct mgmt_pending_cmd *cmd;
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
1437
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
1438
  	bt_dev_dbg(hdev, "sock %p", sk);
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
1439

d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1440
1441
  	if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
  	    !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1442
1443
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
  				       MGMT_STATUS_REJECTED);
33c525c0a   Johan Hedberg   Bluetooth: mgmt: ...
1444

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

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

4b34ee782   Johan Hedberg   Bluetooth: mgmt: ...
1451
  	if (!hdev_is_powered(hdev)) {
e8ba3a1f0   Johan Hedberg   Bluetooth: Refact...
1452
  		err = set_connectable_update_settings(hdev, sk, cp->val);
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
1453
1454
  		goto failed;
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
1455
1456
  	if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
  	    pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1457
1458
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
  				      MGMT_STATUS_BUSY);
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
1459
1460
  		goto failed;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
1461
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
366a03369   Johan Hedberg   Bluetooth: Make p...
1462
1463
  	if (!cmd) {
  		err = -ENOMEM;
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
1464
  		goto failed;
366a03369   Johan Hedberg   Bluetooth: Make p...
1465
  	}
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
1466

53c0ba745   Johan Hedberg   Bluetooth: Move c...
1467
1468
1469
1470
1471
  	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...
1472

53c0ba745   Johan Hedberg   Bluetooth: Move c...
1473
1474
1475
  		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...
1476
  	}
2b76f4539   Johan Hedberg   Bluetooth: Use an...
1477

53c0ba745   Johan Hedberg   Bluetooth: Move c...
1478
1479
  	queue_work(hdev->req_workqueue, &hdev->connectable_update);
  	err = 0;
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
1480
1481
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1482
  	hci_dev_unlock(hdev);
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
1483
1484
  	return err;
  }
b2939475e   Johan Hedberg   Bluetooth: Rename...
1485
  static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
1486
  			u16 len)
c542a06c2   Johan Hedberg   Bluetooth: Implem...
1487
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
1488
  	struct mgmt_mode *cp = data;
555943565   Marcel Holtmann   Bluetooth: Send n...
1489
  	bool changed;
c542a06c2   Johan Hedberg   Bluetooth: Implem...
1490
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
1491
  	bt_dev_dbg(hdev, "sock %p", sk);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
1492

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

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1497
  	hci_dev_lock(hdev);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
1498
1499
  
  	if (cp->val)
238be788f   Marcel Holtmann   Bluetooth: Introd...
1500
  		changed = !hci_dev_test_and_set_flag(hdev, HCI_BONDABLE);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
1501
  	else
a69d89272   Marcel Holtmann   Bluetooth: Introd...
1502
  		changed = hci_dev_test_and_clear_flag(hdev, HCI_BONDABLE);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
1503

b2939475e   Johan Hedberg   Bluetooth: Rename...
1504
  	err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
1505
  	if (err < 0)
555943565   Marcel Holtmann   Bluetooth: Send n...
1506
  		goto unlock;
c542a06c2   Johan Hedberg   Bluetooth: Implem...
1507

82a37adee   Johan Hedberg   Bluetooth: Add su...
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
  	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...
1518
  		err = new_settings(hdev, sk);
82a37adee   Johan Hedberg   Bluetooth: Add su...
1519
  	}
c542a06c2   Johan Hedberg   Bluetooth: Implem...
1520

555943565   Marcel Holtmann   Bluetooth: Send n...
1521
  unlock:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1522
  	hci_dev_unlock(hdev);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
1523
1524
  	return err;
  }
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
1525
1526
  static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
  			     u16 len)
33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
1527
1528
  {
  	struct mgmt_mode *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1529
  	struct mgmt_pending_cmd *cmd;
e6fe79865   Johan Hedberg   Bluetooth: Fix RE...
1530
  	u8 val, status;
33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
1531
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
1532
  	bt_dev_dbg(hdev, "sock %p", sk);
33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
1533

e6fe79865   Johan Hedberg   Bluetooth: Fix RE...
1534
1535
  	status = mgmt_bredr_support(hdev);
  	if (status)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1536
1537
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
  				       status);
33c525c0a   Johan Hedberg   Bluetooth: mgmt: ...
1538

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

33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
1543
  	hci_dev_lock(hdev);
4b34ee782   Johan Hedberg   Bluetooth: mgmt: ...
1544
  	if (!hdev_is_powered(hdev)) {
47990ea09   Johan Hedberg   Bluetooth: mgmt: ...
1545
  		bool changed = false;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1546
  		if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
ce05d603a   Marcel Holtmann   Bluetooth: Introd...
1547
  			hci_dev_change_flag(hdev, HCI_LINK_SECURITY);
47990ea09   Johan Hedberg   Bluetooth: mgmt: ...
1548
1549
1550
1551
1552
1553
1554
1555
1556
  			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: ...
1557
1558
  		goto failed;
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
1559
  	if (pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1560
1561
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
  				      MGMT_STATUS_BUSY);
33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
  		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: ...
1586
1587
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1588
  static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
1589
1590
  {
  	struct mgmt_mode *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1591
  	struct mgmt_pending_cmd *cmd;
72ef0c1a9   Marcel Holtmann   Bluetooth: Remove...
1592
  	u8 status;
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
1593
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
1594
  	bt_dev_dbg(hdev, "sock %p", sk);
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
1595

cdba5281b   Marcel Holtmann   Bluetooth: Restri...
1596
1597
  	status = mgmt_bredr_support(hdev);
  	if (status)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1598
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
cdba5281b   Marcel Holtmann   Bluetooth: Restri...
1599

13ecd8b66   Johan Hedberg   Bluetooth: Move n...
1600
  	if (!lmp_ssp_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1601
1602
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
  				       MGMT_STATUS_NOT_SUPPORTED);
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
1603

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

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

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

9ecb3e242   Marcel Holtmann   Bluetooth: Restri...
1613
  		if (cp->val) {
238be788f   Marcel Holtmann   Bluetooth: Introd...
1614
1615
  			changed = !hci_dev_test_and_set_flag(hdev,
  							     HCI_SSP_ENABLED);
9ecb3e242   Marcel Holtmann   Bluetooth: Restri...
1616
  		} else {
a69d89272   Marcel Holtmann   Bluetooth: Introd...
1617
1618
  			changed = hci_dev_test_and_clear_flag(hdev,
  							      HCI_SSP_ENABLED);
9ecb3e242   Marcel Holtmann   Bluetooth: Restri...
1619
  			if (!changed)
a69d89272   Marcel Holtmann   Bluetooth: Introd...
1620
1621
  				changed = hci_dev_test_and_clear_flag(hdev,
  								      HCI_HS_ENABLED);
9ecb3e242   Marcel Holtmann   Bluetooth: Restri...
1622
  			else
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
1623
  				hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
c0ecddc25   Johan Hedberg   Bluetooth: mgmt: ...
1624
1625
1626
1627
1628
1629
1630
1631
  		}
  
  		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: ...
1632
1633
  		goto failed;
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
1634
  	if (pending_find(MGMT_OP_SET_SSP, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1635
1636
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
  				      MGMT_STATUS_BUSY);
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
1637
1638
  		goto failed;
  	}
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1639
  	if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
1640
1641
1642
1643
1644
1645
1646
1647
1648
  		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...
1649
  	if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
3769972ba   Johan Hedberg   Bluetooth: Add a ...
1650
1651
  		hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
  			     sizeof(cp->val), &cp->val);
72ef0c1a9   Marcel Holtmann   Bluetooth: Remove...
1652
  	err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
1653
1654
1655
1656
1657
1658
1659
  	if (err < 0) {
  		mgmt_pending_remove(cmd);
  		goto failed;
  	}
  
  failed:
  	hci_dev_unlock(hdev);
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
1660
1661
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1662
  static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
6d80dfd09   Johan Hedberg   Bluetooth: mgmt: ...
1663
1664
  {
  	struct mgmt_mode *cp = data;
ee3926936   Marcel Holtmann   Bluetooth: Send n...
1665
  	bool changed;
e6fe79865   Johan Hedberg   Bluetooth: Fix RE...
1666
  	u8 status;
ee3926936   Marcel Holtmann   Bluetooth: Send n...
1667
  	int err;
6d80dfd09   Johan Hedberg   Bluetooth: mgmt: ...
1668

181d69535   Marcel Holtmann   Bluetooth: Replac...
1669
  	bt_dev_dbg(hdev, "sock %p", sk);
6d80dfd09   Johan Hedberg   Bluetooth: mgmt: ...
1670

b560a208c   Luiz Augusto von Dentz   Bluetooth: MGMT: ...
1671
1672
1673
  	if (!IS_ENABLED(CONFIG_BT_HS))
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
  				       MGMT_STATUS_NOT_SUPPORTED);
e6fe79865   Johan Hedberg   Bluetooth: Fix RE...
1674
1675
  	status = mgmt_bredr_support(hdev);
  	if (status)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1676
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
6d80dfd09   Johan Hedberg   Bluetooth: mgmt: ...
1677

9ecb3e242   Marcel Holtmann   Bluetooth: Restri...
1678
  	if (!lmp_ssp_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1679
1680
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
  				       MGMT_STATUS_NOT_SUPPORTED);
9ecb3e242   Marcel Holtmann   Bluetooth: Restri...
1681

d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1682
  	if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1683
1684
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
  				       MGMT_STATUS_REJECTED);
9ecb3e242   Marcel Holtmann   Bluetooth: Restri...
1685

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

ee3926936   Marcel Holtmann   Bluetooth: Send n...
1690
  	hci_dev_lock(hdev);
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
1691
  	if (pending_find(MGMT_OP_SET_SSP, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1692
1693
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
  				      MGMT_STATUS_BUSY);
a2cb01de1   Johan Hedberg   Bluetooth: Fix ch...
1694
1695
  		goto unlock;
  	}
a0cdf960b   Marcel Holtmann   Bluetooth: Restri...
1696
  	if (cp->val) {
238be788f   Marcel Holtmann   Bluetooth: Introd...
1697
  		changed = !hci_dev_test_and_set_flag(hdev, HCI_HS_ENABLED);
a0cdf960b   Marcel Holtmann   Bluetooth: Restri...
1698
1699
  	} else {
  		if (hdev_is_powered(hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1700
1701
  			err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
  					      MGMT_STATUS_REJECTED);
a0cdf960b   Marcel Holtmann   Bluetooth: Restri...
1702
1703
  			goto unlock;
  		}
a69d89272   Marcel Holtmann   Bluetooth: Introd...
1704
  		changed = hci_dev_test_and_clear_flag(hdev, HCI_HS_ENABLED);
a0cdf960b   Marcel Holtmann   Bluetooth: Restri...
1705
  	}
ee3926936   Marcel Holtmann   Bluetooth: Send n...
1706
1707
1708
1709
1710
1711
1712
  
  	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: ...
1713

ee3926936   Marcel Holtmann   Bluetooth: Send n...
1714
1715
1716
  unlock:
  	hci_dev_unlock(hdev);
  	return err;
6d80dfd09   Johan Hedberg   Bluetooth: mgmt: ...
1717
  }
1904a853f   Marcel Holtmann   Bluetooth: Add op...
1718
  static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
416a4ae56   Johan Hedberg   Bluetooth: Use as...
1719
1720
  {
  	struct cmd_lookup match = { NULL, hdev };
3ad675827   Jaganath Kanakkassery   Bluetooth: Fix mi...
1721
  	hci_dev_lock(hdev);
416a4ae56   Johan Hedberg   Bluetooth: Use as...
1722
1723
1724
1725
1726
  	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...
1727
  		goto unlock;
416a4ae56   Johan Hedberg   Bluetooth: Use as...
1728
1729
1730
1731
1732
1733
1734
1735
  	}
  
  	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...
1736
1737
1738
1739
1740
1741
  
  	/* 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...
1742
  	if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
441ad2d04   Marcel Holtmann   Bluetooth: Update...
1743
  		struct hci_request req;
441ad2d04   Marcel Holtmann   Bluetooth: Update...
1744
  		hci_req_init(&req, hdev);
a0fb3726b   Jaganath Kanakkassery   Bluetooth: Use Se...
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
  		if (ext_adv_capable(hdev)) {
  			int err;
  
  			err = __hci_req_setup_ext_adv_instance(&req, 0x00);
  			if (!err)
  				__hci_req_update_scan_rsp_data(&req, 0x00);
  		} else {
  			__hci_req_update_adv_data(&req, 0x00);
  			__hci_req_update_scan_rsp_data(&req, 0x00);
  		}
441ad2d04   Marcel Holtmann   Bluetooth: Update...
1755
  		hci_req_run(&req, NULL);
2e93e53b8   Johan Hedberg   Bluetooth: Run al...
1756
  		hci_update_background_scan(hdev);
441ad2d04   Marcel Holtmann   Bluetooth: Update...
1757
  	}
3ad675827   Jaganath Kanakkassery   Bluetooth: Fix mi...
1758
1759
1760
  
  unlock:
  	hci_dev_unlock(hdev);
416a4ae56   Johan Hedberg   Bluetooth: Use as...
1761
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1762
  static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1763
1764
1765
  {
  	struct mgmt_mode *cp = data;
  	struct hci_cp_write_le_host_supported hci_cp;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1766
  	struct mgmt_pending_cmd *cmd;
416a4ae56   Johan Hedberg   Bluetooth: Use as...
1767
  	struct hci_request req;
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1768
  	int err;
0b60eba1b   Johan Hedberg   Bluetooth: Don't ...
1769
  	u8 val, enabled;
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1770

181d69535   Marcel Holtmann   Bluetooth: Replac...
1771
  	bt_dev_dbg(hdev, "sock %p", sk);
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1772

13ecd8b66   Johan Hedberg   Bluetooth: Move n...
1773
  	if (!lmp_le_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1774
1775
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
  				       MGMT_STATUS_NOT_SUPPORTED);
1de028ceb   Johan Hedberg   Bluetooth: mgmt: ...
1776

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

e7844ee59   Marcel Holtmann   Bluetooth: Gracef...
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
  	/* 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...
1793
1794
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
  				       MGMT_STATUS_REJECTED);
e7844ee59   Marcel Holtmann   Bluetooth: Gracef...
1795
  	}
c73eee917   Johan Hedberg   Bluetooth: Fix se...
1796

13ecd8b66   Johan Hedberg   Bluetooth: Move n...
1797
  	hci_dev_lock(hdev);
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1798
1799
  
  	val = !!cp->val;
ffa88e02b   Gustavo Padovan   Bluetooth: Move d...
1800
  	enabled = lmp_host_le_capable(hdev);
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1801

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

0b60eba1b   Johan Hedberg   Bluetooth: Don't ...
1805
  	if (!hdev_is_powered(hdev) || val == enabled) {
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1806
  		bool changed = false;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1807
  		if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
ce05d603a   Marcel Holtmann   Bluetooth: Introd...
1808
  			hci_dev_change_flag(hdev, HCI_LE_ENABLED);
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1809
1810
  			changed = true;
  		}
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1811
  		if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
1812
  			hci_dev_clear_flag(hdev, HCI_ADVERTISING);
eeca6f891   Johan Hedberg   Bluetooth: Add ne...
1813
1814
  			changed = true;
  		}
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1815
1816
  		err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
  		if (err < 0)
1de028ceb   Johan Hedberg   Bluetooth: mgmt: ...
1817
  			goto unlock;
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1818
1819
1820
  
  		if (changed)
  			err = new_settings(hdev, sk);
1de028ceb   Johan Hedberg   Bluetooth: mgmt: ...
1821
  		goto unlock;
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1822
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
1823
1824
  	if (pending_find(MGMT_OP_SET_LE, hdev) ||
  	    pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1825
1826
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
  				      MGMT_STATUS_BUSY);
1de028ceb   Johan Hedberg   Bluetooth: mgmt: ...
1827
  		goto unlock;
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1828
1829
1830
1831
1832
  	}
  
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
  	if (!cmd) {
  		err = -ENOMEM;
1de028ceb   Johan Hedberg   Bluetooth: mgmt: ...
1833
  		goto unlock;
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1834
  	}
441ad2d04   Marcel Holtmann   Bluetooth: Update...
1835
  	hci_req_init(&req, hdev);
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1836
1837
1838
1839
  	memset(&hci_cp, 0, sizeof(hci_cp));
  
  	if (val) {
  		hci_cp.le = val;
32226e4f1   Marcel Holtmann   Bluetooth: Set Si...
1840
  		hci_cp.simul = 0x00;
441ad2d04   Marcel Holtmann   Bluetooth: Update...
1841
  	} else {
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
1842
  		if (hci_dev_test_flag(hdev, HCI_LE_ADV))
f22525700   Johan Hedberg   Bluetooth: Move a...
1843
  			__hci_req_disable_advertising(&req);
45b7749f1   Jaganath Kanakkassery   Bluetooth: Implem...
1844
1845
1846
  
  		if (ext_adv_capable(hdev))
  			__hci_req_clear_ext_adv_sets(&req);
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1847
  	}
416a4ae56   Johan Hedberg   Bluetooth: Use as...
1848
1849
1850
1851
  	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: ...
1852
  	if (err < 0)
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1853
  		mgmt_pending_remove(cmd);
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1854

1de028ceb   Johan Hedberg   Bluetooth: mgmt: ...
1855
1856
  unlock:
  	hci_dev_unlock(hdev);
06199cf86   Johan Hedberg   Bluetooth: mgmt: ...
1857
1858
  	return err;
  }
0cab9c80f   Johan Hedberg   Bluetooth: Fix bu...
1859
1860
1861
1862
1863
1864
1865
1866
  /* 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...
1867
  	struct mgmt_pending_cmd *cmd;
0cab9c80f   Johan Hedberg   Bluetooth: Fix bu...
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
  
  	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...
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
  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...
1899
1900
  static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1901
  	struct mgmt_pending_cmd *cmd;
92da60975   Johan Hedberg   Bluetooth: Fix UU...
1902
1903
  
  	hci_dev_lock(hdev);
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
1904
  	cmd = pending_find(mgmt_op, hdev);
92da60975   Johan Hedberg   Bluetooth: Fix UU...
1905
1906
  	if (!cmd)
  		goto unlock;
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
1907
1908
  	mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
  			  mgmt_status(status), hdev->dev_class, 3);
92da60975   Johan Hedberg   Bluetooth: Fix UU...
1909
1910
1911
1912
1913
1914
  
  	mgmt_pending_remove(cmd);
  
  unlock:
  	hci_dev_unlock(hdev);
  }
1904a853f   Marcel Holtmann   Bluetooth: Add op...
1915
  static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
92da60975   Johan Hedberg   Bluetooth: Fix UU...
1916
  {
181d69535   Marcel Holtmann   Bluetooth: Replac...
1917
  	bt_dev_dbg(hdev, "status 0x%02x", status);
92da60975   Johan Hedberg   Bluetooth: Fix UU...
1918
1919
1920
  
  	mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1921
  static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1922
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
1923
  	struct mgmt_cp_add_uuid *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1924
  	struct mgmt_pending_cmd *cmd;
890ea8988   Johan Hedberg   Bluetooth: Update...
1925
  	struct hci_request req;
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1926
  	struct bt_uuid *uuid;
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1927
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
1928
  	bt_dev_dbg(hdev, "sock %p", sk);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1929

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

0cab9c80f   Johan Hedberg   Bluetooth: Fix bu...
1932
  	if (pending_eir_or_class(hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
1933
1934
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
  				      MGMT_STATUS_BUSY);
c95f0ba76   Johan Hedberg   Bluetooth: mgmt: ...
1935
1936
  		goto failed;
  	}
92c4c2049   Andre Guedes   Bluetooth: Use GF...
1937
  	uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1938
1939
1940
1941
1942
1943
  	if (!uuid) {
  		err = -ENOMEM;
  		goto failed;
  	}
  
  	memcpy(uuid->uuid, cp->uuid, 16);
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
1944
  	uuid->svc_hint = cp->svc_hint;
83be8eca2   Johan Hedberg   Bluetooth: Keep t...
1945
  	uuid->size = get_uuid_size(cp->uuid);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1946

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

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

14bf5eac7   Johan Hedberg   Bluetooth: Perfor...
1951
  	__hci_req_update_class(&req);
b1a8917c9   Johan Hedberg   Bluetooth: Move E...
1952
  	__hci_req_update_eir(&req);
890ea8988   Johan Hedberg   Bluetooth: Update...
1953

92da60975   Johan Hedberg   Bluetooth: Fix UU...
1954
1955
1956
1957
  	err = hci_req_run(&req, add_uuid_complete);
  	if (err < 0) {
  		if (err != -ENODATA)
  			goto failed;
80a1e1dbf   Johan Hedberg   Bluetooth: Add lo...
1958

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
1959
1960
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
  					hdev->dev_class, 3);
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
1961
1962
1963
1964
  		goto failed;
  	}
  
  	cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
890ea8988   Johan Hedberg   Bluetooth: Update...
1965
  	if (!cmd) {
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
1966
  		err = -ENOMEM;
890ea8988   Johan Hedberg   Bluetooth: Update...
1967
1968
1969
1970
  		goto failed;
  	}
  
  	err = 0;
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1971
1972
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1973
  	hci_dev_unlock(hdev);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1974
1975
  	return err;
  }
24b78d0f4   Johan Hedberg   Bluetooth: mgmt: ...
1976
1977
1978
1979
  static bool enable_service_cache(struct hci_dev *hdev)
  {
  	if (!hdev_is_powered(hdev))
  		return false;
238be788f   Marcel Holtmann   Bluetooth: Introd...
1980
  	if (!hci_dev_test_and_set_flag(hdev, HCI_SERVICE_CACHE)) {
46818ed51   Johan Hedberg   Bluetooth: Fix us...
1981
1982
  		queue_delayed_work(hdev->workqueue, &hdev->service_cache,
  				   CACHE_TIMEOUT);
24b78d0f4   Johan Hedberg   Bluetooth: mgmt: ...
1983
1984
1985
1986
1987
  		return true;
  	}
  
  	return false;
  }
1904a853f   Marcel Holtmann   Bluetooth: Add op...
1988
  static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
92da60975   Johan Hedberg   Bluetooth: Fix UU...
1989
  {
181d69535   Marcel Holtmann   Bluetooth: Replac...
1990
  	bt_dev_dbg(hdev, "status 0x%02x", status);
92da60975   Johan Hedberg   Bluetooth: Fix UU...
1991
1992
1993
  
  	mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
1994
  static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
8ce8e2b56   Gustavo Padovan   Bluetooth: Fix co...
1995
  		       u16 len)
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1996
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
1997
  	struct mgmt_cp_remove_uuid *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
1998
  	struct mgmt_pending_cmd *cmd;
056341c8c   Johan Hedberg   Bluetooth: Simpli...
1999
  	struct bt_uuid *match, *tmp;
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
2000
  	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...
2001
  	struct hci_request req;
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
2002
  	int err, found;
181d69535   Marcel Holtmann   Bluetooth: Replac...
2003
  	bt_dev_dbg(hdev, "sock %p", sk);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
2004

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

0cab9c80f   Johan Hedberg   Bluetooth: Fix bu...
2007
  	if (pending_eir_or_class(hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2008
2009
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
  				      MGMT_STATUS_BUSY);
c95f0ba76   Johan Hedberg   Bluetooth: mgmt: ...
2010
2011
  		goto unlock;
  	}
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
2012
  	if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
35f7498a8   Johan Hedberg   Bluetooth: Remove...
2013
  		hci_uuids_clear(hdev);
4004b6d96   Johan Hedberg   Bluetooth: mgmt: ...
2014

24b78d0f4   Johan Hedberg   Bluetooth: mgmt: ...
2015
  		if (enable_service_cache(hdev)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2016
2017
2018
  			err = mgmt_cmd_complete(sk, hdev->id,
  						MGMT_OP_REMOVE_UUID,
  						0, hdev->dev_class, 3);
24b78d0f4   Johan Hedberg   Bluetooth: mgmt: ...
2019
2020
  			goto unlock;
  		}
4004b6d96   Johan Hedberg   Bluetooth: mgmt: ...
2021

9246a8693   Johan Hedberg   Bluetooth: mgmt: ...
2022
  		goto update_class;
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
2023
2024
2025
  	}
  
  	found = 0;
056341c8c   Johan Hedberg   Bluetooth: Simpli...
2026
  	list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
2027
2028
2029
2030
  		if (memcmp(match->uuid, cp->uuid, 16) != 0)
  			continue;
  
  		list_del(&match->list);
482049f75   Johan Hedberg   Bluetooth: Fix me...
2031
  		kfree(match);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
2032
2033
2034
2035
  		found++;
  	}
  
  	if (found == 0) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2036
2037
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
  				      MGMT_STATUS_INVALID_PARAMS);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
2038
2039
  		goto unlock;
  	}
9246a8693   Johan Hedberg   Bluetooth: mgmt: ...
2040
  update_class:
890ea8988   Johan Hedberg   Bluetooth: Update...
2041
  	hci_req_init(&req, hdev);
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
2042

14bf5eac7   Johan Hedberg   Bluetooth: Perfor...
2043
  	__hci_req_update_class(&req);
b1a8917c9   Johan Hedberg   Bluetooth: Move E...
2044
  	__hci_req_update_eir(&req);
890ea8988   Johan Hedberg   Bluetooth: Update...
2045

92da60975   Johan Hedberg   Bluetooth: Fix UU...
2046
2047
2048
2049
  	err = hci_req_run(&req, remove_uuid_complete);
  	if (err < 0) {
  		if (err != -ENODATA)
  			goto unlock;
80a1e1dbf   Johan Hedberg   Bluetooth: Add lo...
2050

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2051
2052
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
  					hdev->dev_class, 3);
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
2053
2054
2055
2056
  		goto unlock;
  	}
  
  	cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
890ea8988   Johan Hedberg   Bluetooth: Update...
2057
  	if (!cmd) {
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
2058
  		err = -ENOMEM;
890ea8988   Johan Hedberg   Bluetooth: Update...
2059
2060
2061
2062
  		goto unlock;
  	}
  
  	err = 0;
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
2063
2064
  
  unlock:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2065
  	hci_dev_unlock(hdev);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
2066
2067
  	return err;
  }
1904a853f   Marcel Holtmann   Bluetooth: Add op...
2068
  static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
92da60975   Johan Hedberg   Bluetooth: Fix UU...
2069
  {
181d69535   Marcel Holtmann   Bluetooth: Replac...
2070
  	bt_dev_dbg(hdev, "status 0x%02x", status);
92da60975   Johan Hedberg   Bluetooth: Fix UU...
2071
2072
2073
  
  	mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
2074
  static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2075
  			 u16 len)
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
2076
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
2077
  	struct mgmt_cp_set_dev_class *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2078
  	struct mgmt_pending_cmd *cmd;
890ea8988   Johan Hedberg   Bluetooth: Update...
2079
  	struct hci_request req;
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
2080
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
2081
  	bt_dev_dbg(hdev, "sock %p", sk);
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
2082

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

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

0cab9c80f   Johan Hedberg   Bluetooth: Fix bu...
2089
  	if (pending_eir_or_class(hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2090
2091
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
  				      MGMT_STATUS_BUSY);
0cab9c80f   Johan Hedberg   Bluetooth: Fix bu...
2092
2093
  		goto unlock;
  	}
c95f0ba76   Johan Hedberg   Bluetooth: mgmt: ...
2094

0cab9c80f   Johan Hedberg   Bluetooth: Fix bu...
2095
  	if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2096
2097
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
  				      MGMT_STATUS_INVALID_PARAMS);
0cab9c80f   Johan Hedberg   Bluetooth: Fix bu...
2098
2099
  		goto unlock;
  	}
575b3a02e   Johan Hedberg   Bluetooth: Fix ch...
2100

932f5ff5e   Johan Hedberg   Bluetooth: mgmt: ...
2101
2102
  	hdev->major_class = cp->major;
  	hdev->minor_class = cp->minor;
b5235a65a   Johan Hedberg   Bluetooth: mgmt: ...
2103
  	if (!hdev_is_powered(hdev)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2104
2105
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
  					hdev->dev_class, 3);
b5235a65a   Johan Hedberg   Bluetooth: mgmt: ...
2106
2107
  		goto unlock;
  	}
890ea8988   Johan Hedberg   Bluetooth: Update...
2108
  	hci_req_init(&req, hdev);
a69d89272   Marcel Holtmann   Bluetooth: Introd...
2109
  	if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
2110
2111
2112
  		hci_dev_unlock(hdev);
  		cancel_delayed_work_sync(&hdev->service_cache);
  		hci_dev_lock(hdev);
b1a8917c9   Johan Hedberg   Bluetooth: Move E...
2113
  		__hci_req_update_eir(&req);
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
2114
  	}
14c0b6082   Johan Hedberg   Bluetooth: Remove...
2115

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

92da60975   Johan Hedberg   Bluetooth: Fix UU...
2118
2119
2120
2121
  	err = hci_req_run(&req, set_class_complete);
  	if (err < 0) {
  		if (err != -ENODATA)
  			goto unlock;
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
2122

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2123
2124
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
  					hdev->dev_class, 3);
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
2125
2126
2127
2128
  		goto unlock;
  	}
  
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
890ea8988   Johan Hedberg   Bluetooth: Update...
2129
  	if (!cmd) {
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
2130
  		err = -ENOMEM;
890ea8988   Johan Hedberg   Bluetooth: Update...
2131
2132
2133
2134
  		goto unlock;
  	}
  
  	err = 0;
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
2135

b5235a65a   Johan Hedberg   Bluetooth: mgmt: ...
2136
  unlock:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2137
  	hci_dev_unlock(hdev);
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
2138
2139
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
2140
  static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
8ce8e2b56   Gustavo Padovan   Bluetooth: Fix co...
2141
  			  u16 len)
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2142
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
2143
  	struct mgmt_cp_load_link_keys *cp = data;
ba1d6936f   Johan Hedberg   Bluetooth: Fix bu...
2144
2145
  	const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
  				   sizeof(struct mgmt_link_key_info));
4e51eae9c   Szymon Janc   Bluetooth: Move i...
2146
  	u16 key_count, expected_len;
b1de97d8c   Marcel Holtmann   Bluetooth: Add ma...
2147
  	bool changed;
a492cd52b   Vinicius Costa Gomes   Revert "Bluetooth...
2148
  	int i;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2149

181d69535   Marcel Holtmann   Bluetooth: Replac...
2150
  	bt_dev_dbg(hdev, "sock %p", sk);
9060d5cf5   Marcel Holtmann   Bluetooth: Restri...
2151
2152
  
  	if (!lmp_bredr_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2153
2154
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
  				       MGMT_STATUS_NOT_SUPPORTED);
9060d5cf5   Marcel Holtmann   Bluetooth: Restri...
2155

1f350c872   Marcel Holtmann   Bluetooth: Fix br...
2156
  	key_count = __le16_to_cpu(cp->key_count);
ba1d6936f   Johan Hedberg   Bluetooth: Fix bu...
2157
  	if (key_count > max_key_count) {
2064ee332   Marcel Holtmann   Bluetooth: Use bt...
2158
2159
  		bt_dev_err(hdev, "load_link_keys: too big key_count value %u",
  			   key_count);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2160
2161
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
  				       MGMT_STATUS_INVALID_PARAMS);
ba1d6936f   Johan Hedberg   Bluetooth: Fix bu...
2162
  	}
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2163

5bec1fb86   Gustavo A. R. Silva   Bluetooth: Use st...
2164
  	expected_len = struct_size(cp, keys, key_count);
a492cd52b   Vinicius Costa Gomes   Revert "Bluetooth...
2165
  	if (expected_len != len) {
2064ee332   Marcel Holtmann   Bluetooth: Use bt...
2166
2167
  		bt_dev_err(hdev, "load_link_keys: expected %u bytes, got %u bytes",
  			   expected_len, len);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2168
2169
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
  				       MGMT_STATUS_INVALID_PARAMS);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2170
  	}
4ae14301c   Johan Hedberg   Bluetooth: Fix ch...
2171
  	if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2172
2173
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
  				       MGMT_STATUS_INVALID_PARAMS);
4ae14301c   Johan Hedberg   Bluetooth: Fix ch...
2174

181d69535   Marcel Holtmann   Bluetooth: Replac...
2175
2176
  	bt_dev_dbg(hdev, "debug_keys %u key_count %u", cp->debug_keys,
  		   key_count);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2177

4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
2178
2179
  	for (i = 0; i < key_count; i++) {
  		struct mgmt_link_key_info *key = &cp->keys[i];
8e9911327   Marcel Holtmann   Bluetooth: Limit ...
2180
  		if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2181
2182
2183
  			return mgmt_cmd_status(sk, hdev->id,
  					       MGMT_OP_LOAD_LINK_KEYS,
  					       MGMT_STATUS_INVALID_PARAMS);
4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
2184
  	}
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2185
  	hci_dev_lock(hdev);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2186
2187
  
  	hci_link_keys_clear(hdev);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2188
  	if (cp->debug_keys)
238be788f   Marcel Holtmann   Bluetooth: Introd...
2189
  		changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2190
  	else
a69d89272   Marcel Holtmann   Bluetooth: Introd...
2191
2192
  		changed = hci_dev_test_and_clear_flag(hdev,
  						      HCI_KEEP_DEBUG_KEYS);
b1de97d8c   Marcel Holtmann   Bluetooth: Add ma...
2193
2194
2195
  
  	if (changed)
  		new_settings(hdev, NULL);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2196

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

600a87490   Alain Michaud   Bluetooth: Implem...
2200
2201
2202
2203
2204
2205
2206
  		if (hci_is_blocked_key(hdev,
  				       HCI_BLOCKED_KEY_TYPE_LINKKEY,
  				       key->val)) {
  			bt_dev_warn(hdev, "Skipping blocked link key for %pMR",
  				    &key->addr.bdaddr);
  			continue;
  		}
58e9293c4   Johan Hedberg   Bluetooth: Fix ig...
2207
2208
2209
2210
2211
  		/* 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...
2212
2213
  		hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
  				 key->type, key->pin_len, NULL);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2214
  	}
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2215
  	mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
0e5f875a8   Johan Hedberg   Bluetooth: Add mi...
2216

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

a492cd52b   Vinicius Costa Gomes   Revert "Bluetooth...
2219
  	return 0;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2220
  }
b1078ad0b   Johan Hedberg   Bluetooth: Add De...
2221
  static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2222
  			   u8 addr_type, struct sock *skip_sk)
b1078ad0b   Johan Hedberg   Bluetooth: Add De...
2223
2224
2225
2226
2227
2228
2229
  {
  	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...
2230
  			  skip_sk);
b1078ad0b   Johan Hedberg   Bluetooth: Add De...
2231
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
2232
  static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2233
  			 u16 len)
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2234
  {
124f6e352   Johan Hedberg   Bluetooth: Update...
2235
2236
  	struct mgmt_cp_unpair_device *cp = data;
  	struct mgmt_rp_unpair_device rp;
fc64361ac   Johan Hedberg   Bluetooth: Disabl...
2237
  	struct hci_conn_params *params;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2238
  	struct mgmt_pending_cmd *cmd;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2239
  	struct hci_conn *conn;
ec182f039   Johan Hedberg   Bluetooth: Remove...
2240
  	u8 addr_type;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2241
  	int err;
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
2242
  	memset(&rp, 0, sizeof(rp));
124f6e352   Johan Hedberg   Bluetooth: Update...
2243
2244
  	bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
  	rp.addr.type = cp->addr.type;
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
2245

4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
2246
  	if (!bdaddr_type_is_valid(cp->addr.type))
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2247
2248
2249
  		return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
  					 MGMT_STATUS_INVALID_PARAMS,
  					 &rp, sizeof(rp));
4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
2250

118da70b7   Johan Hedberg   Bluetooth: Fix ch...
2251
  	if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2252
2253
2254
  		return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
  					 MGMT_STATUS_INVALID_PARAMS,
  					 &rp, sizeof(rp));
118da70b7   Johan Hedberg   Bluetooth: Fix ch...
2255

4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
2256
  	hci_dev_lock(hdev);
86a8cfc6d   Johan Hedberg   Bluetooth: mgmt: ...
2257
  	if (!hdev_is_powered(hdev)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2258
2259
2260
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
  					MGMT_STATUS_NOT_POWERED, &rp,
  					sizeof(rp));
86a8cfc6d   Johan Hedberg   Bluetooth: mgmt: ...
2261
2262
  		goto unlock;
  	}
e0b2b27e6   Johan Hedberg   Bluetooth: Fix mi...
2263
  	if (cp->addr.type == BDADDR_BREDR) {
89cbb0638   Alfonso Acosta   Bluetooth: Defer ...
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
  		/* 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...
2276
  		err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
ec182f039   Johan Hedberg   Bluetooth: Remove...
2277
2278
2279
2280
2281
2282
  		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 ...
2283
  		}
ec182f039   Johan Hedberg   Bluetooth: Remove...
2284
  		goto done;
e0b2b27e6   Johan Hedberg   Bluetooth: Fix mi...
2285
  	}
b0dbfb46b   Vinicius Costa Gomes   Bluetooth: Add su...
2286

ec182f039   Johan Hedberg   Bluetooth: Remove...
2287
2288
  	/* LE address type */
  	addr_type = le_addr_type(cp->addr.type);
cb28c306b   Matias Karhumaa   Bluetooth: SMP: f...
2289
2290
  	/* 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...
2291
  	if (err < 0) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2292
2293
2294
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
  					MGMT_STATUS_NOT_PAIRED, &rp,
  					sizeof(rp));
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2295
2296
  		goto unlock;
  	}
ec182f039   Johan Hedberg   Bluetooth: Remove...
2297
2298
2299
2300
2301
  	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...
2302

ec182f039   Johan Hedberg   Bluetooth: Remove...
2303
2304
2305
2306
  	/* 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...
2307
2308
2309
2310
2311
2312
2313
2314
  	/* 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...
2315
2316
2317
2318
2319
2320
2321
  	/* 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 ...
2322
2323
2324
  	/* If the connection variable is set, then termination of the
  	 * link is requested.
  	 */
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
2325
  	if (!conn) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2326
2327
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
  					&rp, sizeof(rp));
b1078ad0b   Johan Hedberg   Bluetooth: Add De...
2328
  		device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
2329
2330
  		goto unlock;
  	}
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2331

124f6e352   Johan Hedberg   Bluetooth: Update...
2332
  	cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2333
  			       sizeof(*cp));
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
2334
2335
2336
  	if (!cmd) {
  		err = -ENOMEM;
  		goto unlock;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2337
  	}
d8b7b1e49   Johan Hedberg   Bluetooth: Conver...
2338
  	cmd->cmd_complete = addr_cmd_complete;
89e0ccc88   Johan Hedberg   Bluetooth: Take a...
2339
  	err = hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM);
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
2340
2341
  	if (err < 0)
  		mgmt_pending_remove(cmd);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2342
  unlock:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2343
  	hci_dev_unlock(hdev);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2344
2345
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
2346
  static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2347
  		      u16 len)
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2348
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
2349
  	struct mgmt_cp_disconnect *cp = data;
06a63b19e   Johan Hedberg   Bluetooth: Fix re...
2350
  	struct mgmt_rp_disconnect rp;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2351
  	struct mgmt_pending_cmd *cmd;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2352
  	struct hci_conn *conn;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2353
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
2354
  	bt_dev_dbg(hdev, "sock %p", sk);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2355

06a63b19e   Johan Hedberg   Bluetooth: Fix re...
2356
2357
2358
  	memset(&rp, 0, sizeof(rp));
  	bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
  	rp.addr.type = cp->addr.type;
4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
2359
  	if (!bdaddr_type_is_valid(cp->addr.type))
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2360
2361
2362
  		return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
  					 MGMT_STATUS_INVALID_PARAMS,
  					 &rp, sizeof(rp));
4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
2363

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2364
  	hci_dev_lock(hdev);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2365
2366
  
  	if (!test_bit(HCI_UP, &hdev->flags)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2367
2368
2369
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
  					MGMT_STATUS_NOT_POWERED, &rp,
  					sizeof(rp));
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2370
2371
  		goto failed;
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
2372
  	if (pending_find(MGMT_OP_DISCONNECT, hdev)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2373
2374
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
  					MGMT_STATUS_BUSY, &rp, sizeof(rp));
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2375
2376
  		goto failed;
  	}
591f47f31   Andre Guedes   Bluetooth: Move a...
2377
  	if (cp->addr.type == BDADDR_BREDR)
8fc9ced39   Gustavo Padovan   Bluetooth: Fix co...
2378
2379
  		conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
  					       &cp->addr.bdaddr);
88c3df13c   Johan Hedberg   Bluetooth: Update...
2380
  	else
9d4c1cc15   Johan Hedberg   Bluetooth: Use hc...
2381
2382
  		conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr,
  					       le_addr_type(cp->addr.type));
365227e5f   Vinicius Costa Gomes   Bluetooth: Add su...
2383

f960727e6   Vishal Agarwal   Bluetooth: Fix se...
2384
  	if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2385
2386
2387
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
  					MGMT_STATUS_NOT_CONNECTED, &rp,
  					sizeof(rp));
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2388
2389
  		goto failed;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
2390
  	cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
366a03369   Johan Hedberg   Bluetooth: Make p...
2391
2392
  	if (!cmd) {
  		err = -ENOMEM;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2393
  		goto failed;
366a03369   Johan Hedberg   Bluetooth: Make p...
2394
  	}
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2395

f5818c224   Johan Hedberg   Bluetooth: Conver...
2396
  	cmd->cmd_complete = generic_cmd_complete;
e3f2f92a0   Johan Hedberg   Bluetooth: Use hc...
2397
  	err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2398
  	if (err < 0)
a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
2399
  		mgmt_pending_remove(cmd);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2400
2401
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2402
  	hci_dev_unlock(hdev);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2403
2404
  	return err;
  }
57c1477c2   Andre Guedes   Bluetooth: Rename...
2405
  static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
4c659c397   Johan Hedberg   Bluetooth: Add ad...
2406
2407
2408
  {
  	switch (link_type) {
  	case LE_LINK:
48264f069   Johan Hedberg   Bluetooth: Add pu...
2409
2410
  		switch (addr_type) {
  		case ADDR_LE_DEV_PUBLIC:
591f47f31   Andre Guedes   Bluetooth: Move a...
2411
  			return BDADDR_LE_PUBLIC;
0ed09148f   Andre Guedes   Bluetooth: Remove...
2412

48264f069   Johan Hedberg   Bluetooth: Add pu...
2413
  		default:
0ed09148f   Andre Guedes   Bluetooth: Remove...
2414
  			/* Fallback to LE Random address type */
591f47f31   Andre Guedes   Bluetooth: Move a...
2415
  			return BDADDR_LE_RANDOM;
48264f069   Johan Hedberg   Bluetooth: Add pu...
2416
  		}
0ed09148f   Andre Guedes   Bluetooth: Remove...
2417

4c659c397   Johan Hedberg   Bluetooth: Add ad...
2418
  	default:
0ed09148f   Andre Guedes   Bluetooth: Remove...
2419
  		/* Fallback to BR/EDR type */
591f47f31   Andre Guedes   Bluetooth: Move a...
2420
  		return BDADDR_BREDR;
4c659c397   Johan Hedberg   Bluetooth: Add ad...
2421
2422
  	}
  }
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2423
2424
  static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
  			   u16 data_len)
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
2425
  {
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
2426
  	struct mgmt_rp_get_connections *rp;
8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
2427
  	struct hci_conn *c;
60fc5fb66   Johan Hedberg   Bluetooth: mgmt: ...
2428
2429
  	int err;
  	u16 i;
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
2430

181d69535   Marcel Holtmann   Bluetooth: Replac...
2431
  	bt_dev_dbg(hdev, "sock %p", sk);
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
2432

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2433
  	hci_dev_lock(hdev);
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
2434

5f97c1df5   Johan Hedberg   Bluetooth: mgmt: ...
2435
  	if (!hdev_is_powered(hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2436
2437
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
  				      MGMT_STATUS_NOT_POWERED);
5f97c1df5   Johan Hedberg   Bluetooth: mgmt: ...
2438
2439
  		goto unlock;
  	}
60fc5fb66   Johan Hedberg   Bluetooth: mgmt: ...
2440
  	i = 0;
b644ba336   Johan Hedberg   Bluetooth: Update...
2441
2442
  	list_for_each_entry(c, &hdev->conn_hash.list, list) {
  		if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
60fc5fb66   Johan Hedberg   Bluetooth: mgmt: ...
2443
  			i++;
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
2444
  	}
72bb169e0   Gustavo A. R. Silva   Bluetooth: mgmt: ...
2445
  	rp = kmalloc(struct_size(rp, addr, i), GFP_KERNEL);
a38528f11   Johan Hedberg   Bluetooth: Create...
2446
  	if (!rp) {
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
2447
2448
2449
  		err = -ENOMEM;
  		goto unlock;
  	}
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
2450
  	i = 0;
4c659c397   Johan Hedberg   Bluetooth: Add ad...
2451
  	list_for_each_entry(c, &hdev->conn_hash.list, list) {
b644ba336   Johan Hedberg   Bluetooth: Update...
2452
2453
  		if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
  			continue;
4c659c397   Johan Hedberg   Bluetooth: Add ad...
2454
  		bacpy(&rp->addr[i].bdaddr, &c->dst);
57c1477c2   Andre Guedes   Bluetooth: Rename...
2455
  		rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
0ed09148f   Andre Guedes   Bluetooth: Remove...
2456
  		if (c->type == SCO_LINK || c->type == ESCO_LINK)
4c659c397   Johan Hedberg   Bluetooth: Add ad...
2457
2458
2459
  			continue;
  		i++;
  	}
eb55ef07a   Marcel Holtmann   Bluetooth: Fix br...
2460
  	rp->conn_count = cpu_to_le16(i);
60fc5fb66   Johan Hedberg   Bluetooth: mgmt: ...
2461

4c659c397   Johan Hedberg   Bluetooth: Add ad...
2462
  	/* Recalculate length in case of filtered SCO connections, etc */
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2463
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
72bb169e0   Gustavo A. R. Silva   Bluetooth: mgmt: ...
2464
  				struct_size(rp, addr, i));
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
2465

a38528f11   Johan Hedberg   Bluetooth: Create...
2466
  	kfree(rp);
5f97c1df5   Johan Hedberg   Bluetooth: mgmt: ...
2467
2468
  
  unlock:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2469
  	hci_dev_unlock(hdev);
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
2470
2471
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
2472
  static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2473
  				   struct mgmt_cp_pin_code_neg_reply *cp)
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
2474
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2475
  	struct mgmt_pending_cmd *cmd;
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
2476
  	int err;
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
2477
  	cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2478
  			       sizeof(*cp));
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
2479
2480
  	if (!cmd)
  		return -ENOMEM;
dd7e39bbf   Arek Lichwa   Bluetooth: Fix NU...
2481
  	cmd->cmd_complete = addr_cmd_complete;
d8457698e   Johan Hedberg   Bluetooth: mgmt: ...
2482
  	err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2483
  			   sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
2484
2485
2486
2487
2488
  	if (err < 0)
  		mgmt_pending_remove(cmd);
  
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
2489
  static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2490
  			  u16 len)
980e1a537   Johan Hedberg   Bluetooth: Add su...
2491
  {
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
2492
  	struct hci_conn *conn;
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
2493
  	struct mgmt_cp_pin_code_reply *cp = data;
980e1a537   Johan Hedberg   Bluetooth: Add su...
2494
  	struct hci_cp_pin_code_reply reply;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2495
  	struct mgmt_pending_cmd *cmd;
980e1a537   Johan Hedberg   Bluetooth: Add su...
2496
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
2497
  	bt_dev_dbg(hdev, "sock %p", sk);
980e1a537   Johan Hedberg   Bluetooth: Add su...
2498

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2499
  	hci_dev_lock(hdev);
980e1a537   Johan Hedberg   Bluetooth: Add su...
2500

4b34ee782   Johan Hedberg   Bluetooth: mgmt: ...
2501
  	if (!hdev_is_powered(hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2502
2503
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
  				      MGMT_STATUS_NOT_POWERED);
980e1a537   Johan Hedberg   Bluetooth: Add su...
2504
2505
  		goto failed;
  	}
d8457698e   Johan Hedberg   Bluetooth: mgmt: ...
2506
  	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
2507
  	if (!conn) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2508
2509
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
  				      MGMT_STATUS_NOT_CONNECTED);
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
2510
2511
2512
2513
  		goto failed;
  	}
  
  	if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
d8457698e   Johan Hedberg   Bluetooth: mgmt: ...
2514
2515
2516
  		struct mgmt_cp_pin_code_neg_reply ncp;
  
  		memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
2517

2064ee332   Marcel Holtmann   Bluetooth: Use bt...
2518
  		bt_dev_err(hdev, "PIN code is not 16 bytes long");
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
2519

bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
2520
  		err = send_pin_code_neg_reply(sk, hdev, &ncp);
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
2521
  		if (err >= 0)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2522
2523
  			err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
  					      MGMT_STATUS_INVALID_PARAMS);
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
2524
2525
2526
  
  		goto failed;
  	}
00abfe444   Gustavo F. Padovan   Bluetooth: Fix co...
2527
  	cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
366a03369   Johan Hedberg   Bluetooth: Make p...
2528
2529
  	if (!cmd) {
  		err = -ENOMEM;
980e1a537   Johan Hedberg   Bluetooth: Add su...
2530
  		goto failed;
366a03369   Johan Hedberg   Bluetooth: Make p...
2531
  	}
980e1a537   Johan Hedberg   Bluetooth: Add su...
2532

7776d1d80   Johan Hedberg   Bluetooth: Use cm...
2533
  	cmd->cmd_complete = addr_cmd_complete;
d8457698e   Johan Hedberg   Bluetooth: mgmt: ...
2534
  	bacpy(&reply.bdaddr, &cp->addr.bdaddr);
980e1a537   Johan Hedberg   Bluetooth: Add su...
2535
  	reply.pin_len = cp->pin_len;
24718ca5e   Waldemar Rymarkiewicz   Bluetooth: Remove...
2536
  	memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
980e1a537   Johan Hedberg   Bluetooth: Add su...
2537
2538
2539
  
  	err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
  	if (err < 0)
a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
2540
  		mgmt_pending_remove(cmd);
980e1a537   Johan Hedberg   Bluetooth: Add su...
2541
2542
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2543
  	hci_dev_unlock(hdev);
980e1a537   Johan Hedberg   Bluetooth: Add su...
2544
2545
  	return err;
  }
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2546
2547
  static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
  			     u16 len)
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
2548
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
2549
  	struct mgmt_cp_set_io_capability *cp = data;
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
2550

181d69535   Marcel Holtmann   Bluetooth: Replac...
2551
  	bt_dev_dbg(hdev, "sock %p", sk);
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
2552

4ec86d4c8   Johan Hedberg   Bluetooth: Fix va...
2553
  	if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
9db5c6295   Marcel Holtmann   Bluetooth: Use co...
2554
2555
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
  				       MGMT_STATUS_INVALID_PARAMS);
4ec86d4c8   Johan Hedberg   Bluetooth: Fix va...
2556

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2557
  	hci_dev_lock(hdev);
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
2558
2559
  
  	hdev->io_capability = cp->io_capability;
181d69535   Marcel Holtmann   Bluetooth: Replac...
2560
  	bt_dev_dbg(hdev, "IO capability set to 0x%02x", hdev->io_capability);
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
2561

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

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2564
2565
  	return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
  				 NULL, 0);
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
2566
  }
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2567
  static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2568
2569
  {
  	struct hci_dev *hdev = conn->hdev;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2570
  	struct mgmt_pending_cmd *cmd;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2571

2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
2572
  	list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2573
2574
  		if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
  			continue;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2575
2576
2577
2578
2579
2580
2581
2582
  		if (cmd->user_data != conn)
  			continue;
  
  		return cmd;
  	}
  
  	return NULL;
  }
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2583
  static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2584
2585
2586
  {
  	struct mgmt_rp_pair_device rp;
  	struct hci_conn *conn = cmd->user_data;
9df746535   Johan Hedberg   Bluetooth: Add re...
2587
  	int err;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2588

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

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2592
2593
  	err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
  				status, &rp, sizeof(rp));
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2594
2595
2596
2597
2598
  
  	/* 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...
2599
  	hci_conn_drop(conn);
89cbb0638   Alfonso Acosta   Bluetooth: Defer ...
2600
2601
2602
2603
2604
  
  	/* 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...
2605
2606
  
  	hci_conn_put(conn);
9df746535   Johan Hedberg   Bluetooth: Add re...
2607
2608
  
  	return err;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2609
  }
f4a407bef   Johan Hedberg   Bluetooth: Wait f...
2610
2611
2612
  void mgmt_smp_complete(struct hci_conn *conn, bool complete)
  {
  	u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2613
  	struct mgmt_pending_cmd *cmd;
f4a407bef   Johan Hedberg   Bluetooth: Wait f...
2614
2615
  
  	cmd = find_pairing(conn);
a511b35ba   Johan Hedberg   Bluetooth: Fix in...
2616
  	if (cmd) {
04ab2749e   Johan Hedberg   Bluetooth: Conver...
2617
  		cmd->cmd_complete(cmd, status);
a511b35ba   Johan Hedberg   Bluetooth: Fix in...
2618
2619
  		mgmt_pending_remove(cmd);
  	}
f4a407bef   Johan Hedberg   Bluetooth: Wait f...
2620
  }
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2621
2622
  static void pairing_complete_cb(struct hci_conn *conn, u8 status)
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2623
  	struct mgmt_pending_cmd *cmd;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2624
2625
2626
2627
  
  	BT_DBG("status %u", status);
  
  	cmd = find_pairing(conn);
a511b35ba   Johan Hedberg   Bluetooth: Fix in...
2628
  	if (!cmd) {
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2629
  		BT_DBG("Unable to find a pending command");
a511b35ba   Johan Hedberg   Bluetooth: Fix in...
2630
2631
2632
2633
2634
  		return;
  	}
  
  	cmd->cmd_complete(cmd, mgmt_status(status));
  	mgmt_pending_remove(cmd);
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2635
  }
f4a407bef   Johan Hedberg   Bluetooth: Wait f...
2636
  static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
4c47d7396   Vishal Agarwal   Bluetooth: Fix LE...
2637
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2638
  	struct mgmt_pending_cmd *cmd;
4c47d7396   Vishal Agarwal   Bluetooth: Fix LE...
2639
2640
2641
2642
2643
2644
2645
  
  	BT_DBG("status %u", status);
  
  	if (!status)
  		return;
  
  	cmd = find_pairing(conn);
a511b35ba   Johan Hedberg   Bluetooth: Fix in...
2646
  	if (!cmd) {
4c47d7396   Vishal Agarwal   Bluetooth: Fix LE...
2647
  		BT_DBG("Unable to find a pending command");
a511b35ba   Johan Hedberg   Bluetooth: Fix in...
2648
2649
2650
2651
2652
  		return;
  	}
  
  	cmd->cmd_complete(cmd, mgmt_status(status));
  	mgmt_pending_remove(cmd);
4c47d7396   Vishal Agarwal   Bluetooth: Fix LE...
2653
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
2654
  static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2655
  		       u16 len)
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2656
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
2657
  	struct mgmt_cp_pair_device *cp = data;
1425acb74   Johan Hedberg   Bluetooth: Fix mg...
2658
  	struct mgmt_rp_pair_device rp;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2659
  	struct mgmt_pending_cmd *cmd;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2660
2661
  	u8 sec_level, auth_type;
  	struct hci_conn *conn;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2662
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
2663
  	bt_dev_dbg(hdev, "sock %p", sk);
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2664

f950a30e2   Szymon Janc   Bluetooth: Fix pa...
2665
2666
2667
  	memset(&rp, 0, sizeof(rp));
  	bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
  	rp.addr.type = cp->addr.type;
4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
2668
  	if (!bdaddr_type_is_valid(cp->addr.type))
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2669
2670
2671
  		return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
  					 MGMT_STATUS_INVALID_PARAMS,
  					 &rp, sizeof(rp));
4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
2672

4ec86d4c8   Johan Hedberg   Bluetooth: Fix va...
2673
  	if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2674
2675
2676
  		return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
  					 MGMT_STATUS_INVALID_PARAMS,
  					 &rp, sizeof(rp));
4ec86d4c8   Johan Hedberg   Bluetooth: Fix va...
2677

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

5f97c1df5   Johan Hedberg   Bluetooth: mgmt: ...
2680
  	if (!hdev_is_powered(hdev)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2681
2682
2683
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
  					MGMT_STATUS_NOT_POWERED, &rp,
  					sizeof(rp));
5f97c1df5   Johan Hedberg   Bluetooth: mgmt: ...
2684
2685
  		goto unlock;
  	}
55e76b389   Johan Hedberg   Bluetooth: Add 'A...
2686
2687
2688
2689
2690
2691
  	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...
2692
  	sec_level = BT_SECURITY_MEDIUM;
6fd6b915b   Mikel Astiz   Bluetooth: Refact...
2693
  	auth_type = HCI_AT_DEDICATED_BONDING;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2694

6f77d8c75   Andre Guedes   Bluetooth: Move a...
2695
  	if (cp->addr.type == BDADDR_BREDR) {
04a6c5898   Andre Guedes   Bluetooth: Refact...
2696
  		conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
76b139965   Manish Mandlik   Bluetooth: Termin...
2697
  				       auth_type, CONN_REASON_PAIR_DEVICE);
6f77d8c75   Andre Guedes   Bluetooth: Move a...
2698
  	} else {
85813a7ec   Johan Hedberg   Bluetooth: Add le...
2699
  		u8 addr_type = le_addr_type(cp->addr.type);
5157b8a50   Jakub Pawlowski   Bluetooth: Fix in...
2700
  		struct hci_conn_params *p;
6f77d8c75   Andre Guedes   Bluetooth: Move a...
2701

7c264b100   Marcel Holtmann   Bluetooth: Add de...
2702
2703
2704
2705
2706
2707
2708
2709
2710
  		/* 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...
2711
2712
2713
2714
  		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...
2715

76b139965   Manish Mandlik   Bluetooth: Termin...
2716
2717
2718
  		conn = hci_connect_le_scan(hdev, &cp->addr.bdaddr, addr_type,
  					   sec_level, HCI_LE_CONN_TIMEOUT,
  					   CONN_REASON_PAIR_DEVICE);
6f77d8c75   Andre Guedes   Bluetooth: Move a...
2719
  	}
7a512d017   Vinicius Costa Gomes   Bluetooth: Add su...
2720

30e762721   Ville Tervo   Bluetooth: Use ER...
2721
  	if (IS_ERR(conn)) {
489dc48e7   Andrzej Kaczmarek   Bluetooth: Return...
2722
2723
2724
2725
  		int status;
  
  		if (PTR_ERR(conn) == -EBUSY)
  			status = MGMT_STATUS_BUSY;
faa810303   Lukasz Rymanowski   Bluetooth: Enhanc...
2726
2727
2728
2729
  		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...
2730
2731
  		else
  			status = MGMT_STATUS_CONNECT_FAILED;
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2732
2733
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
  					status, &rp, sizeof(rp));
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2734
2735
2736
2737
  		goto unlock;
  	}
  
  	if (conn->connect_cfm_cb) {
76a68ba0a   David Herrmann   Bluetooth: rename...
2738
  		hci_conn_drop(conn);
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2739
2740
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
  					MGMT_STATUS_BUSY, &rp, sizeof(rp));
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2741
2742
  		goto unlock;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
2743
  	cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2744
2745
  	if (!cmd) {
  		err = -ENOMEM;
76a68ba0a   David Herrmann   Bluetooth: rename...
2746
  		hci_conn_drop(conn);
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2747
2748
  		goto unlock;
  	}
04ab2749e   Johan Hedberg   Bluetooth: Conver...
2749
  	cmd->cmd_complete = pairing_complete;
7a512d017   Vinicius Costa Gomes   Bluetooth: Add su...
2750
  	/* For LE, just connecting isn't a proof that the pairing finished */
f4a407bef   Johan Hedberg   Bluetooth: Wait f...
2751
  	if (cp->addr.type == BDADDR_BREDR) {
7a512d017   Vinicius Costa Gomes   Bluetooth: Add su...
2752
  		conn->connect_cfm_cb = pairing_complete_cb;
f4a407bef   Johan Hedberg   Bluetooth: Wait f...
2753
2754
2755
2756
2757
2758
2759
  		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...
2760

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

6f78fd4bb   Johan Hedberg   Bluetooth: Fix ch...
2764
  	if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
a511b35ba   Johan Hedberg   Bluetooth: Fix in...
2765
2766
2767
2768
  	    hci_conn_security(conn, sec_level, auth_type, true)) {
  		cmd->cmd_complete(cmd, 0);
  		mgmt_pending_remove(cmd);
  	}
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2769
2770
2771
2772
  
  	err = 0;
  
  unlock:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2773
  	hci_dev_unlock(hdev);
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2774
2775
  	return err;
  }
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2776
2777
  static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
  			      u16 len)
28424707a   Johan Hedberg   Bluetooth: mgmt: ...
2778
  {
0f4e68cf6   Johan Hedberg   Bluetooth: mgmt: ...
2779
  	struct mgmt_addr_info *addr = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2780
  	struct mgmt_pending_cmd *cmd;
28424707a   Johan Hedberg   Bluetooth: mgmt: ...
2781
2782
  	struct hci_conn *conn;
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
2783
  	bt_dev_dbg(hdev, "sock %p", sk);
28424707a   Johan Hedberg   Bluetooth: mgmt: ...
2784

28424707a   Johan Hedberg   Bluetooth: mgmt: ...
2785
  	hci_dev_lock(hdev);
5f97c1df5   Johan Hedberg   Bluetooth: mgmt: ...
2786
  	if (!hdev_is_powered(hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2787
2788
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
  				      MGMT_STATUS_NOT_POWERED);
5f97c1df5   Johan Hedberg   Bluetooth: mgmt: ...
2789
2790
  		goto unlock;
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
2791
  	cmd = pending_find(MGMT_OP_PAIR_DEVICE, hdev);
28424707a   Johan Hedberg   Bluetooth: mgmt: ...
2792
  	if (!cmd) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2793
2794
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
  				      MGMT_STATUS_INVALID_PARAMS);
28424707a   Johan Hedberg   Bluetooth: mgmt: ...
2795
2796
2797
2798
2799
2800
  		goto unlock;
  	}
  
  	conn = cmd->user_data;
  
  	if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2801
2802
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
  				      MGMT_STATUS_INVALID_PARAMS);
28424707a   Johan Hedberg   Bluetooth: mgmt: ...
2803
2804
  		goto unlock;
  	}
a511b35ba   Johan Hedberg   Bluetooth: Fix in...
2805
2806
  	cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
  	mgmt_pending_remove(cmd);
28424707a   Johan Hedberg   Bluetooth: mgmt: ...
2807

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2808
2809
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
  				addr, sizeof(*addr));
76b139965   Manish Mandlik   Bluetooth: Termin...
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
  
  	/* Since user doesn't want to proceed with the connection, abort any
  	 * ongoing pairing and then terminate the link if it was created
  	 * because of the pair device action.
  	 */
  	if (addr->type == BDADDR_BREDR)
  		hci_remove_link_key(hdev, &addr->bdaddr);
  	else
  		smp_cancel_and_remove_pairing(hdev, &addr->bdaddr,
  					      le_addr_type(addr->type));
  
  	if (conn->conn_reason == CONN_REASON_PAIR_DEVICE)
  		hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM);
28424707a   Johan Hedberg   Bluetooth: mgmt: ...
2823
2824
  unlock:
  	hci_dev_unlock(hdev);
28424707a   Johan Hedberg   Bluetooth: mgmt: ...
2825
2826
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
2827
  static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
1707c60e5   Johan Hedberg   Bluetooth: Simpli...
2828
  			     struct mgmt_addr_info *addr, u16 mgmt_op,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2829
  			     u16 hci_op, __le32 passkey)
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2830
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2831
  	struct mgmt_pending_cmd *cmd;
0df4c185e   Brian Gix   Bluetooth: User P...
2832
  	struct hci_conn *conn;
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2833
  	int err;
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2834
  	hci_dev_lock(hdev);
08ba53824   Johan Hedberg   Bluetooth: Fix mi...
2835

4b34ee782   Johan Hedberg   Bluetooth: mgmt: ...
2836
  	if (!hdev_is_powered(hdev)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2837
2838
2839
  		err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
  					MGMT_STATUS_NOT_POWERED, addr,
  					sizeof(*addr));
0df4c185e   Brian Gix   Bluetooth: User P...
2840
  		goto done;
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2841
  	}
1707c60e5   Johan Hedberg   Bluetooth: Simpli...
2842
2843
  	if (addr->type == BDADDR_BREDR)
  		conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
272d90df2   Johan Hedberg   Bluetooth: Add ad...
2844
  	else
9d4c1cc15   Johan Hedberg   Bluetooth: Use hc...
2845
2846
  		conn = hci_conn_hash_lookup_le(hdev, &addr->bdaddr,
  					       le_addr_type(addr->type));
272d90df2   Johan Hedberg   Bluetooth: Add ad...
2847
2848
  
  	if (!conn) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2849
2850
2851
  		err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
  					MGMT_STATUS_NOT_CONNECTED, addr,
  					sizeof(*addr));
272d90df2   Johan Hedberg   Bluetooth: Add ad...
2852
2853
  		goto done;
  	}
47c15e2b3   Brian Gix   Bluetooth: Differ...
2854

1707c60e5   Johan Hedberg   Bluetooth: Simpli...
2855
  	if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
5fe57d9e9   Brian Gix   Bluetooth: Add SM...
2856
  		err = smp_user_confirm_reply(conn, mgmt_op, passkey);
5fe57d9e9   Brian Gix   Bluetooth: Add SM...
2857
  		if (!err)
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2858
2859
2860
  			err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
  						MGMT_STATUS_SUCCESS, addr,
  						sizeof(*addr));
5fe57d9e9   Brian Gix   Bluetooth: Add SM...
2861
  		else
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2862
2863
2864
  			err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
  						MGMT_STATUS_FAILED, addr,
  						sizeof(*addr));
47c15e2b3   Brian Gix   Bluetooth: Differ...
2865

47c15e2b3   Brian Gix   Bluetooth: Differ...
2866
2867
  		goto done;
  	}
1707c60e5   Johan Hedberg   Bluetooth: Simpli...
2868
  	cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2869
2870
  	if (!cmd) {
  		err = -ENOMEM;
0df4c185e   Brian Gix   Bluetooth: User P...
2871
  		goto done;
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2872
  	}
7776d1d80   Johan Hedberg   Bluetooth: Use cm...
2873
  	cmd->cmd_complete = addr_cmd_complete;
0df4c185e   Brian Gix   Bluetooth: User P...
2874
  	/* Continue with pairing via HCI */
604086b73   Brian Gix   Bluetooth: Add Us...
2875
2876
  	if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
  		struct hci_cp_user_passkey_reply cp;
1707c60e5   Johan Hedberg   Bluetooth: Simpli...
2877
  		bacpy(&cp.bdaddr, &addr->bdaddr);
604086b73   Brian Gix   Bluetooth: Add Us...
2878
2879
2880
  		cp.passkey = passkey;
  		err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
  	} else
1707c60e5   Johan Hedberg   Bluetooth: Simpli...
2881
2882
  		err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
  				   &addr->bdaddr);
604086b73   Brian Gix   Bluetooth: Add Us...
2883

a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
2884
2885
  	if (err < 0)
  		mgmt_pending_remove(cmd);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2886

0df4c185e   Brian Gix   Bluetooth: User P...
2887
  done:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
2888
  	hci_dev_unlock(hdev);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2889
2890
  	return err;
  }
afeb019d0   Jaganath Kanakkassery   Bluetooth: Refact...
2891
2892
2893
2894
  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;
181d69535   Marcel Holtmann   Bluetooth: Replac...
2895
  	bt_dev_dbg(hdev, "sock %p", sk);
afeb019d0   Jaganath Kanakkassery   Bluetooth: Refact...
2896

1707c60e5   Johan Hedberg   Bluetooth: Simpli...
2897
  	return user_pairing_resp(sk, hdev, &cp->addr,
afeb019d0   Jaganath Kanakkassery   Bluetooth: Refact...
2898
2899
2900
  				MGMT_OP_PIN_CODE_NEG_REPLY,
  				HCI_OP_PIN_CODE_NEG_REPLY, 0);
  }
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2901
2902
  static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
  			      u16 len)
0df4c185e   Brian Gix   Bluetooth: User P...
2903
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
2904
  	struct mgmt_cp_user_confirm_reply *cp = data;
0df4c185e   Brian Gix   Bluetooth: User P...
2905

181d69535   Marcel Holtmann   Bluetooth: Replac...
2906
  	bt_dev_dbg(hdev, "sock %p", sk);
0df4c185e   Brian Gix   Bluetooth: User P...
2907
2908
  
  	if (len != sizeof(*cp))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2909
2910
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
  				       MGMT_STATUS_INVALID_PARAMS);
0df4c185e   Brian Gix   Bluetooth: User P...
2911

1707c60e5   Johan Hedberg   Bluetooth: Simpli...
2912
  	return user_pairing_resp(sk, hdev, &cp->addr,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2913
2914
  				 MGMT_OP_USER_CONFIRM_REPLY,
  				 HCI_OP_USER_CONFIRM_REPLY, 0);
0df4c185e   Brian Gix   Bluetooth: User P...
2915
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
2916
  static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2917
  				  void *data, u16 len)
0df4c185e   Brian Gix   Bluetooth: User P...
2918
  {
c9c2659f1   Johan Hedberg   Bluetooth: Use co...
2919
  	struct mgmt_cp_user_confirm_neg_reply *cp = data;
0df4c185e   Brian Gix   Bluetooth: User P...
2920

181d69535   Marcel Holtmann   Bluetooth: Replac...
2921
  	bt_dev_dbg(hdev, "sock %p", sk);
0df4c185e   Brian Gix   Bluetooth: User P...
2922

1707c60e5   Johan Hedberg   Bluetooth: Simpli...
2923
  	return user_pairing_resp(sk, hdev, &cp->addr,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2924
2925
  				 MGMT_OP_USER_CONFIRM_NEG_REPLY,
  				 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
0df4c185e   Brian Gix   Bluetooth: User P...
2926
  }
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2927
2928
  static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
  			      u16 len)
604086b73   Brian Gix   Bluetooth: Add Us...
2929
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
2930
  	struct mgmt_cp_user_passkey_reply *cp = data;
604086b73   Brian Gix   Bluetooth: Add Us...
2931

181d69535   Marcel Holtmann   Bluetooth: Replac...
2932
  	bt_dev_dbg(hdev, "sock %p", sk);
604086b73   Brian Gix   Bluetooth: Add Us...
2933

1707c60e5   Johan Hedberg   Bluetooth: Simpli...
2934
  	return user_pairing_resp(sk, hdev, &cp->addr,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2935
2936
  				 MGMT_OP_USER_PASSKEY_REPLY,
  				 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
604086b73   Brian Gix   Bluetooth: Add Us...
2937
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
2938
  static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2939
  				  void *data, u16 len)
604086b73   Brian Gix   Bluetooth: Add Us...
2940
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
2941
  	struct mgmt_cp_user_passkey_neg_reply *cp = data;
604086b73   Brian Gix   Bluetooth: Add Us...
2942

181d69535   Marcel Holtmann   Bluetooth: Replac...
2943
  	bt_dev_dbg(hdev, "sock %p", sk);
604086b73   Brian Gix   Bluetooth: Add Us...
2944

1707c60e5   Johan Hedberg   Bluetooth: Simpli...
2945
  	return user_pairing_resp(sk, hdev, &cp->addr,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
2946
2947
  				 MGMT_OP_USER_PASSKEY_NEG_REPLY,
  				 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
604086b73   Brian Gix   Bluetooth: Add Us...
2948
  }
7c295c480   MichaƂ Narajowski   Bluetooth: Add su...
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
  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...
2977
  static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
139289713   Johan Hedberg   Bluetooth: Fix wa...
2978
2979
  {
  	struct mgmt_cp_set_local_name *cp;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
2980
  	struct mgmt_pending_cmd *cmd;
139289713   Johan Hedberg   Bluetooth: Fix wa...
2981

181d69535   Marcel Holtmann   Bluetooth: Replac...
2982
  	bt_dev_dbg(hdev, "status 0x%02x", status);
139289713   Johan Hedberg   Bluetooth: Fix wa...
2983
2984
  
  	hci_dev_lock(hdev);
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
2985
  	cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
139289713   Johan Hedberg   Bluetooth: Fix wa...
2986
2987
2988
2989
  	if (!cmd)
  		goto unlock;
  
  	cp = cmd->param;
7c295c480   MichaƂ Narajowski   Bluetooth: Add su...
2990
  	if (status) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
2991
2992
  		mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
  			        mgmt_status(status));
7c295c480   MichaƂ Narajowski   Bluetooth: Add su...
2993
  	} else {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
2994
2995
  		mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
  				  cp, sizeof(*cp));
139289713   Johan Hedberg   Bluetooth: Fix wa...
2996

7c295c480   MichaƂ Narajowski   Bluetooth: Add su...
2997
2998
2999
  		if (hci_dev_test_flag(hdev, HCI_LE_ADV))
  			adv_expire(hdev, MGMT_ADV_FLAG_LOCAL_NAME);
  	}
139289713   Johan Hedberg   Bluetooth: Fix wa...
3000
3001
3002
3003
3004
  	mgmt_pending_remove(cmd);
  
  unlock:
  	hci_dev_unlock(hdev);
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
3005
  static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
3006
  			  u16 len)
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
3007
  {
2b4bf3974   Johan Hedberg   Bluetooth: mgmt: ...
3008
  	struct mgmt_cp_set_local_name *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
3009
  	struct mgmt_pending_cmd *cmd;
890ea8988   Johan Hedberg   Bluetooth: Update...
3010
  	struct hci_request req;
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
3011
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
3012
  	bt_dev_dbg(hdev, "sock %p", sk);
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
3013

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
3014
  	hci_dev_lock(hdev);
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
3015

b3f2ca944   Johan Hedberg   Bluetooth: Fix se...
3016
3017
3018
3019
3020
3021
  	/* 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...
3022
3023
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
  					data, len);
b3f2ca944   Johan Hedberg   Bluetooth: Fix se...
3024
3025
  		goto failed;
  	}
2b4bf3974   Johan Hedberg   Bluetooth: mgmt: ...
3026
  	memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
28cc7bde5   Johan Hedberg   Bluetooth: mgmt: ...
3027

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

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
3031
3032
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
  					data, len);
28cc7bde5   Johan Hedberg   Bluetooth: mgmt: ...
3033
3034
  		if (err < 0)
  			goto failed;
5504c3a31   Marcel Holtmann   Bluetooth: Use in...
3035
3036
  		err = mgmt_limited_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data,
  					 len, HCI_MGMT_LOCAL_NAME_EVENTS, sk);
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
3037
  		ext_info_changed(hdev, sk);
28cc7bde5   Johan Hedberg   Bluetooth: mgmt: ...
3038

b5235a65a   Johan Hedberg   Bluetooth: mgmt: ...
3039
3040
  		goto failed;
  	}
28cc7bde5   Johan Hedberg   Bluetooth: mgmt: ...
3041
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
3042
3043
3044
3045
  	if (!cmd) {
  		err = -ENOMEM;
  		goto failed;
  	}
139289713   Johan Hedberg   Bluetooth: Fix wa...
3046
  	memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
890ea8988   Johan Hedberg   Bluetooth: Update...
3047
  	hci_req_init(&req, hdev);
3f985050f   Johan Hedberg   Bluetooth: Fix lo...
3048
3049
  
  	if (lmp_bredr_capable(hdev)) {
00cf5040b   Johan Hedberg   Bluetooth: HCI na...
3050
  		__hci_req_update_name(&req);
b1a8917c9   Johan Hedberg   Bluetooth: Move E...
3051
  		__hci_req_update_eir(&req);
3f985050f   Johan Hedberg   Bluetooth: Fix lo...
3052
  	}
7a5f4990a   Marcel Holtmann   Bluetooth: Store ...
3053
3054
3055
  	/* 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...
3056
  	if (lmp_le_capable(hdev) && hci_dev_test_flag(hdev, HCI_ADVERTISING))
cab054ab4   Johan Hedberg   Bluetooth: Clean ...
3057
  		__hci_req_update_scan_rsp_data(&req, hdev->cur_adv_instance);
3f985050f   Johan Hedberg   Bluetooth: Fix lo...
3058

139289713   Johan Hedberg   Bluetooth: Fix wa...
3059
  	err = hci_req_run(&req, set_name_complete);
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
3060
3061
3062
3063
  	if (err < 0)
  		mgmt_pending_remove(cmd);
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
3064
  	hci_dev_unlock(hdev);
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
3065
3066
  	return err;
  }
c4960ecf2   MichaƂ Narajowski   Bluetooth: Add su...
3067
3068
3069
3070
  static int set_appearance(struct sock *sk, struct hci_dev *hdev, void *data,
  			  u16 len)
  {
  	struct mgmt_cp_set_appearance *cp = data;
6613babaf   Alain Michaud   Bluetooth: fix ap...
3071
  	u16 appearance;
c4960ecf2   MichaƂ Narajowski   Bluetooth: Add su...
3072
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
3073
  	bt_dev_dbg(hdev, "sock %p", sk);
c4960ecf2   MichaƂ Narajowski   Bluetooth: Add su...
3074

af4168c5a   MichaƂ Narajowski   Bluetooth: Set ap...
3075
3076
3077
  	if (!lmp_le_capable(hdev))
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_APPEARANCE,
  				       MGMT_STATUS_NOT_SUPPORTED);
6613babaf   Alain Michaud   Bluetooth: fix ap...
3078
  	appearance = le16_to_cpu(cp->appearance);
c4960ecf2   MichaƂ Narajowski   Bluetooth: Add su...
3079
3080
  
  	hci_dev_lock(hdev);
6613babaf   Alain Michaud   Bluetooth: fix ap...
3081
3082
  	if (hdev->appearance != appearance) {
  		hdev->appearance = appearance;
c4960ecf2   MichaƂ Narajowski   Bluetooth: Add su...
3083
3084
3085
  
  		if (hci_dev_test_flag(hdev, HCI_LE_ADV))
  			adv_expire(hdev, MGMT_ADV_FLAG_APPEARANCE);
e74317f43   MichaƂ Narajowski   Bluetooth: Fix mi...
3086
3087
  
  		ext_info_changed(hdev, sk);
c4960ecf2   MichaƂ Narajowski   Bluetooth: Add su...
3088
3089
3090
3091
3092
3093
3094
3095
3096
  	}
  
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_APPEARANCE, 0, NULL,
  				0);
  
  	hci_dev_unlock(hdev);
  
  	return err;
  }
6244691fe   Jaganath Kanakkassery   Bluetooth: Implem...
3097
3098
3099
3100
  static int get_phy_configuration(struct sock *sk, struct hci_dev *hdev,
  				 void *data, u16 len)
  {
  	struct mgmt_rp_get_phy_confguration rp;
181d69535   Marcel Holtmann   Bluetooth: Replac...
3101
  	bt_dev_dbg(hdev, "sock %p", sk);
6244691fe   Jaganath Kanakkassery   Bluetooth: Implem...
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
  
  	hci_dev_lock(hdev);
  
  	memset(&rp, 0, sizeof(rp));
  
  	rp.supported_phys = cpu_to_le32(get_supported_phys(hdev));
  	rp.selected_phys = cpu_to_le32(get_selected_phys(hdev));
  	rp.configurable_phys = cpu_to_le32(get_configurable_phys(hdev));
  
  	hci_dev_unlock(hdev);
  
  	return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_PHY_CONFIGURATION, 0,
  				 &rp, sizeof(rp));
  }
b7c23df85   Jaganath Kanakkassery   Bluetooth: Implem...
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
  int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip)
  {
  	struct mgmt_ev_phy_configuration_changed ev;
  
  	memset(&ev, 0, sizeof(ev));
  
  	ev.selected_phys = cpu_to_le32(get_selected_phys(hdev));
  
  	return mgmt_event(MGMT_EV_PHY_CONFIGURATION_CHANGED, hdev, &ev,
  			  sizeof(ev), skip);
  }
0314f2867   Jaganath Kanakkassery   Bluetooth: Implem...
3127
3128
3129
  static void set_default_phy_complete(struct hci_dev *hdev, u8 status,
  				     u16 opcode, struct sk_buff *skb)
  {
0314f2867   Jaganath Kanakkassery   Bluetooth: Implem...
3130
  	struct mgmt_pending_cmd *cmd;
181d69535   Marcel Holtmann   Bluetooth: Replac...
3131
  	bt_dev_dbg(hdev, "status 0x%02x", status);
0314f2867   Jaganath Kanakkassery   Bluetooth: Implem...
3132
3133
3134
3135
3136
3137
  
  	hci_dev_lock(hdev);
  
  	cmd = pending_find(MGMT_OP_SET_PHY_CONFIGURATION, hdev);
  	if (!cmd)
  		goto unlock;
0314f2867   Jaganath Kanakkassery   Bluetooth: Implem...
3138
3139
3140
3141
3142
3143
3144
3145
  	if (status) {
  		mgmt_cmd_status(cmd->sk, hdev->id,
  				MGMT_OP_SET_PHY_CONFIGURATION,
  				mgmt_status(status));
  	} else {
  		mgmt_cmd_complete(cmd->sk, hdev->id,
  				  MGMT_OP_SET_PHY_CONFIGURATION, 0,
  				  NULL, 0);
b7c23df85   Jaganath Kanakkassery   Bluetooth: Implem...
3146
3147
  
  		mgmt_phy_configuration_changed(hdev, cmd->sk);
0314f2867   Jaganath Kanakkassery   Bluetooth: Implem...
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
  	}
  
  	mgmt_pending_remove(cmd);
  
  unlock:
  	hci_dev_unlock(hdev);
  }
  
  static int set_phy_configuration(struct sock *sk, struct hci_dev *hdev,
  				 void *data, u16 len)
  {
  	struct mgmt_cp_set_phy_confguration *cp = data;
  	struct hci_cp_le_set_default_phy cp_phy;
  	struct mgmt_pending_cmd *cmd;
  	struct hci_request req;
  	u32 selected_phys, configurable_phys, supported_phys, unconfigure_phys;
  	u16 pkt_type = (HCI_DH1 | HCI_DM1);
b7c23df85   Jaganath Kanakkassery   Bluetooth: Implem...
3165
  	bool changed = false;
0314f2867   Jaganath Kanakkassery   Bluetooth: Implem...
3166
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
3167
  	bt_dev_dbg(hdev, "sock %p", sk);
0314f2867   Jaganath Kanakkassery   Bluetooth: Implem...
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
  
  	configurable_phys = get_configurable_phys(hdev);
  	supported_phys = get_supported_phys(hdev);
  	selected_phys = __le32_to_cpu(cp->selected_phys);
  
  	if (selected_phys & ~supported_phys)
  		return mgmt_cmd_status(sk, hdev->id,
  				       MGMT_OP_SET_PHY_CONFIGURATION,
  				       MGMT_STATUS_INVALID_PARAMS);
  
  	unconfigure_phys = supported_phys & ~configurable_phys;
  
  	if ((selected_phys & unconfigure_phys) != unconfigure_phys)
  		return mgmt_cmd_status(sk, hdev->id,
  				       MGMT_OP_SET_PHY_CONFIGURATION,
  				       MGMT_STATUS_INVALID_PARAMS);
  
  	if (selected_phys == get_selected_phys(hdev))
  		return mgmt_cmd_complete(sk, hdev->id,
  					 MGMT_OP_SET_PHY_CONFIGURATION,
  					 0, NULL, 0);
  
  	hci_dev_lock(hdev);
  
  	if (!hdev_is_powered(hdev)) {
  		err = mgmt_cmd_status(sk, hdev->id,
  				      MGMT_OP_SET_PHY_CONFIGURATION,
  				      MGMT_STATUS_REJECTED);
  		goto unlock;
  	}
  
  	if (pending_find(MGMT_OP_SET_PHY_CONFIGURATION, hdev)) {
  		err = mgmt_cmd_status(sk, hdev->id,
  				      MGMT_OP_SET_PHY_CONFIGURATION,
  				      MGMT_STATUS_BUSY);
  		goto unlock;
  	}
  
  	if (selected_phys & MGMT_PHY_BR_1M_3SLOT)
  		pkt_type |= (HCI_DH3 | HCI_DM3);
  	else
  		pkt_type &= ~(HCI_DH3 | HCI_DM3);
  
  	if (selected_phys & MGMT_PHY_BR_1M_5SLOT)
  		pkt_type |= (HCI_DH5 | HCI_DM5);
  	else
  		pkt_type &= ~(HCI_DH5 | HCI_DM5);
  
  	if (selected_phys & MGMT_PHY_EDR_2M_1SLOT)
  		pkt_type &= ~HCI_2DH1;
  	else
  		pkt_type |= HCI_2DH1;
  
  	if (selected_phys & MGMT_PHY_EDR_2M_3SLOT)
  		pkt_type &= ~HCI_2DH3;
  	else
  		pkt_type |= HCI_2DH3;
  
  	if (selected_phys & MGMT_PHY_EDR_2M_5SLOT)
  		pkt_type &= ~HCI_2DH5;
  	else
  		pkt_type |= HCI_2DH5;
  
  	if (selected_phys & MGMT_PHY_EDR_3M_1SLOT)
  		pkt_type &= ~HCI_3DH1;
  	else
  		pkt_type |= HCI_3DH1;
  
  	if (selected_phys & MGMT_PHY_EDR_3M_3SLOT)
  		pkt_type &= ~HCI_3DH3;
  	else
  		pkt_type |= HCI_3DH3;
  
  	if (selected_phys & MGMT_PHY_EDR_3M_5SLOT)
  		pkt_type &= ~HCI_3DH5;
  	else
  		pkt_type |= HCI_3DH5;
b7c23df85   Jaganath Kanakkassery   Bluetooth: Implem...
3245
  	if (pkt_type != hdev->pkt_type) {
0314f2867   Jaganath Kanakkassery   Bluetooth: Implem...
3246
  		hdev->pkt_type = pkt_type;
b7c23df85   Jaganath Kanakkassery   Bluetooth: Implem...
3247
3248
  		changed = true;
  	}
0314f2867   Jaganath Kanakkassery   Bluetooth: Implem...
3249
3250
3251
  
  	if ((selected_phys & MGMT_PHY_LE_MASK) ==
  	    (get_selected_phys(hdev) & MGMT_PHY_LE_MASK)) {
b7c23df85   Jaganath Kanakkassery   Bluetooth: Implem...
3252
3253
  		if (changed)
  			mgmt_phy_configuration_changed(hdev, sk);
0314f2867   Jaganath Kanakkassery   Bluetooth: Implem...
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
  		err = mgmt_cmd_complete(sk, hdev->id,
  					MGMT_OP_SET_PHY_CONFIGURATION,
  					0, NULL, 0);
  
  		goto unlock;
  	}
  
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_PHY_CONFIGURATION, hdev, data,
  			       len);
  	if (!cmd) {
  		err = -ENOMEM;
  		goto unlock;
  	}
  
  	hci_req_init(&req, hdev);
  
  	memset(&cp_phy, 0, sizeof(cp_phy));
  
  	if (!(selected_phys & MGMT_PHY_LE_TX_MASK))
  		cp_phy.all_phys |= 0x01;
  
  	if (!(selected_phys & MGMT_PHY_LE_RX_MASK))
  		cp_phy.all_phys |= 0x02;
  
  	if (selected_phys & MGMT_PHY_LE_1M_TX)
  		cp_phy.tx_phys |= HCI_LE_SET_PHY_1M;
  
  	if (selected_phys & MGMT_PHY_LE_2M_TX)
  		cp_phy.tx_phys |= HCI_LE_SET_PHY_2M;
  
  	if (selected_phys & MGMT_PHY_LE_CODED_TX)
  		cp_phy.tx_phys |= HCI_LE_SET_PHY_CODED;
  
  	if (selected_phys & MGMT_PHY_LE_1M_RX)
  		cp_phy.rx_phys |= HCI_LE_SET_PHY_1M;
  
  	if (selected_phys & MGMT_PHY_LE_2M_RX)
  		cp_phy.rx_phys |= HCI_LE_SET_PHY_2M;
  
  	if (selected_phys & MGMT_PHY_LE_CODED_RX)
  		cp_phy.rx_phys |= HCI_LE_SET_PHY_CODED;
  
  	hci_req_add(&req, HCI_OP_LE_SET_DEFAULT_PHY, sizeof(cp_phy), &cp_phy);
  
  	err = hci_req_run_skb(&req, set_default_phy_complete);
  	if (err < 0)
  		mgmt_pending_remove(cmd);
  
  unlock:
  	hci_dev_unlock(hdev);
  
  	return err;
  }
600a87490   Alain Michaud   Bluetooth: Implem...
3307
3308
3309
3310
3311
3312
3313
3314
3315
  static int set_blocked_keys(struct sock *sk, struct hci_dev *hdev, void *data,
  			    u16 len)
  {
  	int err = MGMT_STATUS_SUCCESS;
  	struct mgmt_cp_set_blocked_keys *keys = data;
  	const u16 max_key_count = ((U16_MAX - sizeof(*keys)) /
  				   sizeof(struct mgmt_blocked_key_info));
  	u16 key_count, expected_len;
  	int i;
181d69535   Marcel Holtmann   Bluetooth: Replac...
3316
  	bt_dev_dbg(hdev, "sock %p", sk);
600a87490   Alain Michaud   Bluetooth: Implem...
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
  
  	key_count = __le16_to_cpu(keys->key_count);
  	if (key_count > max_key_count) {
  		bt_dev_err(hdev, "too big key_count value %u", key_count);
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BLOCKED_KEYS,
  				       MGMT_STATUS_INVALID_PARAMS);
  	}
  
  	expected_len = struct_size(keys, keys, key_count);
  	if (expected_len != len) {
  		bt_dev_err(hdev, "expected %u bytes, got %u bytes",
  			   expected_len, len);
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BLOCKED_KEYS,
  				       MGMT_STATUS_INVALID_PARAMS);
  	}
  
  	hci_dev_lock(hdev);
  
  	hci_blocked_keys_clear(hdev);
  
  	for (i = 0; i < keys->key_count; ++i) {
  		struct blocked_key *b = kzalloc(sizeof(*b), GFP_KERNEL);
  
  		if (!b) {
  			err = MGMT_STATUS_NO_RESOURCES;
  			break;
  		}
  
  		b->type = keys->keys[i].type;
  		memcpy(b->val, keys->keys[i].val, sizeof(b->val));
  		list_add_rcu(&b->list, &hdev->blocked_keys);
  	}
  	hci_dev_unlock(hdev);
  
  	return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_BLOCKED_KEYS,
  				err, NULL, 0);
  }
00bce3fb0   Alain Michaud   Bluetooth: Enable...
3354
3355
3356
3357
3358
3359
  static int set_wideband_speech(struct sock *sk, struct hci_dev *hdev,
  			       void *data, u16 len)
  {
  	struct mgmt_mode *cp = data;
  	int err;
  	bool changed = false;
181d69535   Marcel Holtmann   Bluetooth: Replac...
3360
  	bt_dev_dbg(hdev, "sock %p", sk);
00bce3fb0   Alain Michaud   Bluetooth: Enable...
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
  
  	if (!test_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks))
  		return mgmt_cmd_status(sk, hdev->id,
  				       MGMT_OP_SET_WIDEBAND_SPEECH,
  				       MGMT_STATUS_NOT_SUPPORTED);
  
  	if (cp->val != 0x00 && cp->val != 0x01)
  		return mgmt_cmd_status(sk, hdev->id,
  				       MGMT_OP_SET_WIDEBAND_SPEECH,
  				       MGMT_STATUS_INVALID_PARAMS);
  
  	hci_dev_lock(hdev);
  
  	if (pending_find(MGMT_OP_SET_WIDEBAND_SPEECH, hdev)) {
  		err = mgmt_cmd_status(sk, hdev->id,
  				      MGMT_OP_SET_WIDEBAND_SPEECH,
  				      MGMT_STATUS_BUSY);
  		goto unlock;
  	}
  
  	if (hdev_is_powered(hdev) &&
  	    !!cp->val != hci_dev_test_flag(hdev,
  					   HCI_WIDEBAND_SPEECH_ENABLED)) {
  		err = mgmt_cmd_status(sk, hdev->id,
  				      MGMT_OP_SET_WIDEBAND_SPEECH,
  				      MGMT_STATUS_REJECTED);
  		goto unlock;
  	}
  
  	if (cp->val)
  		changed = !hci_dev_test_and_set_flag(hdev,
  						   HCI_WIDEBAND_SPEECH_ENABLED);
  	else
  		changed = hci_dev_test_and_clear_flag(hdev,
  						   HCI_WIDEBAND_SPEECH_ENABLED);
  
  	err = send_settings_rsp(sk, MGMT_OP_SET_WIDEBAND_SPEECH, hdev);
  	if (err < 0)
  		goto unlock;
  
  	if (changed)
  		err = new_settings(hdev, sk);
  
  unlock:
  	hci_dev_unlock(hdev);
  	return err;
  }
bc292258c   Marcel Holtmann   Bluetooth: Add su...
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
  static int read_security_info(struct sock *sk, struct hci_dev *hdev,
  			      void *data, u16 data_len)
  {
  	char buf[16];
  	struct mgmt_rp_read_security_info *rp = (void *)buf;
  	u16 sec_len = 0;
  	u8 flags = 0;
  
  	bt_dev_dbg(hdev, "sock %p", sk);
  
  	memset(&buf, 0, sizeof(buf));
  
  	hci_dev_lock(hdev);
  
  	/* When the Read Simple Pairing Options command is supported, then
  	 * the remote public key validation is supported.
  	 */
  	if (hdev->commands[41] & 0x08)
  		flags |= 0x01;	/* Remote public key validation (BR/EDR) */
  
  	flags |= 0x02;		/* Remote public key validation (LE) */
  
  	/* When the Read Encryption Key Size command is supported, then the
  	 * encryption key size is enforced.
  	 */
  	if (hdev->commands[20] & 0x10)
  		flags |= 0x04;	/* Encryption key size enforcement (BR/EDR) */
  
  	flags |= 0x08;		/* Encryption key size enforcement (LE) */
  
  	sec_len = eir_append_data(rp->sec, sec_len, 0x01, &flags, 1);
  
  	/* When the Read Simple Pairing Options command is supported, then
  	 * also max encryption key size information is provided.
  	 */
  	if (hdev->commands[41] & 0x08)
  		sec_len = eir_append_le16(rp->sec, sec_len, 0x02,
  					  hdev->max_enc_key_size);
  
  	sec_len = eir_append_le16(rp->sec, sec_len, 0x03, SMP_MAX_ENC_KEY_SIZE);
  
  	rp->sec_len = cpu_to_le16(sec_len);
  
  	hci_dev_unlock(hdev);
  
  	return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_SECURITY_INFO, 0,
  				 rp, sizeof(*rp) + sec_len);
  }
e625e50ce   Marcel Holtmann   Bluetooth: Introd...
3456
3457
3458
3459
3460
3461
3462
  #ifdef CONFIG_BT_FEATURE_DEBUG
  /* d4992530-b9ec-469f-ab01-6c481c47da1c */
  static const u8 debug_uuid[16] = {
  	0x1c, 0xda, 0x47, 0x1c, 0x48, 0x6c, 0x01, 0xab,
  	0x9f, 0x46, 0xec, 0xb9, 0x30, 0x25, 0x99, 0xd4,
  };
  #endif
15d8ce05e   Alain Michaud   Bluetooth: le_sim...
3463
3464
3465
3466
3467
  /* 671b10b5-42c0-4696-9227-eb28d1b049d6 */
  static const u8 simult_central_periph_uuid[16] = {
  	0xd6, 0x49, 0xb0, 0xd1, 0x28, 0xeb, 0x27, 0x92,
  	0x96, 0x46, 0xc0, 0x42, 0xb5, 0x10, 0x1b, 0x67,
  };
cbbdfa6f3   Sathish Narasimman   Bluetooth: Enable...
3468
3469
3470
3471
3472
  /* 15c0a148-c273-11ea-b3de-0242ac130004 */
  static const u8 rpa_resolution_uuid[16] = {
  	0x04, 0x00, 0x13, 0xac, 0x42, 0x02, 0xde, 0xb3,
  	0xea, 0x11, 0x73, 0xc2, 0x48, 0xa1, 0xc0, 0x15,
  };
a10c907ce   Marcel Holtmann   Bluetooth: Add su...
3473
3474
3475
  static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev,
  				  void *data, u16 data_len)
  {
cbbdfa6f3   Sathish Narasimman   Bluetooth: Enable...
3476
  	char buf[62];	/* Enough space for 3 features */
a10c907ce   Marcel Holtmann   Bluetooth: Add su...
3477
3478
  	struct mgmt_rp_read_exp_features_info *rp = (void *)buf;
  	u16 idx = 0;
15d8ce05e   Alain Michaud   Bluetooth: le_sim...
3479
  	u32 flags;
a10c907ce   Marcel Holtmann   Bluetooth: Add su...
3480
3481
3482
3483
  
  	bt_dev_dbg(hdev, "sock %p", sk);
  
  	memset(&buf, 0, sizeof(buf));
e625e50ce   Marcel Holtmann   Bluetooth: Introd...
3484
3485
  #ifdef CONFIG_BT_FEATURE_DEBUG
  	if (!hdev) {
15d8ce05e   Alain Michaud   Bluetooth: le_sim...
3486
  		flags = bt_dbg_get() ? BIT(0) : 0;
e625e50ce   Marcel Holtmann   Bluetooth: Introd...
3487
3488
3489
3490
3491
3492
  
  		memcpy(rp->features[idx].uuid, debug_uuid, 16);
  		rp->features[idx].flags = cpu_to_le32(flags);
  		idx++;
  	}
  #endif
15d8ce05e   Alain Michaud   Bluetooth: le_sim...
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
  	if (hdev) {
  		if (test_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks) &&
  		    (hdev->le_states[4] & 0x08) &&	/* Central */
  		    (hdev->le_states[4] & 0x40) &&	/* Peripheral */
  		    (hdev->le_states[3] & 0x10))	/* Simultaneous */
  			flags = BIT(0);
  		else
  			flags = 0;
  
  		memcpy(rp->features[idx].uuid, simult_central_periph_uuid, 16);
  		rp->features[idx].flags = cpu_to_le32(flags);
  		idx++;
  	}
cbbdfa6f3   Sathish Narasimman   Bluetooth: Enable...
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
  	if (hdev && use_ll_privacy(hdev)) {
  		if (hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
  			flags = BIT(0) | BIT(1);
  		else
  			flags = BIT(1);
  
  		memcpy(rp->features[idx].uuid, rpa_resolution_uuid, 16);
  		rp->features[idx].flags = cpu_to_le32(flags);
  		idx++;
  	}
a10c907ce   Marcel Holtmann   Bluetooth: Add su...
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
  	rp->feature_count = cpu_to_le16(idx);
  
  	/* After reading the experimental features information, enable
  	 * the events to update client on any future change.
  	 */
  	hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
  
  	return mgmt_cmd_complete(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
  				 MGMT_OP_READ_EXP_FEATURES_INFO,
  				 0, rp, sizeof(*rp) + (20 * idx));
  }
cbbdfa6f3   Sathish Narasimman   Bluetooth: Enable...
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
  static int exp_ll_privacy_feature_changed(bool enabled, struct hci_dev *hdev,
  					  struct sock *skip)
  {
  	struct mgmt_ev_exp_feature_changed ev;
  
  	memset(&ev, 0, sizeof(ev));
  	memcpy(ev.uuid, rpa_resolution_uuid, 16);
  	ev.flags = cpu_to_le32((enabled ? BIT(0) : 0) | BIT(1));
  
  	return mgmt_limited_event(MGMT_EV_EXP_FEATURE_CHANGED, hdev,
  				  &ev, sizeof(ev),
  				  HCI_MGMT_EXP_FEATURE_EVENTS, skip);
  
  }
e625e50ce   Marcel Holtmann   Bluetooth: Introd...
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
  #ifdef CONFIG_BT_FEATURE_DEBUG
  static int exp_debug_feature_changed(bool enabled, struct sock *skip)
  {
  	struct mgmt_ev_exp_feature_changed ev;
  
  	memset(&ev, 0, sizeof(ev));
  	memcpy(ev.uuid, debug_uuid, 16);
  	ev.flags = cpu_to_le32(enabled ? BIT(0) : 0);
  
  	return mgmt_limited_event(MGMT_EV_EXP_FEATURE_CHANGED, NULL,
  				  &ev, sizeof(ev),
  				  HCI_MGMT_EXP_FEATURE_EVENTS, skip);
  }
  #endif
a10c907ce   Marcel Holtmann   Bluetooth: Add su...
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
  static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
  			   void *data, u16 data_len)
  {
  	struct mgmt_cp_set_exp_feature *cp = data;
  	struct mgmt_rp_set_exp_feature rp;
  
  	bt_dev_dbg(hdev, "sock %p", sk);
  
  	if (!memcmp(cp->uuid, ZERO_KEY, 16)) {
  		memset(rp.uuid, 0, 16);
  		rp.flags = cpu_to_le32(0);
e625e50ce   Marcel Holtmann   Bluetooth: Introd...
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
  #ifdef CONFIG_BT_FEATURE_DEBUG
  		if (!hdev) {
  			bool changed = bt_dbg_get();
  
  			bt_dbg_set(false);
  
  			if (changed)
  				exp_debug_feature_changed(false, sk);
  		}
  #endif
cbbdfa6f3   Sathish Narasimman   Bluetooth: Enable...
3576
3577
3578
3579
3580
3581
3582
3583
3584
  		if (hdev && use_ll_privacy(hdev) && !hdev_is_powered(hdev)) {
  			bool changed = hci_dev_test_flag(hdev,
  							 HCI_ENABLE_LL_PRIVACY);
  
  			hci_dev_clear_flag(hdev, HCI_ENABLE_LL_PRIVACY);
  
  			if (changed)
  				exp_ll_privacy_feature_changed(false, hdev, sk);
  		}
a10c907ce   Marcel Holtmann   Bluetooth: Add su...
3585
3586
3587
3588
3589
3590
  		hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
  
  		return mgmt_cmd_complete(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
  					 MGMT_OP_SET_EXP_FEATURE, 0,
  					 &rp, sizeof(rp));
  	}
e625e50ce   Marcel Holtmann   Bluetooth: Introd...
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
  #ifdef CONFIG_BT_FEATURE_DEBUG
  	if (!memcmp(cp->uuid, debug_uuid, 16)) {
  		bool val, changed;
  		int err;
  
  		/* Command requires to use the non-controller index */
  		if (hdev)
  			return mgmt_cmd_status(sk, hdev->id,
  					       MGMT_OP_SET_EXP_FEATURE,
  					       MGMT_STATUS_INVALID_INDEX);
  
  		/* Parameters are limited to a single octet */
  		if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
  			return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
  					       MGMT_OP_SET_EXP_FEATURE,
  					       MGMT_STATUS_INVALID_PARAMS);
  
  		/* Only boolean on/off is supported */
  		if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
  			return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
  					       MGMT_OP_SET_EXP_FEATURE,
  					       MGMT_STATUS_INVALID_PARAMS);
  
  		val = !!cp->param[0];
  		changed = val ? !bt_dbg_get() : bt_dbg_get();
  		bt_dbg_set(val);
  
  		memcpy(rp.uuid, debug_uuid, 16);
  		rp.flags = cpu_to_le32(val ? BIT(0) : 0);
  
  		hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
  
  		err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
  					MGMT_OP_SET_EXP_FEATURE, 0,
  					&rp, sizeof(rp));
  
  		if (changed)
  			exp_debug_feature_changed(val, sk);
  
  		return err;
  	}
  #endif
cbbdfa6f3   Sathish Narasimman   Bluetooth: Enable...
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
  	if (!memcmp(cp->uuid, rpa_resolution_uuid, 16)) {
  		bool val, changed;
  		int err;
  		u32 flags;
  
  		/* Command requires to use the controller index */
  		if (!hdev)
  			return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
  					       MGMT_OP_SET_EXP_FEATURE,
  					       MGMT_STATUS_INVALID_INDEX);
  
  		/* Changes can only be made when controller is powered down */
  		if (hdev_is_powered(hdev))
  			return mgmt_cmd_status(sk, hdev->id,
  					       MGMT_OP_SET_EXP_FEATURE,
  					       MGMT_STATUS_NOT_POWERED);
  
  		/* Parameters are limited to a single octet */
  		if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
  			return mgmt_cmd_status(sk, hdev->id,
  					       MGMT_OP_SET_EXP_FEATURE,
  					       MGMT_STATUS_INVALID_PARAMS);
  
  		/* Only boolean on/off is supported */
  		if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
  			return mgmt_cmd_status(sk, hdev->id,
  					       MGMT_OP_SET_EXP_FEATURE,
  					       MGMT_STATUS_INVALID_PARAMS);
  
  		val = !!cp->param[0];
  
  		if (val) {
  			changed = !hci_dev_test_flag(hdev,
  						     HCI_ENABLE_LL_PRIVACY);
  			hci_dev_set_flag(hdev, HCI_ENABLE_LL_PRIVACY);
  			hci_dev_clear_flag(hdev, HCI_ADVERTISING);
  
  			/* Enable LL privacy + supported settings changed */
  			flags = BIT(0) | BIT(1);
  		} else {
  			changed = hci_dev_test_flag(hdev,
  						    HCI_ENABLE_LL_PRIVACY);
  			hci_dev_clear_flag(hdev, HCI_ENABLE_LL_PRIVACY);
  
  			/* Disable LL privacy + supported settings changed */
  			flags = BIT(1);
  		}
  
  		memcpy(rp.uuid, rpa_resolution_uuid, 16);
  		rp.flags = cpu_to_le32(flags);
  
  		hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
  
  		err = mgmt_cmd_complete(sk, hdev->id,
  					MGMT_OP_SET_EXP_FEATURE, 0,
  					&rp, sizeof(rp));
  
  		if (changed)
  			exp_ll_privacy_feature_changed(val, hdev, sk);
  
  		return err;
  	}
a10c907ce   Marcel Holtmann   Bluetooth: Add su...
3695
3696
3697
3698
  	return mgmt_cmd_status(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
  			       MGMT_OP_SET_EXP_FEATURE,
  			       MGMT_STATUS_NOT_SUPPORTED);
  }
4c54bf2b0   Abhishek Pandit-Subedi   Bluetooth: Add ge...
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
  #define SUPPORTED_DEVICE_FLAGS() ((1U << HCI_CONN_FLAG_MAX) - 1)
  
  static int get_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
  			    u16 data_len)
  {
  	struct mgmt_cp_get_device_flags *cp = data;
  	struct mgmt_rp_get_device_flags rp;
  	struct bdaddr_list_with_flags *br_params;
  	struct hci_conn_params *params;
  	u32 supported_flags = SUPPORTED_DEVICE_FLAGS();
  	u32 current_flags = 0;
  	u8 status = MGMT_STATUS_INVALID_PARAMS;
  
  	bt_dev_dbg(hdev, "Get device flags %pMR (type 0x%x)
  ",
  		   &cp->addr.bdaddr, cp->addr.type);
3ca33e3fb   Abhishek Pandit-Subedi   Bluetooth: Add hc...
3715
  	hci_dev_lock(hdev);
4c54bf2b0   Abhishek Pandit-Subedi   Bluetooth: Add ge...
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
  	if (cp->addr.type == BDADDR_BREDR) {
  		br_params = hci_bdaddr_list_lookup_with_flags(&hdev->whitelist,
  							      &cp->addr.bdaddr,
  							      cp->addr.type);
  		if (!br_params)
  			goto done;
  
  		current_flags = br_params->current_flags;
  	} else {
  		params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
  						le_addr_type(cp->addr.type));
  
  		if (!params)
  			goto done;
  
  		current_flags = params->current_flags;
  	}
  
  	bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
  	rp.addr.type = cp->addr.type;
  	rp.supported_flags = cpu_to_le32(supported_flags);
  	rp.current_flags = cpu_to_le32(current_flags);
  
  	status = MGMT_STATUS_SUCCESS;
  
  done:
3ca33e3fb   Abhishek Pandit-Subedi   Bluetooth: Add hc...
3742
  	hci_dev_unlock(hdev);
4c54bf2b0   Abhishek Pandit-Subedi   Bluetooth: Add ge...
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
  	return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_DEVICE_FLAGS, status,
  				&rp, sizeof(rp));
  }
  
  static void device_flags_changed(struct sock *sk, struct hci_dev *hdev,
  				 bdaddr_t *bdaddr, u8 bdaddr_type,
  				 u32 supported_flags, u32 current_flags)
  {
  	struct mgmt_ev_device_flags_changed ev;
  
  	bacpy(&ev.addr.bdaddr, bdaddr);
  	ev.addr.type = bdaddr_type;
  	ev.supported_flags = cpu_to_le32(supported_flags);
  	ev.current_flags = cpu_to_le32(current_flags);
  
  	mgmt_event(MGMT_EV_DEVICE_FLAGS_CHANGED, hdev, &ev, sizeof(ev), sk);
  }
  
  static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
  			    u16 len)
  {
  	struct mgmt_cp_set_device_flags *cp = data;
  	struct bdaddr_list_with_flags *br_params;
  	struct hci_conn_params *params;
  	u8 status = MGMT_STATUS_INVALID_PARAMS;
  	u32 supported_flags = SUPPORTED_DEVICE_FLAGS();
  	u32 current_flags = __le32_to_cpu(cp->current_flags);
  
  	bt_dev_dbg(hdev, "Set device flags %pMR (type 0x%x) = 0x%x",
  		   &cp->addr.bdaddr, cp->addr.type,
  		   __le32_to_cpu(current_flags));
  
  	if ((supported_flags | current_flags) != supported_flags) {
  		bt_dev_warn(hdev, "Bad flag given (0x%x) vs supported (0x%0x)",
  			    current_flags, supported_flags);
  		goto done;
  	}
3ca33e3fb   Abhishek Pandit-Subedi   Bluetooth: Add hc...
3780
  	hci_dev_lock(hdev);
4c54bf2b0   Abhishek Pandit-Subedi   Bluetooth: Add ge...
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
  	if (cp->addr.type == BDADDR_BREDR) {
  		br_params = hci_bdaddr_list_lookup_with_flags(&hdev->whitelist,
  							      &cp->addr.bdaddr,
  							      cp->addr.type);
  
  		if (br_params) {
  			br_params->current_flags = current_flags;
  			status = MGMT_STATUS_SUCCESS;
  		} else {
  			bt_dev_warn(hdev, "No such BR/EDR device %pMR (0x%x)",
  				    &cp->addr.bdaddr, cp->addr.type);
  		}
  	} else {
  		params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
  						le_addr_type(cp->addr.type));
  		if (params) {
  			params->current_flags = current_flags;
  			status = MGMT_STATUS_SUCCESS;
  		} else {
  			bt_dev_warn(hdev, "No such LE device %pMR (0x%x)",
  				    &cp->addr.bdaddr,
  				    le_addr_type(cp->addr.type));
  		}
  	}
  
  done:
3ca33e3fb   Abhishek Pandit-Subedi   Bluetooth: Add hc...
3807
  	hci_dev_unlock(hdev);
4c54bf2b0   Abhishek Pandit-Subedi   Bluetooth: Add ge...
3808
3809
3810
3811
3812
3813
3814
  	if (status == MGMT_STATUS_SUCCESS)
  		device_flags_changed(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
  				     supported_flags, current_flags);
  
  	return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_FLAGS, status,
  				 &cp->addr, sizeof(cp->addr));
  }
b52729f27   Miao-chen Chou   Bluetooth: Notify...
3815
3816
3817
3818
3819
3820
3821
3822
3823
  static void mgmt_adv_monitor_added(struct sock *sk, struct hci_dev *hdev,
  				   u16 handle)
  {
  	struct mgmt_ev_adv_monitor_added ev;
  
  	ev.monitor_handle = cpu_to_le16(handle);
  
  	mgmt_event(MGMT_EV_ADV_MONITOR_ADDED, hdev, &ev, sizeof(ev), sk);
  }
cdde92e23   Miao-chen Chou   Bluetooth: Notify...
3824
3825
3826
3827
3828
3829
3830
3831
3832
  static void mgmt_adv_monitor_removed(struct sock *sk, struct hci_dev *hdev,
  				     u16 handle)
  {
  	struct mgmt_ev_adv_monitor_added ev;
  
  	ev.monitor_handle = cpu_to_le16(handle);
  
  	mgmt_event(MGMT_EV_ADV_MONITOR_REMOVED, hdev, &ev, sizeof(ev), sk);
  }
e5e1e7fd4   Miao-chen Chou   Bluetooth: Add ha...
3833
3834
3835
3836
3837
  static int read_adv_mon_features(struct sock *sk, struct hci_dev *hdev,
  				 void *data, u16 len)
  {
  	struct adv_monitor *monitor = NULL;
  	struct mgmt_rp_read_adv_monitor_features *rp = NULL;
cafd472a1   Peilin Ye   Bluetooth: Fix me...
3838
  	int handle, err;
e5e1e7fd4   Miao-chen Chou   Bluetooth: Add ha...
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
  	size_t rp_size = 0;
  	__u32 supported = 0;
  	__u16 num_handles = 0;
  	__u16 handles[HCI_MAX_ADV_MONITOR_NUM_HANDLES];
  
  	BT_DBG("request for %s", hdev->name);
  
  	hci_dev_lock(hdev);
  
  	if (msft_get_features(hdev) & MSFT_FEATURE_MASK_LE_ADV_MONITOR)
  		supported |= MGMT_ADV_MONITOR_FEATURE_MASK_OR_PATTERNS;
  
  	idr_for_each_entry(&hdev->adv_monitors_idr, monitor, handle) {
  		handles[num_handles++] = monitor->handle;
  	}
  
  	hci_dev_unlock(hdev);
  
  	rp_size = sizeof(*rp) + (num_handles * sizeof(u16));
  	rp = kmalloc(rp_size, GFP_KERNEL);
  	if (!rp)
  		return -ENOMEM;
  
  	/* Once controller-based monitoring is in place, the enabled_features
  	 * should reflect the use.
  	 */
  	rp->supported_features = cpu_to_le32(supported);
  	rp->enabled_features = 0;
  	rp->max_num_handles = cpu_to_le16(HCI_MAX_ADV_MONITOR_NUM_HANDLES);
  	rp->max_num_patterns = HCI_MAX_ADV_MONITOR_NUM_PATTERNS;
  	rp->num_handles = cpu_to_le16(num_handles);
  	if (num_handles)
  		memcpy(&rp->handles, &handles, (num_handles * sizeof(u16)));
cafd472a1   Peilin Ye   Bluetooth: Fix me...
3872
3873
3874
3875
3876
3877
3878
  	err = mgmt_cmd_complete(sk, hdev->id,
  				MGMT_OP_READ_ADV_MONITOR_FEATURES,
  				MGMT_STATUS_SUCCESS, rp, rp_size);
  
  	kfree(rp);
  
  	return err;
e5e1e7fd4   Miao-chen Chou   Bluetooth: Add ha...
3879
  }
b139553db   Miao-chen Chou   Bluetooth: Add ha...
3880
3881
3882
3883
3884
3885
3886
  static int add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev,
  				    void *data, u16 len)
  {
  	struct mgmt_cp_add_adv_patterns_monitor *cp = data;
  	struct mgmt_rp_add_adv_patterns_monitor rp;
  	struct adv_monitor *m = NULL;
  	struct adv_pattern *p = NULL;
b52729f27   Miao-chen Chou   Bluetooth: Notify...
3887
  	unsigned int mp_cnt = 0, prev_adv_monitors_cnt;
b139553db   Miao-chen Chou   Bluetooth: Add ha...
3888
  	__u8 cp_ofst = 0, cp_len = 0;
b139553db   Miao-chen Chou   Bluetooth: Add ha...
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
  	int err, i;
  
  	BT_DBG("request for %s", hdev->name);
  
  	if (len <= sizeof(*cp) || cp->pattern_count == 0) {
  		err = mgmt_cmd_status(sk, hdev->id,
  				      MGMT_OP_ADD_ADV_PATTERNS_MONITOR,
  				      MGMT_STATUS_INVALID_PARAMS);
  		goto failed;
  	}
  
  	m = kmalloc(sizeof(*m), GFP_KERNEL);
  	if (!m) {
  		err = -ENOMEM;
  		goto failed;
  	}
  
  	INIT_LIST_HEAD(&m->patterns);
  	m->active = false;
  
  	for (i = 0; i < cp->pattern_count; i++) {
  		if (++mp_cnt > HCI_MAX_ADV_MONITOR_NUM_PATTERNS) {
  			err = mgmt_cmd_status(sk, hdev->id,
  					      MGMT_OP_ADD_ADV_PATTERNS_MONITOR,
  					      MGMT_STATUS_INVALID_PARAMS);
  			goto failed;
  		}
  
  		cp_ofst = cp->patterns[i].offset;
  		cp_len = cp->patterns[i].length;
  		if (cp_ofst >= HCI_MAX_AD_LENGTH ||
  		    cp_len > HCI_MAX_AD_LENGTH ||
  		    (cp_ofst + cp_len) > HCI_MAX_AD_LENGTH) {
  			err = mgmt_cmd_status(sk, hdev->id,
  					      MGMT_OP_ADD_ADV_PATTERNS_MONITOR,
  					      MGMT_STATUS_INVALID_PARAMS);
  			goto failed;
  		}
  
  		p = kmalloc(sizeof(*p), GFP_KERNEL);
  		if (!p) {
  			err = -ENOMEM;
  			goto failed;
  		}
  
  		p->ad_type = cp->patterns[i].ad_type;
  		p->offset = cp->patterns[i].offset;
  		p->length = cp->patterns[i].length;
  		memcpy(p->value, cp->patterns[i].value, p->length);
  
  		INIT_LIST_HEAD(&p->list);
  		list_add(&p->list, &m->patterns);
  	}
  
  	if (mp_cnt != cp->pattern_count) {
  		err = mgmt_cmd_status(sk, hdev->id,
  				      MGMT_OP_ADD_ADV_PATTERNS_MONITOR,
  				      MGMT_STATUS_INVALID_PARAMS);
  		goto failed;
  	}
  
  	hci_dev_lock(hdev);
b52729f27   Miao-chen Chou   Bluetooth: Notify...
3951
  	prev_adv_monitors_cnt = hdev->adv_monitors_cnt;
b139553db   Miao-chen Chou   Bluetooth: Add ha...
3952
3953
3954
3955
3956
3957
3958
3959
3960
  	err = hci_add_adv_monitor(hdev, m);
  	if (err) {
  		if (err == -ENOSPC) {
  			mgmt_cmd_status(sk, hdev->id,
  					MGMT_OP_ADD_ADV_PATTERNS_MONITOR,
  					MGMT_STATUS_NO_RESOURCES);
  		}
  		goto unlock;
  	}
b52729f27   Miao-chen Chou   Bluetooth: Notify...
3961
3962
  	if (hdev->adv_monitors_cnt > prev_adv_monitors_cnt)
  		mgmt_adv_monitor_added(sk, hdev, m->handle);
b139553db   Miao-chen Chou   Bluetooth: Add ha...
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
  	hci_dev_unlock(hdev);
  
  	rp.monitor_handle = cpu_to_le16(m->handle);
  
  	return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_ADV_PATTERNS_MONITOR,
  				 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
  
  unlock:
  	hci_dev_unlock(hdev);
  
  failed:
  	hci_free_adv_monitor(m);
  	return err;
  }
bd2fbc6cb   Miao-chen Chou   Bluetooth: Add ha...
3977
3978
3979
3980
3981
  static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev,
  			      void *data, u16 len)
  {
  	struct mgmt_cp_remove_adv_monitor *cp = data;
  	struct mgmt_rp_remove_adv_monitor rp;
cdde92e23   Miao-chen Chou   Bluetooth: Notify...
3982
  	unsigned int prev_adv_monitors_cnt;
bd2fbc6cb   Miao-chen Chou   Bluetooth: Add ha...
3983
3984
3985
3986
3987
3988
3989
3990
  	u16 handle;
  	int err;
  
  	BT_DBG("request for %s", hdev->name);
  
  	hci_dev_lock(hdev);
  
  	handle = __le16_to_cpu(cp->monitor_handle);
cdde92e23   Miao-chen Chou   Bluetooth: Notify...
3991
  	prev_adv_monitors_cnt = hdev->adv_monitors_cnt;
bd2fbc6cb   Miao-chen Chou   Bluetooth: Add ha...
3992
3993
3994
3995
3996
3997
3998
  
  	err = hci_remove_adv_monitor(hdev, handle);
  	if (err == -ENOENT) {
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADV_MONITOR,
  				      MGMT_STATUS_INVALID_INDEX);
  		goto unlock;
  	}
cdde92e23   Miao-chen Chou   Bluetooth: Notify...
3999
4000
  	if (hdev->adv_monitors_cnt < prev_adv_monitors_cnt)
  		mgmt_adv_monitor_removed(sk, hdev, handle);
bd2fbc6cb   Miao-chen Chou   Bluetooth: Add ha...
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
  	hci_dev_unlock(hdev);
  
  	rp.monitor_handle = cp->monitor_handle;
  
  	return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_ADV_MONITOR,
  				 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
  
  unlock:
  	hci_dev_unlock(hdev);
  	return err;
  }
1b9441f8e   Johan Hedberg   Bluetooth: Conver...
4012
4013
4014
4015
4016
4017
  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;
181d69535   Marcel Holtmann   Bluetooth: Replac...
4018
  	bt_dev_dbg(hdev, "status %u", status);
1b9441f8e   Johan Hedberg   Bluetooth: Conver...
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
  
  	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: ...
4069
  static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
4070
  			       void *data, u16 data_len)
c35938b2f   Szymon Janc   Bluetooth: Add re...
4071
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
4072
  	struct mgmt_pending_cmd *cmd;
1b9441f8e   Johan Hedberg   Bluetooth: Conver...
4073
  	struct hci_request req;
c35938b2f   Szymon Janc   Bluetooth: Add re...
4074
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
4075
  	bt_dev_dbg(hdev, "sock %p", sk);
c35938b2f   Szymon Janc   Bluetooth: Add re...
4076

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

4b34ee782   Johan Hedberg   Bluetooth: mgmt: ...
4079
  	if (!hdev_is_powered(hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4080
4081
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
  				      MGMT_STATUS_NOT_POWERED);
c35938b2f   Szymon Janc   Bluetooth: Add re...
4082
4083
  		goto unlock;
  	}
9a1a1996d   Andre Guedes   Bluetooth: Use lm...
4084
  	if (!lmp_ssp_capable(hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4085
4086
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
  				      MGMT_STATUS_NOT_SUPPORTED);
c35938b2f   Szymon Janc   Bluetooth: Add re...
4087
4088
  		goto unlock;
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
4089
  	if (pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4090
4091
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
  				      MGMT_STATUS_BUSY);
c35938b2f   Szymon Janc   Bluetooth: Add re...
4092
4093
  		goto unlock;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
4094
  	cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
c35938b2f   Szymon Janc   Bluetooth: Add re...
4095
4096
4097
4098
  	if (!cmd) {
  		err = -ENOMEM;
  		goto unlock;
  	}
1b9441f8e   Johan Hedberg   Bluetooth: Conver...
4099
  	hci_req_init(&req, hdev);
710f11c08   Johan Hedberg   Bluetooth: Use cu...
4100
  	if (bredr_sc_enabled(hdev))
1b9441f8e   Johan Hedberg   Bluetooth: Conver...
4101
  		hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_EXT_DATA, 0, NULL);
4d2d27962   Marcel Holtmann   Bluetooth: Add su...
4102
  	else
1b9441f8e   Johan Hedberg   Bluetooth: Conver...
4103
  		hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
4d2d27962   Marcel Holtmann   Bluetooth: Add su...
4104

1b9441f8e   Johan Hedberg   Bluetooth: Conver...
4105
  	err = hci_req_run_skb(&req, read_local_oob_data_complete);
c35938b2f   Szymon Janc   Bluetooth: Add re...
4106
4107
4108
4109
  	if (err < 0)
  		mgmt_pending_remove(cmd);
  
  unlock:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
4110
  	hci_dev_unlock(hdev);
c35938b2f   Szymon Janc   Bluetooth: Add re...
4111
4112
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
4113
  static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
4114
  			       void *data, u16 len)
2763eda6c   Szymon Janc   Bluetooth: Add ad...
4115
  {
5d57e7964   Johan Hedberg   Bluetooth: Check ...
4116
  	struct mgmt_addr_info *addr = data;
2763eda6c   Szymon Janc   Bluetooth: Add ad...
4117
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
4118
  	bt_dev_dbg(hdev, "sock %p", sk);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
4119

5d57e7964   Johan Hedberg   Bluetooth: Check ...
4120
  	if (!bdaddr_type_is_valid(addr->type))
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4121
4122
4123
4124
  		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 ...
4125

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

ec1091131   Marcel Holtmann   Bluetooth: Add su...
4128
4129
4130
  	if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
  		struct mgmt_cp_add_remote_oob_data *cp = data;
  		u8 status;
bf1e3541f   Johan Hedberg   Bluetooth: mgmt: ...
4131

c19a495c8   Johan Hedberg   Bluetooth: Fix BR...
4132
  		if (cp->addr.type != BDADDR_BREDR) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4133
4134
4135
4136
  			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...
4137
4138
  			goto unlock;
  		}
ec1091131   Marcel Holtmann   Bluetooth: Add su...
4139
  		err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
6928a9245   Johan Hedberg   Bluetooth: Store ...
4140
4141
  					      cp->addr.type, cp->hash,
  					      cp->rand, NULL, NULL);
ec1091131   Marcel Holtmann   Bluetooth: Add su...
4142
4143
4144
4145
  		if (err < 0)
  			status = MGMT_STATUS_FAILED;
  		else
  			status = MGMT_STATUS_SUCCESS;
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4146
4147
4148
  		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...
4149
4150
  	} 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 ...
4151
  		u8 *rand192, *hash192, *rand256, *hash256;
ec1091131   Marcel Holtmann   Bluetooth: Add su...
4152
  		u8 status;
86df9200c   Johan Hedberg   Bluetooth: Add su...
4153
  		if (bdaddr_type_is_le(cp->addr.type)) {
d25b78e2e   Johan Hedberg   Bluetooth: Enforc...
4154
4155
4156
4157
4158
  			/* 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...
4159
4160
4161
4162
  				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...
4163
4164
  				goto unlock;
  			}
86df9200c   Johan Hedberg   Bluetooth: Add su...
4165
4166
4167
  			rand192 = NULL;
  			hash192 = NULL;
  		} else {
41bcfd50d   Marcel Holtmann   Bluetooth: Allow ...
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
  			/* 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...
4191
  		}
81328d5cc   Johan Hedberg   Bluetooth: Unify ...
4192
  		err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
86df9200c   Johan Hedberg   Bluetooth: Add su...
4193
  					      cp->addr.type, hash192, rand192,
41bcfd50d   Marcel Holtmann   Bluetooth: Allow ...
4194
  					      hash256, rand256);
ec1091131   Marcel Holtmann   Bluetooth: Add su...
4195
4196
4197
4198
  		if (err < 0)
  			status = MGMT_STATUS_FAILED;
  		else
  			status = MGMT_STATUS_SUCCESS;
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4199
4200
4201
  		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...
4202
  	} else {
2064ee332   Marcel Holtmann   Bluetooth: Use bt...
4203
4204
  		bt_dev_err(hdev, "add_remote_oob_data: invalid len of %u bytes",
  			   len);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4205
4206
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
  				      MGMT_STATUS_INVALID_PARAMS);
ec1091131   Marcel Holtmann   Bluetooth: Add su...
4207
  	}
2763eda6c   Szymon Janc   Bluetooth: Add ad...
4208

c19a495c8   Johan Hedberg   Bluetooth: Fix BR...
4209
  unlock:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
4210
  	hci_dev_unlock(hdev);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
4211
4212
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
4213
  static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
8ce8e2b56   Gustavo Padovan   Bluetooth: Fix co...
4214
  				  void *data, u16 len)
2763eda6c   Szymon Janc   Bluetooth: Add ad...
4215
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
4216
  	struct mgmt_cp_remove_remote_oob_data *cp = data;
bf1e3541f   Johan Hedberg   Bluetooth: mgmt: ...
4217
  	u8 status;
2763eda6c   Szymon Janc   Bluetooth: Add ad...
4218
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
4219
  	bt_dev_dbg(hdev, "sock %p", sk);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
4220

c19a495c8   Johan Hedberg   Bluetooth: Fix BR...
4221
  	if (cp->addr.type != BDADDR_BREDR)
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4222
4223
4224
4225
  		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...
4226

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

eedbd5812   Johan Hedberg   Bluetooth: Fix cl...
4229
4230
4231
4232
4233
  	if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
  		hci_remote_oob_data_clear(hdev);
  		status = MGMT_STATUS_SUCCESS;
  		goto done;
  	}
6928a9245   Johan Hedberg   Bluetooth: Store ...
4234
  	err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
4235
  	if (err < 0)
bf1e3541f   Johan Hedberg   Bluetooth: mgmt: ...
4236
  		status = MGMT_STATUS_INVALID_PARAMS;
2763eda6c   Szymon Janc   Bluetooth: Add ad...
4237
  	else
a6785be2f   Szymon Janc   Bluetooth: mgmt: ...
4238
  		status = MGMT_STATUS_SUCCESS;
bf1e3541f   Johan Hedberg   Bluetooth: mgmt: ...
4239

eedbd5812   Johan Hedberg   Bluetooth: Fix cl...
4240
  done:
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4241
4242
  	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...
4243

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
4244
  	hci_dev_unlock(hdev);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
4245
4246
  	return err;
  }
e68f072b7   Johan Hedberg   Bluetooth: Move S...
4247
  void mgmt_start_discovery_complete(struct hci_dev *hdev, u8 status)
7c3077207   Andre Guedes   Bluetooth: Update...
4248
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
4249
  	struct mgmt_pending_cmd *cmd;
ae55f5982   Lukasz Rymanowski   Bluetooth: Keep m...
4250

181d69535   Marcel Holtmann   Bluetooth: Replac...
4251
  	bt_dev_dbg(hdev, "status %d", status);
7c3077207   Andre Guedes   Bluetooth: Update...
4252

11e6e25d0   Marcel Holtmann   Bluetooth: Use {s...
4253
  	hci_dev_lock(hdev);
41dc2bd6d   Andre Guedes   Bluetooth: Make m...
4254

333ae95d0   Johan Hedberg   Bluetooth: Add ch...
4255
  	cmd = pending_find(MGMT_OP_START_DISCOVERY, hdev);
66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
4256
  	if (!cmd)
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
4257
  		cmd = pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
4258

78b781ca0   Johan Hedberg   Bluetooth: Add su...
4259
4260
  	if (!cmd)
  		cmd = pending_find(MGMT_OP_START_LIMITED_DISCOVERY, hdev);
11e6e25d0   Marcel Holtmann   Bluetooth: Use {s...
4261
  	if (cmd) {
2922a94fc   Johan Hedberg   Bluetooth: Conver...
4262
  		cmd->cmd_complete(cmd, mgmt_status(status));
11e6e25d0   Marcel Holtmann   Bluetooth: Use {s...
4263
4264
  		mgmt_pending_remove(cmd);
  	}
7c3077207   Andre Guedes   Bluetooth: Update...
4265

11e6e25d0   Marcel Holtmann   Bluetooth: Use {s...
4266
  	hci_dev_unlock(hdev);
4867bd007   Abhishek Pandit-Subedi   Bluetooth: Pause ...
4267
4268
4269
4270
4271
4272
4273
  
  	/* Handle suspend notifier */
  	if (test_and_clear_bit(SUSPEND_UNPAUSE_DISCOVERY,
  			       hdev->suspend_tasks)) {
  		bt_dev_dbg(hdev, "Unpaused discovery");
  		wake_up(&hdev->suspend_wait_q);
  	}
7c3077207   Andre Guedes   Bluetooth: Update...
4274
  }
591752afb   Johan Hedberg   Bluetooth: Add di...
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
  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;
19186c7b4   Gustavo A. R. Silva   Bluetooth: core: ...
4288
  		fallthrough;
591752afb   Johan Hedberg   Bluetooth: Add di...
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
  	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...
4301
4302
  static int start_discovery_internal(struct sock *sk, struct hci_dev *hdev,
  				    u16 op, void *data, u16 len)
14a536641   Johan Hedberg   Bluetooth: Add ba...
4303
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
4304
  	struct mgmt_cp_start_discovery *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
4305
  	struct mgmt_pending_cmd *cmd;
8019044dc   Marcel Holtmann   Bluetooth: Split ...
4306
  	u8 status;
14a536641   Johan Hedberg   Bluetooth: Add ba...
4307
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
4308
  	bt_dev_dbg(hdev, "sock %p", sk);
14a536641   Johan Hedberg   Bluetooth: Add ba...
4309

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

4b34ee782   Johan Hedberg   Bluetooth: mgmt: ...
4312
  	if (!hdev_is_powered(hdev)) {
78b781ca0   Johan Hedberg   Bluetooth: Add su...
4313
  		err = mgmt_cmd_complete(sk, hdev->id, op,
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4314
4315
  					MGMT_STATUS_NOT_POWERED,
  					&cp->type, sizeof(cp->type));
bd2d1334e   Johan Hedberg   Bluetooth: Fix re...
4316
4317
  		goto failed;
  	}
f5a969f23   Marcel Holtmann   Bluetooth: Simpli...
4318
  	if (hdev->discovery.state != DISCOVERY_STOPPED ||
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
4319
  	    hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
78b781ca0   Johan Hedberg   Bluetooth: Add su...
4320
4321
  		err = mgmt_cmd_complete(sk, hdev->id, op, MGMT_STATUS_BUSY,
  					&cp->type, sizeof(cp->type));
642be6c76   Andre Guedes   Bluetooth: Check ...
4322
4323
  		goto failed;
  	}
591752afb   Johan Hedberg   Bluetooth: Add di...
4324
  	if (!discovery_type_is_valid(hdev, cp->type, &status)) {
78b781ca0   Johan Hedberg   Bluetooth: Add su...
4325
4326
  		err = mgmt_cmd_complete(sk, hdev->id, op, status,
  					&cp->type, sizeof(cp->type));
591752afb   Johan Hedberg   Bluetooth: Add di...
4327
4328
  		goto failed;
  	}
4867bd007   Abhishek Pandit-Subedi   Bluetooth: Pause ...
4329
4330
4331
4332
4333
4334
  	/* Can't start discovery when it is paused */
  	if (hdev->discovery_paused) {
  		err = mgmt_cmd_complete(sk, hdev->id, op, MGMT_STATUS_BUSY,
  					&cp->type, sizeof(cp->type));
  		goto failed;
  	}
22078800c   Marcel Holtmann   Bluetooth: Fix me...
4335
4336
4337
4338
  	/* 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 ...
4339
  	hdev->discovery.type = cp->type;
da25cf6a9   Marcel Holtmann   Bluetooth: Report...
4340
  	hdev->discovery.report_invalid_rssi = false;
78b781ca0   Johan Hedberg   Bluetooth: Add su...
4341
4342
4343
4344
  	if (op == MGMT_OP_START_LIMITED_DISCOVERY)
  		hdev->discovery.limited = true;
  	else
  		hdev->discovery.limited = false;
4aab14e55   Andre Guedes   Bluetooth: Track ...
4345

78b781ca0   Johan Hedberg   Bluetooth: Add su...
4346
  	cmd = mgmt_pending_add(sk, op, hdev, data, len);
e68f072b7   Johan Hedberg   Bluetooth: Move S...
4347
4348
  	if (!cmd) {
  		err = -ENOMEM;
041067557   Johan Hedberg   Bluetooth: Fix re...
4349
  		goto failed;
f39799f50   Andre Guedes   Bluetooth: Prepar...
4350
  	}
041067557   Johan Hedberg   Bluetooth: Fix re...
4351

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

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

14a536641   Johan Hedberg   Bluetooth: Add ba...
4358
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
4359
  	hci_dev_unlock(hdev);
14a536641   Johan Hedberg   Bluetooth: Add ba...
4360
4361
  	return err;
  }
f39799f50   Andre Guedes   Bluetooth: Prepar...
4362

78b781ca0   Johan Hedberg   Bluetooth: Add su...
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
  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...
4377
4378
  static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
  					  u8 status)
2922a94fc   Johan Hedberg   Bluetooth: Conver...
4379
  {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4380
4381
  	return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
  				 cmd->param, 1);
2922a94fc   Johan Hedberg   Bluetooth: Conver...
4382
  }
041067557   Johan Hedberg   Bluetooth: Fix re...
4383

66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
4384
4385
4386
4387
  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...
4388
  	struct mgmt_pending_cmd *cmd;
66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
4389
4390
4391
4392
  	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...
4393

181d69535   Marcel Holtmann   Bluetooth: Replac...
4394
  	bt_dev_dbg(hdev, "sock %p", sk);
e8bb6b973   Johan Hedberg   Bluetooth: Fix ad...
4395

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

66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
4398
  	if (!hdev_is_powered(hdev)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4399
4400
4401
4402
  		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...
4403
4404
  		goto failed;
  	}
7c3077207   Andre Guedes   Bluetooth: Update...
4405

66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
4406
  	if (hdev->discovery.state != DISCOVERY_STOPPED ||
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
4407
  	    hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4408
4409
4410
4411
  		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...
4412
4413
  		goto failed;
  	}
d94839436   Johan Hedberg   Bluetooth: Use hc...
4414

66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
4415
4416
  	uuid_count = __le16_to_cpu(cp->uuid_count);
  	if (uuid_count > max_uuid_count) {
2064ee332   Marcel Holtmann   Bluetooth: Use bt...
4417
4418
  		bt_dev_err(hdev, "service_discovery: too big uuid_count value %u",
  			   uuid_count);
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4419
4420
4421
4422
  		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...
4423
4424
4425
4426
4427
  		goto failed;
  	}
  
  	expected_len = sizeof(*cp) + uuid_count * 16;
  	if (expected_len != len) {
2064ee332   Marcel Holtmann   Bluetooth: Use bt...
4428
4429
  		bt_dev_err(hdev, "service_discovery: expected %u bytes, got %u bytes",
  			   expected_len, len);
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4430
4431
4432
4433
  		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...
4434
4435
  		goto failed;
  	}
591752afb   Johan Hedberg   Bluetooth: Add di...
4436
4437
4438
4439
4440
4441
  	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...
4442
  	cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
2922a94fc   Johan Hedberg   Bluetooth: Conver...
4443
  			       hdev, data, len);
66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
4444
4445
4446
4447
  	if (!cmd) {
  		err = -ENOMEM;
  		goto failed;
  	}
2922a94fc   Johan Hedberg   Bluetooth: Conver...
4448
  	cmd->cmd_complete = service_discovery_cmd_complete;
22078800c   Marcel Holtmann   Bluetooth: Fix me...
4449
4450
4451
4452
  	/* 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...
4453
  	hdev->discovery.result_filtering = true;
66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
4454
4455
4456
4457
4458
4459
4460
4461
  	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...
4462
4463
4464
4465
  			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...
4466
4467
4468
  			mgmt_pending_remove(cmd);
  			goto failed;
  		}
66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
4469
  	}
d94839436   Johan Hedberg   Bluetooth: Use hc...
4470

66ea9427e   Jakub Pawlowski   Bluetooth: Add su...
4471
  	hci_discovery_set_state(hdev, DISCOVERY_STARTING);
e68f072b7   Johan Hedberg   Bluetooth: Move S...
4472
4473
  	queue_work(hdev->req_workqueue, &hdev->discov_update);
  	err = 0;
14a536641   Johan Hedberg   Bluetooth: Add ba...
4474
4475
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
4476
  	hci_dev_unlock(hdev);
14a536641   Johan Hedberg   Bluetooth: Add ba...
4477
4478
  	return err;
  }
2154d3f4f   Johan Hedberg   Bluetooth: Move S...
4479
  void mgmt_stop_discovery_complete(struct hci_dev *hdev, u8 status)
1183fdcad   Andre Guedes   Bluetooth: Make m...
4480
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
4481
  	struct mgmt_pending_cmd *cmd;
1183fdcad   Andre Guedes   Bluetooth: Make m...
4482

181d69535   Marcel Holtmann   Bluetooth: Replac...
4483
  	bt_dev_dbg(hdev, "status %d", status);
0e05bba6f   Andre Guedes   Bluetooth: Update...
4484
4485
  
  	hci_dev_lock(hdev);
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
4486
  	cmd = pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
11e6e25d0   Marcel Holtmann   Bluetooth: Use {s...
4487
  	if (cmd) {
2922a94fc   Johan Hedberg   Bluetooth: Conver...
4488
  		cmd->cmd_complete(cmd, mgmt_status(status));
11e6e25d0   Marcel Holtmann   Bluetooth: Use {s...
4489
  		mgmt_pending_remove(cmd);
0e05bba6f   Andre Guedes   Bluetooth: Update...
4490
  	}
0e05bba6f   Andre Guedes   Bluetooth: Update...
4491
  	hci_dev_unlock(hdev);
4867bd007   Abhishek Pandit-Subedi   Bluetooth: Pause ...
4492
4493
4494
4495
4496
4497
  
  	/* Handle suspend notifier */
  	if (test_and_clear_bit(SUSPEND_PAUSE_DISCOVERY, hdev->suspend_tasks)) {
  		bt_dev_dbg(hdev, "Paused discovery");
  		wake_up(&hdev->suspend_wait_q);
  	}
0e05bba6f   Andre Guedes   Bluetooth: Update...
4498
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
4499
  static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
4500
  			  u16 len)
14a536641   Johan Hedberg   Bluetooth: Add ba...
4501
  {
d930650b5   Johan Hedberg   Bluetooth: mgmt: ...
4502
  	struct mgmt_cp_stop_discovery *mgmt_cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
4503
  	struct mgmt_pending_cmd *cmd;
14a536641   Johan Hedberg   Bluetooth: Add ba...
4504
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
4505
  	bt_dev_dbg(hdev, "sock %p", sk);
14a536641   Johan Hedberg   Bluetooth: Add ba...
4506

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

30dc78e1a   Johan Hedberg   Bluetooth: Add na...
4509
  	if (!hci_discovery_active(hdev)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4510
4511
4512
  		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: ...
4513
4514
4515
4516
  		goto unlock;
  	}
  
  	if (hdev->discovery.type != mgmt_cp->type) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4517
4518
4519
  		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...
4520
  		goto unlock;
ff9ef5787   Johan Hedberg   Bluetooth: Add di...
4521
  	}
2922a94fc   Johan Hedberg   Bluetooth: Conver...
4522
  	cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
14a536641   Johan Hedberg   Bluetooth: Add ba...
4523
4524
  	if (!cmd) {
  		err = -ENOMEM;
30dc78e1a   Johan Hedberg   Bluetooth: Add na...
4525
4526
  		goto unlock;
  	}
2922a94fc   Johan Hedberg   Bluetooth: Conver...
4527
  	cmd->cmd_complete = generic_cmd_complete;
2154d3f4f   Johan Hedberg   Bluetooth: Move S...
4528
4529
4530
  	hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
  	queue_work(hdev->req_workqueue, &hdev->discov_update);
  	err = 0;
14a536641   Johan Hedberg   Bluetooth: Add ba...
4531

30dc78e1a   Johan Hedberg   Bluetooth: Add na...
4532
  unlock:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
4533
  	hci_dev_unlock(hdev);
14a536641   Johan Hedberg   Bluetooth: Add ba...
4534
4535
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
4536
  static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
4537
  			u16 len)
561aafbcb   Johan Hedberg   Bluetooth: Add in...
4538
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
4539
  	struct mgmt_cp_confirm_name *cp = data;
561aafbcb   Johan Hedberg   Bluetooth: Add in...
4540
  	struct inquiry_entry *e;
561aafbcb   Johan Hedberg   Bluetooth: Add in...
4541
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
4542
  	bt_dev_dbg(hdev, "sock %p", sk);
561aafbcb   Johan Hedberg   Bluetooth: Add in...
4543

561aafbcb   Johan Hedberg   Bluetooth: Add in...
4544
  	hci_dev_lock(hdev);
30dc78e1a   Johan Hedberg   Bluetooth: Add na...
4545
  	if (!hci_discovery_active(hdev)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4546
4547
4548
  		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...
4549
4550
  		goto failed;
  	}
a198e7b10   Johan Hedberg   Bluetooth: mgmt: ...
4551
  	e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
561aafbcb   Johan Hedberg   Bluetooth: Add in...
4552
  	if (!e) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4553
4554
4555
  		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...
4556
4557
4558
4559
4560
4561
4562
4563
  		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...
4564
  		hci_inquiry_cache_update_resolve(hdev, e);
561aafbcb   Johan Hedberg   Bluetooth: Add in...
4565
  	}
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4566
4567
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
  				&cp->addr, sizeof(cp->addr));
561aafbcb   Johan Hedberg   Bluetooth: Add in...
4568
4569
4570
  
  failed:
  	hci_dev_unlock(hdev);
561aafbcb   Johan Hedberg   Bluetooth: Add in...
4571
4572
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
4573
  static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
4574
  			u16 len)
7fbec224c   Antti Julku   Bluetooth: Add bl...
4575
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
4576
  	struct mgmt_cp_block_device *cp = data;
f0eeea8b6   Johan Hedberg   Bluetooth: mgmt: ...
4577
  	u8 status;
7fbec224c   Antti Julku   Bluetooth: Add bl...
4578
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
4579
  	bt_dev_dbg(hdev, "sock %p", sk);
7fbec224c   Antti Julku   Bluetooth: Add bl...
4580

4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
4581
  	if (!bdaddr_type_is_valid(cp->addr.type))
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4582
4583
4584
  		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...
4585

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

dcc36c16c   Johan Hedberg   Bluetooth: Unify ...
4588
4589
  	err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
  				  cp->addr.type);
2a8357f23   Johan Hedberg   Bluetooth: Fix re...
4590
  	if (err < 0) {
f0eeea8b6   Johan Hedberg   Bluetooth: mgmt: ...
4591
  		status = MGMT_STATUS_FAILED;
2a8357f23   Johan Hedberg   Bluetooth: Fix re...
4592
4593
4594
4595
4596
4597
  		goto done;
  	}
  
  	mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
  		   sk);
  	status = MGMT_STATUS_SUCCESS;
f0eeea8b6   Johan Hedberg   Bluetooth: mgmt: ...
4598

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

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
4603
  	hci_dev_unlock(hdev);
7fbec224c   Antti Julku   Bluetooth: Add bl...
4604
4605
4606
  
  	return err;
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
4607
  static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
4608
  			  u16 len)
7fbec224c   Antti Julku   Bluetooth: Add bl...
4609
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
4610
  	struct mgmt_cp_unblock_device *cp = data;
f0eeea8b6   Johan Hedberg   Bluetooth: mgmt: ...
4611
  	u8 status;
7fbec224c   Antti Julku   Bluetooth: Add bl...
4612
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
4613
  	bt_dev_dbg(hdev, "sock %p", sk);
7fbec224c   Antti Julku   Bluetooth: Add bl...
4614

4ee71b201   Johan Hedberg   Bluetooth: Fix ch...
4615
  	if (!bdaddr_type_is_valid(cp->addr.type))
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4616
4617
4618
  		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...
4619

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

dcc36c16c   Johan Hedberg   Bluetooth: Unify ...
4622
4623
  	err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
  				  cp->addr.type);
2a8357f23   Johan Hedberg   Bluetooth: Fix re...
4624
  	if (err < 0) {
f0eeea8b6   Johan Hedberg   Bluetooth: mgmt: ...
4625
  		status = MGMT_STATUS_INVALID_PARAMS;
2a8357f23   Johan Hedberg   Bluetooth: Fix re...
4626
4627
4628
4629
4630
4631
  		goto done;
  	}
  
  	mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
  		   sk);
  	status = MGMT_STATUS_SUCCESS;
f0eeea8b6   Johan Hedberg   Bluetooth: mgmt: ...
4632

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

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
4637
  	hci_dev_unlock(hdev);
7fbec224c   Antti Julku   Bluetooth: Add bl...
4638
4639
4640
  
  	return err;
  }
cdbaccca7   Marcel Holtmann   Bluetooth: Add ma...
4641
4642
4643
4644
  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...
4645
  	struct hci_request req;
cdbaccca7   Marcel Holtmann   Bluetooth: Add ma...
4646
  	int err;
c72d4b8af   Szymon Janc   Bluetooth: mgmt: ...
4647
  	__u16 source;
cdbaccca7   Marcel Holtmann   Bluetooth: Add ma...
4648

181d69535   Marcel Holtmann   Bluetooth: Replac...
4649
  	bt_dev_dbg(hdev, "sock %p", sk);
cdbaccca7   Marcel Holtmann   Bluetooth: Add ma...
4650

c72d4b8af   Szymon Janc   Bluetooth: mgmt: ...
4651
4652
4653
  	source = __le16_to_cpu(cp->source);
  
  	if (source > 0x0002)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4654
4655
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
  				       MGMT_STATUS_INVALID_PARAMS);
c72d4b8af   Szymon Janc   Bluetooth: mgmt: ...
4656

cdbaccca7   Marcel Holtmann   Bluetooth: Add ma...
4657
  	hci_dev_lock(hdev);
c72d4b8af   Szymon Janc   Bluetooth: mgmt: ...
4658
  	hdev->devid_source = source;
cdbaccca7   Marcel Holtmann   Bluetooth: Add ma...
4659
4660
4661
  	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...
4662
4663
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
  				NULL, 0);
cdbaccca7   Marcel Holtmann   Bluetooth: Add ma...
4664

890ea8988   Johan Hedberg   Bluetooth: Update...
4665
  	hci_req_init(&req, hdev);
b1a8917c9   Johan Hedberg   Bluetooth: Move E...
4666
  	__hci_req_update_eir(&req);
890ea8988   Johan Hedberg   Bluetooth: Update...
4667
  	hci_req_run(&req, NULL);
cdbaccca7   Marcel Holtmann   Bluetooth: Add ma...
4668
4669
4670
4671
4672
  
  	hci_dev_unlock(hdev);
  
  	return err;
  }
24b4f38fc   Arman Uguray   Bluetooth: Implem...
4673
4674
4675
  static void enable_advertising_instance(struct hci_dev *hdev, u8 status,
  					u16 opcode)
  {
181d69535   Marcel Holtmann   Bluetooth: Replac...
4676
  	bt_dev_dbg(hdev, "status %d", status);
24b4f38fc   Arman Uguray   Bluetooth: Implem...
4677
  }
1904a853f   Marcel Holtmann   Bluetooth: Add op...
4678
4679
  static void set_advertising_complete(struct hci_dev *hdev, u8 status,
  				     u16 opcode)
4375f1037   Johan Hedberg   Bluetooth: Add ne...
4680
4681
  {
  	struct cmd_lookup match = { NULL, hdev };
24b4f38fc   Arman Uguray   Bluetooth: Implem...
4682
  	struct hci_request req;
7816b8203   Florian Grandel   Bluetooth: mgmt: ...
4683
4684
4685
  	u8 instance;
  	struct adv_info *adv_instance;
  	int err;
4375f1037   Johan Hedberg   Bluetooth: Add ne...
4686

3ad675827   Jaganath Kanakkassery   Bluetooth: Fix mi...
4687
  	hci_dev_lock(hdev);
4375f1037   Johan Hedberg   Bluetooth: Add ne...
4688
4689
4690
4691
4692
  	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...
4693
  		goto unlock;
4375f1037   Johan Hedberg   Bluetooth: Add ne...
4694
  	}
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
4695
  	if (hci_dev_test_flag(hdev, HCI_LE_ADV))
a1536da25   Marcel Holtmann   Bluetooth: Introd...
4696
  		hci_dev_set_flag(hdev, HCI_ADVERTISING);
c93bd1503   Johan Hedberg   Bluetooth: Remove...
4697
  	else
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
4698
  		hci_dev_clear_flag(hdev, HCI_ADVERTISING);
c93bd1503   Johan Hedberg   Bluetooth: Remove...
4699

4375f1037   Johan Hedberg   Bluetooth: Add ne...
4700
4701
4702
4703
4704
4705
4706
  	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...
4707

4867bd007   Abhishek Pandit-Subedi   Bluetooth: Pause ...
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
  	/* Handle suspend notifier */
  	if (test_and_clear_bit(SUSPEND_PAUSE_ADVERTISING,
  			       hdev->suspend_tasks)) {
  		bt_dev_dbg(hdev, "Paused advertising");
  		wake_up(&hdev->suspend_wait_q);
  	} else if (test_and_clear_bit(SUSPEND_UNPAUSE_ADVERTISING,
  				      hdev->suspend_tasks)) {
  		bt_dev_dbg(hdev, "Unpaused advertising");
  		wake_up(&hdev->suspend_wait_q);
  	}
24b4f38fc   Arman Uguray   Bluetooth: Implem...
4718
  	/* If "Set Advertising" was just disabled and instance advertising was
7816b8203   Florian Grandel   Bluetooth: mgmt: ...
4719
  	 * set up earlier, then re-enable multi-instance advertising.
24b4f38fc   Arman Uguray   Bluetooth: Implem...
4720
4721
  	 */
  	if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
7816b8203   Florian Grandel   Bluetooth: mgmt: ...
4722
  	    list_empty(&hdev->adv_instances))
24b4f38fc   Arman Uguray   Bluetooth: Implem...
4723
  		goto unlock;
7816b8203   Florian Grandel   Bluetooth: mgmt: ...
4724
4725
4726
4727
4728
4729
4730
4731
4732
  	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...
4733
  	hci_req_init(&req, hdev);
f22525700   Johan Hedberg   Bluetooth: Move a...
4734
  	err = __hci_req_schedule_adv_instance(&req, instance, true);
7816b8203   Florian Grandel   Bluetooth: mgmt: ...
4735
4736
4737
  
  	if (!err)
  		err = hci_req_run(&req, enable_advertising_instance);
24b4f38fc   Arman Uguray   Bluetooth: Implem...
4738

7816b8203   Florian Grandel   Bluetooth: mgmt: ...
4739
  	if (err)
2064ee332   Marcel Holtmann   Bluetooth: Use bt...
4740
  		bt_dev_err(hdev, "failed to re-configure advertising");
24b4f38fc   Arman Uguray   Bluetooth: Implem...
4741

3ad675827   Jaganath Kanakkassery   Bluetooth: Fix mi...
4742
4743
  unlock:
  	hci_dev_unlock(hdev);
4375f1037   Johan Hedberg   Bluetooth: Add ne...
4744
  }
21b5187f2   Marcel Holtmann   Bluetooth: Fix to...
4745
4746
  static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
  			   u16 len)
4375f1037   Johan Hedberg   Bluetooth: Add ne...
4747
4748
  {
  	struct mgmt_mode *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
4749
  	struct mgmt_pending_cmd *cmd;
4375f1037   Johan Hedberg   Bluetooth: Add ne...
4750
  	struct hci_request req;
cc91cb042   Marcel Holtmann   Bluetooth: Add su...
4751
  	u8 val, status;
4375f1037   Johan Hedberg   Bluetooth: Add ne...
4752
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
4753
  	bt_dev_dbg(hdev, "sock %p", sk);
4375f1037   Johan Hedberg   Bluetooth: Add ne...
4754

e6fe79865   Johan Hedberg   Bluetooth: Fix RE...
4755
4756
  	status = mgmt_le_support(hdev);
  	if (status)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4757
4758
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
  				       status);
4375f1037   Johan Hedberg   Bluetooth: Add ne...
4759

cbbdfa6f3   Sathish Narasimman   Bluetooth: Enable...
4760
4761
4762
4763
4764
4765
  	/* Enabling the experimental LL Privay support disables support for
  	 * advertising.
  	 */
  	if (hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
  				       MGMT_STATUS_NOT_SUPPORTED);
cc91cb042   Marcel Holtmann   Bluetooth: Add su...
4766
  	if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4767
4768
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
  				       MGMT_STATUS_INVALID_PARAMS);
4375f1037   Johan Hedberg   Bluetooth: Add ne...
4769

4867bd007   Abhishek Pandit-Subedi   Bluetooth: Pause ...
4770
4771
4772
  	if (hdev->advertising_paused)
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
  				       MGMT_STATUS_BUSY);
4375f1037   Johan Hedberg   Bluetooth: Add ne...
4773
4774
4775
  	hci_dev_lock(hdev);
  
  	val = !!cp->val;
4375f1037   Johan Hedberg   Bluetooth: Add ne...
4776

f74ca9b80   Johan Hedberg   Bluetooth: Fix ch...
4777
4778
4779
4780
4781
  	/* 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...
4782
  	if (!hdev_is_powered(hdev) ||
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
4783
4784
  	    (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...
4785
  	    hci_conn_num(hdev, LE_LINK) > 0 ||
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
4786
  	    (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
e8bb6b973   Johan Hedberg   Bluetooth: Fix ad...
4787
  	     hdev->le_scan_type == LE_SCAN_ACTIVE)) {
cc91cb042   Marcel Holtmann   Bluetooth: Add su...
4788
  		bool changed;
4375f1037   Johan Hedberg   Bluetooth: Add ne...
4789

cc91cb042   Marcel Holtmann   Bluetooth: Add su...
4790
  		if (cp->val) {
cab054ab4   Johan Hedberg   Bluetooth: Clean ...
4791
  			hdev->cur_adv_instance = 0x00;
238be788f   Marcel Holtmann   Bluetooth: Introd...
4792
  			changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING);
cc91cb042   Marcel Holtmann   Bluetooth: Add su...
4793
  			if (cp->val == 0x02)
a1536da25   Marcel Holtmann   Bluetooth: Introd...
4794
  				hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
cc91cb042   Marcel Holtmann   Bluetooth: Add su...
4795
  			else
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
4796
  				hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
cc91cb042   Marcel Holtmann   Bluetooth: Add su...
4797
  		} else {
a69d89272   Marcel Holtmann   Bluetooth: Introd...
4798
  			changed = hci_dev_test_and_clear_flag(hdev, HCI_ADVERTISING);
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
4799
  			hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
4375f1037   Johan Hedberg   Bluetooth: Add ne...
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
  		}
  
  		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...
4811
4812
  	if (pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
  	    pending_find(MGMT_OP_SET_LE, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4813
4814
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
  				      MGMT_STATUS_BUSY);
4375f1037   Johan Hedberg   Bluetooth: Add ne...
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
  		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...
4825
  	if (cp->val == 0x02)
a1536da25   Marcel Holtmann   Bluetooth: Introd...
4826
  		hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
cc91cb042   Marcel Holtmann   Bluetooth: Add su...
4827
  	else
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
4828
  		hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
cc91cb042   Marcel Holtmann   Bluetooth: Add su...
4829

7816b8203   Florian Grandel   Bluetooth: mgmt: ...
4830
  	cancel_adv_timeout(hdev);
24b4f38fc   Arman Uguray   Bluetooth: Implem...
4831
  	if (val) {
7816b8203   Florian Grandel   Bluetooth: mgmt: ...
4832
4833
4834
4835
  		/* 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 ...
4836
  		hdev->cur_adv_instance = 0x00;
de181e887   Jaganath Kanakkassery   Bluetooth: Impmle...
4837
4838
4839
4840
4841
4842
4843
4844
  
  		if (ext_adv_capable(hdev)) {
  			__hci_req_start_ext_adv(&req, 0x00);
  		} else {
  			__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...
4845
  	} else {
f22525700   Johan Hedberg   Bluetooth: Move a...
4846
  		__hci_req_disable_advertising(&req);
24b4f38fc   Arman Uguray   Bluetooth: Implem...
4847
  	}
4375f1037   Johan Hedberg   Bluetooth: Add ne...
4848
4849
4850
4851
4852
4853
4854
4855
4856
  
  	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...
4857
4858
4859
4860
4861
  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;
181d69535   Marcel Holtmann   Bluetooth: Replac...
4862
  	bt_dev_dbg(hdev, "sock %p", sk);
d13eafce2   Marcel Holtmann   Bluetooth: Add ma...
4863

62af44431   Marcel Holtmann   Bluetooth: Allow ...
4864
  	if (!lmp_le_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4865
4866
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
  				       MGMT_STATUS_NOT_SUPPORTED);
d13eafce2   Marcel Holtmann   Bluetooth: Add ma...
4867
4868
  
  	if (hdev_is_powered(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4869
4870
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
  				       MGMT_STATUS_REJECTED);
d13eafce2   Marcel Holtmann   Bluetooth: Add ma...
4871
4872
4873
  
  	if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
  		if (!bacmp(&cp->bdaddr, BDADDR_NONE))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4874
4875
4876
  			return mgmt_cmd_status(sk, hdev->id,
  					       MGMT_OP_SET_STATIC_ADDRESS,
  					       MGMT_STATUS_INVALID_PARAMS);
d13eafce2   Marcel Holtmann   Bluetooth: Add ma...
4877
4878
4879
  
  		/* Two most significant bits shall be set */
  		if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4880
4881
4882
  			return mgmt_cmd_status(sk, hdev->id,
  					       MGMT_OP_SET_STATIC_ADDRESS,
  					       MGMT_STATUS_INVALID_PARAMS);
d13eafce2   Marcel Holtmann   Bluetooth: Add ma...
4883
4884
4885
4886
4887
  	}
  
  	hci_dev_lock(hdev);
  
  	bacpy(&hdev->static_addr, &cp->bdaddr);
93690c227   Marcel Holtmann   Bluetooth: Introd...
4888
4889
4890
4891
4892
  	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...
4893

93690c227   Marcel Holtmann   Bluetooth: Introd...
4894
  unlock:
d13eafce2   Marcel Holtmann   Bluetooth: Add ma...
4895
  	hci_dev_unlock(hdev);
d13eafce2   Marcel Holtmann   Bluetooth: Add ma...
4896
4897
  	return err;
  }
14b49b9a4   Marcel Holtmann   Bluetooth: Add ma...
4898
4899
4900
4901
4902
4903
  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;
181d69535   Marcel Holtmann   Bluetooth: Replac...
4904
  	bt_dev_dbg(hdev, "sock %p", sk);
14b49b9a4   Marcel Holtmann   Bluetooth: Add ma...
4905
4906
  
  	if (!lmp_le_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4907
4908
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
  				       MGMT_STATUS_NOT_SUPPORTED);
14b49b9a4   Marcel Holtmann   Bluetooth: Add ma...
4909
4910
4911
4912
  
  	interval = __le16_to_cpu(cp->interval);
  
  	if (interval < 0x0004 || interval > 0x4000)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4913
4914
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
  				       MGMT_STATUS_INVALID_PARAMS);
14b49b9a4   Marcel Holtmann   Bluetooth: Add ma...
4915
4916
4917
4918
  
  	window = __le16_to_cpu(cp->window);
  
  	if (window < 0x0004 || window > 0x4000)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4919
4920
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
  				       MGMT_STATUS_INVALID_PARAMS);
14b49b9a4   Marcel Holtmann   Bluetooth: Add ma...
4921

899e10757   Marcel Holtmann   Bluetooth: Check ...
4922
  	if (window > interval)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4923
4924
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
  				       MGMT_STATUS_INVALID_PARAMS);
899e10757   Marcel Holtmann   Bluetooth: Check ...
4925

14b49b9a4   Marcel Holtmann   Bluetooth: Add ma...
4926
4927
4928
4929
  	hci_dev_lock(hdev);
  
  	hdev->le_scan_interval = interval;
  	hdev->le_scan_window = window;
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
4930
4931
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
  				NULL, 0);
14b49b9a4   Marcel Holtmann   Bluetooth: Add ma...
4932

dd2ef8e27   Andre Guedes   Bluetooth: Update...
4933
4934
4935
  	/* If background scan is running, restart it so new parameters are
  	 * loaded.
  	 */
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
4936
  	if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
dd2ef8e27   Andre Guedes   Bluetooth: Update...
4937
4938
4939
4940
  	    hdev->discovery.state == DISCOVERY_STOPPED) {
  		struct hci_request req;
  
  		hci_req_init(&req, hdev);
5c49bcce5   Sathish Narasimman   Bluetooth: Enable...
4941
  		hci_req_add_le_scan_disable(&req, false);
dd2ef8e27   Andre Guedes   Bluetooth: Update...
4942
4943
4944
4945
  		hci_req_add_le_passive_scan(&req);
  
  		hci_req_run(&req, NULL);
  	}
14b49b9a4   Marcel Holtmann   Bluetooth: Add ma...
4946
4947
4948
4949
  	hci_dev_unlock(hdev);
  
  	return err;
  }
1904a853f   Marcel Holtmann   Bluetooth: Add op...
4950
4951
  static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
  				      u16 opcode)
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
4952
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
4953
  	struct mgmt_pending_cmd *cmd;
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
4954

181d69535   Marcel Holtmann   Bluetooth: Replac...
4955
  	bt_dev_dbg(hdev, "status 0x%02x", status);
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
4956
4957
  
  	hci_dev_lock(hdev);
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
4958
  	cmd = pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
4959
4960
4961
4962
  	if (!cmd)
  		goto unlock;
  
  	if (status) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4963
4964
  		mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
  			        mgmt_status(status));
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
4965
  	} else {
1a4d3c4b3   Johan Hedberg   Bluetooth: Add pr...
4966
4967
4968
  		struct mgmt_mode *cp = cmd->param;
  
  		if (cp->val)
a1536da25   Marcel Holtmann   Bluetooth: Introd...
4969
  			hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
1a4d3c4b3   Johan Hedberg   Bluetooth: Add pr...
4970
  		else
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
4971
  			hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
1a4d3c4b3   Johan Hedberg   Bluetooth: Add pr...
4972

33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
4973
4974
4975
4976
4977
4978
4979
4980
4981
  		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: ...
4982
  static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
4983
  				void *data, u16 len)
f6422ec62   Antti Julku   Bluetooth: Add mg...
4984
  {
650f726d1   Vinicius Costa Gomes   Bluetooth: Fix do...
4985
  	struct mgmt_mode *cp = data;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
4986
  	struct mgmt_pending_cmd *cmd;
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
4987
  	struct hci_request req;
f6422ec62   Antti Julku   Bluetooth: Add mg...
4988
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
4989
  	bt_dev_dbg(hdev, "sock %p", sk);
f6422ec62   Antti Julku   Bluetooth: Add mg...
4990

d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
4991
  	if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
56f879010   Johan Hedberg   Bluetooth: Introd...
4992
  	    hdev->hci_ver < BLUETOOTH_VER_1_2)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
4993
4994
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
  				       MGMT_STATUS_NOT_SUPPORTED);
33c525c0a   Johan Hedberg   Bluetooth: mgmt: ...
4995

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

f6422ec62   Antti Julku   Bluetooth: Add mg...
5000
  	hci_dev_lock(hdev);
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
5001
  	if (pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5002
5003
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
  				      MGMT_STATUS_BUSY);
05cbf29f8   Johan Hedberg   Bluetooth: Fix er...
5004
5005
  		goto unlock;
  	}
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
5006
  	if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
1a4d3c4b3   Johan Hedberg   Bluetooth: Add pr...
5007
5008
5009
5010
  		err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
  					hdev);
  		goto unlock;
  	}
406ef2a67   Johan Hedberg   Bluetooth: Make F...
5011
  	if (!hdev_is_powered(hdev)) {
ce05d603a   Marcel Holtmann   Bluetooth: Introd...
5012
  		hci_dev_change_flag(hdev, HCI_FAST_CONNECTABLE);
406ef2a67   Johan Hedberg   Bluetooth: Make F...
5013
5014
5015
5016
5017
  		err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
  					hdev);
  		new_settings(hdev, sk);
  		goto unlock;
  	}
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
5018
5019
5020
5021
5022
  	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...
5023
  	}
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
5024
  	hci_req_init(&req, hdev);
bf943cbf7   Johan Hedberg   Bluetooth: Move f...
5025
  	__hci_req_write_fast_connectable(&req, cp->val);
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
5026
5027
  
  	err = hci_req_run(&req, fast_connectable_complete);
f6422ec62   Antti Julku   Bluetooth: Add mg...
5028
  	if (err < 0) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5029
5030
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
  				      MGMT_STATUS_FAILED);
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
5031
  		mgmt_pending_remove(cmd);
f6422ec62   Antti Julku   Bluetooth: Add mg...
5032
  	}
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
5033
  unlock:
f6422ec62   Antti Julku   Bluetooth: Add mg...
5034
  	hci_dev_unlock(hdev);
33e38b3e1   Johan Hedberg   Bluetooth: Fix fa...
5035

f6422ec62   Antti Julku   Bluetooth: Add mg...
5036
5037
  	return err;
  }
1904a853f   Marcel Holtmann   Bluetooth: Add op...
5038
  static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
5039
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
5040
  	struct mgmt_pending_cmd *cmd;
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
5041

181d69535   Marcel Holtmann   Bluetooth: Replac...
5042
  	bt_dev_dbg(hdev, "status 0x%02x", status);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
5043
5044
  
  	hci_dev_lock(hdev);
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
5045
  	cmd = pending_find(MGMT_OP_SET_BREDR, hdev);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
5046
5047
5048
5049
5050
5051
5052
5053
5054
  	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...
5055
  		hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
5056

a69e8375a   Johan Hedberg   Bluetooth: Rename...
5057
  		mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
  	} 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...
5072
  	struct mgmt_pending_cmd *cmd;
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
5073
5074
  	struct hci_request req;
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
5075
  	bt_dev_dbg(hdev, "sock %p", sk);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
5076
5077
  
  	if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5078
5079
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
  				       MGMT_STATUS_NOT_SUPPORTED);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
5080

d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
5081
  	if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5082
5083
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
  				       MGMT_STATUS_REJECTED);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
5084
5085
  
  	if (cp->val != 0x00 && cp->val != 0x01)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5086
5087
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
  				       MGMT_STATUS_INVALID_PARAMS);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
5088
5089
  
  	hci_dev_lock(hdev);
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
5090
  	if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
5091
5092
5093
5094
5095
5096
  		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...
5097
5098
5099
5100
5101
  			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 ...
5102
  		}
ce05d603a   Marcel Holtmann   Bluetooth: Introd...
5103
  		hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
  
  		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...
5115
5116
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
  				      MGMT_STATUS_REJECTED);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
5117
  		goto unlock;
111e4bccd   Marcel Holtmann   Bluetooth: Fix is...
5118
5119
5120
5121
5122
5123
5124
5125
  	} 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 ...
5126
5127
5128
5129
5130
5131
  		 *
  		 * 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...
5132
  		 */
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
5133
  		if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
3a5486e1f   Marcel Holtmann   Bluetooth: Limit ...
5134
  		    (bacmp(&hdev->static_addr, BDADDR_ANY) ||
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
5135
  		     hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5136
5137
  			err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
  					      MGMT_STATUS_REJECTED);
111e4bccd   Marcel Holtmann   Bluetooth: Fix is...
5138
5139
  			goto unlock;
  		}
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
5140
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
5141
  	if (pending_find(MGMT_OP_SET_BREDR, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5142
5143
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
  				      MGMT_STATUS_BUSY);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
5144
5145
5146
5147
5148
5149
5150
5151
  		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...
5152
5153
  	/* 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 ...
5154
  	 */
a1536da25   Marcel Holtmann   Bluetooth: Introd...
5155
  	hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
5156
5157
  
  	hci_req_init(&req, hdev);
aa8af46e9   Johan Hedberg   Bluetooth: Fix up...
5158

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

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

0663ca2a0   Johan Hedberg   Bluetooth: Add a ...
5167
5168
5169
5170
5171
5172
5173
5174
  	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...
5175
5176
  static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
5177
  	struct mgmt_pending_cmd *cmd;
a1443f5a2   Johan Hedberg   Bluetooth: Conver...
5178
  	struct mgmt_mode *cp;
181d69535   Marcel Holtmann   Bluetooth: Replac...
5179
  	bt_dev_dbg(hdev, "status %u", status);
a1443f5a2   Johan Hedberg   Bluetooth: Conver...
5180
5181
  
  	hci_dev_lock(hdev);
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
5182
  	cmd = pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
a1443f5a2   Johan Hedberg   Bluetooth: Conver...
5183
5184
5185
5186
  	if (!cmd)
  		goto unlock;
  
  	if (status) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5187
5188
  		mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
  			        mgmt_status(status));
a1443f5a2   Johan Hedberg   Bluetooth: Conver...
5189
5190
5191
5192
5193
5194
5195
  		goto remove;
  	}
  
  	cp = cmd->param;
  
  	switch (cp->val) {
  	case 0x00:
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
5196
5197
  		hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
  		hci_dev_clear_flag(hdev, HCI_SC_ONLY);
a1443f5a2   Johan Hedberg   Bluetooth: Conver...
5198
5199
  		break;
  	case 0x01:
a1536da25   Marcel Holtmann   Bluetooth: Introd...
5200
  		hci_dev_set_flag(hdev, HCI_SC_ENABLED);
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
5201
  		hci_dev_clear_flag(hdev, HCI_SC_ONLY);
a1443f5a2   Johan Hedberg   Bluetooth: Conver...
5202
5203
  		break;
  	case 0x02:
a1536da25   Marcel Holtmann   Bluetooth: Introd...
5204
5205
  		hci_dev_set_flag(hdev, HCI_SC_ENABLED);
  		hci_dev_set_flag(hdev, HCI_SC_ONLY);
a1443f5a2   Johan Hedberg   Bluetooth: Conver...
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
  		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...
5217
5218
5219
5220
  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...
5221
  	struct mgmt_pending_cmd *cmd;
a1443f5a2   Johan Hedberg   Bluetooth: Conver...
5222
  	struct hci_request req;
a3209694f   Johan Hedberg   Bluetooth: Add mg...
5223
  	u8 val;
eac83dc63   Marcel Holtmann   Bluetooth: Add ma...
5224
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
5225
  	bt_dev_dbg(hdev, "sock %p", sk);
eac83dc63   Marcel Holtmann   Bluetooth: Add ma...
5226

05b3c3e79   Marcel Holtmann   Bluetooth: Remove...
5227
  	if (!lmp_sc_capable(hdev) &&
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
5228
  	    !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5229
5230
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
  				       MGMT_STATUS_NOT_SUPPORTED);
eac83dc63   Marcel Holtmann   Bluetooth: Add ma...
5231

d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
5232
  	if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
592002863   Johan Hedberg   Bluetooth: Fix ch...
5233
  	    lmp_sc_capable(hdev) &&
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
5234
  	    !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5235
5236
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
  				       MGMT_STATUS_REJECTED);
ed93ec69c   Marcel Holtmann   Bluetooth: Requir...
5237

0ab04a9c0   Marcel Holtmann   Bluetooth: Add ma...
5238
  	if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5239
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
eac83dc63   Marcel Holtmann   Bluetooth: Add ma...
5240
5241
5242
  				  MGMT_STATUS_INVALID_PARAMS);
  
  	hci_dev_lock(hdev);
05b3c3e79   Marcel Holtmann   Bluetooth: Remove...
5243
  	if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
5244
  	    !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
eac83dc63   Marcel Holtmann   Bluetooth: Add ma...
5245
  		bool changed;
0ab04a9c0   Marcel Holtmann   Bluetooth: Add ma...
5246
  		if (cp->val) {
238be788f   Marcel Holtmann   Bluetooth: Introd...
5247
5248
  			changed = !hci_dev_test_and_set_flag(hdev,
  							     HCI_SC_ENABLED);
0ab04a9c0   Marcel Holtmann   Bluetooth: Add ma...
5249
  			if (cp->val == 0x02)
a1536da25   Marcel Holtmann   Bluetooth: Introd...
5250
  				hci_dev_set_flag(hdev, HCI_SC_ONLY);
0ab04a9c0   Marcel Holtmann   Bluetooth: Add ma...
5251
  			else
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
5252
  				hci_dev_clear_flag(hdev, HCI_SC_ONLY);
0ab04a9c0   Marcel Holtmann   Bluetooth: Add ma...
5253
  		} else {
a69d89272   Marcel Holtmann   Bluetooth: Introd...
5254
5255
  			changed = hci_dev_test_and_clear_flag(hdev,
  							      HCI_SC_ENABLED);
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
5256
  			hci_dev_clear_flag(hdev, HCI_SC_ONLY);
0ab04a9c0   Marcel Holtmann   Bluetooth: Add ma...
5257
  		}
eac83dc63   Marcel Holtmann   Bluetooth: Add ma...
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
  
  		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...
5268
  	if (pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5269
5270
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
  				      MGMT_STATUS_BUSY);
eac83dc63   Marcel Holtmann   Bluetooth: Add ma...
5271
5272
  		goto failed;
  	}
0ab04a9c0   Marcel Holtmann   Bluetooth: Add ma...
5273
  	val = !!cp->val;
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
5274
5275
  	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...
5276
5277
5278
5279
5280
5281
5282
5283
5284
  		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...
5285
5286
5287
  	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...
5288
5289
5290
5291
5292
5293
5294
5295
5296
  	if (err < 0) {
  		mgmt_pending_remove(cmd);
  		goto failed;
  	}
  
  failed:
  	hci_dev_unlock(hdev);
  	return err;
  }
4e39ac813   Marcel Holtmann   Bluetooth: Add ma...
5297
5298
5299
5300
  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...
5301
  	bool changed, use_changed;
4e39ac813   Marcel Holtmann   Bluetooth: Add ma...
5302
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
5303
  	bt_dev_dbg(hdev, "sock %p", sk);
4e39ac813   Marcel Holtmann   Bluetooth: Add ma...
5304

b97109790   Johan Hedberg   Bluetooth: Add su...
5305
  	if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5306
5307
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
  				       MGMT_STATUS_INVALID_PARAMS);
4e39ac813   Marcel Holtmann   Bluetooth: Add ma...
5308
5309
5310
5311
  
  	hci_dev_lock(hdev);
  
  	if (cp->val)
238be788f   Marcel Holtmann   Bluetooth: Introd...
5312
  		changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
4e39ac813   Marcel Holtmann   Bluetooth: Add ma...
5313
  	else
a69d89272   Marcel Holtmann   Bluetooth: Introd...
5314
5315
  		changed = hci_dev_test_and_clear_flag(hdev,
  						      HCI_KEEP_DEBUG_KEYS);
4e39ac813   Marcel Holtmann   Bluetooth: Add ma...
5316

b97109790   Johan Hedberg   Bluetooth: Add su...
5317
  	if (cp->val == 0x02)
238be788f   Marcel Holtmann   Bluetooth: Introd...
5318
5319
  		use_changed = !hci_dev_test_and_set_flag(hdev,
  							 HCI_USE_DEBUG_KEYS);
b97109790   Johan Hedberg   Bluetooth: Add su...
5320
  	else
a69d89272   Marcel Holtmann   Bluetooth: Introd...
5321
5322
  		use_changed = hci_dev_test_and_clear_flag(hdev,
  							  HCI_USE_DEBUG_KEYS);
b97109790   Johan Hedberg   Bluetooth: Add su...
5323
5324
  
  	if (hdev_is_powered(hdev) && use_changed &&
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
5325
  	    hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
b97109790   Johan Hedberg   Bluetooth: Add su...
5326
5327
5328
5329
  		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...
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
  	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...
5341
5342
5343
5344
5345
5346
  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;
181d69535   Marcel Holtmann   Bluetooth: Replac...
5347
  	bt_dev_dbg(hdev, "sock %p", sk);
62b04cd12   Johan Hedberg   Bluetooth: Add su...
5348
5349
  
  	if (!lmp_le_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5350
5351
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
  				       MGMT_STATUS_NOT_SUPPORTED);
62b04cd12   Johan Hedberg   Bluetooth: Add su...
5352

82a37adee   Johan Hedberg   Bluetooth: Add su...
5353
  	if (cp->privacy != 0x00 && cp->privacy != 0x01 && cp->privacy != 0x02)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5354
5355
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
  				       MGMT_STATUS_INVALID_PARAMS);
62b04cd12   Johan Hedberg   Bluetooth: Add su...
5356
5357
  
  	if (hdev_is_powered(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5358
5359
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
  				       MGMT_STATUS_REJECTED);
62b04cd12   Johan Hedberg   Bluetooth: Add su...
5360
5361
  
  	hci_dev_lock(hdev);
c21c0ea07   Johan Hedberg   Bluetooth: Enable...
5362
5363
5364
  	/* 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...
5365
  	hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
c21c0ea07   Johan Hedberg   Bluetooth: Enable...
5366

62b04cd12   Johan Hedberg   Bluetooth: Add su...
5367
  	if (cp->privacy) {
238be788f   Marcel Holtmann   Bluetooth: Introd...
5368
  		changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY);
62b04cd12   Johan Hedberg   Bluetooth: Add su...
5369
  		memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
a1536da25   Marcel Holtmann   Bluetooth: Introd...
5370
  		hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
a73c046a2   Jaganath Kanakkassery   Bluetooth: Implem...
5371
  		hci_adv_instances_set_rpa_expired(hdev, true);
82a37adee   Johan Hedberg   Bluetooth: Add su...
5372
5373
5374
5375
  		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...
5376
  	} else {
a69d89272   Marcel Holtmann   Bluetooth: Introd...
5377
  		changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
62b04cd12   Johan Hedberg   Bluetooth: Add su...
5378
  		memset(hdev->irk, 0, sizeof(hdev->irk));
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
5379
  		hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
a73c046a2   Jaganath Kanakkassery   Bluetooth: Implem...
5380
  		hci_adv_instances_set_rpa_expired(hdev, false);
82a37adee   Johan Hedberg   Bluetooth: Add su...
5381
  		hci_dev_clear_flag(hdev, HCI_LIMITED_PRIVACY);
62b04cd12   Johan Hedberg   Bluetooth: Add su...
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
  	}
  
  	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...
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
  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...
5415
5416
  	const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
  				   sizeof(struct mgmt_irk_info));
41edf1601   Johan Hedberg   Bluetooth: Implem...
5417
5418
  	u16 irk_count, expected_len;
  	int i, err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
5419
  	bt_dev_dbg(hdev, "sock %p", sk);
41edf1601   Johan Hedberg   Bluetooth: Implem...
5420
5421
  
  	if (!lmp_le_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5422
5423
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
  				       MGMT_STATUS_NOT_SUPPORTED);
41edf1601   Johan Hedberg   Bluetooth: Implem...
5424
5425
  
  	irk_count = __le16_to_cpu(cp->irk_count);
ba1d6936f   Johan Hedberg   Bluetooth: Fix bu...
5426
  	if (irk_count > max_irk_count) {
2064ee332   Marcel Holtmann   Bluetooth: Use bt...
5427
5428
  		bt_dev_err(hdev, "load_irks: too big irk_count value %u",
  			   irk_count);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5429
5430
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
  				       MGMT_STATUS_INVALID_PARAMS);
ba1d6936f   Johan Hedberg   Bluetooth: Fix bu...
5431
  	}
41edf1601   Johan Hedberg   Bluetooth: Implem...
5432

5bec1fb86   Gustavo A. R. Silva   Bluetooth: Use st...
5433
  	expected_len = struct_size(cp, irks, irk_count);
41edf1601   Johan Hedberg   Bluetooth: Implem...
5434
  	if (expected_len != len) {
2064ee332   Marcel Holtmann   Bluetooth: Use bt...
5435
5436
  		bt_dev_err(hdev, "load_irks: expected %u bytes, got %u bytes",
  			   expected_len, len);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5437
5438
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
  				       MGMT_STATUS_INVALID_PARAMS);
41edf1601   Johan Hedberg   Bluetooth: Implem...
5439
  	}
181d69535   Marcel Holtmann   Bluetooth: Replac...
5440
  	bt_dev_dbg(hdev, "irk_count %u", irk_count);
41edf1601   Johan Hedberg   Bluetooth: Implem...
5441
5442
5443
5444
5445
  
  	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...
5446
5447
5448
  			return mgmt_cmd_status(sk, hdev->id,
  					       MGMT_OP_LOAD_IRKS,
  					       MGMT_STATUS_INVALID_PARAMS);
41edf1601   Johan Hedberg   Bluetooth: Implem...
5449
5450
5451
5452
5453
5454
5455
5456
  	}
  
  	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...
5457

600a87490   Alain Michaud   Bluetooth: Implem...
5458
5459
5460
5461
5462
5463
5464
  		if (hci_is_blocked_key(hdev,
  				       HCI_BLOCKED_KEY_TYPE_IRK,
  				       irk->val)) {
  			bt_dev_warn(hdev, "Skipping blocked IRK for %pMR",
  				    &irk->addr.bdaddr);
  			continue;
  		}
85813a7ec   Johan Hedberg   Bluetooth: Add le...
5465
5466
  		hci_add_irk(hdev, &irk->addr.bdaddr,
  			    le_addr_type(irk->addr.type), irk->val,
41edf1601   Johan Hedberg   Bluetooth: Implem...
5467
5468
  			    BDADDR_ANY);
  	}
a1536da25   Marcel Holtmann   Bluetooth: Introd...
5469
  	hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
41edf1601   Johan Hedberg   Bluetooth: Implem...
5470

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
5471
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
41edf1601   Johan Hedberg   Bluetooth: Implem...
5472
5473
5474
5475
5476
  
  	hci_dev_unlock(hdev);
  
  	return err;
  }
3f706b720   Johan Hedberg   Bluetooth: Refact...
5477
5478
5479
5480
  static bool ltk_is_valid(struct mgmt_ltk_info *key)
  {
  	if (key->master != 0x00 && key->master != 0x01)
  		return false;
490cb0b31   Marcel Holtmann   Bluetooth: Restri...
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
  
  	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...
5494
  }
bdb6d9715   Johan Hedberg   Bluetooth: mgmt: ...
5495
  static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
5496
  			       void *cp_data, u16 len)
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
5497
  {
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
5498
  	struct mgmt_cp_load_long_term_keys *cp = cp_data;
ba1d6936f   Johan Hedberg   Bluetooth: Fix bu...
5499
5500
  	const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
  				   sizeof(struct mgmt_ltk_info));
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
5501
  	u16 key_count, expected_len;
715a5bf2d   Johan Hedberg   Bluetooth: Fix mi...
5502
  	int i, err;
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
5503

181d69535   Marcel Holtmann   Bluetooth: Replac...
5504
  	bt_dev_dbg(hdev, "sock %p", sk);
cf99ba135   Marcel Holtmann   Bluetooth: Restri...
5505
5506
  
  	if (!lmp_le_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5507
5508
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
  				       MGMT_STATUS_NOT_SUPPORTED);
cf99ba135   Marcel Holtmann   Bluetooth: Restri...
5509

1f350c872   Marcel Holtmann   Bluetooth: Fix br...
5510
  	key_count = __le16_to_cpu(cp->key_count);
ba1d6936f   Johan Hedberg   Bluetooth: Fix bu...
5511
  	if (key_count > max_key_count) {
2064ee332   Marcel Holtmann   Bluetooth: Use bt...
5512
5513
  		bt_dev_err(hdev, "load_ltks: too big key_count value %u",
  			   key_count);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5514
5515
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
  				       MGMT_STATUS_INVALID_PARAMS);
ba1d6936f   Johan Hedberg   Bluetooth: Fix bu...
5516
  	}
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
5517

5bec1fb86   Gustavo A. R. Silva   Bluetooth: Use st...
5518
  	expected_len = struct_size(cp, keys, key_count);
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
5519
  	if (expected_len != len) {
2064ee332   Marcel Holtmann   Bluetooth: Use bt...
5520
5521
  		bt_dev_err(hdev, "load_keys: expected %u bytes, got %u bytes",
  			   expected_len, len);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5522
5523
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
  				       MGMT_STATUS_INVALID_PARAMS);
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
5524
  	}
181d69535   Marcel Holtmann   Bluetooth: Replac...
5525
  	bt_dev_dbg(hdev, "key_count %u", key_count);
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
5526

54ad6d8a5   Johan Hedberg   Bluetooth: Fix ch...
5527
5528
  	for (i = 0; i < key_count; i++) {
  		struct mgmt_ltk_info *key = &cp->keys[i];
3f706b720   Johan Hedberg   Bluetooth: Refact...
5529
  		if (!ltk_is_valid(key))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
5530
5531
5532
  			return mgmt_cmd_status(sk, hdev->id,
  					       MGMT_OP_LOAD_LONG_TERM_KEYS,
  					       MGMT_STATUS_INVALID_PARAMS);
54ad6d8a5   Johan Hedberg   Bluetooth: Fix ch...
5533
  	}
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
5534
5535
5536
5537
5538
5539
  	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...
5540
  		u8 type, authenticated;
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
5541

600a87490   Alain Michaud   Bluetooth: Implem...
5542
5543
5544
5545
5546
5547
5548
  		if (hci_is_blocked_key(hdev,
  				       HCI_BLOCKED_KEY_TYPE_LTK,
  				       key->val)) {
  			bt_dev_warn(hdev, "Skipping blocked LTK for %pMR",
  				    &key->addr.bdaddr);
  			continue;
  		}
61b433579   Johan Hedberg   Bluetooth: Fix pr...
5549
5550
  		switch (key->type) {
  		case MGMT_LTK_UNAUTHENTICATED:
d7b254502   Johan Hedberg   Bluetooth: Clearl...
5551
  			authenticated = 0x00;
23fb8de37   Johan Hedberg   Bluetooth: Add mg...
5552
  			type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
61b433579   Johan Hedberg   Bluetooth: Fix pr...
5553
5554
  			break;
  		case MGMT_LTK_AUTHENTICATED:
d7b254502   Johan Hedberg   Bluetooth: Clearl...
5555
  			authenticated = 0x01;
23fb8de37   Johan Hedberg   Bluetooth: Add mg...
5556
5557
5558
5559
5560
  			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...
5561
  			break;
23fb8de37   Johan Hedberg   Bluetooth: Add mg...
5562
5563
5564
  		case MGMT_LTK_P256_AUTH:
  			authenticated = 0x01;
  			type = SMP_LTK_P256;
61b433579   Johan Hedberg   Bluetooth: Fix pr...
5565
  			break;
23fb8de37   Johan Hedberg   Bluetooth: Add mg...
5566
5567
5568
  		case MGMT_LTK_P256_DEBUG:
  			authenticated = 0x00;
  			type = SMP_LTK_P256_DEBUG;
19186c7b4   Gustavo A. R. Silva   Bluetooth: core: ...
5569
  			fallthrough;
61b433579   Johan Hedberg   Bluetooth: Fix pr...
5570
5571
5572
  		default:
  			continue;
  		}
d7b254502   Johan Hedberg   Bluetooth: Clearl...
5573

85813a7ec   Johan Hedberg   Bluetooth: Add le...
5574
5575
5576
  		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...
5577
  	}
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
5578
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
715a5bf2d   Johan Hedberg   Bluetooth: Fix mi...
5579
  			   NULL, 0);
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
5580
  	hci_dev_unlock(hdev);
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
5581

715a5bf2d   Johan Hedberg   Bluetooth: Fix mi...
5582
  	return err;
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
5583
  }
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
5584
  static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5585
  {
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5586
  	struct hci_conn *conn = cmd->user_data;
9981bdb05   Johan Hedberg   Bluetooth: Fix Ge...
5587
  	struct mgmt_rp_get_conn_info rp;
9df746535   Johan Hedberg   Bluetooth: Add re...
5588
  	int err;
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5589

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

9981bdb05   Johan Hedberg   Bluetooth: Fix Ge...
5592
  	if (status == MGMT_STATUS_SUCCESS) {
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5593
  		rp.rssi = conn->rssi;
9981bdb05   Johan Hedberg   Bluetooth: Fix Ge...
5594
5595
5596
5597
5598
5599
  		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...
5600
  	}
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
5601
5602
  	err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
  				status, &rp, sizeof(rp));
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5603
5604
  
  	hci_conn_drop(conn);
f8aaf9b65   Johan Hedberg   Bluetooth: Fix us...
5605
  	hci_conn_put(conn);
9df746535   Johan Hedberg   Bluetooth: Add re...
5606
5607
  
  	return err;
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5608
  }
1904a853f   Marcel Holtmann   Bluetooth: Add op...
5609
5610
  static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
  				       u16 opcode)
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5611
5612
  {
  	struct hci_cp_read_rssi *cp;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
5613
  	struct mgmt_pending_cmd *cmd;
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5614
  	struct hci_conn *conn;
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5615
  	u16 handle;
9981bdb05   Johan Hedberg   Bluetooth: Fix Ge...
5616
  	u8 status;
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5617

181d69535   Marcel Holtmann   Bluetooth: Replac...
5618
  	bt_dev_dbg(hdev, "status 0x%02x", hci_status);
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5619
5620
  
  	hci_dev_lock(hdev);
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
  	/* 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...
5633
5634
5635
  		status = MGMT_STATUS_SUCCESS;
  	} else {
  		status = mgmt_status(hci_status);
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5636
5637
5638
  	}
  
  	if (!cp) {
2064ee332   Marcel Holtmann   Bluetooth: Use bt...
5639
  		bt_dev_err(hdev, "invalid sent_cmd in conn_info response");
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5640
5641
5642
5643
5644
5645
  		goto unlock;
  	}
  
  	handle = __le16_to_cpu(cp->handle);
  	conn = hci_conn_hash_lookup_handle(hdev, handle);
  	if (!conn) {
2064ee332   Marcel Holtmann   Bluetooth: Use bt...
5646
5647
  		bt_dev_err(hdev, "unknown handle (%d) in conn_info response",
  			   handle);
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5648
5649
  		goto unlock;
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
5650
  	cmd = pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
9981bdb05   Johan Hedberg   Bluetooth: Fix Ge...
5651
5652
  	if (!cmd)
  		goto unlock;
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5653

9981bdb05   Johan Hedberg   Bluetooth: Fix Ge...
5654
5655
  	cmd->cmd_complete(cmd, status);
  	mgmt_pending_remove(cmd);
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
  
  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;
181d69535   Marcel Holtmann   Bluetooth: Replac...
5669
  	bt_dev_dbg(hdev, "sock %p", sk);
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5670
5671
5672
5673
5674
5675
  
  	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...
5676
5677
5678
  		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...
5679
5680
5681
5682
  
  	hci_dev_lock(hdev);
  
  	if (!hdev_is_powered(hdev)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
5683
5684
5685
  		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...
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
  		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...
5696
5697
5698
  		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...
5699
5700
  		goto unlock;
  	}
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
5701
  	if (pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
5702
5703
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
  					MGMT_STATUS_BUSY, &rp, sizeof(rp));
9981bdb05   Johan Hedberg   Bluetooth: Fix Ge...
5704
5705
  		goto unlock;
  	}
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
  	/* 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...
5716
5717
  	if (time_after(jiffies, conn->conn_info_timestamp +
  		       msecs_to_jiffies(conn_info_age)) ||
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5718
5719
5720
5721
  	    !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...
5722
  		struct mgmt_pending_cmd *cmd;
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5723
5724
5725
5726
5727
  
  		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 ...
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
  		/* 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...
5738

eed5daf31   Andrzej Kaczmarek   Bluetooth: Add su...
5739
5740
5741
5742
5743
5744
5745
  		/* 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...
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
  		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...
5758
  		cmd->user_data = hci_conn_get(conn);
9981bdb05   Johan Hedberg   Bluetooth: Fix Ge...
5759
  		cmd->cmd_complete = conn_info_cmd_complete;
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5760
5761
5762
5763
5764
5765
  
  		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...
5766
  		rp.max_tx_power = conn->max_tx_power;
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5767

2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
5768
5769
  		err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
  					MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
dd9838087   Andrzej Kaczmarek   Bluetooth: Add su...
5770
5771
5772
5773
5774
5775
  	}
  
  unlock:
  	hci_dev_unlock(hdev);
  	return err;
  }
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
5776
  static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
958684263   Johan Hedberg   Bluetooth: Add su...
5777
  {
69487371d   Johan Hedberg   Bluetooth: Conver...
5778
  	struct hci_conn *conn = cmd->user_data;
958684263   Johan Hedberg   Bluetooth: Add su...
5779
  	struct mgmt_rp_get_clock_info rp;
69487371d   Johan Hedberg   Bluetooth: Conver...
5780
  	struct hci_dev *hdev;
9df746535   Johan Hedberg   Bluetooth: Add re...
5781
  	int err;
69487371d   Johan Hedberg   Bluetooth: Conver...
5782
5783
  
  	memset(&rp, 0, sizeof(rp));
56f787c50   Marcel Holtmann   Bluetooth: Fix wr...
5784
  	memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
69487371d   Johan Hedberg   Bluetooth: Conver...
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
  
  	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...
5801
5802
  	err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
  				sizeof(rp));
69487371d   Johan Hedberg   Bluetooth: Conver...
5803
5804
5805
5806
5807
  
  	if (conn) {
  		hci_conn_drop(conn);
  		hci_conn_put(conn);
  	}
9df746535   Johan Hedberg   Bluetooth: Add re...
5808
5809
  
  	return err;
69487371d   Johan Hedberg   Bluetooth: Conver...
5810
  }
1904a853f   Marcel Holtmann   Bluetooth: Add op...
5811
  static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
69487371d   Johan Hedberg   Bluetooth: Conver...
5812
  {
958684263   Johan Hedberg   Bluetooth: Add su...
5813
  	struct hci_cp_read_clock *hci_cp;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
5814
  	struct mgmt_pending_cmd *cmd;
958684263   Johan Hedberg   Bluetooth: Add su...
5815
  	struct hci_conn *conn;
181d69535   Marcel Holtmann   Bluetooth: Replac...
5816
  	bt_dev_dbg(hdev, "status %u", status);
958684263   Johan Hedberg   Bluetooth: Add su...
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
  
  	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...
5830
  	cmd = pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
958684263   Johan Hedberg   Bluetooth: Add su...
5831
5832
  	if (!cmd)
  		goto unlock;
69487371d   Johan Hedberg   Bluetooth: Conver...
5833
  	cmd->cmd_complete(cmd, mgmt_status(status));
958684263   Johan Hedberg   Bluetooth: Add su...
5834
  	mgmt_pending_remove(cmd);
958684263   Johan Hedberg   Bluetooth: Add su...
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
  
  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...
5846
  	struct mgmt_pending_cmd *cmd;
958684263   Johan Hedberg   Bluetooth: Add su...
5847
5848
5849
  	struct hci_request req;
  	struct hci_conn *conn;
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
5850
  	bt_dev_dbg(hdev, "sock %p", sk);
958684263   Johan Hedberg   Bluetooth: Add su...
5851
5852
5853
5854
5855
5856
  
  	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...
5857
5858
5859
  		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...
5860
5861
5862
5863
  
  	hci_dev_lock(hdev);
  
  	if (!hdev_is_powered(hdev)) {
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
5864
5865
5866
  		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...
5867
5868
5869
5870
5871
5872
5873
  		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...
5874
5875
5876
5877
  			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...
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
  			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...
5889
  	cmd->cmd_complete = clock_info_cmd_complete;
958684263   Johan Hedberg   Bluetooth: Add su...
5890
5891
5892
5893
5894
5895
5896
  	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...
5897
  		cmd->user_data = hci_conn_get(conn);
958684263   Johan Hedberg   Bluetooth: Add su...
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
  
  		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...
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
  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 ...
5930
  static int hci_conn_params_set(struct hci_dev *hdev, bdaddr_t *addr,
5a154e6f7   Johan Hedberg   Bluetooth: Fix Ad...
5931
5932
  			       u8 addr_type, u8 auto_connect)
  {
5a154e6f7   Johan Hedberg   Bluetooth: Fix Ad...
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
  	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...
5947
5948
5949
5950
5951
  		/* 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...
5952
5953
  		break;
  	case HCI_AUTO_CONN_REPORT:
49c509220   Johan Hedberg   Bluetooth: Fix LE...
5954
5955
5956
5957
  		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...
5958
5959
5960
  		break;
  	case HCI_AUTO_CONN_DIRECT:
  	case HCI_AUTO_CONN_ALWAYS:
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
5961
  		if (!is_connected(hdev, addr, addr_type))
5a154e6f7   Johan Hedberg   Bluetooth: Fix Ad...
5962
  			list_add(&params->action, &hdev->pend_le_conns);
5a154e6f7   Johan Hedberg   Bluetooth: Fix Ad...
5963
5964
5965
5966
  		break;
  	}
  
  	params->auto_connect = auto_connect;
181d69535   Marcel Holtmann   Bluetooth: Replac...
5967
5968
  	bt_dev_dbg(hdev, "addr %pMR (type %u) auto_connect %u",
  		   addr, addr_type, auto_connect);
5a154e6f7   Johan Hedberg   Bluetooth: Fix Ad...
5969
5970
5971
  
  	return 0;
  }
8afef092a   Marcel Holtmann   Bluetooth: Add De...
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
  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...
5983
5984
5985
5986
5987
  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;
4c54bf2b0   Abhishek Pandit-Subedi   Bluetooth: Add ge...
5988
  	struct hci_conn_params *params;
2faade53e   Marcel Holtmann   Bluetooth: Add su...
5989
  	int err;
4c54bf2b0   Abhishek Pandit-Subedi   Bluetooth: Add ge...
5990
  	u32 current_flags = 0;
2faade53e   Marcel Holtmann   Bluetooth: Add su...
5991

181d69535   Marcel Holtmann   Bluetooth: Replac...
5992
  	bt_dev_dbg(hdev, "sock %p", sk);
2faade53e   Marcel Holtmann   Bluetooth: Add su...
5993

6659358ef   Johan Hedberg   Bluetooth: Introd...
5994
  	if (!bdaddr_type_is_valid(cp->addr.type) ||
2faade53e   Marcel Holtmann   Bluetooth: Add su...
5995
  	    !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
5996
5997
5998
  		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...
5999

4b9e7e751   Marcel Holtmann   Bluetooth: Fix is...
6000
  	if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
2a1afb5ac   Johan Hedberg   Bluetooth: Rename...
6001
6002
6003
  		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...
6004
6005
  
  	hci_dev_lock(hdev);
6659358ef   Johan Hedberg   Bluetooth: Introd...
6006
  	if (cp->addr.type == BDADDR_BREDR) {
4b9e7e751   Marcel Holtmann   Bluetooth: Fix is...
6007
  		/* Only incoming connections action is supported for now */
6659358ef   Johan Hedberg   Bluetooth: Introd...
6008
  		if (cp->action != 0x01) {
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
6009
6010
6011
6012
  			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...
6013
6014
  			goto unlock;
  		}
8baaa4038   Abhishek Pandit-Subedi   Bluetooth: Add bd...
6015
6016
6017
  		err = hci_bdaddr_list_add_with_flags(&hdev->whitelist,
  						     &cp->addr.bdaddr,
  						     cp->addr.type, 0);
6659358ef   Johan Hedberg   Bluetooth: Introd...
6018
6019
  		if (err)
  			goto unlock;
a397407f2   Johan Hedberg   Bluetooth: Update...
6020

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

6659358ef   Johan Hedberg   Bluetooth: Introd...
6023
6024
  		goto added;
  	}
85813a7ec   Johan Hedberg   Bluetooth: Add le...
6025
  	addr_type = le_addr_type(cp->addr.type);
2faade53e   Marcel Holtmann   Bluetooth: Add su...
6026

4b9e7e751   Marcel Holtmann   Bluetooth: Fix is...
6027
  	if (cp->action == 0x02)
2faade53e   Marcel Holtmann   Bluetooth: Add su...
6028
  		auto_conn = HCI_AUTO_CONN_ALWAYS;
4b9e7e751   Marcel Holtmann   Bluetooth: Fix is...
6029
6030
  	else if (cp->action == 0x01)
  		auto_conn = HCI_AUTO_CONN_DIRECT;
2faade53e   Marcel Holtmann   Bluetooth: Add su...
6031
  	else
a3451d279   Johan Hedberg   Bluetooth: Add ne...
6032
  		auto_conn = HCI_AUTO_CONN_REPORT;
2faade53e   Marcel Holtmann   Bluetooth: Add su...
6033

9a0a8a8e8   Jakub Pawlowski   Bluetooth: Move I...
6034
6035
6036
6037
6038
6039
  	/* 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 ...
6040
6041
6042
  		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...
6043
6044
  		goto unlock;
  	}
bf5b3c8be   Marcel Holtmann   Bluetooth: Provid...
6045
6046
6047
  	/* If the connection parameters don't exist for this device,
  	 * they will be created and configured with defaults.
  	 */
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
6048
  	if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
d06b50ce1   Marcel Holtmann   Bluetooth: Remove...
6049
  				auto_conn) < 0) {
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
6050
6051
6052
  		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...
6053
  		goto unlock;
4c54bf2b0   Abhishek Pandit-Subedi   Bluetooth: Add ge...
6054
6055
6056
6057
6058
  	} else {
  		params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
  						addr_type);
  		if (params)
  			current_flags = params->current_flags;
2faade53e   Marcel Holtmann   Bluetooth: Add su...
6059
  	}
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
6060
  	hci_update_background_scan(hdev);
6659358ef   Johan Hedberg   Bluetooth: Introd...
6061
  added:
8afef092a   Marcel Holtmann   Bluetooth: Add De...
6062
  	device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
4c54bf2b0   Abhishek Pandit-Subedi   Bluetooth: Add ge...
6063
6064
  	device_flags_changed(NULL, hdev, &cp->addr.bdaddr, cp->addr.type,
  			     SUPPORTED_DEVICE_FLAGS(), current_flags);
8afef092a   Marcel Holtmann   Bluetooth: Add De...
6065

51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
6066
6067
6068
  	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...
6069
6070
6071
6072
6073
  
  unlock:
  	hci_dev_unlock(hdev);
  	return err;
  }
8afef092a   Marcel Holtmann   Bluetooth: Add De...
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
  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...
6084
6085
6086
6087
6088
  static int remove_device(struct sock *sk, struct hci_dev *hdev,
  			 void *data, u16 len)
  {
  	struct mgmt_cp_remove_device *cp = data;
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
6089
  	bt_dev_dbg(hdev, "sock %p", sk);
2faade53e   Marcel Holtmann   Bluetooth: Add su...
6090
6091
6092
6093
  
  	hci_dev_lock(hdev);
  
  	if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
c71593dd3   Johan Hedberg   Bluetooth: Remove...
6094
  		struct hci_conn_params *params;
2faade53e   Marcel Holtmann   Bluetooth: Add su...
6095
  		u8 addr_type;
6659358ef   Johan Hedberg   Bluetooth: Introd...
6096
  		if (!bdaddr_type_is_valid(cp->addr.type)) {
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
6097
6098
6099
6100
  			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...
6101
6102
  			goto unlock;
  		}
6659358ef   Johan Hedberg   Bluetooth: Introd...
6103
6104
6105
6106
6107
  		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 ...
6108
6109
6110
6111
6112
  				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...
6113
6114
  				goto unlock;
  			}
01b1cb87d   Johan Hedberg   Bluetooth: Run pa...
6115
  			hci_req_update_scan(hdev);
a397407f2   Johan Hedberg   Bluetooth: Update...
6116

6659358ef   Johan Hedberg   Bluetooth: Introd...
6117
6118
6119
6120
  			device_removed(sk, hdev, &cp->addr.bdaddr,
  				       cp->addr.type);
  			goto complete;
  		}
85813a7ec   Johan Hedberg   Bluetooth: Add le...
6121
  		addr_type = le_addr_type(cp->addr.type);
2faade53e   Marcel Holtmann   Bluetooth: Add su...
6122

9a0a8a8e8   Jakub Pawlowski   Bluetooth: Move I...
6123
6124
6125
6126
6127
6128
  		/* 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 ...
6129
6130
6131
6132
  			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...
6133
6134
  			goto unlock;
  		}
c71593dd3   Johan Hedberg   Bluetooth: Remove...
6135
6136
6137
  		params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
  						addr_type);
  		if (!params) {
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
6138
6139
6140
6141
  			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...
6142
6143
  			goto unlock;
  		}
679d2b6f9   Johan Hedberg   Bluetooth: Fix re...
6144
6145
  		if (params->auto_connect == HCI_AUTO_CONN_DISABLED ||
  		    params->auto_connect == HCI_AUTO_CONN_EXPLICIT) {
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
6146
6147
6148
6149
  			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...
6150
6151
  			goto unlock;
  		}
d1dbf12e3   Johan Hedberg   Bluetooth: Use li...
6152
  		list_del(&params->action);
c71593dd3   Johan Hedberg   Bluetooth: Remove...
6153
6154
  		list_del(&params->list);
  		kfree(params);
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
6155
  		hci_update_background_scan(hdev);
8afef092a   Marcel Holtmann   Bluetooth: Add De...
6156
6157
  
  		device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
2faade53e   Marcel Holtmann   Bluetooth: Add su...
6158
  	} else {
19de0825c   Johan Hedberg   Bluetooth: Fix se...
6159
  		struct hci_conn_params *p, *tmp;
6659358ef   Johan Hedberg   Bluetooth: Introd...
6160
  		struct bdaddr_list *b, *btmp;
19de0825c   Johan Hedberg   Bluetooth: Fix se...
6161

2faade53e   Marcel Holtmann   Bluetooth: Add su...
6162
  		if (cp->addr.type) {
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
6163
6164
6165
6166
  			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...
6167
6168
  			goto unlock;
  		}
6659358ef   Johan Hedberg   Bluetooth: Introd...
6169
6170
6171
6172
6173
  		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...
6174
  		hci_req_update_scan(hdev);
a397407f2   Johan Hedberg   Bluetooth: Update...
6175

19de0825c   Johan Hedberg   Bluetooth: Fix se...
6176
6177
6178
6179
  		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...
6180
6181
6182
6183
  			if (p->explicit_connect) {
  				p->auto_connect = HCI_AUTO_CONN_EXPLICIT;
  				continue;
  			}
19de0825c   Johan Hedberg   Bluetooth: Fix se...
6184
6185
6186
6187
  			list_del(&p->action);
  			list_del(&p->list);
  			kfree(p);
  		}
181d69535   Marcel Holtmann   Bluetooth: Replac...
6188
  		bt_dev_dbg(hdev, "All LE connection parameters were removed");
19de0825c   Johan Hedberg   Bluetooth: Fix se...
6189

51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
6190
  		hci_update_background_scan(hdev);
2faade53e   Marcel Holtmann   Bluetooth: Add su...
6191
  	}
6659358ef   Johan Hedberg   Bluetooth: Introd...
6192
  complete:
51d7a94d5   Johan Hedberg   Bluetooth: Don't ...
6193
6194
6195
  	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...
6196
6197
6198
6199
  unlock:
  	hci_dev_unlock(hdev);
  	return err;
  }
a26f3dcff   Johan Hedberg   Bluetooth: Add Lo...
6200
6201
6202
6203
  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...
6204
6205
  	const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
  				     sizeof(struct mgmt_conn_param));
a26f3dcff   Johan Hedberg   Bluetooth: Add Lo...
6206
6207
6208
6209
  	u16 param_count, expected_len;
  	int i;
  
  	if (!lmp_le_capable(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
6210
6211
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
  				       MGMT_STATUS_NOT_SUPPORTED);
a26f3dcff   Johan Hedberg   Bluetooth: Add Lo...
6212
6213
  
  	param_count = __le16_to_cpu(cp->param_count);
ba1d6936f   Johan Hedberg   Bluetooth: Fix bu...
6214
  	if (param_count > max_param_count) {
2064ee332   Marcel Holtmann   Bluetooth: Use bt...
6215
6216
  		bt_dev_err(hdev, "load_conn_param: too big param_count value %u",
  			   param_count);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
6217
6218
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
  				       MGMT_STATUS_INVALID_PARAMS);
ba1d6936f   Johan Hedberg   Bluetooth: Fix bu...
6219
  	}
a26f3dcff   Johan Hedberg   Bluetooth: Add Lo...
6220

5bec1fb86   Gustavo A. R. Silva   Bluetooth: Use st...
6221
  	expected_len = struct_size(cp, params, param_count);
a26f3dcff   Johan Hedberg   Bluetooth: Add Lo...
6222
  	if (expected_len != len) {
2064ee332   Marcel Holtmann   Bluetooth: Use bt...
6223
6224
  		bt_dev_err(hdev, "load_conn_param: expected %u bytes, got %u bytes",
  			   expected_len, len);
a69e8375a   Johan Hedberg   Bluetooth: Rename...
6225
6226
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
  				       MGMT_STATUS_INVALID_PARAMS);
a26f3dcff   Johan Hedberg   Bluetooth: Add Lo...
6227
  	}
181d69535   Marcel Holtmann   Bluetooth: Replac...
6228
  	bt_dev_dbg(hdev, "param_count %u", param_count);
a26f3dcff   Johan Hedberg   Bluetooth: Add Lo...
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
  
  	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;
181d69535   Marcel Holtmann   Bluetooth: Replac...
6239
6240
  		bt_dev_dbg(hdev, "Adding %pMR (type %u)", &param->addr.bdaddr,
  			   param->addr.type);
a26f3dcff   Johan Hedberg   Bluetooth: Add Lo...
6241
6242
6243
6244
6245
6246
  
  		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 {
2064ee332   Marcel Holtmann   Bluetooth: Use bt...
6247
  			bt_dev_err(hdev, "ignoring invalid connection parameters");
a26f3dcff   Johan Hedberg   Bluetooth: Add Lo...
6248
6249
6250
6251
6252
6253
6254
  			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);
181d69535   Marcel Holtmann   Bluetooth: Replac...
6255
6256
  		bt_dev_dbg(hdev, "min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
  			   min, max, latency, timeout);
a26f3dcff   Johan Hedberg   Bluetooth: Add Lo...
6257
6258
  
  		if (hci_check_conn_params(min, max, latency, timeout) < 0) {
2064ee332   Marcel Holtmann   Bluetooth: Use bt...
6259
  			bt_dev_err(hdev, "ignoring invalid connection parameters");
a26f3dcff   Johan Hedberg   Bluetooth: Add Lo...
6260
6261
6262
6263
6264
6265
  			continue;
  		}
  
  		hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
  						addr_type);
  		if (!hci_param) {
2064ee332   Marcel Holtmann   Bluetooth: Use bt...
6266
  			bt_dev_err(hdev, "failed to add connection parameters");
a26f3dcff   Johan Hedberg   Bluetooth: Add Lo...
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
  			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...
6277
6278
  	return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
  				 NULL, 0);
a26f3dcff   Johan Hedberg   Bluetooth: Add Lo...
6279
  }
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
6280
6281
6282
6283
6284
6285
  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;
181d69535   Marcel Holtmann   Bluetooth: Replac...
6286
  	bt_dev_dbg(hdev, "sock %p", sk);
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
6287
6288
  
  	if (hdev_is_powered(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
6289
6290
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
  				       MGMT_STATUS_REJECTED);
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
6291
6292
  
  	if (cp->config != 0x00 && cp->config != 0x01)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
6293
6294
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
  				         MGMT_STATUS_INVALID_PARAMS);
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
6295
6296
  
  	if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
6297
6298
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
  				       MGMT_STATUS_NOT_SUPPORTED);
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
6299
6300
6301
6302
  
  	hci_dev_lock(hdev);
  
  	if (cp->config)
238be788f   Marcel Holtmann   Bluetooth: Introd...
6303
  		changed = !hci_dev_test_and_set_flag(hdev, HCI_EXT_CONFIGURED);
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
6304
  	else
a69d89272   Marcel Holtmann   Bluetooth: Introd...
6305
  		changed = hci_dev_test_and_clear_flag(hdev, HCI_EXT_CONFIGURED);
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
6306
6307
6308
6309
6310
6311
6312
  
  	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...
6313
  	err = new_options(hdev, sk);
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
6314
  	if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
6315
  		mgmt_index_removed(hdev);
d603b76b0   Marcel Holtmann   Bluetooth: Run co...
6316

516018a9c   Marcel Holtmann   Bluetooth: Introd...
6317
  		if (hci_dev_test_and_change_flag(hdev, HCI_UNCONFIGURED)) {
a1536da25   Marcel Holtmann   Bluetooth: Introd...
6318
6319
  			hci_dev_set_flag(hdev, HCI_CONFIG);
  			hci_dev_set_flag(hdev, HCI_AUTO_OFF);
d603b76b0   Marcel Holtmann   Bluetooth: Run co...
6320
6321
6322
  
  			queue_work(hdev->req_workqueue, &hdev->power_on);
  		} else {
5ea234d3e   Marcel Holtmann   Bluetooth: Clear ...
6323
  			set_bit(HCI_RAW, &hdev->flags);
d603b76b0   Marcel Holtmann   Bluetooth: Run co...
6324
6325
  			mgmt_index_added(hdev);
  		}
dbece37a3   Marcel Holtmann   Bluetooth: Add su...
6326
6327
6328
6329
6330
6331
  	}
  
  unlock:
  	hci_dev_unlock(hdev);
  	return err;
  }
9713c17b0   Marcel Holtmann   Bluetooth: Add su...
6332
6333
6334
6335
6336
6337
  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;
181d69535   Marcel Holtmann   Bluetooth: Replac...
6338
  	bt_dev_dbg(hdev, "sock %p", sk);
9713c17b0   Marcel Holtmann   Bluetooth: Add su...
6339
6340
  
  	if (hdev_is_powered(hdev))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
6341
6342
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
  				       MGMT_STATUS_REJECTED);
9713c17b0   Marcel Holtmann   Bluetooth: Add su...
6343
6344
  
  	if (!bacmp(&cp->bdaddr, BDADDR_ANY))
a69e8375a   Johan Hedberg   Bluetooth: Rename...
6345
6346
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
  				       MGMT_STATUS_INVALID_PARAMS);
9713c17b0   Marcel Holtmann   Bluetooth: Add su...
6347
6348
  
  	if (!hdev->set_bdaddr)
a69e8375a   Johan Hedberg   Bluetooth: Rename...
6349
6350
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
  				       MGMT_STATUS_NOT_SUPPORTED);
9713c17b0   Marcel Holtmann   Bluetooth: Add su...
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
  
  	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...
6363
  	if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
9713c17b0   Marcel Holtmann   Bluetooth: Add su...
6364
6365
6366
6367
  		err = new_options(hdev, sk);
  
  	if (is_configured(hdev)) {
  		mgmt_index_removed(hdev);
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
6368
  		hci_dev_clear_flag(hdev, HCI_UNCONFIGURED);
9713c17b0   Marcel Holtmann   Bluetooth: Add su...
6369

a1536da25   Marcel Holtmann   Bluetooth: Introd...
6370
6371
  		hci_dev_set_flag(hdev, HCI_CONFIG);
  		hci_dev_set_flag(hdev, HCI_AUTO_OFF);
9713c17b0   Marcel Holtmann   Bluetooth: Add su...
6372
6373
6374
6375
6376
6377
6378
6379
  
  		queue_work(hdev->req_workqueue, &hdev->power_on);
  	}
  
  unlock:
  	hci_dev_unlock(hdev);
  	return err;
  }
40f66c05c   Johan Hedberg   Bluetooth: Add lo...
6380
6381
6382
6383
6384
6385
6386
6387
6388
  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;
181d69535   Marcel Holtmann   Bluetooth: Replac...
6389
  	bt_dev_dbg(hdev, "status %u", status);
40f66c05c   Johan Hedberg   Bluetooth: Add lo...
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
  
  	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...
6517
6518
6519
6520
6521
6522
6523
  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...
6524
  	u8 status, flags, role, addr[7], hash[16], rand[16];
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
6525
  	int err;
181d69535   Marcel Holtmann   Bluetooth: Replac...
6526
  	bt_dev_dbg(hdev, "sock %p", sk);
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
6527

57b0d3e8e   Marcel Holtmann   Bluetooth: Fix er...
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
  	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...
6552
  	}
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
6553
6554
  	rp_len = sizeof(*rp) + eir_len;
  	rp = kmalloc(rp_len, GFP_ATOMIC);
efcd8c98e   Marcel Holtmann   Bluetooth: Move m...
6555
  	if (!rp)
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
6556
  		return -ENOMEM;
efcd8c98e   Marcel Holtmann   Bluetooth: Move m...
6557

57b0d3e8e   Marcel Holtmann   Bluetooth: Fix er...
6558
6559
  	if (status)
  		goto complete;
efcd8c98e   Marcel Holtmann   Bluetooth: Move m...
6560
  	hci_dev_lock(hdev);
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
6561
6562
6563
6564
  
  	eir_len = 0;
  	switch (cp->type) {
  	case BIT(BDADDR_BREDR):
40f66c05c   Johan Hedberg   Bluetooth: Add lo...
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
  		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...
6578
6579
  		break;
  	case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
5082a5996   Marcel Holtmann   Bluetooth: Do not...
6580
6581
  		if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
  		    smp_generate_oob(hdev, hash, rand) < 0) {
0821a2c5a   Marcel Holtmann   Bluetooth: Return...
6582
  			hci_dev_unlock(hdev);
57b0d3e8e   Marcel Holtmann   Bluetooth: Fix er...
6583
6584
  			status = MGMT_STATUS_FAILED;
  			goto complete;
0821a2c5a   Marcel Holtmann   Bluetooth: Return...
6585
  		}
e213568ad   Marcel Holtmann   Bluetooth: Disall...
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
  		/* 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...
6596
  		if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
e213568ad   Marcel Holtmann   Bluetooth: Disall...
6597
6598
6599
6600
6601
6602
6603
6604
6605
  			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...
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
  			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...
6623
6624
6625
6626
  		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...
6627

5082a5996   Marcel Holtmann   Bluetooth: Do not...
6628
6629
6630
6631
  			eir_len = eir_append_data(rp->eir, eir_len,
  						  EIR_LE_SC_RANDOM,
  						  rand, sizeof(rand));
  		}
0821a2c5a   Marcel Holtmann   Bluetooth: Return...
6632

f22525700   Johan Hedberg   Bluetooth: Move a...
6633
  		flags = mgmt_get_adv_discov_flags(hdev);
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
6634
6635
6636
6637
6638
6639
6640
6641
  
  		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...
6642
  	hci_dev_unlock(hdev);
72000df2c   Marcel Holtmann   Bluetooth: Add su...
6643
  	hci_sock_set_flag(sk, HCI_MGMT_OOB_DATA_EVENTS);
57b0d3e8e   Marcel Holtmann   Bluetooth: Fix er...
6644
6645
6646
  	status = MGMT_STATUS_SUCCESS;
  
  complete:
efcd8c98e   Marcel Holtmann   Bluetooth: Move m...
6647
6648
  	rp->type = cp->type;
  	rp->eir_len = cpu_to_le16(eir_len);
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
6649
  	err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
57b0d3e8e   Marcel Holtmann   Bluetooth: Fix er...
6650
6651
  				status, rp, sizeof(*rp) + eir_len);
  	if (err < 0 || status)
72000df2c   Marcel Holtmann   Bluetooth: Add su...
6652
6653
6654
6655
6656
  		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...
6657

0821a2c5a   Marcel Holtmann   Bluetooth: Return...
6658
  done:
4f0f155ce   Marcel Holtmann   Bluetooth: Add si...
6659
6660
6661
6662
  	kfree(rp);
  
  	return err;
  }
089fa8c09   Arman Uguray   Bluetooth: Update...
6663
6664
6665
6666
6667
6668
6669
6670
  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...
6671
  	flags |= MGMT_ADV_FLAG_APPEARANCE;
7c295c480   MichaƂ Narajowski   Bluetooth: Add su...
6672
  	flags |= MGMT_ADV_FLAG_LOCAL_NAME;
089fa8c09   Arman Uguray   Bluetooth: Update...
6673

de181e887   Jaganath Kanakkassery   Bluetooth: Impmle...
6674
6675
6676
6677
6678
  	/* In extended adv TX_POWER returned from Set Adv Param
  	 * will be always valid.
  	 */
  	if ((hdev->adv_tx_power != HCI_TX_POWER_INVALID) ||
  	    ext_adv_capable(hdev))
089fa8c09   Arman Uguray   Bluetooth: Update...
6679
  		flags |= MGMT_ADV_FLAG_TX_POWER;
85a721a8b   Jaganath Kanakkassery   Bluetooth: Implem...
6680
6681
  	if (ext_adv_capable(hdev)) {
  		flags |= MGMT_ADV_FLAG_SEC_1M;
d5ea32da8   Daniel Winkler   Bluetooth: Add MG...
6682
6683
  		flags |= MGMT_ADV_FLAG_HW_OFFLOAD;
  		flags |= MGMT_ADV_FLAG_CAN_SET_TX_POWER;
85a721a8b   Jaganath Kanakkassery   Bluetooth: Implem...
6684
6685
6686
6687
6688
6689
6690
  
  		if (hdev->le_features[1] & HCI_LE_PHY_2M)
  			flags |= MGMT_ADV_FLAG_SEC_2M;
  
  		if (hdev->le_features[1] & HCI_LE_PHY_CODED)
  			flags |= MGMT_ADV_FLAG_SEC_CODED;
  	}
089fa8c09   Arman Uguray   Bluetooth: Update...
6691
6692
  	return flags;
  }
d3d5305bf   Marcel Holtmann   Bluetooth: Add si...
6693
6694
6695
6696
6697
  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...
6698
  	int err;
286e0c83d   Florian Grandel   Bluetooth: mgmt: ...
6699
  	struct adv_info *adv_instance;
089fa8c09   Arman Uguray   Bluetooth: Update...
6700
  	u32 supported_flags;
02c04afea   Johan Hedberg   Bluetooth: Simpli...
6701
  	u8 *instance;
d3d5305bf   Marcel Holtmann   Bluetooth: Add si...
6702

181d69535   Marcel Holtmann   Bluetooth: Replac...
6703
  	bt_dev_dbg(hdev, "sock %p", sk);
d3d5305bf   Marcel Holtmann   Bluetooth: Add si...
6704

089fa8c09   Arman Uguray   Bluetooth: Update...
6705
6706
6707
  	if (!lmp_le_capable(hdev))
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
  				       MGMT_STATUS_REJECTED);
cbbdfa6f3   Sathish Narasimman   Bluetooth: Enable...
6708
6709
6710
6711
6712
6713
  	/* Enabling the experimental LL Privay support disables support for
  	 * advertising.
  	 */
  	if (hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
  				       MGMT_STATUS_NOT_SUPPORTED);
d3d5305bf   Marcel Holtmann   Bluetooth: Add si...
6714
  	hci_dev_lock(hdev);
02c04afea   Johan Hedberg   Bluetooth: Simpli...
6715
  	rp_len = sizeof(*rp) + hdev->adv_instance_cnt;
d3d5305bf   Marcel Holtmann   Bluetooth: Add si...
6716
6717
6718
6719
6720
  	rp = kmalloc(rp_len, GFP_ATOMIC);
  	if (!rp) {
  		hci_dev_unlock(hdev);
  		return -ENOMEM;
  	}
089fa8c09   Arman Uguray   Bluetooth: Update...
6721
6722
6723
  	supported_flags = get_supported_adv_flags(hdev);
  
  	rp->supported_flags = cpu_to_le32(supported_flags);
dc5d82a9f   Marcel Holtmann   Bluetooth: Use HC...
6724
6725
  	rp->max_adv_data_len = HCI_MAX_AD_LENGTH;
  	rp->max_scan_rsp_len = HCI_MAX_AD_LENGTH;
87597482c   Daniel Winkler   Bluetooth: Report...
6726
  	rp->max_instances = hdev->le_num_of_adv_sets;
02c04afea   Johan Hedberg   Bluetooth: Simpli...
6727
  	rp->num_instances = hdev->adv_instance_cnt;
24b4f38fc   Arman Uguray   Bluetooth: Implem...
6728

02c04afea   Johan Hedberg   Bluetooth: Simpli...
6729
6730
6731
6732
  	instance = rp->instance;
  	list_for_each_entry(adv_instance, &hdev->adv_instances, list) {
  		*instance = adv_instance->instance;
  		instance++;
24b4f38fc   Arman Uguray   Bluetooth: Implem...
6733
  	}
d3d5305bf   Marcel Holtmann   Bluetooth: Add si...
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
  
  	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...
6744
6745
6746
6747
6748
6749
6750
6751
6752
  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...
6753
  {
4117ed70a   Arman Uguray   Bluetooth: Add su...
6754
  	u8 max_len = HCI_MAX_AD_LENGTH;
24b4f38fc   Arman Uguray   Bluetooth: Implem...
6755

31a3248dd   Marcel Holtmann   Bluetooth: Simpli...
6756
6757
6758
  	if (is_adv_data) {
  		if (adv_flags & (MGMT_ADV_FLAG_DISCOV |
  				 MGMT_ADV_FLAG_LIMITED_DISCOV |
2bb36870e   Szymon Janc   Bluetooth: Unify ...
6759
  				 MGMT_ADV_FLAG_MANAGED_FLAGS))
31a3248dd   Marcel Holtmann   Bluetooth: Simpli...
6760
  			max_len -= 3;
24b4f38fc   Arman Uguray   Bluetooth: Implem...
6761

2bb36870e   Szymon Janc   Bluetooth: Unify ...
6762
  		if (adv_flags & MGMT_ADV_FLAG_TX_POWER)
31a3248dd   Marcel Holtmann   Bluetooth: Simpli...
6763
  			max_len -= 3;
7c295c480   MichaƂ Narajowski   Bluetooth: Add su...
6764
  	} else {
7c295c480   MichaƂ Narajowski   Bluetooth: Add su...
6765
  		if (adv_flags & MGMT_ADV_FLAG_LOCAL_NAME)
f61851f64   MichaƂ Narajowski   Bluetooth: Fix ap...
6766
  			max_len -= calculate_name_len(hdev);
c4960ecf2   MichaƂ Narajowski   Bluetooth: Add su...
6767

2bb36870e   Szymon Janc   Bluetooth: Unify ...
6768
  		if (adv_flags & (MGMT_ADV_FLAG_APPEARANCE))
c4960ecf2   MichaƂ Narajowski   Bluetooth: Add su...
6769
  			max_len -= 4;
5507e3581   Arman Uguray   Bluetooth: Suppor...
6770
  	}
2bb36870e   Szymon Janc   Bluetooth: Unify ...
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
  	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...
6795
6796
  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 ...
6797
6798
6799
  {
  	int i, cur_len;
  	u8 max_len;
f61851f64   MichaƂ Narajowski   Bluetooth: Fix ap...
6800
  	max_len = tlv_data_max_len(hdev, adv_flags, is_adv_data);
2bb36870e   Szymon Janc   Bluetooth: Unify ...
6801

4117ed70a   Arman Uguray   Bluetooth: Add su...
6802
  	if (len > max_len)
24b4f38fc   Arman Uguray   Bluetooth: Implem...
6803
  		return false;
4117ed70a   Arman Uguray   Bluetooth: Add su...
6804
6805
6806
  	/* 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...
6807

9c9db78dc   Szymon Janc   Bluetooth: Fix ad...
6808
6809
  		if (data[i + 1] == EIR_FLAGS &&
  		    (!is_adv_data || flags_managed(adv_flags)))
2bb36870e   Szymon Janc   Bluetooth: Unify ...
6810
6811
6812
6813
6814
6815
6816
6817
6818
  			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...
6819
  			return false;
2bb36870e   Szymon Janc   Bluetooth: Unify ...
6820
6821
  		if (data[i + 1] == EIR_APPEARANCE &&
  		    appearance_managed(adv_flags))
5507e3581   Arman Uguray   Bluetooth: Suppor...
6822
  			return false;
24b4f38fc   Arman Uguray   Bluetooth: Implem...
6823
6824
6825
  		/* If the current field length would exceed the total data
  		 * length, then it's invalid.
  		 */
4117ed70a   Arman Uguray   Bluetooth: Add su...
6826
  		if (i + cur_len >= len)
24b4f38fc   Arman Uguray   Bluetooth: Implem...
6827
6828
6829
6830
6831
  			return false;
  	}
  
  	return true;
  }
24b4f38fc   Arman Uguray   Bluetooth: Implem...
6832
6833
6834
6835
  static void add_advertising_complete(struct hci_dev *hdev, u8 status,
  				     u16 opcode)
  {
  	struct mgmt_pending_cmd *cmd;
fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
6836
  	struct mgmt_cp_add_advertising *cp;
24b4f38fc   Arman Uguray   Bluetooth: Implem...
6837
  	struct mgmt_rp_add_advertising rp;
fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
6838
6839
  	struct adv_info *adv_instance, *n;
  	u8 instance;
24b4f38fc   Arman Uguray   Bluetooth: Implem...
6840

181d69535   Marcel Holtmann   Bluetooth: Replac...
6841
  	bt_dev_dbg(hdev, "status %d", status);
24b4f38fc   Arman Uguray   Bluetooth: Implem...
6842
6843
6844
6845
  
  	hci_dev_lock(hdev);
  
  	cmd = pending_find(MGMT_OP_ADD_ADVERTISING, hdev);
fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
  	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...
6861
  		mgmt_advertising_removed(cmd ? cmd->sk : NULL, hdev, instance);
24b4f38fc   Arman Uguray   Bluetooth: Implem...
6862
6863
6864
6865
  	}
  
  	if (!cmd)
  		goto unlock;
fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
6866
6867
  	cp = cmd->param;
  	rp.instance = cp->instance;
24b4f38fc   Arman Uguray   Bluetooth: Implem...
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
  
  	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;
85a721a8b   Jaganath Kanakkassery   Bluetooth: Implem...
6888
  	u32 supported_flags, phy_flags;
24b4f38fc   Arman Uguray   Bluetooth: Implem...
6889
  	u8 status;
fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
6890
6891
6892
6893
  	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...
6894
6895
6896
  	int err;
  	struct mgmt_pending_cmd *cmd;
  	struct hci_request req;
181d69535   Marcel Holtmann   Bluetooth: Replac...
6897
  	bt_dev_dbg(hdev, "sock %p", sk);
24b4f38fc   Arman Uguray   Bluetooth: Implem...
6898
6899
6900
6901
6902
  
  	status = mgmt_le_support(hdev);
  	if (status)
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
  				       status);
cbbdfa6f3   Sathish Narasimman   Bluetooth: Enable...
6903
6904
6905
6906
6907
6908
  	/* Enabling the experimental LL Privay support disables support for
  	 * advertising.
  	 */
  	if (hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
  				       MGMT_STATUS_NOT_SUPPORTED);
87597482c   Daniel Winkler   Bluetooth: Report...
6909
  	if (cp->instance < 1 || cp->instance > hdev->le_num_of_adv_sets)
ceff86af5   Marcel Holtmann   Bluetooth: Add in...
6910
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
6a0e78072   Johan Hedberg   Bluetooth: Fix po...
6911
6912
6913
6914
  				       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...
6915
  				       MGMT_STATUS_INVALID_PARAMS);
24b4f38fc   Arman Uguray   Bluetooth: Implem...
6916
  	flags = __le32_to_cpu(cp->flags);
912098a63   Arman Uguray   Bluetooth: Add su...
6917
  	timeout = __le16_to_cpu(cp->timeout);
fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
6918
  	duration = __le16_to_cpu(cp->duration);
24b4f38fc   Arman Uguray   Bluetooth: Implem...
6919

fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
6920
  	/* The current implementation only supports a subset of the specified
85a721a8b   Jaganath Kanakkassery   Bluetooth: Implem...
6921
  	 * flags. Also need to check mutual exclusiveness of sec flags.
089fa8c09   Arman Uguray   Bluetooth: Update...
6922
6923
  	 */
  	supported_flags = get_supported_adv_flags(hdev);
85a721a8b   Jaganath Kanakkassery   Bluetooth: Implem...
6924
6925
6926
  	phy_flags = flags & MGMT_ADV_FLAG_SEC_MASK;
  	if (flags & ~supported_flags ||
  	    ((phy_flags && (phy_flags ^ (phy_flags & -phy_flags)))))
24b4f38fc   Arman Uguray   Bluetooth: Implem...
6927
6928
6929
6930
  		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...
6931
6932
6933
6934
6935
  	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...
6936
  	if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) ||
da929335f   Arman Uguray   Bluetooth: Implem...
6937
  	    pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
24b4f38fc   Arman Uguray   Bluetooth: Implem...
6938
6939
6940
6941
6942
  	    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...
6943
6944
  	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...
6945
  			       cp->scan_rsp_len, false)) {
24b4f38fc   Arman Uguray   Bluetooth: Implem...
6946
6947
6948
6949
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
  				      MGMT_STATUS_INVALID_PARAMS);
  		goto unlock;
  	}
fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
  	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...
6960

fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
6961
6962
6963
6964
  	/* 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...
6965
  		mgmt_advertising_added(sk, hdev, cp->instance);
912098a63   Arman Uguray   Bluetooth: Add su...
6966

fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
6967
6968
6969
6970
6971
6972
6973
  	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...
6974

fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
6975
6976
6977
6978
6979
6980
6981
6982
6983
  		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...
6984

fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
6985
6986
6987
  	/* 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...
6988
6989
  	 */
  	if (!hdev_is_powered(hdev) ||
fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
6990
6991
6992
  	    hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
  	    !schedule_instance) {
  		rp.instance = cp->instance;
24b4f38fc   Arman Uguray   Bluetooth: Implem...
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007
7008
  		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...
7009
  	err = __hci_req_schedule_adv_instance(&req, schedule_instance, true);
fffd38bca   Florian Grandel   Bluetooth: mgmt/h...
7010
7011
7012
  
  	if (!err)
  		err = hci_req_run(&req, add_advertising_complete);
24b4f38fc   Arman Uguray   Bluetooth: Implem...
7013

72da7b2cc   Joseph Hwang   Bluetooth: mgmt: ...
7014
7015
7016
  	if (err < 0) {
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
  				      MGMT_STATUS_FAILED);
24b4f38fc   Arman Uguray   Bluetooth: Implem...
7017
  		mgmt_pending_remove(cmd);
72da7b2cc   Joseph Hwang   Bluetooth: mgmt: ...
7018
  	}
24b4f38fc   Arman Uguray   Bluetooth: Implem...
7019
7020
7021
7022
7023
7024
  
  unlock:
  	hci_dev_unlock(hdev);
  
  	return err;
  }
da929335f   Arman Uguray   Bluetooth: Implem...
7025
7026
7027
7028
  static void remove_advertising_complete(struct hci_dev *hdev, u8 status,
  					u16 opcode)
  {
  	struct mgmt_pending_cmd *cmd;
01948331a   Florian Grandel   Bluetooth: mgmt: ...
7029
  	struct mgmt_cp_remove_advertising *cp;
da929335f   Arman Uguray   Bluetooth: Implem...
7030
  	struct mgmt_rp_remove_advertising rp;
181d69535   Marcel Holtmann   Bluetooth: Replac...
7031
  	bt_dev_dbg(hdev, "status %d", status);
da929335f   Arman Uguray   Bluetooth: Implem...
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
  
  	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: ...
7042
7043
  	cp = cmd->param;
  	rp.instance = cp->instance;
da929335f   Arman Uguray   Bluetooth: Implem...
7044
7045
7046
7047
7048
7049
7050
7051
7052
7053
7054
7055
7056
7057
  
  	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...
7058
7059
  	struct mgmt_pending_cmd *cmd;
  	struct hci_request req;
952497b15   Johan Hedberg   Bluetooth: Fix wa...
7060
  	int err;
da929335f   Arman Uguray   Bluetooth: Implem...
7061

181d69535   Marcel Holtmann   Bluetooth: Replac...
7062
  	bt_dev_dbg(hdev, "sock %p", sk);
da929335f   Arman Uguray   Bluetooth: Implem...
7063

cbbdfa6f3   Sathish Narasimman   Bluetooth: Enable...
7064
7065
7066
7067
7068
7069
  	/* Enabling the experimental LL Privay support disables support for
  	 * advertising.
  	 */
  	if (hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
  				       MGMT_STATUS_NOT_SUPPORTED);
da929335f   Arman Uguray   Bluetooth: Implem...
7070
  	hci_dev_lock(hdev);
952497b15   Johan Hedberg   Bluetooth: Fix wa...
7071
  	if (cp->instance && !hci_find_adv_instance(hdev, cp->instance)) {
01948331a   Florian Grandel   Bluetooth: mgmt: ...
7072
7073
7074
7075
7076
  		err = mgmt_cmd_status(sk, hdev->id,
  				      MGMT_OP_REMOVE_ADVERTISING,
  				      MGMT_STATUS_INVALID_PARAMS);
  		goto unlock;
  	}
da929335f   Arman Uguray   Bluetooth: Implem...
7077
7078
7079
7080
7081
7082
7083
  	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...
7084
  	if (list_empty(&hdev->adv_instances)) {
da929335f   Arman Uguray   Bluetooth: Implem...
7085
7086
7087
7088
  		err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
  				      MGMT_STATUS_INVALID_PARAMS);
  		goto unlock;
  	}
01948331a   Florian Grandel   Bluetooth: mgmt: ...
7089
  	hci_req_init(&req, hdev);
da929335f   Arman Uguray   Bluetooth: Implem...
7090

37adf701d   Daniel Winkler   Bluetooth: Add pe...
7091
7092
7093
7094
7095
  	/* If we use extended advertising, instance is disabled and removed */
  	if (ext_adv_capable(hdev)) {
  		__hci_req_disable_ext_adv_instance(&req, cp->instance);
  		__hci_req_remove_ext_adv_instance(&req, cp->instance);
  	}
37d3a1fab   Johan Hedberg   Bluetooth: mgmt: ...
7096
  	hci_req_clear_adv_instance(hdev, sk, &req, cp->instance, true);
da929335f   Arman Uguray   Bluetooth: Implem...
7097

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

01948331a   Florian Grandel   Bluetooth: mgmt: ...
7101
7102
7103
  	/* 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...
7104
  	 */
01948331a   Florian Grandel   Bluetooth: mgmt: ...
7105
7106
  	if (skb_queue_empty(&req.cmd_q) ||
  	    !hdev_is_powered(hdev) ||
da929335f   Arman Uguray   Bluetooth: Implem...
7107
  	    hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
f17d858ed   Jaganath Kanakkassery   Bluetooth: Fix po...
7108
  		hci_req_purge(&req);
01948331a   Florian Grandel   Bluetooth: mgmt: ...
7109
  		rp.instance = cp->instance;
da929335f   Arman Uguray   Bluetooth: Implem...
7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
  		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...
7122
7123
7124
7125
7126
7127
7128
7129
7130
  	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...
7131
7132
7133
7134
7135
7136
7137
  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;
181d69535   Marcel Holtmann   Bluetooth: Replac...
7138
  	bt_dev_dbg(hdev, "sock %p", sk);
40b25fe5d   Marcel Holtmann   Bluetooth: Add su...
7139
7140
7141
7142
  
  	if (!lmp_le_capable(hdev))
  		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_ADV_SIZE_INFO,
  				       MGMT_STATUS_REJECTED);
87597482c   Daniel Winkler   Bluetooth: Report...
7143
  	if (cp->instance < 1 || cp->instance > hdev->le_num_of_adv_sets)
40b25fe5d   Marcel Holtmann   Bluetooth: Add su...
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
  		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...
7159
7160
  	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...
7161
7162
7163
7164
7165
7166
  
  	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...
7167
  static const struct hci_mgmt_handler mgmt_handlers[] = {
0f4e68cf6   Johan Hedberg   Bluetooth: mgmt: ...
7168
  	{ NULL }, /* 0x0000 (no command) */
b9a245fb1   Johan Hedberg   Bluetooth: Move a...
7169
  	{ read_version,            MGMT_READ_VERSION_SIZE,
c91041dc4   Marcel Holtmann   Bluetooth: Add su...
7170
7171
  						HCI_MGMT_NO_HDEV |
  						HCI_MGMT_UNTRUSTED },
b9a245fb1   Johan Hedberg   Bluetooth: Move a...
7172
  	{ read_commands,           MGMT_READ_COMMANDS_SIZE,
c91041dc4   Marcel Holtmann   Bluetooth: Add su...
7173
7174
  						HCI_MGMT_NO_HDEV |
  						HCI_MGMT_UNTRUSTED },
b9a245fb1   Johan Hedberg   Bluetooth: Move a...
7175
  	{ read_index_list,         MGMT_READ_INDEX_LIST_SIZE,
c91041dc4   Marcel Holtmann   Bluetooth: Add su...
7176
7177
7178
7179
  						HCI_MGMT_NO_HDEV |
  						HCI_MGMT_UNTRUSTED },
  	{ read_controller_info,    MGMT_READ_INFO_SIZE,
  						HCI_MGMT_UNTRUSTED },
7aea8616c   Marcel Holtmann   Bluetooth: Remove...
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
  	{ 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...
7193
7194
7195
7196
  	{ 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...
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
  	{ 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...
7209
7210
7211
  	{ 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...
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
  	{ 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...
7226
7227
  	{ load_irks,               MGMT_LOAD_IRKS_SIZE,
  						HCI_MGMT_VAR_LEN },
7aea8616c   Marcel Holtmann   Bluetooth: Remove...
7228
7229
7230
7231
  	{ 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...
7232
7233
7234
  	{ 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...
7235
7236
  						HCI_MGMT_NO_HDEV |
  						HCI_MGMT_UNTRUSTED },
b9a245fb1   Johan Hedberg   Bluetooth: Move a...
7237
  	{ read_config_info,        MGMT_READ_CONFIG_INFO_SIZE,
c91041dc4   Marcel Holtmann   Bluetooth: Add su...
7238
7239
  						HCI_MGMT_UNCONFIGURED |
  						HCI_MGMT_UNTRUSTED },
b9a245fb1   Johan Hedberg   Bluetooth: Move a...
7240
7241
7242
7243
7244
7245
  	{ 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...
7246
  	{ read_local_oob_ext_data, MGMT_READ_LOCAL_OOB_EXT_DATA_SIZE },
96f1474af   Marcel Holtmann   Bluetooth: Add su...
7247
  	{ read_ext_index_list,     MGMT_READ_EXT_INDEX_LIST_SIZE,
c91041dc4   Marcel Holtmann   Bluetooth: Add su...
7248
7249
  						HCI_MGMT_NO_HDEV |
  						HCI_MGMT_UNTRUSTED },
d3d5305bf   Marcel Holtmann   Bluetooth: Add si...
7250
  	{ read_adv_features,       MGMT_READ_ADV_FEATURES_SIZE },
24b4f38fc   Arman Uguray   Bluetooth: Implem...
7251
7252
  	{ add_advertising,	   MGMT_ADD_ADVERTISING_SIZE,
  						HCI_MGMT_VAR_LEN },
da929335f   Arman Uguray   Bluetooth: Implem...
7253
  	{ remove_advertising,	   MGMT_REMOVE_ADVERTISING_SIZE },
40b25fe5d   Marcel Holtmann   Bluetooth: Add su...
7254
  	{ get_adv_size_info,       MGMT_GET_ADV_SIZE_INFO_SIZE },
78b781ca0   Johan Hedberg   Bluetooth: Add su...
7255
  	{ start_limited_discovery, MGMT_START_DISCOVERY_SIZE },
321c6feed   Marcel Holtmann   Bluetooth: Add fr...
7256
7257
  	{ read_ext_controller_info,MGMT_READ_EXT_INFO_SIZE,
  						HCI_MGMT_UNTRUSTED },
c4960ecf2   MichaƂ Narajowski   Bluetooth: Add su...
7258
  	{ set_appearance,	   MGMT_SET_APPEARANCE_SIZE },
6244691fe   Jaganath Kanakkassery   Bluetooth: Implem...
7259
  	{ get_phy_configuration,   MGMT_GET_PHY_CONFIGURATION_SIZE },
0314f2867   Jaganath Kanakkassery   Bluetooth: Implem...
7260
  	{ set_phy_configuration,   MGMT_SET_PHY_CONFIGURATION_SIZE },
600a87490   Alain Michaud   Bluetooth: Implem...
7261
7262
  	{ set_blocked_keys,	   MGMT_OP_SET_BLOCKED_KEYS_SIZE,
  						HCI_MGMT_VAR_LEN },
00bce3fb0   Alain Michaud   Bluetooth: Enable...
7263
  	{ set_wideband_speech,	   MGMT_SETTING_SIZE },
bc292258c   Marcel Holtmann   Bluetooth: Add su...
7264
7265
  	{ read_security_info,      MGMT_READ_SECURITY_INFO_SIZE,
  						HCI_MGMT_UNTRUSTED },
a10c907ce   Marcel Holtmann   Bluetooth: Add su...
7266
7267
7268
7269
7270
7271
  	{ read_exp_features_info,  MGMT_READ_EXP_FEATURES_INFO_SIZE,
  						HCI_MGMT_UNTRUSTED |
  						HCI_MGMT_HDEV_OPTIONAL },
  	{ set_exp_feature,         MGMT_SET_EXP_FEATURE_SIZE,
  						HCI_MGMT_VAR_LEN |
  						HCI_MGMT_HDEV_OPTIONAL },
17896406f   Alain Michaud   Bluetooth: implem...
7272
7273
7274
7275
  	{ read_def_system_config,  MGMT_READ_DEF_SYSTEM_CONFIG_SIZE,
  						HCI_MGMT_UNTRUSTED },
  	{ set_def_system_config,   MGMT_SET_DEF_SYSTEM_CONFIG_SIZE,
  						HCI_MGMT_VAR_LEN },
aececa645   Marcel Holtmann   Bluetooth: mgmt: ...
7276
7277
7278
7279
  	{ read_def_runtime_config, MGMT_READ_DEF_RUNTIME_CONFIG_SIZE,
  						HCI_MGMT_UNTRUSTED },
  	{ set_def_runtime_config,  MGMT_SET_DEF_RUNTIME_CONFIG_SIZE,
  						HCI_MGMT_VAR_LEN },
4c54bf2b0   Abhishek Pandit-Subedi   Bluetooth: Add ge...
7280
7281
  	{ get_device_flags,        MGMT_GET_DEVICE_FLAGS_SIZE },
  	{ set_device_flags,        MGMT_SET_DEVICE_FLAGS_SIZE },
e5e1e7fd4   Miao-chen Chou   Bluetooth: Add ha...
7282
  	{ read_adv_mon_features,   MGMT_READ_ADV_MONITOR_FEATURES_SIZE },
b139553db   Miao-chen Chou   Bluetooth: Add ha...
7283
7284
  	{ add_adv_patterns_monitor,MGMT_ADD_ADV_PATTERNS_MONITOR_SIZE,
  						HCI_MGMT_VAR_LEN },
bd2fbc6cb   Miao-chen Chou   Bluetooth: Add ha...
7285
  	{ remove_adv_monitor,      MGMT_REMOVE_ADV_MONITOR_SIZE },
0f4e68cf6   Johan Hedberg   Bluetooth: mgmt: ...
7286
  };
bf6b56db0   Marcel Holtmann   Bluetooth: Make m...
7287
  void mgmt_index_added(struct hci_dev *hdev)
c71e97bfa   Johan Hedberg   Bluetooth: Add ma...
7288
  {
ced85549c   Marcel Holtmann   Bluetooth: Add su...
7289
  	struct mgmt_ev_ext_index ev;
bb4b2a9ae   Andrei Emeltchenko   Bluetooth: mgmt: ...
7290

0602a8adc   Marcel Holtmann   Bluetooth: Add su...
7291
7292
  	if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
  		return;
f92073388   Marcel Holtmann   Bluetooth: Use sp...
7293
  	switch (hdev->dev_type) {
ca8bee5dd   Marcel Holtmann   Bluetooth: Rename...
7294
  	case HCI_PRIMARY:
f92073388   Marcel Holtmann   Bluetooth: Use sp...
7295
7296
7297
  		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...
7298
  			ev.type = 0x01;
f92073388   Marcel Holtmann   Bluetooth: Use sp...
7299
7300
7301
  		} else {
  			mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
  					 HCI_MGMT_INDEX_EVENTS);
ced85549c   Marcel Holtmann   Bluetooth: Add su...
7302
  			ev.type = 0x00;
f92073388   Marcel Holtmann   Bluetooth: Use sp...
7303
7304
  		}
  		break;
ced85549c   Marcel Holtmann   Bluetooth: Add su...
7305
7306
7307
7308
7309
  	case HCI_AMP:
  		ev.type = 0x02;
  		break;
  	default:
  		return;
f92073388   Marcel Holtmann   Bluetooth: Use sp...
7310
  	}
ced85549c   Marcel Holtmann   Bluetooth: Add su...
7311
7312
7313
7314
7315
  
  	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...
7316
  }
bf6b56db0   Marcel Holtmann   Bluetooth: Make m...
7317
  void mgmt_index_removed(struct hci_dev *hdev)
c71e97bfa   Johan Hedberg   Bluetooth: Add ma...
7318
  {
ced85549c   Marcel Holtmann   Bluetooth: Add su...
7319
  	struct mgmt_ev_ext_index ev;
5f1590327   Johan Hedberg   Bluetooth: mgmt: ...
7320
  	u8 status = MGMT_STATUS_INVALID_INDEX;
b24752fe6   Johan Hedberg   Bluetooth: Fix mg...
7321

0602a8adc   Marcel Holtmann   Bluetooth: Add su...
7322
7323
  	if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
  		return;
f92073388   Marcel Holtmann   Bluetooth: Use sp...
7324
  	switch (hdev->dev_type) {
ca8bee5dd   Marcel Holtmann   Bluetooth: Rename...
7325
  	case HCI_PRIMARY:
f92073388   Marcel Holtmann   Bluetooth: Use sp...
7326
  		mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
b24752fe6   Johan Hedberg   Bluetooth: Fix mg...
7327

f92073388   Marcel Holtmann   Bluetooth: Use sp...
7328
7329
7330
  		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...
7331
  			ev.type = 0x01;
f92073388   Marcel Holtmann   Bluetooth: Use sp...
7332
7333
7334
  		} else {
  			mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
  					 HCI_MGMT_INDEX_EVENTS);
ced85549c   Marcel Holtmann   Bluetooth: Add su...
7335
  			ev.type = 0x00;
f92073388   Marcel Holtmann   Bluetooth: Use sp...
7336
7337
  		}
  		break;
ced85549c   Marcel Holtmann   Bluetooth: Add su...
7338
7339
7340
7341
7342
  	case HCI_AMP:
  		ev.type = 0x02;
  		break;
  	default:
  		return;
f92073388   Marcel Holtmann   Bluetooth: Use sp...
7343
  	}
ced85549c   Marcel Holtmann   Bluetooth: Add su...
7344
7345
7346
7347
7348
  
  	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...
7349
  }
6046dc3e0   Andre Guedes   Bluetooth: Auto c...
7350
  /* This function requires the caller holds hdev->lock */
af02dd446   Johan Hedberg   Bluetooth: Use re...
7351
  static void restart_le_actions(struct hci_dev *hdev)
6046dc3e0   Andre Guedes   Bluetooth: Auto c...
7352
7353
7354
7355
  {
  	struct hci_conn_params *p;
  
  	list_for_each_entry(p, &hdev->le_conn_params, list) {
d7347f3cc   Johan Hedberg   Bluetooth: Fix cl...
7356
7357
7358
7359
7360
7361
  		/* 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...
7362
  		case HCI_AUTO_CONN_DIRECT:
d7347f3cc   Johan Hedberg   Bluetooth: Fix cl...
7363
7364
7365
7366
7367
7368
7369
7370
  		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...
7371
  		}
6046dc3e0   Andre Guedes   Bluetooth: Auto c...
7372
7373
  	}
  }
2ff13894c   Johan Hedberg   Bluetooth: Perfor...
7374
  void mgmt_power_on(struct hci_dev *hdev, int err)
229ab39ca   Johan Hedberg   Bluetooth: Wait f...
7375
7376
  {
  	struct cmd_lookup match = { NULL, hdev };
181d69535   Marcel Holtmann   Bluetooth: Replac...
7377
  	bt_dev_dbg(hdev, "err %d", err);
229ab39ca   Johan Hedberg   Bluetooth: Wait f...
7378

2ff13894c   Johan Hedberg   Bluetooth: Perfor...
7379
7380
7381
  	hci_dev_lock(hdev);
  
  	if (!err) {
af02dd446   Johan Hedberg   Bluetooth: Use re...
7382
7383
  		restart_le_actions(hdev);
  		hci_update_background_scan(hdev);
162a3bac8   Marcel Holtmann   Bluetooth: Bind t...
7384
  	}
229ab39ca   Johan Hedberg   Bluetooth: Wait f...
7385
7386
7387
  	mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
  
  	new_settings(hdev, match.sk);
229ab39ca   Johan Hedberg   Bluetooth: Wait f...
7388
7389
  	if (match.sk)
  		sock_put(match.sk);
229ab39ca   Johan Hedberg   Bluetooth: Wait f...
7390

2ff13894c   Johan Hedberg   Bluetooth: Perfor...
7391
  	hci_dev_unlock(hdev);
70da62437   Johan Hedberg   Bluetooth: Move p...
7392
  }
562fcc246   Andrzej Kaczmarek   Bluetooth: mgmt: ...
7393

2ff13894c   Johan Hedberg   Bluetooth: Perfor...
7394
  void __mgmt_power_off(struct hci_dev *hdev)
70da62437   Johan Hedberg   Bluetooth: Move p...
7395
7396
  {
  	struct cmd_lookup match = { NULL, hdev };
9845904fd   Johan Hedberg   Bluetooth: Fix mg...
7397
  	u8 status, zero_cod[] = { 0, 0, 0 };
b24752fe6   Johan Hedberg   Bluetooth: Fix mg...
7398

229ab39ca   Johan Hedberg   Bluetooth: Wait f...
7399
  	mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
9845904fd   Johan Hedberg   Bluetooth: Fix mg...
7400
7401
7402
7403
7404
7405
7406
7407
  
  	/* 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...
7408
  	if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
9845904fd   Johan Hedberg   Bluetooth: Fix mg...
7409
7410
7411
7412
7413
  		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...
7414

321c6feed   Marcel Holtmann   Bluetooth: Add fr...
7415
  	if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) {
5504c3a31   Marcel Holtmann   Bluetooth: Use in...
7416
7417
7418
  		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...
7419
7420
  		ext_info_changed(hdev, NULL);
  	}
229ab39ca   Johan Hedberg   Bluetooth: Wait f...
7421

2ff13894c   Johan Hedberg   Bluetooth: Perfor...
7422
  	new_settings(hdev, match.sk);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
7423
7424
7425
  
  	if (match.sk)
  		sock_put(match.sk);
5add6af8f   Johan Hedberg   Bluetooth: Add su...
7426
  }
73f22f623   Johan Hedberg   Bluetooth: Add su...
7427

3eec705e4   Marcel Holtmann   Bluetooth: Make m...
7428
  void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
96570ffcc   Johan Hedberg   Bluetooth: Fix mg...
7429
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
7430
  	struct mgmt_pending_cmd *cmd;
96570ffcc   Johan Hedberg   Bluetooth: Fix mg...
7431
  	u8 status;
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
7432
  	cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
96570ffcc   Johan Hedberg   Bluetooth: Fix mg...
7433
  	if (!cmd)
3eec705e4   Marcel Holtmann   Bluetooth: Make m...
7434
  		return;
96570ffcc   Johan Hedberg   Bluetooth: Fix mg...
7435
7436
7437
7438
7439
  
  	if (err == -ERFKILL)
  		status = MGMT_STATUS_RFKILLED;
  	else
  		status = MGMT_STATUS_FAILED;
a69e8375a   Johan Hedberg   Bluetooth: Rename...
7440
  	mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
96570ffcc   Johan Hedberg   Bluetooth: Fix mg...
7441
7442
  
  	mgmt_pending_remove(cmd);
96570ffcc   Johan Hedberg   Bluetooth: Fix mg...
7443
  }
dc4a5ee2a   Marcel Holtmann   Bluetooth: Make m...
7444
7445
  void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
  		       bool persistent)
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
7446
  {
86742e1ec   Johan Hedberg   Bluetooth: Update...
7447
  	struct mgmt_ev_new_link_key ev;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
7448

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

a492cd52b   Vinicius Costa Gomes   Revert "Bluetooth...
7451
  	ev.store_hint = persistent;
d753fdc40   Johan Hedberg   Bluetooth: mgmt: ...
7452
  	bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
591f47f31   Andre Guedes   Bluetooth: Move a...
7453
  	ev.key.addr.type = BDADDR_BREDR;
a492cd52b   Vinicius Costa Gomes   Revert "Bluetooth...
7454
  	ev.key.type = key->type;
9b3b44604   Andrei Emeltchenko   Bluetooth: Use de...
7455
  	memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
a492cd52b   Vinicius Costa Gomes   Revert "Bluetooth...
7456
  	ev.key.pin_len = key->pin_len;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
7457

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

d7b254502   Johan Hedberg   Bluetooth: Clearl...
7461
7462
  static u8 mgmt_ltk_type(struct smp_ltk *ltk)
  {
23fb8de37   Johan Hedberg   Bluetooth: Add mg...
7463
7464
7465
7466
7467
7468
7469
7470
7471
7472
7473
7474
7475
  	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...
7476
7477
7478
  
  	return MGMT_LTK_UNAUTHENTICATED;
  }
53ac6ab61   Marcel Holtmann   Bluetooth: Make L...
7479
  void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
7480
7481
7482
7483
  {
  	struct mgmt_ev_new_long_term_key ev;
  
  	memset(&ev, 0, sizeof(ev));
5192d3011   Marcel Holtmann   Bluetooth: Add co...
7484
  	/* Devices using resolvable or non-resolvable random addresses
f72186d22   Florian Grandel   Bluetooth: mgmt: ...
7485
  	 * without providing an identity resolving key don't require
5192d3011   Marcel Holtmann   Bluetooth: Add co...
7486
7487
7488
7489
7490
7491
7492
7493
7494
  	 * 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...
7495
7496
7497
7498
  	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...
7499
  		ev.store_hint = persistent;
ba74b666b   Johan Hedberg   Bluetooth: Move N...
7500

346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
7501
  	bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
57c1477c2   Andre Guedes   Bluetooth: Rename...
7502
  	ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
d7b254502   Johan Hedberg   Bluetooth: Clearl...
7503
  	ev.key.type = mgmt_ltk_type(key);
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
7504
7505
  	ev.key.enc_size = key->enc_size;
  	ev.key.ediv = key->ediv;
fe39c7b2d   Marcel Holtmann   Bluetooth: Use __...
7506
  	ev.key.rand = key->rand;
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
7507

2ceba5393   Johan Hedberg   Bluetooth: Remove...
7508
  	if (key->type == SMP_LTK)
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
7509
  		ev.key.master = 1;
1fc62c526   Johan Hedberg   Bluetooth: Fix ex...
7510
7511
7512
  	/* 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...
7513
  	memcpy(ev.key.val, key->val, key->enc_size);
1fc62c526   Johan Hedberg   Bluetooth: Fix ex...
7514
7515
  	memset(ev.key.val + key->enc_size, 0,
  	       sizeof(ev.key.val) - key->enc_size);
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
7516

083368f7b   Marcel Holtmann   Bluetooth: Make m...
7517
  	mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
346af67b8   Vinicius Costa Gomes   Bluetooth: Add MG...
7518
  }
cad20c278   Johan Hedberg   Bluetooth: Don't ...
7519
  void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk, bool persistent)
95fbac8a8   Johan Hedberg   Bluetooth: Add su...
7520
7521
7522
7523
  {
  	struct mgmt_ev_new_irk ev;
  
  	memset(&ev, 0, sizeof(ev));
cad20c278   Johan Hedberg   Bluetooth: Don't ...
7524
  	ev.store_hint = persistent;
bab6d1e59   Marcel Holtmann   Bluetooth: Don't ...
7525

95fbac8a8   Johan Hedberg   Bluetooth: Add su...
7526
7527
7528
7529
7530
7531
7532
  	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...
7533
7534
  void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
  		   bool persistent)
7ee4ea369   Marcel Holtmann   Bluetooth: Add su...
7535
7536
7537
7538
7539
7540
  {
  	struct mgmt_ev_new_csrk ev;
  
  	memset(&ev, 0, sizeof(ev));
  
  	/* Devices using resolvable or non-resolvable random addresses
f72186d22   Florian Grandel   Bluetooth: mgmt: ...
7541
  	 * without providing an identity resolving key don't require
7ee4ea369   Marcel Holtmann   Bluetooth: Add su...
7542
7543
7544
7545
7546
7547
7548
7549
7550
7551
7552
  	 * 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...
7553
  		ev.store_hint = persistent;
7ee4ea369   Marcel Holtmann   Bluetooth: Add su...
7554
7555
7556
  
  	bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
  	ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
4cd3928a8   Johan Hedberg   Bluetooth: Update...
7557
  	ev.key.type = csrk->type;
7ee4ea369   Marcel Holtmann   Bluetooth: Add su...
7558
7559
7560
7561
  	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...
7562
  void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
f4869e2ad   Johan Hedberg   Bluetooth: Pass s...
7563
7564
  			 u8 bdaddr_type, u8 store_hint, u16 min_interval,
  			 u16 max_interval, u16 latency, u16 timeout)
ffb5a827d   Andre Guedes   Bluetooth: Introd...
7565
7566
  {
  	struct mgmt_ev_new_conn_param ev;
c103aea6f   Johan Hedberg   Bluetooth: Don't ...
7567
7568
  	if (!hci_is_identity_address(bdaddr, bdaddr_type))
  		return;
ffb5a827d   Andre Guedes   Bluetooth: Introd...
7569
7570
7571
  	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...
7572
  	ev.store_hint = store_hint;
ffb5a827d   Andre Guedes   Bluetooth: Introd...
7573
7574
7575
7576
7577
7578
7579
  	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...
7580
7581
  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...
7582
  {
b644ba336   Johan Hedberg   Bluetooth: Update...
7583
7584
7585
  	char buf[512];
  	struct mgmt_ev_device_connected *ev = (void *) buf;
  	u16 eir_len = 0;
f7520543a   Johan Hedberg   Bluetooth: Add co...
7586

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

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

fd45ada91   Alfonso Acosta   Bluetooth: Includ...
7592
7593
7594
7595
7596
7597
7598
7599
7600
7601
7602
7603
  	/* 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...
7604

ddbea5cff   Alfonso Acosta   Bluetooth: Remove...
7605
  		if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
fd45ada91   Alfonso Acosta   Bluetooth: Includ...
7606
7607
7608
7609
  			eir_len = eir_append_data(ev->eir, eir_len,
  						  EIR_CLASS_OF_DEV,
  						  conn->dev_class, 3);
  	}
b644ba336   Johan Hedberg   Bluetooth: Update...
7610

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

ecd90ae7f   Marcel Holtmann   Bluetooth: Make m...
7613
7614
  	mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
  		    sizeof(*ev) + eir_len, NULL);
f7520543a   Johan Hedberg   Bluetooth: Add co...
7615
  }
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
7616
  static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
8962ee74b   Johan Hedberg   Bluetooth: Add di...
7617
  {
8962ee74b   Johan Hedberg   Bluetooth: Add di...
7618
  	struct sock **sk = data;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
7619

f5818c224   Johan Hedberg   Bluetooth: Conver...
7620
  	cmd->cmd_complete(cmd, 0);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
7621
7622
7623
  
  	*sk = cmd->sk;
  	sock_hold(*sk);
a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
7624
  	mgmt_pending_remove(cmd);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
7625
  }
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
7626
  static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
7627
  {
b1078ad0b   Johan Hedberg   Bluetooth: Add De...
7628
  	struct hci_dev *hdev = data;
124f6e352   Johan Hedberg   Bluetooth: Update...
7629
  	struct mgmt_cp_unpair_device *cp = cmd->param;
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
7630

b1078ad0b   Johan Hedberg   Bluetooth: Add De...
7631
  	device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
d8b7b1e49   Johan Hedberg   Bluetooth: Conver...
7632
  	cmd->cmd_complete(cmd, 0);
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
7633
7634
  	mgmt_pending_remove(cmd);
  }
84c61d92b   Johan Hedberg   Bluetooth: Add co...
7635
7636
  bool mgmt_powering_down(struct hci_dev *hdev)
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
7637
  	struct mgmt_pending_cmd *cmd;
84c61d92b   Johan Hedberg   Bluetooth: Add co...
7638
  	struct mgmt_mode *cp;
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
7639
  	cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
84c61d92b   Johan Hedberg   Bluetooth: Add co...
7640
7641
7642
7643
7644
7645
7646
7647
7648
  	if (!cmd)
  		return false;
  
  	cp = cmd->param;
  	if (!cp->val)
  		return true;
  
  	return false;
  }
9b80ec5e8   Marcel Holtmann   Bluetooth: Make m...
7649
  void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
12d4a3b2c   Johan Hedberg   Bluetooth: Move c...
7650
7651
  			      u8 link_type, u8 addr_type, u8 reason,
  			      bool mgmt_connected)
f7520543a   Johan Hedberg   Bluetooth: Add co...
7652
  {
f0d6a0ea3   Mikel Astiz   Bluetooth: mgmt: ...
7653
  	struct mgmt_ev_device_disconnected ev;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
7654
  	struct sock *sk = NULL;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
7655

84c61d92b   Johan Hedberg   Bluetooth: Add co...
7656
7657
7658
7659
7660
7661
  	/* 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 ...
7662
  	}
12d4a3b2c   Johan Hedberg   Bluetooth: Move c...
7663
7664
  	if (!mgmt_connected)
  		return;
57eb776fe   Andre Guedes   Bluetooth: Add an...
7665
7666
  	if (link_type != ACL_LINK && link_type != LE_LINK)
  		return;
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
7667
  	mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
f7520543a   Johan Hedberg   Bluetooth: Add co...
7668

f0d6a0ea3   Mikel Astiz   Bluetooth: mgmt: ...
7669
7670
7671
  	bacpy(&ev.addr.bdaddr, bdaddr);
  	ev.addr.type = link_to_bdaddr(link_type, addr_type);
  	ev.reason = reason;
f7520543a   Johan Hedberg   Bluetooth: Add co...
7672

f0cfc486f   Abhishek Pandit-Subedi   Bluetooth: Add su...
7673
7674
7675
  	/* Report disconnects due to suspend */
  	if (hdev->suspended)
  		ev.reason = MGMT_DEV_DISCONN_LOCAL_HOST_SUSPEND;
9b80ec5e8   Marcel Holtmann   Bluetooth: Make m...
7676
  	mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
7677
7678
  
  	if (sk)
d97dcb660   Szymon Janc   Bluetooth: mgmt: ...
7679
  		sock_put(sk);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
7680

124f6e352   Johan Hedberg   Bluetooth: Update...
7681
  	mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
7682
  			     hdev);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
7683
  }
7892924c7   Marcel Holtmann   Bluetooth: Make m...
7684
7685
  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...
7686
  {
3655bba8f   Andre Guedes   Bluetooth: Check ...
7687
7688
  	u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
  	struct mgmt_cp_disconnect *cp;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
7689
  	struct mgmt_pending_cmd *cmd;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
7690

36a75f1b3   Jefferson Delfes   Bluetooth: Force ...
7691
7692
  	mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
  			     hdev);
333ae95d0   Johan Hedberg   Bluetooth: Add ch...
7693
  	cmd = pending_find(MGMT_OP_DISCONNECT, hdev);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
7694
  	if (!cmd)
7892924c7   Marcel Holtmann   Bluetooth: Make m...
7695
  		return;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
7696

3655bba8f   Andre Guedes   Bluetooth: Check ...
7697
7698
7699
7700
7701
7702
7703
  	cp = cmd->param;
  
  	if (bacmp(bdaddr, &cp->addr.bdaddr))
  		return;
  
  	if (cp->addr.type != bdaddr_type)
  		return;
f5818c224   Johan Hedberg   Bluetooth: Conver...
7704
  	cmd->cmd_complete(cmd, mgmt_status(status));
a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
7705
  	mgmt_pending_remove(cmd);
f7520543a   Johan Hedberg   Bluetooth: Add co...
7706
  }
17d5c04cb   Johan Hedberg   Bluetooth: Add su...
7707

445608d07   Marcel Holtmann   Bluetooth: Make m...
7708
7709
  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...
7710
7711
  {
  	struct mgmt_ev_connect_failed ev;
c9910d0fb   Johan Hedberg   Bluetooth: Fix di...
7712

84c61d92b   Johan Hedberg   Bluetooth: Add co...
7713
7714
7715
7716
7717
7718
  	/* 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...
7719
  	}
17d5c04cb   Johan Hedberg   Bluetooth: Add su...
7720

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

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

ce0e4a0d7   Marcel Holtmann   Bluetooth: Make m...
7728
  void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
980e1a537   Johan Hedberg   Bluetooth: Add su...
7729
7730
  {
  	struct mgmt_ev_pin_code_request ev;
d8457698e   Johan Hedberg   Bluetooth: mgmt: ...
7731
  	bacpy(&ev.addr.bdaddr, bdaddr);
591f47f31   Andre Guedes   Bluetooth: Move a...
7732
  	ev.addr.type = BDADDR_BREDR;
a770bb5ae   Waldemar Rymarkiewicz   Bluetooth: Add se...
7733
  	ev.secure = secure;
980e1a537   Johan Hedberg   Bluetooth: Add su...
7734

ce0e4a0d7   Marcel Holtmann   Bluetooth: Make m...
7735
  	mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
980e1a537   Johan Hedberg   Bluetooth: Add su...
7736
  }
e669cf803   Marcel Holtmann   Bluetooth: Make m...
7737
7738
  void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
  				  u8 status)
980e1a537   Johan Hedberg   Bluetooth: Add su...
7739
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
7740
  	struct mgmt_pending_cmd *cmd;
980e1a537   Johan Hedberg   Bluetooth: Add su...
7741

333ae95d0   Johan Hedberg   Bluetooth: Add ch...
7742
  	cmd = pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
980e1a537   Johan Hedberg   Bluetooth: Add su...
7743
  	if (!cmd)
e669cf803   Marcel Holtmann   Bluetooth: Make m...
7744
  		return;
980e1a537   Johan Hedberg   Bluetooth: Add su...
7745

7776d1d80   Johan Hedberg   Bluetooth: Use cm...
7746
  	cmd->cmd_complete(cmd, mgmt_status(status));
a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
7747
  	mgmt_pending_remove(cmd);
980e1a537   Johan Hedberg   Bluetooth: Add su...
7748
  }
3eb385289   Marcel Holtmann   Bluetooth: Make m...
7749
7750
  void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
  				      u8 status)
980e1a537   Johan Hedberg   Bluetooth: Add su...
7751
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
7752
  	struct mgmt_pending_cmd *cmd;
980e1a537   Johan Hedberg   Bluetooth: Add su...
7753

333ae95d0   Johan Hedberg   Bluetooth: Add ch...
7754
  	cmd = pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
980e1a537   Johan Hedberg   Bluetooth: Add su...
7755
  	if (!cmd)
3eb385289   Marcel Holtmann   Bluetooth: Make m...
7756
  		return;
980e1a537   Johan Hedberg   Bluetooth: Add su...
7757

7776d1d80   Johan Hedberg   Bluetooth: Use cm...
7758
  	cmd->cmd_complete(cmd, mgmt_status(status));
a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
7759
  	mgmt_pending_remove(cmd);
980e1a537   Johan Hedberg   Bluetooth: Add su...
7760
  }
a5c296832   Johan Hedberg   Bluetooth: Add ma...
7761

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
7762
  int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
39adbffe4   Johan Hedberg   Bluetooth: Fix pa...
7763
  			      u8 link_type, u8 addr_type, u32 value,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
7764
  			      u8 confirm_hint)
a5c296832   Johan Hedberg   Bluetooth: Add ma...
7765
7766
  {
  	struct mgmt_ev_user_confirm_request ev;
181d69535   Marcel Holtmann   Bluetooth: Replac...
7767
  	bt_dev_dbg(hdev, "bdaddr %pMR", bdaddr);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
7768

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

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
7774
  	return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
7775
  			  NULL);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
7776
  }
272d90df2   Johan Hedberg   Bluetooth: Add ad...
7777
  int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
8ce8e2b56   Gustavo Padovan   Bluetooth: Fix co...
7778
  			      u8 link_type, u8 addr_type)
604086b73   Brian Gix   Bluetooth: Add Us...
7779
7780
  {
  	struct mgmt_ev_user_passkey_request ev;
181d69535   Marcel Holtmann   Bluetooth: Replac...
7781
  	bt_dev_dbg(hdev, "bdaddr %pMR", bdaddr);
604086b73   Brian Gix   Bluetooth: Add Us...
7782

272d90df2   Johan Hedberg   Bluetooth: Add ad...
7783
  	bacpy(&ev.addr.bdaddr, bdaddr);
57c1477c2   Andre Guedes   Bluetooth: Rename...
7784
  	ev.addr.type = link_to_bdaddr(link_type, addr_type);
604086b73   Brian Gix   Bluetooth: Add Us...
7785
7786
  
  	return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
7787
  			  NULL);
604086b73   Brian Gix   Bluetooth: Add Us...
7788
  }
0df4c185e   Brian Gix   Bluetooth: User P...
7789
  static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
8ce8e2b56   Gustavo Padovan   Bluetooth: Fix co...
7790
7791
  				      u8 link_type, u8 addr_type, u8 status,
  				      u8 opcode)
a5c296832   Johan Hedberg   Bluetooth: Add ma...
7792
  {
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
7793
  	struct mgmt_pending_cmd *cmd;
a5c296832   Johan Hedberg   Bluetooth: Add ma...
7794

333ae95d0   Johan Hedberg   Bluetooth: Add ch...
7795
  	cmd = pending_find(opcode, hdev);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
7796
7797
  	if (!cmd)
  		return -ENOENT;
7776d1d80   Johan Hedberg   Bluetooth: Use cm...
7798
  	cmd->cmd_complete(cmd, mgmt_status(status));
a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
7799
  	mgmt_pending_remove(cmd);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
7800

7776d1d80   Johan Hedberg   Bluetooth: Use cm...
7801
  	return 0;
a5c296832   Johan Hedberg   Bluetooth: Add ma...
7802
  }
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
7803
  int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
7804
  				     u8 link_type, u8 addr_type, u8 status)
a5c296832   Johan Hedberg   Bluetooth: Add ma...
7805
  {
272d90df2   Johan Hedberg   Bluetooth: Add ad...
7806
  	return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
7807
  					  status, MGMT_OP_USER_CONFIRM_REPLY);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
7808
  }
272d90df2   Johan Hedberg   Bluetooth: Add ad...
7809
  int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
7810
  					 u8 link_type, u8 addr_type, u8 status)
a5c296832   Johan Hedberg   Bluetooth: Add ma...
7811
  {
272d90df2   Johan Hedberg   Bluetooth: Add ad...
7812
  	return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
8fc9ced39   Gustavo Padovan   Bluetooth: Fix co...
7813
7814
  					  status,
  					  MGMT_OP_USER_CONFIRM_NEG_REPLY);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
7815
  }
2a6116920   Johan Hedberg   Bluetooth: Add mg...
7816

604086b73   Brian Gix   Bluetooth: Add Us...
7817
  int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
7818
  				     u8 link_type, u8 addr_type, u8 status)
604086b73   Brian Gix   Bluetooth: Add Us...
7819
  {
272d90df2   Johan Hedberg   Bluetooth: Add ad...
7820
  	return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
7821
  					  status, MGMT_OP_USER_PASSKEY_REPLY);
604086b73   Brian Gix   Bluetooth: Add Us...
7822
  }
272d90df2   Johan Hedberg   Bluetooth: Add ad...
7823
  int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
7824
  					 u8 link_type, u8 addr_type, u8 status)
604086b73   Brian Gix   Bluetooth: Add Us...
7825
  {
272d90df2   Johan Hedberg   Bluetooth: Add ad...
7826
  	return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
8fc9ced39   Gustavo Padovan   Bluetooth: Fix co...
7827
7828
  					  status,
  					  MGMT_OP_USER_PASSKEY_NEG_REPLY);
604086b73   Brian Gix   Bluetooth: Add Us...
7829
  }
92a25256f   Johan Hedberg   Bluetooth: mgmt: ...
7830
7831
7832
7833
7834
  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;
181d69535   Marcel Holtmann   Bluetooth: Replac...
7835
  	bt_dev_dbg(hdev, "bdaddr %pMR", bdaddr);
92a25256f   Johan Hedberg   Bluetooth: mgmt: ...
7836
7837
7838
7839
7840
7841
7842
7843
  
  	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...
7844
  void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
2a6116920   Johan Hedberg   Bluetooth: Add mg...
7845
7846
  {
  	struct mgmt_ev_auth_failed ev;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
7847
  	struct mgmt_pending_cmd *cmd;
e1e930f59   Johan Hedberg   Bluetooth: Fix mg...
7848
  	u8 status = mgmt_status(hci_status);
2a6116920   Johan Hedberg   Bluetooth: Add mg...
7849

e1e930f59   Johan Hedberg   Bluetooth: Fix mg...
7850
7851
7852
  	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...
7853

e1e930f59   Johan Hedberg   Bluetooth: Fix mg...
7854
7855
7856
7857
  	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...
7858
7859
7860
7861
  	if (cmd) {
  		cmd->cmd_complete(cmd, status);
  		mgmt_pending_remove(cmd);
  	}
2a6116920   Johan Hedberg   Bluetooth: Add mg...
7862
  }
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
7863

464996aea   Marcel Holtmann   Bluetooth: Make m...
7864
  void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
7865
7866
  {
  	struct cmd_lookup match = { NULL, hdev };
464996aea   Marcel Holtmann   Bluetooth: Make m...
7867
  	bool changed;
33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
7868
7869
7870
7871
  
  	if (status) {
  		u8 mgmt_err = mgmt_status(status);
  		mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
7872
  				     cmd_status_rsp, &mgmt_err);
464996aea   Marcel Holtmann   Bluetooth: Make m...
7873
  		return;
33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
7874
  	}
464996aea   Marcel Holtmann   Bluetooth: Make m...
7875
  	if (test_bit(HCI_AUTH, &hdev->flags))
238be788f   Marcel Holtmann   Bluetooth: Introd...
7876
  		changed = !hci_dev_test_and_set_flag(hdev, HCI_LINK_SECURITY);
464996aea   Marcel Holtmann   Bluetooth: Make m...
7877
  	else
a69d89272   Marcel Holtmann   Bluetooth: Introd...
7878
  		changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
47990ea09   Johan Hedberg   Bluetooth: mgmt: ...
7879

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

47990ea09   Johan Hedberg   Bluetooth: mgmt: ...
7883
  	if (changed)
464996aea   Marcel Holtmann   Bluetooth: Make m...
7884
  		new_settings(hdev, match.sk);
33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
7885
7886
7887
  
  	if (match.sk)
  		sock_put(match.sk);
33ef95ed3   Johan Hedberg   Bluetooth: mgmt: ...
7888
  }
890ea8988   Johan Hedberg   Bluetooth: Update...
7889
  static void clear_eir(struct hci_request *req)
cacaf52f5   Johan Hedberg   Bluetooth: mgmt: ...
7890
  {
890ea8988   Johan Hedberg   Bluetooth: Update...
7891
  	struct hci_dev *hdev = req->hdev;
cacaf52f5   Johan Hedberg   Bluetooth: mgmt: ...
7892
  	struct hci_cp_write_eir cp;
976eb20e6   Johan Hedberg   Bluetooth: Make u...
7893
  	if (!lmp_ext_inq_capable(hdev))
890ea8988   Johan Hedberg   Bluetooth: Update...
7894
  		return;
cacaf52f5   Johan Hedberg   Bluetooth: mgmt: ...
7895

c80da27e8   Johan Hedberg   Bluetooth: mgmt: ...
7896
  	memset(hdev->eir, 0, sizeof(hdev->eir));
cacaf52f5   Johan Hedberg   Bluetooth: mgmt: ...
7897
  	memset(&cp, 0, sizeof(cp));
890ea8988   Johan Hedberg   Bluetooth: Update...
7898
  	hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
cacaf52f5   Johan Hedberg   Bluetooth: mgmt: ...
7899
  }
3e248560d   Marcel Holtmann   Bluetooth: Make m...
7900
  void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
7901
7902
  {
  	struct cmd_lookup match = { NULL, hdev };
890ea8988   Johan Hedberg   Bluetooth: Update...
7903
  	struct hci_request req;
c0ecddc25   Johan Hedberg   Bluetooth: mgmt: ...
7904
  	bool changed = false;
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
7905
7906
7907
  
  	if (status) {
  		u8 mgmt_err = mgmt_status(status);
c0ecddc25   Johan Hedberg   Bluetooth: mgmt: ...
7908

a69d89272   Marcel Holtmann   Bluetooth: Introd...
7909
7910
  		if (enable && hci_dev_test_and_clear_flag(hdev,
  							  HCI_SSP_ENABLED)) {
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
7911
  			hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
3e248560d   Marcel Holtmann   Bluetooth: Make m...
7912
  			new_settings(hdev, NULL);
9ecb3e242   Marcel Holtmann   Bluetooth: Restri...
7913
  		}
c0ecddc25   Johan Hedberg   Bluetooth: mgmt: ...
7914

04124681f   Gustavo F. Padovan   Bluetooth: fix co...
7915
7916
  		mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
  				     &mgmt_err);
3e248560d   Marcel Holtmann   Bluetooth: Make m...
7917
  		return;
c0ecddc25   Johan Hedberg   Bluetooth: mgmt: ...
7918
7919
7920
  	}
  
  	if (enable) {
238be788f   Marcel Holtmann   Bluetooth: Introd...
7921
  		changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
c0ecddc25   Johan Hedberg   Bluetooth: mgmt: ...
7922
  	} else {
a69d89272   Marcel Holtmann   Bluetooth: Introd...
7923
  		changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
9ecb3e242   Marcel Holtmann   Bluetooth: Restri...
7924
  		if (!changed)
a69d89272   Marcel Holtmann   Bluetooth: Introd...
7925
7926
  			changed = hci_dev_test_and_clear_flag(hdev,
  							      HCI_HS_ENABLED);
9ecb3e242   Marcel Holtmann   Bluetooth: Restri...
7927
  		else
a358dc11d   Marcel Holtmann   Bluetooth: Introd...
7928
  			hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
7929
7930
7931
  	}
  
  	mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
c0ecddc25   Johan Hedberg   Bluetooth: mgmt: ...
7932
  	if (changed)
3e248560d   Marcel Holtmann   Bluetooth: Make m...
7933
  		new_settings(hdev, match.sk);
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
7934

5fc6ebb10   Johan Hedberg   Bluetooth: mgmt: ...
7935
  	if (match.sk)
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
7936
  		sock_put(match.sk);
890ea8988   Johan Hedberg   Bluetooth: Update...
7937
  	hci_req_init(&req, hdev);
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
7938
7939
  	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 ...
7940
7941
  			hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
  				    sizeof(enable), &enable);
b1a8917c9   Johan Hedberg   Bluetooth: Move E...
7942
  		__hci_req_update_eir(&req);
3769972ba   Johan Hedberg   Bluetooth: Add a ...
7943
  	} else {
890ea8988   Johan Hedberg   Bluetooth: Update...
7944
  		clear_eir(&req);
3769972ba   Johan Hedberg   Bluetooth: Add a ...
7945
  	}
890ea8988   Johan Hedberg   Bluetooth: Update...
7946
7947
  
  	hci_req_run(&req, NULL);
ed2c4ee36   Johan Hedberg   Bluetooth: mgmt: ...
7948
  }
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
7949
  static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
7950
7951
  {
  	struct cmd_lookup *match = data;
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
7952
7953
7954
7955
  	if (match->sk == NULL) {
  		match->sk = cmd->sk;
  		sock_hold(match->sk);
  	}
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
7956
  }
4e1b0245f   Marcel Holtmann   Bluetooth: Make m...
7957
7958
  void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
  				    u8 status)
7f9a903c5   Marcel Holtmann   Bluetooth: Send m...
7959
  {
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
7960
  	struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
7f9a903c5   Marcel Holtmann   Bluetooth: Send m...
7961

92da60975   Johan Hedberg   Bluetooth: Fix UU...
7962
7963
7964
  	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: ...
7965

321c6feed   Marcel Holtmann   Bluetooth: Add fr...
7966
  	if (!status) {
5504c3a31   Marcel Holtmann   Bluetooth: Use in...
7967
7968
  		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...
7969
7970
  		ext_info_changed(hdev, NULL);
  	}
90e704543   Johan Hedberg   Bluetooth: mgmt: ...
7971
7972
7973
  
  	if (match.sk)
  		sock_put(match.sk);
7f9a903c5   Marcel Holtmann   Bluetooth: Send m...
7974
  }
7667da342   Marcel Holtmann   Bluetooth: Make m...
7975
  void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
7976
  {
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
7977
  	struct mgmt_cp_set_local_name ev;
3b0602cd0   Johan Hedberg   Bluetooth: Rename...
7978
  	struct mgmt_pending_cmd *cmd;
28cc7bde5   Johan Hedberg   Bluetooth: mgmt: ...
7979

139289713   Johan Hedberg   Bluetooth: Fix wa...
7980
  	if (status)
7667da342   Marcel Holtmann   Bluetooth: Make m...
7981
  		return;
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
7982
7983
7984
  
  	memset(&ev, 0, sizeof(ev));
  	memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
28cc7bde5   Johan Hedberg   Bluetooth: mgmt: ...
7985
  	memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
7986

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

139289713   Johan Hedberg   Bluetooth: Fix wa...
7991
7992
7993
  		/* 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...
7994
  		if (pending_find(MGMT_OP_SET_POWERED, hdev))
7667da342   Marcel Holtmann   Bluetooth: Make m...
7995
  			return;
890ea8988   Johan Hedberg   Bluetooth: Update...
7996
  	}
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
7997

5504c3a31   Marcel Holtmann   Bluetooth: Use in...
7998
7999
  	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...
8000
  	ext_info_changed(hdev, cmd ? cmd->sk : NULL);
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
8001
  }
c35938b2f   Szymon Janc   Bluetooth: Add re...
8002

799ce93df   Jakub Pawlowski   Bluetooth: Add lo...
8003
8004
8005
8006
8007
8008
8009
8010
8011
8012
8013
  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...
8014
8015
  static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
  {
799ce93df   Jakub Pawlowski   Bluetooth: Add lo...
8016
8017
8018
8019
8020
8021
8022
8023
8024
8025
8026
8027
8028
8029
8030
8031
8032
  	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...
8033
  				memcpy(uuid, bluetooth_base_uuid, 16);
799ce93df   Jakub Pawlowski   Bluetooth: Add lo...
8034
8035
8036
8037
8038
8039
8040
8041
8042
  				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...
8043
  				memcpy(uuid, bluetooth_base_uuid, 16);
799ce93df   Jakub Pawlowski   Bluetooth: Add lo...
8044
8045
8046
8047
8048
8049
8050
8051
8052
8053
8054
8055
8056
8057
8058
8059
8060
8061
8062
8063
8064
  				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...
8065
8066
  	return false;
  }
4b0e0cedd   Jakub Pawlowski   Bluetooth: Add re...
8067
8068
8069
  static void restart_le_scan(struct hci_dev *hdev)
  {
  	/* If controller is not scanning we are done. */
d7a5a11d7   Marcel Holtmann   Bluetooth: Introd...
8070
  	if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
4b0e0cedd   Jakub Pawlowski   Bluetooth: Add re...
8071
8072
8073
8074
8075
8076
  		return;
  
  	if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
  		       hdev->discovery.scan_start +
  		       hdev->discovery.scan_duration))
  		return;
7c1fbed23   Johan Hedberg   Bluetooth: Move L...
8077
  	queue_delayed_work(hdev->req_workqueue, &hdev->le_scan_restart,
4b0e0cedd   Jakub Pawlowski   Bluetooth: Add re...
8078
8079
  			   DISCOV_LE_RESTART_DELAY);
  }
48f86b7f2   Jakub Pawlowski   Bluetooth: Move S...
8080
8081
  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...
8082
  {
48f86b7f2   Jakub Pawlowski   Bluetooth: Move S...
8083
8084
8085
8086
8087
  	/* 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...
8088
8089
8090
  	 *
  	 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
  	 * the results are also dropped.
bda157a40   Marcel Holtmann   Bluetooth: Filter...
8091
8092
  	 */
  	if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
4b0e0cedd   Jakub Pawlowski   Bluetooth: Add re...
8093
8094
8095
  	    (rssi == HCI_RSSI_INVALID ||
  	    (rssi < hdev->discovery.rssi &&
  	     !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
48f86b7f2   Jakub Pawlowski   Bluetooth: Move S...
8096
  		return  false;
efb2513fd   Marcel Holtmann   Bluetooth: Fix di...
8097

2976cdeb2   Jakub Pawlowski   Bluetooth: Refact...
8098
8099
8100
  	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...
8101
  		 */
2976cdeb2   Jakub Pawlowski   Bluetooth: Refact...
8102
8103
8104
8105
8106
8107
  		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...
8108
  	}
5d2e9fadf   Johan Hedberg   Bluetooth: Add sc...
8109

2976cdeb2   Jakub Pawlowski   Bluetooth: Refact...
8110
8111
  	/* 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...
8112
  	 */
2976cdeb2   Jakub Pawlowski   Bluetooth: Refact...
8113
8114
8115
8116
8117
8118
8119
8120
  	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...
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135
8136
8137
8138
8139
  
  	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;
8208f5a9d   Miao-chen Chou   Bluetooth: Update...
8140
8141
8142
  		if (link_type == LE_LINK &&
  		    list_empty(&hdev->pend_le_reports) &&
  		    !hci_is_adv_monitoring(hdev)) {
48f86b7f2   Jakub Pawlowski   Bluetooth: Move S...
8143
  			return;
8208f5a9d   Miao-chen Chou   Bluetooth: Update...
8144
  		}
48f86b7f2   Jakub Pawlowski   Bluetooth: Move S...
8145
  	}
82f8b651a   Jakub Pawlowski   Bluetooth: fix se...
8146
  	if (hdev->discovery.result_filtering) {
48f86b7f2   Jakub Pawlowski   Bluetooth: Move S...
8147
8148
8149
8150
8151
  		/* 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...
8152
8153
8154
8155
8156
8157
8158
8159
8160
8161
8162
  	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...
8163
8164
8165
8166
  	/* 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...
8167
  		return;
48f86b7f2   Jakub Pawlowski   Bluetooth: Move S...
8168
8169
8170
8171
8172
8173
8174
8175
8176
8177
8178
8179
8180
8181
8182
8183
8184
8185
8186
8187
8188
8189
  	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...
8190
8191
  	if (dev_class && !eir_get_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
  				       NULL))
48f86b7f2   Jakub Pawlowski   Bluetooth: Move S...
8192
8193
8194
8195
8196
8197
  		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...
8198
8199
  	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 ...
8200

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

9cf12aee8   Marcel Holtmann   Bluetooth: Make m...
8204
8205
  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...
8206
  {
b644ba336   Johan Hedberg   Bluetooth: Update...
8207
8208
8209
  	struct mgmt_ev_device_found *ev;
  	char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
  	u16 eir_len;
a88a9652d   Johan Hedberg   Bluetooth: Add mg...
8210

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

b644ba336   Johan Hedberg   Bluetooth: Update...
8213
8214
8215
  	memset(buf, 0, sizeof(buf));
  
  	bacpy(&ev->addr.bdaddr, bdaddr);
57c1477c2   Andre Guedes   Bluetooth: Rename...
8216
  	ev->addr.type = link_to_bdaddr(link_type, addr_type);
b644ba336   Johan Hedberg   Bluetooth: Update...
8217
8218
8219
  	ev->rssi = rssi;
  
  	eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
04124681f   Gustavo F. Padovan   Bluetooth: fix co...
8220
  				  name_len);
b644ba336   Johan Hedberg   Bluetooth: Update...
8221

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

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

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

181d69535   Marcel Holtmann   Bluetooth: Replac...
8231
  	bt_dev_dbg(hdev, "discovering %u", discovering);
343fb1454   Andre Guedes   Bluetooth: Add BT...
8232

f963e8e9d   Johan Hedberg   Bluetooth: mgmt: ...
8233
8234
8235
  	memset(&ev, 0, sizeof(ev));
  	ev.type = hdev->discovery.type;
  	ev.discovering = discovering;
2f1e063bc   Marcel Holtmann   Bluetooth: Make m...
8236
  	mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
314b2381a   Johan Hedberg   Bluetooth: Add di...
8237
  }
5e762444b   Antti Julku   Bluetooth: Add mg...
8238

346ce5b7d   Abhishek Pandit-Subedi   Bluetooth: Add mg...
8239
8240
8241
8242
8243
8244
8245
8246
8247
8248
8249
8250
8251
8252
8253
8254
8255
8256
8257
8258
8259
8260
8261
  void mgmt_suspending(struct hci_dev *hdev, u8 state)
  {
  	struct mgmt_ev_controller_suspend ev;
  
  	ev.suspend_state = state;
  	mgmt_event(MGMT_EV_CONTROLLER_SUSPEND, hdev, &ev, sizeof(ev), NULL);
  }
  
  void mgmt_resuming(struct hci_dev *hdev, u8 reason, bdaddr_t *bdaddr,
  		   u8 addr_type)
  {
  	struct mgmt_ev_controller_resume ev;
  
  	ev.wake_reason = reason;
  	if (bdaddr) {
  		bacpy(&ev.addr.bdaddr, bdaddr);
  		ev.addr.type = addr_type;
  	} else {
  		memset(&ev.addr, 0, sizeof(ev.addr));
  	}
  
  	mgmt_event(MGMT_EV_CONTROLLER_RESUME, hdev, &ev, sizeof(ev), NULL);
  }
6d785aa34   Johan Hedberg   Bluetooth: Conver...
8262
8263
8264
8265
  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...
8266
  	.hdev_init	= mgmt_init_hdev,
6d785aa34   Johan Hedberg   Bluetooth: Conver...
8267
8268
8269
8270
8271
8272
8273
8274
8275
8276
8277
  };
  
  int mgmt_init(void)
  {
  	return hci_mgmt_chan_register(&chan);
  }
  
  void mgmt_exit(void)
  {
  	hci_mgmt_chan_unregister(&chan);
  }