- Alan Cox: synch. PA-RISC arch and bitops cleanups
[davej-history.git] / drivers / usb / serial / ftdi_sio.c
blobc52ad0b37200d358668a877eb0947b4fad44e05a
1 /*
2 * USB FTDI SIO driver
4 * Copyright (C) 1999, 2000
5 * Greg Kroah-Hartman (greg@kroah.com)
6 * Bill Ryder (bryder@sgi.com)
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * See Documentation/usb/usb-serial.txt for more information on using this driver
15 * See http://reality.sgi.com/bryder_wellington/ftdi_sio for upto date testing info
16 * and extra documentation
18 * (12/3/2000) Bill Ryder
19 * Added support for 8U232AM device.
20 * Moved PID and VIDs into header file only.
21 * Turned on low-latency for the tty (device will do high baudrates)
22 * Added shutdown routine to close files when device removed.
23 * More debug and error message cleanups.
26 * (11/13/2000) Bill Ryder
27 * Added spinlock protected open code and close code.
28 * Multiple opens work (sort of - see webpage mentioned above).
29 * Cleaned up comments. Removed multiple PID/VID definitions.
30 * Factorised cts/dtr code
31 * Made use of __FUNCTION__ in dbg's
33 * (11/01/2000) Adam J. Richter
34 * usb_device_id table support
36 * (10/05/2000) gkh
37 * Fixed bug with urb->dev not being set properly, now that the usb
38 * core needs it.
40 * (09/11/2000) gkh
41 * Removed DEBUG #ifdefs with call to usb_serial_debug_data
43 * (07/19/2000) gkh
44 * Added module_init and module_exit functions to handle the fact that this
45 * driver is a loadable module now.
47 * (04/04/2000) Bill Ryder
48 * Fixed bugs in TCGET/TCSET ioctls (by removing them - they are
49 * handled elsewhere in the tty io driver chain).
51 * (03/30/2000) Bill Ryder
52 * Implemented lots of ioctls
53 * Fixed a race condition in write
54 * Changed some dbg's to errs
56 * (03/26/2000) gkh
57 * Split driver up into device specific pieces.
61 /* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */
62 /* Thanx to FTDI for so kindly providing details of the protocol required */
63 /* to talk to the device */
64 /* Thanx to gkh and the rest of the usb dev group for all code I have assimilated :-) */
67 #include <linux/config.h>
68 #include <linux/kernel.h>
69 #include <linux/sched.h>
70 #include <linux/signal.h>
71 #include <linux/errno.h>
72 #include <linux/poll.h>
73 #include <linux/init.h>
74 #include <linux/malloc.h>
75 #include <linux/fcntl.h>
76 #include <linux/tty_driver.h>
77 #include <linux/tty_flip.h>
78 #include <linux/tty.h>
79 #include <linux/module.h>
80 #include <linux/spinlock.h>
82 #ifdef CONFIG_USB_SERIAL_DEBUG
83 #define DEBUG
84 #else
85 #undef DEBUG
86 #endif
87 #include <linux/usb.h>
89 #include "usb-serial.h"
91 #include "ftdi_sio.h"
94 static __devinitdata struct usb_device_id id_table_sio [] = {
95 { idVendor: FTDI_VID, idProduct: FTDI_SIO_PID },
96 { } /* Terminating entry */
99 /* THe 8U232AM has the same API as the sio - but it can support MUCH
100 higher baudrates (921600 at 48MHz/230400 at 12MHz
101 so .. it's baudrate setting codes are different */
104 static __devinitdata struct usb_device_id id_table_8U232AM [] = {
105 { idVendor: FTDI_VID, idProduct: FTDI_8U232AM_PID },
106 { } /* Terminating entry */
110 static __devinitdata struct usb_device_id id_table_combined [] = {
111 { idVendor: FTDI_VID, idProduct: FTDI_SIO_PID },
112 { idVendor: FTDI_VID, idProduct: FTDI_8U232AM_PID },
113 { } /* Terminating entry */
116 MODULE_DEVICE_TABLE (usb, id_table_combined);
119 struct ftdi_private {
120 ftdi_type_t ftdi_type;
121 char last_status_byte; /* device sends this every 40ms when open */
125 /* function prototypes for a FTDI serial converter */
126 static int ftdi_sio_startup (struct usb_serial *serial);
127 static int ftdi_8U232AM_startup (struct usb_serial *serial);
128 static void ftdi_sio_shutdown (struct usb_serial *serial);
129 static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp);
130 static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp);
131 static int ftdi_sio_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
132 static void ftdi_sio_write_bulk_callback (struct urb *urb);
133 static void ftdi_sio_read_bulk_callback (struct urb *urb);
134 static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios * old);
135 static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
137 /* Should rename most ftdi_sio's to ftdi_ now since there are two devices
138 which share common code */
140 struct usb_serial_device_type ftdi_sio_device = {
141 name: "FTDI SIO",
142 id_table: id_table_sio,
143 needs_interrupt_in: MUST_HAVE_NOT,
144 needs_bulk_in: MUST_HAVE,
145 needs_bulk_out: MUST_HAVE,
146 num_interrupt_in: 0,
147 num_bulk_in: 1,
148 num_bulk_out: 1,
149 num_ports: 1,
150 open: ftdi_sio_open,
151 close: ftdi_sio_close,
152 write: ftdi_sio_write,
153 read_bulk_callback: ftdi_sio_read_bulk_callback,
154 write_bulk_callback: ftdi_sio_write_bulk_callback,
155 ioctl: ftdi_sio_ioctl,
156 set_termios: ftdi_sio_set_termios,
157 startup: ftdi_sio_startup,
158 shutdown: ftdi_sio_shutdown,
161 struct usb_serial_device_type ftdi_8U232AM_device = {
162 name: "FTDI 8U232AM",
163 id_table: id_table_8U232AM,
164 needs_interrupt_in: DONT_CARE,
165 needs_bulk_in: MUST_HAVE,
166 needs_bulk_out: MUST_HAVE,
167 num_interrupt_in: 0,
168 num_bulk_in: 1,
169 num_bulk_out: 1,
170 num_ports: 1,
171 open: ftdi_sio_open,
172 close: ftdi_sio_close,
173 write: ftdi_sio_write,
174 read_bulk_callback: ftdi_sio_read_bulk_callback,
175 write_bulk_callback: ftdi_sio_write_bulk_callback,
176 ioctl: ftdi_sio_ioctl,
177 set_termios: ftdi_sio_set_termios,
178 startup: ftdi_8U232AM_startup,
179 shutdown: ftdi_sio_shutdown,
184 * ***************************************************************************
185 * FTDI SIO Serial Converter specific driver functions
186 * ***************************************************************************
189 #define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
191 /* utility functions to set and unset dtr and rts */
192 #define HIGH 1
193 #define LOW 0
194 static int set_rts(struct usb_device *dev,
195 unsigned int pipe,
196 int high_or_low)
198 static char buf[1];
199 unsigned ftdi_high_or_low = (high_or_low? FTDI_SIO_SET_RTS_HIGH :
200 FTDI_SIO_SET_RTS_LOW);
201 return(usb_control_msg(dev, pipe,
202 FTDI_SIO_SET_MODEM_CTRL_REQUEST,
203 FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
204 ftdi_high_or_low, 0,
205 buf, 0, WDR_TIMEOUT));
207 static int set_dtr(struct usb_device *dev,
208 unsigned int pipe,
209 int high_or_low)
211 static char buf[1];
212 unsigned ftdi_high_or_low = (high_or_low? FTDI_SIO_SET_DTR_HIGH :
213 FTDI_SIO_SET_DTR_LOW);
214 return(usb_control_msg(dev, pipe,
215 FTDI_SIO_SET_MODEM_CTRL_REQUEST,
216 FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
217 ftdi_high_or_low, 0,
218 buf, 0, WDR_TIMEOUT));
223 static int ftdi_sio_startup (struct usb_serial *serial)
225 struct ftdi_private *priv;
227 init_waitqueue_head(&serial->port[0].write_wait);
229 priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL);
230 if (!priv){
231 err(__FUNCTION__"- kmalloc(%d) failed.", sizeof(struct ftdi_private));
232 return -ENOMEM;
235 priv->ftdi_type = sio;
237 return (0);
241 static int ftdi_8U232AM_startup (struct usb_serial *serial)
243 struct ftdi_private *priv;
245 init_waitqueue_head(&serial->port[0].write_wait);
247 priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL);
248 if (!priv){
249 err(__FUNCTION__"- kmalloc(%d) failed.", sizeof(struct ftdi_private));
250 return -ENOMEM;
253 priv->ftdi_type = F8U232AM;
255 return (0);
258 static void ftdi_sio_shutdown (struct usb_serial *serial)
261 dbg (__FUNCTION__);
263 /* Close ports if they are open */
264 while (serial->port[0].open_count > 0) {
265 ftdi_sio_close (&serial->port[0], NULL);
267 if (serial->port->private){
268 kfree(serial->port->private);
269 serial->port->private = NULL;
275 static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp)
276 { /* ftdi_sio_open */
277 struct termios tmp_termios;
278 struct usb_serial *serial = port->serial;
279 unsigned long flags; /* Used for spinlock */
280 int result;
281 char buf[1]; /* Needed for the usb_control_msg I think */
283 dbg(__FUNCTION__);
285 spin_lock_irqsave (&port->port_lock, flags);
287 MOD_INC_USE_COUNT;
288 ++port->open_count;
290 if (!port->active){
291 port->active = 1;
293 spin_unlock_irqrestore (&port->port_lock, flags);
295 /* do not allow a task to be queued to deliver received data */
296 port->tty->low_latency = 1;
298 /* No error checking for this (will get errors later anyway) */
299 /* See ftdi_sio.h for description of what is reset */
300 usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
301 FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE,
302 FTDI_SIO_RESET_SIO,
303 0, buf, 0, WDR_TIMEOUT);
305 /* Setup termios defaults. According to tty_io.c the
306 settings are driver specific */
307 port->tty->termios->c_cflag =
308 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
310 /* ftdi_sio_set_termios will send usb control messages */
311 ftdi_sio_set_termios(port, &tmp_termios);
313 /* Turn on RTS and DTR since we are not flow controlling by default */
314 if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),HIGH) < 0) {
315 err(__FUNCTION__ " Error from DTR HIGH urb");
317 if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),HIGH) < 0){
318 err(__FUNCTION__ " Error from RTS HIGH urb");
321 /* Start reading from the device */
322 FILL_BULK_URB(port->read_urb, serial->dev,
323 usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
324 port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
325 ftdi_sio_read_bulk_callback, port);
326 result = usb_submit_urb(port->read_urb);
327 if (result)
328 err(__FUNCTION__ " - failed submitting read urb, error %d", result);
329 } else { /* the port was already active - so no initialisation is done */
330 spin_unlock_irqrestore (&port->port_lock, flags);
333 return (0);
334 } /* ftdi_sio_open */
337 static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp)
338 { /* ftdi_sio_close */
339 struct usb_serial *serial = port->serial;
340 unsigned int c_cflag = port->tty->termios->c_cflag;
341 char buf[1];
342 unsigned long flags;
344 dbg( __FUNCTION__);
346 spin_lock_irqsave (&port->port_lock, flags);
347 --port->open_count;
349 if (port->open_count <= 0) {
350 spin_unlock_irqrestore (&port->port_lock, flags);
351 if (c_cflag & HUPCL){
352 /* Disable flow control */
353 if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
354 FTDI_SIO_SET_FLOW_CTRL_REQUEST,
355 FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
356 0, 0,
357 buf, 0, WDR_TIMEOUT) < 0) {
358 err("error from flowcontrol urb");
361 /* drop DTR */
362 if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0), LOW) < 0){
363 err("Error from DTR LOW urb");
365 /* drop RTS */
366 if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0) {
367 err("Error from RTS LOW urb");
369 } /* Note change no line is hupcl is off */
371 /* shutdown our bulk reads and writes */
372 usb_unlink_urb (port->write_urb);
373 usb_unlink_urb (port->read_urb);
374 port->active = 0;
375 port->open_count = 0;
376 } else {
377 spin_unlock_irqrestore (&port->port_lock, flags);
379 /* Send a HUP if necessary */
380 if (!(port->tty->termios->c_cflag & CLOCAL)){
381 tty_hangup(port->tty);
386 MOD_DEC_USE_COUNT;
388 } /* ftdi_sio_close */
392 /* The ftdi_sio requires the first byte to have:
393 * B0 1
394 * B1 0
395 * B2..7 length of message excluding byte 0
397 static int ftdi_sio_write (struct usb_serial_port *port, int from_user,
398 const unsigned char *buf, int count)
399 { /* ftdi_sio_write */
400 struct usb_serial *serial = port->serial;
401 struct ftdi_private *priv = (struct ftdi_private *)port->private;
402 int data_offset ;
403 int rc;
404 int result;
405 DECLARE_WAITQUEUE(wait, current);
407 dbg(__FUNCTION__ " port %d, %d bytes", port->number, count);
409 if (count == 0) {
410 err("write request of 0 bytes");
411 return 0;
414 if (priv->ftdi_type == sio){
415 data_offset = 1;
416 } else {
417 data_offset = 0;
419 dbg("data_offset set to %d",data_offset);
421 /* only do something if we have a bulk out endpoint */
422 if (serial->num_bulk_out) {
423 unsigned char *first_byte = port->write_urb->transfer_buffer;
425 /* Was seeing a race here, got a read callback, then write callback before
426 hitting interuptible_sleep_on - so wrapping in a wait_queue */
428 add_wait_queue(&port->write_wait, &wait);
429 set_current_state (TASK_INTERRUPTIBLE);
430 while (port->write_urb->status == -EINPROGRESS) {
431 dbg(__FUNCTION__ " write in progress - retrying");
432 if (signal_pending(current)) {
433 current->state = TASK_RUNNING;
434 remove_wait_queue(&port->write_wait, &wait);
435 rc = -ERESTARTSYS;
436 goto err;
438 schedule();
440 remove_wait_queue(&port->write_wait, &wait);
441 set_current_state(TASK_RUNNING);
443 count += data_offset;
444 count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
445 if (count == 0) {
446 return 0;
449 /* Copy in the data to send */
450 if (from_user) {
451 copy_from_user(port->write_urb->transfer_buffer + data_offset ,
452 buf, count - data_offset );
454 else {
455 memcpy(port->write_urb->transfer_buffer + data_offset,
456 buf, count - data_offset );
459 first_byte = port->write_urb->transfer_buffer;
460 if (data_offset > 0){
461 /* Write the control byte at the front of the packet*/
462 *first_byte = 1 | ((count-data_offset) << 2) ;
465 dbg(__FUNCTION__ " Bytes: %d, First Byte: 0o%03o",count, first_byte[0]);
466 usb_serial_debug_data (__FILE__, __FUNCTION__, count, first_byte);
468 /* send the data out the bulk port */
469 FILL_BULK_URB(port->write_urb, serial->dev,
470 usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
471 port->write_urb->transfer_buffer, count,
472 ftdi_sio_write_bulk_callback, port);
474 result = usb_submit_urb(port->write_urb);
475 if (result) {
476 err(__FUNCTION__ " - failed submitting write urb, error %d", result);
477 return 0;
480 dbg(__FUNCTION__ " write returning: %d", count - data_offset);
481 return (count - data_offset);
484 /* no bulk out, so return 0 bytes written */
485 return 0;
486 err: /* error exit */
487 return(rc);
488 } /* ftdi_sio_write */
490 static void ftdi_sio_write_bulk_callback (struct urb *urb)
492 struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
493 struct usb_serial *serial;
494 struct tty_struct *tty = port->tty;
496 dbg("ftdi_sio_write_bulk_callback");
498 if (port_paranoia_check (port, "ftdi_sio_write_bulk_callback")) {
499 return;
502 serial = port->serial;
503 if (serial_paranoia_check (serial, "ftdi_sio_write_bulk_callback")) {
504 return;
507 if (urb->status) {
508 dbg("nonzero write bulk status received: %d", urb->status);
509 return;
512 wake_up_interruptible(&port->write_wait);
513 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
514 (tty->ldisc.write_wakeup)(tty);
516 wake_up_interruptible(&tty->write_wait);
518 return;
519 } /* ftdi_sio_write_bulk_callback */
521 static void ftdi_sio_read_bulk_callback (struct urb *urb)
522 { /* ftdi_sio_serial_buld_callback */
523 struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
524 struct ftdi_private *priv = (struct ftdi_private *)port->private;
525 struct usb_serial *serial;
526 struct tty_struct *tty = port->tty ;
527 unsigned char *data = urb->transfer_buffer;
529 const int data_offset = 2;
530 int i;
531 int result;
533 dbg(__FUNCTION__);
535 if (port_paranoia_check (port, "ftdi_sio_read_bulk_callback")) {
536 return;
539 serial = port->serial;
540 if (serial_paranoia_check (serial, "ftdi_sio_read_bulk_callback")) {
541 return;
544 if (urb->status) {
545 /* This will happen at close every time so it is a dbg not an err */
546 dbg("nonzero read bulk status received: %d", urb->status);
547 return;
550 if (urb->actual_length > 2) {
551 usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
552 } else {
553 dbg("Just status");
556 priv->last_status_byte = data[0]; /* this has modem control lines */
558 /* TO DO -- check for hung up line and handle appropriately: */
559 /* send hangup */
560 /* See acm.c - you do a tty_hangup - eg tty_hangup(tty) */
561 /* if CD is dropped and the line is not CLOCAL then we should hangup */
564 if (urb->actual_length > data_offset) {
565 for (i = data_offset ; i < urb->actual_length ; ++i) {
566 tty_insert_flip_char(tty, data[i], 0);
568 tty_flip_buffer_push(tty);
571 /* Continue trying to always read */
572 FILL_BULK_URB(urb, serial->dev,
573 usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
574 urb->transfer_buffer, urb->transfer_buffer_length,
575 ftdi_sio_read_bulk_callback, port);
577 result = usb_submit_urb(urb);
578 if (result)
579 err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
581 return;
582 } /* ftdi_sio_serial_read_bulk_callback */
585 __u16 translate_baudrate_to_ftdi(unsigned int cflag, ftdi_type_t ftdi_type)
586 { /* translate_baudrate_to_ftdi */
588 __u16 urb_value = ftdi_sio_b9600;
590 if (ftdi_type == sio){
591 switch(cflag & CBAUD){
592 case B0: break; /* ignored by this */
593 case B300: urb_value = ftdi_sio_b300; dbg("Set to 300"); break;
594 case B600: urb_value = ftdi_sio_b600; dbg("Set to 600") ; break;
595 case B1200: urb_value = ftdi_sio_b1200; dbg("Set to 1200") ; break;
596 case B2400: urb_value = ftdi_sio_b2400; dbg("Set to 2400") ; break;
597 case B4800: urb_value = ftdi_sio_b4800; dbg("Set to 4800") ; break;
598 case B9600: urb_value = ftdi_sio_b9600; dbg("Set to 9600") ; break;
599 case B19200: urb_value = ftdi_sio_b19200; dbg("Set to 19200") ; break;
600 case B38400: urb_value = ftdi_sio_b38400; dbg("Set to 38400") ; break;
601 case B57600: urb_value = ftdi_sio_b57600; dbg("Set to 57600") ; break;
602 case B115200: urb_value = ftdi_sio_b115200; dbg("Set to 115200") ; break;
603 default: dbg(__FUNCTION__ " FTDI_SIO does not support the baudrate (%d) requested",
604 (cflag & CBAUD));
605 break;
607 } else { /* it is 8U232AM */
608 switch(cflag & CBAUD){
609 case B0: break; /* ignored by this */
610 case B300: urb_value = ftdi_8U232AM_48MHz_b300; dbg("Set to 300"); break;
611 case B600: urb_value = ftdi_8U232AM_48MHz_b600; dbg("Set to 600") ; break;
612 case B1200: urb_value = ftdi_8U232AM_48MHz_b1200; dbg("Set to 1200") ; break;
613 case B2400: urb_value = ftdi_8U232AM_48MHz_b2400; dbg("Set to 2400") ; break;
614 case B4800: urb_value = ftdi_8U232AM_48MHz_b4800; dbg("Set to 4800") ; break;
615 case B9600: urb_value = ftdi_8U232AM_48MHz_b9600; dbg("Set to 9600") ; break;
616 case B19200: urb_value = ftdi_8U232AM_48MHz_b19200; dbg("Set to 19200") ; break;
617 case B38400: urb_value = ftdi_8U232AM_48MHz_b38400; dbg("Set to 38400") ; break;
618 case B57600: urb_value = ftdi_8U232AM_48MHz_b57600; dbg("Set to 57600") ; break;
619 case B115200: urb_value = ftdi_8U232AM_48MHz_b115200; dbg("Set to 115200") ; break;
620 case B230400: urb_value = ftdi_8U232AM_48MHz_b230400; dbg("Set to 230400") ; break;
621 case B460800: urb_value = ftdi_8U232AM_48MHz_b460800; dbg("Set to 460800") ; break;
622 case B921600: urb_value = ftdi_8U232AM_48MHz_b921600; dbg("Set to 921600") ; break;
623 default: dbg(__FUNCTION__ " The baudrate (%d) requested is not implemented",
624 (cflag & CBAUD));
625 break;
628 return(urb_value);
631 /* As I understand this - old_termios contains the original termios settings */
632 /* and tty->termios contains the new setting to be used */
633 /* */
634 /* WARNING: set_termios calls this with old_termios in kernel space */
636 static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios *old_termios)
637 { /* ftdi_sio_set_termios */
638 struct usb_serial *serial = port->serial;
639 unsigned int cflag = port->tty->termios->c_cflag;
640 struct ftdi_private *priv = (struct ftdi_private *)port->private;
641 __u16 urb_value; /* will hold the new flags */
642 char buf[1]; /* Perhaps I should dynamically alloc this? */
645 dbg(__FUNCTION__);
648 /* FIXME -For this cut I don't care if the line is really changing or
649 not - so just do the change regardless - should be able to
650 compare old_termios and tty->termios */
651 /* NOTE These routines can get interrupted by
652 ftdi_sio_read_bulk_callback - need to examine what this
653 means - don't see any problems yet */
655 /* Set number of data bits, parity, stop bits */
657 urb_value = 0;
658 urb_value |= (cflag & CSTOPB ? FTDI_SIO_SET_DATA_STOP_BITS_2 :
659 FTDI_SIO_SET_DATA_STOP_BITS_1);
660 urb_value |= (cflag & PARENB ?
661 (cflag & PARODD ? FTDI_SIO_SET_DATA_PARITY_ODD :
662 FTDI_SIO_SET_DATA_PARITY_EVEN) :
663 FTDI_SIO_SET_DATA_PARITY_NONE);
664 if (cflag & CSIZE) {
665 switch (cflag & CSIZE) {
666 case CS5: urb_value |= 5; dbg("Setting CS5"); break;
667 case CS6: urb_value |= 6; dbg("Setting CS6"); break;
668 case CS7: urb_value |= 7; dbg("Setting CS7"); break;
669 case CS8: urb_value |= 8; dbg("Setting CS8"); break;
670 default:
671 err("CSIZE was set but not CS5-CS8");
674 if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
675 FTDI_SIO_SET_DATA_REQUEST,
676 FTDI_SIO_SET_DATA_REQUEST_TYPE,
677 urb_value , 0,
678 buf, 0, 100) < 0) {
679 err(__FUNCTION__ " FAILED to set databits/stopbits/parity");
682 /* Now do the baudrate */
683 urb_value = translate_baudrate_to_ftdi((cflag & CBAUD), priv->ftdi_type);
685 if ((cflag & CBAUD) == B0 ) {
686 /* Disable flow control */
687 if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
688 FTDI_SIO_SET_FLOW_CTRL_REQUEST,
689 FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
690 0, 0,
691 buf, 0, WDR_TIMEOUT) < 0) {
692 err(__FUNCTION__ " error from disable flowcontrol urb");
694 /* Drop RTS and DTR */
695 if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0){
696 err(__FUNCTION__ " Error from DTR LOW urb");
698 if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0){
699 err(__FUNCTION__ " Error from RTS LOW urb");
702 } else {
703 /* set the baudrate determined before */
704 if (usb_control_msg(serial->dev,
705 usb_sndctrlpipe(serial->dev, 0),
706 FTDI_SIO_SET_BAUDRATE_REQUEST,
707 FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE,
708 urb_value, 0,
709 buf, 0, 100) < 0) {
710 err(__FUNCTION__ " urb failed to set baurdrate");
713 /* Set flow control */
714 /* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */
715 if (cflag & CRTSCTS) {
716 dbg(__FUNCTION__ " Setting to CRTSCTS flow control");
717 if (usb_control_msg(serial->dev,
718 usb_sndctrlpipe(serial->dev, 0),
719 FTDI_SIO_SET_FLOW_CTRL_REQUEST,
720 FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
721 0 , FTDI_SIO_RTS_CTS_HS,
722 buf, 0, WDR_TIMEOUT) < 0) {
723 err("urb failed to set to rts/cts flow control");
726 } else {
727 /* CHECKME Assuming XON/XOFF handled by tty stack - not by device */
728 dbg(__FUNCTION__ " Turning off hardware flow control");
729 if (usb_control_msg(serial->dev,
730 usb_sndctrlpipe(serial->dev, 0),
731 FTDI_SIO_SET_FLOW_CTRL_REQUEST,
732 FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
733 0, 0,
734 buf, 0, WDR_TIMEOUT) < 0) {
735 err("urb failed to clear flow control");
739 return;
740 } /* ftdi_sio_set_termios */
742 static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
744 struct usb_serial *serial = port->serial;
745 struct ftdi_private *priv = (struct ftdi_private *)port->private;
746 __u16 urb_value=0; /* Will hold the new flags */
747 char buf[1];
748 int ret, mask;
750 dbg(__FUNCTION__ " cmd 0x%04x", cmd);
752 /* Based on code from acm.c and others */
753 switch (cmd) {
755 case TIOCMGET:
756 dbg(__FUNCTION__ " TIOCMGET");
757 /* The MODEM_STATUS_REQUEST works for the sio but not the 232 */
758 if (priv->ftdi_type == sio){
759 /* TO DECIDE - use the 40ms status packets or not? */
760 /* PRO: No need to send urb */
761 /* CON: Could be 40ms out of date */
763 /* Request the status from the device */
764 if ((ret = usb_control_msg(serial->dev,
765 usb_rcvctrlpipe(serial->dev, 0),
766 FTDI_SIO_GET_MODEM_STATUS_REQUEST,
767 FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
768 0, 0,
769 buf, 1, WDR_TIMEOUT)) < 0 ) {
770 err(__FUNCTION__ " Could not get modem status of device - err: %d",
771 ret);
772 return(ret);
774 } else {
775 /* This gets updated every 40ms - so just copy it in */
776 buf[0] = priv->last_status_byte;
779 return put_user((buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
780 (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
781 (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) |
782 (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0),
783 (unsigned long *) arg);
784 break;
786 case TIOCMSET: /* Turns on and off the lines as specified by the mask */
787 dbg(__FUNCTION__ " TIOCMSET");
788 if ((ret = get_user(mask, (unsigned long *) arg))) return ret;
789 urb_value = ((mask & TIOCM_DTR) ? HIGH : LOW);
790 if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),urb_value) < 0){
791 err("Error from DTR set urb (TIOCMSET)");
793 urb_value = ((mask & TIOCM_RTS) ? HIGH : LOW);
794 if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),urb_value) < 0){
795 err("Error from RTS set urb (TIOCMSET)");
797 break;
799 case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */
800 dbg(__FUNCTION__ " TIOCMBIS");
801 if ((ret = get_user(mask, (unsigned long *) arg))) return ret;
802 if (mask & TIOCM_DTR){
803 if ((ret = set_dtr(serial->dev,
804 usb_sndctrlpipe(serial->dev, 0),
805 HIGH)) < 0) {
806 err("Urb to set DTR failed");
807 return(ret);
810 if (mask & TIOCM_RTS) {
811 if ((ret = set_rts(serial->dev,
812 usb_sndctrlpipe(serial->dev, 0),
813 HIGH)) < 0){
814 err("Urb to set RTS failed");
815 return(ret);
818 break;
820 case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */
821 dbg(__FUNCTION__ " TIOCMBIC");
822 if ((ret = get_user(mask, (unsigned long *) arg))) return ret;
823 if (mask & TIOCM_DTR){
824 if ((ret = set_dtr(serial->dev,
825 usb_sndctrlpipe(serial->dev, 0),
826 LOW)) < 0){
827 err("Urb to unset DTR failed");
828 return(ret);
831 if (mask & TIOCM_RTS) {
832 if ((ret = set_rts(serial->dev,
833 usb_sndctrlpipe(serial->dev, 0),
834 LOW)) < 0){
835 err("Urb to unset RTS failed");
836 return(ret);
839 break;
842 * I had originally implemented TCSET{A,S}{,F,W} and
843 * TCGET{A,S} here separately, however when testing I
844 * found that the higher layers actually do the termios
845 * conversions themselves and pass the call onto
846 * ftdi_sio_set_termios.
850 default:
851 /* This is not an error - turns out the higher layers will do
852 * some ioctls itself (see comment above)
854 dbg(__FUNCTION__ " arg not supported - it was 0x%04x",cmd);
855 return(-ENOIOCTLCMD);
856 break;
858 return 0;
859 } /* ftdi_sio_ioctl */
862 static int __init ftdi_sio_init (void)
864 dbg(__FUNCTION__);
865 usb_serial_register (&ftdi_sio_device);
866 usb_serial_register (&ftdi_8U232AM_device);
867 return 0;
871 static void __exit ftdi_sio_exit (void)
873 dbg(__FUNCTION__);
874 usb_serial_deregister (&ftdi_sio_device);
875 usb_serial_deregister (&ftdi_8U232AM_device);
879 module_init(ftdi_sio_init);
880 module_exit(ftdi_sio_exit);
882 MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>");
883 MODULE_DESCRIPTION("USB FTDI RS232 converters driver");