Commit 0ca1268e109acf6d71507398cb95cab2e670b654

Authored by Lucy McCoy
Committed by Greg Kroah-Hartman
1 parent 87e71b473e

USB Serial Keyspan: add support for USA-49WG & USA-28XG

Add support for Keyspan adapters: USA-49WG and USA-28XG

Signed-off-by: Lucy P. McCoy <lucy@keyspan.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

Showing 3 changed files with 709 additions and 33 deletions Side-by-side Diff

drivers/usb/serial/keyspan.c
... ... @@ -115,12 +115,13 @@
115 115 /*
116 116 * Version Information
117 117 */
118   -#define DRIVER_VERSION "v1.1.4"
  118 +#define DRIVER_VERSION "v1.1.5"
119 119 #define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu"
120 120 #define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
121 121  
122 122 #define INSTAT_BUFLEN 32
123 123 #define GLOCONT_BUFLEN 64
  124 +#define INDAT49W_BUFLEN 512
124 125  
125 126 /* Per device and per port private data */
126 127 struct keyspan_serial_private {
127 128  
... ... @@ -129,9 +130,15 @@
129 130 struct urb *instat_urb;
130 131 char instat_buf[INSTAT_BUFLEN];
131 132  
  133 + /* added to support 49wg, where data from all 4 ports comes in on 1 EP */
  134 + /* and high-speed supported */
  135 + struct urb *indat_urb;
  136 + char indat_buf[INDAT49W_BUFLEN];
  137 +
132 138 /* XXX this one probably will need a lock */
133 139 struct urb *glocont_urb;
134 140 char glocont_buf[GLOCONT_BUFLEN];
  141 + char ctrl_buf[8]; // for EP0 control message
135 142 };
136 143  
137 144 struct keyspan_port_private {
138 145  
... ... @@ -179,12 +186,13 @@
179 186  
180 187  
181 188 /* Include Keyspan message headers. All current Keyspan Adapters
182   - make use of one of four message formats which are referred
183   - to as USA-26, USA-28 and USA-49, USA-90 by Keyspan and within this driver. */
  189 + make use of one of five message formats which are referred
  190 + to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and within this driver. */
184 191 #include "keyspan_usa26msg.h"
185 192 #include "keyspan_usa28msg.h"
186 193 #include "keyspan_usa49msg.h"
187 194 #include "keyspan_usa90msg.h"
  195 +#include "keyspan_usa67msg.h"
188 196  
189 197  
190 198 /* Functions used by new usb-serial code. */
191 199  
192 200  
... ... @@ -850,13 +858,89 @@
850 858 }
851 859 }
852 860  
  861 +static void usa49wg_indat_callback(struct urb *urb)
  862 +{
  863 + int i, len, x, err;
  864 + struct usb_serial *serial;
  865 + struct usb_serial_port *port;
  866 + struct tty_struct *tty;
  867 + unsigned char *data = urb->transfer_buffer;
  868 +
  869 + dbg ("%s", __FUNCTION__);
  870 +
  871 + serial = urb->context;
  872 +
  873 + if (urb->status) {
  874 + dbg("%s - nonzero status: %x", __FUNCTION__, urb->status);
  875 + return;
  876 + }
  877 +
  878 + /* inbound data is in the form P#, len, status, data */
  879 + i = 0;
  880 + len = 0;
  881 +
  882 + if (urb->actual_length) {
  883 + while (i < urb->actual_length) {
  884 +
  885 + /* Check port number from message*/
  886 + if (data[i] >= serial->num_ports) {
  887 + dbg ("%s - Unexpected port number %d",
  888 + __FUNCTION__, data[i]);
  889 + return;
  890 + }
  891 + port = serial->port[data[i++]];
  892 + tty = port->tty;
  893 + len = data[i++];
  894 +
  895 + /* 0x80 bit is error flag */
  896 + if ((data[i] & 0x80) == 0) {
  897 + /* no error on any byte */
  898 + i++;
  899 + for (x = 1; x < len ; ++x)
  900 + if (port->open_count)
  901 + tty_insert_flip_char(tty,
  902 + data[i++], 0);
  903 + else
  904 + i++;
  905 + } else {
  906 + /*
  907 + * some bytes had errors, every byte has status
  908 + */
  909 + for (x = 0; x + 1 < len; x += 2) {
  910 + int stat = data[i], flag = 0;
  911 + if (stat & RXERROR_OVERRUN)
  912 + flag |= TTY_OVERRUN;
  913 + if (stat & RXERROR_FRAMING)
  914 + flag |= TTY_FRAME;
  915 + if (stat & RXERROR_PARITY)
  916 + flag |= TTY_PARITY;
  917 + /* XXX should handle break (0x10) */
  918 + if (port->open_count)
  919 + tty_insert_flip_char(tty,
  920 + data[i+1], flag);
  921 + i += 2;
  922 + }
  923 + }
  924 + if (port->open_count)
  925 + tty_flip_buffer_push(tty);
  926 + }
  927 + }
  928 +
  929 + /* Resubmit urb so we continue receiving */
  930 + urb->dev = serial->dev;
  931 +
  932 + err = usb_submit_urb(urb, GFP_ATOMIC);
  933 + if (err != 0)
  934 + dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
  935 +}
  936 +
853 937 /* not used, usa-49 doesn't have per-port control endpoints */
854   -static void usa49_outcont_callback(struct urb *urb)
  938 +static void usa49_outcont_callback(struct urb *urb)
855 939 {
856 940 dbg ("%s", __FUNCTION__);
857 941 }
858 942  
859   -static void usa90_indat_callback(struct urb *urb)
  943 +static void usa90_indat_callback(struct urb *urb)
