OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [bluetooth/] [hci_ldisc.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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
 * BlueZ HCI UART driver.
27
 *
28
 * $Id: hci_ldisc.c,v 1.1.1.1 2004-04-15 02:29:46 phoenix Exp $
29
 */
30
#define VERSION "2.1"
31
 
32
#include <linux/config.h>
33
#include <linux/module.h>
34
 
35
#include <linux/version.h>
36
#include <linux/config.h>
37
#include <linux/kernel.h>
38
#include <linux/init.h>
39
#include <linux/sched.h>
40
#include <linux/types.h>
41
#include <linux/fcntl.h>
42
#include <linux/interrupt.h>
43
#include <linux/ptrace.h>
44
#include <linux/poll.h>
45
 
46
#include <linux/slab.h>
47
#include <linux/tty.h>
48
#include <linux/errno.h>
49
#include <linux/string.h>
50
#include <linux/signal.h>
51
#include <linux/ioctl.h>
52
#include <linux/skbuff.h>
53
 
54
#include <net/bluetooth/bluetooth.h>
55
#include <net/bluetooth/hci_core.h>
56
#include "hci_uart.h"
57
 
58
#ifndef HCI_UART_DEBUG
59
#undef  BT_DBG
60
#define BT_DBG( A... )
61
#undef  BT_DMP
62
#define BT_DMP( A... )
63
#endif
64
 
65
static struct hci_uart_proto *hup[HCI_UART_MAX_PROTO];
66
 
67
int hci_uart_register_proto(struct hci_uart_proto *p)
68
{
69
        if (p->id >= HCI_UART_MAX_PROTO)
70
                return -EINVAL;
71
 
72
        if (hup[p->id])
73
                return -EEXIST;
74
 
75
        hup[p->id] = p;
76
        return 0;
77
}
78
 
79
int hci_uart_unregister_proto(struct hci_uart_proto *p)
80
{
81
        if (p->id >= HCI_UART_MAX_PROTO)
82
                return -EINVAL;
83
 
84
        if (!hup[p->id])
85
                return -EINVAL;
86
 
87
        hup[p->id] = NULL;
88
        return 0;
89
}
90
 
91
static struct hci_uart_proto *hci_uart_get_proto(unsigned int id)
92
{
93
        if (id >= HCI_UART_MAX_PROTO)
94
                return NULL;
95
        return hup[id];
96
}
97
 
98
static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type)
99
{
100
        struct hci_dev *hdev = &hu->hdev;
101
 
102
        /* Update HCI stat counters */
103
        switch (pkt_type) {
104
        case HCI_COMMAND_PKT:
105
                hdev->stat.cmd_tx++;
106
                break;
107
 
108
        case HCI_ACLDATA_PKT:
109
                hdev->stat.acl_tx++;
110
                break;
111
 
112
        case HCI_SCODATA_PKT:
113
                hdev->stat.cmd_tx++;
114
                break;
115
        }
116
}
117
 
118
static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu)
119
{
120
        struct sk_buff *skb = hu->tx_skb;
121
        if (!skb)
122
                skb = hu->proto->dequeue(hu);
123
        else
124
                hu->tx_skb = NULL;
125
        return skb;
126
}
127
 
128
int hci_uart_tx_wakeup(struct hci_uart *hu)
129
{
130
        struct tty_struct *tty = hu->tty;
131
        struct hci_dev *hdev = &hu->hdev;
132
        struct sk_buff *skb;
133
 
134
        if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) {
135
                set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
136
                return 0;
137
        }
138
 
139
        BT_DBG("");
140
 
141
restart:
142
        clear_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
143
 
144
        while ((skb = hci_uart_dequeue(hu))) {
145
                int len;
146
 
147
                set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
148
                len = tty->driver.write(tty, 0, skb->data, skb->len);
149
                hdev->stat.byte_tx += len;
150
 
151
                skb_pull(skb, len);
152
                if (skb->len) {
153
                        hu->tx_skb = skb;
154
                        break;
155
                }
156
 
157
                hci_uart_tx_complete(hu, skb->pkt_type);
158
                kfree_skb(skb);
159
        }
160
 
161
        if (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state))
162
                goto restart;
163
 
164
        clear_bit(HCI_UART_SENDING, &hu->tx_state);
165
        return 0;
166
}
167
 
168
/* ------- Interface to HCI layer ------ */
169
/* Initialize device */
170
static int hci_uart_open(struct hci_dev *hdev)
171
{
172
        BT_DBG("%s %p", hdev->name, hdev);
173
 
174
        /* Nothing to do for UART driver */
175
 
176
        set_bit(HCI_RUNNING, &hdev->flags);
177
        return 0;
178
}
179
 
