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