in common/recipes-utils/ftditool/files/ftditool.c [413:704]
int main(int argc, char *argv[])
{
struct libusb_device_handle *devh = NULL;
libusb_device **devs;
ssize_t cnt;
int opt;
int ret, i;
int pid = 0x6001, vid = 0x0403;
int reg_addr = 0, reg_data = 0;
char reg_addr_set = 0, reg_data_set = 0;
char vid_set = 0, pid_set = 0;
unsigned char datas[32];
union FTDI_EEPROM eeprom = {0};
while((opt = getopt(argc, argv, "hvV:P:a:d:")) != -1) {
switch(opt)
{
case 'h':
usage(argc, argv);
return 0;
case 'v':
verbose++;
break;
case 'P':
pid_set = 1;
pid = strtol(optarg, NULL, 0);
break;
case 'V':
vid_set = 1;
vid = strtol(optarg, NULL, 0);
break;
case 'a':
reg_addr_set = 1;
reg_addr = strtol(optarg, NULL, 0);
break;
case 'd':
reg_data_set = 1;
reg_data = strtol(optarg, NULL ,0);
break;
default:
usage(argc, argv);
return -1;
}
}
if (optind >= argc) {
usage(argc, argv);
fprintf(stderr, "Error: No command\n");
return -1;
}
if (!strcmp(argv[optind], "list")) {
ret = libusb_init(NULL);
if (ret < 0)
return ret;
cnt = libusb_get_device_list(NULL, &devs);
if (cnt < 0)
return (int)cnt;
for (i = 0; devs[i]; i++) {
//filter for FTDI PID VID
struct libusb_device_descriptor desc;
if (libusb_get_device_descriptor(devs[i], &desc) < 0) {
fprintf(stderr, "failed to get device descriptor\n");
continue;
}
usb_print_device(devs[i]);
}
libusb_free_device_list(devs, 1);
libusb_exit(NULL);
} else if (!strcmp(argv[optind], "dump")) {
if (!vid_set) {
printf("VID use default value : 0x%04X\n", vid);
}
if (!pid_set) {
printf("PID use default value : 0x%04X\n", pid);
}
ret = libusb_init(NULL);
if (ret < 0)
return ret;
devh = libusb_open_device_with_vid_pid(NULL, vid, pid);
if (!devh) {
fprintf(stderr, "failed to open VID:%04X PID:%04X\n", vid, pid);
return -1;
}
for(int index = 0; index <= 127; index++) {
ret = libusb_control_transfer(devh,
0xc0, //bmRequestType
0x90, //bRequest
0, //wValue
index, //wIndex
datas, //data
2, //wLength
100 //timeout
);
if (ret < 0) {
fprintf(stderr," getting data error %d\n",ret);
break;
}
eeprom.data[index * 2] = datas[0];
eeprom.data[index * 2 + 1] = datas[1];
}
ftdi_eeprom_dump(eeprom);
ftdi_eeprom_print(eeprom);
printf("checksum %04X\n",ftdi_eeprom_checksum(eeprom));
libusb_exit(NULL);
} else if (!strcmp(argv[optind], "write")) {
if (!vid_set) {
printf("VID use default value : 0x%04X\n", vid);
}
if (!pid_set) {
printf("PID use default value : 0x%04X\n", pid);
}
if (!reg_addr_set || !reg_data_set) {
usage(argc,argv);
fprintf(stderr,"need define addr (-a), \n"
" data (-d) \n");
return -1;
}
ret = libusb_init(NULL);
if (ret < 0)
return ret;
devh = libusb_open_device_with_vid_pid(NULL, vid, pid);
if (!devh) {
fprintf(stderr, "failed to open VID:%04X PID:%04X\n", vid, pid);
return -1;
}
for(int index = 0; index <= 127; index++) {
ret = libusb_control_transfer(devh,
0xc0, //bmRequestType
0x90, //bRequest
0, //wValue
index, //wIndex
datas, //data
2, //wLength
100 //timeout
);
if (ret < 0) {
fprintf(stderr, " getting data error %d\n", ret);
break;
}
eeprom.data[index * 2] = datas[0];
eeprom.data[index * 2 + 1] = datas[1];
}
if (verbose) {
ftdi_eeprom_dump(eeprom);
}
uint16_t *reg_ptr = (uint16_t*)&eeprom.data[reg_addr];
printf("[current data] data[0x%02X] = 0x%04X\n", reg_addr, *reg_ptr);
if (*reg_ptr != reg_data) {
*reg_ptr = reg_data;
printf("[new data] data[0x%02X] = 0x%04X\n", reg_addr, *reg_ptr);
eeprom.info.checksum = ftdi_eeprom_checksum(eeprom);
if (verbose) {
ftdi_eeprom_dump(eeprom);
}
ftdi_eeprom_write_prepare(devh);
//Erase FTDI_EEPROM
usb_control_transfer(devh, 0x40, 0x92, 0, 0x00, 0x00, 0, 100);
for(int index = 0; index <= 127; index++) {
reg_data = (eeprom.data[index * 2 + 1] << 8) | eeprom.data[index * 2];
usb_control_transfer(devh, 0x40, 0x91, reg_data,index, NULL, 0, 100);
}
}else{
printf(" data not changed, ignore write process\n");
}
libusb_exit(NULL);
} else if (!strcmp(argv[optind], "useExtOsc")) {
if (!reg_data_set) {
usage(argc, argv);
fprintf(stderr, "need define data (-d) \n"
" -d 1 enable external oscillator\n"
" -d 0 disable external oscillator\n");
return -1;
}
ret = libusb_init(NULL);
if (ret < 0)
return ret;
devh = libusb_open_device_with_vid_pid(NULL, vid, pid);
if (!devh) {
fprintf(stderr, "failed to open VID:%04X PID:%04X\n", vid, pid);
return -1;
}
for(int index = 0; index <= 127; index++) {
ret = libusb_control_transfer(devh,
0xc0, //bmRequestType
0x90, //bRequest
0, //wValue
index, //wIndex
datas, //data
2, //wLength
100 //timeout
);
if (ret < 0) {
fprintf(stderr, " getting data error %d\n", ret);
break;
}
eeprom.data[index * 2] = datas[0];
eeprom.data[index * 2 + 1] = datas[1];
}
if (verbose) {
ftdi_eeprom_dump(eeprom);
}
printf("[current config] useExtOsc = %d\n", eeprom.info.useExtOsc);
if (eeprom.info.useExtOsc != reg_data) {
eeprom.info.useExtOsc = 1 - eeprom.info.useExtOsc;
printf("[new config] useExtOsc = %d\n", eeprom.info.useExtOsc);
eeprom.info.checksum = ftdi_eeprom_checksum(eeprom);
if (verbose) {
ftdi_eeprom_dump(eeprom);
}
ftdi_eeprom_write_prepare(devh);
//Erase FTDI_EEPROM
usb_control_transfer(devh, 0x40, 0x92, 0, 0x00, 0x00, 0, 100);
for(int index = 0; index <= 127; index++) {
reg_data = (eeprom.data[index * 2 + 1] << 8) | eeprom.data[index * 2];
usb_control_transfer(devh, 0x40, 0x91, reg_data, index, NULL, 0, 100);
}
}else{
printf(" data not changed, ignore write process\n");
}
libusb_exit(NULL);
} else if (!strcmp(argv[optind], "restore")) {
ret = libusb_init(NULL);
if (ret < 0)
return ret;
devh = libusb_open_device_with_vid_pid(NULL, vid, pid);
if (!devh) {
fprintf(stderr, "failed to open VID:%04X PID:%04X\n", vid, pid);
return -1;
}
uint16_t original[] = {
0x4000, 0x0403, 0x6001, 0x0000, 0x2DA0, 0x0008, 0x0000, 0x0A98,
0x20A2, 0x12C2, 0x1023, 0x0005, 0x030A, 0x0046, 0x0054, 0x0044,
0x0049, 0x0320, 0x0046, 0x0054, 0x0032, 0x0033, 0x0032, 0x0052,
0x0020, 0x0055, 0x0053, 0x0042, 0x0020, 0x0055, 0x0041, 0x0052,
0x0054, 0x0312, 0x0041, 0x0043, 0x0030, 0x0031, 0x0036, 0x0032,
0x0036, 0x0030, 0xEBD9, 0xC0B3, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x51B6,
0x042C, 0xFBD3, 0x0000, 0xEBD9, 0xC0B3, 0x0042, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x4143, 0x5258, 0x5558, 0x4A41,
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF
};
memcpy(eeprom.data, original, FTDI_EEPROM_SIZE);
if (verbose) {
ftdi_eeprom_dump(eeprom);
ftdi_eeprom_print(eeprom);
}
ftdi_eeprom_write_prepare(devh);
//Erase FTDI_EEPROM
usb_control_transfer(devh, 0x40, 0x92, 0, 0x00, NULL, 0, 100);
for(int index = 0; index <= 127; index++) {
reg_data = (eeprom.data[index * 2 + 1] << 8) | eeprom.data[index * 2];
libusb_control_transfer(devh, 0x40, 0x91, reg_data, index, NULL, 0, 100);
}
libusb_exit(NULL);
} else {
usage(argc, argv);
fprintf(stderr, "Error: command invalid.\n");
return -1;
}
return 0;
}