xref: /linux/drivers/usb/serial/mct_u232.c (revision 564eb714f5f09ac733c26860d5f0831f213fbdf1)
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 
24 #include <linux/kernel.h>
25 #include <linux/errno.h>
26 #include <linux/init.h>
27 #include <linux/slab.h>
28 #include <linux/tty.h>
29 #include <linux/tty_driver.h>
30 #include <linux/tty_flip.h>
31 #include <linux/module.h>
32 #include <linux/spinlock.h>
33 #include <linux/uaccess.h>
34 #include <asm/unaligned.h>
35 #include <linux/usb.h>
36 #include <linux/usb/serial.h>
37 #include <linux/serial.h>
38 #include "mct_u232.h"
39 
40 #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
41 #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
42 
43 /*
44  * Function prototypes
45  */
46 static int  mct_u232_port_probe(struct usb_serial_port *port);
47 static int  mct_u232_port_remove(struct usb_serial_port *remove);
48 static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port);
49 static void mct_u232_close(struct usb_serial_port *port);
50 static void mct_u232_dtr_rts(struct usb_serial_port *port, int on);
51 static void mct_u232_read_int_callback(struct urb *urb);
52 static void mct_u232_set_termios(struct tty_struct *tty,
53 			struct usb_serial_port *port, struct ktermios *old);
54 static void mct_u232_break_ctl(struct tty_struct *tty, int break_state);
55 static int  mct_u232_tiocmget(struct tty_struct *tty);
56 static int  mct_u232_tiocmset(struct tty_struct *tty,
57 			unsigned int set, unsigned int clear);
58 static void mct_u232_throttle(struct tty_struct *tty);
59 static void mct_u232_unthrottle(struct tty_struct *tty);
60 
61 
62 /*
63  * All of the device info needed for the MCT USB-RS232 converter.
64  */
65 static const struct usb_device_id id_table[] = {
66 	{ USB_DEVICE(MCT_U232_VID, MCT_U232_PID) },
67 	{ USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) },
68 	{ USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) },
69 	{ USB_DEVICE(MCT_U232_BELKIN_F5U109_VID, MCT_U232_BELKIN_F5U109_PID) },
70 	{ }		/* Terminating entry */
71 };
72 MODULE_DEVICE_TABLE(usb, id_table);
73 
74 static struct usb_serial_driver mct_u232_device = {
75 	.driver = {
76 		.owner =	THIS_MODULE,
77 		.name =		"mct_u232",
78 	},
79 	.description =	     "MCT U232",
80 	.id_table =	     id_table,
81 	.num_ports =	     1,
82 	.open =		     mct_u232_open,
83 	.close =	     mct_u232_close,
84 	.dtr_rts =	     mct_u232_dtr_rts,
85 	.throttle =	     mct_u232_throttle,
86 	.unthrottle =	     mct_u232_unthrottle,
87 	.read_int_callback = mct_u232_read_int_callback,
88 	.set_termios =	     mct_u232_set_termios,
89 	.break_ctl =	     mct_u232_break_ctl,
90 	.tiocmget =	     mct_u232_tiocmget,
91 	.tiocmset =	     mct_u232_tiocmset,
92 	.tiocmiwait =        usb_serial_generic_tiocmiwait,
93 	.port_probe =        mct_u232_port_probe,
94 	.port_remove =       mct_u232_port_remove,
95 	.get_icount =        usb_serial_generic_get_icount,
96 };
97 
98 static struct usb_serial_driver * const serial_drivers[] = {
99 	&mct_u232_device, NULL
100 };
101 
102 struct mct_u232_private {
103 	struct urb *read_urb;
104 	spinlock_t lock;
105 	unsigned int	     control_state; /* Modem Line Setting (TIOCM) */
106 	unsigned char        last_lcr;      /* Line Control Register */
107 	unsigned char	     last_lsr;      /* Line Status Register */
108 	unsigned char	     last_msr;      /* Modem Status Register */
109 	unsigned int	     rx_flags;      /* Throttling flags */
110 };
111 
112 #define THROTTLED		0x01
113 
114 /*
115  * Handle vendor specific USB requests
116  */
117 
118 #define WDR_TIMEOUT 5000 /* default urb timeout */
119 
120 /*
121  * Later day 2.6.0-test kernels have new baud rates like B230400 which
122  * we do not know how to support. We ignore them for the moment.
123  */
124 static int mct_u232_calculate_baud_rate(struct usb_serial *serial,
125 					speed_t value, speed_t *result)
126 {
127 	*result = value;
128 
129 	if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID
130 		|| le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) {
131 		switch (value) {
132 		case 300:
133 			return 0x01;
134 		case 600:
135 			return 0x02; /* this one not tested */
136 		case 1200:
137 			return 0x03;
138 		case 2400:
139 			return 0x04;
140 		case 4800:
141 			return 0x06;
142 		case 9600:
143 			return 0x08;
144 		case 19200:
145 			return 0x09;
146 		case 38400:
147 			return 0x0a;
148 		case 57600:
149 			return 0x0b;
150 		case 115200:
151 			return 0x0c;
152 		default:
153 			*result = 9600;
154 			return 0x08;
155 		}
156 	} else {
157 		/* FIXME: Can we use any divider - should we do
158 		   divider = 115200/value;
159 		   real baud = 115200/divider */
160 		switch (value) {
161 		case 300: break;
162 		case 600: break;
163 		case 1200: break;
164 		case 2400: break;
165 		case 4800: break;
166 		case 9600: break;
167 		case 19200: break;
168 		case 38400: break;
169 		case 57600: break;
170 		case 115200: break;
171 		default:
172 			value = 9600;
173 			*result = 9600;
174 		}
175 		return 115200/value;
176 	}
177 }
178 
179 static int mct_u232_set_baud_rate(struct tty_struct *tty,
180 	struct usb_serial *serial, struct usb_serial_port *port, speed_t value)
181 {
182 	unsigned int divisor;
183 	int rc;
184 	unsigned char *buf;
185 	unsigned char cts_enable_byte = 0;
186 	speed_t speed;
187 
188 	buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL);
189 	if (buf == NULL)
190 		return -ENOMEM;
191 
192 	divisor = mct_u232_calculate_baud_rate(serial, value, &speed);
193 	put_unaligned_le32(cpu_to_le32(divisor), buf);
194 	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
195 				MCT_U232_SET_BAUD_RATE_REQUEST,
196 				MCT_U232_SET_REQUEST_TYPE,
197 				0, 0, buf, MCT_U232_SET_BAUD_RATE_SIZE,
198 				WDR_TIMEOUT);
199 	if (rc < 0)	/*FIXME: What value speed results */
200 		dev_err(&port->dev, "Set BAUD RATE %d failed (error = %d)\n",
201 			value, rc);
202 	else
203 		tty_encode_baud_rate(tty, speed, speed);
204 	dev_dbg(&port->dev, "set_baud_rate: value: 0x%x, divisor: 0x%x\n", value, divisor);
205 
206 	/* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which
207 	   always sends two extra USB 'device request' messages after the
208 	   'baud rate change' message.  The actual functionality of the
209 	   request codes in these messages is not fully understood but these
210 	   particular codes are never seen in any operation besides a baud
211 	   rate change.  Both of these messages send a single byte of data.
212 	   In the first message, the value of this byte is always zero.
213 
214 	   The second message has been determined experimentally to control
215 	   whether data will be transmitted to a device which is not asserting
216 	   the 'CTS' signal.  If the second message's data byte is zero, data
217 	   will be transmitted even if 'CTS' is not asserted (i.e. no hardware
218 	   flow control).  if the second message's data byte is nonzero (a
219 	   value of 1 is used by this driver), data will not be transmitted to
220 	   a device which is not asserting 'CTS'.
221 	*/
222 
223 	buf[0] = 0;
224 	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
225 				MCT_U232_SET_UNKNOWN1_REQUEST,
226 				MCT_U232_SET_REQUEST_TYPE,
227 				0, 0, buf, MCT_U232_SET_UNKNOWN1_SIZE,
228 				WDR_TIMEOUT);
229 	if (rc < 0)
230 		dev_err(&port->dev, "Sending USB device request code %d "
231 			"failed (error = %d)\n", MCT_U232_SET_UNKNOWN1_REQUEST,
232 			rc);
233 
234 	if (port && C_CRTSCTS(tty))
235 	   cts_enable_byte = 1;
236 
237 	dev_dbg(&port->dev, "set_baud_rate: send second control message, data = %02X\n",
238 		cts_enable_byte);
239 	buf[0] = cts_enable_byte;
240 	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
241 			MCT_U232_SET_CTS_REQUEST,
242 			MCT_U232_SET_REQUEST_TYPE,
243 			0, 0, buf, MCT_U232_SET_CTS_SIZE,
244 			WDR_TIMEOUT);
245 	if (rc < 0)
246 		dev_err(&port->dev, "Sending USB device request code %d "
247 			"failed (error = %d)\n", MCT_U232_SET_CTS_REQUEST, rc);
248 
249 	kfree(buf);
250 	return rc;
251 } /* mct_u232_set_baud_rate */
252 
253 static int mct_u232_set_line_ctrl(struct usb_serial_port *port,
254 				  unsigned char lcr)
255 {
256 	int rc;
257 	unsigned char *buf;
258 
259 	buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL);
260 	if (buf == NULL)
261 		return -ENOMEM;
262 
263 	buf[0] = lcr;
264 	rc = usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0),
265 			MCT_U232_SET_LINE_CTRL_REQUEST,
266 			MCT_U232_SET_REQUEST_TYPE,
267 			0, 0, buf, MCT_U232_SET_LINE_CTRL_SIZE,
268 			WDR_TIMEOUT);
269 	if (rc < 0)
270 		dev_err(&port->dev, "Set LINE CTRL 0x%x failed (error = %d)\n", lcr, rc);
271 	dev_dbg(&port->dev, "set_line_ctrl: 0x%x\n", lcr);
272 	kfree(buf);
273 	return rc;
274 } /* mct_u232_set_line_ctrl */
275 
276 static int mct_u232_set_modem_ctrl(struct usb_serial_port *port,
277 				   unsigned int control_state)
278 {
279 	int rc;
280 	unsigned char mcr;
281 	unsigned char *buf;
282 
283 	buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL);
284 	if (buf == NULL)
285 		return -ENOMEM;
286 
287 	mcr = MCT_U232_MCR_NONE;
288 	if (control_state & TIOCM_DTR)
289 		mcr |= MCT_U232_MCR_DTR;
290 	if (control_state & TIOCM_RTS)
291 		mcr |= MCT_U232_MCR_RTS;
292 
293 	buf[0] = mcr;
294 	rc = usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0),
295 			MCT_U232_SET_MODEM_CTRL_REQUEST,
296 			MCT_U232_SET_REQUEST_TYPE,
297 			0, 0, buf, MCT_U232_SET_MODEM_CTRL_SIZE,
298 			WDR_TIMEOUT);
299 	kfree(buf);
300 
301 	dev_dbg(&port->dev, "set_modem_ctrl: state=0x%x ==> mcr=0x%x\n", control_state, mcr);
302 
303 	if (rc < 0) {
304 		dev_err(&port->dev, "Set MODEM CTRL 0x%x failed (error = %d)\n", mcr, rc);
305 		return rc;
306 	}
307 	return 0;
308 } /* mct_u232_set_modem_ctrl */
309 
310 static int mct_u232_get_modem_stat(struct usb_serial_port *port,
311 				   unsigned char *msr)
312 {
313 	int rc;
314 	unsigned char *buf;
315 
316 	buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL);
317 	if (buf == NULL) {
318 		*msr = 0;
319 		return -ENOMEM;
320 	}
321 	rc = usb_control_msg(port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0),
322 			MCT_U232_GET_MODEM_STAT_REQUEST,
323 			MCT_U232_GET_REQUEST_TYPE,
324 			0, 0, buf, MCT_U232_GET_MODEM_STAT_SIZE,
325 			WDR_TIMEOUT);
326 	if (rc < 0) {
327 		dev_err(&port->dev, "Get MODEM STATus failed (error = %d)\n", rc);
328 		*msr = 0;
329 	} else {
330 		*msr = buf[0];
331 	}
332 	dev_dbg(&port->dev, "get_modem_stat: 0x%x\n", *msr);
333 	kfree(buf);
334 	return rc;
335 } /* mct_u232_get_modem_stat */
336 
337 static void mct_u232_msr_to_icount(struct async_icount *icount,
338 						unsigned char msr)
339 {
340 	/* Translate Control Line states */
341 	if (msr & MCT_U232_MSR_DDSR)
342 		icount->dsr++;
343 	if (msr & MCT_U232_MSR_DCTS)
344 		icount->cts++;
345 	if (msr & MCT_U232_MSR_DRI)
346 		icount->rng++;
347 	if (msr & MCT_U232_MSR_DCD)
348 		icount->dcd++;
349 } /* mct_u232_msr_to_icount */
350 
351 static void mct_u232_msr_to_state(struct usb_serial_port *port,
352 				  unsigned int *control_state, unsigned char msr)
353 {
354 	/* Translate Control Line states */
355 	if (msr & MCT_U232_MSR_DSR)
356 		*control_state |=  TIOCM_DSR;
357 	else
358 		*control_state &= ~TIOCM_DSR;
359 	if (msr & MCT_U232_MSR_CTS)
360 		*control_state |=  TIOCM_CTS;
361 	else
362 		*control_state &= ~TIOCM_CTS;
363 	if (msr & MCT_U232_MSR_RI)
364 		*control_state |=  TIOCM_RI;
365 	else
366 		*control_state &= ~TIOCM_RI;
367 	if (msr & MCT_U232_MSR_CD)
368 		*control_state |=  TIOCM_CD;
369 	else
370 		*control_state &= ~TIOCM_CD;
371 	dev_dbg(&port->dev, "msr_to_state: msr=0x%x ==> state=0x%x\n", msr, *control_state);
372 } /* mct_u232_msr_to_state */
373 
374 /*
375  * Driver's tty interface functions
376  */
377 
378 static int mct_u232_port_probe(struct usb_serial_port *port)
379 {
380 	struct mct_u232_private *priv;
381 
382 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
383 	if (!priv)
384 		return -ENOMEM;
385 
386 	/* Use second interrupt-in endpoint for reading. */
387 	priv->read_urb = port->serial->port[1]->interrupt_in_urb;
388 	priv->read_urb->context = port;
389 
390 	spin_lock_init(&priv->lock);
391 
392 	usb_set_serial_port_data(port, priv);
393 
394 	return 0;
395 }
396 
397 static int mct_u232_port_remove(struct usb_serial_port *port)
398 {
399 	struct mct_u232_private *priv;
400 
401 	priv = usb_get_serial_port_data(port);
402 	kfree(priv);
403 
404 	return 0;
405 }
406 
407 static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)
408 {
409 	struct usb_serial *serial = port->serial;
410 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
411 	int retval = 0;
412 	unsigned int control_state;
413 	unsigned long flags;
414 	unsigned char last_lcr;
415 	unsigned char last_msr;
416 
417 	/* Compensate for a hardware bug: although the Sitecom U232-P25
418 	 * device reports a maximum output packet size of 32 bytes,
419 	 * it seems to be able to accept only 16 bytes (and that's what
420 	 * SniffUSB says too...)
421 	 */
422 	if (le16_to_cpu(serial->dev->descriptor.idProduct)
423 						== MCT_U232_SITECOM_PID)
424 		port->bulk_out_size = 16;
425 
426 	/* Do a defined restart: the normal serial device seems to
427 	 * always turn on DTR and RTS here, so do the same. I'm not
428 	 * sure if this is really necessary. But it should not harm
429 	 * either.
430 	 */
431 	spin_lock_irqsave(&priv->lock, flags);
432 	if (tty && (tty->termios.c_cflag & CBAUD))
433 		priv->control_state = TIOCM_DTR | TIOCM_RTS;
434 	else
435 		priv->control_state = 0;
436 
437 	priv->last_lcr = (MCT_U232_DATA_BITS_8 |
438 			  MCT_U232_PARITY_NONE |
439 			  MCT_U232_STOP_BITS_1);
440 	control_state = priv->control_state;
441 	last_lcr = priv->last_lcr;
442 	spin_unlock_irqrestore(&priv->lock, flags);
443 	mct_u232_set_modem_ctrl(port, control_state);
444 	mct_u232_set_line_ctrl(port, last_lcr);
445 
446 	/* Read modem status and update control state */
447 	mct_u232_get_modem_stat(port, &last_msr);
448 	spin_lock_irqsave(&priv->lock, flags);
449 	priv->last_msr = last_msr;
450 	mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr);
451 	spin_unlock_irqrestore(&priv->lock, flags);
452 
453 	retval = usb_submit_urb(priv->read_urb, GFP_KERNEL);
454 	if (retval) {
455 		dev_err(&port->dev,
456 			"usb_submit_urb(read) failed pipe 0x%x err %d\n",
457 			port->read_urb->pipe, retval);
458 		goto error;
459 	}
460 
461 	retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
462 	if (retval) {
463 		usb_kill_urb(priv->read_urb);
464 		dev_err(&port->dev,
465 			"usb_submit_urb(read int) failed pipe 0x%x err %d",
466 			port->interrupt_in_urb->pipe, retval);
467 		goto error;
468 	}
469 	return 0;
470 
471 error:
472 	return retval;
473 } /* mct_u232_open */
474 
475 static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)
476 {
477 	unsigned int control_state;
478 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
479 
480 	spin_lock_irq(&priv->lock);
481 	if (on)
482 		priv->control_state |= TIOCM_DTR | TIOCM_RTS;
483 	else
484 		priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
485 	control_state = priv->control_state;
486 	spin_unlock_irq(&priv->lock);
487 
488 	mct_u232_set_modem_ctrl(port, control_state);
489 }
490 
491 static void mct_u232_close(struct usb_serial_port *port)
492 {
493 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
494 
495 	usb_kill_urb(priv->read_urb);
496 	usb_kill_urb(port->interrupt_in_urb);
497 
498 	usb_serial_generic_close(port);
499 } /* mct_u232_close */
500 
501 
502 static void mct_u232_read_int_callback(struct urb *urb)
503 {
504 	struct usb_serial_port *port = urb->context;
505 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
506 	unsigned char *data = urb->transfer_buffer;
507 	int retval;
508 	int status = urb->status;
509 	unsigned long flags;
510 
511 	switch (status) {
512 	case 0:
513 		/* success */
514 		break;
515 	case -ECONNRESET:
516 	case -ENOENT:
517 	case -ESHUTDOWN:
518 		/* this urb is terminated, clean up */
519 		dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
520 			__func__, status);
521 		return;
522 	default:
523 		dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
524 			__func__, status);
525 		goto exit;
526 	}
527 
528 	usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
529 
530 	/*
531 	 * Work-a-round: handle the 'usual' bulk-in pipe here
532 	 */
533 	if (urb->transfer_buffer_length > 2) {
534 		if (urb->actual_length) {
535 			tty_insert_flip_string(&port->port, data,
536 					urb->actual_length);
537 			tty_flip_buffer_push(&port->port);
538 		}
539 		goto exit;
540 	}
541 
542 	/*
543 	 * The interrupt-in pipe signals exceptional conditions (modem line
544 	 * signal changes and errors). data[0] holds MSR, data[1] holds LSR.
545 	 */
546 	spin_lock_irqsave(&priv->lock, flags);
547 	priv->last_msr = data[MCT_U232_MSR_INDEX];
548 
549 	/* Record Control Line states */
550 	mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr);
551 
552 	mct_u232_msr_to_icount(&port->icount, priv->last_msr);
553 
554 #if 0
555 	/* Not yet handled. See belkin_sa.c for further information */
556 	/* Now to report any errors */
557 	priv->last_lsr = data[MCT_U232_LSR_INDEX];
558 	/*
559 	 * fill in the flip buffer here, but I do not know the relation
560 	 * to the current/next receive buffer or characters.  I need
561 	 * to look in to this before committing any code.
562 	 */
563 	if (priv->last_lsr & MCT_U232_LSR_ERR) {
564 		tty = tty_port_tty_get(&port->port);
565 		/* Overrun Error */
566 		if (priv->last_lsr & MCT_U232_LSR_OE) {
567 		}
568 		/* Parity Error */
569 		if (priv->last_lsr & MCT_U232_LSR_PE) {
570 		}
571 		/* Framing Error */
572 		if (priv->last_lsr & MCT_U232_LSR_FE) {
573 		}
574 		/* Break Indicator */
575 		if (priv->last_lsr & MCT_U232_LSR_BI) {
576 		}
577 		tty_kref_put(tty);
578 	}
579 #endif
580 	wake_up_interruptible(&port->port.delta_msr_wait);
581 	spin_unlock_irqrestore(&priv->lock, flags);
582 exit:
583 	retval = usb_submit_urb(urb, GFP_ATOMIC);
584 	if (retval)
585 		dev_err(&port->dev,
586 			"%s - usb_submit_urb failed with result %d\n",
587 			__func__, retval);
588 } /* mct_u232_read_int_callback */
589 
590 static void mct_u232_set_termios(struct tty_struct *tty,
591 				 struct usb_serial_port *port,
592 				 struct ktermios *old_termios)
593 {
594 	struct usb_serial *serial = port->serial;
595 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
596 	struct ktermios *termios = &tty->termios;
597 	unsigned int cflag = termios->c_cflag;
598 	unsigned int old_cflag = old_termios->c_cflag;
599 	unsigned long flags;
600 	unsigned int control_state;
601 	unsigned char last_lcr;
602 
603 	/* get a local copy of the current port settings */
604 	spin_lock_irqsave(&priv->lock, flags);
605 	control_state = priv->control_state;
606 	spin_unlock_irqrestore(&priv->lock, flags);
607 	last_lcr = 0;
608 
609 	/*
610 	 * Update baud rate.
611 	 * Do not attempt to cache old rates and skip settings,
612 	 * disconnects screw such tricks up completely.
613 	 * Premature optimization is the root of all evil.
614 	 */
615 
616 	/* reassert DTR and RTS on transition from B0 */
617 	if ((old_cflag & CBAUD) == B0) {
618 		dev_dbg(&port->dev, "%s: baud was B0\n", __func__);
619 		control_state |= TIOCM_DTR | TIOCM_RTS;
620 		mct_u232_set_modem_ctrl(port, control_state);
621 	}
622 
623 	mct_u232_set_baud_rate(tty, serial, port, tty_get_baud_rate(tty));
624 
625 	if ((cflag & CBAUD) == B0) {
626 		dev_dbg(&port->dev, "%s: baud is B0\n", __func__);
627 		/* Drop RTS and DTR */
628 		control_state &= ~(TIOCM_DTR | TIOCM_RTS);
629 		mct_u232_set_modem_ctrl(port, control_state);
630 	}
631 
632 	/*
633 	 * Update line control register (LCR)
634 	 */
635 
636 	/* set the parity */
637 	if (cflag & PARENB)
638 		last_lcr |= (cflag & PARODD) ?
639 			MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN;
640 	else
641 		last_lcr |= MCT_U232_PARITY_NONE;
642 
643 	/* set the number of data bits */
644 	switch (cflag & CSIZE) {
645 	case CS5:
646 		last_lcr |= MCT_U232_DATA_BITS_5; break;
647 	case CS6:
648 		last_lcr |= MCT_U232_DATA_BITS_6; break;
649 	case CS7:
650 		last_lcr |= MCT_U232_DATA_BITS_7; break;
651 	case CS8:
652 		last_lcr |= MCT_U232_DATA_BITS_8; break;
653 	default:
654 		dev_err(&port->dev,
655 			"CSIZE was not CS5-CS8, using default of 8\n");
656 		last_lcr |= MCT_U232_DATA_BITS_8;
657 		break;
658 	}
659 
660 	termios->c_cflag &= ~CMSPAR;
661 
662 	/* set the number of stop bits */
663 	last_lcr |= (cflag & CSTOPB) ?
664 		MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
665 
666 	mct_u232_set_line_ctrl(port, last_lcr);
667 
668 	/* save off the modified port settings */
669 	spin_lock_irqsave(&priv->lock, flags);
670 	priv->control_state = control_state;
671 	priv->last_lcr = last_lcr;
672 	spin_unlock_irqrestore(&priv->lock, flags);
673 } /* mct_u232_set_termios */
674 
675 static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
676 {
677 	struct usb_serial_port *port = tty->driver_data;
678 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
679 	unsigned char lcr;
680 	unsigned long flags;
681 
682 	spin_lock_irqsave(&priv->lock, flags);
683 	lcr = priv->last_lcr;
684 
685 	if (break_state)
686 		lcr |= MCT_U232_SET_BREAK;
687 	spin_unlock_irqrestore(&priv->lock, flags);
688 
689 	mct_u232_set_line_ctrl(port, lcr);
690 } /* mct_u232_break_ctl */
691 
692 
693 static int mct_u232_tiocmget(struct tty_struct *tty)
694 {
695 	struct usb_serial_port *port = tty->driver_data;
696 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
697 	unsigned int control_state;
698 	unsigned long flags;
699 
700 	spin_lock_irqsave(&priv->lock, flags);
701 	control_state = priv->control_state;
702 	spin_unlock_irqrestore(&priv->lock, flags);
703 
704 	return control_state;
705 }
706 
707 static int mct_u232_tiocmset(struct tty_struct *tty,
708 			      unsigned int set, unsigned int clear)
709 {
710 	struct usb_serial_port *port = tty->driver_data;
711 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
712 	unsigned int control_state;
713 	unsigned long flags;
714 
715 	spin_lock_irqsave(&priv->lock, flags);
716 	control_state = priv->control_state;
717 
718 	if (set & TIOCM_RTS)
719 		control_state |= TIOCM_RTS;
720 	if (set & TIOCM_DTR)
721 		control_state |= TIOCM_DTR;
722 	if (clear & TIOCM_RTS)
723 		control_state &= ~TIOCM_RTS;
724 	if (clear & TIOCM_DTR)
725 		control_state &= ~TIOCM_DTR;
726 
727 	priv->control_state = control_state;
728 	spin_unlock_irqrestore(&priv->lock, flags);
729 	return mct_u232_set_modem_ctrl(port, control_state);
730 }
731 
732 static void mct_u232_throttle(struct tty_struct *tty)
733 {
734 	struct usb_serial_port *port = tty->driver_data;
735 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
736 	unsigned int control_state;
737 
738 	spin_lock_irq(&priv->lock);
739 	priv->rx_flags |= THROTTLED;
740 	if (C_CRTSCTS(tty)) {
741 		priv->control_state &= ~TIOCM_RTS;
742 		control_state = priv->control_state;
743 		spin_unlock_irq(&priv->lock);
744 		mct_u232_set_modem_ctrl(port, control_state);
745 	} else {
746 		spin_unlock_irq(&priv->lock);
747 	}
748 }
749 
750 static void mct_u232_unthrottle(struct tty_struct *tty)
751 {
752 	struct usb_serial_port *port = tty->driver_data;
753 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
754 	unsigned int control_state;
755 
756 	spin_lock_irq(&priv->lock);
757 	if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) {
758 		priv->rx_flags &= ~THROTTLED;
759 		priv->control_state |= TIOCM_RTS;
760 		control_state = priv->control_state;
761 		spin_unlock_irq(&priv->lock);
762 		mct_u232_set_modem_ctrl(port, control_state);
763 	} else {
764 		spin_unlock_irq(&priv->lock);
765 	}
766 }
767 
768 module_usb_serial_driver(serial_drivers, id_table);
769 
770 MODULE_AUTHOR(DRIVER_AUTHOR);
771 MODULE_DESCRIPTION(DRIVER_DESC);
772 MODULE_LICENSE("GPL");
773