ChangeSet 1.1439, 2003/10/03 16:22:11-07:00, [EMAIL PROTECTED]

[PATCH] USB: port keyspan patch from 2.4 to 2.6

Original patch from [EMAIL PROTECTED]

Changes include:
     Add support for new USA19H(s) USB Serial Adapter
     Improve handing of config/control messages for all devices

Note that the new adapter doesn't currently require a firmware download.
We will add support for re-programming the eeprom with updated firmware
when new firmware is  required.


 drivers/usb/serial/keyspan.c          |  420 ++++++++++++++++++++++++++++++++--
 drivers/usb/serial/keyspan.h          |   33 ++
 drivers/usb/serial/keyspan_usa90msg.h |  198 ++++++++++++++++
 3 files changed, 625 insertions(+), 26 deletions(-)


diff -Nru a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
--- a/drivers/usb/serial/keyspan.c      Fri Oct  3 16:43:54 2003
+++ b/drivers/usb/serial/keyspan.c      Fri Oct  3 16:43:55 2003
@@ -28,6 +28,9 @@
 
   Change History
 
+    2003sep04  LPM (Keyspan) add support for new single port product USA19HS.
+                               Improve setup message handling for all devices.
+
     Wed Feb 19 22:00:00 PST 2003 (Jeffrey S. Laing <[EMAIL PROTECTED]>)
       Merged the current (1/31/03) Keyspan code with the current (2.4.21-pre4)
       Linux source tree.  The Linux tree lacked support for the 49WLC and
@@ -172,6 +175,7 @@
        int             baud;
        int             old_baud;
        unsigned int    cflag;
+       unsigned int    old_cflag;
        enum            {flow_none, flow_cts, flow_xon} flow_control;
        int             rts_state;      /* Handshaking pins (outputs) */
        int             dtr_state;
@@ -187,11 +191,12 @@
 
        
 /* Include Keyspan message headers.  All current Keyspan Adapters
-   make use of one of three message formats which are referred
-   to as USA-26, USA-28 and USA-49 by Keyspan and within this driver. */
+   make use of one of four message formats which are referred
+   to as USA-26, USA-28 and USA-49, USA-90 by Keyspan and within this driver. */
 #include "keyspan_usa26msg.h"
 #include "keyspan_usa28msg.h"
 #include "keyspan_usa49msg.h"
+#include "keyspan_usa90msg.h"
        
 
 /* Functions used by new usb-serial code. */
@@ -346,8 +351,8 @@
        return -ENOIOCTLCMD;
 }
 
