Blame view

net/bluetooth/mgmt.c 63 KB
0381101fd   Johan Hedberg   Bluetooth: Add in...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  /*
     BlueZ - Bluetooth protocol stack for Linux
     Copyright (C) 2010  Nokia Corporation
  
     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 */
ca69b7957   Johan Hedberg   Bluetooth: Create...
24
  #include <linux/kernel.h>
723597538   Szymon Janc   Bluetooth: Use #i...
25
  #include <linux/uaccess.h>
3a9a231d9   Paul Gortmaker   net: Fix files ex...
26
  #include <linux/module.h>
0381101fd   Johan Hedberg   Bluetooth: Add in...
27
28
29
30
31
  #include <asm/unaligned.h>
  
  #include <net/bluetooth/bluetooth.h>
  #include <net/bluetooth/hci_core.h>
  #include <net/bluetooth/mgmt.h>
5fe57d9e9   Brian Gix   Bluetooth: Add SM...
32
  #include <net/bluetooth/smp.h>
0381101fd   Johan Hedberg   Bluetooth: Add in...
33

02d981292   Johan Hedberg   Bluetooth: Add re...
34
35
  #define MGMT_VERSION	0
  #define MGMT_REVISION	1
2519a1fc8   Andre Guedes   Bluetooth: Create...
36
  #define INQUIRY_LEN_BREDR 0x08 /* TGAP(100) */
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
37
  #define SERVICE_CACHE_TIMEOUT (5 * 1000)
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
38
39
  struct pending_cmd {
  	struct list_head list;
fc2f4b13d   Johan Hedberg   Bluetooth: Fix co...
40
  	u16 opcode;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
41
  	int index;
c68fb7ff2   Szymon Janc   Bluetooth: Rename...
42
  	void *param;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
43
  	struct sock *sk;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
44
  	void *user_data;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
45
  };
ca69b7957   Johan Hedberg   Bluetooth: Create...
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
  /* HCI to MGMT error code conversion table */
  static u8 mgmt_status_table[] = {
  	MGMT_STATUS_SUCCESS,
  	MGMT_STATUS_UNKNOWN_COMMAND,	/* Unknown Command */
  	MGMT_STATUS_NOT_CONNECTED,	/* No Connection */
  	MGMT_STATUS_FAILED,		/* Hardware Failure */
  	MGMT_STATUS_CONNECT_FAILED,	/* Page Timeout */
  	MGMT_STATUS_AUTH_FAILED,	/* Authentication Failed */
  	MGMT_STATUS_NOT_PAIRED,		/* PIN or Key Missing */
  	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;
  }
4e51eae9c   Szymon Janc   Bluetooth: Move i...
118
  static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
f7b64e69c   Johan Hedberg   Bluetooth: Add re...
119
120
121
122
  {
  	struct sk_buff *skb;
  	struct mgmt_hdr *hdr;
  	struct mgmt_ev_cmd_status *ev;
56b7d1378   Gustavo F. Padovan   Bluetooth: return...
123
  	int err;
f7b64e69c   Johan Hedberg   Bluetooth: Add re...
124

34eb525c1   Szymon Janc   Bluetooth: Log al...
125
  	BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
f7b64e69c   Johan Hedberg   Bluetooth: Add re...
126
127
128
129
130
131
132
133
  
  	skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_ATOMIC);
  	if (!skb)
  		return -ENOMEM;
  
  	hdr = (void *) skb_put(skb, sizeof(*hdr));
  
  	hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
4e51eae9c   Szymon Janc   Bluetooth: Move i...
134
  	hdr->index = cpu_to_le16(index);
f7b64e69c   Johan Hedberg   Bluetooth: Add re...
135
136
137
138
139
  	hdr->len = cpu_to_le16(sizeof(*ev));
  
  	ev = (void *) skb_put(skb, sizeof(*ev));
  	ev->status = status;
  	put_unaligned_le16(cmd, &ev->opcode);
56b7d1378   Gustavo F. Padovan   Bluetooth: return...
140
141
  	err = sock_queue_rcv_skb(sk, skb);
  	if (err < 0)
f7b64e69c   Johan Hedberg   Bluetooth: Add re...
142
  		kfree_skb(skb);
56b7d1378   Gustavo F. Padovan   Bluetooth: return...
143
  	return err;
f7b64e69c   Johan Hedberg   Bluetooth: Add re...
144
  }
4e51eae9c   Szymon Janc   Bluetooth: Move i...
145
146
  static int cmd_complete(struct sock *sk, u16 index, u16 cmd, void *rp,
  								size_t rp_len)
02d981292   Johan Hedberg   Bluetooth: Add re...
147
148
149
150
  {
  	struct sk_buff *skb;
  	struct mgmt_hdr *hdr;
  	struct mgmt_ev_cmd_complete *ev;
56b7d1378   Gustavo F. Padovan   Bluetooth: return...
151
  	int err;
02d981292   Johan Hedberg   Bluetooth: Add re...
152
153
  
  	BT_DBG("sock %p", sk);
a38528f11   Johan Hedberg   Bluetooth: Create...
154
  	skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_ATOMIC);
02d981292   Johan Hedberg   Bluetooth: Add re...
155
156
157
158
  	if (!skb)
  		return -ENOMEM;
  
  	hdr = (void *) skb_put(skb, sizeof(*hdr));
02d981292   Johan Hedberg   Bluetooth: Add re...
159

a38528f11   Johan Hedberg   Bluetooth: Create...
160
  	hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
4e51eae9c   Szymon Janc   Bluetooth: Move i...
161
  	hdr->index = cpu_to_le16(index);
a38528f11   Johan Hedberg   Bluetooth: Create...
162
  	hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
02d981292   Johan Hedberg   Bluetooth: Add re...
163

a38528f11   Johan Hedberg   Bluetooth: Create...
164
165
  	ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
  	put_unaligned_le16(cmd, &ev->opcode);
8020c16a6   Szymon Janc   Bluetooth: Fix po...
166
167
168
  
  	if (rp)
  		memcpy(ev->data, rp, rp_len);
02d981292   Johan Hedberg   Bluetooth: Add re...
169

56b7d1378   Gustavo F. Padovan   Bluetooth: return...
170
171
  	err = sock_queue_rcv_skb(sk, skb);
  	if (err < 0)
02d981292   Johan Hedberg   Bluetooth: Add re...
172
  		kfree_skb(skb);
56b7d1378   Gustavo F. Padovan   Bluetooth: return...
173
  	return err;;
02d981292   Johan Hedberg   Bluetooth: Add re...
174
  }
a38528f11   Johan Hedberg   Bluetooth: Create...
175
176
177
178
179
180
181
182
  static int read_version(struct sock *sk)
  {
  	struct mgmt_rp_read_version rp;
  
  	BT_DBG("sock %p", sk);
  
  	rp.version = MGMT_VERSION;
  	put_unaligned_le16(MGMT_REVISION, &rp.revision);
4e51eae9c   Szymon Janc   Bluetooth: Move i...
183
184
  	return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, &rp,
  								sizeof(rp));
a38528f11   Johan Hedberg   Bluetooth: Create...
185
  }
faba42eb2   Johan Hedberg   Bluetooth: Add re...
186
187
  static int read_index_list(struct sock *sk)
  {
faba42eb2   Johan Hedberg   Bluetooth: Add re...
188
189
  	struct mgmt_rp_read_index_list *rp;
  	struct list_head *p;
8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
190
  	struct hci_dev *d;
a38528f11   Johan Hedberg   Bluetooth: Create...
191
  	size_t rp_len;
faba42eb2   Johan Hedberg   Bluetooth: Add re...
192
  	u16 count;
a38528f11   Johan Hedberg   Bluetooth: Create...
193
  	int i, err;
faba42eb2   Johan Hedberg   Bluetooth: Add re...
194
195
196
197
198
199
200
201
202
  
  	BT_DBG("sock %p", sk);
  
  	read_lock(&hci_dev_list_lock);
  
  	count = 0;
  	list_for_each(p, &hci_dev_list) {
  		count++;
  	}
a38528f11   Johan Hedberg   Bluetooth: Create...
203
204
205
  	rp_len = sizeof(*rp) + (2 * count);
  	rp = kmalloc(rp_len, GFP_ATOMIC);
  	if (!rp) {
b2c60d42d   Jesper Juhl   Bluetooth: Fix fa...
206
  		read_unlock(&hci_dev_list_lock);
faba42eb2   Johan Hedberg   Bluetooth: Add re...
207
  		return -ENOMEM;
b2c60d42d   Jesper Juhl   Bluetooth: Fix fa...
208
  	}
faba42eb2   Johan Hedberg   Bluetooth: Add re...
209

faba42eb2   Johan Hedberg   Bluetooth: Add re...
210
211
212
  	put_unaligned_le16(count, &rp->num_controllers);
  
  	i = 0;
8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
213
  	list_for_each_entry(d, &hci_dev_list, list) {
3243553fd   Johan Hedberg   Bluetooth: Conver...
214
  		if (test_and_clear_bit(HCI_AUTO_OFF, &d->flags))
e0f9309f3   Johan Hedberg   Bluetooth: Fix ca...
215
  			cancel_delayed_work(&d->power_off);
ab81cbf99   Johan Hedberg   Bluetooth: Implem...
216
217
218
  
  		if (test_bit(HCI_SETUP, &d->flags))
  			continue;
faba42eb2   Johan Hedberg   Bluetooth: Add re...
219
220
221
222
223
  		put_unaligned_le16(d->id, &rp->index[i++]);
  		BT_DBG("Added hci%u", d->id);
  	}
  
  	read_unlock(&hci_dev_list_lock);
4e51eae9c   Szymon Janc   Bluetooth: Move i...
224
225
  	err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, rp,
  									rp_len);
faba42eb2   Johan Hedberg   Bluetooth: Add re...
226

a38528f11   Johan Hedberg   Bluetooth: Create...
227
228
229
  	kfree(rp);
  
  	return err;
faba42eb2   Johan Hedberg   Bluetooth: Add re...
230
  }
69ab39ea5   Johan Hedberg   Bluetooth: Update...
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
273
274
  static u32 get_supported_settings(struct hci_dev *hdev)
  {
  	u32 settings = 0;
  
  	settings |= MGMT_SETTING_POWERED;
  	settings |= MGMT_SETTING_CONNECTABLE;
  	settings |= MGMT_SETTING_FAST_CONNECTABLE;
  	settings |= MGMT_SETTING_DISCOVERABLE;
  	settings |= MGMT_SETTING_PAIRABLE;
  
  	if (hdev->features[6] & LMP_SIMPLE_PAIR)
  		settings |= MGMT_SETTING_SSP;
  
  	if (!(hdev->features[4] & LMP_NO_BREDR)) {
  		settings |= MGMT_SETTING_BREDR;
  		settings |= MGMT_SETTING_LINK_SECURITY;
  	}
  
  	if (hdev->features[4] & LMP_LE)
  		settings |= MGMT_SETTING_LE;
  
  	return settings;
  }
  
  static u32 get_current_settings(struct hci_dev *hdev)
  {
  	u32 settings = 0;
  
  	if (test_bit(HCI_UP, &hdev->flags))
  		settings |= MGMT_SETTING_POWERED;
  	else
  		return settings;
  
  	if (test_bit(HCI_PSCAN, &hdev->flags))
  		settings |= MGMT_SETTING_CONNECTABLE;
  
  	if (test_bit(HCI_ISCAN, &hdev->flags))
  		settings |= MGMT_SETTING_DISCOVERABLE;
  
  	if (test_bit(HCI_PAIRABLE, &hdev->flags))
  		settings |= MGMT_SETTING_PAIRABLE;
  
  	if (!(hdev->features[4] & LMP_NO_BREDR))
  		settings |= MGMT_SETTING_BREDR;
59e294065   Andre Guedes   Bluetooth: Rename...
275
  	if (hdev->host_features[0] & LMP_HOST_LE)
69ab39ea5   Johan Hedberg   Bluetooth: Update...
276
277
278
279
280
281
282
283
284
285
  		settings |= MGMT_SETTING_LE;
  
  	if (test_bit(HCI_AUTH, &hdev->flags))
  		settings |= MGMT_SETTING_LINK_SECURITY;
  
  	if (hdev->ssp_mode > 0)
  		settings |= MGMT_SETTING_SSP;
  
  	return settings;
  }
ef5803729   Johan Hedberg   Bluetooth: Move E...
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
  #define EIR_FLAGS		0x01 /* flags */
  #define EIR_UUID16_SOME		0x02 /* 16-bit UUID, more available */
  #define EIR_UUID16_ALL		0x03 /* 16-bit UUID, all listed */
  #define EIR_UUID32_SOME		0x04 /* 32-bit UUID, more available */
  #define EIR_UUID32_ALL		0x05 /* 32-bit UUID, all listed */
  #define EIR_UUID128_SOME	0x06 /* 128-bit UUID, more available */
  #define EIR_UUID128_ALL		0x07 /* 128-bit UUID, all listed */
  #define EIR_NAME_SHORT		0x08 /* shortened local name */
  #define EIR_NAME_COMPLETE	0x09 /* complete local name */
  #define EIR_TX_POWER		0x0A /* transmit power level */
  #define EIR_DEVICE_ID		0x10 /* device ID */
  
  #define PNP_INFO_SVCLASS_ID		0x1200
  
  static u8 bluetooth_base_uuid[] = {
  			0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
  			0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };
  
  static u16 get_uuid16(u8 *uuid128)
  {
  	u32 val;
  	int i;
  
  	for (i = 0; i < 12; i++) {
  		if (bluetooth_base_uuid[i] != uuid128[i])
  			return 0;
  	}
  
  	memcpy(&val, &uuid128[12], 4);
  
  	val = le32_to_cpu(val);
  	if (val > 0xffff)
  		return 0;
  
  	return (u16) val;
  }
  
  static void create_eir(struct hci_dev *hdev, u8 *data)
  {
  	u8 *ptr = data;
  	u16 eir_len = 0;
  	u16 uuid16_list[HCI_MAX_EIR_LENGTH / sizeof(u16)];
  	int i, truncated = 0;
  	struct bt_uuid *uuid;
  	size_t name_len;
  
  	name_len = strlen(hdev->dev_name);
  
  	if (name_len > 0) {
  		/* EIR Data type */
  		if (name_len > 48) {
  			name_len = 48;
  			ptr[1] = EIR_NAME_SHORT;
  		} else
  			ptr[1] = EIR_NAME_COMPLETE;
  
  		/* EIR Data length */
  		ptr[0] = name_len + 1;
  
  		memcpy(ptr + 2, hdev->dev_name, name_len);
  
  		eir_len += (name_len + 2);
  		ptr += (name_len + 2);
  	}
  
  	memset(uuid16_list, 0, sizeof(uuid16_list));
  
  	/* Group all UUID16 types */
  	list_for_each_entry(uuid, &hdev->uuids, list) {
  		u16 uuid16;
  
  		uuid16 = get_uuid16(uuid->uuid);
  		if (uuid16 == 0)
  			return;
  
  		if (uuid16 < 0x1100)
  			continue;
  
  		if (uuid16 == PNP_INFO_SVCLASS_ID)
  			continue;
  
  		/* Stop if not enough space to put next UUID */
  		if (eir_len + 2 + sizeof(u16) > HCI_MAX_EIR_LENGTH) {
  			truncated = 1;
  			break;
  		}
  
  		/* Check for duplicates */
  		for (i = 0; uuid16_list[i] != 0; i++)
  			if (uuid16_list[i] == uuid16)
  				break;
  
  		if (uuid16_list[i] == 0) {
  			uuid16_list[i] = uuid16;
  			eir_len += sizeof(u16);
  		}
  	}
  
  	if (uuid16_list[0] != 0) {
  		u8 *length = ptr;
  
  		/* EIR Data type */
  		ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL;
  
  		ptr += 2;
  		eir_len += 2;
  
  		for (i = 0; uuid16_list[i] != 0; i++) {
  			*ptr++ = (uuid16_list[i] & 0x00ff);
  			*ptr++ = (uuid16_list[i] & 0xff00) >> 8;
  		}
  
  		/* EIR Data length */
  		*length = (i * sizeof(u16)) + 1;
  	}
  }
  
  static int update_eir(struct hci_dev *hdev)
  {
  	struct hci_cp_write_eir cp;
  
  	if (!(hdev->features[6] & LMP_EXT_INQ))
  		return 0;
  
  	if (hdev->ssp_mode == 0)
  		return 0;
  
  	if (test_bit(HCI_SERVICE_CACHE, &hdev->flags))
  		return 0;
  
  	memset(&cp, 0, sizeof(cp));
  
  	create_eir(hdev, cp.data);
  
  	if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
  		return 0;
  
  	memcpy(hdev->eir, cp.data, sizeof(cp.data));
  
  	return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
  }
  
  static u8 get_service_classes(struct hci_dev *hdev)
  {
  	struct bt_uuid *uuid;
  	u8 val = 0;
  
  	list_for_each_entry(uuid, &hdev->uuids, list)
  		val |= uuid->svc_hint;
  
  	return val;
  }
  
  static int update_class(struct hci_dev *hdev)
  {
  	u8 cod[3];
  
  	BT_DBG("%s", hdev->name);
  
  	if (test_bit(HCI_SERVICE_CACHE, &hdev->flags))
  		return 0;
  
  	cod[0] = hdev->minor_class;
  	cod[1] = hdev->major_class;
  	cod[2] = get_service_classes(hdev);
  
  	if (memcmp(cod, hdev->dev_class, 3) == 0)
  		return 0;
  
  	return hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
  }
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
  static void service_cache_off(struct work_struct *work)
  {
  	struct hci_dev *hdev = container_of(work, struct hci_dev,
  							service_cache.work);
  
  	if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->flags))
  		return;
  
  	hci_dev_lock(hdev);
  
  	update_eir(hdev);
  	update_class(hdev);
  
  	hci_dev_unlock(hdev);
  }
  
  static void mgmt_init_hdev(struct hci_dev *hdev)
  {
  	if (!test_and_set_bit(HCI_MGMT, &hdev->flags))
  		INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
  
  	if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->flags))
  		schedule_delayed_work(&hdev->service_cache,
  				msecs_to_jiffies(SERVICE_CACHE_TIMEOUT));
  }
