ext Greg Kroah-Hartman wrote:
> From: Lucy McCoy <[EMAIL PROTECTED]>
> 
> Add support for Keyspan adapters: USA-49WG and USA-28XG
> 
> Signed-off-by: Lucy P. McCoy <[EMAIL PROTECTED]>
> Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
> Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>
> ---
>  drivers/usb/serial/keyspan.c          |  414 
> +++++++++++++++++++++++++++++++--
>  drivers/usb/serial/keyspan.h          |   74 ++++++-
>  drivers/usb/serial/keyspan_usa67msg.h |  254 ++++++++++++++++++++
>  3 files changed, 709 insertions(+), 33 deletions(-)
>  create mode 100644 drivers/usb/serial/keyspan_usa67msg.h
> 
> diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
> index e6966f1..fa91dde 100644
> --- a/drivers/usb/serial/keyspan.c
> +++ b/drivers/usb/serial/keyspan.c
> @@ -115,12 +115,13 @@ static int debug;
>  /*
>   * Version Information
>   */
> -#define DRIVER_VERSION "v1.1.4"
> +#define DRIVER_VERSION "v1.1.5"
>  #define DRIVER_AUTHOR "Hugh Blemings <[EMAIL PROTECTED]"
>  #define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
>  
>  #define INSTAT_BUFLEN        32
>  #define GLOCONT_BUFLEN       64
> +#define INDAT49W_BUFLEN      512
>  
>       /* Per device and per port private data */
>  struct keyspan_serial_private {
> @@ -129,9 +130,15 @@ struct keyspan_serial_private {
>       struct urb      *instat_urb;
>       char            instat_buf[INSTAT_BUFLEN];
>  
> +     /* added to support 49wg, where data from all 4 ports comes in on 1 EP 
> */
> +     /* and high-speed supported */
> +     struct urb      *indat_urb;
> +     char            indat_buf[INDAT49W_BUFLEN];
> +
>       /* XXX this one probably will need a lock */
>       struct urb      *glocont_urb;
>       char            glocont_buf[GLOCONT_BUFLEN];
> +     char            ctrl_buf[8];                    // for EP0 control 
> message
Commnets with // ...
>  };
>  
>  struct keyspan_port_private {
> @@ -179,12 +186,13 @@ struct keyspan_port_private {
>  
>       
>  /* Include Keyspan message headers.  All current Keyspan Adapters
> -   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. */
> +   make use of one of five message formats which are referred
> +   to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and within this 
> driver. */
>  #include "keyspan_usa26msg.h"
>  #include "keyspan_usa28msg.h"
>  #include "keyspan_usa49msg.h"
>  #include "keyspan_usa90msg.h"
> +#include "keyspan_usa67msg.h"
>       
>  
>  /* Functions used by new usb-serial code. */
> @@ -850,13 +858,89 @@ static void     usa49_indat_callback(struct urb *urb)
>               }
>  }
>  
> +static void usa49wg_indat_callback(struct urb *urb)
> +{
> +     int                     i, len, x, err;
> +     struct usb_serial       *serial;
> +     struct usb_serial_port  *port;
> +     struct tty_struct       *tty;
> +     unsigned char           *data = urb->transfer_buffer;
> +
> +     dbg ("%s", __FUNCTION__);
> +
> +     serial = urb->context;
> +
> +     if (urb->status) {
> +             dbg("%s - nonzero status: %x", __FUNCTION__, urb->status);
> +             return;
> +     }
> +
> +     /* inbound data is in the form P#, len, status, data */
> +     i = 0;
> +     len = 0;
> +
> +     if (urb->actual_length) {
> +             while (i < urb->actual_length) {
> +
> +                     /* Check port number from message*/
> +                     if (data[i] >= serial->num_ports) {
> +                             dbg ("%s - Unexpected port number %d",
> +                                     __FUNCTION__, data[i]);
> +                             return;
> +                     }
> +                     port = serial->port[data[i++]];
> +                     tty = port->tty;
> +                     len = data[i++];
> +
> +                     /* 0x80 bit is error flag */
> +                     if ((data[i] & 0x80) == 0) {
> +                             /* no error on any byte */
> +                             i++;
> +                             for (x = 1; x < len ; ++x)
> +                                     if (port->open_count)
> +                                             tty_insert_flip_char(tty,
> +                                                             data[i++], 0);
> +                                     else
> +                                             i++;
> +                     } else {
> +                             /*
> +                              * some bytes had errors, every byte has status
> +                              */
> +                             for (x = 0; x + 1 < len; x += 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) */
> +                                     if (port->open_count)
> +                                             tty_insert_flip_char(tty,
> +                                                     data[i+1], flag);
> +                                     i += 2;
> +                             }
> +                     }
> +                     if (port->open_count)
> +                             tty_flip_buffer_push(tty);
> +             }
> +     }
> +
> +     /* Resubmit urb so we continue receiving */
> +     urb->dev = serial->dev;
> +
> +     err = usb_submit_urb(urb, GFP_ATOMIC);
> +     if (err != 0)
> +             dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
> +}
> +
>  /* not used, usa-49 doesn't have per-port control endpoints */
> -static void  usa49_outcont_callback(struct urb *urb)
> +static void usa49_outcont_callback(struct urb *urb)
>  {
>       dbg ("%s", __FUNCTION__);
>  }
>  
> -static void  usa90_indat_callback(struct urb *urb)
> +static void usa90_indat_callback(struct urb *urb)
>  {
>       int                     i, err;
>       int                     endpoint;
> @@ -869,7 +953,6 @@ static void       usa90_indat_callback(struct urb *urb)
>  
>       endpoint = usb_pipeendpoint(urb->pipe);
>  
> -
>       if (urb->status) {
>               dbg("%s - nonzero status: %x on endpoint %d.",
>                   __FUNCTION__, urb->status, endpoint);
> @@ -995,6 +1078,87 @@ static void     usa90_outcont_callback(struct urb *urb)
>       }
>  }
>  
> +/* Status messages from the 28xg */
> +static void  usa67_instat_callback(struct urb *urb)
> +{
> +     int                                     err;
> +     unsigned char                           *data = urb->transfer_buffer;
> +     struct keyspan_usa67_portStatusMessage  *msg;
> +     struct usb_serial                       *serial;
> +     struct usb_serial_port                  *port;
> +     struct keyspan_port_private             *p_priv;
> +     int old_dcd_state;
> +
> +     dbg ("%s", __FUNCTION__);
> +
> +     serial = urb->context;
> +
> +     if (urb->status) {
> +             dbg("%s - nonzero status: %x", __FUNCTION__, urb->status);
> +             return;
> +     }
> +
> +     if (urb->actual_length != sizeof(struct 
> keyspan_usa67_portStatusMessage)) {
> +             dbg("%s - bad length %d", __FUNCTION__, urb->actual_length);
> +             return;
> +     }
> +
> +
> +     /* Now do something useful with the data */
> +     msg = (struct keyspan_usa67_portStatusMessage *)data;
> +
> +     /* Check port number from message and retrieve private data */
> +     if (msg->port >= serial->num_ports) {
> +             dbg ("%s - Unexpected port number %d", __FUNCTION__, msg->port);
> +             return;
> +     }
> +
> +     port = serial->port[msg->port];
> +     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->hskia_cts) ? 1 : 0);
> +     p_priv->dcd_state = ((msg->gpia_dcd) ? 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); */
I think you could to cut this comments above ...
> +     }
> +
> +     /* Resubmit urb so we continue receiving */
> +     urb->dev = serial->dev;
> +     err = usb_submit_urb(urb, GFP_ATOMIC);
> +     if (err != 0)
> +             dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
> +}
> +
> +static void usa67_glocont_callback(struct urb *urb)
> +{
> +     struct usb_serial *serial;
> +     struct usb_serial_port *port;
> +     struct keyspan_port_private *p_priv;
> +     int i;
> +
> +     dbg ("%s", __FUNCTION__);
> +
> +     serial = urb->context;
> +     for (i = 0; i < serial->num_ports; ++i) {
> +             port = serial->port[i];
> +             p_priv = usb_get_serial_port_data(port);
> +
> +             if (p_priv->resend_cont) {
> +                     dbg ("%s - sending setup", __FUNCTION__);
> +                     keyspan_usa67_send_setup(serial, port,
> +                                             p_priv->resend_cont - 1);
> +                     break;
> +             }
> +     }
> +}
> +
>  static int keyspan_write_room (struct usb_serial_port *port)
>  {
>       struct keyspan_port_private     *p_priv;
> @@ -1311,6 +1475,11 @@ static struct urb *keyspan_setup_urb (struct 
> usb_serial *serial, int endpoint,
>               return NULL;
>       }
>  
> +     if (endpoint == 0) {
> +             /* control EP filled in when used */
> +             return urb;
> +     }
> +
>       ep_desc = find_ep(serial, endpoint);
>       if (!ep_desc) {
>               /* leak the urb, something's wrong and the callers don't care */
> @@ -1380,6 +1549,14 @@ static struct callbacks {
>               .outdat_callback =      usa2x_outdat_callback,
>               .inack_callback =       usa28_inack_callback,
>               .outcont_callback =     usa90_outcont_callback,
> +     }, {
> +             /* msg_usa67 callbacks */
> +             .instat_callback =      usa67_instat_callback,
> +             .glocont_callback =     usa67_glocont_callback,
> +             .indat_callback =       usa26_indat_callback,
> +             .outdat_callback =      usa2x_outdat_callback,
> +             .inack_callback =       usa26_inack_callback,
> +             .outcont_callback =     usa26_outcont_callback,
>       }
>  };
>  
> @@ -1410,6 +1587,11 @@ static void keyspan_setup_urbs(struct usb_serial 
> *serial)
>                serial, s_priv->instat_buf, INSTAT_BUFLEN,
>                cback->instat_callback);
>  
> +     s_priv->indat_urb = keyspan_setup_urb
> +             (serial, d_details->indat_endpoint, USB_DIR_IN,
> +              serial, s_priv->indat_buf, INDAT49W_BUFLEN,
> +              usa49wg_indat_callback);
> +
>       s_priv->glocont_urb = keyspan_setup_urb
>               (serial, d_details->glocont_endpoint, USB_DIR_OUT,
>                serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
> @@ -1685,8 +1867,8 @@ static int keyspan_usa26_send_setup(struct usb_serial 
> *serial,
>       }
>  
>       /* Save reset port val for resend.
> -     Don't overwrite resend for close condition. */
> -     if (p_priv->resend_cont != 3)
> +        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__); */
> @@ -1836,8 +2018,8 @@ static int keyspan_usa28_send_setup(struct usb_serial 
> *serial,
>       }
>  
>       /* Save reset port val for resend.
> -        Don't overwrite resend for close condition. */
> -     if (p_priv->resend_cont != 3)
> +        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__);
> @@ -1940,11 +2122,11 @@ static int keyspan_usa49_send_setup(struct usb_serial 
> *serial,
>                                   struct usb_serial_port *port,
>                                   int reset_port)
>  {
> -     struct keyspan_usa49_portControlMessage msg;            
> +     struct keyspan_usa49_portControlMessage msg;
> +     struct usb_ctrlrequest                  *dr = NULL;
>       struct keyspan_serial_private           *s_priv;
>       struct keyspan_port_private             *p_priv;
>       const struct keyspan_device_details     *d_details;
> -     int                                     glocont_urb;
>       struct urb                              *this_urb;
>       int                                     err, device_port;
>  
> @@ -1954,10 +2136,9 @@ static int keyspan_usa49_send_setup(struct usb_serial 
> *serial,
>       p_priv = usb_get_serial_port_data(port);
>       d_details = s_priv->device_details;
>  
> -     glocont_urb = d_details->glocont_endpoint;
>       this_urb = s_priv->glocont_urb;
>  
> -             /* Work out which port within the device is being setup */
> +     /* Work out which port within the device is being setup */
>       device_port = port->number - port->serial->minor;
>  
>       dbg("%s - endpoint %d port %d (%d)",__FUNCTION__, 
> usb_pipeendpoint(this_urb->pipe), port->number, device_port);
> @@ -1969,9 +2150,10 @@ static int keyspan_usa49_send_setup(struct usb_serial 
> *serial,
>       }
>  
>       /* Save reset port val for resend.
> -        Don't overwrite resend for close condition. */
> -     if (p_priv->resend_cont != 3)
> +        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);
> @@ -2083,20 +2265,39 @@ static int keyspan_usa49_send_setup(struct usb_serial 
> *serial,
>       msg.dtr = p_priv->dtr_state;
>               
>       p_priv->resend_cont = 0;
> -     memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
> +
> +     /* if the device is a 49wg, we send control message on usb control EP 0 
> */
> +
> +     if (d_details->product_id == keyspan_usa49wg_product_id) {
> +             dr = (void *)(s_priv->ctrl_buf);
> +             dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
> +             dr->bRequest = 0xB0;    /* 49wg control message */;
> +             dr->wValue = 0;
> +             dr->wIndex = 0;
> +             dr->wLength = cpu_to_le16(sizeof(msg));
> +
> +             memcpy (s_priv->glocont_buf, &msg, sizeof(msg));
> +
> +             usb_fill_control_urb(this_urb, serial->dev, 
> usb_sndctrlpipe(serial->dev, 0),
> +                          (unsigned char *)dr, s_priv->glocont_buf, 
> sizeof(msg),
> +                          usa49_glocont_callback, serial);
> +
> +     } else {
> +             memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
>       
> -     /* send the data out the device on control endpoint */
> -     this_urb->transfer_buffer_length = sizeof(msg);
> +             /* send the data out the device on control endpoint */
> +             this_urb->transfer_buffer_length = sizeof(msg);
>  
> -     this_urb->dev = serial->dev;
> +             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);
>       }
>  #if 0
>       else {
>               dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", 
> __FUNCTION__,
> -                 outcont_urb, this_urb->transfer_buffer_length,
> -                 usb_pipeendpoint(this_urb->pipe));
> +                        outcont_urb, this_urb->transfer_buffer_length,
> +                        usb_pipeendpoint(this_urb->pipe));
>       }
>  #endif
>  
> @@ -2241,6 +2442,154 @@ static int keyspan_usa90_send_setup(struct usb_serial 
> *serial,
>       return (0);
>  }
>  
> +static int keyspan_usa67_send_setup(struct usb_serial *serial,
> +                                 struct usb_serial_port *port,
> +                                 int reset_port)
> +{
> +     struct keyspan_usa67_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, device_port;
> +
> +     dbg ("%s", __FUNCTION__);
> +
> +     s_priv = usb_get_serial_data(serial);
> +     p_priv = usb_get_serial_port_data(port);
> +     d_details = s_priv->device_details;
> +
> +     this_urb = s_priv->glocont_urb;
> +
> +     /* Work out which port within the device is being setup */
> +     device_port = port->number - port->serial->minor;
> +
> +     /* Make sure we have an urb then send the message */
> +     if (this_urb == NULL) {
> +             dbg("%s - oops no urb for port %d.", __FUNCTION__,
> +                     port->number);
> +             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__); */
I think you could to cut this comment ...
> +             mdelay(5);
> +             return(-1);
> +     }
> +
> +     memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
> +
> +     msg.port = device_port;
> +
> +     /* 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 = 0xff;
> +             if (d_details->calculate_baud_rate
> +                 (p_priv->baud, d_details->baudclk, &msg.baudHi,
> +                  &msg.baudLo, &msg.prescaler, device_port) == 
> KEYSPAN_INVALID_BAUD_RATE ) {
> +                     dbg("%s - Invalid baud rate %d requested, using 9600.", 
> __FUNCTION__,
> +                         p_priv->baud);
> +                     msg.baudLo = 0;
> +                     msg.baudHi = 125;       /* Values for 9600 baud */
> +                     msg.prescaler = 10;
> +             }
> +             msg.setPrescaler = 0xff;
> +     }
> +
> +     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;
> +     }
> +     msg.setLcr = 0xff;
> +
> +     msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
> +     msg.xonFlowControl = 0;
> +     msg.setFlowControl = 0xff;
> +     msg.forwardingLength = 16;
> +     msg.xonChar = 17;
> +     msg.xoffChar = 19;
> +
> +     if (reset_port == 1) {
> +             /* Opening port */
> +             msg._txOn = 1;
> +             msg._txOff = 0;
> +             msg.txFlush = 0;
> +             msg.txBreak = 0;
> +             msg.rxOn = 1;
> +             msg.rxOff = 0;
> +             msg.rxFlush = 1;
> +             msg.rxForward = 0;
> +             msg.returnStatus = 0;
> +             msg.resetDataToggle = 0xff;
> +     } else if (reset_port == 2) {
> +             /* Closing port */
> +             msg._txOn = 0;
> +             msg._txOff = 1;
> +             msg.txFlush = 0;
> +             msg.txBreak = 0;
> +             msg.rxOn = 0;
> +             msg.rxOff = 1;
> +             msg.rxFlush = 1;
> +             msg.rxForward = 0;
> +             msg.returnStatus = 0;
> +             msg.resetDataToggle = 0;
> +     } else {
> +             /* Sending intermediate configs */
> +             msg._txOn = (! p_priv->break_on);
> +             msg._txOff = 0;
> +             msg.txFlush = 0;
> +             msg.txBreak = (p_priv->break_on);
> +             msg.rxOn = 0;
> +             msg.rxOff = 0;
> +             msg.rxFlush = 0;
> +             msg.rxForward = 0;
> +             msg.returnStatus = 0;
> +             msg.resetDataToggle = 0x0;
> +     }
> +
> +     /* Do handshaking outputs */
> +     msg.setTxTriState_setRts = 0xff;
> +     msg.txTriState_rts = p_priv->rts_state;
> +
> +     msg.setHskoa_setDtr = 0xff;
> +     msg.hskoa_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;
> +
> +     err = usb_submit_urb(this_urb, GFP_ATOMIC);
> +     if (err != 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;
> @@ -2265,6 +2614,9 @@ static void keyspan_send_setup(struct usb_serial_port 
> *port, int reset_port)
>       case msg_usa90:
>               keyspan_usa90_send_setup(serial, port, reset_port);
>               break;
> +     case msg_usa67:
> +             keyspan_usa67_send_setup(serial, port, reset_port);
> +             break;
>       }
>  }
>  
> @@ -2313,9 +2665,19 @@ static int keyspan_startup (struct usb_serial *serial)
>  
>       keyspan_setup_urbs(serial);
>  
> -     s_priv->instat_urb->dev = serial->dev;
> -     if ((err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL)) != 0) {
> -             dbg("%s - submit instat urb failed %d", __FUNCTION__, err);
> +     if (s_priv->instat_urb != NULL) {
> +             s_priv->instat_urb->dev = serial->dev;
> +             err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
> +             if (err != 0)
> +                     dbg("%s - submit instat urb failed %d", __FUNCTION__,
> +                             err);
> +     }
> +     if (s_priv->indat_urb != NULL) {
> +             s_priv->indat_urb->dev = serial->dev;
> +             err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
> +             if (err != 0)
> +                     dbg("%s - submit indat urb failed %d", __FUNCTION__,
> +                             err);
>       }
>                       
>       return (0);
> @@ -2335,6 +2697,7 @@ static void keyspan_shutdown (struct usb_serial *serial)
>       /* Stop reading/writing urbs */
>       stop_urb(s_priv->instat_urb);
>       stop_urb(s_priv->glocont_urb);
> +     stop_urb(s_priv->indat_urb);
>       for (i = 0; i < serial->num_ports; ++i) {
>               port = serial->port[i];
>               p_priv = usb_get_serial_port_data(port);
> @@ -2348,6 +2711,7 @@ static void keyspan_shutdown (struct usb_serial *serial)
>  
>       /* Now free them */
>       usb_free_urb(s_priv->instat_urb);
> +     usb_free_urb(s_priv->indat_urb);
>       usb_free_urb(s_priv->glocont_urb);
>       for (i = 0; i < serial->num_ports; ++i) {
>               port = serial->port[i];
> diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
> index c6830cb..8a0d174 100644
> --- a/drivers/usb/serial/keyspan.h
> +++ b/drivers/usb/serial/keyspan.h
> @@ -99,6 +99,10 @@ static int  keyspan_usa90_send_setup       (struct 
> usb_serial *serial,
>                                        struct usb_serial_port *port,
>                                        int reset_port);
>  
> +static int  keyspan_usa67_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 */
>  struct ezusb_hex_record {
> @@ -229,15 +233,17 @@ struct ezusb_hex_record {
>  #define      keyspan_usa28_product_id                0x010f
>  #define      keyspan_usa28x_product_id               0x0110
>  #define      keyspan_usa28xa_product_id              0x0115
> +#define      keyspan_usa28xb_product_id              0x0110
> +#define      keyspan_usa28xg_product_id              0x0135
>  #define      keyspan_usa49w_product_id               0x010a
>  #define      keyspan_usa49wlc_product_id             0x012a
> -
> +#define      keyspan_usa49wg_product_id              0x0131
>  
>  struct keyspan_device_details {
>       /* product ID value */
>       int     product_id;
>  
> -     enum    {msg_usa26, msg_usa28, msg_usa49, msg_usa90} msg_format;
> +     enum    {msg_usa26, msg_usa28, msg_usa49, msg_usa90, msg_usa67} 
> msg_format;
>  
>               /* Number of physical ports */
>       int     num_ports;
> @@ -264,6 +270,9 @@ struct keyspan_device_details {
>               /* Endpoint used for input status */
>       int     instat_endpoint;
>  
> +             /* Endpoint used for input data 49WG only */
> +     int     indat_endpoint;
> +
>               /* Endpoint used for global control functions */
>       int     glocont_endpoint;
>  
> @@ -287,6 +296,7 @@ static const struct keyspan_device_details 
> usa18x_device_details = {
>       .inack_endpoints        = {0x85},
>       .outcont_endpoints      = {0x05},
>       .instat_endpoint        = 0x87,
> +     .indat_endpoint         = -1,
>       .glocont_endpoint       = 0x07,
>       .calculate_baud_rate    = keyspan_usa19w_calc_baud,
>       .baudclk                = KEYSPAN_USA18X_BAUDCLK,
> @@ -303,6 +313,7 @@ static const struct keyspan_device_details 
> usa19_device_details = {
>       .inack_endpoints        = {0x83},
>       .outcont_endpoints      = {0x03},
>       .instat_endpoint        = 0x84,
> +     .indat_endpoint         = -1,
>       .glocont_endpoint       = -1,
>       .calculate_baud_rate    = keyspan_usa19_calc_baud,
>       .baudclk                = KEYSPAN_USA19_BAUDCLK,
> @@ -319,6 +330,7 @@ static const struct keyspan_device_details 
> usa19qi_device_details = {
>       .inack_endpoints        = {0x83},
>       .outcont_endpoints      = {0x03},
>       .instat_endpoint        = 0x84,
> +     .indat_endpoint         = -1,
>       .glocont_endpoint       = -1,
>       .calculate_baud_rate    = keyspan_usa28_calc_baud,
>       .baudclk                = KEYSPAN_USA19_BAUDCLK,
> @@ -335,6 +347,7 @@ static const struct keyspan_device_details 
> mpr_device_details = {
>       .inack_endpoints        = {0x83},
>       .outcont_endpoints      = {0x03},
>       .instat_endpoint        = 0x84,
> +     .indat_endpoint         = -1,
>       .glocont_endpoint       = -1,
>       .calculate_baud_rate    = keyspan_usa28_calc_baud,
>       .baudclk                = KEYSPAN_USA19_BAUDCLK,
> @@ -351,6 +364,7 @@ static const struct keyspan_device_details 
> usa19qw_device_details = {
>       .inack_endpoints        = {0x85},
>       .outcont_endpoints      = {0x05},
>       .instat_endpoint        = 0x87,
> +     .indat_endpoint         = -1,
>       .glocont_endpoint       = 0x07,
>       .calculate_baud_rate    = keyspan_usa19w_calc_baud,
>       .baudclk                = KEYSPAN_USA19W_BAUDCLK,
> @@ -367,6 +381,7 @@ static const struct keyspan_device_details 
> usa19w_device_details = {
>       .inack_endpoints        = {0x85},
>       .outcont_endpoints      = {0x05},
>       .instat_endpoint        = 0x87,
> +     .indat_endpoint         = -1,
>       .glocont_endpoint       = 0x07,
>       .calculate_baud_rate    = keyspan_usa19w_calc_baud,
>       .baudclk                = KEYSPAN_USA19W_BAUDCLK,
> @@ -383,6 +398,7 @@ static const struct keyspan_device_details 
> usa19hs_device_details = {
>       .inack_endpoints        = {-1},
>       .outcont_endpoints      = {0x02},
>       .instat_endpoint        = 0x82,
> +     .indat_endpoint         = -1,
>       .glocont_endpoint       = -1,
>       .calculate_baud_rate    = keyspan_usa19hs_calc_baud,
>       .baudclk                = KEYSPAN_USA19HS_BAUDCLK,
> @@ -399,6 +415,7 @@ static const struct keyspan_device_details 
> usa28_device_details = {
>       .inack_endpoints        = {0x85, 0x86},
>       .outcont_endpoints      = {0x05, 0x06},
>       .instat_endpoint        = 0x87,
> +     .indat_endpoint         = -1,
>       .glocont_endpoint       = 0x07,
>       .calculate_baud_rate    = keyspan_usa28_calc_baud,
>       .baudclk                = KEYSPAN_USA28_BAUDCLK,                
> @@ -415,6 +432,7 @@ static const struct keyspan_device_details 
> usa28x_device_details = {
>       .inack_endpoints        = {0x85, 0x86},
>       .outcont_endpoints      = {0x05, 0x06},
>       .instat_endpoint        = 0x87,
> +     .indat_endpoint         = -1,
>       .glocont_endpoint       = 0x07,
>       .calculate_baud_rate    = keyspan_usa19w_calc_baud,
>       .baudclk                = KEYSPAN_USA28X_BAUDCLK,
> @@ -431,11 +449,28 @@ static const struct keyspan_device_details 
> usa28xa_device_details = {
>       .inack_endpoints        = {0x85, 0x86},
>       .outcont_endpoints      = {0x05, 0x06},
>       .instat_endpoint        = 0x87,
> +     .indat_endpoint         = -1,
>       .glocont_endpoint       = 0x07,
>       .calculate_baud_rate    = keyspan_usa19w_calc_baud,
>       .baudclk                = KEYSPAN_USA28X_BAUDCLK,
>  };
>  
> +static const struct keyspan_device_details usa28xg_device_details = {
> +     .product_id             = keyspan_usa28xg_product_id,
> +     .msg_format             = msg_usa67,
> +     .num_ports              = 2,
> +     .indat_endp_flip        = 0,
> +     .outdat_endp_flip       = 0,
> +     .indat_endpoints        = {0x84, 0x88},
> +     .outdat_endpoints       = {0x02, 0x06},
> +     .inack_endpoints        = {-1, -1},
> +     .outcont_endpoints      = {-1, -1},
> +     .instat_endpoint        = 0x81,
> +     .indat_endpoint         = -1,
> +     .glocont_endpoint       = 0x01,
> +     .calculate_baud_rate    = keyspan_usa19w_calc_baud,
> +     .baudclk                = KEYSPAN_USA28X_BAUDCLK,
> +};
>  /* We don't need a separate entry for the usa28xb as it appears as a 28x 
> anyway */
>  
>  static const struct keyspan_device_details usa49w_device_details = {
> @@ -449,6 +484,7 @@ static const struct keyspan_device_details 
> usa49w_device_details = {
>       .inack_endpoints        = {-1, -1, -1, -1},
>       .outcont_endpoints      = {-1, -1, -1, -1},
>       .instat_endpoint        = 0x87,
> +     .indat_endpoint         = -1,
>       .glocont_endpoint       = 0x07,
>       .calculate_baud_rate    = keyspan_usa19w_calc_baud,
>       .baudclk                = KEYSPAN_USA49W_BAUDCLK,
> @@ -465,11 +501,29 @@ static const struct keyspan_device_details 
> usa49wlc_device_details = {
>       .inack_endpoints        = {-1, -1, -1, -1},
>       .outcont_endpoints      = {-1, -1, -1, -1},
>       .instat_endpoint        = 0x87,
> +     .indat_endpoint         = -1,
>       .glocont_endpoint       = 0x07,
>       .calculate_baud_rate    = keyspan_usa19w_calc_baud,
>       .baudclk                = KEYSPAN_USA19W_BAUDCLK,
>  };
>  
> +static const struct keyspan_device_details usa49wg_device_details = {
> +     .product_id             = keyspan_usa49wg_product_id,
> +     .msg_format             = msg_usa49,
> +     .num_ports              = 4,
> +     .indat_endp_flip        = 0,
> +     .outdat_endp_flip       = 0,
> +     .indat_endpoints        = {-1, -1, -1, -1},             /* single 
> 'global' data in EP */
> +     .outdat_endpoints       = {0x01, 0x02, 0x04, 0x06},
> +     .inack_endpoints        = {-1, -1, -1, -1},
> +     .outcont_endpoints      = {-1, -1, -1, -1},
> +     .instat_endpoint        = 0x81,
> +     .indat_endpoint         = 0x88,
> +     .glocont_endpoint       = 0x00,                         /* uses control 
> EP */
> +     .calculate_baud_rate    = keyspan_usa19w_calc_baud,
> +     .baudclk                = KEYSPAN_USA19W_BAUDCLK,
> +};
> +
>  static const struct keyspan_device_details *keyspan_devices[] = {
>       &usa18x_device_details,
>       &usa19_device_details,
> @@ -481,9 +535,11 @@ static const struct keyspan_device_details 
> *keyspan_devices[] = {
>       &usa28_device_details,
>       &usa28x_device_details,
>       &usa28xa_device_details,
> +     &usa28xg_device_details,
>       /* 28xb not required as it renumerates as a 28x */
>       &usa49w_device_details,
>       &usa49wlc_device_details,
> +     &usa49wg_device_details,
>       NULL,
>  };
>  
> @@ -510,8 +566,11 @@ static struct usb_device_id keyspan_ids_combined[] = {
>       { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
>       { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
>       { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
> +     { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) },
> +     { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) },
>       { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id)},
>       { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)},
> +     { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wg_product_id)},
>       { } /* Terminating entry */
>  };
>  
> @@ -557,12 +616,15 @@ static struct usb_device_id keyspan_2port_ids[] = {
>       { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
>       { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
>       { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
> +     { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) },
> +     { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) },
>       { } /* Terminating entry */
>  };
>  
>  static struct usb_device_id keyspan_4port_ids[] = {
>       { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id) },
>       { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)},
> +     { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wg_product_id)},
>       { } /* Terminating entry */
>  };
>  
> @@ -573,7 +635,6 @@ static struct usb_serial_driver keyspan_pre_device = {
>               .name           = "keyspan_no_firm",
>       },
>       .description            = "Keyspan - (without firmware)",
> -     .usb_driver             = &keyspan_driver,
>       .id_table               = keyspan_pre_ids,
>       .num_interrupt_in       = NUM_DONT_CARE,
>       .num_bulk_in            = NUM_DONT_CARE,
> @@ -588,7 +649,6 @@ static struct usb_serial_driver keyspan_1port_device = {
>               .name           = "keyspan_1",
>       },
>       .description            = "Keyspan 1 port adapter",
> -     .usb_driver             = &keyspan_driver,
>       .id_table               = keyspan_1port_ids,
>       .num_interrupt_in       = NUM_DONT_CARE,
>       .num_bulk_in            = NUM_DONT_CARE,
> @@ -616,7 +676,6 @@ static struct usb_serial_driver keyspan_2port_device = {
>               .name           = "keyspan_2",
>       },
>       .description            = "Keyspan 2 port adapter",
> -     .usb_driver             = &keyspan_driver,
>       .id_table               = keyspan_2port_ids,
>       .num_interrupt_in       = NUM_DONT_CARE,
>       .num_bulk_in            = NUM_DONT_CARE,
> @@ -644,11 +703,10 @@ static struct usb_serial_driver keyspan_4port_device = {
>               .name           = "keyspan_4",
>       },
>       .description            = "Keyspan 4 port adapter",
> -     .usb_driver             = &keyspan_driver,
>       .id_table               = keyspan_4port_ids,
>       .num_interrupt_in       = NUM_DONT_CARE,
> -     .num_bulk_in            = 5,
> -     .num_bulk_out           = 5,
> +     .num_bulk_in            = NUM_DONT_CARE,
> +     .num_bulk_out           = NUM_DONT_CARE,
>       .num_ports              = 4,
>       .open                   = keyspan_open,
>       .close                  = keyspan_close,
> diff --git a/drivers/usb/serial/keyspan_usa67msg.h 
> b/drivers/usb/serial/keyspan_usa67msg.h
> new file mode 100644
> index 0000000..20fa3e2
> --- /dev/null
> +++ b/drivers/usb/serial/keyspan_usa67msg.h
> @@ -0,0 +1,254 @@
> +/*
> +     usa67msg.h
> +
> +     Copyright (c) 1998-2007 InnoSys Incorporated.  All Rights Reserved
> +     This file is available under a BSD-style copyright
> +
> +     Keyspan USB Async Firmware to run on Anchor FX1
> +
> +     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-2007 InnoSys Incorporated.  All Rights 
> Reserved
> +
> +             This file is available under a BSD-style copyright
> +
> +     2. Redistributions in binary form must reproduce the above copyright
> +     notice, this list of conditions and the following disclaimer in the
> +     documentation and/or other materials provided with the distribution.
> +
> +     3. 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.
> +
> +     Fourth revision: This message format supports the USA28XG
> +
> +     Buffer formats for RX/TX data messages are not defined by
> +     a structure, but are described here:
> +
> +     USB OUT (host -> USAxx, transmit) messages contain a
> +     REQUEST_ACK indicator (set to 0xff to request an ACK at the
> +     completion of transmit; 0x00 otherwise), followed by data:
> +
> +             RQSTACK DAT DAT DAT ...
> +
> +     with a total data length of up to 63.
> +
> +     USB IN (USAxx -> host, receive) messages begin with a status
> +     byte in which the 0x80 bit is either:
> +
> +             (a)     0x80 bit clear
> +                     indicates that the bytes following it are all data
> +                     bytes:
> +
> +                             STAT DATA DATA DATA DATA DATA ...
> +
> +                     for a total of up to 63 DATA bytes,
> +
> +     or:
> +
> +             (b)     0x80 bit set
> +                     indiates that the bytes following alternate data and
> +                     status bytes:
> +
> +                             STAT DATA STAT DATA STAT DATA STAT DATA ...
> +
> +                     for a total of up to 32 DATA bytes.
> +
> +     The valid bits in the STAT bytes are:
> +
> +             OVERRUN 0x02
> +             PARITY  0x04
> +             FRAMING 0x08
> +             BREAK   0x10
> +
> +     Notes:
> +
> +     (1) The OVERRUN bit can appear in either (a) or (b) format
> +             messages, but the but the PARITY/FRAMING/BREAK bits
> +             only appear in (b) format messages.
> +     (2) For the host to determine the exact point at which the
> +             overrun occurred (to identify the point in the data
> +             stream at which the data was lost), it needs to count
> +             128 characters, starting at the first character of the
> +             message in which OVERRUN was reported; the lost character(s)
> +             would have been received between the 128th and 129th
> +             characters.
> +     (3)     An RX data message in which the first byte has 0x80 clear
> +             serves as a "break off" indicator.
> +
> +     revision history:
> +
> +     1999feb10       add reportHskiaChanges to allow us to ignore them
> +     1999feb10       add txAckThreshold for fast+loose throughput enhancement
> +     1999mar30       beef up support for RX error reporting
> +     1999apr14       add resetDataToggle to control message
> +     2000jan04       merge with usa17msg.h
> +     2000jun01       add extended BSD-style copyright text
> +     2001jul05       change message format to improve OVERRUN case
> +     2002jun05       update copyright date, improve comments
> +     2006feb06       modify for FX1 chip
> +
> +*/
> +
> +#ifndef      __USA67MSG__
> +#define      __USA67MSG__

A lot of comments with // ... in this path below ...

> +
> +
> +// all things called "ControlMessage" are sent on the 'control' endpoint
> +
> +typedef struct keyspan_usa67_portControlMessage
> +{
> +     u8      port;           // 0 or 1 (selects port)
> +     /*
> +             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,                 // baudHi is only used for first port 
> (gives lower rates)
> +             externalClock_txClocking,
> +                                             // 0=internal, other=external
> +
> +             setLcr,                 // host requests lcr be set
> +             lcr,                    // use PARITY, STOPBITS, DATABITS below
> +
> +             setFlowControl, // host requests flow control be set
> +             ctsFlowControl, // 1=use CTS flow control, 0=don't
> +             xonFlowControl, // 1=use XON/XOFF flow control, 0=don't
> +             xonChar,                // specified in current character format
> +             xoffChar,               // specified in current character format
> +
> +             setTxTriState_setRts,
> +                                             // host requests TX tri-state 
> be set
> +             txTriState_rts, // 1=active (normal), 0=tristate (off)
> +
> +             setHskoa_setDtr,
> +                                             // host requests HSKOA output 
> be set
> +             hskoa_dtr,              // 1=on, 0=off
> +
> +             setPrescaler,   // host requests prescalar be set (default: 13)
> +             prescaler;              // specified as N/8; values 8-ff are 
> valid
> +                                             // must be set any time 
> internal baud rate is set;
> +                                             // must not be set when 
> external clocking is used
> +
> +     /*
> +             3.      configuration data which is simply used as is (no 
> overhead,
> +                     but must be specified correctly in every host message).
> +     */
> +     u8      forwardingLength,  // forward when this number of chars 
> available
> +             reportHskiaChanges_dsrFlowControl,
> +                                             // 1=normal; 0=ignore external 
> clock
> +                                             // 1=use DSR flow control, 
> 0=don't
> +             txAckThreshold, // 0=not allowed, 1=normal, 2-255 deliver ACK 
> faster
> +             loopbackMode;   // 0=no loopback, 1=loopback enabled
> +
> +     /*
> +             4.      commands which are flags only; these are processed in 
> order
> +                     (so that, e.g., if both _txOn and _txOff flags are set, 
> the
> +                     port ends in a TX_OFF state); any non-zero value is 
> respected
> +     */
> +     u8      _txOn,                  // enable transmitting (and continue if 
> there's data)
> +             _txOff,                 // stop transmitting
> +             txFlush,                // toss outbound data
> +             txBreak,                // turn on break (cleared by _txOn)
> +             rxOn,                   // turn on receiver
> +             rxOff,                  // turn off receiver
> +             rxFlush,                // toss inbound data
> +             rxForward,              // forward all inbound data, NOW (as if 
> fwdLen==1)
> +             returnStatus,   // return current status (even if it hasn't 
> changed)
> +             resetDataToggle;// reset data toggle state to DATA0
> +
> +} keyspan_usa67_portControlMessage;
> +
> +// 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/7/8-bit 
> byte
> +#define      USA_PARITY_NONE         0x00
> +#define      USA_PARITY_ODD          0x08
> +#define      USA_PARITY_EVEN         0x18
> +#define      PARITY_1                        0x28
> +#define      PARITY_0                        0x38
> +
> +// all things called "StatusMessage" are sent on the status endpoint
> +
> +typedef struct keyspan_usa67_portStatusMessage       // one for each port
> +{
> +     u8      port,                   // 0=first, 1=second, other=see below
> +             hskia_cts,              // reports HSKIA pin
> +             gpia_dcd,               // reports GPIA pin
> +             _txOff,                 // port has been disabled (by host)
> +             _txXoff,                // port is in XOFF state (either host 
> or RX XOFF)
> +             txAck,                  // indicates a TX message 
> acknowledgement
> +             rxEnabled,              // as configured by rxOn/rxOff 1=on, 
> 0=off
> +             controlResponse;// 1=a control message has been processed
> +} keyspan_usa67_portStatusMessage;
> +
> +// 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
> +
> +typedef struct keyspan_usa67_globalControlMessage
> +{
> +     u8      port,                           // 3
> +             sendGlobalStatus,       // 2=request for two status responses
> +             resetStatusToggle,      // 1=reset global status toggle
> +             resetStatusCount;       // a cycling value
> +} keyspan_usa67_globalControlMessage;
> +
> +typedef struct keyspan_usa67_globalStatusMessage
> +{
> +     u8      port,                           // 3
> +             sendGlobalStatus,       // from request, decremented
> +             resetStatusCount;       // as in request
> +} keyspan_usa67_globalStatusMessage;
> +
> +typedef struct keyspan_usa67_globalDebugMessage
> +{
> +     u8      port,                           // 2
> +             a,
> +             b,
> +             c,
> +             d;
> +} keyspan_usa67_globalDebugMessage;
> +
> +// ie: the maximum length of an FX1 endpoint buffer
> +#define      MAX_DATA_LEN                    64
> +
> +// update status approx. 60 times a second (16.6666 ms)
> +#define      STATUS_UPDATE_INTERVAL  16
> +
> +// status rationing tuning value (each port gets checked each n ms)
> +#define      STATUS_RATION   10
> +
> +#endif
> +
> +


-- 
Ragner Magalhaes

Instituto Nokia de Tecnologia - INdT
Open Source Mobile Research Center - OSMRC
Linux Kernel Team

E-mail.: [EMAIL PROTECTED]


-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to