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 /drivers/usb/serial/keyspan.c | |
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>
Diffstat (limited to 'drivers/usb/serial/keyspan.c')
-rw-r--r-- | drivers/usb/serial/keyspan.c | 414 |
1 files changed, 389 insertions, 25 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]; |