static void tty_receive_char(struct tty_struct *tty, char ch)
{
	if (tty == NULL)
		return;

	if (I_IXON(tty) && !I_IXOFF(tty) && !tty->raw) {
		if (ch == STOP_CHAR(tty)) {
			stop_tty(tty);
			return;
		}
		else if (ch == START_CHAR(tty)) {
			start_tty(tty);
			return;
		}
	}

	tty_insert_flip_char(tty, ch, TTY_NORMAL);
}
static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
{
	unsigned long flags;
	int parmrk;

	if (tty->raw) {
		put_tty_queue(c, tty);
		return;
	}

	if (I_ISTRIP(tty))
		c &= 0x7f;
	if (I_IUCLC(tty) && L_IEXTEN(tty))
		c = tolower(c);

	if (L_EXTPROC(tty)) {
		put_tty_queue(c, tty);
		return;
	}

	if (tty->stopped && !tty->flow_stopped && I_IXON(tty) &&
	    I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty) &&
	    c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) && c != SUSP_CHAR(tty)) {
		start_tty(tty);
		process_echoes(tty);
	}

	if (tty->closing) {
		if (I_IXON(tty)) {
			if (c == START_CHAR(tty)) {
				start_tty(tty);
				process_echoes(tty);
			} else if (c == STOP_CHAR(tty))
				stop_tty(tty);
		}
		return;
	}

	if (!test_bit(c, tty->process_char_map) || tty->lnext) {
		tty->lnext = 0;
		parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0;
		if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
			
			if (L_ECHO(tty))
				process_output('\a', tty);
			return;
		}
		if (L_ECHO(tty)) {
			finish_erasing(tty);
			
			if (tty->canon_head == tty->read_head)
				echo_set_canon_col(tty);
			echo_char(c, tty);
			process_echoes(tty);
		}
		if (parmrk)
			put_tty_queue(c, tty);
		put_tty_queue(c, tty);
		return;
	}

	if (I_IXON(tty)) {
		if (c == START_CHAR(tty)) {
			start_tty(tty);
			process_echoes(tty);
			return;
		}
		if (c == STOP_CHAR(tty)) {
			stop_tty(tty);
			return;
		}
	}

	if (L_ISIG(tty)) {
		int signal;
		signal = SIGINT;
		if (c == INTR_CHAR(tty))
			goto send_signal;
		signal = SIGQUIT;
		if (c == QUIT_CHAR(tty))
			goto send_signal;
		signal = SIGTSTP;
		if (c == SUSP_CHAR(tty)) {
send_signal:
			if (!L_NOFLSH(tty)) {
				n_tty_flush_buffer(tty);
				tty_driver_flush_buffer(tty);
			}
			if (I_IXON(tty))
				start_tty(tty);
			if (L_ECHO(tty)) {
				echo_char(c, tty);
				process_echoes(tty);
			}
			if (tty->pgrp)
				kill_pgrp(tty->pgrp, signal, 1);
			return;
		}
	}

	if (c == '\r') {
		if (I_IGNCR(tty))
			return;
		if (I_ICRNL(tty))
			c = '\n';
	} else if (c == '\n' && I_INLCR(tty))
		c = '\r';

	if (tty->icanon) {
		if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) ||
		    (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) {
			eraser(c, tty);
			process_echoes(tty);
			return;
		}
		if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) {
			tty->lnext = 1;
			if (L_ECHO(tty)) {
				finish_erasing(tty);
				if (L_ECHOCTL(tty)) {
					echo_char_raw('^', tty);
					echo_char_raw('\b', tty);
					process_echoes(tty);
				}
			}
			return;
		}
		if (c == REPRINT_CHAR(tty) && L_ECHO(tty) &&
		    L_IEXTEN(tty)) {
			unsigned long tail = tty->canon_head;

			finish_erasing(tty);
			echo_char(c, tty);
			echo_char_raw('\n', tty);
			while (tail != tty->read_head) {
				echo_char(tty->read_buf[tail], tty);
				tail = (tail+1) & (N_TTY_BUF_SIZE-1);
			}
			process_echoes(tty);
			return;
		}
		if (c == '\n') {
			if (tty->read_cnt >= N_TTY_BUF_SIZE) {
				if (L_ECHO(tty))
					process_output('\a', tty);
				return;
			}
			if (L_ECHO(tty) || L_ECHONL(tty)) {
				echo_char_raw('\n', tty);
				process_echoes(tty);
			}
			goto handle_newline;
		}
		if (c == EOF_CHAR(tty)) {
			if (tty->read_cnt >= N_TTY_BUF_SIZE)
				return;
			if (tty->canon_head != tty->read_head)
				set_bit(TTY_PUSH, &tty->flags);
			c = __DISABLED_CHAR;
			goto handle_newline;
		}
		if ((c == EOL_CHAR(tty)) ||
		    (c == EOL2_CHAR(tty) && L_IEXTEN(tty))) {
			parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty))
				 ? 1 : 0;
			if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk)) {
				if (L_ECHO(tty))
					process_output('\a', tty);
				return;
			}
			if (L_ECHO(tty)) {
				
				if (tty->canon_head == tty->read_head)
					echo_set_canon_col(tty);
				echo_char(c, tty);
				process_echoes(tty);
			}
			if (parmrk)
				put_tty_queue(c, tty);