180
/* Reset device */
181
static int hci_uart_flush(struct hci_dev *hdev)
182
{
183
        struct hci_uart *hu  = (struct hci_uart *) hdev->driver_data;
184
        struct tty_struct *tty = hu->tty;
185
 
186
        BT_DBG("hdev %p tty %p", hdev, tty);
187
 
188
        if (hu->tx_skb) {
189
                kfree_skb(hu->tx_skb); hu->tx_skb = NULL;
190
        }
191
 
192
        /* Flush any pending characters in the driver and discipline. */
193
        if (tty->ldisc.flush_buffer)
194
                tty->ldisc.flush_buffer(tty);
195
 
196
        if (tty->driver.flush_buffer)
197
                tty->driver.flush_buffer(tty);
198
 
199
        if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
200
                hu->proto->flush(hu);
201
 
202
        return 0;
203
}
204
 
205
/* Close device */
206
static int hci_uart_close(struct hci_dev *hdev)
207
{
208
        BT_DBG("hdev %p", hdev);
209
 
210
        if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
211
                return 0;
212
 
213
        hci_uart_flush(hdev);
214
        return 0;
215
}
216
 
217
/* Send frames from HCI layer */
218
static int hci_uart_send_frame(struct sk_buff *skb)
219
{
220
        struct hci_dev* hdev = (struct hci_dev *) skb->dev;
221
        struct tty_struct *tty;
222
        struct hci_uart *hu;
223
 
224
        if (!hdev) {
225
                BT_ERR("Frame for uknown device (hdev=NULL)");
226
                return -ENODEV;
227
        }
228
 
229
        if (!test_bit(HCI_RUNNING, &hdev->flags))
230
                return -EBUSY;
231
 
232
        hu = (struct hci_uart *) hdev->driver_data;
233
        tty = hu->tty;
234
 
235
        BT_DBG("%s: type %d len %d", hdev->name, skb->pkt_type, skb->len);
236
 
237
        hu->proto->enqueue(hu, skb);
238
 
239
        hci_uart_tx_wakeup(hu);
240
        return 0;
241
}
242
 
243
static void hci_uart_destruct(struct hci_dev *hdev)
244
{
245
        struct hci_uart *hu;
246
 
247
        if (!hdev) return;
248
 
249
        BT_DBG("%s", hdev->name);
250
 
251
        hu = (struct hci_uart *) hdev->driver_data;
252
        kfree(hu);
253
 
254
        MOD_DEC_USE_COUNT;
255
}
256
 
257
/* ------ LDISC part ------ */
258
/* hci_uart_tty_open
259
 *
260
 *     Called when line discipline changed to HCI_UART.
261
 *
262
 * Arguments:
263
 *     tty    pointer to tty info structure
264
 * Return Value:
265
 *     0 if success, otherwise error code
266
 */
267
static int hci_uart_tty_open(struct tty_struct *tty)
268
{
269
        struct hci_uart *hu = (void *) tty->disc_data;
270
 
271
        BT_DBG("tty %p", tty);
272
 
273
        if (hu)
274
                return -EEXIST;
275
 
276
        if (!(hu = kmalloc(sizeof(struct hci_uart), GFP_KERNEL))) {
277
                BT_ERR("Can't allocate controll structure");
278
                return -ENFILE;
279
        }
280
        memset(hu, 0, sizeof(struct hci_uart));
281
 
282
        tty->disc_data = hu;
283
        hu->tty = tty;
284
 
285
        spin_lock_init(&hu->rx_lock);
286
 
287
        /* Flush any pending characters in the driver and line discipline */
288
        if (tty->ldisc.flush_buffer)
289
                tty->ldisc.flush_buffer(tty);
290
 
291
        if (tty->driver.flush_buffer)
292
                tty->driver.flush_buffer(tty);
293
 
294
        MOD_INC_USE_COUNT;
295
        return 0;
296
}
297
 
298
/* hci_uart_tty_close()
299
 *
300
 *    Called when the line discipline is changed to something
301
 *    else, the tty is closed, or the tty detects a hangup.
302
 */
303
static void hci_uart_tty_close(struct tty_struct *tty)
304
{
305
        struct hci_uart *hu = (void *)tty->disc_data;
306
 
307
        BT_DBG("tty %p", tty);
308
 
309
        /* Detach from the tty */
310
        tty->disc_data = NULL;
311
 
312
        if (hu) {
313
                struct hci_dev *hdev = &hu->hdev;
314
                hci_uart_close(hdev);
315
 
316
                if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
317
                        hu->proto->close(hu);
318
                        hci_unregister_dev(hdev);
319
                }
320
 
321
                MOD_DEC_USE_COUNT;
322
        }
