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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [irda/] [ircomm/] [ircomm_tty.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*********************************************************************
2
 *
3
 * Filename:      ircomm_tty.c
4
 * Version:       1.0
5
 * Description:   IrCOMM serial TTY driver
6
 * Status:        Experimental.
7
 * Author:        Dag Brattli <dagb@cs.uit.no>
8
 * Created at:    Sun Jun  6 21:00:56 1999
9
 * Modified at:   Wed Feb 23 00:09:02 2000
10
 * Modified by:   Dag Brattli <dagb@cs.uit.no>
11
 * Sources:       serial.c and previous IrCOMM work by Takahide Higuchi
12
 *
13
 *     Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
14
 *
15
 *     This program is free software; you can redistribute it and/or
16
 *     modify it under the terms of the GNU General Public License as
17
 *     published by the Free Software Foundation; either version 2 of
18
 *     the License, or (at your option) any later version.
19
 *
20
 *     This program is distributed in the hope that it will be useful,
21
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
 *     GNU General Public License for more details.
24
 *
25
 *     You should have received a copy of the GNU General Public License
26
 *     along with this program; if not, write to the Free Software
27
 *     Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28
 *     MA 02111-1307 USA
29
 *
30
 ********************************************************************/
31
 
32
#include <linux/config.h>
33
#include <linux/init.h>
34
#include <linux/module.h>
35
#include <linux/fs.h>
36
#include <linux/sched.h>
37
#include <linux/termios.h>
38
#include <linux/tty.h>
39
#include <linux/interrupt.h>
40
 
41
#include <asm/segment.h>
42
#include <asm/uaccess.h>
43
 
44
#include <net/irda/irda.h>
45
#include <net/irda/irmod.h>
46
 
47
#include <net/irda/ircomm_core.h>
48
#include <net/irda/ircomm_param.h>
49
#include <net/irda/ircomm_tty_attach.h>
50
#include <net/irda/ircomm_tty.h>
51
 
52
static int  ircomm_tty_open(struct tty_struct *tty, struct file *filp);
53
static void ircomm_tty_close(struct tty_struct * tty, struct file *filp);
54
static int  ircomm_tty_write(struct tty_struct * tty, int from_user,
55
                             const unsigned char *buf, int count);
56
static int  ircomm_tty_write_room(struct tty_struct *tty);
57
static void ircomm_tty_throttle(struct tty_struct *tty);
58
static void ircomm_tty_unthrottle(struct tty_struct *tty);
59
static int  ircomm_tty_chars_in_buffer(struct tty_struct *tty);
60
static void ircomm_tty_flush_buffer(struct tty_struct *tty);
61
static void ircomm_tty_send_xchar(struct tty_struct *tty, char ch);
62
static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout);
63
static void ircomm_tty_hangup(struct tty_struct *tty);
64
static void ircomm_tty_do_softint(void *private_);
65
static void ircomm_tty_shutdown(struct ircomm_tty_cb *self);
66
 
67
static int ircomm_tty_data_indication(void *instance, void *sap,
68
                                      struct sk_buff *skb);
69
static int ircomm_tty_control_indication(void *instance, void *sap,
70
                                         struct sk_buff *skb);
71
static void ircomm_tty_flow_indication(void *instance, void *sap,
72
                                       LOCAL_FLOW cmd);
73
#ifdef CONFIG_PROC_FS
74
static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len,
75
                                int *eof, void *unused);
76
#endif /* CONFIG_PROC_FS */
77
static struct tty_driver driver;
78
static int ircomm_tty_refcount;       /* If we manage several devices */
79
 
80
static struct tty_struct *ircomm_tty_table[NR_PTYS];
81
static struct termios *ircomm_tty_termios[NR_PTYS];
82
static struct termios *ircomm_tty_termios_locked[NR_PTYS];
83
 
84
hashbin_t *ircomm_tty = NULL;
85
 
86
/*
87
 * Function ircomm_tty_init()
88
 *
89
 *    Init IrCOMM TTY layer/driver
90
 *
91
 */
92
int __init ircomm_tty_init(void)
93
{
94
        ircomm_tty = hashbin_new(HB_LOCAL);
95
        if (ircomm_tty == NULL) {
96
                ERROR("%s(), can't allocate hashbin!\n", __FUNCTION__);
97
                return -ENOMEM;
98
        }
99
 
100
        memset(&driver, 0, sizeof(struct tty_driver));
101
        driver.magic           = TTY_DRIVER_MAGIC;
102
        driver.driver_name     = "ircomm";
103
#ifdef CONFIG_DEVFS_FS
104
        driver.name            = "ircomm%d";
105
#else
106
        driver.name            = "ircomm";
107
#endif
108
        driver.major           = IRCOMM_TTY_MAJOR;
109
        driver.minor_start     = IRCOMM_TTY_MINOR;
110
        driver.num             = IRCOMM_TTY_PORTS;
111
        driver.type            = TTY_DRIVER_TYPE_SERIAL;
112
        driver.subtype         = SERIAL_TYPE_NORMAL;
113
        driver.init_termios    = tty_std_termios;
114
        driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
115
        driver.flags           = TTY_DRIVER_REAL_RAW;
116
        driver.refcount        = &ircomm_tty_refcount;
117
        driver.table           = ircomm_tty_table;
118
        driver.termios         = ircomm_tty_termios;
119
        driver.termios_locked  = ircomm_tty_termios_locked;
120
        driver.open            = ircomm_tty_open;
121
        driver.close           = ircomm_tty_close;
122
        driver.write           = ircomm_tty_write;
123
        driver.write_room      = ircomm_tty_write_room;
124
        driver.chars_in_buffer = ircomm_tty_chars_in_buffer;
125
        driver.flush_buffer    = ircomm_tty_flush_buffer;
126
        driver.ioctl           = ircomm_tty_ioctl;
127
        driver.throttle        = ircomm_tty_throttle;
128
        driver.unthrottle      = ircomm_tty_unthrottle;
129
        driver.send_xchar      = ircomm_tty_send_xchar;
130
        driver.set_termios     = ircomm_tty_set_termios;
131
        driver.stop            = ircomm_tty_stop;
132
        driver.start           = ircomm_tty_start;
133
        driver.hangup          = ircomm_tty_hangup;
134
        driver.wait_until_sent = ircomm_tty_wait_until_sent;
135
#ifdef CONFIG_PROC_FS
136
        driver.read_proc       = ircomm_tty_read_proc;
137
#endif /* CONFIG_PROC_FS */
138
        if (tty_register_driver(&driver)) {
139
                ERROR("%s: Couldn't register serial driver\n", __FUNCTION__);
140
                return -1;
141
        }
142
        return 0;
143
}
144
 
145
#ifdef MODULE
146
static void __ircomm_tty_cleanup(struct ircomm_tty_cb *self)
147
{
148
        IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
149
 
150
        ASSERT(self != NULL, return;);
151
        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
152
 
153
        ircomm_tty_shutdown(self);
154
 
155
        self->magic = 0;
156
        kfree(self);
157
}
158
 
159
/*
160
 * Function ircomm_tty_cleanup ()
161
 *
162
 *    Remove IrCOMM TTY layer/driver
163
 *
164
 */
165
void ircomm_tty_cleanup(void)
166
{
167
        int ret;
168
 
169
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
170
 
171
        ret = tty_unregister_driver(&driver);
172
        if (ret) {
173
                ERROR("%s, failed to unregister driver\n", __FUNCTION__);
174
                return;
175
        }
176
 
177
        hashbin_delete(ircomm_tty, (FREE_FUNC) __ircomm_tty_cleanup);
178
}
179
#endif /* MODULE */
180
 
181
/*
182
 * Function ircomm_startup (self)
183
 *
184
 *
185
 *
186
 */
187
static int ircomm_tty_startup(struct ircomm_tty_cb *self)
188
{
189
        notify_t notify;
190
        int ret;
191
 
192
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
193
 
194
        ASSERT(self != NULL, return -1;);
195
        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
196
 
197
        /* Already open */
198
        if (self->flags & ASYNC_INITIALIZED) {
199
                IRDA_DEBUG(2, "%s(), already open so break out!\n", __FUNCTION__);
200
                return 0;
201
        }
202
 
203
        /* Register with IrCOMM */
204
        irda_notify_init(&notify);
205
        /* These callbacks we must handle ourselves */
206
        notify.data_indication       = ircomm_tty_data_indication;
207
        notify.udata_indication      = ircomm_tty_control_indication;
208
        notify.flow_indication       = ircomm_tty_flow_indication;
209
 
210
        /* Use the ircomm_tty interface for these ones */
211
        notify.disconnect_indication = ircomm_tty_disconnect_indication;
212
        notify.connect_confirm       = ircomm_tty_connect_confirm;
213
        notify.connect_indication    = ircomm_tty_connect_indication;
214
        strncpy(notify.name, "ircomm_tty", NOTIFY_MAX_NAME);
215
        notify.instance = self;
216
 
217
        if (!self->ircomm) {
218
                self->ircomm = ircomm_open(&notify, self->service_type,
219
                                           self->line);
220
        }
221
        if (!self->ircomm)
222
                return -ENODEV;
223
 
224
        self->slsap_sel = self->ircomm->slsap_sel;
225
 
226
        /* Connect IrCOMM link with remote device */
227
        ret = ircomm_tty_attach_cable(self);
228
        if (ret < 0) {
229
                ERROR("%s(), error attaching cable!\n", __FUNCTION__);
230
                return ret;
231
        }
232
 
233
        self->flags |= ASYNC_INITIALIZED;
234
 
235
        return 0;
236
}
237
 
238
/*
239
 * Function ircomm_block_til_ready (self, filp)
240
 *
241
 *
242
 *
243
 */
244
static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
245
                                      struct file *filp)
246
{
247
        DECLARE_WAITQUEUE(wait, current);
248
        int             retval;
249
        int             do_clocal = 0, extra_count = 0;
250
        unsigned long   flags;
251
        struct tty_struct *tty;
252
 
253
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
254
 
255
        tty = self->tty;
256
 
257
        if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
258
                /* this is a callout device */
259
                /* just verify that normal device is not in use */
260
                if (self->flags & ASYNC_NORMAL_ACTIVE)
261
                        return -EBUSY;
262
                if ((self->flags & ASYNC_CALLOUT_ACTIVE) &&
263
                    (self->flags & ASYNC_SESSION_LOCKOUT) &&
264
                    (self->session != current->session))
265
                        return -EBUSY;
266
                if ((self->flags & ASYNC_CALLOUT_ACTIVE) &&
267
                    (self->flags & ASYNC_PGRP_LOCKOUT) &&
268
                    (self->pgrp != current->pgrp))
269
                        return -EBUSY;
270
                self->flags |= ASYNC_CALLOUT_ACTIVE;
271
                return 0;
272
        }
273
 
274
        /*
275
         * If non-blocking mode is set, or the port is not enabled,
276
         * then make the check up front and then exit.
277
         */
278
        if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
279
                /* nonblock mode is set or port is not enabled */
280
                /* just verify that callout device is not active */
281
                if (self->flags & ASYNC_CALLOUT_ACTIVE)
282
                        return -EBUSY;
283
                self->flags |= ASYNC_NORMAL_ACTIVE;
284
 
285
                IRDA_DEBUG(1, "%s(), O_NONBLOCK requested!\n", __FUNCTION__);
286
                return 0;
287
        }
288
 
289
        if (self->flags & ASYNC_CALLOUT_ACTIVE) {
290
                if (self->normal_termios.c_cflag & CLOCAL) {
291
                        IRDA_DEBUG(1, "%s(), doing CLOCAL!\n", __FUNCTION__);
292
                        do_clocal = 1;
293
                }
294
        } else {
295
                if (tty->termios->c_cflag & CLOCAL) {
296
                        IRDA_DEBUG(1, "%s(), doing CLOCAL!\n", __FUNCTION__);
297
                        do_clocal = 1;
298
                }
299
        }
300
 
301
        /* Wait for carrier detect and the line to become
302
         * free (i.e., not in use by the callout).  While we are in
303
         * this loop, self->open_count is dropped by one, so that
304
         * mgsl_close() knows when to free things.  We restore it upon
305
         * exit, either normal or abnormal.
306
         */
307
 
308
        retval = 0;
309
        add_wait_queue(&self->open_wait, &wait);
310
 
311
        IRDA_DEBUG(2, "%s(%d):block_til_ready before block on %s open_count=%d\n",
312
              __FILE__,__LINE__, tty->driver.name, self->open_count );
313
 
314
        save_flags(flags); cli();
315
        if (!tty_hung_up_p(filp)) {
316
                extra_count = 1;
317
                self->open_count--;
318
        }
319
        restore_flags(flags);
320
        self->blocked_open++;
321
 
