2 * MCT (Magic Control Technology Corp.) USB RS232 Converter Driver
4 * Copyright (C) 2000 Wolfgang Grandegger (wolfgang@ces.ch)
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.
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.
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.
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.
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).
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.
32 * 10-Nov-2001 Wolfgang Grandegger
33 * - Fixed an endianess problem with the baudrate selection for PowerPC.
35 * 06-Dec-2001 Martin Hamilton <martinh@gnu.org>
36 * Added support for the Belkin F5U109 DB9 adaptor
38 * 30-May-2001 Greg Kroah-Hartman
39 * switched from using spinlock to a semaphore, which fixes lots of problems.
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).
46 * 02-May-2001 Stelian Pop
47 * - Fixed the baud calculation for Sitecom U232-P25 model
50 * - Identify version on module load.
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)
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.
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).
67 #include <linux/config.h>
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 <asm/uaccess.h>
78 #include <linux/usb.h>
79 #include "usb-serial.h"
85 #define DRIVER_VERSION "v1.2"
86 #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
87 #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
90 * Some not properly written applications do not handle the return code of
91 * write() correctly. This can result in character losses. A work-a-round
92 * can be compiled in with the following definition. This work-a-round
93 * should _NOT_ be part of an 'official' kernel release, of course!
95 #undef FIX_WRITE_RETURN_CODE_PROBLEM
96 #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
97 static int write_blocking; /* disabled by default */
103 * Function prototypes
105 static int mct_u232_startup (struct usb_serial *serial);
106 static void mct_u232_shutdown (struct usb_serial *serial);
107 static int mct_u232_open (struct usb_serial_port *port,
109 static void mct_u232_close (struct usb_serial_port *port,
111 #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
112 static int mct_u232_write (struct usb_serial_port *port,
113 const unsigned char *buf,
115 static void mct_u232_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
117 static void mct_u232_read_int_callback (struct urb *urb, struct pt_regs *regs);
118 static void mct_u232_set_termios (struct usb_serial_port *port,
119 struct termios * old);
120 static int mct_u232_ioctl (struct usb_serial_port *port,
124 static void mct_u232_break_ctl (struct usb_serial_port *port,
126 static int mct_u232_tiocmget (struct usb_serial_port *port,
128 static int mct_u232_tiocmset (struct usb_serial_port *port,
129 struct file *file, unsigned int set,
132 * All of the device info needed for the MCT USB-RS232 converter.
134 static struct usb_device_id id_table_combined [] = {
135 { USB_DEVICE(MCT_U232_VID, MCT_U232_PID) },
136 { USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) },
137 { USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) },
138 { USB_DEVICE(MCT_U232_BELKIN_F5U109_VID, MCT_U232_BELKIN_F5U109_PID) },
139 { } /* Terminating entry */
142 MODULE_DEVICE_TABLE (usb, id_table_combined);
144 static struct usb_driver mct_u232_driver = {
145 .owner = THIS_MODULE,
147 .probe = usb_serial_probe,
148 .disconnect = usb_serial_disconnect,
149 .id_table = id_table_combined,
152 static struct usb_serial_device_type mct_u232_device = {
153 .owner = THIS_MODULE,
154 .name = "Magic Control Technology USB-RS232",
155 .short_name = "mct_u232",
156 .id_table = id_table_combined,
157 .num_interrupt_in = 2,
161 .open = mct_u232_open,
162 .close = mct_u232_close,
163 #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
164 .write = mct_u232_write,
165 .write_bulk_callback = mct_u232_write_bulk_callback,
167 .read_int_callback = mct_u232_read_int_callback,
168 .ioctl = mct_u232_ioctl,
169 .set_termios = mct_u232_set_termios,
170 .break_ctl = mct_u232_break_ctl,
171 .tiocmget = mct_u232_tiocmget,
172 .tiocmset = mct_u232_tiocmset,
173 .attach = mct_u232_startup,
174 .shutdown = mct_u232_shutdown,
178 struct mct_u232_private {
180 unsigned int control_state; /* Modem Line Setting (TIOCM) */
181 unsigned char last_lcr; /* Line Control Register */
182 unsigned char last_lsr; /* Line Status Register */
183 unsigned char last_msr; /* Modem Status Register */
187 * Handle vendor specific USB requests
190 #define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
193 * Later day 2.6.0-test kernels have new baud rates like B230400 which
194 * we do not know how to support. We ignore them for the moment.
195 * XXX Rate-limit the error message, it's user triggerable.
197 static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value) {
198 if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID
199 || serial->dev->descriptor.idProduct == MCT_U232_BELKIN_F5U109_PID) {
201 case B300: return 0x01;
202 case B600: return 0x02; /* this one not tested */
203 case B1200: return 0x03;
204 case B2400: return 0x04;
205 case B4800: return 0x06;
206 case B9600: return 0x08;
207 case B19200: return 0x09;
208 case B38400: return 0x0a;
209 case B57600: return 0x0b;
210 case B115200: return 0x0c;
212 err("MCT USB-RS232: unsupported baudrate request 0x%x,"
213 " using default of B9600", value);
218 case B300: value = 300;
219 case B600: value = 600;
220 case B1200: value = 1200;
221 case B2400: value = 2400;
222 case B4800: value = 4800;
223 case B9600: value = 9600;
224 case B19200: value = 19200;
225 case B38400: value = 38400;
226 case B57600: value = 57600;
227 case B115200: value = 115200;
229 err("MCT USB-RS232: unsupported baudrate request 0x%x,"
230 " using default of B9600", value);
237 static int mct_u232_set_baud_rate(struct usb_serial *serial, int value)
241 unsigned char zero_byte = 0;
243 divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value));
245 rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
246 MCT_U232_SET_BAUD_RATE_REQUEST,
247 MCT_U232_SET_REQUEST_TYPE,
248 0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE,
251 err("Set BAUD RATE %d failed (error = %d)", value, rc);
252 dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor);
254 /* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which
255 always sends two extra USB 'device request' messages after the
256 'baud rate change' message. The actual functionality of the
257 request codes in these messages is not fully understood but these
258 particular codes are never seen in any operation besides a baud
259 rate change. Both of these messages send a single byte of data
260 whose value is always zero. The second of these two extra messages
261 is required in order for data to be properly written to an RS-232
262 device which does not assert the 'CTS' signal. */
264 rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
265 MCT_U232_SET_UNKNOWN1_REQUEST,
266 MCT_U232_SET_REQUEST_TYPE,
267 0, 0, &zero_byte, MCT_U232_SET_UNKNOWN1_SIZE,
270 err("Sending USB device request code %d failed (error = %d)",
271 MCT_U232_SET_UNKNOWN1_REQUEST, rc);
273 rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
274 MCT_U232_SET_UNKNOWN2_REQUEST,
275 MCT_U232_SET_REQUEST_TYPE,
276 0, 0, &zero_byte, MCT_U232_SET_UNKNOWN2_SIZE,
279 err("Sending USB device request code %d failed (error = %d)",
280 MCT_U232_SET_UNKNOWN2_REQUEST, rc);
283 } /* mct_u232_set_baud_rate */
285 static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr)
288 rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
289 MCT_U232_SET_LINE_CTRL_REQUEST,
290 MCT_U232_SET_REQUEST_TYPE,
291 0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE,
294 err("Set LINE CTRL 0x%x failed (error = %d)", lcr, rc);
295 dbg("set_line_ctrl: 0x%x", lcr);
297 } /* mct_u232_set_line_ctrl */
299 static int mct_u232_set_modem_ctrl(struct usb_serial *serial,
300 unsigned int control_state)
303 unsigned char mcr = MCT_U232_MCR_NONE;
305 if (control_state & TIOCM_DTR)
306 mcr |= MCT_U232_MCR_DTR;
307 if (control_state & TIOCM_RTS)
308 mcr |= MCT_U232_MCR_RTS;
310 rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
311 MCT_U232_SET_MODEM_CTRL_REQUEST,
312 MCT_U232_SET_REQUEST_TYPE,
313 0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE,
316 err("Set MODEM CTRL 0x%x failed (error = %d)", mcr, rc);
317 dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr);
320 } /* mct_u232_set_modem_ctrl */
322 static int mct_u232_get_modem_stat(struct usb_serial *serial, unsigned char *msr)
325 rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
326 MCT_U232_GET_MODEM_STAT_REQUEST,
327 MCT_U232_GET_REQUEST_TYPE,
328 0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE,
331 err("Get MODEM STATus failed (error = %d)", rc);
334 dbg("get_modem_stat: 0x%x", *msr);
336 } /* mct_u232_get_modem_stat */
338 static void mct_u232_msr_to_state(unsigned int *control_state, unsigned char msr)
340 /* Translate Control Line states */
341 if (msr & MCT_U232_MSR_DSR)
342 *control_state |= TIOCM_DSR;
344 *control_state &= ~TIOCM_DSR;
345 if (msr & MCT_U232_MSR_CTS)
346 *control_state |= TIOCM_CTS;
348 *control_state &= ~TIOCM_CTS;
349 if (msr & MCT_U232_MSR_RI)
350 *control_state |= TIOCM_RI;
352 *control_state &= ~TIOCM_RI;
353 if (msr & MCT_U232_MSR_CD)
354 *control_state |= TIOCM_CD;
356 *control_state &= ~TIOCM_CD;
357 dbg("msr_to_state: msr=0x%x ==> state=0x%x", msr, *control_state);
358 } /* mct_u232_msr_to_state */
361 * Driver's tty interface functions
364 static int mct_u232_startup (struct usb_serial *serial)
366 struct mct_u232_private *priv;
367 struct usb_serial_port *port, *rport;
369 /* allocate the private data structure */
370 priv = kmalloc(sizeof(struct mct_u232_private), GFP_KERNEL);
373 /* set initial values for control structures */
374 spin_lock_init(&priv->lock);
375 priv->control_state = 0;
378 usb_set_serial_port_data(serial->port[0], priv);
380 init_waitqueue_head(&serial->port[0]->write_wait);
382 /* Puh, that's dirty */
383 port = serial->port[0];
384 rport = serial->port[1];
385 if (port->read_urb) {
386 /* No unlinking, it wasn't submitted yet. */
387 usb_free_urb(port->read_urb);
389 port->read_urb = rport->interrupt_in_urb;
390 rport->interrupt_in_urb = NULL;
391 port->read_urb->context = port;
394 } /* mct_u232_startup */
397 static void mct_u232_shutdown (struct usb_serial *serial)
399 struct mct_u232_private *priv;
402 dbg("%s", __FUNCTION__);
404 for (i=0; i < serial->num_ports; ++i) {
405 /* My special items, the standard routines free my urbs */
406 priv = usb_get_serial_port_data(serial->port[i]);
410 } /* mct_u232_shutdown */
412 static int mct_u232_open (struct usb_serial_port *port, struct file *filp)
414 struct usb_serial *serial = port->serial;
415 struct mct_u232_private *priv = usb_get_serial_port_data(port);
417 unsigned int control_state;
419 unsigned char last_lcr;
420 unsigned char last_msr;
422 dbg("%s port %d", __FUNCTION__, port->number);
424 /* Compensate for a hardware bug: although the Sitecom U232-P25
425 * device reports a maximum output packet size of 32 bytes,
426 * it seems to be able to accept only 16 bytes (and that's what
427 * SniffUSB says too...)
429 if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID)
430 port->bulk_out_size = 16;
432 /* Do a defined restart: the normal serial device seems to
433 * always turn on DTR and RTS here, so do the same. I'm not
434 * sure if this is really necessary. But it should not harm
437 spin_lock_irqsave(&priv->lock, flags);
438 if (port->tty->termios->c_cflag & CBAUD)
439 priv->control_state = TIOCM_DTR | TIOCM_RTS;
441 priv->control_state = 0;
443 priv->last_lcr = (MCT_U232_DATA_BITS_8 |
444 MCT_U232_PARITY_NONE |
445 MCT_U232_STOP_BITS_1);
446 control_state = priv->control_state;
447 last_lcr = priv->last_lcr;
448 spin_unlock_irqrestore(&priv->lock, flags);
449 mct_u232_set_modem_ctrl(serial, control_state);
450 mct_u232_set_line_ctrl(serial, last_lcr);
452 /* Read modem status and update control state */
453 mct_u232_get_modem_stat(serial, &last_msr);
454 spin_lock_irqsave(&priv->lock, flags);
455 priv->last_msr = last_msr;
456 mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
457 spin_unlock_irqrestore(&priv->lock, flags);
459 port->read_urb->dev = port->serial->dev;
460 retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
462 err("usb_submit_urb(read bulk) failed");
466 port->interrupt_in_urb->dev = port->serial->dev;
467 retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
469 err(" usb_submit_urb(read int) failed");
473 } /* mct_u232_open */
476 static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
478 dbg("%s port %d", __FUNCTION__, port->number);
480 if (port->serial->dev) {
481 /* shutdown our urbs */
482 usb_kill_urb(port->write_urb);
483 usb_kill_urb(port->read_urb);
484 usb_kill_urb(port->interrupt_in_urb);
486 } /* mct_u232_close */
489 #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
490 /* The generic routines work fine otherwise */
492 static int mct_u232_write (struct usb_serial_port *port,
493 const unsigned char *buf, int count)
495 struct usb_serial *serial = port->serial;
496 int result, bytes_sent, size;
498 dbg("%s - port %d", __FUNCTION__, port->number);
501 dbg("%s - write request of 0 bytes", __FUNCTION__);
505 /* only do something if we have a bulk out endpoint */
506 if (!serial->num_bulk_out)
509 /* another write is still pending? */
510 if (port->write_urb->status == -EINPROGRESS) {
511 dbg("%s - already writing", __FUNCTION__);
517 size = (count > port->bulk_out_size) ? port->bulk_out_size : count;
519 usb_serial_debug_data(debug, &port->dev, __FUNCTION__, size, buf);
521 memcpy (port->write_urb->transfer_buffer, buf, size);
524 usb_fill_bulk_urb(port->write_urb, serial->dev,
525 usb_sndbulkpipe(serial->dev,
526 port->bulk_out_endpointAddress),
527 port->write_urb->transfer_buffer, size,
528 ((serial->type->write_bulk_callback) ?
529 serial->type->write_bulk_callback :
530 mct_u232_write_bulk_callback),
533 /* send the data out the bulk port */
534 result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
536 err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
542 interruptible_sleep_on(&port->write_wait);
551 } /* mct_u232_write */
553 static void mct_u232_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
555 struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
556 struct usb_serial *serial = port->serial;
557 struct tty_struct *tty = port->tty;
559 dbg("%s - port %d", __FUNCTION__, port->number);
562 dbg("%s - bad serial pointer, exiting", __FUNCTION__);
567 dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,
572 if (write_blocking) {
573 wake_up_interruptible(&port->write_wait);
576 /* from generic_write_bulk_callback */
577 schedule_work(&port->work);
581 } /* mct_u232_write_bulk_callback */
584 static void mct_u232_read_int_callback (struct urb *urb, struct pt_regs *regs)
586 struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
587 struct mct_u232_private *priv = usb_get_serial_port_data(port);
588 struct usb_serial *serial = port->serial;
589 struct tty_struct *tty;
590 unsigned char *data = urb->transfer_buffer;
594 dbg("%s - port %d", __FUNCTION__, port->number);
596 switch (urb->status) {
603 /* this urb is terminated, clean up */
604 dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
607 dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
612 dbg("%s - bad serial pointer, exiting", __FUNCTION__);
616 usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
619 * Work-a-round: handle the 'usual' bulk-in pipe here
621 if (urb->transfer_buffer_length > 2) {
624 if (urb->actual_length) {
625 for (i = 0; i < urb->actual_length ; ++i) {
626 tty_insert_flip_char(tty, data[i], 0);
628 tty_flip_buffer_push(tty);
634 * The interrupt-in pipe signals exceptional conditions (modem line
635 * signal changes and errors). data[0] holds MSR, data[1] holds LSR.
637 spin_lock_irqsave(&priv->lock, flags);
638 priv->last_msr = data[MCT_U232_MSR_INDEX];
640 /* Record Control Line states */
641 mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
644 /* Not yet handled. See belin_sa.c for further information */
645 /* Now to report any errors */
646 priv->last_lsr = data[MCT_U232_LSR_INDEX];
648 * fill in the flip buffer here, but I do not know the relation
649 * to the current/next receive buffer or characters. I need
650 * to look in to this before committing any code.
652 if (priv->last_lsr & MCT_U232_LSR_ERR) {
655 if (priv->last_lsr & MCT_U232_LSR_OE) {
658 if (priv->last_lsr & MCT_U232_LSR_PE) {
661 if (priv->last_lsr & MCT_U232_LSR_FE) {
663 /* Break Indicator */
664 if (priv->last_lsr & MCT_U232_LSR_BI) {
668 spin_unlock_irqrestore(&priv->lock, flags);
670 status = usb_submit_urb (urb, GFP_ATOMIC);
672 err ("%s - usb_submit_urb failed with result %d",
673 __FUNCTION__, status);
674 } /* mct_u232_read_int_callback */
676 static void mct_u232_set_termios (struct usb_serial_port *port,
677 struct termios *old_termios)
679 struct usb_serial *serial = port->serial;
680 struct mct_u232_private *priv = usb_get_serial_port_data(port);
681 unsigned int iflag = port->tty->termios->c_iflag;
682 unsigned int cflag = port->tty->termios->c_cflag;
683 unsigned int old_cflag = old_termios->c_cflag;
685 unsigned int control_state, new_state;
686 unsigned char last_lcr;
688 /* get a local copy of the current port settings */
689 spin_lock_irqsave(&priv->lock, flags);
690 control_state = priv->control_state;
691 spin_unlock_irqrestore(&priv->lock, flags);
696 * Do not attempt to cache old rates and skip settings,
697 * disconnects screw such tricks up completely.
698 * Premature optimization is the root of all evil.
701 /* reassert DTR and (maybe) RTS on transition from B0 */
702 if ((old_cflag & CBAUD) == B0) {
703 dbg("%s: baud was B0", __FUNCTION__);
704 control_state |= TIOCM_DTR;
705 /* don't set RTS if using hardware flow control */
706 if (!(old_cflag & CRTSCTS)) {
707 control_state |= TIOCM_RTS;
709 mct_u232_set_modem_ctrl(serial, control_state);
712 mct_u232_set_baud_rate(serial, cflag & CBAUD);
714 if ((cflag & CBAUD) == B0 ) {
715 dbg("%s: baud is B0", __FUNCTION__);
716 /* Drop RTS and DTR */
717 control_state &= ~(TIOCM_DTR | TIOCM_RTS);
718 mct_u232_set_modem_ctrl(serial, control_state);
722 * Update line control register (LCR)
727 last_lcr |= (cflag & PARODD) ?
728 MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN;
730 last_lcr |= MCT_U232_PARITY_NONE;
732 /* set the number of data bits */
733 switch (cflag & CSIZE) {
735 last_lcr |= MCT_U232_DATA_BITS_5; break;
737 last_lcr |= MCT_U232_DATA_BITS_6; break;
739 last_lcr |= MCT_U232_DATA_BITS_7; break;
741 last_lcr |= MCT_U232_DATA_BITS_8; break;
743 err("CSIZE was not CS5-CS8, using default of 8");
744 last_lcr |= MCT_U232_DATA_BITS_8;
748 /* set the number of stop bits */
749 last_lcr |= (cflag & CSTOPB) ?
750 MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
752 mct_u232_set_line_ctrl(serial, last_lcr);
755 * Set flow control: well, I do not really now how to handle DTR/RTS.
756 * Just do what we have seen with SniffUSB on Win98.
758 /* Drop DTR/RTS if no flow control otherwise assert */
759 new_state = control_state;
760 if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS))
761 new_state |= TIOCM_DTR | TIOCM_RTS;
763 new_state &= ~(TIOCM_DTR | TIOCM_RTS);
764 if (new_state != control_state) {
765 mct_u232_set_modem_ctrl(serial, control_state);
766 control_state = new_state;
769 /* save off the modified port settings */
770 spin_lock_irqsave(&priv->lock, flags);
771 priv->control_state = control_state;
772 priv->last_lcr = last_lcr;
773 spin_unlock_irqrestore(&priv->lock, flags);
774 } /* mct_u232_set_termios */
776 static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
778 struct usb_serial *serial = port->serial;
779 struct mct_u232_private *priv = usb_get_serial_port_data(port);
783 dbg("%sstate=%d", __FUNCTION__, break_state);
785 spin_lock_irqsave(&priv->lock, flags);
786 lcr = priv->last_lcr;
787 spin_unlock_irqrestore(&priv->lock, flags);
790 lcr |= MCT_U232_SET_BREAK;
792 mct_u232_set_line_ctrl(serial, lcr);
793 } /* mct_u232_break_ctl */
796 static int mct_u232_tiocmget (struct usb_serial_port *port, struct file *file)
798 struct mct_u232_private *priv = usb_get_serial_port_data(port);
799 unsigned int control_state;
802 dbg("%s", __FUNCTION__);
804 spin_lock_irqsave(&priv->lock, flags);
805 control_state = priv->control_state;
806 spin_unlock_irqrestore(&priv->lock, flags);
808 return control_state;
811 static int mct_u232_tiocmset (struct usb_serial_port *port, struct file *file,
812 unsigned int set, unsigned int clear)
814 struct usb_serial *serial = port->serial;
815 struct mct_u232_private *priv = usb_get_serial_port_data(port);
816 unsigned int control_state;
819 dbg("%s", __FUNCTION__);
821 spin_lock_irqsave(&priv->lock, flags);
822 control_state = priv->control_state;
825 control_state |= TIOCM_RTS;
827 control_state |= TIOCM_DTR;
828 if (clear & TIOCM_RTS)
829 control_state &= ~TIOCM_RTS;
830 if (clear & TIOCM_DTR)
831 control_state &= ~TIOCM_DTR;
833 priv->control_state = control_state;
834 spin_unlock_irqrestore(&priv->lock, flags);
835 return mct_u232_set_modem_ctrl(serial, control_state);
838 static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
839 unsigned int cmd, unsigned long arg)
841 dbg("%scmd=0x%x", __FUNCTION__, cmd);
843 /* Based on code from acm.c and others */
846 /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
851 /* return count of modemline transitions */
856 dbg("%s: arg not supported - 0x%04x", __FUNCTION__,cmd);
857 return(-ENOIOCTLCMD);
861 } /* mct_u232_ioctl */
864 static int __init mct_u232_init (void)
867 retval = usb_serial_register(&mct_u232_device);
869 goto failed_usb_serial_register;
870 retval = usb_register(&mct_u232_driver);
872 goto failed_usb_register;
873 info(DRIVER_DESC " " DRIVER_VERSION);
876 usb_serial_deregister(&mct_u232_device);
877 failed_usb_serial_register:
882 static void __exit mct_u232_exit (void)
884 usb_deregister (&mct_u232_driver);
885 usb_serial_deregister (&mct_u232_device);
889 module_init (mct_u232_init);
890 module_exit(mct_u232_exit);
892 MODULE_AUTHOR( DRIVER_AUTHOR );
893 MODULE_DESCRIPTION( DRIVER_DESC );
894 MODULE_LICENSE("GPL");
896 #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
897 module_param(write_blocking, int, 0);
898 MODULE_PARM_DESC(write_blocking,
899 "The write function will block to write out all data");
902 module_param(debug, bool, S_IRUGO | S_IWUSR);
903 MODULE_PARM_DESC(debug, "Debug enabled or not");