diff --git a/Makefile b/Makefile index 6db6fc0..a180cf4 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ -CC = clang -CFLAGS = -Wall -O2 +CC = gcc +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 9a4159d..ec55726 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,292 +19,315 @@ // 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 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[12], 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; - 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 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"; + 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 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' }, + { "scan", no_argument, 0, 'x' }, + { 0, 0, 0, 0 } }; - static int speed_table[] = {20, 100, 400, 750}; + 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, "hvdexs: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"); + return -1; + } + break; + case 'r': + if (!operation) { + operation = 'r'; + filename = optarg; + } else { + fprintf(stderr, "Conflicting command line options\n"); + return -1; + } + break; + case 'w': + if (!operation) { + operation = 'w'; + filename = optarg; + } else { + fprintf(stderr, "Conflicting command line options\n"); + return -1; + } + break; + case 'V': + if (!operation) { + operation = 'V'; + filename = optarg; + } else { + fprintf(stderr, "Conflicting command line options\n"); + 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); + fprintf(stderr, "%s", usage_msg); + return 0; } } - 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) { + return -1; + } + + if (eepromsize <= 0 && operation != 'x') { fprintf(stderr, "Invalid EEPROM size\n"); - goto shutdown; + return -1; } - readbuf = (uint8_t *) malloc(MAX_EEPROM_SIZE); // space to store loaded EEPROM - if(!readbuf) { + 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))) { + 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); - 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, eepromsize); - 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(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"); + munmap(verifybuf, eepromsize); + fclose(fp); + break; + case 'w': // write + if (!(fp = fopen(filename, "rb"))) { + fprintf(stderr, "Couldnt open file [%s] for reading\n", filename); goto shutdown; } + memset(readbuf, 0xff, eepromsize); + bytesread = fread(readbuf, 1, eepromsize, fp); + if (ferror(fp)) { + fprintf(stderr, "Error reading file [%s]\n", filename); + if (fp) + fclose(fp); + goto shutdown; + } + fclose(fp); + fprintf(stdout, "Read [%d] bytes from file [%s]\n", bytesread, filename); -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); + if (bytesread < eepromsize) + fprintf(stdout, "Padded to [%d] bytes for [%s] EEPROM\n", eepromsize, eepromname); + + 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, eepromsize); + 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; + case 'x': {// scan + for (unsigned i = 0x8; i < 0x80; ++i) { + ch341_quick_write(devHandle, i); + } + break; } + default: + fprintf(stderr, "Unknown option\n"); + } + +shutdown: + 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.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.h b/ch341eeprom.h index 0704207..16c29a2 100644 --- a/ch341eeprom.h +++ b/ch341eeprom.h @@ -1,376 +1,151 @@ // libUSB driver for the ch341a in i2c mode // // Copyright 2011 asbokid +// (c) December 2023 aystarik -#define CH341TOOLVERSION "0.5" +#pragma once +#include +#include -#define USB_LOCK_VENDOR 0x1a86 // Dev : (1a86) QinHeng Electronics -#define USB_LOCK_PRODUCT 0x5512 // (5512) CH341A in i2c mode +#define CH341TOOLVERSION "0.6" - -#define MAX_EEPROM_SIZE 131072 /* For 24c1024*/ +#define USB_LOCK_VENDOR 0x1a86 // Dev : (1a86) QinHeng Electronics +#define USB_LOCK_PRODUCT 0x5512 // (5512) CH341A in i2c mode #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 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 DEFAULT_TIMEOUT 300 // 300mS for USB timeouts /* 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. -*/ +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; 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", 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, 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); - -// callback functions for async USB transfers -void cbBulkIn(struct libusb_transfer *transfer); -void cbBulkOut(struct libusb_transfer *transfer); +int ch341_quick_write(struct libusb_device_handle *devHandle, uint8_t addr); +int32_t parseEEPsize(char *eepromname, const struct EEPROM **eeprom); diff --git a/ch341eeprom.includes b/ch341eeprom.includes new file mode 100644 index 0000000..9c558e3 --- /dev/null +++ b/ch341eeprom.includes @@ -0,0 +1 @@ +. diff --git a/ch341funcs.c b/ch341funcs.c index 638213f..cc56e28 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,21 @@ // 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; + +struct xxx { + uint8_t ibuf[32]; + uint8_t obuf[32]; +} i2c_dev; // -------------------------------------------------------------------------- // ch341configure() @@ -41,410 +44,328 @@ uint32_t byteoffset; // identify device revision // returns *usb device handle -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); - if(ret < 0) { +struct libusb_device_handle *ch341configure(uint16_t vid, uint16_t pid) +{ + int32_t ret = libusb_init(NULL); + 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))) { + 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; } - if(!(dev = libusb_get_device(devHandle))) { + struct libusb_device *dev; + 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 fprintf(verbout, "Detached kernel driver\n"); } + int32_t currentConfig = 0; 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; } 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) { + 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 (unsigned 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) +{ int32_t actuallen = 0; - outptr = ch341outBuffer; + i2c_dev.obuf[0] = mCH341A_CMD_I2C_STREAM; + i2c_dev.obuf[1] = mCH341A_CMD_I2C_STM_SET | (speed & 0x3); - *outptr++ = mCH341A_CMD_I2C_STREAM; - *outptr++ = mCH341A_CMD_I2C_STM_SET | (speed & 0x3); - *outptr = mCH341A_CMD_I2C_STM_END; + int ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, i2c_dev.obuf, 2, &actuallen, DEFAULT_TIMEOUT); - 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", 2, strerror(-ret)); + return -1; } - fprintf(debugout, "ch341setstream(): Wrote %d bytes: ", 3); - for(i=0; i < 3; i++) - fprintf(debugout, "%02x ", ch341outBuffer[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; } -size_t ch341ReadCmdMarshall(uint8_t *buffer, uint32_t addr, 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 - // 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 >= 2) { - // 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 - } 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 +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 > 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; // ask for status + *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; + + 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 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; + } + if (actuallen != bytestoread + 1) { + fprintf(stderr, "actuallen != bytestoread\b"); + return -1; + } + if (i2c_dev.ibuf[0] & 0x80) { + return -1; + } + memcpy(&msg->buf[byteoffset], &i2c_dev.ibuf[1], bytestoread); + byteoffset += bytestoread; } - *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 - - // 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; - *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; - - return ptr - buffer; + return 0; } -// -------------------------------------------------------------------------- -// 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) { - - uint8_t ch341outBuffer[EEPROM_READ_BULKOUT_BUF_SZ]; - uint8_t ch341inBuffer[IN_BUF_SZ]; // 0x100 bytes - int32_t ret = 0, readpktcount = 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; - } - - 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 - - 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); - - fprintf(debugout, "Filled USB transfer structures\n"); - - libusb_submit_transfer(xferBulkIn); - fprintf(debugout, "Submitted BULK IN start packet\n"); - libusb_submit_transfer(xferBulkOut); - fprintf(debugout, "Submitted BULK OUT setup packet\n"); +int ch341_i2c_write(struct libusb_device_handle *devHandle, struct i2c_msg *msg) { + unsigned left = msg->len; + uint8_t *ptr = msg->buf; + bool first = true; + do { + uint8_t *outptr = i2c_dev.obuf; + *outptr++ = mCH341A_CMD_I2C_STREAM; + if (first) { // Start packet + *outptr++ = mCH341A_CMD_I2C_STM_STA; + } + uint8_t *lenptr = outptr++; + if (first) { + *outptr++ = msg->addr << 1; + } + unsigned avail = 32 - (outptr - i2c_dev.obuf); + unsigned wlen = avail; + if (left < avail) { + wlen = left; + } else if (left == avail) { + wlen = avail - 1; + } + memcpy(outptr, ptr, wlen); + outptr += wlen; + ptr += wlen; + left -= wlen; + wlen = outptr - lenptr - 1; + *lenptr = mCH341A_CMD_I2C_STM_OUT | wlen; + if (left == 0) { // Stop packet + *outptr++ = mCH341A_CMD_I2C_STM_STO; + } - readbuf = buffer; + wlen = outptr - i2c_dev.obuf; + assert(wlen <= 32); + for (unsigned i = 0; i < wlen; ++i) { + if (!(i % 0x10)) + fprintf(debugout, "\n%02x : ", i); + fprintf(debugout, "%02x ", i2c_dev.obuf[i]); + } + fprintf(debugout, "\n"); - while (1) { - fprintf(stdout, "Read %d%% [%d] of [%d] bytes \r", 100*byteoffset/bytestoread, byteoffset, bytestoread); - ret = libusb_handle_events_timeout(NULL, &tv); + first = false; + int actuallen = 0, ret = 0; + ret = libusb_bulk_transfer(devHandle, BULK_WRITE_ENDPOINT, i2c_dev.obuf, wlen, &actuallen, DEFAULT_TIMEOUT); - 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); + if (ret < 0) { + fprintf(stderr, "Failed to write to I2C: '%s'\n", strerror(-ret)); return -1; } - if(getnextpkt == 1) { // callback function reports a new BULK IN packet received - getnextpkt = 0; // reset the flag - readpktcount++; // increment the read packet counter - 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; - // 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); - - libusb_submit_transfer(xferBulkOut);// update transfer struct (with new EEPROM page offset) - // and re-submit next transfer request to BULK OUT endpoint - } - } - } + } while (left); - libusb_free_transfer(xferBulkIn); - libusb_free_transfer(xferBulkOut); return 0; } -// 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; +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]); + if (ret) return ret; + } else { + int ret = ch341_i2c_write(devHandle, &msg[i]); + if (ret) return ret; + } } - return; + return 0; +} + +// -------------------------------------------------------------------------- +// 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) +{ + 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; + + return ch341_i2c_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) { + i2c_dev.obuf[0] = mCH341A_CMD_I2C_STREAM; + 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, 2, &actuallen, DEFAULT_TIMEOUT); } +int ch341_quick_write(struct libusb_device_handle *devHandle, uint8_t addr) { + 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 + *ptr++ = addr << 1; // WRITE0 +#endif + *ptr++ = mCH341A_CMD_I2C_STM_STO; + 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 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) -int32_t ch341writeEEPROM(struct libusb_device_handle *devHandle, uint8_t *buffer, uint32_t bytesum, struct EEPROM *eeprom_info) { - - uint8_t ch341outBuffer[512/*EEPROM_WRITE_BUF_SZ*/]; - uint8_t *outptr, *bufptr; - uint8_t i2cCmdBuffer[256]; - int32_t ret = 0, i; - 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; - 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 - } else { - *outptr++ = (uint8_t) (0xa0 | (byteoffset >> 8 & (*eeprom_info).i2c_addr_mask)<<1); // EEPROM device address - } - *outptr++ = (uint8_t) (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) { - uint8_t to_write = MIN(page_size_left, 28); - *outptr++ = mCH341A_CMD_I2C_STREAM; - if (part_no == 0) { // Start packet - *outptr++ = mCH341A_CMD_I2C_STM_STA; - } - *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++; +int32_t ch341writeEEPROM(struct libusb_device_handle *devHandle, uint8_t *buffer, uint32_t bytesum, const struct EEPROM *eeprom_info) +{ + 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++ = offset >> 8; } - uint32_t payload_size = outptr - ch341outBuffer; - - for(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); - - if(ret < 0) { - fprintf(stderr, "Failed to write to EEPROM: '%s'\n", strerror(-ret)); - return -1; + *outptr++ = offset; + if (bytesum - offset < wlen) { + wlen = bytesum - offset; } - - fprintf(debugout, "Writing [aa 5a 00] to EEPROM\n"); // Magic CH341a packet! Undocumented, unknown purpose - - 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); - - if(ret < 0) { + memcpy(outptr, buffer + offset, wlen); + outptr += wlen; + msg.len = outptr - msgbuffer; + int ret = 0; + ret = ch341_i2c_xfer(devHandle, &msg, 1); + if (ret < 0) { fprintf(stderr, "Failed to write to EEPROM: '%s'\n", strerror(-ret)); return -1; } + offset += wlen; - /* - 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)); + ret = ch341delay_ms(devHandle, 10); + if (ret < 0) { + fprintf(stderr, "Failed to set timeout: '%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; } - // -------------------------------------------------------------------------- // 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; }