From ff764a61a066b50152ebbf705a6bc94791c4cbf5 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Fri, 24 Mar 2023 15:51:12 +0300 Subject: [PATCH 1/7] fix large page handling --- Makefile | 2 +- ch341eeprom.c | 426 ++++++++++++++++++++++++++------------------------ ch341eeprom.h | 378 +++++++++----------------------------------- ch341funcs.c | 325 +++++++++++++++++++------------------- 4 files changed, 448 insertions(+), 683 deletions(-) diff --git a/Makefile b/Makefile index 6db6fc0..a1ffd9e 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -CC = clang +CC = gcc CFLAGS = -Wall -O2 default: diff --git a/ch341eeprom.c b/ch341eeprom.c index 9a4159d..26d2c22 100644 --- a/ch341eeprom.c +++ b/ch341eeprom.c @@ -18,7 +18,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#include +#include #include #include #include @@ -33,271 +33,286 @@ FILE *debugout, *verbout; uint8_t *readbuf = NULL; -int main(int argc, char **argv) { +int main(int argc, char **argv) +{ int i, eepromsize = 0, bytesread = 0; uint8_t debug = FALSE, verbose = FALSE; struct libusb_device_handle *devHandle = NULL; - char *filename = NULL, eepromname[12], operation = 0; + char *filename = NULL, *eepromname, operation = 0; uint32_t speed = CH341_I2C_STANDARD_SPEED; uint8_t *verifybuf; uint8_t verify_failed = FALSE; FILE *fp; - struct EEPROM eeprom_info; + const struct EEPROM *eeprom_info; - static char version_msg[] = - "ch341eeprom - an i2c EEPROM programming tool for the WCH CH341a IC\n" \ - "Version " CH341TOOLVERSION " copyright (c) 2011 asbokid \n\n" \ - "This program comes with absolutely no warranty; This is free software,\n" \ - "and you are welcome to redistribute it under certain conditions:\n" \ - "GNU GPL v3 License: http://www.gnu.org/licenses/gpl.html\n"; + static char version_msg[] = + "ch341eeprom - an i2c EEPROM programming tool for the WCH CH341a IC\n" + "Version " CH341TOOLVERSION + " copyright (c) 2011 asbokid \n\n" + "This program comes with absolutely no warranty; This is free software,\n" + "and you are welcome to redistribute it under certain conditions:\n" "GNU GPL v3 License: http://www.gnu.org/licenses/gpl.html\n"; - static char usage_msg[] = - "Usage:\n" \ - " -h, --help display this text\n" \ - " -v, --verbose verbose output\n" \ - " -d, --debug debug output\n" \ - " -s, --size size of EEPROM {24c01|24c02|24c04|24c08|24c16|24c32|24c64|24c128|24c256|24c512|24c1024}\n" \ - " -e, --erase erase EEPROM (fill with 0xff)\n" \ - " -p, --speed i2c speed (low|fast|high) if different than standard which is default\n" \ - " -w, --write write EEPROM with image from filename\n" \ - " -r, --read read EEPROM and save image to filename\n" \ - " -V, --verify verify EEPROM contents against image in filename\n\n" \ - "Example: ch341eeprom -v -s 24c64 -w bootrom.bin\n"; + static char usage_msg[] = + "Usage:\n" + " -h, --help display this text\n" + " -v, --verbose verbose output\n" + " -d, --debug debug output\n" + " -s, --size size of EEPROM {24c01|24c02|24c04|24c08|24c16|24c32|24c64|24c128|24c256|24c512|24c1024}\n" + " -e, --erase erase EEPROM (fill with 0xff)\n" + " -p, --speed i2c speed (low|fast|high) if different than standard which is default\n" + " -w, --write write EEPROM with image from filename\n" + " -r, --read read EEPROM and save image to filename\n" + " -V, --verify verify EEPROM contents against image in filename\n\n" "Example: ch341eeprom -v -s 24c64 -w bootrom.bin\n"; static struct option longopts[] = { - {"help", no_argument, 0, 'h'}, - {"verbose", no_argument, 0, 'v'}, - {"debug", no_argument, 0, 'd'}, - {"erase", no_argument, 0, 'e'}, - {"size", required_argument, 0, 's'}, - {"speed", required_argument, 0, 'p'}, - {"read", required_argument, 0, 'r'}, - {"write", required_argument, 0, 'w'}, - {"verify", required_argument, 0, 'V'}, - {0, 0, 0, 0} + { "help", no_argument, 0, 'h' }, + { "verbose", no_argument, 0, 'v' }, + { "debug", no_argument, 0, 'd' }, + { "erase", no_argument, 0, 'e' }, + { "size", required_argument, 0, 's' }, + { "speed", required_argument, 0, 'p' }, + { "read", required_argument, 0, 'r' }, + { "write", required_argument, 0, 'w' }, + { "verify", required_argument, 0, 'V' }, + { 0, 0, 0, 0 } }; - static int speed_table[] = {20, 100, 400, 750}; + static int speed_table[] = { 20, 100, 400, 750 }; while (TRUE) { int32_t optidx = 0; - int8_t c = getopt_long(argc,argv,"hvdes:p:w:r:V:", longopts, &optidx); + int8_t c = getopt_long(argc, argv, "hvdes:p:w:r:V:", longopts, + &optidx); if (c == -1) break; switch (c) { - case 'h': fprintf(stdout, "%s\n%s", version_msg, usage_msg); - return 0; - case 'v': verbose = TRUE; - break; - case 'd': debug = TRUE; - break; - case 's': if((eepromsize = parseEEPsize(optarg, &eeprom_info)) > 0) - strncpy(eepromname, optarg, 10); - break; - case 'p': if(strstr(optarg, "low")) - speed = CH341_I2C_LOW_SPEED; - else if(strstr(optarg, "fast")) - speed = CH341_I2C_FAST_SPEED; - else if(strstr(optarg, "high")) - speed = CH341_I2C_HIGH_SPEED; - else - speed = CH341_I2C_STANDARD_SPEED; - break; - case 'e': if(!operation) - operation = 'e'; - else { - fprintf(stderr, "Conflicting command line options\n"); - goto shutdown; - } - break; - case 'r': if(!operation) { - operation = 'r'; - filename = (char *) malloc(strlen(optarg)+1); - strcpy(filename, optarg); - } else { - fprintf(stderr, "Conflicting command line options\n"); - goto shutdown; - } - break; - case 'w': if(!operation) { - operation = 'w'; - filename = (char *) malloc(strlen(optarg)+1); - strcpy(filename, optarg); - } else { - fprintf(stderr, "Conflicting command line options\n"); - goto shutdown; - } - break; - case 'V': if(!operation) { - operation = 'V'; - filename = (char *) malloc(strlen(optarg)+1); - strcpy(filename, optarg); - } else { - fprintf(stderr, "Conflicting command line options\n"); - goto shutdown; - } - break; - default : - case '?': fprintf(stdout, "%s", version_msg); - fprintf(stderr, "%s", usage_msg); - goto shutdown; + case 'h': + fprintf(stdout, "%s\n%s", version_msg, usage_msg); + return 0; + case 'v': + verbose = TRUE; + break; + case 'd': + debug = TRUE; + break; + case 's': + if ((eepromsize = parseEEPsize(optarg, &eeprom_info)) > 0) + eepromname = optarg; + break; + case 'p': + if (strstr(optarg, "low")) + speed = CH341_I2C_LOW_SPEED; + else if (strstr(optarg, "fast")) + speed = CH341_I2C_FAST_SPEED; + else if (strstr(optarg, "high")) + speed = CH341_I2C_HIGH_SPEED; + else + speed = CH341_I2C_STANDARD_SPEED; + break; + case 'e': + if (!operation) + operation = 'e'; + else { + fprintf(stderr, "Conflicting command line options\n"); + goto shutdown; + } + break; + case 'r': + if (!operation) { + operation = 'r'; + filename = (char *)malloc(strlen(optarg) + 1); + strcpy(filename, optarg); + } else { + fprintf(stderr, "Conflicting command line options\n"); + goto shutdown; + } + break; + case 'w': + if (!operation) { + operation = 'w'; + filename = (char *)malloc(strlen(optarg) + 1); + strcpy(filename, optarg); + } else { + fprintf(stderr, "Conflicting command line options\n"); + goto shutdown; + } + break; + case 'V': + if (!operation) { + operation = 'V'; + filename = (char *)malloc(strlen(optarg) + 1); + strcpy(filename, optarg); + } else { + fprintf(stderr, "Conflicting command line options\n"); + goto shutdown; + } + break; + default: + case '?': + fprintf(stdout, "%s", version_msg); + fprintf(stderr, "%s", usage_msg); + goto shutdown; } } - debugout = (debug == TRUE) ? stdout : fopen("/dev/null","w"); - verbout = (verbose == TRUE) ? stdout : fopen("/dev/null","w"); - fprintf(debugout, "Debug Enabled\n"); + debugout = (debug == TRUE) ? stdout : fopen("/dev/null", "w"); + verbout = (verbose == TRUE) ? stdout : fopen("/dev/null", "w"); + fprintf(debugout, "Debug Enabled\n"); - if(!operation) { + if (!operation) { fprintf(stderr, "%s\n%s", version_msg, usage_msg); goto shutdown; - } - - if(eepromsize <= 0) { + } + + if (eepromsize <= 0) { fprintf(stderr, "Invalid EEPROM size\n"); goto shutdown; } - readbuf = (uint8_t *) malloc(MAX_EEPROM_SIZE); // space to store loaded EEPROM - if(!readbuf) { + readbuf = (uint8_t *) malloc(MAX_EEPROM_SIZE); // space to store loaded EEPROM + if (!readbuf) { fprintf(stderr, "Couldnt malloc space needed for EEPROM image\n"); goto shutdown; } - if(!(devHandle = ch341configure(USB_LOCK_VENDOR, USB_LOCK_PRODUCT))) { + if (!(devHandle = ch341configure(USB_LOCK_VENDOR, USB_LOCK_PRODUCT))) { fprintf(stderr, "Couldnt configure USB device with vendor ID: %04x product ID: %04x\n", USB_LOCK_VENDOR, USB_LOCK_PRODUCT); goto shutdown; } fprintf(verbout, "Configured USB device with vendor ID: %04x product ID: %04x\n", USB_LOCK_VENDOR, USB_LOCK_PRODUCT); - if(ch341setstream(devHandle, speed) < 0) { + if (ch341setstream(devHandle, speed) < 0) { fprintf(stderr, "Couldnt set i2c bus speed\n"); goto shutdown; } - fprintf(verbout, "Set i2c bus speed to [%dkHz]\n", speed_table[speed]); + fprintf(verbout, "Set i2c bus speed to [%d kHz]\n", speed_table[speed]); - switch(operation) { - case 'r': // read - memset(readbuf, 0xff, MAX_EEPROM_SIZE); + switch (operation) { + case 'r': // read + memset(readbuf, 0xff, MAX_EEPROM_SIZE); - if(ch341readEEPROM(devHandle, readbuf, eepromsize, &eeprom_info) < 0) { - fprintf(stderr, "Couldnt read [%d] bytes from [%s] EEPROM\n", eepromsize, eepromname); - goto shutdown; - } - fprintf(stdout, "Read [%d] bytes from [%s] EEPROM\n", eepromsize, eepromname); - for(i=0;i eepromsize) - fprintf(stdout, "Truncated to [%d] bytes for [%s] EEPROM\n", eepromsize, eepromname); + if (bytesread < eepromsize) + fprintf(stdout, "Padded to [%d] bytes for [%s] EEPROM\n", eepromsize, eepromname); - if(ch341writeEEPROM(devHandle, readbuf, eepromsize, &eeprom_info) < 0) { - fprintf(stderr,"Failed to write [%d] bytes from [%s] to [%s] EEPROM\n", eepromsize, filename, eepromname); - goto shutdown; - } - fprintf(stdout, "Wrote [%d] bytes to [%s] EEPROM\n", eepromsize, eepromname); - break; - case 'e': // erase - memset(readbuf, 0xff, MAX_EEPROM_SIZE); - if(ch341writeEEPROM(devHandle, readbuf, eepromsize, &eeprom_info) < 0) { - fprintf(stderr,"Failed to erase [%d] bytes of [%s] EEPROM\n", eepromsize, eepromname); - goto shutdown; - } - fprintf(stdout, "Erased [%d] bytes of [%s] EEPROM\n", eepromsize, eepromname); - break; - default: - fprintf(stderr, "Unknown option\n"); + if (bytesread > eepromsize) + fprintf(stdout, "Truncated to [%d] bytes for [%s] EEPROM\n", eepromsize, eepromname); + + if (ch341writeEEPROM(devHandle, readbuf, eepromsize, eeprom_info) < 0) { + fprintf(stderr, "Failed to write [%d] bytes from [%s] to [%s] EEPROM\n", eepromsize, filename, eepromname); goto shutdown; } + fprintf(stdout, "Wrote [%d] bytes to [%s] EEPROM\n", eepromsize, eepromname); + break; + case 'e': // erase + memset(readbuf, 0xff, MAX_EEPROM_SIZE); + if (ch341writeEEPROM(devHandle, readbuf, eepromsize, eeprom_info) < 0) { + fprintf(stderr, "Failed to erase [%d] bytes of [%s] EEPROM\n", eepromsize, eepromname); + goto shutdown; + } + fprintf(stdout, "Erased [%d] bytes of [%s] EEPROM\n", eepromsize, eepromname); + break; + default: + fprintf(stderr, "Unknown option\n"); + goto shutdown; + } shutdown: - if(readbuf) + if (readbuf) free(readbuf); - if(filename) + if (filename) free(filename); - if(devHandle) { + if (devHandle) { libusb_release_interface(devHandle, DEFAULT_INTERFACE); fprintf(debugout, "Released device interface [%d]\n", DEFAULT_INTERFACE); libusb_close(devHandle); @@ -306,4 +321,3 @@ int main(int argc, char **argv) { } return 0; } - diff --git a/ch341eeprom.h b/ch341eeprom.h index 0704207..7cab1fb 100644 --- a/ch341eeprom.h +++ b/ch341eeprom.h @@ -4,335 +4,97 @@ #define CH341TOOLVERSION "0.5" -#define USB_LOCK_VENDOR 0x1a86 // Dev : (1a86) QinHeng Electronics -#define USB_LOCK_PRODUCT 0x5512 // (5512) CH341A in i2c mode +#define USB_LOCK_VENDOR 0x1a86 // Dev : (1a86) QinHeng Electronics +#define USB_LOCK_PRODUCT 0x5512 // (5512) CH341A in i2c mode - -#define MAX_EEPROM_SIZE 131072 /* For 24c1024*/ +#define MAX_EEPROM_SIZE 131072 /* For 24c1024 */ #define EEPROM_I2C_BUS_ADDRESS 0x50 -#define BULK_WRITE_ENDPOINT 0x02 /* bEndpointAddress 0x02 EP 2 OUT (Bulk)*/ -#define BULK_READ_ENDPOINT 0x82 /* bEndpointAddress 0x82 EP 2 IN (Bulk)*/ +#define BULK_WRITE_ENDPOINT 0x02 /* bEndpointAddress 0x02 EP 2 OUT (Bulk) */ +#define BULK_READ_ENDPOINT 0x82 /* bEndpointAddress 0x82 EP 2 IN (Bulk) */ #define DEFAULT_INTERFACE 0x00 #define DEFAULT_CONFIGURATION 0x01 -#define DEFAULT_TIMEOUT 300 // 300mS for USB timeouts +#define DEFAULT_TIMEOUT 300 // 300mS for USB timeouts #define IN_BUF_SZ 0x100 -#define EEPROM_WRITE_BUF_SZ 0x2b // only for 24c64 / 24c32 ?? #define EEPROM_READ_BULKIN_BUF_SZ 0x20 -#define EEPROM_READ_BULKOUT_BUF_SZ 0x65 +#define EEPROM_READ_BULKOUT_BUF_SZ 0x100 /* Based on (closed-source) DLL V1.9 for USB by WinChipHead (c) 2005. Supports USB chips: CH341, CH341A This can be a problem for copyright, sure asbokid can't release this part on any GPL licence*/ -#define mCH341_PACKET_LENGTH 32 /* wMaxPacketSize 0x0020 1x 32 bytes, unused on the source*/ -#define mCH341_PKT_LEN_SHORT 8 /* wMaxPacketSize 0x0008 1x 8 bytes, unused on the source*/ +#define mCH341_PACKET_LENGTH 32 /* wMaxPacketSize 0x0020 1x 32 bytes, unused on the source */ +#define mCH341_PKT_LEN_SHORT 8 /* wMaxPacketSize 0x0008 1x 8 bytes, unused on the source */ -#define mCH341_ENDP_INTER_UP 0x81 /* bEndpointAddress 0x81 EP 1 IN (Interrupt), unused on the source*/ -#define mCH341_ENDP_INTER_DOWN 0x01 /* This endpoint isn't list on my lsusb -v output, unused on the source*/ -#define mCH341_ENDP_DATA_UP 0x82 /* ==BULK_READ_ENDPOINT Why repeat it?*/ -#define mCH341_ENDP_DATA_DOWN 0x02 /* ==BULK_WRITE_ENDPOINT Why repeat it?*/ +#define mCH341_ENDP_INTER_UP 0x81 /* bEndpointAddress 0x81 EP 1 IN (Interrupt), unused on the source */ +#define mCH341_ENDP_INTER_DOWN 0x01 /* This endpoint isn't list on my lsusb -v output, unused on the source */ +#define mCH341_ENDP_DATA_UP 0x82 /* ==BULK_READ_ENDPOINT Why repeat it? */ +#define mCH341_ENDP_DATA_DOWN 0x02 /* ==BULK_WRITE_ENDPOINT Why repeat it? */ -#define mCH341_VENDOR_READ 0xC0 /* Unused on the source*/ -#define mCH341_VENDOR_WRITE 0x40 /* Unused on the source*/ +#define mCH341_VENDOR_READ 0xC0 /* Unused on the source */ +#define mCH341_VENDOR_WRITE 0x40 /* Unused on the source */ -#define mCH341_PARA_INIT 0xB1 /* Unused on the source*/ -#define mCH341_I2C_STATUS 0x52 /* Unused on the source*/ -#define mCH341_I2C_COMMAND 0x53 /* Unused on the source*/ +#define mCH341_PARA_INIT 0xB1 /* Unused on the source */ +#define mCH341_I2C_STATUS 0x52 /* Unused on the source */ +#define mCH341_I2C_COMMAND 0x53 /* Unused on the source */ -#define mCH341_PARA_CMD_R0 0xAC /* Unused on the source*/ -#define mCH341_PARA_CMD_R1 0xAD /* Unused on the source*/ -#define mCH341_PARA_CMD_W0 0xA6 /* Unused on the source*/ -#define mCH341_PARA_CMD_W1 0xA7 /* Unused on the source*/ -#define mCH341_PARA_CMD_STS 0xA0 /* Unused on the source*/ +#define mCH341_PARA_CMD_R0 0xAC /* Unused on the source */ +#define mCH341_PARA_CMD_R1 0xAD /* Unused on the source */ +#define mCH341_PARA_CMD_W0 0xA6 /* Unused on the source */ +#define mCH341_PARA_CMD_W1 0xA7 /* Unused on the source */ +#define mCH341_PARA_CMD_STS 0xA0 /* Unused on the source */ -#define mCH341A_CMD_SET_OUTPUT 0xA1 /* Unused on the source*/ -#define mCH341A_CMD_IO_ADDR 0xA2 /* Unused on the source*/ -#define mCH341A_CMD_PRINT_OUT 0xA3 /* Unused on the source*/ -#define mCH341A_CMD_SPI_STREAM 0xA8 /* Unused on the source*/ -#define mCH341A_CMD_SIO_STREAM 0xA9 /* Unused on the source*/ +#define mCH341A_CMD_SET_OUTPUT 0xA1 /* Unused on the source */ +#define mCH341A_CMD_IO_ADDR 0xA2 /* Unused on the source */ +#define mCH341A_CMD_PRINT_OUT 0xA3 /* Unused on the source */ +#define mCH341A_CMD_SPI_STREAM 0xA8 /* Unused on the source */ +#define mCH341A_CMD_SIO_STREAM 0xA9 /* Unused on the source */ #define mCH341A_CMD_I2C_STREAM 0xAA -#define mCH341A_CMD_UIO_STREAM 0xAB /* Unused on the source*/ +#define mCH341A_CMD_UIO_STREAM 0xAB /* Unused on the source */ -#define mCH341A_BUF_CLEAR 0xB2 /* Unused on the source*/ -#define mCH341A_I2C_CMD_X 0x54 /* Unused on the source*/ -#define mCH341A_DELAY_MS 0x5E /* Unused on the source*/ -#define mCH341A_GET_VER 0x5F /* Unused on the source*/ +#define mCH341A_BUF_CLEAR 0xB2 /* Unused on the source */ +#define mCH341A_I2C_CMD_X 0x54 /* Unused on the source */ +#define mCH341A_DELAY_MS 0x5E /* Unused on the source */ +#define mCH341A_GET_VER 0x5F /* Unused on the source */ -#define mCH341_EPP_IO_MAX ( mCH341_PACKET_LENGTH - 1 ) /* Unused on the source*/ -#define mCH341A_EPP_IO_MAX 0xFF /* Unused on the source*/ +#define mCH341_EPP_IO_MAX ( mCH341_PACKET_LENGTH - 1 ) /* Unused on the source */ +#define mCH341A_EPP_IO_MAX 0xFF /* Unused on the source */ -#define mCH341A_CMD_IO_ADDR_W 0x00 /* Unused on the source*/ -#define mCH341A_CMD_IO_ADDR_R 0x80 /* Unused on the source*/ +#define mCH341A_CMD_IO_ADDR_W 0x00 /* Unused on the source */ +#define mCH341A_CMD_IO_ADDR_R 0x80 /* Unused on the source */ #define mCH341A_CMD_I2C_STM_STA 0x74 #define mCH341A_CMD_I2C_STM_STO 0x75 #define mCH341A_CMD_I2C_STM_OUT 0x80 #define mCH341A_CMD_I2C_STM_IN 0xC0 -#define mCH341A_CMD_I2C_STM_MAX ( min( 0x3F, mCH341_PACKET_LENGTH ) ) /* Unused on the source*/ +#define mCH341A_CMD_I2C_STM_MAX ( min( 0x3F, mCH341_PACKET_LENGTH ) ) /* Unused on the source */ #define mCH341A_CMD_I2C_STM_SET 0x60 -#define mCH341A_CMD_I2C_STM_US 0x40 /* Unused on the source*/ -#define mCH341A_CMD_I2C_STM_MS 0x50 /* Unused on the source*/ -#define mCH341A_CMD_I2C_STM_DLY 0x0F /* Unused on the source*/ +#define mCH341A_CMD_I2C_STM_US 0x40 /* Unused on the source */ +#define mCH341A_CMD_I2C_STM_MS 0x50 /* Unused on the source */ +#define mCH341A_CMD_I2C_STM_DLY 0x0F /* Unused on the source */ #define mCH341A_CMD_I2C_STM_END 0x00 -#define mCH341A_CMD_UIO_STM_IN 0x00 /* Unused on the source*/ -#define mCH341A_CMD_UIO_STM_DIR 0x40 /* Unused on the source*/ -#define mCH341A_CMD_UIO_STM_OUT 0x80 /* Unused on the source*/ -#define mCH341A_CMD_UIO_STM_US 0xC0 /* Unused on the source*/ -#define mCH341A_CMD_UIO_STM_END 0x20 /* Unused on the source*/ +#define mCH341A_CMD_UIO_STM_IN 0x00 /* Unused on the source */ +#define mCH341A_CMD_UIO_STM_DIR 0x40 /* Unused on the source */ +#define mCH341A_CMD_UIO_STM_OUT 0x80 /* Unused on the source */ +#define mCH341A_CMD_UIO_STM_US 0xC0 /* Unused on the source */ +#define mCH341A_CMD_UIO_STM_END 0x20 /* Unused on the source */ -#define mCH341_PARA_MODE_EPP 0x00 /* Unused on the source*/ -#define mCH341_PARA_MODE_EPP17 0x00 /* Unused on the source*/ -#define mCH341_PARA_MODE_EPP19 0x01 /* Unused on the source*/ -#define mCH341_PARA_MODE_MEM 0x02 /* Unused on the source*/ +#define mCH341_PARA_MODE_EPP 0x00 /* Unused on the source */ +#define mCH341_PARA_MODE_EPP17 0x00 /* Unused on the source */ +#define mCH341_PARA_MODE_EPP19 0x01 /* Unused on the source */ +#define mCH341_PARA_MODE_MEM 0x02 /* Unused on the source */ /* End of part based on (closed-source) DLL V1.9 for USB by WinChipHead (c) 2005. Since is largely unused we can replace it*/ - -#define CH341_I2C_LOW_SPEED 0 // low speed - 20kHz -#define CH341_I2C_STANDARD_SPEED 1 // standard speed - 100kHz -#define CH341_I2C_FAST_SPEED 2 // fast speed - 400kHz -#define CH341_I2C_HIGH_SPEED 3 // high speed - 750kHz - -#define CH341_EEPROM_READ_CMD_SZ 0x65 /* Same size for all 24cXX read setup and next packets*/ - -/* CH341a READ EEPROM setup packet for the 24c01 - this needs putting into a struct to allow convenient access to individual elements*/ -#define CH341_EEPROM_24c01_READ_SETUP_CMD "\xaa\x74\x82\xa0\x00\x74\x81\xa1\xe0\x00\x0f\x00\x06\x04\x00\x00" \ - "\x00\x00\x00\x00\x01\x00\x00\x00\x11\x4d\x40\x77\xcd\xab\xba\xdc" \ - "\xaa\xe0\x00\x00\xc4\xf1\x12\x00\x11\x4d\x40\x77\xf0\xf1\x12\x00" \ - "\xd9\x8b\x41\x7e\x00\xd0\xfd\x7f\xf0\xf1\x12\x00\x5a\x88\x41\x7e" \ - "\xaa\xe0\x00\x00\x2a\x88\x41\x7e\x06\x04\x00\x00\x11\x4d\x40\x77" \ - "\xe8\xf3\x12\x00\x14\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" \ - "\xaa\xdf\xc0\x75\x00" -/* please se file /wiresharkusbsniffing/sniffed.txt - this is the read setup packet for 24c01 - -0040 aa 74 82 a0 00 74 81 a1 e0 00 0f 00 06 04 00 00 .t...t.. ........ -0050 00 00 00 00 01 00 00 00 11 4d 40 77 cd ab ba dc ........ .M@w.... -0060 aa e0 00 00 c4 f1 12 00 11 4d 40 77 f0 f1 12 00 ........ .M@w.... -0070 d9 8b 41 7e 00 d0 fd 7f f0 f1 12 00 5a 88 41 7e ..A~.... ....Z.A~ -0080 aa e0 00 00 2a 88 41 7e 06 04 00 00 11 4d 40 77 ....*.A~ .....M@w -0090 e8 f3 12 00 14 00 00 00 01 00 00 00 00 00 00 00 ........ ........ -00a0 aa df c0 75 00 ...u. -*/ - -/* CH341a READ EEPROM next packet for 24c01 (no packets!!!)*/ - - -/* CH341a READ EEPROM setup packet for the 24c02 - this needs putting into a struct to allow convenient access to individual elements*/ -#define CH341_EEPROM_24c02_READ_SETUP_CMD "\xaa\x74\x82\xa0\x00\x74\x81\xa1\xe0\x00\x10\x00\x06\x04\x00\x00" \ - "\x00\x00\x00\x00\x02\x00\x00\x00\x11\x4d\x40\x77\xcd\xab\xba\xdc" \ - "\xaa\xe0\x00\x00\xc4\xf1\x12\x00\x11\x4d\x40\x77\xf0\xf1\x12\x00" \ - "\xd9\x8b\x41\x7e\x00\xf0\xfd\x7f\xf0\xf1\x12\x00\x5a\x88\x41\x7e" \ - "\xaa\xe0\x00\x00\x2a\x88\x41\x7e\x06\x04\x00\x00\x11\x4d\x40\x77" \ - "\xe8\xf3\x12\x00\x14\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" \ - "\xaa\xdf\xc0\x75\x00" -/* please se file /wiresharkusbsniffing/sniffed.txt - this is the read setup packet for 24c02 - -0040 aa 74 82 a0 00 74 81 a1 e0 00 10 00 06 04 00 00 .t...t.. ........ -0050 00 00 00 00 02 00 00 00 11 4d 40 77 cd ab ba dc ........ .M@w.... -0060 aa e0 00 00 c4 f1 12 00 11 4d 40 77 f0 f1 12 00 ........ .M@w.... -0070 d9 8b 41 7e 00 f0 fd 7f f0 f1 12 00 5a 88 41 7e ..A~.... ....Z.A~ -0080 aa e0 00 00 2a 88 41 7e 06 04 00 00 11 4d 40 77 ....*.A~ .....M@w -0090 e8 f3 12 00 14 00 00 00 01 00 00 00 00 00 00 00 ........ ........ -00a0 aa df c0 75 00 ...u. -*/ - -/* CH341a READ EEPROM next packet for 24c02 (one packet)*/ -#define CH341_EEPROM_24c02_READ_NEXT_CMD "\xaa\x74\x82\xa0\x80\x74\x81\xa1\xe0\x00\x00\x00\x10\x00\x00\x00" \ - "\x00\x00\x00\x00\x8c\xf1\x12\x00\x01\x00\x00\x00\x00\x00\x00\x00" \ - "\xaa\xe0\x00\x00\x4c\xf1\x12\x00\x5d\x22\xd7\x5a\xdc\xf1\x12\x00" \ - "\x8f\x04\x44\x7e\x30\x88\x41\x7e\xff\xff\xff\xff\x2a\x88\x41\x7e" \ - "\xaa\xe0\x00\x7e\x00\x00\x00\x00\x69\x0e\x3c\x00\xe4\x00\x18\x00" \ - "\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8c\xe8\x67\x00" \ - "\xaa\xdf\xc0\x75\x00" -/*please see file /wiresharkusbsniffing/sniffed.txt - this is the read next packet for 24c02 (one packet) - -0040 aa 74 82 a0 80 74 81 a1 e0 00 00 00 10 00 00 00 .t...t.. ........ -0050 00 00 00 00 8c f1 12 00 01 00 00 00 00 00 00 00 ........ ........ -0060 aa e0 00 00 4c f1 12 00 5d 22 d7 5a dc f1 12 00 ....L... ]".Z.... -0070 8f 04 44 7e 30 88 41 7e ff ff ff ff 2a 88 41 7e ..D~0.A~ ....*.A~ -0080 aa e0 00 7e 00 00 00 00 69 0e 3c 00 e4 00 18 00 ...~.... i.<..... -0090 0f 00 00 00 00 00 00 00 00 00 00 00 8c e8 67 00 ........ ......g. -00a0 aa df c0 75 00 ...u. -*/ - - -/* CH341a READ EEPROM setup packet for the 24c04 - this needs putting into a struct to allow convenient access to individual elements*/ -#define CH341_EEPROM_24c04_READ_SETUP_CMD "\xaa\x74\x82\xa0\x00\x74\x81\xa1\xe0\x00\x11\x00\x06\x04\x00\x00" \ - "\x00\x00\x00\x00\x04\x00\x00\x00\x11\x4d\x40\x77\xcd\xab\xba\xdc" \ - "\xaa\xe0\x00\x00\xc4\xf1\x12\x00\x11\x4d\x40\x77\xf0\xf1\x12\x00" \ - "\xd9\x8b\x41\x7e\x00\xd0\xfd\x7f\xf0\xf1\x12\x00\x5a\x88\x41\x7e" \ - "\xaa\xe0\x00\x00\x2a\x88\x41\x7e\x06\x04\x00\x00\x11\x4d\x40\x77" \ - "\xe8\xf3\x12\x00\x14\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" \ - "\xaa\xdf\xc0\x75\x00" -/* please se file /wiresharkusbsniffing/sniffed.txt - this is the read setup packet for 24c04 - -0040 aa 74 82 a0 00 74 81 a1 e0 00 11 00 06 04 00 00 .t...t.. ........ -0050 00 00 00 00 04 00 00 00 11 4d 40 77 cd ab ba dc ........ .M@w.... -0060 aa e0 00 00 c4 f1 12 00 11 4d 40 77 f0 f1 12 00 ........ .M@w.... -0070 d9 8b 41 7e 00 d0 fd 7f f0 f1 12 00 5a 88 41 7e ..A~.... ....Z.A~ -0080 aa e0 00 00 2a 88 41 7e 06 04 00 00 11 4d 40 77 ....*.A~ .....M@w -0090 e8 f3 12 00 14 00 00 00 01 00 00 00 00 00 00 00 ........ ........ -00a0 aa df c0 75 00 ...u. -*/ - -/* CH341a READ EEPROM next packet for 24c04 (three packets)*/ -#define CH341_EEPROM_24c04_READ_NEXT_CMD "\xaa\x74\x82\xa0\x80\x74\x81\xa1\xe0\x00\x00\x00\x10\x00\x00\x00" \ - "\x00\x00\x00\x00\x8c\xf1\x12\x00\x01\x00\x00\x00\x00\x00\x00\x00" \ - "\xaa\xe0\x00\x00\x4c\xf1\x12\x00\x5d\x22\xd7\x5a\xdc\xf1\x12\x00" \ - "\x8f\x04\x44\x7e\x30\x88\x41\x7e\xff\xff\xff\xff\x2a\x88\x41\x7e" \ - "\xaa\xe0\x00\x7e\x00\x00\x00\x00\x69\x0e\x3c\x00\xde\x00\x16\x00" \ - "\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8c\xe8\x67\x00" \ - "\xaa\xdf\xc0\x75\x00" -/*please see file /wiresharkusbsniffing/sniffed.txt - this is the first read next packet for 24c04 (three different packets) - -0040 aa 74 82 a0 80 74 81 a1 e0 00 00 00 10 00 00 00 .t...t.. ........ -0050 00 00 00 00 8c f1 12 00 01 00 00 00 00 00 00 00 ........ ........ -0060 aa e0 00 00 4c f1 12 00 5d 22 d7 5a dc f1 12 00 ....L... ]".Z.... -0070 8f 04 44 7e 30 88 41 7e ff ff ff ff 2a 88 41 7e ..D~0.A~ ....*.A~ -0080 aa e0 00 7e 00 00 00 00 69 0e 3c 00 de 00 16 00 ...~.... i.<..... -0090 0f 00 00 00 00 00 00 00 00 00 00 00 8c e8 67 00 ........ ......g. -00a0 aa df c0 75 00 ...u. -*/ - - -/* CH341a READ EEPROM setup packet for the 24c08 - this needs putting into a struct to allow convenient access to individual elements*/ -#define CH341_EEPROM_24c08_READ_SETUP_CMD "\xaa\x74\x82\xa0\x00\x74\x81\xa1\xe0\x00\x16\x00\x06\x04\x00\x00" \ - "\x00\x00\x00\x00\x08\x00\x00\x00\x11\x4d\x40\x77\xcd\xab\xba\xdc" \ - "\xaa\xe0\x00\x00\xc4\xf1\x12\x00\x11\x4d\x40\x77\xf0\xf1\x12\x00" \ - "\xd9\x8b\x41\x7e\x00\xd0\xfd\x7f\xf0\xf1\x12\x00\x5a\x88\x41\x7e" \ - "\xaa\xe0\x00\x00\x2a\x88\x41\x7e\x06\x04\x00\x00\x11\x4d\x40\x77" \ - "\xe8\xf3\x12\x00\x14\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" \ - "\xaa\xdf\xc0\x75\x00" -/* please se file /wiresharkusbsniffing/sniffed.txt - this is the read setup packet for 24c08 - -0040 aa 74 82 a0 00 74 81 a1 e0 00 16 00 06 04 00 00 .t...t.. ........ -0050 00 00 00 00 08 00 00 00 11 4d 40 77 cd ab ba dc ........ .M@w.... -0060 aa e0 00 00 c4 f1 12 00 11 4d 40 77 f0 f1 12 00 ........ .M@w.... -0070 d9 8b 41 7e 00 d0 fd 7f f0 f1 12 00 5a 88 41 7e ..A~.... ....Z.A~ -0080 aa e0 00 00 2a 88 41 7e 06 04 00 00 11 4d 40 77 ....*.A~ .....M@w -0090 e8 f3 12 00 14 00 00 00 01 00 00 00 00 00 00 00 ........ ........ -00a0 aa df c0 75 00 ...u. -*/ - -/* CH341a READ EEPROM next packet for 24c08 (seven packets)*/ -#define CH341_EEPROM_24c08_READ_NEXT_CMD "\xaa\x74\x82\xa0\x80\x74\x81\xa1\xe0\x00\x00\x00\x10\x00\x00\x00" \ - "\x00\x00\x00\x00\x8c\xf1\x12\x00\x01\x00\x00\x00\x00\x00\x00\x00" \ - "\xaa\xe0\x00\x00\x4c\xf1\x12\x00\x5d\x22\xd7\x5a\xdc\xf1\x12\x00" \ - "\x8f\x04\x44\x7e\x30\x88\x41\x7e\xff\xff\xff\xff\x2a\x88\x41\x7e" \ - "\xaa\xe0\x00\x7e\x00\x00\x00\x00\x69\x0e\x3c\x00\x00\x01\x1a\x00" \ - "\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8c\xe8\x67\x00" \ - "\xaa\xdf\xc0\x75\x00" -/*please see file /wiresharkusbsniffing/sniffed.txt - this is the first read next packet for 24c08 (seven different packets) - -0040 aa 74 82 a0 80 74 81 a1 e0 00 00 00 10 00 00 00 .t...t.. ........ -0050 00 00 00 00 8c f1 12 00 01 00 00 00 00 00 00 00 ........ ........ -0060 aa e0 00 00 4c f1 12 00 5d 22 d7 5a dc f1 12 00 ....L... ]".Z.... -0070 8f 04 44 7e 30 88 41 7e ff ff ff ff 2a 88 41 7e ..D~0.A~ ....*.A~ -0080 aa e0 00 7e 00 00 00 00 69 0e 3c 00 00 01 1a 00 ...~.... i.<..... -0090 0f 00 00 00 00 00 00 00 00 00 00 00 8c e8 67 00 ........ ......g. -00a0 aa df c0 75 00 ...u. -*/ - - -/* CH341a READ EEPROM setup packet for the 24c16 - this needs putting into a struct to allow convenient access to individual elements*/ -#define CH341_EEPROM_24c16_READ_SETUP_CMD "\xaa\x74\x82\xa0\x00\x74\x81\xa1\xe0\x00\x0e\x00\x06\x04\x00\x00" \ - "\x00\x00\x00\x00\x10\x00\x00\x00\x11\x4d\x40\x77\xcd\xab\xba\xdc" \ - "\xaa\xe0\x00\x00\xc4\xf1\x12\x00\x11\x4d\x40\x77\xf0\xf1\x12\x00" \ - "\xd9\x8b\x41\x7e\x00\xe0\xfd\x7f\xf0\xf1\x12\x00\x5a\x88\x41\x7e" \ - "\xaa\xe0\x00\x00\x2a\x88\x41\x7e\x06\x04\x00\x00\x11\x4d\x40\x77" \ - "\xe8\xf3\x12\x00\x14\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" \ - "\xaa\xdf\xc0\x75\x00" -/* please se file /wiresharkusbsniffing/sniffed.txt - this is the read setup packet for 24c16 - -0040 aa 74 82 a0 00 74 81 a1 e0 00 0e 00 06 04 00 00 .t...t.. ........ -0050 00 00 00 00 10 00 00 00 11 4d 40 77 cd ab ba dc ........ .M@w.... -0060 aa e0 00 00 c4 f1 12 00 11 4d 40 77 f0 f1 12 00 ........ .M@w.... -0070 d9 8b 41 7e 00 e0 fd 7f f0 f1 12 00 5a 88 41 7e ..A~.... ....Z.A~ -0080 aa e0 00 00 2a 88 41 7e 06 04 00 00 11 4d 40 77 ....*.A~ .....M@w -0090 e8 f3 12 00 14 00 00 00 01 00 00 00 00 00 00 00 ........ ........ -00a0 aa df c0 75 00 ...u. -*/ - -/* CH341a READ EEPROM next packet for 24c16*/ -#define CH341_EEPROM_24c16_READ_NEXT_CMD "\xaa\x74\x82\xa0\x80\x74\x81\xa1\xe0\x00\x00\x00\x10\x00\x00\x00" \ - "\x00\x00\x00\x00\x8c\xf1\x12\x00\x01\x00\x00\x00\x00\x00\x00\x00" \ - "\xaa\xe0\x00\x00\x4c\xf1\x12\x00\x5d\x22\xd7\x5a\xdc\xf1\x12\x00" \ - "\x8f\x04\x44\x7e\x30\x88\x41\x7e\xff\xff\xff\xff\x2a\x88\x41\x7e" \ - "\xaa\xe0\x00\x7e\x00\x00\x00\x00\x69\x0e\x3c\x00\xfa\x00\x31\x00" \ - "\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8c\xe8\x67\x00" \ - "\xaa\xdf\xc0\x75\x00" -/*please see file /wiresharkusbsniffing/sniffed.txt - this is the first read next packet for 24c16 (fifteen different packets) - -0040 aa 74 82 a0 80 74 81 a1 e0 00 00 00 10 00 00 00 .t...t.. ........ -0050 00 00 00 00 8c f1 12 00 01 00 00 00 00 00 00 00 ........ ........ -0060 aa e0 00 00 4c f1 12 00 5d 22 d7 5a dc f1 12 00 ....L... ]".Z.... -0070 8f 04 44 7e 30 88 41 7e ff ff ff ff 2a 88 41 7e ..D~0.A~ ....*.A~ -0080 aa e0 00 7e 00 00 00 00 69 0e 3c 00 fa 00 31 00 ...~.... i.<...1. -0090 0f 00 00 00 00 00 00 00 00 00 00 00 8c e8 67 00 ........ ......g. -00a0 aa df c0 75 00 ...u. -*/ - - -/* CH341a READ EEPROM setup packet for the 24c64 - this needs putting into a struct to allow convenient access to individual elements*/ -#define CH341_EEPROM_24c64_READ_SETUP_CMD "\xaa\x74\x83\xa0\x00\x00\x74\x81\xa1\xe0\x00\x00\x06\x04\x00\x00" \ - "\x00\x00\x00\x00\x40\x00\x00\x00\x11\x4d\x40\x77\xcd\xab\xba\xdc" \ - "\xaa\xe0\x00\x00\xc4\xf1\x12\x00\x11\x4d\x40\x77\xf0\xf1\x12\x00" \ - "\xd9\x8b\x41\x7e\x00\xf0\xfd\x7f\xf0\xf1\x12\x00\x5a\x88\x41\x7e" \ - "\xaa\xe0\x00\x00\x2a\x88\x41\x7e\x06\x04\x00\x00\x11\x4d\x40\x77" \ - "\xe8\xf3\x12\x00\x14\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" \ - "\xaa\xdf\xc0\x75\x00" -/* please se file /wiresharkusbsniffing/sniffed.txt - this is the read setup packet for 24c64 - -0040 aa 74 83 a0 00 00 74 81 a1 e0 00 00 06 04 00 00 .t....t. ........ -0050 00 00 00 00 40 00 00 00 11 4d 40 77 cd ab ba dc ....@... .M@w.... -0060 aa e0 00 00 c4 f1 12 00 11 4d 40 77 f0 f1 12 00 ........ .M@w.... -0070 d9 8b 41 7e 00 e0 fd 7f f0 f1 12 00 5a 88 41 7e ..A~.... ....Z.A~ -0080 aa e0 00 00 2a 88 41 7e 06 04 00 00 11 4d 40 77 ....*.A~ .....M@w -0090 e8 f3 12 00 14 00 00 00 01 00 00 00 00 00 00 00 ........ ........ -00a0 aa df c0 75 00 ...u. -*/ - -/* CH341a READ EEPROM next packet for 24c64 (63 packets)*/ -#define CH341_EEPROM_24c64_READ_NEXT_CMD "\xaa\x74\x83\xa0\x00\x00\x74\x81\xa1\xe0\x00\x00\x10\x00\x00\x00" \ - "\x00\x00\x00\x00\x8c\xf1\x12\x00\x01\x00\x00\x00\x00\x00\x00\x00" \ - "\xaa\xe0\x00\x00\x4c\xf1\x12\x00\x5d\x22\xd7\x5a\xdc\xf1\x12\x00" \ - "\x8f\x04\x44\x7e\x30\x88\x41\x7e\xff\xff\xff\xff\x2a\x88\x41\x7e" \ - "\xaa\xe0\x00\x7e\x00\x00\x00\x00\x69\x0e\x3c\x00\x12\x01\x19\x00" \ - "\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9c\x2e\x68\x00" \ - "\xaa\xdf\xc0\x75\x00" -/* please see file /wiresharkusbsniffing/sniffed.txt - this is the first read next packet for 24c64 (63 different packets) - -0040 aa 74 83 a0 00 80 74 81 a1 e0 00 00 10 00 00 00 .t....t. ........ -0050 00 00 00 00 8c f1 12 00 01 00 00 00 00 00 00 00 ........ ........ -0060 aa e0 00 00 4c f1 12 00 5d 22 d7 5a dc f1 12 00 ....L... ]".Z.... -0070 8f 04 44 7e 30 88 41 7e ff ff ff ff 2a 88 41 7e ..D~0.A~ ....*.A~ -0080 aa e0 00 7e 00 00 00 00 69 0e 3c 00 3a 01 1b 00 ...~.... i.<.:... -0090 0f 00 00 00 00 00 00 00 00 00 00 00 8c e8 67 00 ........ ......g. -00a0 aa df c0 75 00 ...u. -*/ +#define CH341_I2C_LOW_SPEED 0 // low speed - 20kHz +#define CH341_I2C_STANDARD_SPEED 1 // standard speed - 100kHz +#define CH341_I2C_FAST_SPEED 2 // fast speed - 400kHz +#define CH341_I2C_HIGH_SPEED 3 // high speed - 750kHz #define MIN(a,b) (((a)<(b))?(a):(b)) #define MAX(a,b) (((a)>(b))?(a):(b)) @@ -344,32 +106,32 @@ struct EEPROM { char *name; uint32_t size; uint16_t page_size; - uint8_t addr_size; // Length of addres in bytes + uint8_t addr_size; // Length of addres in bytes uint8_t i2c_addr_mask; }; const static struct EEPROM eepromlist[] = { - { "24c01", 128, 8, 1, 0x00}, // 16 pages of 8 bytes each = 128 bytes - { "24c02", 256, 8, 1, 0x00}, // 32 pages of 8 bytes each = 256 bytes - { "24c04", 512, 16, 1, 0x01}, // 32 pages of 16 bytes each = 512 bytes - { "24c08", 1024, 16, 1, 0x03}, // 64 pages of 16 bytes each = 1024 bytes - { "24c16", 2048, 16, 1, 0x07}, // 128 pages of 16 bytes each = 2048 bytes - { "24c32", 4096, 32, 2, 0x00}, // 32kbit = 4kbyte - { "24c64", 8192, 32, 2, 0x00}, - { "24c128", 16384, 32/*64*/, 2, 0x00}, - { "24c256", 32768, 32/*64*/, 2, 0x00}, - { "24c512", 65536, 32/*128*/, 2, 0x00}, - { "24c1024", 131072, 32/*128*/, 2, 0x01}, - { 0, 0, 0, 0 } + { "24c01", 128, 8, 1, 0 }, // 16 pages of 8 bytes each = 128 bytes + { "24c02", 256, 8, 1, 0 }, // 32 pages of 8 bytes each = 256 bytes + { "24c04", 512, 16, 1, 1 }, // 32 pages of 16 bytes each = 512 bytes + { "24c08", 1024, 16, 1, 3 }, // 64 pages of 16 bytes each = 1024 bytes + { "24c16", 2048, 16, 1, 7 }, // 128 pages of 16 bytes each = 2048 bytes + { "24c32", 4096, 32, 2, 0 }, // 32kbit = 4kbyte + { "24c64", 8192, 32, 2, 0 }, + { "24c128", 16384, 64, 2, 0 }, + { "24c256", 32768, 64 , 2, 0 }, + { "24c512", 65536, 128, 2, 0 }, + { "24c1024", 131072, 128, 2, 1 }, + { 0, 0, 0, 0 } }; extern uint8_t *readbuf; -int32_t ch341readEEPROM(struct libusb_device_handle *devHandle, uint8_t *buf, uint32_t bytes, struct EEPROM* eeprom_info); -int32_t ch341writeEEPROM(struct libusb_device_handle *devHandle, uint8_t *buf, uint32_t bytes, struct EEPROM* eeprom_info); +int32_t ch341readEEPROM(struct libusb_device_handle *devHandle, uint8_t * buf, uint32_t bytes, const struct EEPROM *eeprom_info); +int32_t ch341writeEEPROM(struct libusb_device_handle *devHandle, uint8_t * buf, uint32_t bytes, const struct EEPROM *eeprom_info); struct libusb_device_handle *ch341configure(uint16_t vid, uint16_t pid); int32_t ch341setstream(struct libusb_device_handle *devHandle, uint32_t speed); -int32_t parseEEPsize(char* eepromname, struct EEPROM *eeprom); +int32_t parseEEPsize(char *eepromname, const struct EEPROM **eeprom); // callback functions for async USB transfers void cbBulkIn(struct libusb_transfer *transfer); diff --git a/ch341funcs.c b/ch341funcs.c index 638213f..ff08da2 100644 --- a/ch341funcs.c +++ b/ch341funcs.c @@ -28,8 +28,8 @@ #include "ch341eeprom.h" extern FILE *debugout, *verbout; -uint32_t getnextpkt; // set by the callback function -uint32_t syncackpkt; // synch / ack flag used by BULK OUT cb function +uint32_t getnextpkt; // set by the callback function +uint32_t syncackpkt; // synch / ack flag used by BULK OUT cb function uint32_t byteoffset; // -------------------------------------------------------------------------- @@ -41,52 +41,48 @@ uint32_t byteoffset; // identify device revision // returns *usb device handle -struct libusb_device_handle *ch341configure(uint16_t vid, uint16_t pid) { +struct libusb_device_handle *ch341configure(uint16_t vid, uint16_t pid) +{ struct libusb_device *dev; struct libusb_device_handle *devHandle; - int32_t ret=0; // set to < 0 to indicate USB errors + int32_t ret = 0; // set to < 0 to indicate USB errors uint32_t i = 0; int32_t currentConfig = 0; uint8_t ch341DescriptorBuffer[0x12]; ret = libusb_init(NULL); - if(ret < 0) { + if (ret < 0) { fprintf(stderr, "Couldnt initialise libusb\n"); return NULL; } +#if LIBUSBX_API_VERSION < 0x01000106 + libusb_set_debug(NULL, 3); // maximum debug logging level +#else + libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, 3); +#endif + fprintf(verbout, "Searching USB buses for WCH CH341a i2c EEPROM programmer [%04x:%04x]\n", USB_LOCK_VENDOR, USB_LOCK_PRODUCT); - - #if LIBUSBX_API_VERSION < 0x01000106 - libusb_set_debug(NULL, 3); // maximum debug logging level - #else - libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, 3); - #endif - - fprintf(verbout, "Searching USB buses for WCH CH341a i2c EEPROM programmer [%04x:%04x]\n", - USB_LOCK_VENDOR, USB_LOCK_PRODUCT); - - if(!(devHandle = libusb_open_device_with_vid_pid(NULL, USB_LOCK_VENDOR, USB_LOCK_PRODUCT))) { + if (!(devHandle = libusb_open_device_with_vid_pid(NULL, USB_LOCK_VENDOR, USB_LOCK_PRODUCT))) { fprintf(stderr, "Couldn't open device [%04x:%04x]\n", USB_LOCK_VENDOR, USB_LOCK_PRODUCT); return NULL; } - if(!(dev = libusb_get_device(devHandle))) { + if (!(dev = libusb_get_device(devHandle))) { fprintf(stderr, "Couldnt get bus number and address of device\n"); return NULL; } - fprintf(verbout, "Found [%04x:%04x] as device [%d] on USB bus [%d]\n", USB_LOCK_VENDOR, USB_LOCK_PRODUCT, - libusb_get_device_address(dev), libusb_get_bus_number(dev)); + fprintf(verbout, "Found [%04x:%04x] as device [%d] on USB bus [%d]\n", + USB_LOCK_VENDOR, USB_LOCK_PRODUCT, libusb_get_device_address(dev), libusb_get_bus_number(dev)); fprintf(verbout, "Opened device [%04x:%04x]\n", USB_LOCK_VENDOR, USB_LOCK_PRODUCT); - - if(libusb_kernel_driver_active(devHandle, DEFAULT_INTERFACE)) { + if (libusb_kernel_driver_active(devHandle, DEFAULT_INTERFACE)) { ret = libusb_detach_kernel_driver(devHandle, DEFAULT_INTERFACE); - if(ret) { + if (ret) { fprintf(stderr, "Failed to detach kernel driver: '%s'\n", strerror(-ret)); return NULL; } else @@ -94,22 +90,22 @@ struct libusb_device_handle *ch341configure(uint16_t vid, uint16_t pid) { } ret = libusb_get_configuration(devHandle, ¤tConfig); - if(ret) { + if (ret) { fprintf(stderr, "Failed to get current device configuration: '%s'\n", strerror(-ret)); return NULL; } - if(currentConfig != DEFAULT_CONFIGURATION) + if (currentConfig != DEFAULT_CONFIGURATION) ret = libusb_set_configuration(devHandle, currentConfig); - if(ret) { + if (ret) { fprintf(stderr, "Failed to set device configuration to %d: '%s'\n", DEFAULT_CONFIGURATION, strerror(-ret)); return NULL; } ret = libusb_claim_interface(devHandle, DEFAULT_INTERFACE); // interface 0 - if(ret) { + if (ret) { fprintf(stderr, "Failed to claim interface %d: '%s'\n", DEFAULT_INTERFACE, strerror(-ret)); return NULL; } @@ -118,78 +114,74 @@ struct libusb_device_handle *ch341configure(uint16_t vid, uint16_t pid) { ret = libusb_get_descriptor(devHandle, LIBUSB_DT_DEVICE, 0x00, ch341DescriptorBuffer, 0x12); - if(ret < 0) { + if (ret < 0) { fprintf(stderr, "Failed to get device descriptor: '%s'\n", strerror(-ret)); return NULL; } - fprintf(verbout, "Device reported its revision [%d.%02d]\n", - ch341DescriptorBuffer[12], ch341DescriptorBuffer[13]); + fprintf(verbout, "Device reported its revision [%d.%02d]\n", ch341DescriptorBuffer[12], ch341DescriptorBuffer[13]); - for(i=0;i<0x12;i++) - fprintf(debugout,"%02x ", ch341DescriptorBuffer[i]); - fprintf(debugout,"\n"); + for (i = 0; i < 0x12; i++) + fprintf(debugout, "%02x ", ch341DescriptorBuffer[i]); + fprintf(debugout, "\n"); return devHandle; } - // -------------------------------------------------------------------------- // ch341setstream() // set the i2c bus speed (speed: 0 = 20kHz; 1 = 100kHz, 2 = 400kHz, 3 = 750kHz) -int32_t ch341setstream(struct libusb_device_handle *devHandle, uint32_t speed) { - int32_t ret, i; - uint8_t ch341outBuffer[EEPROM_READ_BULKOUT_BUF_SZ], *outptr; +int32_t ch341setstream(struct libusb_device_handle *devHandle, uint32_t speed) +{ + uint8_t ch341outBuffer[EEPROM_READ_BULKOUT_BUF_SZ], *outptr = ch341outBuffer; int32_t actuallen = 0; - outptr = ch341outBuffer; - *outptr++ = mCH341A_CMD_I2C_STREAM; *outptr++ = mCH341A_CMD_I2C_STM_SET | (speed & 0x3); - *outptr = mCH341A_CMD_I2C_STM_END; + *outptr = mCH341A_CMD_I2C_STM_END; - ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, ch341outBuffer, 3, &actuallen, DEFAULT_TIMEOUT); + int ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, ch341outBuffer, 3, &actuallen, DEFAULT_TIMEOUT); - if(ret < 0) { - fprintf(stderr, "ch341setstream(): Failed write %d bytes '%s'\n", 3, strerror(-ret)); - return -1; + if (ret < 0) { + fprintf(stderr, "ch341setstream(): Failed write %d bytes '%s'\n", 3, strerror(-ret)); + return -1; } fprintf(debugout, "ch341setstream(): Wrote %d bytes: ", 3); - for(i=0; i < 3; i++) + for (unsigned i = 0; i < 3; ++i) fprintf(debugout, "%02x ", ch341outBuffer[i]); fprintf(debugout, "\n"); return 0; } -size_t ch341ReadCmdMarshall(uint8_t *buffer, uint32_t addr, struct EEPROM *eeprom_info) { +size_t ch341ReadCmdMarshall(uint8_t *buffer, uint32_t addr, const struct EEPROM *eeprom_info) +{ uint8_t *ptr = buffer; // Frame 1. Program data address, and read 32 bytes. - *ptr++ = mCH341A_CMD_I2C_STREAM; // 0 - *ptr++ = mCH341A_CMD_I2C_STM_STA; // 1 + *ptr++ = mCH341A_CMD_I2C_STREAM; // 0 + *ptr++ = mCH341A_CMD_I2C_STM_STA; // 1 // Write address - *ptr++ = mCH341A_CMD_I2C_STM_OUT | ((*eeprom_info).addr_size+1); // 2: I2C bus adddress + EEPROM address + *ptr++ = mCH341A_CMD_I2C_STM_OUT | ((*eeprom_info).addr_size + 1); // 2: I2C bus adddress + EEPROM address uint8_t msb_addr; - if ((*eeprom_info).addr_size >= 2) { + if ((*eeprom_info).addr_size > 1) { // 24C32 and more - msb_addr = addr>>16 & (*eeprom_info).i2c_addr_mask; - *ptr++ = (EEPROM_I2C_BUS_ADDRESS | msb_addr)<<1; // 3 - *ptr++ = (addr>>8 & 0xFF); // 4 - *ptr++ = (addr>>0 & 0xFF); // 5 + msb_addr = addr >> 16 & (*eeprom_info).i2c_addr_mask; + *ptr++ = (EEPROM_I2C_BUS_ADDRESS | msb_addr) << 1; // 3 + *ptr++ = addr >> 8; // 4 } else { // 24C16 and less - msb_addr = addr>>8 & (*eeprom_info).i2c_addr_mask; - *ptr++ = (EEPROM_I2C_BUS_ADDRESS | msb_addr)<<1; // 3 - *ptr++ = (addr>>0 & 0xFF); // 4 + msb_addr = addr >> 8 & (*eeprom_info).i2c_addr_mask; + *ptr++ = (EEPROM_I2C_BUS_ADDRESS | msb_addr) << 1; // 3 } - *ptr++ = mCH341A_CMD_I2C_STM_STA; // 6/5 - *ptr++ = mCH341A_CMD_I2C_STM_OUT | 1; // 7/6 - *ptr++ = (EEPROM_I2C_BUS_ADDRESS | msb_addr)<<1 | 1; // 8/7: Read command - + *ptr++ = addr; // 5/4 + *ptr++ = mCH341A_CMD_I2C_STM_STA; // 6/5 + *ptr++ = mCH341A_CMD_I2C_STM_OUT | 1; // 7/6 + *ptr++ = (EEPROM_I2C_BUS_ADDRESS | msb_addr) << 1 | 1; // 8/7: Read command +#if 0 // Read 32 bytes - *ptr++ = mCH341A_CMD_I2C_STM_IN | 32; // 9/8 - *ptr++ = mCH341A_CMD_I2C_STM_END; // 10/9 + *ptr++ = mCH341A_CMD_I2C_STM_IN | 32; // 9/8 + *ptr++ = mCH341A_CMD_I2C_STM_END; // 10/9 // Frame 2 - read 32 bytes ptr = &buffer[32]; @@ -206,10 +198,20 @@ size_t ch341ReadCmdMarshall(uint8_t *buffer, uint32_t addr, struct EEPROM *eepro // Finalize - read last 32 bytes ptr = &buffer[96]; *ptr++ = mCH341A_CMD_I2C_STREAM; +#endif *ptr++ = mCH341A_CMD_I2C_STM_IN | 31; *ptr++ = mCH341A_CMD_I2C_STM_IN; *ptr++ = mCH341A_CMD_I2C_STM_STO; *ptr++ = mCH341A_CMD_I2C_STM_END; + + unsigned xfer_len = ptr - buffer; + fprintf(debugout, "\nch341ReadCmdMarshall(): prepared %d bytes\n", xfer_len); + for (unsigned i = 0; i < xfer_len; ++i) { + if (!(i % 16)) + fprintf(debugout, "\n "); + fprintf(debugout, "%02x ", buffer[i]); + } + fprintf(debugout, "\n"); return ptr - buffer; } @@ -217,19 +219,20 @@ size_t ch341ReadCmdMarshall(uint8_t *buffer, uint32_t addr, struct EEPROM *eepro // -------------------------------------------------------------------------- // ch341readEEPROM() // read n bytes from device (in packets of 32 bytes) -int32_t ch341readEEPROM(struct libusb_device_handle *devHandle, uint8_t *buffer, uint32_t bytestoread, struct EEPROM *eeprom_info) { +int32_t ch341readEEPROM(struct libusb_device_handle *devHandle, uint8_t *buffer, uint32_t bytestoread, const struct EEPROM *eeprom_info) +{ uint8_t ch341outBuffer[EEPROM_READ_BULKOUT_BUF_SZ]; - uint8_t ch341inBuffer[IN_BUF_SZ]; // 0x100 bytes - int32_t ret = 0, readpktcount = 0; + uint8_t ch341inBuffer[IN_BUF_SZ]; // 0x100 bytes + int32_t ret = 0; struct libusb_transfer *xferBulkIn, *xferBulkOut; - struct timeval tv = {0, 100}; // our async polling interval + struct timeval tv = { 0, 100 }; // our async polling interval size_t xfer_size; - xferBulkIn = libusb_alloc_transfer(0); + xferBulkIn = libusb_alloc_transfer(0); xferBulkOut = libusb_alloc_transfer(0); - if(!xferBulkIn || !xferBulkOut) { + if (!xferBulkIn || !xferBulkOut) { fprintf(stderr, "Couldnt allocate USB transfer structures\n"); return -1; } @@ -239,13 +242,11 @@ int32_t ch341readEEPROM(struct libusb_device_handle *devHandle, uint8_t *buffer, fprintf(debugout, "Allocated USB transfer structures\n"); memset(ch341inBuffer, 0, EEPROM_READ_BULKIN_BUF_SZ); - xfer_size = ch341ReadCmdMarshall(ch341outBuffer, 0, eeprom_info); // Fill output buffer + xfer_size = ch341ReadCmdMarshall(ch341outBuffer, 0, eeprom_info); // Fill output buffer - libusb_fill_bulk_transfer(xferBulkIn, devHandle, BULK_READ_ENDPOINT, ch341inBuffer, - EEPROM_READ_BULKIN_BUF_SZ, cbBulkIn, NULL, DEFAULT_TIMEOUT); + libusb_fill_bulk_transfer(xferBulkIn, devHandle, BULK_READ_ENDPOINT, ch341inBuffer, EEPROM_READ_BULKIN_BUF_SZ, cbBulkIn, NULL, DEFAULT_TIMEOUT); - libusb_fill_bulk_transfer(xferBulkOut, devHandle, BULK_WRITE_ENDPOINT, - ch341outBuffer, xfer_size, cbBulkOut, NULL, DEFAULT_TIMEOUT); + libusb_fill_bulk_transfer(xferBulkOut, devHandle, BULK_WRITE_ENDPOINT, ch341outBuffer, xfer_size, cbBulkOut, NULL, DEFAULT_TIMEOUT); fprintf(debugout, "Filled USB transfer structures\n"); @@ -255,80 +256,69 @@ int32_t ch341readEEPROM(struct libusb_device_handle *devHandle, uint8_t *buffer, fprintf(debugout, "Submitted BULK OUT setup packet\n"); readbuf = buffer; - while (1) { - fprintf(stdout, "Read %d%% [%d] of [%d] bytes \r", 100*byteoffset/bytestoread, byteoffset, bytestoread); - ret = libusb_handle_events_timeout(NULL, &tv); + fprintf(stdout, "Read %d%% [%d] of [%d] bytes\r", (100 * byteoffset) / bytestoread, byteoffset, bytestoread); + ret = libusb_handle_events_timeout(NULL, &tv); - if (ret < 0 || getnextpkt == -1) { // indicates an error + if (ret < 0 || getnextpkt == -1) { // indicates an error fprintf(stderr, "ret from libusb_handle_timeout = %d\n", ret); fprintf(stderr, "getnextpkt = %d\n", getnextpkt); if (ret < 0) fprintf(stderr, "USB read error : %s\n", strerror(-ret)); - libusb_free_transfer(xferBulkIn); - libusb_free_transfer(xferBulkOut); - return -1; + goto cleanup; } - if(getnextpkt == 1) { // callback function reports a new BULK IN packet received - getnextpkt = 0; // reset the flag - readpktcount++; // increment the read packet counter + if (getnextpkt == 1) { // callback function reports a new BULK IN packet received + getnextpkt = 0; // reset the flag byteoffset += EEPROM_READ_BULKIN_BUF_SZ; if (byteoffset == bytestoread) break; fprintf(debugout, "\nRe-submitting transfer request to BULK IN endpoint\n"); - libusb_submit_transfer(xferBulkIn); // re-submit request for next BULK IN packet of EEPROM data - if(syncackpkt) + libusb_submit_transfer(xferBulkIn); // re-submit request for next BULK IN packet of EEPROM data + if (syncackpkt) syncackpkt = 0; - // if 4th packet received, we are at end of 0x80 byte data block, - // if it is not the last block, then resubmit request for data - if(readpktcount==4) { - fprintf(debugout, "\nSubmitting next transfer request to BULK OUT endpoint\n"); - readpktcount = 0; - - ch341ReadCmdMarshall(ch341outBuffer, byteoffset, eeprom_info); // Fill output buffer - libusb_fill_bulk_transfer(xferBulkOut, devHandle, BULK_WRITE_ENDPOINT, ch341outBuffer, - EEPROM_READ_BULKOUT_BUF_SZ, cbBulkOut, NULL, DEFAULT_TIMEOUT); + fprintf(debugout, "\nSubmitting next transfer request to BULK OUT endpoint\n"); + ch341ReadCmdMarshall(ch341outBuffer, byteoffset, eeprom_info); // Fill output buffer + libusb_fill_bulk_transfer(xferBulkOut, devHandle, BULK_WRITE_ENDPOINT, ch341outBuffer, xfer_size, cbBulkOut, NULL, DEFAULT_TIMEOUT); - libusb_submit_transfer(xferBulkOut);// update transfer struct (with new EEPROM page offset) + libusb_submit_transfer(xferBulkOut); // update transfer struct (with new EEPROM page offset) // and re-submit next transfer request to BULK OUT endpoint - } } - } - + } +cleanup: libusb_free_transfer(xferBulkIn); libusb_free_transfer(xferBulkOut); - return 0; + return ret; } // Callback function for async bulk in comms -void cbBulkIn(struct libusb_transfer *transfer) { - int i; - - switch(transfer->status) { - case LIBUSB_TRANSFER_COMPLETED: - // display the contents of the BULK IN data buffer - fprintf(debugout,"\ncbBulkIn(): status %d - Read %d bytes\n",transfer->status,transfer->actual_length); - - for(i=0; i < transfer->actual_length; i++) { - if(!(i%16)) - fprintf(debugout, "\n "); - fprintf(debugout, "%02x ", transfer->buffer[i]); - } - fprintf(debugout, "\n"); - // copy read data to our EEPROM buffer - memcpy(readbuf + byteoffset, transfer->buffer, transfer->actual_length); - getnextpkt = 1; - break; - default: - fprintf(stderr, "\ncbBulkIn: error : %d\n", transfer->status); - getnextpkt = -1; +void cbBulkIn(struct libusb_transfer *transfer) +{ + switch (transfer->status) { + case LIBUSB_TRANSFER_COMPLETED: + // display the contents of the BULK IN data buffer + fprintf(debugout, "\ncbBulkIn(): status %d - Read %d bytes\n", transfer->status, transfer->actual_length); + + for (unsigned i = 0; i < transfer->actual_length; ++i) { + if (!(i % 16)) + fprintf(debugout, "\n "); + fprintf(debugout, "%02x ", transfer->buffer[i]); + } + fprintf(debugout, "\n"); + // copy read data to our EEPROM buffer + memcpy(readbuf + byteoffset, transfer->buffer, transfer->actual_length); + getnextpkt = 1; + break; + default: + fprintf(stderr, "\ncbBulkIn: error : %d\n", transfer->status); + getnextpkt = -1; } - return; + return; } // Callback function for async bulk out comms -void cbBulkOut(struct libusb_transfer *transfer) { +void cbBulkOut(struct libusb_transfer *transfer) +{ syncackpkt = 1; fprintf(debugout, "\ncbBulkOut(): Sync/Ack received: status %d\n", transfer->status); return; @@ -337,114 +327,113 @@ void cbBulkOut(struct libusb_transfer *transfer) { // -------------------------------------------------------------------------- // ch341writeEEPROM() // write n bytes to 24c32/24c64 device (in packets of 32 bytes) -int32_t ch341writeEEPROM(struct libusb_device_handle *devHandle, uint8_t *buffer, uint32_t bytesum, struct EEPROM *eeprom_info) { +int32_t ch341writeEEPROM(struct libusb_device_handle *devHandle, uint8_t *buffer, uint32_t bytesum, const struct EEPROM *eeprom_info) +{ - uint8_t ch341outBuffer[512/*EEPROM_WRITE_BUF_SZ*/]; + uint8_t ch341outBuffer[512]; uint8_t *outptr, *bufptr; uint8_t i2cCmdBuffer[256]; - int32_t ret = 0, i; + int32_t ret = 0; uint32_t byteoffset = 0; uint32_t bytes = bytesum; - uint8_t addrbytecount = (*eeprom_info).addr_size+1; // 24c32 and 24c64 (and other 24c??) use 3 bytes for addressing + uint8_t addrbytecount = eeprom_info->addr_size + 1; // 24c32 and 24c64 (and other 24c??) use 3 bytes for addressing int32_t actuallen = 0; - uint16_t page_size = (*eeprom_info).page_size; + uint16_t page_size = eeprom_info->page_size; bufptr = buffer; - while(bytes) { + while (bytes) { outptr = i2cCmdBuffer; - if ((*eeprom_info).addr_size >= 2) { - *outptr++ = (uint8_t) (0xa0 | (byteoffset >> 16 & (*eeprom_info).i2c_addr_mask)<<1); // EEPROM device address - *outptr++ = (uint8_t) (byteoffset >> 8 & 0xff); // MSB (big-endian) byte address + if (eeprom_info->addr_size > 1) { + *outptr++ = 0xa0 | ((byteoffset >> 15) & (eeprom_info->i2c_addr_mask << 1)); // EEPROM device address + *outptr++ = byteoffset >> 8 & 0xff; // MSB (big-endian) byte address } else { - *outptr++ = (uint8_t) (0xa0 | (byteoffset >> 8 & (*eeprom_info).i2c_addr_mask)<<1); // EEPROM device address + *outptr++ = 0xa0 | ((byteoffset >> 7) & (eeprom_info->i2c_addr_mask << 1)); // EEPROM device address } - *outptr++ = (uint8_t) (byteoffset & 0xff); // LSB of 16-bit byte address + *outptr++ = byteoffset & 0xff; // LSB of 16-bit byte address - memcpy(outptr, bufptr, page_size); // Copy one page + memcpy(outptr, bufptr, page_size); // Copy one page byteoffset += page_size; - bufptr += page_size; - bytes -= page_size; + bufptr += page_size; + bytes -= page_size; - outptr = ch341outBuffer; + outptr = ch341outBuffer; uint16_t page_size_left = page_size + addrbytecount; uint8_t part_no = 0; uint8_t *i2cBufPtr = i2cCmdBuffer; - while(page_size_left) { - uint8_t to_write = MIN(page_size_left, 28); + while (page_size_left) { *outptr++ = mCH341A_CMD_I2C_STREAM; if (part_no == 0) { // Start packet *outptr++ = mCH341A_CMD_I2C_STM_STA; } + // middle packet has 29 slots + uint8_t to_write = (page_size_left < 29) ? page_size_left : (part_no != 0) + 28; *outptr++ = mCH341A_CMD_I2C_STM_OUT | to_write; memcpy(outptr, i2cBufPtr, to_write); outptr += to_write; i2cBufPtr += to_write; page_size_left -= to_write; - if (page_size_left == 0) { // Stop packet + if (page_size_left == 0) { // Stop packet *outptr++ = mCH341A_CMD_I2C_STM_STO; } *outptr++ = mCH341A_CMD_I2C_STM_END; - part_no++; + ++part_no; } uint32_t payload_size = outptr - ch341outBuffer; - for(i=0; i < payload_size; i++) { - if(!(i%0x10)) + for (unsigned i = 0; i < payload_size; ++i) { + if (!(i % 0x10)) fprintf(debugout, "\n%04x : ", i); fprintf(debugout, "%02x ", ch341outBuffer[i]); } fprintf(debugout, "\n"); - ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, - ch341outBuffer, payload_size, &actuallen, DEFAULT_TIMEOUT); + ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, ch341outBuffer, payload_size, &actuallen, DEFAULT_TIMEOUT); - if(ret < 0) { + if (ret < 0) { fprintf(stderr, "Failed to write to EEPROM: '%s'\n", strerror(-ret)); return -1; } - fprintf(debugout, "Writing [aa 5a 00] to EEPROM\n"); // Magic CH341a packet! Undocumented, unknown purpose + fprintf(debugout, "Writing [aa 5a 00] to EEPROM\n"); - outptr = ch341outBuffer; + outptr = ch341outBuffer; *outptr++ = mCH341A_CMD_I2C_STREAM; - *outptr++ = mCH341A_CMD_I2C_STM_MS | 10; // Wait 10ms (?) + *outptr++ = mCH341A_CMD_I2C_STM_MS | 10; // Wait 10ms (?) *outptr++ = mCH341A_CMD_I2C_STM_END; ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, ch341outBuffer, 3, &actuallen, DEFAULT_TIMEOUT); - if(ret < 0) { - fprintf(stderr, "Failed to write to EEPROM: '%s'\n", strerror(-ret)); + if (ret < 0) { + fprintf(stderr, "Failed to set timeout: '%s'\n", strerror(-ret)); return -1; } /* - struct timeval tv = {0, 100}; // our async polling interval - ret = libusb_handle_events_timeout(NULL, &tv); - if (ret < 0) { // indicates an error - fprintf(stderr, "ret from libusb_handle_timeout = %d\n", ret); - fprintf(stderr, "USB read error : %s\n", strerror(-ret)); - return -1; - } - */ - fprintf(stdout, "Written %d%% [%d] of [%d] bytes \r", 100*(bytesum-bytes)/bytesum, bytesum-bytes, bytesum); + struct timeval tv = {0, 100}; // our async polling interval + ret = libusb_handle_events_timeout(NULL, &tv); + if (ret < 0) { // indicates an error + fprintf(stderr, "ret from libusb_handle_timeout = %d\n", ret); + fprintf(stderr, "USB read error : %s\n", strerror(-ret)); + return -1; + } + */ + fprintf(stdout, "Written %d%% [%d] of [%d] bytes \r", 100 * (bytesum - bytes) / bytesum, bytesum - bytes, bytesum); } return 0; } - // -------------------------------------------------------------------------- // parseEEPsize() // passed an EEPROM name (case-sensitive), returns its byte size -int32_t parseEEPsize(char* eepromname, struct EEPROM *eeprom) { - int i; - - for(i=0; eepromlist[i].size; i++) - if(strstr(eepromlist[i].name, eepromname)) { - memcpy(eeprom, &(eepromlist[i]), sizeof(struct EEPROM)); - return(eepromlist[i].size); +int32_t parseEEPsize(char *eepromname, const struct EEPROM **eeprom) +{ + for (unsigned i = 0; eepromlist[i].size; ++i) + if (strcmp(eepromlist[i].name, eepromname) == 0) { + *eeprom = &eepromlist[i]; + return (eepromlist[i].size); } return -1; } From 1d6409a0a7ae7100fbcff17966b6c493e16ec669 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Fri, 24 Mar 2023 21:52:02 +0300 Subject: [PATCH 2/7] Qt files --- ch341eeprom.cflags | 1 + ch341eeprom.config | 2 ++ ch341eeprom.creator | 1 + ch341eeprom.cxxflags | 1 + ch341eeprom.files | 3 +++ ch341eeprom.includes | 1 + 6 files changed, 9 insertions(+) create mode 100644 ch341eeprom.cflags create mode 100644 ch341eeprom.config create mode 100644 ch341eeprom.creator create mode 100644 ch341eeprom.cxxflags create mode 100644 ch341eeprom.files create mode 100644 ch341eeprom.includes diff --git a/ch341eeprom.cflags b/ch341eeprom.cflags new file mode 100644 index 0000000..68d5165 --- /dev/null +++ b/ch341eeprom.cflags @@ -0,0 +1 @@ +-std=c17 \ No newline at end of file diff --git a/ch341eeprom.config b/ch341eeprom.config new file mode 100644 index 0000000..e0284f4 --- /dev/null +++ b/ch341eeprom.config @@ -0,0 +1,2 @@ +// Add predefined macros for your project here. For example: +// #define THE_ANSWER 42 diff --git a/ch341eeprom.creator b/ch341eeprom.creator new file mode 100644 index 0000000..e94cbbd --- /dev/null +++ b/ch341eeprom.creator @@ -0,0 +1 @@ +[General] diff --git a/ch341eeprom.cxxflags b/ch341eeprom.cxxflags new file mode 100644 index 0000000..6435dfc --- /dev/null +++ b/ch341eeprom.cxxflags @@ -0,0 +1 @@ +-std=c++17 \ No newline at end of file diff --git a/ch341eeprom.files b/ch341eeprom.files new file mode 100644 index 0000000..7364bff --- /dev/null +++ b/ch341eeprom.files @@ -0,0 +1,3 @@ +ch341eeprom.c +ch341eeprom.h +ch341funcs.c diff --git a/ch341eeprom.includes b/ch341eeprom.includes new file mode 100644 index 0000000..9c558e3 --- /dev/null +++ b/ch341eeprom.includes @@ -0,0 +1 @@ +. From 5c7da0610d8038e97193d66bd33432810fd6e382 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Fri, 24 Mar 2023 21:51:02 +0300 Subject: [PATCH 3/7] i2c_msg for write path --- Makefile | 4 +- ch341eeprom.c | 98 ++++++------- ch341eeprom.h | 72 ++++++---- ch341funcs.c | 392 ++++++++++++++++++++------------------------------ 4 files changed, 246 insertions(+), 320 deletions(-) diff --git a/Makefile b/Makefile index a1ffd9e..a180cf4 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CC = gcc -CFLAGS = -Wall -O2 +CFLAGS = -Wall -g -O0 -default: +all: $(CC) $(CFLAGS) -o ch341eeprom ch341eeprom.c ch341funcs.c -lusb-1.0 $(CC) $(CFLAGS) -o mktestimg mktestimg.c diff --git a/ch341eeprom.c b/ch341eeprom.c index 26d2c22..6db502d 100644 --- a/ch341eeprom.c +++ b/ch341eeprom.c @@ -1,10 +1,11 @@ // -// ch341eeprom programmer version 0.1 (Beta) +// ch341eeprom programmer version 0.6 (Beta) // // Programming tool for the 24Cxx serial EEPROMs using the Winchiphead CH341A IC // // (c) December 2011 asbokid -// +// (c) December 2023 aystarik +// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or @@ -18,30 +19,33 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#include +#define _POSIX_C_SOURCE 1 + #include #include #include #include +#include #include #include #include #include #include + #include "ch341eeprom.h" -FILE *debugout, *verbout; -uint8_t *readbuf = NULL; +FILE *debugout = NULL, *verbout = NULL; int main(int argc, char **argv) { int i, eepromsize = 0, bytesread = 0; - uint8_t debug = FALSE, verbose = FALSE; + uint8_t debug = false, verbose = false; struct libusb_device_handle *devHandle = NULL; - char *filename = NULL, *eepromname, operation = 0; + const char *filename = NULL, *eepromname = NULL; + char operation = 0; uint32_t speed = CH341_I2C_STANDARD_SPEED; uint8_t *verifybuf; - uint8_t verify_failed = FALSE; + uint8_t verify_failed = false; FILE *fp; const struct EEPROM *eeprom_info; @@ -80,10 +84,9 @@ int main(int argc, char **argv) static int speed_table[] = { 20, 100, 400, 750 }; - while (TRUE) { + while (true) { int32_t optidx = 0; - int8_t c = getopt_long(argc, argv, "hvdes:p:w:r:V:", longopts, - &optidx); + int8_t c = getopt_long(argc, argv, "hvdes:p:w:r:V:", longopts, &optidx); if (c == -1) break; @@ -92,10 +95,10 @@ int main(int argc, char **argv) fprintf(stdout, "%s\n%s", version_msg, usage_msg); return 0; case 'v': - verbose = TRUE; + verbose = true; break; case 'd': - debug = TRUE; + debug = true; break; case 's': if ((eepromsize = parseEEPsize(optarg, &eeprom_info)) > 0) @@ -116,70 +119,67 @@ int main(int argc, char **argv) operation = 'e'; else { fprintf(stderr, "Conflicting command line options\n"); - goto shutdown; + return -1; } break; case 'r': if (!operation) { operation = 'r'; - filename = (char *)malloc(strlen(optarg) + 1); - strcpy(filename, optarg); + filename = optarg; } else { fprintf(stderr, "Conflicting command line options\n"); - goto shutdown; + return -1; } break; case 'w': if (!operation) { operation = 'w'; - filename = (char *)malloc(strlen(optarg) + 1); - strcpy(filename, optarg); + filename = optarg; } else { fprintf(stderr, "Conflicting command line options\n"); - goto shutdown; + return -1; } break; case 'V': if (!operation) { operation = 'V'; - filename = (char *)malloc(strlen(optarg) + 1); - strcpy(filename, optarg); + filename = optarg; } else { fprintf(stderr, "Conflicting command line options\n"); - goto shutdown; + return -1; } break; default: case '?': fprintf(stdout, "%s", version_msg); fprintf(stderr, "%s", usage_msg); - goto shutdown; + return 0; } } - debugout = (debug == TRUE) ? stdout : fopen("/dev/null", "w"); - verbout = (verbose == TRUE) ? stdout : fopen("/dev/null", "w"); + debugout = (debug == true) ? stdout : fopen("/dev/null", "w"); + verbout = (verbose == true) ? stdout : fopen("/dev/null", "w"); fprintf(debugout, "Debug Enabled\n"); if (!operation) { fprintf(stderr, "%s\n%s", version_msg, usage_msg); - goto shutdown; + return -1; } if (eepromsize <= 0) { fprintf(stderr, "Invalid EEPROM size\n"); - goto shutdown; + return -1; } - readbuf = (uint8_t *) malloc(MAX_EEPROM_SIZE); // space to store loaded EEPROM + uint8_t *readbuf = (uint8_t *)malloc(eepromsize); // space to store loaded EEPROM if (!readbuf) { fprintf(stderr, "Couldnt malloc space needed for EEPROM image\n"); - goto shutdown; + return -1; } if (!(devHandle = ch341configure(USB_LOCK_VENDOR, USB_LOCK_PRODUCT))) { fprintf(stderr, "Couldnt configure USB device with vendor ID: %04x product ID: %04x\n", USB_LOCK_VENDOR, USB_LOCK_PRODUCT); - goto shutdown; + goto free_readbuf; } fprintf(verbout, "Configured USB device with vendor ID: %04x product ID: %04x\n", USB_LOCK_VENDOR, USB_LOCK_PRODUCT); @@ -191,7 +191,7 @@ int main(int argc, char **argv) switch (operation) { case 'r': // read - memset(readbuf, 0xff, MAX_EEPROM_SIZE); + memset(readbuf, 0xff, eepromsize); if (ch341readEEPROM(devHandle, readbuf, eepromsize, eeprom_info) < 0) { @@ -222,7 +222,7 @@ int main(int argc, char **argv) fprintf(stdout, "Wrote [%d] bytes to file [%s]\n", eepromsize, filename); break; case 'V': // verify - memset(readbuf, 0xff, MAX_EEPROM_SIZE); + memset(readbuf, 0xff, eepromsize); if (ch341readEEPROM(devHandle, readbuf, eepromsize, eeprom_info) < 0) { @@ -250,15 +250,14 @@ int main(int argc, char **argv) goto shutdown; } - for (i = 0; i < eepromsize; i++) { + for (unsigned i = 0; i < eepromsize; ++i) { if (readbuf[i] != verifybuf[i]) { - verify_failed = TRUE; + verify_failed = true; break; } } if (verify_failed) - fprintf(stdout, - "Verification against file [%s] failed at offset [%d], EEPROM: %02hhX, file: %02hhX\n", + fprintf(stdout, "Verification against file [%s] failed at offset [%d], EEPROM: %02hhX, file: %02hhX\n", filename, i, readbuf[i], verifybuf[i]); else fprintf(stdout, "Verified [%d] bytes against file [%s]\n", eepromsize, filename); @@ -271,8 +270,8 @@ int main(int argc, char **argv) fprintf(stderr, "Couldnt open file [%s] for reading\n", filename); goto shutdown; } - memset(readbuf, 0xff, MAX_EEPROM_SIZE); - bytesread = fread(readbuf, 1, MAX_EEPROM_SIZE, fp); + memset(readbuf, 0xff, eepromsize); + bytesread = fread(readbuf, 1, eepromsize, fp); if (ferror(fp)) { fprintf(stderr, "Error reading file [%s]\n", filename); if (fp) @@ -295,7 +294,7 @@ int main(int argc, char **argv) fprintf(stdout, "Wrote [%d] bytes to [%s] EEPROM\n", eepromsize, eepromname); break; case 'e': // erase - memset(readbuf, 0xff, MAX_EEPROM_SIZE); + memset(readbuf, 0xff, eepromsize); if (ch341writeEEPROM(devHandle, readbuf, eepromsize, eeprom_info) < 0) { fprintf(stderr, "Failed to erase [%d] bytes of [%s] EEPROM\n", eepromsize, eepromname); goto shutdown; @@ -304,20 +303,15 @@ int main(int argc, char **argv) break; default: fprintf(stderr, "Unknown option\n"); - goto shutdown; } shutdown: - if (readbuf) - free(readbuf); - if (filename) - free(filename); - if (devHandle) { - libusb_release_interface(devHandle, DEFAULT_INTERFACE); - fprintf(debugout, "Released device interface [%d]\n", DEFAULT_INTERFACE); - libusb_close(devHandle); - fprintf(verbout, "Closed USB device\n"); - libusb_exit(NULL); - } + libusb_release_interface(devHandle, DEFAULT_INTERFACE); + fprintf(debugout, "Released device interface [%d]\n", DEFAULT_INTERFACE); + libusb_close(devHandle); + fprintf(verbout, "Closed USB device\n"); + libusb_exit(NULL); +free_readbuf: + free(readbuf); return 0; } diff --git a/ch341eeprom.h b/ch341eeprom.h index 7cab1fb..7d7379e 100644 --- a/ch341eeprom.h +++ b/ch341eeprom.h @@ -1,14 +1,17 @@ // libUSB driver for the ch341a in i2c mode // // Copyright 2011 asbokid +// (c) December 2023 aystarik -#define CH341TOOLVERSION "0.5" +#pragma once +#include +#include + +#define CH341TOOLVERSION "0.6" #define USB_LOCK_VENDOR 0x1a86 // Dev : (1a86) QinHeng Electronics #define USB_LOCK_PRODUCT 0x5512 // (5512) CH341A in i2c mode -#define MAX_EEPROM_SIZE 131072 /* For 24c1024 */ - #define EEPROM_I2C_BUS_ADDRESS 0x50 #define BULK_WRITE_ENDPOINT 0x02 /* bEndpointAddress 0x02 EP 2 OUT (Bulk) */ @@ -18,10 +21,6 @@ #define DEFAULT_CONFIGURATION 0x01 #define DEFAULT_TIMEOUT 300 // 300mS for USB timeouts -#define IN_BUF_SZ 0x100 -#define EEPROM_READ_BULKIN_BUF_SZ 0x20 -#define EEPROM_READ_BULKOUT_BUF_SZ 0x100 - /* Based on (closed-source) DLL V1.9 for USB by WinChipHead (c) 2005. Supports USB chips: CH341, CH341A This can be a problem for copyright, sure asbokid can't release this part on any GPL licence*/ @@ -91,17 +90,16 @@ /* End of part based on (closed-source) DLL V1.9 for USB by WinChipHead (c) 2005. Since is largely unused we can replace it*/ -#define CH341_I2C_LOW_SPEED 0 // low speed - 20kHz -#define CH341_I2C_STANDARD_SPEED 1 // standard speed - 100kHz -#define CH341_I2C_FAST_SPEED 2 // fast speed - 400kHz -#define CH341_I2C_HIGH_SPEED 3 // high speed - 750kHz +enum ch341_speed_t { + CH341_I2C_LOW_SPEED = 0, // low speed - 20kHz + CH341_I2C_STANDARD_SPEED = 1, // standard speed - 100kHz + CH341_I2C_FAST_SPEED = 2, // fast speed - 400kHz + CH341_I2C_HIGH_SPEED = 3, // high speed - 750kHz +}; #define MIN(a,b) (((a)<(b))?(a):(b)) #define MAX(a,b) (((a)>(b))?(a):(b)) -#define TRUE 1 -#define FALSE 0 - struct EEPROM { char *name; uint32_t size; @@ -111,28 +109,42 @@ struct EEPROM { }; const static struct EEPROM eepromlist[] = { - { "24c01", 128, 8, 1, 0 }, // 16 pages of 8 bytes each = 128 bytes - { "24c02", 256, 8, 1, 0 }, // 32 pages of 8 bytes each = 256 bytes - { "24c04", 512, 16, 1, 1 }, // 32 pages of 16 bytes each = 512 bytes - { "24c08", 1024, 16, 1, 3 }, // 64 pages of 16 bytes each = 1024 bytes - { "24c16", 2048, 16, 1, 7 }, // 128 pages of 16 bytes each = 2048 bytes - { "24c32", 4096, 32, 2, 0 }, // 32kbit = 4kbyte - { "24c64", 8192, 32, 2, 0 }, - { "24c128", 16384, 64, 2, 0 }, - { "24c256", 32768, 64 , 2, 0 }, - { "24c512", 65536, 128, 2, 0 }, - { "24c1024", 131072, 128, 2, 1 }, + { "24c01", 0x80, 8, 1, 0 }, // 16 pages of 8 bytes each = 128 bytes + { "24c02", 0x100, 8, 1, 0 }, // 32 pages of 8 bytes each = 256 bytes + { "24c04", 0x200, 16, 1, 1 }, // 32 pages of 16 bytes each = 512 bytes + { "24c08", 0x400, 16, 1, 3 }, // 64 pages of 16 bytes each = 1024 bytes + { "24c16", 0x800, 16, 1, 7 }, // 128 pages of 16 bytes each = 2048 bytes + { "24c32", 0x1000, 32, 2, 0 }, // 32kbit = 4kbyte + { "24c64", 0x2000, 32, 2, 0 }, + { "24c128", 0x4000, 64, 2, 0 }, + { "24c256", 0x8000, 64, 2, 0 }, + { "24c512", 0x10000, 128, 2, 0 }, + { "24c1024", 0x20000, 128, 2, 1 }, + { "24cm02", 0x40000, 256, 2, 3 }, { 0, 0, 0, 0 } }; -extern uint8_t *readbuf; +struct i2c_msg { + uint16_t addr; /* slave address */ + uint16_t flags; +#define I2C_M_RD 0x0001 /* read data, from slave to master */ + /* I2C_M_RD is guaranteed to be 0x0001! */ +#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */ +#define I2C_M_DMA_SAFE 0x0200 /* the buffer of this message is DMA safe */ + /* makes only sense in kernelspace */ + /* userspace buffers are copied anyway */ +#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */ +#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_NOSTART */ +#define I2C_M_STOP 0x8000 /* if I2C_FUNC_PROTOCOL_MANGLING */ + uint16_t len; /* msg length */ + uint8_t *buf; /* pointer to msg data */ +}; int32_t ch341readEEPROM(struct libusb_device_handle *devHandle, uint8_t * buf, uint32_t bytes, const struct EEPROM *eeprom_info); int32_t ch341writeEEPROM(struct libusb_device_handle *devHandle, uint8_t * buf, uint32_t bytes, const struct EEPROM *eeprom_info); struct libusb_device_handle *ch341configure(uint16_t vid, uint16_t pid); int32_t ch341setstream(struct libusb_device_handle *devHandle, uint32_t speed); int32_t parseEEPsize(char *eepromname, const struct EEPROM **eeprom); - -// callback functions for async USB transfers -void cbBulkIn(struct libusb_transfer *transfer); -void cbBulkOut(struct libusb_transfer *transfer); diff --git a/ch341funcs.c b/ch341funcs.c index ff08da2..cedcc16 100644 --- a/ch341funcs.c +++ b/ch341funcs.c @@ -4,6 +4,7 @@ // Programming tool for the 24Cxx serial EEPROMs using the Winchiphead CH341A IC // // (c) December 2011 asbokid +// (c) December 2023 aystarik // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -18,19 +19,16 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#include #include #include #include -#include #include #include +#include + #include "ch341eeprom.h" extern FILE *debugout, *verbout; -uint32_t getnextpkt; // set by the callback function -uint32_t syncackpkt; // synch / ack flag used by BULK OUT cb function -uint32_t byteoffset; // -------------------------------------------------------------------------- // ch341configure() @@ -43,16 +41,7 @@ uint32_t byteoffset; struct libusb_device_handle *ch341configure(uint16_t vid, uint16_t pid) { - - struct libusb_device *dev; - struct libusb_device_handle *devHandle; - int32_t ret = 0; // set to < 0 to indicate USB errors - uint32_t i = 0; - int32_t currentConfig = 0; - - uint8_t ch341DescriptorBuffer[0x12]; - - ret = libusb_init(NULL); + int32_t ret = libusb_init(NULL); if (ret < 0) { fprintf(stderr, "Couldnt initialise libusb\n"); return NULL; @@ -65,11 +54,13 @@ struct libusb_device_handle *ch341configure(uint16_t vid, uint16_t pid) fprintf(verbout, "Searching USB buses for WCH CH341a i2c EEPROM programmer [%04x:%04x]\n", USB_LOCK_VENDOR, USB_LOCK_PRODUCT); + struct libusb_device_handle *devHandle; if (!(devHandle = libusb_open_device_with_vid_pid(NULL, USB_LOCK_VENDOR, USB_LOCK_PRODUCT))) { fprintf(stderr, "Couldn't open device [%04x:%04x]\n", USB_LOCK_VENDOR, USB_LOCK_PRODUCT); return NULL; } + struct libusb_device *dev; if (!(dev = libusb_get_device(devHandle))) { fprintf(stderr, "Couldnt get bus number and address of device\n"); return NULL; @@ -89,6 +80,7 @@ struct libusb_device_handle *ch341configure(uint16_t vid, uint16_t pid) fprintf(verbout, "Detached kernel driver\n"); } + int32_t currentConfig = 0; ret = libusb_get_configuration(devHandle, ¤tConfig); if (ret) { fprintf(stderr, "Failed to get current device configuration: '%s'\n", strerror(-ret)); @@ -112,6 +104,7 @@ struct libusb_device_handle *ch341configure(uint16_t vid, uint16_t pid) fprintf(verbout, "Claimed device interface [%d]\n", DEFAULT_INTERFACE); + uint8_t ch341DescriptorBuffer[0x12]; ret = libusb_get_descriptor(devHandle, LIBUSB_DT_DEVICE, 0x00, ch341DescriptorBuffer, 0x12); if (ret < 0) { @@ -121,7 +114,7 @@ struct libusb_device_handle *ch341configure(uint16_t vid, uint16_t pid) fprintf(verbout, "Device reported its revision [%d.%02d]\n", ch341DescriptorBuffer[12], ch341DescriptorBuffer[13]); - for (i = 0; i < 0x12; i++) + for (unsigned i = 0; i < 0x12; ++i) fprintf(debugout, "%02x ", ch341DescriptorBuffer[i]); fprintf(debugout, "\n"); @@ -133,14 +126,14 @@ struct libusb_device_handle *ch341configure(uint16_t vid, uint16_t pid) // set the i2c bus speed (speed: 0 = 20kHz; 1 = 100kHz, 2 = 400kHz, 3 = 750kHz) int32_t ch341setstream(struct libusb_device_handle *devHandle, uint32_t speed) { - uint8_t ch341outBuffer[EEPROM_READ_BULKOUT_BUF_SZ], *outptr = ch341outBuffer; + uint8_t buffer[3]; int32_t actuallen = 0; - *outptr++ = mCH341A_CMD_I2C_STREAM; - *outptr++ = mCH341A_CMD_I2C_STM_SET | (speed & 0x3); - *outptr = mCH341A_CMD_I2C_STM_END; + buffer[0] = mCH341A_CMD_I2C_STREAM; + buffer[1] = mCH341A_CMD_I2C_STM_SET | (speed & 0x3); + buffer[2] = mCH341A_CMD_I2C_STM_END; - int ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, ch341outBuffer, 3, &actuallen, DEFAULT_TIMEOUT); + int ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, buffer, 3, &actuallen, DEFAULT_TIMEOUT); if (ret < 0) { fprintf(stderr, "ch341setstream(): Failed write %d bytes '%s'\n", 3, strerror(-ret)); @@ -149,61 +142,25 @@ int32_t ch341setstream(struct libusb_device_handle *devHandle, uint32_t speed) fprintf(debugout, "ch341setstream(): Wrote %d bytes: ", 3); for (unsigned i = 0; i < 3; ++i) - fprintf(debugout, "%02x ", ch341outBuffer[i]); + fprintf(debugout, "%02x ", buffer[i]); fprintf(debugout, "\n"); return 0; } -size_t ch341ReadCmdMarshall(uint8_t *buffer, uint32_t addr, const struct EEPROM *eeprom_info) +size_t ch341ReadCmdMarshall(uint8_t *buffer, uint8_t addr, uint32_t size) { uint8_t *ptr = buffer; - - // Frame 1. Program data address, and read 32 bytes. - *ptr++ = mCH341A_CMD_I2C_STREAM; // 0 - *ptr++ = mCH341A_CMD_I2C_STM_STA; // 1 - // Write address - *ptr++ = mCH341A_CMD_I2C_STM_OUT | ((*eeprom_info).addr_size + 1); // 2: I2C bus adddress + EEPROM address - uint8_t msb_addr; - if ((*eeprom_info).addr_size > 1) { - // 24C32 and more - msb_addr = addr >> 16 & (*eeprom_info).i2c_addr_mask; - *ptr++ = (EEPROM_I2C_BUS_ADDRESS | msb_addr) << 1; // 3 - *ptr++ = addr >> 8; // 4 - } else { - // 24C16 and less - msb_addr = addr >> 8 & (*eeprom_info).i2c_addr_mask; - *ptr++ = (EEPROM_I2C_BUS_ADDRESS | msb_addr) << 1; // 3 - } - *ptr++ = addr; // 5/4 - *ptr++ = mCH341A_CMD_I2C_STM_STA; // 6/5 - *ptr++ = mCH341A_CMD_I2C_STM_OUT | 1; // 7/6 - *ptr++ = (EEPROM_I2C_BUS_ADDRESS | msb_addr) << 1 | 1; // 8/7: Read command -#if 0 - // Read 32 bytes - *ptr++ = mCH341A_CMD_I2C_STM_IN | 32; // 9/8 - *ptr++ = mCH341A_CMD_I2C_STM_END; // 10/9 - - // Frame 2 - read 32 bytes - ptr = &buffer[32]; - *ptr++ = mCH341A_CMD_I2C_STREAM; - *ptr++ = mCH341A_CMD_I2C_STM_IN | 32; - *ptr++ = mCH341A_CMD_I2C_STM_END; - - // Frame 3 - read 32 bytes - ptr = &buffer[64]; *ptr++ = mCH341A_CMD_I2C_STREAM; - *ptr++ = mCH341A_CMD_I2C_STM_IN | 32; - *ptr++ = mCH341A_CMD_I2C_STM_END; - - // Finalize - read last 32 bytes - ptr = &buffer[96]; - *ptr++ = mCH341A_CMD_I2C_STREAM; -#endif - *ptr++ = mCH341A_CMD_I2C_STM_IN | 31; + *ptr++ = mCH341A_CMD_I2C_STM_STA; + *ptr++ = mCH341A_CMD_I2C_STM_OUT | 1; + *ptr++ = (addr << 1) | 1; + if (size > 1) { + *ptr++ = mCH341A_CMD_I2C_STM_IN | (size - 1); + } *ptr++ = mCH341A_CMD_I2C_STM_IN; *ptr++ = mCH341A_CMD_I2C_STM_STO; *ptr++ = mCH341A_CMD_I2C_STM_END; - + unsigned xfer_len = ptr - buffer; fprintf(debugout, "\nch341ReadCmdMarshall(): prepared %d bytes\n", xfer_len); for (unsigned i = 0; i < xfer_len; ++i) { @@ -216,112 +173,134 @@ size_t ch341ReadCmdMarshall(uint8_t *buffer, uint32_t addr, const struct EEPROM return ptr - buffer; } -// -------------------------------------------------------------------------- -// ch341readEEPROM() -// read n bytes from device (in packets of 32 bytes) -int32_t ch341readEEPROM(struct libusb_device_handle *devHandle, uint8_t *buffer, uint32_t bytestoread, const struct EEPROM *eeprom_info) +int ch341_i2c_read(struct libusb_device_handle *devHandle, struct i2c_msg *msg) { - - uint8_t ch341outBuffer[EEPROM_READ_BULKOUT_BUF_SZ]; - uint8_t ch341inBuffer[IN_BUF_SZ]; // 0x100 bytes - int32_t ret = 0; - struct libusb_transfer *xferBulkIn, *xferBulkOut; - struct timeval tv = { 0, 100 }; // our async polling interval - size_t xfer_size; - - xferBulkIn = libusb_alloc_transfer(0); - xferBulkOut = libusb_alloc_transfer(0); - - if (!xferBulkIn || !xferBulkOut) { - fprintf(stderr, "Couldnt allocate USB transfer structures\n"); - return -1; + unsigned byteoffset = 0; + uint8_t ch341inBuffer[32]; + uint8_t ch341outBuffer[32]; + while (msg->len - byteoffset > 0) { + unsigned bytestoread = msg->len - byteoffset; + if (bytestoread > 32) + bytestoread = 32; + + size_t xfer_size = ch341ReadCmdMarshall(ch341outBuffer, msg->addr, bytestoread); + int actuallen = 0; + int ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, ch341outBuffer, xfer_size, &actuallen, DEFAULT_TIMEOUT); + if (ret < 0) { + fprintf(stderr, "USB read error : %s\n", strerror(-ret)); + return ret; + } + ret = libusb_bulk_transfer(devHandle, BULK_READ_ENDPOINT, ch341inBuffer, bytestoread, &actuallen, DEFAULT_TIMEOUT); + if (ret < 0) { + fprintf(stderr, "USB read error : %s\n", strerror(-ret)); + return ret; + } + if (actuallen != bytestoread) { + fprintf(stderr, "actuallen != bytestoread\b"); + return -1; + } + memcpy(&msg->buf[byteoffset], ch341inBuffer, actuallen); + byteoffset += actuallen; } + return 0; +} - byteoffset = 0; - - fprintf(debugout, "Allocated USB transfer structures\n"); - - memset(ch341inBuffer, 0, EEPROM_READ_BULKIN_BUF_SZ); - xfer_size = ch341ReadCmdMarshall(ch341outBuffer, 0, eeprom_info); // Fill output buffer +int ch341_i2c_write(struct libusb_device_handle *devHandle, struct i2c_msg *msg) { + uint8_t buffer[32]; + unsigned left = msg->len + 1; + uint8_t *ptr = msg->buf; + bool first = true; + do { + uint8_t *outptr = buffer; + *outptr++ = mCH341A_CMD_I2C_STREAM; + if (first) { // Start packet + *outptr++ = mCH341A_CMD_I2C_STM_STA; + } + // middle packet has 29 slots + uint8_t to_write = (left < 29) ? left : (!first) + 28; + *outptr++ = mCH341A_CMD_I2C_STM_OUT | to_write; + if (first) { + *outptr++ = msg->addr << 1; + --left; + --to_write; + } + memcpy(outptr, ptr, to_write); + outptr += to_write; + ptr += to_write; + if (left == 0) { // handle msg->len == 0 case + *outptr++ = mCH341A_CMD_I2C_STM_IN; + } + left -= to_write; + if (left == 0) { // Stop packet + *outptr++ = mCH341A_CMD_I2C_STM_STO; + } + *outptr++ = mCH341A_CMD_I2C_STM_END; - libusb_fill_bulk_transfer(xferBulkIn, devHandle, BULK_READ_ENDPOINT, ch341inBuffer, EEPROM_READ_BULKIN_BUF_SZ, cbBulkIn, NULL, DEFAULT_TIMEOUT); + uint32_t payload_size = outptr - buffer; - libusb_fill_bulk_transfer(xferBulkOut, devHandle, BULK_WRITE_ENDPOINT, ch341outBuffer, xfer_size, cbBulkOut, NULL, DEFAULT_TIMEOUT); + for (unsigned i = 0; i < payload_size; ++i) { + if (!(i % 0x10)) + fprintf(debugout, "\n%04x : ", i); + fprintf(debugout, "%02x ", buffer[i]); + } + fprintf(debugout, "\n"); - fprintf(debugout, "Filled USB transfer structures\n"); + first = false; + int actuallen = 0, ret = 0; + ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, buffer, payload_size, &actuallen, DEFAULT_TIMEOUT); - libusb_submit_transfer(xferBulkIn); - fprintf(debugout, "Submitted BULK IN start packet\n"); - libusb_submit_transfer(xferBulkOut); - fprintf(debugout, "Submitted BULK OUT setup packet\n"); + if (ret < 0) { + fprintf(stderr, "Failed to write to I2C: '%s'\n", strerror(-ret)); + return -1; + } + } while (left); - readbuf = buffer; - while (1) { - fprintf(stdout, "Read %d%% [%d] of [%d] bytes\r", (100 * byteoffset) / bytestoread, byteoffset, bytestoread); - ret = libusb_handle_events_timeout(NULL, &tv); + return 0; +} - if (ret < 0 || getnextpkt == -1) { // indicates an error - fprintf(stderr, "ret from libusb_handle_timeout = %d\n", ret); - fprintf(stderr, "getnextpkt = %d\n", getnextpkt); - if (ret < 0) - fprintf(stderr, "USB read error : %s\n", strerror(-ret)); - goto cleanup; - } - if (getnextpkt == 1) { // callback function reports a new BULK IN packet received - getnextpkt = 0; // reset the flag - byteoffset += EEPROM_READ_BULKIN_BUF_SZ; - if (byteoffset == bytestoread) - break; - - fprintf(debugout, "\nRe-submitting transfer request to BULK IN endpoint\n"); - libusb_submit_transfer(xferBulkIn); // re-submit request for next BULK IN packet of EEPROM data - if (syncackpkt) - syncackpkt = 0; - fprintf(debugout, "\nSubmitting next transfer request to BULK OUT endpoint\n"); - ch341ReadCmdMarshall(ch341outBuffer, byteoffset, eeprom_info); // Fill output buffer - libusb_fill_bulk_transfer(xferBulkOut, devHandle, BULK_WRITE_ENDPOINT, ch341outBuffer, xfer_size, cbBulkOut, NULL, DEFAULT_TIMEOUT); - - libusb_submit_transfer(xferBulkOut); // update transfer struct (with new EEPROM page offset) - // and re-submit next transfer request to BULK OUT endpoint +int ch341_i2x_xfer(struct libusb_device_handle *devHandle, struct i2c_msg *msg, unsigned num) { + for (unsigned i = 0; i < num; ++i) { + if (msg[i].flags & I2C_M_RD) { + int ret = ch341_i2c_read(devHandle, &msg[i]); + if (ret) return ret; + } else { + int ret = ch341_i2c_write(devHandle, &msg[i]); + if (ret) return ret; } } -cleanup: - libusb_free_transfer(xferBulkIn); - libusb_free_transfer(xferBulkOut); - return ret; + return 0; } -// Callback function for async bulk in comms -void cbBulkIn(struct libusb_transfer *transfer) +// -------------------------------------------------------------------------- +// ch341readEEPROM() +// read n bytes from device (in packets of 32 bytes) +int ch341readEEPROM(struct libusb_device_handle *devHandle, uint8_t *buffer, uint32_t bytestoread, const struct EEPROM *eeprom_info) { - switch (transfer->status) { - case LIBUSB_TRANSFER_COMPLETED: - // display the contents of the BULK IN data buffer - fprintf(debugout, "\ncbBulkIn(): status %d - Read %d bytes\n", transfer->status, transfer->actual_length); - - for (unsigned i = 0; i < transfer->actual_length; ++i) { - if (!(i % 16)) - fprintf(debugout, "\n "); - fprintf(debugout, "%02x ", transfer->buffer[i]); - } - fprintf(debugout, "\n"); - // copy read data to our EEPROM buffer - memcpy(readbuf + byteoffset, transfer->buffer, transfer->actual_length); - getnextpkt = 1; - break; - default: - fprintf(stderr, "\ncbBulkIn: error : %d\n", transfer->status); - getnextpkt = -1; - } - return; + struct i2c_msg msg[2]; + + uint8_t out[2] = {0}; + msg[0].len = eeprom_info->addr_size; + msg[0].flags = 0; + msg[0].addr = EEPROM_I2C_BUS_ADDRESS; + msg[0].buf = out; + msg[1].flags = I2C_M_RD; + msg[1].buf = buffer; + msg[1].addr = EEPROM_I2C_BUS_ADDRESS; + msg[1].len = bytestoread; // + + //msg[1].len = bytestoread; + + return ch341_i2x_xfer(devHandle, msg, 2); } -// Callback function for async bulk out comms -void cbBulkOut(struct libusb_transfer *transfer) -{ - syncackpkt = 1; - fprintf(debugout, "\ncbBulkOut(): Sync/Ack received: status %d\n", transfer->status); - return; +int ch341delay_ms(struct libusb_device_handle *devHandle, unsigned ms) { + fprintf(debugout, "Writing [aa 5a 00] to EEPROM\n"); + uint8_t buffer[3]; + buffer[0] = mCH341A_CMD_I2C_STREAM; + buffer[1] = mCH341A_CMD_I2C_STM_MS | (ms & 0xf); // Wait 10ms (?) + buffer[2] = mCH341A_CMD_I2C_STM_END; + int actuallen = 0; + return libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, buffer, 3, &actuallen, DEFAULT_TIMEOUT); } // -------------------------------------------------------------------------- @@ -329,98 +308,39 @@ void cbBulkOut(struct libusb_transfer *transfer) // write n bytes to 24c32/24c64 device (in packets of 32 bytes) int32_t ch341writeEEPROM(struct libusb_device_handle *devHandle, uint8_t *buffer, uint32_t bytesum, const struct EEPROM *eeprom_info) { - - uint8_t ch341outBuffer[512]; - uint8_t *outptr, *bufptr; - uint8_t i2cCmdBuffer[256]; - int32_t ret = 0; - uint32_t byteoffset = 0; - uint32_t bytes = bytesum; - uint8_t addrbytecount = eeprom_info->addr_size + 1; // 24c32 and 24c64 (and other 24c??) use 3 bytes for addressing - int32_t actuallen = 0; - uint16_t page_size = eeprom_info->page_size; - - bufptr = buffer; - - while (bytes) { - outptr = i2cCmdBuffer; + uint8_t msgbuffer[256 + 2]; // max EEPROM page size is 256 in 2M part, and 2 bytes for address + struct i2c_msg msg; + msg.addr = EEPROM_I2C_BUS_ADDRESS; + msg.buf = msgbuffer; + msg.flags = 0; + unsigned offset = 0; + while (offset < bytesum) { + uint8_t *outptr = msgbuffer; + unsigned wlen = eeprom_info->page_size; if (eeprom_info->addr_size > 1) { - *outptr++ = 0xa0 | ((byteoffset >> 15) & (eeprom_info->i2c_addr_mask << 1)); // EEPROM device address - *outptr++ = byteoffset >> 8 & 0xff; // MSB (big-endian) byte address - } else { - *outptr++ = 0xa0 | ((byteoffset >> 7) & (eeprom_info->i2c_addr_mask << 1)); // EEPROM device address - } - *outptr++ = byteoffset & 0xff; // LSB of 16-bit byte address - - memcpy(outptr, bufptr, page_size); // Copy one page - - byteoffset += page_size; - bufptr += page_size; - bytes -= page_size; - - outptr = ch341outBuffer; - uint16_t page_size_left = page_size + addrbytecount; - uint8_t part_no = 0; - uint8_t *i2cBufPtr = i2cCmdBuffer; - while (page_size_left) { - *outptr++ = mCH341A_CMD_I2C_STREAM; - if (part_no == 0) { // Start packet - *outptr++ = mCH341A_CMD_I2C_STM_STA; - } - // middle packet has 29 slots - uint8_t to_write = (page_size_left < 29) ? page_size_left : (part_no != 0) + 28; - *outptr++ = mCH341A_CMD_I2C_STM_OUT | to_write; - memcpy(outptr, i2cBufPtr, to_write); - outptr += to_write; - i2cBufPtr += to_write; - page_size_left -= to_write; - - if (page_size_left == 0) { // Stop packet - *outptr++ = mCH341A_CMD_I2C_STM_STO; - } - *outptr++ = mCH341A_CMD_I2C_STM_END; - ++part_no; + *outptr++ = offset >> 8; } - uint32_t payload_size = outptr - ch341outBuffer; - - for (unsigned i = 0; i < payload_size; ++i) { - if (!(i % 0x10)) - fprintf(debugout, "\n%04x : ", i); - fprintf(debugout, "%02x ", ch341outBuffer[i]); + *outptr++ = offset; + if (bytesum - offset < wlen) { + wlen = bytesum - offset; } - fprintf(debugout, "\n"); - - ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, ch341outBuffer, payload_size, &actuallen, DEFAULT_TIMEOUT); - + memcpy(outptr, buffer + offset, wlen); + outptr += wlen; + msg.len = outptr - msgbuffer; + int ret = 0; + ret = ch341_i2x_xfer(devHandle, &msg, 1); if (ret < 0) { fprintf(stderr, "Failed to write to EEPROM: '%s'\n", strerror(-ret)); return -1; } + offset += wlen; - fprintf(debugout, "Writing [aa 5a 00] to EEPROM\n"); - - outptr = ch341outBuffer; - *outptr++ = mCH341A_CMD_I2C_STREAM; - *outptr++ = mCH341A_CMD_I2C_STM_MS | 10; // Wait 10ms (?) - *outptr++ = mCH341A_CMD_I2C_STM_END; - - ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, ch341outBuffer, 3, &actuallen, DEFAULT_TIMEOUT); - + ret = ch341delay_ms(devHandle, 10); if (ret < 0) { fprintf(stderr, "Failed to set timeout: '%s'\n", strerror(-ret)); return -1; } - - /* - struct timeval tv = {0, 100}; // our async polling interval - ret = libusb_handle_events_timeout(NULL, &tv); - if (ret < 0) { // indicates an error - fprintf(stderr, "ret from libusb_handle_timeout = %d\n", ret); - fprintf(stderr, "USB read error : %s\n", strerror(-ret)); - return -1; - } - */ - fprintf(stdout, "Written %d%% [%d] of [%d] bytes \r", 100 * (bytesum - bytes) / bytesum, bytesum - bytes, bytesum); + fprintf(stdout, "Written %d%% [%d] of [%d] bytes\r", 100 * offset / bytesum, offset, bytesum); } return 0; } From 40bf1a20be3be6b3db3f5733241c4d8bfb4fe4c7 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Mon, 27 Mar 2023 18:52:11 +0300 Subject: [PATCH 4/7] write offset calculation --- ch341funcs.c | 115 +++++++++++++++++++++++---------------------------- 1 file changed, 52 insertions(+), 63 deletions(-) diff --git a/ch341funcs.c b/ch341funcs.c index cedcc16..3fc496a 100644 --- a/ch341funcs.c +++ b/ch341funcs.c @@ -30,6 +30,11 @@ extern FILE *debugout, *verbout; +struct xxx { + uint8_t ibuf[32]; + uint8_t obuf[32]; +} i2c_dev; + // -------------------------------------------------------------------------- // ch341configure() // lock USB device for exclusive use @@ -126,14 +131,13 @@ struct libusb_device_handle *ch341configure(uint16_t vid, uint16_t pid) // set the i2c bus speed (speed: 0 = 20kHz; 1 = 100kHz, 2 = 400kHz, 3 = 750kHz) int32_t ch341setstream(struct libusb_device_handle *devHandle, uint32_t speed) { - uint8_t buffer[3]; int32_t actuallen = 0; - buffer[0] = mCH341A_CMD_I2C_STREAM; - buffer[1] = mCH341A_CMD_I2C_STM_SET | (speed & 0x3); - buffer[2] = mCH341A_CMD_I2C_STM_END; + i2c_dev.obuf[0] = mCH341A_CMD_I2C_STREAM; + i2c_dev.obuf[1] = mCH341A_CMD_I2C_STM_SET | (speed & 0x3); + i2c_dev.obuf[2] = mCH341A_CMD_I2C_STM_END; - int ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, buffer, 3, &actuallen, DEFAULT_TIMEOUT); + int ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, i2c_dev.obuf, 3, &actuallen, DEFAULT_TIMEOUT); if (ret < 0) { fprintf(stderr, "ch341setstream(): Failed write %d bytes '%s'\n", 3, strerror(-ret)); @@ -142,55 +146,37 @@ int32_t ch341setstream(struct libusb_device_handle *devHandle, uint32_t speed) fprintf(debugout, "ch341setstream(): Wrote %d bytes: ", 3); for (unsigned i = 0; i < 3; ++i) - fprintf(debugout, "%02x ", buffer[i]); + fprintf(debugout, "%02x ", i2c_dev.obuf[i]); fprintf(debugout, "\n"); return 0; } -size_t ch341ReadCmdMarshall(uint8_t *buffer, uint8_t addr, uint32_t size) -{ - uint8_t *ptr = buffer; - *ptr++ = mCH341A_CMD_I2C_STREAM; - *ptr++ = mCH341A_CMD_I2C_STM_STA; - *ptr++ = mCH341A_CMD_I2C_STM_OUT | 1; - *ptr++ = (addr << 1) | 1; - if (size > 1) { - *ptr++ = mCH341A_CMD_I2C_STM_IN | (size - 1); - } - *ptr++ = mCH341A_CMD_I2C_STM_IN; - *ptr++ = mCH341A_CMD_I2C_STM_STO; - *ptr++ = mCH341A_CMD_I2C_STM_END; - - unsigned xfer_len = ptr - buffer; - fprintf(debugout, "\nch341ReadCmdMarshall(): prepared %d bytes\n", xfer_len); - for (unsigned i = 0; i < xfer_len; ++i) { - if (!(i % 16)) - fprintf(debugout, "\n "); - fprintf(debugout, "%02x ", buffer[i]); - } - fprintf(debugout, "\n"); - - return ptr - buffer; -} - int ch341_i2c_read(struct libusb_device_handle *devHandle, struct i2c_msg *msg) { unsigned byteoffset = 0; - uint8_t ch341inBuffer[32]; - uint8_t ch341outBuffer[32]; while (msg->len - byteoffset > 0) { unsigned bytestoread = msg->len - byteoffset; if (bytestoread > 32) bytestoread = 32; + uint8_t *ptr = i2c_dev.obuf; + *ptr++ = mCH341A_CMD_I2C_STREAM; + *ptr++ = mCH341A_CMD_I2C_STM_STA; + *ptr++ = mCH341A_CMD_I2C_STM_OUT | 1; + *ptr++ = (msg->addr << 1) | 1; + if (bytestoread > 1) { + *ptr++ = mCH341A_CMD_I2C_STM_IN | (bytestoread - 1); + } + *ptr++ = mCH341A_CMD_I2C_STM_IN; + *ptr++ = mCH341A_CMD_I2C_STM_STO; + *ptr++ = mCH341A_CMD_I2C_STM_END; - size_t xfer_size = ch341ReadCmdMarshall(ch341outBuffer, msg->addr, bytestoread); int actuallen = 0; - int ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, ch341outBuffer, xfer_size, &actuallen, DEFAULT_TIMEOUT); + int ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, i2c_dev.obuf, ptr - i2c_dev.obuf, &actuallen, DEFAULT_TIMEOUT); if (ret < 0) { fprintf(stderr, "USB read error : %s\n", strerror(-ret)); return ret; } - ret = libusb_bulk_transfer(devHandle, BULK_READ_ENDPOINT, ch341inBuffer, bytestoread, &actuallen, DEFAULT_TIMEOUT); + ret = libusb_bulk_transfer(devHandle, BULK_READ_ENDPOINT, i2c_dev.ibuf, bytestoread, &actuallen, DEFAULT_TIMEOUT); if (ret < 0) { fprintf(stderr, "USB read error : %s\n", strerror(-ret)); return ret; @@ -199,55 +185,59 @@ int ch341_i2c_read(struct libusb_device_handle *devHandle, struct i2c_msg *msg) fprintf(stderr, "actuallen != bytestoread\b"); return -1; } - memcpy(&msg->buf[byteoffset], ch341inBuffer, actuallen); + memcpy(&msg->buf[byteoffset], i2c_dev.ibuf, actuallen); byteoffset += actuallen; } return 0; } int ch341_i2c_write(struct libusb_device_handle *devHandle, struct i2c_msg *msg) { - uint8_t buffer[32]; - unsigned left = msg->len + 1; + unsigned left = msg->len; uint8_t *ptr = msg->buf; bool first = true; do { - uint8_t *outptr = buffer; + uint8_t *outptr = i2c_dev.obuf; *outptr++ = mCH341A_CMD_I2C_STREAM; if (first) { // Start packet *outptr++ = mCH341A_CMD_I2C_STM_STA; } - // middle packet has 29 slots - uint8_t to_write = (left < 29) ? left : (!first) + 28; - *outptr++ = mCH341A_CMD_I2C_STM_OUT | to_write; + uint8_t *lenptr = outptr++; if (first) { *outptr++ = msg->addr << 1; - --left; - --to_write; + if (left == 0) { + *outptr++ = mCH341A_CMD_I2C_STM_IN; + } } - memcpy(outptr, ptr, to_write); - outptr += to_write; - ptr += to_write; - if (left == 0) { // handle msg->len == 0 case - *outptr++ = mCH341A_CMD_I2C_STM_IN; + unsigned avail = 32 - (outptr - i2c_dev.obuf) - 1; + unsigned wlen = avail; + if (left < avail) { + wlen = left; + } else if (left == avail) { + wlen = avail - 1; } - left -= to_write; + memcpy(outptr, ptr, wlen); + outptr += wlen; + ptr += wlen; + left -= wlen; + wlen = outptr - lenptr; + *lenptr = mCH341A_CMD_I2C_STM_OUT | wlen; if (left == 0) { // Stop packet *outptr++ = mCH341A_CMD_I2C_STM_STO; } *outptr++ = mCH341A_CMD_I2C_STM_END; - uint32_t payload_size = outptr - buffer; - - for (unsigned i = 0; i < payload_size; ++i) { + wlen = outptr - i2c_dev.obuf; + assert(wlen <= 32); + for (unsigned i = 0; i < wlen; ++i) { if (!(i % 0x10)) - fprintf(debugout, "\n%04x : ", i); - fprintf(debugout, "%02x ", buffer[i]); + fprintf(debugout, "\n%02x : ", i); + fprintf(debugout, "%02x ", i2c_dev.obuf[i]); } fprintf(debugout, "\n"); first = false; int actuallen = 0, ret = 0; - ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, buffer, payload_size, &actuallen, DEFAULT_TIMEOUT); + //ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, i2c_dev.obuf, wlen, &actuallen, DEFAULT_TIMEOUT); if (ret < 0) { fprintf(stderr, "Failed to write to I2C: '%s'\n", strerror(-ret)); @@ -295,12 +285,11 @@ int ch341readEEPROM(struct libusb_device_handle *devHandle, uint8_t *buffer, uin int ch341delay_ms(struct libusb_device_handle *devHandle, unsigned ms) { fprintf(debugout, "Writing [aa 5a 00] to EEPROM\n"); - uint8_t buffer[3]; - buffer[0] = mCH341A_CMD_I2C_STREAM; - buffer[1] = mCH341A_CMD_I2C_STM_MS | (ms & 0xf); // Wait 10ms (?) - buffer[2] = mCH341A_CMD_I2C_STM_END; + i2c_dev.obuf[0] = mCH341A_CMD_I2C_STREAM; + i2c_dev.obuf[1] = mCH341A_CMD_I2C_STM_MS | (ms & 0xf); // Wait 10ms (?) + i2c_dev.obuf[2] = mCH341A_CMD_I2C_STM_END; int actuallen = 0; - return libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, buffer, 3, &actuallen, DEFAULT_TIMEOUT); + return libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, i2c_dev.obuf, 3, &actuallen, DEFAULT_TIMEOUT); } // -------------------------------------------------------------------------- From 976e6e93db055428e438d2799c1b3d9aac16f038 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Fri, 7 Apr 2023 22:09:46 +0300 Subject: [PATCH 5/7] Optimize command sequences, add scan command with SMB_QUICK_WRITE --- ch341eeprom.c | 20 +++++++++++++-- ch341eeprom.h | 1 + ch341funcs.c | 68 +++++++++++++++++++++++++++++++++------------------ 3 files changed, 63 insertions(+), 26 deletions(-) diff --git a/ch341eeprom.c b/ch341eeprom.c index 6db502d..ec55726 100644 --- a/ch341eeprom.c +++ b/ch341eeprom.c @@ -79,6 +79,7 @@ int main(int argc, char **argv) { "read", required_argument, 0, 'r' }, { "write", required_argument, 0, 'w' }, { "verify", required_argument, 0, 'V' }, + { "scan", no_argument, 0, 'x' }, { 0, 0, 0, 0 } }; @@ -86,7 +87,7 @@ int main(int argc, char **argv) while (true) { int32_t optidx = 0; - int8_t c = getopt_long(argc, argv, "hvdes:p:w:r:V:", longopts, &optidx); + int8_t c = getopt_long(argc, argv, "hvdexs:p:w:r:V:", longopts, &optidx); if (c == -1) break; @@ -149,6 +150,15 @@ int main(int argc, char **argv) return -1; } break; + case 'x': + if (!operation) + operation = 'x'; + else { + fprintf(stderr, "Conflicting command line options\n"); + return -1; + } + break; + default: case '?': fprintf(stdout, "%s", version_msg); @@ -166,7 +176,7 @@ int main(int argc, char **argv) return -1; } - if (eepromsize <= 0) { + if (eepromsize <= 0 && operation != 'x') { fprintf(stderr, "Invalid EEPROM size\n"); return -1; } @@ -301,6 +311,12 @@ int main(int argc, char **argv) } fprintf(stdout, "Erased [%d] bytes of [%s] EEPROM\n", eepromsize, eepromname); break; + case 'x': {// scan + for (unsigned i = 0x8; i < 0x80; ++i) { + ch341_quick_write(devHandle, i); + } + break; + } default: fprintf(stderr, "Unknown option\n"); } diff --git a/ch341eeprom.h b/ch341eeprom.h index 7d7379e..16c29a2 100644 --- a/ch341eeprom.h +++ b/ch341eeprom.h @@ -147,4 +147,5 @@ int32_t ch341readEEPROM(struct libusb_device_handle *devHandle, uint8_t * buf, u int32_t ch341writeEEPROM(struct libusb_device_handle *devHandle, uint8_t * buf, uint32_t bytes, const struct EEPROM *eeprom_info); struct libusb_device_handle *ch341configure(uint16_t vid, uint16_t pid); int32_t ch341setstream(struct libusb_device_handle *devHandle, uint32_t speed); +int ch341_quick_write(struct libusb_device_handle *devHandle, uint8_t addr); int32_t parseEEPsize(char *eepromname, const struct EEPROM **eeprom); diff --git a/ch341funcs.c b/ch341funcs.c index 3fc496a..c752d4a 100644 --- a/ch341funcs.c +++ b/ch341funcs.c @@ -135,17 +135,16 @@ int32_t ch341setstream(struct libusb_device_handle *devHandle, uint32_t speed) i2c_dev.obuf[0] = mCH341A_CMD_I2C_STREAM; i2c_dev.obuf[1] = mCH341A_CMD_I2C_STM_SET | (speed & 0x3); - i2c_dev.obuf[2] = mCH341A_CMD_I2C_STM_END; - int ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, i2c_dev.obuf, 3, &actuallen, DEFAULT_TIMEOUT); + int ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, i2c_dev.obuf, 2, &actuallen, DEFAULT_TIMEOUT); if (ret < 0) { - fprintf(stderr, "ch341setstream(): Failed write %d bytes '%s'\n", 3, strerror(-ret)); + fprintf(stderr, "ch341setstream(): Failed write %d bytes '%s'\n", 2, strerror(-ret)); return -1; } - fprintf(debugout, "ch341setstream(): Wrote %d bytes: ", 3); - for (unsigned i = 0; i < 3; ++i) + fprintf(debugout, "ch341setstream(): Wrote 2 bytes: "); + for (unsigned i = 0; i < 2; ++i) fprintf(debugout, "%02x ", i2c_dev.obuf[i]); fprintf(debugout, "\n"); return 0; @@ -168,12 +167,11 @@ int ch341_i2c_read(struct libusb_device_handle *devHandle, struct i2c_msg *msg) } *ptr++ = mCH341A_CMD_I2C_STM_IN; *ptr++ = mCH341A_CMD_I2C_STM_STO; - *ptr++ = mCH341A_CMD_I2C_STM_END; int actuallen = 0; int ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, i2c_dev.obuf, ptr - i2c_dev.obuf, &actuallen, DEFAULT_TIMEOUT); if (ret < 0) { - fprintf(stderr, "USB read error : %s\n", strerror(-ret)); + fprintf(stderr, "USB write error : %s\n", strerror(-ret)); return ret; } ret = libusb_bulk_transfer(devHandle, BULK_READ_ENDPOINT, i2c_dev.ibuf, bytestoread, &actuallen, DEFAULT_TIMEOUT); @@ -204,11 +202,8 @@ int ch341_i2c_write(struct libusb_device_handle *devHandle, struct i2c_msg *msg) uint8_t *lenptr = outptr++; if (first) { *outptr++ = msg->addr << 1; - if (left == 0) { - *outptr++ = mCH341A_CMD_I2C_STM_IN; - } } - unsigned avail = 32 - (outptr - i2c_dev.obuf) - 1; + unsigned avail = 32 - (outptr - i2c_dev.obuf); unsigned wlen = avail; if (left < avail) { wlen = left; @@ -219,12 +214,11 @@ int ch341_i2c_write(struct libusb_device_handle *devHandle, struct i2c_msg *msg) outptr += wlen; ptr += wlen; left -= wlen; - wlen = outptr - lenptr; + wlen = outptr - lenptr - 1; *lenptr = mCH341A_CMD_I2C_STM_OUT | wlen; if (left == 0) { // Stop packet *outptr++ = mCH341A_CMD_I2C_STM_STO; } - *outptr++ = mCH341A_CMD_I2C_STM_END; wlen = outptr - i2c_dev.obuf; assert(wlen <= 32); @@ -237,7 +231,7 @@ int ch341_i2c_write(struct libusb_device_handle *devHandle, struct i2c_msg *msg) first = false; int actuallen = 0, ret = 0; - //ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, i2c_dev.obuf, wlen, &actuallen, DEFAULT_TIMEOUT); + ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, i2c_dev.obuf, wlen, &actuallen, DEFAULT_TIMEOUT); if (ret < 0) { fprintf(stderr, "Failed to write to I2C: '%s'\n", strerror(-ret)); @@ -248,7 +242,7 @@ int ch341_i2c_write(struct libusb_device_handle *devHandle, struct i2c_msg *msg) return 0; } -int ch341_i2x_xfer(struct libusb_device_handle *devHandle, struct i2c_msg *msg, unsigned num) { +int ch341_i2c_xfer(struct libusb_device_handle *devHandle, struct i2c_msg *msg, unsigned num) { for (unsigned i = 0; i < num; ++i) { if (msg[i].flags & I2C_M_RD) { int ret = ch341_i2c_read(devHandle, &msg[i]); @@ -273,25 +267,51 @@ int ch341readEEPROM(struct libusb_device_handle *devHandle, uint8_t *buffer, uin msg[0].flags = 0; msg[0].addr = EEPROM_I2C_BUS_ADDRESS; msg[0].buf = out; + msg[1].flags = I2C_M_RD; msg[1].buf = buffer; msg[1].addr = EEPROM_I2C_BUS_ADDRESS; - msg[1].len = bytestoread; // + msg[1].len = bytestoread; - //msg[1].len = bytestoread; - - return ch341_i2x_xfer(devHandle, msg, 2); + return ch341_i2c_xfer(devHandle, msg, 2); } int ch341delay_ms(struct libusb_device_handle *devHandle, unsigned ms) { - fprintf(debugout, "Writing [aa 5a 00] to EEPROM\n"); i2c_dev.obuf[0] = mCH341A_CMD_I2C_STREAM; - i2c_dev.obuf[1] = mCH341A_CMD_I2C_STM_MS | (ms & 0xf); // Wait 10ms (?) - i2c_dev.obuf[2] = mCH341A_CMD_I2C_STM_END; + i2c_dev.obuf[1] = mCH341A_CMD_I2C_STM_MS | (ms & 0xf); // Wait up to 15ms int actuallen = 0; - return libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, i2c_dev.obuf, 3, &actuallen, DEFAULT_TIMEOUT); + return libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, i2c_dev.obuf, 2, &actuallen, DEFAULT_TIMEOUT); } +int ch341_quick_write(struct libusb_device_handle *devHandle, uint8_t addr) { + unsigned olen = 0; + i2c_dev.obuf[olen++] = mCH341A_CMD_I2C_STREAM; + i2c_dev.obuf[olen++] = mCH341A_CMD_I2C_STM_STA; + i2c_dev.obuf[olen++] = mCH341A_CMD_I2C_STM_OUT; +#if 0 + i2c_dev.obuf[olen++] = addr << 1 | 1; // READ1 + i2c_dev.obuf[olen++] = mCH341A_CMD_I2C_STM_IN; +#else + i2c_dev.obuf[olen++] = addr << 1; // WRITE +#endif + i2c_dev.obuf[olen++] = mCH341A_CMD_I2C_STM_STO; + int actuallen = 0; + int ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, i2c_dev.obuf, olen, &actuallen, DEFAULT_TIMEOUT); + if (ret < 0) { + fprintf(stderr, "USB write error : %s\n", strerror(-ret)); + return ret; + } + ret = libusb_bulk_transfer(devHandle, BULK_READ_ENDPOINT, i2c_dev.ibuf, 32, &actuallen, DEFAULT_TIMEOUT); + if (ret < 0) { + fprintf(stderr, "USB read error : %s\n", strerror(-ret)); + return ret; + } + for (unsigned i = 0; i < actuallen; ++i) { + fprintf(debugout, "%02x ", i2c_dev.ibuf[i]); + } + fprintf(debugout, "0x%02x: %s\n", addr, (i2c_dev.ibuf[0] & 0x80) ? "NACK" : "ACK"); + return 0; +} // -------------------------------------------------------------------------- // ch341writeEEPROM() // write n bytes to 24c32/24c64 device (in packets of 32 bytes) @@ -317,7 +337,7 @@ int32_t ch341writeEEPROM(struct libusb_device_handle *devHandle, uint8_t *buffer outptr += wlen; msg.len = outptr - msgbuffer; int ret = 0; - ret = ch341_i2x_xfer(devHandle, &msg, 1); + ret = ch341_i2c_xfer(devHandle, &msg, 1); if (ret < 0) { fprintf(stderr, "Failed to write to EEPROM: '%s'\n", strerror(-ret)); return -1; From 693cfd326ee5c77ff12bb2ec901a39332509fee4 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Sat, 8 Apr 2023 17:34:13 +0300 Subject: [PATCH 6/7] Add checks for ACK --- ch341funcs.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/ch341funcs.c b/ch341funcs.c index c752d4a..cd809b6 100644 --- a/ch341funcs.c +++ b/ch341funcs.c @@ -155,12 +155,12 @@ int ch341_i2c_read(struct libusb_device_handle *devHandle, struct i2c_msg *msg) unsigned byteoffset = 0; while (msg->len - byteoffset > 0) { unsigned bytestoread = msg->len - byteoffset; - if (bytestoread > 32) - bytestoread = 32; + if (bytestoread > 31) // reserve first byte for status + bytestoread = 31; uint8_t *ptr = i2c_dev.obuf; *ptr++ = mCH341A_CMD_I2C_STREAM; *ptr++ = mCH341A_CMD_I2C_STM_STA; - *ptr++ = mCH341A_CMD_I2C_STM_OUT | 1; + *ptr++ = mCH341A_CMD_I2C_STM_OUT; // ask for status *ptr++ = (msg->addr << 1) | 1; if (bytestoread > 1) { *ptr++ = mCH341A_CMD_I2C_STM_IN | (bytestoread - 1); @@ -179,12 +179,15 @@ int ch341_i2c_read(struct libusb_device_handle *devHandle, struct i2c_msg *msg) fprintf(stderr, "USB read error : %s\n", strerror(-ret)); return ret; } - if (actuallen != bytestoread) { + if (actuallen != bytestoread + 1) { fprintf(stderr, "actuallen != bytestoread\b"); return -1; } - memcpy(&msg->buf[byteoffset], i2c_dev.ibuf, actuallen); - byteoffset += actuallen; + if (i2c_dev.ibuf[0] & 0x80) { + return -1; + } + memcpy(&msg->buf[byteoffset], &i2c_dev.ibuf[1], bytestoread); + byteoffset += bytestoread; } return 0; } @@ -284,19 +287,19 @@ int ch341delay_ms(struct libusb_device_handle *devHandle, unsigned ms) { } int ch341_quick_write(struct libusb_device_handle *devHandle, uint8_t addr) { - unsigned olen = 0; - i2c_dev.obuf[olen++] = mCH341A_CMD_I2C_STREAM; - i2c_dev.obuf[olen++] = mCH341A_CMD_I2C_STM_STA; - i2c_dev.obuf[olen++] = mCH341A_CMD_I2C_STM_OUT; -#if 0 - i2c_dev.obuf[olen++] = addr << 1 | 1; // READ1 - i2c_dev.obuf[olen++] = mCH341A_CMD_I2C_STM_IN; + uint8_t * ptr = i2c_dev.obuf; + *ptr++ = mCH341A_CMD_I2C_STREAM; + *ptr++ = mCH341A_CMD_I2C_STM_STA; + *ptr++ = mCH341A_CMD_I2C_STM_OUT; +#if 1 + *ptr++ = addr << 1 | 1; // READ1 + *ptr++ = mCH341A_CMD_I2C_STM_IN; #else - i2c_dev.obuf[olen++] = addr << 1; // WRITE + *ptr++ = addr << 1; // WRITE0 #endif - i2c_dev.obuf[olen++] = mCH341A_CMD_I2C_STM_STO; + *ptr++ = mCH341A_CMD_I2C_STM_STO; int actuallen = 0; - int ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, i2c_dev.obuf, olen, &actuallen, DEFAULT_TIMEOUT); + int ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, i2c_dev.obuf, ptr - i2c_dev.obuf, &actuallen, DEFAULT_TIMEOUT); if (ret < 0) { fprintf(stderr, "USB write error : %s\n", strerror(-ret)); return ret; From 4f77316bd1fa6aaca496244973fca25195a84cc4 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Sun, 9 Apr 2023 18:27:24 +0300 Subject: [PATCH 7/7] fix read op --- ch341funcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ch341funcs.c b/ch341funcs.c index cd809b6..cc56e28 100644 --- a/ch341funcs.c +++ b/ch341funcs.c @@ -174,7 +174,7 @@ int ch341_i2c_read(struct libusb_device_handle *devHandle, struct i2c_msg *msg) fprintf(stderr, "USB write error : %s\n", strerror(-ret)); return ret; } - ret = libusb_bulk_transfer(devHandle, BULK_READ_ENDPOINT, i2c_dev.ibuf, bytestoread, &actuallen, DEFAULT_TIMEOUT); + ret = libusb_bulk_transfer(devHandle, BULK_READ_ENDPOINT, i2c_dev.ibuf, 32, &actuallen, DEFAULT_TIMEOUT); if (ret < 0) { fprintf(stderr, "USB read error : %s\n", strerror(-ret)); return ret;