读写FT232 USB转串口芯片的EEPROM (2011-11-07 19:48)

 
读写FT232BM USB转串口芯片的EEPROM项目需要在嵌入式linux下读写usb芯片的EEPROM。ft232官方有读写EEPROM的lib,但是不开源,民间的ftdi驱动可在http://www.intra2net.com/en/developer/libftdi/download.php
 
下载,libftdi是ft232的开源驱动,使用libusb,可读写EEPROM,下libftdi-0.19.tar.gzftdi_eeprom-0.3.tar.gz源码包。其实只需截取libftdi源码中的一部分宏定义即可用libusb实现对tf232的EEPROM读写。
 
 
我的部分源码如下:
 
 
 
使用libusb读取ft232芯片的EEPROM:
//==================================================
#define USB_RW_TIMEOUT 5000
#define EEPROM_SIZE 128
#define SIO_READ_EEPROM_REQUEST 0x90
#define SIO_WRITE_EEPROM_REQUEST 0x91
#define SIO_RESET_SIO 0
#define SIO_RESET 0 /* Reset the port */
#define SIO_RESET_REQUEST SIO_RESET
#define SIO_POLL_MODEM_STATUS_REQUEST 0x05
#define SIO_SET_LATENCY_TIMER_REQUEST 0x09
#define FTDI_DEVICE_OUT_REQTYPE (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT)
#define FTDI_DEVICE_IN_REQTYPE (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN)

/**
 * ftdi_read_eeprom - Read ft232B's EEPROM 128-byte to ebuf.
 * @usb_dev: Usb dev handle
 * @ebuf: Where EEPROM data save to
 * @buflen: Length of ebuf
 * @return: 0 sucess. -1 error and set ebuf[0:127] 0x00.
 */
static int ftdi_read_eeprom(struct usb_dev_handle *usb_dev, unsigned char *ebuf, int buflen)
{
    int i;
    if (usb_dev == NULL || buflen < 128){
        dprint("#USB device unavailable or buflen too short\n");
        return -1;
    }

    // Read FTDI EEPROM
    for (i = 0; i < EEPROM_SIZE / 2; i++){
        if (usb_control_msg(usb_dev, FTDI_DEVICE_IN_REQTYPE, SIO_READ_EEPROM_REQUEST, 0, i, (char *)ebuf+(i*2), 2, USB_RW_TIMEOUT) != 2){
            dprint("#reading eeprom failed.\n");
            return -1;
        }
    }
 
    // Calculate checksum
    unsigned short checksum, value;
        checksum = 0xAAAA;
    for (i = 0; i < EEPROM_SIZE/2-1; i++){
        value = ebuf[i*2];
        value += ebuf[(i*2)+1] << 8;
        checksum = value^checksum;
        checksum = (checksum << 1) | (checksum >> 15);
    }

    // check if read success
    if(ebuf[EEPROM_SIZE-2] != (unsigned char)checksum || ebuf[EEPROM_SIZE-1] != checksum >> 8){
        dprint("#read EEPROM error.\n");
        memset(ebuf, 0x00, EEPROM_SIZE);
        return -1;
    }
    return 0;
}

 
 
使用libusb写入ft232芯片的EEPROM:
/**
 * ftdi_write_eeprom - Write 128 byte inti ft232 EEPROM
 * @usb_dev: Usb dev handler
 * @eeprom: Pointer of 128 byte data
 * @buflen: Length of ebuf
 * @return: 0 sucess. -1: read failed. -2: USB device unavailable
 */

static int ftdi_write_eeprom(struct usb_dev_handle *usb_dev, unsigned char *eeprom, int buflen)
{
    unsigned short usb_val;
    int i;

    if (usb_dev == NULL || eeprom == NULL || buflen < 128){
        dprint("#USB device unavailable or buflen too short\n");
        return -2;
    }

    // calculate checksum
    unsigned short checksum, value;
        checksum = 0xAAAA;
    for (i = 0; i < EEPROM_SIZE/2-1; i++) {
        value = eeprom[i*2];
        value += eeprom[(i*2)+1] << 8;
        checksum = value^checksum;
        checksum = (checksum << 1) | (checksum >> 15);
    }

    // Write checksum
    eeprom[EEPROM_SIZE-2] = (unsigned char)checksum;
    eeprom[EEPROM_SIZE-1] = checksum >> 8;

    usb_claim_interface(usb_dev, 0);

    /* These commands were traced while running MProg */
    if (usb_control_msg(usb_dev, FTDI_DEVICE_OUT_REQTYPE,
                        SIO_RESET_REQUEST, SIO_RESET_SIO,
                        0, NULL, 0, USB_RW_TIMEOUT) != 0){
      dprint("#FTDI reset failed\n");
                return -1;
            }

    //if ((ret = ftdi_poll_modem_status(ftdi, &status)) != 0)
    if (usb_control_msg(usb_dev, FTDI_DEVICE_IN_REQTYPE, 0x05, 0, 0, NULL, 0, USB_RW_TIMEOUT) != 2){
        dprint("#getting modem status failed\n");
                //return -1;
        }
    //if ((ret = ftdi_set_latency_timer(ftdi, 0x77)) != 0)
    if (usb_control_msg(usb_dev, FTDI_DEVICE_OUT_REQTYPE, SIO_SET_LATENCY_TIMER_REQUEST, 0x77, 0, NULL, 0, USB_RW_TIMEOUT) != 0){
        dprint("#unable to set latency timer\n");
                return -2;
        }

    for (i = 0; i < EEPROM_SIZE / 2; i++) {
        usb_val = eeprom[i*2];
        usb_val += eeprom[(i*2)+1] << 8;
        if (usb_control_msg(usb_dev, FTDI_DEVICE_OUT_REQTYPE,
                         SIO_WRITE_EEPROM_REQUEST, usb_val, i,
                            NULL, 0, USB_RW_TIMEOUT) != 0){
            dprint("#unable to write eeprom\n");
                        return -1;
        }
    }
    usb_release_interface(usb_dev, 0);
    return 0;
}

 
保存信息到usb芯片里,我选择保存到product字符串里面,读取的时候
 
我不再使用libusb读取,而是让内核把它读取到sysfs里面:
 
EEPROM里面的usb config file 是固定格式的,可以在libftdi找到,以下
 
是部分内容:
 
// Addr 10: Offset of the product string + 0x80, calculated later
    // Addr 11: Length of product string
    output[0x11] = product_size*2 + 2;

    // Addr 12: Offset of the serial string + 0x80, calculated later
    // Addr 13: Length of serial string
    output[0x13] = serial_size*2 + 2;

    // Output product name
    output[0x10] = i | 0x80; // calculate offset
    output[i] = product_size*2 + 2, i++;
    output[i] = 0x03, i++;

    for (j = 0; j < product_size; j++){
        output[i] = eeprom->product[j], i++;
        output[i] = 0x00, i++;
    }
    // Output serial
    output[0x12] = i | 0x80; // calculate offset
    output[i] = serial_size*2 + 2, i++;
    output[i] = 0x03, i++;

    for (j = 0; j < serial_size; j++) {
        output[i] = eeprom->serial[j], i++;
        output[i] = 0x00, i++;
    }

可以很方便地定制usb配置信息

 
 

你可能感兴趣的:(timer,String,struct,null,interface,output)