-       /* Write function is generic for the three protocols used
-          with only a minor change for usa49 required */
+       /* Write function is similar for the four protocols used
+          with only a minor change for usa90 (usa19hs) required */
 static int keyspan_write(struct usb_serial_port *port, int from_user, 
                         const unsigned char *buf, int count)
 {
@@ -356,18 +361,26 @@
        int                             flip;
        int                             left, todo;
        struct urb                      *this_urb;
-       int                             err;
+       int                             err, maxDataLen, dataOffset;
 
        p_priv = usb_get_serial_port_data(port);
        d_details = p_priv->device_details;
 
+       if (d_details->msg_format == msg_usa90) {
+               maxDataLen = 64;
+               dataOffset = 0;
+       } else {
+               maxDataLen = 63;
+               dataOffset = 1;
+       }
+       
        dbg("%s - for port %d (%d chars), flip=%d",
            __FUNCTION__, port->number, count, p_priv->out_flip);
 
        for (left = count; left > 0; left -= todo) {
                todo = left;
-               if (todo > 63)
-                       todo = 63;
+               if (todo > maxDataLen)
+                       todo = maxDataLen;
 
                flip = p_priv->out_flip;
        
@@ -390,20 +403,20 @@
                        break;
                }
 
-               /* First byte in buffer is "last flag" - unused so
+               /* First byte in buffer is "last flag" (except for usa19hx) - unused so
                   for now so set to zero */
                ((char *)this_urb->transfer_buffer)[0] = 0;
 
                if (from_user) {
-                       if (copy_from_user(this_urb->transfer_buffer + 1, buf, todo))
+                       if (copy_from_user(this_urb->transfer_buffer + dataOffset, 
buf, todo))
                                return -EFAULT;
                } else {
-                       memcpy (this_urb->transfer_buffer + 1, buf, todo);
+                       memcpy (this_urb->transfer_buffer + dataOffset, buf, todo);
                }
                buf += todo;
 
                /* send the data out the bulk port */
-               this_urb->transfer_buffer_length = todo + 1;
+               this_urb->transfer_buffer_length = todo + dataOffset;
 
                this_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
                this_urb->dev = port->serial->dev;
@@ -443,9 +456,12 @@
        if (urb->actual_length) {
                /* 0x80 bit is error flag */
                if ((data[0] & 0x80) == 0) {
-                       /* no error on any byte */
+                       /* no errors on individual bytes, only possible overrun err*/
+                       if (data[0] & RXERROR_OVERRUN)
+                                       err = TTY_OVERRUN;
+                       else err = 0;
                        for (i = 1; i < urb->actual_length ; ++i) {
-                               tty_insert_flip_char(tty, data[i], 0);
+                               tty_insert_flip_char(tty, data[i], err);
                        }
                } else {
                        /* some bytes had errors, every byte has status */
@@ -474,7 +490,7 @@
        return;
 }
 
-       /* Outdat handling is common for usa26, usa28 and usa49 messages */
+       /* Outdat handling is common for all devices */
 static void    usa2x_outdat_callback(struct urb *urb, struct pt_regs *regs)
 {
        struct usb_serial_port *port;
@@ -577,7 +593,7 @@
 }
 
 
-static void     usa28_indat_callback(struct urb *urb, struct pt_regs *regs)
+static void usa28_indat_callback(struct urb *urb, struct pt_regs *regs)
 {
        int                     i, err;
        struct usb_serial_port  *port;
@@ -861,29 +877,172 @@
        dbg ("%s", __FUNCTION__);
 }
 
+static void    usa90_indat_callback(struct urb *urb, struct pt_regs *regs)
+{
+       int                     i, err;
+       int                     endpoint;
+       struct usb_serial_port  *port;
+       struct keyspan_port_private             *p_priv;
+       struct tty_struct       *tty;
+       unsigned char           *data = urb->transfer_buffer;
+
+       dbg ("%s", __FUNCTION__); 
+
+       endpoint = usb_pipeendpoint(urb->pipe);
+
 
+       if (urb->status) {
+               dbg("%s - nonzero status: %x on endpoint %d.",
+                   __FUNCTION__, urb->status, endpoint);
+               return;
+       }
+
+       port = (struct usb_serial_port *) urb->context;
+       p_priv = usb_get_serial_port_data(port);
+
+       tty = port->tty;
+       if (urb->actual_length) {
+       
+               /* if current mode is DMA, looks like usa28 format
+                       otherwise looks like usa26 data format */
+
+               if (p_priv->baud > 57600) {
+                       for (i = 0; i < urb->actual_length ; ++i) 
+                               tty_insert_flip_char(tty, data[i], 0);
+               }
+               else {
+                       
+                       /* 0x80 bit is error flag */
+                       if ((data[0] & 0x80) == 0) {
+                               /* no errors on individual bytes, only possible 
overrun err*/
+                               if (data[0] & RXERROR_OVERRUN)
+                                               err = TTY_OVERRUN;
+                               else err = 0;
+                               for (i = 1; i < urb->actual_length ; ++i) 
+                                       tty_insert_flip_char(tty, data[i], err);
+                       
+                       } 
+                       else {
+                       /* some bytes had errors, every byte has status */
+                               dbg("%s - RX error!!!!", __FUNCTION__);
+                               for (i = 0; i + 1 < urb->actual_length; i += 2) {
+                                       int stat = data[i], flag = 0;
+                                       if (stat & RXERROR_OVERRUN)
+                                               flag |= TTY_OVERRUN;
+                                       if (stat & RXERROR_FRAMING)
+                                               flag |= TTY_FRAME;
+                                       if (stat & RXERROR_PARITY)
+                                               flag |= TTY_PARITY;
+                                       /* XXX should handle break (0x10) */
+                                       tty_insert_flip_char(tty, data[i+1], flag);
+                               }
+                       }
+               }
+               tty_flip_buffer_push(tty);
+       }
+                               
+       /* Resubmit urb so we continue receiving */
+       urb->dev = port->serial->dev;
+       if (port->open_count)
+               if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+                       dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
+               }
+       return;
+}
+
+
+static void    usa90_instat_callback(struct urb *urb, struct pt_regs *regs)
+{
+       unsigned char                           *data = urb->transfer_buffer;
+       struct keyspan_usa90_portStatusMessage  *msg;
+       struct usb_serial                       *serial;
+       struct usb_serial_port                  *port;
+       struct keyspan_port_private             *p_priv;
+       int old_dcd_state, err;
+
+       serial = (struct usb_serial *) urb->context;
+
+       if (urb->status) {
+               dbg("%s - nonzero status: %x", __FUNCTION__, urb->status);
+               return;
+       }
+       if (urb->actual_length < 14) {
+               dbg("%s - %d byte report??", __FUNCTION__, urb->actual_length);
+               goto exit;
+       }
+
+       msg = (struct keyspan_usa90_portStatusMessage *)data;
+
+       /* Now do something useful with the data */
+
+       port = serial->port[0];
+       p_priv = usb_get_serial_port_data(port);
+       
+       /* Update handshaking pin state information */
+       old_dcd_state = p_priv->dcd_state;
+       p_priv->cts_state = ((msg->cts) ? 1 : 0);
+       p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
+       p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
+       p_priv->ri_state = ((msg->ri) ? 1 : 0);
+
+       if (port->tty && !C_CLOCAL(port->tty)
+           && old_dcd_state != p_priv->dcd_state) {
+               if (old_dcd_state)
+                       tty_hangup(port->tty);
+               /*  else */
+               /*      wake_up_interruptible(&p_priv->open_wait); */
+       }
+       
+       /* Resubmit urb so we continue receiving */
+       urb->dev = serial->dev;
+       if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+               dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
+       }
+exit:
+       ;
+}
+
+static void    usa90_outcont_callback(struct urb *urb, struct pt_regs *regs)
+{
+       struct usb_serial_port *port;
+       struct keyspan_port_private *p_priv;
+
+       port = (struct usb_serial_port *) urb->context;
+       p_priv = usb_get_serial_port_data(port);
+
+       if (p_priv->resend_cont) {
+               dbg ("%s - sending setup", __FUNCTION__); 
+               keyspan_usa90_send_setup(port->serial, port, p_priv->resend_cont - 1);
+       }
+}
 
 static int keyspan_write_room (struct usb_serial_port *port)
 {
        struct keyspan_port_private     *p_priv;
        const struct keyspan_device_details     *d_details;
        int                             flip;
+       int                             data_len;
        struct urb                      *this_urb;
 
        dbg("%s", __FUNCTION__);
        p_priv = usb_get_serial_port_data(port);
        d_details = p_priv->device_details;
 
+       if (d_details->msg_format == msg_usa90)
+               data_len = 64;
+       else
+               data_len = 63;
+
        flip = p_priv->out_flip;
 
        /* Check both endpoints to see if any are available. */
        if ((this_urb = p_priv->out_urbs[flip]) != 0) {
                if (this_urb->status != -EINPROGRESS)
-                       return (63);
+                       return (data_len);
                flip = (flip + 1) & d_details->outdat_endp_flip;        
                if ((this_urb = p_priv->out_urbs[flip]) != 0) 
                        if (this_urb->status != -EINPROGRESS)
-                               return (63);
+                               return (data_len);
        }
        return (0);
 }
