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>
80 #ifdef CONFIG_USB_SERIAL_DEBUG
86 #include "usb-serial.h"
93 #define DRIVER_VERSION "v1.2"
94 #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
95 #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
98 * Some not properly written applications do not handle the return code of
99 * write() correctly. This can result in character losses. A work-a-round
100 * can be compiled in with the following definition. This work-a-round
101 * should _NOT_ be part of an 'official' kernel release, of course!
103 #undef FIX_WRITE_RETURN_CODE_PROBLEM
104 #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
105 static int write_blocking; /* disabled by default */
109 * Function prototypes
111 static int mct_u232_startup (struct usb_serial *serial);
112 static void mct_u232_shutdown (struct usb_serial *serial);
113 static int mct_u232_open (struct usb_serial_port *port,
115 static void mct_u232_close (struct usb_serial_port *port,
117 #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
118 static int mct_u232_write (struct usb_serial_port *port,
120 const unsigned char *buf,
122 static void mct_u232_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
124 static void mct_u232_read_int_callback (struct urb *urb, struct pt_regs *regs);
125 static void mct_u232_set_termios (struct usb_serial_port *port,
126 struct termios * old);
127 static int mct_u232_ioctl (struct usb_serial_port *port,
131 static void mct_u232_break_ctl (struct usb_serial_port *port,
133 static int mct_u232_tiocmget (struct usb_serial_port *port,
135 static int mct_u232_tiocmset (struct usb_serial_port *port,
136 struct file *file, unsigned int set,
139 * All of the device info needed for the MCT USB-RS232 converter.
141 static struct usb_device_id id_table_combined [] = {
142 { USB_DEVICE(MCT_U232_VID, MCT_U232_PID) },
143 { USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) },
144 { USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) },
145 { USB_DEVICE(MCT_U232_BELKIN_F5U109_VID, MCT_U232_BELKIN_F5U109_PID) },
146 { } /* Terminating entry */
149 MODULE_DEVICE_TABLE (usb, id_table_combined);
151 static struct usb_driver mct_u232_driver = {
152 .owner = THIS_MODULE,
154 .probe = usb_serial_probe,
155 .disconnect = usb_serial_disconnect,
156 .id_table = id_table_combined,
159 static struct usb_serial_device_type mct_u232_device = {
160 .owner = THIS_MODULE,
161 .name = "Magic Control Technology USB-RS232",
162 .short_name = "mct_u232",
163 .id_table = id_table_combined,
164 .num_interrupt_in = 2,
168 .open = mct_u232_open,
169 .close = mct_u232_close,
170 #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
171 .write = mct_u232_write,
172 .write_bulk_callback = mct_u232_write_bulk_callback,
174 .read_int_callback = mct_u232_read_int_callback,
175 .ioctl = mct_u232_ioctl,
176 .set_termios = mct_u232_set_termios,
177 .break_ctl = mct_u232_break_ctl,
178 .tiocmget = mct_u232_tiocmget,
179 .tiocmset = mct_u232_tiocmset,
180 .attach = mct_u232_startup,
181 .shutdown = mct_u232_shutdown,
185 struct mct_u232_private {
187 unsigned int control_state; /* Modem Line Setting (TIOCM) */
188 unsigned char last_lcr; /* Line Control Register */
189 unsigned char last_lsr; /* Line Status Register */
190 unsigned char last_msr; /* Modem Status Register */
194 * Handle vendor specific USB requests
197 #define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
200 * Later day 2.6.0-test kernels have new baud rates like B230400 which
201 * we do not know how to support. We ignore them for the moment.
202 * XXX Rate-limit the error message, it's user triggerable.
204 static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value) {
205 if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID
206 || serial->dev->descriptor.idProduct == MCT_U232_BELKIN_F5U109_PID) {
208 case B300: return 0x01;
209 case B600: return 0x02; /* this one not tested */
210 case B1200: return 0x03;
211 case B2400: return 0x04;
212 case B4800: return 0x06;
213 case B9600: return 0x08;
214 case B19200: return 0x09;
215 case B38400: return 0x0a;
216 case B57600: return 0x0b;
217 case B115200: return 0x0c;
219 err("MCT USB-RS232: unsupported baudrate request 0x%x,"
220 " using default of B9600", value);
225 case B300: value = 300;
226 case B600: value = 600;
227 case B1200: value = 1200;
228 case B2400: value = 2400;
229 case B4800: value = 4800;
230 case B9600: value = 9600;
231 case B19200: value = 19200;
232 case B38400: value = 38400;
233 case B57600: value = 57600;
234 case B115200: value = 115200;
236 err("MCT USB-RS232: unsupported baudrate request 0x%x,"
237 " using default of B9600", value);
244 static int mct_u232_set_baud_rate(struct usb_serial *serial, int value)
246 unsigned int divisor;
248 unsigned char zero_byte = 0;
250 divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value));
252 rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
253 MCT_U232_SET_BAUD_RATE_REQUEST,
254 MCT_U232_SET_REQUEST_TYPE,
255 0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE,
258 err("Set BAUD RATE %d failed (error = %d)", value, rc);
259 dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor);
261 /* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which
262 always sends two extra USB 'device request' messages after the
263 'baud rate change' message. The actual functionality of the
264 request codes in these messages is not fully understood but these
265 particular codes are never seen in any operation besides a baud
266 rate change. Both of these messages send a single byte of data
267 whose value is always zero. The second of these two extra messages
268 is required in order for data to be properly written to an RS-232
269 device which does not assert the 'CTS' signal. */
271 rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
272 MCT_U232_SET_UNKNOWN1_REQUEST,
273 MCT_U232_SET_REQUEST_TYPE,
274 0, 0, &zero_byte, MCT_U232_SET_UNKNOWN1_SIZE,
277 err("Sending USB device request code %d failed (error = %d)",
278 MCT_U232_SET_UNKNOWN1_REQUEST, rc);
280 rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
281 MCT_U232_SET_UNKNOWN2_REQUEST,
282 MCT_U232_SET_REQUEST_TYPE,
283 0, 0, &zero_byte, MCT_U232_SET_UNKNOWN2_SIZE,
286 err("Sending USB device request code %d failed (error = %d)",
287 MCT_U232_SET_UNKNOWN2_REQUEST, rc);
290 } /* mct_u232_set_baud_rate */
292 static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr)
295 rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
296 MCT_U232_SET_LINE_CTRL_REQUEST,
297 MCT_U232_SET_REQUEST_TYPE,
298 0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE,
301 err("Set LINE CTRL 0x%x failed (error = %d)", lcr, rc);
302 dbg("set_line_ctrl: 0x%x", lcr);
304 } /* mct_u232_set_line_ctrl */
306 static int mct_u232_set_modem_ctrl(struct usb_serial *serial,
307 unsigned int control_state)
310 unsigned char mcr = MCT_U232_MCR_NONE;
312 if (control_state & TIOCM_DTR)
313 mcr |= MCT_U232_MCR_DTR;
314 if (control_state & TIOCM_RTS)
315 mcr |= MCT_U232_MCR_RTS;
317 rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
318 MCT_U232_SET_MODEM_CTRL_REQUEST,
319 MCT_U232_SET_REQUEST_TYPE,
320 0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE,
323 err("Set MODEM CTRL 0x%x failed (error = %d)", mcr, rc);
324 dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr);
327 } /* mct_u232_set_modem_ctrl */
329 static int mct_u232_get_modem_stat(struct usb_serial *serial, unsigned char *msr)
332 rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
333 MCT_U232_GET_MODEM_STAT_REQUEST,
334 MCT_U232_GET_REQUEST_TYPE,
335 0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE,
338 err("Get MODEM STATus failed (error = %d)", rc);
341 dbg("get_modem_stat: 0x%x", *msr);
343 } /* mct_u232_get_modem_stat */
345 static void mct_u232_msr_to_state(unsigned int *control_state, unsigned char msr)
347 /* Translate Control Line states */
348 if (msr & MCT_U232_MSR_DSR)
349 *control_state |= TIOCM_DSR;
351 *control_state &= ~TIOCM_DSR;
352 if (msr & MCT_U232_MSR_CTS)
353 *control_state |= TIOCM_CTS;
355 *control_state &= ~TIOCM_CTS;
356 if (msr & MCT_U232_MSR_RI)
357 *control_state |= TIOCM_RI;
359 *control_state &= ~TIOCM_RI;
360 if (msr & MCT_U232_MSR_CD)
361 *control_state |= TIOCM_CD;
363 *control_state &= ~TIOCM_CD;
364 dbg("msr_to_state: msr=0x%x ==> state=0x%x", msr, *control_state);
365 } /* mct_u232_msr_to_state */
368 * Driver's tty interface functions
371 static int mct_u232_startup (struct usb_serial *serial)
373 struct mct_u232_private *priv;
374 struct usb_serial_port *port, *rport;
376 /* allocate the private data structure */
377 priv = kmalloc(sizeof(struct mct_u232_private), GFP_KERNEL);
380 /* set initial values for control structures */
381 spin_lock_init(&priv->lock);
382 priv->control_state = 0;
385 usb_set_serial_port_data(serial->port[0], priv);
387 init_waitqueue_head(&serial->port[0]->write_wait);
389 /* Puh, that's dirty */
390 port = serial->port[0];
391 rport = serial->port[1];
392 if (port->read_urb) {
393 /* No unlinking, it wasn't submitted yet. */
394 usb_free_urb(port->read_urb);
396 port->read_urb = rport->interrupt_in_urb;
397 rport->interrupt_in_urb = NULL;
398 port->read_urb->context = port;
401 } /* mct_u232_startup */
404 static void mct_u232_shutdown (struct usb_serial *serial)
406 struct mct_u232_private *priv;
409 dbg("%s", __FUNCTION__);
411 for (i=0; i < serial->num_ports; ++i) {
412 /* My special items, the standard routines free my urbs */
413 priv = usb_get_serial_port_data(serial->port[i]);
417 } /* mct_u232_shutdown */
419 static int mct_u232_open (struct usb_serial_port *port, struct file *filp)
421 struct usb_serial *serial = port->serial;
422 struct mct_u232_private *priv = usb_get_serial_port_data(port);
424 unsigned int control_state;
426 unsigned char last_lcr;
427 unsigned char last_msr;
429 dbg("%s port %d", __FUNCTION__, port->number);
431 /* Compensate for a hardware bug: although the Sitecom U232-P25
432 * device reports a maximum output packet size of 32 bytes,
433 * it seems to be able to accept only 16 bytes (and that's what
434 * SniffUSB says too...)
436 if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID)
437 port->bulk_out_size = 16;
439 /* Do a defined restart: the normal serial device seems to
440 * always turn on DTR and RTS here, so do the same. I'm not
441 * sure if this is really necessary. But it should not harm
444 spin_lock_irqsave(&priv->lock, flags);
445 if (port->tty->termios->c_cflag & CBAUD)
446 priv->control_state = TIOCM_DTR | TIOCM_RTS;
448 priv->control_state = 0;
450 priv->last_lcr = (MCT_U232_DATA_BITS_8 |
451 MCT_U232_PARITY_NONE |
452 MCT_U232_STOP_BITS_1);
453 control_state = priv->control_state;
454 last_lcr = priv->last_lcr;
455 spin_unlock_irqrestore(&priv->lock, flags);
456 mct_u232_set_modem_ctrl(serial, control_state);
457 mct_u232_set_line_ctrl(serial, last_lcr);
459 /* Read modem status and update control state */
460 mct_u232_get_modem_stat(serial, &last_msr);
461 spin_lock_irqsave(&priv->lock, flags);
462 priv->last_msr = last_msr;
463 mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
464 spin_unlock_irqrestore(&priv->lock, flags);
466 port->read_urb->dev = port->serial->dev;
467 retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
469 err("usb_submit_urb(read bulk) failed");
473 port->interrupt_in_urb->dev = port->serial->dev;
474 retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
476 err(" usb_submit_urb(read int) failed");
480 } /* mct_u232_open */
483 static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
485 dbg("%s port %d", __FUNCTION__, port->number);
487 if (port->serial->dev) {
488 /* shutdown our urbs */
489 usb_unlink_urb (port->write_urb);
490 usb_unlink_urb (port->read_urb);
491 usb_unlink_urb (port->interrupt_in_urb);
493 } /* mct_u232_close */
496 #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
497 /* The generic routines work fine otherwise */
499 static int mct_u232_write (struct usb_serial_port *port, int from_user,
500 const unsigned char *buf, int count)
502 struct usb_serial *serial = port->serial;
503 int result, bytes_sent, size;
505 dbg("%s - port %d", __FUNCTION__, port->number);
508 dbg("%s - write request of 0 bytes", __FUNCTION__);
512 /* only do something if we have a bulk out endpoint */
513 if (!serial->num_bulk_out)
516 /* another write is still pending? */
517 if (port->write_urb->status == -EINPROGRESS) {
518 dbg("%s - already writing", __FUNCTION__);
524 size = (count > port->bulk_out_size) ? port->bulk_out_size : count;
526 usb_serial_debug_data (__FILE__, __FUNCTION__, size, buf);
529 if (copy_from_user(port->write_urb->transfer_buffer, buf, size)) {
534 memcpy (port->write_urb->transfer_buffer, buf, size);
538 usb_fill_bulk_urb(port->write_urb, serial->dev,
539 usb_sndbulkpipe(serial->dev,
540 port->bulk_out_endpointAddress),
541 port->write_urb->transfer_buffer, size,
542 ((serial->type->write_bulk_callback) ?
543 serial->type->write_bulk_callback :
544 mct_u232_write_bulk_callback),
547 /* send the data out the bulk port */
548 result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
550 err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
556 interruptible_sleep_on(&port->write_wait);
565 } /* mct_u232_write */
567 static void mct_u232_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
569 struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
570 struct usb_serial *serial = port->serial;
571 struct tty_struct *tty = port->tty;
573 dbg("%s - port %d", __FUNCTION__, port->number);
576 dbg("%s - bad serial pointer, exiting", __FUNCTION__);
581 dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,
586 if (write_blocking) {
587 wake_up_interruptible(&port->write_wait);
588 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
589 tty->ldisc.write_wakeup)
590 (tty->ldisc.write_wakeup)(tty);
591 wake_up_interruptible(&tty->write_wait);
594 /* from generic_write_bulk_callback */
595 schedule_work(&port->work);
599 } /* mct_u232_write_bulk_callback */
602 static void mct_u232_read_int_callback (struct urb *urb, struct pt_regs *regs)
604 struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
605 struct mct_u232_private *priv = usb_get_serial_port_data(port);
606 struct usb_serial *serial = port->serial;
607 struct tty_struct *tty;
608 unsigned char *data = urb->transfer_buffer;
612 dbg("%s - port %d", __FUNCTION__, port->number);
614 switch (urb->status) {
621 /* this urb is terminated, clean up */
622 dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
625 dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
630 dbg("%s - bad serial pointer, exiting", __FUNCTION__);
634 usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
637 * Work-a-round: handle the 'usual' bulk-in pipe here
639 if (urb->transfer_buffer_length > 2) {
642 if (urb->actual_length) {
643 for (i = 0; i < urb->actual_length ; ++i) {
644 tty_insert_flip_char(tty, data[i], 0);
646 tty_flip_buffer_push(tty);
652 * The interrupt-in pipe signals exceptional conditions (modem line
653 * signal changes and errors). data[0] holds MSR, data[1] holds LSR.
655 spin_lock_irqsave(&priv->lock, flags);
656 priv->last_msr = data[MCT_U232_MSR_INDEX];
658 /* Record Control Line states */
659 mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
662 /* Not yet handled. See belin_sa.c for further information */
663 /* Now to report any errors */
664 priv->last_lsr = data[MCT_U232_LSR_INDEX];
666 * fill in the flip buffer here, but I do not know the relation
667 * to the current/next receive buffer or characters. I need
668 * to look in to this before committing any code.
670 if (priv->last_lsr & MCT_U232_LSR_ERR) {
673 if (priv->last_lsr & MCT_U232_LSR_OE) {
676 if (priv->last_lsr & MCT_U232_LSR_PE) {
679 if (priv->last_lsr & MCT_U232_LSR_FE) {
681 /* Break Indicator */
682 if (priv->last_lsr & MCT_U232_LSR_BI) {
686 spin_unlock_irqrestore(&priv->lock, flags);
688 status = usb_submit_urb (urb, GFP_ATOMIC);
690 err ("%s - usb_submit_urb failed with result %d",
691 __FUNCTION__, status);
692 } /* mct_u232_read_int_callback */
694 static void mct_u232_set_termios (struct usb_serial_port *port,
695 struct termios *old_termios)
697 struct usb_serial *serial = port->serial;
698 struct mct_u232_private *priv = usb_get_serial_port_data(port);
699 unsigned int iflag = port->tty->termios->c_iflag;
700 unsigned int cflag = port->tty->termios->c_cflag;
701 unsigned int old_cflag = old_termios->c_cflag;
703 unsigned int control_state, new_state;
704 unsigned char last_lcr;
706 /* get a local copy of the current port settings */
707 spin_lock_irqsave(&priv->lock, flags);
708 control_state = priv->control_state;
709 spin_unlock_irqrestore(&priv->lock, flags);
714 * Do not attempt to cache old rates and skip settings,
715 * disconnects screw such tricks up completely.
716 * Premature optimization is the root of all evil.
719 /* reassert DTR and (maybe) RTS on transition from B0 */
720 if ((old_cflag & CBAUD) == B0) {
721 dbg("%s: baud was B0", __FUNCTION__);
722 control_state |= TIOCM_DTR;
723 /* don't set RTS if using hardware flow control */
724 if (!(old_cflag & CRTSCTS)) {
725 control_state |= TIOCM_RTS;
727 mct_u232_set_modem_ctrl(serial, control_state);
730 mct_u232_set_baud_rate(serial, cflag & CBAUD);
732 if ((cflag & CBAUD) == B0 ) {
733 dbg("%s: baud is B0", __FUNCTION__);
734 /* Drop RTS and DTR */
735 control_state &= ~(TIOCM_DTR | TIOCM_RTS);
736 mct_u232_set_modem_ctrl(serial, control_state);
740 * Update line control register (LCR)
745 last_lcr |= (cflag & PARODD) ?
746 MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN;
748 last_lcr |= MCT_U232_PARITY_NONE;
750 /* set the number of data bits */
751 switch (cflag & CSIZE) {
753 last_lcr |= MCT_U232_DATA_BITS_5; break;
755 last_lcr |= MCT_U232_DATA_BITS_6; break;
757 last_lcr |= MCT_U232_DATA_BITS_7; break;
759 last_lcr |= MCT_U232_DATA_BITS_8; break;
761 err("CSIZE was not CS5-CS8, using default of 8");
762 last_lcr |= MCT_U232_DATA_BITS_8;
766 /* set the number of stop bits */
767 last_lcr |= (cflag & CSTOPB) ?
768 MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
770 mct_u232_set_line_ctrl(serial, last_lcr);
773 * Set flow control: well, I do not really now how to handle DTR/RTS.
774 * Just do what we have seen with SniffUSB on Win98.
776 /* Drop DTR/RTS if no flow control otherwise assert */
777 new_state = control_state;
778 if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS))
779 new_state |= TIOCM_DTR | TIOCM_RTS;
781 new_state &= ~(TIOCM_DTR | TIOCM_RTS);
782 if (new_state != control_state) {
783 mct_u232_set_modem_ctrl(serial, control_state);
784 control_state = new_state;
787 /* save off the modified port settings */
788 spin_lock_irqsave(&priv->lock, flags);
789 priv->control_state = control_state;
790 priv->last_lcr = last_lcr;
791 spin_unlock_irqrestore(&priv->lock, flags);
792 } /* mct_u232_set_termios */
794 static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
796 struct usb_serial *serial = port->serial;
797 struct mct_u232_private *priv = usb_get_serial_port_data(port);
801 dbg("%sstate=%d", __FUNCTION__, break_state);
803 spin_lock_irqsave(&priv->lock, flags);
804 lcr = priv->last_lcr;
805 spin_unlock_irqrestore(&priv->lock, flags);
808 lcr |= MCT_U232_SET_BREAK;
810 mct_u232_set_line_ctrl(serial, lcr);
811 } /* mct_u232_break_ctl */
814 static int mct_u232_tiocmget (struct usb_serial_port *port, struct file *file)
816 struct mct_u232_private *priv = usb_get_serial_port_data(port);
817 unsigned int control_state;
820 dbg("%s", __FUNCTION__);
822 spin_lock_irqsave(&priv->lock, flags);
823 control_state = priv->control_state;
824 spin_unlock_irqrestore(&priv->lock, flags);
826 return control_state;
829 static int mct_u232_tiocmset (struct usb_serial_port *port, struct file *file,
830 unsigned int set, unsigned int clear)
832 struct usb_serial *serial = port->serial;
833 struct mct_u232_private *priv = usb_get_serial_port_data(port);
834 unsigned int control_state;
837 dbg("%s", __FUNCTION__);
839 spin_lock_irqsave(&priv->lock, flags);
840 control_state = priv->control_state;
843 control_state |= TIOCM_RTS;
845 control_state |= TIOCM_DTR;
846 if (clear & TIOCM_RTS)
847 control_state &= ~TIOCM_RTS;
848 if (clear & TIOCM_DTR)
849 control_state &= ~TIOCM_DTR;
851 priv->control_state = control_state;
852 spin_unlock_irqrestore(&priv->lock, flags);
853 return mct_u232_set_modem_ctrl(serial, control_state);
856 static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
857 unsigned int cmd, unsigned long arg)
859 dbg("%scmd=0x%x", __FUNCTION__, cmd);
861 /* Based on code from acm.c and others */
864 /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
869 /* return count of modemline transitions */
874 dbg("%s: arg not supported - 0x%04x", __FUNCTION__,cmd);
875 return(-ENOIOCTLCMD);
879 } /* mct_u232_ioctl */
882 static int __init mct_u232_init (void)
885 retval = usb_serial_register(&mct_u232_device);
887 goto failed_usb_serial_register;
888 retval = usb_register(&mct_u232_driver);
890 goto failed_usb_register;
891 info(DRIVER_DESC " " DRIVER_VERSION);
894 usb_serial_deregister(&mct_u232_device);
895 failed_usb_serial_register:
900 static void __exit mct_u232_exit (void)
902 usb_deregister (&mct_u232_driver);
903 usb_serial_deregister (&mct_u232_device);
907 module_init (mct_u232_init);
908 module_exit(mct_u232_exit);
910 MODULE_AUTHOR( DRIVER_AUTHOR );
911 MODULE_DESCRIPTION( DRIVER_DESC );
912 MODULE_LICENSE("GPL");
914 #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
915 MODULE_PARM(write_blocking, "i");
916 MODULE_PARM_DESC(write_blocking,
917 "The write function will block to write out all data");
920 MODULE_PARM(debug, "i");
921 MODULE_PARM_DESC(debug, "Debug enabled or not");