cypress_m8: Limit baud rate to <=4800 for USB low speed devices

From: Mike Isely <[EMAIL PROTECTED]>

The cypress app note for the M8 states that for the USB low speed
version of the part, throughput is effectively limited to 800
bytes/sec.  So if we were to try a faster baud rate in such cases then
we risk overrun errors on receive.  Best to just identify this case
and limit the rate to 4800 baud or less (by ignoring any request to
set a faster rate).  The old baud rate setting code was somewhat
fragile; this change also hopefully makes it easier in the future to
better checking / limiting.

Signed-off-by: Mike Isely <[EMAIL PROTECTED]>

---
 cypress_m8.c |  103 +++++++++++++++++++++++++++++++++--------------------------
 1 file changed, 58 insertions(+), 45 deletions(-)

---

diff -uprN -X linux-2.6.23.12-vanilla/Documentation/dontdiff 
cypress_patch_04_null_check/drivers/usb/serial/cypress_m8.c 
cypress_patch_05_baud_rate/drivers/usb/serial/cypress_m8.c
--- cypress_patch_04_null_check/drivers/usb/serial/cypress_m8.c 2008-02-10 
19:37:47.000000000 -0600
+++ cypress_patch_05_baud_rate/drivers/usb/serial/cypress_m8.c  2008-02-10 
19:38:08.000000000 -0600
@@ -289,6 +289,59 @@ static struct usb_serial_driver cypress_
  *****************************************************************************/
 
 
+static int analyze_baud_rate(struct usb_serial_port *port, unsigned baud_mask)
+{
+       int new_rate;
+       struct cypress_private *priv;
+       priv = usb_get_serial_port_data(port);
+
+       /*
+        * The general purpose firmware for the Cypress M8 allows for
+        * a maximum speed of 57600bps (I have no idea whether DeLorme
+        * chose to use the general purpose firmware or not), if you
+        * need to modify this speed setting for your own project
+        * please add your own chiptype and modify the code likewise.
+        * The Cypress HID->COM device will work successfully up to
+        * 115200bps (but the actual throughput is around 3kBps).
+        */
+       new_rate = mask_to_rate(baud_mask);
+       if (new_rate < 0) {
+               dbg("%s - failed setting baud rate, untranslatable speed",
+                   __FUNCTION__);
+               return -1;
+       }
+       if (port->serial->dev->speed == USB_SPEED_LOW) {
+               /*
+                * Mike Isely <[EMAIL PROTECTED]> 2-Feb-2008: The
+                * Cypress app note that describes this mechanism
+                * states the the low-speed part can't handle more
+                * than 800 bytes/sec, in which case 4800 baud is the
+                * safest speed for a part like that.
+                */
+               if (new_rate > 4800) {
+                       dbg("%s - failed setting baud rate, device incapable 
speed %d",
+                           __FUNCTION__, new_rate);
+                       return -1;
+               }
+       }
+       switch (priv->chiptype) {
+       case CT_EARTHMATE:
+               if (new_rate <= 600) {
+                       /* 300 and 600 baud rates are supported under
+                        * the generic firmware, but are not used with
+                        * NMEA and SiRF protocols */
+                       dbg("%s - failed setting baud rate, unsupported speed 
of %d on Earthmate GPS",
+                           __FUNCTION__, new_rate);
+                       return -1;
+               }
+               break;
+       default:
+               break;
+       }
+       return new_rate;
+}
+
+
 /* This function can either set or retrieve the current serial line settings */
 static int cypress_serial_control (struct usb_serial_port *port, unsigned 
baud_mask, int data_bits, int stop_bits,
                                   int parity_enable, int parity_type, int 
reset, int cypress_request_type)
@@ -307,54 +360,14 @@ static int cypress_serial_control (struc
 
        switch(cypress_request_type) {
                case CYPRESS_SET_CONFIG:
-
-                       /*
-                        * The general purpose firmware for the Cypress M8 
allows for a maximum speed
-                        * of 57600bps (I have no idea whether DeLorme chose to 
use the general purpose
-                        * firmware or not), if you need to modify this speed 
setting for your own
-                        * project please add your own chiptype and modify the 
code likewise.  The
-                        * Cypress HID->COM device will work successfully up to 
115200bps (but the
-                        * actual throughput is around 3kBps).
-                        */
+                       new_baudrate = priv->baud_rate;
                        if (baud_mask != priv->cbr_mask) {
                                dbg("%s - baud rate is changing", __FUNCTION__);
-                               if ( priv->chiptype == CT_EARTHMATE ) {
-                                       /* 300 and 600 baud rates are supported 
under the generic firmware,
-                                        * but are not used with NMEA and SiRF 
protocols */
-                                       
-                                       if ( (baud_mask == B300) || (baud_mask 
== B600) ) {
-                                               err("%s - failed setting baud 
rate, unsupported speed",
-                                                   __FUNCTION__);
-                                               new_baudrate = priv->baud_rate;
-                                       } else if ( (new_baudrate = 
mask_to_rate(baud_mask)) == -1) {
-                                               err("%s - failed setting baud 
rate, unsupported speed",
-                                                   __FUNCTION__);
-                                               new_baudrate = priv->baud_rate;
-                                       }
-                               } else if (priv->chiptype == CT_CYPHIDCOM) {
-                                       if ( (new_baudrate = 
mask_to_rate(baud_mask)) == -1) {
-                                               err("%s - failed setting baud 
rate, unsupported speed",
-                                                   __FUNCTION__);
-                                               new_baudrate = priv->baud_rate;
-                                       }
-                               } else if (priv->chiptype == CT_CA42V2) {
-                                       if ( (new_baudrate = 
mask_to_rate(baud_mask)) == -1) {
-                                               err("%s - failed setting baud 
rate, unsupported speed",
-                                                   __FUNCTION__);
-                                               new_baudrate = priv->baud_rate;
-                                       }
-                               } else if (priv->chiptype == CT_GENERIC) {
-                                       if ( (new_baudrate = 
mask_to_rate(baud_mask)) == -1) {
-                                               err("%s - failed setting baud 
rate, unsupported speed",
-                                                   __FUNCTION__);
-                                               new_baudrate = priv->baud_rate;
-                                       }
-                               } else {
-                                       info("%s - please define your 
chiptype", __FUNCTION__);
-                                       new_baudrate = priv->baud_rate;
+                               retval = analyze_baud_rate(port, baud_mask);
+                               if (retval >=  0) {
+                                       new_baudrate = retval;
+                                       dbg("%s - New baud rate set to %d", 
__FUNCTION__, new_baudrate);
                                }
-                       } else {  /* baud rate not changing, keep the old */
-                               new_baudrate = priv->baud_rate;
                        }
                        dbg("%s - baud rate is being sent as %d", __FUNCTION__, 
new_baudrate);
                        

-- 
                        |         Mike Isely          |     PGP fingerprint
     Spammers Die!!     |                             | 03 54 43 4D 75 E5 CC 92
                        |   isely @ pobox (dot) com   | 71 16 01 E2 B5 F5 C1 E8
                        |                             |
-
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to