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

📄 termios.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 3 页
字号:
  /* check for incoming RTS/CTS flow control switched off */  if (( tty->flow_ctrl & FL_MDRTS) &&      !(tty->termios.c_cflag & CRTSCTS)) {    /* clear related flags in flow_ctrl */    tty->flow_ctrl &= ~(FL_MDRTS);        /* restart remote Tx, if it was stopped */    if ((tty->flow_ctrl & FL_IRTSOFF) &&	(tty->device.startRemoteTx != NULL)) {      tty->device.startRemoteTx(tty->minor);    }    tty->flow_ctrl &= ~(FL_IRTSOFF);  }        /*    * check for flow control options to be switched on     */  /* check for incoming RTS/CTS flow control switched on */  if (tty->termios.c_cflag & CRTSCTS) {    tty->flow_ctrl |= FL_MDRTS;  }  /* check for incoming XON/XOF flow control switched on */  if (tty->termios.c_iflag & IXOFF) {    tty->flow_ctrl |= FL_MDXOF;  }  /* check for outgoing XON/XOF flow control switched on */  if (tty->termios.c_iflag & IXON) {    tty->flow_ctrl |= FL_MDXON;  }}rtems_status_codertems_termios_ioctl (void *arg){	rtems_libio_ioctl_args_t *args = arg;	struct rtems_termios_tty *tty = args->iop->data1;	struct ttywakeup         *wakeup = (struct ttywakeup *)args->buffer;	rtems_status_code sc; 	args->ioctl_return = 0;	sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);	if (sc != RTEMS_SUCCESSFUL) {		args->ioctl_return = sc;		return sc;	}	switch (args->command) {	default:		if (linesw[tty->t_line].l_ioctl != NULL) {			sc = linesw[tty->t_line].l_ioctl(tty,args);		}		else {			sc = RTEMS_INVALID_NUMBER;		}		break;	case RTEMS_IO_GET_ATTRIBUTES:		*(struct termios *)args->buffer = tty->termios;		break;	case RTEMS_IO_SET_ATTRIBUTES:		tty->termios = *(struct termios *)args->buffer;		/* check for and process change in flow control options */		termios_set_flowctrl(tty);		if (tty->termios.c_lflag & ICANON) {			tty->rawInBufSemaphoreOptions = RTEMS_WAIT;			tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;			tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;		}		else {			rtems_interval ticksPerSecond;			rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond);			tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;			if (tty->termios.c_cc[VTIME]) {				tty->rawInBufSemaphoreOptions = RTEMS_WAIT;				tty->rawInBufSemaphoreTimeout = tty->vtimeTicks;				if (tty->termios.c_cc[VMIN])					tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;				else					tty->rawInBufSemaphoreFirstTimeout = tty->vtimeTicks;			}			else {				if (tty->termios.c_cc[VMIN]) {					tty->rawInBufSemaphoreOptions = RTEMS_WAIT;					tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;					tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;				}				else {					tty->rawInBufSemaphoreOptions = RTEMS_NO_WAIT;				}			}		}		if (tty->device.setAttributes)			(*tty->device.setAttributes)(tty->minor, &tty->termios);		break;	case RTEMS_IO_TCDRAIN:		drainOutput (tty);		break;	case RTEMS_IO_SNDWAKEUP:		tty->tty_snd = *wakeup;		break;	case RTEMS_IO_RCVWAKEUP:		tty->tty_rcv = *wakeup;		break;		/*		 * FIXME: add various ioctl code handlers		 */#if 1 /* FIXME */	case TIOCSETD:		/*		 * close old line discipline		 */		if (linesw[tty->t_line].l_close != NULL) {			sc = linesw[tty->t_line].l_close(tty);		}		tty->t_line=*(int*)(args->buffer);		tty->t_sc = NULL; /* ensure that no more valid data */		/*		 * open new line discipline		 */		if (linesw[tty->t_line].l_open != NULL) {			sc = linesw[tty->t_line].l_open(tty);		}		break;	case TIOCGETD:			*(int*)(args->buffer)=tty->t_line;		break;		#endif 	case FIONREAD:		{		int rawnc = tty->rawInBuf.Tail - tty->rawInBuf.Head;		if ( rawnc < 0 )			rawnc += tty->rawInBuf.Size;		/* Half guess that this is the right operation */		*(int *)args->buffer = tty->ccount - tty->cindex + rawnc;		}		break;	}	rtems_semaphore_release (tty->osem);	args->ioctl_return = sc;	return sc;}/* * Send characters to device-specific code */voidrtems_termios_puts (const char *buf, int len, struct rtems_termios_tty *tty){	unsigned int newHead;	rtems_interrupt_level level;	rtems_status_code sc;	if (tty->device.outputUsesInterrupts == TERMIOS_POLLED) {		(*tty->device.write)(tty->minor, buf, len);		return;	}	newHead = tty->rawOutBuf.Head;	while (len) {		/*		 * Performance improvement could be made here.		 * Copy multiple bytes to raw buffer:		 * if (len > 1) && (space to buffer end, or tail > 1)		 *	ncopy = MIN (len, space to buffer end or tail)		 *	memcpy (raw buffer, buf, ncopy)		 *	buf += ncopy		 *	len -= ncopy		 *		 * To minimize latency, the memcpy should be done		 * with interrupts enabled.		 */		newHead = (newHead + 1) % tty->rawOutBuf.Size;		rtems_interrupt_disable (level);		while (newHead == tty->rawOutBuf.Tail) {			tty->rawOutBufState = rob_wait;			rtems_interrupt_enable (level);			sc = rtems_semaphore_obtain (tty->rawOutBuf.Semaphore,							RTEMS_WAIT,							RTEMS_NO_TIMEOUT);			if (sc != RTEMS_SUCCESSFUL)				rtems_fatal_error_occurred (sc);			rtems_interrupt_disable (level);		}		tty->rawOutBuf.theBuf[tty->rawOutBuf.Head] = *buf++;		tty->rawOutBuf.Head = newHead;		if (tty->rawOutBufState == rob_idle) {		  /* check, whether XOFF has been received */		  if (!(tty->flow_ctrl & FL_ORCVXOF)) {		    (*tty->device.write)(tty->minor,			(char *)&tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail],1);		  }		  else {		    /* remember that output has been stopped due to flow ctrl*/		    tty->flow_ctrl |= FL_OSTOP; 		  }		  tty->rawOutBufState = rob_busy;		}		rtems_interrupt_enable (level);		len--;	}}/* * Handle output processing */static voidoproc (unsigned char c, struct rtems_termios_tty *tty){	int	i;	if (tty->termios.c_oflag & OPOST) {		switch (c) {		case '\n':			if (tty->termios.c_oflag & ONLRET)				tty->column = 0;			if (tty->termios.c_oflag & ONLCR) {				rtems_termios_puts ("\r", 1, tty);				tty->column = 0;			}			break;		case '\r':			if ((tty->termios.c_oflag & ONOCR) && (tty->column == 0))				return;			if (tty->termios.c_oflag & OCRNL) {				c = '\n';				if (tty->termios.c_oflag & ONLRET)					tty->column = 0;				break;			}			tty->column = 0;			break;		case '\t':			i = 8 - (tty->column & 7);			if ((tty->termios.c_oflag & TABDLY) == XTABS) {				tty->column += i;				rtems_termios_puts ( "        ",  i, tty);				return;			}			tty->column += i;			break;		case '\b':			if (tty->column > 0)				tty->column--;			break;		default:			if (tty->termios.c_oflag & OLCUC)				c = toupper(c);			if (!iscntrl(c))				tty->column++;			break;		}	}	rtems_termios_puts (&c, 1, tty);}rtems_status_codertems_termios_write (void *arg){	rtems_libio_rw_args_t *args = arg;	struct rtems_termios_tty *tty = args->iop->data1;	rtems_status_code sc;	sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);	if (sc != RTEMS_SUCCESSFUL)		return sc;	if (linesw[tty->t_line].l_write != NULL) {		sc = linesw[tty->t_line].l_write(tty,args);		rtems_semaphore_release (tty->osem);		return sc;	}	if (tty->termios.c_oflag & OPOST) {		unsigned32 count = args->count;		unsigned8 *buffer = args->buffer;		while (count--)			oproc (*buffer++, tty);		args->bytes_moved = args->count;	}	else {		rtems_termios_puts (args->buffer, args->count, tty);		args->bytes_moved = args->count;	}	rtems_semaphore_release (tty->osem);	return sc;}/* * Echo a typed character */static voidecho (unsigned char c, struct rtems_termios_tty *tty){	if ((tty->termios.c_lflag & ECHOCTL) && iscntrl(c) && (c != '\t') && (c != '\n')) {		char echobuf[2];		echobuf[0] = '^';		echobuf[1] = c ^ 0x40;		rtems_termios_puts (echobuf, 2, tty);		tty->column += 2;	}	else {		oproc (c, tty);	}}/* * Erase a character or line * FIXME: Needs support for WERASE and ECHOPRT. * FIXME: Some of the tests should check for IEXTEN, too. */static voiderase (struct rtems_termios_tty *tty, int lineFlag){	if (tty->ccount == 0)		return;	if (lineFlag) {		if (!(tty->termios.c_lflag & ECHO)) {			tty->ccount = 0;			return;		}		if (!(tty->termios.c_lflag & ECHOE)) {			tty->ccount = 0;			echo (tty->termios.c_cc[VKILL], tty);			if (tty->termios.c_lflag & ECHOK)				echo ('\n', tty);			return;		}	}	while (tty->ccount) {		unsigned char c = tty->cbuf[--tty->ccount];		if (tty->termios.c_lflag & ECHO) {			if (!lineFlag && !(tty->termios.c_lflag & ECHOE)) {				echo (tty->termios.c_cc[VERASE], tty);			}			else if (c == '\t') {				int col = tty->read_start_column;				int i = 0;				/*				 * Find the character before the tab				 */				while (i != tty->ccount) {					c = tty->cbuf[i++];					if (c == '\t') {						col = (col | 7) + 1;					}					else if (iscntrl (c)) {						if (tty->termios.c_lflag & ECHOCTL)							col += 2;					}					else {						col++;					}				}				/*				 * Back up over the tab				 */				while (tty->column > col) {					rtems_termios_puts ("\b", 1, tty);					tty->column--;				}			}			else {				if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) {					rtems_termios_puts ("\b \b", 3, tty);					if (tty->column)						tty->column--;				}				if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) {					rtems_termios_puts ("\b \b", 3, tty);					if (tty->column)						tty->column--;				}			}		}		if (!lineFlag)			break;	}}/* * Process a single input character */static intiproc (unsigned char c, struct rtems_termios_tty *tty){	if (tty->termios.c_iflag & ISTRIP)		c &= 0x7f;	if (tty->termios.c_iflag & IUCLC)		c = tolower (c);	if (c == '\r') {		if (tty->termios.c_iflag & IGNCR)			return 0;		if (tty->termios.c_iflag & ICRNL)			c = '\n';	}	else if ((c == '\n') && (tty->termios.c_iflag & INLCR)) {		c = '\r';	}	if ((c != '\0') && (tty->termios.c_lflag & ICANON)) {		if (c == tty->termios.c_cc[VERASE]) {			erase (tty, 0);			return 0;		}		else if (c == tty->termios.c_cc[VKILL]) {			erase (tty, 1);			return 0;		}		else if (c == tty->termios.c_cc[VEOF]) {			return 1;		}		else if (c == '\n') {			if (tty->termios.c_lflag & (ECHO | ECHONL))				echo (c, tty);			tty->cbuf[tty->ccount++] = c;			return 1;		}		else if ((c == tty->termios.c_cc[VEOL])		      || (c == tty->termios.c_cc[VEOL2])) {			if (tty->termios.c_lflag & ECHO)				echo (c, tty);			tty->cbuf[tty->ccount++] = c;			return 1;		}	}	/*	 * FIXME: Should do IMAXBEL handling somehow	 */	if (tty->ccount < (CBUFSIZE-1)) {		if (tty->termios.c_lflag & ECHO)			echo (c, tty);		tty->cbuf[tty->ccount++] = c;	}	return 0;}/* * Process input character, with semaphore. */static intsiproc (unsigned char c, struct rtems_termios_tty *tty){	int i;	/*	 * Obtain output semaphore if character will be echoed	 */	if (tty->termios.c_lflag & (ECHO|ECHOE|ECHOK|ECHONL|ECHOPRT|ECHOCTL|ECHOKE)) {		rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);		i = iproc (c, tty);		rtems_semaphore_release (tty->osem);	}	else {		i = iproc (c, tty);	}	return i;}/* * Fill the input buffer by polling the device */static rtems_status_codefillBufferPoll (struct rtems_termios_tty *tty){	int n;	if (tty->termios.c_lflag & ICANON) {		for (;;) {			n = (*tty->device.pollRead)(tty->minor);			if (n < 0) {				rtems_task_wake_after (1);			}			else {				if  (siproc (n, tty))					break;			}		}	}	else {		rtems_interval then, now;		if (!tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME])			rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);		for (;;) {			n = (*tty->device.pollRead)(tty->minor);			if (n < 0) {				if (tty->termios.c_cc[VMIN]) {					if (tty->termios.c_cc[VTIME] && tty->ccount) {						rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);						if ((now - then) > tty->vtimeTicks) {							break;						}					}				}				else {					if (!tty->termios.c_cc[VTIME])						break;					rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);					if ((now - then) > tty->vtimeTicks) {						break;

⌨️ 快捷键说明

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