special usb hub handling, IDE disks, and retries all over the place
[linux-2.4.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/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
80 #ifdef CONFIG_USB_SERIAL_DEBUG
81         static int debug = 1;
82 #else
83         static int debug;
84 #endif
85
86 #include "usb-serial.h"
87 #include "mct_u232.h"
88
89 /*
90  * Version Information
91  */
92 #define DRIVER_VERSION "z2.0"           /* Linux in-kernel version */
93 #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
94 #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
95
96 /*
97  * Function prototypes
98  */
99 static int  mct_u232_startup             (struct usb_serial *serial);
100 static void mct_u232_shutdown            (struct usb_serial *serial);
101 static int  mct_u232_open                (struct usb_serial_port *port,
102                                           struct file *filp);
103 static void mct_u232_close               (struct usb_serial_port *port,
104                                           struct file *filp);
105 static void mct_u232_read_int_callback   (struct urb *urb);
106 static void mct_u232_set_termios         (struct usb_serial_port *port,
107                                           struct termios * old);
108 static int  mct_u232_ioctl               (struct usb_serial_port *port,
109                                           struct file * file,
110                                           unsigned int cmd,
111                                           unsigned long arg);
112 static void mct_u232_break_ctl           (struct usb_serial_port *port,
113                                           int break_state );
114
115 /*
116  * All of the device info needed for the MCT USB-RS232 converter.
117  */
118 static struct usb_device_id id_table_combined [] = {
119         { USB_DEVICE(MCT_U232_VID, MCT_U232_PID) },
120         { USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) },
121         { USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) },
122         { USB_DEVICE(MCT_U232_BELKIN_F5U109_VID, MCT_U232_BELKIN_F5U109_PID) },
123         { }             /* Terminating entry */
124 };
125
126 MODULE_DEVICE_TABLE (usb, id_table_combined);
127
128
129 static struct usb_serial_device_type mct_u232_device = {
130         .owner =             THIS_MODULE,
131         .name =              "MCT U232",
132         .id_table =          id_table_combined,
133         .num_interrupt_in =  2,
134         .num_bulk_in =       0,
135         .num_bulk_out =      1,
136         .num_ports =         1,
137         .open =              mct_u232_open,
138         .close =             mct_u232_close,
139         .read_int_callback = mct_u232_read_int_callback,
140         .ioctl =             mct_u232_ioctl,
141         .set_termios =       mct_u232_set_termios,
142         .break_ctl =         mct_u232_break_ctl,
143         .startup =           mct_u232_startup,
144         .shutdown =          mct_u232_shutdown,
145 };
146
147 struct mct_u232_interval_kludge {
148         int ecnt;                       /* Error counter */
149         int ibase;                      /* Initial interval value */
150 };
151
152 struct mct_u232_private {
153         spinlock_t lock;
154         struct mct_u232_interval_kludge ik[2];
155         unsigned int         control_state; /* Modem Line Setting (TIOCM) */
156         unsigned char        last_lcr;      /* Line Control Register */
157         unsigned char        last_lsr;      /* Line Status Register */
158         unsigned char        last_msr;      /* Modem Status Register */
159 };
160
161 /*
162  * Handle vendor specific USB requests
163  */
164
165 #define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
166
167 /*
168  * Later day 2.6.0-test kernels have new baud rates like B230400 which
169  * we do not know how to support. We ignore them for the moment.
170  * XXX Rate-limit the error message, it's user triggerable.
171  */
172 static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value) {
173         if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID
174           || serial->dev->descriptor.idProduct == MCT_U232_BELKIN_F5U109_PID) {
175                 switch (value) {
176                 case    B300: return 0x01;
177                 case    B600: return 0x02; /* this one not tested */
178                 case   B1200: return 0x03;
179                 case   B2400: return 0x04;
180                 case   B4800: return 0x06;
181                 case   B9600: return 0x08;
182                 case  B19200: return 0x09;
183                 case  B38400: return 0x0a;
184                 case  B57600: return 0x0b;
185                 case B115200: return 0x0c;
186                 default:
187                         err("MCT USB-RS232: unsupported baudrate request 0x%x,"
188                             " using default of B9600", value);
189                         return 0x08;
190                 }
191         } else {
192                 switch (value) {
193                 case    B300: value =     300; break;
194                 case    B600: value =     600; break;
195                 case   B1200: value =    1200; break;
196                 case   B2400: value =    2400; break;
197                 case   B4800: value =    4800; break;
198                 case   B9600: value =    9600; break;
199                 case  B19200: value =   19200; break;
200                 case  B38400: value =   38400; break;
201                 case  B57600: value =   57600; break;
202                 case B115200: value =  115200; break;
203                 default:
204                         err("MCT USB-RS232: unsupported baudrate request 0x%x,"
205                             " using default of B9600", value);
206                         value = 9600;
207                 }
208                 return 115200/value;
209         }
210 }
211
212 static int mct_u232_set_baud_rate(struct usb_serial *serial, int value)
213 {
214         unsigned int divisor;
215         int rc;
216         unsigned char zero_byte = 0;
217
218         divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value));
219
220         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
221                              MCT_U232_SET_BAUD_RATE_REQUEST,
222                              MCT_U232_SET_REQUEST_TYPE,
223                              0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE,
224                              WDR_TIMEOUT);
225         if (rc < 0)
226                 err("Set BAUD RATE %d failed (error = %d)", value, rc);
227         dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor);
228
229         /* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which
230            always sends two extra USB 'device request' messages after the
231            'baud rate change' message.  The actual functionality of the
232            request codes in these messages is not fully understood but these
233            particular codes are never seen in any operation besides a baud
234            rate change.  Both of these messages send a single byte of data
235            whose value is always zero.  The second of these two extra messages
236            is required in order for data to be properly written to an RS-232
237            device which does not assert the 'CTS' signal. */
238
239         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
240                              MCT_U232_SET_UNKNOWN1_REQUEST, 
241                              MCT_U232_SET_REQUEST_TYPE,
242                              0, 0, &zero_byte, MCT_U232_SET_UNKNOWN1_SIZE, 
243                              WDR_TIMEOUT);
244         if (rc < 0)
245                 err("Sending USB device request code %d failed (error = %d)", 
246                     MCT_U232_SET_UNKNOWN1_REQUEST, rc);
247
248         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
249                              MCT_U232_SET_UNKNOWN2_REQUEST, 
250                              MCT_U232_SET_REQUEST_TYPE,
251                              0, 0, &zero_byte, MCT_U232_SET_UNKNOWN2_SIZE, 
252                              WDR_TIMEOUT);
253         if (rc < 0)
254                 err("Sending USB device request code %d failed (error = %d)", 
255                     MCT_U232_SET_UNKNOWN2_REQUEST, rc);
256
257         return rc;
258 } /* mct_u232_set_baud_rate */
259
260 static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr)
261 {
262         int rc;
263         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
264                              MCT_U232_SET_LINE_CTRL_REQUEST,
265                              MCT_U232_SET_REQUEST_TYPE,
266                              0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE,
267                              WDR_TIMEOUT);
268         if (rc < 0)
269                 err("Set LINE CTRL 0x%x failed (error = %d)", lcr, rc);
270         dbg("set_line_ctrl: 0x%x", lcr);
271         return rc;
272 } /* mct_u232_set_line_ctrl */
273
274 static int mct_u232_set_modem_ctrl(struct usb_serial *serial,
275                                    unsigned int control_state)
276 {
277         int rc;
278         unsigned char mcr = MCT_U232_MCR_NONE;
279
280         if (control_state & TIOCM_DTR)
281                 mcr |= MCT_U232_MCR_DTR;
282         if (control_state & TIOCM_RTS)
283                 mcr |= MCT_U232_MCR_RTS;
284
285         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
286                              MCT_U232_SET_MODEM_CTRL_REQUEST,
287                              MCT_U232_SET_REQUEST_TYPE,
288                              0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE,
289                              WDR_TIMEOUT);
290         if (rc < 0)
291                 err("Set MODEM CTRL 0x%x failed (error = %d)", mcr, rc);
292         dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr);
293
294         return rc;
295 } /* mct_u232_set_modem_ctrl */
296
297 static int mct_u232_get_modem_stat(struct usb_serial *serial, unsigned char *msr)
298 {
299         int rc;
300         rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
301                              MCT_U232_GET_MODEM_STAT_REQUEST,
302                              MCT_U232_GET_REQUEST_TYPE,
303                              0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE,
304                              WDR_TIMEOUT);
305         if (rc < 0) {
306                 err("Get MODEM STATus failed (error = %d)", rc);
307                 *msr = 0;
308         }
309         dbg("get_modem_stat: 0x%x", *msr);
310         return rc;
311 } /* mct_u232_get_modem_stat */
312
313 static void mct_u232_msr_to_state(unsigned int *control_state, unsigned char msr)
314 {
315         /* Translate Control Line states */
316         if (msr & MCT_U232_MSR_DSR)
317                 *control_state |=  TIOCM_DSR;
318         else
319                 *control_state &= ~TIOCM_DSR;
320         if (msr & MCT_U232_MSR_CTS)
321                 *control_state |=  TIOCM_CTS;
322         else
323                 *control_state &= ~TIOCM_CTS;
324         if (msr & MCT_U232_MSR_RI)
325                 *control_state |=  TIOCM_RI;
326         else
327                 *control_state &= ~TIOCM_RI;
328         if (msr & MCT_U232_MSR_CD)
329                 *control_state |=  TIOCM_CD;
330         else
331                 *control_state &= ~TIOCM_CD;
332         dbg("msr_to_state: msr=0x%x ==> state=0x%x", msr, *control_state);
333 } /* mct_u232_msr_to_state */
334
335 /*
336  * Driver's tty interface functions
337  */
338
339 static int mct_u232_startup (struct usb_serial *serial)
340 {
341         struct mct_u232_private *priv;
342         struct usb_serial_port *port, *rport;
343
344         priv = kmalloc(sizeof(struct mct_u232_private), GFP_KERNEL);
345         if (!priv)
346                 return -ENOMEM;
347         memset(priv, 0, sizeof(struct mct_u232_private));
348         spin_lock_init(&priv->lock);
349         serial->port->private = priv;
350
351         init_waitqueue_head(&serial->port->write_wait);
352
353         /* Puh, that's dirty */
354         port = &serial->port[0];
355         rport = &serial->port[1];
356         if (port->read_urb) {
357                 /* No unlinking, it wasn't submitted yet. */
358                 usb_free_urb(port->read_urb);
359         }
360         port->read_urb = rport->interrupt_in_urb;
361         rport->interrupt_in_urb = NULL;
362         port->read_urb->context = port;
363
364         priv->ik[0].ibase = port->read_urb->interval;
365         priv->ik[1].ibase = port->interrupt_in_urb->interval;
366
367         return (0);
368 } /* mct_u232_startup */
369
370
371 static void mct_u232_shutdown (struct usb_serial *serial)
372 {
373         struct mct_u232_private *priv;
374         int i;
375         
376         dbg("%s", __FUNCTION__);
377
378         for (i=0; i < serial->num_ports; ++i) {
379                 /* My special items, the standard routines free my urbs */
380                 priv = serial->port[i].private;
381                 if (priv) {
382                         serial->port[i].private = NULL;
383                         kfree(priv);
384                 }
385         }
386 } /* mct_u232_shutdown */
387
388 static int  mct_u232_open (struct usb_serial_port *port, struct file *filp)
389 {
390         struct usb_serial *serial = port->serial;
391         struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
392         int retval = 0;
393         unsigned int control_state;
394         unsigned long flags;
395         unsigned char last_lcr;
396         unsigned char last_msr;
397
398         dbg("%s port %d", __FUNCTION__, port->number);
399
400         /* Compensate for a hardware bug: although the Sitecom U232-P25
401          * device reports a maximum output packet size of 32 bytes,
402          * it seems to be able to accept only 16 bytes (and that's what
403          * SniffUSB says too...)
404          */
405         if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID)
406                 port->bulk_out_size = 16;
407
408         /* Do a defined restart: the normal serial device seems to 
409          * always turn on DTR and RTS here, so do the same. I'm not
410          * sure if this is really necessary. But it should not harm
411          * either.
412          */
413         spin_lock_irqsave(&priv->lock, flags);
414         if (port->tty->termios->c_cflag & CBAUD)
415                 priv->control_state = TIOCM_DTR | TIOCM_RTS;
416         else
417                 priv->control_state = 0;
418         
419         priv->last_lcr = (MCT_U232_DATA_BITS_8 | 
420                           MCT_U232_PARITY_NONE |
421                           MCT_U232_STOP_BITS_1);
422         control_state = priv->control_state;
423         last_lcr = priv->last_lcr;
424         spin_unlock_irqrestore(&priv->lock, flags);
425         mct_u232_set_modem_ctrl(serial, control_state);
426         mct_u232_set_line_ctrl(serial, last_lcr);
427
428         /* Read modem status and update control state */
429         mct_u232_get_modem_stat(serial, &last_msr);
430         spin_lock_irqsave(&priv->lock, flags);
431         priv->last_msr = last_msr;
432         mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
433         spin_unlock_irqrestore(&priv->lock, flags);
434
435         port->read_urb->dev = port->serial->dev;
436         port->read_urb->interval = priv->ik[0].ibase;
437         retval = usb_submit_urb(port->read_urb);
438         if (retval) {
439                 err("usb_submit_urb(read bulk) failed pipe 0x%x err %d",
440                     port->read_urb->pipe, retval);
441                 goto exit;
442         }
443
444         port->interrupt_in_urb->dev = port->serial->dev;
445         port->interrupt_in_urb->interval = priv->ik[1].ibase;
446         retval = usb_submit_urb(port->interrupt_in_urb);
447         if (retval)
448                 err(" usb_submit_urb(read int) failed pipe 0x%x err %d",
449                     port->interrupt_in_urb->pipe, retval);
450
451 exit:
452         return 0;
453 } /* mct_u232_open */
454
455
456 static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
457 {
458         dbg("%s port %d", __FUNCTION__, port->number);
459
460         if (port->serial->dev) {
461                 /* shutdown our urbs */
462                 usb_unlink_urb (port->write_urb);
463                 usb_unlink_urb (port->read_urb);
464                 usb_unlink_urb (port->interrupt_in_urb);
465         }
466 } /* mct_u232_close */
467
468 static void mct_u232_error_step (struct urb *urb,
469     struct mct_u232_private *priv, int n)
470 {
471         struct mct_u232_interval_kludge *ikp = &priv->ik[n];
472
473         if (ikp->ecnt >= 2) {
474                 if (urb->interval)
475                         err("%s - too many errors: "
476                             "status %d pipe 0x%x interval %d",
477                             __FUNCTION__,
478                             urb->status, urb->pipe, urb->interval);
479                 urb->interval = 0;
480         } else {
481                 ++ikp->ecnt;
482         }
483 }
484
485 static void mct_u232_read_int_callback (struct urb *urb)
486 {
487         struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
488         struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
489         struct usb_serial *serial = port->serial;
490         struct tty_struct *tty;
491         unsigned char *data = urb->transfer_buffer;
492         unsigned long flags;
493
494         /* The urb might have been killed. */
495         if (urb->status) {
496                 dbg("%s - nonzero status %d, pipe 0x%x flags 0x%x interval %d",
497                     __FUNCTION__,
498                     urb->status, urb->pipe, urb->transfer_flags, urb->interval);
499                 /*
500                  * The bad stuff happens when a device is disconnected.
501                  * This can cause us to spin while trying to resubmit.
502                  * Unfortunately, in kernel 2.4 error codes are wildly
503                  * different between controllers, so the status is useless.
504                  * Instead we just refuse to spin too much.
505                  */
506                 if (urb == port->read_urb)
507                         mct_u232_error_step(urb, priv, 0);
508                 if (urb == port->interrupt_in_urb)
509                         mct_u232_error_step(urb, priv, 1);
510                 return;
511         }
512         if (!serial) {
513                 dbg("%s - bad serial pointer, exiting", __FUNCTION__);
514                 return;
515         }
516
517         dbg("%s - port %d", __FUNCTION__, port->number);
518         usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
519
520         if (urb == port->read_urb)
521                 priv->ik[0].ecnt = 0;
522         if (urb == port->interrupt_in_urb)
523                 priv->ik[1].ecnt = 0;
524
525         /*
526          * Work-a-round: handle the 'usual' bulk-in pipe here
527          */
528         if (urb->transfer_buffer_length > 2) {
529                 int i;
530                 tty = port->tty;
531                 if (urb->actual_length) {
532                         for (i = 0; i < urb->actual_length ; ++i) {
533                                 tty_insert_flip_char(tty, data[i], 0);
534                         }
535                         tty_flip_buffer_push(tty);
536                 }
537                 /* INT urbs are automatically re-submitted */
538                 return;
539         }
540         
541         /*
542          * The interrupt-in pipe signals exceptional conditions (modem line
543          * signal changes and errors). data[0] holds MSR, data[1] holds LSR.
544          */
545         spin_lock_irqsave(&priv->lock, flags);
546         priv->last_msr = data[MCT_U232_MSR_INDEX];
547         
548         /* Record Control Line states */
549         mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
550
551 #if 0
552         /* Not yet handled. See belin_sa.c for further information */
553         /* Now to report any errors */
554         priv->last_lsr = data[MCT_U232_LSR_INDEX];
555         /*
556          * fill in the flip buffer here, but I do not know the relation
557          * to the current/next receive buffer or characters.  I need
558          * to look in to this before committing any code.
559          */
560         if (priv->last_lsr & MCT_U232_LSR_ERR) {
561                 tty = port->tty;
562                 /* Overrun Error */
563                 if (priv->last_lsr & MCT_U232_LSR_OE) {
564                 }
565                 /* Parity Error */
566                 if (priv->last_lsr & MCT_U232_LSR_PE) {
567                 }
568                 /* Framing Error */
569                 if (priv->last_lsr & MCT_U232_LSR_FE) {
570                 }
571                 /* Break Indicator */
572                 if (priv->last_lsr & MCT_U232_LSR_BI) {
573                 }
574         }
575 #endif
576         spin_unlock_irqrestore(&priv->lock, flags);
577
578         /* INT urbs are automatically re-submitted */
579 } /* mct_u232_read_int_callback */
580
581 static void mct_u232_set_termios (struct usb_serial_port *port,
582                                   struct termios *old_termios)
583 {
584         struct usb_serial *serial = port->serial;
585         struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
586         unsigned int iflag = port->tty->termios->c_iflag;
587         unsigned int cflag = port->tty->termios->c_cflag;
588         unsigned int old_cflag = old_termios->c_cflag;
589         unsigned long flags;
590         unsigned int control_state, new_state;
591         unsigned char last_lcr;
592
593         /* get a local copy of the current port settings */
594         spin_lock_irqsave(&priv->lock, flags);
595         control_state = priv->control_state;
596         spin_unlock_irqrestore(&priv->lock, flags);
597         last_lcr = 0;
598
599         /*
600          * Update baud rate.
601          * Do not attempt to cache old rates and skip settings,
602          * disconnects screw such tricks up completely.
603          * Premature optimization is the root of all evil.
604          */
605
606         /* reassert DTR and (maybe) RTS on transition from B0 */
607         if ((old_cflag & CBAUD) == B0) {
608                 dbg("%s: baud was B0", __FUNCTION__);
609                 control_state |= TIOCM_DTR;
610                 /* don't set RTS if using hardware flow control */
611                 if (!(old_cflag & CRTSCTS)) {
612                         control_state |= TIOCM_RTS;
613                 }
614                 mct_u232_set_modem_ctrl(serial, control_state);
615         }
616
617         mct_u232_set_baud_rate(serial, cflag & CBAUD);
618
619         if ((cflag & CBAUD) == B0 ) {
620                 dbg("%s: baud is B0", __FUNCTION__);
621                 /* Drop RTS and DTR */
622                 control_state &= ~(TIOCM_DTR | TIOCM_RTS);
623                 mct_u232_set_modem_ctrl(serial, control_state);
624         }
625
626         /*
627          * Update line control register (LCR)
628          */
629
630         /* set the parity */
631         if (cflag & PARENB)
632                 last_lcr |= (cflag & PARODD) ?
633                         MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN;
634         else
635                 last_lcr |= MCT_U232_PARITY_NONE;
636
637         /* set the number of data bits */
638         switch (cflag & CSIZE) {
639         case CS5:
640                 last_lcr |= MCT_U232_DATA_BITS_5; break;
641         case CS6:
642                 last_lcr |= MCT_U232_DATA_BITS_6; break;
643         case CS7:
644                 last_lcr |= MCT_U232_DATA_BITS_7; break;
645         case CS8:
646                 last_lcr |= MCT_U232_DATA_BITS_8; break;
647         default:
648                 err("CSIZE was not CS5-CS8, using default of 8");
649                 last_lcr |= MCT_U232_DATA_BITS_8;
650                 break;
651         }
652
653         /* set the number of stop bits */
654         last_lcr |= (cflag & CSTOPB) ?
655                 MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
656
657         mct_u232_set_line_ctrl(serial, last_lcr);
658
659         /*
660          * Set flow control: well, I do not really now how to handle DTR/RTS.
661          * Just do what we have seen with SniffUSB on Win98.
662          */
663         /* Drop DTR/RTS if no flow control otherwise assert */
664         new_state = control_state;
665         if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS))
666                 new_state |= TIOCM_DTR | TIOCM_RTS;
667         else
668                 new_state &= ~(TIOCM_DTR | TIOCM_RTS);
669         if (new_state != control_state) {
670                 mct_u232_set_modem_ctrl(serial, new_state);
671                 control_state = new_state;
672         }
673
674         /* save off the modified port settings */
675         spin_lock_irqsave(&priv->lock, flags);
676         priv->control_state = control_state;
677         priv->last_lcr = last_lcr;
678         spin_unlock_irqrestore(&priv->lock, flags);
679 } /* mct_u232_set_termios */
680
681 static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
682 {
683         struct usb_serial *serial = port->serial;
684         struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
685         unsigned char lcr;
686         unsigned long flags;
687
688         dbg("%sstate=%d", __FUNCTION__, break_state);
689
690         spin_lock_irqsave(&priv->lock, flags);
691         lcr = priv->last_lcr;
692         spin_unlock_irqrestore(&priv->lock, flags);
693
694         if (break_state)
695                 lcr |= MCT_U232_SET_BREAK;
696
697         mct_u232_set_line_ctrl(serial, lcr);
698 } /* mct_u232_break_ctl */
699
700
701 static int mct_u232_tiocmget (struct usb_serial_port *port, struct file *file)
702 {
703         struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
704         unsigned int control_state;
705         unsigned long flags;
706         
707         dbg("%s", __FUNCTION__);
708
709         spin_lock_irqsave(&priv->lock, flags);
710         control_state = priv->control_state;
711         spin_unlock_irqrestore(&priv->lock, flags);
712
713         return control_state;
714 }
715
716 static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
717                            unsigned int cmd, unsigned long arg)
718 {
719         struct usb_serial *serial = port->serial;
720         struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
721         int mask;
722         unsigned long flags;
723
724         dbg("%scmd=0x%x", __FUNCTION__, cmd);
725
726         /* Based on code from acm.c and others */
727         switch (cmd) {
728         case TIOCMGET:
729                 mask = mct_u232_tiocmget(port, file);
730                 return put_user(mask, (unsigned long *) arg);
731
732         case TIOCMSET: /* Turns on and off the lines as specified by the mask */
733         case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */
734         case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */
735                 if (get_user(mask, (unsigned long *) arg))
736                         return -EFAULT;
737
738                 spin_lock_irqsave(&priv->lock, flags);
739                 if ((cmd == TIOCMSET) || (mask & TIOCM_RTS)) {
740                         /* RTS needs set */
741                         if( ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) ||
742                             (cmd == TIOCMBIS) )
743                                 priv->control_state |=  TIOCM_RTS;
744                         else
745                                 priv->control_state &= ~TIOCM_RTS;
746                 }
747
748                 if ((cmd == TIOCMSET) || (mask & TIOCM_DTR)) {
749                         /* DTR needs set */
750                         if( ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) ||
751                             (cmd == TIOCMBIS) )
752                                 priv->control_state |=  TIOCM_DTR;
753                         else
754                                 priv->control_state &= ~TIOCM_DTR;
755                 }
756                 spin_unlock_irqrestore(&priv->lock, flags);
757                 mct_u232_set_modem_ctrl(serial, priv->control_state);
758                 break;
759                                         
760         case TIOCMIWAIT:
761                 /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
762                 /* TODO */
763                 return( 0 );
764
765         case TIOCGICOUNT:
766                 /* return count of modemline transitions */
767                 /* TODO */
768                 return 0;
769
770         default:
771                 dbg("%s: arg not supported - 0x%04x", __FUNCTION__,cmd);
772                 return(-ENOIOCTLCMD);
773                 break;
774         }
775         return 0;
776 } /* mct_u232_ioctl */
777
778
779 static int __init mct_u232_init (void)
780 {
781         usb_serial_register (&mct_u232_device);
782         info(DRIVER_DESC " " DRIVER_VERSION);
783         return 0;
784 }
785
786
787 static void __exit mct_u232_exit (void)
788 {
789         usb_serial_deregister (&mct_u232_device);
790 }
791
792
793 module_init (mct_u232_init);
794 module_exit(mct_u232_exit);
795
796 MODULE_AUTHOR( DRIVER_AUTHOR );
797 MODULE_DESCRIPTION( DRIVER_DESC );
798 MODULE_LICENSE("GPL");
799
800 MODULE_PARM(debug, "i");
801 MODULE_PARM_DESC(debug, "Debug enabled or not");