diff --git a/Makefile b/Makefile index ab38584..15b7b42 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,4 @@ -VERSION_MAIN = 1 -VERSION_SUB = 8 +include version.mk CC = gcc OBJS = main.o hex.o @@ -16,7 +15,7 @@ ifeq ($(shell uname -s),Darwin) else # Rules for Linux, etc. OBJS += usb-libusb.o - CFLAGS = -O3 + CFLAGS = -O3 LDFLAGS = -lusb SYSTEM = linux endif @@ -24,7 +23,7 @@ endif CFLAGS += -DVERSION_MAIN=$(VERSION_MAIN) -DVERSION_SUB=$(VERSION_SUB) #CFLAGS += -DDEBUG -all: +all: @echo @echo Please make 'mphidflash32' or 'mphidflash64' for 32 or 64 bit version @echo @@ -39,7 +38,7 @@ mphidflash64: LDFLAGS += -m64 mphidflash64: EXEC = mphidflash-$(VERSION_MAIN).$(VERSION_SUB)-$(SYSTEM)-64 mphidflash64: mphidflash -mphidflash32: CFLAGS += -m32 +mphidflash32: CFLAGS += -m32 mphidflash32: LDFLAGS += -m32 mphidflash32: EXEC = mphidflash-$(VERSION_MAIN).$(VERSION_SUB)-$(SYSTEM)-32 mphidflash32: mphidflash @@ -50,7 +49,7 @@ mphidflash: $(OBJS) install: @echo - @echo Please make 'install32 or install64' to install 32 or 64 bit target + @echo Please make 'install32' or 'install64' to install 32 or 64 bit target @echo # Must install as root; e.g. 'sudo make install' @@ -82,3 +81,21 @@ src-zipfile: rm -f $(DISTPATH)/mphidflash-$(VERSION_MAIN).$(VERSION_SUB)-src.zip zip $(DISTPATH)/mphidflash-$(VERSION_MAIN).$(VERSION_SUB)-src.zip README.txt CHANGELOG COPYING Makefile* *.c *.h + +cross: windows + +win: windows + +windows: + make -f Makefile.win + +win32: mingw32 + +mingw32: + make -f Makefile.win mphidflash32 + +win64: mingw64 + +mingw64: + make -f Makefile.win mphidflash64 + diff --git a/Makefile.win b/Makefile.win index 4f02d75..847fb3a 100644 --- a/Makefile.win +++ b/Makefile.win @@ -1,11 +1,16 @@ -VERSION_MAIN = 1 -VERSION_SUB = 8 +include version.mk +SYSTEM = win + +# determine the compiler in reach - it might be a cross-compiler +CC32 := $(shell basename `which i586-mingw32msvc-gcc i686-w64-mingw32-gcc | head -n 1`) +CC64 := $(shell basename `which x86_64-mingw32msvc-gcc x86_64-w64-mingw32-gcc | head -n 1`) +CC = $(CC32) -CC = i586-mingw32msvc-gcc EXECS = mphidflash.exe +EXECPATH = binaries OBJS = main.o hex.o usb-windows.o CFLAGS = -DWIN -DVERSION_MAIN=$(VERSION_MAIN) -DVERSION_SUB=$(VERSION_SUB) -LDFLAGS = -lhid -lsetupapi +LDFLAGS = -lhid -lsetupapi all: $(EXECS) @@ -14,14 +19,20 @@ all: $(EXECS) .c.o: $(CC) $(CFLAGS) -c $*.c -# todo: add 64 bit target (low priority as 32 bit works on all platforms) +mphidflash64: CC = $(CC64) +mphidflash64: CFLAGS += -m64 +mphidflash64: LDFLAGS += -m64 +mphidflash64: EXEC = mphidflash-$(VERSION_MAIN).$(VERSION_SUB)-$(SYSTEM)-64.exe +mphidflash64: mphidflash.exe -mphidflash32: CFLAGS += -m32 +mphidflash32: CC = $(CC32) +mphidflash32: CFLAGS += -m32 mphidflash32: LDFLAGS += -m32 +mphidflash32: EXEC = mphidflash-$(VERSION_MAIN).$(VERSION_SUB)-$(SYSTEM)-32.exe mphidflash32: mphidflash.exe mphidflash.exe: $(OBJS) - $(CC) $(OBJS) $(LDFLAGS) -o binaries/mphidflash-$(VERSION_MAIN).$(VERSION_SUB)-win-32.exe + $(CC) $(OBJS) $(LDFLAGS) -o $(EXECPATH)/$(EXEC) clean: rm -f $(EXECS) *.o core diff --git a/README.txt b/README.txt index 42c0519..be372f8 100644 --- a/README.txt +++ b/README.txt @@ -16,7 +16,7 @@ the PIC32 HID Bootloader uses the same default USB Product Id as the supported HID Bootloader. If used in error either 'mphidflash' or the development board may freeze or indicate an error. -The 'mphidflash' project is hosted at https://github.com/ApertureLabsLtd/mphidflash +The 'mphidflash' project is hosted at https://github.com/AdamLaurie/mphidflash (migrated from http://code.google.com/p/mphidflash/) Building and Installing @@ -28,24 +28,24 @@ For Linux, you'll need the 'libhid' development library (and associated dependencies) installed, which can be handled by most package managers or from the command line: - sudo apt-get install libhid-dev + sudo apt-get install libhid-dev Assuming you're reading this as the README.txt alongside the source code, to compile mphidflash for a 32 or 64 bit system, in the Terminal window type: - make mphidflash32 + make mphidflash32 or - make mphidflash64 + make mphidflash64 Then install with the command: - sudo make install32 + sudo make install32 or - sudo make install64 + sudo make install64 This will copy the appropriate executable to /usr/local/bin/mphidflash so you don't need to specify a complete path to the program each time. @@ -60,19 +60,19 @@ the command line interface. Assuming you're reading this as the README.txt alongside the source code, to compile mphidflash for a 32 or 64 bit system, in the Terminal window type: - make mphidflash32 + make mphidflash32 or - make mphidflash64 + make mphidflash64 Then install with the command: - sudo make install32 + sudo make install32 or - sudo make install64 + sudo make install64 This will copy the appropriate executable to /usr/local/bin/mphidflash so you don't need to specify a complete path to the program each time. @@ -85,14 +85,18 @@ cross compiling on Linux, you'll need the 'mingw32' toolchain (and associated dependencies) installed, which can be handled by most package mangager or from the command line: - sudo apt-get install mingw32 + sudo apt-get install mingw32 Assuming you're reading this as the README.txt alongside the source code, to compile mphidflash, in the Terminal window type: - make -f Makefile.win + make win32 -This will create a .exe in the binaries sub-directory, which can be called + or + + make win64 + +This will create an .exe in the binaries sub-directory, which can be called from the Windows commmand line - e.g. 'mphidflash-1.6-win-32.exe'. You should copy this file somewhere on your executable path and rename it to 'mphidflash.exe'. @@ -104,22 +108,23 @@ in usb_windows.c that need to be edited to match your DDK install location. Usage ===== To upload a new program to your PIC, it must be connected to your computer and -set into bootloader mode. mphidflash can then be used with the following +set into bootloader mode. mphidflash can then be used with the following options: --help Display help screen (alternately: -?) --write Upload given file to PIC --reset Reset PIC --noverify Skip verification step --erase Erase PIC memory --sign Sign flash --vendor Use given USB vendor id instead of default id --product Use given USB product id instead of default id +-help Display help screen (alternately: -?) +-write Upload given file to PIC +-reset Reset PIC +-noverify Skip verification step +-erase Erase PIC memory (implicit if -w) +-unlock Unlock config mem before erase/write +-sign Sign flash (for later versions of boot loader) +-vendor Use given USB vendor id instead of default id 04d8 +-product Use given USB product id instead of default id 003c Example: To upload the program test.hex to the PIC and to reset the PIC thereafter the following command line can be used: - mphidflash -write test.hex -reset + mphidflash -write test.hex -reset Tips ==== diff --git a/binaries/mphidflash-1.8-linux-32 b/binaries/mphidflash-1.8-linux-32 new file mode 100755 index 0000000..48a1c9a Binary files /dev/null and b/binaries/mphidflash-1.8-linux-32 differ diff --git a/binaries/mphidflash-1.8-linux-64 b/binaries/mphidflash-1.8-linux-64 new file mode 100755 index 0000000..20fe000 Binary files /dev/null and b/binaries/mphidflash-1.8-linux-64 differ diff --git a/binaries/mphidflash-1.8-win-32.exe b/binaries/mphidflash-1.8-win-32.exe new file mode 100755 index 0000000..88fb588 Binary files /dev/null and b/binaries/mphidflash-1.8-win-32.exe differ diff --git a/binaries/mphidflash-1.8-win-64.exe b/binaries/mphidflash-1.8-win-64.exe new file mode 100755 index 0000000..2cfb966 Binary files /dev/null and b/binaries/mphidflash-1.8-win-64.exe differ diff --git a/binaries/mphidflash-1.9-linux-32 b/binaries/mphidflash-1.9-linux-32 new file mode 100755 index 0000000..a89e9bf Binary files /dev/null and b/binaries/mphidflash-1.9-linux-32 differ diff --git a/binaries/mphidflash-1.9-linux-64 b/binaries/mphidflash-1.9-linux-64 new file mode 100755 index 0000000..1d6226d Binary files /dev/null and b/binaries/mphidflash-1.9-linux-64 differ diff --git a/binaries/mphidflash-1.9-win-32.exe b/binaries/mphidflash-1.9-win-32.exe new file mode 100755 index 0000000..70723f0 Binary files /dev/null and b/binaries/mphidflash-1.9-win-32.exe differ diff --git a/binaries/mphidflash-1.9-win-64.exe b/binaries/mphidflash-1.9-win-64.exe new file mode 100755 index 0000000..54390cf Binary files /dev/null and b/binaries/mphidflash-1.9-win-64.exe differ diff --git a/build_all_linux.sh b/build_all_linux.sh new file mode 100755 index 0000000..c2bd25a --- /dev/null +++ b/build_all_linux.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +make clean +make mphidflash32 + +make clean +make mphidflash64 + +make clean +make win32 + +make clean +make win64 + +make clean + diff --git a/hex.c b/hex.c index cbdd677..4e1d61b 100644 --- a/hex.c +++ b/hex.c @@ -6,7 +6,7 @@ * Initial implementation 2009-12-26 Thomas Fischl, Dominik Fisch (www.FundF.net) * Ported mmap functions to windows - + License : Copyright (C) 2009 Phillip Burgess Copyright (C) 2009 Thomas Fischl, Dominik Fisch (www.FundF.net) @@ -71,7 +71,18 @@ Returns : Nothing (void) ****************************************************************************/ void hexSetBytesPerAddress(unsigned char bytes) { - bytesPerAddress = bytes; + bytesPerAddress = bytes; +} + +/**************************************************************************** +Function : hexGetBytesPerAddress +Description : returns set byte width +Parameters : Nothing (void) +Returns : unsigned char Bytes per address +****************************************************************************/ +unsigned char hexGetBytesPerAddress(void) +{ + return bytesPerAddress; } /**************************************************************************** @@ -85,85 +96,86 @@ void hexSetBytesPerAddress(unsigned char bytes) ****************************************************************************/ ErrorCode hexOpen(char * const filename) { - ErrorCode status = ERR_HEX_OPEN; + ErrorCode status = ERR_HEX_OPEN; - if((hexFd = open(filename,O_RDONLY)) >= 0) { + if((hexFd = open(filename,O_RDONLY)) >= 0) { - struct stat filestat; + struct stat filestat; - status = ERR_HEX_STAT; - if(!fstat(hexFd,&filestat)) { + status = ERR_HEX_STAT; + if(!fstat(hexFd,&filestat)) { - status = ERR_HEX_MMAP; - hexFileSize = filestat.st_size; + status = ERR_HEX_MMAP; + hexFileSize = filestat.st_size; #ifndef WIN - if((hexFileData = mmap(0,hexFileSize,PROT_READ, - MAP_FILE | MAP_SHARED,hexFd,0)) != (void *)(-1)) { - hexPlusOne = &hexFileData[1]; - return ERR_NONE; - } + if((hexFileData = mmap(0,hexFileSize,PROT_READ, + MAP_FILE | MAP_SHARED,hexFd,0)) != (void *)(-1)) { + hexPlusOne = &hexFileData[1]; + return ERR_NONE; + } #else - { - HANDLE handle; - handle = CreateFileMapping((HANDLE)_get_osfhandle(hexFd), NULL, PAGE_WRITECOPY, 0, 0, NULL); - if (handle != NULL) { - hexFileData = (char *) MapViewOfFile(handle, FILE_MAP_COPY, 0, 0, hexFileSize); - hexPlusOne = &hexFileData[1]; - CloseHandle(handle); - return ERR_NONE; - } - } + { + HANDLE handle; + handle = CreateFileMapping((HANDLE)_get_osfhandle(hexFd), NULL, PAGE_WRITECOPY, 0, 0, NULL); + if (handle != NULL) { + hexFileData = (char *) MapViewOfFile(handle, FILE_MAP_COPY, 0, 0, hexFileSize); + hexPlusOne = &hexFileData[1]; + CloseHandle(handle); + return ERR_NONE; + } + } #endif - /* Else clean up and return error code */ - hexFileData = NULL; - } - (void)close(hexFd); - } + /* Else clean up and return error code */ + hexFileData = NULL; + } + (void)close(hexFd); + } - return status; + return status; } /* check memory address & length are in a programmable memory area, as reported by device's Bootloader */ static int verifyBlockProgrammable( unsigned int *addr, unsigned int *len ) { - int i, isA, isL; - unsigned int MA , ML; - - for ( i = 0; i < devQuery.memBlocks; i++ ) - { - /* only look at programmable memory blocks */ - if ( !devQuery.mem[ i ].Type ) - continue; - - /* calc if first or last address is in this block */ - MA = devQuery.mem[ i ].Address; - ML = devQuery.mem[ i ].Length; - isA = ( *addr >= MA ) && ( *addr < MA + ML ); - isL = ( *addr + *len > MA ) && ( *addr + *len <= MA + ML ); - - /* loop if neither */ - if ( !isA && !isL ) - continue; - - /* both addresses is fine */ - if ( isA && isL ) - return 0; - - /* if only start address we adjust length to end of block */ - if ( isA ) - *len = ( MA + ML ) - *addr; - - /* if only last address we adjust start to start of block */ - if ( isL ) { - *len = ( *addr + *len ) - MA; - *addr = MA; - } - - return 0; - } - return 1; + int i, isA, isL; + unsigned int MA , ML; + + for ( i = 0; i < devQuery.memBlocks; i++ ) + { + /* only look at programmable memory blocks */ + if ( !devQuery.mem[ i ].Type ) + continue; + + /* calc if first or last address is in this block */ + MA = devQuery.mem[ i ].Address; + ML = devQuery.mem[ i ].Length; + isA = ( *addr >= MA ) && ( *addr < MA + ML ); + isL = ( *addr + *len > MA ) && ( *addr + *len <= MA + ML ); + + /* loop if neither */ + if ( !isA && !isL ) + continue; + + /* both addresses is fine */ + if ( isA && isL ) + return 0; + + /* if only start address we adjust length to end of block */ + if ( isA ) + *len = ( MA + ML ) - *addr; + + /* if only last address we adjust start to start of block */ + if ( isL ) { + *len = ( *addr + *len ) - MA; + *addr = MA; + } + + return 0; + } + + return 1; } /**************************************************************************** @@ -198,88 +210,87 @@ static ErrorCode issueBlock( unsigned int len, char verify) { - ErrorCode status; + ErrorCode status; #ifdef DEBUG - (void)printf("Address: %08x Len %d\n",addr,len); + (void)printf("Address: %08x Len %d\n",addr,len); #else - (void)putchar('.'); fflush(stdout); + (void)putchar('.'); fflush(stdout); #endif - // check device memory blocks are programmable - if ( verifyBlockProgrammable( &addr, &len ) ) { -#ifdef DEBUG - printf( "Skip data on address %04x with length %d\n", addr, len ); + // check device memory blocks are programmable + if ( verifyBlockProgrammable( &addr, &len ) ) { +#ifdef DEBUG + printf( "Skip data on address %04x with length %d\n", addr, len ); #endif - return ERR_NONE; - } - // length must be even - if ( len & 1 ) { + return ERR_NONE; + } + // length must be even + if ( len & 1 ) { #ifdef DEBUG - printf( "Add one byte to data on address %04x with length %d\n", addr, len ); + printf( "Add one byte to data on address %04x with length %d\n", addr, len ); #endif - hexBuf[ len++ ] = 0xff; - } - - /* Short data packets need flushing */ - if (!verify && len == 0 && !Flushed) { - DEBUGMSG("Completing"); - usbBuf[0] = PROGRAM_COMPLETE; - status = usbWrite(1,0); - Flushed= 1; - return status; - } - - bufWrite32(usbBuf,1,addr / bytesPerAddress); - usbBuf[5] = len; - - if(verify) { - DEBUGMSG("Verifying"); - usbBuf[0] = GET_DATA; - if(ERR_NONE == (status = usbWrite(6,1))) { + hexBuf[ len++ ] = 0xff; + } + + /* Short data packets need flushing */ + if (!verify && len == 0 && !Flushed) { + DEBUGMSG("Completing"); + usbBuf[0] = PROGRAM_COMPLETE; + status = usbWrite(1,0); + Flushed= 1; + return status; + } + + bufWrite32(usbBuf,1,addr / bytesPerAddress); + usbBuf[5] = len; + + if(verify) { + DEBUGMSG("Verifying"); + usbBuf[0] = GET_DATA; + if(ERR_NONE == (status = usbWrite(6,1))) { #ifdef DEBUG - unsigned int i; - if(memcmp(&usbBuf[64 - len],hexBuf,len)) { - (void)puts("Verify FAIL\nExpected:"); - (void)printf("NA NA NA NA NA NA NA NA - "); - for(i=0;i<(56-len);i++) (void)printf("NA "); - for(i=0;i 1) && - (0 != (devQuery.mem[i].Length % bytesPerAddress))) { - return ERR_BAD_MEM_LENGTH2; - } - - // TODO check memory address makes sense for PIC18, PIC24, etc - - // each block type is defined max one time, must not overlap other blocks - for (j = 0; j < i; j++) { - // we expect each memory block type to be listed only once - // (based on reviewing Microchip's published reference code) - if ((devQuery.mem[i].Type) == (devQuery.mem[j].Type)) { - return ERR_MEM_BLOCK_TYPE_REPEATS; - } - // memory blocks should not overlap - if (devQuery.mem[i].Address == devQuery.mem[j].Address) { - return ERR_OVERLAPPING_MEM_BLOCKS; - } else if (devQuery.mem[i].Address < devQuery.mem[j].Address) { - tempaddr = devQuery.mem[i].Address + (devQuery.mem[i].Length / bytesPerAddress); - if (tempaddr >= devQuery.mem[j].Address) { - return ERR_OVERLAPPING_MEM_BLOCKS; - } - } else { - tempaddr = devQuery.mem[j].Address + (devQuery.mem[j].Length / bytesPerAddress); - if (tempaddr >= devQuery.mem[i].Address) { - return ERR_OVERLAPPING_MEM_BLOCKS; - } - } - } - } // sanity iter over blocks - - if (!hasProgramMemory) { - return ERR_NO_PROGRAM_MEMORY; - } - - // TODO check for Bootloader v1.01: supports SIGN_FLASH & QUERY_EXTENDED_INFO - return ERR_NONE; + char hasProgramMemory = 0; + char hasConfigMemory = 0; + int i = 0, j; + char *name = NULL; + unsigned int tempaddr; + + memcpy( &devQuery, usbBuf, 64 ); + + // bad values here probably indicate a garbage response + if (QUERY_DEVICE != devQuery.Command) + return ERR_RESPONSE_HAS_WRONG_COMMAND; + + if (56 != devQuery.PacketDataFieldSize) { + // we have hardcoded assumptions this will be 56 & total buffer of 64 + fprintf(stderr, "Reported Packet Data Field Size is %d\n", + devQuery.PacketDataFieldSize); + return ERR_BAD_PACKET_DATA_FIELD_SIZE; + } + + // count how many memory blocks are defined + while ( (devQuery.mem[ i ].Type != TypeEndOfTypeList) && (i < MAX_DATA_REGIONS) ) + i++; + devQuery.memBlocks = i; + + switch (devQuery.DeviceFamily) + { + case DEVICE_FAMILY_PIC18: // PIC16 per experience + hexSetBytesPerAddress(1); + name = "PIC18 (or PIC16)"; + break; + case DEVICE_FAMILY_PIC24: + hexSetBytesPerAddress(2); + name = "PIC24 or dsPIC33"; + break; + case DEVICE_FAMILY_PIC32: + hexSetBytesPerAddress(1); + name = "PIC32"; + break; + case DEVICE_FAMILY_PIC16: // PIC16 per documentation + hexSetBytesPerAddress(2); + name = "PIC16"; + break; + default: + hexSetBytesPerAddress(1); + name = "Unknown. Bytes per address set to 1."; + break; + } + if (doExtendedQuery) + (void)printf("Device family: %s\n", name); + else + (void)puts("Refetching memory block information..."); + + if (!doExtendedQuery && !hasConfigMemory) + (void)puts("No Config Memory found after unlocking"); + + // endian conversion, report available memory + for ( i = 0; i < devQuery.memBlocks; i++ ) { + name = NULL; + devQuery.mem[i].Address = convertEndian(devQuery.mem[i].Address); + devQuery.mem[i].Length = convertEndian(devQuery.mem[i].Length); + switch(devQuery.mem[i].Type) + { + case TypeProgramMemory: + name = "Program"; + hasProgramMemory = 1; + break; + case TypeEEPROM: + name = "EEPROM"; + break; + case TypeConfigWords: + name = "Config"; + hasConfigMemory = 1; + break; + case TypeUserID: + name = "User ID"; + break; + default: + break; + } + + if (name) + (void)printf("%s", name); + else + (void)printf("Unknown (type id %d)", devQuery.mem[i].Type); + (void)printf(" memory at 0x%x: %d bytes free\n", + devQuery.mem[i].Address, devQuery.mem[i].Length); + } + + // sanity checks + for ( i = 0; i < devQuery.memBlocks; i++ ) { + // memory type 0 not defined by Microchip, & used in mphidflash to disable programming + if(0 == devQuery.mem[i].Type) + return ERR_BAD_MEM_TYPE; + + // sane info for block length? + if (devQuery.mem[i].Length == 0) { + return ERR_BAD_MEM_LENGTH; + } else if ((bytesPerAddress > 1) && + (0 != (devQuery.mem[i].Length % bytesPerAddress))) { + return ERR_BAD_MEM_LENGTH2; + } + + // TODO check memory address makes sense for PIC18, PIC24, etc + + // each block type is defined max one time, must not overlap other blocks + for (j = 0; j < i; j++) { + // we expect each memory block type to be listed only once + // (based on reviewing Microchip's published reference code) + if ((devQuery.mem[i].Type) == (devQuery.mem[j].Type)) { + return ERR_MEM_BLOCK_TYPE_REPEATS; + } + // memory blocks should not overlap + if (devQuery.mem[i].Address == devQuery.mem[j].Address) { + return ERR_OVERLAPPING_MEM_BLOCKS; + } else if (devQuery.mem[i].Address < devQuery.mem[j].Address) { + tempaddr = devQuery.mem[i].Address + (devQuery.mem[i].Length / bytesPerAddress); + if (tempaddr >= devQuery.mem[j].Address) { + return ERR_OVERLAPPING_MEM_BLOCKS; + } + } else { + tempaddr = devQuery.mem[j].Address + (devQuery.mem[j].Length / bytesPerAddress); + if (tempaddr >= devQuery.mem[i].Address) { + return ERR_OVERLAPPING_MEM_BLOCKS; + } + } + } + } // sanity iter over blocks + + if (!hasProgramMemory) { + return ERR_NO_PROGRAM_MEMORY; + } + + // TODO check for Bootloader v1.01: supports SIGN_FLASH & QUERY_EXTENDED_INFO + return ERR_NONE; } @@ -221,92 +221,92 @@ int main( int argc, char *argv[]) { - char *hexFile = NULL, - actions = ACTION_VERIFY, - eol; /* 1 = last command-line arg */ - ErrorCode status = ERR_NONE; - int i; - // default USB Vendor & Product Ids for various Microchip Bootloaders - unsigned int vendorID = 0x04d8, - productID = 0x003c; - - const char * const errorString[ERR_EOL] = { - "Missing or malformed command-line argument", - "Command not recognized", - "Device not found (is device attached and in Bootloader mode?)", - "USB initialization failed (phase 1)", - "USB initialization failed (phase 2)", - "Device could not be opened for I/O", - "USB write error", - "USB read error", - "Could not open hex file for input", - "Could not query hex file size", - "Could not map hex file to memory", - "Unrecognized or invalid hex file syntax", - "Bad end-of-line checksum in hex file", - "Unsupported record type in hex file", - "Verify failed (is device connected to a powered root or hub?)", - "Bad memory type (0) in device memory list", - "Memory block length is bad (0, too big)", - "Memory block length is not multiple of 2", // for PIC24 - "Memory blocks overlap", - "Memory block type defined more than once", - "Device has no program memory block", - "Device response has unexpected command value", - "Device reports unexpected Packet Data Field Size", - "Signing Flash failed", - }; - - /* To create a sensible sequence of operations, all command-line - input is processed prior to taking any actions. The sequence - of actions performed may not always directly correspond to the - order or quantity of input; commands follow precedence, not - input order. For example, the action corresponding to the "-u" - (unlock) command must take place early on, before any erase or - write operations, even if specified late on the command line; - conversely, "-r" (reset) should always be performed last - regardless of input order. In the case of duplicitous - commands (e.g. if multiple "-w" (write) commands are present), - only the last one will take effect. - - The precedence of commands (first to last) is: - - -v and -p USB vendor and/or product IDs - -u Unlock configuration memory - -e Erase program memory - -n No verify after write - -w Write program memory - -s Sign code - -r Reset */ - - for(i=1;(i < argc) && (ERR_NONE == status);i++) { - eol = (i >= (argc - 1)); - if(!strncasecmp(argv[i],"-v",2)) { - if(eol || (1 != sscanf(argv[++i],"%x",&vendorID))) - status = ERR_CMD_ARG; - } else if(!strncasecmp(argv[i],"-p",2)) { - if(eol || (1 != sscanf(argv[++i],"%x",&productID))) - status = ERR_CMD_ARG; - } else if(!strncasecmp(argv[i],"-u",2)) { - actions |= ACTION_UNLOCK; - } else if(!strncasecmp(argv[i],"-e",2)) { - actions |= ACTION_ERASE; - } else if(!strncasecmp(argv[i],"-n",2)) { - actions &= ~ACTION_VERIFY; - } else if(!strncasecmp(argv[i],"-w",2)) { - if(eol) { - status = ERR_CMD_ARG; - } else { - hexFile = argv[++i]; - actions |= ACTION_ERASE; - } - } else if(!strncasecmp(argv[i],"-s",2)) { - actions |= ACTION_SIGN; - } else if(!strncasecmp(argv[i],"-r",2)) { - actions |= ACTION_RESET; - } else if(!strncasecmp(argv[i],"-h",2) || - !strncmp(argv[i],"-?",2)) { - (void)printf( + char *hexFile = NULL, + actions = ACTION_VERIFY, + eol; /* 1 = last command-line arg */ + ErrorCode status = ERR_NONE; + int i; + // default USB Vendor & Product Ids for various Microchip Bootloaders + unsigned int vendorID = 0x04d8, + productID = 0x003c; + + const char * const errorString[ERR_EOL] = { + "Missing or malformed command-line argument", + "Command not recognized", + "Device not found (is device attached and in Bootloader mode?)", + "USB initialization failed (phase 1)", + "USB initialization failed (phase 2)", + "Device could not be opened for I/O", + "USB write error", + "USB read error", + "Could not open hex file for input", + "Could not query hex file size", + "Could not map hex file to memory", + "Unrecognized or invalid hex file syntax", + "Bad end-of-line checksum in hex file", + "Unsupported record type in hex file", + "Verify failed (is device connected to a powered root or hub?)", + "Bad memory type (0) in device memory list", + "Memory block length is bad (0, too big)", + "Memory block length is not multiple of 2", // for PIC24 + "Memory blocks overlap", + "Memory block type defined more than once", + "Device has no program memory block", + "Device response has unexpected command value", + "Device reports unexpected Packet Data Field Size", + "Signing Flash failed", + }; + + /* To create a sensible sequence of operations, all command-line + input is processed prior to taking any actions. The sequence + of actions performed may not always directly correspond to the + order or quantity of input; commands follow precedence, not + input order. For example, the action corresponding to the "-u" + (unlock) command must take place early on, before any erase or + write operations, even if specified late on the command line; + conversely, "-r" (reset) should always be performed last + regardless of input order. In the case of duplicitous + commands (e.g. if multiple "-w" (write) commands are present), + only the last one will take effect. + + The precedence of commands (first to last) is: + + -v and -p USB vendor and/or product IDs + -u Unlock configuration memory + -e Erase program memory + -n No verify after write + -w Write program memory + -s Sign code + -r Reset */ + + for(i=1;(i < argc) && (ERR_NONE == status);i++) { + eol = (i >= (argc - 1)); + if(!strncasecmp(argv[i],"-v",2)) { + if(eol || (1 != sscanf(argv[++i],"%x",&vendorID))) + status = ERR_CMD_ARG; + } else if(!strncasecmp(argv[i],"-p",2)) { + if(eol || (1 != sscanf(argv[++i],"%x",&productID))) + status = ERR_CMD_ARG; + } else if(!strncasecmp(argv[i],"-u",2)) { + actions |= ACTION_UNLOCK; + } else if(!strncasecmp(argv[i],"-e",2)) { + actions |= ACTION_ERASE; + } else if(!strncasecmp(argv[i],"-n",2)) { + actions &= ~ACTION_VERIFY; + } else if(!strncasecmp(argv[i],"-w",2)) { + if(eol) { + status = ERR_CMD_ARG; + } else { + hexFile = argv[++i]; + actions |= ACTION_ERASE; + } + } else if(!strncasecmp(argv[i],"-s",2)) { + actions |= ACTION_SIGN; + } else if(!strncasecmp(argv[i],"-r",2)) { + actions |= ACTION_RESET; + } else if(!strncasecmp(argv[i],"-h",2) || + !strncmp(argv[i],"-?",2)) { + (void)printf( "mphidflash v%d.%d: a Microchip HID Bootloader utility\n" "Option Description Default\n" "-------------------------------------------------------------------------\n" @@ -314,117 +314,117 @@ int main( "-e Erase device code space (implicit if -w) No erase\n" "-r Reset device on program exit No reset\n" "-n No verify after write Verify on\n" -"-u Unlock configuration memory before erase/write Config locked\n" +"-u Unlock configuration memory before erase/write Keep lock state\n" "-s Sign flash. This option is required by later No signing\n" " versions of the bootloader.\n" "-v USB device vendor ID %04x\n" "-p USB device product ID %04x\n" "-h or -? Help\n", VERSION_MAIN, VERSION_SUB, vendorID, productID); - return 0; - } else { - status = ERR_CMD_UNKNOWN; - } - } - - /* After successful command-line parsage, find/open USB device. */ - - if((ERR_NONE == status) && - (ERR_NONE == (status = usbOpen(vendorID,productID)))) { - - /* And start doing stuff... */ - - (void)printf("USB HID device found"); - usbBuf[0] = QUERY_DEVICE; - if(ERR_NONE == (status = usbWrite(1,1))) { - status = deviceQueryProcessResult(1); - } - (void)putchar('\n'); - - if((ERR_NONE == status) && (actions & ACTION_UNLOCK)) { - (void)puts("Unlocking configuration memory..."); - usbBuf[0] = UNLOCK_CONFIG; - usbBuf[1] = UNLOCKCONFIG; - status = usbWrite(2,0); - // redo DEVICE_QUERY & process memory block info again - // for Bootloader versions that only report Config mem after Unlock - usbBuf[0] = QUERY_DEVICE; - if((ERR_NONE == status) && (ERR_NONE == (status = usbWrite(1,1)))) { - status = deviceQueryProcessResult(0); - } - } - // disable all configuration blocks in devQuery if locked - if ( !( actions & ACTION_UNLOCK ) ) { - for ( i = 0; i < devQuery.memBlocks; i++ ) - if ( devQuery.mem[ i ].Type == TypeConfigWords ) - devQuery.mem[ i ].Type = 0; - } - - /* Although the next actual operation is ACTION_ERASE, - if we anticipate hex-writing in a subsequent step, - attempt opening file now so we can display any error - message quickly rather than waiting through the whole - erase operation (it's usually a simple filename typo). */ - if((ERR_NONE == status) && hexFile && - (ERR_NONE != (status = hexOpen(hexFile)))) - hexFile = NULL; /* Open or mmap error */ - - if((ERR_NONE == status) && (actions & ACTION_ERASE)) { - (void)puts("Erasing..."); - usbBuf[0] = ERASE_DEVICE; - status = usbWrite(1,0); - if (ERR_NONE == status) { - /* The query here isn't needed for any technical - reason, just makes the presentation better. - The ERASE_DEVICE command above returns - immediately...subsequent commands can be made - but will pause until the erase cycle completes. - So this query just keeps the "Writing" message - or others from being displayed prematurely. */ - usbBuf[0] = QUERY_DEVICE; - status = usbWrite(1,1); - } - } - - if(hexFile) { - if(ERR_NONE == status) { - (void)printf("Writing hex file '%s':",hexFile); - status = hexWrite((actions & ACTION_VERIFY) != 0); - (void)putchar('\n'); - } - hexClose(); - } - - if((ERR_NONE == status) && (actions & ACTION_SIGN)) { - (void)puts("Signing flash..."); - usbBuf[0] = SIGN_FLASH; - status = usbWrite(1,0); - if (ERR_NONE == status) { - /* Send another Query as it gives a result when - device is ready, but Sign Flash doesn't by itself */ - usbBuf[0] = QUERY_DEVICE; - status = usbWrite(1,1); - } - if (ERR_NONE != status) { - status = ERR_SIGN_FLASH; - } - } - - if((ERR_NONE == status) && (actions & ACTION_RESET)) { - (void)puts("Resetting device..."); - usbBuf[0] = RESET_DEVICE; - status = usbWrite(1,0); - } - - usbClose(); - } - - if(ERR_NONE != status) { - (void)printf("%s Error",argv[0]); - if(status <= ERR_EOL) - (void)printf(": %s\n",errorString[status - 1]); - else - (void)puts(" of indeterminate type."); - } - - return (int)status; + return 0; + } else { + status = ERR_CMD_UNKNOWN; + } + } + + /* After successful command-line parsage, find/open USB device. */ + + if((ERR_NONE == status) && + (ERR_NONE == (status = usbOpen(vendorID,productID)))) { + + /* And start doing stuff... */ + + (void)printf("USB HID device found"); + usbBuf[0] = QUERY_DEVICE; + if(ERR_NONE == (status = usbWrite(1,1))) { + status = deviceQueryProcessResult(1); + } + (void)putchar('\n'); + + if((ERR_NONE == status) && (actions & ACTION_UNLOCK)) { + (void)puts("Unlocking configuration memory..."); + usbBuf[0] = UNLOCK_CONFIG; + usbBuf[1] = UNLOCKCONFIG; + status = usbWrite(2,0); + // redo DEVICE_QUERY & process memory block info again + // for Bootloader versions that only report Config mem after Unlock + usbBuf[0] = QUERY_DEVICE; + if((ERR_NONE == status) && (ERR_NONE == (status = usbWrite(1,1)))) { + status = deviceQueryProcessResult(0); + } + } + // disable all configuration blocks in devQuery if locked + if ( !( actions & ACTION_UNLOCK ) ) { + for ( i = 0; i < devQuery.memBlocks; i++ ) + if ( devQuery.mem[ i ].Type == TypeConfigWords ) + devQuery.mem[ i ].Type = 0; + } + + /* Although the next actual operation is ACTION_ERASE, + if we anticipate hex-writing in a subsequent step, + attempt opening file now so we can display any error + message quickly rather than waiting through the whole + erase operation (it's usually a simple filename typo). */ + if((ERR_NONE == status) && hexFile && + (ERR_NONE != (status = hexOpen(hexFile)))) + hexFile = NULL; /* Open or mmap error */ + + if((ERR_NONE == status) && (actions & ACTION_ERASE)) { + (void)puts("Erasing..."); + usbBuf[0] = ERASE_DEVICE; + status = usbWrite(1,0); + if (ERR_NONE == status) { + /* The query here isn't needed for any technical + reason, just makes the presentation better. + The ERASE_DEVICE command above returns + immediately...subsequent commands can be made + but will pause until the erase cycle completes. + So this query just keeps the "Writing" message + or others from being displayed prematurely. */ + usbBuf[0] = QUERY_DEVICE; + status = usbWrite(1,1); + } + } + + if(hexFile) { + if(ERR_NONE == status) { + (void)printf("Writing hex file '%s':",hexFile); + status = hexWrite((actions & ACTION_VERIFY) != 0); + (void)putchar('\n'); + } + hexClose(); + } + + if((ERR_NONE == status) && (actions & ACTION_SIGN)) { + (void)puts("Signing flash..."); + usbBuf[0] = SIGN_FLASH; + status = usbWrite(1,0); + if (ERR_NONE == status) { + /* Send another Query as it gives a result when + device is ready, but Sign Flash doesn't by itself */ + usbBuf[0] = QUERY_DEVICE; + status = usbWrite(1,1); + } + if (ERR_NONE != status) { + status = ERR_SIGN_FLASH; + } + } + + if((ERR_NONE == status) && (actions & ACTION_RESET)) { + (void)puts("Resetting device..."); + usbBuf[0] = RESET_DEVICE; + status = usbWrite(1,0); + } + + usbClose(); + } + + if(ERR_NONE != status) { + (void)printf("%s Error",argv[0]); + if(status <= ERR_EOL) + (void)printf(": %s\n",errorString[status - 1]); + else + (void)puts(" of indeterminate type."); + } + + return (int)status; } diff --git a/mphidflash.h b/mphidflash.h index 83001f0..9859079 100644 --- a/mphidflash.h +++ b/mphidflash.h @@ -11,7 +11,7 @@ 2010-12-28 Petr Olivka * program and verify only data for defined memory areas * send only even length of data to PIC - + License : Copyright (C) 2009 Phillip Burgess Copyright (C) 2009 Thomas Fischl, Dominik Fisch (www.FundF.net) Copyright (C) 2010 Petr Olivka @@ -115,45 +115,47 @@ typedef enum { - ERR_NONE = 0, /* Success (non-error) */ - ERR_CMD_ARG, - ERR_CMD_UNKNOWN, - ERR_DEVICE_NOT_FOUND, - ERR_USB_INIT1, - ERR_USB_INIT2, - ERR_USB_OPEN, - ERR_USB_WRITE, - ERR_USB_READ, - ERR_HEX_OPEN, - ERR_HEX_STAT, - ERR_HEX_MMAP, - ERR_HEX_SYNTAX, - ERR_HEX_CHECKSUM, - ERR_HEX_RECORD, - ERR_VERIFY, - ERR_BAD_MEM_TYPE, - ERR_BAD_MEM_LENGTH, - ERR_BAD_MEM_LENGTH2, - ERR_OVERLAPPING_MEM_BLOCKS, - ERR_MEM_BLOCK_TYPE_REPEATS, - ERR_NO_PROGRAM_MEMORY, - ERR_RESPONSE_HAS_WRONG_COMMAND, - ERR_BAD_PACKET_DATA_FIELD_SIZE, - ERR_SIGN_FLASH, - ERR_EOL /* End-of-list, not actual error code */ + ERR_NONE = 0, /* Success (non-error) */ + ERR_CMD_ARG, + ERR_CMD_UNKNOWN, + ERR_DEVICE_NOT_FOUND, + ERR_USB_INIT1, + ERR_USB_INIT2, + ERR_USB_OPEN, + ERR_USB_WRITE, + ERR_USB_READ, + ERR_HEX_OPEN, + ERR_HEX_STAT, + ERR_HEX_MMAP, + ERR_HEX_SYNTAX, + ERR_HEX_CHECKSUM, + ERR_HEX_RECORD, + ERR_VERIFY, + ERR_BAD_MEM_TYPE, + ERR_BAD_MEM_LENGTH, + ERR_BAD_MEM_LENGTH2, + ERR_OVERLAPPING_MEM_BLOCKS, + ERR_MEM_BLOCK_TYPE_REPEATS, + ERR_NO_PROGRAM_MEMORY, + ERR_RESPONSE_HAS_WRONG_COMMAND, + ERR_BAD_PACKET_DATA_FIELD_SIZE, + ERR_SIGN_FLASH, + ERR_EOL /* End-of-list, not actual error code */ } ErrorCode; + /* Function prototypes */ extern ErrorCode - hexOpen(char * const), - hexWrite(const char), - usbOpen(const unsigned short,const unsigned short), - usbWrite(const char,const char); + hexOpen(char * const), + hexWrite(const char), + usbOpen(const unsigned short,const unsigned short), + usbWrite(const char,const char); extern void - hexClose(void), - usbClose(void), - hexSetBytesPerAddress(unsigned char); + hexClose(void), + usbClose(void), + hexSetBytesPerAddress(unsigned char); +extern unsigned char hexGetBytesPerAddress(void); #pragma pack( push ) #pragma pack( 1 ) diff --git a/usb-libusb.c b/usb-libusb.c index f12f495..ee13f98 100644 --- a/usb-libusb.c +++ b/usb-libusb.c @@ -7,7 +7,7 @@ * Initial implementation of usb-linux with libhid 2009-12-28 Thomas Fischl, Dominik Fisch (www.FundF.net) * Support for libusb without dependencies to libhid - + License : Copyright (C) 2009 Phillip Burgess Copyright (C) 2009 Thomas Fischl, Dominik Fisch (www.FundF.net) @@ -33,9 +33,9 @@ #include "mphidflash.h" -unsigned char usbBufX[64]; -unsigned char * usbBuf = usbBufX; -usb_dev_handle *usbdevice = NULL; +unsigned char usbBufX[64]; +unsigned char *usbBuf = usbBufX; +usb_dev_handle *usbdevice = NULL; ErrorCode usbOpen( const unsigned short vendorID, @@ -53,7 +53,7 @@ ErrorCode usbOpen( if (dev->descriptor.idVendor == vendorID && dev->descriptor.idProduct == productID) { usbdevice = usb_open(dev); - if (!usbdevice) { + if (!usbdevice) { fprintf(stderr, "Warning: matching device found, but cannot open usb device: %s\n", usb_strerror()); continue; } @@ -67,7 +67,7 @@ ErrorCode usbOpen( usbdevice = NULL; fprintf(stderr, "Warning: cannot claim interface: %s\n", usb_strerror()); continue; - } + } } return ERR_NONE; @@ -76,7 +76,6 @@ ErrorCode usbOpen( } return ERR_DEVICE_NOT_FOUND; - } ErrorCode usbWrite( @@ -93,9 +92,9 @@ ErrorCode usbWrite( if (read) { bytesRead = usb_interrupt_read(usbdevice, 0x81, usbBuf, 64, 5000); - if (bytesRead < 0) - return ERR_USB_READ; - } + if (bytesRead < 0) + return ERR_USB_READ; + } return ERR_NONE; } diff --git a/usb-linux.c b/usb-linux.c index 3453136..0552c29 100644 --- a/usb-linux.c +++ b/usb-linux.c @@ -12,11 +12,11 @@ 2010-12-28 Petr Olivka * program and verify only data for defined memory areas * send only even length of data to PIC - + License : Copyright (C) 2009 Phillip Burgess Copyright (C) 2009 Thomas Fischl, Dominik Fisch (www.FundF.net) Copyright (C) 2010 Petr Olivka - + This file is part of 'mphidflash' program. 'mphidflash' is free software: you can redistribute it and/or @@ -41,8 +41,9 @@ #include static HIDInterface *hid = NULL; -unsigned char usbBufX[64]; -unsigned char * usbBuf = usbBufX; + +unsigned char usbBufX[64]; +unsigned char *usbBuf = usbBufX; /**************************************************************************** Function : usbOpen @@ -66,32 +67,32 @@ ErrorCode usbOpen( const unsigned short vendorID, const unsigned short productID) { - ErrorCode status = ERR_USB_INIT1; - HIDInterfaceMatcher matcher; - - matcher.vendor_id = vendorID; - matcher.product_id = productID; - matcher.matcher_fn = NULL; - - if (debugLevel >= DEBUG_USB) { - hid_set_debug(HID_DEBUG_ALL); - hid_set_usb_debug(HID_DEBUG_ALL); - } - - if(HID_RET_SUCCESS == hid_init()) { - status = ERR_USB_INIT2; - if((hid = hid_new_HIDInterface())) { - if(HID_RET_SUCCESS == - hid_force_open(hid,0,&matcher,3)) { - return ERR_NONE; - } - status = ERR_DEVICE_NOT_FOUND; - hid_delete_HIDInterface(&hid); - } - hid_cleanup(); - } - - return status; + ErrorCode status = ERR_USB_INIT1; + HIDInterfaceMatcher matcher; + + matcher.vendor_id = vendorID; + matcher.product_id = productID; + matcher.matcher_fn = NULL; + + if (debugLevel >= DEBUG_USB) { + hid_set_debug(HID_DEBUG_ALL); + hid_set_usb_debug(HID_DEBUG_ALL); + } + + if(HID_RET_SUCCESS == hid_init()) { + status = ERR_USB_INIT2; + if((hid = hid_new_HIDInterface())) { + if(HID_RET_SUCCESS == + hid_force_open(hid,0,&matcher,3)) { + return ERR_NONE; + } + status = ERR_DEVICE_NOT_FOUND; + hid_delete_HIDInterface(&hid); + } + hid_cleanup(); + } + + return status; } /**************************************************************************** @@ -111,34 +112,34 @@ ErrorCode usbWrite( const char read) { #ifdef DEBUG - int i; - (void)puts("Sending:"); - for(i=0;i<8;i++) (void)printf("%02x ",((unsigned char *)usbBuf)[i]); - (void)printf(": "); - for(;i<64;i++) (void)printf("%02x ",((unsigned char *)usbBuf)[i]); - (void)putchar('\n'); fflush(stdout); - DEBUGMSG("\nAbout to write"); + int i; + (void)puts("Sending:"); + for(i=0;i<8;i++) (void)printf("%02x ",((unsigned char *)usbBuf)[i]); + (void)printf(": "); + for(;i<64;i++) (void)printf("%02x ",((unsigned char *)usbBuf)[i]); + (void)putchar('\n'); fflush(stdout); + DEBUGMSG("\nAbout to write"); #endif - if(HID_RET_SUCCESS != hid_interrupt_write(hid,0x01,usbBuf,len,0)) - return ERR_USB_WRITE; + if(HID_RET_SUCCESS != hid_interrupt_write(hid,0x01,usbBuf,len,0)) + return ERR_USB_WRITE; - DEBUGMSG("Done w/write"); + DEBUGMSG("Done w/write"); - if(read) { - DEBUGMSG("About to read"); - if(HID_RET_SUCCESS != hid_interrupt_read(hid,0x81,usbBuf,64,0)) - return ERR_USB_READ; + if(read) { + DEBUGMSG("About to read"); + if(HID_RET_SUCCESS != hid_interrupt_read(hid,0x81,usbBuf,64,0)) + return ERR_USB_READ; #ifdef DEBUG - (void)puts("Done reading\nReceived:"); - for(i=0;i<8;i++) (void)printf("%02x ",usbBuf[i]); - (void)printf(": "); - for(;i<64;i++) (void)printf("%02x ",usbBuf[i]); - (void)putchar('\n'); fflush(stdout); + (void)puts("Done reading\nReceived:"); + for(i=0;i<8;i++) (void)printf("%02x ",usbBuf[i]); + (void)printf(": "); + for(;i<64;i++) (void)printf("%02x ",usbBuf[i]); + (void)putchar('\n'); fflush(stdout); #endif - } + } - return ERR_NONE; + return ERR_NONE; } /**************************************************************************** @@ -151,8 +152,8 @@ ErrorCode usbWrite( ****************************************************************************/ void usbClose(void) { - (void)hid_close(hid); - hid_delete_HIDInterface(&hid); - (void)hid_cleanup(); - hid = NULL; + (void)hid_close(hid); + hid_delete_HIDInterface(&hid); + (void)hid_cleanup(); + hid = NULL; } diff --git a/usb-osx.c b/usb-osx.c index b8e2955..5e11e88 100644 --- a/usb-osx.c +++ b/usb-osx.c @@ -1,6 +1,6 @@ /**************************************************************************** File : usb-osx.c - Description : Encapsulates all nonportable, Linux-specific USB I/O code + Description : Encapsulates all nonportable, OSX-specific USB I/O code within the mphidflash program. Each supported operating system has its own source file, providing a common calling syntax to the portable sections of the code. @@ -9,7 +9,7 @@ * Initial implementation 2009-12-26 Thomas Fischl, Dominik Fisch (www.FundF.net) * Renamed 'ubw32' to 'mphidflash' - + License : Copyright (C) 2009 Phillip Burgess Copyright (C) 2009 Thomas Fischl, Dominik Fisch (www.FundF.net) @@ -36,8 +36,8 @@ #include "mphidflash.h" static IOHIDDeviceDeviceInterface **device = NULL; -unsigned char usbBufX[64]; -unsigned char * usbBuf = usbBufX; +unsigned char usbBufX[64]; +unsigned char *usbBuf = usbBufX; /**************************************************************************** Function : usbCallback @@ -55,9 +55,9 @@ static void usbCallback( uint8_t *report, CFIndex reportLength) { - DEBUGMSG("In callback"); - CFRunLoopStop(CFRunLoopGetCurrent()); - DEBUGMSG("Exiting callback"); + DEBUGMSG("In callback"); + CFRunLoopStop(CFRunLoopGetCurrent()); + DEBUGMSG("Exiting callback"); } /**************************************************************************** @@ -119,7 +119,7 @@ ErrorCode usbOpen( (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOHIDDeviceDeviceInterfaceID),(LPVOID)&device); - (*plugInInterface)->Release(plugInInterface); + (*plugInInterface)->Release(plugInInterface); if(device) { status = ERR_USB_OPEN; /* Init phase 1 OK, but not yet open */ @@ -171,34 +171,34 @@ ErrorCode usbWrite( const char read) { #ifdef DEBUG - int i; - (void)puts("Sending:"); - for(i=0;i<8;i++) (void)printf("%02x ",((unsigned char *)usbBuf)[i]); - (void)printf(": "); - for(;i<64;i++) (void)printf("%02x ",((unsigned char *)usbBuf)[i]); - (void)putchar('\n'); fflush(stdout); - DEBUGMSG("\nAbout to write"); + int i; + (void)puts("Sending:"); + for(i=0;i<8;i++) (void)printf("%02x ",((unsigned char *)usbBuf)[i]); + (void)printf(": "); + for(;i<64;i++) (void)printf("%02x ",((unsigned char *)usbBuf)[i]); + (void)putchar('\n'); fflush(stdout); + DEBUGMSG("\nAbout to write"); #endif - if(kIOReturnSuccess != (*device)->setReport(device, - kIOHIDReportTypeOutput,0,usbBuf,len,500,NULL,NULL,0)) - return ERR_USB_WRITE; + if(kIOReturnSuccess != (*device)->setReport(device, + kIOHIDReportTypeOutput,0,usbBuf,len,500,NULL,NULL,0)) + return ERR_USB_WRITE; - DEBUGMSG("Done w/write"); + DEBUGMSG("Done w/write"); - if(read) { - DEBUGMSG("About to read"); - CFRunLoopRun(); /* Read invokes callback when done */ + if(read) { + DEBUGMSG("About to read"); + CFRunLoopRun(); /* Read invokes callback when done */ #ifdef DEBUG - (void)puts("Done reading\nReceived:"); - for(i=0;i<8;i++) (void)printf("%02x ",usbBuf[i]); - (void)printf(": "); - for(;i<64;i++) (void)printf("%02x ",usbBuf[i]); - (void)putchar('\n'); fflush(stdout); + (void)puts("Done reading\nReceived:"); + for(i=0;i<8;i++) (void)printf("%02x ",usbBuf[i]); + (void)printf(": "); + for(;i<64;i++) (void)printf("%02x ",usbBuf[i]); + (void)putchar('\n'); fflush(stdout); #endif - } + } - return ERR_NONE; + return ERR_NONE; } /**************************************************************************** @@ -211,7 +211,7 @@ ErrorCode usbWrite( ****************************************************************************/ void usbClose(void) { - (*device)->close(device,0); - (*device)->Release(device); - device = NULL; + (*device)->close(device,0); + (*device)->Release(device); + device = NULL; } diff --git a/usb-windows.c b/usb-windows.c index 61c0b7a..cfe8a42 100644 --- a/usb-windows.c +++ b/usb-windows.c @@ -1,6 +1,6 @@ /**************************************************************************** File : usb-windows.c - Description : Encapsulates all nonportable, Linux-specific USB I/O code + Description : Encapsulates all nonportable, Windows-specific USB I/O code within the mphidflash program. Each supported operating system has its own source file, providing a common calling syntax to the portable sections of the code. @@ -33,14 +33,21 @@ ****************************************************************************/ +//#define __CRT__NO_INLINE +#define __CRT_STRSAFE_IMPL #include #include #include #include #if !defined (_MSC_VER) // headers are distributed with mingw compiler +#if __GNUC__ >= 5 +#include +#include +#else #include #include +#endif #else // MS Visual C // headers from the Device (driver) Development Kit, fixup paths for your system @@ -70,12 +77,12 @@ #undef STRINGIZE2 #endif -HANDLE usbdevhandle = INVALID_HANDLE_VALUE; -unsigned char usbBufX[65]; -unsigned char * usbBuf = &usbBufX[1]; +HANDLE usbdevhandle = INVALID_HANDLE_VALUE; +unsigned char usbBufX[65]; +unsigned char * usbBuf = &usbBufX[1]; -HIDP_CAPS Capabilities; -PHIDP_PREPARSED_DATA HidParsedData; +HIDP_CAPS Capabilities; +PHIDP_PREPARSED_DATA HidParsedData; // private to file static ErrorCode tryUsbOpen( @@ -87,101 +94,101 @@ ErrorCode usbOpen( const unsigned short vendorID, const unsigned short productID) { - ErrorCode status = ERR_DEVICE_NOT_FOUND; - unsigned tries; - const unsigned max_tries = 6; - const DWORD delay_ms = 100; - - /* first try after connecting often fails, whilst Windows initializes device */ - for (tries = 0; (tries < max_tries) && (ERR_DEVICE_NOT_FOUND == status); tries++) { - if (tries != 0) - Sleep(delay_ms); // ms - status = tryUsbOpen(vendorID, productID); - } + ErrorCode status = ERR_DEVICE_NOT_FOUND; + unsigned tries; + const unsigned max_tries = 6; + const DWORD delay_ms = 100; + + /* first try after connecting often fails, whilst Windows initializes device */ + for (tries = 0; (tries < max_tries) && (ERR_DEVICE_NOT_FOUND == status); tries++) { + if (tries != 0) + Sleep(delay_ms); // ms + status = tryUsbOpen(vendorID, productID); + } #ifdef DEBUG - if ((ERR_NONE == status) && tries) - (void)printf("\nSuccess opening Bootloader after %u ms", tries * delay_ms); + if ((ERR_NONE == status) && tries) + (void)printf("\nSuccess opening Bootloader after %u ms", tries * delay_ms); #endif - return status; + return status; } ErrorCode tryUsbOpen( const unsigned short vendorID, const unsigned short productID) { - ErrorCode status = ERR_DEVICE_NOT_FOUND; - int i; - GUID hidGuid; - HDEVINFO deviceInfoList; - SP_DEVICE_INTERFACE_DATA deviceInfo; - SP_DEVICE_INTERFACE_DETAIL_DATA *deviceDetails = NULL; - DWORD size; - char pathPrefix[40]; - int prefixLength; - HRESULT hr; - - // expected start of DevicePath specifies the USB Vendor & Product Identities - hr = StringCchPrintf(pathPrefix, ARRAYSIZE(pathPrefix), "\\\\?\\hid#vid_%04x&pid_%04x#", vendorID, productID); - if (FAILED(hr)) { - fprintf(stderr, "internal error calling StringCchPrintf in " __FILE__ ); - return ERR_USB_OPEN; - } - prefixLength = strlen(pathPrefix); - - HidD_GetHidGuid(&hidGuid); - deviceInfoList = SetupDiGetClassDevs(&hidGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE); - - if (INVALID_HANDLE_VALUE == deviceInfoList) - return status; // no HID devices connected - - deviceInfo.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - - for (i = 0; SetupDiEnumDeviceInterfaces(deviceInfoList, 0, &hidGuid, i, &deviceInfo); i++) { - - /* get size for detail structure */ - SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInfo, NULL, 0, &size, NULL); - if (deviceDetails != NULL) - free(deviceDetails); - deviceDetails = (SP_DEVICE_INTERFACE_DETAIL_DATA*) malloc(size); - deviceDetails->cbSize = sizeof(*deviceDetails); - - /* now get details */ - SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInfo, deviceDetails, size, &size, NULL); - - /* check for expected USB VID & PID in device path before opening device */ - if (strncasecmp(deviceDetails->DevicePath, pathPrefix, prefixLength)) { - continue; - } - - /* try to open device */ - usbdevhandle = CreateFile(deviceDetails->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - if (usbdevhandle == INVALID_HANDLE_VALUE) { - fprintf(stderr, "Warning: matching device found, but cannot open usb device. (System Error %u)\n", GetLastError()); - /* cannot open device, go to next */ - status = ERR_USB_OPEN; - continue; - } - - HidD_GetPreparsedData(usbdevhandle, &HidParsedData); - - /* extract the capabilities info */ - HidP_GetCaps(HidParsedData ,&Capabilities); - - /* Free the memory allocated when getting the preparsed data */ - HidD_FreePreparsedData(HidParsedData); - - /* okay, here we found our device */ - status = ERR_NONE; - break; - } - - SetupDiDestroyDeviceInfoList(deviceInfoList); - - if (deviceDetails != NULL) - free(deviceDetails); - - return status; + ErrorCode status = ERR_DEVICE_NOT_FOUND; + int i; + GUID hidGuid; + HDEVINFO deviceInfoList; + SP_DEVICE_INTERFACE_DATA deviceInfo; + SP_DEVICE_INTERFACE_DETAIL_DATA *deviceDetails = NULL; + DWORD size; + char pathPrefix[40]; + int prefixLength; + HRESULT hr; + + // expected start of DevicePath specifies the USB Vendor & Product Identities + hr = StringCchPrintf(pathPrefix, ARRAYSIZE(pathPrefix), "\\\\?\\hid#vid_%04x&pid_%04x#", vendorID, productID); + if (FAILED(hr)) { + fprintf(stderr, "internal error calling StringCchPrintf in " __FILE__ ); + return ERR_USB_OPEN; + } + prefixLength = strlen(pathPrefix); + + HidD_GetHidGuid(&hidGuid); + deviceInfoList = SetupDiGetClassDevs(&hidGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE); + + if (INVALID_HANDLE_VALUE == deviceInfoList) + return status; // no HID devices connected + + deviceInfo.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + + for (i = 0; SetupDiEnumDeviceInterfaces(deviceInfoList, 0, &hidGuid, i, &deviceInfo); i++) { + + /* get size for detail structure */ + SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInfo, NULL, 0, &size, NULL); + if (deviceDetails != NULL) + free(deviceDetails); + deviceDetails = (SP_DEVICE_INTERFACE_DETAIL_DATA*) malloc(size); + deviceDetails->cbSize = sizeof(*deviceDetails); + + /* now get details */ + SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInfo, deviceDetails, size, &size, NULL); + + /* check for expected USB VID & PID in device path before opening device */ + if (strncasecmp(deviceDetails->DevicePath, pathPrefix, prefixLength)) { + continue; + } + + /* try to open device */ + usbdevhandle = CreateFile(deviceDetails->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (usbdevhandle == INVALID_HANDLE_VALUE) { + fprintf(stderr, "Warning: matching device found, but cannot open usb device. (System Error %u)\n", GetLastError()); + /* cannot open device, go to next */ + status = ERR_USB_OPEN; + continue; + } + + HidD_GetPreparsedData(usbdevhandle, &HidParsedData); + + /* extract the capabilities info */ + HidP_GetCaps(HidParsedData ,&Capabilities); + + /* Free the memory allocated when getting the preparsed data */ + HidD_FreePreparsedData(HidParsedData); + + /* okay, here we found our device */ + status = ERR_NONE; + break; + } + + SetupDiDestroyDeviceInfoList(deviceInfoList); + + if (deviceDetails != NULL) + free(deviceDetails); + + return status; } @@ -190,53 +197,53 @@ ErrorCode usbWrite( const char read) { - BOOLEAN rval = 0; - DWORD bytesWritten = 0; - DWORD bytesRead = 0; + BOOLEAN rval = 0; + DWORD bytesWritten = 0; + DWORD bytesRead = 0; #ifdef DEBUG - int i; - (void)puts("Sending:"); - for(i=0;i<8;i++) (void)printf("%02x ",((unsigned char *)usbBuf)[i]); - (void)printf(": "); - for(;i<64;i++) (void)printf("%02x ",((unsigned char *)usbBuf)[i]); - (void)putchar('\n'); fflush(stdout); - DEBUGMSG("\nAbout to write"); - printf("usbdevhandle: %d, usbBuf: %d, len: %d, %d\n", usbdevhandle, usbBuf, len, Capabilities.OutputReportByteLength); + int i; + (void)puts("Sending:"); + for(i=0;i<8;i++) (void)printf("%02x ",((unsigned char *)usbBuf)[i]); + (void)printf(": "); + for(;i<64;i++) (void)printf("%02x ",((unsigned char *)usbBuf)[i]); + (void)putchar('\n'); fflush(stdout); + DEBUGMSG("\nAbout to write"); + printf("usbdevhandle: %d, usbBuf: %d, len: %d, %d\n", usbdevhandle, usbBuf, len, Capabilities.OutputReportByteLength); #endif - /* report id */ - usbBufX[0] = 0; + /* report id */ + usbBufX[0] = 0; - if (WriteFile(usbdevhandle, usbBufX, Capabilities.OutputReportByteLength, &bytesWritten, 0) == 0) { -// printf("usb write failed, Error %u\n", GetLastError()); + if (WriteFile(usbdevhandle, usbBufX, Capabilities.OutputReportByteLength, &bytesWritten, 0) == 0) { +// printf("usb write failed, Error %u\n", GetLastError()); - return ERR_USB_WRITE; - } + return ERR_USB_WRITE; + } - DEBUGMSG("Done w/write"); + DEBUGMSG("Done w/write"); - if (read) { - if (ReadFile(usbdevhandle, usbBufX, Capabilities.OutputReportByteLength, &bytesRead, 0) == 0) { -// printf("usb read failed, Error %u\n", GetLastError()); - return ERR_USB_READ; - } + if (read) { + if (ReadFile(usbdevhandle, usbBufX, Capabilities.OutputReportByteLength, &bytesRead, 0) == 0) { +// printf("usb read failed, Error %u\n", GetLastError()); + return ERR_USB_READ; + } #ifdef DEBUG - (void)puts("Done reading\nReceived:"); - for(i=0;i<8;i++) (void)printf("%02x ",usbBuf[i]); - (void)printf(": "); - for(;i<64;i++) (void)printf("%02x ",usbBuf[i]); - (void)putchar('\n'); fflush(stdout); + (void)puts("Done reading\nReceived:"); + for(i=0;i<8;i++) (void)printf("%02x ",usbBuf[i]); + (void)printf(": "); + for(;i<64;i++) (void)printf("%02x ",usbBuf[i]); + (void)putchar('\n'); fflush(stdout); #endif - } + } - return ERR_NONE; + return ERR_NONE; } void usbClose(void) { - CloseHandle(usbdevhandle); + CloseHandle(usbdevhandle); } diff --git a/version.mk b/version.mk new file mode 100644 index 0000000..2a8cceb --- /dev/null +++ b/version.mk @@ -0,0 +1,2 @@ +VERSION_MAIN = 1 +VERSION_SUB = 9