예제 #1
0
파일: ch341.c 프로젝트: aywq2008/omniplay
/* open this device, set default parameters */
static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
{
	struct usb_serial *serial = port->serial;
	struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]);
	int r;

	priv->baud_rate = DEFAULT_BAUD_RATE;

	r = ch341_configure(serial->dev, priv);
	if (r)
		goto out;

	r = ch341_set_handshake(serial->dev, priv->line_control);
	if (r)
		goto out;

	r = ch341_set_baudrate(serial->dev, priv);
	if (r)
		goto out;

	dbg("%s - submitting interrupt urb", __func__);
	r = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
	if (r) {
		dev_err(&port->dev, "%s - failed submitting interrupt urb,"
			" error %d\n", __func__, r);
		ch341_close(port);
		goto out;
	}

	r = usb_serial_generic_open(tty, port);

out:	return r;
}
예제 #2
0
파일: ch341.c 프로젝트: aywq2008/omniplay
/* Old_termios contains the original termios settings and
 * tty->termios contains the new setting to be used.
 */
static void ch341_set_termios(struct tty_struct *tty,
		struct usb_serial_port *port, struct ktermios *old_termios)
{
	struct ch341_private *priv = usb_get_serial_port_data(port);
	unsigned baud_rate;
	unsigned long flags;

	baud_rate = tty_get_baud_rate(tty);

	priv->baud_rate = baud_rate;

	if (baud_rate) {
		spin_lock_irqsave(&priv->lock, flags);
		priv->line_control |= (CH341_BIT_DTR | CH341_BIT_RTS);
		spin_unlock_irqrestore(&priv->lock, flags);
		ch341_set_baudrate(port->serial->dev, priv);
	} else {
		spin_lock_irqsave(&priv->lock, flags);
		priv->line_control &= ~(CH341_BIT_DTR | CH341_BIT_RTS);
		spin_unlock_irqrestore(&priv->lock, flags);
	}

	ch341_set_handshake(port->serial->dev, priv->line_control);

	/* Unimplemented:
	 * (cflag & CSIZE) : data bits [5, 8]
	 * (cflag & PARENB) : parity {NONE, EVEN, ODD}
	 * (cflag & CSTOPB) : stop bits [1, 2]
	 */
}
예제 #3
0
파일: ch341.c 프로젝트: maraz/linux-2.6
/* open this device, set default parameters */
static int ch341_open(struct usb_serial_port *port, struct file *filp)
{
	struct usb_serial *serial = port->serial;
	struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]);
	int r;

	dbg("ch341_open()");

	priv->baud_rate = DEFAULT_BAUD_RATE;
	priv->dtr = 1;
	priv->rts = 1;

	r = ch341_configure(serial->dev, priv);
	if (r)
		goto out;

	r = ch341_set_handshake(serial->dev, priv);
	if (r)
		goto out;

	r = ch341_set_baudrate(serial->dev, priv);
	if (r)
		goto out;

	r = usb_serial_generic_open(port, filp);

out:	return r;
}
예제 #4
0
static void ch341_close(struct tty_struct *tty, struct usb_serial_port *port,
				struct file *filp)
{
	struct ch341_private *priv = usb_get_serial_port_data(port);
	unsigned long flags;
	unsigned int c_cflag;

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

	/* shutdown our urbs */
	dbg("%s - shutting down urbs", __func__);
	usb_kill_urb(port->write_urb);
	usb_kill_urb(port->read_urb);
	usb_kill_urb(port->interrupt_in_urb);