322
        while (1) {
323
                if (!(self->flags & ASYNC_CALLOUT_ACTIVE) &&
324
                    (tty->termios->c_cflag & CBAUD)) {
325
                        save_flags(flags); cli();
326
                        self->settings.dte |= IRCOMM_RTS + IRCOMM_DTR;
327
 
328
                        ircomm_param_request(self, IRCOMM_DTE, TRUE);
329
                        restore_flags(flags);
330
                }
331
 
332
                current->state = TASK_INTERRUPTIBLE;
333
 
334
                if (tty_hung_up_p(filp) || !(self->flags & ASYNC_INITIALIZED)){
335
                        retval = (self->flags & ASYNC_HUP_NOTIFY) ?
336
                                        -EAGAIN : -ERESTARTSYS;
337
                        break;
338
                }
339
 
340
                /*
341
                 * Check if link is ready now. Even if CLOCAL is
342
                 * specified, we cannot return before the IrCOMM link is
343
                 * ready
344
                 */
345
                if (!(self->flags & ASYNC_CALLOUT_ACTIVE) &&
346
                    !(self->flags & ASYNC_CLOSING) &&
347
                    (do_clocal || (self->settings.dce & IRCOMM_CD)) &&
348
                    self->state == IRCOMM_TTY_READY)
349
                {
350
                        break;
351
                }
352
 
353
                if (signal_pending(current)) {
354
                        retval = -ERESTARTSYS;
355
                        break;
356
                }
357
 
358
                IRDA_DEBUG(1, "%s(%d):block_til_ready blocking on %s open_count=%d\n",
359
                      __FILE__,__LINE__, tty->driver.name, self->open_count );
360
 
361
                schedule();
362
        }
363
 
364
        __set_current_state(TASK_RUNNING);
365
        remove_wait_queue(&self->open_wait, &wait);
366
 
367
        if (extra_count)
368
                self->open_count++;
369
        self->blocked_open--;
370
 
371
        IRDA_DEBUG(1, "%s(%d):block_til_ready after blocking on %s open_count=%d\n",
372
              __FILE__,__LINE__, tty->driver.name, self->open_count);
373
 
374
        if (!retval)
375
                self->flags |= ASYNC_NORMAL_ACTIVE;
376
 
377
        return retval;
378
}
379
 
380
/*
381
 * Function ircomm_tty_open (tty, filp)
382
 *
383
 *    This routine is called when a particular tty device is opened. This
384
 *    routine is mandatory; if this routine is not filled in, the attempted
385
 *    open will fail with ENODEV.
386
 */
387
static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
388
{
389
        struct ircomm_tty_cb *self;
390
        int line;
391
        int ret;
392
 
393
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
394
 
395
        MOD_INC_USE_COUNT;
396
        line = MINOR(tty->device) - tty->driver.minor_start;
397
        if ((line < 0) || (line >= IRCOMM_TTY_PORTS)) {
398
                MOD_DEC_USE_COUNT;
399
                return -ENODEV;
400
        }
401
 
402
        /* Check if instance already exists */
403
        self = hashbin_find(ircomm_tty, line, NULL);
404
        if (!self) {
405
                /* No, so make new instance */
406
                self = kmalloc(sizeof(struct ircomm_tty_cb), GFP_KERNEL);
407
                if (self == NULL) {
408
                        ERROR("%s(), kmalloc failed!\n", __FUNCTION__);
409
                        MOD_DEC_USE_COUNT;
410
                        return -ENOMEM;
411
                }
412
                memset(self, 0, sizeof(struct ircomm_tty_cb));
413
 
414
                self->magic = IRCOMM_TTY_MAGIC;
415
                self->flow = FLOW_STOP;
416
 
417
                self->line = line;
418
                self->tqueue.routine = ircomm_tty_do_softint;
419
                self->tqueue.data = self;
420
                self->max_header_size = IRCOMM_TTY_HDR_UNINITIALISED;
421
                self->max_data_size = IRCOMM_TTY_DATA_UNINITIALISED;
422
                self->close_delay = 5*HZ/10;
423
                self->closing_wait = 30*HZ;
424
 
425
                /* Init some important stuff */
426
                init_timer(&self->watchdog_timer);
427
                init_waitqueue_head(&self->open_wait);
428
                init_waitqueue_head(&self->close_wait);
429
 
430
                /*
431
                 * Force TTY into raw mode by default which is usually what
432
                 * we want for IrCOMM and IrLPT. This way applications will
433
                 * not have to twiddle with printcap etc.
434
                 */
435
                tty->termios->c_iflag = 0;
436
                tty->termios->c_oflag = 0;
437
 
438
                /* Insert into hash */
439
                hashbin_insert(ircomm_tty, (irda_queue_t *) self, line, NULL);
440
        }
441
        self->open_count++;
442
 
443
        tty->driver_data = self;
444
        self->tty = tty;
445
 
446
        IRDA_DEBUG(1, "%s(), %s%d, count = %d\n", __FUNCTION__,
447
                tty->driver.name, self->line, self->open_count);
448
 
449
        /* Not really used by us, but lets do it anyway */
450
        self->tty->low_latency = (self->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
451
 
452
        /*
453
         * If the port is the middle of closing, bail out now
454
         */
455
        if (tty_hung_up_p(filp) ||
456
            (self->flags & ASYNC_CLOSING)) {
457
                if (self->flags & ASYNC_CLOSING)
458
                        interruptible_sleep_on(&self->close_wait);
459
                /* MOD_DEC_USE_COUNT; "info->tty" will cause this? */
460
#ifdef SERIAL_DO_RESTART
461
                return ((self->flags & ASYNC_HUP_NOTIFY) ?
462
                        -EAGAIN : -ERESTARTSYS);
463
#else
464
                return -EAGAIN;
465
#endif
466
        }
467
 
468
        /* Check if this is a "normal" ircomm device, or an irlpt device */
469
        if (line < 0x10) {
470
                self->service_type = IRCOMM_3_WIRE | IRCOMM_9_WIRE;
471
                self->settings.service_type = IRCOMM_9_WIRE; /* 9 wire as default */
472
                self->settings.dce = IRCOMM_CTS | IRCOMM_CD; /* Default line settings */
473
                IRDA_DEBUG(2, "%s(), IrCOMM device\n", __FUNCTION__);
474
        } else {
475
                IRDA_DEBUG(2, "%s(), IrLPT device\n", __FUNCTION__);
476
                self->service_type = IRCOMM_3_WIRE_RAW;
477
                self->settings.service_type = IRCOMM_3_WIRE_RAW; /* Default */
478
        }
479
 
480
        ret = ircomm_tty_startup(self);
481
        if (ret)
482
                return ret;
483
 
484
        ret = ircomm_tty_block_til_ready(self, filp);
485
        if (ret) {
486
                /* MOD_DEC_USE_COUNT; "info->tty" will cause this? */
487
                IRDA_DEBUG(2, "%s(), returning after block_til_ready with %d\n",
488
                        __FUNCTION__, ret);
489
 
490
                return ret;
491
        }
492
 
493
        self->session = current->session;
494
        self->pgrp = current->pgrp;
495
 
496
        return 0;
497
}
498
 
499
/*
500
 * Function ircomm_tty_close (tty, filp)
501
 *
502
 *    This routine is called when a particular tty device is closed.
503
 *
504
 */
505
static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
506
{
507
        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
508
        unsigned long flags;
509
 
510
        IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
511
 
512
        if (!tty)
513
                return;
514
 
515
        ASSERT(self != NULL, return;);
516
        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
517
 
518
        save_flags(flags);
519
        cli();
520
 
521
        if (tty_hung_up_p(filp)) {
522
                MOD_DEC_USE_COUNT;
523
                restore_flags(flags);
524
 
525
                IRDA_DEBUG(0, "%s(), returning 1\n", __FUNCTION__);
526
                return;
527
        }
528
 
529
        if ((tty->count == 1) && (self->open_count != 1)) {
530
                /*
531
                 * Uh, oh.  tty->count is 1, which means that the tty
532
                 * structure will be freed.  state->count should always
533
                 * be one in these conditions.  If it's greater than
534
                 * one, we've got real problems, since it means the
535
                 * serial port won't be shutdown.
536
                 */
537
                IRDA_DEBUG(0, "%s(), bad serial port count; "
538
                           "tty->count is 1, state->count is %d\n",
539
                           __FUNCTION__, self->open_count);
540
                self->open_count = 1;
541
        }
542
 
543
        if (--self->open_count < 0) {
544
                ERROR("%s(), bad serial port count for ttys%d: %d\n",
545
                        __FUNCTION__, self->line, self->open_count);
546
                self->open_count = 0;
547
        }
548
        if (self->open_count) {
549
                MOD_DEC_USE_COUNT;
550
                restore_flags(flags);
551
 
552
                IRDA_DEBUG(0, "%s(), open count > 0\n", __FUNCTION__);
553
                return;
554
        }
555
        self->flags |= ASYNC_CLOSING;
556
 
557
        /*
558
         * Now we wait for the transmit buffer to clear; and we notify
559
         * the line discipline to only process XON/XOFF characters.
560
         */
561
        tty->closing = 1;
562
        if (self->closing_wait != ASYNC_CLOSING_WAIT_NONE)
563
                tty_wait_until_sent(tty, self->closing_wait);
564
 
565
        ircomm_tty_shutdown(self);
566
 
567
        if (tty->driver.flush_buffer)
568
                tty->driver.flush_buffer(tty);
569
        if (tty->ldisc.flush_buffer)
570
                tty->ldisc.flush_buffer(tty);
571
 
572
        tty->closing = 0;
573
        self->tty = 0;
574
 
575
        if (self->blocked_open) {
576
                if (self->close_delay) {
577
                        current->state = TASK_INTERRUPTIBLE;
578
                        schedule_timeout(self->close_delay);
579
                }
580
                wake_up_interruptible(&self->open_wait);
581
        }
582
 
583
        self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
584
                         ASYNC_CLOSING);
585
        wake_up_interruptible(&self->close_wait);
586
 
587
        MOD_DEC_USE_COUNT;
588
        restore_flags(flags);
589
}
590
 
591
/*
592
 * Function ircomm_tty_flush_buffer (tty)
593
 *
594
 *
595
 *
596
 */
597
static void ircomm_tty_flush_buffer(struct tty_struct *tty)
598
{
599
        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
600
 
601
        ASSERT(self != NULL, return;);
602
        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
603
 
604
        /*
605
         * Let do_softint() do this to avoid race condition with
606
         * do_softint() ;-)
607
         */
608
        queue_task(&self->tqueue, &tq_immediate);
609
        mark_bh(IMMEDIATE_BH);
610
}
611
 
612
/*
613
 * Function ircomm_tty_do_softint (private_)
614
 *
615
 *    We use this routine to give the write wakeup to the user at at a
616
 *    safe time (as fast as possible after write have completed). This
617
 *    can be compared to the Tx interrupt.
618
 */
619
static void ircomm_tty_do_softint(void *private_)
620
{
621
        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) private_;
622
        struct tty_struct *tty;
623
        unsigned long flags;
624
        struct sk_buff *skb, *ctrl_skb;
625
 
626
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
627
 
628
        if (!self || self->magic != IRCOMM_TTY_MAGIC)
629
                return;
630
 
631
        tty = self->tty;
632
        if (!tty)
633
                return;
634
 
635
        /* Unlink control buffer */
636
        save_flags(flags);
637
        cli();
638
 
639
        ctrl_skb = self->ctrl_skb;
640
        self->ctrl_skb = NULL;
641
 
642
        restore_flags(flags);
643
 
644
        /* Flush control buffer if any */
645
        if (ctrl_skb && self->flow == FLOW_START)
646
                ircomm_control_request(self->ircomm, ctrl_skb);
647
 
648
        if (tty->hw_stopped)
649
                return;
650
 
651
        /* Unlink transmit buffer */
652
        save_flags(flags);
653
        cli();
654
 
655
        skb = self->tx_skb;
656
        self->tx_skb = NULL;
657
 
658
        restore_flags(flags);
659
 
660
        /* Flush transmit buffer if any */
661
        if (skb)
662
                ircomm_tty_do_event(self, IRCOMM_TTY_DATA_REQUEST, skb, NULL);
663
 
664
        /* Check if user (still) wants to be waken up */
665
        if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
666
            tty->ldisc.write_wakeup)
667
        {
668
                (tty->ldisc.write_wakeup)(tty);
669
        }
670
        wake_up_interruptible(&tty->write_wait);
671
}
672
 
673
/*
674
 * Function ircomm_tty_write (tty, from_user, buf, count)
675
 *
676
 *    This routine is called by the kernel to write a series of characters
677
 *    to the tty device. The characters may come from user space or kernel
678
 *    space. This routine will return the number of characters actually
679
 *    accepted for writing. This routine is mandatory.
680
 */
681
static int ircomm_tty_write(struct tty_struct *tty, int from_user,
682
                            const unsigned char *buf, int count)
683
{
684
        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
685
        unsigned long flags;
686
        struct sk_buff *skb;
687
        int tailroom = 0;
688
        int len = 0;
689
        int size;
690
 
691
        IRDA_DEBUG(2, "%s(), count=%d, hw_stopped=%d\n",
692
                __FUNCTION__, count, tty->hw_stopped);
693
 
694
        ASSERT(self != NULL, return -1;);
695
        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
696
 
697
        /* We may receive packets from the TTY even before we have finished
698
         * our setup. Not cool.
699
         * The problem is that we don't know the final header and data size
700
         * to create the proper skb, so any skb we would create would have
701
         * bogus header and data size, so need care.
702
         * We use a bogus header size to safely detect this condition.
703
         * Another problem is that hw_stopped was set to 0 way before it
704
         * should be, so we would drop this skb. It should now be fixed.
705
         * One option is to not accept data until we are properly setup.
706
         * But, I suspect that when it happens, the ppp line discipline
707
         * just "drops" the data, which might screw up connect scripts.
708
         * The second option is to create a "safe skb", with large header
709
         * and small size (see ircomm_tty_open() for values).
710
         * We just need to make sure that when the real values get filled,
711
         * we don't mess up the original "safe skb" (see tx_data_size).
712
         * Jean II */
713
        if (self->max_header_size == IRCOMM_TTY_HDR_UNINITIALISED) {
714
                IRDA_DEBUG(1, "%s() : not initialised\n", __FUNCTION__);
715
#ifdef IRCOMM_NO_TX_BEFORE_INIT
716
                /* We didn't consume anything, TTY will retry */
717
                return 0;
718
#endif
719
        }
720
 
721
        save_flags(flags);
722
        cli();
723
 
724
        /* Fetch current transmit buffer */
725
        skb = self->tx_skb;
726
 
727
        /*
728
         * Send out all the data we get, possibly as multiple fragmented
729
         * frames, but this will only happen if the data is larger than the
730
         * max data size. The normal case however is just the opposite, and
731
         * this function may be called multiple times, and will then actually
732
         * defragment the data and send it out as one packet as soon as
733
         * possible, but at a safer point in time
734
         */
735
        while (count) {
736
                size = count;
737
 
738
                /* Adjust data size to the max data size */
739
                if (size > self->max_data_size)
740
                        size = self->max_data_size;
741
 
742
                /*
743
                 * Do we already have a buffer ready for transmit, or do
744
                 * we need to allocate a new frame
745
                 */
746
                if (skb) {
747
                        /*
748
                         * Any room for more data at the end of the current
749
                         * transmit buffer? Cannot use skb_tailroom, since
750
                         * dev_alloc_skb gives us a larger skb than we
751
                         * requested
752
                         * Note : use tx_data_size, because max_data_size
753
                         * may have changed and we don't want to overwrite
754
                         * the skb. - Jean II
755
                         */
756
                        if ((tailroom = (self->tx_data_size - skb->len)) > 0) {
757
                                /* Adjust data to tailroom */
758
                                if (size > tailroom)
759
                                        size = tailroom;
760
                        } else {
761
                                /*
762
                                 * Current transmit frame is full, so break
763
                                 * out, so we can send it as soon as possible
764
                                 */
765
                                break;
766
                        }
767
                } else {
768
                        /* Prepare a full sized frame */
769
                        skb = dev_alloc_skb(self->max_data_size+
770
                                            self->max_header_size);
771
                        if (!skb) {
772
                                restore_flags(flags);
773
                                return -ENOBUFS;
774
                        }
775
                        skb_reserve(skb, self->max_header_size);
776
                        self->tx_skb = skb;
777
                        /* Remember skb size because max_data_size may
778
                         * change later on - Jean II */
779
                        self->tx_data_size = self->max_data_size;
780
                }
781
 
782
                /* Copy data */
783
                if (from_user)
784
                        copy_from_user(skb_put(skb,size), buf+len, size);
785
                else
786
                        memcpy(skb_put(skb,size), buf+len, size);
787
 
788
                count -= size;
789
                len += size;
790
        }
791
 
792
        restore_flags(flags);
793
 
794
        /*
795
         * Schedule a new thread which will transmit the frame as soon
796
         * as possible, but at a safe point in time. We do this so the
797
         * "user" can give us data multiple times, as PPP does (because of
798
         * its 256 byte tx buffer). We will then defragment and send out
799
         * all this data as one single packet.
800
         */
801
        queue_task(&self->tqueue, &tq_immediate);
802
        mark_bh(IMMEDIATE_BH);
803
 
804
        return len;
805
}
806
 
807
/*
808
 * Function ircomm_tty_write_room (tty)
809
 *
810
 *    This routine returns the numbers of characters the tty driver will
811
 *    accept for queuing to be written. This number is subject to change as
812
 *    output buffers get emptied, or if the output flow control is acted.
813
 */
814
static int ircomm_tty_write_room(struct tty_struct *tty)
815
{
816
        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
817
        unsigned long flags;
818
        int ret;
819
 
820
        ASSERT(self != NULL, return -1;);
821
        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
822
 
823
#ifdef IRCOMM_NO_TX_BEFORE_INIT
824
        /* max_header_size tells us if the channel is initialised or not. */
825
        if (self->max_header_size == IRCOMM_TTY_HDR_UNINITIALISED)
826
                /* Don't bother us yet */
827
                return 0;
828
#endif
829
 
830
        /* Check if we are allowed to transmit any data.
831
         * hw_stopped is the regular flow control.
832
         * Jean II */
833
        if (tty->hw_stopped)
834
                ret = 0;
835
        else {
836
                save_flags(flags);
837
                cli();
838
                if (self->tx_skb)
839
                        ret = self->tx_data_size - self->tx_skb->len;
840
                else
841
                        ret = self->max_data_size;
842
                restore_flags(flags);
843
        }
844
        IRDA_DEBUG(2, "%s(), ret=%d\n", __FUNCTION__, ret);
845
 
846
        return ret;
847
}
848
 
849
/*
850
 * Function ircomm_tty_wait_until_sent (tty, timeout)
851
 *
852
 *    This routine waits until the device has written out all of the
853
 *    characters in its transmitter FIFO.
854
 */
855
static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout)
856
{
857
        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
858
        unsigned long orig_jiffies, poll_time;
859
 
860
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
861
 
862
        ASSERT(self != NULL, return;);
863
        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
864
 
865
        orig_jiffies = jiffies;
866
 
867
        /* Set poll time to 200 ms */
868
        poll_time = IRDA_MIN(timeout, MSECS_TO_JIFFIES(200));
869
 
870
        while (self->tx_skb && self->tx_skb->len) {
871
                current->state = TASK_INTERRUPTIBLE;
872
                schedule_timeout(poll_time);
873
                if (signal_pending(current))
874
                        break;
875
                if (timeout && time_after(jiffies, orig_jiffies + timeout))
876
                        break;
877
        }
878
        current->state = TASK_RUNNING;
879
}
880
 
881
/*
882
 * Function ircomm_tty_throttle (tty)
883
 *
884
 *    This routine notifies the tty driver that input buffers for the line
885
 *    discipline are close to full, and it should somehow signal that no
886
 *    more characters should be sent to the tty.
887
 */
888
static void ircomm_tty_throttle(struct tty_struct *tty)
889
{
890
        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
891
 
892
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
893
 
894
        ASSERT(self != NULL, return;);
895
        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
896
 
897
        /* Software flow control? */
898
        if (I_IXOFF(tty))
899
                ircomm_tty_send_xchar(tty, STOP_CHAR(tty));
900
 
901
        /* Hardware flow control? */
902
        if (tty->termios->c_cflag & CRTSCTS) {
903
                self->settings.dte &= ~IRCOMM_RTS;
904
                self->settings.dte |= IRCOMM_DELTA_RTS;
905
 
906
                ircomm_param_request(self, IRCOMM_DTE, TRUE);
907
        }
908
 
909
        ircomm_flow_request(self->ircomm, FLOW_STOP);
910
}
911
 
