aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r--drivers/usb/serial/ftdi_sio.c146
-rw-r--r--drivers/usb/serial/ftdi_sio.h14
-rw-r--r--drivers/usb/serial/option.c228
3 files changed, 175 insertions, 213 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 0b03ddab53d9..d1964a0c4168 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -429,6 +429,9 @@ static struct usb_device_id id_table_combined [] = {
429 { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) }, 429 { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) },
430 { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) }, 430 { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
431 { USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) }, 431 { USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) },
432 { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y6_PID) },
433 { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y8_PID) },
434 { USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
432 { } /* Terminating entry */ 435 { } /* Terminating entry */
433}; 436};
434 437
@@ -545,6 +548,7 @@ static struct usb_serial_device_type ftdi_sio_device = {
545 548
546 549
547#define WDR_TIMEOUT 5000 /* default urb timeout */ 550#define WDR_TIMEOUT 5000 /* default urb timeout */
551#define WDR_SHORT_TIMEOUT 1000 /* shorter urb timeout */
548 552
549/* High and low are for DTR, RTS etc etc */ 553/* High and low are for DTR, RTS etc etc */
550#define HIGH 1 554#define HIGH 1
@@ -593,62 +597,59 @@ static __u32 ftdi_232bm_baud_to_divisor(int baud)
593 return(ftdi_232bm_baud_base_to_divisor(baud, 48000000)); 597 return(ftdi_232bm_baud_base_to_divisor(baud, 48000000));
594} 598}
595 599
596static int set_rts(struct usb_serial_port *port, int high_or_low) 600#define set_mctrl(port, set) update_mctrl((port), (set), 0)
601#define clear_mctrl(port, clear) update_mctrl((port), 0, (clear))
602
603static int update_mctrl(struct usb_serial_port *port, unsigned int set, unsigned int clear)
597{ 604{
598 struct ftdi_private *priv = usb_get_serial_port_data(port); 605 struct ftdi_private *priv = usb_get_serial_port_data(port);
599 char *buf; 606 char *buf;
600 unsigned ftdi_high_or_low; 607 unsigned urb_value;
601 int rv; 608 int rv;
602
603 buf = kmalloc(1, GFP_NOIO);
604 if (!buf)
605 return -ENOMEM;
606
607 if (high_or_low) {
608 ftdi_high_or_low = FTDI_SIO_SET_RTS_HIGH;
609 priv->last_dtr_rts |= TIOCM_RTS;
610 } else {
611 ftdi_high_or_low = FTDI_SIO_SET_RTS_LOW;
612 priv->last_dtr_rts &= ~TIOCM_RTS;
613 }
614 rv = usb_control_msg(port->serial->dev,
615 usb_sndctrlpipe(port->serial->dev, 0),
616 FTDI_SIO_SET_MODEM_CTRL_REQUEST,
617 FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
618 ftdi_high_or_low, priv->interface,
619 buf, 0, WDR_TIMEOUT);
620
621 kfree(buf);
622 return rv;
623}
624 609
610 if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) {
611 dbg("%s - DTR|RTS not being set|cleared", __FUNCTION__);
612 return 0; /* no change */
613 }
625 614
626static int set_dtr(struct usb_serial_port *port, int high_or_low)
627{
628 struct ftdi_private *priv = usb_get_serial_port_data(port);
629 char *buf;
630 unsigned ftdi_high_or_low;
631 int rv;
632
633 buf = kmalloc(1, GFP_NOIO); 615 buf = kmalloc(1, GFP_NOIO);
634 if (!buf) 616 if (!buf) {
635 return -ENOMEM; 617 return -ENOMEM;
636
637 if (high_or_low) {
638 ftdi_high_or_low = FTDI_SIO_SET_DTR_HIGH;
639 priv->last_dtr_rts |= TIOCM_DTR;
640 } else {
641 ftdi_high_or_low = FTDI_SIO_SET_DTR_LOW;
642 priv->last_dtr_rts &= ~TIOCM_DTR;
643 } 618 }
619
620 clear &= ~set; /* 'set' takes precedence over 'clear' */
621 urb_value = 0;
622 if (clear & TIOCM_DTR)
623 urb_value |= FTDI_SIO_SET_DTR_LOW;
624 if (clear & TIOCM_RTS)
625 urb_value |= FTDI_SIO_SET_RTS_LOW;
626 if (set & TIOCM_DTR)
627 urb_value |= FTDI_SIO_SET_DTR_HIGH;
628 if (set & TIOCM_RTS)
629 urb_value |= FTDI_SIO_SET_RTS_HIGH;
644 rv = usb_control_msg(port->serial->dev, 630 rv = usb_control_msg(port->serial->dev,
645 usb_sndctrlpipe(port->serial->dev, 0), 631 usb_sndctrlpipe(port->serial->dev, 0),
646 FTDI_SIO_SET_MODEM_CTRL_REQUEST, 632 FTDI_SIO_SET_MODEM_CTRL_REQUEST,
647 FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, 633 FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
648 ftdi_high_or_low, priv->interface, 634 urb_value, priv->interface,
649 buf, 0, WDR_TIMEOUT); 635 buf, 0, WDR_TIMEOUT);
650 636
651 kfree(buf); 637 kfree(buf);
638 if (rv < 0) {
639 err("%s Error from MODEM_CTRL urb: DTR %s, RTS %s",
640 __FUNCTION__,
641 (set & TIOCM_DTR) ? "HIGH" :
642 (clear & TIOCM_DTR) ? "LOW" : "unchanged",
643 (set & TIOCM_RTS) ? "HIGH" :
644 (clear & TIOCM_RTS) ? "LOW" : "unchanged");
645 } else {
646 dbg("%s - DTR %s, RTS %s", __FUNCTION__,
647 (set & TIOCM_DTR) ? "HIGH" :
648 (clear & TIOCM_DTR) ? "LOW" : "unchanged",
649 (set & TIOCM_RTS) ? "HIGH" :
650 (clear & TIOCM_RTS) ? "LOW" : "unchanged");
651 priv->last_dtr_rts = (priv->last_dtr_rts & ~clear) | set;
652 }
652 return rv; 653 return rv;
653} 654}
654 655
@@ -681,7 +682,7 @@ static int change_speed(struct usb_serial_port *port)
681 FTDI_SIO_SET_BAUDRATE_REQUEST, 682 FTDI_SIO_SET_BAUDRATE_REQUEST,
682 FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, 683 FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE,
683 urb_value, urb_index, 684 urb_value, urb_index,
684 buf, 0, 100); 685 buf, 0, WDR_SHORT_TIMEOUT);
685 686
686 kfree(buf); 687 kfree(buf);
687 return rv; 688 return rv;
@@ -1219,12 +1220,7 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp)
1219 /* FIXME: Flow control might be enabled, so it should be checked - 1220 /* FIXME: Flow control might be enabled, so it should be checked -
1220 we have no control of defaults! */ 1221 we have no control of defaults! */
1221 /* Turn on RTS and DTR since we are not flow controlling by default */ 1222 /* Turn on RTS and DTR since we are not flow controlling by default */
1222 if (set_dtr(port, HIGH) < 0) { 1223 set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
1223 err("%s Error from DTR HIGH urb", __FUNCTION__);
1224 }
1225 if (set_rts(port, HIGH) < 0){
1226 err("%s Error from RTS HIGH urb", __FUNCTION__);
1227 }
1228 1224
1229 /* Not throttled */ 1225 /* Not throttled */
1230 spin_lock_irqsave(&priv->rx_lock, flags); 1226 spin_lock_irqsave(&priv->rx_lock, flags);
@@ -1274,14 +1270,8 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp)
1274 err("error from flowcontrol urb"); 1270 err("error from flowcontrol urb");
1275 } 1271 }
1276 1272
1277 /* drop DTR */ 1273 /* drop RTS and DTR */
1278 if (set_dtr(port, LOW) < 0){ 1274 clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
1279 err("Error from DTR LOW urb");
1280 }
1281 /* drop RTS */
1282 if (set_rts(port, LOW) < 0) {
1283 err("Error from RTS LOW urb");
1284 }
1285 } /* Note change no line if hupcl is off */ 1275 } /* Note change no line if hupcl is off */
1286 1276
1287 /* cancel any scheduled reading */ 1277 /* cancel any scheduled reading */
@@ -1797,7 +1787,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_
1797 FTDI_SIO_SET_DATA_REQUEST, 1787 FTDI_SIO_SET_DATA_REQUEST,
1798 FTDI_SIO_SET_DATA_REQUEST_TYPE, 1788 FTDI_SIO_SET_DATA_REQUEST_TYPE,
1799 urb_value , priv->interface, 1789 urb_value , priv->interface,
1800 buf, 0, 100) < 0) { 1790 buf, 0, WDR_SHORT_TIMEOUT) < 0) {
1801 err("%s FAILED to set databits/stopbits/parity", __FUNCTION__); 1791 err("%s FAILED to set databits/stopbits/parity", __FUNCTION__);
1802 } 1792 }
1803 1793
@@ -1812,25 +1802,14 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_
1812 err("%s error from disable flowcontrol urb", __FUNCTION__); 1802 err("%s error from disable flowcontrol urb", __FUNCTION__);
1813 } 1803 }
1814 /* Drop RTS and DTR */ 1804 /* Drop RTS and DTR */
1815 if (set_dtr(port, LOW) < 0){ 1805 clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
1816 err("%s Error from DTR LOW urb", __FUNCTION__);
1817 }
1818 if (set_rts(port, LOW) < 0){
1819 err("%s Error from RTS LOW urb", __FUNCTION__);
1820 }
1821
1822 } else { 1806 } else {
1823 /* set the baudrate determined before */ 1807 /* set the baudrate determined before */
1824 if (change_speed(port)) { 1808 if (change_speed(port)) {
1825 err("%s urb failed to set baurdrate", __FUNCTION__); 1809 err("%s urb failed to set baurdrate", __FUNCTION__);
1826 } 1810 }
1827 /* Ensure RTS and DTR are raised */ 1811 /* Ensure RTS and DTR are raised */
1828 else if (set_dtr(port, HIGH) < 0){ 1812 set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
1829 err("%s Error from DTR HIGH urb", __FUNCTION__);
1830 }
1831 else if (set_rts(port, HIGH) < 0){
1832 err("%s Error from RTS HIGH urb", __FUNCTION__);
1833 }
1834 } 1813 }
1835 1814
1836 /* Set flow control */ 1815 /* Set flow control */
@@ -1942,35 +1921,8 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file)
1942 1921
1943static int ftdi_tiocmset(struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear) 1922static int ftdi_tiocmset(struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear)
1944{ 1923{
1945 int ret;
1946
1947 dbg("%s TIOCMSET", __FUNCTION__); 1924 dbg("%s TIOCMSET", __FUNCTION__);
1948 if (set & TIOCM_DTR){ 1925 return update_mctrl(port, set, clear);
1949 if ((ret = set_dtr(port, HIGH)) < 0) {
1950 err("Urb to set DTR failed");
1951 return(ret);
1952 }
1953 }
1954 if (set & TIOCM_RTS) {
1955 if ((ret = set_rts(port, HIGH)) < 0){
1956 err("Urb to set RTS failed");
1957 return(ret);
1958 }
1959 }
1960
1961 if (clear & TIOCM_DTR){
1962 if ((ret = set_dtr(port, LOW)) < 0){
1963 err("Urb to unset DTR failed");
1964 return(ret);
1965 }
1966 }
1967 if (clear & TIOCM_RTS) {
1968 if ((ret = set_rts(port, LOW)) < 0){
1969 err("Urb to unset RTS failed");
1970 return(ret);
1971 }
1972 }
1973 return(0);
1974} 1926}
1975 1927
1976 1928
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 8866376823a5..9f4342093e8b 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -265,10 +265,24 @@
265#define MOBILITY_USB_SERIAL_PID 0x0202 /* EasiDock USB 200 serial */ 265#define MOBILITY_USB_SERIAL_PID 0x0202 /* EasiDock USB 200 serial */
266 266
267/* 267/*
268 * microHAM product IDs (http://www.microham.com).
269 * Submitted by Justin Burket (KL1RL) <zorton@jtan.com>.
270 */
271#define FTDI_MHAM_Y6_PID 0xEEEA /* USB-Y6 interface */
272#define FTDI_MHAM_Y8_PID 0xEEEB /* USB-Y8 interface */
273
274/*
268 * Active Robots product ids. 275 * Active Robots product ids.
269 */ 276 */
270#define FTDI_ACTIVE_ROBOTS_PID 0xE548 /* USB comms board */ 277#define FTDI_ACTIVE_ROBOTS_PID 0xE548 /* USB comms board */
271 278
279/*
280 * Evolution Robotics products (http://www.evolution.com/).
281 * Submitted by Shawn M. Lavelle.
282 */
283#define EVOLUTION_VID 0xDEEE /* Vendor ID */
284#define EVOLUTION_ER1_PID 0x0300 /* ER1 Control Module */
285
272/* Commands */ 286/* Commands */
273#define FTDI_SIO_RESET 0 /* Reset the port */ 287#define FTDI_SIO_RESET 0 /* Reset the port */
274#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ 288#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index b722175f108f..e9256408757f 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -12,14 +12,25 @@
12 History: 12 History:
13 13
14 2005-05-19 v0.1 Initial version, based on incomplete docs 14 2005-05-19 v0.1 Initial version, based on incomplete docs
15 and analysis of misbehavior of the standard driver 15 and analysis of misbehavior with the standard driver
16 2005-05-20 v0.2 Extended the input buffer to avoid losing 16 2005-05-20 v0.2 Extended the input buffer to avoid losing
17 random 64-byte chunks of data 17 random 64-byte chunks of data
18 2005-05-21 v0.3 implemented chars_in_buffer() 18 2005-05-21 v0.3 implemented chars_in_buffer()
19 turned on low_latency 19 turned on low_latency
20 simplified the code somewhat 20 simplified the code somewhat
21 2005-05-24 v0.4 option_write() sometimes deadlocked under heavy load
22 removed some dead code
23 added sponsor notice
24 coding style clean-up
25 2005-06-20 v0.4.1 add missing braces :-/
26 killed end-of-line whitespace
27 2005-07-15 v0.4.2 rename WLAN product to FUSION, add FUSION2
28
29 Work sponsored by: Sigos GmbH, Germany <info@sigos.de>
30
21*/ 31*/
22#define DRIVER_VERSION "v0.3" 32
33#define DRIVER_VERSION "v0.4"
23#define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>" 34#define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
24#define DRIVER_DESC "Option Card (PC-Card to) USB to Serial Driver" 35#define DRIVER_DESC "Option Card (PC-Card to) USB to Serial Driver"
25 36
@@ -44,7 +55,6 @@ static int option_write_room (struct usb_serial_port *port);
44 55
45static void option_instat_callback(struct urb *urb, struct pt_regs *regs); 56static void option_instat_callback(struct urb *urb, struct pt_regs *regs);
46 57
47
48static int option_write (struct usb_serial_port *port, 58static int option_write (struct usb_serial_port *port,
49 const unsigned char *buf, int count); 59 const unsigned char *buf, int count);
50 60
@@ -60,14 +70,17 @@ static int option_tiocmset (struct usb_serial_port *port, struct file *file,
60static int option_send_setup (struct usb_serial_port *port); 70static int option_send_setup (struct usb_serial_port *port);
61 71
62/* Vendor and product IDs */ 72/* Vendor and product IDs */
63#define OPTION_VENDOR_ID 0x0AF0 73#define OPTION_VENDOR_ID 0x0AF0
74
75#define OPTION_PRODUCT_OLD 0x5000
76#define OPTION_PRODUCT_FUSION 0x6000
77#define OPTION_PRODUCT_FUSION2 0x6300
64 78
65#define OPTION_PRODUCT_OLD 0x5000
66#define OPTION_PRODUCT_WLAN 0x6000
67 79
68static struct usb_device_id option_ids[] = { 80static struct usb_device_id option_ids[] = {
69 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, 81 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
70 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_WLAN) }, 82 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
83 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
71 { } /* Terminating entry */ 84 { } /* Terminating entry */
72}; 85};
73 86
@@ -85,58 +98,62 @@ static struct usb_driver option_driver = {
85 * recognizes separately, thus num_port=1. 98 * recognizes separately, thus num_port=1.
86 */ 99 */
87static struct usb_serial_device_type option_3port_device = { 100static struct usb_serial_device_type option_3port_device = {
88 .owner = THIS_MODULE, 101 .owner = THIS_MODULE,
89 .name = "Option 3-port card", 102 .name = "Option 3G data card",
90 .short_name = "option", 103 .short_name = "option",
91 .id_table = option_ids, 104 .id_table = option_ids,
92 .num_interrupt_in = NUM_DONT_CARE, 105 .num_interrupt_in = NUM_DONT_CARE,
93 .num_bulk_in = NUM_DONT_CARE, 106 .num_bulk_in = NUM_DONT_CARE,
94 .num_bulk_out = NUM_DONT_CARE, 107 .num_bulk_out = NUM_DONT_CARE,
95 .num_ports = 1, /* 3 */ 108 .num_ports = 1, /* 3, but the card reports its ports separately */
96 .open = option_open, 109 .open = option_open,
97 .close = option_close, 110 .close = option_close,
98 .write = option_write, 111 .write = option_write,
99 .write_room = option_write_room, 112 .write_room = option_write_room,
100 .chars_in_buffer = option_chars_in_buffer, 113 .chars_in_buffer = option_chars_in_buffer,
101 .throttle = option_rx_throttle, 114 .throttle = option_rx_throttle,
102 .unthrottle = option_rx_unthrottle, 115 .unthrottle = option_rx_unthrottle,
103 .ioctl = option_ioctl, 116 .ioctl = option_ioctl,
104 .set_termios = option_set_termios, 117 .set_termios = option_set_termios,
105 .break_ctl = option_break_ctl, 118 .break_ctl = option_break_ctl,
106 .tiocmget = option_tiocmget, 119 .tiocmget = option_tiocmget,
107 .tiocmset = option_tiocmset, 120 .tiocmset = option_tiocmset,
108 .attach = option_startup, 121 .attach = option_startup,
109 .shutdown = option_shutdown, 122 .shutdown = option_shutdown,
110 .read_int_callback = option_instat_callback, 123 .read_int_callback = option_instat_callback,
111}; 124};
112 125
126#ifdef CONFIG_USB_DEBUG
113static int debug; 127static int debug;
128#else
129#define debug 0
130#endif
131
114 132
115/* per port private data */ 133/* per port private data */
116 134
117#define N_IN_URB 4 135#define N_IN_URB 4
118#define N_OUT_URB 1 136#define N_OUT_URB 1
119#define IN_BUFLEN 1024 137#define IN_BUFLEN 1024
120#define OUT_BUFLEN 1024 138#define OUT_BUFLEN 128
121 139
122struct option_port_private { 140struct option_port_private {
123 /* Input endpoints and buffer for this port */ 141 /* Input endpoints and buffer for this port */
124 struct urb *in_urbs[N_IN_URB]; 142 struct urb *in_urbs[N_IN_URB];
125 char in_buffer[N_IN_URB][IN_BUFLEN]; 143 char in_buffer[N_IN_URB][IN_BUFLEN];
126 /* Output endpoints and buffer for this port */ 144 /* Output endpoints and buffer for this port */
127 struct urb *out_urbs[N_OUT_URB]; 145 struct urb *out_urbs[N_OUT_URB];
128 char out_buffer[N_OUT_URB][OUT_BUFLEN]; 146 char out_buffer[N_OUT_URB][OUT_BUFLEN];
129 147
130 /* Settings for the port */ 148 /* Settings for the port */
131 int rts_state; /* Handshaking pins (outputs) */ 149 int rts_state; /* Handshaking pins (outputs) */
132 int dtr_state; 150 int dtr_state;
133 int cts_state; /* Handshaking pins (inputs) */ 151 int cts_state; /* Handshaking pins (inputs) */
134 int dsr_state; 152 int dsr_state;
135 int dcd_state; 153 int dcd_state;
136 int ri_state; 154 int ri_state;
137 // int break_on; 155
138 156 unsigned long tx_start_time[N_OUT_URB];
139 unsigned long tx_start_time[N_OUT_URB];
140}; 157};
141 158
142 159
@@ -190,13 +207,13 @@ static void
190option_break_ctl (struct usb_serial_port *port, int break_state) 207option_break_ctl (struct usb_serial_port *port, int break_state)
191{ 208{
192 /* Unfortunately, I don't know how to send a break */ 209 /* Unfortunately, I don't know how to send a break */
193 dbg("%s", __FUNCTION__); 210 dbg("%s", __FUNCTION__);
194} 211}
195 212
196 213
197static void 214static void
198option_set_termios (struct usb_serial_port *port, 215option_set_termios (struct usb_serial_port *port,
199 struct termios *old_termios) 216 struct termios *old_termios)
200{ 217{
201 dbg("%s", __FUNCTION__); 218 dbg("%s", __FUNCTION__);
202 219
@@ -204,10 +221,10 @@ option_set_termios (struct usb_serial_port *port,
204} 221}
205 222
206static int 223static int
207option_tiocmget(struct usb_serial_port *port, struct file *file) 224option_tiocmget (struct usb_serial_port *port, struct file *file)
208{ 225{
209 unsigned int value; 226 unsigned int value;
210 struct option_port_private *portdata; 227 struct option_port_private *portdata;
211 228
212 portdata = usb_get_serial_port_data(port); 229 portdata = usb_get_serial_port_data(port);
213 230
@@ -225,7 +242,7 @@ static int
225option_tiocmset (struct usb_serial_port *port, struct file *file, 242option_tiocmset (struct usb_serial_port *port, struct file *file,
226 unsigned int set, unsigned int clear) 243 unsigned int set, unsigned int clear)
227{ 244{
228 struct option_port_private *portdata; 245 struct option_port_private *portdata;
229 246
230 portdata = usb_get_serial_port_data(port); 247 portdata = usb_get_serial_port_data(port);
231 248
@@ -250,71 +267,50 @@ option_ioctl (struct usb_serial_port *port, struct file *file,
250 267
251/* Write */ 268/* Write */
252static int 269static int
253option_write(struct usb_serial_port *port, 270option_write (struct usb_serial_port *port,
254 const unsigned char *buf, int count) 271 const unsigned char *buf, int count)
255{ 272{
256 struct option_port_private *portdata; 273 struct option_port_private *portdata;
257 int i; 274 int i;
258 int left, todo; 275 int left, todo;
259 struct urb *this_urb = NULL; /* spurious */ 276 struct urb *this_urb = NULL; /* spurious */
260 int err; 277 int err;
261 278
262 portdata = usb_get_serial_port_data(port); 279 portdata = usb_get_serial_port_data(port);
263 280
264 dbg("%s: write (%d chars)", __FUNCTION__, count); 281 dbg("%s: write (%d chars)", __FUNCTION__, count);
265 282
266#if 0
267 spin_lock(&port->lock);
268 if (port->write_urb_busy) {
269 spin_unlock(&port->lock);
270 dbg("%s: already writing", __FUNCTION__);
271 return 0;
272 }
273 port->write_urb_busy = 1;
274 spin_unlock(&port->lock);
275#endif
276
277 i = 0; 283 i = 0;
278 left = count; 284 left = count;
279 while (left>0) { 285 for (i=0; left > 0 && i < N_OUT_URB; i++) {
280 todo = left; 286 todo = left;
281 if (todo > OUT_BUFLEN) 287 if (todo > OUT_BUFLEN)
282 todo = OUT_BUFLEN; 288 todo = OUT_BUFLEN;
283 289
284 for (;i < N_OUT_URB; i++) { 290 this_urb = portdata->out_urbs[i];
285 /* Check we have a valid urb/endpoint before we use it... */ 291 if (this_urb->status == -EINPROGRESS) {
286 this_urb = portdata->out_urbs[i];
287 if (this_urb->status != -EINPROGRESS)
288 break;
289 if (this_urb->transfer_flags & URB_ASYNC_UNLINK) 292 if (this_urb->transfer_flags & URB_ASYNC_UNLINK)
290 continue; 293 continue;
291 if (time_before(jiffies, portdata->tx_start_time[i] + 10 * HZ)) 294 if (time_before(jiffies, portdata->tx_start_time[i] + 10 * HZ))
292 continue; 295 continue;
293 this_urb->transfer_flags |= URB_ASYNC_UNLINK; 296 this_urb->transfer_flags |= URB_ASYNC_UNLINK;
294 usb_unlink_urb(this_urb); 297 usb_unlink_urb(this_urb);
298 continue;
295 } 299 }
296 300 if (this_urb->status != 0)
297 if (i == N_OUT_URB) { 301 dbg("usb_write %p failed (err=%d)", this_urb, this_urb->status);
298 /* no bulk out free! */
299 dbg("%s: no output urb -- left %d", __FUNCTION__,count-left);
300#if 0
301 port->write_urb_busy = 0;
302#endif
303 return count-left;
304 }
305 302
306 dbg("%s: endpoint %d buf %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe), i); 303 dbg("%s: endpoint %d buf %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe), i);
307 304
305 /* send the data */
308 memcpy (this_urb->transfer_buffer, buf, todo); 306 memcpy (this_urb->transfer_buffer, buf, todo);
309
310 /* send the data out the bulk port */
311 this_urb->transfer_buffer_length = todo; 307 this_urb->transfer_buffer_length = todo;
312 308
313 this_urb->transfer_flags &= ~URB_ASYNC_UNLINK; 309 this_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
314 this_urb->dev = port->serial->dev; 310 this_urb->dev = port->serial->dev;
315 err = usb_submit_urb(this_urb, GFP_ATOMIC); 311 err = usb_submit_urb(this_urb, GFP_ATOMIC);
316 if (err) { 312 if (err) {
317 dbg("usb_submit_urb %p (write bulk) failed (%d,, has %d)", this_urb, err, this_urb->status); 313 dbg("usb_submit_urb %p (write bulk) failed (%d, has %d)", this_urb, err, this_urb->status);
318 continue; 314 continue;
319 } 315 }
320 portdata->tx_start_time[i] = jiffies; 316 portdata->tx_start_time[i] = jiffies;
@@ -323,9 +319,6 @@ option_write(struct usb_serial_port *port,
323 } 319 }
324 320
325 count -= left; 321 count -= left;
326#if 0
327 port->write_urb_busy = 0;
328#endif
329 dbg("%s: wrote (did %d)", __FUNCTION__, count); 322 dbg("%s: wrote (did %d)", __FUNCTION__, count);
330 return count; 323 return count;
331} 324}
@@ -333,7 +326,7 @@ option_write(struct usb_serial_port *port,
333static void 326static void
334option_indat_callback (struct urb *urb, struct pt_regs *regs) 327option_indat_callback (struct urb *urb, struct pt_regs *regs)
335{ 328{
336 int i, err; 329 int i, err;
337 int endpoint; 330 int endpoint;
338 struct usb_serial_port *port; 331 struct usb_serial_port *port;
339 struct tty_struct *tty; 332 struct tty_struct *tty;
@@ -444,10 +437,11 @@ option_write_room (struct usb_serial_port *port)
444 437
445 portdata = usb_get_serial_port_data(port); 438 portdata = usb_get_serial_port_data(port);
446 439
447 for (i=0; i < N_OUT_URB; i++) 440 for (i=0; i < N_OUT_URB; i++) {
448 this_urb = portdata->out_urbs[i]; 441 this_urb = portdata->out_urbs[i];
449 if (this_urb && this_urb->status != -EINPROGRESS) 442 if (this_urb && this_urb->status != -EINPROGRESS)
450 data_len += OUT_BUFLEN; 443 data_len += OUT_BUFLEN;
444 }
451 445
452 dbg("%s: %d", __FUNCTION__, data_len); 446 dbg("%s: %d", __FUNCTION__, data_len);
453 return data_len; 447 return data_len;
@@ -464,11 +458,11 @@ option_chars_in_buffer (struct usb_serial_port *port)
464 458
465 portdata = usb_get_serial_port_data(port); 459 portdata = usb_get_serial_port_data(port);
466 460
467 for (i=0; i < N_OUT_URB; i++) 461 for (i=0; i < N_OUT_URB; i++) {
468 this_urb = portdata->out_urbs[i]; 462 this_urb = portdata->out_urbs[i];
469 if (this_urb && this_urb->status == -EINPROGRESS) 463 if (this_urb && this_urb->status == -EINPROGRESS)
470 data_len += this_urb->transfer_buffer_length; 464 data_len += this_urb->transfer_buffer_length;
471 465 }
472 dbg("%s: %d", __FUNCTION__, data_len); 466 dbg("%s: %d", __FUNCTION__, data_len);
473 return data_len; 467 return data_len;
474} 468}
@@ -477,10 +471,10 @@ option_chars_in_buffer (struct usb_serial_port *port)
477static int 471static int
478option_open (struct usb_serial_port *port, struct file *filp) 472option_open (struct usb_serial_port *port, struct file *filp)
479{ 473{
480 struct option_port_private *portdata; 474 struct option_port_private *portdata;
481 struct usb_serial *serial = port->serial; 475 struct usb_serial *serial = port->serial;
482 int i, err; 476 int i, err;
483 struct urb *urb; 477 struct urb *urb;
484 478
485 portdata = usb_get_serial_port_data(port); 479 portdata = usb_get_serial_port_data(port);
486 480
@@ -528,7 +522,7 @@ option_open (struct usb_serial_port *port, struct file *filp)
528} 522}
529 523
530static inline void 524static inline void
531stop_urb(struct urb *urb) 525stop_urb (struct urb *urb)
532{ 526{
533 if (urb && urb->status == -EINPROGRESS) { 527 if (urb && urb->status == -EINPROGRESS) {
534 urb->transfer_flags &= ~URB_ASYNC_UNLINK; 528 urb->transfer_flags &= ~URB_ASYNC_UNLINK;
@@ -537,11 +531,11 @@ stop_urb(struct urb *urb)
537} 531}
538 532
539static void 533static void
540option_close(struct usb_serial_port *port, struct file *filp) 534option_close (struct usb_serial_port *port, struct file *filp)
541{ 535{
542 int i; 536 int i;
543 struct usb_serial *serial = port->serial; 537 struct usb_serial *serial = port->serial;
544 struct option_port_private *portdata; 538 struct option_port_private *portdata;
545 539
546 dbg("%s", __FUNCTION__); 540 dbg("%s", __FUNCTION__);
547 portdata = usb_get_serial_port_data(port); 541 portdata = usb_get_serial_port_data(port);
@@ -589,11 +583,11 @@ option_setup_urb (struct usb_serial *serial, int endpoint,
589 583
590/* Setup urbs */ 584/* Setup urbs */
591static void 585static void
592option_setup_urbs(struct usb_serial *serial) 586option_setup_urbs (struct usb_serial *serial)
593{ 587{
594 int j; 588 int j;
595 struct usb_serial_port *port; 589 struct usb_serial_port *port;
596 struct option_port_private *portdata; 590 struct option_port_private *portdata;
597 591
598 dbg("%s", __FUNCTION__); 592 dbg("%s", __FUNCTION__);
599 593
@@ -617,7 +611,7 @@ option_setup_urbs(struct usb_serial *serial)
617 611
618 612
619static int 613static int
620option_send_setup(struct usb_serial_port *port) 614option_send_setup (struct usb_serial_port *port)
621{ 615{
622 struct usb_serial *serial = port->serial; 616 struct usb_serial *serial = port->serial;
623 struct option_port_private *portdata; 617 struct option_port_private *portdata;
@@ -644,9 +638,9 @@ option_send_setup(struct usb_serial_port *port)
644static int 638static int
645option_startup (struct usb_serial *serial) 639option_startup (struct usb_serial *serial)
646{ 640{
647 int i, err; 641 int i, err;
648 struct usb_serial_port *port; 642 struct usb_serial_port *port;
649 struct option_port_private *portdata; 643 struct option_port_private *portdata;
650 644
651 dbg("%s", __FUNCTION__); 645 dbg("%s", __FUNCTION__);
652 646
@@ -677,9 +671,9 @@ option_startup (struct usb_serial *serial)
677static void 671static void
678option_shutdown (struct usb_serial *serial) 672option_shutdown (struct usb_serial *serial)
679{ 673{
680 int i, j; 674 int i, j;
681 struct usb_serial_port *port; 675 struct usb_serial_port *port;
682 struct option_port_private *portdata; 676 struct option_port_private *portdata;
683 677
684 dbg("%s", __FUNCTION__); 678 dbg("%s", __FUNCTION__);
685 679
@@ -724,6 +718,8 @@ MODULE_DESCRIPTION(DRIVER_DESC);
724MODULE_VERSION(DRIVER_VERSION); 718MODULE_VERSION(DRIVER_VERSION);
725MODULE_LICENSE("GPL"); 719MODULE_LICENSE("GPL");
726 720
721#ifdef CONFIG_USB_DEBUG
727module_param(debug, bool, S_IRUGO | S_IWUSR); 722module_param(debug, bool, S_IRUGO | S_IWUSR);
728MODULE_PARM_DESC(debug, "Debug messages"); 723MODULE_PARM_DESC(debug, "Debug messages");
724#endif
729 725