linux-old/net/irda/ircomm/ircomm_tty.c
<<
>>
Prefs
   1/*********************************************************************
   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
  52static int  ircomm_tty_open(struct tty_struct *tty, struct file *filp);
  53static void ircomm_tty_close(struct tty_struct * tty, struct file *filp);
  54static int  ircomm_tty_write(struct tty_struct * tty, int from_user,
  55                             const unsigned char *buf, int count);
  56static int  ircomm_tty_write_room(struct tty_struct *tty);
  57static void ircomm_tty_throttle(struct tty_struct *tty);
  58static void ircomm_tty_unthrottle(struct tty_struct *tty);
  59static int  ircomm_tty_chars_in_buffer(struct tty_struct *tty);
  60static void ircomm_tty_flush_buffer(struct tty_struct *tty);
  61static void ircomm_tty_send_xchar(struct tty_struct *tty, char ch);
  62static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout);
  63static void ircomm_tty_hangup(struct tty_struct *tty);
  64static void ircomm_tty_do_softint(void *private_);
  65static void ircomm_tty_shutdown(struct ircomm_tty_cb *self);
  66
  67static int ircomm_tty_data_indication(void *instance, void *sap,
  68                                      struct sk_buff *skb);
  69static int ircomm_tty_control_indication(void *instance, void *sap,
  70                                         struct sk_buff *skb);
  71static void ircomm_tty_flow_indication(void *instance, void *sap, 
  72                                       LOCAL_FLOW cmd);
  73#ifdef CONFIG_PROC_FS
  74static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len,
  75                                int *eof, void *unused);
  76#endif /* CONFIG_PROC_FS */
  77static struct tty_driver driver;
  78static int ircomm_tty_refcount;       /* If we manage several devices */
  79
  80static struct tty_struct *ircomm_tty_table[NR_PTYS];
  81static struct termios *ircomm_tty_termios[NR_PTYS];
  82static struct termios *ircomm_tty_termios_locked[NR_PTYS];
  83
  84hashbin_t *ircomm_tty = NULL;
  85
  86/*
  87 * Function ircomm_tty_init()
  88 *
  89 *    Init IrCOMM TTY layer/driver
  90 *
  91 */
  92int __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
 146static 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 */
 165void 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 */
 187static 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 */
 244static 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 */
 387static 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 */
 505static 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        tty_ldisc_flush(tty);
 570
 571        tty->closing = 0;
 572        self->tty = 0;
 573
 574        if (self->blocked_open) {
 575                if (self->close_delay) {
 576                        current->state = TASK_INTERRUPTIBLE;
 577                        schedule_timeout(self->close_delay);
 578                }
 579                wake_up_interruptible(&self->open_wait);
 580        }
 581
 582        self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
 583                         ASYNC_CLOSING);
 584        wake_up_interruptible(&self->close_wait);
 585
 586        MOD_DEC_USE_COUNT;
 587        restore_flags(flags);
 588}
 589
 590/*
 591 * Function ircomm_tty_flush_buffer (tty)
 592 *
 593 *    
 594 *
 595 */
 596static void ircomm_tty_flush_buffer(struct tty_struct *tty)
 597{
 598        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
 599
 600        ASSERT(self != NULL, return;);
 601        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
 602
 603        /* 
 604         * Let do_softint() do this to avoid race condition with 
 605         * do_softint() ;-) 
 606         */
 607        queue_task(&self->tqueue, &tq_immediate);
 608        mark_bh(IMMEDIATE_BH);
 609}
 610
 611/*
 612 * Function ircomm_tty_do_softint (private_)
 613 *
 614 *    We use this routine to give the write wakeup to the user at at a
 615 *    safe time (as fast as possible after write have completed). This 
 616 *    can be compared to the Tx interrupt.
 617 */
 618static void ircomm_tty_do_softint(void *private_)
 619{
 620        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) private_;
 621        struct tty_struct *tty;
 622        unsigned long flags;
 623        struct sk_buff *skb, *ctrl_skb;
 624
 625        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 626
 627        if (!self || self->magic != IRCOMM_TTY_MAGIC)
 628                return;
 629
 630        tty = self->tty;
 631        if (!tty)
 632                return;
 633
 634        /* Unlink control buffer */
 635        save_flags(flags);
 636        cli();
 637
 638        ctrl_skb = self->ctrl_skb;
 639        self->ctrl_skb = NULL;
 640
 641        restore_flags(flags);
 642
 643        /* Flush control buffer if any */
 644        if (ctrl_skb && self->flow == FLOW_START)
 645                ircomm_control_request(self->ircomm, ctrl_skb);
 646
 647        if (tty->hw_stopped)
 648                return;
 649
 650        /* Unlink transmit buffer */
 651        save_flags(flags);
 652        cli();
 653        
 654        skb = self->tx_skb;
 655        self->tx_skb = NULL;
 656
 657        restore_flags(flags);   
 658
 659        /* Flush transmit buffer if any */
 660        if (skb)
 661                ircomm_tty_do_event(self, IRCOMM_TTY_DATA_REQUEST, skb, NULL);
 662                
 663        /* Check if user (still) wants to be waken up */
 664        tty_wakeup(tty);
 665}
 666
 667/*
 668 * Function ircomm_tty_write (tty, from_user, buf, count)
 669 *
 670 *    This routine is called by the kernel to write a series of characters
 671 *    to the tty device. The characters may come from user space or kernel
 672 *    space. This routine will return the number of characters actually
 673 *    accepted for writing. This routine is mandatory.
 674 */
 675static int ircomm_tty_write(struct tty_struct *tty, int from_user,
 676                            const unsigned char *buf, int count)
 677{
 678        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
 679        unsigned long flags;
 680        struct sk_buff *skb;
 681        int tailroom = 0;
 682        int len = 0;
 683        int size;
 684
 685        IRDA_DEBUG(2, "%s(), count=%d, hw_stopped=%d\n", 
 686                __FUNCTION__, count, tty->hw_stopped);
 687
 688        ASSERT(self != NULL, return -1;);
 689        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 690
 691        /* We may receive packets from the TTY even before we have finished
 692         * our setup. Not cool.
 693         * The problem is that we don't know the final header and data size
 694         * to create the proper skb, so any skb we would create would have
 695         * bogus header and data size, so need care.
 696         * We use a bogus header size to safely detect this condition.
 697         * Another problem is that hw_stopped was set to 0 way before it
 698         * should be, so we would drop this skb. It should now be fixed.
 699         * One option is to not accept data until we are properly setup.
 700         * But, I suspect that when it happens, the ppp line discipline
 701         * just "drops" the data, which might screw up connect scripts.
 702         * The second option is to create a "safe skb", with large header
 703         * and small size (see ircomm_tty_open() for values).
 704         * We just need to make sure that when the real values get filled,
 705         * we don't mess up the original "safe skb" (see tx_data_size).
 706         * Jean II */
 707        if (self->max_header_size == IRCOMM_TTY_HDR_UNINITIALISED) {
 708                IRDA_DEBUG(1, "%s() : not initialised\n", __FUNCTION__);
 709#ifdef IRCOMM_NO_TX_BEFORE_INIT
 710                /* We didn't consume anything, TTY will retry */
 711                return 0;
 712#endif
 713        }
 714
 715        save_flags(flags);
 716        cli();
 717
 718        /* Fetch current transmit buffer */
 719        skb = self->tx_skb;
 720
 721        /*  
 722         * Send out all the data we get, possibly as multiple fragmented
 723         * frames, but this will only happen if the data is larger than the
 724         * max data size. The normal case however is just the opposite, and
 725         * this function may be called multiple times, and will then actually
 726         * defragment the data and send it out as one packet as soon as 
 727         * possible, but at a safer point in time
 728         */
 729        while (count) {
 730                size = count;
 731
 732                /* Adjust data size to the max data size */
 733                if (size > self->max_data_size)
 734                        size = self->max_data_size;
 735                
 736                /* 
 737                 * Do we already have a buffer ready for transmit, or do
 738                 * we need to allocate a new frame 
 739                 */
 740                if (skb) {                      
 741                        /* 
 742                         * Any room for more data at the end of the current 
 743                         * transmit buffer? Cannot use skb_tailroom, since
 744                         * dev_alloc_skb gives us a larger skb than we 
 745                         * requested
 746                         * Note : use tx_data_size, because max_data_size
 747                         * may have changed and we don't want to overwrite
 748                         * the skb. - Jean II
 749                         */
 750                        if ((tailroom = (self->tx_data_size - skb->len)) > 0) {
 751                                /* Adjust data to tailroom */
 752                                if (size > tailroom)
 753                                        size = tailroom;
 754                        } else {
 755                                /* 
 756                                 * Current transmit frame is full, so break 
 757                                 * out, so we can send it as soon as possible
 758                                 */
 759                                break;
 760                        }
 761                } else {
 762                        /* Prepare a full sized frame */
 763                        skb = dev_alloc_skb(self->max_data_size+
 764                                            self->max_header_size);
 765                        if (!skb) {
 766                                restore_flags(flags);
 767                                return -ENOBUFS;
 768                        }
 769                        skb_reserve(skb, self->max_header_size);
 770                        self->tx_skb = skb;
 771                        /* Remember skb size because max_data_size may
 772                         * change later on - Jean II */
 773                        self->tx_data_size = self->max_data_size;
 774                }
 775                
 776                /* Copy data */
 777                if (from_user)
 778                        copy_from_user(skb_put(skb,size), buf+len, size);
 779                else
 780                        memcpy(skb_put(skb,size), buf+len, size);
 781                
 782                count -= size;
 783                len += size;
 784        }
 785
 786        restore_flags(flags);
 787
 788        /*     
 789         * Schedule a new thread which will transmit the frame as soon
 790         * as possible, but at a safe point in time. We do this so the
 791         * "user" can give us data multiple times, as PPP does (because of
 792         * its 256 byte tx buffer). We will then defragment and send out
 793         * all this data as one single packet.  
 794         */
 795        queue_task(&self->tqueue, &tq_immediate);
 796        mark_bh(IMMEDIATE_BH);
 797        
 798        return len;
 799}
 800
 801/*
 802 * Function ircomm_tty_write_room (tty)
 803 *
 804 *    This routine returns the numbers of characters the tty driver will
 805 *    accept for queuing to be written. This number is subject to change as
 806 *    output buffers get emptied, or if the output flow control is acted.
 807 */
 808static int ircomm_tty_write_room(struct tty_struct *tty)
 809{
 810        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
 811        unsigned long flags;
 812        int ret;
 813
 814        ASSERT(self != NULL, return -1;);
 815        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 816
 817#ifdef IRCOMM_NO_TX_BEFORE_INIT
 818        /* max_header_size tells us if the channel is initialised or not. */
 819        if (self->max_header_size == IRCOMM_TTY_HDR_UNINITIALISED)
 820                /* Don't bother us yet */
 821                return 0;
 822#endif
 823
 824        /* Check if we are allowed to transmit any data.
 825         * hw_stopped is the regular flow control.
 826         * Jean II */
 827        if (tty->hw_stopped)
 828                ret = 0;
 829        else {
 830                save_flags(flags);
 831                cli();
 832                if (self->tx_skb)
 833                        ret = self->tx_data_size - self->tx_skb->len;
 834                else
 835                        ret = self->max_data_size;
 836                restore_flags(flags);
 837        }
 838        IRDA_DEBUG(2, "%s(), ret=%d\n", __FUNCTION__, ret);
 839
 840        return ret;
 841}
 842
 843/*
 844 * Function ircomm_tty_wait_until_sent (tty, timeout)
 845 *
 846 *    This routine waits until the device has written out all of the
 847 *    characters in its transmitter FIFO.
 848 */
 849static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout)
 850{
 851        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
 852        unsigned long orig_jiffies, poll_time;
 853        
 854        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 855
 856        ASSERT(self != NULL, return;);
 857        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
 858
 859        orig_jiffies = jiffies;
 860
 861        /* Set poll time to 200 ms */
 862        poll_time = IRDA_MIN(timeout, MSECS_TO_JIFFIES(200));
 863
 864        while (self->tx_skb && self->tx_skb->len) {
 865                current->state = TASK_INTERRUPTIBLE;
 866                schedule_timeout(poll_time);
 867                if (signal_pending(current))
 868                        break;
 869                if (timeout && time_after(jiffies, orig_jiffies + timeout))
 870                        break;
 871        }
 872        current->state = TASK_RUNNING;
 873}
 874
 875/*
 876 * Function ircomm_tty_throttle (tty)
 877 *
 878 *    This routine notifies the tty driver that input buffers for the line
 879 *    discipline are close to full, and it should somehow signal that no
 880 *    more characters should be sent to the tty.  
 881 */
 882static void ircomm_tty_throttle(struct tty_struct *tty)
 883{
 884        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
 885
 886        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 887
 888        ASSERT(self != NULL, return;);
 889        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
 890
 891        /* Software flow control? */
 892        if (I_IXOFF(tty))
 893                ircomm_tty_send_xchar(tty, STOP_CHAR(tty));
 894        
 895        /* Hardware flow control? */
 896        if (tty->termios->c_cflag & CRTSCTS) {
 897                self->settings.dte &= ~IRCOMM_RTS;
 898                self->settings.dte |= IRCOMM_DELTA_RTS;
 899        
 900                ircomm_param_request(self, IRCOMM_DTE, TRUE);
 901        }
 902
 903        ircomm_flow_request(self->ircomm, FLOW_STOP);
 904}
 905
 906/*
 907 * Function ircomm_tty_unthrottle (tty)
 908 *
 909 *    This routine notifies the tty drivers that it should signals that
 910 *    characters can now be sent to the tty without fear of overrunning the
 911 *    input buffers of the line disciplines.
 912 */
 913static void ircomm_tty_unthrottle(struct tty_struct *tty)
 914{
 915        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
 916
 917        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 918
 919        ASSERT(self != NULL, return;);
 920        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
 921
 922        /* Using software flow control? */
 923        if (I_IXOFF(tty)) {
 924                ircomm_tty_send_xchar(tty, START_CHAR(tty));
 925        }
 926
 927        /* Using hardware flow control? */
 928        if (tty->termios->c_cflag & CRTSCTS) {
 929                self->settings.dte |= (IRCOMM_RTS|IRCOMM_DELTA_RTS);
 930
 931                ircomm_param_request(self, IRCOMM_DTE, TRUE);
 932                IRDA_DEBUG(1, "%s(), FLOW_START\n", __FUNCTION__);
 933        }
 934        ircomm_flow_request(self->ircomm, FLOW_START);
 935}
 936
 937/*
 938 * Function ircomm_tty_chars_in_buffer (tty)
 939 *
 940 *    Indicates if there are any data in the buffer
 941 *
 942 */
 943static int ircomm_tty_chars_in_buffer(struct tty_struct *tty)
 944{
 945        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
 946        unsigned long flags;
 947        int len = 0;
 948
 949        ASSERT(self != NULL, return -1;);
 950        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 951
 952        save_flags(flags);
 953        cli();
 954
 955        if (self->tx_skb)
 956                len = self->tx_skb->len;
 957
 958        restore_flags(flags);
 959
 960        return len;
 961}
 962
 963static void ircomm_tty_shutdown(struct ircomm_tty_cb *self)
 964{
 965        unsigned long flags;
 966
 967        ASSERT(self != NULL, return;);
 968        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
 969
 970        IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
 971        
 972        if (!(self->flags & ASYNC_INITIALIZED))
 973                return;
 974
 975        save_flags(flags);
 976        cli();
 977
 978        del_timer(&self->watchdog_timer);
 979        
 980        /* Free parameter buffer */
 981        if (self->ctrl_skb) {
 982                dev_kfree_skb(self->ctrl_skb);
 983                self->ctrl_skb = NULL;
 984        }
 985
 986        /* Free transmit buffer */
 987        if (self->tx_skb) {
 988                dev_kfree_skb(self->tx_skb);
 989                self->tx_skb = NULL;
 990        }
 991
 992        ircomm_tty_detach_cable(self);
 993
 994        if (self->ircomm) {
 995                ircomm_close(self->ircomm);
 996                self->ircomm = NULL;
 997        }
 998        self->flags &= ~ASYNC_INITIALIZED;
 999
1000        restore_flags(flags);
1001}
1002
1003/*
1004 * Function ircomm_tty_hangup (tty)
1005 *
1006 *    This routine notifies the tty driver that it should hangup the tty
1007 *    device.
1008 * 
1009 */
1010static void ircomm_tty_hangup(struct tty_struct *tty)
1011{
1012        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
1013
1014        IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
1015
1016        ASSERT(self != NULL, return;);
1017        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
1018
1019        if (!tty)
1020                return;
1021
1022        /* ircomm_tty_flush_buffer(tty); */
1023        ircomm_tty_shutdown(self);
1024
1025        self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
1026        self->tty = 0;
1027        self->open_count = 0;
1028        wake_up_interruptible(&self->open_wait);
1029}
1030
1031/*
1032 * Function ircomm_tty_send_xchar (tty, ch)
1033 *
1034 *    This routine is used to send a high-priority XON/XOFF character to
1035 *    the device.
1036 */
1037static void ircomm_tty_send_xchar(struct tty_struct *tty, char ch)
1038{
1039        IRDA_DEBUG(0, "%s(), not impl\n", __FUNCTION__);
1040}
1041
1042/*
1043 * Function ircomm_tty_start (tty)
1044 *
1045 *    This routine notifies the tty driver that it resume sending
1046 *    characters to the tty device.  
1047 */
1048void ircomm_tty_start(struct tty_struct *tty)
1049{
1050        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
1051
1052        ircomm_flow_request(self->ircomm, FLOW_START);
1053}
1054
1055/*
1056 * Function ircomm_tty_stop (tty)
1057 *
1058 *     This routine notifies the tty driver that it should stop outputting
1059 *     characters to the tty device. 
1060 */
1061void ircomm_tty_stop(struct tty_struct *tty) 
1062{
1063        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
1064
1065        ASSERT(self != NULL, return;);
1066        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
1067
1068        ircomm_flow_request(self->ircomm, FLOW_STOP);
1069}
1070
1071/*
1072 * Function ircomm_check_modem_status (self)
1073 *
1074 *    Check for any changes in the DCE's line settings. This function should
1075 *    be called whenever the dce parameter settings changes, to update the
1076 *    flow control settings and other things
1077 */
1078void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
1079{
1080        struct tty_struct *tty;
1081        int status;
1082
1083        IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
1084
1085        ASSERT(self != NULL, return;);
1086        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
1087
1088        tty = self->tty;
1089
1090        status = self->settings.dce;
1091
1092        if (status & IRCOMM_DCE_DELTA_ANY) {
1093                /*wake_up_interruptible(&self->delta_msr_wait);*/
1094        }
1095        if ((self->flags & ASYNC_CHECK_CD) && (status & IRCOMM_DELTA_CD)) {
1096                IRDA_DEBUG(2, "%s(), ircomm%d CD now %s...\n", 
1097                        __FUNCTION__, self->line, (status & IRCOMM_CD) ? "on" : "off");
1098
1099                if (status & IRCOMM_CD) {
1100                        wake_up_interruptible(&self->open_wait);
1101                } else if (!((self->flags & ASYNC_CALLOUT_ACTIVE) &&
1102                           (self->flags & ASYNC_CALLOUT_NOHUP))) 
1103                {
1104                        IRDA_DEBUG(2, "%s(), Doing serial hangup..\n", __FUNCTION__);
1105                        if (tty)
1106                                tty_hangup(tty);
1107
1108                        /* Hangup will remote the tty, so better break out */
1109                        return;
1110                }
1111        }
1112        if (self->flags & ASYNC_CTS_FLOW) {
1113                if (tty->hw_stopped) {
1114                        if (status & IRCOMM_CTS) {
1115                                IRDA_DEBUG(2, "%s(), CTS tx start...\n", __FUNCTION__);
1116                                tty->hw_stopped = 0;
1117                                
1118                                /* Wake up processes blocked on open */
1119                                wake_up_interruptible(&self->open_wait);
1120
1121                                queue_task(&self->tqueue, &tq_immediate);
1122                                mark_bh(IMMEDIATE_BH);
1123                                return;
1124                        }
1125                } else {
1126                        if (!(status & IRCOMM_CTS)) {
1127                                IRDA_DEBUG(2, "%s(), CTS tx stop...\n", __FUNCTION__);
1128                                tty->hw_stopped = 1;
1129                        }
1130                }
1131        }
1132}
1133
1134/*
1135 * Function ircomm_tty_data_indication (instance, sap, skb)
1136 *
1137 *    Handle incoming data, and deliver it to the line discipline
1138 *
1139 */
1140static int ircomm_tty_data_indication(void *instance, void *sap,
1141                                      struct sk_buff *skb)
1142{
1143        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
1144
1145        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
1146        
1147        ASSERT(self != NULL, return -1;);
1148        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
1149        ASSERT(skb != NULL, return -1;);
1150
1151        if (!self->tty) {
1152                IRDA_DEBUG(0, "%s(), no tty!\n", __FUNCTION__);
1153                dev_kfree_skb(skb);
1154                return 0;
1155        }
1156
1157        /* 
1158         * If we receive data when hardware is stopped then something is wrong.
1159         * We try to poll the peers line settings to check if we are up todate.
1160         * Devices like WinCE can do this, and since they don't send any 
1161         * params, we can just as well declare the hardware for running.
1162         */
1163        if (self->tty->hw_stopped && (self->flow == FLOW_START)) {
1164                IRDA_DEBUG(0, "%s(), polling for line settings!\n", __FUNCTION__);
1165                ircomm_param_request(self, IRCOMM_POLL, TRUE);
1166
1167                /* We can just as well declare the hardware for running */
1168                ircomm_tty_send_initial_parameters(self);
1169                ircomm_tty_link_established(self);
1170        }
1171
1172        /* 
1173         * Just give it over to the line discipline. There is no need to
1174         * involve the flip buffers, since we are not running in an interrupt 
1175         * handler
1176         */
1177        self->tty->ldisc.receive_buf(self->tty, skb->data, NULL, skb->len);
1178        dev_kfree_skb(skb);
1179
1180        return 0;
1181}
1182
1183/*
1184 * Function ircomm_tty_control_indication (instance, sap, skb)
1185 *
1186 *    Parse all incoming parameters (easy!)
1187 *
1188 */
1189static int ircomm_tty_control_indication(void *instance, void *sap,
1190                                         struct sk_buff *skb)
1191{
1192        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
1193        int clen;
1194
1195        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
1196        
1197        ASSERT(self != NULL, return -1;);
1198        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
1199        ASSERT(skb != NULL, return -1;);
1200
1201        clen = skb->data[0];
1202
1203        irda_param_extract_all(self, skb->data+1, IRDA_MIN(skb->len-1, clen), 
1204                               &ircomm_param_info);
1205        dev_kfree_skb(skb);
1206
1207        return 0;
1208}
1209
1210/*
1211 * Function ircomm_tty_flow_indication (instance, sap, cmd)
1212 *
1213 *    This function is called by IrTTP when it wants us to slow down the
1214 *    transmission of data. We just mark the hardware as stopped, and wait
1215 *    for IrTTP to notify us that things are OK again.
1216 */
1217static void ircomm_tty_flow_indication(void *instance, void *sap, 
1218                                       LOCAL_FLOW cmd)
1219{
1220        struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
1221        struct tty_struct *tty;
1222
1223        ASSERT(self != NULL, return;);
1224        ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
1225
1226        tty = self->tty;
1227
1228        switch (cmd) {
1229        case FLOW_START:
1230                IRDA_DEBUG(2, "%s(), hw start!\n", __FUNCTION__);
1231                tty->hw_stopped = 0;
1232
1233                /* ircomm_tty_do_softint will take care of the rest */
1234                queue_task(&self->tqueue, &tq_immediate);
1235                mark_bh(IMMEDIATE_BH);
1236                break;
1237        default:  /* If we get here, something is very wrong, better stop */
1238        case FLOW_STOP:
1239                IRDA_DEBUG(2, "%s(), hw stopped!\n", __FUNCTION__);
1240                tty->hw_stopped = 1;
1241                break;
1242        }
1243        self->flow = cmd;
1244}
1245
1246static int ircomm_tty_line_info(struct ircomm_tty_cb *self, char *buf)
1247{
1248        int  ret=0;
1249
1250        ret += sprintf(buf+ret, "State: %s\n", ircomm_tty_state[self->state]);
1251
1252        ret += sprintf(buf+ret, "Service type: ");
1253        if (self->service_type & IRCOMM_9_WIRE)
1254                ret += sprintf(buf+ret, "9_WIRE");
1255        else if (self->service_type & IRCOMM_3_WIRE)
1256                ret += sprintf(buf+ret, "3_WIRE");
1257        else if (self->service_type & IRCOMM_3_WIRE_RAW)
1258                ret += sprintf(buf+ret, "3_WIRE_RAW");
1259        else
1260                ret += sprintf(buf+ret, "No common service type!\n");
1261        ret += sprintf(buf+ret, "\n");
1262
1263        ret += sprintf(buf+ret, "Port name: %s\n", self->settings.port_name);
1264
1265        ret += sprintf(buf+ret, "DTE status: ");        
1266        if (self->settings.dte & IRCOMM_RTS)
1267                ret += sprintf(buf+ret, "RTS|");
1268        if (self->settings.dte & IRCOMM_DTR)
1269                ret += sprintf(buf+ret, "DTR|");
1270        if (self->settings.dte)
1271                ret--; /* remove the last | */
1272        ret += sprintf(buf+ret, "\n");
1273
1274        ret += sprintf(buf+ret, "DCE status: ");
1275        if (self->settings.dce & IRCOMM_CTS)
1276                ret += sprintf(buf+ret, "CTS|");
1277        if (self->settings.dce & IRCOMM_DSR)
1278                ret += sprintf(buf+ret, "DSR|");
1279        if (self->settings.dce & IRCOMM_CD)
1280                ret += sprintf(buf+ret, "CD|");
1281        if (self->settings.dce & IRCOMM_RI) 
1282                ret += sprintf(buf+ret, "RI|");
1283        if (self->settings.dce)
1284                ret--; /* remove the last | */
1285        ret += sprintf(buf+ret, "\n");
1286
1287        ret += sprintf(buf+ret, "Configuration: ");
1288        if (!self->settings.null_modem)
1289                ret += sprintf(buf+ret, "DTE <-> DCE\n");
1290        else
1291                ret += sprintf(buf+ret, 
1292                               "DTE <-> DTE (null modem emulation)\n");
1293
1294        ret += sprintf(buf+ret, "Data rate: %d\n", self->settings.data_rate);
1295
1296        ret += sprintf(buf+ret, "Flow control: ");
1297        if (self->settings.flow_control & IRCOMM_XON_XOFF_IN)
1298                ret += sprintf(buf+ret, "XON_XOFF_IN|");
1299        if (self->settings.flow_control & IRCOMM_XON_XOFF_OUT)
1300                ret += sprintf(buf+ret, "XON_XOFF_OUT|");
1301        if (self->settings.flow_control & IRCOMM_RTS_CTS_IN)
1302                ret += sprintf(buf+ret, "RTS_CTS_IN|");
1303        if (self->settings.flow_control & IRCOMM_RTS_CTS_OUT)
1304                ret += sprintf(buf+ret, "RTS_CTS_OUT|");
1305        if (self->settings.flow_control & IRCOMM_DSR_DTR_IN)
1306                ret += sprintf(buf+ret, "DSR_DTR_IN|");
1307        if (self->settings.flow_control & IRCOMM_DSR_DTR_OUT)
1308                ret += sprintf(buf+ret, "DSR_DTR_OUT|");
1309        if (self->settings.flow_control & IRCOMM_ENQ_ACK_IN)
1310                ret += sprintf(buf+ret, "ENQ_ACK_IN|");
1311        if (self->settings.flow_control & IRCOMM_ENQ_ACK_OUT)
1312                ret += sprintf(buf+ret, "ENQ_ACK_OUT|");
1313        if (self->settings.flow_control)
1314                ret--; /* remove the last | */
1315        ret += sprintf(buf+ret, "\n");
1316
1317        ret += sprintf(buf+ret, "Flags: ");
1318        if (self->flags & ASYNC_CTS_FLOW)
1319                ret += sprintf(buf+ret, "ASYNC_CTS_FLOW|");
1320        if (self->flags & ASYNC_CHECK_CD)
1321                ret += sprintf(buf+ret, "ASYNC_CHECK_CD|");
1322        if (self->flags & ASYNC_INITIALIZED)
1323                ret += sprintf(buf+ret, "ASYNC_INITIALIZED|");
1324        if (self->flags & ASYNC_LOW_LATENCY)
1325                ret += sprintf(buf+ret, "ASYNC_LOW_LATENCY|");
1326        if (self->flags & ASYNC_CLOSING)
1327                ret += sprintf(buf+ret, "ASYNC_CLOSING|");
1328        if (self->flags & ASYNC_NORMAL_ACTIVE)
1329                ret += sprintf(buf+ret, "ASYNC_NORMAL_ACTIVE|");
1330        if (self->flags & ASYNC_CALLOUT_ACTIVE)
1331                ret += sprintf(buf+ret, "ASYNC_CALLOUT_ACTIVE|");
1332        if (self->flags)
1333                ret--; /* remove the last | */
1334        ret += sprintf(buf+ret, "\n");
1335
1336        ret += sprintf(buf+ret, "Role: %s\n", self->client ? 
1337                       "client" : "server");
1338        ret += sprintf(buf+ret, "Open count: %d\n", self->open_count);
1339        ret += sprintf(buf+ret, "Max data size: %d\n", self->max_data_size);
1340        ret += sprintf(buf+ret, "Max header size: %d\n", self->max_header_size);
1341                
1342        if (self->tty)
1343                ret += sprintf(buf+ret, "Hardware: %s\n", 
1344                               self->tty->hw_stopped ? "Stopped" : "Running");
1345
1346        ret += sprintf(buf+ret, "\n");
1347        return ret;
1348}
1349
1350
1351/*
1352 * Function ircomm_tty_read_proc (buf, start, offset, len, eof, unused)
1353 *
1354 *    
1355 *
1356 */
1357#ifdef CONFIG_PROC_FS
1358static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len,
1359                                int *eof, void *unused)
1360{
1361        struct ircomm_tty_cb *self;
1362        int count = 0, l;
1363        off_t begin = 0;
1364
1365        self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty);
1366        while ((self != NULL) && (count < 4000)) {
1367                if (self->magic != IRCOMM_TTY_MAGIC)
1368                        return 0;
1369
1370                l = ircomm_tty_line_info(self, buf + count);
1371                count += l;
1372                if (count+begin > offset+len)
1373                        goto done;
1374                if (count+begin < offset) {
1375                        begin += count;
1376                        count = 0;
1377                }
1378                                
1379                self = (struct ircomm_tty_cb *) hashbin_get_next(ircomm_tty);
1380        }
1381        *eof = 1;
1382done:
1383        if (offset >= count+begin)
1384                return 0;
1385        *start = buf + (offset-begin);
1386        return ((len < begin+count-offset) ? len : begin+count-offset);
1387}
1388#endif /* CONFIG_PROC_FS */
1389
1390#ifdef MODULE
1391MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
1392MODULE_DESCRIPTION("IrCOMM serial TTY driver");
1393MODULE_LICENSE("GPL");
1394
1395int init_module(void) 
1396{
1397        return ircomm_tty_init();
1398}
1399
1400void cleanup_module(void)
1401{
1402        ircomm_tty_cleanup();
1403}
1404
1405#endif /* MODULE */
1406
1407
1408
1409
1410
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.