912
/*
913
 * Function ircomm_tty_unthrottle (tty)
914
 *
915
 *    This routine notifies the tty drivers that it should signals that
916
 *    characters can now be sent to the tty without fear of overrunning the
917
 *    input buffers of the line disciplines.
918
 */
919
static void ircomm_tty_unthrottle(struct tty_struct *tty)
920
{
921
        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
922
 
923
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
924
 
925
        ASSERT(self != NULL, return;);
926
        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
927
 
928
        /* Using software flow control? */
929
        if (I_IXOFF(tty)) {
930
                ircomm_tty_send_xchar(tty, START_CHAR(tty));
931
        }
932
 
933
        /* Using hardware flow control? */
934
        if (tty->termios->c_cflag & CRTSCTS) {
935
                self->settings.dte |= (IRCOMM_RTS|IRCOMM_DELTA_RTS);
936
 
937
                ircomm_param_request(self, IRCOMM_DTE, TRUE);
938
                IRDA_DEBUG(1, "%s(), FLOW_START\n", __FUNCTION__);
939
        }
940
        ircomm_flow_request(self->ircomm, FLOW_START);
941
}
942
 
943
/*
944
 * Function ircomm_tty_chars_in_buffer (tty)
945
 *
946
 *    Indicates if there are any data in the buffer
947
 *
948
 */
949
static int ircomm_tty_chars_in_buffer(struct tty_struct *tty)
950
{
951
        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
952
        unsigned long flags;
953
        int len = 0;
954
 
955
        ASSERT(self != NULL, return -1;);
956
        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
957
 
958
        save_flags(flags);
959
        cli();
960
 
961
        if (self->tx_skb)
962
                len = self->tx_skb->len;
963
 
964
        restore_flags(flags);
965
 
966
        return len;
967
}
968
 
969
static void ircomm_tty_shutdown(struct ircomm_tty_cb *self)
970
{
971
        unsigned long flags;
972
 
973
        ASSERT(self != NULL, return;);
974
        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
975
 
976
        IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
977
 
978
        if (!(self->flags & ASYNC_INITIALIZED))
979
                return;
980
 
981
        save_flags(flags);
982
        cli();
983
 
984
        del_timer(&self->watchdog_timer);
985
 
986
        /* Free parameter buffer */
987
        if (self->ctrl_skb) {
988
                dev_kfree_skb(self->ctrl_skb);
989
                self->ctrl_skb = NULL;
990
        }
991
 
992
        /* Free transmit buffer */
993
        if (self->tx_skb) {
994
                dev_kfree_skb(self->tx_skb);
995
                self->tx_skb = NULL;
996
        }
997
 
998
        ircomm_tty_detach_cable(self);
999
 
1000
        if (self->ircomm) {
1001
                ircomm_close(self->ircomm);
1002
                self->ircomm = NULL;
1003
        }
1004
        self->flags &= ~ASYNC_INITIALIZED;
1005
 
1006
        restore_flags(flags);
1007
}
1008
 
1009
/*
1010
 * Function ircomm_tty_hangup (tty)
1011
 *
1012
 *    This routine notifies the tty driver that it should hangup the tty
1013
 *    device.
1014
 *
1015
 */
1016
static void ircomm_tty_hangup(struct tty_struct *tty)
1017
{
1018
        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
1019
 
1020
        IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
1021
 
1022
        ASSERT(self != NULL, return;);
1023
        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
1024
 
1025
        if (!tty)
1026
                return;
1027
 
1028
        /* ircomm_tty_flush_buffer(tty); */
1029
        ircomm_tty_shutdown(self);
1030
 
1031
        self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
1032
        self->tty = 0;
1033
        self->open_count = 0;
1034
        wake_up_interruptible(&self->open_wait);
1035
}
1036
 
1037
/*
1038
 * Function ircomm_tty_send_xchar (tty, ch)
1039
 *
1040
 *    This routine is used to send a high-priority XON/XOFF character to
1041
 *    the device.
1042
 */
1043
static void ircomm_tty_send_xchar(struct tty_struct *tty, char ch)
1044
{
1045
        IRDA_DEBUG(0, "%s(), not impl\n", __FUNCTION__);
1046
}
1047
 
1048
/*
1049
 * Function ircomm_tty_start (tty)
1050
 *
1051
 *    This routine notifies the tty driver that it resume sending
1052
 *    characters to the tty device.
1053
 */
1054
void ircomm_tty_start(struct tty_struct *tty)
1055
{
1056
        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
1057
 
1058
        ircomm_flow_request(self->ircomm, FLOW_START);
1059
}
1060
 
1061
/*
1062
 * Function ircomm_tty_stop (tty)
1063
 *
1064
 *     This routine notifies the tty driver that it should stop outputting
1065
 *     characters to the tty device.
1066
 */
1067
void ircomm_tty_stop(struct tty_struct *tty)
1068
{
1069
        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
1070
 
1071
        ASSERT(self != NULL, return;);
1072
        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
1073
 
1074
        ircomm_flow_request(self->ircomm, FLOW_STOP);
1075
}
1076
 
1077
/*
1078
 * Function ircomm_check_modem_status (self)
1079
 *
1080
 *    Check for any changes in the DCE's line settings. This function should
1081
 *    be called whenever the dce parameter settings changes, to update the
1082
 *    flow control settings and other things
1083
 */
