v2.5.0.7 -> v2.5.0.8
[opensuse:kernel.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  * 10-Nov-2001 Wolfgang Grandegger
28  *   - Fixed an endianess problem with the baudrate selection for PowerPC.
29  *
30  * 06-Dec-2001 Martin Hamilton <martinh@gnu.org>
31  *      Added support for the Belkin F5U109 DB9 adaptor
32  *
33  * 30-May-2001 Greg Kroah-Hartman
34  *      switched from using spinlock to a semaphore, which fixes lots of problems.
35  *
36  * 04-May-2001 Stelian Pop
37  *   - Set the maximum bulk output size for Sitecom U232-P25 model to 16 bytes
38  *     instead of the device reported 32 (using 32 bytes causes many data
39  *     loss, Windows driver uses 16 too).
40  *
41  * 02-May-2001 Stelian Pop
42  *   - Fixed the baud calculation for Sitecom U232-P25 model
43  *
44  * 08-Apr-2001 gb
45  *   - Identify version on module load.
46  *
47  * 06-Jan-2001 Cornel Ciocirlan 
48  *   - Added support for Sitecom U232-P25 model (Product Id 0x0230)
49  *   - Added support for D-Link DU-H3SP USB BAY (Product Id 0x0200)
50  *
51  * 29-Nov-2000 Greg Kroah-Hartman
52  *   - Added device id table to fit with 2.4.0-test11 structure.
53  *   - took out DEAL_WITH_TWO_INT_IN_ENDPOINTS #define as it's not needed
54  *     (lots of things will change if/when the usb-serial core changes to
55  *     handle these issues.
56  *
57  * 27-Nov-2000 Wolfgang Grandegger
58  *   A version for kernel 2.4.0-test10 released to the Linux community 
59  *   (via linux-usb-devel).
60  */
61
62 #include <linux/config.h>
63 #include <linux/kernel.h>
64 #include <linux/sched.h>
65 #include <linux/signal.h>
66 #include <linux/errno.h>
67 #include <linux/poll.h>
68 #include <linux/init.h>
69 #include <linux/slab.h>
70 #include <linux/fcntl.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 <linux/usb.h>
77
78 #ifdef CONFIG_USB_SERIAL_DEBUG
79         static int debug = 1;
80 #else
81         static int debug;
82 #endif
83
84 #include "usb-serial.h"
85 #include "mct_u232.h"
86
87
88 /*
89  * Version Information
90  */
91 #define DRIVER_VERSION "v1.1"
92 #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
93 #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
94
95 /*
96  * Some not properly written applications do not handle the return code of
97  * write() correctly. This can result in character losses. A work-a-round
98  * can be compiled in with the following definition. This work-a-round
99  * should _NOT_ be part of an 'official' kernel release, of course!
100  */
101 #undef FIX_WRITE_RETURN_CODE_PROBLEM
102 #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
103 static int write_blocking; /* disabled by default */
104 #endif
105
106 /*
107  * Function prototypes
108  */
109 static int  mct_u232_startup             (struct usb_serial *serial);
110 static void mct_u232_shutdown            (struct usb_serial *serial);
111 static int  mct_u232_open                (struct usb_serial_port *port,
112                                           struct file *filp);
113 static void mct_u232_close               (struct usb_serial_port *port,
114                                           struct file *filp);
115 #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
116 static int  mct_u232_write               (struct usb_serial_port *port,
117                                           int from_user,
118                                           const unsigned char *buf,
119                                           int count);
120 static void mct_u232_write_bulk_callback (struct urb *urb);
121 #endif
122 static void mct_u232_read_int_callback   (struct urb *urb);
123 static void mct_u232_set_termios         (struct usb_serial_port *port,
124                                           struct termios * old);
125 static int  mct_u232_ioctl               (struct usb_serial_port *port,
126                                           struct file * file,
127                                           unsigned int cmd,
128                                           unsigned long arg);
129 static void mct_u232_break_ctl           (struct usb_serial_port *port,
130                                           int break_state );
131
132 /*
133  * All of the device info needed for the MCT USB-RS232 converter.
134  */
135 static __devinitdata struct usb_device_id id_table_combined [] = {
136         { USB_DEVICE(MCT_U232_VID, MCT_U232_PID) },
137         { USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) },
138         { USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) },
139         { USB_DEVICE(MCT_U232_BELKIN_F5U109_VID, MCT_U232_BELKIN_F5U109_PID) },
140         { }             /* Terminating entry */
141 };
142
143 MODULE_DEVICE_TABLE (usb, id_table_combined);
144
145
146 static struct usb_serial_device_type mct_u232_device = {
147         name:                "Magic Control Technology USB-RS232",
148         id_table:            id_table_combined,
149         num_interrupt_in:    2,
150         num_bulk_in:         0,
151         num_bulk_out:        1,
152         num_ports:           1,
153         open:                mct_u232_open,
154         close:               mct_u232_close,
155 #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
156         write:               mct_u232_write,
157         write_bulk_callback: mct_u232_write_bulk_callback,
158 #endif
159         read_int_callback:   mct_u232_read_int_callback,
160         ioctl:               mct_u232_ioctl,
161         set_termios:         mct_u232_set_termios,
162         break_ctl:           mct_u232_break_ctl,
163         startup:             mct_u232_startup,
164         shutdown:            mct_u232_shutdown,
165 };
166
167
168 struct mct_u232_private {
169         unsigned long        control_state; /* Modem Line Setting (TIOCM) */
170         unsigned char        last_lcr;      /* Line Control Register */
171         unsigned char        last_lsr;      /* Line Status Register */
172         unsigned char        last_msr;      /* Modem Status Register */
173 };
174
175 /*
176  * Handle vendor specific USB requests
177  */
178
179 #define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
180
181 static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value) {
182         if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID
183           || serial->dev->descriptor.idProduct == MCT_U232_BELKIN_F5U109_PID) {
184                 switch (value) {
185                         case    300: return 0x01;
186                         case    600: return 0x02; /* this one not tested */
187                         case   1200: return 0x03;
188                         case   2400: return 0x04;
189                         case   4800: return 0x06;
190                         case   9600: return 0x08;
191                         case  19200: return 0x09;
192                         case  38400: return 0x0a;
193                         case  57600: return 0x0b;
194                         case 115200: return 0x0c;
195                         default:     return -1; /* normally not reached */
196                 }
197         }
198         else
199                 return MCT_U232_BAUD_RATE(value);
200 }
201
202 static int mct_u232_set_baud_rate(struct usb_serial *serial, int value)
203 {
204         unsigned int divisor;
205         int rc;
206         divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value));
207         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
208                              MCT_U232_SET_BAUD_RATE_REQUEST,
209                              MCT_U232_SET_REQUEST_TYPE,
210                              0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE,
211                              WDR_TIMEOUT);
212         if (rc < 0)
213                 err("Set BAUD RATE %d failed (error = %d)", value, rc);
214         dbg("set_baud_rate: value: %d, divisor: 0x%x", value, divisor);
215         return rc;
216 } /* mct_u232_set_baud_rate */
217
218 static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr)
219 {
220         int rc;
221         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
222                              MCT_U232_SET_LINE_CTRL_REQUEST,
223                              MCT_U232_SET_REQUEST_TYPE,
224                              0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE,
225                              WDR_TIMEOUT);
226         if (rc < 0)
227                 err("Set LINE CTRL 0x%x failed (error = %d)", lcr, rc);
228         dbg("set_line_ctrl: 0x%x", lcr);
229         return rc;
230 } /* mct_u232_set_line_ctrl */
231
232 static int mct_u232_set_modem_ctrl(struct usb_serial *serial,
233                                    unsigned long control_state)
234 {
235         int rc;
236         unsigned char mcr = MCT_U232_MCR_NONE;
237
238         if (control_state & TIOCM_DTR)
239                 mcr |= MCT_U232_MCR_DTR;
240         if (control_state & TIOCM_RTS)
241                 mcr |= MCT_U232_MCR_RTS;
242
243         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
244                              MCT_U232_SET_MODEM_CTRL_REQUEST,
245                              MCT_U232_SET_REQUEST_TYPE,
246                              0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE,
247                              WDR_TIMEOUT);
248         if (rc < 0)
249                 err("Set MODEM CTRL 0x%x failed (error = %d)", mcr, rc);
250         dbg("set_modem_ctrl: state=0x%lx ==> mcr=0x%x", control_state, mcr);
251
252         return rc;
253 } /* mct_u232_set_modem_ctrl */
254
255 static int mct_u232_get_modem_stat(struct usb_serial *serial, unsigned char *msr)
256 {
257         int rc;
258         rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
259                              MCT_U232_GET_MODEM_STAT_REQUEST,
260                              MCT_U232_GET_REQUEST_TYPE,
261                              0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE,
262                              WDR_TIMEOUT);
263         if (rc < 0) {
264                 err("Get MODEM STATus failed (error = %d)", rc);
265                 *msr = 0;
266         }
267         dbg("get_modem_stat: 0x%x", *msr);
268         return rc;
269 } /* mct_u232_get_modem_stat */
270
271 static void mct_u232_msr_to_state(unsigned long *control_state, unsigned char msr)
272 {
273         /* Translate Control Line states */
274         if (msr & MCT_U232_MSR_DSR)
275                 *control_state |=  TIOCM_DSR;
276         else
277                 *control_state &= ~TIOCM_DSR;
278         if (msr & MCT_U232_MSR_CTS)
279                 *control_state |=  TIOCM_CTS;
280         else
281                 *control_state &= ~TIOCM_CTS;
282         if (msr & MCT_U232_MSR_RI)
283                 *control_state |=  TIOCM_RI;
284         else
285                 *control_state &= ~TIOCM_RI;
286         if (msr & MCT_U232_MSR_CD)
287                 *control_state |=  TIOCM_CD;
288         else
289                 *control_state &= ~TIOCM_CD;
290         dbg("msr_to_state: msr=0x%x ==> state=0x%lx", msr, *control_state);
291 } /* mct_u232_msr_to_state */
292
293 /*
294  * Driver's tty interface functions
295  */
296
297 static int mct_u232_startup (struct usb_serial *serial)
298 {
299         struct mct_u232_private *priv;
300
301         /* allocate the private data structure */
302         serial->port->private = kmalloc(sizeof(struct mct_u232_private),
303                                         GFP_KERNEL);
304         if (!serial->port->private)
305                 return (-1); /* error */
306         priv = (struct mct_u232_private *)serial->port->private;
307         /* set initial values for control structures */
308         priv->control_state = 0;
309         priv->last_lsr = 0;
310         priv->last_msr = 0;
311
312         init_waitqueue_head(&serial->port->write_wait);
313         
314         return (0);
315 } /* mct_u232_startup */
316
317
318 static void mct_u232_shutdown (struct usb_serial *serial)
319 {
320         int i;
321         
322         dbg (__FUNCTION__);
323
324         /* stop reads and writes on all ports */
325         for (i=0; i < serial->num_ports; ++i) {
326                 while (serial->port[i].open_count > 0) {
327                         mct_u232_close (&serial->port[i], NULL);
328                 }
329                 /* My special items, the standard routines free my urbs */
330                 if (serial->port[i].private)
331                         kfree(serial->port[i].private);
332         }
333 } /* mct_u232_shutdown */
334
335 static int  mct_u232_open (struct usb_serial_port *port, struct file *filp)
336 {
337         struct usb_serial *serial = port->serial;
338         struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
339         int retval = 0;
340
341         dbg(__FUNCTION__" port %d", port->number);
342
343         down (&port->sem);
344         
345         ++port->open_count;
346         MOD_INC_USE_COUNT;
347
348         if (port->open_count == 1) {
349                 /* Compensate for a hardware bug: although the Sitecom U232-P25
350                  * device reports a maximum output packet size of 32 bytes,
351                  * it seems to be able to accept only 16 bytes (and that's what
352                  * SniffUSB says too...)
353                  */
354                 if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID)
355                         port->bulk_out_size = 16;
356
357                 /* Do a defined restart: the normal serial device seems to 
358                  * always turn on DTR and RTS here, so do the same. I'm not
359                  * sure if this is really necessary. But it should not harm
360                  * either.
361                  */
362                 if (port->tty->termios->c_cflag & CBAUD)
363                         priv->control_state = TIOCM_DTR | TIOCM_RTS;
364                 else
365                         priv->control_state = 0;
366                 mct_u232_set_modem_ctrl(serial, priv->control_state);
367                 
368                 priv->last_lcr = (MCT_U232_DATA_BITS_8 | 
369                                   MCT_U232_PARITY_NONE |
370                                   MCT_U232_STOP_BITS_1);
371                 mct_u232_set_line_ctrl(serial, priv->last_lcr);
372
373                 /* Read modem status and update control state */
374                 mct_u232_get_modem_stat(serial, &priv->last_msr);
375                 mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
376
377                 {
378                         /* Puh, that's dirty */
379                         struct usb_serial_port *rport;  
380                         rport = &serial->port[1];
381                         rport->tty = port->tty;
382                         rport->private = port->private;
383                         port->read_urb = rport->interrupt_in_urb;
384                 }
385
386                 port->read_urb->dev = port->serial->dev;
387                 retval = usb_submit_urb(port->read_urb);
388                 if (retval) {
389                         err("usb_submit_urb(read bulk) failed");
390                         goto exit;
391                 }
392
393                 port->interrupt_in_urb->dev = port->serial->dev;
394                 retval = usb_submit_urb(port->interrupt_in_urb);
395                 if (retval)
396                         err(" usb_submit_urb(read int) failed");
397
398         }
399
400 exit:
401         up (&port->sem);
402         
403         return 0;
404 } /* mct_u232_open */
405
406
407 static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
408 {
409         dbg(__FUNCTION__" port %d", port->number);
410
411         down (&port->sem);
412
413         --port->open_count;
414
415         if (port->open_count <= 0) {
416                 if (port->serial->dev) {
417                         /* shutdown our urbs */
418                         usb_unlink_urb (port->write_urb);
419                         usb_unlink_urb (port->read_urb);
420                         usb_unlink_urb (port->interrupt_in_urb);
421                 }
422                 port->open_count = 0;
423         }
424         
425         up (&port->sem);
426         MOD_DEC_USE_COUNT;
427 } /* mct_u232_close */
428
429
430 #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
431 /* The generic routines work fine otherwise */
432
433 static int mct_u232_write (struct usb_serial_port *port, int from_user,
434                            const unsigned char *buf, int count)
435 {
436         struct usb_serial *serial = port->serial;
437         int result, bytes_sent, size;
438
439         dbg(__FUNCTION__ " - port %d", port->number);
440
441         if (count == 0) {
442                 dbg(__FUNCTION__ " - write request of 0 bytes");
443                 return (0);
444         }
445
446         /* only do something if we have a bulk out endpoint */
447         if (!serial->num_bulk_out)
448                 return(0);;
449         
450         /* another write is still pending? */
451         if (port->write_urb->status == -EINPROGRESS) {
452                 dbg (__FUNCTION__ " - already writing");
453                 return (0);
454         }
455                 
456         bytes_sent = 0;
457         while (count > 0) {
458                 
459                 down (&port->sem);
460                 
461                 size = (count > port->bulk_out_size) ? port->bulk_out_size : count;
462                 
463                 usb_serial_debug_data (__FILE__, __FUNCTION__, size, buf);
464                 
465                 if (from_user) {
466                         if (copy_from_user(port->write_urb->transfer_buffer, buf, size)) {
467                                 up (&port->sem);
468                                 return -EFAULT;
469                         }
470                 }
471                 else {
472                         memcpy (port->write_urb->transfer_buffer, buf, size);
473                 }
474                 
475                 /* set up our urb */
476                 FILL_BULK_URB(port->write_urb, serial->dev,
477                               usb_sndbulkpipe(serial->dev,
478                                               port->bulk_out_endpointAddress),
479                               port->write_urb->transfer_buffer, size,
480                               ((serial->type->write_bulk_callback) ?
481                                serial->type->write_bulk_callback :
482                                mct_u232_write_bulk_callback),
483                               port);
484                 
485                 /* send the data out the bulk port */
486                 result = usb_submit_urb(port->write_urb);
487                 if (result) {
488                         err(__FUNCTION__
489                             " - failed submitting write urb, error %d", result);
490                         up (&port->sem);
491                         return result;
492                 }
493
494                 up (&port->sem);
495
496                 bytes_sent += size;
497                 if (write_blocking)
498                         interruptible_sleep_on(&port->write_wait);
499                 else
500                         break;
501
502                 buf += size;
503                 count -= size;
504         }
505         
506         return bytes_sent;
507 } /* mct_u232_write */
508
509 static void mct_u232_write_bulk_callback (struct urb *urb)
510 {
511         struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
512         struct usb_serial *serial = port->serial;
513         struct tty_struct *tty = port->tty;
514
515         dbg(__FUNCTION__ " - port %d", port->number);
516         
517         if (!serial) {
518                 dbg(__FUNCTION__ " - bad serial pointer, exiting");
519                 return;
520         }
521
522         if (urb->status) {
523                 dbg(__FUNCTION__ " - nonzero write bulk status received: %d",
524                     urb->status);
525                 return;
526         }
527
528         if (write_blocking) {
529                 wake_up_interruptible(&port->write_wait);
530                 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
531                     tty->ldisc.write_wakeup)
532                         (tty->ldisc.write_wakeup)(tty);
533                 wake_up_interruptible(&tty->write_wait);
534                 
535         } else {
536                 /* from generic_write_bulk_callback */
537                 queue_task(&port->tqueue, &tq_immediate);
538                 mark_bh(IMMEDIATE_BH);
539         }
540
541         return;
542 } /* mct_u232_write_bulk_callback */
543 #endif
544
545 static void mct_u232_read_int_callback (struct urb *urb)
546 {
547         struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
548         struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
549         struct usb_serial *serial = port->serial;
550         struct tty_struct *tty;
551         unsigned char *data = urb->transfer_buffer;
552
553         dbg(__FUNCTION__ " - port %d", port->number);
554
555         /* The urb might have been killed. */
556         if (urb->status) {
557                 dbg(__FUNCTION__ " - nonzero read bulk status received: %d",
558                     urb->status);
559                 return;
560         }
561         if (!serial) {
562                 dbg(__FUNCTION__ " - bad serial pointer, exiting");
563                 return;
564         }
565         
566         usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
567
568         /*
569          * Work-a-round: handle the 'usual' bulk-in pipe here
570          */
571         if (urb->transfer_buffer_length > 2) {
572                 int i;
573                 tty = port->tty;
574                 if (urb->actual_length) {
575                         for (i = 0; i < urb->actual_length ; ++i) {
576                                 tty_insert_flip_char(tty, data[i], 0);
577                         }
578                         tty_flip_buffer_push(tty);
579                 }
580                 /* INT urbs are automatically re-submitted */
581                 return;
582         }
583         
584         /*
585          * The interrupt-in pipe signals exceptional conditions (modem line
586          * signal changes and errors). data[0] holds MSR, data[1] holds LSR.
587          */
588         priv->last_msr = data[MCT_U232_MSR_INDEX];
589         
590         /* Record Control Line states */
591         mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
592
593 #if 0
594         /* Not yet handled. See belin_sa.c for further information */
595         /* Now to report any errors */
596         priv->last_lsr = data[MCT_U232_LSR_INDEX];
597         /*
598          * fill in the flip buffer here, but I do not know the relation
599          * to the current/next receive buffer or characters.  I need
600          * to look in to this before committing any code.
601          */
602         if (priv->last_lsr & MCT_U232_LSR_ERR) {
603                 tty = port->tty;
604                 /* Overrun Error */
605                 if (priv->last_lsr & MCT_U232_LSR_OE) {
606                 }
607                 /* Parity Error */
608                 if (priv->last_lsr & MCT_U232_LSR_PE) {
609                 }
610                 /* Framing Error */
611                 if (priv->last_lsr & MCT_U232_LSR_FE) {
612                 }
613                 /* Break Indicator */
614                 if (priv->last_lsr & MCT_U232_LSR_BI) {
615                 }
616         }
617 #endif
618
619         /* INT urbs are automatically re-submitted */
620 } /* mct_u232_read_int_callback */
621
622
623 static void mct_u232_set_termios (struct usb_serial_port *port,
624                                   struct termios *old_termios)
625 {
626         struct usb_serial *serial = port->serial;
627         struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
628         unsigned int iflag = port->tty->termios->c_iflag;
629         unsigned int old_iflag = old_termios->c_iflag;
630         unsigned int cflag = port->tty->termios->c_cflag;
631         unsigned int old_cflag = old_termios->c_cflag;
632         
633         /*
634          * Update baud rate
635          */
636         if( (cflag & CBAUD) != (old_cflag & CBAUD) ) {
637                 /* reassert DTR and (maybe) RTS on transition from B0 */
638                 if( (old_cflag & CBAUD) == B0 ) {
639                         dbg(__FUNCTION__ ": baud was B0");
640                         priv->control_state |= TIOCM_DTR;
641                         /* don't set RTS if using hardware flow control */
642                         if (!(old_cflag & CRTSCTS)) {
643                                 priv->control_state |= TIOCM_RTS;
644                         }
645                         mct_u232_set_modem_ctrl(serial, priv->control_state);
646                 }
647                 
648                 switch(cflag & CBAUD) {
649                 case B0: /* handled below */
650                         break;
651                 case B300: mct_u232_set_baud_rate(serial, 300);
652                         break;
653                 case B600: mct_u232_set_baud_rate(serial, 600);
654                         break;
655                 case B1200: mct_u232_set_baud_rate(serial, 1200);
656                         break;
657                 case B2400: mct_u232_set_baud_rate(serial, 2400);
658                         break;
659                 case B4800: mct_u232_set_baud_rate(serial, 4800);
660                         break;
661                 case B9600: mct_u232_set_baud_rate(serial, 9600);
662                         break;
663                 case B19200: mct_u232_set_baud_rate(serial, 19200);
664                         break;
665                 case B38400: mct_u232_set_baud_rate(serial, 38400);
666                         break;
667                 case B57600: mct_u232_set_baud_rate(serial, 57600);
668                         break;
669                 case B115200: mct_u232_set_baud_rate(serial, 115200);
670                         break;
671                 default: err("MCT USB-RS232 converter: unsupported baudrate request, using default of 9600");
672                         mct_u232_set_baud_rate(serial, 9600); break;
673                 }
674                 if ((cflag & CBAUD) == B0 ) {
675                         dbg(__FUNCTION__ ": baud is B0");
676                         /* Drop RTS and DTR */
677                         priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
678                         mct_u232_set_modem_ctrl(serial, priv->control_state);
679                 }
680         }
681
682         /*
683          * Update line control register (LCR)
684          */
685         if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))
686             || (cflag & CSIZE) != (old_cflag & CSIZE)
687             || (cflag & CSTOPB) != (old_cflag & CSTOPB) ) {
688                 
689
690                 priv->last_lcr = 0;
691
692                 /* set the parity */
693                 if (cflag & PARENB)
694                         priv->last_lcr |= (cflag & PARODD) ?
695                                 MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN;
696                 else
697                         priv->last_lcr |= MCT_U232_PARITY_NONE;
698
699                 /* set the number of data bits */
700                 switch (cflag & CSIZE) {
701                 case CS5:
702                         priv->last_lcr |= MCT_U232_DATA_BITS_5; break;
703                 case CS6:
704                         priv->last_lcr |= MCT_U232_DATA_BITS_6; break;
705                 case CS7:
706                         priv->last_lcr |= MCT_U232_DATA_BITS_7; break;
707                 case CS8:
708                         priv->last_lcr |= MCT_U232_DATA_BITS_8; break;
709                 default:
710                         err("CSIZE was not CS5-CS8, using default of 8");
711                         priv->last_lcr |= MCT_U232_DATA_BITS_8;
712                         break;
713                 }
714
715                 /* set the number of stop bits */
716                 priv->last_lcr |= (cflag & CSTOPB) ?
717                         MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
718
719                 mct_u232_set_line_ctrl(serial, priv->last_lcr);
720         }
721         
722         /*
723          * Set flow control: well, I do not really now how to handle DTR/RTS.
724          * Just do what we have seen with SniffUSB on Win98.
725          */
726         if( (iflag & IXOFF) != (old_iflag & IXOFF)
727             || (iflag & IXON) != (old_iflag & IXON)
728             ||  (cflag & CRTSCTS) != (old_cflag & CRTSCTS) ) {
729                 
730                 /* Drop DTR/RTS if no flow control otherwise assert */
731                 if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS) )
732                         priv->control_state |= TIOCM_DTR | TIOCM_RTS;
733                 else
734                         priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
735                 mct_u232_set_modem_ctrl(serial, priv->control_state);
736         }
737 } /* mct_u232_set_termios */
738
739
740 static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
741 {
742         struct usb_serial *serial = port->serial;
743         struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
744         unsigned char lcr = priv->last_lcr;
745
746         dbg (__FUNCTION__ "state=%d", break_state);
747
748         if (break_state)
749                 lcr |= MCT_U232_SET_BREAK;
750
751         mct_u232_set_line_ctrl(serial, lcr);
752 } /* mct_u232_break_ctl */
753
754
755 static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
756                            unsigned int cmd, unsigned long arg)
757 {
758         struct usb_serial *serial = port->serial;
759         struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
760         int mask;
761         
762         dbg (__FUNCTION__ "cmd=0x%x", cmd);
763
764         /* Based on code from acm.c and others */
765         switch (cmd) {
766         case TIOCMGET:
767                 return put_user(priv->control_state, (unsigned long *) arg);
768                 break;
769
770         case TIOCMSET: /* Turns on and off the lines as specified by the mask */
771         case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */
772         case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */
773                 if (get_user(mask, (unsigned long *) arg))
774                         return -EFAULT;
775
776                 if ((cmd == TIOCMSET) || (mask & TIOCM_RTS)) {
777                         /* RTS needs set */
778                         if( ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) ||
779                             (cmd == TIOCMBIS) )
780                                 priv->control_state |=  TIOCM_RTS;
781                         else
782                                 priv->control_state &= ~TIOCM_RTS;
783                 }
784
785                 if ((cmd == TIOCMSET) || (mask & TIOCM_DTR)) {
786                         /* DTR needs set */
787                         if( ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) ||
788                             (cmd == TIOCMBIS) )
789                                 priv->control_state |=  TIOCM_DTR;
790                         else
791                                 priv->control_state &= ~TIOCM_DTR;
792                 }
793                 mct_u232_set_modem_ctrl(serial, priv->control_state);
794                 break;
795                                         
796         case TIOCMIWAIT:
797                 /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
798                 /* TODO */
799                 return( 0 );
800
801         case TIOCGICOUNT:
802                 /* return count of modemline transitions */
803                 /* TODO */
804                 return 0;
805
806         default:
807                 dbg(__FUNCTION__ ": arg not supported - 0x%04x",cmd);
808                 return(-ENOIOCTLCMD);
809                 break;
810         }
811         return 0;
812 } /* mct_u232_ioctl */
813
814
815 static int __init mct_u232_init (void)
816 {
817         usb_serial_register (&mct_u232_device);
818         info(DRIVER_DESC " " DRIVER_VERSION);
819         return 0;
820 }
821
822
823 static void __exit mct_u232_exit (void)
824 {
825         usb_serial_deregister (&mct_u232_device);
826 }
827
828
829 module_init (mct_u232_init);
830 module_exit(mct_u232_exit);
831
832 MODULE_AUTHOR( DRIVER_AUTHOR );
833 MODULE_DESCRIPTION( DRIVER_DESC );
834 MODULE_LICENSE("GPL");
835
836 #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
837 MODULE_PARM(write_blocking, "i");
838 MODULE_PARM_DESC(write_blocking, 
839                  "The write function will block to write out all data");
840 #endif
841
842 MODULE_PARM(debug, "i");
843 MODULE_PARM_DESC(debug, "Debug enabled or not");
844