323
}
324
 
325
/* hci_uart_tty_wakeup()
326
 *
327
 *    Callback for transmit wakeup. Called when low level
328
 *    device driver can accept more send data.
329
 *
330
 * Arguments:        tty    pointer to associated tty instance data
331
 * Return Value:    None
332
 */
333
static void hci_uart_tty_wakeup(struct tty_struct *tty)
334
{
335
        struct hci_uart *hu = (void *)tty->disc_data;
336
 
337
        BT_DBG("");
338
 
339
        if (!hu)
340
                return;
341
 
342
        clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
343
 
344
        if (tty != hu->tty)
345
                return;
346
 
347
        if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
348
                hci_uart_tx_wakeup(hu);
349
}
350
 
351
/* hci_uart_tty_room()
352
 *
353
 *    Callback function from tty driver. Return the amount of
354
 *    space left in the receiver's buffer to decide if remote
355
 *    transmitter is to be throttled.
356
 *
357
 * Arguments:        tty    pointer to associated tty instance data
358
 * Return Value:    number of bytes left in receive buffer
359
 */
360
static int hci_uart_tty_room (struct tty_struct *tty)
361
{
362
        return 65536;
363
}
364
 
365
/* hci_uart_tty_receive()
366
 *
367
 *     Called by tty low level driver when receive data is
368
 *     available.
369
 *
370
 * Arguments:  tty          pointer to tty isntance data
371
 *             data         pointer to received data
372
 *             flags        pointer to flags for data
373
 *             count        count of received data in bytes
374
 *
375
 * Return Value:    None
376
 */
377
static void hci_uart_tty_receive(struct tty_struct *tty, const __u8 *data, char *flags, int count)
378
{
379
        struct hci_uart *hu = (void *)tty->disc_data;
380
 
381
        if (!hu || tty != hu->tty)
382
                return;
383
 
384
        if (!test_bit(HCI_UART_PROTO_SET, &hu->flags))
385
                return;
386
 
387
        spin_lock(&hu->rx_lock);
388
        hu->proto->recv(hu, (void *) data, count);
389
        hu->hdev.stat.byte_rx += count;
390
        spin_unlock(&hu->rx_lock);
391
 
392
        if (test_and_clear_bit(TTY_THROTTLED,&tty->flags) && tty->driver.unthrottle)
393
                tty->driver.unthrottle(tty);
394
}
395
 
396
static int hci_uart_register_dev(struct hci_uart *hu)
397
{
398
        struct hci_dev *hdev;
399
 
400
        BT_DBG("");
401
 
402
        /* Initialize and register HCI device */
403
        hdev = &hu->hdev;
404
 
405
        hdev->type = HCI_UART;
406
        hdev->driver_data = hu;
407
 
408
        hdev->open  = hci_uart_open;
409
        hdev->close = hci_uart_close;
410
        hdev->flush = hci_uart_flush;
411
        hdev->send  = hci_uart_send_frame;
412
        hdev->destruct = hci_uart_destruct;
413
 
414
        if (hci_register_dev(hdev) < 0) {
415
                BT_ERR("Can't register HCI device %s", hdev->name);
416
                return -ENODEV;
417
        }
418
        MOD_INC_USE_COUNT;
419
        return 0;
420
}
421
 
422
static int hci_uart_set_proto(struct hci_uart *hu, int id)
423
{
424
        struct hci_uart_proto *p;
425
        int err;
426
 
427
        p = hci_uart_get_proto(id);
428
        if (!p)
429
                return -EPROTONOSUPPORT;
430
 
431
        err = p->open(hu);
432
        if (err)
433
                return err;
434
 
435
        hu->proto = p;
436
 
437
        err = hci_uart_register_dev(hu);
438
        if (err) {
439
                p->close(hu);
440
                return err;
441
        }
442
        return 0;
443
}
444
 
445
/* hci_uart_tty_ioctl()
446
 *
447
 *    Process IOCTL system call for the tty device.
448
 *
449
 * Arguments:
450
 *
451
 *    tty        pointer to tty instance data
452
 *    file       pointer to open file object for device
453
 *    cmd        IOCTL command code
454
 *    arg        argument for IOCTL call (cmd dependent)
455
 *
456
 * Return Value:    Command dependent
457
 */