handle_newline:
			spin_lock_irqsave(&tty->read_lock, flags);
			set_bit(tty->read_head, tty->read_flags);
			put_tty_queue_nolock(c, tty);
			tty->canon_head = tty->read_head;
			tty->canon_data++;
			spin_unlock_irqrestore(&tty->read_lock, flags);
			kill_fasync(&tty->fasync, SIGIO, POLL_IN);
			if (waitqueue_active(&tty->read_wait))
				wake_up_interruptible(&tty->read_wait);
			return;
		}
	}

	parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0;
	if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
		
		if (L_ECHO(tty))
			process_output('\a', tty);
		return;
	}
	if (L_ECHO(tty)) {
		finish_erasing(tty);
		if (c == '\n')
			echo_char_raw('\n', tty);
		else {
			
			if (tty->canon_head == tty->read_head)
				echo_set_canon_col(tty);
			echo_char(c, tty);
		}
		process_echoes(tty);
	}

	if (parmrk)
		put_tty_queue(c, tty);

	put_tty_queue(c, tty);
}
static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
{
	int canon_change = 1;
	BUG_ON(!tty);

	if (old)
		canon_change = (old->c_lflag ^ tty->termios->c_lflag) & ICANON;
	if (canon_change) {
		memset(&tty->read_flags, 0, sizeof tty->read_flags);
		tty->canon_head = tty->read_tail;
		tty->canon_data = 0;
		tty->erasing = 0;
	}

	if (canon_change && !L_ICANON(tty) && tty->read_cnt)
		wake_up_interruptible(&tty->read_wait);

	tty->icanon = (L_ICANON(tty) != 0);
	if (test_bit(TTY_HW_COOK_IN, &tty->flags)) {
		tty->raw = 1;
		tty->real_raw = 1;
		n_tty_set_room(tty);
		return;
	}
	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)) {
		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);
		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;
	}
	n_tty_set_room(tty);
	
	wake_up_interruptible(&tty->write_wait);
	wake_up_interruptible(&tty->read_wait);
}
Example #4
0
static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
{
	if (tty->raw) {
		put_tty_queue(c, tty);
		return;
	}
	
	if (tty->stopped && I_IXON(tty) && I_IXANY(tty)) {
		start_tty(tty);
		return;
	}
	
	if (I_ISTRIP(tty))
		c &= 0x7f;
	if (I_IUCLC(tty) && L_IEXTEN(tty))
		c=tolower(c);

	if (tty->closing) {
		if (I_IXON(tty)) {
			if (c == START_CHAR(tty))
				start_tty(tty);
			else if (c == STOP_CHAR(tty))
				stop_tty(tty);
		}
		return;
	}

	/*
	 * If the previous character was LNEXT, or we know that this
	 * character is not one of the characters that we'll have to
	 * handle specially, do shortcut processing to speed things
	 * up.
	 */
	if (!test_bit(c, &tty->process_char_map) || tty->lnext) {
		finish_erasing(tty);
		tty->lnext = 0;
		if (L_ECHO(tty)) {
			if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
				put_char('\a', tty); /* beep if no space */
				return;
			}
			/* 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);
		return;
	}
		
	if (c == '\r') {
		if (I_IGNCR(tty))
			return;
		if (I_ICRNL(tty))
			c = '\n';
	} else if (c == '\n' && I_INLCR(tty))
		c = '\r';
	if (I_IXON(tty)) {
		if (c == START_CHAR(tty)) {
			start_tty(tty);
			return;
		}
		if (c == STOP_CHAR(tty)) {
			stop_tty(tty);
			return;
		}
	}
	if (L_ISIG(tty)) {
		int signal;
		signal = SIGINT;
		if (c == INTR_CHAR(tty))
			goto send_signal;
		signal = SIGQUIT;
		if (c == QUIT_CHAR(tty))
			goto send_signal;
		signal = SIGTSTP;
		if (c == SUSP_CHAR(tty)) {
send_signal:
			isig(signal, tty, 0);
			return;
		}
	}
	if (L_ICANON(tty)) {
		if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) ||
		    (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) {
			eraser(c, tty);
			return;
		}
		if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) {
			tty->lnext = 1;
			if (L_ECHO(tty)) {
				finish_erasing(tty);
				if (L_ECHOCTL(tty)) {
					put_char('^', tty);
					put_char('\b', tty);
				}
			}
			return;
		}
		if (c == REPRINT_CHAR(tty) && L_ECHO(tty) &&
		    L_IEXTEN(tty)) {
			unsigned long tail = tty->canon_head;

			finish_erasing(tty);
			echo_char(c, tty);
			opost('\n', tty);
			while (tail != tty->read_head) {
				echo_char(tty->read_buf[tail], tty);
				tail = (tail+1) & (N_TTY_BUF_SIZE-1);
			}
			return;
		}
		if (c == '\n') {
			if (L_ECHO(tty) || L_ECHONL(tty)) {
				if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
					put_char('\a', tty);
					return;
				}
				opost('\n', tty);
			}
			goto handle_newline;
		}
		if (c == EOF_CHAR(tty)) {
		        if (tty->canon_head != tty->read_head)
			        set_bit(TTY_PUSH, &tty->flags);
			c = __DISABLED_CHAR;
			goto handle_newline;
		}
		if ((c == EOL_CHAR(tty)) ||
		    (c == EOL2_CHAR(tty) && L_IEXTEN(tty))) {
			/*
			 * XXX are EOL_CHAR and EOL2_CHAR echoed?!?
			 */
			if (L_ECHO(tty)) {
				if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
					put_char('\a', tty);
					return;
				}
				/* Record the column of first canon char. */
				if (tty->canon_head == tty->read_head)
					tty->canon_column = tty->column;
				echo_char(c, tty);
			}
			/*
			 * XXX does PARMRK doubling happen for
			 * EOL_CHAR and EOL2_CHAR?
			 */
			if (I_PARMRK(tty) && c == (unsigned char) '\377')
				put_tty_queue(c, tty);

		handle_newline:
			set_bit(tty->read_head, &tty->read_flags);
			put_tty_queue(c, tty);
			tty->canon_head = tty->read_head;
			tty->canon_data++;
			if (tty->fasync)
				kill_fasync(tty->fasync, SIGIO);
			if (tty->read_wait)
				wake_up_interruptible(&tty->read_wait);
			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);
}	
Example #5
0
static void ssu100_set_termios(struct tty_struct *tty,
			       struct usb_serial_port *port,
			       struct ktermios *old_termios)
{
	struct usb_device *dev = port->serial->dev;
	struct ktermios *termios = &tty->termios;
	u16 baud, divisor, remainder;
	unsigned int cflag = termios->c_cflag;
	u16 urb_value = 0; /* will hold the new flags */
	int result;

	if (cflag & PARENB) {
		if (cflag & PARODD)
			urb_value |= UART_LCR_PARITY;
		else
			urb_value |= SERIAL_EVEN_PARITY;
	}

	switch (cflag & CSIZE) {
	case CS5:
		urb_value |= UART_LCR_WLEN5;
		break;
	case CS6:
		urb_value |= UART_LCR_WLEN6;
		break;
	case CS7:
		urb_value |= UART_LCR_WLEN7;
		break;
	default:
	case CS8:
		urb_value |= UART_LCR_WLEN8;
		break;
	}

	baud = tty_get_baud_rate(tty);
	if (!baud)
		baud = 9600;

	dev_dbg(&port->dev, "%s - got baud = %d\n", __func__, baud);


	divisor = MAX_BAUD_RATE / baud;
	remainder = MAX_BAUD_RATE % baud;
	if (((remainder * 2) >= baud) && (baud != 110))
		divisor++;

	urb_value = urb_value << 8;

	result = ssu100_control_msg(dev, QT_GET_SET_UART, divisor, urb_value);
	if (result < 0)
		dev_dbg(&port->dev, "%s - set uart failed\n", __func__);

	if (cflag & CRTSCTS)
		result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
					    SERIAL_CRTSCTS, 0);
	else
		result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
					    0, 0);
	if (result < 0)
		dev_dbg(&port->dev, "%s - set HW flow control failed\n", __func__);

	if (I_IXOFF(tty) || I_IXON(tty)) {
		u16 x = ((u16)(START_CHAR(tty) << 8) | (u16)(STOP_CHAR(tty)));

		result = ssu100_control_msg(dev, QT_SW_FLOW_CONTROL_MASK,
					    x, 0);
	} else
		result = ssu100_control_msg(dev, QT_SW_FLOW_CONTROL_MASK,
					    0, 0);

	if (result < 0)
		dev_dbg(&port->dev, "%s - set SW flow control failed\n", __func__);

}
Example #6
0
static void qt2_set_termios(struct tty_struct *tty,
			    struct usb_serial_port *port,
			    struct ktermios *old_termios)
{
	struct usb_device *dev = port->serial->dev;
	struct qt2_port_private *port_priv;
	struct ktermios *termios = &tty->termios;
	u16 baud;
	unsigned int cflag = termios->c_cflag;
	u16 new_lcr = 0;
	int status;

	port_priv = usb_get_serial_port_data(port);

	if (cflag & PARENB) {
		if (cflag & PARODD)
			new_lcr |= UART_LCR_PARITY;
		else
			new_lcr |= SERIAL_EVEN_PARITY;
	}

	switch (cflag & CSIZE) {
	case CS5:
		new_lcr |= UART_LCR_WLEN5;
		break;
	case CS6:
		new_lcr |= UART_LCR_WLEN6;
		break;
	case CS7:
		new_lcr |= UART_LCR_WLEN7;
		break;
	default:
	case CS8:
		new_lcr |= UART_LCR_WLEN8;
		break;
	}

	baud = tty_get_baud_rate(tty);
	if (!baud)
		baud = 9600;

	status = qt2_set_port_config(dev, port_priv->device_port, baud,
				     new_lcr);
	if (status < 0)
		dev_err(&port->dev, "%s - qt2_set_port_config failed: %i\n",
			__func__, status);

	if (cflag & CRTSCTS)
		status = qt2_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
					 SERIAL_CRTSCTS,
					 port_priv->device_port);
	else
		status = qt2_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
					 0, port_priv->device_port);
	if (status < 0)
		dev_err(&port->dev, "%s - set HW flow control failed: %i\n",
			__func__, status);

	if (I_IXOFF(tty) || I_IXON(tty)) {
		u16 x = ((u16) (START_CHAR(tty) << 8) | (u16) (STOP_CHAR(tty)));

		status = qt2_control_msg(dev, QT_SW_FLOW_CONTROL_MASK,
					 x, port_priv->device_port);
	} else
		status = qt2_control_msg(dev, QT_SW_FLOW_CONTROL_MASK,
					 0, port_priv->device_port);

	if (status < 0)
		dev_err(&port->dev, "%s - set SW flow control failed: %i\n",
			__func__, status);

}
Example #7
0
static void tiny_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
	unsigned int cflag;

	cflag = tty->termios.c_cflag;

	/* check that they really want us to change something */
	if (old_termios) {
		if ((cflag == old_termios->c_cflag) &&
		    (RELEVANT_IFLAG(tty->termios.c_iflag) ==
		     RELEVANT_IFLAG(old_termios->c_iflag))) {
			printk(KERN_DEBUG " - nothing to change...\n");
			return;
		}
	}

	/* get the byte size */
	switch (cflag & CSIZE) {
		case CS5:
			printk(KERN_DEBUG " - data bits = 5\n");
			break;
		case CS6:
			printk(KERN_DEBUG " - data bits = 6\n");
			break;
		case CS7:
			printk(KERN_DEBUG " - data bits = 7\n");
			break;
		default:
		case CS8:
			printk(KERN_DEBUG " - data bits = 8\n");
			break;
	}
	
	/* determine the parity */
	if (cflag & PARENB)
		if (cflag & PARODD)
			printk(KERN_DEBUG " - parity = odd\n");
		else
			printk(KERN_DEBUG " - parity = even\n");
	else
		printk(KERN_DEBUG " - parity = none\n");

	/* figure out the stop bits requested */
	if (cflag & CSTOPB)
		printk(KERN_DEBUG " - stop bits = 2\n");
	else
		printk(KERN_DEBUG " - stop bits = 1\n");

	/* figure out the hardware flow control settings */
	if (cflag & CRTSCTS)
		printk(KERN_DEBUG " - RTS/CTS is enabled\n");
	else
		printk(KERN_DEBUG " - RTS/CTS is disabled\n");
	
	/* determine software flow control */
	/* if we are implementing XON/XOFF, set the start and 
	 * stop character in the device */
	if (I_IXOFF(tty) || I_IXON(tty)) {
		unsigned char stop_char  = STOP_CHAR(tty);
		unsigned char start_char = START_CHAR(tty);

		/* if we are implementing INBOUND XON/XOFF */
		if (I_IXOFF(tty))
			printk(KERN_DEBUG " - INBOUND XON/XOFF is enabled, "
				"XON = %2x, XOFF = %2x", start_char, stop_char);
		else
			printk(KERN_DEBUG" - INBOUND XON/XOFF is disabled");

		/* if we are implementing OUTBOUND XON/XOFF */
		if (I_IXON(tty))
			printk(KERN_DEBUG" - OUTBOUND XON/XOFF is enabled, "
				"XON = %2x, XOFF = %2x", start_char, stop_char);
		else
			printk(KERN_DEBUG" - OUTBOUND XON/XOFF is disabled");
	}

	/* get the baud rate wanted */
	printk(KERN_DEBUG " - baud rate = %d", tty_get_baud_rate(tty));
}
Example #8
0
static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
{
	if (!tty)
		return;
	
	tty->icanon = (L_ICANON(tty) != 0);
	if (test_bit(TTY_HW_COOK_IN, &tty->flags)) {
		tty->raw = 1;
		tty->real_raw = 1;
		return;
	}
	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;
	}
}
Example #9
0
static void mxu1_set_termios(struct tty_struct *tty,
			     struct usb_serial_port *port,
			     struct ktermios *old_termios)
{
	struct mxu1_port *mxport = usb_get_serial_port_data(port);
	struct mxu1_uart_config *config;
	tcflag_t cflag, iflag;
	speed_t baud;
	int status;
	unsigned int mcr;

	dev_dbg(&port->dev, "%s\n", __func__);

	cflag = tty->termios.c_cflag;
	iflag = tty->termios.c_iflag;

