int main()

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;
}