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