	if (old_termios &&
	    !tty_termios_hw_change(&tty->termios, old_termios) &&
	    tty->termios.c_iflag == old_termios->c_iflag) {
		dev_dbg(&port->dev, "%s - nothing to change\n", __func__);
		return;
	}

	dev_dbg(&port->dev,
		"%s - clfag %08x, iflag %08x\n", __func__, cflag, iflag);

	if (old_termios) {
		dev_dbg(&port->dev, "%s - old clfag %08x, old iflag %08x\n",
			__func__,
			old_termios->c_cflag,
			old_termios->c_iflag);
	}

	config = kzalloc(sizeof(*config), GFP_KERNEL);
	if (!config)
		return;

	config->wFlags = 0;

	/* these flags must be set */
	config->wFlags |= MXU1_UART_ENABLE_MS_INTS;
	config->wFlags |= MXU1_UART_ENABLE_AUTO_START_DMA;
	if (mxport->mxp_send_break == MXU1_LCR_BREAK)
		config->wFlags |= MXU1_UART_SEND_BREAK_SIGNAL;
	config->bUartMode = (u8)(mxport->mxp_uart_mode);

	switch (C_CSIZE(tty)) {
	case CS5:
		config->bDataBits = MXU1_UART_5_DATA_BITS;
		break;
	case CS6:
		config->bDataBits = MXU1_UART_6_DATA_BITS;
		break;
	case CS7:
		config->bDataBits = MXU1_UART_7_DATA_BITS;
		break;
	default:
	case CS8:
		config->bDataBits = MXU1_UART_8_DATA_BITS;
		break;
	}

	if (C_PARENB(tty)) {
		config->wFlags |= MXU1_UART_ENABLE_PARITY_CHECKING;
		if (C_CMSPAR(tty)) {
			if (C_PARODD(tty))
				config->bParity = MXU1_UART_MARK_PARITY;
			else
				config->bParity = MXU1_UART_SPACE_PARITY;
		} else {
			if (C_PARODD(tty))
				config->bParity = MXU1_UART_ODD_PARITY;
			else
				config->bParity = MXU1_UART_EVEN_PARITY;
		}
	} else {
		config->bParity = MXU1_UART_NO_PARITY;
	}

	if (C_CSTOPB(tty))
		config->bStopBits = MXU1_UART_2_STOP_BITS;
	else
		config->bStopBits = MXU1_UART_1_STOP_BITS;

	if (C_CRTSCTS(tty)) {
		/* RTS flow control must be off to drop RTS for baud rate B0 */
		if (C_BAUD(tty) != B0)
			config->wFlags |= MXU1_UART_ENABLE_RTS_IN;
		config->wFlags |= MXU1_UART_ENABLE_CTS_OUT;
	}

	if (I_IXOFF(tty) || I_IXON(tty)) {
		config->cXon  = START_CHAR(tty);
		config->cXoff = STOP_CHAR(tty);

		if (I_IXOFF(tty))
			config->wFlags |= MXU1_UART_ENABLE_X_IN;

		if (I_IXON(tty))
			config->wFlags |= MXU1_UART_ENABLE_X_OUT;
	}

	baud = tty_get_baud_rate(tty);
	if (!baud)
		baud = 9600;
	config->wBaudRate = MXU1_BAUD_BASE / baud;

	dev_dbg(&port->dev, "%s - BaudRate=%d, wBaudRate=%d, wFlags=0x%04X, bDataBits=%d, bParity=%d, bStopBits=%d, cXon=%d, cXoff=%d, bUartMode=%d\n",
		__func__, baud, config->wBaudRate, config->wFlags,
		config->bDataBits, config->bParity, config->bStopBits,
		config->cXon, config->cXoff, config->bUartMode);

	cpu_to_be16s(&config->wBaudRate);
	cpu_to_be16s(&config->wFlags);

	status = mxu1_send_ctrl_data_urb(port->serial, MXU1_SET_CONFIG, 0,
					 MXU1_UART1_PORT, (u8 *)config,
					 sizeof(*config));
	if (status)
		dev_err(&port->dev, "cannot set config: %d\n", status);

	mutex_lock(&mxport->mxp_mutex);
	mcr = mxport->mxp_mcr;

	if (C_BAUD(tty) == B0)
		mcr &= ~(MXU1_MCR_DTR | MXU1_MCR_RTS);
	else if (old_termios && (old_termios->c_cflag & CBAUD) == B0)
		mcr |= ~(MXU1_MCR_DTR | MXU1_MCR_RTS);

	status = mxu1_set_mcr(port, mcr);
	if (status)
		dev_err(&port->dev, "cannot set modem control: %d\n", status);
	else
		mxport->mxp_mcr = mcr;

	mutex_unlock(&mxport->mxp_mutex);

	kfree(config);
}
Example #10
0
static void qt_set_termios(struct tty_struct *tty,
			   struct usb_serial_port *port,
			   struct ktermios *old_termios)
{
	struct ktermios *termios = &tty->termios;
	unsigned char new_LCR = 0;
	unsigned int cflag = termios->c_cflag;
	unsigned int index;
	int baud, divisor, remainder;
	int status;

