Blame view

net/bluetooth/hci_core.c 53.9 KB
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
     BlueZ - Bluetooth protocol stack for Linux
     Copyright (C) 2000-2001 Qualcomm Incorporated
590051de5   Gustavo F. Padovan   Bluetooth: Add Pr...
4
     Copyright (C) 2011 ProFUSION Embedded Systems
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
7
8
9
10
11
12
13
14
15
  
     Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
  
     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
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
16
17
18
     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
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
20
21
     ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
     COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
25
     SOFTWARE IS DISCLAIMED.
  */
  
  /* Bluetooth HCI core. */
82453021b   S.Çağlar Onur   [BLUETOOTH] net/b...
26
  #include <linux/jiffies.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
29
30
31
32
  #include <linux/module.h>
  #include <linux/kmod.h>
  
  #include <linux/types.h>
  #include <linux/errno.h>
  #include <linux/kernel.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
34
35
36
37
38
  #include <linux/sched.h>
  #include <linux/slab.h>
  #include <linux/poll.h>
  #include <linux/fcntl.h>
  #include <linux/init.h>
  #include <linux/skbuff.h>
f48fd9c8c   Marcel Holtmann   Bluetooth: Create...
39
  #include <linux/workqueue.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
  #include <linux/interrupt.h>
  #include <linux/notifier.h>
611b30f74   Marcel Holtmann   Bluetooth: Add na...
42
  #include <linux/rfkill.h>
6bd32326c   Ville Tervo   Bluetooth: Use pr...
43
  #include <linux/timer.h>
3a0259bb8   Vinicius Costa Gomes   Bluetooth: Add su...
44
  #include <linux/crypto.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
47
  #include <net/sock.h>
  
  #include <asm/system.h>
70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
48
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
51
52
  #include <asm/unaligned.h>
  
  #include <net/bluetooth/bluetooth.h>
  #include <net/bluetooth/hci_core.h>
ab81cbf99   Johan Hedberg   Bluetooth: Implem...
53
  #define AUTO_OFF_TIMEOUT 2000
7784d78f1   Andrei Emeltchenko   Bluetooth: making...
54
  int enable_hs;
b78752cc7   Marcel Holtmann   Bluetooth: Proces...
55
  static void hci_rx_work(struct work_struct *work);
c347b765f   Gustavo F. Padovan   Bluetooth: Move c...
56
  static void hci_cmd_work(struct work_struct *work);
3eff45eaf   Gustavo F. Padovan   Bluetooth: conver...
57
  static void hci_tx_work(struct work_struct *work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
61
62
63
64
65
  /* HCI device list */
  LIST_HEAD(hci_dev_list);
  DEFINE_RWLOCK(hci_dev_list_lock);
  
  /* HCI callback list */
  LIST_HEAD(hci_cb_list);
  DEFINE_RWLOCK(hci_cb_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
  /* HCI notifiers list */
e041c6834   Alan Stern   [PATCH] Notifier ...
67
  static ATOMIC_NOTIFIER_HEAD(hci_notifier);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
69
70
71
72
  
  /* ---- HCI notifications ---- */
  
  int hci_register_notifier(struct notifier_block *nb)
  {
e041c6834   Alan Stern   [PATCH] Notifier ...
73
  	return atomic_notifier_chain_register(&hci_notifier, nb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
76
77
  }
  
  int hci_unregister_notifier(struct notifier_block *nb)
  {
e041c6834   Alan Stern   [PATCH] Notifier ...
78
  	return atomic_notifier_chain_unregister(&hci_notifier, nb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
  }
6516455d3   Marcel Holtmann   [Bluetooth] Make ...
80
  static void hci_notify(struct hci_dev *hdev, int event)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
  {
e041c6834   Alan Stern   [PATCH] Notifier ...
82
  	atomic_notifier_call_chain(&hci_notifier, event, hdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
84
85
  }
  
  /* ---- HCI requests ---- */
23bb57633   Johan Hedberg   Bluetooth: Fix __...
86
  void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87
  {
23bb57633   Johan Hedberg   Bluetooth: Fix __...
88
  	BT_DBG("%s command 0x%04x result 0x%2.2x", hdev->name, cmd, result);
a5040efa2   Johan Hedberg   Bluetooth: Add sp...
89
90
91
92
  	/* If this is the init phase check if the completed command matches
  	 * the last init command, and if not just return.
  	 */
  	if (test_bit(HCI_INIT, &hdev->flags) && hdev->init_last_cmd != cmd)
23bb57633   Johan Hedberg   Bluetooth: Fix __...
93
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
  
  	if (hdev->req_status == HCI_REQ_PEND) {
  		hdev->req_result = result;
  		hdev->req_status = HCI_REQ_DONE;
  		wake_up_interruptible(&hdev->req_wait_q);
  	}
  }
  
  static void hci_req_cancel(struct hci_dev *hdev, int err)
  {
  	BT_DBG("%s err 0x%2.2x", hdev->name, err);
  
  	if (hdev->req_status == HCI_REQ_PEND) {
  		hdev->req_result = err;
  		hdev->req_status = HCI_REQ_CANCELED;
  		wake_up_interruptible(&hdev->req_wait_q);
  	}
  }
  
  /* Execute request and wait for completion. */
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
114
  static int __hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev *hdev, unsigned long opt),
01df8c31d   Szymon Janc   Bluetooth: Fix so...
115
  					unsigned long opt, __u32 timeout)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
  {
  	DECLARE_WAITQUEUE(wait, current);
  	int err = 0;
  
  	BT_DBG("%s start", hdev->name);
  
  	hdev->req_status = HCI_REQ_PEND;
  
  	add_wait_queue(&hdev->req_wait_q, &wait);
  	set_current_state(TASK_INTERRUPTIBLE);
  
  	req(hdev, opt);
  	schedule_timeout(timeout);
  
  	remove_wait_queue(&hdev->req_wait_q, &wait);
  
  	if (signal_pending(current))
  		return -EINTR;
  
  	switch (hdev->req_status) {
  	case HCI_REQ_DONE:
e175072f3   Joe Perches   Bluetooth: Rename...
137
  		err = -bt_to_errno(hdev->req_result);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
139
140
141
142
143
144
145
146
  		break;
  
  	case HCI_REQ_CANCELED:
  		err = -hdev->req_result;
  		break;
  
  	default:
  		err = -ETIMEDOUT;
  		break;
3ff50b799   Stephen Hemminger   [NET]: cleanup ex...
147
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148

a5040efa2   Johan Hedberg   Bluetooth: Add sp...
149
  	hdev->req_status = hdev->req_result = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
151
152
153
154
155
156
  
  	BT_DBG("%s end: err %d", hdev->name, err);
  
  	return err;
  }
  
  static inline int hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev *hdev, unsigned long opt),
01df8c31d   Szymon Janc   Bluetooth: Fix so...
157
  					unsigned long opt, __u32 timeout)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
  {
  	int ret;
7c6a329e4   Marcel Holtmann   [Bluetooth] Fix r...
160
161
  	if (!test_bit(HCI_UP, &hdev->flags))
  		return -ENETDOWN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
163
164
165
166
167
168
169
170
171
172
173
174
  	/* Serialize all requests */
  	hci_req_lock(hdev);
  	ret = __hci_request(hdev, req, opt, timeout);
  	hci_req_unlock(hdev);
  
  	return ret;
  }
  
  static void hci_reset_req(struct hci_dev *hdev, unsigned long opt)
  {
  	BT_DBG("%s %ld", hdev->name, opt);
  
  	/* Reset device */
f630cf0d5   Gustavo F. Padovan   Bluetooth: Fix HC...
175
  	set_bit(HCI_RESET, &hdev->flags);
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
176
  	hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
  }
e61ef4996   Andrei Emeltchenko   Bluetooth: Split ...
178
  static void bredr_init(struct hci_dev *hdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
  {
b0916ea0d   Johan Hedberg   Bluetooth: Add co...
180
  	struct hci_cp_delete_stored_link_key cp;
1ebb92521   Marcel Holtmann   [Bluetooth]: Add ...
181
  	__le16 param;
89f2783de   Marcel Holtmann   [Bluetooth] Fix p...
182
  	__u8 flt_type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183

2455a3ea0   Andrei Emeltchenko   Bluetooth: Initia...
184
  	hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
186
187
  	/* Mandatory initialization */
  
  	/* Reset */
f630cf0d5   Gustavo F. Padovan   Bluetooth: Fix HC...
188
  	if (!test_bit(HCI_QUIRK_NO_RESET, &hdev->quirks)) {
e61ef4996   Andrei Emeltchenko   Bluetooth: Split ...
189
190
  		set_bit(HCI_RESET, &hdev->flags);
  		hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL);
f630cf0d5   Gustavo F. Padovan   Bluetooth: Fix HC...
191
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
193
  
  	/* Read Local Supported Features */
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
194
  	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_FEATURES, 0, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195

1143e5a6d   Marcel Holtmann   [Bluetooth] Read ...
196
  	/* Read Local Version */
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
197
  	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL);
1143e5a6d   Marcel Holtmann   [Bluetooth] Read ...
198

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
  	/* Read Buffer Size (ACL mtu, max pkt, etc.) */
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
200
  	hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
  	/* Read BD Address */
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
203
204
205
206
207
208
209
  	hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
  
  	/* Read Class of Device */
  	hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
  
  	/* Read Local Name */
  	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
211
  
  	/* Read Voice Setting */
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
212
  	hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
214
215
216
  
  	/* Optional initialization */
  
  	/* Clear Event Filters */
89f2783de   Marcel Holtmann   [Bluetooth] Fix p...
217
  	flt_type = HCI_FLT_CLEAR_ALL;
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
218
  	hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
  	/* Connection accept timeout ~20 secs */
aca3192cc   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
221
  	param = cpu_to_le16(0x7d00);
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
222
  	hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
b0916ea0d   Johan Hedberg   Bluetooth: Add co...
223
224
225
226
  
  	bacpy(&cp.bdaddr, BDADDR_ANY);
  	cp.delete_all = 1;
  	hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
  }
e61ef4996   Andrei Emeltchenko   Bluetooth: Split ...
228
229
  static void amp_init(struct hci_dev *hdev)
  {
2455a3ea0   Andrei Emeltchenko   Bluetooth: Initia...
230
  	hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_BLOCK_BASED;
e61ef4996   Andrei Emeltchenko   Bluetooth: Split ...
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
  	/* Reset */
  	hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL);
  
  	/* Read Local Version */
  	hci_send_cmd(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL);
  }
  
  static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
  {
  	struct sk_buff *skb;
  
  	BT_DBG("%s %ld", hdev->name, opt);
  
  	/* Driver initialization */
  
  	/* Special commands */
  	while ((skb = skb_dequeue(&hdev->driver_init))) {
  		bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
  		skb->dev = (void *) hdev;
  
  		skb_queue_tail(&hdev->cmd_q, skb);
  		queue_work(hdev->workqueue, &hdev->cmd_work);
  	}
  	skb_queue_purge(&hdev->driver_init);
  
  	switch (hdev->dev_type) {
  	case HCI_BREDR:
  		bredr_init(hdev);
  		break;
  
  	case HCI_AMP:
  		amp_init(hdev);
  		break;
  
  	default:
  		BT_ERR("Unknown device type %d", hdev->dev_type);
  		break;
  	}
  
  }
6ed58ec52   Ville Tervo   Bluetooth: Use LE...
271
272
273
274
275
276
277
  static void hci_le_init_req(struct hci_dev *hdev, unsigned long opt)
  {
  	BT_DBG("%s", hdev->name);
  
  	/* Read LE buffer size */
  	hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278
279
280
281
282
283
284
  static void hci_scan_req(struct hci_dev *hdev, unsigned long opt)
  {
  	__u8 scan = opt;
  
  	BT_DBG("%s %x", hdev->name, scan);
  
  	/* Inquiry and Page scans */
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
285
  	hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286
287
288
289
290
291
292
293
294
  }
  
  static void hci_auth_req(struct hci_dev *hdev, unsigned long opt)
  {
  	__u8 auth = opt;
  
  	BT_DBG("%s %x", hdev->name, auth);
  
  	/* Authentication */
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
295
  	hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, 1, &auth);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
297
298
299
300
301
302
  }
  
  static void hci_encrypt_req(struct hci_dev *hdev, unsigned long opt)
  {
  	__u8 encrypt = opt;
  
  	BT_DBG("%s %x", hdev->name, encrypt);
e4e8e37c4   Marcel Holtmann   [Bluetooth] Make ...
303
  	/* Encryption */
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
304
  	hci_send_cmd(hdev, HCI_OP_WRITE_ENCRYPT_MODE, 1, &encrypt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
  }
e4e8e37c4   Marcel Holtmann   [Bluetooth] Make ...
306
307
308
  static void hci_linkpol_req(struct hci_dev *hdev, unsigned long opt)
  {
  	__le16 policy = cpu_to_le16(opt);
a418b893a   Marcel Holtmann   Bluetooth: Enable...
309
  	BT_DBG("%s %x", hdev->name, policy);
e4e8e37c4   Marcel Holtmann   [Bluetooth] Make ...
310
311
312
313
  
  	/* Default link policy */
  	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, 2, &policy);
  }
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
314
  /* Get HCI device by index.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
316
317
   * Device is held on return. */
  struct hci_dev *hci_dev_get(int index)
  {
8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
318
  	struct hci_dev *hdev = NULL, *d;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
319
320
321
322
323
324
325
  
  	BT_DBG("%d", index);
  
  	if (index < 0)
  		return NULL;
  
  	read_lock(&hci_dev_list_lock);
8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
326
  	list_for_each_entry(d, &hci_dev_list, list) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
328
329
330
331
332
333
334
  		if (d->id == index) {
  			hdev = hci_dev_hold(d);
  			break;
  		}
  	}
  	read_unlock(&hci_dev_list_lock);
  	return hdev;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
  
  /* ---- Inquiry support ---- */
  static void inquiry_cache_flush(struct hci_dev *hdev)
  {
  	struct inquiry_cache *cache = &hdev->inq_cache;
  	struct inquiry_entry *next  = cache->list, *e;
  
  	BT_DBG("cache %p", cache);
  
  	cache->list = NULL;
  	while ((e = next)) {
  		next = e->next;
  		kfree(e);
  	}
  }
  
  struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
  {
  	struct inquiry_cache *cache = &hdev->inq_cache;
  	struct inquiry_entry *e;
  
  	BT_DBG("cache %p, %s", cache, batostr(bdaddr));
  
  	for (e = cache->list; e; e = e->next)
  		if (!bacmp(&e->data.bdaddr, bdaddr))
  			break;
  	return e;
  }
  
  void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data)
  {
  	struct inquiry_cache *cache = &hdev->inq_cache;
70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
367
  	struct inquiry_entry *ie;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368
369
  
  	BT_DBG("cache %p, %s", cache, batostr(&data->bdaddr));
70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
370
371
  	ie = hci_inquiry_cache_lookup(hdev, &data->bdaddr);
  	if (!ie) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
372
  		/* Entry not in the cache. Add new one. */
70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
373
374
  		ie = kzalloc(sizeof(struct inquiry_entry), GFP_ATOMIC);
  		if (!ie)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
  			return;
70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
376
377
378
  
  		ie->next = cache->list;
  		cache->list = ie;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
  	}
