irtty-sir.c
来自「linux 内核源代码」· C语言 代码 · 共 622 行 · 第 1/2 页
C
622 行
/********************************************************************* * * Filename: irtty-sir.c * Version: 2.0 * Description: IrDA line discipline implementation * Status: Experimental. * Author: Dag Brattli <dagb@cs.uit.no> * Created at: Tue Dec 9 21:18:38 1997 * Modified at: Sun Oct 27 22:13:30 2002 * Modified by: Martin Diehl <mad@mdiehl.de> * Sources: slip.c by Laurence Culhane, <loz@holmes.demon.co.uk> * Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org> * * Copyright (c) 1998-2000 Dag Brattli, * Copyright (c) 2002 Martin Diehl, * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Neither Dag Brattli nor University of Tromsø admit liability nor * provide warranty for any of this software. This material is * provided "AS-IS" and at no charge. * ********************************************************************/ #include <linux/module.h>#include <linux/kernel.h>#include <linux/tty.h>#include <linux/init.h>#include <asm/uaccess.h>#include <linux/smp_lock.h>#include <linux/delay.h>#include <linux/mutex.h>#include <net/irda/irda.h>#include <net/irda/irda_device.h>#include "sir-dev.h"#include "irtty-sir.h"static int qos_mtt_bits = 0x03; /* 5 ms or more */module_param(qos_mtt_bits, int, 0);MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time");/* ------------------------------------------------------- *//* device configuration callbacks always invoked with irda-thread context *//* find out, how many chars we have in buffers below us * this is allowed to lie, i.e. return less chars than we * actually have. The returned value is used to determine * how long the irdathread should wait before doing the * real blocking wait_until_sent() */static int irtty_chars_in_buffer(struct sir_dev *dev){ struct sirtty_cb *priv = dev->priv; IRDA_ASSERT(priv != NULL, return -1;); IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;); return priv->tty->driver->chars_in_buffer(priv->tty);}/* Wait (sleep) until underlaying hardware finished transmission * i.e. hardware buffers are drained * this must block and not return before all characters are really sent * * If the tty sits on top of a 16550A-like uart, there are typically * up to 16 bytes in the fifo - f.e. 9600 bps 8N1 needs 16.7 msec * * With usbserial the uart-fifo is basically replaced by the converter's * outgoing endpoint buffer, which can usually hold 64 bytes (at least). * With pl2303 it appears we are safe with 60msec here. * * I really wish all serial drivers would provide * correct implementation of wait_until_sent() */#define USBSERIAL_TX_DONE_DELAY 60static void irtty_wait_until_sent(struct sir_dev *dev){ struct sirtty_cb *priv = dev->priv; struct tty_struct *tty; IRDA_ASSERT(priv != NULL, return;); IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;); tty = priv->tty; if (tty->driver->wait_until_sent) { lock_kernel(); tty->driver->wait_until_sent(tty, msecs_to_jiffies(100)); unlock_kernel(); } else { msleep(USBSERIAL_TX_DONE_DELAY); }}/* * Function irtty_change_speed (dev, speed) * * Change the speed of the serial port. * * This may sleep in set_termios (usbserial driver f.e.) and must * not be called from interrupt/timer/tasklet therefore. * All such invocations are deferred to kIrDAd now so we can sleep there. */static int irtty_change_speed(struct sir_dev *dev, unsigned speed){ struct sirtty_cb *priv = dev->priv; struct tty_struct *tty; struct ktermios old_termios; int cflag; IRDA_ASSERT(priv != NULL, return -1;); IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;); tty = priv->tty; lock_kernel(); old_termios = *(tty->termios); cflag = tty->termios->c_cflag; cflag &= ~CBAUD; IRDA_DEBUG(2, "%s(), Setting speed to %d\n", __FUNCTION__, speed); switch (speed) { case 1200: cflag |= B1200; break; case 2400: cflag |= B2400; break; case 4800: cflag |= B4800; break; case 19200: cflag |= B19200; break; case 38400: cflag |= B38400; break; case 57600: cflag |= B57600; break; case 115200: cflag |= B115200; break; case 9600: default: cflag |= B9600; break; } tty->termios->c_cflag = cflag; if (tty->driver->set_termios) tty->driver->set_termios(tty, &old_termios); unlock_kernel(); priv->io.speed = speed; return 0;}/* * Function irtty_set_dtr_rts (dev, dtr, rts) * * This function can be used by dongles etc. to set or reset the status * of the dtr and rts lines */static int irtty_set_dtr_rts(struct sir_dev *dev, int dtr, int rts){ struct sirtty_cb *priv = dev->priv; int set = 0; int clear = 0; IRDA_ASSERT(priv != NULL, return -1;); IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;); if (rts) set |= TIOCM_RTS; else clear |= TIOCM_RTS; if (dtr) set |= TIOCM_DTR; else clear |= TIOCM_DTR; /* * We can't use ioctl() because it expects a non-null file structure, * and we don't have that here. * This function is not yet defined for all tty driver, so * let's be careful... Jean II */ IRDA_ASSERT(priv->tty->driver->tiocmset != NULL, return -1;); priv->tty->driver->tiocmset(priv->tty, NULL, set, clear); return 0;}/* ------------------------------------------------------- *//* called from sir_dev when there is more data to send * context is either netdev->hard_xmit or some transmit-completion bh * i.e. we are under spinlock here and must not sleep. */static int irtty_do_write(struct sir_dev *dev, const unsigned char *ptr, size_t len){ struct sirtty_cb *priv = dev->priv; struct tty_struct *tty; int writelen; IRDA_ASSERT(priv != NULL, return -1;); IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;); tty = priv->tty; if (!tty->driver->write) return 0; tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); if (tty->driver->write_room) { writelen = tty->driver->write_room(tty); if (writelen > len) writelen = len; } else writelen = len; return tty->driver->write(tty, ptr, writelen);}/* ------------------------------------------------------- *//* irda line discipline callbacks *//* * Function irtty_receive_buf( tty, cp, count) * * Handle the 'receiver data ready' interrupt. This function is called * by the 'tty_io' module in the kernel when a block of IrDA data has * been received, which can now be decapsulated and delivered for * further processing * * calling context depends on underlying driver and tty->low_latency! * for example (low_latency: 1 / 0): * serial.c: uart-interrupt / softint * usbserial: urb-complete-interrupt / softint */static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { struct sir_dev *dev; struct sirtty_cb *priv = tty->disc_data; int i; IRDA_ASSERT(priv != NULL, return;); IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;); if (unlikely(count==0)) /* yes, this happens */ return; dev = priv->dev; if (!dev) { IRDA_WARNING("%s(), not ready yet!\n", __FUNCTION__); return; } for (i = 0; i < count; i++) { /* * Characters received with a parity error, etc? */ if (fp && *fp++) { IRDA_DEBUG(0, "Framing or parity error!\n"); sirdev_receive(dev, NULL, 0); /* notify sir_dev (updating stats) */ return; } } sirdev_receive(dev, cp, count);}/* * Function irtty_write_wakeup (tty) * * Called by the driver when there's room for more data. If we have * more packets to send, we send them here. * */static void irtty_write_wakeup(struct tty_struct *tty) { struct sirtty_cb *priv = tty->disc_data; IRDA_ASSERT(priv != NULL, return;); IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;); tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); if (priv->dev) sirdev_write_complete(priv->dev);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?