4e51eae9c   Szymon Janc   Bluetooth: Move i...
483
  static int read_controller_info(struct sock *sk, u16 index)
0381101fd   Johan Hedberg   Bluetooth: Add in...
484
  {
a38528f11   Johan Hedberg   Bluetooth: Create...
485
  	struct mgmt_rp_read_info rp;
f7b64e69c   Johan Hedberg   Bluetooth: Add re...
486
  	struct hci_dev *hdev;
0381101fd   Johan Hedberg   Bluetooth: Add in...
487

4e51eae9c   Szymon Janc   Bluetooth: Move i...
488
  	BT_DBG("sock %p hci%u", sk, index);
f7b64e69c   Johan Hedberg   Bluetooth: Add re...
489

4e51eae9c   Szymon Janc   Bluetooth: Move i...
490
  	hdev = hci_dev_get(index);
a38528f11   Johan Hedberg   Bluetooth: Create...
491
  	if (!hdev)
ca69b7957   Johan Hedberg   Bluetooth: Create...
492
493
  		return cmd_status(sk, index, MGMT_OP_READ_INFO,
  						MGMT_STATUS_INVALID_PARAMS);
f7b64e69c   Johan Hedberg   Bluetooth: Add re...
494

3243553fd   Johan Hedberg   Bluetooth: Conver...
495
496
  	if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->flags))
  		cancel_delayed_work_sync(&hdev->power_off);
ab81cbf99   Johan Hedberg   Bluetooth: Implem...
497

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

7d78525dc   Johan Hedberg   Bluetooth: Add ti...
500
501
  	if (test_and_clear_bit(HCI_PI_MGMT_INIT, &hci_pi(sk)->flags))
  		mgmt_init_hdev(hdev);
ebc99feba   Johan Hedberg   Bluetooth: Add fl...
502

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

69ab39ea5   Johan Hedberg   Bluetooth: Update...
506
  	rp.version = hdev->hci_ver;
f7b64e69c   Johan Hedberg   Bluetooth: Add re...
507

69ab39ea5   Johan Hedberg   Bluetooth: Update...
508
509
510
511
  	put_unaligned_le16(hdev->manufacturer, &rp.manufacturer);
  
  	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...
512

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

dc4fe30b8   Johan Hedberg   Bluetooth: mgmt: ...
515
  	memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
516
  	hci_dev_unlock(hdev);
f7b64e69c   Johan Hedberg   Bluetooth: Add re...
517
  	hci_dev_put(hdev);
0381101fd   Johan Hedberg   Bluetooth: Add in...
518

4e51eae9c   Szymon Janc   Bluetooth: Move i...
519
  	return cmd_complete(sk, index, MGMT_OP_READ_INFO, &rp, sizeof(rp));
0381101fd   Johan Hedberg   Bluetooth: Add in...
520
  }
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
521
522
523
  static void mgmt_pending_free(struct pending_cmd *cmd)
  {
  	sock_put(cmd->sk);
c68fb7ff2   Szymon Janc   Bluetooth: Rename...
524
  	kfree(cmd->param);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
525
526
  	kfree(cmd);
  }
366a03369   Johan Hedberg   Bluetooth: Make p...
527
  static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
528
529
  							struct hci_dev *hdev,
  							void *data, u16 len)
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
530
531
532
533
534
  {
  	struct pending_cmd *cmd;
  
  	cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC);
  	if (!cmd)
366a03369   Johan Hedberg   Bluetooth: Make p...
535
  		return NULL;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
536
537
  
  	cmd->opcode = opcode;
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
538
  	cmd->index = hdev->id;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
539

c68fb7ff2   Szymon Janc   Bluetooth: Rename...
540
541
  	cmd->param = kmalloc(len, GFP_ATOMIC);
  	if (!cmd->param) {
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
542
  		kfree(cmd);
366a03369   Johan Hedberg   Bluetooth: Make p...
543
  		return NULL;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
544
  	}
8fce6357a   Szymon Janc   Bluetooth: Allow ...
545
546
  	if (data)
  		memcpy(cmd->param, data, len);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
547
548
549
  
  	cmd->sk = sk;
  	sock_hold(sk);
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
550
  	list_add(&cmd->list, &hdev->mgmt_pending);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
551

366a03369   Johan Hedberg   Bluetooth: Make p...
552
  	return cmd;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
553
  }
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
554
  static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
555
556
557
558
  				void (*cb)(struct pending_cmd *cmd, void *data),
  				void *data)
  {
  	struct list_head *p, *n;
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
559
  	list_for_each_safe(p, n, &hdev->mgmt_pending) {
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
560
561
562
  		struct pending_cmd *cmd;
  
  		cmd = list_entry(p, struct pending_cmd, list);
b24752fe6   Johan Hedberg   Bluetooth: Fix mg...
563
  		if (opcode > 0 && cmd->opcode != opcode)
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
564
  			continue;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
565
566
567
  		cb(cmd, data);
  	}
  }
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
568
  static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
569
  {
8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
570
  	struct pending_cmd *cmd;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
571

2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
572
  	list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2aeabcbed   Johan Hedberg   Bluetooth: Remove...
573
574
  		if (cmd->opcode == opcode)
  			return cmd;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
575
576
577
578
  	}
  
  	return NULL;
  }
a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
579
  static void mgmt_pending_remove(struct pending_cmd *cmd)
73f22f623   Johan Hedberg   Bluetooth: Add su...
580
  {
73f22f623   Johan Hedberg   Bluetooth: Add su...
581
582
583
  	list_del(&cmd->list);
  	mgmt_pending_free(cmd);
  }
69ab39ea5   Johan Hedberg   Bluetooth: Update...
584
  static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
8680570b0   Johan Hedberg   Bluetooth: Return...
585
  {
69ab39ea5   Johan Hedberg   Bluetooth: Update...
586
  	__le32 settings = cpu_to_le32(get_current_settings(hdev));
8680570b0   Johan Hedberg   Bluetooth: Return...
587

69ab39ea5   Johan Hedberg   Bluetooth: Update...
588
  	return cmd_complete(sk, hdev->id, opcode, &settings, sizeof(settings));
8680570b0   Johan Hedberg   Bluetooth: Return...
589
  }
4e51eae9c   Szymon Janc   Bluetooth: Move i...
590
  static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
591
  {
72a734ec1   Johan Hedberg   Bluetooth: Unify ...
592
  	struct mgmt_mode *cp;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
593
  	struct hci_dev *hdev;
366a03369   Johan Hedberg   Bluetooth: Make p...
594
  	struct pending_cmd *cmd;
366a03369   Johan Hedberg   Bluetooth: Make p...
595
  	int err, up;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
596
597
  
  	cp = (void *) data;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
598

4e51eae9c   Szymon Janc   Bluetooth: Move i...
599
  	BT_DBG("request for hci%u", index);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
600

bdce7bafb   Szymon Janc   Bluetooth: Valida...
601
  	if (len != sizeof(*cp))
ca69b7957   Johan Hedberg   Bluetooth: Create...
602
603
  		return cmd_status(sk, index, MGMT_OP_SET_POWERED,
  						MGMT_STATUS_INVALID_PARAMS);
bdce7bafb   Szymon Janc   Bluetooth: Valida...
604

4e51eae9c   Szymon Janc   Bluetooth: Move i...
605
  	hdev = hci_dev_get(index);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
606
  	if (!hdev)
ca69b7957   Johan Hedberg   Bluetooth: Create...
607
608
  		return cmd_status(sk, index, MGMT_OP_SET_POWERED,
  						MGMT_STATUS_INVALID_PARAMS);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
609

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
610
  	hci_dev_lock(hdev);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
611
612
  
  	up = test_bit(HCI_UP, &hdev->flags);
72a734ec1   Johan Hedberg   Bluetooth: Unify ...
613
  	if ((cp->val && up) || (!cp->val && !up)) {
69ab39ea5   Johan Hedberg   Bluetooth: Update...
614
  		err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
615
616
  		goto failed;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
617
  	if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
ca69b7957   Johan Hedberg   Bluetooth: Create...
618
619
  		err = cmd_status(sk, index, MGMT_OP_SET_POWERED,
  							MGMT_STATUS_BUSY);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
620
621
  		goto failed;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
622
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
366a03369   Johan Hedberg   Bluetooth: Make p...
623
624
  	if (!cmd) {
  		err = -ENOMEM;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
625
  		goto failed;
366a03369   Johan Hedberg   Bluetooth: Make p...
626
  	}
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
627

72a734ec1   Johan Hedberg   Bluetooth: Unify ...
628
  	if (cp->val)
7f971041c   Gustavo F. Padovan   Bluetooth: Use sy...
629
  		schedule_work(&hdev->power_on);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
630
  	else
80b7ab334   Gustavo F. Padovan   Bluetooth: move p...
631
  		schedule_work(&hdev->power_off.work);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
632

366a03369   Johan Hedberg   Bluetooth: Make p...
633
  	err = 0;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
634
635
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
636
  	hci_dev_unlock(hdev);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
637
  	hci_dev_put(hdev);
366a03369   Johan Hedberg   Bluetooth: Make p...
638
  	return err;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
639
  }
4e51eae9c   Szymon Janc   Bluetooth: Move i...
640
641
  static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
  									u16 len)
73f22f623   Johan Hedberg   Bluetooth: Add su...
642
  {
16ab91ab4   Johan Hedberg   Bluetooth: Add ti...
643
  	struct mgmt_cp_set_discoverable *cp;
73f22f623   Johan Hedberg   Bluetooth: Add su...
644
  	struct hci_dev *hdev;
366a03369   Johan Hedberg   Bluetooth: Make p...
645
  	struct pending_cmd *cmd;
73f22f623   Johan Hedberg   Bluetooth: Add su...
646
647
648
649
  	u8 scan;
  	int err;
  
  	cp = (void *) data;
73f22f623   Johan Hedberg   Bluetooth: Add su...
650

4e51eae9c   Szymon Janc   Bluetooth: Move i...
651
  	BT_DBG("request for hci%u", index);
73f22f623   Johan Hedberg   Bluetooth: Add su...
652

bdce7bafb   Szymon Janc   Bluetooth: Valida...
653
  	if (len != sizeof(*cp))
ca69b7957   Johan Hedberg   Bluetooth: Create...
654
655
  		return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
  						MGMT_STATUS_INVALID_PARAMS);
bdce7bafb   Szymon Janc   Bluetooth: Valida...
656

4e51eae9c   Szymon Janc   Bluetooth: Move i...
657
  	hdev = hci_dev_get(index);
73f22f623   Johan Hedberg   Bluetooth: Add su...
658
  	if (!hdev)
ca69b7957   Johan Hedberg   Bluetooth: Create...
659
660
  		return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
  						MGMT_STATUS_INVALID_PARAMS);
73f22f623   Johan Hedberg   Bluetooth: Add su...
661

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
662
  	hci_dev_lock(hdev);
73f22f623   Johan Hedberg   Bluetooth: Add su...
663
664
  
  	if (!test_bit(HCI_UP, &hdev->flags)) {
ca69b7957   Johan Hedberg   Bluetooth: Create...
665
666
  		err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
  						MGMT_STATUS_NOT_POWERED);
73f22f623   Johan Hedberg   Bluetooth: Add su...
667
668
  		goto failed;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
669
670
  	if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
  			mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
ca69b7957   Johan Hedberg   Bluetooth: Create...
671
672
  		err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
  							MGMT_STATUS_BUSY);
73f22f623   Johan Hedberg   Bluetooth: Add su...
673
674
  		goto failed;
  	}
72a734ec1   Johan Hedberg   Bluetooth: Unify ...
675
  	if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) &&
73f22f623   Johan Hedberg   Bluetooth: Add su...
676
  					test_bit(HCI_PSCAN, &hdev->flags)) {
69ab39ea5   Johan Hedberg   Bluetooth: Update...
677
  		err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
73f22f623   Johan Hedberg   Bluetooth: Add su...
678
679
  		goto failed;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
680
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
366a03369   Johan Hedberg   Bluetooth: Make p...
681
682
  	if (!cmd) {
  		err = -ENOMEM;
73f22f623   Johan Hedberg   Bluetooth: Add su...
683
  		goto failed;
366a03369   Johan Hedberg   Bluetooth: Make p...
684
  	}
73f22f623   Johan Hedberg   Bluetooth: Add su...
685
686
  
  	scan = SCAN_PAGE;
72a734ec1   Johan Hedberg   Bluetooth: Unify ...
687
  	if (cp->val)
73f22f623   Johan Hedberg   Bluetooth: Add su...
688
  		scan |= SCAN_INQUIRY;
16ab91ab4   Johan Hedberg   Bluetooth: Add ti...
689
  	else
e0f9309f3   Johan Hedberg   Bluetooth: Fix ca...
690
  		cancel_delayed_work(&hdev->discov_off);
73f22f623   Johan Hedberg   Bluetooth: Add su...
691
692
693
  
  	err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
  	if (err < 0)
a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
694
  		mgmt_pending_remove(cmd);
73f22f623   Johan Hedberg   Bluetooth: Add su...
695

16ab91ab4   Johan Hedberg   Bluetooth: Add ti...
696
697
  	if (cp->val)
  		hdev->discov_timeout = get_unaligned_le16(&cp->timeout);
73f22f623   Johan Hedberg   Bluetooth: Add su...
698
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
699
  	hci_dev_unlock(hdev);
73f22f623   Johan Hedberg   Bluetooth: Add su...
700
701
702
703
  	hci_dev_put(hdev);
  
  	return err;
  }
4e51eae9c   Szymon Janc   Bluetooth: Move i...
704
705
  static int set_connectable(struct sock *sk, u16 index, unsigned char *data,
  									u16 len)
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
706
  {
72a734ec1   Johan Hedberg   Bluetooth: Unify ...
707
  	struct mgmt_mode *cp;
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
708
  	struct hci_dev *hdev;
366a03369   Johan Hedberg   Bluetooth: Make p...
709
  	struct pending_cmd *cmd;
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
710
711
712
713
  	u8 scan;
  	int err;
  
  	cp = (void *) data;
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
714

4e51eae9c   Szymon Janc   Bluetooth: Move i...
715
  	BT_DBG("request for hci%u", index);
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
716

bdce7bafb   Szymon Janc   Bluetooth: Valida...
717
  	if (len != sizeof(*cp))
ca69b7957   Johan Hedberg   Bluetooth: Create...
718
719
  		return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE,
  						MGMT_STATUS_INVALID_PARAMS);
bdce7bafb   Szymon Janc   Bluetooth: Valida...
720

4e51eae9c   Szymon Janc   Bluetooth: Move i...
721
  	hdev = hci_dev_get(index);
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
722
  	if (!hdev)
ca69b7957   Johan Hedberg   Bluetooth: Create...
723
724
  		return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE,
  						MGMT_STATUS_INVALID_PARAMS);
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
725

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
726
  	hci_dev_lock(hdev);
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
727
728
  
  	if (!test_bit(HCI_UP, &hdev->flags)) {
ca69b7957   Johan Hedberg   Bluetooth: Create...
729
730
  		err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE,
  						MGMT_STATUS_NOT_POWERED);
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
731
732
  		goto failed;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
733
734
  	if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
  			mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
ca69b7957   Johan Hedberg   Bluetooth: Create...
735
736
  		err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE,
  							MGMT_STATUS_BUSY);
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
737
738
  		goto failed;
  	}
72a734ec1   Johan Hedberg   Bluetooth: Unify ...
739
  	if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) {
69ab39ea5   Johan Hedberg   Bluetooth: Update...
740
  		err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
741
742
  		goto failed;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
743
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
366a03369   Johan Hedberg   Bluetooth: Make p...
744
745
  	if (!cmd) {
  		err = -ENOMEM;
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
746
  		goto failed;
366a03369   Johan Hedberg   Bluetooth: Make p...
747
  	}
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
748

72a734ec1   Johan Hedberg   Bluetooth: Unify ...
749
  	if (cp->val)
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
750
751
752
753
754
755
  		scan = SCAN_PAGE;
  	else
  		scan = 0;
  
  	err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
  	if (err < 0)
a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
756
  		mgmt_pending_remove(cmd);
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
757
758
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
759
  	hci_dev_unlock(hdev);
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
760
761
762
763
  	hci_dev_put(hdev);
  
  	return err;
  }
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
764
765
  static int mgmt_event(u16 event, struct hci_dev *hdev, void *data,
  					u16 data_len, struct sock *skip_sk)
c542a06c2   Johan Hedberg   Bluetooth: Implem...
766
767
768
769
770
771
772
773
774
775
776
777
  {
  	struct sk_buff *skb;
  	struct mgmt_hdr *hdr;
  
  	skb = alloc_skb(sizeof(*hdr) + data_len, GFP_ATOMIC);
  	if (!skb)
  		return -ENOMEM;
  
  	bt_cb(skb)->channel = HCI_CHANNEL_CONTROL;
  
  	hdr = (void *) skb_put(skb, sizeof(*hdr));
  	hdr->opcode = cpu_to_le16(event);
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
778
779
780
781
  	if (hdev)
  		hdr->index = cpu_to_le16(hdev->id);
  	else
  		hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
782
  	hdr->len = cpu_to_le16(data_len);
4e51eae9c   Szymon Janc   Bluetooth: Move i...
783
784
  	if (data)
  		memcpy(skb_put(skb, data_len), data, data_len);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
785
786
787
788
789
790
  
  	hci_send_to_sock(NULL, skb, skip_sk);
  	kfree_skb(skb);
  
  	return 0;
  }
4e51eae9c   Szymon Janc   Bluetooth: Move i...
791
792
  static int set_pairable(struct sock *sk, u16 index, unsigned char *data,
  									u16 len)
c542a06c2   Johan Hedberg   Bluetooth: Implem...
793
  {
69ab39ea5   Johan Hedberg   Bluetooth: Update...
794
  	struct mgmt_mode *cp;
c542a06c2   Johan Hedberg   Bluetooth: Implem...
795
  	struct hci_dev *hdev;
69ab39ea5   Johan Hedberg   Bluetooth: Update...
796
  	__le32 ev;
c542a06c2   Johan Hedberg   Bluetooth: Implem...
797
798
799
  	int err;
  
  	cp = (void *) data;
c542a06c2   Johan Hedberg   Bluetooth: Implem...
800

4e51eae9c   Szymon Janc   Bluetooth: Move i...
801
  	BT_DBG("request for hci%u", index);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
802

bdce7bafb   Szymon Janc   Bluetooth: Valida...
803
  	if (len != sizeof(*cp))
ca69b7957   Johan Hedberg   Bluetooth: Create...
804
805
  		return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE,
  						MGMT_STATUS_INVALID_PARAMS);
bdce7bafb   Szymon Janc   Bluetooth: Valida...
806

4e51eae9c   Szymon Janc   Bluetooth: Move i...
807
  	hdev = hci_dev_get(index);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
808
  	if (!hdev)
ca69b7957   Johan Hedberg   Bluetooth: Create...
809
810
  		return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE,
  						MGMT_STATUS_INVALID_PARAMS);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
811

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
812
  	hci_dev_lock(hdev);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
813
814
815
816
817
  
  	if (cp->val)
  		set_bit(HCI_PAIRABLE, &hdev->flags);
  	else
  		clear_bit(HCI_PAIRABLE, &hdev->flags);
69ab39ea5   Johan Hedberg   Bluetooth: Update...
818
  	err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
819
820
  	if (err < 0)
  		goto failed;
69ab39ea5   Johan Hedberg   Bluetooth: Update...
821
  	ev = cpu_to_le32(get_current_settings(hdev));
c542a06c2   Johan Hedberg   Bluetooth: Implem...
822

69ab39ea5   Johan Hedberg   Bluetooth: Update...
823
  	err = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), sk);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
824
825
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
826
  	hci_dev_unlock(hdev);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
827
828
829
830
  	hci_dev_put(hdev);
  
  	return err;
  }
4e51eae9c   Szymon Janc   Bluetooth: Move i...
831
  static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
832
833
834
835
  {
  	struct mgmt_cp_add_uuid *cp;
  	struct hci_dev *hdev;
  	struct bt_uuid *uuid;
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
836
837
838
  	int err;
  
  	cp = (void *) data;
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
839

4e51eae9c   Szymon Janc   Bluetooth: Move i...
840
  	BT_DBG("request for hci%u", index);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
841

bdce7bafb   Szymon Janc   Bluetooth: Valida...
842
  	if (len != sizeof(*cp))
ca69b7957   Johan Hedberg   Bluetooth: Create...
843
844
  		return cmd_status(sk, index, MGMT_OP_ADD_UUID,
  						MGMT_STATUS_INVALID_PARAMS);
bdce7bafb   Szymon Janc   Bluetooth: Valida...
845

4e51eae9c   Szymon Janc   Bluetooth: Move i...
846
  	hdev = hci_dev_get(index);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
847
  	if (!hdev)
ca69b7957   Johan Hedberg   Bluetooth: Create...
848
849
  		return cmd_status(sk, index, MGMT_OP_ADD_UUID,
  						MGMT_STATUS_INVALID_PARAMS);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
850

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
851
  	hci_dev_lock(hdev);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
852
853
854
855
856
857
858
859
  
  	uuid = kmalloc(sizeof(*uuid), GFP_ATOMIC);
  	if (!uuid) {
  		err = -ENOMEM;
  		goto failed;
  	}
  
  	memcpy(uuid->uuid, cp->uuid, 16);
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
860
  	uuid->svc_hint = cp->svc_hint;
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
861
862
  
  	list_add(&uuid->list, &hdev->uuids);
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
863
864
865
  	err = update_class(hdev);
  	if (err < 0)
  		goto failed;
80a1e1dbf   Johan Hedberg   Bluetooth: Add lo...
866
867
868
  	err = update_eir(hdev);
  	if (err < 0)
  		goto failed;
4e51eae9c   Szymon Janc   Bluetooth: Move i...
869
  	err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, NULL, 0);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
870
871
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
872
  	hci_dev_unlock(hdev);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
873
874
875
876
  	hci_dev_put(hdev);
  
  	return err;
  }
4e51eae9c   Szymon Janc   Bluetooth: Move i...
877
  static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
878
879
  {
  	struct list_head *p, *n;
779cb8501   Szymon Janc   Bluetooth: Use pr...
880
  	struct mgmt_cp_remove_uuid *cp;
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
881
882
  	struct hci_dev *hdev;
  	u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
883
884
885
  	int err, found;
  
  	cp = (void *) data;
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
886

4e51eae9c   Szymon Janc   Bluetooth: Move i...
887
  	BT_DBG("request for hci%u", index);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
888

bdce7bafb   Szymon Janc   Bluetooth: Valida...
889
  	if (len != sizeof(*cp))
ca69b7957   Johan Hedberg   Bluetooth: Create...
890
891
  		return cmd_status(sk, index, MGMT_OP_REMOVE_UUID,
  						MGMT_STATUS_INVALID_PARAMS);
bdce7bafb   Szymon Janc   Bluetooth: Valida...
892

4e51eae9c   Szymon Janc   Bluetooth: Move i...
893
  	hdev = hci_dev_get(index);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
894
  	if (!hdev)
ca69b7957   Johan Hedberg   Bluetooth: Create...
895
896
  		return cmd_status(sk, index, MGMT_OP_REMOVE_UUID,
  						MGMT_STATUS_INVALID_PARAMS);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
897

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
898
  	hci_dev_lock(hdev);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
  
  	if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
  		err = hci_uuids_clear(hdev);
  		goto unlock;
  	}
  
  	found = 0;
  
  	list_for_each_safe(p, n, &hdev->uuids) {
  		struct bt_uuid *match = list_entry(p, struct bt_uuid, list);
  
  		if (memcmp(match->uuid, cp->uuid, 16) != 0)
  			continue;
  
  		list_del(&match->list);
  		found++;
  	}
  
  	if (found == 0) {
ca69b7957   Johan Hedberg   Bluetooth: Create...
918
919
  		err = cmd_status(sk, index, MGMT_OP_REMOVE_UUID,
  						MGMT_STATUS_INVALID_PARAMS);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
920
921
  		goto unlock;
  	}
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
922
923
924
  	err = update_class(hdev);
  	if (err < 0)
  		goto unlock;
80a1e1dbf   Johan Hedberg   Bluetooth: Add lo...
925
926
927
  	err = update_eir(hdev);
  	if (err < 0)
  		goto unlock;
4e51eae9c   Szymon Janc   Bluetooth: Move i...
928
  	err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, NULL, 0);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
929
930
  
  unlock:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
931
  	hci_dev_unlock(hdev);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
932
933
934
935
  	hci_dev_put(hdev);
  
  	return err;
  }
4e51eae9c   Szymon Janc   Bluetooth: Move i...
936
937
  static int set_dev_class(struct sock *sk, u16 index, unsigned char *data,
  									u16 len)
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
938
939
940
  {
  	struct hci_dev *hdev;
  	struct mgmt_cp_set_dev_class *cp;
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
941
942
943
  	int err;
  
  	cp = (void *) data;
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
944

4e51eae9c   Szymon Janc   Bluetooth: Move i...
945
  	BT_DBG("request for hci%u", index);
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
946

bdce7bafb   Szymon Janc   Bluetooth: Valida...
947
  	if (len != sizeof(*cp))
ca69b7957   Johan Hedberg   Bluetooth: Create...
948
949
  		return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS,
  						MGMT_STATUS_INVALID_PARAMS);
bdce7bafb   Szymon Janc   Bluetooth: Valida...
950

4e51eae9c   Szymon Janc   Bluetooth: Move i...
951
  	hdev = hci_dev_get(index);
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
952
  	if (!hdev)
ca69b7957   Johan Hedberg   Bluetooth: Create...
953
954
  		return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS,
  						MGMT_STATUS_INVALID_PARAMS);
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
955

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
956
  	hci_dev_lock(hdev);
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
957
958
959
  
  	hdev->major_class = cp->major;
  	hdev->minor_class = cp->minor;
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
960
961
962
963
  	if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->flags)) {
  		hci_dev_unlock(hdev);
  		cancel_delayed_work_sync(&hdev->service_cache);
  		hci_dev_lock(hdev);
14c0b6082   Johan Hedberg   Bluetooth: Remove...
964
  		update_eir(hdev);
7d78525dc   Johan Hedberg   Bluetooth: Add ti...
965
  	}
14c0b6082   Johan Hedberg   Bluetooth: Remove...
966

1aff6f094   Johan Hedberg   Bluetooth: Add cl...
967
968
969
  	err = update_class(hdev);
  
  	if (err == 0)
4e51eae9c   Szymon Janc   Bluetooth: Move i...
970
  		err = cmd_complete(sk, index, MGMT_OP_SET_DEV_CLASS, NULL, 0);
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
971

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
972
  	hci_dev_unlock(hdev);
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
973
974
975
976
  	hci_dev_put(hdev);
  
  	return err;
  }
86742e1ec   Johan Hedberg   Bluetooth: Update...
977
978
  static int load_link_keys(struct sock *sk, u16 index, unsigned char *data,
  								u16 len)
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
979
980
  {
  	struct hci_dev *hdev;
86742e1ec   Johan Hedberg   Bluetooth: Update...
981
  	struct mgmt_cp_load_link_keys *cp;
4e51eae9c   Szymon Janc   Bluetooth: Move i...
982
  	u16 key_count, expected_len;
a492cd52b   Vinicius Costa Gomes   Revert "Bluetooth...
983
  	int i;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
984
985
  
  	cp = (void *) data;
bdce7bafb   Szymon Janc   Bluetooth: Valida...
986
987
  
  	if (len < sizeof(*cp))
ca69b7957   Johan Hedberg   Bluetooth: Create...
988
989
  		return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS,
  						MGMT_STATUS_INVALID_PARAMS);
bdce7bafb   Szymon Janc   Bluetooth: Valida...
990

55ed8ca10   Johan Hedberg   Bluetooth: Implem...
991
  	key_count = get_unaligned_le16(&cp->key_count);
86742e1ec   Johan Hedberg   Bluetooth: Update...
992
993
  	expected_len = sizeof(*cp) + key_count *
  					sizeof(struct mgmt_link_key_info);
a492cd52b   Vinicius Costa Gomes   Revert "Bluetooth...
994
  	if (expected_len != len) {
86742e1ec   Johan Hedberg   Bluetooth: Update...
995
  		BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
a492cd52b   Vinicius Costa Gomes   Revert "Bluetooth...
996
  							len, expected_len);
ca69b7957   Johan Hedberg   Bluetooth: Create...
997
998
  		return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS,
  						MGMT_STATUS_INVALID_PARAMS);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
999
  	}
4e51eae9c   Szymon Janc   Bluetooth: Move i...
1000
  	hdev = hci_dev_get(index);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1001
  	if (!hdev)
ca69b7957   Johan Hedberg   Bluetooth: Create...
1002
1003
  		return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS,
  						MGMT_STATUS_INVALID_PARAMS);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1004

4e51eae9c   Szymon Janc   Bluetooth: Move i...
1005
  	BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys,
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1006
  								key_count);
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1007
  	hci_dev_lock(hdev);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1008
1009
1010
1011
1012
1013
1014
1015
1016
  
  	hci_link_keys_clear(hdev);
  
  	set_bit(HCI_LINK_KEYS, &hdev->flags);
  
  	if (cp->debug_keys)
  		set_bit(HCI_DEBUG_KEYS, &hdev->flags);
  	else
  		clear_bit(HCI_DEBUG_KEYS, &hdev->flags);
a492cd52b   Vinicius Costa Gomes   Revert "Bluetooth...
1017
  	for (i = 0; i < key_count; i++) {
86742e1ec   Johan Hedberg   Bluetooth: Update...
1018
  		struct mgmt_link_key_info *key = &cp->keys[i];
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1019

d25e28abe   Johan Hedberg   Bluetooth: Fix li...
1020
  		hci_add_link_key(hdev, NULL, 0, &key->bdaddr, key->val, key->type,
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1021
1022
  								key->pin_len);
  	}
0e5f875a8   Johan Hedberg   Bluetooth: Add mi...
1023
  	cmd_complete(sk, index, MGMT_OP_LOAD_LINK_KEYS, NULL, 0);
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1024
  	hci_dev_unlock(hdev);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1025
  	hci_dev_put(hdev);
a492cd52b   Vinicius Costa Gomes   Revert "Bluetooth...
1026
  	return 0;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1027
  }
86742e1ec   Johan Hedberg   Bluetooth: Update...
1028
1029
  static int remove_keys(struct sock *sk, u16 index, unsigned char *data,
  								u16 len)
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1030
1031
  {
  	struct hci_dev *hdev;
86742e1ec   Johan Hedberg   Bluetooth: Update...
1032
  	struct mgmt_cp_remove_keys *cp;
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
1033
1034
1035
  	struct mgmt_rp_remove_keys rp;
  	struct hci_cp_disconnect dc;
  	struct pending_cmd *cmd;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1036
  	struct hci_conn *conn;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1037
1038
1039
  	int err;
  
  	cp = (void *) data;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1040

bdce7bafb   Szymon Janc   Bluetooth: Valida...
1041
  	if (len != sizeof(*cp))
ca69b7957   Johan Hedberg   Bluetooth: Create...
1042
1043
  		return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS,
  						MGMT_STATUS_INVALID_PARAMS);
bdce7bafb   Szymon Janc   Bluetooth: Valida...
1044

4e51eae9c   Szymon Janc   Bluetooth: Move i...
1045
  	hdev = hci_dev_get(index);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1046
  	if (!hdev)
ca69b7957   Johan Hedberg   Bluetooth: Create...
1047
1048
  		return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS,
  						MGMT_STATUS_INVALID_PARAMS);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1049

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1050
  	hci_dev_lock(hdev);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1051

a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
1052
1053
  	memset(&rp, 0, sizeof(rp));
  	bacpy(&rp.bdaddr, &cp->bdaddr);
ca69b7957   Johan Hedberg   Bluetooth: Create...
1054
  	rp.status = MGMT_STATUS_FAILED;
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
1055

55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1056
1057
  	err = hci_remove_link_key(hdev, &cp->bdaddr);
  	if (err < 0) {
ca69b7957   Johan Hedberg   Bluetooth: Create...
1058
  		rp.status = MGMT_STATUS_NOT_PAIRED;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1059
1060
  		goto unlock;
  	}
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
1061
1062
1063
  	if (!test_bit(HCI_UP, &hdev->flags) || !cp->disconnect) {
  		err = cmd_complete(sk, index, MGMT_OP_REMOVE_KEYS, &rp,
  								sizeof(rp));
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1064
  		goto unlock;
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
1065
  	}
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1066
1067
  
  	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
1068
1069
1070
1071
1072
  	if (!conn) {
  		err = cmd_complete(sk, index, MGMT_OP_REMOVE_KEYS, &rp,
  								sizeof(rp));
  		goto unlock;
  	}
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1073

a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
1074
1075
1076
1077
  	cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_KEYS, hdev, cp, sizeof(*cp));
  	if (!cmd) {
  		err = -ENOMEM;
  		goto unlock;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1078
  	}
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
1079
1080
1081
1082
1083
  	put_unaligned_le16(conn->handle, &dc.handle);
  	dc.reason = 0x13; /* Remote User Terminated Connection */
  	err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
  	if (err < 0)
  		mgmt_pending_remove(cmd);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1084
  unlock:
ca69b7957   Johan Hedberg   Bluetooth: Create...
1085
  	if (err < 0)
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
1086
1087
  		err = cmd_complete(sk, index, MGMT_OP_REMOVE_KEYS, &rp,
  								sizeof(rp));
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1088
  	hci_dev_unlock(hdev);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1089
1090
1091
1092
  	hci_dev_put(hdev);
  
  	return err;
  }
4e51eae9c   Szymon Janc   Bluetooth: Move i...
1093
  static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
8962ee74b   Johan Hedberg   Bluetooth: Add di...
1094
1095
1096
1097
  {
  	struct hci_dev *hdev;
  	struct mgmt_cp_disconnect *cp;
  	struct hci_cp_disconnect dc;
366a03369   Johan Hedberg   Bluetooth: Make p...
1098
  	struct pending_cmd *cmd;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
1099
  	struct hci_conn *conn;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
1100
1101
1102
1103
1104
  	int err;
  
  	BT_DBG("");
  
  	cp = (void *) data;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
1105

bdce7bafb   Szymon Janc   Bluetooth: Valida...
1106
  	if (len != sizeof(*cp))
ca69b7957   Johan Hedberg   Bluetooth: Create...
1107
1108
  		return cmd_status(sk, index, MGMT_OP_DISCONNECT,
  						MGMT_STATUS_INVALID_PARAMS);
bdce7bafb   Szymon Janc   Bluetooth: Valida...
1109

4e51eae9c   Szymon Janc   Bluetooth: Move i...
1110
  	hdev = hci_dev_get(index);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
1111
  	if (!hdev)
ca69b7957   Johan Hedberg   Bluetooth: Create...
1112
1113
  		return cmd_status(sk, index, MGMT_OP_DISCONNECT,
  						MGMT_STATUS_INVALID_PARAMS);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
1114

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1115
  	hci_dev_lock(hdev);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
1116
1117
  
  	if (!test_bit(HCI_UP, &hdev->flags)) {
ca69b7957   Johan Hedberg   Bluetooth: Create...
1118
1119
  		err = cmd_status(sk, index, MGMT_OP_DISCONNECT,
  						MGMT_STATUS_NOT_POWERED);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
1120
1121
  		goto failed;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
1122
  	if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
ca69b7957   Johan Hedberg   Bluetooth: Create...
1123
1124
  		err = cmd_status(sk, index, MGMT_OP_DISCONNECT,
  							MGMT_STATUS_BUSY);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
1125
1126
1127
1128
  		goto failed;
  	}
  
  	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
365227e5f   Vinicius Costa Gomes   Bluetooth: Add su...
1129
1130
  	if (!conn)
  		conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
1131
  	if (!conn) {
ca69b7957   Johan Hedberg   Bluetooth: Create...
1132
1133
  		err = cmd_status(sk, index, MGMT_OP_DISCONNECT,
  						MGMT_STATUS_NOT_CONNECTED);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
1134
1135
  		goto failed;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
1136
  	cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
366a03369   Johan Hedberg   Bluetooth: Make p...
1137
1138
  	if (!cmd) {
  		err = -ENOMEM;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
1139
  		goto failed;
366a03369   Johan Hedberg   Bluetooth: Make p...
1140
  	}
8962ee74b   Johan Hedberg   Bluetooth: Add di...
1141
1142
1143
1144
1145
1146
  
  	put_unaligned_le16(conn->handle, &dc.handle);
  	dc.reason = 0x13; /* Remote User Terminated Connection */
  
  	err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
  	if (err < 0)
a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
1147
  		mgmt_pending_remove(cmd);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
1148
1149
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1150
  	hci_dev_unlock(hdev);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
1151
1152
1153
1154
  	hci_dev_put(hdev);
  
  	return err;
  }
48264f069   Johan Hedberg   Bluetooth: Add pu...
1155
  static u8 link_to_mgmt(u8 link_type, u8 addr_type)
4c659c397   Johan Hedberg   Bluetooth: Add ad...
1156
1157
1158
  {
  	switch (link_type) {
  	case LE_LINK:
48264f069   Johan Hedberg   Bluetooth: Add pu...
1159
1160
1161
1162
1163
1164
1165
1166
  		switch (addr_type) {
  		case ADDR_LE_DEV_PUBLIC:
  			return MGMT_ADDR_LE_PUBLIC;
  		case ADDR_LE_DEV_RANDOM:
  			return MGMT_ADDR_LE_RANDOM;
  		default:
  			return MGMT_ADDR_INVALID;
  		}
4c659c397   Johan Hedberg   Bluetooth: Add ad...
1167
1168
1169
1170
1171
1172
  	case ACL_LINK:
  		return MGMT_ADDR_BREDR;
  	default:
  		return MGMT_ADDR_INVALID;
  	}
  }
8ce6284ea   Szymon Janc   Bluetooth: Remove...
1173
  static int get_connections(struct sock *sk, u16 index)
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
1174
  {
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
1175
1176
  	struct mgmt_rp_get_connections *rp;
  	struct hci_dev *hdev;
8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
1177
  	struct hci_conn *c;
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
1178
  	struct list_head *p;
a38528f11   Johan Hedberg   Bluetooth: Create...
1179
  	size_t rp_len;
4e51eae9c   Szymon Janc   Bluetooth: Move i...
1180
  	u16 count;
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
1181
1182
1183
  	int i, err;
  
  	BT_DBG("");
4e51eae9c   Szymon Janc   Bluetooth: Move i...
1184
  	hdev = hci_dev_get(index);
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
1185
  	if (!hdev)
ca69b7957   Johan Hedberg   Bluetooth: Create...
1186
1187
  		return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS,
  						MGMT_STATUS_INVALID_PARAMS);
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
1188

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1189
  	hci_dev_lock(hdev);
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
1190
1191
1192
1193
1194
  
  	count = 0;
  	list_for_each(p, &hdev->conn_hash.list) {
  		count++;
  	}
4c659c397   Johan Hedberg   Bluetooth: Add ad...
1195
  	rp_len = sizeof(*rp) + (count * sizeof(struct mgmt_addr_info));
a38528f11   Johan Hedberg   Bluetooth: Create...
1196
1197
  	rp = kmalloc(rp_len, GFP_ATOMIC);
  	if (!rp) {
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
1198
1199
1200
  		err = -ENOMEM;
  		goto unlock;
  	}
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
1201
  	put_unaligned_le16(count, &rp->conn_count);
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
1202
  	i = 0;
4c659c397   Johan Hedberg   Bluetooth: Add ad...
1203
1204
  	list_for_each_entry(c, &hdev->conn_hash.list, list) {
  		bacpy(&rp->addr[i].bdaddr, &c->dst);
48264f069   Johan Hedberg   Bluetooth: Add pu...
1205
  		rp->addr[i].type = link_to_mgmt(c->type, c->dst_type);
4c659c397   Johan Hedberg   Bluetooth: Add ad...
1206
1207
1208
1209
1210
1211
1212
  		if (rp->addr[i].type == MGMT_ADDR_INVALID)
  			continue;
  		i++;
  	}
  
  	/* Recalculate length in case of filtered SCO connections, etc */
  	rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
1213

4e51eae9c   Szymon Janc   Bluetooth: Move i...
1214
  	err = cmd_complete(sk, index, MGMT_OP_GET_CONNECTIONS, rp, rp_len);
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
1215
1216
  
  unlock:
a38528f11   Johan Hedberg   Bluetooth: Create...
1217
  	kfree(rp);
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1218
  	hci_dev_unlock(hdev);
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
1219
1220
1221
  	hci_dev_put(hdev);
  	return err;
  }
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
1222
1223
1224
1225
1226
  static int send_pin_code_neg_reply(struct sock *sk, u16 index,
  		struct hci_dev *hdev, struct mgmt_cp_pin_code_neg_reply *cp)
  {
  	struct pending_cmd *cmd;
  	int err;
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
1227
  	cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
  								sizeof(*cp));
  	if (!cmd)
  		return -ENOMEM;
  
  	err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(cp->bdaddr),
  								&cp->bdaddr);
  	if (err < 0)
  		mgmt_pending_remove(cmd);
  
  	return err;
  }
4e51eae9c   Szymon Janc   Bluetooth: Move i...
1239
1240
  static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
  									u16 len)
980e1a537   Johan Hedberg   Bluetooth: Add su...
1241
1242
  {
  	struct hci_dev *hdev;
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
1243
  	struct hci_conn *conn;
980e1a537   Johan Hedberg   Bluetooth: Add su...
1244
  	struct mgmt_cp_pin_code_reply *cp;
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
1245
  	struct mgmt_cp_pin_code_neg_reply ncp;
980e1a537   Johan Hedberg   Bluetooth: Add su...
1246
  	struct hci_cp_pin_code_reply reply;
366a03369   Johan Hedberg   Bluetooth: Make p...
1247
  	struct pending_cmd *cmd;
980e1a537   Johan Hedberg   Bluetooth: Add su...
1248
1249
1250
1251
1252
  	int err;
  
  	BT_DBG("");
  
  	cp = (void *) data;
980e1a537   Johan Hedberg   Bluetooth: Add su...
1253

bdce7bafb   Szymon Janc   Bluetooth: Valida...
1254
  	if (len != sizeof(*cp))
ca69b7957   Johan Hedberg   Bluetooth: Create...
1255
1256
  		return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
  						MGMT_STATUS_INVALID_PARAMS);
bdce7bafb   Szymon Janc   Bluetooth: Valida...
1257

4e51eae9c   Szymon Janc   Bluetooth: Move i...
1258
  	hdev = hci_dev_get(index);
980e1a537   Johan Hedberg   Bluetooth: Add su...
1259
  	if (!hdev)
ca69b7957   Johan Hedberg   Bluetooth: Create...
1260
1261
  		return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
  						MGMT_STATUS_INVALID_PARAMS);
980e1a537   Johan Hedberg   Bluetooth: Add su...
1262

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1263
  	hci_dev_lock(hdev);
980e1a537   Johan Hedberg   Bluetooth: Add su...
1264
1265
  
  	if (!test_bit(HCI_UP, &hdev->flags)) {
ca69b7957   Johan Hedberg   Bluetooth: Create...
1266
1267
  		err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
  						MGMT_STATUS_NOT_POWERED);
980e1a537   Johan Hedberg   Bluetooth: Add su...
1268
1269
  		goto failed;
  	}
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
1270
1271
  	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
  	if (!conn) {
ca69b7957   Johan Hedberg   Bluetooth: Create...
1272
1273
  		err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
  						MGMT_STATUS_NOT_CONNECTED);
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
  		goto failed;
  	}
  
  	if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
  		bacpy(&ncp.bdaddr, &cp->bdaddr);
  
  		BT_ERR("PIN code is not 16 bytes long");
  
  		err = send_pin_code_neg_reply(sk, index, hdev, &ncp);
  		if (err >= 0)
  			err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
ca69b7957   Johan Hedberg   Bluetooth: Create...
1285
  						MGMT_STATUS_INVALID_PARAMS);
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
1286
1287
1288
  
  		goto failed;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
1289
  	cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
366a03369   Johan Hedberg   Bluetooth: Make p...
1290
1291
  	if (!cmd) {
  		err = -ENOMEM;
980e1a537   Johan Hedberg   Bluetooth: Add su...
1292
  		goto failed;
366a03369   Johan Hedberg   Bluetooth: Make p...
1293
  	}
980e1a537   Johan Hedberg   Bluetooth: Add su...
1294
1295
1296
  
  	bacpy(&reply.bdaddr, &cp->bdaddr);
  	reply.pin_len = cp->pin_len;
24718ca5e   Waldemar Rymarkiewicz   Bluetooth: Remove...
1297
  	memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
980e1a537   Johan Hedberg   Bluetooth: Add su...
1298
1299
1300
  
  	err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
  	if (err < 0)
a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
1301
  		mgmt_pending_remove(cmd);
980e1a537   Johan Hedberg   Bluetooth: Add su...
1302
1303
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1304
  	hci_dev_unlock(hdev);
980e1a537   Johan Hedberg   Bluetooth: Add su...
1305
1306
1307
1308
  	hci_dev_put(hdev);
  
  	return err;
  }
4e51eae9c   Szymon Janc   Bluetooth: Move i...
1309
1310
  static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
  									u16 len)
980e1a537   Johan Hedberg   Bluetooth: Add su...
1311
1312
1313
  {
  	struct hci_dev *hdev;
  	struct mgmt_cp_pin_code_neg_reply *cp;
980e1a537   Johan Hedberg   Bluetooth: Add su...
1314
1315
1316
1317
1318
  	int err;
  
  	BT_DBG("");
  
  	cp = (void *) data;
980e1a537   Johan Hedberg   Bluetooth: Add su...
1319

bdce7bafb   Szymon Janc   Bluetooth: Valida...
1320
1321
  	if (len != sizeof(*cp))
  		return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
ca69b7957   Johan Hedberg   Bluetooth: Create...
1322
  						MGMT_STATUS_INVALID_PARAMS);
bdce7bafb   Szymon Janc   Bluetooth: Valida...
1323

4e51eae9c   Szymon Janc   Bluetooth: Move i...
1324
  	hdev = hci_dev_get(index);
980e1a537   Johan Hedberg   Bluetooth: Add su...
1325
  	if (!hdev)
4e51eae9c   Szymon Janc   Bluetooth: Move i...
1326
  		return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
ca69b7957   Johan Hedberg   Bluetooth: Create...
1327
  						MGMT_STATUS_INVALID_PARAMS);
980e1a537   Johan Hedberg   Bluetooth: Add su...
1328

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1329
  	hci_dev_lock(hdev);
980e1a537   Johan Hedberg   Bluetooth: Add su...
1330
1331
  
  	if (!test_bit(HCI_UP, &hdev->flags)) {
4e51eae9c   Szymon Janc   Bluetooth: Move i...
1332
  		err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
ca69b7957   Johan Hedberg   Bluetooth: Create...
1333
  						MGMT_STATUS_NOT_POWERED);
980e1a537   Johan Hedberg   Bluetooth: Add su...
1334
1335
  		goto failed;
  	}
96d97a673   Waldemar Rymarkiewicz   Bluetooth: Verify...
1336
  	err = send_pin_code_neg_reply(sk, index, hdev, cp);
980e1a537   Johan Hedberg   Bluetooth: Add su...
1337
1338
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1339
  	hci_dev_unlock(hdev);
980e1a537   Johan Hedberg   Bluetooth: Add su...
1340
1341
1342
1343
  	hci_dev_put(hdev);
  
  	return err;
  }
4e51eae9c   Szymon Janc   Bluetooth: Move i...
1344
1345
  static int set_io_capability(struct sock *sk, u16 index, unsigned char *data,
  									u16 len)
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
1346
1347
1348
  {
  	struct hci_dev *hdev;
  	struct mgmt_cp_set_io_capability *cp;
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
1349
1350
1351
1352
  
  	BT_DBG("");
  
  	cp = (void *) data;
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
1353

bdce7bafb   Szymon Janc   Bluetooth: Valida...
1354
  	if (len != sizeof(*cp))
ca69b7957   Johan Hedberg   Bluetooth: Create...
1355
1356
  		return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY,
  						MGMT_STATUS_INVALID_PARAMS);
bdce7bafb   Szymon Janc   Bluetooth: Valida...
1357

4e51eae9c   Szymon Janc   Bluetooth: Move i...
1358
  	hdev = hci_dev_get(index);
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
1359
  	if (!hdev)
ca69b7957   Johan Hedberg   Bluetooth: Create...
1360
1361
  		return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY,
  						MGMT_STATUS_INVALID_PARAMS);
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
1362

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1363
  	hci_dev_lock(hdev);
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
1364
1365
1366
1367
  
  	hdev->io_capability = cp->io_capability;
  
  	BT_DBG("%s IO capability set to 0x%02x", hdev->name,
b8534e0f2   Szymon Janc   Bluetooth: Fix so...
1368
  							hdev->io_capability);
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
1369

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1370
  	hci_dev_unlock(hdev);
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
1371
  	hci_dev_put(hdev);
