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