@@ -902,17 +1061,24 @@
        struct usb_serial               *serial = port->serial;
        const struct keyspan_device_details     *d_details;
        int                             i, err;
+       int                             baud_rate, device_port;
        struct urb                      *urb;
+       unsigned int                    cflag;
 
        s_priv = usb_get_serial_data(serial);
        p_priv = usb_get_serial_port_data(port);
-       d_details = s_priv->device_details;
+       d_details = p_priv->device_details;
        
        dbg("%s - port%d.", __FUNCTION__, port->number); 
 
        /* Set some sane defaults */
        p_priv->rts_state = 1;
        p_priv->dtr_state = 1;
+       p_priv->baud = 9600;
+
+       /* force baud and lcr to be set on open */
+       p_priv->old_baud = 0;
+       p_priv->old_cflag = 0;
 
        p_priv->out_flip = 0;
        p_priv->in_flip = 0;
@@ -922,7 +1088,10 @@
                if ((urb = p_priv->in_urbs[i]) == NULL)
                        continue;
                urb->dev = serial->dev;
-               usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), 
usb_pipeout(urb->pipe), 0);
+
+               /* make sure endpoint data toggle is synchronized with the device */
+               
+               usb_clear_halt(urb->dev, urb->pipe);
 
                if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
                        dbg("%s - submit urb %d failed (%d)", __FUNCTION__, i, err);