	index = tty->index - port->serial->minor;

	switch (cflag & CSIZE) {
	case CS5:
		new_LCR |= SERIAL_5_DATA;
		break;
	case CS6:
		new_LCR |= SERIAL_6_DATA;
		break;
	case CS7:
		new_LCR |= SERIAL_7_DATA;
		break;
	default:
		termios->c_cflag &= ~CSIZE;
		termios->c_cflag |= CS8;
	case CS8:
		new_LCR |= SERIAL_8_DATA;
		break;
	}

	/* Parity stuff */
	if (cflag & PARENB) {
		if (cflag & PARODD)
			new_LCR |= SERIAL_ODD_PARITY;
		else
			new_LCR |= SERIAL_EVEN_PARITY;
	}
	if (cflag & CSTOPB)
		new_LCR |= SERIAL_TWO_STOPB;
	else
		new_LCR |= SERIAL_ONE_STOPB;

	dev_dbg(&port->dev, "%s - 4\n", __func__);

	/* Thats the LCR stuff, go ahead and set it */
	baud = tty_get_baud_rate(tty);
	if (!baud)
		/* pick a default, any default... */
		baud = 9600;

	dev_dbg(&port->dev, "%s - got baud = %d\n", __func__, baud);

	divisor = MAX_BAUD_RATE / baud;
	remainder = MAX_BAUD_RATE % baud;
	/* Round to nearest divisor */
	if (((remainder * 2) >= baud) && (baud != 110))
		divisor++;

	/*
	 * Set Baud rate to default and turn off (default)flow control here
	 */
	status =
	    qt_setuart(port->serial, index, (unsigned short)divisor, new_LCR);
	if (status < 0) {
		dev_dbg(&port->dev, "qt_setuart failed\n");
		return;
	}

	/* Now determine flow control */
	if (cflag & CRTSCTS) {
		dev_dbg(&port->dev, "%s - Enabling HW flow control port %d\n",
			__func__, port->number);

		/* Enable RTS/CTS flow control */
		status = BoxSetHW_FlowCtrl(port->serial, index, 1);

		if (status < 0) {
			dev_dbg(&port->dev, "BoxSetHW_FlowCtrl failed\n");
			return;
		}
	} else {
		/* Disable RTS/CTS flow control */
		dev_dbg(&port->dev,
			"%s - disabling HW flow control port %d\n",
			__func__, port->number);

		status = BoxSetHW_FlowCtrl(port->serial, index, 0);
		if (status < 0) {
			dev_dbg(&port->dev, "BoxSetHW_FlowCtrl failed\n");
			return;
		}

	}

