diff options
Diffstat (limited to 'drivers/usb/serial/cypress_m8.c')
-rw-r--r-- | drivers/usb/serial/cypress_m8.c | 84 |
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 | 74 | static int debug; |
74 | static int debug = 1; | ||
75 | #else | ||
76 | static int debug; | ||
77 | #endif | ||
78 | static int stats; | 75 | static int stats; |
79 | static int interval; | 76 | static int interval; |
77 | static 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 | ||
92 | static struct usb_device_id id_table_earthmate [] = { | 90 | static 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 | ||
98 | static struct usb_device_id id_table_cyphidcomrs232 [] = { | 96 | static 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 | ||
104 | static struct usb_device_id id_table_nokiaca42v2 [] = { | 102 | static 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 | ||
109 | static struct usb_device_id id_table_combined [] = { | 107 | static 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 | 464 | out: | |
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) | |||
1325 | continue_read: | 1321 | continue_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); | |||
1650 | MODULE_PARM_DESC(stats, "Enable statistics or not"); | 1646 | MODULE_PARM_DESC(stats, "Enable statistics or not"); |
1651 | module_param(interval, int, S_IRUGO | S_IWUSR); | 1647 | module_param(interval, int, S_IRUGO | S_IWUSR); |
1652 | MODULE_PARM_DESC(interval, "Overrides interrupt interval"); | 1648 | MODULE_PARM_DESC(interval, "Overrides interrupt interval"); |
1649 | module_param(unstable_bauds, bool, S_IRUGO | S_IWUSR); | ||
1650 | MODULE_PARM_DESC(unstable_bauds, "Allow unstable baud rates"); | ||