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