	/* if we are implementing XON/XOFF, set the start and stop character in
	 * the device */
	if (I_IXOFF(tty) || I_IXON(tty)) {
		unsigned char stop_char = STOP_CHAR(tty);
		unsigned char start_char = START_CHAR(tty);
		status =
		    BoxSetSW_FlowCtrl(port->serial, index, stop_char,
				      start_char);
		if (status < 0)
			dev_dbg(&port->dev,
				"BoxSetSW_FlowCtrl (enabled) failed\n");

	} else {
		/* disable SW flow control */
		status = BoxDisable_SW_FlowCtrl(port->serial, index);
		if (status < 0)
			dev_dbg(&port->dev,
				"BoxSetSW_FlowCtrl (diabling) failed\n");

	}
	termios->c_cflag &= ~CMSPAR;
	/* FIXME:
	   Error cases should be returning the actual bits changed only
	*/
}
Example #11
0
static void copy_to_cooked(struct tty_struct * tty)
{
	int c, special_flag;
	unsigned long flags;

	if (!tty) {
		printk("copy_to_cooked: called with NULL tty\n");
		return;
	}
	if (!tty->write) {
		printk("copy_to_cooked: tty %d has null write routine\n",
		       tty->line);
	}
	while (1) {
		/*
		 * Check to see how much room we have left in the
		 * secondary queue.  Send a throttle command or abort
		 * if necessary.
		 */
		c = LEFT(&tty->secondary);
		if (tty->throttle && (c < SQ_THRESHOLD_LW)
		    && !set_bit(TTY_SQ_THROTTLED, &tty->flags))
			tty->throttle(tty, TTY_THROTTLE_SQ_FULL);
		if (c == 0)
			break;
		save_flags(flags); cli();
		if (!EMPTY(&tty->read_q)) {
			c = tty->read_q.buf[tty->read_q.tail];
			special_flag = clear_bit(tty->read_q.tail,
						 &tty->readq_flags);
			INC(tty->read_q.tail);
			restore_flags(flags);
		} else {
			restore_flags(flags);
			break;
		}
		if (special_flag) {
			tty->char_error = c;
			continue;
		}
		if (tty->char_error) {
			if (tty->char_error == TTY_BREAK) {
				tty->char_error = 0;
				if (I_IGNBRK(tty))
					continue;
				/* A break is handled by the lower levels. */
				if (I_BRKINT(tty))
					continue;
				if (I_PARMRK(tty)) {
					put_tty_queue('\377', &tty->secondary);
					put_tty_queue('\0', &tty->secondary);
				}
				put_tty_queue('\0', &tty->secondary);
				continue;
			}
			if (tty->char_error == TTY_OVERRUN) {
				tty->char_error = 0;
				printk("tty%d: input overrun\n", tty->line);
				continue;
			}
			/* Must be a parity or frame error */
			tty->char_error = 0;
			if (I_IGNPAR(tty)) {
				continue;
			}
			if (I_PARMRK(tty)) {
				put_tty_queue('\377', &tty->secondary);
				put_tty_queue('\0', &tty->secondary);
				put_tty_queue(c, &tty->secondary);
			} else
				put_tty_queue('\0', &tty->secondary);
			continue;
		}
		if (I_ISTRIP(tty))
			c &= 0x7f;
		if (!tty->lnext) {
			if (c == '\r') {
				if (I_IGNCR(tty))
					continue;
				if (I_ICRNL(tty))
					c = '\n';
			} else if (c == '\n' && I_INLCR(tty))
				c = '\r';
		}
		if (I_IUCLC(tty) && L_IEXTEN(tty))
			c=tolower(c);
		if (c == __DISABLED_CHAR)
			tty->lnext = 1;
		if (L_ICANON(tty) && !tty->lnext) {
			if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) ||
			    (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) {
				eraser(c, tty);
				continue;
			}
			if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) {
				tty->lnext = 1;
				if (L_ECHO(tty)) {
					if (tty->erasing) {
						opost('/', tty);
						tty->erasing = 0;
					}
					if (L_ECHOCTL(tty)) {
						opost('^', tty);
						opost('\b', tty);
					}
				}
				continue;
			}
			if (c == REPRINT_CHAR(tty) && L_ECHO(tty) &&
			    L_IEXTEN(tty)) {
				unsigned long tail = tty->canon_head;

				if (tty->erasing) {
					opost('/', tty);
					tty->erasing = 0;
				}
				echo_char(c, tty);
				opost('\n', tty);
				while (tail != tty->secondary.head) {
					echo_char(tty->secondary.buf[tail],
						  tty);
					INC(tail);
				}
				continue;
			}
		}
		if (I_IXON(tty) && !tty->lnext) {
			if ((tty->stopped && I_IXANY(tty) && L_IEXTEN(tty)) ||
			    c == START_CHAR(tty)) {
				start_tty(tty);
				continue;
			}
			if (c == STOP_CHAR(tty)) {
				stop_tty(tty);
				continue;
			}
		}
		if (L_ISIG(tty) && !tty->lnext) {
			if (c == INTR_CHAR(tty)) {
				isig(SIGINT, tty);
				continue;
			}
			if (c == QUIT_CHAR(tty)) {
				isig(SIGQUIT, tty);
				continue;
			}
			if (c == SUSP_CHAR(tty)) {
				if (!is_orphaned_pgrp(tty->pgrp))
					isig(SIGTSTP, tty);
				continue;
			}
		}

		if (tty->erasing) {
			opost('/', tty);
			tty->erasing = 0;
		}
		if (c == '\n' && !tty->lnext) {
			if (L_ECHO(tty) || (L_ICANON(tty) && L_ECHONL(tty)))
				opost('\n', tty);
		} else if (L_ECHO(tty)) {
			/* Don't echo the EOF char in canonical mode.  Sun
			   handles this differently by echoing the char and
			   then backspacing, but that's a hack. */
			if (c != EOF_CHAR(tty) || !L_ICANON(tty) ||
			    tty->lnext) {
				/* Record the column of first canon char. */
				if (tty->canon_head == tty->secondary.head)
					tty->canon_column = tty->column;
				echo_char(c, tty);
			}
		}

		if (I_PARMRK(tty) && c == (unsigned char) '\377' &&
		    (c != EOF_CHAR(tty) || !L_ICANON(tty) || tty->lnext))
			put_tty_queue(c, &tty->secondary);

		if (L_ICANON(tty) && !tty->lnext &&
		    (c == '\n' || c == EOF_CHAR(tty) || c == EOL_CHAR(tty) ||
		     (c == EOL2_CHAR(tty) && L_IEXTEN(tty)))) {
			if (c == EOF_CHAR(tty))
				c = __DISABLED_CHAR;
			set_bit(tty->secondary.head, &tty->secondary_flags);
			put_tty_queue(c, &tty->secondary);
			tty->canon_head = tty->secondary.head;
			tty->canon_data++;
		} else
			put_tty_queue(c, &tty->secondary);
		tty->lnext = 0;
	}
	if (!EMPTY(&tty->write_q))
		TTY_WRITE_FLUSH(tty);
	if (L_ICANON(tty) ? tty->canon_data : !EMPTY(&tty->secondary))
		wake_up_interruptible(&tty->secondary.proc_list);

	if (tty->throttle && (LEFT(&tty->read_q) >= RQ_THRESHOLD_HW)
	    && clear_bit(TTY_RQ_THROTTLED, &tty->flags))
		tty->throttle(tty, TTY_THROTTLE_RQ_AVAIL);
}
static void cidatatty_set_termios(struct tty_struct *tty,
				  struct ktermios *old_termios)
{
	unsigned int cflag;