4e51eae9c   Szymon Janc   Bluetooth: Move i...
1372
  	return cmd_complete(sk, index, MGMT_OP_SET_IO_CAPABILITY, NULL, 0);
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
1373
  }
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1374
1375
1376
  static inline struct pending_cmd *find_pairing(struct hci_conn *conn)
  {
  	struct hci_dev *hdev = conn->hdev;
8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
1377
  	struct pending_cmd *cmd;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1378

2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
1379
  	list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1380
1381
  		if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
  			continue;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
  		if (cmd->user_data != conn)
  			continue;
  
  		return cmd;
  	}
  
  	return NULL;
  }
  
  static void pairing_complete(struct pending_cmd *cmd, u8 status)
  {
  	struct mgmt_rp_pair_device rp;
  	struct hci_conn *conn = cmd->user_data;
ba4e564f6   Johan Hedberg   Bluetooth: Add ad...
1395
1396
  	bacpy(&rp.addr.bdaddr, &conn->dst);
  	rp.addr.type = link_to_mgmt(conn->type, conn->dst_type);
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1397
  	rp.status = status;
4e51eae9c   Szymon Janc   Bluetooth: Move i...
1398
  	cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, &rp, sizeof(rp));
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1399
1400
1401
1402
1403
1404
1405
  
  	/* 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;
  
  	hci_conn_put(conn);
a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
1406
  	mgmt_pending_remove(cmd);
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1407
1408
1409
1410
1411
1412
1413
1414
1415
  }
  
  static void pairing_complete_cb(struct hci_conn *conn, u8 status)
  {
  	struct pending_cmd *cmd;
  
  	BT_DBG("status %u", status);
  
  	cmd = find_pairing(conn);
56e5cb86e   Johan Hedberg   Bluetooth: Add mi...
1416
  	if (!cmd)
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1417
  		BT_DBG("Unable to find a pending command");
56e5cb86e   Johan Hedberg   Bluetooth: Add mi...
1418
1419
  	else
  		pairing_complete(cmd, status);
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1420
  }
4e51eae9c   Szymon Janc   Bluetooth: Move i...
1421
  static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1422
1423
1424
  {
  	struct hci_dev *hdev;
  	struct mgmt_cp_pair_device *cp;
1425acb74   Johan Hedberg   Bluetooth: Fix mg...
1425
  	struct mgmt_rp_pair_device rp;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1426
1427
1428
  	struct pending_cmd *cmd;
  	u8 sec_level, auth_type;
  	struct hci_conn *conn;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1429
1430
1431
1432
1433
  	int err;
  
  	BT_DBG("");
  
  	cp = (void *) data;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1434

bdce7bafb   Szymon Janc   Bluetooth: Valida...
1435
  	if (len != sizeof(*cp))
ca69b7957   Johan Hedberg   Bluetooth: Create...
1436
1437
  		return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE,
  						MGMT_STATUS_INVALID_PARAMS);
bdce7bafb   Szymon Janc   Bluetooth: Valida...
1438

4e51eae9c   Szymon Janc   Bluetooth: Move i...
1439
  	hdev = hci_dev_get(index);
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1440
  	if (!hdev)
ca69b7957   Johan Hedberg   Bluetooth: Create...
1441
1442
  		return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE,
  						MGMT_STATUS_INVALID_PARAMS);
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1443

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

c908df362   Vinicius Costa Gomes   Bluetooth: Use th...
1446
1447
  	sec_level = BT_SECURITY_MEDIUM;
  	if (cp->io_cap == 0x03)
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1448
  		auth_type = HCI_AT_DEDICATED_BONDING;
c908df362   Vinicius Costa Gomes   Bluetooth: Use th...
1449
  	else
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1450
  		auth_type = HCI_AT_DEDICATED_BONDING_MITM;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1451

ba4e564f6   Johan Hedberg   Bluetooth: Add ad...
1452
1453
  	if (cp->addr.type == MGMT_ADDR_BREDR)
  		conn = hci_connect(hdev, ACL_LINK, &cp->addr.bdaddr, sec_level,
7a512d017   Vinicius Costa Gomes   Bluetooth: Add su...
1454
1455
  								auth_type);
  	else
ba4e564f6   Johan Hedberg   Bluetooth: Add ad...
1456
  		conn = hci_connect(hdev, LE_LINK, &cp->addr.bdaddr, sec_level,
7a512d017   Vinicius Costa Gomes   Bluetooth: Add su...
1457
  								auth_type);
1425acb74   Johan Hedberg   Bluetooth: Fix mg...
1458
1459
1460
  	memset(&rp, 0, sizeof(rp));
  	bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
  	rp.addr.type = cp->addr.type;
30e762721   Ville Tervo   Bluetooth: Use ER...
1461
  	if (IS_ERR(conn)) {
1425acb74   Johan Hedberg   Bluetooth: Fix mg...
1462
1463
1464
  		rp.status = -PTR_ERR(conn);
  		err = cmd_complete(sk, index, MGMT_OP_PAIR_DEVICE,
  							&rp, sizeof(rp));
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1465
1466
1467
1468
1469
  		goto unlock;
  	}
  
  	if (conn->connect_cfm_cb) {
  		hci_conn_put(conn);
1425acb74   Johan Hedberg   Bluetooth: Fix mg...
1470
1471
1472
  		rp.status = EBUSY;
  		err = cmd_complete(sk, index, MGMT_OP_PAIR_DEVICE,
  							&rp, sizeof(rp));
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1473
1474
  		goto unlock;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
1475
  	cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1476
1477
1478
1479
1480
  	if (!cmd) {
  		err = -ENOMEM;
  		hci_conn_put(conn);
  		goto unlock;
  	}
7a512d017   Vinicius Costa Gomes   Bluetooth: Add su...
1481
  	/* For LE, just connecting isn't a proof that the pairing finished */
ba4e564f6   Johan Hedberg   Bluetooth: Add ad...
1482
  	if (cp->addr.type == MGMT_ADDR_BREDR)
7a512d017   Vinicius Costa Gomes   Bluetooth: Add su...
1483
  		conn->connect_cfm_cb = pairing_complete_cb;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
  	conn->security_cfm_cb = pairing_complete_cb;
  	conn->disconn_cfm_cb = pairing_complete_cb;
  	conn->io_capability = cp->io_cap;
  	cmd->user_data = conn;
  
  	if (conn->state == BT_CONNECTED &&
  				hci_conn_security(conn, sec_level, auth_type))
  		pairing_complete(cmd, 0);
  
  	err = 0;
  
  unlock:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1496
  	hci_dev_unlock(hdev);
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
1497
1498
1499
1500
  	hci_dev_put(hdev);
  
  	return err;
  }
0df4c185e   Brian Gix   Bluetooth: User P...
1501
1502
  static int user_pairing_resp(struct sock *sk, u16 index, bdaddr_t *bdaddr,
  					u16 mgmt_op, u16 hci_op, __le32 passkey)
a5c296832   Johan Hedberg   Bluetooth: Add ma...
1503
  {
a5c296832   Johan Hedberg   Bluetooth: Add ma...
1504
1505
  	struct pending_cmd *cmd;
  	struct hci_dev *hdev;
0df4c185e   Brian Gix   Bluetooth: User P...
1506
  	struct hci_conn *conn;
a5c296832   Johan Hedberg   Bluetooth: Add ma...
1507
  	int err;
4e51eae9c   Szymon Janc   Bluetooth: Move i...
1508
  	hdev = hci_dev_get(index);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
1509
  	if (!hdev)
ca69b7957   Johan Hedberg   Bluetooth: Create...
1510
1511
  		return cmd_status(sk, index, mgmt_op,
  						MGMT_STATUS_INVALID_PARAMS);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
1512

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1513
  	hci_dev_lock(hdev);
08ba53824   Johan Hedberg   Bluetooth: Fix mi...
1514

a5c296832   Johan Hedberg   Bluetooth: Add ma...
1515
  	if (!test_bit(HCI_UP, &hdev->flags)) {
0df4c185e   Brian Gix   Bluetooth: User P...
1516
1517
  		err = cmd_status(sk, index, mgmt_op, MGMT_STATUS_NOT_POWERED);
  		goto done;
a5c296832   Johan Hedberg   Bluetooth: Add ma...
1518
  	}
47c15e2b3   Brian Gix   Bluetooth: Differ...
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
  	/*
  	 * Check for an existing ACL link, if present pair via
  	 * HCI commands.
  	 *
  	 * If no ACL link is present, check for an LE link and if
  	 * present, pair via the SMP engine.
  	 *
  	 * If neither ACL nor LE links are present, fail with error.
  	 */
  	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr);
  	if (!conn) {
  		conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, bdaddr);
  		if (!conn) {
  			err = cmd_status(sk, index, mgmt_op,
  						MGMT_STATUS_NOT_CONNECTED);
  			goto done;
  		}
  
  		/* Continue with pairing via SMP */
5fe57d9e9   Brian Gix   Bluetooth: Add SM...
1538
1539
1540
1541
1542
1543
1544
1545
  		err = smp_user_confirm_reply(conn, mgmt_op, passkey);
  
  		if (!err)
  			err = cmd_status(sk, index, mgmt_op,
  							MGMT_STATUS_SUCCESS);
  		else
  			err = cmd_status(sk, index, mgmt_op,
  							MGMT_STATUS_FAILED);
47c15e2b3   Brian Gix   Bluetooth: Differ...
1546

47c15e2b3   Brian Gix   Bluetooth: Differ...
1547
1548
  		goto done;
  	}
0df4c185e   Brian Gix   Bluetooth: User P...
1549
  	cmd = mgmt_pending_add(sk, mgmt_op, hdev, bdaddr, sizeof(*bdaddr));
a5c296832   Johan Hedberg   Bluetooth: Add ma...
1550
1551
  	if (!cmd) {
  		err = -ENOMEM;
0df4c185e   Brian Gix   Bluetooth: User P...
1552
  		goto done;
a5c296832   Johan Hedberg   Bluetooth: Add ma...
1553
  	}
0df4c185e   Brian Gix   Bluetooth: User P...
1554
  	/* Continue with pairing via HCI */
604086b73   Brian Gix   Bluetooth: Add Us...
1555
1556
1557
1558
1559
1560
1561
1562
  	if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
  		struct hci_cp_user_passkey_reply cp;
  
  		bacpy(&cp.bdaddr, bdaddr);
  		cp.passkey = passkey;
  		err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
  	} else
  		err = hci_send_cmd(hdev, hci_op, sizeof(*bdaddr), bdaddr);
a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
1563
1564
  	if (err < 0)
  		mgmt_pending_remove(cmd);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
1565

0df4c185e   Brian Gix   Bluetooth: User P...
1566
  done:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1567
  	hci_dev_unlock(hdev);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
1568
1569
1570
1571
  	hci_dev_put(hdev);
  
  	return err;
  }
0df4c185e   Brian Gix   Bluetooth: User P...
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
  static int user_confirm_reply(struct sock *sk, u16 index, void *data, u16 len)
  {
  	struct mgmt_cp_user_confirm_reply *cp = (void *) data;
  
  	BT_DBG("");
  
  	if (len != sizeof(*cp))
  		return cmd_status(sk, index, MGMT_OP_USER_CONFIRM_REPLY,
  						MGMT_STATUS_INVALID_PARAMS);
  
  	return user_pairing_resp(sk, index, &cp->bdaddr,
  			MGMT_OP_USER_CONFIRM_REPLY,
  			HCI_OP_USER_CONFIRM_REPLY, 0);
  }
  
  static int user_confirm_neg_reply(struct sock *sk, u16 index, void *data,
  									u16 len)
  {
c9c2659f1   Johan Hedberg   Bluetooth: Use co...
1590
  	struct mgmt_cp_user_confirm_neg_reply *cp = data;
0df4c185e   Brian Gix   Bluetooth: User P...
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
  
  	BT_DBG("");
  
  	if (len != sizeof(*cp))
  		return cmd_status(sk, index, MGMT_OP_USER_CONFIRM_NEG_REPLY,
  						MGMT_STATUS_INVALID_PARAMS);
  
  	return user_pairing_resp(sk, index, &cp->bdaddr,
  			MGMT_OP_USER_CONFIRM_NEG_REPLY,
  			HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
  }
604086b73   Brian Gix   Bluetooth: Add Us...
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
  static int user_passkey_reply(struct sock *sk, u16 index, void *data, u16 len)
  {
  	struct mgmt_cp_user_passkey_reply *cp = (void *) data;
  
  	BT_DBG("");
  
  	if (len != sizeof(*cp))
  		return cmd_status(sk, index, MGMT_OP_USER_PASSKEY_REPLY,
  									EINVAL);
  
  	return user_pairing_resp(sk, index, &cp->bdaddr,
  			MGMT_OP_USER_PASSKEY_REPLY,
  			HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
  }
  
  static int user_passkey_neg_reply(struct sock *sk, u16 index, void *data,
  									u16 len)
  {
  	struct mgmt_cp_user_passkey_neg_reply *cp = (void *) data;
  
  	BT_DBG("");
  
  	if (len != sizeof(*cp))
  		return cmd_status(sk, index, MGMT_OP_USER_PASSKEY_NEG_REPLY,
  									EINVAL);
  
  	return user_pairing_resp(sk, index, &cp->bdaddr,
  			MGMT_OP_USER_PASSKEY_NEG_REPLY,
  			HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
  }
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
  static int set_local_name(struct sock *sk, u16 index, unsigned char *data,
  								u16 len)
  {
  	struct mgmt_cp_set_local_name *mgmt_cp = (void *) data;
  	struct hci_cp_write_local_name hci_cp;
  	struct hci_dev *hdev;
  	struct pending_cmd *cmd;
  	int err;
  
  	BT_DBG("");
  
  	if (len != sizeof(*mgmt_cp))
ca69b7957   Johan Hedberg   Bluetooth: Create...
1644
1645
  		return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME,
  						MGMT_STATUS_INVALID_PARAMS);
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
1646
1647
1648
  
  	hdev = hci_dev_get(index);
  	if (!hdev)
ca69b7957   Johan Hedberg   Bluetooth: Create...
1649
1650
  		return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME,
  						MGMT_STATUS_INVALID_PARAMS);
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
1651

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

2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
1654
  	cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
  	if (!cmd) {
  		err = -ENOMEM;
  		goto failed;
  	}
  
  	memcpy(hci_cp.name, mgmt_cp->name, sizeof(hci_cp.name));
  	err = hci_send_cmd(hdev, HCI_OP_WRITE_LOCAL_NAME, sizeof(hci_cp),
  								&hci_cp);
  	if (err < 0)
  		mgmt_pending_remove(cmd);
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1667
  	hci_dev_unlock(hdev);
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
1668
1669
1670
1671
  	hci_dev_put(hdev);
  
  	return err;
  }
c35938b2f   Szymon Janc   Bluetooth: Add re...
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
  static int read_local_oob_data(struct sock *sk, u16 index)
  {
  	struct hci_dev *hdev;
  	struct pending_cmd *cmd;
  	int err;
  
  	BT_DBG("hci%u", index);
  
  	hdev = hci_dev_get(index);
  	if (!hdev)
  		return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
ca69b7957   Johan Hedberg   Bluetooth: Create...
1683
  						MGMT_STATUS_INVALID_PARAMS);
c35938b2f   Szymon Janc   Bluetooth: Add re...
1684

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1685
  	hci_dev_lock(hdev);
c35938b2f   Szymon Janc   Bluetooth: Add re...
1686
1687
1688
  
  	if (!test_bit(HCI_UP, &hdev->flags)) {
  		err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
ca69b7957   Johan Hedberg   Bluetooth: Create...
1689
  						MGMT_STATUS_NOT_POWERED);
c35938b2f   Szymon Janc   Bluetooth: Add re...
1690
1691
1692
1693
1694
  		goto unlock;
  	}
  
  	if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) {
  		err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
ca69b7957   Johan Hedberg   Bluetooth: Create...
1695
  						MGMT_STATUS_NOT_SUPPORTED);
c35938b2f   Szymon Janc   Bluetooth: Add re...
1696
1697
  		goto unlock;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
1698
  	if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
ca69b7957   Johan Hedberg   Bluetooth: Create...
1699
1700
  		err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
  							MGMT_STATUS_BUSY);
c35938b2f   Szymon Janc   Bluetooth: Add re...
1701
1702
  		goto unlock;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
1703
  	cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
c35938b2f   Szymon Janc   Bluetooth: Add re...
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
  	if (!cmd) {
  		err = -ENOMEM;
  		goto unlock;
  	}
  
  	err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
  	if (err < 0)
  		mgmt_pending_remove(cmd);
  
  unlock:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1714
  	hci_dev_unlock(hdev);
c35938b2f   Szymon Janc   Bluetooth: Add re...
1715
1716
1717
1718
  	hci_dev_put(hdev);
  
  	return err;
  }
2763eda6c   Szymon Janc   Bluetooth: Add ad...
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
  static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data,
  									u16 len)
  {
  	struct hci_dev *hdev;
  	struct mgmt_cp_add_remote_oob_data *cp = (void *) data;
  	int err;
  
  	BT_DBG("hci%u ", index);
  
  	if (len != sizeof(*cp))
  		return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
ca69b7957   Johan Hedberg   Bluetooth: Create...
1730
  						MGMT_STATUS_INVALID_PARAMS);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
