/* 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; }
/* 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] */ }
/* 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; }
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); }
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; }
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); }
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); }
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); }