vserver 1.9.5.x5
[linux-2.6.git] / drivers / usb / serial / ftdi_sio.c
index 9073ea8..8e75ea1 100644 (file)
@@ -368,6 +368,11 @@ static struct usb_device_id id_table_8U232AM [] = {
        { USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0, 0x3ff) },
        { USB_DEVICE_VER(FALCOM_VID, FALCOM_TWIST_PID, 0, 0x3ff) },
        { USB_DEVICE_VER(FTDI_VID, FTDI_SUUNTO_SPORTS_PID, 0, 0x3ff) },
+       { USB_DEVICE_VER(FTDI_RM_VID, FTDI_RMCANVIEW_PID, 0, 0x3ff) },
+       { USB_DEVICE_VER(BANDB_VID, BANDB_USOTL4_PID, 0, 0x3ff) },
+       { USB_DEVICE_VER(BANDB_VID, BANDB_USTL4_PID, 0, 0x3ff) },
+       { USB_DEVICE_VER(BANDB_VID, BANDB_USO9ML2_PID, 0, 0x3ff) },
+       { USB_DEVICE_VER(FTDI_VID, EVER_ECO_PRO_CDS, 0, 0x3ff) },
        { }                                             /* Terminating entry */
 };
 
@@ -478,6 +483,11 @@ static struct usb_device_id id_table_FT232BM [] = {
        { USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0x400, 0xffff) },
        { USB_DEVICE_VER(FALCOM_VID, FALCOM_TWIST_PID, 0x400, 0xffff) },
        { USB_DEVICE_VER(FTDI_VID, FTDI_SUUNTO_SPORTS_PID, 0x400, 0xffff) },
+       { USB_DEVICE_VER(FTDI_RM_VID, FTDI_RMCANVIEW_PID, 0x400, 0xffff) },
+       { USB_DEVICE_VER(BANDB_VID, BANDB_USOTL4_PID, 0x400, 0xffff) },
+       { USB_DEVICE_VER(BANDB_VID, BANDB_USTL4_PID, 0x400, 0xffff) },
+       { USB_DEVICE_VER(BANDB_VID, BANDB_USO9ML2_PID, 0x400, 0xffff) },
+       { USB_DEVICE_VER(FTDI_VID, EVER_ECO_PRO_CDS, 0x400, 0xffff) },
        { }                                             /* Terminating entry */
 };
 
@@ -528,6 +538,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_5_PID, 0x400, 0xffff) },
        { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_6_PID, 0x400, 0xffff) },
        { USB_DEVICE_VER(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID, 0x400, 0xffff) },
+       { USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) },
        { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) },
        { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) },
        { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) },
@@ -595,6 +606,11 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) },
        { USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) },
+       { USB_DEVICE(FTDI_RM_VID, FTDI_RMCANVIEW_PID) },
+       { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },
+       { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) },
+       { USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) },
+       { USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) },
        { }                                             /* Terminating entry */
 };
 
@@ -657,7 +673,7 @@ static int  ftdi_HE_TIRA1_startup   (struct usb_serial *serial);
 static void ftdi_shutdown              (struct usb_serial *serial);
 static int  ftdi_open                  (struct usb_serial_port *port, struct file *filp);
 static void ftdi_close                 (struct usb_serial_port *port, struct file *filp);
-static int  ftdi_write                 (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
+static int  ftdi_write                 (struct usb_serial_port *port, const unsigned char *buf, int count);
 static int  ftdi_write_room            (struct usb_serial_port *port);
 static int  ftdi_chars_in_buffer       (struct usb_serial_port *port);
 static void ftdi_write_bulk_callback   (struct urb *urb, struct pt_regs *regs);
@@ -1124,7 +1140,7 @@ static int set_serial_info(struct usb_serial_port * port, struct serial_struct _
                goto check_and_exit;
        }
 
-       if ((new_serial.baud_base != priv->baud_base) ||
+       if ((new_serial.baud_base != priv->baud_base) &&
            (new_serial.baud_base < 9600))
                return -EINVAL;
 
@@ -1161,6 +1177,135 @@ check_and_exit:
 
 } /* set_serial_info */
 
+
+/*
+ * ***************************************************************************
+ * Sysfs Attribute
+ * ***************************************************************************
+ */
+
+ssize_t show_latency_timer(struct device *dev, char *buf)
+{
+       struct usb_serial_port *port = to_usb_serial_port(dev);
+       struct ftdi_private *priv = usb_get_serial_port_data(port);
+       struct usb_device *udev;
+       unsigned short latency = 0;
+       int rv = 0;
+       
+       udev = to_usb_device(dev);
+       
+       dbg("%s",__FUNCTION__);
+       
+       rv = usb_control_msg(udev,
+                            usb_rcvctrlpipe(udev, 0),
+                            FTDI_SIO_GET_LATENCY_TIMER_REQUEST,
+                            FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE,
+                            0, priv->interface, 
+                            (char*) &latency, 1, WDR_TIMEOUT);
+       
+       if (rv < 0) {
+               dev_err(dev, "Unable to read latency timer: %i", rv);
+               return -EIO;
+       }
+       return sprintf(buf, "%i\n", latency);
+}
+
+/* Write a new value of the latency timer, in units of milliseconds. */
+ssize_t store_latency_timer(struct device *dev, const char *valbuf, size_t count)
+{
+       struct usb_serial_port *port = to_usb_serial_port(dev);
+       struct ftdi_private *priv = usb_get_serial_port_data(port);
+       struct usb_device *udev;
+       char buf[1];
+       int v = simple_strtoul(valbuf, NULL, 10);
+       int rv = 0;
+       
+       udev = to_usb_device(dev);
+       
+       dbg("%s: setting latency timer = %i", __FUNCTION__, v);
+       
+       rv = usb_control_msg(udev,
+                            usb_sndctrlpipe(udev, 0),
+                            FTDI_SIO_SET_LATENCY_TIMER_REQUEST,
+                            FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE,
+                            v, priv->interface, 
+                            buf, 0, WDR_TIMEOUT);
+       
+       if (rv < 0) {
+               dev_err(dev, "Unable to write latency timer: %i", rv);
+               return -EIO;
+       }
+       
+       return count;
+}
+
+/* Write an event character directly to the FTDI register.  The ASCII
+   value is in the low 8 bits, with the enable bit in the 9th bit. */
+ssize_t store_event_char(struct device *dev, const char *valbuf, size_t count)
+{
+       struct usb_serial_port *port = to_usb_serial_port(dev);
+       struct ftdi_private *priv = usb_get_serial_port_data(port);
+       struct usb_device *udev;
+       char buf[1];
+       int v = simple_strtoul(valbuf, NULL, 10);
+       int rv = 0;
+       
+       udev = to_usb_device(dev);
+       
+       dbg("%s: setting event char = %i", __FUNCTION__, v);
+       
+       rv = usb_control_msg(udev,
+                            usb_sndctrlpipe(udev, 0),
+                            FTDI_SIO_SET_EVENT_CHAR_REQUEST,
+                            FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE,
+                            v, priv->interface, 
+                            buf, 0, WDR_TIMEOUT);
+       
+       if (rv < 0) {
+               dbg("Unable to write event character: %i", rv);
+               return -EIO;
+       }
+       
+       return count;
+}
+
+static DEVICE_ATTR(latency_timer, S_IWUGO | S_IRUGO, show_latency_timer, store_latency_timer);
+static DEVICE_ATTR(event_char, S_IWUGO, NULL, store_event_char);
+
+void create_sysfs_attrs(struct usb_serial *serial)
+{      
+       struct ftdi_private *priv;
+       struct usb_device *udev;
+
+       dbg("%s",__FUNCTION__);
+       
+       priv = usb_get_serial_port_data(serial->port[0]);
+       udev = serial->dev;
+       
+       if (priv->chip_type == FT232BM) {
+               dbg("sysfs attributes for FT232BM");
+               device_create_file(&udev->dev, &dev_attr_event_char);
+               device_create_file(&udev->dev, &dev_attr_latency_timer);
+       }
+}
+
+void remove_sysfs_attrs(struct usb_serial *serial)
+{
+       struct ftdi_private *priv;
+       struct usb_device *udev;
+
+       dbg("%s",__FUNCTION__); 
+
+       priv = usb_get_serial_port_data(serial->port[0]);
+       udev = serial->dev;
+       
+       if (priv->chip_type == FT232BM) {
+               device_remove_file(&udev->dev, &dev_attr_event_char);
+               device_remove_file(&udev->dev, &dev_attr_latency_timer);
+       }
+       
+}
+
 /*
  * ***************************************************************************
  * FTDI driver specific functions
@@ -1278,6 +1423,8 @@ static int ftdi_FT232BM_startup (struct usb_serial *serial)
        priv->chip_type = FT232BM;
        priv->baud_base = 48000000 / 2; /* Would be / 16, but FT232BM supports multiple of 0.125 divisor fractions! */
        
+       create_sysfs_attrs(serial);
+
        return (0);
 } /* ftdi_FT232BM_startup */
 
