/* open the serial port. do some usb system call. set termios and get the line * status of the device. then submit the read urb */ static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp) { struct ktermios tmp_termios; struct usb_serial *serial = port->serial; struct spcp8x5_private *priv = usb_get_serial_port_data(port); int ret; unsigned long flags; u8 status = 0x30; /* status 0x30 means DSR and CTS = 1 other CDC RI and delta = 0 */ dbg("%s - port %d", __func__, port->number); usb_clear_halt(serial->dev, port->write_urb->pipe); usb_clear_halt(serial->dev, port->read_urb->pipe); ret = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 0x09, 0x00, 0x01, 0x00, NULL, 0x00, 100); if (ret) return ret; spin_lock_irqsave(&priv->lock, flags); if (tty && (tty->termios->c_cflag & CBAUD)) priv->line_control = MCR_DTR | MCR_RTS; else priv->line_control = 0; spin_unlock_irqrestore(&priv->lock, flags); spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type); /* Setup termios */ if (tty) spcp8x5_set_termios(tty, port, &tmp_termios); spcp8x5_get_msr(serial->dev, &status, priv->type); /* may be we should update uart status here but now we did not do */ spin_lock_irqsave(&priv->lock, flags); priv->line_status = status & 0xf0 ; spin_unlock_irqrestore(&priv->lock, flags); /* FIXME: need to assert RTS and DTR if CRTSCTS off */ dbg("%s - submitting read urb", __func__); port->read_urb->dev = serial->dev; ret = usb_submit_urb(port->read_urb, GFP_KERNEL); if (ret) { spcp8x5_close(tty, port, NULL); return -EPROTO; } return 0; }
static void spcp8x5_dtr_rts(struct usb_serial_port *port, int on) { struct spcp8x5_private *priv = usb_get_serial_port_data(port); unsigned long flags; u8 control; spin_lock_irqsave(&priv->lock, flags); if (on) priv->line_control = MCR_CONTROL_LINE_DTR | MCR_CONTROL_LINE_RTS; else priv->line_control &= ~ (MCR_CONTROL_LINE_DTR | MCR_CONTROL_LINE_RTS); control = priv->line_control; spin_unlock_irqrestore(&priv->lock, flags); spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type); }
static int spcp8x5_tiocmset(struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear) { struct spcp8x5_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 |= MCR_RTS; if (set & TIOCM_DTR) priv->line_control |= MCR_DTR; if (clear & TIOCM_RTS) priv->line_control &= ~MCR_RTS; if (clear & TIOCM_DTR) priv->line_control &= ~MCR_DTR; control = priv->line_control; spin_unlock_irqrestore(&priv->lock, flags); return spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type); }
/* open the serial port. do some usb system call. set termios and get the line * status of the device. */ static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port) { struct ktermios tmp_termios; struct usb_serial *serial = port->serial; struct spcp8x5_private *priv = usb_get_serial_port_data(port); int ret; unsigned long flags; u8 status = 0x30; /* status 0x30 means DSR and CTS = 1 other CDC RI and delta = 0 */ usb_clear_halt(serial->dev, port->write_urb->pipe); usb_clear_halt(serial->dev, port->read_urb->pipe); ret = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 0x09, 0x00, 0x01, 0x00, NULL, 0x00, 100); if (ret) return ret; spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type); /* Setup termios */ if (tty) spcp8x5_set_termios(tty, port, &tmp_termios); spcp8x5_get_msr(serial->dev, &status, priv->type); /* may be we should update uart status here but now we did not do */ spin_lock_irqsave(&priv->lock, flags); priv->line_status = status & 0xf0 ; spin_unlock_irqrestore(&priv->lock, flags); port->port.drain_delay = 256; return usb_serial_generic_open(tty, port); }
/* set the serial param for transfer. we should check if we really need to * transfer. then if be set flow contorl we should do this too. */ static void spcp8x5_set_termios(struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct spcp8x5_private *priv = usb_get_serial_port_data(port); unsigned long flags; unsigned int cflag = port->tty->termios->c_cflag; unsigned int old_cflag = old_termios->c_cflag; unsigned short uartdata; unsigned char buf[2] = {0, 0}; int baud; int i; u8 control; if ((!port->tty) || (!port->tty->termios)) return; /* for the 1st time call this function */ spin_lock_irqsave(&priv->lock, flags); if (!priv->termios_initialized) { *(port->tty->termios) = tty_std_termios; port->tty->termios->c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL; priv->termios_initialized = 1; } spin_unlock_irqrestore(&priv->lock, flags); /* check that they really want us to change something */ if (!tty_termios_hw_change(port->tty->termios, old_termios)) return; /* set DTR/RTS active */ spin_lock_irqsave(&priv->lock, flags); control = priv->line_control; if ((old_cflag & CBAUD) == B0) { priv->line_control |= MCR_DTR; if (!(old_cflag & CRTSCTS)) priv->line_control |= MCR_RTS; } if (control != priv->line_control) { control = priv->line_control; spin_unlock_irqrestore(&priv->lock, flags); spcp8x5_set_ctrlLine(serial->dev, control , priv->type); } else { spin_unlock_irqrestore(&priv->lock, flags); } /* Set Baud Rate */ baud = tty_get_baud_rate(port->tty);; switch (baud) { case 300: buf[0] = 0x00; break; case 600: buf[0] = 0x01; break; case 1200: buf[0] = 0x02; break; case 2400: buf[0] = 0x03; break; case 4800: buf[0] = 0x04; break; case 9600: buf[0] = 0x05; break; case 19200: buf[0] = 0x07; break; case 38400: buf[0] = 0x09; break; case 57600: buf[0] = 0x0a; break; case 115200: buf[0] = 0x0b; break; case 230400: buf[0] = 0x0c; break; case 460800: buf[0] = 0x0d; break; case 921600: buf[0] = 0x0e; break; /* case 1200000: buf[0] = 0x0f; break; */ /* case 2400000: buf[0] = 0x10; break; */ case 3000000: buf[0] = 0x11; break; /* case 6000000: buf[0] = 0x12; break; */ case 0: case 1000000: buf[0] = 0x0b; break; default: err("spcp825 driver does not support the baudrate " "requested, using default of 9600."); } /* Set Data Length : 00:5bit, 01:6bit, 10:7bit, 11:8bit */ if (cflag & CSIZE) { switch (cflag & CSIZE) { case CS5: buf[1] |= SET_UART_FORMAT_SIZE_5; break; case CS6: buf[1] |= SET_UART_FORMAT_SIZE_6; break; case CS7: buf[1] |= SET_UART_FORMAT_SIZE_7; break; default: case CS8: buf[1] |= SET_UART_FORMAT_SIZE_8; break; } } /* Set Stop bit2 : 0:1bit 1:2bit */ buf[1] |= (cflag & CSTOPB) ? SET_UART_FORMAT_STOP_2 : SET_UART_FORMAT_STOP_1; /* Set Parity bit3-4 01:Odd 11:Even */ if (cflag & PARENB) { buf[1] |= (cflag & PARODD) ? SET_UART_FORMAT_PAR_ODD : SET_UART_FORMAT_PAR_EVEN ; } else buf[1] |= SET_UART_FORMAT_PAR_NONE; uartdata = buf[0] | buf[1]<<8; i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), SET_UART_FORMAT_TYPE, SET_UART_FORMAT, uartdata, 0, NULL, 0, 100); if (i < 0) err("Set UART format %#x failed (error = %d)", uartdata, i); dbg("0x21:0x40:0:0 %d\n", i); if (cflag & CRTSCTS) { /* enable hardware flow control */ spcp8x5_set_workMode(serial->dev, 0x000a, SET_WORKING_MODE_U2C, priv->type); } return; }
/* close the serial port. We should wait for data sending to device 1st and * then kill all urb. */ static void spcp8x5_close(struct usb_serial_port *port, struct file *filp) { struct spcp8x5_private *priv = usb_get_serial_port_data(port); unsigned long flags; unsigned int c_cflag; int bps; long timeout; wait_queue_t wait; int result; dbg("%s - port %d", __func__, port->number); /* wait for data to drain from the buffer */ spin_lock_irqsave(&priv->lock, flags); timeout = SPCP8x5_CLOSING_WAIT; init_waitqueue_entry(&wait, current); add_wait_queue(&port->tty->write_wait, &wait); for (;;) { set_current_state(TASK_INTERRUPTIBLE); if (ringbuf_avail_data(priv->buf) == 0 || timeout == 0 || signal_pending(current)) break; spin_unlock_irqrestore(&priv->lock, flags); timeout = schedule_timeout(timeout); spin_lock_irqsave(&priv->lock, flags); } set_current_state(TASK_RUNNING); remove_wait_queue(&port->tty->write_wait, &wait); /* clear out any remaining data in the buffer */ clear_ringbuf(priv->buf); spin_unlock_irqrestore(&priv->lock, flags); /* wait for characters to drain from the device (this is long enough * for the entire all byte spcp8x5 hardware buffer to drain with no * flow control for data rates of 1200 bps or more, for lower rates we * should really know how much data is in the buffer to compute a delay * that is not unnecessarily long) */ bps = tty_get_baud_rate(port->tty); if (bps > 1200) timeout = max((HZ*2560) / bps, HZ/10); else timeout = 2*HZ; set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(timeout); /* clear control lines */ if (port->tty) { c_cflag = port->tty->termios->c_cflag; if (c_cflag & HUPCL) { spin_lock_irqsave(&priv->lock, flags); priv->line_control = 0; spin_unlock_irqrestore(&priv->lock, flags); spcp8x5_set_ctrlLine(port->serial->dev, 0 , priv->type); } } /* kill urb */ if (port->write_urb != NULL) { result = usb_unlink_urb(port->write_urb); if (result) dev_dbg(&port->dev, "usb_unlink_urb(write_urb) = %d\n", result); } result = usb_unlink_urb(port->read_urb); if (result) dev_dbg(&port->dev, "usb_unlink_urb(read_urb) = %d\n", result); }