860 944 {
861 945 int i, err;
862 946 int endpoint;
... ... @@ -869,7 +953,6 @@
869 953  
870 954 endpoint = usb_pipeendpoint(urb->pipe);
871 955  
872   -
873 956 if (urb->status) {
874 957 dbg("%s - nonzero status: %x on endpoint %d.",
875 958 __FUNCTION__, urb->status, endpoint);
... ... @@ -995,6 +1078,87 @@
995 1078 }
996 1079 }
997 1080  
  1081 +/* Status messages from the 28xg */
  1082 +static void usa67_instat_callback(struct urb *urb)
  1083 +{
  1084 + int err;
  1085 + unsigned char *data = urb->transfer_buffer;
  1086 + struct keyspan_usa67_portStatusMessage *msg;
  1087 + struct usb_serial *serial;
  1088 + struct usb_serial_port *port;
  1089 + struct keyspan_port_private *p_priv;
  1090 + int old_dcd_state;
  1091 +
  1092 + dbg ("%s", __FUNCTION__);
  1093 +
  1094 + serial = urb->context;
  1095 +
  1096 + if (urb->status) {
  1097 + dbg("%s - nonzero status: %x", __FUNCTION__, urb->status);
  1098 + return;
  1099 + }
  1100 +
  1101 + if (urb->actual_length != sizeof(struct keyspan_usa67_portStatusMessage)) {
  1102 + dbg("%s - bad length %d", __FUNCTION__, urb->actual_length);
  1103 + return;
  1104 + }
  1105 +
  1106 +
  1107 + /* Now do something useful with the data */
  1108 + msg = (struct keyspan_usa67_portStatusMessage *)data;
  1109 +
  1110 + /* Check port number from message and retrieve private data */
  1111 + if (msg->port >= serial->num_ports) {
  1112 + dbg ("%s - Unexpected port number %d", __FUNCTION__, msg->port);
  1113 + return;
  1114 + }
  1115 +
  1116 + port = serial->port[msg->port];
  1117 + p_priv = usb_get_serial_port_data(port);
  1118 +
  1119 + /* Update handshaking pin state information */
  1120 + old_dcd_state = p_priv->dcd_state;
  1121 + p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
  1122 + p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
  1123 +
  1124 + if (port->tty && !C_CLOCAL(port->tty)
  1125 + && old_dcd_state != p_priv->dcd_state) {
  1126 + if (old_dcd_state)
  1127 + tty_hangup(port->tty);
  1128 + /* else */
  1129 + /* wake_up_interruptible(&p_priv->open_wait); */
  1130 + }
  1131 +
  1132 + /* Resubmit urb so we continue receiving */
  1133 + urb->dev = serial->dev;
  1134 + err = usb_submit_urb(urb, GFP_ATOMIC);
  1135 + if (err != 0)
  1136 + dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
  1137 +}
  1138 +
  1139 +static void usa67_glocont_callback(struct urb *urb)
  1140 +{
  1141 + struct usb_serial *serial;
  1142 + struct usb_serial_port *port;
  1143 + struct keyspan_port_private *p_priv;
  1144 + int i;
  1145 +
  1146 + dbg ("%s", __FUNCTION__);
  1147 +
  1148 + serial = urb->context;
  1149 + for (i = 0; i < serial->num_ports; ++i) {
  1150 + port = serial->port[i];
  1151 + p_priv = usb_get_serial_port_data(port);
  1152 +
  1153 + if (p_priv->resend_cont) {
  1154 + dbg ("%s - sending setup", __FUNCTION__);
  1155 + keyspan_usa67_send_setup(serial, port,
  1156 + p_priv->resend_cont - 1);
  1157 + break;
  1158 + }
  1159 + }
  1160 +}
  1161 +
998 1162 static int keyspan_write_room (struct usb_serial_port *port)
999 1163 {
1000 1164 struct keyspan_port_private *p_priv;
... ... @@ -1311,6 +1475,11 @@
1311 1475 return NULL;
1312 1476 }
1313 1477  
  1478 + if (endpoint == 0) {
  1479 + /* control EP filled in when used */
  1480 + return urb;
  1481 + }
  1482 +
1314 1483 ep_desc = find_ep(serial, endpoint);
1315 1484 if (!ep_desc) {
1316 1485 /* leak the urb, something's wrong and the callers don't care */
... ... @@ -1380,6 +1549,14 @@
1380 1549 .outdat_callback = usa2x_outdat_callback,
1381 1550 .inack_callback = usa28_inack_callback,
1382 1551 .outcont_callback = usa90_outcont_callback,
  1552 + }, {
  1553 + /* msg_usa67 callbacks */
  1554 + .instat_callback = usa67_instat_callback,
  1555 + .glocont_callback = usa67_glocont_callback,
  1556 + .indat_callback = usa26_indat_callback,
  1557 + .outdat_callback = usa2x_outdat_callback,
  1558 + .inack_callback = usa26_inack_callback,
  1559 + .outcont_callback = usa26_outcont_callback,
1383 1560 }
1384 1561 };
1385 1562  
... ... @@ -1410,6 +1587,11 @@
1410 1587 serial, s_priv->instat_buf, INSTAT_BUFLEN,
1411 1588 cback->instat_callback);
1412 1589  
  1590 + s_priv->indat_urb = keyspan_setup_urb
  1591 + (serial, d_details->indat_endpoint, USB_DIR_IN,
  1592 + serial, s_priv->indat_buf, INDAT49W_BUFLEN,
  1593 + usa49wg_indat_callback);
  1594 +
1413 1595 s_priv->glocont_urb = keyspan_setup_urb
1414 1596 (serial, d_details->glocont_endpoint, USB_DIR_OUT,
1415 1597 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
... ... @@ -1685,8 +1867,8 @@
1685 1867 }
1686 1868  
1687 1869 /* Save reset port val for resend.
1688   - Don't overwrite resend for close condition. */
1689   - if (p_priv->resend_cont != 3)
  1870 + Don't overwrite resend for open/close condition. */
  1871 + if ((reset_port + 1) > p_priv->resend_cont)
1690 1872 p_priv->resend_cont = reset_port + 1;
1691 1873 if (this_urb->status == -EINPROGRESS) {
1692 1874 /* dbg ("%s - already writing", __FUNCTION__); */
... ... @@ -1836,8 +2018,8 @@
1836 2018 }
1837 2019  
1838 2020 /* Save reset port val for resend.
1839   - Don't overwrite resend for close condition. */
1840   - if (p_priv->resend_cont != 3)
  2021 + Don't overwrite resend for open/close condition. */
  2022 + if ((reset_port + 1) > p_priv->resend_cont)
1841 2023 p_priv->resend_cont = reset_port + 1;
1842 2024 if (this_urb->status == -EINPROGRESS) {
1843 2025 dbg ("%s already writing", __FUNCTION__);
1844 2026  
... ... @@ -1940,11 +2122,11 @@
1940 2122 struct usb_serial_port *port,
1941 2123 int reset_port)
1942 2124 {
1943   - struct keyspan_usa49_portControlMessage msg;
  2125 + struct keyspan_usa49_portControlMessage msg;
  2126 + struct usb_ctrlrequest *dr = NULL;
1944 2127 struct keyspan_serial_private *s_priv;
1945 2128 struct keyspan_port_private *p_priv;
1946 2129 const struct keyspan_device_details *d_details;
1947   - int glocont_urb;
1948 2130 struct urb *this_urb;
1949 2131 int err, device_port;
1950 2132  
1951 2133  
... ... @@ -1954,10 +2136,9 @@
1954 2136 p_priv = usb_get_serial_port_data(port);
1955 2137 d_details = s_priv->device_details;
1956 2138  
1957   - glocont_urb = d_details->glocont_endpoint;
1958 2139 this_urb = s_priv->glocont_urb;
1959 2140  
1960   - /* Work out which port within the device is being setup */
  2141 + /* Work out which port within the device is being setup */
1961 2142 device_port = port->number - port->serial->minor;
1962 2143  
1963 2144 dbg("%s - endpoint %d port %d (%d)",__FUNCTION__, usb_pipeendpoint(this_urb->pipe), port->number, device_port);
1964 2145  
... ... @@ -1969,9 +2150,10 @@
1969 2150 }
1970 2151  
1971 2152 /* Save reset port val for resend.
1972   - Don't overwrite resend for close condition. */
1973   - if (p_priv->resend_cont != 3)
  2153 + Don't overwrite resend for open/close condition. */
  2154 + if ((reset_port + 1) > p_priv->resend_cont)
1974 2155 p_priv->resend_cont = reset_port + 1;
  2156 +
1975 2157 if (this_urb->status == -EINPROGRESS) {
1976 2158 /* dbg ("%s - already writing", __FUNCTION__); */
1977 2159 mdelay(5);
1978 2160  
1979 2161  
1980 2162  
... ... @@ -2083,20 +2265,39 @@
2083 2265 msg.dtr = p_priv->dtr_state;
2084 2266  
2085 2267 p_priv->resend_cont = 0;
2086   - memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
  2268 +
  2269 + /* if the device is a 49wg, we send control message on usb control EP 0 */
  2270 +
  2271 + if (d_details->product_id == keyspan_usa49wg_product_id) {
  2272 + dr = (void *)(s_priv->ctrl_buf);
  2273 + dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
  2274 + dr->bRequest = 0xB0; /* 49wg control message */;
  2275 + dr->wValue = 0;
  2276 + dr->wIndex = 0;
  2277 + dr->wLength = cpu_to_le16(sizeof(msg));
  2278 +
  2279 + memcpy (s_priv->glocont_buf, &msg, sizeof(msg));
  2280 +
  2281 + usb_fill_control_urb(this_urb, serial->dev, usb_sndctrlpipe(serial->dev, 0),
  2282 + (unsigned char *)dr, s_priv->glocont_buf, sizeof(msg),
  2283 + usa49_glocont_callback, serial);
  2284 +
  2285 + } else {
  2286 + memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2087 2287  
2088   - /* send the data out the device on control endpoint */
2089   - this_urb->transfer_buffer_length = sizeof(msg);
  2288 + /* send the data out the device on control endpoint */
  2289 + this_urb->transfer_buffer_length = sizeof(msg);
2090 2290  
2091   - this_urb->dev = serial->dev;
  2291 + this_urb->dev = serial->dev;
  2292 + }
2092 2293 if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
2093 2294 dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__, err);
2094 2295 }
2095 2296 #if 0
2096 2297 else {
2097 2298 dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __FUNCTION__,
2098   - outcont_urb, this_urb->transfer_buffer_length,
2099   - usb_pipeendpoint(this_urb->pipe));
  2299 + outcont_urb, this_urb->transfer_buffer_length,
  2300 + usb_pipeendpoint(this_urb->pipe));
2100 2301 }
2101 2302 #endif
2102 2303  
... ... @@ -2241,6 +2442,154 @@
2241 2442 return (0);
2242 2443 }
2243 2444  
  2445 +static int keyspan_usa67_send_setup(struct usb_serial *serial,
  2446 + struct usb_serial_port *port,
  2447 + int reset_port)
  2448 +{
  2449 + struct keyspan_usa67_portControlMessage msg;
  2450 + struct keyspan_serial_private *s_priv;
  2451 + struct keyspan_port_private *p_priv;
  2452 + const struct keyspan_device_details *d_details;
  2453 + struct urb *this_urb;
  2454 + int err, device_port;
  2455 +
  2456 + dbg ("%s", __FUNCTION__);
  2457 +
  2458 + s_priv = usb_get_serial_data(serial);
  2459 + p_priv = usb_get_serial_port_data(port);
  2460 + d_details = s_priv->device_details;
  2461 +
  2462 + this_urb = s_priv->glocont_urb;
  2463 +
  2464 + /* Work out which port within the device is being setup */
  2465 + device_port = port->number - port->serial->minor;
  2466 +
  2467 + /* Make sure we have an urb then send the message */
  2468 + if (this_urb == NULL) {
  2469 + dbg("%s - oops no urb for port %d.", __FUNCTION__,
  2470 + port->number);
  2471 + return -1;
  2472 + }
  2473 +
  2474 + /* Save reset port val for resend.
  2475 + Don't overwrite resend for open/close condition. */
  2476 + if ((reset_port + 1) > p_priv->resend_cont)
  2477 + p_priv->resend_cont = reset_port + 1;
  2478 + if (this_urb->status == -EINPROGRESS) {
  2479 + /* dbg ("%s - already writing", __FUNCTION__); */
  2480 + mdelay(5);
  2481 + return(-1);
  2482 + }
  2483 +
  2484 + memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
  2485 +
  2486 + msg.port = device_port;
  2487 +
  2488 + /* Only set baud rate if it's changed */
  2489 + if (p_priv->old_baud != p_priv->baud) {
  2490 + p_priv->old_baud = p_priv->baud;
  2491 + msg.setClocking = 0xff;
  2492 + if (d_details->calculate_baud_rate
  2493 + (p_priv->baud, d_details->baudclk, &msg.baudHi,
  2494 + &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
  2495 + dbg("%s - Invalid baud rate %d requested, using 9600.", __FUNCTION__,
  2496 + p_priv->baud);
  2497 + msg.baudLo = 0;
  2498 + msg.baudHi = 125; /* Values for 9600 baud */
  2499 + msg.prescaler = 10;
  2500 + }
  2501 + msg.setPrescaler = 0xff;
  2502 + }
  2503 +
  2504 + msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
  2505 + switch (p_priv->cflag & CSIZE) {
  2506 + case CS5:
  2507 + msg.lcr |= USA_DATABITS_5;
  2508 + break;
  2509 + case CS6:
  2510 + msg.lcr |= USA_DATABITS_6;
  2511 + break;
  2512 + case CS7:
  2513 + msg.lcr |= USA_DATABITS_7;
  2514 + break;
  2515 + case CS8:
  2516 + msg.lcr |= USA_DATABITS_8;
  2517 + break;
  2518 + }
  2519 + if (p_priv->cflag & PARENB) {
  2520 + /* note USA_PARITY_NONE == 0 */
  2521 + msg.lcr |= (p_priv->cflag & PARODD)?
  2522 + USA_PARITY_ODD: USA_PARITY_EVEN;
  2523 + }
  2524 + msg.setLcr = 0xff;
  2525 +
  2526 + msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
  2527 + msg.xonFlowControl = 0;
  2528 + msg.setFlowControl = 0xff;
  2529 + msg.forwardingLength = 16;
  2530 + msg.xonChar = 17;
  2531 + msg.xoffChar = 19;
  2532 +
  2533 + if (reset_port == 1) {
  2534 + /* Opening port */
  2535 + msg._txOn = 1;
  2536 + msg._txOff = 0;
  2537 + msg.txFlush = 0;
  2538 + msg.txBreak = 0;
  2539 + msg.rxOn = 1;
  2540 + msg.rxOff = 0;
  2541 + msg.rxFlush = 1;
  2542 + msg.rxForward = 0;
  2543 + msg.returnStatus = 0;
  2544 + msg.resetDataToggle = 0xff;
  2545 + } else if (reset_port == 2) {
  2546 + /* Closing port */
  2547 + msg._txOn = 0;
  2548 + msg._txOff = 1;
  2549 + msg.txFlush = 0;
  2550 + msg.txBreak = 0;
  2551 + msg.rxOn = 0;
  2552 + msg.rxOff = 1;
  2553 + msg.rxFlush = 1;
  2554 + msg.rxForward = 0;
  2555 + msg.returnStatus = 0;
  2556 + msg.resetDataToggle = 0;
  2557 + } else {
  2558 + /* Sending intermediate configs */
  2559 + msg._txOn = (! p_priv->break_on);
  2560 + msg._txOff = 0;
  2561 + msg.txFlush = 0;
  2562 + msg.txBreak = (p_priv->break_on);
  2563 + msg.rxOn = 0;
  2564 + msg.rxOff = 0;
  2565 + msg.rxFlush = 0;
  2566 + msg.rxForward = 0;
  2567 + msg.returnStatus = 0;
  2568 + msg.resetDataToggle = 0x0;
  2569 + }
  2570 +
  2571 + /* Do handshaking outputs */
  2572 + msg.setTxTriState_setRts = 0xff;
  2573 + msg.txTriState_rts = p_priv->rts_state;
  2574 +
  2575 + msg.setHskoa_setDtr = 0xff;
  2576 + msg.hskoa_dtr = p_priv->dtr_state;
  2577 +
  2578 + p_priv->resend_cont = 0;
  2579 +
  2580 + memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
  2581 +
  2582 + /* send the data out the device on control endpoint */
  2583 + this_urb->transfer_buffer_length = sizeof(msg);
  2584 + this_urb->dev = serial->dev;
  2585 +
  2586 + err = usb_submit_urb(this_urb, GFP_ATOMIC);
  2587 + if (err != 0)
  2588 + dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__,
  2589 + err);
  2590 + return (0);
  2591 +}
  2592 +
2244 2593 static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
2245 2594 {
2246 2595 struct usb_serial *serial = port->serial;
... ... @@ -2265,6 +2614,9 @@
2265 2614 case msg_usa90:
2266 2615 keyspan_usa90_send_setup(serial, port, reset_port);
2267 2616 break;
  2617 + case msg_usa67:
  2618 + keyspan_usa67_send_setup(serial, port, reset_port);
  2619 + break;
2268 2620 }
2269 2621 }
2270 2622  
2271 2623  
... ... @@ -2313,10 +2665,20 @@
2313 2665  
2314 2666 keyspan_setup_urbs(serial);
2315 2667  
2316   - s_priv->instat_urb->dev = serial->dev;
2317   - if ((err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL)) != 0) {
2318   - dbg("%s - submit instat urb failed %d", __FUNCTION__, err);
  2668 + if (s_priv->instat_urb != NULL) {
  2669 + s_priv->instat_urb->dev = serial->dev;
  2670 + err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
  2671 + if (err != 0)
  2672 + dbg("%s - submit instat urb failed %d", __FUNCTION__,
  2673 + err);
2319 2674 }
  2675 + if (s_priv->indat_urb != NULL) {
  2676 + s_priv->indat_urb->dev = serial->dev;
  2677 + err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
  2678 + if (err != 0)
  2679 + dbg("%s - submit indat urb failed %d", __FUNCTION__,
  2680 + err);
  2681 + }
2320 2682  
2321 2683 return (0);
2322 2684 }
... ... @@ -2335,6 +2697,7 @@
2335 2697 /* Stop reading/writing urbs */
2336 2698 stop_urb(s_priv->instat_urb);
2337 2699 stop_urb(s_priv->glocont_urb);
  2700 + stop_urb(s_priv->indat_urb);
