*****************************************************************************/
 
 
+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",
+                   __func__);
+               return -1;
+       }
+       if (port->serial->dev->speed == USB_SPEED_LOW) {
+               /*
+                * Mike Isely <isely@pobox.com> 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", __func__, 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", __func__, 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)
 
        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",
+                                           __func__, 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);