--- linux/drivers/usb/serial/pl2303.c.orig 2005-10-17 12:09:48.000000000 +0200 +++ linux/drivers/usb/serial/pl2303.c 2005-10-19 04:10:46.000000000 +0200 @@ -14,6 +14,13 @@ * See Documentation/usb/usb-serial.txt for more information on using this driver * * + * 2005_Oct_19 grsch + * added some missing ioctl commands + * it seems that there's still an issue with the 2.6.8 version when + * using the device with echo "whatever" >/dev/usb/tts/0 . + * Apparently, a timeout is needed upon pl2303_close (implemented in + * 2.6.13.4) + * * 2005_Mar_05 grsch * ported 2.6.8 pl2303.c to 2.4.20 format * (HX model works fine now, ID table should be brought up to date) @@ -142,9 +149,8 @@ static int pl2303_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); static void pl2303_break_ctl(struct usb_serial_port *port,int break_state); -static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file); -static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file, - unsigned int set, unsigned int clear); +static int pl2303_tiocmget (struct usb_serial_port *port, unsigned int* value); +static int pl2303_tiocmset (struct usb_serial_port *port, unsigned int cmd, unsigned int *value); static int pl2303_startup (struct usb_serial *serial); static void pl2303_shutdown (struct usb_serial *serial); @@ -642,11 +648,108 @@ return 0; } + + +static int pl2303_tiocmget (struct usb_serial_port *port, unsigned int *value) +{ + struct pl2303_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + unsigned int mcr; + unsigned int status; + unsigned int result; + + dbg("%s (%d)", __FUNCTION__, port->number); + + spin_lock_irqsave (&priv->lock, flags); + mcr = priv->line_control; + status = priv->line_status; + spin_unlock_irqrestore (&priv->lock, flags); + + result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0) + | ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0) + | ((status & UART_CTS) ? TIOCM_CTS : 0) + | ((status & UART_DSR) ? TIOCM_DSR : 0) + | ((status & UART_RING) ? TIOCM_RI : 0) + | ((status & UART_DCD) ? TIOCM_CD : 0); + + dbg("%s - result = %x", __FUNCTION__, result); + + if (copy_to_user(value, &result, sizeof(int))) + return -EFAULT; + return 0; +} + + + +static int pl2303_tiocmset (struct usb_serial_port *port, unsigned int cmd, unsigned int *value) +{ + /* + struct pl2303_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 |= CONTROL_RTS; + if (set & TIOCM_DTR) + priv->line_control |= CONTROL_DTR; + if (clear & TIOCM_RTS) + priv->line_control &= ~CONTROL_RTS; + if (clear & TIOCM_DTR) + priv->line_control &= ~CONTROL_DTR; + control = priv->line_control; + spin_unlock_irqrestore (&priv->lock, flags); + + return set_control_lines (port->serial->dev, control); + */ + struct pl2303_private *priv = port->private; + unsigned int arg; + + if (copy_from_user(&arg, value, sizeof(int))) + return -EFAULT; + + switch (cmd) { + case TIOCMBIS: + if (arg & TIOCM_RTS) + priv->line_control |= CONTROL_RTS; + if (arg & TIOCM_DTR) + priv->line_control |= CONTROL_DTR; + break; + + case TIOCMBIC: + if (arg & TIOCM_RTS) + priv->line_control &= ~CONTROL_RTS; + if (arg & TIOCM_DTR) + priv->line_control &= ~CONTROL_DTR; + break; + + case TIOCMSET: + /* turn off RTS and DTR and then only turn + on what was asked to */ + priv->line_control &= ~(CONTROL_RTS | CONTROL_DTR); + priv->line_control |= ((arg & TIOCM_RTS) ? CONTROL_RTS : 0); + priv->line_control |= ((arg & TIOCM_DTR) ? CONTROL_DTR : 0); + break; + } + + return set_control_lines (port->serial->dev, priv->line_control); +} + + + static int pl2303_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg) { dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd); switch (cmd) { + case TIOCMGET: + dbg("%s (%d) TIOCMGET", __FUNCTION__, port->number); + return pl2303_tiocmget(port,(unsigned int *)arg); + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__, port->number); + return pl2303_tiocmset(port,cmd,(unsigned int*)arg); case TIOCMIWAIT: dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number); return wait_modem_info(port, arg); @@ -705,6 +808,8 @@ dbg("%s (%d)", __FUNCTION__, port->number); + dbg("%s - urb status %d...", __FUNCTION__, urb->status); + switch (urb->status) { case 0: /* success */