* *
***************************************************************************/
+/**
+ \mainpage libftdi API documentation
+
+ Library to talk to FTDI chips. You find the latest versions of libftdi at
+ http://www.intra2net.com/de/produkte/opensource/ftdi/
+
+ The library is easy to use. Have a look at this short example:
+ \include simple.c
+
+ More examples can be found in the "examples" directory.
+*/
+/** \addtogroup libftdi */
+/* @{ */
+
#include <usb.h>
#include <string.h>
#include <errno.h>
ftdi_error_return(-2, "usb_find_devices() failed");
curdev = devlist;
+ *curdev = NULL;
for (bus = usb_busses; bus; bus = bus->next) {
for (dev = bus->devices; dev; dev = dev->next) {
if (dev->descriptor.idVendor == vendor
*/
void ftdi_list_free(struct ftdi_device_list **devlist)
{
- struct ftdi_device_list **curdev;
- for (; *devlist == NULL; devlist = curdev) {
- curdev = &(*devlist)->next;
- free(*devlist);
+ struct ftdi_device_list *curdev, *next;
+
+ for (curdev = *devlist; curdev != NULL;) {
+ next = curdev->next;
+ free(curdev);
+ curdev = next;
+ }
+
+ *devlist = NULL;
+}
+
+/**
+ Return device ID strings from the usb device.
+
+ The parameters manufacturer, description and serial may be NULL
+ or pointer to buffers to store the fetched strings.
+
+ \note Use this function only in combination with ftdi_usb_find_all()
+ as it closes the internal "usb_dev" after use.
+
+ \param ftdi pointer to ftdi_context
+ \param dev libusb usb_dev to use
+ \param manufacturer Store manufacturer string here if not NULL
+ \param mnf_len Buffer size of manufacturer string
+ \param description Store product description string here if not NULL
+ \param desc_len Buffer size of product description string
+ \param serial Store serial string here if not NULL
+ \param serial_len Buffer size of serial string
+
+ \retval 0: all fine
+ \retval -1: wrong arguments
+ \retval -4: unable to open device
+ \retval -7: get product manufacturer failed
+ \retval -8: get product description failed
+ \retval -9: get serial number failed
+ \retval -10: unable to close device
+*/
+int ftdi_usb_get_strings(struct ftdi_context * ftdi, struct usb_device * dev,
+ char * manufacturer, int mnf_len, char * description, int desc_len, char * serial, int serial_len)
+{
+ if ((ftdi==NULL) || (dev==NULL))
+ return -1;
+
+ if (!(ftdi->usb_dev = usb_open(dev)))
+ ftdi_error_return(-4, usb_strerror());
+
+ if (manufacturer != NULL) {
+ if (usb_get_string_simple(ftdi->usb_dev, dev->descriptor.iManufacturer, manufacturer, mnf_len) <= 0) {
+ usb_close (ftdi->usb_dev);
+ ftdi_error_return(-7, usb_strerror());
+ }
+ }
+
+ if (description != NULL) {
+ if (usb_get_string_simple(ftdi->usb_dev, dev->descriptor.iProduct, description, desc_len) <= 0) {
+ usb_close (ftdi->usb_dev);
+ ftdi_error_return(-8, usb_strerror());
+ }
+ }
+
+ if (serial != NULL) {
+ if (usb_get_string_simple(ftdi->usb_dev, dev->descriptor.iSerialNumber, serial, serial_len) <= 0) {
+ usb_close (ftdi->usb_dev);
+ ftdi_error_return(-9, usb_strerror());
+ }
}
- devlist = NULL;
+ if (usb_close (ftdi->usb_dev) != 0)
+ ftdi_error_return(-10, usb_strerror());
+
+ return 0;
}
/**
ftdi->type = TYPE_2232C;
if (!ftdi->index)
ftdi->index = INTERFACE_A;
- }
+ } else if (dev->descriptor.bcdDevice == 0x600)
+ ftdi->type = TYPE_R;
ftdi_error_return(0, "all fine");
}
/*
ftdi_convert_baudrate returns nearest supported baud rate to that requested.
Function is only used internally
+ \internal
*/
static int ftdi_convert_baudrate(int baudrate, struct ftdi_context *ftdi,
unsigned short *value, unsigned short *index)
\param size Size of the buffer
\retval <0: error code from usb_bulk_read()
+ \retval 0: no data was available
\retval >0: number of bytes read
\remark This function is not useful in bitbang mode.
return 0;
}
+/*
+ ftdi_read_chipid_shift does the bitshift operation needed for the FTDIChip-ID
+ Function is only used internally
+ \internal
+*/
+static unsigned char ftdi_read_chipid_shift(unsigned char value)
+{
+ return ((value & 1) << 1) |
+ ((value & 2) << 5) |
+ ((value & 4) >> 2) |
+ ((value & 8) << 4) |
+ ((value & 16) >> 1) |
+ ((value & 32) >> 1) |
+ ((value & 64) >> 4) |
+ ((value & 128) >> 2);
+}
+
+/**
+ Read the FTDIChip-ID from R-type devices
+
+ \param ftdi pointer to ftdi_context
+ \param chipid Pointer to store FTDIChip-ID
+
+ \retval 0: all fine
+ \retval -1: read failed
+*/
+int ftdi_read_chipid(struct ftdi_context *ftdi, unsigned int *chipid)
+{
+ unsigned int a = 0, b = 0;
+
+ if (usb_control_msg(ftdi->usb_dev, 0xC0, 0x90, 0, 0x43, (char *)&a, 2, ftdi->usb_read_timeout) == 2)
+ {
+ a = a << 8 | a >> 8;
+ if (usb_control_msg(ftdi->usb_dev, 0xC0, 0x90, 0, 0x44, (char *)&b, 2, ftdi->usb_read_timeout) == 2)
+ {
+ b = b << 8 | b >> 8;
+ a = (a << 16) | b;
+ a = ftdi_read_chipid_shift(a) | ftdi_read_chipid_shift(a>>8)<<8
+ | ftdi_read_chipid_shift(a>>16)<<16 | ftdi_read_chipid_shift(a>>24)<<24;
+ *chipid = a ^ 0xa5f0f7d1;
+ return 0;
+ }
+ }
+
+ ftdi_error_return(-1, "read of FTDIChip-ID failed");
+}
+
/**
Write eeprom
return 0;
}
+
+/* @} end of doxygen libftdi group */