Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Lucy McCoy and committed by
Greg Kroah-Hartman
0ca1268e 87e71b47

+710 -34
+390 -26
drivers/usb/serial/keyspan.c
··· 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 { ··· 130 129 struct urb *instat_urb; 131 130 char instat_buf[INSTAT_BUFLEN]; 132 131 132 + /* added to support 49wg, where data from all 4 ports comes in on 1 EP */ 133 + /* and high-speed supported */ 134 + struct urb *indat_urb; 135 + char indat_buf[INDAT49W_BUFLEN]; 136 + 133 137 /* XXX this one probably will need a lock */ 134 138 struct urb *glocont_urb; 135 139 char glocont_buf[GLOCONT_BUFLEN]; 140 + char ctrl_buf[8]; // for EP0 control message 136 141 }; 137 142 138 143 struct keyspan_port_private { ··· 186 179 187 180 188 181 /* Include Keyspan message headers. All current Keyspan Adapters 189 - make use of one of four message formats which are referred 190 - to as USA-26, USA-28 and USA-49, USA-90 by Keyspan and within this driver. */ 182 + make use of one of five message formats which are referred 183 + to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and within this driver. */ 191 184 #include "keyspan_usa26msg.h" 192 185 #include "keyspan_usa28msg.h" 193 186 #include "keyspan_usa49msg.h" 194 187 #include "keyspan_usa90msg.h" 188 + #include "keyspan_usa67msg.h" 195 189 196 190 197 191 /* Functions used by new usb-serial code. */ ··· 858 850 } 859 851 } 860 852 853 + static void usa49wg_indat_callback(struct urb *urb) 854 + { 855 + int i, len, x, err; 856 + struct usb_serial *serial; 857 + struct usb_serial_port *port; 858 + struct tty_struct *tty; 859 + unsigned char *data = urb->transfer_buffer; 860 + 861 + dbg ("%s", __FUNCTION__); 862 + 863 + serial = urb->context; 864 + 865 + if (urb->status) { 866 + dbg("%s - nonzero status: %x", __FUNCTION__, urb->status); 867 + return; 868 + } 869 + 870 + /* inbound data is in the form P#, len, status, data */ 871 + i = 0; 872 + len = 0; 873 + 874 + if (urb->actual_length) { 875 + while (i < urb->actual_length) { 876 + 877 + /* Check port number from message*/ 878 + if (data[i] >= serial->num_ports) { 879 + dbg ("%s - Unexpected port number %d", 880 + __FUNCTION__, data[i]); 881 + return; 882 + } 883 + port = serial->port[data[i++]]; 884 + tty = port->tty; 885 + len = data[i++]; 886 + 887 + /* 0x80 bit is error flag */ 888 + if ((data[i] & 0x80) == 0) { 889 + /* no error on any byte */ 890 + i++; 891 + for (x = 1; x < len ; ++x) 892 + if (port->open_count) 893 + tty_insert_flip_char(tty, 894 + data[i++], 0); 895 + else 896 + i++; 897 + } else { 898 + /* 899 + * some bytes had errors, every byte has status 900 + */ 901 + for (x = 0; x + 1 < len; x += 2) { 902 + int stat = data[i], flag = 0; 903 + if (stat & RXERROR_OVERRUN) 904 + flag |= TTY_OVERRUN; 905 + if (stat & RXERROR_FRAMING) 906 + flag |= TTY_FRAME; 907 + if (stat & RXERROR_PARITY) 908 + flag |= TTY_PARITY; 909 + /* XXX should handle break (0x10) */ 910 + if (port->open_count) 911 + tty_insert_flip_char(tty, 912 + data[i+1], flag); 913 + i += 2; 914 + } 915 + } 916 + if (port->open_count) 917 + tty_flip_buffer_push(tty); 918 + } 919 + } 920 + 921 + /* Resubmit urb so we continue receiving */ 922 + urb->dev = serial->dev; 923 + 924 + err = usb_submit_urb(urb, GFP_ATOMIC); 925 + if (err != 0) 926 + dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); 927 + } 928 + 861 929 /* not used, usa-49 doesn't have per-port control endpoints */ 862 - static void usa49_outcont_callback(struct urb *urb) 930 + static void usa49_outcont_callback(struct urb *urb) 863 931 { 864 932 dbg ("%s", __FUNCTION__); 865 933 } 866 934 867 - static void usa90_indat_callback(struct urb *urb) 935 + static void usa90_indat_callback(struct urb *urb) 868 936 { 869 937 int i, err; 870 938 int endpoint; ··· 952 868 dbg ("%s", __FUNCTION__); 953 869 954 870 endpoint = usb_pipeendpoint(urb->pipe); 955 - 956 871 957 872 if (urb->status) { 958 873 dbg("%s - nonzero status: %x on endpoint %d.", ··· 1075 992 if (p_priv->resend_cont) { 1076 993 dbg ("%s - sending setup", __FUNCTION__); 1077 994 keyspan_usa90_send_setup(port->serial, port, p_priv->resend_cont - 1); 995 + } 996 + } 997 + 998 + /* Status messages from the 28xg */ 999 + static void usa67_instat_callback(struct urb *urb) 1000 + { 1001 + int err; 1002 + unsigned char *data = urb->transfer_buffer; 1003 + struct keyspan_usa67_portStatusMessage *msg; 1004 + struct usb_serial *serial; 1005 + struct usb_serial_port *port; 1006 + struct keyspan_port_private *p_priv; 1007 + int old_dcd_state; 1008 + 1009 + dbg ("%s", __FUNCTION__); 1010 + 1011 + serial = urb->context; 1012 + 1013 + if (urb->status) { 1014 + dbg("%s - nonzero status: %x", __FUNCTION__, urb->status); 1015 + return; 1016 + } 1017 + 1018 + if (urb->actual_length != sizeof(struct keyspan_usa67_portStatusMessage)) { 1019 + dbg("%s - bad length %d", __FUNCTION__, urb->actual_length); 1020 + return; 1021 + } 1022 + 1023 + 1024 + /* Now do something useful with the data */ 1025 + msg = (struct keyspan_usa67_portStatusMessage *)data; 1026 + 1027 + /* Check port number from message and retrieve private data */ 1028 + if (msg->port >= serial->num_ports) { 1029 + dbg ("%s - Unexpected port number %d", __FUNCTION__, msg->port); 1030 + return; 1031 + } 1032 + 1033 + port = serial->port[msg->port]; 1034 + p_priv = usb_get_serial_port_data(port); 1035 + 1036 + /* Update handshaking pin state information */ 1037 + old_dcd_state = p_priv->dcd_state; 1038 + p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0); 1039 + p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0); 1040 + 1041 + if (port->tty && !C_CLOCAL(port->tty) 1042 + && old_dcd_state != p_priv->dcd_state) { 1043 + if (old_dcd_state) 1044 + tty_hangup(port->tty); 1045 + /* else */ 1046 + /* wake_up_interruptible(&p_priv->open_wait); */ 1047 + } 1048 + 1049 + /* Resubmit urb so we continue receiving */ 1050 + urb->dev = serial->dev; 1051 + err = usb_submit_urb(urb, GFP_ATOMIC); 1052 + if (err != 0) 1053 + dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); 1054 + } 1055 + 1056 + static void usa67_glocont_callback(struct urb *urb) 1057 + { 1058 + struct usb_serial *serial; 1059 + struct usb_serial_port *port; 1060 + struct keyspan_port_private *p_priv; 1061 + int i; 1062 + 1063 + dbg ("%s", __FUNCTION__); 1064 + 1065 + serial = urb->context; 1066 + for (i = 0; i < serial->num_ports; ++i) { 1067 + port = serial->port[i]; 1068 + p_priv = usb_get_serial_port_data(port); 1069 + 1070 + if (p_priv->resend_cont) { 1071 + dbg ("%s - sending setup", __FUNCTION__); 1072 + keyspan_usa67_send_setup(serial, port, 1073 + p_priv->resend_cont - 1); 1074 + break; 1075 + } 1078 1076 } 1079 1077 } 1080 1078 ··· 1475 1311 return NULL; 1476 1312 } 1477 1313 1314 + if (endpoint == 0) { 1315 + /* control EP filled in when used */ 1316 + return urb; 1317 + } 1318 + 1478 1319 ep_desc = find_ep(serial, endpoint); 1479 1320 if (!ep_desc) { 1480 1321 /* leak the urb, something's wrong and the callers don't care */ ··· 1549 1380 .outdat_callback = usa2x_outdat_callback, 1550 1381 .inack_callback = usa28_inack_callback, 1551 1382 .outcont_callback = usa90_outcont_callback, 1383 + }, { 1384 + /* msg_usa67 callbacks */ 1385 + .instat_callback = usa67_instat_callback, 1386 + .glocont_callback = usa67_glocont_callback, 1387 + .indat_callback = usa26_indat_callback, 1388 + .outdat_callback = usa2x_outdat_callback, 1389 + .inack_callback = usa26_inack_callback, 1390 + .outcont_callback = usa26_outcont_callback, 1552 1391 } 1553 1392 }; 1554 1393 ··· 1586 1409 (serial, d_details->instat_endpoint, USB_DIR_IN, 1587 1410 serial, s_priv->instat_buf, INSTAT_BUFLEN, 1588 1411 cback->instat_callback); 1412 + 1413 + s_priv->indat_urb = keyspan_setup_urb 1414 + (serial, d_details->indat_endpoint, USB_DIR_IN, 1415 + serial, s_priv->indat_buf, INDAT49W_BUFLEN, 1416 + usa49wg_indat_callback); 1589 1417 1590 1418 s_priv->glocont_urb = keyspan_setup_urb 1591 1419 (serial, d_details->glocont_endpoint, USB_DIR_OUT, ··· 1867 1685 } 1868 1686 1869 1687 /* Save reset port val for resend. 1870 - Don't overwrite resend for close condition. */ 1871 - if (p_priv->resend_cont != 3) 1688 + Don't overwrite resend for open/close condition. */ 1689 + if ((reset_port + 1) > p_priv->resend_cont) 1872 1690 p_priv->resend_cont = reset_port + 1; 1873 1691 if (this_urb->status == -EINPROGRESS) { 1874 1692 /* dbg ("%s - already writing", __FUNCTION__); */ ··· 2018 1836 } 2019 1837 2020 1838 /* Save reset port val for resend. 2021 - Don't overwrite resend for close condition. */ 2022 - if (p_priv->resend_cont != 3) 1839 + Don't overwrite resend for open/close condition. */ 1840 + if ((reset_port + 1) > p_priv->resend_cont) 2023 1841 p_priv->resend_cont = reset_port + 1; 2024 1842 if (this_urb->status == -EINPROGRESS) { 2025 1843 dbg ("%s already writing", __FUNCTION__); ··· 2122 1940 struct usb_serial_port *port, 2123 1941 int reset_port) 2124 1942 { 2125 - struct keyspan_usa49_portControlMessage msg; 1943 + struct keyspan_usa49_portControlMessage msg; 1944 + struct usb_ctrlrequest *dr = NULL; 2126 1945 struct keyspan_serial_private *s_priv; 2127 1946 struct keyspan_port_private *p_priv; 2128 1947 const struct keyspan_device_details *d_details; 2129 - int glocont_urb; 2130 1948 struct urb *this_urb; 2131 1949 int err, device_port; 2132 1950 ··· 2136 1954 p_priv = usb_get_serial_port_data(port); 2137 1955 d_details = s_priv->device_details; 2138 1956 2139 - glocont_urb = d_details->glocont_endpoint; 2140 1957 this_urb = s_priv->glocont_urb; 2141 1958 2142 - /* Work out which port within the device is being setup */ 1959 + /* Work out which port within the device is being setup */ 2143 1960 device_port = port->number - port->serial->minor; 2144 1961 2145 1962 dbg("%s - endpoint %d port %d (%d)",__FUNCTION__, usb_pipeendpoint(this_urb->pipe), port->number, device_port); ··· 2150 1969 } 2151 1970 2152 1971 /* Save reset port val for resend. 2153 - Don't overwrite resend for close condition. */ 2154 - if (p_priv->resend_cont != 3) 1972 + Don't overwrite resend for open/close condition. */ 1973 + if ((reset_port + 1) > p_priv->resend_cont) 2155 1974 p_priv->resend_cont = reset_port + 1; 1975 + 2156 1976 if (this_urb->status == -EINPROGRESS) { 2157 1977 /* dbg ("%s - already writing", __FUNCTION__); */ 2158 1978 mdelay(5); ··· 2265 2083 msg.dtr = p_priv->dtr_state; 2266 2084 2267 2085 p_priv->resend_cont = 0; 2268 - memcpy (this_urb->transfer_buffer, &msg, sizeof(msg)); 2269 - 2270 - /* send the data out the device on control endpoint */ 2271 - this_urb->transfer_buffer_length = sizeof(msg); 2272 2086 2273 - this_urb->dev = serial->dev; 2087 + /* if the device is a 49wg, we send control message on usb control EP 0 */ 2088 + 2089 + if (d_details->product_id == keyspan_usa49wg_product_id) { 2090 + dr = (void *)(s_priv->ctrl_buf); 2091 + dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT; 2092 + dr->bRequest = 0xB0; /* 49wg control message */; 2093 + dr->wValue = 0; 2094 + dr->wIndex = 0; 2095 + dr->wLength = cpu_to_le16(sizeof(msg)); 2096 + 2097 + memcpy (s_priv->glocont_buf, &msg, sizeof(msg)); 2098 + 2099 + usb_fill_control_urb(this_urb, serial->dev, usb_sndctrlpipe(serial->dev, 0), 2100 + (unsigned char *)dr, s_priv->glocont_buf, sizeof(msg), 2101 + usa49_glocont_callback, serial); 2102 + 2103 + } else { 2104 + memcpy(this_urb->transfer_buffer, &msg, sizeof(msg)); 2105 + 2106 + /* send the data out the device on control endpoint */ 2107 + this_urb->transfer_buffer_length = sizeof(msg); 2108 + 2109 + this_urb->dev = serial->dev; 2110 + } 2274 2111 if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) { 2275 2112 dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__, err); 2276 2113 } 2277 2114 #if 0 2278 2115 else { 2279 2116 dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __FUNCTION__, 2280 - outcont_urb, this_urb->transfer_buffer_length, 2281 - usb_pipeendpoint(this_urb->pipe)); 2117 + outcont_urb, this_urb->transfer_buffer_length, 2118 + usb_pipeendpoint(this_urb->pipe)); 2282 2119 } 2283 2120 #endif 2284 2121 ··· 2442 2241 return (0); 2443 2242 } 2444 2243 2244 + static int keyspan_usa67_send_setup(struct usb_serial *serial, 2245 + struct usb_serial_port *port, 2246 + int reset_port) 2247 + { 2248 + struct keyspan_usa67_portControlMessage msg; 2249 + struct keyspan_serial_private *s_priv; 2250 + struct keyspan_port_private *p_priv; 2251 + const struct keyspan_device_details *d_details; 2252 + struct urb *this_urb; 2253 + int err, device_port; 2254 + 2255 + dbg ("%s", __FUNCTION__); 2256 + 2257 + s_priv = usb_get_serial_data(serial); 2258 + p_priv = usb_get_serial_port_data(port); 2259 + d_details = s_priv->device_details; 2260 + 2261 + this_urb = s_priv->glocont_urb; 2262 + 2263 + /* Work out which port within the device is being setup */ 2264 + device_port = port->number - port->serial->minor; 2265 + 2266 + /* Make sure we have an urb then send the message */ 2267 + if (this_urb == NULL) { 2268 + dbg("%s - oops no urb for port %d.", __FUNCTION__, 2269 + port->number); 2270 + return -1; 2271 + } 2272 + 2273 + /* Save reset port val for resend. 2274 + Don't overwrite resend for open/close condition. */ 2275 + if ((reset_port + 1) > p_priv->resend_cont) 2276 + p_priv->resend_cont = reset_port + 1; 2277 + if (this_urb->status == -EINPROGRESS) { 2278 + /* dbg ("%s - already writing", __FUNCTION__); */ 2279 + mdelay(5); 2280 + return(-1); 2281 + } 2282 + 2283 + memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage)); 2284 + 2285 + msg.port = device_port; 2286 + 2287 + /* Only set baud rate if it's changed */ 2288 + if (p_priv->old_baud != p_priv->baud) { 2289 + p_priv->old_baud = p_priv->baud; 2290 + msg.setClocking = 0xff; 2291 + if (d_details->calculate_baud_rate 2292 + (p_priv->baud, d_details->baudclk, &msg.baudHi, 2293 + &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) { 2294 + dbg("%s - Invalid baud rate %d requested, using 9600.", __FUNCTION__, 2295 + p_priv->baud); 2296 + msg.baudLo = 0; 2297 + msg.baudHi = 125; /* Values for 9600 baud */ 2298 + msg.prescaler = 10; 2299 + } 2300 + msg.setPrescaler = 0xff; 2301 + } 2302 + 2303 + msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1; 2304 + switch (p_priv->cflag & CSIZE) { 2305 + case CS5: 2306 + msg.lcr |= USA_DATABITS_5; 2307 + break; 2308 + case CS6: 2309 + msg.lcr |= USA_DATABITS_6; 2310 + break; 2311 + case CS7: 2312 + msg.lcr |= USA_DATABITS_7; 2313 + break; 2314 + case CS8: 2315 + msg.lcr |= USA_DATABITS_8; 2316 + break; 2317 + } 2318 + if (p_priv->cflag & PARENB) { 2319 + /* note USA_PARITY_NONE == 0 */ 2320 + msg.lcr |= (p_priv->cflag & PARODD)? 2321 + USA_PARITY_ODD: USA_PARITY_EVEN; 2322 + } 2323 + msg.setLcr = 0xff; 2324 + 2325 + msg.ctsFlowControl = (p_priv->flow_control == flow_cts); 2326 + msg.xonFlowControl = 0; 2327 + msg.setFlowControl = 0xff; 2328 + msg.forwardingLength = 16; 2329 + msg.xonChar = 17; 2330 + msg.xoffChar = 19; 2331 + 2332 + if (reset_port == 1) { 2333 + /* Opening port */ 2334 + msg._txOn = 1; 2335 + msg._txOff = 0; 2336 + msg.txFlush = 0; 2337 + msg.txBreak = 0; 2338 + msg.rxOn = 1; 2339 + msg.rxOff = 0; 2340 + msg.rxFlush = 1; 2341 + msg.rxForward = 0; 2342 + msg.returnStatus = 0; 2343 + msg.resetDataToggle = 0xff; 2344 + } else if (reset_port == 2) { 2345 + /* Closing port */ 2346 + msg._txOn = 0; 2347 + msg._txOff = 1; 2348 + msg.txFlush = 0; 2349 + msg.txBreak = 0; 2350 + msg.rxOn = 0; 2351 + msg.rxOff = 1; 2352 + msg.rxFlush = 1; 2353 + msg.rxForward = 0; 2354 + msg.returnStatus = 0; 2355 + msg.resetDataToggle = 0; 2356 + } else { 2357 + /* Sending intermediate configs */ 2358 + msg._txOn = (! p_priv->break_on); 2359 + msg._txOff = 0; 2360 + msg.txFlush = 0; 2361 + msg.txBreak = (p_priv->break_on); 2362 + msg.rxOn = 0; 2363 + msg.rxOff = 0; 2364 + msg.rxFlush = 0; 2365 + msg.rxForward = 0; 2366 + msg.returnStatus = 0; 2367 + msg.resetDataToggle = 0x0; 2368 + } 2369 + 2370 + /* Do handshaking outputs */ 2371 + msg.setTxTriState_setRts = 0xff; 2372 + msg.txTriState_rts = p_priv->rts_state; 2373 + 2374 + msg.setHskoa_setDtr = 0xff; 2375 + msg.hskoa_dtr = p_priv->dtr_state; 2376 + 2377 + p_priv->resend_cont = 0; 2378 + 2379 + memcpy(this_urb->transfer_buffer, &msg, sizeof(msg)); 2380 + 2381 + /* send the data out the device on control endpoint */ 2382 + this_urb->transfer_buffer_length = sizeof(msg); 2383 + this_urb->dev = serial->dev; 2384 + 2385 + err = usb_submit_urb(this_urb, GFP_ATOMIC); 2386 + if (err != 0) 2387 + dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__, 2388 + err); 2389 + return (0); 2390 + } 2391 + 2445 2392 static void keyspan_send_setup(struct usb_serial_port *port, int reset_port) 2446 2393 { 2447 2394 struct usb_serial *serial = port->serial; ··· 2613 2264 break; 2614 2265 case msg_usa90: 2615 2266 keyspan_usa90_send_setup(serial, port, reset_port); 2267 + break; 2268 + case msg_usa67: 2269 + keyspan_usa67_send_setup(serial, port, reset_port); 2616 2270 break; 2617 2271 } 2618 2272 } ··· 2665 2313 2666 2314 keyspan_setup_urbs(serial); 2667 2315 2668 - s_priv->instat_urb->dev = serial->dev; 2669 - if ((err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL)) != 0) { 2670 - dbg("%s - submit instat urb failed %d", __FUNCTION__, err); 2316 + if (s_priv->instat_urb != NULL) { 2317 + s_priv->instat_urb->dev = serial->dev; 2318 + err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL); 2319 + if (err != 0) 2320 + dbg("%s - submit instat urb failed %d", __FUNCTION__, 2321 + err); 2322 + } 2323 + if (s_priv->indat_urb != NULL) { 2324 + s_priv->indat_urb->dev = serial->dev; 2325 + err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL); 2326 + if (err != 0) 2327 + dbg("%s - submit indat urb failed %d", __FUNCTION__, 2328 + err); 2671 2329 } 2672 2330 2673 2331 return (0); ··· 2697 2335 /* Stop reading/writing urbs */ 2698 2336 stop_urb(s_priv->instat_urb); 2699 2337 stop_urb(s_priv->glocont_urb); 2338 + stop_urb(s_priv->indat_urb); 2700 2339 for (i = 0; i < serial->num_ports; ++i) { 2701 2340 port = serial->port[i]; 2702 2341 p_priv = usb_get_serial_port_data(port); ··· 2711 2348 2712 2349 /* Now free them */ 2713 2350 usb_free_urb(s_priv->instat_urb); 2351 + usb_free_urb(s_priv->indat_urb); 2714 2352 usb_free_urb(s_priv->glocont_urb); 2715 2353 for (i = 0; i < serial->num_ports; ++i) { 2716 2354 port = serial->port[i];
+66 -8
drivers/usb/serial/keyspan.h
··· 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 { ··· 233 229 #define keyspan_usa28_product_id 0x010f 234 230 #define keyspan_usa28x_product_id 0x0110 235 231 #define keyspan_usa28xa_product_id 0x0115 232 + #define keyspan_usa28xb_product_id 0x0110 233 + #define keyspan_usa28xg_product_id 0x0135 236 234 #define keyspan_usa49w_product_id 0x010a 237 235 #define keyspan_usa49wlc_product_id 0x012a 238 - 236 + #define keyspan_usa49wg_product_id 0x0131 239 237 240 238 struct keyspan_device_details { 241 239 /* product ID value */ 242 240 int product_id; 243 241 244 - enum {msg_usa26, msg_usa28, msg_usa49, msg_usa90} msg_format; 242 + enum {msg_usa26, msg_usa28, msg_usa49, msg_usa90, msg_usa67} msg_format; 245 243 246 244 /* Number of physical ports */ 247 245 int num_ports; ··· 270 264 /* Endpoint used for input status */ 271 265 int instat_endpoint; 272 266 267 + /* Endpoint used for input data 49WG only */ 268 + int indat_endpoint; 269 + 273 270 /* Endpoint used for global control functions */ 274 271 int glocont_endpoint; 275 272 ··· 296 287 .inack_endpoints = {0x85}, 297 288 .outcont_endpoints = {0x05}, 298 289 .instat_endpoint = 0x87, 290 + .indat_endpoint = -1, 299 291 .glocont_endpoint = 0x07, 300 292 .calculate_baud_rate = keyspan_usa19w_calc_baud, 301 293 .baudclk = KEYSPAN_USA18X_BAUDCLK, ··· 313 303 .inack_endpoints = {0x83}, 314 304 .outcont_endpoints = {0x03}, 315 305 .instat_endpoint = 0x84, 306 + .indat_endpoint = -1, 316 307 .glocont_endpoint = -1, 317 308 .calculate_baud_rate = keyspan_usa19_calc_baud, 318 309 .baudclk = KEYSPAN_USA19_BAUDCLK, ··· 330 319 .inack_endpoints = {0x83}, 331 320 .outcont_endpoints = {0x03}, 332 321 .instat_endpoint = 0x84, 322 + .indat_endpoint = -1, 333 323 .glocont_endpoint = -1, 334 324 .calculate_baud_rate = keyspan_usa28_calc_baud, 335 325 .baudclk = KEYSPAN_USA19_BAUDCLK, ··· 347 335 .inack_endpoints = {0x83}, 348 336 .outcont_endpoints = {0x03}, 349 337 .instat_endpoint = 0x84, 338 + .indat_endpoint = -1, 350 339 .glocont_endpoint = -1, 351 340 .calculate_baud_rate = keyspan_usa28_calc_baud, 352 341 .baudclk = KEYSPAN_USA19_BAUDCLK, ··· 364 351 .inack_endpoints = {0x85}, 365 352 .outcont_endpoints = {0x05}, 366 353 .instat_endpoint = 0x87, 354 + .indat_endpoint = -1, 367 355 .glocont_endpoint = 0x07, 368 356 .calculate_baud_rate = keyspan_usa19w_calc_baud, 369 357 .baudclk = KEYSPAN_USA19W_BAUDCLK, ··· 381 367 .inack_endpoints = {0x85}, 382 368 .outcont_endpoints = {0x05}, 383 369 .instat_endpoint = 0x87, 370 + .indat_endpoint = -1, 384 371 .glocont_endpoint = 0x07, 385 372 .calculate_baud_rate = keyspan_usa19w_calc_baud, 386 373 .baudclk = KEYSPAN_USA19W_BAUDCLK, ··· 398 383 .inack_endpoints = {-1}, 399 384 .outcont_endpoints = {0x02}, 400 385 .instat_endpoint = 0x82, 386 + .indat_endpoint = -1, 401 387 .glocont_endpoint = -1, 402 388 .calculate_baud_rate = keyspan_usa19hs_calc_baud, 403 389 .baudclk = KEYSPAN_USA19HS_BAUDCLK, ··· 415 399 .inack_endpoints = {0x85, 0x86}, 416 400 .outcont_endpoints = {0x05, 0x06}, 417 401 .instat_endpoint = 0x87, 402 + .indat_endpoint = -1, 418 403 .glocont_endpoint = 0x07, 419 404 .calculate_baud_rate = keyspan_usa28_calc_baud, 420 405 .baudclk = KEYSPAN_USA28_BAUDCLK, ··· 432 415 .inack_endpoints = {0x85, 0x86}, 433 416 .outcont_endpoints = {0x05, 0x06}, 434 417 .instat_endpoint = 0x87, 418 + .indat_endpoint = -1, 435 419 .glocont_endpoint = 0x07, 436 420 .calculate_baud_rate = keyspan_usa19w_calc_baud, 437 421 .baudclk = KEYSPAN_USA28X_BAUDCLK, ··· 449 431 .inack_endpoints = {0x85, 0x86}, 450 432 .outcont_endpoints = {0x05, 0x06}, 451 433 .instat_endpoint = 0x87, 434 + .indat_endpoint = -1, 452 435 .glocont_endpoint = 0x07, 453 436 .calculate_baud_rate = keyspan_usa19w_calc_baud, 454 437 .baudclk = KEYSPAN_USA28X_BAUDCLK, 455 438 }; 456 439 440 + static const struct keyspan_device_details usa28xg_device_details = { 441 + .product_id = keyspan_usa28xg_product_id, 442 + .msg_format = msg_usa67, 443 + .num_ports = 2, 444 + .indat_endp_flip = 0, 445 + .outdat_endp_flip = 0, 446 + .indat_endpoints = {0x84, 0x88}, 447 + .outdat_endpoints = {0x02, 0x06}, 448 + .inack_endpoints = {-1, -1}, 449 + .outcont_endpoints = {-1, -1}, 450 + .instat_endpoint = 0x81, 451 + .indat_endpoint = -1, 452 + .glocont_endpoint = 0x01, 453 + .calculate_baud_rate = keyspan_usa19w_calc_baud, 454 + .baudclk = KEYSPAN_USA28X_BAUDCLK, 455 + }; 457 456 /* We don't need a separate entry for the usa28xb as it appears as a 28x anyway */ 458 457 459 458 static const struct keyspan_device_details usa49w_device_details = { ··· 484 449 .inack_endpoints = {-1, -1, -1, -1}, 485 450 .outcont_endpoints = {-1, -1, -1, -1}, 486 451 .instat_endpoint = 0x87, 452 + .indat_endpoint = -1, 487 453 .glocont_endpoint = 0x07, 488 454 .calculate_baud_rate = keyspan_usa19w_calc_baud, 489 455 .baudclk = KEYSPAN_USA49W_BAUDCLK, ··· 501 465 .inack_endpoints = {-1, -1, -1, -1}, 502 466 .outcont_endpoints = {-1, -1, -1, -1}, 503 467 .instat_endpoint = 0x87, 468 + .indat_endpoint = -1, 504 469 .glocont_endpoint = 0x07, 470 + .calculate_baud_rate = keyspan_usa19w_calc_baud, 471 + .baudclk = KEYSPAN_USA19W_BAUDCLK, 472 + }; 473 + 474 + static const struct keyspan_device_details usa49wg_device_details = { 475 + .product_id = keyspan_usa49wg_product_id, 476 + .msg_format = msg_usa49, 477 + .num_ports = 4, 478 + .indat_endp_flip = 0, 479 + .outdat_endp_flip = 0, 480 + .indat_endpoints = {-1, -1, -1, -1}, /* single 'global' data in EP */ 481 + .outdat_endpoints = {0x01, 0x02, 0x04, 0x06}, 482 + .inack_endpoints = {-1, -1, -1, -1}, 483 + .outcont_endpoints = {-1, -1, -1, -1}, 484 + .instat_endpoint = 0x81, 485 + .indat_endpoint = 0x88, 486 + .glocont_endpoint = 0x00, /* uses control EP */ 505 487 .calculate_baud_rate = keyspan_usa19w_calc_baud, 506 488 .baudclk = KEYSPAN_USA19W_BAUDCLK, 507 489 }; ··· 535 481 &usa28_device_details, 536 482 &usa28x_device_details, 537 483 &usa28xa_device_details, 484 + &usa28xg_device_details, 538 485 /* 28xb not required as it renumerates as a 28x */ 539 486 &usa49w_device_details, 540 487 &usa49wlc_device_details, 488 + &usa49wg_device_details, 541 489 NULL, 542 490 }; 543 491 ··· 566 510 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) }, 567 511 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) }, 568 512 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) }, 513 + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) }, 514 + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) }, 569 515 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id)}, 570 516 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)}, 517 + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wg_product_id)}, 571 518 { } /* Terminating entry */ 572 519 }; 573 520 ··· 616 557 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) }, 617 558 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) }, 618 559 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) }, 560 + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) }, 561 + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) }, 619 562 { } /* Terminating entry */ 620 563 }; 621 564 622 565 static struct usb_device_id keyspan_4port_ids[] = { 623 566 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id) }, 624 567 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)}, 568 + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wg_product_id)}, 625 569 { } /* Terminating entry */ 626 570 }; 627 571 ··· 635 573 .name = "keyspan_no_firm", 636 574 }, 637 575 .description = "Keyspan - (without firmware)", 638 - .usb_driver = &keyspan_driver, 639 576 .id_table = keyspan_pre_ids, 640 577 .num_interrupt_in = NUM_DONT_CARE, 641 578 .num_bulk_in = NUM_DONT_CARE, ··· 649 588 .name = "keyspan_1", 650 589 }, 651 590 .description = "Keyspan 1 port adapter", 652 - .usb_driver = &keyspan_driver, 653 591 .id_table = keyspan_1port_ids, 654 592 .num_interrupt_in = NUM_DONT_CARE, 655 593 .num_bulk_in = NUM_DONT_CARE, ··· 676 616 .name = "keyspan_2", 677 617 }, 678 618 .description = "Keyspan 2 port adapter", 679 - .usb_driver = &keyspan_driver, 680 619 .id_table = keyspan_2port_ids, 681 620 .num_interrupt_in = NUM_DONT_CARE, 682 621 .num_bulk_in = NUM_DONT_CARE, ··· 703 644 .name = "keyspan_4", 704 645 }, 705 646 .description = "Keyspan 4 port adapter", 706 - .usb_driver = &keyspan_driver, 707 647 .id_table = keyspan_4port_ids, 708 648 .num_interrupt_in = NUM_DONT_CARE, 709 - .num_bulk_in = 5, 710 - .num_bulk_out = 5, 649 + .num_bulk_in = NUM_DONT_CARE, 650 + .num_bulk_out = NUM_DONT_CARE, 711 651 .num_ports = 4, 712 652 .open = keyspan_open, 713 653 .close = keyspan_close,
+254
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 253 + 254 +