aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/cypress_m8.c
diff options
context:
space:
mode:
authorMike Isely <isely@pobox.com>2008-02-10 21:23:32 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2008-04-25 00:16:38 -0400
commit92983c2121fb46f234add1c36b5e596779899d56 (patch)
tree75c51452bd60fcc38edda00cd54e25976e7b3f5f /drivers/usb/serial/cypress_m8.c
parent6768306c3d9568bc66dc22f8b863bfbda3e7c4d2 (diff)
USB: cypress_m8: Limit baud rate to <=4800 for USB low speed devices
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 <isely@pobox.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/cypress_m8.c')
-rw-r--r--drivers/usb/serial/cypress_m8.c104
1 files changed, 59 insertions, 45 deletions
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index bdeda0936951..4bf45c711b9d 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -291,6 +291,59 @@ static struct usb_serial_driver cypress_ca42v2_device = {
291 *****************************************************************************/ 291 *****************************************************************************/
292 292
293 293
294static int analyze_baud_rate(struct usb_serial_port *port, unsigned baud_mask)
295{
296 int new_rate;
297 struct cypress_private *priv;
298 priv = usb_get_serial_port_data(port);
299
300 /*
301 * The general purpose firmware for the Cypress M8 allows for
302 * a maximum speed of 57600bps (I have no idea whether DeLorme
303 * chose to use the general purpose firmware or not), if you
304 * need to modify this speed setting for your own project
305 * please add your own chiptype and modify the code likewise.
306 * The Cypress HID->COM device will work successfully up to
307 * 115200bps (but the actual throughput is around 3kBps).
308 */
309 new_rate = mask_to_rate(baud_mask);
310 if (new_rate < 0) {
311 dbg("%s - failed setting baud rate, untranslatable speed",
312 __func__);
313 return -1;
314 }
315 if (port->serial->dev->speed == USB_SPEED_LOW) {
316 /*
317 * Mike Isely <isely@pobox.com> 2-Feb-2008: The
318 * Cypress app note that describes this mechanism
319 * states the the low-speed part can't handle more
320 * than 800 bytes/sec, in which case 4800 baud is the
321 * safest speed for a part like that.
322 */
323 if (new_rate > 4800) {
324 dbg("%s - failed setting baud rate, device incapable "
325 "speed %d", __func__, new_rate);
326 return -1;
327 }
328 }
329 switch (priv->chiptype) {
330 case CT_EARTHMATE:
331 if (new_rate <= 600) {
332 /* 300 and 600 baud rates are supported under
333 * the generic firmware, but are not used with
334 * NMEA and SiRF protocols */
335 dbg("%s - failed setting baud rate, unsupported speed "
336 "of %d on Earthmate GPS", __func__, new_rate);
337 return -1;
338 }
339 break;
340 default:
341 break;
342 }
343 return new_rate;
344}
345
346
294/* This function can either set or retrieve the current serial line settings */ 347/* This function can either set or retrieve the current serial line settings */
295static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_mask, int data_bits, int stop_bits, 348static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_mask, int data_bits, int stop_bits,
296 int parity_enable, int parity_type, int reset, int cypress_request_type) 349 int parity_enable, int parity_type, int reset, int cypress_request_type)
@@ -309,54 +362,15 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
309 362
310 switch(cypress_request_type) { 363 switch(cypress_request_type) {
311 case CYPRESS_SET_CONFIG: 364 case CYPRESS_SET_CONFIG:
312 365 new_baudrate = priv->baud_rate;
313 /*
314 * The general purpose firmware for the Cypress M8 allows for a maximum speed
315 * of 57600bps (I have no idea whether DeLorme chose to use the general purpose
316 * firmware or not), if you need to modify this speed setting for your own
317 * project please add your own chiptype and modify the code likewise. The
318 * Cypress HID->COM device will work successfully up to 115200bps (but the
319 * actual throughput is around 3kBps).
320 */
321 if (baud_mask != priv->cbr_mask) { 366 if (baud_mask != priv->cbr_mask) {
322 dbg("%s - baud rate is changing", __FUNCTION__); 367 dbg("%s - baud rate is changing", __FUNCTION__);
323 if ( priv->chiptype == CT_EARTHMATE ) { 368 retval = analyze_baud_rate(port, baud_mask);
324 /* 300 and 600 baud rates are supported under the generic firmware, 369 if (retval >= 0) {
325 * but are not used with NMEA and SiRF protocols */ 370 new_baudrate = retval;
326 371 dbg("%s - New baud rate set to %d",
327 if ( (baud_mask == B300) || (baud_mask == B600) ) { 372 __func__, new_baudrate);
328 err("%s - failed setting baud rate, unsupported speed",
329 __FUNCTION__);
330 new_baudrate = priv->baud_rate;
331 } else if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) {
332 err("%s - failed setting baud rate, unsupported speed",
333 __FUNCTION__);
334 new_baudrate = priv->baud_rate;
335 }
336 } else if (priv->chiptype == CT_CYPHIDCOM) {
337 if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) {
338 err("%s - failed setting baud rate, unsupported speed",
339 __FUNCTION__);
340 new_baudrate = priv->baud_rate;
341 }
342 } else if (priv->chiptype == CT_CA42V2) {
343 if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) {
344 err("%s - failed setting baud rate, unsupported speed",
345 __FUNCTION__);
346 new_baudrate = priv->baud_rate;
347 }
348 } else if (priv->chiptype == CT_GENERIC) {
349 if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) {
350 err("%s - failed setting baud rate, unsupported speed",
351 __FUNCTION__);
352 new_baudrate = priv->baud_rate;
353 }
354 } else {
355 info("%s - please define your chiptype", __FUNCTION__);
356 new_baudrate = priv->baud_rate;
357 } 373 }
358 } else { /* baud rate not changing, keep the old */
359 new_baudrate = priv->baud_rate;
360 } 374 }
361 dbg("%s - baud rate is being sent as %d", __FUNCTION__, new_baudrate); 375 dbg("%s - baud rate is being sent as %d", __FUNCTION__, new_baudrate);
362 376