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

来源:互联网 发布:23端口网址 编辑:程序博客网 时间:2024/05/15 15:41
 
读写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配置信息