FTDI SIO, 8U232AM and 245 Linux USB serial driver

Quick summary
Ways to use the device
POSIX serial programming
libftdi
Frequently Asked Questions
How do I check to see if the driver loaded?
My device is not recognised by the kernel. How do I manually load it?
What are some debug techniques
Why doesn't setserial work as expected?
Submitting patches for new VID/PIDs
Old web site stuff
Serial loopback tester.
Non Standard Baudrates
What ioctls are known to work
Todo
References and useful links
USBINFO for the devices I have
The original FTDI_SIO I have
The 8U232AM sample I have
The 245 sample I have
Acknowledgements
Feedback

Quick summary

Use the most up to date linux kernel. This means 2.6.x or at least 2.4.30. Although the driver is marked experimental it's not really. Most distros will include the driver by default. All comments in this page are based on 2.6.32.16 so there may be some minor differences.

If you have a device that is new or isn't in the list of VID/PIDs you'll need to do some work. See below about how to do that.

I (Bill Ryder) do not maintain this driver anymore. Every so often I will update this webpage. If you want to actively maintain the driver and look after this sourceforge site send me a mail at bill.ryder.nz@gmail.com

Ways to use the device

You can interact with the device in two ways.

POSIX serial programming

I wrote the driver so I could talk to unix servers and my palm pilot using a usb serial interface from my laptop. For this to work you need a standard serial interface so you can use off the shelf tools like terminal emulators and palm pilot software.

man termios(3) is the correct man page for this style of programming.

Any serial application which talks to the device using just the termios interface will probably work.

The usual mistake people make is assuming they can just open the serial port and read and write to it without setting any serial communications parameters.

A good place to start learning this style of programming is to read the LDP Serial Progarmming Howto.

libftdi

This may be the best way for you to talk to the device if you are writing programs and need to do more than the serial interface was ever designed for:

Go to http://www.intra2net.com/en/developer/libftdi/links.php.

The other advantage in using libftdi is that there's no kernel programming involved.

Frequently Asked Questions

How do I check to see if the driver loaded?

dmesg | grep -i ftdi

You should see something like:

usb 1-7.6: Manufacturer: FTDI
ftdi_sio 1-7.6:1.0: FTDI USB Serial Device converter detected
usb 1-7.6: FTDI USB Serial Device converter now attached to ttyUSB0

If you don't you probably need to look at the following section.