1084
void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
1085
{
1086
        struct tty_struct *tty;
1087
        int status;
1088
 
1089
        IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
1090
 
1091
        ASSERT(self != NULL, return;);
1092
        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
1093
 
1094
        tty = self->tty;
1095
 
1096
        status = self->settings.dce;
1097
 
1098
        if (status & IRCOMM_DCE_DELTA_ANY) {
1099
                /*wake_up_interruptible(&self->delta_msr_wait);*/
1100
        }
1101
        if ((self->flags & ASYNC_CHECK_CD) && (status & IRCOMM_DELTA_CD)) {
1102
                IRDA_DEBUG(2, "%s(), ircomm%d CD now %s...\n",
1103
                        __FUNCTION__, self->line, (status & IRCOMM_CD) ? "on" : "off");
1104
 
1105
                if (status & IRCOMM_CD) {
1106
                        wake_up_interruptible(&self->open_wait);
1107
                } else if (!((self->flags & ASYNC_CALLOUT_ACTIVE) &&
1108
                           (self->flags & ASYNC_CALLOUT_NOHUP)))
1109
                {
1110
                        IRDA_DEBUG(2, "%s(), Doing serial hangup..\n", __FUNCTION__);
1111
                        if (tty)
1112
                                tty_hangup(tty);
1113
 
1114
                        /* Hangup will remote the tty, so better break out */
1115
                        return;
1116
                }
1117
        }
1118
        if (self->flags & ASYNC_CTS_FLOW) {
1119
                if (tty->hw_stopped) {
1120
                        if (status & IRCOMM_CTS) {
1121
                                IRDA_DEBUG(2, "%s(), CTS tx start...\n", __FUNCTION__);
1122
                                tty->hw_stopped = 0;
1123
 
1124
                                /* Wake up processes blocked on open */
1125
                                wake_up_interruptible(&self->open_wait);
1126
 
1127
                                queue_task(&self->tqueue, &tq_immediate);
1128
                                mark_bh(IMMEDIATE_BH);
1129
                                return;
1130
                        }
1131
                } else {
1132
                        if (!(status & IRCOMM_CTS)) {
1133
                                IRDA_DEBUG(2, "%s(), CTS tx stop...\n", __FUNCTION__);
1134
                                tty->hw_stopped = 1;
1135
                        }
1136
                }
1137
        }
1138
}
1139
 
1140
/*
1141
 * Function ircomm_tty_data_indication (instance, sap, skb)
1142
 *
1143
 *    Handle incoming data, and deliver it to the line discipline
1144
 *
1145
 */
1146
static int ircomm_tty_data_indication(void *instance, void *sap,
1147
                                      struct sk_buff *skb)
1148
{
1149
        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
1150
 
1151
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
1152
 
1153
        ASSERT(self != NULL, return -1;);
1154
        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
1155
        ASSERT(skb != NULL, return -1;);
1156
 
1157
        if (!self->tty) {
1158
                IRDA_DEBUG(0, "%s(), no tty!\n", __FUNCTION__);
1159
                dev_kfree_skb(skb);
1160
                return 0;
1161
        }
1162
 
1163
        /*
1164
         * If we receive data when hardware is stopped then something is wrong.
1165
         * We try to poll the peers line settings to check if we are up todate.
1166
         * Devices like WinCE can do this, and since they don't send any
1167
         * params, we can just as well declare the hardware for running.
1168
         */
1169
        if (self->tty->hw_stopped && (self->flow == FLOW_START)) {
1170
                IRDA_DEBUG(0, "%s(), polling for line settings!\n", __FUNCTION__);
1171
                ircomm_param_request(self, IRCOMM_POLL, TRUE);
1172
 
1173
                /* We can just as well declare the hardware for running */
1174
                ircomm_tty_send_initial_parameters(self);
1175
                ircomm_tty_link_established(self);
1176
        }
1177
 
1178
        /*
1179
         * Just give it over to the line discipline. There is no need to
1180
         * involve the flip buffers, since we are not running in an interrupt
1181
         * handler
1182
         */
1183
        self->tty->ldisc.receive_buf(self->tty, skb->data, NULL, skb->len);
1184
        dev_kfree_skb(skb);
1185
 
1186
        return 0;
1187
}
1188
 
1189
/*
1190
 * Function ircomm_tty_control_indication (instance, sap, skb)
1191
 *
1192
 *    Parse all incoming parameters (easy!)
1193
 *
1194
 */
1195
static int ircomm_tty_control_indication(void *instance, void *sap,
1196
                                         struct sk_buff *skb)
1197
{
1198
        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
1199
        int clen;
1200
 
1201
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
1202
 
1203
        ASSERT(self != NULL, return -1;);
1204
        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
1205
        ASSERT(skb != NULL, return -1;);
1206
 
1207
        clen = skb->data[0];
1208
 
1209
        irda_param_extract_all(self, skb->data+1, IRDA_MIN(skb->len-1, clen),
1210
                               &ircomm_param_info);
1211
        dev_kfree_skb(skb);
1212
 
1213
        return 0;
1214
}
1215
 
1216
/*
1217
 * Function ircomm_tty_flow_indication (instance, sap, cmd)
1218
 *
1219
 *    This function is called by IrTTP when it wants us to slow down the
1220
 *    transmission of data. We just mark the hardware as stopped, and wait
1221
 *    for IrTTP to notify us that things are OK again.
1222
 */
1223
static void ircomm_tty_flow_indication(void *instance, void *sap,
1224
                                       LOCAL_FLOW cmd)
1225
{
1226
        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
1227
        struct tty_struct *tty;
1228
 
1229
        ASSERT(self != NULL, return;);
1230
        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
1231
 
1232
        tty = self->tty;
1233
 
1234
        switch (cmd) {
1235
        case FLOW_START:
1236
                IRDA_DEBUG(2, "%s(), hw start!\n", __FUNCTION__);
1237
                tty->hw_stopped = 0;
1238
 
1239
                /* ircomm_tty_do_softint will take care of the rest */
1240
                queue_task(&self->tqueue, &tq_immediate);
1241
                mark_bh(IMMEDIATE_BH);
1242
                break;
1243
        default:  /* If we get here, something is very wrong, better stop */
1244
        case FLOW_STOP:
1245
                IRDA_DEBUG(2, "%s(), hw stopped!\n", __FUNCTION__);
1246
                tty->hw_stopped = 1;
1247
                break;
1248
        }
1249
        self->flow = cmd;
1250
}
1251
 