	F_ENTER();
	cflag = tty->termios.c_cflag;

	/* check that they really want us to change something */
	if (old_termios) {
		if ((cflag == old_termios->c_cflag) &&
		    (RELEVANT_IFLAG(tty->termios.c_iflag) ==
		     RELEVANT_IFLAG(old_termios->c_iflag))) {
			PDEBUG(" - nothing to change...\n");
			return;
		}
	}

	/* get the byte size */
	switch (cflag & CSIZE) {
	case CS5:
		PDEBUG(" - data bits = 5\n");
		break;
	case CS6:
		PDEBUG(" - data bits = 6\n");
		break;
	case CS7:
		PDEBUG(" - data bits = 7\n");
		break;
	default:
	case CS8:
		PDEBUG(" - data bits = 8\n");
		break;
	}

	/* determine the parity */
	if (cflag & PARENB)
		if (cflag & PARODD)
			PDEBUG(" - parity = odd\n");
		else
			PDEBUG(" - parity = even\n");
	else
		PDEBUG(" - parity = none\n");

	/* figure out the stop bits requested */
	if (cflag & CSTOPB)
		PDEBUG(" - stop bits = 2\n");
	else
		PDEBUG(" - stop bits = 1\n");

	/* figure out the hardware flow control settings */
	if (cflag & CRTSCTS)
		PDEBUG(" - RTS/CTS is enabled\n");
	else
		PDEBUG(" - RTS/CTS is disabled\n");

	/* determine software flow control */
	/* if we are implementing XON/XOFF, set the start and
	 * stop character in the device */
	if (I_IXOFF(tty) || I_IXON(tty))
		;/* CHECKPOINT */

	/* get the baud rate wanted */
	PDEBUG(" - baud rate = %d", tty_get_baud_rate(tty));

	F_LEAVE();
}
Example #13
0
static void nullmodem_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
	struct nullmodem_end *end = tty->driver_data;
	unsigned long flags;
	unsigned int cflag;

	dprintf("%s - #%d\n", __FUNCTION__, tty->index);

	cflag = tty->termios.c_cflag;

	/* check that they really want us to change something */
	if (old_termios)
	{
		if (cflag == old_termios->c_cflag
		&& RELEVANT_IFLAG(tty->termios.c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))
		{
			dprintf(" - nothing to change...\n");
			return;
		}
	}
	spin_lock_irqsave(&end->pair->spin, flags);
	handle_termios(tty);
	spin_unlock_irqrestore(&end->pair->spin, flags);

#ifdef SCULL_DEBUG
	speed_t speed = tty_get_baud_rate(tty);
	dprintf(" - baud = %u", speed);
	dprintf(" - ispeed = %u", tty->termios.c_ispeed);
	dprintf(" - ospeed = %u", tty->termios.c_ospeed);

	/* get the byte size */
	switch (cflag & CSIZE)
	{
	case CS5:	dprintf(" - data bits = 5\n");	break;
	case CS6:	dprintf(" - data bits = 6\n");	break;
	case CS7:	dprintf(" - data bits = 7\n");	break;
	default:
	case CS8:	dprintf(" - data bits = 8\n");	break;
	}

	/* determine the parity */
	if (cflag & PARENB)
		if (cflag & PARODD)
			dprintf(" - parity = odd\n");
		else
			dprintf(" - parity = even\n");
	else
		dprintf(" - parity = none\n");

	/* figure out the stop bits requested */
	if (cflag & CSTOPB)
		dprintf(" - stop bits = 2\n");
	else
		dprintf(" - stop bits = 1\n");

	/* figure out the hardware flow control settings */
	if (cflag & CRTSCTS)
		dprintf(" - RTS/CTS is enabled\n");
	else
		dprintf(" - RTS/CTS is disabled\n");

	/* determine software flow control */
	/* if we are implementing XON/XOFF, set the start and
	 * stop character in the device */
	/* if we are implementing INBOUND XON/XOFF */
	if (I_IXOFF(tty))
		dprintf(" - INBOUND XON/XOFF is enabled, "
			"XON = %2x, XOFF = %2x\n", START_CHAR(tty), STOP_CHAR(tty));
	else
		dprintf(" - INBOUND XON/XOFF is disabled\n");

	/* if we are implementing OUTBOUND XON/XOFF */
	if (I_IXON(tty))
		dprintf(" - OUTBOUND XON/XOFF is enabled, "
			"XON = %2x, XOFF = %2x\n", START_CHAR(tty), STOP_CHAR(tty));
	else
		dprintf(" - OUTBOUND XON/XOFF is disabled\n");
#endif
}