⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ircomm_tty.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			-EAGAIN : -ERESTARTSYS);#else		return -EAGAIN;#endif	}	/* Check if this is a "normal" ircomm device, or an irlpt device */	if (line < 0x10) {		self->service_type = IRCOMM_3_WIRE | IRCOMM_9_WIRE;		self->settings.service_type = IRCOMM_9_WIRE; /* Default */		IRDA_DEBUG(2, __FUNCTION__ "(), IrCOMM device\n");	} else {		IRDA_DEBUG(2, __FUNCTION__ "(), IrLPT device\n");		self->service_type = IRCOMM_3_WIRE_RAW;		self->settings.service_type = IRCOMM_3_WIRE_RAW; /* Default */	}	ret = ircomm_tty_startup(self);	if (ret)		return ret;	ret = ircomm_tty_block_til_ready(self, filp);	if (ret) {		/* MOD_DEC_USE_COUNT; "info->tty" will cause this? */		IRDA_DEBUG(2, __FUNCTION__ 		      "(), returning after block_til_ready with %d\n",		      ret);		return ret;	}	self->session = current->session;	self->pgrp = current->pgrp;	return 0;}/* * Function ircomm_tty_close (tty, filp) * *    This routine is called when a particular tty device is closed. * */static void ircomm_tty_close(struct tty_struct *tty, struct file *filp){	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;	unsigned long flags;	IRDA_DEBUG(0, __FUNCTION__ "()\n");	if (!tty)		return;	save_flags(flags); 	cli();	if (tty_hung_up_p(filp)) {		MOD_DEC_USE_COUNT;		restore_flags(flags);		IRDA_DEBUG(0, __FUNCTION__ "(), returning 1\n");		return;	}	ASSERT(self != NULL, return;);	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);	if ((tty->count == 1) && (self->open_count != 1)) {		/*		 * Uh, oh.  tty->count is 1, which means that the tty		 * structure will be freed.  state->count should always		 * be one in these conditions.  If it's greater than		 * one, we've got real problems, since it means the		 * serial port won't be shutdown.		 */		IRDA_DEBUG(0, __FUNCTION__ "(), bad serial port count; "			   "tty->count is 1, state->count is %d\n", 			   self->open_count);		self->open_count = 1;	}	if (--self->open_count < 0) {		ERROR(__FUNCTION__ 		      "(), bad serial port count for ttys%d: %d\n",		      self->line, self->open_count);		self->open_count = 0;	}	if (self->open_count) {		MOD_DEC_USE_COUNT;		restore_flags(flags);		IRDA_DEBUG(0, __FUNCTION__ "(), open count > 0\n");		return;	}	self->flags |= ASYNC_CLOSING;	/*	 * Now we wait for the transmit buffer to clear; and we notify 	 * the line discipline to only process XON/XOFF characters.	 */	tty->closing = 1;	if (self->closing_wait != ASYNC_CLOSING_WAIT_NONE)		tty_wait_until_sent(tty, self->closing_wait);	ircomm_tty_shutdown(self);	if (tty->driver.flush_buffer)		tty->driver.flush_buffer(tty);	if (tty->ldisc.flush_buffer)		tty->ldisc.flush_buffer(tty);	tty->closing = 0;	self->tty = 0;	if (self->blocked_open) {		if (self->close_delay) {			current->state = TASK_INTERRUPTIBLE;			schedule_timeout(self->close_delay);		}		wake_up_interruptible(&self->open_wait);	}	self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|			 ASYNC_CLOSING);	wake_up_interruptible(&self->close_wait);	MOD_DEC_USE_COUNT;	restore_flags(flags);}/* * Function ircomm_tty_flush_buffer (tty) * *     * */static void ircomm_tty_flush_buffer(struct tty_struct *tty){	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;	ASSERT(self != NULL, return;);	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);	/* 	 * Let do_softint() do this to avoid race condition with 	 * do_softint() ;-) 	 */	queue_task(&self->tqueue, &tq_immediate);	mark_bh(IMMEDIATE_BH);}/* * Function ircomm_tty_do_softint (private_) * *    We use this routine to give the write wakeup to the user at at a *    safe time (as fast as possible after write have completed). This  *    can be compared to the Tx interrupt. */static void ircomm_tty_do_softint(void *private_){	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) private_;	struct tty_struct *tty;	unsigned long flags;	struct sk_buff *skb, *ctrl_skb;	IRDA_DEBUG(2, __FUNCTION__ "()\n");	if (!self || self->magic != IRCOMM_TTY_MAGIC)		return;	tty = self->tty;	if (!tty)		return;	/* Unlink control buffer */	save_flags(flags);	cli();	ctrl_skb = self->ctrl_skb;	self->ctrl_skb = NULL;	restore_flags(flags);	/* Flush control buffer if any */	if (ctrl_skb && self->flow == FLOW_START)		ircomm_control_request(self->ircomm, ctrl_skb);	if (tty->hw_stopped)		return;	/* Unlink transmit buffer */	save_flags(flags);	cli();		skb = self->tx_skb;	self->tx_skb = NULL;	restore_flags(flags);		/* Flush transmit buffer if any */	if (skb)		ircomm_tty_do_event(self, IRCOMM_TTY_DATA_REQUEST, skb, NULL);			/* Check if user (still) wants to be waken up */	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && 	    tty->ldisc.write_wakeup)	{		(tty->ldisc.write_wakeup)(tty);	}	wake_up_interruptible(&tty->write_wait);}/* * Function ircomm_tty_write (tty, from_user, buf, count) * *    This routine is called by the kernel to write a series of characters *    to the tty device. The characters may come from user space or kernel *    space. This routine will return the number of characters actually *    accepted for writing. This routine is mandatory. */static int ircomm_tty_write(struct tty_struct *tty, int from_user,			    const unsigned char *buf, int count){	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;	unsigned long flags;	struct sk_buff *skb;	int tailroom = 0;	int len = 0;	int size;	IRDA_DEBUG(2, __FUNCTION__ "(), count=%d, hw_stopped=%d\n", count,		   tty->hw_stopped);	ASSERT(self != NULL, return -1;);	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);	save_flags(flags);	cli();	/* Fetch current transmit buffer */	skb = self->tx_skb;	/*  	 * Send out all the data we get, possibly as multiple fragmented	 * frames, but this will only happen if the data is larger than the	 * max data size. The normal case however is just the opposite, and	 * this function may be called multiple times, and will then actually	 * defragment the data and send it out as one packet as soon as 	 * possible, but at a safer point in time	 */	while (count) {		size = count;		/* Adjust data size to the max data size */		if (size > self->max_data_size)			size = self->max_data_size;				/* 		 * Do we already have a buffer ready for transmit, or do		 * we need to allocate a new frame 		 */		if (skb) {						/* 			 * Any room for more data at the end of the current 			 * transmit buffer? Cannot use skb_tailroom, since			 * dev_alloc_skb gives us a larger skb than we 			 * requested			 */			if ((tailroom = (self->max_data_size-skb->len)) > 0) {				/* Adjust data to tailroom */				if (size > tailroom)					size = tailroom;			} else {				/* 				 * Current transmit frame is full, so break 				 * out, so we can send it as soon as possible				 */				break;			}		} else {			/* Prepare a full sized frame */			skb = dev_alloc_skb(self->max_data_size+					    self->max_header_size);			if (!skb) {				restore_flags(flags);				return -ENOBUFS;			}			skb_reserve(skb, self->max_header_size);			self->tx_skb = skb;		}				/* Copy data */		if (from_user)			copy_from_user(skb_put(skb,size), buf+len, size);		else			memcpy(skb_put(skb,size), buf+len, size);				count -= size;		len += size;	}	restore_flags(flags);	/*     	 * Schedule a new thread which will transmit the frame as soon	 * as possible, but at a safe point in time. We do this so the	 * "user" can give us data multiple times, as PPP does (because of	 * its 256 byte tx buffer). We will then defragment and send out	 * all this data as one single packet.  	 */	queue_task(&self->tqueue, &tq_immediate);	mark_bh(IMMEDIATE_BH);		return len;}/* * Function ircomm_tty_write_room (tty) * *    This routine returns the numbers of characters the tty driver will *    accept for queuing to be written. This number is subject to change as *    output buffers get emptied, or if the output flow control is acted. */static int ircomm_tty_write_room(struct tty_struct *tty){	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;	unsigned long flags;	int ret;	ASSERT(self != NULL, return -1;);	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);	/* Check if we are allowed to transmit any data */	if (tty->hw_stopped)		ret = 0;	else {		save_flags(flags);		cli();		if (self->tx_skb)			ret = self->max_data_size - self->tx_skb->len;		else			ret = self->max_data_size;		restore_flags(flags);	}	IRDA_DEBUG(2, __FUNCTION__ "(), ret=%d\n", ret);	return ret;}/* * Function ircomm_tty_wait_until_sent (tty, timeout) * *    This routine waits until the device has written out all of the *    characters in its transmitter FIFO. */static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout){	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;	unsigned long orig_jiffies, poll_time;		IRDA_DEBUG(2, __FUNCTION__ "()\n");	ASSERT(self != NULL, return;);	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);	orig_jiffies = jiffies;	/* Set poll time to 200 ms */	poll_time = IRDA_MIN(timeout, MSECS_TO_JIFFIES(200));	while (self->tx_skb && self->tx_skb->len) {		current->state = TASK_INTERRUPTIBLE;		schedule_timeout(poll_time);		if (signal_pending(current))			break;		if (timeout && time_after(jiffies, orig_jiffies + timeout))			break;	}	current->state = TASK_RUNNING;}/* * Function ircomm_tty_throttle (tty) * *    This routine notifies the tty driver that input buffers for the line *    discipline are close to full, and it should somehow signal that no *    more characters should be sent to the tty.   */static void ircomm_tty_throttle(struct tty_struct *tty){	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;	IRDA_DEBUG(2, __FUNCTION__ "()\n");	ASSERT(self != NULL, return;);	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);	/* Software flow control? */	if (I_IXOFF(tty))		ircomm_tty_send_xchar(tty, STOP_CHAR(tty));		/* Hardware flow control? */	if (tty->termios->c_cflag & CRTSCTS) {		self->settings.dte &= ~IRCOMM_RTS;		self->settings.dte |= IRCOMM_DELTA_RTS;			ircomm_param_request(self, IRCOMM_DTE, TRUE);	}        ircomm_flow_request(self->ircomm, FLOW_STOP);}/* * Function ircomm_tty_unthrottle (tty) * *    This routine notifies the tty drivers that it should signals that *    characters can now be sent to the tty without fear of overrunning the *    input buffers of the line disciplines. */static void ircomm_tty_unthrottle(struct tty_struct *tty){	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;	IRDA_DEBUG(2, __FUNCTION__ "()\n");	ASSERT(self != NULL, return;);	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);	/* Using software flow control? */	if (I_IXOFF(tty)) {		ircomm_tty_send_xchar(tty, START_CHAR(tty));	}	/* Using hardware flow control? */	if (tty->termios->c_cflag & CRTSCTS) {		self->settings.dte |= (IRCOMM_RTS|IRCOMM_DELTA_RTS);		ircomm_param_request(self, IRCOMM_DTE, TRUE);		IRDA_DEBUG(1, __FUNCTION__"(), FLOW_START\n");	}        ircomm_flow_request(self->ircomm, FLOW_START);}/* * Function ircomm_tty_chars_in_buffer (tty) * *    Indicates if there are any data in the buffer * */static int ircomm_tty_chars_in_buffer(struct tty_struct *tty){	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;	unsigned long flags;	int len = 0;	ASSERT(self != NULL, return -1;);	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);	save_flags(flags);	cli();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -