Commit 0ca1268e109acf6d71507398cb95cab2e670b654
Committed by
Greg Kroah-Hartman
1 parent
87e71b473e
Exists in
master
and in
7 other branches
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 |