Note the device name - ttyUSB0 - that is the device you point your serial program at (it'll probably be /dev/ttyUSB0 in this case).

My device is not recognised by the kernel. How do I manually load it?

  1. Find the VID (Vendor ID) and PID (Product ID) for the device - use lsusb
  2. Manually modload the driver
lsusb | grep -i ft
Bus 001 Device 031: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC

The VID is 0403 - the PID is 6001

modprobe ftdi_sio vendor=0x403 product=0x6001

You should see the module in the lsmod list if modprobe worked:

# lsmod | grep ft
ftdi_sio               50508  0
usbserial              36296  1 ftdi_sio
usbcore               185584  8 ftdi_sio,usbserial,usb_storage,uhci_hcd,ohci_hcd,ehci_hcd,usbhid

You can also check dmesg

# dmesg | tail

USB Serial support registered for FTDI USB Serial Device
ftdi_sio 1-5.6:1.0: FTDI USB Serial Device converter detected
usb 1-5.6: Detected FT8U232AM
usb 1-5.6: Number of endpoints 2
usb 1-5.6: Endpoint 1 MaxPacketSize 64
usb 1-5.6: Endpoint 2 MaxPacketSize 64
usb 1-5.6: Setting MaxPacketSize 64
usb 1-5.6: FTDI USB Serial Device converter now attached to ttyUSB0
usbcore: registered new interface driver ftdi_sio
ftdi_sio: v1.5.0:USB FTDI Serial Converters Driver

Caveat about new devices

The modprobe above will only work if the driver can figure out the chip type. When I wrote the driver there were only a few chip types. 2.6.17 supports 232RL versions for example. So if you have a new chip you may need to do some driver work!

Look in drivers/usb/serial/ftdi_sio.c in your kernel source tree. Look for things which set chip_type.

There are a lot more since I wrote the driver so some of the comments for that structure earlier on in the code are incorrect.

What are some debug techniques

Turn debugging on for the driver.

When you modprobe the driver you need to set the debug flag

modprobe ftdi_sio vendor=0x403 product=0x6001 debug

There'll be a lot of stuff dumped now that's viewable with dmesg or in a log file (somewhere in /var/log depending on your distro).

To really understand what's going on you'll need to look at the source (ftdi_sio.c for the ftdi specific stuff).

Using strace

The other thing you will probably want to do is strace the application trying to talk to the device.

These are the appropriate options

strace -f -tt -T -v

I always use -tt -T so I can get timing information to see how long was spend in a system call.

You'll be able to see what ioctls the application is using and what is failing.

Why doesn't setserial work as expected?

setserial uses some special hardware specific ioctls which are not supported by the driver.

If you want to set things like baudrate, flow control etc using the ftdi serial driver you should use stty.

However. stty only has a limited set of baudrates. You'll need to write your own software to set 'unusual' baudrates or just use libftdi library referenced earlier.

Submitting patches for new VID/PIDs

If you have a patch to submit (adding PIDs etc) please read Documentation/SubmittingPatches in your kernel source directory and submit it to the usb devel list and lmkl (linux kernel mailing)

For adding a new VID/PID you'll probably only need to patch ftdi_sio_ids.h.

If it's an unrecognised chip type you'll need to edit ftdi_sio_id.h and ftdi_sio.c.

Old web site stuff

For my own sentimental reasons I've kept a copy of the original websites here.

Serial loopback tester.

Download from here.

This will work with two RS232 (or backtoback 245) devices or with a loopback plug on the RS232 end. See the script for the loopback plug assumed configuration.

The program tests simple writes of any size using simple data. It will optionally check hardware lines, send a break, and time runs to get throughput figures.

NOTE: it requires the Benchmark::Timer module available from CPAN - read the script for details.

If when you try to run serial_loopback.pl you see something like:

syntax error at /usr/lib/perl5/5.6.1/i386-linux/features.ph line 149, near ") ("
syntax error at /usr/lib/perl5/5.6.1/i386-linux/features.ph line 155, near "}"
Compilation failed in require at /usr/lib/perl5/5.6.1/i386-linux/sys/ioctl.ph line 5.
Compilation failed in require at serial_loopback.pl line 42.
You will need to fix broken .ph files - read the serial_loopback script for details about how to do this.

Run it with -x for help.

Tests the following ioctls:

Baudrate changes and BREAK setting are also tested.

Non Standard Baudrates

Thanx to Kuba Ober the driver supports non-standard baudrates using the TIOCSSERIAL interface. I haven't tested this myself so I reproduce Kuba's documentation (slightly edited) he added to the patch below:

	 * 1. Standard baud rates are set in tty->termios->c_cflag
	 * 2. If these are not enough, you can set any speed using alt_speed as follows:
	 *    - set tty->termios->c_cflag speed to B38400
	 *    - set your real speed in tty->alt_speed; it gets ignored when
	 *      alt_speed==0, (or)
	 *    - call TIOCSSERIAL ioctl with (struct serial_struct) set as follows:
	 *      flags & ASYNC_SPD_MASK == ASYNC_SPD_[HI, VHI, SHI, WARP], this just
	 *      sets alt_speed to (HI: 57600, VHI: 115200, SHI: 230400, WARP: 460800)
	 * 3. You can also set baud rate by setting custom divisor as follows
	 *    - set tty->termios->c_cflag speed to B38400
	 *    - call TIOCSSERIAL ioctl with (struct serial_struct) set as follows:
	 *      o flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST
	 *      o custom_divisor set to baud_base / your_new_baudrate

What ioctls are known to work

  1. This was the patch to drivers/char/tty_io.c

Todo

I'm sure I'll never do this but I'm leaving the list here anyway.

References and useful links

USBINFO for the devices I have

This section reproduces the usb device output from /proc/bus/usb/devices assuming you compiled the usbdevfs into the kernel and have mounted it.

The original FTDI_SIO I have

T:  Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12  MxCh= 2
B:  Alloc=  0/900 us ( 0%), #Int=  0, #Iso=  0
D:  Ver= 1.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
P:  Vendor=0000 ProdID=0000 Rev= 0.00
S:  Product=USB UHCI Root Hub
S:  SerialNumber=ece0
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr=  0mA
I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   8 Ivl=255ms
T:  Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  5 Spd=12  MxCh= 0
D:  Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
P:  Vendor=0403 ProdID=8372 Rev= 0.01
S:  Manufacturer=FTDI
S:  Product=FTDI EVALUATION USB <-> Serial
S:  SerialNumber=FTDI2090
C:* #Ifs= 1 Cfg#= 1 Atr=20 MxPwr= 60mA
I:  If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=serial
E:  Ad=82(I) Atr=02(Bulk) MxPS=  64 Ivl=  0ms
E:  Ad=02(O) Atr=02(Bulk) MxPS=  64 Ivl=  0ms

The 8U232AM sample I have

T:  Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12  MxCh= 2
B:  Alloc=  0/900 us ( 0%), #Int=  0, #Iso=  0
D:  Ver= 1.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
P:  Vendor=0000 ProdID=0000 Rev= 0.00
S:  Product=USB UHCI Root Hub
S:  SerialNumber=ece0
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr=  0mA
I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   8 Ivl=255ms
T:  Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  4 Spd=12  MxCh= 0
D:  Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
P:  Vendor=0403 ProdID=6001 Rev= 2.00
S:  Manufacturer=FTDI
S:  Product=FT8U232AM EVALUATION KIT
S:  SerialNumber=FT9LM012
C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr= 50mA
I:  If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=serial
E:  Ad=81(I) Atr=02(Bulk) MxPS=  64 Ivl=  0ms
E:  Ad=02(O) Atr=02(Bulk) MxPS=  64 Ivl=  0ms

The 245 sample I have

T:  Bus=01 Lev=02 Prnt=09 Port=01 Cnt=01 Dev#= 10 Spd=12  MxCh= 0
D:  Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
P:  Vendor=0403 ProdID=6001 Rev= 2.00
S:  Manufacturer=FTDI
S:  Product=USB <-> Serial
S:  SerialNumber=12345678
C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr= 90mA
I:  If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=serial
E:  Ad=81(I) Atr=02(Bulk) MxPS=  64 Ivl=0ms
E:  Ad=02(O) Atr=02(Bulk) MxPS=  64 Ivl=0ms
T:  Bus=01 Lev=02 Prnt=09 Port=03 Cnt=02 Dev#= 11 Spd=12  MxCh= 0
D:  Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
P:  Vendor=0403 ProdID=6001 Rev= 2.00
S:  Manufacturer=FTDI
S:  Product=USB <-> Serial
S:  SerialNumber=12345678
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr= 90mA
I:  If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=serial
E:  Ad=81(I) Atr=02(Bulk) MxPS=  64 Ivl=0ms
E:  Ad=02(O) Atr=02(Bulk) MxPS=  64 Ivl=0ms

Acknowledgements

FTDI for making the specifications for the device available, and providing me with their new product when I started writing this.

Greg Kroah-Hartman and other members of the USB development team for hints, sample code for me to steal and updating the driver when I don't have time to do it and it is urgent.

Kuba Ober for the June_2002 patch (even though he sent it to me in February 2002 - sorry about that).

Sourceforge for providing such a great resource.

Ian Abbot for helping people out all the time on the ftdi list and still paying attention to this driver.

Thomas Jarosch for prompting me to actually update this page and for his libftdi work which has meant I don't get hassled about things that shouldn't really be done by a serial driver.

Feedback

Send me a mail for errors etc in this page - bill.ryder.nz@gmail.com

I'll probably take months to fix it but it should get fixed.

SourceForge Logo