Merge git://www.linux-watchdog.org/linux-watchdog
[linux/fpc-iii.git] / drivers / usb / serial / mct_u232.c
blob6a15adf53360f75994d9e7f3c62d2ac1ff04a461
1 /*
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 #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"
40 #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
41 #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
44 * Function prototypes
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);
63 * All of the device info needed for the MCT USB-RS232 converter.
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 */
72 MODULE_DEVICE_TABLE(usb, id_table);
74 static struct usb_serial_driver mct_u232_device = {
75 .driver = {
76 .owner = THIS_MODULE,
77 .name = "mct_u232",
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,
98 static struct usb_serial_driver * const serial_drivers[] = {
99 &mct_u232_device, NULL
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 */
112 #define THROTTLED 0x01
115 * Handle vendor specific USB requests
118 #define WDR_TIMEOUT 5000 /* default urb timeout */
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.
124 static int mct_u232_calculate_baud_rate(struct usb_serial *serial,
125 speed_t value, speed_t *result)
127 *result = value;
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;
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;
175 return 115200/value;
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)
182 unsigned int divisor;
183 int rc;
184 unsigned char *buf;
185 unsigned char cts_enable_byte = 0;
186 speed_t speed;
188 buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL);
189 if (buf == NULL)
190 return -ENOMEM;
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);
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.
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'.
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);
234 if (port && C_CRTSCTS(tty))
235 cts_enable_byte = 1;
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);
249 kfree(buf);
250 return rc;
251 } /* mct_u232_set_baud_rate */
253 static int mct_u232_set_line_ctrl(struct usb_serial_port *port,
254 unsigned char lcr)
256 int rc;
257 unsigned char *buf;
259 buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL);
260 if (buf == NULL)
261 return -ENOMEM;
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 */
276 static int mct_u232_set_modem_ctrl(struct usb_serial_port *port,
277 unsigned int control_state)
279 int rc;
280 unsigned char mcr;
281 unsigned char *buf;
283 buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL);
284 if (buf == NULL)
285 return -ENOMEM;
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;
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);
301 dev_dbg(&port->dev, "set_modem_ctrl: state=0x%x ==> mcr=0x%x\n", control_state, mcr);
303 if (rc < 0) {
304 dev_err(&port->dev, "Set MODEM CTRL 0x%x failed (error = %d)\n", mcr, rc);
305 return rc;
307 return 0;
308 } /* mct_u232_set_modem_ctrl */
310 static int mct_u232_get_modem_stat(struct usb_serial_port *port,
311 unsigned char *msr)
313 int rc;
314 unsigned char *buf;
316 buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL);
317 if (buf == NULL) {
318 *msr = 0;
319 return -ENOMEM;
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];
332 dev_dbg(&port->dev, "get_modem_stat: 0x%x\n", *msr);
333 kfree(buf);
334 return rc;
335 } /* mct_u232_get_modem_stat */
337 static void mct_u232_msr_to_icount(struct async_icount *icount,
338 unsigned char msr)
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 */
351 static void mct_u232_msr_to_state(struct usb_serial_port *port,
352 unsigned int *control_state, unsigned char msr)
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 */
375 * Driver's tty interface functions
378 static int mct_u232_port_probe(struct usb_serial_port *port)
380 struct mct_u232_private *priv;
382 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
383 if (!priv)
384 return -ENOMEM;
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;
390 spin_lock_init(&priv->lock);
392 usb_set_serial_port_data(port, priv);
394 return 0;
397 static int mct_u232_port_remove(struct usb_serial_port *port)
399 struct mct_u232_private *priv;
401 priv = usb_get_serial_port_data(port);
402 kfree(priv);
404 return 0;
407 static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)
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;
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...)
422 if (le16_to_cpu(serial->dev->descriptor.idProduct)
423 == MCT_U232_SITECOM_PID)
424 port->bulk_out_size = 16;
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.
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;
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);
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);
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;
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;
469 return 0;
471 error:
472 return retval;
473 } /* mct_u232_open */
475 static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)
477 unsigned int control_state;
478 struct mct_u232_private *priv = usb_get_serial_port_data(port);
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);
488 mct_u232_set_modem_ctrl(port, control_state);
491 static void mct_u232_close(struct usb_serial_port *port)
493 struct mct_u232_private *priv = usb_get_serial_port_data(port);
495 usb_kill_urb(priv->read_urb);
496 usb_kill_urb(port->interrupt_in_urb);
498 usb_serial_generic_close(port);
499 } /* mct_u232_close */
502 static void mct_u232_read_int_callback(struct urb *urb)
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;
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;
528 usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
531 * Work-a-round: handle the 'usual' bulk-in pipe here
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);
539 goto exit;
543 * The interrupt-in pipe signals exceptional conditions (modem line
544 * signal changes and errors). data[0] holds MSR, data[1] holds LSR.
546 spin_lock_irqsave(&priv->lock, flags);
547 priv->last_msr = data[MCT_U232_MSR_INDEX];
549 /* Record Control Line states */
550 mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr);
552 mct_u232_msr_to_icount(&port->icount, priv->last_msr);
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];
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.
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) {
568 /* Parity Error */
569 if (priv->last_lsr & MCT_U232_LSR_PE) {
571 /* Framing Error */
572 if (priv->last_lsr & MCT_U232_LSR_FE) {
574 /* Break Indicator */
575 if (priv->last_lsr & MCT_U232_LSR_BI) {
577 tty_kref_put(tty);
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 */
590 static void mct_u232_set_termios(struct tty_struct *tty,
591 struct usb_serial_port *port,
592 struct ktermios *old_termios)
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;
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;
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.
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);
623 mct_u232_set_baud_rate(tty, serial, port, tty_get_baud_rate(tty));
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);
633 * Update line control register (LCR)
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;
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;
660 termios->c_cflag &= ~CMSPAR;
662 /* set the number of stop bits */
663 last_lcr |= (cflag & CSTOPB) ?
664 MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
666 mct_u232_set_line_ctrl(port, last_lcr);
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 */
675 static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
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;
682 spin_lock_irqsave(&priv->lock, flags);
683 lcr = priv->last_lcr;
685 if (break_state)
686 lcr |= MCT_U232_SET_BREAK;
687 spin_unlock_irqrestore(&priv->lock, flags);
689 mct_u232_set_line_ctrl(port, lcr);
690 } /* mct_u232_break_ctl */
693 static int mct_u232_tiocmget(struct tty_struct *tty)
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;
700 spin_lock_irqsave(&priv->lock, flags);
701 control_state = priv->control_state;
702 spin_unlock_irqrestore(&priv->lock, flags);
704 return control_state;
707 static int mct_u232_tiocmset(struct tty_struct *tty,
708 unsigned int set, unsigned int clear)
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;
715 spin_lock_irqsave(&priv->lock, flags);
716 control_state = priv->control_state;
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;
727 priv->control_state = control_state;
728 spin_unlock_irqrestore(&priv->lock, flags);
729 return mct_u232_set_modem_ctrl(port, control_state);
732 static void mct_u232_throttle(struct tty_struct *tty)
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;
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);
750 static void mct_u232_unthrottle(struct tty_struct *tty)
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;
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);
768 module_usb_serial_driver(serial_drivers, id_table);
770 MODULE_AUTHOR(DRIVER_AUTHOR);
771 MODULE_DESCRIPTION(DRIVER_DESC);
772 MODULE_LICENSE("GPL");