@@ -937,12 +1106,29 @@
                /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), 
usb_pipeout(urb->pipe), 0); */
        }
 
-       // if the device is a USA49x, determine whether it is an W or WLC model
-       // and set the baud clock accordingly
+       /* get the terminal config for the setup message now so we don't 
+        * need to send 2 of them */
+
+       cflag = port->tty->termios->c_cflag;
+       device_port = port->number - port->serial->minor;
+
+       /* Baud rate calculation takes baud rate as an integer
+          so other rates can be generated if desired. */
+       baud_rate = tty_get_baud_rate(port->tty);
+       /* If no match or invalid, leave as default */          
+       if (baud_rate >= 0
+           && d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
+                               NULL, NULL, NULL, device_port) == 
KEYSPAN_BAUD_RATE_OK) {
+               p_priv->baud = baud_rate;
+       }
+
+       /* set CTS/RTS handshake etc. */
+       p_priv->cflag = cflag;
+       p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none;
 
        keyspan_send_setup(port, 1);
        //mdelay(100);
-       keyspan_set_termios(port, NULL);
+       //keyspan_set_termios(port, NULL);
 
        return (0);
 }
@@ -977,7 +1163,7 @@
                keyspan_send_setup(port, 2);
                /* pilot-xfer seems to work best with this delay */
                mdelay(100);
-               keyspan_set_termios(port, NULL);
+               // keyspan_set_termios(port, NULL);
        }
 
        /*while (p_priv->outcont_urb->status == -EINPROGRESS) {
@@ -1172,6 +1358,14 @@
                .outdat_callback =      usa2x_outdat_callback,
                .inack_callback =       usa49_inack_callback,
                .outcont_callback =     usa49_outcont_callback,
+       }, {
+               /* msg_usa90 callbacks */
+               .instat_callback =      usa90_instat_callback,
+               .glocont_callback =     usa28_glocont_callback,         
+               .indat_callback =       usa90_indat_callback,
+               .outdat_callback =      usa2x_outdat_callback,
+               .inack_callback =       usa28_inack_callback,
+               .outcont_callback =     usa90_outcont_callback,
        }
 };
 
@@ -1295,6 +1489,41 @@
        return (KEYSPAN_BAUD_RATE_OK);
 }
 
+/* usa19hs function doesn't require prescaler */
+static int keyspan_usa19hs_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
+                                  u8 *rate_low, u8 *prescaler, int portnum)
+{
+       u32     b16,    /* baud rate times 16 (actual rate used internally) */
+                       div;    /* divisor */   
+               
+       dbg ("%s - %d.", __FUNCTION__, baud_rate);
+
+               /* prevent divide by zero...  */
+       if( (b16 = (baud_rate * 16L)) == 0) 
+               return (KEYSPAN_INVALID_BAUD_RATE);
+       
+
+
+               /* calculate the divisor */
+       if( (div = (baudclk / b16)) == 0) 
+               return (KEYSPAN_INVALID_BAUD_RATE);
+
+       if(div > 0xffff) 
+               return (KEYSPAN_INVALID_BAUD_RATE);
+
+               /* return the counter values if non-null */
+       if (rate_low) 
+               *rate_low = (u8) (div & 0xff);
+       
+       if (rate_hi) 
+               *rate_hi = (u8) ((div >> 8) & 0xff);
+       
+       if (rate_low && rate_hi) 
+               dbg ("%s - %d %02x %02x.", __FUNCTION__, baud_rate, *rate_hi, 
*rate_low);
+       
+       return (KEYSPAN_BAUD_RATE_OK);
+}
+
 static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
                                    u8 *rate_low, u8 *prescaler, int portnum)
 {
@@ -1447,6 +1676,7 @@
                p_priv->resend_cont = reset_port + 1;
        if (this_urb->status == -EINPROGRESS) {
                /*  dbg ("%s - already writing", __FUNCTION__); */
+               mdelay(5);
                return(-1);
        }
 
@@ -1597,6 +1827,7 @@
                p_priv->resend_cont = reset_port + 1;
        if (this_urb->status == -EINPROGRESS) {
                dbg ("%s already writing", __FUNCTION__);
+               mdelay(5);
                return(-1);
        }
 
@@ -1729,6 +1960,7 @@
                p_priv->resend_cont = reset_port + 1;
        if (this_urb->status == -EINPROGRESS) {
                /*  dbg ("%s - already writing", __FUNCTION__); */
+               mdelay(5);
                return(-1);
        }
 
@@ -1857,6 +2089,144 @@
        return (0);
 }
 
