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

📄 n_tty.c

📁 arm平台上的uclinux系统全部源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
			return;		}	}		finish_erasing(tty);	if (L_ECHO(tty)) {		if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {			put_char('\a', tty); /* beep if no space */			return;		}		if (c == '\n')			opost('\n', tty);		else {			/* Record the column of first canon char. */			if (tty->canon_head == tty->read_head)				tty->canon_column = tty->column;			echo_char(c, tty);		}	}	if (I_PARMRK(tty) && c == (unsigned char) '\377')		put_tty_queue(c, tty);	put_tty_queue(c, tty);}	static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,			      char *fp, int count){	const unsigned char *p;	char *f, flags = 0;	int	i;	if (!tty->read_buf)		return;	if (tty->real_raw) {		i = MIN(count, MIN(N_TTY_BUF_SIZE - tty->read_cnt,				   N_TTY_BUF_SIZE - tty->read_head));		memcpy(tty->read_buf + tty->read_head, cp, i);		tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);		tty->read_cnt += i;		cp += i;		count -= i;		i = MIN(count, MIN(N_TTY_BUF_SIZE - tty->read_cnt,			       N_TTY_BUF_SIZE - tty->read_head));		memcpy(tty->read_buf + tty->read_head, cp, i);		tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);		tty->read_cnt += i;	} else {		for (i=count, p = cp, f = fp; i; i--, p++) {			if (f)				flags = *f++;			switch (flags) {			case TTY_NORMAL:				n_tty_receive_char(tty, *p);				break;			case TTY_BREAK:				n_tty_receive_break(tty);				break;			case TTY_PARITY:			case TTY_FRAME:				n_tty_receive_parity_error(tty, *p);				break;			case TTY_OVERRUN:				n_tty_receive_overrun(tty);				break;			default:				printk("%s: unknown flag %d\n", tty_name(tty),				       flags);				break;			}		}		if (tty->driver.flush_chars)			tty->driver.flush_chars(tty);	}	if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) {		if (tty->fasync)			kill_fasync(tty->fasync, SIGIO);		if (tty->read_wait)			wake_up_interruptible(&tty->read_wait);	}	if ((tty->read_cnt >= TTY_THRESHOLD_THROTTLE) &&	    tty->driver.throttle &&	    !set_bit(TTY_THROTTLED, &tty->flags))		tty->driver.throttle(tty);}static int n_tty_receive_room(struct tty_struct *tty){	int	left = N_TTY_BUF_SIZE - tty->read_cnt - 1;	/*	 * If we are doing input canonicalization, and there are no	 * pending newlines, let characters through without limit, so	 * that erase characters will be handled.  Other excess	 * characters will be beeped.	 */	if (tty->icanon && !tty->canon_data)		return N_TTY_BUF_SIZE;	if (left > 0)		return left;	return 0;}int is_ignored(int sig){	return ((current->blocked & (1<<(sig-1))) ||	        (current->sig->action[sig-1].sa_handler == SIG_IGN));}static void n_tty_set_termios(struct tty_struct *tty, struct termios * old){	if (!tty)		return;		tty->icanon = (L_ICANON(tty) != 0);	if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) ||	    I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) ||	    I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) ||	    I_PARMRK(tty)) {		cli();		memset(tty->process_char_map, 0, 256/8);		if (I_IGNCR(tty) || I_ICRNL(tty))			set_bit('\r', &tty->process_char_map);		if (I_INLCR(tty))			set_bit('\n', &tty->process_char_map);		if (L_ICANON(tty)) {			set_bit(ERASE_CHAR(tty), &tty->process_char_map);			set_bit(KILL_CHAR(tty), &tty->process_char_map);			set_bit(EOF_CHAR(tty), &tty->process_char_map);			set_bit('\n', &tty->process_char_map);			set_bit(EOL_CHAR(tty), &tty->process_char_map);			if (L_IEXTEN(tty)) {				set_bit(WERASE_CHAR(tty),					&tty->process_char_map);				set_bit(LNEXT_CHAR(tty),					&tty->process_char_map);				set_bit(EOL2_CHAR(tty),					&tty->process_char_map);				if (L_ECHO(tty))					set_bit(REPRINT_CHAR(tty),						&tty->process_char_map);			}		}		if (I_IXON(tty)) {			set_bit(START_CHAR(tty), &tty->process_char_map);			set_bit(STOP_CHAR(tty), &tty->process_char_map);		}		if (L_ISIG(tty)) {			set_bit(INTR_CHAR(tty), &tty->process_char_map);			set_bit(QUIT_CHAR(tty), &tty->process_char_map);			set_bit(SUSP_CHAR(tty), &tty->process_char_map);		}		clear_bit(__DISABLED_CHAR, &tty->process_char_map);		sti();		tty->raw = 0;		tty->real_raw = 0;	} else {		tty->raw = 1;		if ((I_IGNBRK(tty) || (!I_BRKINT(tty) && !I_PARMRK(tty))) &&		    (I_IGNPAR(tty) || !I_INPCK(tty)) &&		    (tty->driver.flags & TTY_DRIVER_REAL_RAW))			tty->real_raw = 1;		else			tty->real_raw = 0;	}}static void n_tty_close(struct tty_struct *tty){	n_tty_flush_buffer(tty);	if (tty->read_buf) {		kfree_s (tty->read_buf, N_TTY_BUF_SIZE);		tty->read_buf = 0;	}}static int n_tty_open(struct tty_struct *tty){	if (!tty)		return -EINVAL;	if (!tty->read_buf) {		tty->read_buf = (unsigned char *)			kmalloc (N_TTY_BUF_SIZE, intr_count ? GFP_ATOMIC : GFP_KERNEL);		if (!tty->read_buf)			return -ENOMEM;	}	memset(tty->read_buf, 0, N_TTY_BUF_SIZE);	tty->read_head = tty->read_tail = tty->read_cnt = 0;	tty->canon_head = tty->canon_data = tty->erasing = 0;	tty->column = 0;	memset(tty->read_flags, 0, sizeof(tty->read_flags));	n_tty_set_termios(tty, 0);	tty->minimum_to_wake = 1;	tty->closing = 0;	return 0;}static inline int input_available_p(struct tty_struct *tty, int amt){	if (L_ICANON(tty)) {		if (tty->canon_data)			return 1;	} else if (tty->read_cnt >= (amt ? amt : 1))		return 1;	return 0;}/* * Helper function to speed up read_chan.  It is only called when * ICANON is off; it copies characters straight from the tty queue to * user space directly.  It can be profitably called twice; once to * drain the space from the tail pointer to the (physical) end of the * buffer, and once to drain the space from the (physical) beginning of * the buffer to head pointer. */static inline void copy_from_read_buf(struct tty_struct *tty,				      unsigned char **b,				      unsigned int *nr){	int	n;	n = MIN(*nr, MIN(tty->read_cnt, N_TTY_BUF_SIZE - tty->read_tail));	if (!n)		return;	memcpy_tofs(*b, &tty->read_buf[tty->read_tail], n);	tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);	tty->read_cnt -= n;	*b += n;	*nr -= n;}static int read_chan(struct tty_struct *tty, struct file *file,		     unsigned char *buf, unsigned int nr){	struct wait_queue wait = { current, NULL };	int c;	unsigned char *b = buf;	int minimum, time;	int retval = 0;	int size;do_it_again:	if (!tty->read_buf) {		printk("n_tty_read_chan: called with read_buf == NULL?!?\n");		return -EIO;	}	/* Job control check -- must be done at start and after	   every sleep (POSIX.1 7.1.1.4). */	/* NOTE: not yet done after every sleep pending a thorough	   check of the logic of this change. -- jlc */	/* don't stop on /dev/console */	if (file->f_inode->i_rdev != CONSOLE_DEV &&	    current->tty == tty) {		if (tty->pgrp <= 0)			printk("read_chan: tty->pgrp <= 0!\n");		else if (current->pgrp != tty->pgrp) {			if (is_ignored(SIGTTIN) ||			    is_orphaned_pgrp(current->pgrp))				return -EIO;			kill_pg(current->pgrp, SIGTTIN, 1);			return -ERESTARTSYS;		}	}	if (L_ICANON(tty)) {		minimum = time = 0;		current->timeout = (unsigned long) -1;	} else {		time = (HZ / 10) * TIME_CHAR(tty);		minimum = MIN_CHAR(tty);		if (minimum) {		  	current->timeout = (unsigned long) -1;			if (time)				tty->minimum_to_wake = 1;			else if (!waitqueue_active(&tty->read_wait) ||				 (tty->minimum_to_wake > minimum))				tty->minimum_to_wake = minimum;		} else {			if (time) {				current->timeout = time + jiffies;				time = 0;			} else				current->timeout = 0;			tty->minimum_to_wake = minimum = 1;		}	}	add_wait_queue(&tty->read_wait, &wait);	while (1) {		/* First test for status change. */		if (tty->packet && tty->link->ctrl_status) {			if (b != buf)				break;			put_user(tty->link->ctrl_status, b++);			tty->link->ctrl_status = 0;			break;		}		/* This statement must be first before checking for input		   so that any interrupt will set the state back to		   TASK_RUNNING. */		current->state = TASK_INTERRUPTIBLE;				if (((minimum - (b - buf)) < tty->minimum_to_wake) &&		    ((minimum - (b - buf)) >= 1))			tty->minimum_to_wake = (minimum - (b - buf));				if (!input_available_p(tty, 0)) {			if (tty->flags & (1 << TTY_OTHER_CLOSED)) {				retval = -EIO;				break;			}			if (tty_hung_up_p(file))				break;			if (!current->timeout)				break;			if (file->f_flags & O_NONBLOCK) {				retval = -EAGAIN;				break;			}			if (current->signal & ~current->blocked) {				retval = -ERESTARTSYS;				break;			}			schedule();			continue;		}		current->state = TASK_RUNNING;		/* Deal with packet mode. */		if (tty->packet && b == buf) {			put_user(TIOCPKT_DATA, b++);			nr--;		}		if (L_ICANON(tty)) {			while (1) {				int eol;				disable_bh(TQUEUE_BH);				if (!tty->read_cnt) {					enable_bh(TQUEUE_BH);					break;				}				eol = clear_bit(tty->read_tail,						&tty->read_flags);				c = tty->read_buf[tty->read_tail];				tty->read_tail = ((tty->read_tail+1) &						  (N_TTY_BUF_SIZE-1));				tty->read_cnt--;				enable_bh(TQUEUE_BH);				if (!eol) {					put_user(c, b++);					if (--nr)						continue;					break;				}				if (--tty->canon_data < 0) {					tty->canon_data = 0;				}				if (c != __DISABLED_CHAR) {					put_user(c, b++);					nr--;				}				break;			}		} else {			disable_bh(TQUEUE_BH);			copy_from_read_buf(tty, &b, &nr);			copy_from_read_buf(tty, &b, &nr);			enable_bh(TQUEUE_BH);		}		/* If there is enough space in the read buffer now, let the		   low-level driver know. */		if (tty->driver.unthrottle &&		    (tty->read_cnt <= TTY_THRESHOLD_UNTHROTTLE)		    && clear_bit(TTY_THROTTLED, &tty->flags))			tty->driver.unthrottle(tty);		if (b - buf >= minimum || !nr)			break;		if (time)			current->timeout = time + jiffies;	}	remove_wait_queue(&tty->read_wait, &wait);	if (!waitqueue_active(&tty->read_wait))		tty->minimum_to_wake = minimum;	current->state = TASK_RUNNING;	current->timeout = 0;	size = b - buf;	if (size && nr)	        clear_bit(TTY_PUSH, &tty->flags);        if (!size && clear_bit(TTY_PUSH, &tty->flags))                goto do_it_again;	if (!size && !retval)	        clear_bit(TTY_PUSH, &tty->flags);        return (size ? size : retval);}static int write_chan(struct tty_struct * tty, struct file * file,		      const unsigned char * buf, unsigned int nr){	struct wait_queue wait = { current, NULL };	int c;	const unsigned char *b = buf;	int retval = 0;	/* Job control check -- must be done at start (POSIX.1 7.1.1.4). */	if (L_TOSTOP(tty) && file->f_inode->i_rdev != CONSOLE_DEV) {		retval = tty_check_change(tty);		if (retval)			return retval;	}	add_wait_queue(&tty->write_wait, &wait);	while (1) {		current->state = TASK_INTERRUPTIBLE;		if (current->signal & ~current->blocked) {			retval = -ERESTARTSYS;			break;		}		if (tty_hung_up_p(file) || (tty->link && !tty->link->count)) {			retval = -EIO;			break;		}		if (O_OPOST(tty)) {			while (nr > 0) {				c = get_user(b);				if (opost(c, tty) < 0)					break;				b++; nr--;			}			if (tty->driver.flush_chars)				tty->driver.flush_chars(tty);		} else {			c = tty->driver.write(tty, 1, b, nr);			b += c;			nr -= c;		}		if (!nr)			break;		if (file->f_flags & O_NONBLOCK) {			retval = -EAGAIN;			break;		}		schedule();	}	current->state = TASK_RUNNING;	remove_wait_queue(&tty->write_wait, &wait);	return (b - buf) ? b - buf : retval;}static int normal_select(struct tty_struct * tty, struct inode * inode,			 struct file * file, int sel_type, select_table *wait){	switch (sel_type) {		case SEL_IN:			if (input_available_p(tty, TIME_CHAR(tty) ? 0 :					      MIN_CHAR(tty)))				return 1;			/* fall through */		case SEL_EX:			if (tty->packet && tty->link->ctrl_status)				return 1;			if (tty->flags & (1 << TTY_OTHER_CLOSED))				return 1;			if (tty_hung_up_p(file))				return 1;			if (!waitqueue_active(&tty->read_wait)) {				if (MIN_CHAR(tty) && !TIME_CHAR(tty))					tty->minimum_to_wake = MIN_CHAR(tty);				else					tty->minimum_to_wake = 1;			}			select_wait(&tty->read_wait, wait);			return 0;		case SEL_OUT:			if (tty->driver.chars_in_buffer(tty) < WAKEUP_CHARS)				return 1;			select_wait(&tty->write_wait, wait);			return 0;	}	return 0;}struct tty_ldisc tty_ldisc_N_TTY = {	TTY_LDISC_MAGIC,	/* magic */	0,			/* num */	0,			/* flags */	n_tty_open,		/* open */	n_tty_close,		/* close */	n_tty_flush_buffer,	/* flush_buffer */	n_tty_chars_in_buffer,	/* chars_in_buffer */	read_chan,		/* read */	write_chan,		/* write */	n_tty_ioctl,		/* ioctl */	n_tty_set_termios,	/* set_termios */	normal_select,		/* select */	n_tty_receive_buf,	/* receive_buf */	n_tty_receive_room,	/* receive_room */	0			/* write_wakeup */};

⌨️ 快捷键说明

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