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/
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel