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