aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/cypress_m8.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial/cypress_m8.c')
-rw-r--r--drivers/usb/serial/cypress_m8.c84
1 files changed, 41 insertions, 43 deletions
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index a591ebec0f89..e23c77925e7a 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -66,17 +66,15 @@
66#include <linux/serial.h> 66#include <linux/serial.h>
67#include <linux/delay.h> 67#include <linux/delay.h>
68#include <linux/uaccess.h> 68#include <linux/uaccess.h>
69#include <asm/unaligned.h>
69 70
70#include "cypress_m8.h" 71#include "cypress_m8.h"
71 72
72 73
73#ifdef CONFIG_USB_SERIAL_DEBUG 74static int debug;
74 static int debug = 1;
75#else
76 static int debug;
77#endif
78static int stats; 75static int stats;
79static int interval; 76static int interval;
77static int unstable_bauds;
80 78
81/* 79/*
82 * Version Information 80 * Version Information
@@ -89,24 +87,24 @@ static int interval;
89#define CYPRESS_BUF_SIZE 1024 87#define CYPRESS_BUF_SIZE 1024
90#define CYPRESS_CLOSING_WAIT (30*HZ) 88#define CYPRESS_CLOSING_WAIT (30*HZ)
91 89
92static struct usb_device_id id_table_earthmate [] = { 90static const struct usb_device_id id_table_earthmate[] = {
93 { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) }, 91 { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
94 { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) }, 92 { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) },
95 { } /* Terminating entry */ 93 { } /* Terminating entry */
96}; 94};
97 95
98static struct usb_device_id id_table_cyphidcomrs232 [] = { 96static const struct usb_device_id id_table_cyphidcomrs232[] = {
99 { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) }, 97 { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
100 { USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) }, 98 { USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) },
101 { } /* Terminating entry */ 99 { } /* Terminating entry */
102}; 100};
103 101
104static struct usb_device_id id_table_nokiaca42v2 [] = { 102static const struct usb_device_id id_table_nokiaca42v2[] = {
105 { USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) }, 103 { USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) },
106 { } /* Terminating entry */ 104 { } /* Terminating entry */
107}; 105};
108 106
109static struct usb_device_id id_table_combined [] = { 107static const struct usb_device_id id_table_combined[] = {
110 { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) }, 108 { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
111 { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) }, 109 { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) },
112 { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) }, 110 { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
@@ -154,7 +152,7 @@ struct cypress_private {
154 int isthrottled; /* if throttled, discard reads */ 152 int isthrottled; /* if throttled, discard reads */
155 wait_queue_head_t delta_msr_wait; /* used for TIOCMIWAIT */ 153 wait_queue_head_t delta_msr_wait; /* used for TIOCMIWAIT */
156 char prev_status, diff_status; /* used for TIOCMIWAIT */ 154 char prev_status, diff_status; /* used for TIOCMIWAIT */
157 /* we pass a pointer to this as the arguement sent to 155 /* we pass a pointer to this as the argument sent to
158 cypress_set_termios old_termios */ 156 cypress_set_termios old_termios */
159 struct ktermios tmp_termios; /* stores the old termios settings */ 157 struct ktermios tmp_termios; /* stores the old termios settings */
160}; 158};
@@ -295,6 +293,9 @@ static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate)
295 struct cypress_private *priv; 293 struct cypress_private *priv;
296 priv = usb_get_serial_port_data(port); 294 priv = usb_get_serial_port_data(port);
297 295
296 if (unstable_bauds)
297 return new_rate;
298
298 /* 299 /*
299 * The general purpose firmware for the Cypress M8 allows for 300 * The general purpose firmware for the Cypress M8 allows for
300 * a maximum speed of 57600bps (I have no idea whether DeLorme 301 * a maximum speed of 57600bps (I have no idea whether DeLorme
@@ -344,7 +345,8 @@ static int cypress_serial_control(struct tty_struct *tty,
344{ 345{
345 int new_baudrate = 0, retval = 0, tries = 0; 346 int new_baudrate = 0, retval = 0, tries = 0;
346 struct cypress_private *priv; 347 struct cypress_private *priv;
347 __u8 feature_buffer[5]; 348 u8 *feature_buffer;
349 const unsigned int feature_len = 5;
348 unsigned long flags; 350 unsigned long flags;
349 351
350 dbg("%s", __func__); 352 dbg("%s", __func__);
@@ -354,17 +356,18 @@ static int cypress_serial_control(struct tty_struct *tty,
354 if (!priv->comm_is_ok) 356 if (!priv->comm_is_ok)
355 return -ENODEV; 357 return -ENODEV;
356 358
359 feature_buffer = kcalloc(feature_len, sizeof(u8), GFP_KERNEL);
360 if (!feature_buffer)
361 return -ENOMEM;
362
357 switch (cypress_request_type) { 363 switch (cypress_request_type) {
358 case CYPRESS_SET_CONFIG: 364 case CYPRESS_SET_CONFIG:
359 new_baudrate = priv->baud_rate;
360 /* 0 means 'Hang up' so doesn't change the true bit rate */ 365 /* 0 means 'Hang up' so doesn't change the true bit rate */
361 if (baud_rate == 0) 366 new_baudrate = priv->baud_rate;
362 new_baudrate = priv->baud_rate; 367 if (baud_rate && baud_rate != priv->baud_rate) {
363 /* Change of speed ? */
364 else if (baud_rate != priv->baud_rate) {
365 dbg("%s - baud rate is changing", __func__); 368 dbg("%s - baud rate is changing", __func__);
366 retval = analyze_baud_rate(port, baud_rate); 369 retval = analyze_baud_rate(port, baud_rate);
367 if (retval >= 0) { 370 if (retval >= 0) {
368 new_baudrate = retval; 371 new_baudrate = retval;
369 dbg("%s - New baud rate set to %d", 372 dbg("%s - New baud rate set to %d",
370 __func__, new_baudrate); 373 __func__, new_baudrate);
@@ -373,9 +376,8 @@ static int cypress_serial_control(struct tty_struct *tty,
373 dbg("%s - baud rate is being sent as %d", 376 dbg("%s - baud rate is being sent as %d",
374 __func__, new_baudrate); 377 __func__, new_baudrate);
375 378
376 memset(feature_buffer, 0, sizeof(feature_buffer));
377 /* fill the feature_buffer with new configuration */ 379 /* fill the feature_buffer with new configuration */
378 *((u_int32_t *)feature_buffer) = new_baudrate; 380 put_unaligned_le32(new_baudrate, feature_buffer);
379 feature_buffer[4] |= data_bits; /* assign data bits in 2 bit space ( max 3 ) */ 381 feature_buffer[4] |= data_bits; /* assign data bits in 2 bit space ( max 3 ) */
380 /* 1 bit gap */ 382 /* 1 bit gap */
381 feature_buffer[4] |= (stop_bits << 3); /* assign stop bits in 1 bit space */ 383 feature_buffer[4] |= (stop_bits << 3); /* assign stop bits in 1 bit space */
@@ -397,15 +399,15 @@ static int cypress_serial_control(struct tty_struct *tty,
397 HID_REQ_SET_REPORT, 399 HID_REQ_SET_REPORT,
398 USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS, 400 USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
399 0x0300, 0, feature_buffer, 401 0x0300, 0, feature_buffer,
400 sizeof(feature_buffer), 500); 402 feature_len, 500);
401 403
402 if (tries++ >= 3) 404 if (tries++ >= 3)
403 break; 405 break;
404 406
405 } while (retval != sizeof(feature_buffer) && 407 } while (retval != feature_len &&
406 retval != -ENODEV); 408 retval != -ENODEV);
407 409
408 if (retval != sizeof(feature_buffer)) { 410 if (retval != feature_len) {
409 dev_err(&port->dev, "%s - failed sending serial " 411 dev_err(&port->dev, "%s - failed sending serial "
410 "line settings - %d\n", __func__, retval); 412 "line settings - %d\n", __func__, retval);
411 cypress_set_dead(port); 413 cypress_set_dead(port);
@@ -425,43 +427,42 @@ static int cypress_serial_control(struct tty_struct *tty,
425 /* Not implemented for this device, 427 /* Not implemented for this device,
426 and if we try to do it we're likely 428 and if we try to do it we're likely
427 to crash the hardware. */ 429 to crash the hardware. */
428 return -ENOTTY; 430 retval = -ENOTTY;
431 goto out;
429 } 432 }
430 dbg("%s - retreiving serial line settings", __func__); 433 dbg("%s - retreiving serial line settings", __func__);
431 /* set initial values in feature buffer */
432 memset(feature_buffer, 0, sizeof(feature_buffer));
433
434 do { 434 do {
435 retval = usb_control_msg(port->serial->dev, 435 retval = usb_control_msg(port->serial->dev,
436 usb_rcvctrlpipe(port->serial->dev, 0), 436 usb_rcvctrlpipe(port->serial->dev, 0),
437 HID_REQ_GET_REPORT, 437 HID_REQ_GET_REPORT,
438 USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS, 438 USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
439 0x0300, 0, feature_buffer, 439 0x0300, 0, feature_buffer,
440 sizeof(feature_buffer), 500); 440 feature_len, 500);
441 441
442 if (tries++ >= 3) 442 if (tries++ >= 3)
443 break; 443 break;
444 } while (retval != sizeof(feature_buffer) 444 } while (retval != feature_len
445 && retval != -ENODEV); 445 && retval != -ENODEV);
446 446
447 if (retval != sizeof(feature_buffer)) { 447 if (retval != feature_len) {
448 dev_err(&port->dev, "%s - failed to retrieve serial " 448 dev_err(&port->dev, "%s - failed to retrieve serial "
449 "line settings - %d\n", __func__, retval); 449 "line settings - %d\n", __func__, retval);
450 cypress_set_dead(port); 450 cypress_set_dead(port);
451 return retval; 451 goto out;
452 } else { 452 } else {
453 spin_lock_irqsave(&priv->lock, flags); 453 spin_lock_irqsave(&priv->lock, flags);
454 /* store the config in one byte, and later 454 /* store the config in one byte, and later
455 use bit masks to check values */ 455 use bit masks to check values */
456 priv->current_config = feature_buffer[4]; 456 priv->current_config = feature_buffer[4];
457 priv->baud_rate = *((u_int32_t *)feature_buffer); 457 priv->baud_rate = get_unaligned_le32(feature_buffer);
458 spin_unlock_irqrestore(&priv->lock, flags); 458 spin_unlock_irqrestore(&priv->lock, flags);
459 } 459 }
460 } 460 }
461 spin_lock_irqsave(&priv->lock, flags); 461 spin_lock_irqsave(&priv->lock, flags);
462 ++priv->cmd_count; 462 ++priv->cmd_count;
463 spin_unlock_irqrestore(&priv->lock, flags); 463 spin_unlock_irqrestore(&priv->lock, flags);
464 464out:
465 kfree(feature_buffer);
465 return retval; 466 return retval;
466} /* cypress_serial_control */ 467} /* cypress_serial_control */
467 468
@@ -690,7 +691,6 @@ static void cypress_dtr_rts(struct usb_serial_port *port, int on)
690{ 691{
691 struct cypress_private *priv = usb_get_serial_port_data(port); 692 struct cypress_private *priv = usb_get_serial_port_data(port);
692 /* drop dtr and rts */ 693 /* drop dtr and rts */
693 priv = usb_get_serial_port_data(port);
694 spin_lock_irq(&priv->lock); 694 spin_lock_irq(&priv->lock);
695 if (on == 0) 695 if (on == 0)
696 priv->line_control = 0; 696 priv->line_control = 0;
@@ -1307,13 +1307,9 @@ static void cypress_read_int_callback(struct urb *urb)
1307 spin_unlock_irqrestore(&priv->lock, flags); 1307 spin_unlock_irqrestore(&priv->lock, flags);
1308 1308
1309 /* process read if there is data other than line status */ 1309 /* process read if there is data other than line status */
1310 if (tty && (bytes > i)) { 1310 if (tty && bytes > i) {
1311 bytes = tty_buffer_request_room(tty, bytes); 1311 tty_insert_flip_string_fixed_flag(tty, data + i,
1312 for (; i < bytes ; ++i) { 1312 bytes - i, tty_flag);
1313 dbg("pushing byte number %d - %d - %c", i, data[i],
1314 data[i]);
1315 tty_insert_flip_char(tty, data[i], tty_flag);
1316 }
1317 tty_flip_buffer_push(tty); 1313 tty_flip_buffer_push(tty);
1318 } 1314 }
1319 1315
@@ -1325,9 +1321,9 @@ static void cypress_read_int_callback(struct urb *urb)
1325continue_read: 1321continue_read:
1326 tty_kref_put(tty); 1322 tty_kref_put(tty);
1327 1323
1328 /* Continue trying to always read... unless the port has closed. */ 1324 /* Continue trying to always read */
1329 1325
1330 if (port->port.count > 0 && priv->comm_is_ok) { 1326 if (priv->comm_is_ok) {
1331 usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev, 1327 usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev,
1332 usb_rcvintpipe(port->serial->dev, 1328 usb_rcvintpipe(port->serial->dev,
1333 port->interrupt_in_endpointAddress), 1329 port->interrupt_in_endpointAddress),
@@ -1336,7 +1332,7 @@ continue_read:
1336 cypress_read_int_callback, port, 1332 cypress_read_int_callback, port,
1337 priv->read_urb_interval); 1333 priv->read_urb_interval);
1338 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); 1334 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
1339 if (result) { 1335 if (result && result != -EPERM) {
1340 dev_err(&urb->dev->dev, "%s - failed resubmitting " 1336 dev_err(&urb->dev->dev, "%s - failed resubmitting "
1341 "read urb, error %d\n", __func__, 1337 "read urb, error %d\n", __func__,
1342 result); 1338 result);
@@ -1650,3 +1646,5 @@ module_param(stats, bool, S_IRUGO | S_IWUSR);
1650MODULE_PARM_DESC(stats, "Enable statistics or not"); 1646MODULE_PARM_DESC(stats, "Enable statistics or not");
1651module_param(interval, int, S_IRUGO | S_IWUSR); 1647module_param(interval, int, S_IRUGO | S_IWUSR);
1652MODULE_PARM_DESC(interval, "Overrides interrupt interval"); 1648MODULE_PARM_DESC(interval, "Overrides interrupt interval");
1649module_param(unstable_bauds, bool, S_IRUGO | S_IWUSR);
1650MODULE_PARM_DESC(unstable_bauds, "Allow unstable baud rates");