1252
static int ircomm_tty_line_info(struct ircomm_tty_cb *self, char *buf)
1253
{
1254
        int  ret=0;
1255
 
1256
        ret += sprintf(buf+ret, "State: %s\n", ircomm_tty_state[self->state]);
1257
 
1258
        ret += sprintf(buf+ret, "Service type: ");
1259
        if (self->service_type & IRCOMM_9_WIRE)
1260
                ret += sprintf(buf+ret, "9_WIRE");
1261
        else if (self->service_type & IRCOMM_3_WIRE)
1262
                ret += sprintf(buf+ret, "3_WIRE");
1263
        else if (self->service_type & IRCOMM_3_WIRE_RAW)
1264
                ret += sprintf(buf+ret, "3_WIRE_RAW");
1265
        else
1266
                ret += sprintf(buf+ret, "No common service type!\n");
1267
        ret += sprintf(buf+ret, "\n");
1268
 
1269
        ret += sprintf(buf+ret, "Port name: %s\n", self->settings.port_name);
1270
 
1271
        ret += sprintf(buf+ret, "DTE status: ");
1272
        if (self->settings.dte & IRCOMM_RTS)
1273
                ret += sprintf(buf+ret, "RTS|");
1274
        if (self->settings.dte & IRCOMM_DTR)
1275
                ret += sprintf(buf+ret, "DTR|");
1276
        if (self->settings.dte)
1277
                ret--; /* remove the last | */
1278
        ret += sprintf(buf+ret, "\n");
1279
 
1280
        ret += sprintf(buf+ret, "DCE status: ");
1281
        if (self->settings.dce & IRCOMM_CTS)
1282
                ret += sprintf(buf+ret, "CTS|");
1283
        if (self->settings.dce & IRCOMM_DSR)
1284
                ret += sprintf(buf+ret, "DSR|");
1285
        if (self->settings.dce & IRCOMM_CD)
1286
                ret += sprintf(buf+ret, "CD|");
1287
        if (self->settings.dce & IRCOMM_RI)
1288
                ret += sprintf(buf+ret, "RI|");
1289
        if (self->settings.dce)
1290
                ret--; /* remove the last | */
1291
        ret += sprintf(buf+ret, "\n");
1292
 
1293
        ret += sprintf(buf+ret, "Configuration: ");
1294
        if (!self->settings.null_modem)
1295
                ret += sprintf(buf+ret, "DTE <-> DCE\n");
1296
        else
1297
                ret += sprintf(buf+ret,
1298
                               "DTE <-> DTE (null modem emulation)\n");
1299
 
1300
        ret += sprintf(buf+ret, "Data rate: %d\n", self->settings.data_rate);
1301
 
1302
        ret += sprintf(buf+ret, "Flow control: ");
1303
        if (self->settings.flow_control & IRCOMM_XON_XOFF_IN)
1304
                ret += sprintf(buf+ret, "XON_XOFF_IN|");
1305
        if (self->settings.flow_control & IRCOMM_XON_XOFF_OUT)
1306
                ret += sprintf(buf+ret, "XON_XOFF_OUT|");
1307
        if (self->settings.flow_control & IRCOMM_RTS_CTS_IN)
1308
                ret += sprintf(buf+ret, "RTS_CTS_IN|");
1309
        if (self->settings.flow_control & IRCOMM_RTS_CTS_OUT)
1310
                ret += sprintf(buf+ret, "RTS_CTS_OUT|");
1311
        if (self->settings.flow_control & IRCOMM_DSR_DTR_IN)
1312
                ret += sprintf(buf+ret, "DSR_DTR_IN|");
1313
        if (self->settings.flow_control & IRCOMM_DSR_DTR_OUT)
1314
                ret += sprintf(buf+ret, "DSR_DTR_OUT|");
1315
        if (self->settings.flow_control & IRCOMM_ENQ_ACK_IN)
1316
                ret += sprintf(buf+ret, "ENQ_ACK_IN|");
1317
        if (self->settings.flow_control & IRCOMM_ENQ_ACK_OUT)
1318
                ret += sprintf(buf+ret, "ENQ_ACK_OUT|");
1319
        if (self->settings.flow_control)
1320
                ret--; /* remove the last | */
1321
        ret += sprintf(buf+ret, "\n");
1322
 
1323
        ret += sprintf(buf+ret, "Flags: ");
1324
        if (self->flags & ASYNC_CTS_FLOW)
1325
                ret += sprintf(buf+ret, "ASYNC_CTS_FLOW|");
1326
        if (self->flags & ASYNC_CHECK_CD)
1327
                ret += sprintf(buf+ret, "ASYNC_CHECK_CD|");
1328
        if (self->flags & ASYNC_INITIALIZED)
1329
                ret += sprintf(buf+ret, "ASYNC_INITIALIZED|");
1330
        if (self->flags & ASYNC_LOW_LATENCY)
1331
                ret += sprintf(buf+ret, "ASYNC_LOW_LATENCY|");
1332
        if (self->flags & ASYNC_CLOSING)
1333
                ret += sprintf(buf+ret, "ASYNC_CLOSING|");
1334
        if (self->flags & ASYNC_NORMAL_ACTIVE)
1335
                ret += sprintf(buf+ret, "ASYNC_NORMAL_ACTIVE|");
1336
        if (self->flags & ASYNC_CALLOUT_ACTIVE)
1337
                ret += sprintf(buf+ret, "ASYNC_CALLOUT_ACTIVE|");
1338
        if (self->flags)
1339
                ret--; /* remove the last | */
1340
        ret += sprintf(buf+ret, "\n");
1341
 
1342
        ret += sprintf(buf+ret, "Role: %s\n", self->client ?
1343
                       "client" : "server");
1344
        ret += sprintf(buf+ret, "Open count: %d\n", self->open_count);
1345
        ret += sprintf(buf+ret, "Max data size: %d\n", self->max_data_size);
1346
        ret += sprintf(buf+ret, "Max header size: %d\n", self->max_header_size);
1347
 
1348
        if (self->tty)
1349
                ret += sprintf(buf+ret, "Hardware: %s\n",
1350
                               self->tty->hw_stopped ? "Stopped" : "Running");
1351
 
1352
        ret += sprintf(buf+ret, "\n");
1353
        return ret;
1354
}
1355
 
1356
 
1357
/*
1358
 * Function ircomm_tty_read_proc (buf, start, offset, len, eof, unused)
1359
 *
1360
 *
1361
 *
1362
 */
1363
#ifdef CONFIG_PROC_FS
1364
static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len,
1365
                                int *eof, void *unused)
1366
{
1367
        struct ircomm_tty_cb *self;
1368
        int count = 0, l;
1369
        off_t begin = 0;
1370
 
1371
        self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty);
1372
        while ((self != NULL) && (count < 4000)) {
1373
                if (self->magic != IRCOMM_TTY_MAGIC)
1374
                        return 0;
1375
 
1376
                l = ircomm_tty_line_info(self, buf + count);
1377
                count += l;
1378
                if (count+begin > offset+len)
1379
                        goto done;
1380
                if (count+begin < offset) {
1381
                        begin += count;
1382
                        count = 0;
1383
                }
1384
 
1385
                self = (struct ircomm_tty_cb *) hashbin_get_next(ircomm_tty);
1386
        }
1387
        *eof = 1;
1388
done:
1389
        if (offset >= count+begin)
1390
                return 0;
1391
        *start = buf + (offset-begin);
1392
        return ((len < begin+count-offset) ? len : begin+count-offset);
1393
}
1394
#endif /* CONFIG_PROC_FS */
1395
 
1396
#ifdef MODULE
1397
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
1398
MODULE_DESCRIPTION("IrCOMM serial TTY driver");
1399
MODULE_LICENSE("GPL");
1400
 
1401
int init_module(void)
1402
{
1403
        return ircomm_tty_init();
1404
}
1405
 
1406
void cleanup_module(void)
1407
{
1408
        ircomm_tty_cleanup();
1409
}
1410
 
1411
#endif /* MODULE */
1412
 
1413
 
1414
 
1415
 

powered by: WebSVN 2.1.0

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