⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftdi.c

📁 libftdi - A library (using libusb) to talk to FTDI s FT2232C, FT232BM and FT245BM type chips includ
💻 C
📖 第 1 页 / 共 3 页
字号:
/***************************************************************************                          ftdi.c  -  description                             -------------------    begin                : Fri Apr 4 2003    copyright            : (C) 2003 by Intra2net AG    email                : opensource@intra2net.com ***************************************************************************//*************************************************************************** *                                                                         * *   This program is free software; you can redistribute it and/or modify  * *   it under the terms of the GNU Lesser General Public License           * *   version 2.1 as published by the Free Software Foundation;             * *                                                                         * ***************************************************************************//**    \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>#include "ftdi.h"#define ftdi_error_return(code, str) do {  \        ftdi->error_str = str;             \        return code;                       \   } while(0);/**    Initializes a ftdi_context.    \param ftdi pointer to ftdi_context    \retval  0: all fine    \retval -1: couldn't allocate read buffer    \remark This should be called before all functions*/int ftdi_init(struct ftdi_context *ftdi){    ftdi->usb_dev = NULL;    ftdi->usb_read_timeout = 5000;    ftdi->usb_write_timeout = 5000;    ftdi->type = TYPE_BM;    /* chip type */    ftdi->baudrate = -1;    ftdi->bitbang_enabled = 0;    ftdi->readbuffer = NULL;    ftdi->readbuffer_offset = 0;    ftdi->readbuffer_remaining = 0;    ftdi->writebuffer_chunksize = 4096;    ftdi->interface = 0;    ftdi->index = 0;    ftdi->in_ep = 0x02;    ftdi->out_ep = 0x81;    ftdi->bitbang_mode = 1; /* 1: Normal bitbang mode, 2: SPI bitbang mode */    ftdi->error_str = NULL;    /* All fine. Now allocate the readbuffer */    return ftdi_read_data_set_chunksize(ftdi, 4096);}/**    Open selected channels on a chip, otherwise use first channel.    \param ftdi pointer to ftdi_context    \param interface Interface to use for FT2232C chips.    \retval  0: all fine    \retval -1: unknown interface*/int ftdi_set_interface(struct ftdi_context *ftdi, enum ftdi_interface interface){    switch (interface) {    case INTERFACE_ANY:    case INTERFACE_A:        /* ftdi_usb_open_desc cares to set the right index, depending on the found chip */        break;    case INTERFACE_B:        ftdi->interface = 1;        ftdi->index     = INTERFACE_B;        ftdi->in_ep     = 0x04;        ftdi->out_ep    = 0x83;        break;    default:        ftdi_error_return(-1, "Unknown interface");    }    return 0;}/**    Deinitializes a ftdi_context.    \param ftdi pointer to ftdi_context*/void ftdi_deinit(struct ftdi_context *ftdi){    if (ftdi->readbuffer != NULL) {        free(ftdi->readbuffer);        ftdi->readbuffer = NULL;    }}/**    Use an already open libusb device.    \param ftdi pointer to ftdi_context    \param usb libusb usb_dev_handle to use*/void ftdi_set_usbdev (struct ftdi_context *ftdi, usb_dev_handle *usb){    ftdi->usb_dev = usb;}/**    Finds all ftdi devices on the usb bus. Creates a new ftdi_device_list which    needs to be deallocated by ftdi_list_free() after use.    \param ftdi pointer to ftdi_context    \param devlist Pointer where to store list of found devices    \param vendor Vendor ID to search for    \param product Product ID to search for    \retval >0: number of devices found    \retval -1: usb_find_busses() failed    \retval -2: usb_find_devices() failed    \retval -3: out of memory*/int ftdi_usb_find_all(struct ftdi_context *ftdi, struct ftdi_device_list **devlist, int vendor, int product){    struct ftdi_device_list **curdev;    struct usb_bus *bus;    struct usb_device *dev;    int count = 0;    usb_init();    if (usb_find_busses() < 0)        ftdi_error_return(-1, "usb_find_busses() failed");    if (usb_find_devices() < 0)        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                    && dev->descriptor.idProduct == product)            {                *curdev = (struct ftdi_device_list*)malloc(sizeof(struct ftdi_device_list));                if (!*curdev)                    ftdi_error_return(-3, "out of memory");                (*curdev)->next = NULL;                (*curdev)->dev = dev;                curdev = &(*curdev)->next;                count++;            }        }    }    return count;}/**    Frees a usb device list.    \param devlist USB device list created by ftdi_usb_find_all()*/void ftdi_list_free(struct ftdi_device_list **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());        }    }    if (usb_close (ftdi->usb_dev) != 0)        ftdi_error_return(-10, usb_strerror());    return 0;}/**    Opens a ftdi device given by a usb_device.    \param ftdi pointer to ftdi_context    \param dev libusb usb_dev to use    \retval  0: all fine    \retval -4: unable to open device    \retval -5: unable to claim device    \retval -6: reset failed    \retval -7: set baudrate failed*/int ftdi_usb_open_dev(struct ftdi_context *ftdi, struct usb_device *dev){    int detach_errno = 0;    if (!(ftdi->usb_dev = usb_open(dev)))        ftdi_error_return(-4, "usb_open() failed");#ifdef LIBUSB_HAS_GET_DRIVER_NP    // Try to detach ftdi_sio kernel module    // Returns ENODATA if driver is not loaded    if (usb_detach_kernel_driver_np(ftdi->usb_dev, ftdi->interface) != 0 && errno != ENODATA)        detach_errno = errno;#endif    if (usb_claim_interface(ftdi->usb_dev, ftdi->interface) != 0) {        usb_close (ftdi->usb_dev);        if (detach_errno == EPERM) {            ftdi_error_return(-8, "inappropriate permissions on device!");        } else {            ftdi_error_return(-5, "unable to claim usb device. Make sure ftdi_sio is unloaded!");        }    }    if (ftdi_usb_reset (ftdi) != 0) {        usb_close (ftdi->usb_dev);        ftdi_error_return(-6, "ftdi_usb_reset failed");    }    if (ftdi_set_baudrate (ftdi, 9600) != 0) {        usb_close (ftdi->usb_dev);        ftdi_error_return(-7, "set baudrate failed");    }    // Try to guess chip type    // Bug in the BM type chips: bcdDevice is 0x200 for serial == 0    if (dev->descriptor.bcdDevice == 0x400 || (dev->descriptor.bcdDevice == 0x200            && dev->descriptor.iSerialNumber == 0))        ftdi->type = TYPE_BM;    else if (dev->descriptor.bcdDevice == 0x200)        ftdi->type = TYPE_AM;    else if (dev->descriptor.bcdDevice == 0x500) {        ftdi->type = TYPE_2232C;        if (!ftdi->index)            ftdi->index = INTERFACE_A;    }    ftdi_error_return(0, "all fine");}/**    Opens the first device with a given vendor and product ids.    \param ftdi pointer to ftdi_context    \param vendor Vendor ID    \param product Product ID    \retval same as ftdi_usb_open_desc()*/int ftdi_usb_open(struct ftdi_context *ftdi, int vendor, int product){    return ftdi_usb_open_desc(ftdi, vendor, product, NULL, NULL);}/**    Opens the first device with a given, vendor id, product id,    description and serial.    \param ftdi pointer to ftdi_context    \param vendor Vendor ID    \param product Product ID    \param description Description to search for. Use NULL if not needed.    \param serial Serial to search for. Use NULL if not needed.    \retval  0: all fine    \retval -1: usb_find_busses() failed    \retval -2: usb_find_devices() failed    \retval -3: usb device not found    \retval -4: unable to open device    \retval -5: unable to claim device    \retval -6: reset failed    \retval -7: set baudrate failed    \retval -8: get product description failed    \retval -9: get serial number failed    \retval -10: unable to close device*/int ftdi_usb_open_desc(struct ftdi_context *ftdi, int vendor, int product,                       const char* description, const char* serial){    struct usb_bus *bus;    struct usb_device *dev;    char string[256];    usb_init();    if (usb_find_busses() < 0)        ftdi_error_return(-1, "usb_find_busses() failed");    if (usb_find_devices() < 0)        ftdi_error_return(-2, "usb_find_devices() failed");    for (bus = usb_busses; bus; bus = bus->next) {        for (dev = bus->devices; dev; dev = dev->next) {            if (dev->descriptor.idVendor == vendor                    && dev->descriptor.idProduct == product) {                if (!(ftdi->usb_dev = usb_open(dev)))                    ftdi_error_return(-4, "usb_open() failed");                if (description != NULL) {                    if (usb_get_string_simple(ftdi->usb_dev, dev->descriptor.iProduct, string, sizeof(string)) <= 0) {                        usb_close (ftdi->usb_dev);                        ftdi_error_return(-8, "unable to fetch product description");                    }                    if (strncmp(string, description, sizeof(string)) != 0) {                        if (usb_close (ftdi->usb_dev) != 0)                            ftdi_error_return(-10, "unable to close device");                        continue;                    }                }                if (serial != NULL) {                    if (usb_get_string_simple(ftdi->usb_dev, dev->descriptor.iSerialNumber, string, sizeof(string)) <= 0) {                        usb_close (ftdi->usb_dev);                        ftdi_error_return(-9, "unable to fetch serial number");                    }                    if (strncmp(string, serial, sizeof(string)) != 0) {                        if (usb_close (ftdi->usb_dev) != 0)                            ftdi_error_return(-10, "unable to close device");                        continue;                    }                }                if (usb_close (ftdi->usb_dev) != 0)                    ftdi_error_return(-10, "unable to close device");                return ftdi_usb_open_dev(ftdi, dev);            }        }    }    // device not found    ftdi_error_return(-3, "device not found");}/**    Resets the ftdi device.    \param ftdi pointer to ftdi_context    \retval  0: all fine    \retval -1: FTDI reset failed*/int ftdi_usb_reset(struct ftdi_context *ftdi){    if (usb_control_msg(ftdi->usb_dev, 0x40, 0, 0, ftdi->index, NULL, 0, ftdi->usb_write_timeout) != 0)        ftdi_error_return(-1,"FTDI reset failed");    // Invalidate data in the readbuffer    ftdi->readbuffer_offset = 0;    ftdi->readbuffer_remaining = 0;    return 0;}/**    Clears the buffers on the chip.    \param ftdi pointer to ftdi_context    \retval  0: all fine    \retval -1: write buffer purge failed    \retval -2: read buffer purge failed*/int ftdi_usb_purge_buffers(struct ftdi_context *ftdi){    if (usb_control_msg(ftdi->usb_dev, 0x40, 0, 1, ftdi->index, NULL, 0, ftdi->usb_write_timeout) != 0)        ftdi_error_return(-1, "FTDI purge of RX buffer failed");    // Invalidate data in the readbuffer    ftdi->readbuffer_offset = 0;    ftdi->readbuffer_remaining = 0;    if (usb_control_msg(ftdi->usb_dev, 0x40, 0, 2, ftdi->index, NULL, 0, ftdi->usb_write_timeout) != 0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -