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