2338 2701 for (i = 0; i < serial->num_ports; ++i) {
2339 2702 port = serial->port[i];
2340 2703 p_priv = usb_get_serial_port_data(port);
... ... @@ -2348,6 +2711,7 @@
2348 2711  
2349 2712 /* Now free them */
2350 2713 usb_free_urb(s_priv->instat_urb);
  2714 + usb_free_urb(s_priv->indat_urb);
2351 2715 usb_free_urb(s_priv->glocont_urb);
2352 2716 for (i = 0; i < serial->num_ports; ++i) {
2353 2717 port = serial->port[i];
drivers/usb/serial/keyspan.h
... ... @@ -99,6 +99,10 @@
99 99 struct usb_serial_port *port,
100 100 int reset_port);
101 101  
  102 +static int keyspan_usa67_send_setup (struct usb_serial *serial,
  103 + struct usb_serial_port *port,
  104 + int reset_port);
  105 +
102 106 /* Struct used for firmware - increased size of data section
103 107 to allow Keyspan's 'C' firmware struct to be used unmodified */
104 108 struct ezusb_hex_record {
105 109  
106 110  
107 111  
... ... @@ -229,15 +233,17 @@
229 233 #define keyspan_usa28_product_id 0x010f
230 234 #define keyspan_usa28x_product_id 0x0110
231 235 #define keyspan_usa28xa_product_id 0x0115
  236 +#define keyspan_usa28xb_product_id 0x0110
  237 +#define keyspan_usa28xg_product_id 0x0135
232 238 #define keyspan_usa49w_product_id 0x010a
233 239 #define keyspan_usa49wlc_product_id 0x012a
  240 +#define keyspan_usa49wg_product_id 0x0131
234 241  
235   -
236 242 struct keyspan_device_details {
237 243 /* product ID value */
238 244 int product_id;
239 245  
240   - enum {msg_usa26, msg_usa28, msg_usa49, msg_usa90} msg_format;
  246 + enum {msg_usa26, msg_usa28, msg_usa49, msg_usa90, msg_usa67} msg_format;
241 247  
242 248 /* Number of physical ports */
243 249 int num_ports;
... ... @@ -264,6 +270,9 @@
264 270 /* Endpoint used for input status */
265 271 int instat_endpoint;
266 272  
  273 + /* Endpoint used for input data 49WG only */
  274 + int indat_endpoint;
  275 +
267 276 /* Endpoint used for global control functions */
268 277 int glocont_endpoint;
269 278  
... ... @@ -287,6 +296,7 @@
287 296 .inack_endpoints = {0x85},
288 297 .outcont_endpoints = {0x05},
289 298 .instat_endpoint = 0x87,
  299 + .indat_endpoint = -1,
290 300 .glocont_endpoint = 0x07,
291 301 .calculate_baud_rate = keyspan_usa19w_calc_baud,
292 302 .baudclk = KEYSPAN_USA18X_BAUDCLK,
... ... @@ -303,6 +313,7 @@
303 313 .inack_endpoints = {0x83},
304 314 .outcont_endpoints = {0x03},
305 315 .instat_endpoint = 0x84,
  316 + .indat_endpoint = -1,
306 317 .glocont_endpoint = -1,
307 318 .calculate_baud_rate = keyspan_usa19_calc_baud,
308 319 .baudclk = KEYSPAN_USA19_BAUDCLK,
... ... @@ -319,6 +330,7 @@
319 330 .inack_endpoints = {0x83},
320 331 .outcont_endpoints = {0x03},
321 332 .instat_endpoint = 0x84,
  333 + .indat_endpoint = -1,
322 334 .glocont_endpoint = -1,
323 335 .calculate_baud_rate = keyspan_usa28_calc_baud,
324 336 .baudclk = KEYSPAN_USA19_BAUDCLK,
... ... @@ -335,6 +347,7 @@
335 347 .inack_endpoints = {0x83},
336 348 .outcont_endpoints = {0x03},
337 349 .instat_endpoint = 0x84,
  350 + .indat_endpoint = -1,
338 351 .glocont_endpoint = -1,
339 352 .calculate_baud_rate = keyspan_usa28_calc_baud,
340 353 .baudclk = KEYSPAN_USA19_BAUDCLK,
... ... @@ -351,6 +364,7 @@
351 364 .inack_endpoints = {0x85},
352 365 .outcont_endpoints = {0x05},
353 366 .instat_endpoint = 0x87,
  367 + .indat_endpoint = -1,
354 368 .glocont_endpoint = 0x07,
355 369 .calculate_baud_rate = keyspan_usa19w_calc_baud,
356 370 .baudclk = KEYSPAN_USA19W_BAUDCLK,
... ... @@ -367,6 +381,7 @@
367 381 .inack_endpoints = {0x85},
368 382 .outcont_endpoints = {0x05},
369 383 .instat_endpoint = 0x87,
  384 + .indat_endpoint = -1,
370 385 .glocont_endpoint = 0x07,
371 386 .calculate_baud_rate = keyspan_usa19w_calc_baud,
372 387 .baudclk = KEYSPAN_USA19W_BAUDCLK,
... ... @@ -383,6 +398,7 @@
383 398 .inack_endpoints = {-1},
384 399 .outcont_endpoints = {0x02},
385 400 .instat_endpoint = 0x82,
  401 + .indat_endpoint = -1,
386 402 .glocont_endpoint = -1,
387 403 .calculate_baud_rate = keyspan_usa19hs_calc_baud,
388 404 .baudclk = KEYSPAN_USA19HS_BAUDCLK,
... ... @@ -399,6 +415,7 @@
399 415 .inack_endpoints = {0x85, 0x86},
400 416 .outcont_endpoints = {0x05, 0x06},
401 417 .instat_endpoint = 0x87,
  418 + .indat_endpoint = -1,
402 419 .glocont_endpoint = 0x07,
403 420 .calculate_baud_rate = keyspan_usa28_calc_baud,
404 421 .baudclk = KEYSPAN_USA28_BAUDCLK,
... ... @@ -415,6 +432,7 @@
415 432 .inack_endpoints = {0x85, 0x86},
416 433 .outcont_endpoints = {0x05, 0x06},
417 434 .instat_endpoint = 0x87,
  435 + .indat_endpoint = -1,
418 436 .glocont_endpoint = 0x07,
419 437 .calculate_baud_rate = keyspan_usa19w_calc_baud,
420 438 .baudclk = KEYSPAN_USA28X_BAUDCLK,
421 439  
... ... @@ -431,11 +449,28 @@
431 449 .inack_endpoints = {0x85, 0x86},
432 450 .outcont_endpoints = {0x05, 0x06},
433 451 .instat_endpoint = 0x87,
  452 + .indat_endpoint = -1,
434 453 .glocont_endpoint = 0x07,
435 454 .calculate_baud_rate = keyspan_usa19w_calc_baud,
436 455 .baudclk = KEYSPAN_USA28X_BAUDCLK,
437 456 };
438 457  
  458 +static const struct keyspan_device_details usa28xg_device_details = {
  459 + .product_id = keyspan_usa28xg_product_id,
  460 + .msg_format = msg_usa67,
  461 + .num_ports = 2,
  462 + .indat_endp_flip = 0,
  463 + .outdat_endp_flip = 0,
  464 + .indat_endpoints = {0x84, 0x88},
  465 + .outdat_endpoints = {0x02, 0x06},
  466 + .inack_endpoints = {-1, -1},
  467 + .outcont_endpoints = {-1, -1},
  468 + .instat_endpoint = 0x81,
  469 + .indat_endpoint = -1,
  470 + .glocont_endpoint = 0x01,
  471 + .calculate_baud_rate = keyspan_usa19w_calc_baud,
  472 + .baudclk = KEYSPAN_USA28X_BAUDCLK,
  473 +};
439 474 /* We don't need a separate entry for the usa28xb as it appears as a 28x anyway */
440 475  
441 476 static const struct keyspan_device_details usa49w_device_details = {
... ... @@ -449,6 +484,7 @@
449 484 .inack_endpoints = {-1, -1, -1, -1},
450 485 .outcont_endpoints = {-1, -1, -1, -1},
451 486 .instat_endpoint = 0x87,
  487 + .indat_endpoint = -1,
452 488 .glocont_endpoint = 0x07,
453 489 .calculate_baud_rate = keyspan_usa19w_calc_baud,
454 490 .baudclk = KEYSPAN_USA49W_BAUDCLK,
455 491  
... ... @@ -465,11 +501,29 @@
465 501 .inack_endpoints = {-1, -1, -1, -1},
466 502 .outcont_endpoints = {-1, -1, -1, -1},
467 503 .instat_endpoint = 0x87,
  504 + .indat_endpoint = -1,
468 505 .glocont_endpoint = 0x07,
469 506 .calculate_baud_rate = keyspan_usa19w_calc_baud,
470 507 .baudclk = KEYSPAN_USA19W_BAUDCLK,
471 508 };
472 509  
  510 +static const struct keyspan_device_details usa49wg_device_details = {
  511 + .product_id = keyspan_usa49wg_product_id,
  512 + .msg_format = msg_usa49,
  513 + .num_ports = 4,
  514 + .indat_endp_flip = 0,
  515 + .outdat_endp_flip = 0,
  516 + .indat_endpoints = {-1, -1, -1, -1}, /* single 'global' data in EP */
  517 + .outdat_endpoints = {0x01, 0x02, 0x04, 0x06},
  518 + .inack_endpoints = {-1, -1, -1, -1},
  519 + .outcont_endpoints = {-1, -1, -1, -1},
  520 + .instat_endpoint = 0x81,
  521 + .indat_endpoint = 0x88,
  522 + .glocont_endpoint = 0x00, /* uses control EP */
  523 + .calculate_baud_rate = keyspan_usa19w_calc_baud,
  524 + .baudclk = KEYSPAN_USA19W_BAUDCLK,
  525 +};
  526 +
473 527 static const struct keyspan_device_details *keyspan_devices[] = {
474 528 &usa18x_device_details,
475 529 &usa19_device_details,
476 530  
... ... @@ -481,9 +535,11 @@
481 535 &usa28_device_details,
482 536 &usa28x_device_details,
483 537 &usa28xa_device_details,
  538 + &usa28xg_device_details,
484 539 /* 28xb not required as it renumerates as a 28x */
485 540 &usa49w_device_details,
486 541 &usa49wlc_device_details,
  542 + &usa49wg_device_details,
487 543 NULL,
488 544 };
489 545  
490 546  
... ... @@ -510,8 +566,11 @@
510 566 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
511 567 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
512 568 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
  569 + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) },
  570 + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) },
513 571 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id)},
514 572 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)},
  573 + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wg_product_id)},
515 574 { } /* Terminating entry */
516 575 };
517 576  
518 577  
... ... @@ -557,12 +616,15 @@
557 616 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
558 617 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
559 618 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
  619 + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) },
  620 + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) },
560 621 { } /* Terminating entry */
561 622 };
562 623  
563 624 static struct usb_device_id keyspan_4port_ids[] = {
564 625 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id) },
565 626 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)},
  627 + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wg_product_id)},
566 628 { } /* Terminating entry */
567 629 };
568 630  
... ... @@ -573,7 +635,6 @@
573 635 .name = "keyspan_no_firm",
574 636 },
575 637 .description = "Keyspan - (without firmware)",
576   - .usb_driver = &keyspan_driver,
577 638 .id_table = keyspan_pre_ids,
578 639 .num_interrupt_in = NUM_DONT_CARE,
579 640 .num_bulk_in = NUM_DONT_CARE,
... ... @@ -588,7 +649,6 @@
588 649 .name = "keyspan_1",
589 650 },
590 651 .description = "Keyspan 1 port adapter",
591   - .usb_driver = &keyspan_driver,
592 652 .id_table = keyspan_1port_ids,
593 653 .num_interrupt_in = NUM_DONT_CARE,
594 654 .num_bulk_in = NUM_DONT_CARE,
... ... @@ -616,7 +676,6 @@
616 676 .name = "keyspan_2",
617 677 },
618 678 .description = "Keyspan 2 port adapter",
619   - .usb_driver = &keyspan_driver,
620 679 .id_table = keyspan_2port_ids,
621 680 .num_interrupt_in = NUM_DONT_CARE,
622 681 .num_bulk_in = NUM_DONT_CARE,
623 682  
... ... @@ -644,11 +703,10 @@
644 703 .name = "keyspan_4",
645 704 },
646 705 .description = "Keyspan 4 port adapter",
647   - .usb_driver = &keyspan_driver,
648 706 .id_table = keyspan_4port_ids,
649 707 .num_interrupt_in = NUM_DONT_CARE,
650   - .num_bulk_in = 5,
651   - .num_bulk_out = 5,
  708 + .num_bulk_in = NUM_DONT_CARE,
  709 + .num_bulk_out = NUM_DONT_CARE,
652 710 .num_ports = 4,
653 711 .open = keyspan_open,
654 712 .close = keyspan_close,
drivers/usb/serial/keyspan_usa67msg.h
  1 +/*
  2 + usa67msg.h
  3 +
  4 + Copyright (c) 1998-2007 InnoSys Incorporated. All Rights Reserved
  5 + This file is available under a BSD-style copyright
  6 +
  7 + Keyspan USB Async Firmware to run on Anchor FX1
  8 +
  9 + Redistribution and use in source and binary forms, with or without
  10 + modification, are permitted provided that the following conditions are
  11 + met:
  12 +
  13 + 1. Redistributions of source code must retain this licence text
  14 + without modification, this list of conditions, and the following
  15 + disclaimer. The following copyright notice must appear immediately at
  16 + the beginning of all source files:
  17 +
  18 + Copyright (c) 1998-2007 InnoSys Incorporated. All Rights Reserved
  19 +
  20 + This file is available under a BSD-style copyright
  21 +
  22 + 2. Redistributions in binary form must reproduce the above copyright
  23 + notice, this list of conditions and the following disclaimer in the
  24 + documentation and/or other materials provided with the distribution.
  25 +
  26 + 3. The name of InnoSys Incorprated may not be used to endorse or promote
  27 + products derived from this software without specific prior written
  28 + permission.
  29 +
  30 + THIS SOFTWARE IS PROVIDED BY INNOSYS CORP. ``AS IS'' AND ANY EXPRESS OR
  31 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  32 + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
  33 + NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  34 + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  35 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  36 + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  37 + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  38 + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  39 + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  40 + SUCH DAMAGE.
  41 +
  42 + Fourth revision: This message format supports the USA28XG
  43 +
  44 + Buffer formats for RX/TX data messages are not defined by
  45 + a structure, but are described here:
  46 +
  47 + USB OUT (host -> USAxx, transmit) messages contain a
  48 + REQUEST_ACK indicator (set to 0xff to request an ACK at the
  49 + completion of transmit; 0x00 otherwise), followed by data:
  50 +
  51 + RQSTACK DAT DAT DAT ...
  52 +
  53 + with a total data length of up to 63.
  54 +
  55 + USB IN (USAxx -> host, receive) messages begin with a status
  56 + byte in which the 0x80 bit is either:
  57 +
  58 + (a) 0x80 bit clear
  59 + indicates that the bytes following it are all data
  60 + bytes:
  61 +
  62 + STAT DATA DATA DATA DATA DATA ...
  63 +
  64 + for a total of up to 63 DATA bytes,
  65 +
  66 + or:
  67 +
  68 + (b) 0x80 bit set
  69 + indiates that the bytes following alternate data and
  70 + status bytes:
  71 +
  72 + STAT DATA STAT DATA STAT DATA STAT DATA ...
  73 +
  74 + for a total of up to 32 DATA bytes.
  75 +
  76 + The valid bits in the STAT bytes are:
  77 +
  78 + OVERRUN 0x02
  79 + PARITY 0x04
  80 + FRAMING 0x08
  81 + BREAK 0x10
  82 +
  83 + Notes:
  84 +
  85 + (1) The OVERRUN bit can appear in either (a) or (b) format
  86 + messages, but the but the PARITY/FRAMING/BREAK bits
  87 + only appear in (b) format messages.
  88 + (2) For the host to determine the exact point at which the
  89 + overrun occurred (to identify the point in the data
  90 + stream at which the data was lost), it needs to count
  91 + 128 characters, starting at the first character of the
  92 + message in which OVERRUN was reported; the lost character(s)
  93 + would have been received between the 128th and 129th
  94 + characters.
  95 + (3) An RX data message in which the first byte has 0x80 clear
  96 + serves as a "break off" indicator.
  97 +
  98 + revision history:
  99 +
  100 + 1999feb10 add reportHskiaChanges to allow us to ignore them
  101 + 1999feb10 add txAckThreshold for fast+loose throughput enhancement
  102 + 1999mar30 beef up support for RX error reporting
  103 + 1999apr14 add resetDataToggle to control message
  104 + 2000jan04 merge with usa17msg.h
  105 + 2000jun01 add extended BSD-style copyright text
  106 + 2001jul05 change message format to improve OVERRUN case
  107 + 2002jun05 update copyright date, improve comments
  108 + 2006feb06 modify for FX1 chip
  109 +
  110 +*/
  111 +
  112 +#ifndef __USA67MSG__
  113 +#define __USA67MSG__
  114 +
  115 +
  116 +// all things called "ControlMessage" are sent on the 'control' endpoint
  117 +
  118 +typedef struct keyspan_usa67_portControlMessage
  119 +{
  120 + u8 port; // 0 or 1 (selects port)
  121 + /*
  122 + there are three types of "commands" sent in the control message:
  123 +
  124 + 1. configuration changes which must be requested by setting
  125 + the corresponding "set" flag (and should only be requested
  126 + when necessary, to reduce overhead on the device):
  127 + */
  128 + u8 setClocking, // host requests baud rate be set
  129 + baudLo, // host does baud divisor calculation
  130 + baudHi, // baudHi is only used for first port (gives lower rates)
  131 + externalClock_txClocking,
  132 + // 0=internal, other=external
  133 +
  134 + setLcr, // host requests lcr be set
  135 + lcr, // use PARITY, STOPBITS, DATABITS below
  136 +
  137 + setFlowControl, // host requests flow control be set
  138 + ctsFlowControl, // 1=use CTS flow control, 0=don't
  139 + xonFlowControl, // 1=use XON/XOFF flow control, 0=don't
  140 + xonChar, // specified in current character format
  141 + xoffChar, // specified in current character format
  142 +
  143 + setTxTriState_setRts,
  144 + // host requests TX tri-state be set
  145 + txTriState_rts, // 1=active (normal), 0=tristate (off)
  146 +
  147 + setHskoa_setDtr,
  148 + // host requests HSKOA output be set
  149 + hskoa_dtr, // 1=on, 0=off
  150 +
  151 + setPrescaler, // host requests prescalar be set (default: 13)
  152 + prescaler; // specified as N/8; values 8-ff are valid
  153 + // must be set any time internal baud rate is set;
  154 + // must not be set when external clocking is used
  155 +
  156 + /*
  157 + 3. configuration data which is simply used as is (no overhead,
  158 + but must be specified correctly in every host message).
  159 + */
  160 + u8 forwardingLength, // forward when this number of chars available
  161 + reportHskiaChanges_dsrFlowControl,
  162 + // 1=normal; 0=ignore external clock
  163 + // 1=use DSR flow control, 0=don't
  164 + txAckThreshold, // 0=not allowed, 1=normal, 2-255 deliver ACK faster
  165 + loopbackMode; // 0=no loopback, 1=loopback enabled
  166 +
  167 + /*
  168 + 4. commands which are flags only; these are processed in order
  169 + (so that, e.g., if both _txOn and _txOff flags are set, the
  170 + port ends in a TX_OFF state); any non-zero value is respected
  171 + */
  172 + u8 _txOn, // enable transmitting (and continue if there's data)
  173 + _txOff, // stop transmitting
  174 + txFlush, // toss outbound data
  175 + txBreak, // turn on break (cleared by _txOn)
  176 + rxOn, // turn on receiver
  177 + rxOff, // turn off receiver
  178 + rxFlush, // toss inbound data
  179 + rxForward, // forward all inbound data, NOW (as if fwdLen==1)
  180 + returnStatus, // return current status (even if it hasn't changed)
  181 + resetDataToggle;// reset data toggle state to DATA0
  182 +
  183 +} keyspan_usa67_portControlMessage;
  184 +
  185 +// defines for bits in lcr
  186 +#define USA_DATABITS_5 0x00
  187 +#define USA_DATABITS_6 0x01
  188 +#define USA_DATABITS_7 0x02
  189 +#define USA_DATABITS_8 0x03
  190 +#define STOPBITS_5678_1 0x00 // 1 stop bit for all byte sizes
  191 +#define STOPBITS_5_1p5 0x04 // 1.5 stop bits for 5-bit byte
  192 +#define STOPBITS_678_2 0x04 // 2 stop bits for 6/7/8-bit byte
  193 +#define USA_PARITY_NONE 0x00
  194 +#define USA_PARITY_ODD 0x08
  195 +#define USA_PARITY_EVEN 0x18
  196 +#define PARITY_1 0x28
  197 +#define PARITY_0 0x38
  198 +
  199 +// all things called "StatusMessage" are sent on the status endpoint
  200 +
  201 +typedef struct keyspan_usa67_portStatusMessage // one for each port
  202 +{
  203 + u8 port, // 0=first, 1=second, other=see below
  204 + hskia_cts, // reports HSKIA pin
  205 + gpia_dcd, // reports GPIA pin
  206 + _txOff, // port has been disabled (by host)
  207 + _txXoff, // port is in XOFF state (either host or RX XOFF)
  208 + txAck, // indicates a TX message acknowledgement
  209 + rxEnabled, // as configured by rxOn/rxOff 1=on, 0=off
  210 + controlResponse;// 1=a control message has been processed
  211 +} keyspan_usa67_portStatusMessage;
  212 +
  213 +// bits in RX data message when STAT byte is included
  214 +#define RXERROR_OVERRUN 0x02
  215 +#define RXERROR_PARITY 0x04
  216 +#define RXERROR_FRAMING 0x08
  217 +#define RXERROR_BREAK 0x10
  218 +
  219 +typedef struct keyspan_usa67_globalControlMessage
  220 +{
  221 + u8 port, // 3
  222 + sendGlobalStatus, // 2=request for two status responses
  223 + resetStatusToggle, // 1=reset global status toggle
  224 + resetStatusCount; // a cycling value
  225 +} keyspan_usa67_globalControlMessage;
  226 +
  227 +typedef struct keyspan_usa67_globalStatusMessage
  228 +{
  229 + u8 port, // 3
  230 + sendGlobalStatus, // from request, decremented
  231 + resetStatusCount; // as in request
  232 +} keyspan_usa67_globalStatusMessage;
  233 +
  234 +typedef struct keyspan_usa67_globalDebugMessage
  235 +{
  236 + u8 port, // 2
  237 + a,
  238 + b,
  239 + c,
  240 + d;
  241 +} keyspan_usa67_globalDebugMessage;
  242 +
  243 +// ie: the maximum length of an FX1 endpoint buffer
  244 +#define MAX_DATA_LEN 64
  245 +
  246 +// update status approx. 60 times a second (16.6666 ms)
  247 +#define STATUS_UPDATE_INTERVAL 16
  248 +
  249 +// status rationing tuning value (each port gets checked each n ms)
  250 +#define STATUS_RATION 10
  251 +
  252 +#endif