1731
1732
1733
1734
  
  	hdev = hci_dev_get(index);
  	if (!hdev)
  		return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
ca69b7957   Johan Hedberg   Bluetooth: Create...
1735
  						MGMT_STATUS_INVALID_PARAMS);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
1736

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1737
  	hci_dev_lock(hdev);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
1738
1739
1740
1741
  
  	err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash,
  								cp->randomizer);
  	if (err < 0)
ca69b7957   Johan Hedberg   Bluetooth: Create...
1742
1743
  		err = cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
  							MGMT_STATUS_FAILED);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
1744
1745
1746
  	else
  		err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL,
  									0);
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1747
  	hci_dev_unlock(hdev);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
  	hci_dev_put(hdev);
  
  	return err;
  }
  
  static int remove_remote_oob_data(struct sock *sk, u16 index,
  						unsigned char *data, u16 len)
  {
  	struct hci_dev *hdev;
  	struct mgmt_cp_remove_remote_oob_data *cp = (void *) data;
  	int err;
  
  	BT_DBG("hci%u ", index);
  
  	if (len != sizeof(*cp))
  		return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
ca69b7957   Johan Hedberg   Bluetooth: Create...
1764
  						MGMT_STATUS_INVALID_PARAMS);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
1765
1766
1767
1768
  
  	hdev = hci_dev_get(index);
  	if (!hdev)
  		return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
ca69b7957   Johan Hedberg   Bluetooth: Create...
1769
  						MGMT_STATUS_INVALID_PARAMS);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
1770

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1771
  	hci_dev_lock(hdev);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
1772
1773
1774
1775
  
  	err = hci_remove_remote_oob_data(hdev, &cp->bdaddr);
  	if (err < 0)
  		err = cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
ca69b7957   Johan Hedberg   Bluetooth: Create...
1776
  						MGMT_STATUS_INVALID_PARAMS);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
1777
1778
1779
  	else
  		err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
  								NULL, 0);
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1780
  	hci_dev_unlock(hdev);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
1781
1782
1783
1784
  	hci_dev_put(hdev);
  
  	return err;
  }
450dfdafb   Johan Hedberg   Bluetooth: Pass a...
1785
1786
  static int start_discovery(struct sock *sk, u16 index,
  						unsigned char *data, u16 len)
14a536641   Johan Hedberg   Bluetooth: Add ba...
1787
  {
450dfdafb   Johan Hedberg   Bluetooth: Pass a...
1788
  	struct mgmt_cp_start_discovery *cp = (void *) data;
14a536641   Johan Hedberg   Bluetooth: Add ba...
1789
1790
1791
1792
1793
  	struct pending_cmd *cmd;
  	struct hci_dev *hdev;
  	int err;
  
  	BT_DBG("hci%u", index);
450dfdafb   Johan Hedberg   Bluetooth: Pass a...
1794
1795
1796
  	if (len != sizeof(*cp))
  		return cmd_status(sk, index, MGMT_OP_START_DISCOVERY,
  						MGMT_STATUS_INVALID_PARAMS);
14a536641   Johan Hedberg   Bluetooth: Add ba...
1797
1798
  	hdev = hci_dev_get(index);
  	if (!hdev)
ca69b7957   Johan Hedberg   Bluetooth: Create...
1799
1800
  		return cmd_status(sk, index, MGMT_OP_START_DISCOVERY,
  						MGMT_STATUS_INVALID_PARAMS);
14a536641   Johan Hedberg   Bluetooth: Add ba...
1801

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

bd2d1334e   Johan Hedberg   Bluetooth: Fix re...
1804
  	if (!test_bit(HCI_UP, &hdev->flags)) {
ca69b7957   Johan Hedberg   Bluetooth: Create...
1805
1806
  		err = cmd_status(sk, index, MGMT_OP_START_DISCOVERY,
  						MGMT_STATUS_NOT_POWERED);
bd2d1334e   Johan Hedberg   Bluetooth: Fix re...
1807
1808
  		goto failed;
  	}
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
1809
  	cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
14a536641   Johan Hedberg   Bluetooth: Add ba...
1810
1811
1812
1813
  	if (!cmd) {
  		err = -ENOMEM;
  		goto failed;
  	}
2519a1fc8   Andre Guedes   Bluetooth: Create...
1814
  	err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR);
14a536641   Johan Hedberg   Bluetooth: Add ba...
1815
1816
1817
1818
  	if (err < 0)
  		mgmt_pending_remove(cmd);
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1819
  	hci_dev_unlock(hdev);
14a536641   Johan Hedberg   Bluetooth: Add ba...
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
  	hci_dev_put(hdev);
  
  	return err;
  }
  
  static int stop_discovery(struct sock *sk, u16 index)
  {
  	struct hci_dev *hdev;
  	struct pending_cmd *cmd;
  	int err;
  
  	BT_DBG("hci%u", index);
  
  	hdev = hci_dev_get(index);
  	if (!hdev)
ca69b7957   Johan Hedberg   Bluetooth: Create...
1835
1836
  		return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY,
  						MGMT_STATUS_INVALID_PARAMS);
14a536641   Johan Hedberg   Bluetooth: Add ba...
1837

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

2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
1840
  	cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
14a536641   Johan Hedberg   Bluetooth: Add ba...
1841
1842
1843
1844
  	if (!cmd) {
  		err = -ENOMEM;
  		goto failed;
  	}
023d50498   Andre Guedes   Bluetooth: Create...
1845
  	err = hci_cancel_inquiry(hdev);
14a536641   Johan Hedberg   Bluetooth: Add ba...
1846
1847
1848
1849
  	if (err < 0)
  		mgmt_pending_remove(cmd);
  
  failed:
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1850
  	hci_dev_unlock(hdev);
14a536641   Johan Hedberg   Bluetooth: Add ba...
1851
1852
1853
1854
  	hci_dev_put(hdev);
  
  	return err;
  }
7fbec224c   Antti Julku   Bluetooth: Add bl...
1855
1856
1857
1858
  static int block_device(struct sock *sk, u16 index, unsigned char *data,
  								u16 len)
  {
  	struct hci_dev *hdev;
5e762444b   Antti Julku   Bluetooth: Add mg...
1859
  	struct mgmt_cp_block_device *cp = (void *) data;
7fbec224c   Antti Julku   Bluetooth: Add bl...
1860
1861
1862
  	int err;
  
  	BT_DBG("hci%u", index);
7fbec224c   Antti Julku   Bluetooth: Add bl...
1863
1864
  	if (len != sizeof(*cp))
  		return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
ca69b7957   Johan Hedberg   Bluetooth: Create...
1865
  						MGMT_STATUS_INVALID_PARAMS);
7fbec224c   Antti Julku   Bluetooth: Add bl...
1866
1867
1868
1869
  
  	hdev = hci_dev_get(index);
  	if (!hdev)
  		return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
ca69b7957   Johan Hedberg   Bluetooth: Create...
1870
  						MGMT_STATUS_INVALID_PARAMS);
7fbec224c   Antti Julku   Bluetooth: Add bl...
1871

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

7fbec224c   Antti Julku   Bluetooth: Add bl...
1874
  	err = hci_blacklist_add(hdev, &cp->bdaddr);
7fbec224c   Antti Julku   Bluetooth: Add bl...
1875
  	if (err < 0)
ca69b7957   Johan Hedberg   Bluetooth: Create...
1876
1877
  		err = cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
  							MGMT_STATUS_FAILED);
7fbec224c   Antti Julku   Bluetooth: Add bl...
1878
1879
1880
  	else
  		err = cmd_complete(sk, index, MGMT_OP_BLOCK_DEVICE,
  							NULL, 0);
5e762444b   Antti Julku   Bluetooth: Add mg...
1881

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1882
  	hci_dev_unlock(hdev);
7fbec224c   Antti Julku   Bluetooth: Add bl...
1883
1884
1885
1886
1887
1888
1889
1890
1891
  	hci_dev_put(hdev);
  
  	return err;
  }
  
  static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
  								u16 len)
  {
  	struct hci_dev *hdev;
5e762444b   Antti Julku   Bluetooth: Add mg...
1892
  	struct mgmt_cp_unblock_device *cp = (void *) data;
7fbec224c   Antti Julku   Bluetooth: Add bl...
1893
1894
1895
  	int err;
  
  	BT_DBG("hci%u", index);
7fbec224c   Antti Julku   Bluetooth: Add bl...
1896
1897
  	if (len != sizeof(*cp))
  		return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
ca69b7957   Johan Hedberg   Bluetooth: Create...
1898
  						MGMT_STATUS_INVALID_PARAMS);
7fbec224c   Antti Julku   Bluetooth: Add bl...
1899
1900
1901
1902
  
  	hdev = hci_dev_get(index);
  	if (!hdev)
  		return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
ca69b7957   Johan Hedberg   Bluetooth: Create...
1903
  						MGMT_STATUS_INVALID_PARAMS);
7fbec224c   Antti Julku   Bluetooth: Add bl...
1904

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

7fbec224c   Antti Julku   Bluetooth: Add bl...
1907
1908
1909
  	err = hci_blacklist_del(hdev, &cp->bdaddr);
  
  	if (err < 0)
ca69b7957   Johan Hedberg   Bluetooth: Create...
1910
1911
  		err = cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
  						MGMT_STATUS_INVALID_PARAMS);
7fbec224c   Antti Julku   Bluetooth: Add bl...
1912
1913
1914
  	else
  		err = cmd_complete(sk, index, MGMT_OP_UNBLOCK_DEVICE,
  								NULL, 0);
5e762444b   Antti Julku   Bluetooth: Add mg...
1915

09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1916
  	hci_dev_unlock(hdev);
7fbec224c   Antti Julku   Bluetooth: Add bl...
1917
1918
1919
1920
  	hci_dev_put(hdev);
  
  	return err;
  }
f6422ec62   Antti Julku   Bluetooth: Add mg...
1921
1922
1923
1924
  static int set_fast_connectable(struct sock *sk, u16 index,
  					unsigned char *data, u16 len)
  {
  	struct hci_dev *hdev;
f7c6869ce   Johan Hedberg   Bluetooth: Move m...
1925
  	struct mgmt_mode *cp = (void *) data;
f6422ec62   Antti Julku   Bluetooth: Add mg...
1926
1927
1928
1929
1930
1931
1932
1933
  	struct hci_cp_write_page_scan_activity acp;
  	u8 type;
  	int err;
  
  	BT_DBG("hci%u", index);
  
  	if (len != sizeof(*cp))
  		return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
ca69b7957   Johan Hedberg   Bluetooth: Create...
1934
  						MGMT_STATUS_INVALID_PARAMS);
f6422ec62   Antti Julku   Bluetooth: Add mg...
1935
1936
1937
1938
  
  	hdev = hci_dev_get(index);
  	if (!hdev)
  		return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
ca69b7957   Johan Hedberg   Bluetooth: Create...
1939
  						MGMT_STATUS_INVALID_PARAMS);
f6422ec62   Antti Julku   Bluetooth: Add mg...
1940
1941
  
  	hci_dev_lock(hdev);
f7c6869ce   Johan Hedberg   Bluetooth: Move m...
1942
  	if (cp->val) {
f6422ec62   Antti Julku   Bluetooth: Add mg...
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
  		type = PAGE_SCAN_TYPE_INTERLACED;
  		acp.interval = 0x0024;	/* 22.5 msec page scan interval */
  	} else {
  		type = PAGE_SCAN_TYPE_STANDARD;	/* default */
  		acp.interval = 0x0800;	/* default 1.28 sec page scan */
  	}
  
  	acp.window = 0x0012;	/* default 11.25 msec page scan window */
  
  	err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
  						sizeof(acp), &acp);
  	if (err < 0) {
  		err = cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
ca69b7957   Johan Hedberg   Bluetooth: Create...
1956
  							MGMT_STATUS_FAILED);
f6422ec62   Antti Julku   Bluetooth: Add mg...
1957
1958
1959
1960
1961
1962
  		goto done;
  	}
  
  	err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
  	if (err < 0) {
  		err = cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
ca69b7957   Johan Hedberg   Bluetooth: Create...
1963
  							MGMT_STATUS_FAILED);
f6422ec62   Antti Julku   Bluetooth: Add mg...
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
  		goto done;
  	}
  
  	err = cmd_complete(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
  							NULL, 0);
  done:
  	hci_dev_unlock(hdev);
  	hci_dev_put(hdev);
  
  	return err;
  }
0381101fd   Johan Hedberg   Bluetooth: Add in...
1975
1976
1977
1978
  int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
  {
  	unsigned char *buf;
  	struct mgmt_hdr *hdr;
4e51eae9c   Szymon Janc   Bluetooth: Move i...
1979
  	u16 opcode, index, len;
0381101fd   Johan Hedberg   Bluetooth: Add in...
1980
1981
1982
1983
1984
1985
  	int err;
  
  	BT_DBG("got %zu bytes", msglen);
  
  	if (msglen < sizeof(*hdr))
  		return -EINVAL;
e63a15ec0   Gustavo F. Padovan   Bluetooth: Use GF...
1986
  	buf = kmalloc(msglen, GFP_KERNEL);
0381101fd   Johan Hedberg   Bluetooth: Add in...
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
  	if (!buf)
  		return -ENOMEM;
  
  	if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
  		err = -EFAULT;
  		goto done;
  	}
  
  	hdr = (struct mgmt_hdr *) buf;
  	opcode = get_unaligned_le16(&hdr->opcode);
4e51eae9c   Szymon Janc   Bluetooth: Move i...
1997
  	index = get_unaligned_le16(&hdr->index);
0381101fd   Johan Hedberg   Bluetooth: Add in...
1998
1999
2000
2001
2002
2003
2004
2005
  	len = get_unaligned_le16(&hdr->len);
  
  	if (len != msglen - sizeof(*hdr)) {
  		err = -EINVAL;
  		goto done;
  	}
  
  	switch (opcode) {
02d981292   Johan Hedberg   Bluetooth: Add re...
2006
2007
2008
  	case MGMT_OP_READ_VERSION:
  		err = read_version(sk);
  		break;
faba42eb2   Johan Hedberg   Bluetooth: Add re...
2009
2010
2011
  	case MGMT_OP_READ_INDEX_LIST:
  		err = read_index_list(sk);
  		break;
f7b64e69c   Johan Hedberg   Bluetooth: Add re...
2012
  	case MGMT_OP_READ_INFO:
4e51eae9c   Szymon Janc   Bluetooth: Move i...
2013
  		err = read_controller_info(sk, index);
f7b64e69c   Johan Hedberg   Bluetooth: Add re...
2014
  		break;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
2015
  	case MGMT_OP_SET_POWERED:
4e51eae9c   Szymon Janc   Bluetooth: Move i...
2016
  		err = set_powered(sk, index, buf + sizeof(*hdr), len);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
2017
  		break;
73f22f623   Johan Hedberg   Bluetooth: Add su...
2018
  	case MGMT_OP_SET_DISCOVERABLE:
4e51eae9c   Szymon Janc   Bluetooth: Move i...
2019
  		err = set_discoverable(sk, index, buf + sizeof(*hdr), len);
73f22f623   Johan Hedberg   Bluetooth: Add su...
2020
  		break;
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
2021
  	case MGMT_OP_SET_CONNECTABLE:
4e51eae9c   Szymon Janc   Bluetooth: Move i...
2022
  		err = set_connectable(sk, index, buf + sizeof(*hdr), len);
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
2023
  		break;
f7c6869ce   Johan Hedberg   Bluetooth: Move m...
2024
2025
2026
2027
  	case MGMT_OP_SET_FAST_CONNECTABLE:
  		err = set_fast_connectable(sk, index, buf + sizeof(*hdr),
  								len);
  		break;
c542a06c2   Johan Hedberg   Bluetooth: Implem...
2028
  	case MGMT_OP_SET_PAIRABLE:
4e51eae9c   Szymon Janc   Bluetooth: Move i...
2029
  		err = set_pairable(sk, index, buf + sizeof(*hdr), len);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
2030
  		break;
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
2031
  	case MGMT_OP_ADD_UUID:
4e51eae9c   Szymon Janc   Bluetooth: Move i...
2032
  		err = add_uuid(sk, index, buf + sizeof(*hdr), len);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
2033
2034
  		break;
  	case MGMT_OP_REMOVE_UUID:
4e51eae9c   Szymon Janc   Bluetooth: Move i...
2035
  		err = remove_uuid(sk, index, buf + sizeof(*hdr), len);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
2036
  		break;
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
2037
  	case MGMT_OP_SET_DEV_CLASS:
4e51eae9c   Szymon Janc   Bluetooth: Move i...
2038
  		err = set_dev_class(sk, index, buf + sizeof(*hdr), len);
1aff6f094   Johan Hedberg   Bluetooth: Add cl...
2039
  		break;
86742e1ec   Johan Hedberg   Bluetooth: Update...
2040
2041
  	case MGMT_OP_LOAD_LINK_KEYS:
  		err = load_link_keys(sk, index, buf + sizeof(*hdr), len);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2042
  		break;
86742e1ec   Johan Hedberg   Bluetooth: Update...
2043
2044
  	case MGMT_OP_REMOVE_KEYS:
  		err = remove_keys(sk, index, buf + sizeof(*hdr), len);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2045
  		break;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2046
  	case MGMT_OP_DISCONNECT:
4e51eae9c   Szymon Janc   Bluetooth: Move i...
2047
  		err = disconnect(sk, index, buf + sizeof(*hdr), len);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2048
  		break;
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
2049
  	case MGMT_OP_GET_CONNECTIONS:
8ce6284ea   Szymon Janc   Bluetooth: Remove...
2050
  		err = get_connections(sk, index);
2784eb41b   Johan Hedberg   Bluetooth: Add ge...
2051
  		break;
980e1a537   Johan Hedberg   Bluetooth: Add su...
2052
  	case MGMT_OP_PIN_CODE_REPLY:
4e51eae9c   Szymon Janc   Bluetooth: Move i...
2053
  		err = pin_code_reply(sk, index, buf + sizeof(*hdr), len);
980e1a537   Johan Hedberg   Bluetooth: Add su...
2054
2055
  		break;
  	case MGMT_OP_PIN_CODE_NEG_REPLY:
4e51eae9c   Szymon Janc   Bluetooth: Move i...
2056
  		err = pin_code_neg_reply(sk, index, buf + sizeof(*hdr), len);
980e1a537   Johan Hedberg   Bluetooth: Add su...
2057
  		break;
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
2058
  	case MGMT_OP_SET_IO_CAPABILITY:
4e51eae9c   Szymon Janc   Bluetooth: Move i...
2059
  		err = set_io_capability(sk, index, buf + sizeof(*hdr), len);
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
2060
  		break;
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2061
  	case MGMT_OP_PAIR_DEVICE:
4e51eae9c   Szymon Janc   Bluetooth: Move i...
2062
  		err = pair_device(sk, index, buf + sizeof(*hdr), len);
e9a416b5c   Johan Hedberg   Bluetooth: Add mg...
2063
  		break;
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2064
  	case MGMT_OP_USER_CONFIRM_REPLY:
0df4c185e   Brian Gix   Bluetooth: User P...
2065
  		err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2066
2067
  		break;
  	case MGMT_OP_USER_CONFIRM_NEG_REPLY:
0df4c185e   Brian Gix   Bluetooth: User P...
2068
2069
  		err = user_confirm_neg_reply(sk, index, buf + sizeof(*hdr),
  									len);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2070
  		break;
604086b73   Brian Gix   Bluetooth: Add Us...
2071
2072
2073
2074
2075
2076
  	case MGMT_OP_USER_PASSKEY_REPLY:
  		err = user_passkey_reply(sk, index, buf + sizeof(*hdr), len);
  		break;
  	case MGMT_OP_USER_PASSKEY_NEG_REPLY:
  		err = user_passkey_neg_reply(sk, index, buf + sizeof(*hdr),
  									len);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2077
  		break;
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
2078
2079
2080
  	case MGMT_OP_SET_LOCAL_NAME:
  		err = set_local_name(sk, index, buf + sizeof(*hdr), len);
  		break;
c35938b2f   Szymon Janc   Bluetooth: Add re...
2081
2082
2083
  	case MGMT_OP_READ_LOCAL_OOB_DATA:
  		err = read_local_oob_data(sk, index);
  		break;
2763eda6c   Szymon Janc   Bluetooth: Add ad...
2084
2085
2086
2087
2088
2089
2090
  	case MGMT_OP_ADD_REMOTE_OOB_DATA:
  		err = add_remote_oob_data(sk, index, buf + sizeof(*hdr), len);
  		break;
  	case MGMT_OP_REMOVE_REMOTE_OOB_DATA:
  		err = remove_remote_oob_data(sk, index, buf + sizeof(*hdr),
  									len);
  		break;
14a536641   Johan Hedberg   Bluetooth: Add ba...
2091
  	case MGMT_OP_START_DISCOVERY:
450dfdafb   Johan Hedberg   Bluetooth: Pass a...
2092
  		err = start_discovery(sk, index, buf + sizeof(*hdr), len);
14a536641   Johan Hedberg   Bluetooth: Add ba...
2093
2094
2095
2096
  		break;
  	case MGMT_OP_STOP_DISCOVERY:
  		err = stop_discovery(sk, index);
  		break;
7fbec224c   Antti Julku   Bluetooth: Add bl...
2097
2098
2099
2100
2101
2102
  	case MGMT_OP_BLOCK_DEVICE:
  		err = block_device(sk, index, buf + sizeof(*hdr), len);
  		break;
  	case MGMT_OP_UNBLOCK_DEVICE:
  		err = unblock_device(sk, index, buf + sizeof(*hdr), len);
  		break;
0381101fd   Johan Hedberg   Bluetooth: Add in...
2103
2104
  	default:
  		BT_DBG("Unknown op %u", opcode);
ca69b7957   Johan Hedberg   Bluetooth: Create...
2105
2106
  		err = cmd_status(sk, index, opcode,
  						MGMT_STATUS_UNKNOWN_COMMAND);
0381101fd   Johan Hedberg   Bluetooth: Add in...
2107
2108
  		break;
  	}
e41d8b4e1   Johan Hedberg   Bluetooth: Add er...
2109
2110
  	if (err < 0)
  		goto done;
0381101fd   Johan Hedberg   Bluetooth: Add in...
2111
2112
2113
2114
2115
2116
  	err = msglen;
  
  done:
  	kfree(buf);
  	return err;
  }
c71e97bfa   Johan Hedberg   Bluetooth: Add ma...
2117

b24752fe6   Johan Hedberg   Bluetooth: Fix mg...
2118
2119
2120
2121
2122
2123
2124
  static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
  {
  	u8 *status = data;
  
  	cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
  	mgmt_pending_remove(cmd);
  }
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2125
  int mgmt_index_added(struct hci_dev *hdev)
c71e97bfa   Johan Hedberg   Bluetooth: Add ma...
2126
  {
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2127
  	return mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
c71e97bfa   Johan Hedberg   Bluetooth: Add ma...
2128
  }
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2129
  int mgmt_index_removed(struct hci_dev *hdev)
c71e97bfa   Johan Hedberg   Bluetooth: Add ma...
2130
  {
b24752fe6   Johan Hedberg   Bluetooth: Fix mg...
2131
  	u8 status = ENODEV;
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2132
  	mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
b24752fe6   Johan Hedberg   Bluetooth: Fix mg...
2133

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2134
  	return mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
2135
  }
73f22f623   Johan Hedberg   Bluetooth: Add su...
2136
  struct cmd_lookup {
72a734ec1   Johan Hedberg   Bluetooth: Unify ...
2137
  	u8 val;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
2138
  	struct sock *sk;
69ab39ea5   Johan Hedberg   Bluetooth: Update...
2139
  	struct hci_dev *hdev;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
2140
  };
69ab39ea5   Johan Hedberg   Bluetooth: Update...
2141
  static void settings_rsp(struct pending_cmd *cmd, void *data)
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
2142
  {
73f22f623   Johan Hedberg   Bluetooth: Add su...
2143
  	struct cmd_lookup *match = data;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
2144

69ab39ea5   Johan Hedberg   Bluetooth: Update...
2145
  	send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
2146
2147
2148
2149
2150
2151
2152
2153
2154
  
  	list_del(&cmd->list);
  
  	if (match->sk == NULL) {
  		match->sk = cmd->sk;
  		sock_hold(match->sk);
  	}
  
  	mgmt_pending_free(cmd);
c71e97bfa   Johan Hedberg   Bluetooth: Add ma...
2155
  }
5add6af8f   Johan Hedberg   Bluetooth: Add su...
2156

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2157
  int mgmt_powered(struct hci_dev *hdev, u8 powered)
5add6af8f   Johan Hedberg   Bluetooth: Add su...
2158
  {
69ab39ea5   Johan Hedberg   Bluetooth: Update...
2159
2160
  	struct cmd_lookup match = { powered, NULL, hdev };
  	__le32 ev;
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
2161
  	int ret;
5add6af8f   Johan Hedberg   Bluetooth: Add su...
2162

69ab39ea5   Johan Hedberg   Bluetooth: Update...
2163
  	mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5add6af8f   Johan Hedberg   Bluetooth: Add su...
2164

b24752fe6   Johan Hedberg   Bluetooth: Fix mg...
2165
2166
  	if (!powered) {
  		u8 status = ENETDOWN;
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2167
  		mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
b24752fe6   Johan Hedberg   Bluetooth: Fix mg...
2168
  	}
69ab39ea5   Johan Hedberg   Bluetooth: Update...
2169
  	ev = cpu_to_le32(get_current_settings(hdev));
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
2170

69ab39ea5   Johan Hedberg   Bluetooth: Update...
2171
2172
  	ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev),
  								match.sk);
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
2173
2174
2175
2176
2177
  
  	if (match.sk)
  		sock_put(match.sk);
  
  	return ret;
5add6af8f   Johan Hedberg   Bluetooth: Add su...
2178
  }
73f22f623   Johan Hedberg   Bluetooth: Add su...
2179

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2180
  int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
73f22f623   Johan Hedberg   Bluetooth: Add su...
2181
  {
69ab39ea5   Johan Hedberg   Bluetooth: Update...
2182
2183
  	struct cmd_lookup match = { discoverable, NULL, hdev };
  	__le32 ev;
73f22f623   Johan Hedberg   Bluetooth: Add su...
2184
  	int ret;
69ab39ea5   Johan Hedberg   Bluetooth: Update...
2185
  	mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, settings_rsp, &match);
72a734ec1   Johan Hedberg   Bluetooth: Unify ...
2186

69ab39ea5   Johan Hedberg   Bluetooth: Update...
2187
  	ev = cpu_to_le32(get_current_settings(hdev));
73f22f623   Johan Hedberg   Bluetooth: Add su...
2188

69ab39ea5   Johan Hedberg   Bluetooth: Update...
2189
  	ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev),
4e51eae9c   Szymon Janc   Bluetooth: Move i...
2190
  								match.sk);
73f22f623   Johan Hedberg   Bluetooth: Add su...
2191
2192
2193
2194
2195
  	if (match.sk)
  		sock_put(match.sk);
  
  	return ret;
  }
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
2196

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2197
  int mgmt_connectable(struct hci_dev *hdev, u8 connectable)
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
2198
  {
69ab39ea5   Johan Hedberg   Bluetooth: Update...
2199
2200
  	__le32 ev;
  	struct cmd_lookup match = { connectable, NULL, hdev };
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
2201
  	int ret;
69ab39ea5   Johan Hedberg   Bluetooth: Update...
2202
2203
  	mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, settings_rsp,
  								&match);
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
2204

69ab39ea5   Johan Hedberg   Bluetooth: Update...
2205
  	ev = cpu_to_le32(get_current_settings(hdev));
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
2206

69ab39ea5   Johan Hedberg   Bluetooth: Update...
2207
  	ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), match.sk);
9fbcbb455   Johan Hedberg   Bluetooth: Add se...
2208
2209
2210
2211
2212
2213
  
  	if (match.sk)
  		sock_put(match.sk);
  
  	return ret;
  }
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2214

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2215
  int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
2d7cee583   Johan Hedberg   Bluetooth: Fix mg...
2216
  {
ca69b7957   Johan Hedberg   Bluetooth: Create...
2217
  	u8 mgmt_err = mgmt_status(status);
2d7cee583   Johan Hedberg   Bluetooth: Fix mg...
2218
  	if (scan & SCAN_PAGE)
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2219
  		mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
ca69b7957   Johan Hedberg   Bluetooth: Create...
2220
  						cmd_status_rsp, &mgmt_err);
2d7cee583   Johan Hedberg   Bluetooth: Fix mg...
2221
2222
  
  	if (scan & SCAN_INQUIRY)
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2223
  		mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
ca69b7957   Johan Hedberg   Bluetooth: Create...
2224
  						cmd_status_rsp, &mgmt_err);
2d7cee583   Johan Hedberg   Bluetooth: Fix mg...
2225
2226
2227
  
  	return 0;
  }
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2228
2229
  int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
  								u8 persistent)
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2230
  {
86742e1ec   Johan Hedberg   Bluetooth: Update...
2231
  	struct mgmt_ev_new_link_key ev;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2232

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

a492cd52b   Vinicius Costa Gomes   Revert "Bluetooth...
2235
2236
2237
2238
2239
  	ev.store_hint = persistent;
  	bacpy(&ev.key.bdaddr, &key->bdaddr);
  	ev.key.type = key->type;
  	memcpy(ev.key.val, key->val, 16);
  	ev.key.pin_len = key->pin_len;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2240

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2241
  	return mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
2242
  }
f7520543a   Johan Hedberg   Bluetooth: Add co...
2243

48264f069   Johan Hedberg   Bluetooth: Add pu...
2244
2245
  int mgmt_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
  								u8 addr_type)
f7520543a   Johan Hedberg   Bluetooth: Add co...
2246
  {
4c659c397   Johan Hedberg   Bluetooth: Add ad...
2247
  	struct mgmt_addr_info ev;
f7520543a   Johan Hedberg   Bluetooth: Add co...
2248

f7520543a   Johan Hedberg   Bluetooth: Add co...
2249
  	bacpy(&ev.bdaddr, bdaddr);
48264f069   Johan Hedberg   Bluetooth: Add pu...
2250
  	ev.type = link_to_mgmt(link_type, addr_type);
f7520543a   Johan Hedberg   Bluetooth: Add co...
2251

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2252
  	return mgmt_event(MGMT_EV_CONNECTED, hdev, &ev, sizeof(ev), NULL);
f7520543a   Johan Hedberg   Bluetooth: Add co...
2253
  }
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2254
2255
  static void disconnect_rsp(struct pending_cmd *cmd, void *data)
  {
c68fb7ff2   Szymon Janc   Bluetooth: Rename...
2256
  	struct mgmt_cp_disconnect *cp = cmd->param;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2257
  	struct sock **sk = data;
a38528f11   Johan Hedberg   Bluetooth: Create...
2258
  	struct mgmt_rp_disconnect rp;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2259

a38528f11   Johan Hedberg   Bluetooth: Create...
2260
  	bacpy(&rp.bdaddr, &cp->bdaddr);
37d9ef76c   Johan Hedberg   Bluetooth: Add st...
2261
  	rp.status = 0;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2262

4e51eae9c   Szymon Janc   Bluetooth: Move i...
2263
  	cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, &rp, sizeof(rp));
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2264
2265
2266
  
  	*sk = cmd->sk;
  	sock_hold(*sk);
a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
2267
  	mgmt_pending_remove(cmd);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2268
  }
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
  static void remove_keys_rsp(struct pending_cmd *cmd, void *data)
  {
  	u8 *status = data;
  	struct mgmt_cp_remove_keys *cp = cmd->param;
  	struct mgmt_rp_remove_keys rp;
  
  	memset(&rp, 0, sizeof(rp));
  	bacpy(&rp.bdaddr, &cp->bdaddr);
  	if (status != NULL)
  		rp.status = *status;
  
  	cmd_complete(cmd->sk, cmd->index, MGMT_OP_REMOVE_KEYS, &rp,
  								sizeof(rp));
  
  	mgmt_pending_remove(cmd);
  }
48264f069   Johan Hedberg   Bluetooth: Add pu...
2285
2286
  int mgmt_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
  								u8 addr_type)
f7520543a   Johan Hedberg   Bluetooth: Add co...
2287
  {
4c659c397   Johan Hedberg   Bluetooth: Add ad...
2288
  	struct mgmt_addr_info ev;
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2289
2290
  	struct sock *sk = NULL;
  	int err;
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2291
  	mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
f7520543a   Johan Hedberg   Bluetooth: Add co...
2292

f7520543a   Johan Hedberg   Bluetooth: Add co...
2293
  	bacpy(&ev.bdaddr, bdaddr);
48264f069   Johan Hedberg   Bluetooth: Add pu...
2294
  	ev.type = link_to_mgmt(link_type, addr_type);
f7520543a   Johan Hedberg   Bluetooth: Add co...
2295

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2296
  	err = mgmt_event(MGMT_EV_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2297
2298
2299
  
  	if (sk)
  		sock_put(sk);
a8a1d19e9   Johan Hedberg   Bluetooth: Add pr...
2300
  	mgmt_pending_foreach(MGMT_OP_REMOVE_KEYS, hdev, remove_keys_rsp, NULL);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2301
2302
  	return err;
  }
37d9ef76c   Johan Hedberg   Bluetooth: Add st...
2303
  int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status)
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2304
2305
  {
  	struct pending_cmd *cmd;
ca69b7957   Johan Hedberg   Bluetooth: Create...
2306
  	u8 mgmt_err = mgmt_status(status);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2307
  	int err;
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
2308
  	cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2309
2310
  	if (!cmd)
  		return -ENOENT;
37d9ef76c   Johan Hedberg   Bluetooth: Add st...
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
  	if (bdaddr) {
  		struct mgmt_rp_disconnect rp;
  
  		bacpy(&rp.bdaddr, bdaddr);
  		rp.status = status;
  
  		err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
  							&rp, sizeof(rp));
  	} else
  		err = cmd_status(cmd->sk, hdev->id, MGMT_OP_DISCONNECT,
ca69b7957   Johan Hedberg   Bluetooth: Create...
2321
  								mgmt_err);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2322

