aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth/hci_ldisc.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/bluetooth/hci_ldisc.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/bluetooth/hci_ldisc.c')
-rw-r--r--drivers/bluetooth/hci_ldisc.c593
1 files changed, 593 insertions, 0 deletions
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
new file mode 100644
index 000000000000..9075bbb56ad4
--- /dev/null
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -0,0 +1,593 @@
1/*
2 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
4
5 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 SOFTWARE IS DISCLAIMED.
23*/
24
25/*
26 * Bluetooth HCI UART driver.
27 *
28 * $Id: hci_ldisc.c,v 1.5 2002/10/02 18:37:20 maxk Exp $
29 */
30#define VERSION "2.1"
31
32#include <linux/config.h>
33#include <linux/module.h>
34
35#include <linux/kernel.h>
36#include <linux/init.h>
37#include <linux/sched.h>
38#include <linux/types.h>
39#include <linux/fcntl.h>
40#include <linux/interrupt.h>
41#include <linux/ptrace.h>
42#include <linux/poll.h>
43
44#include <linux/slab.h>
45#include <linux/tty.h>
46#include <linux/errno.h>
47#include <linux/string.h>
48#include <linux/signal.h>
49#include <linux/ioctl.h>
50#include <linux/skbuff.h>
51
52#include <net/bluetooth/bluetooth.h>
53#include <net/bluetooth/hci_core.h>
54
55#include "hci_uart.h"
56
57#ifndef CONFIG_BT_HCIUART_DEBUG
58#undef BT_DBG
59#define BT_DBG( A... )
60#undef BT_DMP
61#define BT_DMP( A... )
62#endif
63
64static int reset = 0;
65
66static struct hci_uart_proto *hup[HCI_UART_MAX_PROTO];
67
68int hci_uart_register_proto(struct hci_uart_proto *p)
69{
70 if (p->id >= HCI_UART_MAX_PROTO)
71 return -EINVAL;
72
73 if (hup[p->id])
74 return -EEXIST;
75
76 hup[p->id] = p;
77 return 0;
78}
79
80int hci_uart_unregister_proto(struct hci_uart_proto *p)
81{
82 if (p->id >= HCI_UART_MAX_PROTO)
83 return -EINVAL;
84
85 if (!hup[p->id])
86 return -EINVAL;
87
88 hup[p->id] = NULL;
89 return 0;
90}
91
92static struct hci_uart_proto *hci_uart_get_proto(unsigned int id)
93{
94 if (id >= HCI_UART_MAX_PROTO)
95 return NULL;
96 return hup[id];
97}
98
99static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type)
100{
101 struct hci_dev *hdev = hu->hdev;
102
103 /* Update HCI stat counters */
104 switch (pkt_type) {
105 case HCI_COMMAND_PKT:
106 hdev->stat.cmd_tx++;
107 break;
108
109 case HCI_ACLDATA_PKT:
110 hdev->stat.acl_tx++;
111 break;
112
113 case HCI_SCODATA_PKT:
114 hdev->stat.cmd_tx++;
115 break;
116 }
117}
118
119static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu)
120{
121 struct sk_buff *skb = hu->tx_skb;
122 if (!skb)
123 skb = hu->proto->dequeue(hu);
124 else
125 hu->tx_skb = NULL;
126 return skb;
127}
128
129int hci_uart_tx_wakeup(struct hci_uart *hu)
130{
131 struct tty_struct *tty = hu->tty;
132 struct hci_dev *hdev = hu->hdev;
133 struct sk_buff *skb;
134
135 if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) {
136 set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
137 return 0;
138 }
139
140 BT_DBG("");
141
142restart:
143 clear_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
144
145 while ((skb = hci_uart_dequeue(hu))) {
146 int len;
147
148 set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
149 len = tty->driver->write(tty, skb->data, skb->len);
150 hdev->stat.byte_tx += len;
151
152 skb_pull(skb, len);
153 if (skb->len) {
154 hu->tx_skb = skb;
155 break;
156 }
157
158 hci_uart_tx_complete(hu, skb->pkt_type);
159 kfree_skb(skb);
160 }
161
162 if (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state))
163 goto restart;
164
165 clear_bit(HCI_UART_SENDING, &hu->tx_state);
166 return 0;
167}
168
169/* ------- Interface to HCI layer ------ */
170/* Initialize device */
171static int hci_uart_open(struct hci_dev *hdev)
172{
173 BT_DBG("%s %p", hdev->name, hdev);
174
175 /* Nothing to do for UART driver */
176
177 set_bit(HCI_RUNNING, &hdev->flags);
178 return 0;
179}
180
181/* Reset device */
182static int hci_uart_flush(struct hci_dev *hdev)
183{
184 struct hci_uart *hu = (struct hci_uart *) hdev->driver_data;
185 struct tty_struct *tty = hu->tty;
186
187 BT_DBG("hdev %p tty %p", hdev, tty);
188
189 if (hu->tx_skb) {
190 kfree_skb(hu->tx_skb); hu->tx_skb = NULL;
191 }
192
193 /* Flush any pending characters in the driver and discipline. */
194 tty_ldisc_flush(tty);
195 if (tty->driver->flush_buffer)
196 tty->driver->flush_buffer(tty);
197
198 if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
199 hu->proto->flush(hu);
200
201 return 0;
202}
203
204/* Close device */
205static int hci_uart_close(struct hci_dev *hdev)
206{
207 BT_DBG("hdev %p", hdev);
208
209 if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
210 return 0;
211
212 hci_uart_flush(hdev);
213 return 0;
214}
215
216/* Send frames from HCI layer */
217static int hci_uart_send_frame(struct sk_buff *skb)
218{
219 struct hci_dev* hdev = (struct hci_dev *) skb->dev;
220 struct tty_struct *tty;
221 struct hci_uart *hu;
222
223 if (!hdev) {
224 BT_ERR("Frame for uknown device (hdev=NULL)");
225 return -ENODEV;
226 }
227
228 if (!test_bit(HCI_RUNNING, &hdev->flags))
229 return -EBUSY;
230
231 hu = (struct hci_uart *) hdev->driver_data;
232 tty = hu->tty;
233
234 BT_DBG("%s: type %d len %d", hdev->name, skb->pkt_type, skb->len);
235
236 hu->proto->enqueue(hu, skb);
237
238 hci_uart_tx_wakeup(hu);
239 return 0;
240}
241
242static void hci_uart_destruct(struct hci_dev *hdev)
243{
244 struct hci_uart *hu;
245
246 if (!hdev) return;
247
248 BT_DBG("%s", hdev->name);
249
250 hu = (struct hci_uart *) hdev->driver_data;
251 kfree(hu);
252}
253
254/* ------ LDISC part ------ */
255/* hci_uart_tty_open
256 *
257 * Called when line discipline changed to HCI_UART.
258 *
259 * Arguments:
260 * tty pointer to tty info structure
261 * Return Value:
262 * 0 if success, otherwise error code
263 */
264static int hci_uart_tty_open(struct tty_struct *tty)
265{
266 struct hci_uart *hu = (void *) tty->disc_data;
267
268 BT_DBG("tty %p", tty);
269
270 if (hu)
271 return -EEXIST;
272
273 if (!(hu = kmalloc(sizeof(struct hci_uart), GFP_KERNEL))) {
274 BT_ERR("Can't allocate controll structure");
275 return -ENFILE;
276 }
277 memset(hu, 0, sizeof(struct hci_uart));
278
279 tty->disc_data = hu;
280 hu->tty = tty;
281
282 spin_lock_init(&hu->rx_lock);
283
284 /* Flush any pending characters in the driver and line discipline. */
285 /* FIXME: why is this needed. Note don't use ldisc_ref here as the
286 open path is before the ldisc is referencable */
287 if (tty->ldisc.flush_buffer)
288 tty->ldisc.flush_buffer(tty);
289
290 if (tty->driver->flush_buffer)
291 tty->driver->flush_buffer(tty);
292
293 return 0;
294}
295
296/* hci_uart_tty_close()
297 *
298 * Called when the line discipline is changed to something
299 * else, the tty is closed, or the tty detects a hangup.
300 */
301static void hci_uart_tty_close(struct tty_struct *tty)
302{
303 struct hci_uart *hu = (void *)tty->disc_data;
304
305 BT_DBG("tty %p", tty);
306
307 /* Detach from the tty */
308 tty->disc_data = NULL;
309
310 if (hu) {
311 struct hci_dev *hdev = hu->hdev;
312 hci_uart_close(hdev);
313
314 if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
315 hu->proto->close(hu);
316 hci_unregister_dev(hdev);
317 hci_free_dev(hdev);
318 }
319 }
320}
321
322/* hci_uart_tty_wakeup()
323 *
324 * Callback for transmit wakeup. Called when low level
325 * device driver can accept more send data.
326 *
327 * Arguments: tty pointer to associated tty instance data
328 * Return Value: None
329 */
330static void hci_uart_tty_wakeup(struct tty_struct *tty)
331{
332 struct hci_uart *hu = (void *)tty->disc_data;
333
334 BT_DBG("");
335
336 if (!hu)
337 return;
338
339 clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
340
341 if (tty != hu->tty)
342 return;
343
344 if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
345 hci_uart_tx_wakeup(hu);
346}
347
348/* hci_uart_tty_room()
349 *
350 * Callback function from tty driver. Return the amount of
351 * space left in the receiver's buffer to decide if remote
352 * transmitter is to be throttled.
353 *
354 * Arguments: tty pointer to associated tty instance data
355 * Return Value: number of bytes left in receive buffer
356 */
357static int hci_uart_tty_room (struct tty_struct *tty)
358{
359 return 65536;
360}
361
362/* hci_uart_tty_receive()
363 *
364 * Called by tty low level driver when receive data is
365 * available.
366 *
367 * Arguments: tty pointer to tty isntance data
368 * data pointer to received data
369 * flags pointer to flags for data
370 * count count of received data in bytes
371 *
372 * Return Value: None
373 */
374static void hci_uart_tty_receive(struct tty_struct *tty, const __u8 *data, char *flags, int count)
375{
376 struct hci_uart *hu = (void *)tty->disc_data;
377
378 if (!hu || tty != hu->tty)
379 return;
380
381 if (!test_bit(HCI_UART_PROTO_SET, &hu->flags))
382 return;
383
384 spin_lock(&hu->rx_lock);
385 hu->proto->recv(hu, (void *) data, count);
386 hu->hdev->stat.byte_rx += count;
387 spin_unlock(&hu->rx_lock);
388
389 if (test_and_clear_bit(TTY_THROTTLED,&tty->flags) && tty->driver->unthrottle)
390 tty->driver->unthrottle(tty);
391}
392
393static int hci_uart_register_dev(struct hci_uart *hu)
394{
395 struct hci_dev *hdev;
396
397 BT_DBG("");
398
399 /* Initialize and register HCI device */
400 hdev = hci_alloc_dev();
401 if (!hdev) {
402 BT_ERR("Can't allocate HCI device");
403 return -ENOMEM;
404 }
405
406 hu->hdev = hdev;
407
408 hdev->type = HCI_UART;
409 hdev->driver_data = hu;
410
411 hdev->open = hci_uart_open;
412 hdev->close = hci_uart_close;
413 hdev->flush = hci_uart_flush;
414 hdev->send = hci_uart_send_frame;
415 hdev->destruct = hci_uart_destruct;
416
417 hdev->owner = THIS_MODULE;
418
419 if (reset)
420 set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks);
421
422 if (hci_register_dev(hdev) < 0) {
423 BT_ERR("Can't register HCI device");
424 hci_free_dev(hdev);
425 return -ENODEV;
426 }
427
428 return 0;
429}
430
431static int hci_uart_set_proto(struct hci_uart *hu, int id)
432{
433 struct hci_uart_proto *p;
434 int err;
435
436 p = hci_uart_get_proto(id);
437 if (!p)
438 return -EPROTONOSUPPORT;
439
440 err = p->open(hu);
441 if (err)
442 return err;
443
444 hu->proto = p;
445
446 err = hci_uart_register_dev(hu);
447 if (err) {
448 p->close(hu);
449 return err;
450 }
451 return 0;
452}
453
454/* hci_uart_tty_ioctl()
455 *
456 * Process IOCTL system call for the tty device.
457 *
458 * Arguments:
459 *
460 * tty pointer to tty instance data
461 * file pointer to open file object for device
462 * cmd IOCTL command code
463 * arg argument for IOCTL call (cmd dependent)
464 *
465 * Return Value: Command dependent
466 */
467static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
468 unsigned int cmd, unsigned long arg)
469{
470 struct hci_uart *hu = (void *)tty->disc_data;
471 int err = 0;
472
473 BT_DBG("");
474
475 /* Verify the status of the device */
476 if (!hu)
477 return -EBADF;
478
479 switch (cmd) {
480 case HCIUARTSETPROTO:
481 if (!test_and_set_bit(HCI_UART_PROTO_SET, &hu->flags)) {
482 err = hci_uart_set_proto(hu, arg);
483 if (err) {
484 clear_bit(HCI_UART_PROTO_SET, &hu->flags);
485 return err;
486 }
487 tty->low_latency = 1;
488 } else
489 return -EBUSY;
490
491 case HCIUARTGETPROTO:
492 if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
493 return hu->proto->id;
494 return -EUNATCH;
495
496 default:
497 err = n_tty_ioctl(tty, file, cmd, arg);
498 break;
499 };
500
501 return err;
502}
503
504/*
505 * We don't provide read/write/poll interface for user space.
506 */
507static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file, unsigned char __user *buf, size_t nr)
508{
509 return 0;
510}
511static ssize_t hci_uart_tty_write(struct tty_struct *tty, struct file *file, const unsigned char *data, size_t count)
512{
513 return 0;
514}
515static unsigned int hci_uart_tty_poll(struct tty_struct *tty, struct file *filp, poll_table *wait)
516{
517 return 0;
518}
519
520#ifdef CONFIG_BT_HCIUART_H4
521int h4_init(void);
522int h4_deinit(void);
523#endif
524#ifdef CONFIG_BT_HCIUART_BCSP
525int bcsp_init(void);
526int bcsp_deinit(void);
527#endif
528
529static int __init hci_uart_init(void)
530{
531 static struct tty_ldisc hci_uart_ldisc;
532 int err;
533
534 BT_INFO("HCI UART driver ver %s", VERSION);
535
536 /* Register the tty discipline */
537
538 memset(&hci_uart_ldisc, 0, sizeof (hci_uart_ldisc));
539 hci_uart_ldisc.magic = TTY_LDISC_MAGIC;
540 hci_uart_ldisc.name = "n_hci";
541 hci_uart_ldisc.open = hci_uart_tty_open;
542 hci_uart_ldisc.close = hci_uart_tty_close;
543 hci_uart_ldisc.read = hci_uart_tty_read;
544 hci_uart_ldisc.write = hci_uart_tty_write;
545 hci_uart_ldisc.ioctl = hci_uart_tty_ioctl;
546 hci_uart_ldisc.poll = hci_uart_tty_poll;
547 hci_uart_ldisc.receive_room= hci_uart_tty_room;
548 hci_uart_ldisc.receive_buf = hci_uart_tty_receive;
549 hci_uart_ldisc.write_wakeup= hci_uart_tty_wakeup;
550 hci_uart_ldisc.owner = THIS_MODULE;
551
552 if ((err = tty_register_ldisc(N_HCI, &hci_uart_ldisc))) {
553 BT_ERR("HCI line discipline registration failed. (%d)", err);
554 return err;
555 }
556
557#ifdef CONFIG_BT_HCIUART_H4
558 h4_init();
559#endif
560#ifdef CONFIG_BT_HCIUART_BCSP
561 bcsp_init();
562#endif
563
564 return 0;
565}
566
567static void __exit hci_uart_exit(void)
568{
569 int err;
570
571#ifdef CONFIG_BT_HCIUART_H4
572 h4_deinit();
573#endif
574#ifdef CONFIG_BT_HCIUART_BCSP
575 bcsp_deinit();
576#endif
577
578 /* Release tty registration of line discipline */
579 if ((err = tty_register_ldisc(N_HCI, NULL)))
580 BT_ERR("Can't unregister HCI line discipline (%d)", err);
581}
582
583module_init(hci_uart_init);
584module_exit(hci_uart_exit);
585
586module_param(reset, bool, 0644);
587MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
588
589MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
590MODULE_DESCRIPTION("Bluetooth HCI UART driver ver " VERSION);
591MODULE_VERSION(VERSION);
592MODULE_LICENSE("GPL");
593MODULE_ALIAS_LDISC(N_HCI);