This is patch 3 which will apply against 2.4.21-pre5 with the ftdi_sio patch 2 applied. (as an aside patch1 was the reject one with lots of new ioctls).
This patch now allows the device to operate very close to buadrate (I get around baudrate at 921600 with a BM device). Richard Shooter who implemented the read speed change gets 1Mb/s at 1.5MBaud).
John Wilkins fixed Xon/Xoff and added a vid/pid for the videonetworks/homechoice device.
The device driver now has full soft and hard flow control, high speed and seems pretty stable (I test with four different ftdi devices attached through a hub and have no problems).
I have one more very interesting patch from Wayne Wylupski which allows command line setting of vid/pid but I haven't tried it out yet hence haven't submitted it.
---- Bill
diff -rauX ../dontdiff new/drivers/usb/serial/ftdi_sio.c patch_3/drivers/usb/serial/ftdi_sio.c --- new/drivers/usb/serial/ftdi_sio.c 2003-03-26 23:32:44.000000000 +1200 +++ patch_3/drivers/usb/serial/ftdi_sio.c 2003-03-26 23:47:39.000000000 +1200 @@ -17,6 +17,14 @@ * See http://ftdi-usb-sio.sourceforge.net for upto date testing info * and extra documentation * + * (24/Feb/2003) Richard Shooter + * Increase read buffer size to improve read speeds at higher baud rates + * (specifically tested with up to 1Mb/sec at 1.5M baud) + * + * (23/Feb/2003) John Wilkins + * Added Xon/xoff flow control (activating support in the ftdi device) + * Added vid/pid for Videonetworks/Homechoice (UK ISP) + * * (23/Feb/2003) Bill Ryder * Added matrix orb device vid/pids from Wayne Wylupski * @@ -175,7 +183,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.3.2" +#define DRIVER_VERSION "v1.3.3" #define DRIVER_AUTHOR "Greg Kroah-Hartman <[EMAIL PROTECTED]>, Bill Ryder <[EMAIL PROTECTED]>, Kuba Ober <[EMAIL PROTECTED]>" #define DRIVER_DESC "USB FTDI Serial Converters Driver" @@ -206,6 +214,7 @@ { USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_VNHCPCUSB_D_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_1_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_2_PID, 0, 0x3ff) }, @@ -222,6 +231,7 @@ { USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_VNHCPCUSB_D_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_1_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_2_PID, 0x400, 0xffff) }, @@ -240,6 +250,7 @@ { USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) }, { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) }, { USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_VNHCPCUSB_D_PID) }, { USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID) }, { USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_1_PID) }, { USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_2_PID) }, @@ -883,6 +894,17 @@ /* Make sure write_urb is initialised since a write_pool is used now */ port->write_urb = NULL; /* prevents usbserial.c from trying something silly */ +// Read speed increase - start + /* increase the size of read buffers */ +#define BUFSZ 512 + if( port->bulk_in_buffer != NULL) + { + kfree(port->bulk_in_buffer); + port->bulk_in_buffer = kmalloc( BUFSZ, GFP_KERNEL); + port->read_urb->transfer_buffer = port->bulk_in_buffer; + port->read_urb->transfer_buffer_length = BUFSZ; + } +// Read speed increase --end /* Start reading from the device */ FILL_BULK_URB(port->read_urb, serial->dev, @@ -1183,6 +1205,15 @@ int i; int result; + int packet_offset; +#define PKTSZ 64 + if( urb->number_of_packets > 0 ) + { + err("%s transfer_buffer_length %d actual_length %d number of packets %d",__FUNCTION__, + urb->transfer_buffer_length, urb->actual_length, urb->number_of_packets ); + err("%s transfer_flags %x USB_QUEUE_BULK %x ", __FUNCTION__,urb->transfer_flags, USB_QUEUE_BULK ); + } + dbg("%s", __FUNCTION__); if (port_paranoia_check (port, __FUNCTION__)) { @@ -1221,9 +1252,12 @@ /* See acm.c - you do a tty_hangup - eg tty_hangup(tty) */ /* if CD is dropped and the line is not CLOCAL then we should hangup */ + for(packet_offset=0; packet_offset < urb->actual_length; packet_offset += PKTSZ ) + { + /* Compare new line status to the old one, signal if different */ if (priv != NULL) { - char new_status = data[0] & FTDI_STATUS_B0_MASK; + char new_status = data[packet_offset+0] & FTDI_STATUS_B0_MASK; if (new_status != priv->prev_status) { priv->diff_status |= new_status ^ priv->prev_status; wake_up_interruptible(&priv->delta_msr_wait); @@ -1237,25 +1271,27 @@ /* errors on a packet - the order here sets the priority the */ /* error is returned to the tty layer */ - if ( data[1] & FTDI_RS_OE ) { + if ( data[packet_offset+1] & FTDI_RS_OE ) { error_flag = TTY_OVERRUN; dbg("OVERRRUN error"); } - if ( data[1] & FTDI_RS_BI ) { + if ( data[packet_offset+1] & FTDI_RS_BI ) { error_flag = TTY_BREAK; dbg("BREAK received"); } - if ( data[1] & FTDI_RS_PE ) { + if ( data[packet_offset+1] & FTDI_RS_PE ) { error_flag = TTY_PARITY; dbg("PARITY error"); } - if ( data[1] & FTDI_RS_FE ) { + if ( data[packet_offset+1] & FTDI_RS_FE ) { error_flag = TTY_FRAME; dbg("FRAMING error"); } if (urb->actual_length > data_offset) { - for (i = data_offset ; i < urb->actual_length ; ++i) { + /* CHECKME - Does this have any side affects for devices that dont have */ + /* two status bytes at the start of each packet ? */ + for (i = data_offset ; (i < PKTSZ) && ((i+packet_offset) < urb->actual_length) ; ++i) { /* have to make sure we don't overflow the buffer with tty_insert_flip_char's */ if(tty->flip.count >= TTY_FLIPBUF_SIZE) { @@ -1264,12 +1300,12 @@ /* Note that the error flag is duplicated for every character received since we don't know which character it applied to */ - tty_insert_flip_char(tty, data[i], error_flag); + tty_insert_flip_char(tty, data[packet_offset+i], error_flag); } tty_flip_buffer_push(tty); } -#ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOW + #ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOW /* if a parity error is detected you get status packets forever until a character is sent without a parity error. This doesn't work well since the application receives a never @@ -1290,6 +1326,7 @@ } } #endif + } /* "for(packet_offset=0..." */ /* if the port is closed stop trying to read */ if (port->open_count > 0){ @@ -1352,6 +1389,10 @@ __u16 urb_value; /* will hold the new flags */ char buf[1]; /* Perhaps I should dynamically alloc this? */ + // Added for xon/xoff support + unsigned int iflag = port->tty->termios->c_iflag; + unsigned char vstop; + unsigned char vstart; dbg("%s", __FUNCTION__); @@ -1434,6 +1475,33 @@ } } else { + /* + * Xon/Xoff code + * + * Check the IXOFF status in the iflag component of the termios structure + * if IXOFF is not set, the pre-xon/xoff code is executed. + */ + if(iflag & IXOFF) { + dbg("%s request to enable xonxoff iflag=%04x",__FUNCTION__,iflag); + // Try to enable the XON/XOFF on the ftdi_sio + // Set the vstart and vstop -- could have been done up above where + // a lot of other dereferencing is done but that would be very + // inefficient as vstart and vstop are not always needed + vstart=port->tty->termios->c_cc[VSTART]; + vstop=port->tty->termios->c_cc[VSTOP]; + urb_value=(vstop << 8) | (vstart); + + if (usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_FLOW_CTRL_REQUEST, + FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, + urb_value , FTDI_SIO_XON_XOFF_HS, + buf, 0, WDR_TIMEOUT) < 0) { + err("urb failed to set to xon/xoff flow control"); + } + + }else{ + /* else clause to only run if cfag ! CRTSCTS and iflag ! XOFF */ /* CHECKME Assuming XON/XOFF handled by tty stack - not by device */ dbg("%s Turning off hardware flow control", __FUNCTION__); if (usb_control_msg(serial->dev, @@ -1444,6 +1512,7 @@ buf, 0, WDR_TIMEOUT) < 0) { err("urb failed to clear flow control"); } + } } return; diff -rauX ../dontdiff new/drivers/usb/serial/ftdi_sio.h patch_3/drivers/usb/serial/ftdi_sio.h --- new/drivers/usb/serial/ftdi_sio.h 2003-03-26 23:32:44.000000000 +1200 +++ patch_3/drivers/usb/serial/ftdi_sio.h 2003-03-25 23:26:52.000000000 +1200 @@ -25,12 +25,15 @@ #define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */ #define FTDI_NF_RIC_PID 0x0001 /* Product Id */ - /* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */ /* they use the ftdi chipset for the USB interface and the vendor id is the same */ #define FTDI_XF_634_PID 0xFC09 /* Four line device */ #define FTDI_XF_632_PID 0xFC08 /* Two line device */ +/* Video Networks Limited / Homechoice in the UK use an ftdi-based device for their 1Mb */ +/* broadband internet service. The following PID is exhibited by the usb device supplied */ +/* (the VID is the standard ftdi vid (FTDI_VID) */ +#define FTDI_VNHCPCUSB_D_PID 0xfe38 /* Product Id */ /* * The following are the values for the Matrix Orbital LCD displays,