+static int keyspan_usa90_send_setup(struct usb_serial *serial,
+                                   struct usb_serial_port *port,
+                                   int reset_port)
+{
+       struct keyspan_usa90_portControlMessage msg;            
+       struct keyspan_serial_private           *s_priv;
+       struct keyspan_port_private             *p_priv;
+       const struct keyspan_device_details     *d_details;
+       struct urb                              *this_urb;
+       int                                     err;
+       u8                                              prescaler;
+
+       dbg ("%s", __FUNCTION__);
+
+       s_priv = usb_get_serial_data(serial);
+       p_priv = usb_get_serial_port_data(port);
+       d_details = s_priv->device_details;
+
+       /* only do something if we have a bulk out endpoint */
+       if ((this_urb = p_priv->outcont_urb) == NULL) {
+               dbg("%s - oops no urb.", __FUNCTION__);
+               return -1;
+       }
+
+       /* Save reset port val for resend.
+          Don't overwrite resend for open/close condition. */
+       if ((reset_port + 1) > p_priv->resend_cont)
+               p_priv->resend_cont = reset_port + 1;
+       if (this_urb->status == -EINPROGRESS) {
+               dbg ("%s already writing", __FUNCTION__);
+               mdelay(5);
+               return(-1);
+       }
+
+       memset(&msg, 0, sizeof (struct keyspan_usa90_portControlMessage));
+
+       /* Only set baud rate if it's changed */        
+       if (p_priv->old_baud != p_priv->baud) {
+               p_priv->old_baud = p_priv->baud;
+               msg.setClocking = 0x01;
+               if (d_details->calculate_baud_rate
+                   (p_priv->baud, d_details->baudclk, &msg.baudHi,
+                    &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE ) {
+                       dbg("%s - Invalid baud rate %d requested, using 9600.", 
__FUNCTION__,
+                           p_priv->baud);
+                       p_priv->baud = 9600;
+                       d_details->calculate_baud_rate (p_priv->baud, 
d_details->baudclk, 
+                               &msg.baudHi, &msg.baudLo, &prescaler, 0);
+               }
+               msg.setRxMode = 1;
+               msg.setTxMode = 1;
+       }
+
+       /* modes must always be correctly specified */
+       if (p_priv->baud > 57600)
+       {
+               msg.rxMode = RXMODE_DMA;
+               msg.txMode = TXMODE_DMA;
+       }
+       else
+       {
+               msg.rxMode = RXMODE_BYHAND;
+               msg.txMode = TXMODE_BYHAND;
+       }
+
+       msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
+       switch (p_priv->cflag & CSIZE) {
+       case CS5:
+               msg.lcr |= USA_DATABITS_5;
+               break;
+       case CS6:
+               msg.lcr |= USA_DATABITS_6;
+               break;
+       case CS7:
+               msg.lcr |= USA_DATABITS_7;
+               break;
+       case CS8:
+               msg.lcr |= USA_DATABITS_8;
+               break;
+       }
+       if (p_priv->cflag & PARENB) {
+               /* note USA_PARITY_NONE == 0 */
+               msg.lcr |= (p_priv->cflag & PARODD)?
+                       USA_PARITY_ODD: USA_PARITY_EVEN;
+       }
+       if (p_priv->old_cflag != p_priv->cflag) {
+               p_priv->old_cflag = p_priv->cflag;
+               msg.setLcr = 0x01;
+       }
+
+       if (p_priv->flow_control == flow_cts)
+               msg.txFlowControl = TXFLOW_CTS;
+       msg.setTxFlowControl = 0x01;
+       msg.setRxFlowControl = 0x01;
+       
+       msg.rxForwardingLength = 16;
+       msg.rxForwardingTimeout = 16;   
+       msg.txAckSetting = 0;
+       msg.xonChar = 17;
+       msg.xoffChar = 19;
+
+       /* Opening port */ 
+       if (reset_port == 1) {
+               msg.portEnabled = 1;
+               msg.rxFlush = 1;
+               msg.txBreak = (p_priv->break_on);
+       }
+       /* Closing port */
+       else if (reset_port == 2) {
+               msg.portEnabled = 0;
+       }
+       /* Sending intermediate configs */
+       else {
+               if (port->open_count)
+                       msg.portEnabled = 1;
+               msg.txBreak = (p_priv->break_on);
+       }
+
+       /* Do handshaking outputs */    
+       msg.setRts = 0x01;
+       msg.rts = p_priv->rts_state;
+
+       msg.setDtr = 0x01;
+       msg.dtr = p_priv->dtr_state;
+               
+       p_priv->resend_cont = 0;
+       memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
+       
+       /* send the data out the device on control endpoint */
+       this_urb->transfer_buffer_length = sizeof(msg);
+
+       this_urb->dev = serial->dev;
+       if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+               dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__, err);
+       }
+       return (0);
+}
+
 static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
 {
        struct usb_serial *serial = port->serial;
@@ -1878,8 +2248,12 @@
        case msg_usa49:
                keyspan_usa49_send_setup(serial, port, reset_port);
                break;
+       case msg_usa90:
+               keyspan_usa90_send_setup(serial, port, reset_port);
+               break;
        }
 }
