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