@@ -1371,6 +1518,8 @@ static void ftdi_shutdown (struct usb_serial *serial)
 
        dbg("%s", __FUNCTION__);
 
+       remove_sysfs_attrs(serial);
+       
        /* all open ports are closed at this point 
          *    (by usbserial.c:__serial_close, which calls ftdi_close)  
         */
@@ -1479,16 +1628,8 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp)
        } /* Note change no line if hupcl is off */
        
        /* shutdown our bulk read */
-       if (port->read_urb) {
-               if (usb_unlink_urb (port->read_urb) < 0) {
-                       /* Generally, this isn't an error.  If the previous
-                          read bulk callback occurred (or is about to occur)
-                          while the port was being closed or was throtted
-                          (and is still throttled), the read urb will not
-                          have been submitted. */
-                       dbg("%s - failed to unlink read urb (generally not an error)", __FUNCTION__);
-               }
-       }
+       if (port->read_urb)
+               usb_kill_urb(port->read_urb);
 } /* ftdi_close */
 
 
@@ -1500,7 +1641,7 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp)
  *
  * The new devices do not require this byte
  */
-static int ftdi_write (struct usb_serial_port *port, int from_user,
+static int ftdi_write (struct usb_serial_port *port,
                           const unsigned char *buf, int count)
 { /* ftdi_write */
        struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1513,7 +1654,7 @@ static int ftdi_write (struct usb_serial_port *port, int from_user,
        dbg("%s port %d, %d bytes", __FUNCTION__, port->number, count);
 
        if (count == 0) {
-               err("write request of 0 bytes");
+               dbg("write request of 0 bytes");
                return 0;
        }
        
@@ -1557,17 +1698,8 @@ static int ftdi_write (struct usb_serial_port *port, int from_user,
                        /* Write the control byte at the front of the packet*/
                        *first_byte = 1 | ((user_pktsz) << 2); 
                        /* Copy data for packet */
-                       if (from_user) {
-                               if (copy_from_user (first_byte + data_offset,
-                                                   current_position, user_pktsz)){
-                                       kfree (buffer);
-                                       usb_free_urb (urb);
-                                       return -EFAULT;
-                               }
-                       } else {
-                               memcpy (first_byte + data_offset,
-                                       current_position, user_pktsz);
-                       }
+                       memcpy (first_byte + data_offset,
+                               current_position, user_pktsz);
                        first_byte += user_pktsz + data_offset;
                        current_position += user_pktsz;
                        todo -= user_pktsz;
@@ -1575,15 +1707,7 @@ static int ftdi_write (struct usb_serial_port *port, int from_user,
        } else {
                /* No control byte required. */
                /* Copy in the data to send */
-               if (from_user) {
-                       if (copy_from_user (buffer, buf, count)) {
-                               kfree (buffer);
-                               usb_free_urb (urb);
-                               return -EFAULT;
-                       }
-               } else {
-                       memcpy (buffer, buf, count);
-               }
+               memcpy (buffer, buf, count);
        }
 
        usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size, buffer);