📄 ftdi.c
字号:
ftdi->bitbang_enabled = 1; return 0;}/** Disable bitbang mode. \param ftdi pointer to ftdi_context \retval 0: all fine \retval -1: can't disable bitbang mode*/int ftdi_disable_bitbang(struct ftdi_context *ftdi){ if (usb_control_msg(ftdi->usb_dev, 0x40, 0x0B, 0, ftdi->index, NULL, 0, ftdi->usb_write_timeout) != 0) ftdi_error_return(-1, "unable to leave bitbang mode. Perhaps not a BM type chip?"); ftdi->bitbang_enabled = 0; return 0;}/** Enable advanced bitbang mode for FT2232C chips. \param ftdi pointer to ftdi_context \param bitmask Bitmask to configure lines. HIGH/ON value configures a line as output. \param mode Bitbang mode: 1 for normal mode, 2 for SPI mode \retval 0: all fine \retval -1: can't enable bitbang mode*/int ftdi_set_bitmode(struct ftdi_context *ftdi, unsigned char bitmask, unsigned char mode){ unsigned short usb_val; usb_val = bitmask; // low byte: bitmask usb_val |= (mode << 8); if (usb_control_msg(ftdi->usb_dev, 0x40, 0x0B, usb_val, ftdi->index, NULL, 0, ftdi->usb_write_timeout) != 0) ftdi_error_return(-1, "unable to configure bitbang mode. Perhaps not a 2232C type chip?"); ftdi->bitbang_mode = mode; ftdi->bitbang_enabled = (mode == BITMODE_BITBANG || mode == BITMODE_SYNCBB)?1:0; return 0;}/** Directly read pin state. Useful for bitbang mode. \param ftdi pointer to ftdi_context \param pins Pointer to store pins into \retval 0: all fine \retval -1: read pins failed*/int ftdi_read_pins(struct ftdi_context *ftdi, unsigned char *pins){ if (usb_control_msg(ftdi->usb_dev, 0xC0, 0x0C, 0, ftdi->index, (char *)pins, 1, ftdi->usb_read_timeout) != 1) ftdi_error_return(-1, "read pins failed"); return 0;}/** Set latency timer The FTDI chip keeps data in the internal buffer for a specific amount of time if the buffer is not full yet to decrease load on the usb bus. \param ftdi pointer to ftdi_context \param latency Value between 1 and 255 \retval 0: all fine \retval -1: latency out of range \retval -2: unable to set latency timer*/int ftdi_set_latency_timer(struct ftdi_context *ftdi, unsigned char latency){ unsigned short usb_val; if (latency < 1) ftdi_error_return(-1, "latency out of range. Only valid for 1-255"); usb_val = latency; if (usb_control_msg(ftdi->usb_dev, 0x40, 0x09, usb_val, ftdi->index, NULL, 0, ftdi->usb_write_timeout) != 0) ftdi_error_return(-2, "unable to set latency timer"); return 0;}/** Get latency timer \param ftdi pointer to ftdi_context \param latency Pointer to store latency value in \retval 0: all fine \retval -1: unable to get latency timer*/int ftdi_get_latency_timer(struct ftdi_context *ftdi, unsigned char *latency){ unsigned short usb_val; if (usb_control_msg(ftdi->usb_dev, 0xC0, 0x0A, 0, ftdi->index, (char *)&usb_val, 1, ftdi->usb_read_timeout) != 1) ftdi_error_return(-1, "reading latency timer failed"); *latency = (unsigned char)usb_val; return 0;}/** Init eeprom with default values. \param eeprom Pointer to ftdi_eeprom*/void ftdi_eeprom_initdefaults(struct ftdi_eeprom *eeprom){ eeprom->vendor_id = 0x0403; eeprom->product_id = 0x6001; eeprom->self_powered = 1; eeprom->remote_wakeup = 1; eeprom->BM_type_chip = 1; eeprom->in_is_isochronous = 0; eeprom->out_is_isochronous = 0; eeprom->suspend_pull_downs = 0; eeprom->use_serial = 0; eeprom->change_usb_version = 0; eeprom->usb_version = 0x0200; eeprom->max_power = 0; eeprom->manufacturer = NULL; eeprom->product = NULL; eeprom->serial = NULL;}/** Build binary output from ftdi_eeprom structure. Output is suitable for ftdi_write_eeprom(). \param eeprom Pointer to ftdi_eeprom \param output Buffer of 128 bytes to store eeprom image to \retval >0: used eeprom size \retval -1: eeprom size (128 bytes) exceeded by custom strings*/int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output){ unsigned char i, j; unsigned short checksum, value; unsigned char manufacturer_size = 0, product_size = 0, serial_size = 0; int size_check; if (eeprom->manufacturer != NULL) manufacturer_size = strlen(eeprom->manufacturer); if (eeprom->product != NULL) product_size = strlen(eeprom->product); if (eeprom->serial != NULL) serial_size = strlen(eeprom->serial); size_check = 128; // eeprom is 128 bytes size_check -= 28; // 28 are always in use (fixed) size_check -= manufacturer_size*2; size_check -= product_size*2; size_check -= serial_size*2; // eeprom size exceeded? if (size_check < 0) return (-1); // empty eeprom memset (output, 0, 128); // Addr 00: Stay 00 00 // Addr 02: Vendor ID output[0x02] = eeprom->vendor_id; output[0x03] = eeprom->vendor_id >> 8; // Addr 04: Product ID output[0x04] = eeprom->product_id; output[0x05] = eeprom->product_id >> 8; // Addr 06: Device release number (0400h for BM features) output[0x06] = 0x00; if (eeprom->BM_type_chip == 1) output[0x07] = 0x04; else output[0x07] = 0x02; // Addr 08: Config descriptor // Bit 1: remote wakeup if 1 // Bit 0: self powered if 1 // j = 0; if (eeprom->self_powered == 1) j = j | 1; if (eeprom->remote_wakeup == 1) j = j | 2; output[0x08] = j; // Addr 09: Max power consumption: max power = value * 2 mA output[0x09] = eeprom->max_power; ; // Addr 0A: Chip configuration // Bit 7: 0 - reserved // Bit 6: 0 - reserved // Bit 5: 0 - reserved // Bit 4: 1 - Change USB version // Bit 3: 1 - Use the serial number string // Bit 2: 1 - Enable suspend pull downs for lower power // Bit 1: 1 - Out EndPoint is Isochronous // Bit 0: 1 - In EndPoint is Isochronous // j = 0; if (eeprom->in_is_isochronous == 1) j = j | 1; if (eeprom->out_is_isochronous == 1) j = j | 2; if (eeprom->suspend_pull_downs == 1) j = j | 4; if (eeprom->use_serial == 1) j = j | 8; if (eeprom->change_usb_version == 1) j = j | 16; output[0x0A] = j; // Addr 0B: reserved output[0x0B] = 0x00; // Addr 0C: USB version low byte when 0x0A bit 4 is set // Addr 0D: USB version high byte when 0x0A bit 4 is set if (eeprom->change_usb_version == 1) { output[0x0C] = eeprom->usb_version; output[0x0D] = eeprom->usb_version >> 8; } // Addr 0E: Offset of the manufacturer string + 0x80 output[0x0E] = 0x14 + 0x80; // Addr 0F: Length of manufacturer string output[0x0F] = manufacturer_size*2 + 2; // 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; // Dynamic content output[0x14] = manufacturer_size*2 + 2; output[0x15] = 0x03; // type: string i = 0x16, j = 0; // Output manufacturer for (j = 0; j < manufacturer_size; j++) { output[i] = eeprom->manufacturer[j], i++; output[i] = 0x00, i++; } // 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++; } // calculate checksum checksum = 0xAAAA; for (i = 0; i < 63; i++) { value = output[i*2]; value += output[(i*2)+1] << 8; checksum = value^checksum; checksum = (checksum << 1) | (checksum >> 15); } output[0x7E] = checksum; output[0x7F] = checksum >> 8; return size_check;}/** Read eeprom \param ftdi pointer to ftdi_context \param eeprom Pointer to store eeprom into \retval 0: all fine \retval -1: read failed*/int ftdi_read_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom){ int i; for (i = 0; i < 64; i++) { if (usb_control_msg(ftdi->usb_dev, 0xC0, 0x90, 0, i, eeprom+(i*2), 2, ftdi->usb_read_timeout) != 2) ftdi_error_return(-1, "reading eeprom failed"); } return 0;}/** Write eeprom \param ftdi pointer to ftdi_context \param eeprom Pointer to read eeprom from \retval 0: all fine \retval -1: read failed*/int ftdi_write_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom){ unsigned short usb_val; int i; for (i = 0; i < 64; i++) { usb_val = eeprom[i*2]; usb_val += eeprom[(i*2)+1] << 8; if (usb_control_msg(ftdi->usb_dev, 0x40, 0x91, usb_val, i, NULL, 0, ftdi->usb_write_timeout) != 0) ftdi_error_return(-1, "unable to write eeprom"); } return 0;}/** Erase eeprom \param ftdi pointer to ftdi_context \retval 0: all fine \retval -1: erase failed*/int ftdi_erase_eeprom(struct ftdi_context *ftdi){ if (usb_control_msg(ftdi->usb_dev, 0x40, 0x92, 0, 0, NULL, 0, ftdi->usb_write_timeout) != 0) ftdi_error_return(-1, "unable to erase eeprom"); return 0;}/** Get string representation for last error code \param ftdi pointer to ftdi_context \retval Pointer to error string*/char *ftdi_get_error_string (struct ftdi_context *ftdi){ return ftdi->error_str;}/* Flow control code by Lorenz Moesenlechner (lorenz@hcilab.org) and Matthias Kranz (matthias@hcilab.org)*//** Set flowcontrol for ftdi chip \param ftdi pointer to ftdi_context \param flowctrl flow control to use. should be SIO_DISABLE_FLOW_CTRL, SIO_RTS_CTS_HS, SIO_DTR_DSR_HS or SIO_XON_XOFF_HS \retval 0: all fine \retval -1: set flow control failed*/int ftdi_setflowctrl(struct ftdi_context *ftdi, int flowctrl){ if (usb_control_msg(ftdi->usb_dev, SIO_SET_FLOW_CTRL_REQUEST_TYPE, SIO_SET_FLOW_CTRL_REQUEST, 0, (flowctrl | ftdi->interface), NULL, 0, ftdi->usb_write_timeout) != 0) ftdi_error_return(-1, "set flow control failed"); return 0;}/** Set dtr line \param ftdi pointer to ftdi_context \param state state to set line to (1 or 0) \retval 0: all fine \retval -1: set dtr failed*/int ftdi_setdtr(struct ftdi_context *ftdi, int state){ unsigned short usb_val; if (state) usb_val = SIO_SET_DTR_HIGH; else usb_val = SIO_SET_DTR_LOW; if (usb_control_msg(ftdi->usb_dev, SIO_SET_MODEM_CTRL_REQUEST_TYPE, SIO_SET_MODEM_CTRL_REQUEST, usb_val, ftdi->interface, NULL, 0, ftdi->usb_write_timeout) != 0) ftdi_error_return(-1, "set dtr failed"); return 0;}/** Set rts line \param ftdi pointer to ftdi_context \param state state to set line to (1 or 0) \retval 0: all fine \retval -1 set rts failed*/int ftdi_setrts(struct ftdi_context *ftdi, int state){ unsigned short usb_val; if (state) usb_val = SIO_SET_RTS_HIGH; else usb_val = SIO_SET_RTS_LOW; if (usb_control_msg(ftdi->usb_dev, SIO_SET_MODEM_CTRL_REQUEST_TYPE, SIO_SET_MODEM_CTRL_REQUEST, usb_val, ftdi->interface, NULL, 0, ftdi->usb_write_timeout) != 0) ftdi_error_return(-1, "set of rts failed"); return 0;}/* @} end of doxygen libftdi group */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -