diff options
author | Lucy McCoy <lucy@keyspan.com> | 2007-05-18 15:10:41 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-07-12 19:29:45 -0400 |
commit | 0ca1268e109acf6d71507398cb95cab2e670b654 (patch) | |
tree | e73f21cb8313651b9e3616c601868ef09fbc6382 | |
parent | 87e71b473ee199cf4b7b7a0ce890cd01f45e3a0e (diff) |
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>
-rw-r--r-- | drivers/usb/serial/keyspan.c | 414 | ||||
-rw-r--r-- | drivers/usb/serial/keyspan.h | 74 | ||||
-rw-r--r-- | drivers/usb/serial/keyspan_usa67msg.h | 254 |
3 files changed, 709 insertions, 33 deletions
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index e6966f12ed5a..fa91ddee2458 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c | |||
@@ -115,12 +115,13 @@ static int debug; | |||
115 | /* | 115 | /* |
116 | * Version Information | 116 | * Version Information |
117 | */ | 117 | */ |
118 | #define DRIVER_VERSION "v1.1.4" | 118 | #define DRIVER_VERSION "v1.1.5" |
119 | #define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu" | 119 | #define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu" |
120 | #define DRIVER_DESC "Keyspan USB to Serial Converter Driver" | 120 | #define DRIVER_DESC "Keyspan USB to Serial Converter Driver" |
121 | 121 | ||
122 | #define INSTAT_BUFLEN 32 | 122 | #define INSTAT_BUFLEN 32 |
123 | #define GLOCONT_BUFLEN 64 | 123 | #define GLOCONT_BUFLEN 64 |
124 | #define INDAT49W_BUFLEN 512 | ||
124 | 125 | ||
125 | /* Per device and per port private data */ | 126 | /* Per device and per port private data */ |
126 | struct keyspan_serial_private { | 127 | struct keyspan_serial_private { |
@@ -129,9 +130,15 @@ struct keyspan_serial_private { | |||
129 | struct urb *instat_urb; | 130 | struct urb *instat_urb; |
130 | char instat_buf[INSTAT_BUFLEN]; | 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 | /* XXX this one probably will need a lock */ | 138 | /* XXX this one probably will need a lock */ |
133 | struct urb *glocont_urb; | 139 | struct urb *glocont_urb; |
134 | char glocont_buf[GLOCONT_BUFLEN]; | 140 | char glocont_buf[GLOCONT_BUFLEN]; |
141 | char ctrl_buf[8]; // for EP0 control message | ||
135 | }; | 142 | }; |
136 | 143 | ||
137 | struct keyspan_port_private { | 144 | struct keyspan_port_private { |
@@ -179,12 +186,13 @@ struct keyspan_port_private { | |||
179 | 186 | ||
180 | 187 | ||
181 | /* Include Keyspan message headers. All current Keyspan Adapters | 188 | /* Include Keyspan message headers. All current Keyspan Adapters |
182 | make use of one of four message formats which are referred | 189 | make use of one of five message formats which are referred |
183 | to as USA-26, USA-28 and USA-49, USA-90 by Keyspan and within this driver. */ | 190 | to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and within this driver. */ |
184 | #include "keyspan_usa26msg.h" | 191 | #include "keyspan_usa26msg.h" |
185 | #include "keyspan_usa28msg.h" | 192 | #include "keyspan_usa28msg.h" |
186 | #include "keyspan_usa49msg.h" | 193 | #include "keyspan_usa49msg.h" |
187 | #include "keyspan_usa90msg.h" | 194 | #include "keyspan_usa90msg.h" |
195 | #include "keyspan_usa67msg.h" | ||
188 | 196 | ||
189 | 197 | ||
190 | /* Functions used by new usb-serial code. */ | 198 | /* Functions used by new usb-serial code. */ |
@@ -850,13 +858,89 @@ static void usa49_indat_callback(struct urb *urb) | |||
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 | /* not used, usa-49 doesn't have per-port control endpoints */ | 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 | dbg ("%s", __FUNCTION__); | 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 | int i, err; | 945 | int i, err; |
862 | int endpoint; | 946 | int endpoint; |
@@ -869,7 +953,6 @@ static void usa90_indat_callback(struct urb *urb) | |||
869 | 953 | ||
870 | endpoint = usb_pipeendpoint(urb->pipe); | 954 | endpoint = usb_pipeendpoint(urb->pipe); |
871 | 955 | ||
872 | |||
873 | if (urb->status) { | 956 | if (urb->status) { |
874 | dbg("%s - nonzero status: %x on endpoint %d.", | 957 | dbg("%s - nonzero status: %x on endpoint %d.", |
875 | __FUNCTION__, urb->status, endpoint); | 958 | __FUNCTION__, urb->status, endpoint); |
@@ -995,6 +1078,87 @@ static void usa90_outcont_callback(struct urb *urb) | |||
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 | static int keyspan_write_room (struct usb_serial_port *port) | 1162 | static int keyspan_write_room (struct usb_serial_port *port) |
999 | { | 1163 | { |
1000 | struct keyspan_port_private *p_priv; | 1164 | struct keyspan_port_private *p_priv; |
@@ -1311,6 +1475,11 @@ static struct urb *keyspan_setup_urb (struct usb_serial *serial, int endpoint, | |||
1311 | return NULL; | 1475 | return NULL; |
1312 | } | 1476 | } |
1313 | 1477 | ||
1478 | if (endpoint == 0) { | ||
1479 | /* control EP filled in when used */ | ||
1480 | return urb; | ||
1481 | } | ||
1482 | |||
1314 | ep_desc = find_ep(serial, endpoint); | 1483 | ep_desc = find_ep(serial, endpoint); |
1315 | if (!ep_desc) { | 1484 | if (!ep_desc) { |
1316 | /* leak the urb, something's wrong and the callers don't care */ | 1485 | /* leak the urb, something's wrong and the callers don't care */ |
@@ -1380,6 +1549,14 @@ static struct callbacks { | |||
1380 | .outdat_callback = usa2x_outdat_callback, | 1549 | .outdat_callback = usa2x_outdat_callback, |
1381 | .inack_callback = usa28_inack_callback, | 1550 | .inack_callback = usa28_inack_callback, |
1382 | .outcont_callback = usa90_outcont_callback, | 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 @@ static void keyspan_setup_urbs(struct usb_serial *serial) | |||
1410 | serial, s_priv->instat_buf, INSTAT_BUFLEN, | 1587 | serial, s_priv->instat_buf, INSTAT_BUFLEN, |
1411 | cback->instat_callback); | 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 | s_priv->glocont_urb = keyspan_setup_urb | 1595 | s_priv->glocont_urb = keyspan_setup_urb |
1414 | (serial, d_details->glocont_endpoint, USB_DIR_OUT, | 1596 | (serial, d_details->glocont_endpoint, USB_DIR_OUT, |
1415 | serial, s_priv->glocont_buf, GLOCONT_BUFLEN, | 1597 | serial, s_priv->glocont_buf, GLOCONT_BUFLEN, |
@@ -1685,8 +1867,8 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial, | |||
1685 | } | 1867 | } |
1686 | 1868 | ||
1687 | /* Save reset port val for resend. | 1869 | /* Save reset port val for resend. |
1688 | Don't overwrite resend for close condition. */ | 1870 | Don't overwrite resend for open/close condition. */ |
1689 | if (p_priv->resend_cont != 3) | 1871 | if ((reset_port + 1) > p_priv->resend_cont) |
1690 | p_priv->resend_cont = reset_port + 1; | 1872 | p_priv->resend_cont = reset_port + 1; |
1691 | if (this_urb->status == -EINPROGRESS) { | 1873 | if (this_urb->status == -EINPROGRESS) { |
1692 | /* dbg ("%s - already writing", __FUNCTION__); */ | 1874 | /* dbg ("%s - already writing", __FUNCTION__); */ |
@@ -1836,8 +2018,8 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial, | |||
1836 | } | 2018 | } |
1837 | 2019 | ||
1838 | /* Save reset port val for resend. | 2020 | /* Save reset port val for resend. |
1839 | Don't overwrite resend for close condition. */ | 2021 | Don't overwrite resend for open/close condition. */ |
1840 | if (p_priv->resend_cont != 3) | 2022 | if ((reset_port + 1) > p_priv->resend_cont) |
1841 | p_priv->resend_cont = reset_port + 1; | 2023 | p_priv->resend_cont = reset_port + 1; |
1842 | if (this_urb->status == -EINPROGRESS) { | 2024 | if (this_urb->status == -EINPROGRESS) { |
1843 | dbg ("%s already writing", __FUNCTION__); | 2025 | dbg ("%s already writing", __FUNCTION__); |
@@ -1940,11 +2122,11 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, | |||
1940 | struct usb_serial_port *port, | 2122 | struct usb_serial_port *port, |
1941 | int reset_port) | 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 | struct keyspan_serial_private *s_priv; | 2127 | struct keyspan_serial_private *s_priv; |
1945 | struct keyspan_port_private *p_priv; | 2128 | struct keyspan_port_private *p_priv; |
1946 | const struct keyspan_device_details *d_details; | 2129 | const struct keyspan_device_details *d_details; |
1947 | int glocont_urb; | ||
1948 | struct urb *this_urb; | 2130 | struct urb *this_urb; |
1949 | int err, device_port; | 2131 | int err, device_port; |
1950 | 2132 | ||
@@ -1954,10 +2136,9 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, | |||
1954 | p_priv = usb_get_serial_port_data(port); | 2136 | p_priv = usb_get_serial_port_data(port); |
1955 | d_details = s_priv->device_details; | 2137 | d_details = s_priv->device_details; |
1956 | 2138 | ||
1957 | glocont_urb = d_details->glocont_endpoint; | ||
1958 | this_urb = s_priv->glocont_urb; | 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 | device_port = port->number - port->serial->minor; | 2142 | device_port = port->number - port->serial->minor; |
1962 | 2143 | ||
1963 | dbg("%s - endpoint %d port %d (%d)",__FUNCTION__, usb_pipeendpoint(this_urb->pipe), port->number, device_port); | 2144 | dbg("%s - endpoint %d port %d (%d)",__FUNCTION__, usb_pipeendpoint(this_urb->pipe), port->number, device_port); |
@@ -1969,9 +2150,10 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, | |||
1969 | } | 2150 | } |
1970 | 2151 | ||
1971 | /* Save reset port val for resend. | 2152 | /* Save reset port val for resend. |
1972 | Don't overwrite resend for close condition. */ | 2153 | Don't overwrite resend for open/close condition. */ |
1973 | if (p_priv->resend_cont != 3) | 2154 | if ((reset_port + 1) > p_priv->resend_cont) |
1974 | p_priv->resend_cont = reset_port + 1; | 2155 | p_priv->resend_cont = reset_port + 1; |
2156 | |||
1975 | if (this_urb->status == -EINPROGRESS) { | 2157 | if (this_urb->status == -EINPROGRESS) { |
1976 | /* dbg ("%s - already writing", __FUNCTION__); */ | 2158 | /* dbg ("%s - already writing", __FUNCTION__); */ |
1977 | mdelay(5); | 2159 | mdelay(5); |
@@ -2083,20 +2265,39 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, | |||
2083 | msg.dtr = p_priv->dtr_state; | 2265 | msg.dtr = p_priv->dtr_state; |
2084 | 2266 | ||
2085 | p_priv->resend_cont = 0; | 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 */ | 2288 | /* send the data out the device on control endpoint */ |
2089 | this_urb->transfer_buffer_length = sizeof(msg); | 2289 | this_urb->transfer_buffer_length = sizeof(msg); |
2090 | 2290 | ||
2091 | this_urb->dev = serial->dev; | 2291 | this_urb->dev = serial->dev; |
2292 | } | ||
2092 | if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) { | 2293 | if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) { |
2093 | dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__, err); | 2294 | dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__, err); |
2094 | } | 2295 | } |
2095 | #if 0 | 2296 | #if 0 |
2096 | else { | 2297 | else { |
2097 | dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __FUNCTION__, | 2298 | dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __FUNCTION__, |
2098 | outcont_urb, this_urb->transfer_buffer_length, | 2299 | outcont_urb, this_urb->transfer_buffer_length, |
2099 | usb_pipeendpoint(this_urb->pipe)); | 2300 | usb_pipeendpoint(this_urb->pipe)); |
2100 | } | 2301 | } |
2101 | #endif | 2302 | #endif |
2102 | 2303 | ||
@@ -2241,6 +2442,154 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial, | |||
2241 | return (0); | 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 | static void keyspan_send_setup(struct usb_serial_port *port, int reset_port) | 2593 | static void keyspan_send_setup(struct usb_serial_port *port, int reset_port) |
2245 | { | 2594 | { |
2246 | struct usb_serial *serial = port->serial; | 2595 | struct usb_serial *serial = port->serial; |
@@ -2265,6 +2614,9 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port) | |||
2265 | case msg_usa90: | 2614 | case msg_usa90: |
2266 | keyspan_usa90_send_setup(serial, port, reset_port); | 2615 | keyspan_usa90_send_setup(serial, port, reset_port); |
2267 | break; | 2616 | break; |
2617 | case msg_usa67: | ||
2618 | keyspan_usa67_send_setup(serial, port, reset_port); | ||
2619 | break; | ||
2268 | } | 2620 | } |
2269 | } | 2621 | } |
2270 | 2622 | ||
@@ -2313,9 +2665,19 @@ static int keyspan_startup (struct usb_serial *serial) | |||
2313 | 2665 | ||
2314 | keyspan_setup_urbs(serial); | 2666 | keyspan_setup_urbs(serial); |
2315 | 2667 | ||
2316 | s_priv->instat_urb->dev = serial->dev; | 2668 | if (s_priv->instat_urb != NULL) { |
2317 | if ((err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL)) != 0) { | 2669 | s_priv->instat_urb->dev = serial->dev; |
2318 | dbg("%s - submit instat urb failed %d", __FUNCTION__, err); | 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); | ||
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); | ||
2319 | } | 2681 | } |
2320 | 2682 | ||
2321 | return (0); | 2683 | return (0); |
@@ -2335,6 +2697,7 @@ static void keyspan_shutdown (struct usb_serial *serial) | |||
2335 | /* Stop reading/writing urbs */ | 2697 | /* Stop reading/writing urbs */ |
2336 | stop_urb(s_priv->instat_urb); | 2698 | stop_urb(s_priv->instat_urb); |
2337 | stop_urb(s_priv->glocont_urb); | 2699 | stop_urb(s_priv->glocont_urb); |
2700 | stop_urb(s_priv->indat_urb); | ||
2338 | for (i = 0; i < serial->num_ports; ++i) { | 2701 | for (i = 0; i < serial->num_ports; ++i) { |
2339 | port = serial->port[i]; | 2702 | port = serial->port[i]; |
2340 | p_priv = usb_get_serial_port_data(port); | 2703 | p_priv = usb_get_serial_port_data(port); |
@@ -2348,6 +2711,7 @@ static void keyspan_shutdown (struct usb_serial *serial) | |||
2348 | 2711 | ||
2349 | /* Now free them */ | 2712 | /* Now free them */ |
2350 | usb_free_urb(s_priv->instat_urb); | 2713 | usb_free_urb(s_priv->instat_urb); |
2714 | usb_free_urb(s_priv->indat_urb); | ||
2351 | usb_free_urb(s_priv->glocont_urb); | 2715 | usb_free_urb(s_priv->glocont_urb); |
2352 | for (i = 0; i < serial->num_ports; ++i) { | 2716 | for (i = 0; i < serial->num_ports; ++i) { |
2353 | port = serial->port[i]; | 2717 | port = serial->port[i]; |
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index c6830cbdc6df..8a0d17401529 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h | |||
@@ -99,6 +99,10 @@ static int keyspan_usa90_send_setup (struct usb_serial *serial, | |||
99 | struct usb_serial_port *port, | 99 | struct usb_serial_port *port, |
100 | int reset_port); | 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 | /* Struct used for firmware - increased size of data section | 106 | /* Struct used for firmware - increased size of data section |
103 | to allow Keyspan's 'C' firmware struct to be used unmodified */ | 107 | to allow Keyspan's 'C' firmware struct to be used unmodified */ |
104 | struct ezusb_hex_record { | 108 | struct ezusb_hex_record { |
@@ -229,15 +233,17 @@ struct ezusb_hex_record { | |||
229 | #define keyspan_usa28_product_id 0x010f | 233 | #define keyspan_usa28_product_id 0x010f |
230 | #define keyspan_usa28x_product_id 0x0110 | 234 | #define keyspan_usa28x_product_id 0x0110 |
231 | #define keyspan_usa28xa_product_id 0x0115 | 235 | #define keyspan_usa28xa_product_id 0x0115 |
236 | #define keyspan_usa28xb_product_id 0x0110 | ||
237 | #define keyspan_usa28xg_product_id 0x0135 | ||
232 | #define keyspan_usa49w_product_id 0x010a | 238 | #define keyspan_usa49w_product_id 0x010a |
233 | #define keyspan_usa49wlc_product_id 0x012a | 239 | #define keyspan_usa49wlc_product_id 0x012a |
234 | 240 | #define keyspan_usa49wg_product_id 0x0131 | |
235 | 241 | ||
236 | struct keyspan_device_details { | 242 | struct keyspan_device_details { |
237 | /* product ID value */ | 243 | /* product ID value */ |
238 | int product_id; | 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 | /* Number of physical ports */ | 248 | /* Number of physical ports */ |
243 | int num_ports; | 249 | int num_ports; |
@@ -264,6 +270,9 @@ struct keyspan_device_details { | |||
264 | /* Endpoint used for input status */ | 270 | /* Endpoint used for input status */ |
265 | int instat_endpoint; | 271 | int instat_endpoint; |
266 | 272 | ||
273 | /* Endpoint used for input data 49WG only */ | ||
274 | int indat_endpoint; | ||
275 | |||
267 | /* Endpoint used for global control functions */ | 276 | /* Endpoint used for global control functions */ |
268 | int glocont_endpoint; | 277 | int glocont_endpoint; |
269 | 278 | ||
@@ -287,6 +296,7 @@ static const struct keyspan_device_details usa18x_device_details = { | |||
287 | .inack_endpoints = {0x85}, | 296 | .inack_endpoints = {0x85}, |
288 | .outcont_endpoints = {0x05}, | 297 | .outcont_endpoints = {0x05}, |
289 | .instat_endpoint = 0x87, | 298 | .instat_endpoint = 0x87, |
299 | .indat_endpoint = -1, | ||
290 | .glocont_endpoint = 0x07, | 300 | .glocont_endpoint = 0x07, |
291 | .calculate_baud_rate = keyspan_usa19w_calc_baud, | 301 | .calculate_baud_rate = keyspan_usa19w_calc_baud, |
292 | .baudclk = KEYSPAN_USA18X_BAUDCLK, | 302 | .baudclk = KEYSPAN_USA18X_BAUDCLK, |
@@ -303,6 +313,7 @@ static const struct keyspan_device_details usa19_device_details = { | |||
303 | .inack_endpoints = {0x83}, | 313 | .inack_endpoints = {0x83}, |
304 | .outcont_endpoints = {0x03}, | 314 | .outcont_endpoints = {0x03}, |
305 | .instat_endpoint = 0x84, | 315 | .instat_endpoint = 0x84, |
316 | .indat_endpoint = -1, | ||
306 | .glocont_endpoint = -1, | 317 | .glocont_endpoint = -1, |
307 | .calculate_baud_rate = keyspan_usa19_calc_baud, | 318 | .calculate_baud_rate = keyspan_usa19_calc_baud, |
308 | .baudclk = KEYSPAN_USA19_BAUDCLK, | 319 | .baudclk = KEYSPAN_USA19_BAUDCLK, |
@@ -319,6 +330,7 @@ static const struct keyspan_device_details usa19qi_device_details = { | |||
319 | .inack_endpoints = {0x83}, | 330 | .inack_endpoints = {0x83}, |
320 | .outcont_endpoints = {0x03}, | 331 | .outcont_endpoints = {0x03}, |
321 | .instat_endpoint = 0x84, | 332 | .instat_endpoint = 0x84, |
333 | .indat_endpoint = -1, | ||
322 | .glocont_endpoint = -1, | 334 | .glocont_endpoint = -1, |
323 | .calculate_baud_rate = keyspan_usa28_calc_baud, | 335 | .calculate_baud_rate = keyspan_usa28_calc_baud, |
324 | .baudclk = KEYSPAN_USA19_BAUDCLK, | 336 | .baudclk = KEYSPAN_USA19_BAUDCLK, |
@@ -335,6 +347,7 @@ static const struct keyspan_device_details mpr_device_details = { | |||
335 | .inack_endpoints = {0x83}, | 347 | .inack_endpoints = {0x83}, |
336 | .outcont_endpoints = {0x03}, | 348 | .outcont_endpoints = {0x03}, |
337 | .instat_endpoint = 0x84, | 349 | .instat_endpoint = 0x84, |
350 | .indat_endpoint = -1, | ||
338 | .glocont_endpoint = -1, | 351 | .glocont_endpoint = -1, |
339 | .calculate_baud_rate = keyspan_usa28_calc_baud, | 352 | .calculate_baud_rate = keyspan_usa28_calc_baud, |
340 | .baudclk = KEYSPAN_USA19_BAUDCLK, | 353 | .baudclk = KEYSPAN_USA19_BAUDCLK, |
@@ -351,6 +364,7 @@ static const struct keyspan_device_details usa19qw_device_details = { | |||
351 | .inack_endpoints = {0x85}, | 364 | .inack_endpoints = {0x85}, |
352 | .outcont_endpoints = {0x05}, | 365 | .outcont_endpoints = {0x05}, |
353 | .instat_endpoint = 0x87, | 366 | .instat_endpoint = 0x87, |
367 | .indat_endpoint = -1, | ||
354 | .glocont_endpoint = 0x07, | 368 | .glocont_endpoint = 0x07, |
355 | .calculate_baud_rate = keyspan_usa19w_calc_baud, | 369 | .calculate_baud_rate = keyspan_usa19w_calc_baud, |
356 | .baudclk = KEYSPAN_USA19W_BAUDCLK, | 370 | .baudclk = KEYSPAN_USA19W_BAUDCLK, |
@@ -367,6 +381,7 @@ static const struct keyspan_device_details usa19w_device_details = { | |||
367 | .inack_endpoints = {0x85}, | 381 | .inack_endpoints = {0x85}, |
368 | .outcont_endpoints = {0x05}, | 382 | .outcont_endpoints = {0x05}, |
369 | .instat_endpoint = 0x87, | 383 | .instat_endpoint = 0x87, |
384 | .indat_endpoint = -1, | ||
370 | .glocont_endpoint = 0x07, | 385 | .glocont_endpoint = 0x07, |
371 | .calculate_baud_rate = keyspan_usa19w_calc_baud, | 386 | .calculate_baud_rate = keyspan_usa19w_calc_baud, |
372 | .baudclk = KEYSPAN_USA19W_BAUDCLK, | 387 | .baudclk = KEYSPAN_USA19W_BAUDCLK, |
@@ -383,6 +398,7 @@ static const struct keyspan_device_details usa19hs_device_details = { | |||
383 | .inack_endpoints = {-1}, | 398 | .inack_endpoints = {-1}, |
384 | .outcont_endpoints = {0x02}, | 399 | .outcont_endpoints = {0x02}, |
385 | .instat_endpoint = 0x82, | 400 | .instat_endpoint = 0x82, |
401 | .indat_endpoint = -1, | ||
386 | .glocont_endpoint = -1, | 402 | .glocont_endpoint = -1, |
387 | .calculate_baud_rate = keyspan_usa19hs_calc_baud, | 403 | .calculate_baud_rate = keyspan_usa19hs_calc_baud, |
388 | .baudclk = KEYSPAN_USA19HS_BAUDCLK, | 404 | .baudclk = KEYSPAN_USA19HS_BAUDCLK, |
@@ -399,6 +415,7 @@ static const struct keyspan_device_details usa28_device_details = { | |||
399 | .inack_endpoints = {0x85, 0x86}, | 415 | .inack_endpoints = {0x85, 0x86}, |
400 | .outcont_endpoints = {0x05, 0x06}, | 416 | .outcont_endpoints = {0x05, 0x06}, |
401 | .instat_endpoint = 0x87, | 417 | .instat_endpoint = 0x87, |
418 | .indat_endpoint = -1, | ||
402 | .glocont_endpoint = 0x07, | 419 | .glocont_endpoint = 0x07, |
403 | .calculate_baud_rate = keyspan_usa28_calc_baud, | 420 | .calculate_baud_rate = keyspan_usa28_calc_baud, |
404 | .baudclk = KEYSPAN_USA28_BAUDCLK, | 421 | .baudclk = KEYSPAN_USA28_BAUDCLK, |
@@ -415,6 +432,7 @@ static const struct keyspan_device_details usa28x_device_details = { | |||
415 | .inack_endpoints = {0x85, 0x86}, | 432 | .inack_endpoints = {0x85, 0x86}, |
416 | .outcont_endpoints = {0x05, 0x06}, | 433 | .outcont_endpoints = {0x05, 0x06}, |
417 | .instat_endpoint = 0x87, | 434 | .instat_endpoint = 0x87, |
435 | .indat_endpoint = -1, | ||
418 | .glocont_endpoint = 0x07, | 436 | .glocont_endpoint = 0x07, |
419 | .calculate_baud_rate = keyspan_usa19w_calc_baud, | 437 | .calculate_baud_rate = keyspan_usa19w_calc_baud, |
420 | .baudclk = KEYSPAN_USA28X_BAUDCLK, | 438 | .baudclk = KEYSPAN_USA28X_BAUDCLK, |
@@ -431,11 +449,28 @@ static const struct keyspan_device_details usa28xa_device_details = { | |||
431 | .inack_endpoints = {0x85, 0x86}, | 449 | .inack_endpoints = {0x85, 0x86}, |
432 | .outcont_endpoints = {0x05, 0x06}, | 450 | .outcont_endpoints = {0x05, 0x06}, |
433 | .instat_endpoint = 0x87, | 451 | .instat_endpoint = 0x87, |
452 | .indat_endpoint = -1, | ||
434 | .glocont_endpoint = 0x07, | 453 | .glocont_endpoint = 0x07, |
435 | .calculate_baud_rate = keyspan_usa19w_calc_baud, | 454 | .calculate_baud_rate = keyspan_usa19w_calc_baud, |
436 | .baudclk = KEYSPAN_USA28X_BAUDCLK, | 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 | /* We don't need a separate entry for the usa28xb as it appears as a 28x anyway */ | 474 | /* We don't need a separate entry for the usa28xb as it appears as a 28x anyway */ |
440 | 475 | ||
441 | static const struct keyspan_device_details usa49w_device_details = { | 476 | static const struct keyspan_device_details usa49w_device_details = { |
@@ -449,6 +484,7 @@ static const struct keyspan_device_details usa49w_device_details = { | |||
449 | .inack_endpoints = {-1, -1, -1, -1}, | 484 | .inack_endpoints = {-1, -1, -1, -1}, |
450 | .outcont_endpoints = {-1, -1, -1, -1}, | 485 | .outcont_endpoints = {-1, -1, -1, -1}, |
451 | .instat_endpoint = 0x87, | 486 | .instat_endpoint = 0x87, |
487 | .indat_endpoint = -1, | ||
452 | .glocont_endpoint = 0x07, | 488 | .glocont_endpoint = 0x07, |
453 | .calculate_baud_rate = keyspan_usa19w_calc_baud, | 489 | .calculate_baud_rate = keyspan_usa19w_calc_baud, |
454 | .baudclk = KEYSPAN_USA49W_BAUDCLK, | 490 | .baudclk = KEYSPAN_USA49W_BAUDCLK, |
@@ -465,11 +501,29 @@ static const struct keyspan_device_details usa49wlc_device_details = { | |||
465 | .inack_endpoints = {-1, -1, -1, -1}, | 501 | .inack_endpoints = {-1, -1, -1, -1}, |
466 | .outcont_endpoints = {-1, -1, -1, -1}, | 502 | .outcont_endpoints = {-1, -1, -1, -1}, |
467 | .instat_endpoint = 0x87, | 503 | .instat_endpoint = 0x87, |
504 | .indat_endpoint = -1, | ||
468 | .glocont_endpoint = 0x07, | 505 | .glocont_endpoint = 0x07, |
469 | .calculate_baud_rate = keyspan_usa19w_calc_baud, | 506 | .calculate_baud_rate = keyspan_usa19w_calc_baud, |
470 | .baudclk = KEYSPAN_USA19W_BAUDCLK, | 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 | static const struct keyspan_device_details *keyspan_devices[] = { | 527 | static const struct keyspan_device_details *keyspan_devices[] = { |
474 | &usa18x_device_details, | 528 | &usa18x_device_details, |
475 | &usa19_device_details, | 529 | &usa19_device_details, |
@@ -481,9 +535,11 @@ static const struct keyspan_device_details *keyspan_devices[] = { | |||
481 | &usa28_device_details, | 535 | &usa28_device_details, |
482 | &usa28x_device_details, | 536 | &usa28x_device_details, |
483 | &usa28xa_device_details, | 537 | &usa28xa_device_details, |
538 | &usa28xg_device_details, | ||
484 | /* 28xb not required as it renumerates as a 28x */ | 539 | /* 28xb not required as it renumerates as a 28x */ |
485 | &usa49w_device_details, | 540 | &usa49w_device_details, |
486 | &usa49wlc_device_details, | 541 | &usa49wlc_device_details, |
542 | &usa49wg_device_details, | ||
487 | NULL, | 543 | NULL, |
488 | }; | 544 | }; |
489 | 545 | ||
@@ -510,8 +566,11 @@ static struct usb_device_id keyspan_ids_combined[] = { | |||
510 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) }, | 566 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) }, |
511 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) }, | 567 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) }, |
512 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) }, | 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 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id)}, | 571 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id)}, |
514 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)}, | 572 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)}, |
573 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wg_product_id)}, | ||
515 | { } /* Terminating entry */ | 574 | { } /* Terminating entry */ |
516 | }; | 575 | }; |
517 | 576 | ||
@@ -557,12 +616,15 @@ static struct usb_device_id keyspan_2port_ids[] = { | |||
557 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) }, | 616 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) }, |
558 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) }, | 617 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) }, |
559 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) }, | 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 | { } /* Terminating entry */ | 621 | { } /* Terminating entry */ |
561 | }; | 622 | }; |
562 | 623 | ||
563 | static struct usb_device_id keyspan_4port_ids[] = { | 624 | static struct usb_device_id keyspan_4port_ids[] = { |
564 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id) }, | 625 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id) }, |
565 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)}, | 626 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)}, |
627 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wg_product_id)}, | ||
566 | { } /* Terminating entry */ | 628 | { } /* Terminating entry */ |
567 | }; | 629 | }; |
568 | 630 | ||
@@ -573,7 +635,6 @@ static struct usb_serial_driver keyspan_pre_device = { | |||
573 | .name = "keyspan_no_firm", | 635 | .name = "keyspan_no_firm", |
574 | }, | 636 | }, |
575 | .description = "Keyspan - (without firmware)", | 637 | .description = "Keyspan - (without firmware)", |
576 | .usb_driver = &keyspan_driver, | ||
577 | .id_table = keyspan_pre_ids, | 638 | .id_table = keyspan_pre_ids, |
578 | .num_interrupt_in = NUM_DONT_CARE, | 639 | .num_interrupt_in = NUM_DONT_CARE, |
579 | .num_bulk_in = NUM_DONT_CARE, | 640 | .num_bulk_in = NUM_DONT_CARE, |
@@ -588,7 +649,6 @@ static struct usb_serial_driver keyspan_1port_device = { | |||
588 | .name = "keyspan_1", | 649 | .name = "keyspan_1", |
589 | }, | 650 | }, |
590 | .description = "Keyspan 1 port adapter", | 651 | .description = "Keyspan 1 port adapter", |
591 | .usb_driver = &keyspan_driver, | ||
592 | .id_table = keyspan_1port_ids, | 652 | .id_table = keyspan_1port_ids, |
593 | .num_interrupt_in = NUM_DONT_CARE, | 653 | .num_interrupt_in = NUM_DONT_CARE, |
594 | .num_bulk_in = NUM_DONT_CARE, | 654 | .num_bulk_in = NUM_DONT_CARE, |
@@ -616,7 +676,6 @@ static struct usb_serial_driver keyspan_2port_device = { | |||
616 | .name = "keyspan_2", | 676 | .name = "keyspan_2", |
617 | }, | 677 | }, |
618 | .description = "Keyspan 2 port adapter", | 678 | .description = "Keyspan 2 port adapter", |
619 | .usb_driver = &keyspan_driver, | ||
620 | .id_table = keyspan_2port_ids, | 679 | .id_table = keyspan_2port_ids, |
621 | .num_interrupt_in = NUM_DONT_CARE, | 680 | .num_interrupt_in = NUM_DONT_CARE, |
622 | .num_bulk_in = NUM_DONT_CARE, | 681 | .num_bulk_in = NUM_DONT_CARE, |
@@ -644,11 +703,10 @@ static struct usb_serial_driver keyspan_4port_device = { | |||
644 | .name = "keyspan_4", | 703 | .name = "keyspan_4", |
645 | }, | 704 | }, |
646 | .description = "Keyspan 4 port adapter", | 705 | .description = "Keyspan 4 port adapter", |
647 | .usb_driver = &keyspan_driver, | ||
648 | .id_table = keyspan_4port_ids, | 706 | .id_table = keyspan_4port_ids, |
649 | .num_interrupt_in = NUM_DONT_CARE, | 707 | .num_interrupt_in = NUM_DONT_CARE, |
650 | .num_bulk_in = 5, | 708 | .num_bulk_in = NUM_DONT_CARE, |
651 | .num_bulk_out = 5, | 709 | .num_bulk_out = NUM_DONT_CARE, |
652 | .num_ports = 4, | 710 | .num_ports = 4, |
653 | .open = keyspan_open, | 711 | .open = keyspan_open, |
654 | .close = keyspan_close, | 712 | .close = keyspan_close, |
diff --git a/drivers/usb/serial/keyspan_usa67msg.h b/drivers/usb/serial/keyspan_usa67msg.h new file mode 100644 index 000000000000..20fa3e2f7187 --- /dev/null +++ b/drivers/usb/serial/keyspan_usa67msg.h | |||
@@ -0,0 +1,254 @@ | |||
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 | |||