+
 
 /* Gets called by the "real" driver (ie once firmware is loaded
    and renumeration has taken place. */
diff -Nru a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
--- a/drivers/usb/serial/keyspan.h      Fri Oct  3 16:43:55 2003
+++ b/drivers/usb/serial/keyspan.h      Fri Oct  3 16:43:55 2003
@@ -82,6 +82,10 @@
                                         u8 *rate_hi, u8 *rate_low,
                                         u8 *prescaler, int portnum);
 
+static int  keyspan_usa19hs_calc_baud  (u32 baud_rate, u32 baudclk,
+                                        u8 *rate_hi, u8 *rate_low,
+                                        u8 *prescaler, int portnum);
+
 static int  keyspan_usa28_send_setup   (struct usb_serial *serial,
                                         struct usb_serial_port *port,
                                         int reset_port);
@@ -92,6 +96,9 @@
                                         struct usb_serial_port *port,
                                         int reset_port);
 
+static int  keyspan_usa90_send_setup   (struct usb_serial *serial,
+                                        struct usb_serial_port *port,
+                                        int reset_port);
 
 /* Struct used for firmware - increased size of data section
    to allow Keyspan's 'C' firmware struct to be used unmodified */
@@ -183,6 +190,7 @@
 #define        KEYSPAN_USA18X_BAUDCLK                  (12000000L)     /* a guess */
 #define        KEYSPAN_USA19_BAUDCLK                   (12000000L)
 #define        KEYSPAN_USA19W_BAUDCLK                  (24000000L)
+#define        KEYSPAN_USA19HS_BAUDCLK                 (14769231L)
 #define        KEYSPAN_USA28_BAUDCLK                   (1843200L)
 #define        KEYSPAN_USA28X_BAUDCLK                  (12000000L)
 #define        KEYSPAN_USA49W_BAUDCLK                  (48000000L)
@@ -215,6 +223,7 @@
 #define        keyspan_usa18x_product_id               0x0112
 #define        keyspan_usa19_product_id                0x0107
 #define        keyspan_usa19qi_product_id              0x010c
+#define        keyspan_usa19hs_product_id              0x0121
 #define        keyspan_mpr_product_id                  0x011c
 #define        keyspan_usa19qw_product_id              0x0119
 #define        keyspan_usa19w_product_id               0x0108
@@ -230,7 +239,7 @@
        /* product ID value */
        int     product_id;
 
-       enum    {msg_usa26, msg_usa28, msg_usa49} msg_format;
+       enum    {msg_usa26, msg_usa28, msg_usa49, msg_usa90} msg_format;
 
                /* Number of physical ports */
        int     num_ports;
@@ -349,6 +358,22 @@
        .baudclk                = KEYSPAN_USA19W_BAUDCLK,
 };
 
+static const struct keyspan_device_details usa19hs_device_details = {
+       product_id:             keyspan_usa19hs_product_id,
+       msg_format:             msg_usa90,
+       num_ports:              1,
+       indat_endp_flip:        0,
+       outdat_endp_flip:       0,
+       indat_endpoints:        {0x81},
+       outdat_endpoints:       {0x01},
+       inack_endpoints:        {-1},
+       outcont_endpoints:      {0x02},
+       instat_endpoint:        0x82,
+       glocont_endpoint:       -1,
+       calculate_baud_rate:    keyspan_usa19hs_calc_baud,
+       baudclk:                KEYSPAN_USA19HS_BAUDCLK,
+};
+
 static const struct keyspan_device_details usa28_device_details = {
        .product_id             = keyspan_usa28_product_id,
        .msg_format             = msg_usa28,
@@ -437,6 +462,7 @@
        &usa19qi_device_details,
        &usa19qw_device_details,
        &usa19w_device_details,
+       &usa19hs_device_details,
        &usa28_device_details,
        &usa28x_device_details,
        &usa28xa_device_details,
@@ -464,6 +490,7 @@
        { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19w_product_id) },
        { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_product_id) },
        { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qw_product_id) },
+       { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19hs_product_id) },
        { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_mpr_product_id) },
        { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
        { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
@@ -544,8 +571,8 @@
        .short_name             = "keyspan_1",
        .id_table               = keyspan_1port_ids,
        .num_interrupt_in       = NUM_DONT_CARE,
-       .num_bulk_in            = 3,
-       .num_bulk_out           = 4,
+       .num_bulk_in            = NUM_DONT_CARE,
+       .num_bulk_out           = NUM_DONT_CARE,
        .num_ports              = 1,
        .open                   = keyspan_open,
        .close                  = keyspan_close,
diff -Nru a/drivers/usb/serial/keyspan_usa90msg.h 
b/drivers/usb/serial/keyspan_usa90msg.h
--- /dev/null   Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/serial/keyspan_usa90msg.h     Fri Oct  3 16:43:55 2003
@@ -0,0 +1,198 @@
+/*
+       usa90msg.h
+
+       Copyright (c) 1998-2003 InnoSys Incorporated.  All Rights Reserved
+       This file is available under a BSD-style copyright
+
+       Keyspan USB Async Message Formats for the USA19HS
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+
+       1. Redistributions of source code must retain this licence text
+       without modification, this list of conditions, and the following
+       disclaimer.  The following copyright notice must appear immediately at
+       the beginning of all source files:
+
+               Copyright (c) 1998-2003 InnoSys Incorporated.  All Rights Reserved
+
+               This file is available under a BSD-style copyright
+
+       2. The name of InnoSys Incorprated may not be used to endorse or promote
+       products derived from this software without specific prior written
+       permission.
+
+       THIS SOFTWARE IS PROVIDED BY INNOSYS CORP. ``AS IS'' AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+       OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+       NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+       INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+       (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+       SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+       CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+       LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+       OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+       SUCH DAMAGE.    
+
+       Revisions:
+
+       2003feb14               add setTxMode/txMode  and cancelRxXoff to portControl
+       2003mar21               change name of PARITY_0/1 to add MARK/SPACE
+*/
+
+#ifndef        __USA90MSG__
+#define        __USA90MSG__
+
+struct keyspan_usa90_portControlMessage
+{
+       /*
+               there are three types of "commands" sent in the control message:
+
+               1.      configuration changes which must be requested by setting
+                       the corresponding "set" flag (and should only be requested
+                       when necessary, to reduce overhead on the device):
+       */
+
+       u8      setClocking,    // host requests baud rate be set
+               baudLo,                 // host does baud divisor calculation
+               baudHi,                 // host does baud divisor calculation 
+               
+               setLcr,                 // host requests lcr be set
+               lcr,                    // use PARITY, STOPBITS, DATABITS below
+               
+               setRxMode,              // set receive mode
+               rxMode,                 // RXMODE_DMA or RXMODE_BYHAND
+
+               setTxMode,              // set transmit mode
+               txMode,                 // TXMODE_DMA or TXMODE_BYHAND
+
+               setTxFlowControl,       // host requests tx flow control be set
+               txFlowControl   ,       // use TX_FLOW... bits below
+               setRxFlowControl,       // host requests rx flow control be set
+               rxFlowControl,  // use RX_FLOW... bits below
+               sendXoff,               // host requests XOFF transmitted immediately
+               sendXon,                // host requests XON char transmitted
+               xonChar,                // specified in current character format
+               xoffChar,               // specified in current character format
+
+               sendChar,               // host requests char transmitted immediately
+               txChar,                 // character to send
+
+               setRts,                 // host requests RTS output be set
+               rts,                    // 1=on, 0=off
+               setDtr,                 // host requests DTR output be set
+               dtr;                    // 1=on, 0=off
+
+       
+       /*
+               2.      configuration data which is simply used as is 
+                       and must be specified correctly in every host message.
+       */
+
+       u8      rxForwardingLength,  // forward when this number of chars available
+               rxForwardingTimeout, // (1-31 in ms)
+               txAckSetting;      // 0=don't ack, 1=normal, 2-255 TBD...
+       /*
+               3.      Firmware states which cause actions if they change             
                         
+               and must be specified correctly in every host message.
+       */
+
+       u8      portEnabled,    // 0=disabled, 1=enabled
+               txFlush,                // 0=normal, 1=toss outbound data
+               txBreak,                // 0=break off, 1=break on
+               loopbackMode;   // 0=no loopback, 1=loopback enabled
+
+       /*
+               4.      commands which are flags only; these are processed in order
+                       (so that, e.g., if rxFlush and rxForward flags are set, the
+                       port will have no data to forward); any non-zero value 
+                       is respected
+       */
+
+       u8      rxFlush,                // toss inbound data
+               rxForward,              // forward all inbound data, NOW (as if 
fwdLen==1)
+               cancelRxXoff,   // cancel any receive XOFF state (_txXoff)
+               returnStatus;   // return current status NOW
+};
+
+// defines for bits in lcr
+#define                USA_DATABITS_5          0x00
+#define                USA_DATABITS_6          0x01
+#define                USA_DATABITS_7          0x02
+#define                USA_DATABITS_8          0x03
+#define                STOPBITS_5678_1         0x00    // 1 stop bit for all byte 
sizes
+#define                STOPBITS_5_1p5          0x04    // 1.5 stop bits for 5-bit byte
+#define                STOPBITS_678_2          0x04    // 2 stop bits for 6-8 bit byte
+#define                USA_PARITY_NONE         0x00
+#define                USA_PARITY_ODD          0x08
+#define                USA_PARITY_EVEN         0x18
+#define                PARITY_MARK_1           0x28    // force parity MARK
+#define                PARITY_SPACE_0          0x38    // force parity SPACE
+
+#define                TXFLOW_CTS                      0x04    
+#define                TXFLOW_DSR                      0x08
+#define                TXFLOW_XOFF                     0x01    
+#define                TXFLOW_XOFF_ANY         0x02    
+#define                TXFLOW_XOFF_BITS        (TXFLOW_XOFF | TXFLOW_XOFF_ANY)
+
+#define                RXFLOW_XOFF                     0x10    
+#define                RXFLOW_RTS                      0x20    
+#define                RXFLOW_DTR                      0x40
+#define                RXFLOW_DSR_SENSITIVITY  0x80
+
+#define                RXMODE_BYHAND           0x00    
+#define                RXMODE_DMA                      0x02    
+
+#define                TXMODE_BYHAND           0x00    
+#define                TXMODE_DMA                      0x02    
+
+
+// all things called "StatusMessage" are sent on the status endpoint
+
+struct keyspan_usa90_portStatusMessage 
+{
+       u8      msr,                    // reports the actual MSR register
+               cts,                    // reports CTS pin
+               dcd,                    // reports DCD pin
+               dsr,                    // reports DSR pin
+               ri,                             // reports RI pin
+               _txXoff,                // port is in XOFF state (we received XOFF)
+               rxBreak,                // reports break state
+               rxOverrun,              // count of overrun errors (since last 
reported)
+               rxParity,               // count of parity errors (since last reported)
+               rxFrame,                // count of frame errors (since last reported)
+               portState,              // PORTSTATE_xxx bits (useful for debugging)
+               messageAck,             // message acknowledgement
+               charAck,                // character acknowledgement
+               controlResponse;        // (value = returnStatus) a control message 
has been processed 
+};
+
+// bits in RX data message when STAT byte is included
+
+#define        RXERROR_OVERRUN         0x02
+#define        RXERROR_PARITY          0x04
+#define        RXERROR_FRAMING         0x08
+#define        RXERROR_BREAK           0x10
+
+#define        PORTSTATE_ENABLED       0x80
+#define        PORTSTATE_TXFLUSH       0x01
+#define        PORTSTATE_TXBREAK       0x02
+#define        PORTSTATE_LOOPBACK      0x04
+
+// MSR bits
+
+#define MSR_dCTS                       0x01            // CTS has changed since last 
report    
+#define MSR_dDSR                       0x02
+#define MSR_dRI                                0x04
+#define MSR_dDCD                       0x08
+
+#define MSR_CTS                                0x10            // current state of CTS
+#define MSR_DSR                                0x20
+#define MSR_RI                         0x40
+#define MSR_DCD                                0x80
+
+// ie: the maximum length of an endpoint buffer
+#define                MAX_DATA_LEN                    64
+
+#endif



-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to