diff --git a/openwrt/target/linux/linux-2.4/patches/generic/211-pl2303_bugfixes.patch b/openwrt/target/linux/linux-2.4/patches/generic/211-pl2303_bugfixes.patch new file mode 100644 index 0000000000..bf7c3c3c42 --- /dev/null +++ b/openwrt/target/linux/linux-2.4/patches/generic/211-pl2303_bugfixes.patch @@ -0,0 +1,146 @@ +--- 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 */