//================================================== #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; }
/** * 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; }
// 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配置信息