a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
2323
  	mgmt_pending_remove(cmd);
8962ee74b   Johan Hedberg   Bluetooth: Add di...
2324
2325
  
  	return err;
f7520543a   Johan Hedberg   Bluetooth: Add co...
2326
  }
17d5c04cb   Johan Hedberg   Bluetooth: Add su...
2327

48264f069   Johan Hedberg   Bluetooth: Add pu...
2328
2329
  int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
  						u8 addr_type, u8 status)
17d5c04cb   Johan Hedberg   Bluetooth: Add su...
2330
2331
  {
  	struct mgmt_ev_connect_failed ev;
4c659c397   Johan Hedberg   Bluetooth: Add ad...
2332
  	bacpy(&ev.addr.bdaddr, bdaddr);
48264f069   Johan Hedberg   Bluetooth: Add pu...
2333
  	ev.addr.type = link_to_mgmt(link_type, addr_type);
ca69b7957   Johan Hedberg   Bluetooth: Create...
2334
  	ev.status = mgmt_status(status);
17d5c04cb   Johan Hedberg   Bluetooth: Add su...
2335

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2336
  	return mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
17d5c04cb   Johan Hedberg   Bluetooth: Add su...
2337
  }
980e1a537   Johan Hedberg   Bluetooth: Add su...
2338

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2339
  int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
980e1a537   Johan Hedberg   Bluetooth: Add su...
2340
2341
  {
  	struct mgmt_ev_pin_code_request ev;
980e1a537   Johan Hedberg   Bluetooth: Add su...
2342
  	bacpy(&ev.bdaddr, bdaddr);
a770bb5ae   Waldemar Rymarkiewicz   Bluetooth: Add se...
2343
  	ev.secure = secure;
980e1a537   Johan Hedberg   Bluetooth: Add su...
2344

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2345
  	return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev),
4e51eae9c   Szymon Janc   Bluetooth: Move i...
2346
  									NULL);
980e1a537   Johan Hedberg   Bluetooth: Add su...
2347
  }
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2348
2349
  int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
  								u8 status)
980e1a537   Johan Hedberg   Bluetooth: Add su...
2350
2351
  {
  	struct pending_cmd *cmd;
ac56fb13c   Johan Hedberg   Bluetooth: Fix mg...
2352
  	struct mgmt_rp_pin_code_reply rp;
980e1a537   Johan Hedberg   Bluetooth: Add su...
2353
  	int err;
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
2354
  	cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
980e1a537   Johan Hedberg   Bluetooth: Add su...
2355
2356
  	if (!cmd)
  		return -ENOENT;
ac56fb13c   Johan Hedberg   Bluetooth: Fix mg...
2357
  	bacpy(&rp.bdaddr, bdaddr);
ca69b7957   Johan Hedberg   Bluetooth: Create...
2358
  	rp.status = mgmt_status(status);
ac56fb13c   Johan Hedberg   Bluetooth: Fix mg...
2359

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2360
  	err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY, &rp,
4e51eae9c   Szymon Janc   Bluetooth: Move i...
2361
  								sizeof(rp));
980e1a537   Johan Hedberg   Bluetooth: Add su...
2362

a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
2363
  	mgmt_pending_remove(cmd);
980e1a537   Johan Hedberg   Bluetooth: Add su...
2364
2365
2366
  
  	return err;
  }
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2367
2368
  int mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
  								u8 status)
980e1a537   Johan Hedberg   Bluetooth: Add su...
2369
2370
  {
  	struct pending_cmd *cmd;
ac56fb13c   Johan Hedberg   Bluetooth: Fix mg...
2371
  	struct mgmt_rp_pin_code_reply rp;
980e1a537   Johan Hedberg   Bluetooth: Add su...
2372
  	int err;
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
2373
  	cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
980e1a537   Johan Hedberg   Bluetooth: Add su...
2374
2375
  	if (!cmd)
  		return -ENOENT;
ac56fb13c   Johan Hedberg   Bluetooth: Fix mg...
2376
  	bacpy(&rp.bdaddr, bdaddr);
ca69b7957   Johan Hedberg   Bluetooth: Create...
2377
  	rp.status = mgmt_status(status);
ac56fb13c   Johan Hedberg   Bluetooth: Fix mg...
2378

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2379
  	err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY, &rp,
4e51eae9c   Szymon Janc   Bluetooth: Move i...
2380
  								sizeof(rp));
980e1a537   Johan Hedberg   Bluetooth: Add su...
2381

a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
2382
  	mgmt_pending_remove(cmd);
980e1a537   Johan Hedberg   Bluetooth: Add su...
2383
2384
2385
  
  	return err;
  }
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2386

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2387
2388
  int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
  						__le32 value, u8 confirm_hint)
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2389
2390
  {
  	struct mgmt_ev_user_confirm_request ev;
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2391
  	BT_DBG("%s", hdev->name);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2392

a5c296832   Johan Hedberg   Bluetooth: Add ma...
2393
  	bacpy(&ev.bdaddr, bdaddr);
55bc1a378   Johan Hedberg   Bluetooth: Add co...
2394
  	ev.confirm_hint = confirm_hint;
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2395
  	put_unaligned_le32(value, &ev.value);
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2396
  	return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
4e51eae9c   Szymon Janc   Bluetooth: Move i...
2397
  									NULL);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2398
  }
604086b73   Brian Gix   Bluetooth: Add Us...
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
  int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr)
  {
  	struct mgmt_ev_user_passkey_request ev;
  
  	BT_DBG("%s", hdev->name);
  
  	bacpy(&ev.bdaddr, bdaddr);
  
  	return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
  									NULL);
  }
0df4c185e   Brian Gix   Bluetooth: User P...
2410
  static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2411
  							u8 status, u8 opcode)
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2412
2413
2414
2415
  {
  	struct pending_cmd *cmd;
  	struct mgmt_rp_user_confirm_reply rp;
  	int err;
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
2416
  	cmd = mgmt_pending_find(opcode, hdev);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2417
2418
  	if (!cmd)
  		return -ENOENT;
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2419
  	bacpy(&rp.bdaddr, bdaddr);
ca69b7957   Johan Hedberg   Bluetooth: Create...
2420
  	rp.status = mgmt_status(status);
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2421
  	err = cmd_complete(cmd->sk, hdev->id, opcode, &rp, sizeof(rp));
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2422

a664b5bc7   Johan Hedberg   Bluetooth: Fix un...
2423
  	mgmt_pending_remove(cmd);
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2424
2425
2426
  
  	return err;
  }
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2427
2428
  int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
  								u8 status)
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2429
  {
0df4c185e   Brian Gix   Bluetooth: User P...
2430
  	return user_pairing_resp_complete(hdev, bdaddr, status,
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2431
2432
  						MGMT_OP_USER_CONFIRM_REPLY);
  }
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2433
2434
  int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev,
  						bdaddr_t *bdaddr, u8 status)
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2435
  {
0df4c185e   Brian Gix   Bluetooth: User P...
2436
  	return user_pairing_resp_complete(hdev, bdaddr, status,
a5c296832   Johan Hedberg   Bluetooth: Add ma...
2437
2438
  					MGMT_OP_USER_CONFIRM_NEG_REPLY);
  }
2a6116920   Johan Hedberg   Bluetooth: Add mg...
2439

604086b73   Brian Gix   Bluetooth: Add Us...
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
  int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
  								u8 status)
  {
  	return user_pairing_resp_complete(hdev, bdaddr, status,
  						MGMT_OP_USER_PASSKEY_REPLY);
  }
  
  int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev,
  						bdaddr_t *bdaddr, u8 status)
  {
  	return user_pairing_resp_complete(hdev, bdaddr, status,
  					MGMT_OP_USER_PASSKEY_NEG_REPLY);
  }
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2453
  int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status)
2a6116920   Johan Hedberg   Bluetooth: Add mg...
2454
2455
  {
  	struct mgmt_ev_auth_failed ev;
2a6116920   Johan Hedberg   Bluetooth: Add mg...
2456
  	bacpy(&ev.bdaddr, bdaddr);
ca69b7957   Johan Hedberg   Bluetooth: Create...
2457
  	ev.status = mgmt_status(status);
2a6116920   Johan Hedberg   Bluetooth: Add mg...
2458

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2459
  	return mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
2a6116920   Johan Hedberg   Bluetooth: Add mg...
2460
  }
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
2461

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2462
  int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
2463
2464
2465
2466
2467
2468
2469
  {
  	struct pending_cmd *cmd;
  	struct mgmt_cp_set_local_name ev;
  	int err;
  
  	memset(&ev, 0, sizeof(ev));
  	memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
2470
  	cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
2471
2472
2473
2474
  	if (!cmd)
  		goto send_event;
  
  	if (status) {
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2475
  		err = cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
ca69b7957   Johan Hedberg   Bluetooth: Create...
2476
  							mgmt_status(status));
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
2477
2478
  		goto failed;
  	}
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2479
  	update_eir(hdev);
80a1e1dbf   Johan Hedberg   Bluetooth: Add lo...
2480

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2481
  	err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, &ev,
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
2482
2483
2484
2485
2486
  								sizeof(ev));
  	if (err < 0)
  		goto failed;
  
  send_event:
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2487
  	err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
b312b161e   Johan Hedberg   Bluetooth: mgmt: ...
2488
2489
2490
2491
2492
2493
2494
  							cmd ? cmd->sk : NULL);
  
  failed:
  	if (cmd)
  		mgmt_pending_remove(cmd);
  	return err;
  }
c35938b2f   Szymon Janc   Bluetooth: Add re...
2495

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2496
2497
  int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
  						u8 *randomizer, u8 status)
c35938b2f   Szymon Janc   Bluetooth: Add re...
2498
2499
2500
  {
  	struct pending_cmd *cmd;
  	int err;
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2501
  	BT_DBG("%s status %u", hdev->name, status);
c35938b2f   Szymon Janc   Bluetooth: Add re...
2502

2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
2503
  	cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
c35938b2f   Szymon Janc   Bluetooth: Add re...
2504
2505
2506
2507
  	if (!cmd)
  		return -ENOENT;
  
  	if (status) {
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2508
  		err = cmd_status(cmd->sk, hdev->id,
ca69b7957   Johan Hedberg   Bluetooth: Create...
2509
2510
  						MGMT_OP_READ_LOCAL_OOB_DATA,
  						mgmt_status(status));
c35938b2f   Szymon Janc   Bluetooth: Add re...
2511
2512
2513
2514
2515
  	} else {
  		struct mgmt_rp_read_local_oob_data rp;
  
  		memcpy(rp.hash, hash, sizeof(rp.hash));
  		memcpy(rp.randomizer, randomizer, sizeof(rp.randomizer));
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2516
2517
2518
  		err = cmd_complete(cmd->sk, hdev->id,
  						MGMT_OP_READ_LOCAL_OOB_DATA,
  						&rp, sizeof(rp));
c35938b2f   Szymon Janc   Bluetooth: Add re...
2519
2520
2521
2522
2523
2524
  	}
  
  	mgmt_pending_remove(cmd);
  
  	return err;
  }
e17acd40f   Johan Hedberg   Bluetooth: Add mg...
2525

48264f069   Johan Hedberg   Bluetooth: Add pu...
2526
2527
  int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
  				u8 addr_type, u8 *dev_class, s8 rssi, u8 *eir)
e17acd40f   Johan Hedberg   Bluetooth: Add mg...
2528
2529
2530
2531
  {
  	struct mgmt_ev_device_found ev;
  
  	memset(&ev, 0, sizeof(ev));
4c659c397   Johan Hedberg   Bluetooth: Add ad...
2532
  	bacpy(&ev.addr.bdaddr, bdaddr);
48264f069   Johan Hedberg   Bluetooth: Add pu...
2533
  	ev.addr.type = link_to_mgmt(link_type, addr_type);
e17acd40f   Johan Hedberg   Bluetooth: Add mg...
2534
2535
2536
2537
  	ev.rssi = rssi;
  
  	if (eir)
  		memcpy(ev.eir, eir, sizeof(ev.eir));
f8523598e   Andre Guedes   Bluetooth: Check ...
2538
2539
  	if (dev_class)
  		memcpy(ev.dev_class, dev_class, sizeof(ev.dev_class));
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2540
  	return mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, &ev, sizeof(ev), NULL);
e17acd40f   Johan Hedberg   Bluetooth: Add mg...
2541
  }
a88a9652d   Johan Hedberg   Bluetooth: Add mg...
2542

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2543
  int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *name)
a88a9652d   Johan Hedberg   Bluetooth: Add mg...
2544
2545
2546
2547
2548
2549
2550
  {
  	struct mgmt_ev_remote_name ev;
  
  	memset(&ev, 0, sizeof(ev));
  
  	bacpy(&ev.bdaddr, bdaddr);
  	memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2551
  	return mgmt_event(MGMT_EV_REMOTE_NAME, hdev, &ev, sizeof(ev), NULL);
a88a9652d   Johan Hedberg   Bluetooth: Add mg...
2552
  }
314b2381a   Johan Hedberg   Bluetooth: Add di...
2553

7a1351090   Andre Guedes   Bluetooth: Rename...
2554
  int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
164a6e789   Johan Hedberg   Bluetooth: Fix co...
2555
2556
2557
  {
  	struct pending_cmd *cmd;
  	int err;
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
2558
  	cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
164a6e789   Johan Hedberg   Bluetooth: Fix co...
2559
2560
  	if (!cmd)
  		return -ENOENT;
ca69b7957   Johan Hedberg   Bluetooth: Create...
2561
  	err = cmd_status(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status));
164a6e789   Johan Hedberg   Bluetooth: Fix co...
2562
2563
2564
2565
  	mgmt_pending_remove(cmd);
  
  	return err;
  }
e6d465cb4   Andre Guedes   Bluetooth: mgmt_s...
2566
2567
2568
2569
2570
2571
2572
2573
  int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
  {
  	struct pending_cmd *cmd;
  	int err;
  
  	cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
  	if (!cmd)
  		return -ENOENT;
e75a8b0c3   Andre Guedes   Bluetooth: Fix mg...
2574
  	err = cmd_status(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status));
164a6e789   Johan Hedberg   Bluetooth: Fix co...
2575
2576
2577
2578
  	mgmt_pending_remove(cmd);
  
  	return err;
  }
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2579
  int mgmt_discovering(struct hci_dev *hdev, u8 discovering)
314b2381a   Johan Hedberg   Bluetooth: Add di...
2580
  {
164a6e789   Johan Hedberg   Bluetooth: Fix co...
2581
2582
2583
  	struct pending_cmd *cmd;
  
  	if (discovering)
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
2584
  		cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
164a6e789   Johan Hedberg   Bluetooth: Fix co...
2585
  	else
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
2586
  		cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
164a6e789   Johan Hedberg   Bluetooth: Fix co...
2587
2588
  
  	if (cmd != NULL) {
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2589
  		cmd_complete(cmd->sk, hdev->id, cmd->opcode, NULL, 0);
164a6e789   Johan Hedberg   Bluetooth: Fix co...
2590
2591
  		mgmt_pending_remove(cmd);
  	}
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2592
  	return mgmt_event(MGMT_EV_DISCOVERING, hdev, &discovering,
314b2381a   Johan Hedberg   Bluetooth: Add di...
2593
2594
  						sizeof(discovering), NULL);
  }
5e762444b   Antti Julku   Bluetooth: Add mg...
2595

744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2596
  int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr)
5e762444b   Antti Julku   Bluetooth: Add mg...
2597
2598
2599
  {
  	struct pending_cmd *cmd;
  	struct mgmt_ev_device_blocked ev;
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
2600
  	cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev);
5e762444b   Antti Julku   Bluetooth: Add mg...
2601
2602
  
  	bacpy(&ev.bdaddr, bdaddr);
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2603
2604
  	return mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &ev, sizeof(ev),
  							cmd ? cmd->sk : NULL);
5e762444b   Antti Julku   Bluetooth: Add mg...
2605
  }
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2606
  int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr)
5e762444b   Antti Julku   Bluetooth: Add mg...
2607
2608
2609
  {
  	struct pending_cmd *cmd;
  	struct mgmt_ev_device_unblocked ev;
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
2610
  	cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev);
5e762444b   Antti Julku   Bluetooth: Add mg...
2611
2612
  
  	bacpy(&ev.bdaddr, bdaddr);
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
2613
2614
  	return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev),
  							cmd ? cmd->sk : NULL);
5e762444b   Antti Julku   Bluetooth: Add mg...
2615
  }