70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
380
381
  	memcpy(&ie->data, data, sizeof(*data));
  	ie->timestamp = jiffies;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
  	cache->timestamp = jiffies;
  }
  
  static int inquiry_cache_dump(struct hci_dev *hdev, int num, __u8 *buf)
  {
  	struct inquiry_cache *cache = &hdev->inq_cache;
  	struct inquiry_info *info = (struct inquiry_info *) buf;
  	struct inquiry_entry *e;
  	int copied = 0;
  
  	for (e = cache->list; e && copied < num; e = e->next, copied++) {
  		struct inquiry_data *data = &e->data;
  		bacpy(&info->bdaddr, &data->bdaddr);
  		info->pscan_rep_mode	= data->pscan_rep_mode;
  		info->pscan_period_mode	= data->pscan_period_mode;
  		info->pscan_mode	= data->pscan_mode;
  		memcpy(info->dev_class, data->dev_class, 3);
  		info->clock_offset	= data->clock_offset;
  		info++;
  	}
  
  	BT_DBG("cache %p, copied %d", cache, copied);
  	return copied;
  }
  
  static void hci_inq_req(struct hci_dev *hdev, unsigned long opt)
  {
  	struct hci_inquiry_req *ir = (struct hci_inquiry_req *) opt;
  	struct hci_cp_inquiry cp;
  
  	BT_DBG("%s", hdev->name);
  
  	if (test_bit(HCI_INQUIRY, &hdev->flags))
  		return;
  
  	/* Start Inquiry */
  	memcpy(&cp.lap, &ir->lap, 3);
  	cp.length  = ir->length;
  	cp.num_rsp = ir->num_rsp;
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
421
  	hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
423
424
425
426
427
428
429
430
431
432
433
434
  }
  
  int hci_inquiry(void __user *arg)
  {
  	__u8 __user *ptr = arg;
  	struct hci_inquiry_req ir;
  	struct hci_dev *hdev;
  	int err = 0, do_inquiry = 0, max_rsp;
  	long timeo;
  	__u8 *buf;
  
  	if (copy_from_user(&ir, ptr, sizeof(ir)))
  		return -EFAULT;
5a08ecced   Andrei Emeltchenko   Bluetooth: Do not...
435
436
  	hdev = hci_dev_get(ir.dev_id);
  	if (!hdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
  		return -ENODEV;
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
438
  	hci_dev_lock(hdev);
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
439
  	if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX ||
70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
440
441
  				inquiry_cache_empty(hdev) ||
  				ir.flags & IREQ_CACHE_FLUSH) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
442
443
444
  		inquiry_cache_flush(hdev);
  		do_inquiry = 1;
  	}
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
445
  	hci_dev_unlock(hdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446

04837f644   Marcel Holtmann   [Bluetooth] Add a...
447
  	timeo = ir.length * msecs_to_jiffies(2000);
70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
448
449
450
451
452
453
  
  	if (do_inquiry) {
  		err = hci_request(hdev, hci_inq_req, (unsigned long)&ir, timeo);
  		if (err < 0)
  			goto done;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
454
455
456
457
458
459
460
  
  	/* for unlimited number of responses we will use buffer with 255 entries */
  	max_rsp = (ir.num_rsp == 0) ? 255 : ir.num_rsp;
  
  	/* cache_dump can't sleep. Therefore we allocate temp buffer and then
  	 * copy it to the user space.
  	 */
01df8c31d   Szymon Janc   Bluetooth: Fix so...
461
  	buf = kmalloc(sizeof(struct inquiry_info) * max_rsp, GFP_KERNEL);
70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
462
  	if (!buf) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
464
465
  		err = -ENOMEM;
  		goto done;
  	}
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
466
  	hci_dev_lock(hdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
467
  	ir.num_rsp = inquiry_cache_dump(hdev, max_rsp, buf);
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
468
  	hci_dev_unlock(hdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
470
471
472
473
474
475
476
  
  	BT_DBG("num_rsp %d", ir.num_rsp);
  
  	if (!copy_to_user(ptr, &ir, sizeof(ir))) {
  		ptr += sizeof(ir);
  		if (copy_to_user(ptr, buf, sizeof(struct inquiry_info) *
  					ir.num_rsp))
  			err = -EFAULT;
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
477
  	} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
  		err = -EFAULT;
  
  	kfree(buf);
  
  done:
  	hci_dev_put(hdev);
  	return err;
  }
  
  /* ---- HCI ioctl helpers ---- */
  
  int hci_dev_open(__u16 dev)
  {
  	struct hci_dev *hdev;
  	int ret = 0;
5a08ecced   Andrei Emeltchenko   Bluetooth: Do not...
493
494
  	hdev = hci_dev_get(dev);
  	if (!hdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495
496
497
498
499
  		return -ENODEV;
  
  	BT_DBG("%s %p", hdev->name, hdev);
  
  	hci_req_lock(hdev);
611b30f74   Marcel Holtmann   Bluetooth: Add na...
500
501
502
503
  	if (hdev->rfkill && rfkill_blocked(hdev->rfkill)) {
  		ret = -ERFKILL;
  		goto done;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
504
505
506
507
508
509
510
  	if (test_bit(HCI_UP, &hdev->flags)) {
  		ret = -EALREADY;
  		goto done;
  	}
  
  	if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
  		set_bit(HCI_RAW, &hdev->flags);
07e3b94ac   Andrei Emeltchenko   Bluetooth: Do not...
511
512
513
  	/* Treat all non BR/EDR controllers as raw devices if
  	   enable_hs is not set */
  	if (hdev->dev_type != HCI_BREDR && !enable_hs)
943da25d9   Marcel Holtmann   Bluetooth: Add co...
514
  		set_bit(HCI_RAW, &hdev->flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
516
517
518
519
520
521
522
  	if (hdev->open(hdev)) {
  		ret = -EIO;
  		goto done;
  	}
  
  	if (!test_bit(HCI_RAW, &hdev->flags)) {
  		atomic_set(&hdev->cmd_cnt, 1);
  		set_bit(HCI_INIT, &hdev->flags);
a5040efa2   Johan Hedberg   Bluetooth: Add sp...
523
  		hdev->init_last_cmd = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
524

04837f644   Marcel Holtmann   [Bluetooth] Add a...
525
526
  		ret = __hci_request(hdev, hci_init_req, 0,
  					msecs_to_jiffies(HCI_INIT_TIMEOUT));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527

eead27da6   Andre Guedes   Bluetooth: Add lm...
528
  		if (lmp_host_le_capable(hdev))
6ed58ec52   Ville Tervo   Bluetooth: Use LE...
529
530
  			ret = __hci_request(hdev, hci_le_init_req, 0,
  					msecs_to_jiffies(HCI_INIT_TIMEOUT));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531
532
533
534
535
536
537
  		clear_bit(HCI_INIT, &hdev->flags);
  	}
  
  	if (!ret) {
  		hci_dev_hold(hdev);
  		set_bit(HCI_UP, &hdev->flags);
  		hci_notify(hdev, HCI_DEV_UP);
56e5cb86e   Johan Hedberg   Bluetooth: Add mi...
538
  		if (!test_bit(HCI_SETUP, &hdev->flags)) {
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
539
  			hci_dev_lock(hdev);
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
540
  			mgmt_powered(hdev, 1);
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
541
  			hci_dev_unlock(hdev);
56e5cb86e   Johan Hedberg   Bluetooth: Add mi...
542
  		}
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
543
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
544
  		/* Init failed, cleanup */
3eff45eaf   Gustavo F. Padovan   Bluetooth: conver...
545
  		flush_work(&hdev->tx_work);
c347b765f   Gustavo F. Padovan   Bluetooth: Move c...
546
  		flush_work(&hdev->cmd_work);
b78752cc7   Marcel Holtmann   Bluetooth: Proces...
547
  		flush_work(&hdev->rx_work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
  
  		skb_queue_purge(&hdev->cmd_q);
  		skb_queue_purge(&hdev->rx_q);
  
  		if (hdev->flush)
  			hdev->flush(hdev);
  
  		if (hdev->sent_cmd) {
  			kfree_skb(hdev->sent_cmd);
  			hdev->sent_cmd = NULL;
  		}
  
  		hdev->close(hdev);
  		hdev->flags = 0;
  	}
  
  done:
  	hci_req_unlock(hdev);
  	hci_dev_put(hdev);
  	return ret;
  }
  
  static int hci_dev_do_close(struct hci_dev *hdev)
  {
  	BT_DBG("%s %p", hdev->name, hdev);
  
  	hci_req_cancel(hdev, ENODEV);
  	hci_req_lock(hdev);
  
  	if (!test_and_clear_bit(HCI_UP, &hdev->flags)) {
b79f44c16   Vinicius Costa Gomes   Bluetooth: Fix ke...
578
  		del_timer_sync(&hdev->cmd_timer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
579
580
581
  		hci_req_unlock(hdev);
  		return 0;
  	}
3eff45eaf   Gustavo F. Padovan   Bluetooth: conver...
582
583
  	/* Flush RX and TX works */
  	flush_work(&hdev->tx_work);
b78752cc7   Marcel Holtmann   Bluetooth: Proces...
584
  	flush_work(&hdev->rx_work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
585

16ab91ab4   Johan Hedberg   Bluetooth: Add ti...
586
  	if (hdev->discov_timeout > 0) {
e0f9309f3   Johan Hedberg   Bluetooth: Fix ca...
587
  		cancel_delayed_work(&hdev->discov_off);
16ab91ab4   Johan Hedberg   Bluetooth: Add ti...
588
589
  		hdev->discov_timeout = 0;
  	}
3243553fd   Johan Hedberg   Bluetooth: Conver...
590
  	if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->flags))
e0f9309f3   Johan Hedberg   Bluetooth: Fix ca...
591
  		cancel_delayed_work(&hdev->power_off);
3243553fd   Johan Hedberg   Bluetooth: Conver...
592

7d78525dc   Johan Hedberg   Bluetooth: Add ti...
593
594
  	if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->flags))
  		cancel_delayed_work(&hdev->service_cache);
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
595
  	hci_dev_lock(hdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
596
597
  	inquiry_cache_flush(hdev);
  	hci_conn_hash_flush(hdev);
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
598
  	hci_dev_unlock(hdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
599
600
601
602
603
604
605
606
607
608
609
  
  	hci_notify(hdev, HCI_DEV_DOWN);
  
  	if (hdev->flush)
  		hdev->flush(hdev);
  
  	/* Reset device */
  	skb_queue_purge(&hdev->cmd_q);
  	atomic_set(&hdev->cmd_cnt, 1);
  	if (!test_bit(HCI_RAW, &hdev->flags)) {
  		set_bit(HCI_INIT, &hdev->flags);
04837f644   Marcel Holtmann   [Bluetooth] Add a...
610
  		__hci_request(hdev, hci_reset_req, 0,
cad44c2bf   Gustavo F. Padovan   Revert "Bluetooth...
611
  					msecs_to_jiffies(250));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612
613
  		clear_bit(HCI_INIT, &hdev->flags);
  	}
c347b765f   Gustavo F. Padovan   Bluetooth: Move c...
614
615
  	/* flush cmd  work */
  	flush_work(&hdev->cmd_work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
616
617
618
619
620
621
622
623
  
  	/* Drop queues */
  	skb_queue_purge(&hdev->rx_q);
  	skb_queue_purge(&hdev->cmd_q);
  	skb_queue_purge(&hdev->raw_q);
  
  	/* Drop last sent command */
  	if (hdev->sent_cmd) {
b79f44c16   Vinicius Costa Gomes   Bluetooth: Fix ke...
624
  		del_timer_sync(&hdev->cmd_timer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625
626
627
628
629
630
631
  		kfree_skb(hdev->sent_cmd);
  		hdev->sent_cmd = NULL;
  	}
  
  	/* After this point our queues are empty
  	 * and no tasks are scheduled. */
  	hdev->close(hdev);
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
632
  	hci_dev_lock(hdev);
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
633
  	mgmt_powered(hdev, 0);
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
634
  	hci_dev_unlock(hdev);
5add6af8f   Johan Hedberg   Bluetooth: Add su...
635

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
636
637
638
639
640
641
642
643
644
645
646
647
648
  	/* Clear flags */
  	hdev->flags = 0;
  
  	hci_req_unlock(hdev);
  
  	hci_dev_put(hdev);
  	return 0;
  }
  
  int hci_dev_close(__u16 dev)
  {
  	struct hci_dev *hdev;
  	int err;
70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
649
650
  	hdev = hci_dev_get(dev);
  	if (!hdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
651
652
653
654
655
656
657
658
659
660
  		return -ENODEV;
  	err = hci_dev_do_close(hdev);
  	hci_dev_put(hdev);
  	return err;
  }
  
  int hci_dev_reset(__u16 dev)
  {
  	struct hci_dev *hdev;
  	int ret = 0;
70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
661
662
  	hdev = hci_dev_get(dev);
  	if (!hdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
663
664
665
  		return -ENODEV;
  
  	hci_req_lock(hdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
667
668
669
670
671
672
  
  	if (!test_bit(HCI_UP, &hdev->flags))
  		goto done;
  
  	/* Drop queues */
  	skb_queue_purge(&hdev->rx_q);
  	skb_queue_purge(&hdev->cmd_q);
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
673
  	hci_dev_lock(hdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
674
675
  	inquiry_cache_flush(hdev);
  	hci_conn_hash_flush(hdev);
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
676
  	hci_dev_unlock(hdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
677
678
679
  
  	if (hdev->flush)
  		hdev->flush(hdev);
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
680
  	atomic_set(&hdev->cmd_cnt, 1);
6ed58ec52   Ville Tervo   Bluetooth: Use LE...
681
  	hdev->acl_cnt = 0; hdev->sco_cnt = 0; hdev->le_cnt = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
682
683
  
  	if (!test_bit(HCI_RAW, &hdev->flags))
04837f644   Marcel Holtmann   [Bluetooth] Add a...
684
685
  		ret = __hci_request(hdev, hci_reset_req, 0,
  					msecs_to_jiffies(HCI_INIT_TIMEOUT));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
687
  
  done:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
688
689
690
691
692
693
694
695
696
  	hci_req_unlock(hdev);
  	hci_dev_put(hdev);
  	return ret;
  }
  
  int hci_dev_reset_stat(__u16 dev)
  {
  	struct hci_dev *hdev;
  	int ret = 0;
70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
697
698
  	hdev = hci_dev_get(dev);
  	if (!hdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
  		return -ENODEV;
  
  	memset(&hdev->stat, 0, sizeof(struct hci_dev_stats));
  
  	hci_dev_put(hdev);
  
  	return ret;
  }
  
  int hci_dev_cmd(unsigned int cmd, void __user *arg)
  {
  	struct hci_dev *hdev;
  	struct hci_dev_req dr;
  	int err = 0;
  
  	if (copy_from_user(&dr, arg, sizeof(dr)))
  		return -EFAULT;
70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
716
717
  	hdev = hci_dev_get(dr.dev_id);
  	if (!hdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
718
719
720
721
  		return -ENODEV;
  
  	switch (cmd) {
  	case HCISETAUTH:
04837f644   Marcel Holtmann   [Bluetooth] Add a...
722
723
  		err = hci_request(hdev, hci_auth_req, dr.dev_opt,
  					msecs_to_jiffies(HCI_INIT_TIMEOUT));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
724
725
726
727
728
729
730
731
732
733
  		break;
  
  	case HCISETENCRYPT:
  		if (!lmp_encrypt_capable(hdev)) {
  			err = -EOPNOTSUPP;
  			break;
  		}
  
  		if (!test_bit(HCI_AUTH, &hdev->flags)) {
  			/* Auth must be enabled first */
04837f644   Marcel Holtmann   [Bluetooth] Add a...
734
735
  			err = hci_request(hdev, hci_auth_req, dr.dev_opt,
  					msecs_to_jiffies(HCI_INIT_TIMEOUT));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
736
737
738
  			if (err)
  				break;
  		}
04837f644   Marcel Holtmann   [Bluetooth] Add a...
739
740
  		err = hci_request(hdev, hci_encrypt_req, dr.dev_opt,
  					msecs_to_jiffies(HCI_INIT_TIMEOUT));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741
742
743
  		break;
  
  	case HCISETSCAN:
04837f644   Marcel Holtmann   [Bluetooth] Add a...
744
745
  		err = hci_request(hdev, hci_scan_req, dr.dev_opt,
  					msecs_to_jiffies(HCI_INIT_TIMEOUT));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
747
  	case HCISETLINKPOL:
e4e8e37c4   Marcel Holtmann   [Bluetooth] Make ...
748
749
  		err = hci_request(hdev, hci_linkpol_req, dr.dev_opt,
  					msecs_to_jiffies(HCI_INIT_TIMEOUT));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
750
751
752
  		break;
  
  	case HCISETLINKMODE:
e4e8e37c4   Marcel Holtmann   [Bluetooth] Make ...
753
754
755
756
757
758
  		hdev->link_mode = ((__u16) dr.dev_opt) &
  					(HCI_LM_MASTER | HCI_LM_ACCEPT);
  		break;
  
  	case HCISETPTYPE:
  		hdev->pkt_type = (__u16) dr.dev_opt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
759
760
761
  		break;
  
  	case HCISETACLMTU:
e4e8e37c4   Marcel Holtmann   [Bluetooth] Make ...
762
763
  		hdev->acl_mtu  = *((__u16 *) &dr.dev_opt + 1);
  		hdev->acl_pkts = *((__u16 *) &dr.dev_opt + 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
765
766
  		break;
  
  	case HCISETSCOMTU:
e4e8e37c4   Marcel Holtmann   [Bluetooth] Make ...
767
768
  		hdev->sco_mtu  = *((__u16 *) &dr.dev_opt + 1);
  		hdev->sco_pkts = *((__u16 *) &dr.dev_opt + 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
769
770
771
772
773
774
  		break;
  
  	default:
  		err = -EINVAL;
  		break;
  	}
e4e8e37c4   Marcel Holtmann   [Bluetooth] Make ...
775

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
776
777
778
779
780
781
  	hci_dev_put(hdev);
  	return err;
  }
  
  int hci_get_dev_list(void __user *arg)
  {
8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
782
  	struct hci_dev *hdev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
783
784
  	struct hci_dev_list_req *dl;
  	struct hci_dev_req *dr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
785
786
787
788
789
790
791
792
793
794
  	int n = 0, size, err;
  	__u16 dev_num;
  
  	if (get_user(dev_num, (__u16 __user *) arg))
  		return -EFAULT;
  
  	if (!dev_num || dev_num > (PAGE_SIZE * 2) / sizeof(*dr))
  		return -EINVAL;
  
  	size = sizeof(*dl) + dev_num * sizeof(*dr);
70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
795
796
  	dl = kzalloc(size, GFP_KERNEL);
  	if (!dl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
797
798
799
  		return -ENOMEM;
  
  	dr = dl->dev_req;
f20d09d5f   Gustavo F. Padovan   Bluetooth: remove...
800
  	read_lock(&hci_dev_list_lock);
8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
801
  	list_for_each_entry(hdev, &hci_dev_list, list) {
3243553fd   Johan Hedberg   Bluetooth: Conver...
802
  		if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->flags))
e0f9309f3   Johan Hedberg   Bluetooth: Fix ca...
803
  			cancel_delayed_work(&hdev->power_off);
c542a06c2   Johan Hedberg   Bluetooth: Implem...
804
805
806
  
  		if (!test_bit(HCI_MGMT, &hdev->flags))
  			set_bit(HCI_PAIRABLE, &hdev->flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807
808
  		(dr + n)->dev_id  = hdev->id;
  		(dr + n)->dev_opt = hdev->flags;
c542a06c2   Johan Hedberg   Bluetooth: Implem...
809

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
810
811
812
  		if (++n >= dev_num)
  			break;
  	}
f20d09d5f   Gustavo F. Padovan   Bluetooth: remove...
813
  	read_unlock(&hci_dev_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
  
  	dl->dev_num = n;
  	size = sizeof(*dl) + n * sizeof(*dr);
  
  	err = copy_to_user(arg, dl, size);
  	kfree(dl);
  
  	return err ? -EFAULT : 0;
  }
  
  int hci_get_dev_info(void __user *arg)
  {
  	struct hci_dev *hdev;
  	struct hci_dev_info di;
  	int err = 0;
  
  	if (copy_from_user(&di, arg, sizeof(di)))
  		return -EFAULT;
70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
832
833
  	hdev = hci_dev_get(di.dev_id);
  	if (!hdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
834
  		return -ENODEV;
3243553fd   Johan Hedberg   Bluetooth: Conver...
835
836
  	if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->flags))
  		cancel_delayed_work_sync(&hdev->power_off);
ab81cbf99   Johan Hedberg   Bluetooth: Implem...
837

c542a06c2   Johan Hedberg   Bluetooth: Implem...
838
839
  	if (!test_bit(HCI_MGMT, &hdev->flags))
  		set_bit(HCI_PAIRABLE, &hdev->flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
840
841
  	strcpy(di.name, hdev->name);
  	di.bdaddr   = hdev->bdaddr;
943da25d9   Marcel Holtmann   Bluetooth: Add co...
842
  	di.type     = (hdev->bus & 0x0f) | (hdev->dev_type << 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
  	di.flags    = hdev->flags;
  	di.pkt_type = hdev->pkt_type;
  	di.acl_mtu  = hdev->acl_mtu;
  	di.acl_pkts = hdev->acl_pkts;
  	di.sco_mtu  = hdev->sco_mtu;
  	di.sco_pkts = hdev->sco_pkts;
  	di.link_policy = hdev->link_policy;
  	di.link_mode   = hdev->link_mode;
  
  	memcpy(&di.stat, &hdev->stat, sizeof(di.stat));
  	memcpy(&di.features, &hdev->features, sizeof(di.features));
  
  	if (copy_to_user(arg, &di, sizeof(di)))
  		err = -EFAULT;
  
  	hci_dev_put(hdev);
  
  	return err;
  }
  
  /* ---- Interface to HCI drivers ---- */
611b30f74   Marcel Holtmann   Bluetooth: Add na...
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
  static int hci_rfkill_set_block(void *data, bool blocked)
  {
  	struct hci_dev *hdev = data;
  
  	BT_DBG("%p name %s blocked %d", hdev, hdev->name, blocked);
  
  	if (!blocked)
  		return 0;
  
  	hci_dev_do_close(hdev);
  
  	return 0;
  }
  
  static const struct rfkill_ops hci_rfkill_ops = {
  	.set_block = hci_rfkill_set_block,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
881
882
883
884
  /* Alloc HCI device */
  struct hci_dev *hci_alloc_dev(void)
  {
  	struct hci_dev *hdev;
25ea6db04   Marcel Holtmann   [Bluetooth] Remai...
885
  	hdev = kzalloc(sizeof(struct hci_dev), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
886
887
  	if (!hdev)
  		return NULL;
0ac7e7002   David Herrmann   Bluetooth: Fix hc...
888
  	hci_init_sysfs(hdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
889
890
891
892
893
894
895
896
897
898
  	skb_queue_head_init(&hdev->driver_init);
  
  	return hdev;
  }
  EXPORT_SYMBOL(hci_alloc_dev);
  
  /* Free HCI device */
  void hci_free_dev(struct hci_dev *hdev)
  {
  	skb_queue_purge(&hdev->driver_init);
a91f2e396   Marcel Holtmann   [Bluetooth] Use r...
899
900
  	/* will free via device release */
  	put_device(&hdev->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
901
902
  }
  EXPORT_SYMBOL(hci_free_dev);
ab81cbf99   Johan Hedberg   Bluetooth: Implem...
903
904
905
906
907
908
909
910
911
912
  static void hci_power_on(struct work_struct *work)
  {
  	struct hci_dev *hdev = container_of(work, struct hci_dev, power_on);
  
  	BT_DBG("%s", hdev->name);
  
  	if (hci_dev_open(hdev->id) < 0)
  		return;
  
  	if (test_bit(HCI_AUTO_OFF, &hdev->flags))
80b7ab334   Gustavo F. Padovan   Bluetooth: move p...
913
  		schedule_delayed_work(&hdev->power_off,
3243553fd   Johan Hedberg   Bluetooth: Conver...
914
  					msecs_to_jiffies(AUTO_OFF_TIMEOUT));
ab81cbf99   Johan Hedberg   Bluetooth: Implem...
915
916
  
  	if (test_and_clear_bit(HCI_SETUP, &hdev->flags))
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
917
  		mgmt_index_added(hdev);
ab81cbf99   Johan Hedberg   Bluetooth: Implem...
918
919
920
921
  }
  
  static void hci_power_off(struct work_struct *work)
  {
3243553fd   Johan Hedberg   Bluetooth: Conver...
922
923
  	struct hci_dev *hdev = container_of(work, struct hci_dev,
  							power_off.work);
ab81cbf99   Johan Hedberg   Bluetooth: Implem...
924
925
926
927
  
  	BT_DBG("%s", hdev->name);
  
  	clear_bit(HCI_AUTO_OFF, &hdev->flags);
3243553fd   Johan Hedberg   Bluetooth: Conver...
928
  	hci_dev_close(hdev->id);
ab81cbf99   Johan Hedberg   Bluetooth: Implem...
929
  }
16ab91ab4   Johan Hedberg   Bluetooth: Add ti...
930
931
932
933
934
935
936
937
  static void hci_discov_off(struct work_struct *work)
  {
  	struct hci_dev *hdev;
  	u8 scan = SCAN_PAGE;
  
  	hdev = container_of(work, struct hci_dev, discov_off.work);
  
  	BT_DBG("%s", hdev->name);
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
938
  	hci_dev_lock(hdev);
16ab91ab4   Johan Hedberg   Bluetooth: Add ti...
939
940
941
942
  
  	hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
  
  	hdev->discov_timeout = 0;
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
943
  	hci_dev_unlock(hdev);
16ab91ab4   Johan Hedberg   Bluetooth: Add ti...
944
  }
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
  int hci_uuids_clear(struct hci_dev *hdev)
  {
  	struct list_head *p, *n;
  
  	list_for_each_safe(p, n, &hdev->uuids) {
  		struct bt_uuid *uuid;
  
  		uuid = list_entry(p, struct bt_uuid, list);
  
  		list_del(p);
  		kfree(uuid);
  	}
  
  	return 0;
  }
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
  int hci_link_keys_clear(struct hci_dev *hdev)
  {
  	struct list_head *p, *n;
  
  	list_for_each_safe(p, n, &hdev->link_keys) {
  		struct link_key *key;
  
  		key = list_entry(p, struct link_key, list);
  
  		list_del(p);
  		kfree(key);
  	}
  
  	return 0;
  }
  
  struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
  {
8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
978
  	struct link_key *k;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
979

8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
980
  	list_for_each_entry(k, &hdev->link_keys, list)
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
981
982
  		if (bacmp(bdaddr, &k->bdaddr) == 0)
  			return k;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
983
984
985
  
  	return NULL;
  }
d25e28abe   Johan Hedberg   Bluetooth: Fix li...
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
  static int hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn,
  						u8 key_type, u8 old_key_type)
  {
  	/* Legacy key */
  	if (key_type < 0x03)
  		return 1;
  
  	/* Debug keys are insecure so don't store them persistently */
  	if (key_type == HCI_LK_DEBUG_COMBINATION)
  		return 0;
  
  	/* Changed combination key and there's no previous one */
  	if (key_type == HCI_LK_CHANGED_COMBINATION && old_key_type == 0xff)
  		return 0;
  
  	/* Security mode 3 case */
  	if (!conn)
  		return 1;
  
  	/* Neither local nor remote side had no-bonding as requirement */
  	if (conn->auth_type > 0x01 && conn->remote_auth > 0x01)
  		return 1;
  
  	/* Local side had dedicated bonding as requirement */
  	if (conn->auth_type == 0x02 || conn->auth_type == 0x03)
  		return 1;
  
  	/* Remote side had dedicated bonding as requirement */
  	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03)
  		return 1;
  
  	/* If none of the above criteria match, then don't store the key
  	 * persistently */
  	return 0;
  }
75d262c2a   Vinicius Costa Gomes   Bluetooth: Add fu...
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
  struct link_key *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8])
  {
  	struct link_key *k;
  
  	list_for_each_entry(k, &hdev->link_keys, list) {
  		struct key_master_id *id;
  
  		if (k->type != HCI_LK_SMP_LTK)
  			continue;
  
  		if (k->dlen != sizeof(*id))
  			continue;
  
  		id = (void *) &k->data;
  		if (id->ediv == ediv &&
  				(memcmp(rand, id->rand, sizeof(id->rand)) == 0))
  			return k;
  	}
  
  	return NULL;
  }
  EXPORT_SYMBOL(hci_find_ltk);
  
  struct link_key *hci_find_link_key_type(struct hci_dev *hdev,
  					bdaddr_t *bdaddr, u8 type)
  {
  	struct link_key *k;
  
  	list_for_each_entry(k, &hdev->link_keys, list)
  		if (k->type == type && bacmp(bdaddr, &k->bdaddr) == 0)
  			return k;
  
  	return NULL;
  }
  EXPORT_SYMBOL(hci_find_link_key_type);
d25e28abe   Johan Hedberg   Bluetooth: Fix li...
1056
1057
  int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
  				bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len)
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1058
1059
  {
  	struct link_key *key, *old_key;
4df378a10   Johan Hedberg   Bluetooth: Add st...
1060
  	u8 old_key_type, persistent;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1061
1062
1063
1064
1065
1066
  
  	old_key = hci_find_link_key(hdev, bdaddr);
  	if (old_key) {
  		old_key_type = old_key->type;
  		key = old_key;
  	} else {
12adcf3a9   Johan Hedberg   Bluetooth: Fix ol...
1067
  		old_key_type = conn ? conn->key_type : 0xff;
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1068
1069
1070
1071
1072
1073
1074
  		key = kzalloc(sizeof(*key), GFP_ATOMIC);
  		if (!key)
  			return -ENOMEM;
  		list_add(&key->list, &hdev->link_keys);
  	}
  
  	BT_DBG("%s key for %s type %u", hdev->name, batostr(bdaddr), type);
d25e28abe   Johan Hedberg   Bluetooth: Fix li...
1075
1076
1077
1078
1079
  	/* Some buggy controller combinations generate a changed
  	 * combination key for legacy pairing even when there's no
  	 * previous key */
  	if (type == HCI_LK_CHANGED_COMBINATION &&
  					(!conn || conn->remote_auth == 0xff) &&
655fe6ece   Johan Hedberg   Bluetooth: Fix co...
1080
  					old_key_type == 0xff) {
d25e28abe   Johan Hedberg   Bluetooth: Fix li...
1081
  		type = HCI_LK_COMBINATION;
655fe6ece   Johan Hedberg   Bluetooth: Fix co...
1082
1083
1084
  		if (conn)
  			conn->key_type = type;
  	}
d25e28abe   Johan Hedberg   Bluetooth: Fix li...
1085

55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1086
1087
  	bacpy(&key->bdaddr, bdaddr);
  	memcpy(key->val, val, 16);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1088
  	key->pin_len = pin_len;
b6020ba05   Waldemar Rymarkiewicz   Bluetooth: Add de...
1089
  	if (type == HCI_LK_CHANGED_COMBINATION)
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1090
  		key->type = old_key_type;
4748fed2d   Johan Hedberg   Bluetooth: Remove...
1091
1092
  	else
  		key->type = type;
4df378a10   Johan Hedberg   Bluetooth: Add st...
1093
1094
1095
1096
  	if (!new_key)
  		return 0;
  
  	persistent = hci_persistent_key(hdev, conn, type, old_key_type);
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
1097
  	mgmt_new_link_key(hdev, key, persistent);
4df378a10   Johan Hedberg   Bluetooth: Add st...
1098
1099
1100
1101
1102
  
  	if (!persistent) {
  		list_del(&key->list);
  		kfree(key);
  	}
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1103
1104
1105
  
  	return 0;
  }
75d262c2a   Vinicius Costa Gomes   Bluetooth: Add fu...
1106
  int hci_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
726b4ffca   Vinicius Costa Gomes   Bluetooth: Add su...
1107
  			u8 key_size, __le16 ediv, u8 rand[8], u8 ltk[16])
75d262c2a   Vinicius Costa Gomes   Bluetooth: Add fu...
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
  {
  	struct link_key *key, *old_key;
  	struct key_master_id *id;
  	u8 old_key_type;
  
  	BT_DBG("%s addr %s", hdev->name, batostr(bdaddr));
  
  	old_key = hci_find_link_key_type(hdev, bdaddr, HCI_LK_SMP_LTK);
  	if (old_key) {
  		key = old_key;
  		old_key_type = old_key->type;
  	} else {
  		key = kzalloc(sizeof(*key) + sizeof(*id), GFP_ATOMIC);
  		if (!key)
  			return -ENOMEM;
  		list_add(&key->list, &hdev->link_keys);
  		old_key_type = 0xff;
  	}
  
  	key->dlen = sizeof(*id);
  
  	bacpy(&key->bdaddr, bdaddr);
  	memcpy(key->val, ltk, sizeof(key->val));
  	key->type = HCI_LK_SMP_LTK;
726b4ffca   Vinicius Costa Gomes   Bluetooth: Add su...
1132
  	key->pin_len = key_size;
75d262c2a   Vinicius Costa Gomes   Bluetooth: Add fu...
1133
1134
1135
1136
1137
1138
  
  	id = (void *) &key->data;
  	id->ediv = ediv;
  	memcpy(id->rand, rand, sizeof(id->rand));
  
  	if (new_key)
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
1139
  		mgmt_new_link_key(hdev, key, old_key_type);
75d262c2a   Vinicius Costa Gomes   Bluetooth: Add fu...
1140
1141
1142
  
  	return 0;
  }
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
  int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
  {
  	struct link_key *key;
  
  	key = hci_find_link_key(hdev, bdaddr);
  	if (!key)
  		return -ENOENT;
  
  	BT_DBG("%s removing %s", hdev->name, batostr(bdaddr));
  
  	list_del(&key->list);
  	kfree(key);
  
  	return 0;
  }
6bd32326c   Ville Tervo   Bluetooth: Use pr...
1158
1159
1160
1161
1162
1163
1164
  /* HCI command timer function */
  static void hci_cmd_timer(unsigned long arg)
  {
  	struct hci_dev *hdev = (void *) arg;
  
  	BT_ERR("%s command tx timeout", hdev->name);
  	atomic_set(&hdev->cmd_cnt, 1);
c347b765f   Gustavo F. Padovan   Bluetooth: Move c...
1165
  	queue_work(hdev->workqueue, &hdev->cmd_work);
6bd32326c   Ville Tervo   Bluetooth: Use pr...
1166
  }
2763eda6c   Szymon Janc   Bluetooth: Add ad...
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
  struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
  							bdaddr_t *bdaddr)
  {
  	struct oob_data *data;
  
  	list_for_each_entry(data, &hdev->remote_oob_data, list)
  		if (bacmp(bdaddr, &data->bdaddr) == 0)
  			return data;
  
  	return NULL;
  }
  
  int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr)
  {
  	struct oob_data *data;
  
  	data = hci_find_remote_oob_data(hdev, bdaddr);
  	if (!data)
  		return -ENOENT;
  
  	BT_DBG("%s removing %s", hdev->name, batostr(bdaddr));
  
  	list_del(&data->list);
  	kfree(data);
  
  	return 0;
  }
  
  int hci_remote_oob_data_clear(struct hci_dev *hdev)
  {
  	struct oob_data *data, *n;
  
  	list_for_each_entry_safe(data, n, &hdev->remote_oob_data, list) {
  		list_del(&data->list);
  		kfree(data);
  	}
  
  	return 0;
  }
  
  int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
  								u8 *randomizer)
  {
  	struct oob_data *data;
  
  	data = hci_find_remote_oob_data(hdev, bdaddr);
  
  	if (!data) {
  		data = kmalloc(sizeof(*data), GFP_ATOMIC);
  		if (!data)
  			return -ENOMEM;
  
  		bacpy(&data->bdaddr, bdaddr);
  		list_add(&data->list, &hdev->remote_oob_data);
  	}
  
  	memcpy(data->hash, hash, sizeof(data->hash));
  	memcpy(data->randomizer, randomizer, sizeof(data->randomizer));
  
  	BT_DBG("%s for %s", hdev->name, batostr(bdaddr));
  
  	return 0;
  }
b2a66aad8   Antti Julku   Bluetooth: Move b...
1230
1231
1232
  struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev,
  						bdaddr_t *bdaddr)
  {
8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
1233
  	struct bdaddr_list *b;
b2a66aad8   Antti Julku   Bluetooth: Move b...
1234

8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
1235
  	list_for_each_entry(b, &hdev->blacklist, list)
b2a66aad8   Antti Julku   Bluetooth: Move b...
1236
1237
  		if (bacmp(bdaddr, &b->bdaddr) == 0)
  			return b;
b2a66aad8   Antti Julku   Bluetooth: Move b...
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
  
  	return NULL;
  }
  
  int hci_blacklist_clear(struct hci_dev *hdev)
  {
  	struct list_head *p, *n;
  
  	list_for_each_safe(p, n, &hdev->blacklist) {
  		struct bdaddr_list *b;
  
  		b = list_entry(p, struct bdaddr_list, list);
  
  		list_del(p);
  		kfree(b);
  	}
  
  	return 0;
  }
  
  int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr)
  {
  	struct bdaddr_list *entry;
b2a66aad8   Antti Julku   Bluetooth: Move b...
1261
1262
1263
  
  	if (bacmp(bdaddr, BDADDR_ANY) == 0)
  		return -EBADF;
5e762444b   Antti Julku   Bluetooth: Add mg...
1264
1265
  	if (hci_blacklist_lookup(hdev, bdaddr))
  		return -EEXIST;
b2a66aad8   Antti Julku   Bluetooth: Move b...
1266
1267
  
  	entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
5e762444b   Antti Julku   Bluetooth: Add mg...
1268
1269
  	if (!entry)
  		return -ENOMEM;
b2a66aad8   Antti Julku   Bluetooth: Move b...
1270
1271
1272
1273
  
  	bacpy(&entry->bdaddr, bdaddr);
  
  	list_add(&entry->list, &hdev->blacklist);
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
1274
  	return mgmt_device_blocked(hdev, bdaddr);
b2a66aad8   Antti Julku   Bluetooth: Move b...
1275
1276
1277
1278
1279
  }
  
  int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr)
  {
  	struct bdaddr_list *entry;
b2a66aad8   Antti Julku   Bluetooth: Move b...
1280

1ec918cef   Szymon Janc   Bluetooth: Fix so...
1281
  	if (bacmp(bdaddr, BDADDR_ANY) == 0)
5e762444b   Antti Julku   Bluetooth: Add mg...
1282
  		return hci_blacklist_clear(hdev);
b2a66aad8   Antti Julku   Bluetooth: Move b...
1283
1284
  
  	entry = hci_blacklist_lookup(hdev, bdaddr);
1ec918cef   Szymon Janc   Bluetooth: Fix so...
1285
  	if (!entry)
5e762444b   Antti Julku   Bluetooth: Add mg...
1286
  		return -ENOENT;
b2a66aad8   Antti Julku   Bluetooth: Move b...
1287
1288
1289
  
  	list_del(&entry->list);
  	kfree(entry);
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
1290
  	return mgmt_device_unblocked(hdev, bdaddr);
b2a66aad8   Antti Julku   Bluetooth: Move b...
1291
  }
db323f2ff   Gustavo F. Padovan   Bluetooth: Use de...
1292
  static void hci_clear_adv_cache(struct work_struct *work)
358150857   Andre Guedes   Bluetooth: Advert...
1293
  {
db323f2ff   Gustavo F. Padovan   Bluetooth: Use de...
1294
1295
  	struct hci_dev *hdev = container_of(work, struct hci_dev,
  							adv_work.work);
358150857   Andre Guedes   Bluetooth: Advert...
1296
1297
1298
1299
1300
1301
1302
  
  	hci_dev_lock(hdev);
  
  	hci_adv_entries_clear(hdev);
  
  	hci_dev_unlock(hdev);
  }
76c8686f8   Andre Guedes   Bluetooth: LE adv...
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
  int hci_adv_entries_clear(struct hci_dev *hdev)
  {
  	struct adv_entry *entry, *tmp;
  
  	list_for_each_entry_safe(entry, tmp, &hdev->adv_entries, list) {
  		list_del(&entry->list);
  		kfree(entry);
  	}
  
  	BT_DBG("%s adv cache cleared", hdev->name);
  
  	return 0;
  }
  
  struct adv_entry *hci_find_adv_entry(struct hci_dev *hdev, bdaddr_t *bdaddr)
  {
  	struct adv_entry *entry;
  
  	list_for_each_entry(entry, &hdev->adv_entries, list)
  		if (bacmp(bdaddr, &entry->bdaddr) == 0)
  			return entry;
  
  	return NULL;
  }
  
  static inline int is_connectable_adv(u8 evt_type)
  {
  	if (evt_type == ADV_IND || evt_type == ADV_DIRECT_IND)
  		return 1;
  
  	return 0;
  }
  
  int hci_add_adv_entry(struct hci_dev *hdev,
  					struct hci_ev_le_advertising_info *ev)
  {
  	struct adv_entry *entry;
  
  	if (!is_connectable_adv(ev->evt_type))
  		return -EINVAL;
  
  	/* Only new entries should be added to adv_entries. So, if
  	 * bdaddr was found, don't add it. */
  	if (hci_find_adv_entry(hdev, &ev->bdaddr))
  		return 0;
  
  	entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
  	if (!entry)
  		return -ENOMEM;
  
  	bacpy(&entry->bdaddr, &ev->bdaddr);
  	entry->bdaddr_type = ev->bdaddr_type;
  
  	list_add(&entry->list, &hdev->adv_entries);
  
  	BT_DBG("%s adv entry added: address %s type %u", hdev->name,
  				batostr(&entry->bdaddr), entry->bdaddr_type);
  
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1363
1364
1365
1366
  /* Register HCI device */
  int hci_register_dev(struct hci_dev *hdev)
  {
  	struct list_head *head = &hci_dev_list, *p;
08add513c   Mat Martineau   Bluetooth: Guaran...
1367
  	int i, id, error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1368

c13854cef   Marcel Holtmann   Bluetooth: Conver...
1369
1370
  	BT_DBG("%p name %s bus %d owner %p", hdev, hdev->name,
  						hdev->bus, hdev->owner);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1371
1372
1373
  
  	if (!hdev->open || !hdev->close || !hdev->destruct)
  		return -EINVAL;
08add513c   Mat Martineau   Bluetooth: Guaran...
1374
1375
1376
1377
  	/* Do not allow HCI_AMP devices to register at index 0,
  	 * so the index can be used as the AMP controller ID.
  	 */
  	id = (hdev->dev_type == HCI_BREDR) ? 0 : 1;
f20d09d5f   Gustavo F. Padovan   Bluetooth: remove...
1378
  	write_lock(&hci_dev_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1379
1380
1381
1382
1383
1384
1385
  
  	/* Find first available device id */
  	list_for_each(p, &hci_dev_list) {
  		if (list_entry(p, struct hci_dev, list)->id != id)
  			break;
  		head = p; id++;
  	}
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
1386

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1387
1388
  	sprintf(hdev->name, "hci%d", id);
  	hdev->id = id;
c6feeb28a   Andrei Emeltchenko   Bluetooth: Use qu...
1389
  	list_add_tail(&hdev->list, head);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1390
1391
  
  	atomic_set(&hdev->refcnt, 1);
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1392
  	mutex_init(&hdev->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1393
1394
  
  	hdev->flags = 0;
d23264a89   Andre Guedes   Bluetooth: Add de...
1395
  	hdev->dev_flags = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1396
  	hdev->pkt_type  = (HCI_DM1 | HCI_DH1 | HCI_HV1);
5b7f99092   Marcel Holtmann   [Bluetooth] Add b...
1397
  	hdev->esco_type = (ESCO_HV1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1398
  	hdev->link_mode = (HCI_LM_ACCEPT);
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
1399
  	hdev->io_capability = 0x03; /* No Input No Output */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1400

04837f644   Marcel Holtmann   [Bluetooth] Add a...
1401
1402
1403
  	hdev->idle_timeout = 0;
  	hdev->sniff_max_interval = 800;
  	hdev->sniff_min_interval = 80;
b78752cc7   Marcel Holtmann   Bluetooth: Proces...
1404
  	INIT_WORK(&hdev->rx_work, hci_rx_work);
c347b765f   Gustavo F. Padovan   Bluetooth: Move c...
1405
  	INIT_WORK(&hdev->cmd_work, hci_cmd_work);
3eff45eaf   Gustavo F. Padovan   Bluetooth: conver...
1406
  	INIT_WORK(&hdev->tx_work, hci_tx_work);
b78752cc7   Marcel Holtmann   Bluetooth: Proces...
1407

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1408
1409
1410
1411
  
  	skb_queue_head_init(&hdev->rx_q);
  	skb_queue_head_init(&hdev->cmd_q);
  	skb_queue_head_init(&hdev->raw_q);
6bd32326c   Ville Tervo   Bluetooth: Use pr...
1412
  	setup_timer(&hdev->cmd_timer, hci_cmd_timer, (unsigned long) hdev);
cd4c53919   Suraj Sumangala   Bluetooth: Add on...
1413
  	for (i = 0; i < NUM_REASSEMBLY; i++)
ef222013f   Marcel Holtmann   [Bluetooth] Add h...
1414
  		hdev->reassembly[i] = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1415
  	init_waitqueue_head(&hdev->req_wait_q);
a6a67efd7   Thomas Gleixner   Bluetooth: Conver...
1416
  	mutex_init(&hdev->req_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1417
1418
1419
1420
  
  	inquiry_cache_init(hdev);
  
  	hci_conn_hash_init(hdev);
2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
1421
  	INIT_LIST_HEAD(&hdev->mgmt_pending);
ea4bd8ba8   David Miller   Bluetooth: Use li...
1422
  	INIT_LIST_HEAD(&hdev->blacklist);
f03585689   Johan Hedberg   Bluetooth: Add bl...
1423

2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1424
  	INIT_LIST_HEAD(&hdev->uuids);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1425
  	INIT_LIST_HEAD(&hdev->link_keys);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
1426
  	INIT_LIST_HEAD(&hdev->remote_oob_data);
76c8686f8   Andre Guedes   Bluetooth: LE adv...
1427
  	INIT_LIST_HEAD(&hdev->adv_entries);
db323f2ff   Gustavo F. Padovan   Bluetooth: Use de...
1428
  	INIT_DELAYED_WORK(&hdev->adv_work, hci_clear_adv_cache);
ab81cbf99   Johan Hedberg   Bluetooth: Implem...
1429
  	INIT_WORK(&hdev->power_on, hci_power_on);
3243553fd   Johan Hedberg   Bluetooth: Conver...
1430
  	INIT_DELAYED_WORK(&hdev->power_off, hci_power_off);
ab81cbf99   Johan Hedberg   Bluetooth: Implem...
1431

16ab91ab4   Johan Hedberg   Bluetooth: Add ti...
1432
  	INIT_DELAYED_WORK(&hdev->discov_off, hci_discov_off);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1433
1434
1435
  	memset(&hdev->stat, 0, sizeof(struct hci_dev_stats));
  
  	atomic_set(&hdev->promisc, 0);
f20d09d5f   Gustavo F. Padovan   Bluetooth: remove...
1436
  	write_unlock(&hci_dev_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1437

32845eb12   Gustavo F. Padovan   Bluetooth: Use ne...
1438
1439
  	hdev->workqueue = alloc_workqueue(hdev->name, WQ_HIGHPRI | WQ_UNBOUND |
  							WQ_MEM_RECLAIM, 1);
33ca954da   David Herrmann   Bluetooth: Forwar...
1440
1441
1442
1443
  	if (!hdev->workqueue) {
  		error = -ENOMEM;
  		goto err;
  	}
f48fd9c8c   Marcel Holtmann   Bluetooth: Create...
1444

33ca954da   David Herrmann   Bluetooth: Forwar...
1445
1446
1447
  	error = hci_add_sysfs(hdev);
  	if (error < 0)
  		goto err_wqueue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1448

611b30f74   Marcel Holtmann   Bluetooth: Add na...
1449
1450
1451
1452
1453
1454
1455
1456
  	hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
  				RFKILL_TYPE_BLUETOOTH, &hci_rfkill_ops, hdev);
  	if (hdev->rfkill) {
  		if (rfkill_register(hdev->rfkill) < 0) {
  			rfkill_destroy(hdev->rfkill);
  			hdev->rfkill = NULL;
  		}
  	}
ab81cbf99   Johan Hedberg   Bluetooth: Implem...
1457
1458
  	set_bit(HCI_AUTO_OFF, &hdev->flags);
  	set_bit(HCI_SETUP, &hdev->flags);
7f971041c   Gustavo F. Padovan   Bluetooth: Use sy...
1459
  	schedule_work(&hdev->power_on);
ab81cbf99   Johan Hedberg   Bluetooth: Implem...
1460

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1461
1462
1463
  	hci_notify(hdev, HCI_DEV_REG);
  
  	return id;
f48fd9c8c   Marcel Holtmann   Bluetooth: Create...
1464

33ca954da   David Herrmann   Bluetooth: Forwar...
1465
1466
1467
  err_wqueue:
  	destroy_workqueue(hdev->workqueue);
  err:
f20d09d5f   Gustavo F. Padovan   Bluetooth: remove...
1468
  	write_lock(&hci_dev_list_lock);
f48fd9c8c   Marcel Holtmann   Bluetooth: Create...
1469
  	list_del(&hdev->list);
f20d09d5f   Gustavo F. Padovan   Bluetooth: remove...
1470
  	write_unlock(&hci_dev_list_lock);
f48fd9c8c   Marcel Holtmann   Bluetooth: Create...
1471

33ca954da   David Herrmann   Bluetooth: Forwar...
1472
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1473
1474
1475
1476
  }
  EXPORT_SYMBOL(hci_register_dev);
  
  /* Unregister HCI device */
59735631d   David Herrmann   Bluetooth: Make h...
1477
  void hci_unregister_dev(struct hci_dev *hdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1478
  {
ef222013f   Marcel Holtmann   [Bluetooth] Add h...
1479
  	int i;
c13854cef   Marcel Holtmann   Bluetooth: Conver...
1480
  	BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1481

f20d09d5f   Gustavo F. Padovan   Bluetooth: remove...
1482
  	write_lock(&hci_dev_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1483
  	list_del(&hdev->list);
f20d09d5f   Gustavo F. Padovan   Bluetooth: remove...
1484
  	write_unlock(&hci_dev_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1485
1486
  
  	hci_dev_do_close(hdev);
cd4c53919   Suraj Sumangala   Bluetooth: Add on...
1487
  	for (i = 0; i < NUM_REASSEMBLY; i++)
ef222013f   Marcel Holtmann   [Bluetooth] Add h...
1488
  		kfree_skb(hdev->reassembly[i]);
ab81cbf99   Johan Hedberg   Bluetooth: Implem...
1489
  	if (!test_bit(HCI_INIT, &hdev->flags) &&
56e5cb86e   Johan Hedberg   Bluetooth: Add mi...
1490
  					!test_bit(HCI_SETUP, &hdev->flags)) {
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1491
  		hci_dev_lock(hdev);
744cf19ea   Johan Hedberg   Bluetooth: Pass f...
1492
  		mgmt_index_removed(hdev);
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1493
  		hci_dev_unlock(hdev);
56e5cb86e   Johan Hedberg   Bluetooth: Add mi...
1494
  	}
ab81cbf99   Johan Hedberg   Bluetooth: Implem...
1495

2e58ef3e1   Johan Hedberg   Bluetooth: Move p...
1496
1497
1498
  	/* mgmt_index_removed should take care of emptying the
  	 * pending list */
  	BUG_ON(!list_empty(&hdev->mgmt_pending));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1499
  	hci_notify(hdev, HCI_DEV_UNREG);
611b30f74   Marcel Holtmann   Bluetooth: Add na...
1500
1501
1502
1503
  	if (hdev->rfkill) {
  		rfkill_unregister(hdev->rfkill);
  		rfkill_destroy(hdev->rfkill);
  	}
ce242970f   David Herrmann   Bluetooth: Rename...
1504
  	hci_del_sysfs(hdev);
147e2d598   Dave Young   bluetooth: hci_co...
1505

db323f2ff   Gustavo F. Padovan   Bluetooth: Use de...
1506
  	cancel_delayed_work_sync(&hdev->adv_work);
c6f3c5f7f   Gustavo F. Padovan   Bluetooth: Fix cr...
1507

f48fd9c8c   Marcel Holtmann   Bluetooth: Create...
1508
  	destroy_workqueue(hdev->workqueue);
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1509
  	hci_dev_lock(hdev);
e2e0cacbd   Johan Hedberg   Bluetooth: Fix le...
1510
  	hci_blacklist_clear(hdev);
2aeb9a1ae   Johan Hedberg   Bluetooth: Implem...
1511
  	hci_uuids_clear(hdev);
55ed8ca10   Johan Hedberg   Bluetooth: Implem...
1512
  	hci_link_keys_clear(hdev);
2763eda6c   Szymon Janc   Bluetooth: Add ad...
1513
  	hci_remote_oob_data_clear(hdev);
76c8686f8   Andre Guedes   Bluetooth: LE adv...
1514
  	hci_adv_entries_clear(hdev);
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
1515
  	hci_dev_unlock(hdev);
e2e0cacbd   Johan Hedberg   Bluetooth: Fix le...
1516

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1517
  	__hci_dev_put(hdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
  }
  EXPORT_SYMBOL(hci_unregister_dev);
  
  /* Suspend HCI device */
  int hci_suspend_dev(struct hci_dev *hdev)
  {
  	hci_notify(hdev, HCI_DEV_SUSPEND);
  	return 0;
  }
  EXPORT_SYMBOL(hci_suspend_dev);
  
  /* Resume HCI device */
  int hci_resume_dev(struct hci_dev *hdev)
  {
  	hci_notify(hdev, HCI_DEV_RESUME);
  	return 0;
  }
  EXPORT_SYMBOL(hci_resume_dev);
76bca8801   Marcel Holtmann   Bluetooth: Turn h...
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
  /* Receive frame from HCI drivers */
  int hci_recv_frame(struct sk_buff *skb)
  {
  	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
  	if (!hdev || (!test_bit(HCI_UP, &hdev->flags)
  				&& !test_bit(HCI_INIT, &hdev->flags))) {
  		kfree_skb(skb);
  		return -ENXIO;
  	}
  
  	/* Incomming skb */
  	bt_cb(skb)->incoming = 1;
  
  	/* Time stamp */
  	__net_timestamp(skb);
76bca8801   Marcel Holtmann   Bluetooth: Turn h...
1551
  	skb_queue_tail(&hdev->rx_q, skb);
b78752cc7   Marcel Holtmann   Bluetooth: Proces...
1552
  	queue_work(hdev->workqueue, &hdev->rx_work);
c78ae2831   Marcel Holtmann   Bluetooth: Unobfu...
1553

76bca8801   Marcel Holtmann   Bluetooth: Turn h...
1554
1555
1556
  	return 0;
  }
  EXPORT_SYMBOL(hci_recv_frame);
33e882a5f   Suraj Sumangala   Bluetooth: Implem...
1557
  static int hci_reassembly(struct hci_dev *hdev, int type, void *data,
1e429f384   Gustavo F. Padovan   Bluetooth: Remove...
1558
  						  int count, __u8 index)
33e882a5f   Suraj Sumangala   Bluetooth: Implem...
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
  {
  	int len = 0;
  	int hlen = 0;
  	int remain = count;
  	struct sk_buff *skb;
  	struct bt_skb_cb *scb;
  
  	if ((type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) ||
  				index >= NUM_REASSEMBLY)
  		return -EILSEQ;
  
  	skb = hdev->reassembly[index];
  
  	if (!skb) {
  		switch (type) {
  		case HCI_ACLDATA_PKT:
  			len = HCI_MAX_FRAME_SIZE;
  			hlen = HCI_ACL_HDR_SIZE;
  			break;
  		case HCI_EVENT_PKT:
  			len = HCI_MAX_EVENT_SIZE;
  			hlen = HCI_EVENT_HDR_SIZE;
  			break;
  		case HCI_SCODATA_PKT:
  			len = HCI_MAX_SCO_SIZE;
  			hlen = HCI_SCO_HDR_SIZE;
  			break;
  		}
1e429f384   Gustavo F. Padovan   Bluetooth: Remove...
1587
  		skb = bt_skb_alloc(len, GFP_ATOMIC);
33e882a5f   Suraj Sumangala   Bluetooth: Implem...
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
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
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
  		if (!skb)
  			return -ENOMEM;
  
  		scb = (void *) skb->cb;
  		scb->expect = hlen;
  		scb->pkt_type = type;
  
  		skb->dev = (void *) hdev;
  		hdev->reassembly[index] = skb;
  	}
  
  	while (count) {
  		scb = (void *) skb->cb;
  		len = min(scb->expect, (__u16)count);
  
  		memcpy(skb_put(skb, len), data, len);
  
  		count -= len;
  		data += len;
  		scb->expect -= len;
  		remain = count;
  
  		switch (type) {
  		case HCI_EVENT_PKT:
  			if (skb->len == HCI_EVENT_HDR_SIZE) {
  				struct hci_event_hdr *h = hci_event_hdr(skb);
  				scb->expect = h->plen;
  
  				if (skb_tailroom(skb) < scb->expect) {
  					kfree_skb(skb);
  					hdev->reassembly[index] = NULL;
  					return -ENOMEM;
  				}
  			}
  			break;
  
  		case HCI_ACLDATA_PKT:
  			if (skb->len  == HCI_ACL_HDR_SIZE) {
  				struct hci_acl_hdr *h = hci_acl_hdr(skb);
  				scb->expect = __le16_to_cpu(h->dlen);
  
  				if (skb_tailroom(skb) < scb->expect) {
  					kfree_skb(skb);
  					hdev->reassembly[index] = NULL;
  					return -ENOMEM;
  				}
  			}
  			break;
  
  		case HCI_SCODATA_PKT:
  			if (skb->len == HCI_SCO_HDR_SIZE) {
  				struct hci_sco_hdr *h = hci_sco_hdr(skb);
  				scb->expect = h->dlen;
  
  				if (skb_tailroom(skb) < scb->expect) {
  					kfree_skb(skb);
  					hdev->reassembly[index] = NULL;
  					return -ENOMEM;
  				}
  			}
  			break;
  		}
  
  		if (scb->expect == 0) {
  			/* Complete frame */
  
  			bt_cb(skb)->pkt_type = type;
  			hci_recv_frame(skb);
  
  			hdev->reassembly[index] = NULL;
  			return remain;
  		}
  	}
  
  	return remain;
  }
ef222013f   Marcel Holtmann   [Bluetooth] Add h...
1664
1665
  int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count)
  {
f39a3c064   Suraj Sumangala   Bluetooth: Modifi...
1666
  	int rem = 0;
ef222013f   Marcel Holtmann   [Bluetooth] Add h...
1667
1668
  	if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT)
  		return -EILSEQ;
da5f6c37e   Gustavo F. Padovan   Bluetooth: Test '...
1669
  	while (count) {
1e429f384   Gustavo F. Padovan   Bluetooth: Remove...
1670
  		rem = hci_reassembly(hdev, type, data, count, type - 1);
f39a3c064   Suraj Sumangala   Bluetooth: Modifi...
1671
1672
  		if (rem < 0)
  			return rem;
ef222013f   Marcel Holtmann   [Bluetooth] Add h...
1673

f39a3c064   Suraj Sumangala   Bluetooth: Modifi...
1674
1675
  		data += (count - rem);
  		count = rem;
f81c62242   Joe Perches   net: Remove unnec...
1676
  	}
ef222013f   Marcel Holtmann   [Bluetooth] Add h...
1677

f39a3c064   Suraj Sumangala   Bluetooth: Modifi...
1678
  	return rem;
ef222013f   Marcel Holtmann   [Bluetooth] Add h...
1679
1680
  }
  EXPORT_SYMBOL(hci_recv_fragment);
998115108   Suraj Sumangala   Bluetooth: Implem...
1681
1682
1683
1684
1685
1686
  #define STREAM_REASSEMBLY 0
  
  int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count)
  {
  	int type;
  	int rem = 0;
da5f6c37e   Gustavo F. Padovan   Bluetooth: Test '...
1687
  	while (count) {
998115108   Suraj Sumangala   Bluetooth: Implem...
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
  		struct sk_buff *skb = hdev->reassembly[STREAM_REASSEMBLY];
  
  		if (!skb) {
  			struct { char type; } *pkt;
  
  			/* Start of the frame */
  			pkt = data;
  			type = pkt->type;
  
  			data++;
  			count--;
  		} else
  			type = bt_cb(skb)->pkt_type;
1e429f384   Gustavo F. Padovan   Bluetooth: Remove...
1701
1702
  		rem = hci_reassembly(hdev, type, data, count,
  							STREAM_REASSEMBLY);
998115108   Suraj Sumangala   Bluetooth: Implem...
1703
1704
1705
1706
1707
  		if (rem < 0)
  			return rem;
  
  		data += (count - rem);
  		count = rem;
f81c62242   Joe Perches   net: Remove unnec...
1708
  	}
998115108   Suraj Sumangala   Bluetooth: Implem...
1709
1710
1711
1712
  
  	return rem;
  }
  EXPORT_SYMBOL(hci_recv_stream_fragment);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1713
  /* ---- Interface to upper protocols ---- */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1714
1715
1716
  int hci_register_cb(struct hci_cb *cb)
  {
  	BT_DBG("%p name %s", cb, cb->name);
f20d09d5f   Gustavo F. Padovan   Bluetooth: remove...
1717
  	write_lock(&hci_cb_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1718
  	list_add(&cb->list, &hci_cb_list);
f20d09d5f   Gustavo F. Padovan   Bluetooth: remove...
1719
  	write_unlock(&hci_cb_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1720
1721
1722
1723
1724
1725
1726
1727
  
  	return 0;
  }
  EXPORT_SYMBOL(hci_register_cb);
  
  int hci_unregister_cb(struct hci_cb *cb)
  {
  	BT_DBG("%p name %s", cb, cb->name);
f20d09d5f   Gustavo F. Padovan   Bluetooth: remove...
1728
  	write_lock(&hci_cb_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1729
  	list_del(&cb->list);
f20d09d5f   Gustavo F. Padovan   Bluetooth: remove...
1730
  	write_unlock(&hci_cb_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
  
  	return 0;
  }
  EXPORT_SYMBOL(hci_unregister_cb);
  
  static int hci_send_frame(struct sk_buff *skb)
  {
  	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
  
  	if (!hdev) {
  		kfree_skb(skb);
  		return -ENODEV;
  	}
0d48d9394   Marcel Holtmann   [Bluetooth]: Move...
1744
  	BT_DBG("%s type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1745
1746
1747
  
  	if (atomic_read(&hdev->promisc)) {
  		/* Time stamp */
a61bbcf28   Patrick McHardy   [NET]: Store skb-...
1748
  		__net_timestamp(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1749

eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
1750
  		hci_send_to_sock(hdev, skb, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1751
1752
1753
1754
1755
1756
1757
1758
1759
  	}
  
  	/* Get rid of skb owner, prior to sending to the driver. */
  	skb_orphan(skb);
  
  	return hdev->send(skb);
  }
  
  /* Send HCI command */
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
1760
  int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1761
1762
1763
1764
  {
  	int len = HCI_COMMAND_HDR_SIZE + plen;
  	struct hci_command_hdr *hdr;
  	struct sk_buff *skb;
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
1765
  	BT_DBG("%s opcode 0x%x plen %d", hdev->name, opcode, plen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1766
1767
1768
  
  	skb = bt_skb_alloc(len, GFP_ATOMIC);
  	if (!skb) {
ef222013f   Marcel Holtmann   [Bluetooth] Add h...
1769
  		BT_ERR("%s no memory for command", hdev->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1770
1771
1772
1773
  		return -ENOMEM;
  	}
  
  	hdr = (struct hci_command_hdr *) skb_put(skb, HCI_COMMAND_HDR_SIZE);
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
1774
  	hdr->opcode = cpu_to_le16(opcode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1775
1776
1777
1778
1779
1780
  	hdr->plen   = plen;
  
  	if (plen)
  		memcpy(skb_put(skb, plen), param, plen);
  
  	BT_DBG("skb len %d", skb->len);
0d48d9394   Marcel Holtmann   [Bluetooth]: Move...
1781
  	bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1782
  	skb->dev = (void *) hdev;
c78ae2831   Marcel Holtmann   Bluetooth: Unobfu...
1783

a5040efa2   Johan Hedberg   Bluetooth: Add sp...
1784
1785
  	if (test_bit(HCI_INIT, &hdev->flags))
  		hdev->init_last_cmd = opcode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1786
  	skb_queue_tail(&hdev->cmd_q, skb);
c347b765f   Gustavo F. Padovan   Bluetooth: Move c...
1787
  	queue_work(hdev->workqueue, &hdev->cmd_work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1788
1789
1790
  
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1791
1792
  
  /* Get data from the previously sent command */
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
1793
  void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1794
1795
1796
1797
1798
1799
1800
  {
  	struct hci_command_hdr *hdr;
  
  	if (!hdev->sent_cmd)
  		return NULL;
  
  	hdr = (void *) hdev->sent_cmd->data;
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
1801
  	if (hdr->opcode != cpu_to_le16(opcode))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1802
  		return NULL;
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
1803
  	BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1804
1805
1806
1807
1808
1809
1810
1811
1812
  
  	return hdev->sent_cmd->data + HCI_COMMAND_HDR_SIZE;
  }
  
  /* Send ACL data */
  static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags)
  {
  	struct hci_acl_hdr *hdr;
  	int len = skb->len;
badff6d01   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1813
1814
  	skb_push(skb, HCI_ACL_HDR_SIZE);
  	skb_reset_transport_header(skb);
9c70220b7   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1815
  	hdr = (struct hci_acl_hdr *)skb_transport_header(skb);
aca3192cc   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
1816
1817
  	hdr->handle = cpu_to_le16(hci_handle_pack(handle, flags));
  	hdr->dlen   = cpu_to_le16(len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1818
  }
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
1819
1820
  static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue,
  				struct sk_buff *skb, __u16 flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1821
1822
1823
  {
  	struct hci_dev *hdev = conn->hdev;
  	struct sk_buff *list;
70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
1824
1825
  	list = skb_shinfo(skb)->frag_list;
  	if (!list) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1826
1827
  		/* Non fragmented */
  		BT_DBG("%s nonfrag skb %p len %d", hdev->name, skb, skb->len);
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
1828
  		skb_queue_tail(queue, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1829
1830
1831
1832
1833
1834
1835
  	} else {
  		/* Fragmented */
  		BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len);
  
  		skb_shinfo(skb)->frag_list = NULL;
  
  		/* Queue all fragments atomically */
af3e6359a   Gustavo F. Padovan   Bluetooth: Don't ...
1836
  		spin_lock(&queue->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1837

73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
1838
  		__skb_queue_tail(queue, skb);
e702112ff   Andrei Emeltchenko   Bluetooth: Use no...
1839
1840
1841
  
  		flags &= ~ACL_START;
  		flags |= ACL_CONT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1842
1843
  		do {
  			skb = list; list = list->next;
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
1844

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1845
  			skb->dev = (void *) hdev;
0d48d9394   Marcel Holtmann   [Bluetooth]: Move...
1846
  			bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
e702112ff   Andrei Emeltchenko   Bluetooth: Use no...
1847
  			hci_add_acl_hdr(skb, conn->handle, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1848
1849
  
  			BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len);
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
1850
  			__skb_queue_tail(queue, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1851
  		} while (list);
af3e6359a   Gustavo F. Padovan   Bluetooth: Don't ...
1852
  		spin_unlock(&queue->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1853
  	}
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
  }
  
  void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags)
  {
  	struct hci_conn *conn = chan->conn;
  	struct hci_dev *hdev = conn->hdev;
  
  	BT_DBG("%s chan %p flags 0x%x", hdev->name, chan, flags);
  
  	skb->dev = (void *) hdev;
  	bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
  	hci_add_acl_hdr(skb, conn->handle, flags);
  
  	hci_queue_acl(conn, &chan->data_q, skb, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1868

3eff45eaf   Gustavo F. Padovan   Bluetooth: conver...
1869
  	queue_work(hdev->workqueue, &hdev->tx_work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1870
1871
1872
1873
  }
  EXPORT_SYMBOL(hci_send_acl);
  
  /* Send SCO data */
0d861d8b8   Gustavo F. Padovan   Bluetooth: Make h...
1874
  void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1875
1876
1877
1878
1879
  {
  	struct hci_dev *hdev = conn->hdev;
  	struct hci_sco_hdr hdr;
  
  	BT_DBG("%s len %d", hdev->name, skb->len);
aca3192cc   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
1880
  	hdr.handle = cpu_to_le16(conn->handle);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1881
  	hdr.dlen   = skb->len;
badff6d01   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1882
1883
  	skb_push(skb, HCI_SCO_HDR_SIZE);
  	skb_reset_transport_header(skb);
9c70220b7   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1884
  	memcpy(skb_transport_header(skb), &hdr, HCI_SCO_HDR_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1885
1886
  
  	skb->dev = (void *) hdev;
0d48d9394   Marcel Holtmann   [Bluetooth]: Move...
1887
  	bt_cb(skb)->pkt_type = HCI_SCODATA_PKT;
c78ae2831   Marcel Holtmann   Bluetooth: Unobfu...
1888

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1889
  	skb_queue_tail(&conn->data_q, skb);
3eff45eaf   Gustavo F. Padovan   Bluetooth: conver...
1890
  	queue_work(hdev->workqueue, &hdev->tx_work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1891
1892
1893
1894
1895
1896
1897
1898
1899
  }
  EXPORT_SYMBOL(hci_send_sco);
  
  /* ---- HCI TX task (outgoing data) ---- */
  
  /* HCI Connection scheduler */
  static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int *quote)
  {
  	struct hci_conn_hash *h = &hdev->conn_hash;
8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
1900
  	struct hci_conn *conn = NULL, *c;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1901
  	int num = 0, min = ~0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1902

8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
1903
  	/* We don't have to lock device here. Connections are always
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1904
  	 * added and removed with TX task disabled. */
bf4c63252   Gustavo F. Padovan   Bluetooth: conver...
1905
1906
1907
1908
  
  	rcu_read_lock();
  
  	list_for_each_entry_rcu(c, &h->list, list) {
769be974d   Marcel Holtmann   [Bluetooth] Use A...
1909
  		if (c->type != type || skb_queue_empty(&c->data_q))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1910
  			continue;
769be974d   Marcel Holtmann   [Bluetooth] Use A...
1911
1912
1913
  
  		if (c->state != BT_CONNECTED && c->state != BT_CONFIG)
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1914
1915
1916
1917
1918
1919
  		num++;
  
  		if (c->sent < min) {
  			min  = c->sent;
  			conn = c;
  		}
52087a792   Luiz Augusto von Dentz   Bluetooth: make u...
1920
1921
1922
  
  		if (hci_conn_num(hdev, type) == num)
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1923
  	}
bf4c63252   Gustavo F. Padovan   Bluetooth: conver...
1924
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1925
  	if (conn) {
6ed58ec52   Ville Tervo   Bluetooth: Use LE...
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
  		int cnt, q;
  
  		switch (conn->type) {
  		case ACL_LINK:
  			cnt = hdev->acl_cnt;
  			break;
  		case SCO_LINK:
  		case ESCO_LINK:
  			cnt = hdev->sco_cnt;
  			break;
  		case LE_LINK:
  			cnt = hdev->le_mtu ? hdev->le_cnt : hdev->acl_cnt;
  			break;
  		default:
  			cnt = 0;
  			BT_ERR("Unknown link type");
  		}
  
  		q = cnt / num;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1945
1946
1947
1948
1949
1950
1951
  		*quote = q ? q : 1;
  	} else
  		*quote = 0;
  
  	BT_DBG("conn %p quote %d", conn, *quote);
  	return conn;
  }
bae1f5d94   Ville Tervo   Bluetooth: Treat ...
1952
  static inline void hci_link_tx_to(struct hci_dev *hdev, __u8 type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1953
1954
  {
  	struct hci_conn_hash *h = &hdev->conn_hash;
8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
1955
  	struct hci_conn *c;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1956

bae1f5d94   Ville Tervo   Bluetooth: Treat ...
1957
  	BT_ERR("%s link tx timeout", hdev->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1958

bf4c63252   Gustavo F. Padovan   Bluetooth: conver...
1959
  	rcu_read_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1960
  	/* Kill stalled connections */
bf4c63252   Gustavo F. Padovan   Bluetooth: conver...
1961
  	list_for_each_entry_rcu(c, &h->list, list) {
bae1f5d94   Ville Tervo   Bluetooth: Treat ...
1962
1963
  		if (c->type == type && c->sent) {
  			BT_ERR("%s killing stalled connection %s",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1964
1965
1966
1967
  				hdev->name, batostr(&c->dst));
  			hci_acl_disconn(c, 0x13);
  		}
  	}
bf4c63252   Gustavo F. Padovan   Bluetooth: conver...
1968
1969
  
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1970
  }
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
1971
1972
  static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
  						int *quote)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1973
  {
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
1974
1975
1976
  	struct hci_conn_hash *h = &hdev->conn_hash;
  	struct hci_chan *chan = NULL;
  	int num = 0, min = ~0, cur_prio = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1977
  	struct hci_conn *conn;
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
1978
1979
1980
  	int cnt, q, conn_num = 0;
  
  	BT_DBG("%s", hdev->name);
bf4c63252   Gustavo F. Padovan   Bluetooth: conver...
1981
1982
1983
  	rcu_read_lock();
  
  	list_for_each_entry_rcu(conn, &h->list, list) {
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
1984
1985
1986
1987
1988
1989
1990
1991
1992
  		struct hci_chan *tmp;
  
  		if (conn->type != type)
  			continue;
  
  		if (conn->state != BT_CONNECTED && conn->state != BT_CONFIG)
  			continue;
  
  		conn_num++;
8192edef0   Gustavo F. Padovan   Bluetooth: Use RC...
1993
  		list_for_each_entry_rcu(tmp, &conn->chan_list, list) {
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
  			struct sk_buff *skb;
  
  			if (skb_queue_empty(&tmp->data_q))
  				continue;
  
  			skb = skb_peek(&tmp->data_q);
  			if (skb->priority < cur_prio)
  				continue;
  
  			if (skb->priority > cur_prio) {
  				num = 0;
  				min = ~0;
  				cur_prio = skb->priority;
  			}
  
  			num++;
  
  			if (conn->sent < min) {
  				min  = conn->sent;
  				chan = tmp;
  			}
  		}
  
  		if (hci_conn_num(hdev, type) == conn_num)
  			break;
  	}
bf4c63252   Gustavo F. Padovan   Bluetooth: conver...
2020
  	rcu_read_unlock();
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
  	if (!chan)
  		return NULL;
  
  	switch (chan->conn->type) {
  	case ACL_LINK:
  		cnt = hdev->acl_cnt;
  		break;
  	case SCO_LINK:
  	case ESCO_LINK:
  		cnt = hdev->sco_cnt;
  		break;
  	case LE_LINK:
  		cnt = hdev->le_mtu ? hdev->le_cnt : hdev->acl_cnt;
  		break;
  	default:
  		cnt = 0;
  		BT_ERR("Unknown link type");
  	}
  
  	q = cnt / num;
  	*quote = q ? q : 1;
  	BT_DBG("chan %p quote %d", chan, *quote);
  	return chan;
  }
02b20f0bb   Luiz Augusto von Dentz   Bluetooth: recalc...
2045
2046
2047
2048
2049
2050
2051
  static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type)
  {
  	struct hci_conn_hash *h = &hdev->conn_hash;
  	struct hci_conn *conn;
  	int num = 0;
  
  	BT_DBG("%s", hdev->name);
bf4c63252   Gustavo F. Padovan   Bluetooth: conver...
2052
2053
2054
  	rcu_read_lock();
  
  	list_for_each_entry_rcu(conn, &h->list, list) {
02b20f0bb   Luiz Augusto von Dentz   Bluetooth: recalc...
2055
2056
2057
2058
2059
2060
2061
2062
2063
  		struct hci_chan *chan;
  
  		if (conn->type != type)
  			continue;
  
  		if (conn->state != BT_CONNECTED && conn->state != BT_CONFIG)
  			continue;
  
  		num++;
8192edef0   Gustavo F. Padovan   Bluetooth: Use RC...
2064
  		list_for_each_entry_rcu(chan, &conn->chan_list, list) {
02b20f0bb   Luiz Augusto von Dentz   Bluetooth: recalc...
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
  			struct sk_buff *skb;
  
  			if (chan->sent) {
  				chan->sent = 0;
  				continue;
  			}
  
  			if (skb_queue_empty(&chan->data_q))
  				continue;
  
  			skb = skb_peek(&chan->data_q);
  			if (skb->priority >= HCI_PRIO_MAX - 1)
  				continue;
  
  			skb->priority = HCI_PRIO_MAX - 1;
  
  			BT_DBG("chan %p skb %p promoted to %d", chan, skb,
  								skb->priority);
  		}
  
  		if (hci_conn_num(hdev, type) == num)
  			break;
  	}
bf4c63252   Gustavo F. Padovan   Bluetooth: conver...
2088
2089
  
  	rcu_read_unlock();
02b20f0bb   Luiz Augusto von Dentz   Bluetooth: recalc...
2090
  }
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
2091
2092
2093
  static inline void hci_sched_acl(struct hci_dev *hdev)
  {
  	struct hci_chan *chan;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2094
2095
  	struct sk_buff *skb;
  	int quote;
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
2096
  	unsigned int cnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2097
2098
  
  	BT_DBG("%s", hdev->name);
52087a792   Luiz Augusto von Dentz   Bluetooth: make u...
2099
2100
  	if (!hci_conn_num(hdev, ACL_LINK))
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2101
2102
2103
  	if (!test_bit(HCI_RAW, &hdev->flags)) {
  		/* ACL tx timeout must be longer than maximum
  		 * link supervision timeout (40.9 seconds) */
82453021b   S.Çağlar Onur   [BLUETOOTH] net/b...
2104
  		if (!hdev->acl_cnt && time_after(jiffies, hdev->acl_last_tx + HZ * 45))
bae1f5d94   Ville Tervo   Bluetooth: Treat ...
2105
  			hci_link_tx_to(hdev, ACL_LINK);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2106
  	}
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
2107
  	cnt = hdev->acl_cnt;
04837f644   Marcel Holtmann   [Bluetooth] Add a...
2108

73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
2109
2110
  	while (hdev->acl_cnt &&
  			(chan = hci_chan_sent(hdev, ACL_LINK, &quote))) {
ec1cce24d   Luiz Augusto von Dentz   Bluetooth: handle...
2111
2112
  		u32 priority = (skb_peek(&chan->data_q))->priority;
  		while (quote-- && (skb = skb_peek(&chan->data_q))) {
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
2113
2114
  			BT_DBG("chan %p skb %p len %d priority %u", chan, skb,
  					skb->len, skb->priority);
ec1cce24d   Luiz Augusto von Dentz   Bluetooth: handle...
2115
2116
2117
2118
2119
  			/* Stop if priority has changed */
  			if (skb->priority < priority)
  				break;
  
  			skb = skb_dequeue(&chan->data_q);
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
2120
2121
  			hci_conn_enter_active_mode(chan->conn,
  						bt_cb(skb)->force_active);
04837f644   Marcel Holtmann   [Bluetooth] Add a...
2122

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2123
2124
2125
2126
  			hci_send_frame(skb);
  			hdev->acl_last_tx = jiffies;
  
  			hdev->acl_cnt--;
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
2127
2128
  			chan->sent++;
  			chan->conn->sent++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2129
2130
  		}
  	}
02b20f0bb   Luiz Augusto von Dentz   Bluetooth: recalc...
2131
2132
2133
  
  	if (cnt != hdev->acl_cnt)
  		hci_prio_recalculate(hdev, ACL_LINK);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
  }
  
  /* Schedule SCO */
  static inline void hci_sched_sco(struct hci_dev *hdev)
  {
  	struct hci_conn *conn;
  	struct sk_buff *skb;
  	int quote;
  
  	BT_DBG("%s", hdev->name);
52087a792   Luiz Augusto von Dentz   Bluetooth: make u...
2144
2145
  	if (!hci_conn_num(hdev, SCO_LINK))
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
  	while (hdev->sco_cnt && (conn = hci_low_sent(hdev, SCO_LINK, &quote))) {
  		while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
  			BT_DBG("skb %p len %d", skb, skb->len);
  			hci_send_frame(skb);
  
  			conn->sent++;
  			if (conn->sent == ~0)
  				conn->sent = 0;
  		}
  	}
  }
b6a0dc822   Marcel Holtmann   [Bluetooth] Add s...
2157
2158
2159
2160
2161
2162
2163
  static inline void hci_sched_esco(struct hci_dev *hdev)
  {
  	struct hci_conn *conn;
  	struct sk_buff *skb;
  	int quote;
  
  	BT_DBG("%s", hdev->name);
52087a792   Luiz Augusto von Dentz   Bluetooth: make u...
2164
2165
  	if (!hci_conn_num(hdev, ESCO_LINK))
  		return;
b6a0dc822   Marcel Holtmann   [Bluetooth] Add s...
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
  	while (hdev->sco_cnt && (conn = hci_low_sent(hdev, ESCO_LINK, &quote))) {
  		while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
  			BT_DBG("skb %p len %d", skb, skb->len);
  			hci_send_frame(skb);
  
  			conn->sent++;
  			if (conn->sent == ~0)
  				conn->sent = 0;
  		}
  	}
  }
6ed58ec52   Ville Tervo   Bluetooth: Use LE...
2177
2178
  static inline void hci_sched_le(struct hci_dev *hdev)
  {
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
2179
  	struct hci_chan *chan;
6ed58ec52   Ville Tervo   Bluetooth: Use LE...
2180
  	struct sk_buff *skb;
02b20f0bb   Luiz Augusto von Dentz   Bluetooth: recalc...
2181
  	int quote, cnt, tmp;
6ed58ec52   Ville Tervo   Bluetooth: Use LE...
2182
2183
  
  	BT_DBG("%s", hdev->name);
52087a792   Luiz Augusto von Dentz   Bluetooth: make u...
2184
2185
  	if (!hci_conn_num(hdev, LE_LINK))
  		return;
6ed58ec52   Ville Tervo   Bluetooth: Use LE...
2186
2187
2188
  	if (!test_bit(HCI_RAW, &hdev->flags)) {
  		/* LE tx timeout must be longer than maximum
  		 * link supervision timeout (40.9 seconds) */
bae1f5d94   Ville Tervo   Bluetooth: Treat ...
2189
  		if (!hdev->le_cnt && hdev->le_pkts &&
6ed58ec52   Ville Tervo   Bluetooth: Use LE...
2190
  				time_after(jiffies, hdev->le_last_tx + HZ * 45))
bae1f5d94   Ville Tervo   Bluetooth: Treat ...
2191
  			hci_link_tx_to(hdev, LE_LINK);
6ed58ec52   Ville Tervo   Bluetooth: Use LE...
2192
2193
2194
  	}
  
  	cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt;
02b20f0bb   Luiz Augusto von Dentz   Bluetooth: recalc...
2195
  	tmp = cnt;
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
2196
  	while (cnt && (chan = hci_chan_sent(hdev, LE_LINK, &quote))) {
ec1cce24d   Luiz Augusto von Dentz   Bluetooth: handle...
2197
2198
  		u32 priority = (skb_peek(&chan->data_q))->priority;
  		while (quote-- && (skb = skb_peek(&chan->data_q))) {
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
2199
2200
  			BT_DBG("chan %p skb %p len %d priority %u", chan, skb,
  					skb->len, skb->priority);
6ed58ec52   Ville Tervo   Bluetooth: Use LE...
2201

ec1cce24d   Luiz Augusto von Dentz   Bluetooth: handle...
2202
2203
2204
2205
2206
  			/* Stop if priority has changed */
  			if (skb->priority < priority)
  				break;
  
  			skb = skb_dequeue(&chan->data_q);
6ed58ec52   Ville Tervo   Bluetooth: Use LE...
2207
2208
2209
2210
  			hci_send_frame(skb);
  			hdev->le_last_tx = jiffies;
  
  			cnt--;
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
2211
2212
  			chan->sent++;
  			chan->conn->sent++;
6ed58ec52   Ville Tervo   Bluetooth: Use LE...
2213
2214
  		}
  	}
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
2215

6ed58ec52   Ville Tervo   Bluetooth: Use LE...
2216
2217
2218
2219
  	if (hdev->le_pkts)
  		hdev->le_cnt = cnt;
  	else
  		hdev->acl_cnt = cnt;
02b20f0bb   Luiz Augusto von Dentz   Bluetooth: recalc...
2220
2221
2222
  
  	if (cnt != tmp)
  		hci_prio_recalculate(hdev, LE_LINK);
6ed58ec52   Ville Tervo   Bluetooth: Use LE...
2223
  }
3eff45eaf   Gustavo F. Padovan   Bluetooth: conver...
2224
  static void hci_tx_work(struct work_struct *work)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2225
  {
3eff45eaf   Gustavo F. Padovan   Bluetooth: conver...
2226
  	struct hci_dev *hdev = container_of(work, struct hci_dev, tx_work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2227
  	struct sk_buff *skb;
6ed58ec52   Ville Tervo   Bluetooth: Use LE...
2228
2229
  	BT_DBG("%s acl %d sco %d le %d", hdev->name, hdev->acl_cnt,
  		hdev->sco_cnt, hdev->le_cnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2230
2231
2232
2233
2234
2235
  
  	/* Schedule queues and send stuff to HCI driver */
  
  	hci_sched_acl(hdev);
  
  	hci_sched_sco(hdev);
b6a0dc822   Marcel Holtmann   [Bluetooth] Add s...
2236
  	hci_sched_esco(hdev);
6ed58ec52   Ville Tervo   Bluetooth: Use LE...
2237
  	hci_sched_le(hdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2238
2239
2240
  	/* Send next queued raw (unknown type) packet */
  	while ((skb = skb_dequeue(&hdev->raw_q)))
  		hci_send_frame(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2241
  }
25985edce   Lucas De Marchi   Fix common misspe...
2242
  /* ----- HCI RX task (incoming data processing) ----- */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
  
  /* ACL data packet */
  static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)
  {
  	struct hci_acl_hdr *hdr = (void *) skb->data;
  	struct hci_conn *conn;
  	__u16 handle, flags;
  
  	skb_pull(skb, HCI_ACL_HDR_SIZE);
  
  	handle = __le16_to_cpu(hdr->handle);
  	flags  = hci_flags(handle);
  	handle = hci_handle(handle);
  
  	BT_DBG("%s len %d handle 0x%x flags 0x%x", hdev->name, skb->len, handle, flags);
  
  	hdev->stat.acl_rx++;
  
  	hci_dev_lock(hdev);
  	conn = hci_conn_hash_lookup_handle(hdev, handle);
  	hci_dev_unlock(hdev);
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
2264

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2265
  	if (conn) {
65983fc7b   Mat Martineau   Bluetooth: Incomi...
2266
  		hci_conn_enter_active_mode(conn, BT_POWER_FORCE_ACTIVE_OFF);
04837f644   Marcel Holtmann   [Bluetooth] Add a...
2267

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2268
  		/* Send to upper protocol */
686ebf283   Ulisses Furquim   Bluetooth: Make H...
2269
2270
  		l2cap_recv_acldata(conn, skb, flags);
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2271
  	} else {
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
2272
  		BT_ERR("%s ACL packet for unknown connection handle %d",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
  			hdev->name, handle);
  	}
  
  	kfree_skb(skb);
  }
  
  /* SCO data packet */
  static inline void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
  {
  	struct hci_sco_hdr *hdr = (void *) skb->data;
  	struct hci_conn *conn;
  	__u16 handle;
  
  	skb_pull(skb, HCI_SCO_HDR_SIZE);
  
  	handle = __le16_to_cpu(hdr->handle);
  
  	BT_DBG("%s len %d handle 0x%x", hdev->name, skb->len, handle);
  
  	hdev->stat.sco_rx++;
  
  	hci_dev_lock(hdev);
  	conn = hci_conn_hash_lookup_handle(hdev, handle);
  	hci_dev_unlock(hdev);
  
  	if (conn) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2299
  		/* Send to upper protocol */
686ebf283   Ulisses Furquim   Bluetooth: Make H...
2300
2301
  		sco_recv_scodata(conn, skb);
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2302
  	} else {
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
2303
  		BT_ERR("%s SCO packet for unknown connection handle %d",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2304
2305
2306
2307
2308
  			hdev->name, handle);
  	}
  
  	kfree_skb(skb);
  }
b78752cc7   Marcel Holtmann   Bluetooth: Proces...
2309
  static void hci_rx_work(struct work_struct *work)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2310
  {
b78752cc7   Marcel Holtmann   Bluetooth: Proces...
2311
  	struct hci_dev *hdev = container_of(work, struct hci_dev, rx_work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2312
2313
2314
  	struct sk_buff *skb;
  
  	BT_DBG("%s", hdev->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2315
2316
2317
  	while ((skb = skb_dequeue(&hdev->rx_q))) {
  		if (atomic_read(&hdev->promisc)) {
  			/* Send copy to the sockets */
eec8d2bcc   Johan Hedberg   Bluetooth: Add su...
2318
  			hci_send_to_sock(hdev, skb, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2319
2320
2321
2322
2323
2324
2325
2326
2327
  		}
  
  		if (test_bit(HCI_RAW, &hdev->flags)) {
  			kfree_skb(skb);
  			continue;
  		}
  
  		if (test_bit(HCI_INIT, &hdev->flags)) {
  			/* Don't process data packets in this states. */
0d48d9394   Marcel Holtmann   [Bluetooth]: Move...
2328
  			switch (bt_cb(skb)->pkt_type) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2329
2330
2331
2332
  			case HCI_ACLDATA_PKT:
  			case HCI_SCODATA_PKT:
  				kfree_skb(skb);
  				continue;
3ff50b799   Stephen Hemminger   [NET]: cleanup ex...
2333
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2334
2335
2336
  		}
  
  		/* Process frame */
0d48d9394   Marcel Holtmann   [Bluetooth]: Move...
2337
  		switch (bt_cb(skb)->pkt_type) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2338
  		case HCI_EVENT_PKT:
b78752cc7   Marcel Holtmann   Bluetooth: Proces...
2339
  			BT_DBG("%s Event packet", hdev->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
  			hci_event_packet(hdev, skb);
  			break;
  
  		case HCI_ACLDATA_PKT:
  			BT_DBG("%s ACL data packet", hdev->name);
  			hci_acldata_packet(hdev, skb);
  			break;
  
  		case HCI_SCODATA_PKT:
  			BT_DBG("%s SCO data packet", hdev->name);
  			hci_scodata_packet(hdev, skb);
  			break;
  
  		default:
  			kfree_skb(skb);
  			break;
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2358
  }
c347b765f   Gustavo F. Padovan   Bluetooth: Move c...
2359
  static void hci_cmd_work(struct work_struct *work)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2360
  {
c347b765f   Gustavo F. Padovan   Bluetooth: Move c...
2361
  	struct hci_dev *hdev = container_of(work, struct hci_dev, cmd_work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2362
2363
2364
  	struct sk_buff *skb;
  
  	BT_DBG("%s cmd %d", hdev->name, atomic_read(&hdev->cmd_cnt));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2365
  	/* Send queued commands */
5a08ecced   Andrei Emeltchenko   Bluetooth: Do not...
2366
2367
2368
2369
  	if (atomic_read(&hdev->cmd_cnt)) {
  		skb = skb_dequeue(&hdev->cmd_q);
  		if (!skb)
  			return;
7585b97a4   Wei Yongjun   Bluetooth: Remove...
2370
  		kfree_skb(hdev->sent_cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2371

70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
2372
2373
  		hdev->sent_cmd = skb_clone(skb, GFP_ATOMIC);
  		if (hdev->sent_cmd) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2374
2375
  			atomic_dec(&hdev->cmd_cnt);
  			hci_send_frame(skb);
7bdb8a5cf   Szymon Janc   Bluetooth: Don't ...
2376
2377
2378
2379
  			if (test_bit(HCI_RESET, &hdev->flags))
  				del_timer(&hdev->cmd_timer);
  			else
  				mod_timer(&hdev->cmd_timer,
6bd32326c   Ville Tervo   Bluetooth: Use pr...
2380
  				  jiffies + msecs_to_jiffies(HCI_CMD_TIMEOUT));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2381
2382
  		} else {
  			skb_queue_head(&hdev->cmd_q, skb);
c347b765f   Gustavo F. Padovan   Bluetooth: Move c...
2383
  			queue_work(hdev->workqueue, &hdev->cmd_work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2384
2385
2386
  		}
  	}
  }
2519a1fc8   Andre Guedes   Bluetooth: Create...
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
  
  int hci_do_inquiry(struct hci_dev *hdev, u8 length)
  {
  	/* General inquiry access code (GIAC) */
  	u8 lap[3] = { 0x33, 0x8b, 0x9e };
  	struct hci_cp_inquiry cp;
  
  	BT_DBG("%s", hdev->name);
  
  	if (test_bit(HCI_INQUIRY, &hdev->flags))
  		return -EINPROGRESS;
  
  	memset(&cp, 0, sizeof(cp));
  	memcpy(&cp.lap, lap, sizeof(cp.lap));
  	cp.length  = length;
  
  	return hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
  }
023d50498   Andre Guedes   Bluetooth: Create...
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
  
  int hci_cancel_inquiry(struct hci_dev *hdev)
  {
  	BT_DBG("%s", hdev->name);
  
  	if (!test_bit(HCI_INQUIRY, &hdev->flags))
  		return -EPERM;
  
  	return hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
  }
7784d78f1   Andrei Emeltchenko   Bluetooth: making...
2415
2416
2417
  
  module_param(enable_hs, bool, 0644);
  MODULE_PARM_DESC(enable_hs, "Enable High Speed");