cypress_m8: Packet format is separate from characteristic size

From: Mike Isely <[EMAIL PROTECTED]>

The Cypress app note states that when using an 8 byte packet buffer
size that the packet format is modified (to be more compact).  However
I have since discovered that newer DeLorme Earthmate LT-20 devices
(those that are low speed USB with 8 byte packet size) STILL use the
format that is really supposed to correspond to 32 byte packets.
Further confusing things is the subsequent discovery that there are
actually two different types of LT-20 - older LT-20's use 32 byte
packets which is probably why this issue wasn't originally
encountered.  The solution here is to flag the packet format
separately from the buffer size.  Then at initialization time,
identify the correct combination and set it up.  This is a critical
fix for anyone with a newer LT-20.  Older devices and non-Earthmate
devices should remain unaffected by this change.  (If other devices
behave in this, uh, unexpected manner, it's now just a simple 1 line
change to fix them as well (change the pkt_fmt member for that
device).  Default behavior with this patch is still to drive the
format as per the app-note; of course for Earthmate devices this is
overridden.

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

---
 cypress_m8.c |   58 +++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 39 insertions(+), 19 deletions(-)

---

diff -uprN -X linux-2.6.23.12-vanilla/Documentation/dontdiff 
cypress_patch_01_feature_buffer_hardcoded/drivers/usb/serial/cypress_m8.c 
cypress_patch_02_pkt_fmt/drivers/usb/serial/cypress_m8.c
--- cypress_patch_01_feature_buffer_hardcoded/drivers/usb/serial/cypress_m8.c   
2008-02-10 19:35:27.000000000 -0600
+++ cypress_patch_02_pkt_fmt/drivers/usb/serial/cypress_m8.c    2008-02-10 
19:36:51.000000000 -0600
@@ -120,6 +120,11 @@ static struct usb_driver cypress_driver 
        .no_dynamic_id =        1,
 };
 
+enum packet_format {
+       packet_format_1,  /* b0:status, b1:payload count */
+       packet_format_2   /* b0[7:3]:status, b0[2:0]:payload count */
+};
+
 struct cypress_private {
        spinlock_t lock;                   /* private lock */
        int chiptype;                      /* identifier of device, for 
quirks/etc */
@@ -137,6 +142,7 @@ struct cypress_private {
        __u8 current_status;               /* received from last read - info on 
dsr,cts,cd,ri,etc */
        __u8 current_config;               /* stores the current configuration 
byte */
        __u8 rx_flags;                     /* throttling - used from 
whiteheat/ftdi_sio */
+       enum packet_format pkt_fmt;        /* format to use for packet send / 
receive */
        int baud_rate;                     /* stores current baud rate in 
integer form */
        int cbr_mask;                      /* stores current baud rate in 
masked form */
        int isthrottled;                   /* if throttled, discard reads */
@@ -522,6 +528,17 @@ static int generic_startup (struct usb_s
        priv->termios_initialized = 0;
        priv->rx_flags = 0;
        priv->cbr_mask = B300;
+       /* Default packet format setting is determined by packet size.
+          Anything with a size larger then 9 must have a separate
+          count field since the 3 bit count field is otherwise too
+          small.  Otherwise we can use the slightly more compact
+          format.  This is in accordance with the cypress_m8 serial
+          converter app note. */
+       if (port->interrupt_out_size > 9) {
+               priv->pkt_fmt = packet_format_1;
+       } else {
+               priv->pkt_fmt = packet_format_2;
+       }
        if (interval > 0) {
                priv->write_urb_interval = interval;
                priv->read_urb_interval = interval;
@@ -554,6 +571,9 @@ static int cypress_earthmate_startup (st
 
        priv = usb_get_serial_port_data(serial->port[0]);
        priv->chiptype = CT_EARTHMATE;
+       /* All Earthmate devices use the separated-count packet
+          format!  Idiotic. */
+       priv->pkt_fmt = packet_format_1;
 
        return 0;
 } /* cypress_earthmate_startup */
@@ -794,21 +814,18 @@ static void cypress_send(struct usb_seri
        memset(port->interrupt_out_urb->transfer_buffer, 0, 
port->interrupt_out_size);
 
        spin_lock_irqsave(&priv->lock, flags);
-       switch (port->interrupt_out_size) {
-               case 32:
+       switch (priv->pkt_fmt) {
+               default:
+               case packet_format_1:
                        /* this is for the CY7C64013... */
                        offset = 2;
                        port->interrupt_out_buffer[0] = priv->line_control;
                        break;
-               case 8:
+               case packet_format_2:
                        /* this is for the CY7C63743... */
                        offset = 1;
                        port->interrupt_out_buffer[0] = priv->line_control;
                        break;
-               default:
-                       dbg("%s - wrong packet size", __FUNCTION__);
-                       spin_unlock_irqrestore(&priv->lock, flags);
-                       return;
        }
 
        if (priv->line_control & CONTROL_RESET)
@@ -829,11 +846,12 @@ static void cypress_send(struct usb_seri
                return;
        }
 
-       switch (port->interrupt_out_size) {
-               case 32:
+       switch (priv->pkt_fmt) {
+               default:
+               case packet_format_1:
                        port->interrupt_out_buffer[1] = count;
                        break;
-               case 8:
+               case packet_format_2:
                        port->interrupt_out_buffer[0] |= count;
        }
 
@@ -847,7 +865,7 @@ send:
        if (priv->cmd_ctrl)
                actual_size = 1;
        else
-               actual_size = count + (port->interrupt_out_size == 32 ? 2 : 1);
+               actual_size = count + (priv->pkt_fmt == packet_format_1 ? 2 : 
1);
        
        usb_serial_debug_data(debug, &port->dev, __FUNCTION__, 
port->interrupt_out_size,
                              port->interrupt_out_urb->transfer_buffer);
@@ -1314,8 +1332,10 @@ static void cypress_read_int_callback(st
        }
 
        spin_lock_irqsave(&priv->lock, flags);
-       switch(urb->actual_length) {
-               case 32:
+       result = urb->actual_length;
+       switch(priv->pkt_fmt) {
+               default:
+               case packet_format_1:
                        /* This is for the CY7C64013... */
                        priv->current_status = data[0] & 0xF8;
                        bytes = data[1] + 2;
@@ -1323,7 +1343,7 @@ static void cypress_read_int_callback(st
                        if (bytes > 2)
                                havedata = 1;
                        break;
-               case 8:
+               case packet_format_2:
                        /* This is for the CY7C63743... */
                        priv->current_status = data[0] & 0xF8;
                        bytes = (data[0] & 0x07) + 1;
@@ -1331,13 +1351,13 @@ static void cypress_read_int_callback(st
                        if (bytes > 1)
                                havedata = 1;
                        break;
-               default:
-                       dbg("%s - wrong packet size - received %d bytes",
-                                       __FUNCTION__, urb->actual_length);
-                       spin_unlock_irqrestore(&priv->lock, flags);
-                       goto continue_read;
        }
        spin_unlock_irqrestore(&priv->lock, flags);
+       if (result < bytes) {
+               dbg("%s - wrong packet size - received %d bytes but packet said 
%d bytes",
+                   __FUNCTION__, result,bytes);
+               goto continue_read;
+       }
 
        usb_serial_debug_data (debug, &port->dev, __FUNCTION__,
                        urb->actual_length, data);

-- 
                        |         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