Exemplo n.º 1
0
static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
	struct serial_state *info = tty->driver_data;
	unsigned long flags;
	unsigned int cflag = tty->termios.c_cflag;

	change_speed(tty, info, old_termios);

	/* Handle transition to B0 status */
	if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) {
		info->MCR &= ~(SER_DTR|SER_RTS);
		local_irq_save(flags);
		rtsdtr_ctrl(info->MCR);
		local_irq_restore(flags);
	}

	/* Handle transition away from B0 status */
	if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
		info->MCR |= SER_DTR;
		if (!C_CRTSCTS(tty) || !tty_throttled(tty))
			info->MCR |= SER_RTS;
		local_irq_save(flags);
		rtsdtr_ctrl(info->MCR);
		local_irq_restore(flags);
	}

	/* Handle turning off CRTSCTS */
	if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) {
		tty->hw_stopped = 0;
		rs_start(tty);
	}

#if 0
	/*
	 * No need to wake up processes in open wait, since they
	 * sample the CLOCAL flag once, and don't recheck it.
	 * XXX  It's not clear whether the current behavior is correct
	 * or not.  Hence, this may change.....
	 */
	if (!(old_termios->c_cflag & CLOCAL) && C_CLOCAL(tty))
		wake_up_interruptible(&info->open_wait);
#endif
}
Exemplo n.º 2
0
static void mct_u232_unthrottle(struct tty_struct *tty)
{
	struct usb_serial_port *port = tty->driver_data;
	struct mct_u232_private *priv = usb_get_serial_port_data(port);
	unsigned int control_state;

	spin_lock_irq(&priv->lock);
	if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) {
		priv->rx_flags &= ~THROTTLED;
		priv->control_state |= TIOCM_RTS;
		control_state = priv->control_state;
		spin_unlock_irq(&priv->lock);
		mct_u232_set_modem_ctrl(port, control_state);
	} else {
		spin_unlock_irq(&priv->lock);
	}
}
Exemplo n.º 3
0
static void mct_u232_throttle(struct tty_struct *tty)
{
	struct usb_serial_port *port = tty->driver_data;
	struct mct_u232_private *priv = usb_get_serial_port_data(port);
	unsigned int control_state;

	dbg("%s - port %d", __func__, port->number);

	spin_lock_irq(&priv->lock);
	priv->rx_flags |= THROTTLED;
	if (C_CRTSCTS(tty)) {
		priv->control_state &= ~TIOCM_RTS;
		control_state = priv->control_state;
		spin_unlock_irq(&priv->lock);
		(void) mct_u232_set_modem_ctrl(port->serial, control_state);
	} else {
		spin_unlock_irq(&priv->lock);
	}
}
Exemplo n.º 4
0
/*
 * ------------------------------------------------------------
 * rs_throttle()
 * 
 * This routine is called by the upper-layer tty layer to signal that
 * incoming characters should be throttled.
 * ------------------------------------------------------------
 */
static void rs_throttle(struct tty_struct * tty)
{
	struct serial_state *info = tty->driver_data;
	unsigned long flags;
#ifdef SERIAL_DEBUG_THROTTLE
	printk("throttle %s ....\n", tty_name(tty));
#endif

	if (serial_paranoia_check(info, tty->name, "rs_throttle"))
		return;

	if (I_IXOFF(tty))
		rs_send_xchar(tty, STOP_CHAR(tty));

	if (C_CRTSCTS(tty))
		info->MCR &= ~SER_RTS;

	local_irq_save(flags);
	rtsdtr_ctrl(info->MCR);
	local_irq_restore(flags);
}
Exemplo n.º 5
0
static void mct_u232_unthrottle (struct usb_serial_port *port)
{
	struct mct_u232_private *priv = usb_get_serial_port_data(port);
	unsigned long flags;
	unsigned int control_state;
	struct tty_struct *tty;

	dbg("%s - port %d", __FUNCTION__, port->number);

	tty = port->tty;
	spin_lock_irqsave(&priv->lock, flags);
	if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) {
	  priv->rx_flags &= ~THROTTLED;
	  priv->control_state |= TIOCM_RTS;
	  control_state = priv->control_state;
	  spin_unlock_irqrestore(&priv->lock, flags);
	  (void) mct_u232_set_modem_ctrl(port->serial, control_state);
	} else {
	  spin_unlock_irqrestore(&priv->lock, flags);
	}
}
Exemplo n.º 6
0
static int mct_u232_set_baud_rate(struct tty_struct *tty,
	struct usb_serial *serial, struct usb_serial_port *port, speed_t value)
{
	unsigned int divisor;
	int rc;
	unsigned char *buf;
	unsigned char cts_enable_byte = 0;
	speed_t speed;

	buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL);
	if (buf == NULL)
		return -ENOMEM;

	divisor = mct_u232_calculate_baud_rate(serial, value, &speed);
	put_unaligned_le32(cpu_to_le32(divisor), buf);
	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
				MCT_U232_SET_BAUD_RATE_REQUEST,
				MCT_U232_SET_REQUEST_TYPE,
				0, 0, buf, MCT_U232_SET_BAUD_RATE_SIZE,
				WDR_TIMEOUT);
	if (rc < 0)	/*FIXME: What value speed results */
		dev_err(&port->dev, "Set BAUD RATE %d failed (error = %d)\n",
			value, rc);
	else
		tty_encode_baud_rate(tty, speed, speed);
	dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor);

	/* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which
	   always sends two extra USB 'device request' messages after the
	   'baud rate change' message.  The actual functionality of the
	   request codes in these messages is not fully understood but these
	   particular codes are never seen in any operation besides a baud
	   rate change.  Both of these messages send a single byte of data.
	   In the first message, the value of this byte is always zero.

	   The second message has been determined experimentally to control
	   whether data will be transmitted to a device which is not asserting
	   the 'CTS' signal.  If the second message's data byte is zero, data
	   will be transmitted even if 'CTS' is not asserted (i.e. no hardware
	   flow control).  if the second message's data byte is nonzero (a
	   value of 1 is used by this driver), data will not be transmitted to
	   a device which is not asserting 'CTS'.
	*/

	buf[0] = 0;
	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
				MCT_U232_SET_UNKNOWN1_REQUEST,
				MCT_U232_SET_REQUEST_TYPE,
				0, 0, buf, MCT_U232_SET_UNKNOWN1_SIZE,
				WDR_TIMEOUT);
	if (rc < 0)
		dev_err(&port->dev, "Sending USB device request code %d "
			"failed (error = %d)\n", MCT_U232_SET_UNKNOWN1_REQUEST,
			rc);

	if (port && C_CRTSCTS(tty))
	   cts_enable_byte = 1;

	dbg("set_baud_rate: send second control message, data = %02X",
							cts_enable_byte);
	buf[0] = cts_enable_byte;
	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
			MCT_U232_SET_CTS_REQUEST,
			MCT_U232_SET_REQUEST_TYPE,
			0, 0, buf, MCT_U232_SET_CTS_SIZE,
			WDR_TIMEOUT);
	if (rc < 0)
		dev_err(&port->dev, "Sending USB device request code %d "
			"failed (error = %d)\n", MCT_U232_SET_CTS_REQUEST, rc);

	kfree(buf);
	return rc;
} /* mct_u232_set_baud_rate */
Exemplo n.º 7
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);
}
Exemplo n.º 8
0
/* 
** RIOParam is used to open or configure a port. You pass it a PortP,
** which will have a tty struct attached to it. You also pass a command,
** either OPEN or CONFIG. The port's setup is taken from the t_ fields
** of the tty struct inside the PortP, and the port is either opened
** or re-configured. You must also tell RIOParam if the device is a modem
** device or not (i.e. top bit of minor number set or clear - take special
** care when deciding on this!).
** RIOParam neither flushes nor waits for drain, and is NOT preemptive.
**
** RIOParam assumes it will be called at splrio(), and also assumes
** that CookMode is set correctly in the port structure.
**
** NB. for MPX
**    tty lock must NOT have been previously acquired.
*/
int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag)
{
    struct tty_struct *TtyP;
    int retval;
    struct phb_param __iomem *phb_param_ptr;
    struct PKT __iomem *PacketP;
    int res;
    u8 Cor1 = 0, Cor2 = 0, Cor4 = 0, Cor5 = 0;
    u8 TxXon = 0, TxXoff = 0, RxXon = 0, RxXoff = 0;
    u8 LNext = 0, TxBaud = 0, RxBaud = 0;
    int retries = 0xff;
    unsigned long flags;

    func_enter();

    TtyP = PortP->gs.tty;

    rio_dprintk(RIO_DEBUG_PARAM, "RIOParam: Port:%d cmd:%d Modem:%d SleepFlag:%d Mapped: %d, tty=%p\n", PortP->PortNum, cmd, Modem, SleepFlag, PortP->Mapped, TtyP);

    if (!TtyP) {
        rio_dprintk(RIO_DEBUG_PARAM, "Can't call rioparam with null tty.\n");

        func_exit();

        return RIO_FAIL;
    }
    rio_spin_lock_irqsave(&PortP->portSem, flags);

    if (cmd == RIOC_OPEN) {
        /*
         ** If the port is set to store or lock the parameters, and it is
         ** paramed with OPEN, we want to restore the saved port termio, but
         ** only if StoredTermio has been saved, i.e. NOT 1st open after reboot.
         */
    }

    /*
     ** wait for space
     */
    while (!(res = can_add_transmit(&PacketP, PortP)) || (PortP->InUse != NOT_INUSE)) {
        if (retries-- <= 0) {
            break;
        }
        if (PortP->InUse != NOT_INUSE) {
            rio_dprintk(RIO_DEBUG_PARAM, "Port IN_USE for pre-emptive command\n");
        }

        if (!res) {
            rio_dprintk(RIO_DEBUG_PARAM, "Port has no space on transmit queue\n");
        }

        if (SleepFlag != OK_TO_SLEEP) {
            rio_spin_unlock_irqrestore(&PortP->portSem, flags);
            func_exit();

            return RIO_FAIL;
        }

        rio_dprintk(RIO_DEBUG_PARAM, "wait for can_add_transmit\n");
        rio_spin_unlock_irqrestore(&PortP->portSem, flags);
        retval = RIODelay(PortP, HUNDRED_MS);
        rio_spin_lock_irqsave(&PortP->portSem, flags);
        if (retval == RIO_FAIL) {
            rio_dprintk(RIO_DEBUG_PARAM, "wait for can_add_transmit broken by signal\n");
            rio_spin_unlock_irqrestore(&PortP->portSem, flags);
            func_exit();
            return -EINTR;
        }
        if (PortP->State & RIO_DELETED) {
            rio_spin_unlock_irqrestore(&PortP->portSem, flags);
            func_exit();
            return 0;
        }
    }

    if (!res) {
        rio_spin_unlock_irqrestore(&PortP->portSem, flags);
        func_exit();

        return RIO_FAIL;
    }

    rio_dprintk(RIO_DEBUG_PARAM, "can_add_transmit() returns %x\n", res);
    rio_dprintk(RIO_DEBUG_PARAM, "Packet is %p\n", PacketP);

    phb_param_ptr = (struct phb_param __iomem *) PacketP->data;


    switch (TtyP->termios->c_cflag & CSIZE) {
    case CS5:
        {
            rio_dprintk(RIO_DEBUG_PARAM, "5 bit data\n");
            Cor1 |= RIOC_COR1_5BITS;
            break;
        }
    case CS6:
        {
            rio_dprintk(RIO_DEBUG_PARAM, "6 bit data\n");
            Cor1 |= RIOC_COR1_6BITS;
            break;
        }
    case CS7:
        {
            rio_dprintk(RIO_DEBUG_PARAM, "7 bit data\n");
            Cor1 |= RIOC_COR1_7BITS;
            break;
        }
    case CS8:
        {
            rio_dprintk(RIO_DEBUG_PARAM, "8 bit data\n");
            Cor1 |= RIOC_COR1_8BITS;
            break;
        }
    }

    if (TtyP->termios->c_cflag & CSTOPB) {
        rio_dprintk(RIO_DEBUG_PARAM, "2 stop bits\n");
        Cor1 |= RIOC_COR1_2STOP;
    } else {
        rio_dprintk(RIO_DEBUG_PARAM, "1 stop bit\n");
        Cor1 |= RIOC_COR1_1STOP;
    }

    if (TtyP->termios->c_cflag & PARENB) {
        rio_dprintk(RIO_DEBUG_PARAM, "Enable parity\n");
        Cor1 |= RIOC_COR1_NORMAL;
    } else {
        rio_dprintk(RIO_DEBUG_PARAM, "Disable parity\n");
        Cor1 |= RIOC_COR1_NOP;
    }
    if (TtyP->termios->c_cflag & PARODD) {
        rio_dprintk(RIO_DEBUG_PARAM, "Odd parity\n");
        Cor1 |= RIOC_COR1_ODD;
    } else {
        rio_dprintk(RIO_DEBUG_PARAM, "Even parity\n");
        Cor1 |= RIOC_COR1_EVEN;
    }

    /*
     ** COR 2
     */
    if (TtyP->termios->c_iflag & IXON) {
        rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop output control\n");
        Cor2 |= RIOC_COR2_IXON;
    } else {
        if (PortP->Config & RIO_IXON) {
            rio_dprintk(RIO_DEBUG_PARAM, "Force enable start/stop output control\n");
            Cor2 |= RIOC_COR2_IXON;
        } else
            rio_dprintk(RIO_DEBUG_PARAM, "IXON has been disabled.\n");
    }

    if (TtyP->termios->c_iflag & IXANY) {
        if (PortP->Config & RIO_IXANY) {
            rio_dprintk(RIO_DEBUG_PARAM, "Enable any key to restart output\n");
            Cor2 |= RIOC_COR2_IXANY;
        } else
            rio_dprintk(RIO_DEBUG_PARAM, "IXANY has been disabled due to sanity reasons.\n");
    }

    if (TtyP->termios->c_iflag & IXOFF) {
        rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop input control 2\n");
        Cor2 |= RIOC_COR2_IXOFF;
    }

    if (TtyP->termios->c_cflag & HUPCL) {
        rio_dprintk(RIO_DEBUG_PARAM, "Hangup on last close\n");
        Cor2 |= RIOC_COR2_HUPCL;
    }

    if (C_CRTSCTS(TtyP)) {
        rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control enabled\n");
        Cor2 |= RIOC_COR2_CTSFLOW;
        Cor2 |= RIOC_COR2_RTSFLOW;
    } else {
        rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control disabled\n");
        Cor2 &= ~RIOC_COR2_CTSFLOW;
        Cor2 &= ~RIOC_COR2_RTSFLOW;
    }


    if (TtyP->termios->c_cflag & CLOCAL) {
        rio_dprintk(RIO_DEBUG_PARAM, "Local line\n");
    } else {
        rio_dprintk(RIO_DEBUG_PARAM, "Possible Modem line\n");
    }

    /*
     ** COR 4 (there is no COR 3)
     */
    if (TtyP->termios->c_iflag & IGNBRK) {
        rio_dprintk(RIO_DEBUG_PARAM, "Ignore break condition\n");
        Cor4 |= RIOC_COR4_IGNBRK;
    }
    if (!(TtyP->termios->c_iflag & BRKINT)) {
        rio_dprintk(RIO_DEBUG_PARAM, "Break generates NULL condition\n");
        Cor4 |= RIOC_COR4_NBRKINT;
    } else {
        rio_dprintk(RIO_DEBUG_PARAM, "Interrupt on    break condition\n");
    }

    if (TtyP->termios->c_iflag & INLCR) {
        rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage return on input\n");
        Cor4 |= RIOC_COR4_INLCR;
    }

    if (TtyP->termios->c_iflag & IGNCR) {
        rio_dprintk(RIO_DEBUG_PARAM, "Ignore carriage return on input\n");
        Cor4 |= RIOC_COR4_IGNCR;
    }

    if (TtyP->termios->c_iflag & ICRNL) {
        rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on input\n");
        Cor4 |= RIOC_COR4_ICRNL;
    }
    if (TtyP->termios->c_iflag & IGNPAR) {
        rio_dprintk(RIO_DEBUG_PARAM, "Ignore characters with parity errors\n");
        Cor4 |= RIOC_COR4_IGNPAR;
    }
    if (TtyP->termios->c_iflag & PARMRK) {
        rio_dprintk(RIO_DEBUG_PARAM, "Mark parity errors\n");
        Cor4 |= RIOC_COR4_PARMRK;
    }

    /*
     ** Set the RAISEMOD flag to ensure that the modem lines are raised
     ** on reception of a config packet.
     ** The download code handles the zero baud condition.
     */
    Cor4 |= RIOC_COR4_RAISEMOD;

    /*
     ** COR 5
     */

    Cor5 = RIOC_COR5_CMOE;

    /*
     ** Set to monitor tbusy/tstop (or not).
     */

    if (PortP->MonitorTstate)
        Cor5 |= RIOC_COR5_TSTATE_ON;
    else
        Cor5 |= RIOC_COR5_TSTATE_OFF;

    /*
     ** Could set LNE here if you wanted LNext processing. SVR4 will use it.
     */
    if (TtyP->termios->c_iflag & ISTRIP) {
        rio_dprintk(RIO_DEBUG_PARAM, "Strip input characters\n");
        if (!(PortP->State & RIO_TRIAD_MODE)) {
            Cor5 |= RIOC_COR5_ISTRIP;
        }
    }

    if (TtyP->termios->c_oflag & ONLCR) {
        rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage-return, newline on output\n");
        if (PortP->CookMode == COOK_MEDIUM)
            Cor5 |= RIOC_COR5_ONLCR;
    }
    if (TtyP->termios->c_oflag & OCRNL) {
        rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on output\n");
        if (PortP->CookMode == COOK_MEDIUM)
            Cor5 |= RIOC_COR5_OCRNL;
    }
    if ((TtyP->termios->c_oflag & TABDLY) == TAB3) {
        rio_dprintk(RIO_DEBUG_PARAM, "Tab delay 3 set\n");
        if (PortP->CookMode == COOK_MEDIUM)
            Cor5 |= RIOC_COR5_TAB3;
    }

    /*
     ** Flow control bytes.
     */
    TxXon = TtyP->termios->c_cc[VSTART];
    TxXoff = TtyP->termios->c_cc[VSTOP];
    RxXon = TtyP->termios->c_cc[VSTART];
    RxXoff = TtyP->termios->c_cc[VSTOP];
    /*
     ** LNEXT byte
     */
    LNext = 0;

    /*
     ** Baud rate bytes
     */
    rio_dprintk(RIO_DEBUG_PARAM, "Mapping of rx/tx baud %x (%x)\n", TtyP->termios->c_cflag, CBAUD);

    switch (TtyP->termios->c_cflag & CBAUD) {
#define e(b) case B ## b : RxBaud = TxBaud = RIO_B ## b ;break
        e(50);
        e(75);
        e(110);
        e(134);
        e(150);
        e(200);
        e(300);
        e(600);
        e(1200);
        e(1800);
        e(2400);
        e(4800);
        e(9600);
        e(19200);
        e(38400);
        e(57600);
        e(115200);    /* e(230400);e(460800); e(921600);  */
    }

    rio_dprintk(RIO_DEBUG_PARAM, "tx baud 0x%x, rx baud 0x%x\n", TxBaud, RxBaud);


    /*
     ** Leftovers
     */
    if (TtyP->termios->c_cflag & CREAD)
        rio_dprintk(RIO_DEBUG_PARAM, "Enable receiver\n");
#ifdef RCV1EN
    if (TtyP->termios->c_cflag & RCV1EN)
        rio_dprintk(RIO_DEBUG_PARAM, "RCV1EN (?)\n");
#endif
#ifdef XMT1EN
    if (TtyP->termios->c_cflag & XMT1EN)
        rio_dprintk(RIO_DEBUG_PARAM, "XMT1EN (?)\n");
#endif
    if (TtyP->termios->c_lflag & ISIG)
        rio_dprintk(RIO_DEBUG_PARAM, "Input character signal generating enabled\n");
    if (TtyP->termios->c_lflag & ICANON)
        rio_dprintk(RIO_DEBUG_PARAM, "Canonical input: erase and kill enabled\n");
    if (TtyP->termios->c_lflag & XCASE)
        rio_dprintk(RIO_DEBUG_PARAM, "Canonical upper/lower presentation\n");
    if (TtyP->termios->c_lflag & ECHO)
        rio_dprintk(RIO_DEBUG_PARAM, "Enable input echo\n");
    if (TtyP->termios->c_lflag & ECHOE)
        rio_dprintk(RIO_DEBUG_PARAM, "Enable echo erase\n");
    if (TtyP->termios->c_lflag & ECHOK)
        rio_dprintk(RIO_DEBUG_PARAM, "Enable echo kill\n");
    if (TtyP->termios->c_lflag & ECHONL)
        rio_dprintk(RIO_DEBUG_PARAM, "Enable echo newline\n");
    if (TtyP->termios->c_lflag & NOFLSH)
        rio_dprintk(RIO_DEBUG_PARAM, "Disable flush after interrupt or quit\n");
#ifdef TOSTOP
    if (TtyP->termios->c_lflag & TOSTOP)
        rio_dprintk(RIO_DEBUG_PARAM, "Send SIGTTOU for background output\n");
#endif
#ifdef XCLUDE
    if (TtyP->termios->c_lflag & XCLUDE)
        rio_dprintk(RIO_DEBUG_PARAM, "Exclusive use of this line\n");
#endif
    if (TtyP->termios->c_iflag & IUCLC)
        rio_dprintk(RIO_DEBUG_PARAM, "Map uppercase to lowercase on input\n");
    if (TtyP->termios->c_oflag & OPOST)
        rio_dprintk(RIO_DEBUG_PARAM, "Enable output post-processing\n");
    if (TtyP->termios->c_oflag & OLCUC)
        rio_dprintk(RIO_DEBUG_PARAM, "Map lowercase to uppercase on output\n");
    if (TtyP->termios->c_oflag & ONOCR)
        rio_dprintk(RIO_DEBUG_PARAM, "No carriage return output at column 0\n");
    if (TtyP->termios->c_oflag & ONLRET)
        rio_dprintk(RIO_DEBUG_PARAM, "Newline performs carriage return function\n");
    if (TtyP->termios->c_oflag & OFILL)
        rio_dprintk(RIO_DEBUG_PARAM, "Use fill characters for delay\n");
    if (TtyP->termios->c_oflag & OFDEL)
        rio_dprintk(RIO_DEBUG_PARAM, "Fill character is DEL\n");
    if (TtyP->termios->c_oflag & NLDLY)
        rio_dprintk(RIO_DEBUG_PARAM, "Newline delay set\n");
    if (TtyP->termios->c_oflag & CRDLY)
        rio_dprintk(RIO_DEBUG_PARAM, "Carriage return delay set\n");
    if (TtyP->termios->c_oflag & TABDLY)
        rio_dprintk(RIO_DEBUG_PARAM, "Tab delay set\n");
    /*
     ** These things are kind of useful in a later life!
     */
    PortP->Cor2Copy = Cor2;

    if (PortP->State & RIO_DELETED) {
        rio_spin_unlock_irqrestore(&PortP->portSem, flags);
        func_exit();

        return RIO_FAIL;
    }

    /*
     ** Actually write the info into the packet to be sent
     */
    writeb(cmd, &phb_param_ptr->Cmd);
    writeb(Cor1, &phb_param_ptr->Cor1);
    writeb(Cor2, &phb_param_ptr->Cor2);
    writeb(Cor4, &phb_param_ptr->Cor4);
    writeb(Cor5, &phb_param_ptr->Cor5);
    writeb(TxXon, &phb_param_ptr->TxXon);
    writeb(RxXon, &phb_param_ptr->RxXon);
    writeb(TxXoff, &phb_param_ptr->TxXoff);
    writeb(RxXoff, &phb_param_ptr->RxXoff);
    writeb(LNext, &phb_param_ptr->LNext);
    writeb(TxBaud, &phb_param_ptr->TxBaud);
    writeb(RxBaud, &phb_param_ptr->RxBaud);

    /*
     ** Set the length/command field
     */
    writeb(12 | PKT_CMD_BIT, &PacketP->len);

    /*
     ** The packet is formed - now, whack it off
     ** to its final destination:
     */
    add_transmit(PortP);
    /*
     ** Count characters transmitted for port statistics reporting
     */
    if (PortP->statsGather)
        PortP->txchars += 12;

    rio_spin_unlock_irqrestore(&PortP->portSem, flags);

    rio_dprintk(RIO_DEBUG_PARAM, "add_transmit returned.\n");
    /*
     ** job done.
     */
    func_exit();

    return 0;
}
Exemplo n.º 9
0
static int mct_u232_set_baud_rate(struct usb_serial *serial, struct usb_serial_port *port,
				  speed_t value)
{
	__le32 divisor;
        int rc;
        unsigned char zero_byte = 0;
        unsigned char cts_enable_byte = 0;

	divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value));

        rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
                             MCT_U232_SET_BAUD_RATE_REQUEST,
			     MCT_U232_SET_REQUEST_TYPE,
                             0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE,
			     WDR_TIMEOUT);
	if (rc < 0)
		err("Set BAUD RATE %d failed (error = %d)", value, rc);
	dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor);

	/* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which
	   always sends two extra USB 'device request' messages after the
	   'baud rate change' message.  The actual functionality of the
	   request codes in these messages is not fully understood but these
	   particular codes are never seen in any operation besides a baud
	   rate change.  Both of these messages send a single byte of data.
	   In the first message, the value of this byte is always zero.

	   The second message has been determined experimentally to control
	   whether data will be transmitted to a device which is not asserting
	   the 'CTS' signal.  If the second message's data byte is zero, data
	   will be transmitted even if 'CTS' is not asserted (i.e. no hardware
	   flow control).  if the second message's data byte is nonzero (a value
	   of 1 is used by this driver), data will not be transmitted to a device
	   which is not asserting 'CTS'.
	*/

	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
			     MCT_U232_SET_UNKNOWN1_REQUEST, 
			     MCT_U232_SET_REQUEST_TYPE,
			     0, 0, &zero_byte, MCT_U232_SET_UNKNOWN1_SIZE, 
			     WDR_TIMEOUT);
	if (rc < 0)
		err("Sending USB device request code %d failed (error = %d)", 
		    MCT_U232_SET_UNKNOWN1_REQUEST, rc);

	if (port && C_CRTSCTS(port->tty)) {
	   cts_enable_byte = 1;
	}

        dbg("set_baud_rate: send second control message, data = %02X", cts_enable_byte);
	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
			     MCT_U232_SET_CTS_REQUEST,
			     MCT_U232_SET_REQUEST_TYPE,
			     0, 0, &cts_enable_byte, MCT_U232_SET_CTS_SIZE,
			     WDR_TIMEOUT);
	if (rc < 0)
	  err("Sending USB device request code %d failed (error = %d)",
	      MCT_U232_SET_CTS_REQUEST, rc);

        return rc;
} /* mct_u232_set_baud_rate */
Exemplo n.º 10
0
static void pl2303_set_termios(struct tty_struct *tty,
		struct usb_serial_port *port, struct ktermios *old_termios)
{
	struct usb_serial *serial = port->serial;
	struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
	struct pl2303_private *priv = usb_get_serial_port_data(port);
	unsigned long flags;
	unsigned char *buf;
	int i;
	u8 control;

	if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios))
		return;

	buf = kzalloc(7, GFP_KERNEL);
	if (!buf) {
		dev_err(&port->dev, "%s - out of memory.\n", __func__);
		/* Report back no change occurred */
		if (old_termios)
			tty->termios = *old_termios;
		return;
	}

	i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
			    GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
			    0, 0, buf, 7, 100);
	dev_dbg(&port->dev, "0xa1:0x21:0:0  %d - %7ph\n", i, buf);

	switch (C_CSIZE(tty)) {
	case CS5:
		buf[6] = 5;
		break;
	case CS6:
		buf[6] = 6;
		break;
	case CS7:
		buf[6] = 7;
		break;
	default:
	case CS8:
		buf[6] = 8;
	}
	dev_dbg(&port->dev, "data bits = %d\n", buf[6]);

	/* For reference buf[0]:buf[3] baud rate value */
	pl2303_encode_baudrate(tty, port, &buf[0]);

	/* For reference buf[4]=0 is 1 stop bits */
	/* For reference buf[4]=1 is 1.5 stop bits */
	/* For reference buf[4]=2 is 2 stop bits */
	if (C_CSTOPB(tty)) {
		/*
		 * NOTE: Comply with "real" UARTs / RS232:
		 *       use 1.5 instead of 2 stop bits with 5 data bits
		 */
		if (C_CSIZE(tty) == CS5) {
			buf[4] = 1;
			dev_dbg(&port->dev, "stop bits = 1.5\n");
		} else {
			buf[4] = 2;
			dev_dbg(&port->dev, "stop bits = 2\n");
		}
	} else {
		buf[4] = 0;
		dev_dbg(&port->dev, "stop bits = 1\n");
	}

	if (C_PARENB(tty)) {
		/* For reference buf[5]=0 is none parity */
		/* For reference buf[5]=1 is odd parity */
		/* For reference buf[5]=2 is even parity */
		/* For reference buf[5]=3 is mark parity */
		/* For reference buf[5]=4 is space parity */
		if (C_PARODD(tty)) {
			if (tty->termios.c_cflag & CMSPAR) {
				buf[5] = 3;
				dev_dbg(&port->dev, "parity = mark\n");
			} else {
				buf[5] = 1;
				dev_dbg(&port->dev, "parity = odd\n");
			}
		} else {
			if (tty->termios.c_cflag & CMSPAR) {
				buf[5] = 4;
				dev_dbg(&port->dev, "parity = space\n");
			} else {
				buf[5] = 2;
				dev_dbg(&port->dev, "parity = even\n");
			}
		}
	} else {
		buf[5] = 0;
		dev_dbg(&port->dev, "parity = none\n");
	}

	/*
	 * Some PL2303 are known to lose bytes if you change serial settings
	 * even to the same values as before. Thus we actually need to filter
	 * in this specific case.
	 *
	 * Note that the tty_termios_hw_change check above is not sufficient
	 * as a previously requested baud rate may differ from the one
	 * actually used (and stored in old_termios).
	 *
	 * NOTE: No additional locking needed for line_settings as it is
	 *       only used in set_termios, which is serialised against itself.
	 */
	if (!old_termios || memcmp(buf, priv->line_settings, 7)) {
		i = usb_control_msg(serial->dev,
				    usb_sndctrlpipe(serial->dev, 0),
				    SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE,
				    0, 0, buf, 7, 100);

		dev_dbg(&port->dev, "0x21:0x20:0:0  %d\n", i);

		if (i == 7)
			memcpy(priv->line_settings, buf, 7);
	}

	/* change control lines if we are switching to or from B0 */
	spin_lock_irqsave(&priv->lock, flags);
	control = priv->line_control;
	if (C_BAUD(tty) == B0)
		priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
	else if (old_termios && (old_termios->c_cflag & CBAUD) == B0)
		priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
	if (control != priv->line_control) {
		control = priv->line_control;
		spin_unlock_irqrestore(&priv->lock, flags);
		pl2303_set_control_lines(port, control);
	} else {
		spin_unlock_irqrestore(&priv->lock, flags);
	}

	memset(buf, 0, 7);
	i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
			    GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
			    0, 0, buf, 7, 100);
	dev_dbg(&port->dev, "0xa1:0x21:0:0  %d - %7ph\n", i, buf);

	if (C_CRTSCTS(tty)) {
		if (spriv->type == HX)
			pl2303_vendor_write(0x0, 0x61, serial);
		else
			pl2303_vendor_write(0x0, 0x41, serial);
	} else {
		pl2303_vendor_write(0x0, 0x0, serial);
	}

	kfree(buf);
}