458
static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
459
                            unsigned int cmd, unsigned long arg)
460
{
461
        struct hci_uart *hu = (void *)tty->disc_data;
462
        int err = 0;
463
 
464
        BT_DBG("");
465
 
466
        /* Verify the status of the device */
467
        if (!hu)
468
                return -EBADF;
469
 
470
        switch (cmd) {
471
        case HCIUARTSETPROTO:
472
                if (!test_and_set_bit(HCI_UART_PROTO_SET, &hu->flags)) {
473
                        err = hci_uart_set_proto(hu, arg);
474
                        if (err) {
475
                                clear_bit(HCI_UART_PROTO_SET, &hu->flags);
476
                                return err;
477
                        }
478
                        tty->low_latency = 1;
479
                } else
480
                        return -EBUSY;
481
 
482
        case HCIUARTGETPROTO:
483
                if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
484
                        return hu->proto->id;
485
                return -EUNATCH;
486
 
487
        default:
488
                err = n_tty_ioctl(tty, file, cmd, arg);
489
                break;
490
        };
491
 
492
        return err;
493
}
494
 
495
/*
496
 * We don't provide read/write/poll interface for user space.
497
 */
498
static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file, unsigned char *buf, size_t nr)
499
{
500
        return 0;
501
}
502
static ssize_t hci_uart_tty_write(struct tty_struct *tty, struct file *file, const unsigned char *data, size_t count)
503
{
504
        return 0;
505
}
506
static unsigned int hci_uart_tty_poll(struct tty_struct *tty, struct file *filp, poll_table *wait)
507
{
508
        return 0;
509
}
510
 
511
#ifdef CONFIG_BLUEZ_HCIUART_H4
512
int h4_init(void);
513
int h4_deinit(void);
514
#endif
515
#ifdef CONFIG_BLUEZ_HCIUART_BCSP
516
int bcsp_init(void);
517
int bcsp_deinit(void);
518
#endif
519
 
520
int __init hci_uart_init(void)
521
{
522
        static struct tty_ldisc hci_uart_ldisc;
523
        int err;
524
 
525
        BT_INFO("BlueZ HCI UART driver ver %s Copyright (C) 2000,2001 Qualcomm Inc",
526
                VERSION);
527
        BT_INFO("Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>");
528
 
529
        /* Register the tty discipline */
530
 
531
        memset(&hci_uart_ldisc, 0, sizeof (hci_uart_ldisc));
532
        hci_uart_ldisc.magic       = TTY_LDISC_MAGIC;
533
        hci_uart_ldisc.name        = "n_hci";
534
        hci_uart_ldisc.open        = hci_uart_tty_open;
535
        hci_uart_ldisc.close       = hci_uart_tty_close;
536
        hci_uart_ldisc.read        = hci_uart_tty_read;
537
        hci_uart_ldisc.write       = hci_uart_tty_write;
538
        hci_uart_ldisc.ioctl       = hci_uart_tty_ioctl;
539
        hci_uart_ldisc.poll        = hci_uart_tty_poll;
540
        hci_uart_ldisc.receive_room= hci_uart_tty_room;
541
        hci_uart_ldisc.receive_buf = hci_uart_tty_receive;
542
        hci_uart_ldisc.write_wakeup= hci_uart_tty_wakeup;
543
 
544
        if ((err = tty_register_ldisc(N_HCI, &hci_uart_ldisc))) {
545
                BT_ERR("Can't register HCI line discipline (%d)", err);
546
                return err;
547
        }
548
 
549
#ifdef CONFIG_BLUEZ_HCIUART_H4
550
        h4_init();
551
#endif
552
#ifdef CONFIG_BLUEZ_HCIUART_BCSP
553
        bcsp_init();
554
#endif
555
 
556
        return 0;
557
}
558
 
559
void hci_uart_cleanup(void)
560
{
561
        int err;
562
 
563
#ifdef CONFIG_BLUEZ_HCIUART_H4
564
        h4_deinit();
565
#endif
566
#ifdef CONFIG_BLUEZ_HCIUART_BCSP
567
        bcsp_deinit();
568
#endif
569
 
570
        /* Release tty registration of line discipline */
571
        if ((err = tty_register_ldisc(N_HCI, NULL)))
572
                BT_ERR("Can't unregister HCI line discipline (%d)", err);
573
}
574
 
575
module_init(hci_uart_init);
576
module_exit(hci_uart_cleanup);
577
 
578
MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>");
579
MODULE_DESCRIPTION("BlueZ HCI UART driver ver " VERSION);
580
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.