	if (tty) {
		c_cflag = tty->termios->c_cflag;
		if (c_cflag & HUPCL) {
			/* drop DTR and RTS */
			spin_lock_irqsave(&priv->lock, flags);
			priv->line_control = 0;
			spin_unlock_irqrestore(&priv->lock, flags);
			ch341_set_handshake(port->serial->dev, 0);
		}
	}
	wake_up_interruptible(&priv->delta_msr_wait);
}
예제 #5
0
static int ch341_configure(struct usb_device *dev, struct ch341_private *priv)
{
    char *buffer;
    int r;
    const unsigned size = 8;

    dbg("ch341_configure()");

    buffer = kmalloc(size, GFP_KERNEL);
    if (!buffer)
        return -ENOMEM;

    /* expect two bytes 0x27 0x00 */
    r = ch341_control_in(dev, 0x5f, 0, 0, buffer, size);
    if (r < 0)
        goto out;

    r = ch341_control_out(dev, 0xa1, 0, 0);
    if (r < 0)
        goto out;

    r = ch341_set_baudrate(dev, priv);
    if (r < 0)
        goto out;

    /* expect two bytes 0x56 0x00 */
    r = ch341_control_in(dev, 0x95, 0x2518, 0, buffer, size);
    if (r < 0)
        goto out;

    r = ch341_control_out(dev, 0x9a, 0x2518, 0x0050);
    if (r < 0)
        goto out;

    /* expect 0xff 0xee */
    r = ch341_get_status(dev, priv);
    if (r < 0)
        goto out;

    r = ch341_control_out(dev, 0xa1, 0x501f, 0xd90a);
    if (r < 0)
        goto out;

    r = ch341_set_baudrate(dev, priv);
    if (r < 0)
        goto out;

    r = ch341_set_handshake(dev, priv->line_control);
    if (r < 0)
        goto out;

    /* expect 0x9f 0xee */
    r = ch341_get_status(dev, priv);

out:
    kfree(buffer);
    return r;
}
예제 #6
0
파일: ch341.c 프로젝트: 19Dan01/linux
static void ch341_dtr_rts(struct usb_serial_port *port, int on)
{
	struct ch341_private *priv = usb_get_serial_port_data(port);
	unsigned long flags;

	/* drop DTR and RTS */
	spin_lock_irqsave(&priv->lock, flags);
	if (on)
		priv->line_control |= CH341_BIT_RTS | CH341_BIT_DTR;
	else
		priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR);
	spin_unlock_irqrestore(&priv->lock, flags);
	ch341_set_handshake(port->serial->dev, priv->line_control);
}
예제 #7
0
파일: ch341.c 프로젝트: matsufan/linux
static void ch341_dtr_rts(struct usb_serial_port *port, int on)
{
	struct ch341_private *priv = usb_get_serial_port_data(port);
	unsigned long flags;

	dbg("%s - port %d", __func__, port->number);
	/* drop DTR and RTS */
	spin_lock_irqsave(&priv->lock, flags);
	if (on)
		priv->line_control |= CH341_BIT_RTS | CH341_BIT_DTR;
	else
		priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR);
	spin_unlock_irqrestore(&priv->lock, flags);
	ch341_set_handshake(port->serial->dev, priv->line_control);
	wake_up_interruptible(&priv->delta_msr_wait);
}
예제 #8
0
파일: ch341.c 프로젝트: aywq2008/omniplay
static int ch341_tiocmset(struct tty_struct *tty,
			  unsigned int set, unsigned int clear)
{
	struct usb_serial_port *port = tty->driver_data;
	struct ch341_private *priv = usb_get_serial_port_data(port);
	unsigned long flags;
	u8 control;

	spin_lock_irqsave(&priv->lock, flags);
	if (set & TIOCM_RTS)
		priv->line_control |= CH341_BIT_RTS;
	if (set & TIOCM_DTR)
		priv->line_control |= CH341_BIT_DTR;
	if (clear & TIOCM_RTS)
		priv->line_control &= ~CH341_BIT_RTS;
	if (clear & TIOCM_DTR)
		priv->line_control &= ~CH341_BIT_DTR;
	control = priv->line_control;
	spin_unlock_irqrestore(&priv->lock, flags);

	return ch341_set_handshake(port->serial->dev, control);
}