xref: /openbmc/linux/drivers/usb/serial/mct_u232.c (revision 643d1f7f)
1 /*
2  * MCT (Magic Control Technology Corp.) USB RS232 Converter Driver
3  *
4  *   Copyright (C) 2000 Wolfgang Grandegger (wolfgang@ces.ch)
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  * This program is largely derived from the Belkin USB Serial Adapter Driver
12  * (see belkin_sa.[ch]). All of the information about the device was acquired
13  * by using SniffUSB on Windows98. For technical details see mct_u232.h.
14  *
15  * William G. Greathouse and Greg Kroah-Hartman provided great help on how to
16  * do the reverse engineering and how to write a USB serial device driver.
17  *
18  * TO BE DONE, TO BE CHECKED:
19  *   DTR/RTS signal handling may be incomplete or incorrect. I have mainly
20  *   implemented what I have seen with SniffUSB or found in belkin_sa.c.
21  *   For further TODOs check also belkin_sa.c.
22  *
23  * TEST STATUS:
24  *   Basic tests have been performed with minicom/zmodem transfers and
25  *   modem dialing under Linux 2.4.0-test10 (for me it works fine).
26  *
27  * 04-Nov-2003 Bill Marr <marr at flex dot com>
28  *   - Mimic Windows driver by sending 2 USB 'device request' messages
29  *     following normal 'baud rate change' message.  This allows data to be
30  *     transmitted to RS-232 devices which don't assert the 'CTS' signal.
31  *
32  * 10-Nov-2001 Wolfgang Grandegger
33  *   - Fixed an endianess problem with the baudrate selection for PowerPC.
34  *
35  * 06-Dec-2001 Martin Hamilton <martinh@gnu.org>
36  *	Added support for the Belkin F5U109 DB9 adaptor
37  *
38  * 30-May-2001 Greg Kroah-Hartman
39  *	switched from using spinlock to a semaphore, which fixes lots of problems.
40  *
41  * 04-May-2001 Stelian Pop
42  *   - Set the maximum bulk output size for Sitecom U232-P25 model to 16 bytes
43  *     instead of the device reported 32 (using 32 bytes causes many data
44  *     loss, Windows driver uses 16 too).
45  *
46  * 02-May-2001 Stelian Pop
47  *   - Fixed the baud calculation for Sitecom U232-P25 model
48  *
49  * 08-Apr-2001 gb
50  *   - Identify version on module load.
51  *
52  * 06-Jan-2001 Cornel Ciocirlan
53  *   - Added support for Sitecom U232-P25 model (Product Id 0x0230)
54  *   - Added support for D-Link DU-H3SP USB BAY (Product Id 0x0200)
55  *
56  * 29-Nov-2000 Greg Kroah-Hartman
57  *   - Added device id table to fit with 2.4.0-test11 structure.
58  *   - took out DEAL_WITH_TWO_INT_IN_ENDPOINTS #define as it's not needed
59  *     (lots of things will change if/when the usb-serial core changes to
60  *     handle these issues.
61  *
62  * 27-Nov-2000 Wolfgang Grandegger
63  *   A version for kernel 2.4.0-test10 released to the Linux community
64  *   (via linux-usb-devel).
65  */
66 
67 #include <linux/kernel.h>
68 #include <linux/errno.h>
69 #include <linux/init.h>
70 #include <linux/slab.h>
71 #include <linux/tty.h>
72 #include <linux/tty_driver.h>
73 #include <linux/tty_flip.h>
74 #include <linux/module.h>
75 #include <linux/spinlock.h>
76 #include <asm/uaccess.h>
77 #include <linux/usb.h>
78 #include <linux/usb/serial.h>
79 #include "mct_u232.h"
80 
81 /*
82  * Version Information
83  */
84 #define DRIVER_VERSION "z2.1"		/* Linux in-kernel version */
85 #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
86 #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
87 
88 static int debug;
89 
90 /*
91  * Function prototypes
92  */
93 static int  mct_u232_startup	         (struct usb_serial *serial);
94 static void mct_u232_shutdown	         (struct usb_serial *serial);
95 static int  mct_u232_open	         (struct usb_serial_port *port,
96 					  struct file *filp);
97 static void mct_u232_close	         (struct usb_serial_port *port,
98 					  struct file *filp);
99 static void mct_u232_read_int_callback   (struct urb *urb);
100 static void mct_u232_set_termios         (struct usb_serial_port *port,
101 					  struct ktermios * old);
102 static int  mct_u232_ioctl	         (struct usb_serial_port *port,
103 					  struct file * file,
104 					  unsigned int cmd,
105 					  unsigned long arg);
106 static void mct_u232_break_ctl	         (struct usb_serial_port *port,
107 					  int break_state );
108 static int  mct_u232_tiocmget		 (struct usb_serial_port *port,
109 					  struct file *file);
110 static int  mct_u232_tiocmset		 (struct usb_serial_port *port,
111 					  struct file *file, unsigned int set,
112 					  unsigned int clear);
113 static void mct_u232_throttle		 (struct usb_serial_port *port);
114 static void mct_u232_unthrottle		 (struct usb_serial_port *port);
115 
116 
117 /*
118  * All of the device info needed for the MCT USB-RS232 converter.
119  */
120 static struct usb_device_id id_table_combined [] = {
121 	{ USB_DEVICE(MCT_U232_VID, MCT_U232_PID) },
122 	{ USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) },
123 	{ USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) },
124 	{ USB_DEVICE(MCT_U232_BELKIN_F5U109_VID, MCT_U232_BELKIN_F5U109_PID) },
125 	{ }		/* Terminating entry */
126 };
127 
128 MODULE_DEVICE_TABLE (usb, id_table_combined);
129 
130 static struct usb_driver mct_u232_driver = {
131 	.name =		"mct_u232",
132 	.probe =	usb_serial_probe,
133 	.disconnect =	usb_serial_disconnect,
134 	.id_table =	id_table_combined,
135 	.no_dynamic_id = 	1,
136 };
137 
138 static struct usb_serial_driver mct_u232_device = {
139 	.driver = {
140 		.owner =	THIS_MODULE,
141 		.name =		"mct_u232",
142 	},
143 	.description =	     "MCT U232",
144 	.usb_driver = 	     &mct_u232_driver,
145 	.id_table =	     id_table_combined,
146 	.num_interrupt_in =  2,
147 	.num_bulk_in =	     0,
148 	.num_bulk_out =	     1,
149 	.num_ports =	     1,
150 	.open =		     mct_u232_open,
151 	.close =	     mct_u232_close,
152 	.throttle =	     mct_u232_throttle,
153 	.unthrottle =	     mct_u232_unthrottle,
154 	.read_int_callback = mct_u232_read_int_callback,
155 	.ioctl =	     mct_u232_ioctl,
156 	.set_termios =	     mct_u232_set_termios,
157 	.break_ctl =	     mct_u232_break_ctl,
158 	.tiocmget =	     mct_u232_tiocmget,
159 	.tiocmset =	     mct_u232_tiocmset,
160 	.attach =	     mct_u232_startup,
161 	.shutdown =	     mct_u232_shutdown,
162 };
163 
164 
165 struct mct_u232_private {
166 	spinlock_t lock;
167 	unsigned int	     control_state; /* Modem Line Setting (TIOCM) */
168 	unsigned char        last_lcr;      /* Line Control Register */
169 	unsigned char	     last_lsr;      /* Line Status Register */
170 	unsigned char	     last_msr;      /* Modem Status Register */
171 	unsigned int	     rx_flags;      /* Throttling flags */
172 };
173 
174 #define THROTTLED		0x01
175 
176 /*
177  * Handle vendor specific USB requests
178  */
179 
180 #define WDR_TIMEOUT 5000 /* default urb timeout */
181 
182 /*
183  * Later day 2.6.0-test kernels have new baud rates like B230400 which
184  * we do not know how to support. We ignore them for the moment.
185  */
186 static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value, speed_t *result)
187 {
188 	*result = value;
189 
190 	if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID
191 	  || le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) {
192 		switch (value) {
193 		case    300: return 0x01;
194 		case    600: return 0x02; /* this one not tested */
195 		case   1200: return 0x03;
196 		case   2400: return 0x04;
197 		case   4800: return 0x06;
198 		case   9600: return 0x08;
199 		case  19200: return 0x09;
200 		case  38400: return 0x0a;
201 		case  57600: return 0x0b;
202 		case 115200: return 0x0c;
203 		default:
204 			*result = 9600;
205 			return 0x08;
206 		}
207 	} else {
208 		/* FIXME: Can we use any divider - should we do
209 		   divider = 115200/value;
210 		   real baud = 115200/divider */
211 		switch (value) {
212 		case 300: break;
213 		case 600: break;
214 		case 1200: break;
215 		case 2400: break;
216 		case 4800: break;
217 		case 9600: break;
218 		case 19200: break;
219 		case 38400: break;
220 		case 57600: break;
221 		case 115200: break;
222 		default:
223 			value = 9600;
224 			*result = 9600;
225 		}
226 		return 115200/value;
227 	}
228 }
229 
230 static int mct_u232_set_baud_rate(struct usb_serial *serial, struct usb_serial_port *port,
231 				  speed_t value)
232 {
233 	__le32 divisor;
234         int rc;
235         unsigned char zero_byte = 0;
236         unsigned char cts_enable_byte = 0;
237         speed_t speed;
238 
239 	divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value, &speed));
240 
241         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
242                              MCT_U232_SET_BAUD_RATE_REQUEST,
243 			     MCT_U232_SET_REQUEST_TYPE,
244                              0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE,
245 			     WDR_TIMEOUT);
246 	if (rc < 0)	/*FIXME: What value speed results */
247 		err("Set BAUD RATE %d failed (error = %d)", value, rc);
248 	else
249 		tty_encode_baud_rate(port->tty, speed, speed);
250 	dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor);
251 
252 	/* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which
253 	   always sends two extra USB 'device request' messages after the
254 	   'baud rate change' message.  The actual functionality of the
255 	   request codes in these messages is not fully understood but these
256 	   particular codes are never seen in any operation besides a baud
257 	   rate change.  Both of these messages send a single byte of data.
258 	   In the first message, the value of this byte is always zero.
259 
260 	   The second message has been determined experimentally to control
261 	   whether data will be transmitted to a device which is not asserting
262 	   the 'CTS' signal.  If the second message's data byte is zero, data
263 	   will be transmitted even if 'CTS' is not asserted (i.e. no hardware
264 	   flow control).  if the second message's data byte is nonzero (a value
265 	   of 1 is used by this driver), data will not be transmitted to a device
266 	   which is not asserting 'CTS'.
267 	*/
268 
269 	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
270 			     MCT_U232_SET_UNKNOWN1_REQUEST,
271 			     MCT_U232_SET_REQUEST_TYPE,
272 			     0, 0, &zero_byte, MCT_U232_SET_UNKNOWN1_SIZE,
273 			     WDR_TIMEOUT);
274 	if (rc < 0)
275 		err("Sending USB device request code %d failed (error = %d)",
276 		    MCT_U232_SET_UNKNOWN1_REQUEST, rc);
277 
278 	if (port && C_CRTSCTS(port->tty)) {
279 	   cts_enable_byte = 1;
280 	}
281 
282         dbg("set_baud_rate: send second control message, data = %02X", cts_enable_byte);
283 	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
284 			     MCT_U232_SET_CTS_REQUEST,
285 			     MCT_U232_SET_REQUEST_TYPE,
286 			     0, 0, &cts_enable_byte, MCT_U232_SET_CTS_SIZE,
287 			     WDR_TIMEOUT);
288 	if (rc < 0)
289 	  err("Sending USB device request code %d failed (error = %d)",
290 	      MCT_U232_SET_CTS_REQUEST, rc);
291 
292         return rc;
293 } /* mct_u232_set_baud_rate */
294 
295 static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr)
296 {
297         int rc;
298         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
299                              MCT_U232_SET_LINE_CTRL_REQUEST,
300 			     MCT_U232_SET_REQUEST_TYPE,
301                              0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE,
302 			     WDR_TIMEOUT);
303 	if (rc < 0)
304 		err("Set LINE CTRL 0x%x failed (error = %d)", lcr, rc);
305 	dbg("set_line_ctrl: 0x%x", lcr);
306         return rc;
307 } /* mct_u232_set_line_ctrl */
308 
309 static int mct_u232_set_modem_ctrl(struct usb_serial *serial,
310 				   unsigned int control_state)
311 {
312         int rc;
313 	unsigned char mcr = MCT_U232_MCR_NONE;
314 
315 	if (control_state & TIOCM_DTR)
316 		mcr |= MCT_U232_MCR_DTR;
317 	if (control_state & TIOCM_RTS)
318 		mcr |= MCT_U232_MCR_RTS;
319 
320         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
321                              MCT_U232_SET_MODEM_CTRL_REQUEST,
322 			     MCT_U232_SET_REQUEST_TYPE,
323                              0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE,
324 			     WDR_TIMEOUT);
325 	if (rc < 0)
326 		err("Set MODEM CTRL 0x%x failed (error = %d)", mcr, rc);
327 	dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr);
328 
329         return rc;
330 } /* mct_u232_set_modem_ctrl */
331 
332 static int mct_u232_get_modem_stat(struct usb_serial *serial, unsigned char *msr)
333 {
334         int rc;
335         rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
336                              MCT_U232_GET_MODEM_STAT_REQUEST,
337 			     MCT_U232_GET_REQUEST_TYPE,
338                              0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE,
339 			     WDR_TIMEOUT);
340 	if (rc < 0) {
341 		err("Get MODEM STATus failed (error = %d)", rc);
342 		*msr = 0;
343 	}
344 	dbg("get_modem_stat: 0x%x", *msr);
345         return rc;
346 } /* mct_u232_get_modem_stat */
347 
348 static void mct_u232_msr_to_state(unsigned int *control_state, unsigned char msr)
349 {
350  	/* Translate Control Line states */
351 	if (msr & MCT_U232_MSR_DSR)
352 		*control_state |=  TIOCM_DSR;
353 	else
354 		*control_state &= ~TIOCM_DSR;
355 	if (msr & MCT_U232_MSR_CTS)
356 		*control_state |=  TIOCM_CTS;
357 	else
358 		*control_state &= ~TIOCM_CTS;
359 	if (msr & MCT_U232_MSR_RI)
360 		*control_state |=  TIOCM_RI;
361 	else
362 		*control_state &= ~TIOCM_RI;
363 	if (msr & MCT_U232_MSR_CD)
364 		*control_state |=  TIOCM_CD;
365 	else
366 		*control_state &= ~TIOCM_CD;
367  	dbg("msr_to_state: msr=0x%x ==> state=0x%x", msr, *control_state);
368 } /* mct_u232_msr_to_state */
369 
370 /*
371  * Driver's tty interface functions
372  */
373 
374 static int mct_u232_startup (struct usb_serial *serial)
375 {
376 	struct mct_u232_private *priv;
377 	struct usb_serial_port *port, *rport;
378 
379 	priv = kzalloc(sizeof(struct mct_u232_private), GFP_KERNEL);
380 	if (!priv)
381 		return -ENOMEM;
382 	spin_lock_init(&priv->lock);
383 	usb_set_serial_port_data(serial->port[0], priv);
384 
385 	init_waitqueue_head(&serial->port[0]->write_wait);
386 
387 	/* Puh, that's dirty */
388 	port = serial->port[0];
389 	rport = serial->port[1];
390 	/* No unlinking, it wasn't submitted yet. */
391 	usb_free_urb(port->read_urb);
392 	port->read_urb = rport->interrupt_in_urb;
393 	rport->interrupt_in_urb = NULL;
394 	port->read_urb->context = port;
395 
396 	return (0);
397 } /* mct_u232_startup */
398 
399 
400 static void mct_u232_shutdown (struct usb_serial *serial)
401 {
402 	struct mct_u232_private *priv;
403 	int i;
404 
405 	dbg("%s", __FUNCTION__);
406 
407 	for (i=0; i < serial->num_ports; ++i) {
408 		/* My special items, the standard routines free my urbs */
409 		priv = usb_get_serial_port_data(serial->port[i]);
410 		if (priv) {
411 			usb_set_serial_port_data(serial->port[i], NULL);
412 			kfree(priv);
413 		}
414 	}
415 } /* mct_u232_shutdown */
416 
417 static int  mct_u232_open (struct usb_serial_port *port, struct file *filp)
418 {
419 	struct usb_serial *serial = port->serial;
420 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
421 	int retval = 0;
422 	unsigned int control_state;
423 	unsigned long flags;
424 	unsigned char last_lcr;
425 	unsigned char last_msr;
426 
427 	dbg("%s port %d", __FUNCTION__, port->number);
428 
429 	/* Compensate for a hardware bug: although the Sitecom U232-P25
430 	 * device reports a maximum output packet size of 32 bytes,
431 	 * it seems to be able to accept only 16 bytes (and that's what
432 	 * SniffUSB says too...)
433 	 */
434 	if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID)
435 		port->bulk_out_size = 16;
436 
437 	/* Do a defined restart: the normal serial device seems to
438 	 * always turn on DTR and RTS here, so do the same. I'm not
439 	 * sure if this is really necessary. But it should not harm
440 	 * either.
441 	 */
442 	spin_lock_irqsave(&priv->lock, flags);
443 	if (port->tty->termios->c_cflag & CBAUD)
444 		priv->control_state = TIOCM_DTR | TIOCM_RTS;
445 	else
446 		priv->control_state = 0;
447 
448 	priv->last_lcr = (MCT_U232_DATA_BITS_8 |
449 			  MCT_U232_PARITY_NONE |
450 			  MCT_U232_STOP_BITS_1);
451 	control_state = priv->control_state;
452 	last_lcr = priv->last_lcr;
453 	spin_unlock_irqrestore(&priv->lock, flags);
454 	mct_u232_set_modem_ctrl(serial, control_state);
455 	mct_u232_set_line_ctrl(serial, last_lcr);
456 
457 	/* Read modem status and update control state */
458 	mct_u232_get_modem_stat(serial, &last_msr);
459 	spin_lock_irqsave(&priv->lock, flags);
460 	priv->last_msr = last_msr;
461 	mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
462 	spin_unlock_irqrestore(&priv->lock, flags);
463 
464 	port->read_urb->dev = port->serial->dev;
465 	retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
466 	if (retval) {
467 		err("usb_submit_urb(read bulk) failed pipe 0x%x err %d",
468 		    port->read_urb->pipe, retval);
469 		goto error;
470 	}
471 
472 	port->interrupt_in_urb->dev = port->serial->dev;
473 	retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
474 	if (retval) {
475 		usb_kill_urb(port->read_urb);
476 		err(" usb_submit_urb(read int) failed pipe 0x%x err %d",
477 		    port->interrupt_in_urb->pipe, retval);
478 		goto error;
479 	}
480 	return 0;
481 
482 error:
483 	return retval;
484 } /* mct_u232_open */
485 
486 
487 static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
488 {
489 	unsigned int c_cflag;
490 	unsigned int control_state;
491 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
492 	dbg("%s port %d", __FUNCTION__, port->number);
493 
494    	if (port->tty) {
495 		c_cflag = port->tty->termios->c_cflag;
496 		mutex_lock(&port->serial->disc_mutex);
497 		if (c_cflag & HUPCL && !port->serial->disconnected) {
498 			/* drop DTR and RTS */
499 			spin_lock_irq(&priv->lock);
500 			priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
501 			control_state = priv->control_state;
502 			spin_unlock_irq(&priv->lock);
503 			mct_u232_set_modem_ctrl(port->serial, control_state);
504 		}
505 		mutex_unlock(&port->serial->disc_mutex);
506 	}
507 
508 
509 	if (port->serial->dev) {
510 		/* shutdown our urbs */
511 		usb_kill_urb(port->write_urb);
512 		usb_kill_urb(port->read_urb);
513 		usb_kill_urb(port->interrupt_in_urb);
514 	}
515 } /* mct_u232_close */
516 
517 
518 static void mct_u232_read_int_callback (struct urb *urb)
519 {
520 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
521 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
522 	struct usb_serial *serial = port->serial;
523 	struct tty_struct *tty;
524 	unsigned char *data = urb->transfer_buffer;
525 	int retval;
526 	int status = urb->status;
527 	unsigned long flags;
528 
529 	switch (status) {
530 	case 0:
531 		/* success */
532 		break;
533 	case -ECONNRESET:
534 	case -ENOENT:
535 	case -ESHUTDOWN:
536 		/* this urb is terminated, clean up */
537 		dbg("%s - urb shutting down with status: %d",
538 		    __FUNCTION__, status);
539 		return;
540 	default:
541 		dbg("%s - nonzero urb status received: %d",
542 		    __FUNCTION__, status);
543 		goto exit;
544 	}
545 
546 	if (!serial) {
547 		dbg("%s - bad serial pointer, exiting", __FUNCTION__);
548 		return;
549 	}
550 
551         dbg("%s - port %d", __FUNCTION__, port->number);
552 	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
553 
554 	/*
555 	 * Work-a-round: handle the 'usual' bulk-in pipe here
556 	 */
557 	if (urb->transfer_buffer_length > 2) {
558 		int i;
559 		tty = port->tty;
560 		if (urb->actual_length) {
561 			for (i = 0; i < urb->actual_length ; ++i) {
562 				tty_insert_flip_char(tty, data[i], 0);
563 			}
564 			tty_flip_buffer_push(tty);
565 		}
566 		goto exit;
567 	}
568 
569 	/*
570 	 * The interrupt-in pipe signals exceptional conditions (modem line
571 	 * signal changes and errors). data[0] holds MSR, data[1] holds LSR.
572 	 */
573 	spin_lock_irqsave(&priv->lock, flags);
574 	priv->last_msr = data[MCT_U232_MSR_INDEX];
575 
576 	/* Record Control Line states */
577 	mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
578 
579 #if 0
580 	/* Not yet handled. See belin_sa.c for further information */
581 	/* Now to report any errors */
582 	priv->last_lsr = data[MCT_U232_LSR_INDEX];
583 	/*
584 	 * fill in the flip buffer here, but I do not know the relation
585 	 * to the current/next receive buffer or characters.  I need
586 	 * to look in to this before committing any code.
587 	 */
588 	if (priv->last_lsr & MCT_U232_LSR_ERR) {
589 		tty = port->tty;
590 		/* Overrun Error */
591 		if (priv->last_lsr & MCT_U232_LSR_OE) {
592 		}
593 		/* Parity Error */
594 		if (priv->last_lsr & MCT_U232_LSR_PE) {
595 		}
596 		/* Framing Error */
597 		if (priv->last_lsr & MCT_U232_LSR_FE) {
598 		}
599 		/* Break Indicator */
600 		if (priv->last_lsr & MCT_U232_LSR_BI) {
601 		}
602 	}
603 #endif
604 	spin_unlock_irqrestore(&priv->lock, flags);
605 exit:
606 	retval = usb_submit_urb (urb, GFP_ATOMIC);
607 	if (retval)
608 		err ("%s - usb_submit_urb failed with result %d",
609 		     __FUNCTION__, retval);
610 } /* mct_u232_read_int_callback */
611 
612 static void mct_u232_set_termios (struct usb_serial_port *port,
613 				  struct ktermios *old_termios)
614 {
615 	struct usb_serial *serial = port->serial;
616 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
617 	struct ktermios *termios = port->tty->termios;
618 	unsigned int cflag = termios->c_cflag;
619 	unsigned int old_cflag = old_termios->c_cflag;
620 	unsigned long flags;
621 	unsigned int control_state;
622 	unsigned char last_lcr;
623 
624 	/* get a local copy of the current port settings */
625 	spin_lock_irqsave(&priv->lock, flags);
626 	control_state = priv->control_state;
627 	spin_unlock_irqrestore(&priv->lock, flags);
628 	last_lcr = 0;
629 
630 	/*
631 	 * Update baud rate.
632 	 * Do not attempt to cache old rates and skip settings,
633 	 * disconnects screw such tricks up completely.
634 	 * Premature optimization is the root of all evil.
635 	 */
636 
637         /* reassert DTR and RTS on transition from B0 */
638 	if ((old_cflag & CBAUD) == B0) {
639 		dbg("%s: baud was B0", __FUNCTION__);
640 		control_state |= TIOCM_DTR | TIOCM_RTS;
641 		mct_u232_set_modem_ctrl(serial, control_state);
642 	}
643 
644 	mct_u232_set_baud_rate(serial, port, tty_get_baud_rate(port->tty));
645 
646 	if ((cflag & CBAUD) == B0 ) {
647 		dbg("%s: baud is B0", __FUNCTION__);
648 		/* Drop RTS and DTR */
649 		control_state &= ~(TIOCM_DTR | TIOCM_RTS);
650        		mct_u232_set_modem_ctrl(serial, control_state);
651 	}
652 
653 	/*
654 	 * Update line control register (LCR)
655 	 */
656 
657 	/* set the parity */
658 	if (cflag & PARENB)
659 		last_lcr |= (cflag & PARODD) ?
660 			MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN;
661 	else
662 		last_lcr |= MCT_U232_PARITY_NONE;
663 
664 	/* set the number of data bits */
665 	switch (cflag & CSIZE) {
666 	case CS5:
667 		last_lcr |= MCT_U232_DATA_BITS_5; break;
668 	case CS6:
669 		last_lcr |= MCT_U232_DATA_BITS_6; break;
670 	case CS7:
671 		last_lcr |= MCT_U232_DATA_BITS_7; break;
672 	case CS8:
673 		last_lcr |= MCT_U232_DATA_BITS_8; break;
674 	default:
675 		err("CSIZE was not CS5-CS8, using default of 8");
676 		last_lcr |= MCT_U232_DATA_BITS_8;
677 		break;
678 	}
679 
680 	termios->c_cflag &= ~CMSPAR;
681 
682 	/* set the number of stop bits */
683 	last_lcr |= (cflag & CSTOPB) ?
684 		MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
685 
686 	mct_u232_set_line_ctrl(serial, last_lcr);
687 
688 	/* save off the modified port settings */
689 	spin_lock_irqsave(&priv->lock, flags);
690 	priv->control_state = control_state;
691 	priv->last_lcr = last_lcr;
692 	spin_unlock_irqrestore(&priv->lock, flags);
693 } /* mct_u232_set_termios */
694 
695 static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
696 {
697 	struct usb_serial *serial = port->serial;
698 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
699 	unsigned char lcr;
700 	unsigned long flags;
701 
702 	dbg("%sstate=%d", __FUNCTION__, break_state);
703 
704 	spin_lock_irqsave(&priv->lock, flags);
705 	lcr = priv->last_lcr;
706 	spin_unlock_irqrestore(&priv->lock, flags);
707 
708 	if (break_state)
709 		lcr |= MCT_U232_SET_BREAK;
710 
711 	mct_u232_set_line_ctrl(serial, lcr);
712 } /* mct_u232_break_ctl */
713 
714 
715 static int mct_u232_tiocmget (struct usb_serial_port *port, struct file *file)
716 {
717 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
718 	unsigned int control_state;
719 	unsigned long flags;
720 
721 	dbg("%s", __FUNCTION__);
722 
723 	spin_lock_irqsave(&priv->lock, flags);
724 	control_state = priv->control_state;
725 	spin_unlock_irqrestore(&priv->lock, flags);
726 
727 	return control_state;
728 }
729 
730 static int mct_u232_tiocmset (struct usb_serial_port *port, struct file *file,
731 			      unsigned int set, unsigned int clear)
732 {
733 	struct usb_serial *serial = port->serial;
734 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
735 	unsigned int control_state;
736 	unsigned long flags;
737 
738 	dbg("%s", __FUNCTION__);
739 
740 	spin_lock_irqsave(&priv->lock, flags);
741 	control_state = priv->control_state;
742 
743 	if (set & TIOCM_RTS)
744 		control_state |= TIOCM_RTS;
745 	if (set & TIOCM_DTR)
746 		control_state |= TIOCM_DTR;
747 	if (clear & TIOCM_RTS)
748 		control_state &= ~TIOCM_RTS;
749 	if (clear & TIOCM_DTR)
750 		control_state &= ~TIOCM_DTR;
751 
752 	priv->control_state = control_state;
753 	spin_unlock_irqrestore(&priv->lock, flags);
754 	return mct_u232_set_modem_ctrl(serial, control_state);
755 }
756 
757 static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
758 			   unsigned int cmd, unsigned long arg)
759 {
760 	dbg("%scmd=0x%x", __FUNCTION__, cmd);
761 
762 	/* Based on code from acm.c and others */
763 	switch (cmd) {
764 	case TIOCMIWAIT:
765 		/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
766 		/* TODO */
767 		return( 0 );
768 
769 	case TIOCGICOUNT:
770 		/* return count of modemline transitions */
771 		/* TODO */
772 		return 0;
773 
774 	default:
775 		dbg("%s: arg not supported - 0x%04x", __FUNCTION__,cmd);
776 		return(-ENOIOCTLCMD);
777 		break;
778 	}
779 	return 0;
780 } /* mct_u232_ioctl */
781 
782 static void mct_u232_throttle (struct usb_serial_port *port)
783 {
784 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
785 	unsigned long flags;
786 	unsigned int control_state;
787 	struct tty_struct *tty;
788 
789 	tty = port->tty;
790 	dbg("%s - port %d", __FUNCTION__, port->number);
791 
792 	spin_lock_irqsave(&priv->lock, flags);
793 	priv->rx_flags |= THROTTLED;
794 	if (C_CRTSCTS(tty)) {
795 	  priv->control_state &= ~TIOCM_RTS;
796 	  control_state = priv->control_state;
797 	  spin_unlock_irqrestore(&priv->lock, flags);
798 	  (void) mct_u232_set_modem_ctrl(port->serial, control_state);
799 	} else {
800 	  spin_unlock_irqrestore(&priv->lock, flags);
801 	}
802 }
803 
804 
805 static void mct_u232_unthrottle (struct usb_serial_port *port)
806 {
807 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
808 	unsigned long flags;
809 	unsigned int control_state;
810 	struct tty_struct *tty;
811 
812 	dbg("%s - port %d", __FUNCTION__, port->number);
813 
814 	tty = port->tty;
815 	spin_lock_irqsave(&priv->lock, flags);
816 	if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) {
817 	  priv->rx_flags &= ~THROTTLED;
818 	  priv->control_state |= TIOCM_RTS;
819 	  control_state = priv->control_state;
820 	  spin_unlock_irqrestore(&priv->lock, flags);
821 	  (void) mct_u232_set_modem_ctrl(port->serial, control_state);
822 	} else {
823 	  spin_unlock_irqrestore(&priv->lock, flags);
824 	}
825 }
826 
827 static int __init mct_u232_init (void)
828 {
829 	int retval;
830 	retval = usb_serial_register(&mct_u232_device);
831 	if (retval)
832 		goto failed_usb_serial_register;
833 	retval = usb_register(&mct_u232_driver);
834 	if (retval)
835 		goto failed_usb_register;
836 	info(DRIVER_DESC " " DRIVER_VERSION);
837 	return 0;
838 failed_usb_register:
839 	usb_serial_deregister(&mct_u232_device);
840 failed_usb_serial_register:
841 	return retval;
842 }
843 
844 
845 static void __exit mct_u232_exit (void)
846 {
847 	usb_deregister (&mct_u232_driver);
848 	usb_serial_deregister (&mct_u232_device);
849 }
850 
851 
852 module_init (mct_u232_init);
853 module_exit(mct_u232_exit);
854 
855 MODULE_AUTHOR( DRIVER_AUTHOR );
856 MODULE_DESCRIPTION( DRIVER_DESC );
857 MODULE_LICENSE("GPL");
858 
859 module_param(debug, bool, S_IRUGO | S_IWUSR);
860 MODULE_PARM_DESC(debug, "Debug enabled or not");
861