add pl2303 bugfixes (thanks to komodo)
authorNicolas Thill <nico@openwrt.org>
Wed, 19 Oct 2005 02:41:50 +0000 (02:41 +0000)
committerNicolas Thill <nico@openwrt.org>
Wed, 19 Oct 2005 02:41:50 +0000 (02:41 +0000)
SVN-Revision: 2178

openwrt/target/linux/linux-2.4/patches/generic/211-pl2303_bugfixes.patch [new file with mode: 0644]

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 (file)
index 0000000..bf7c3c3
--- /dev/null
@@ -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 */