diff --git a/fileio.cpp b/fileio.cpp index 3d446cd..3535b73 100644 --- a/fileio.cpp +++ b/fileio.cpp @@ -1,8 +1,6 @@ #include "fileio.h" -#define DEBUG 1 - void SkylanderIO::fprinthex(FILE *f, unsigned char *c, unsigned int n) { unsigned int h,i; unsigned char j; @@ -62,9 +60,6 @@ void SkylanderIO::initWithEncryptedFile(char * name) throw (int) void SkylanderIO::initWithPortal(int number) throw (int) { -#if DEBUG -printf(">>> SkylanderIO::initWithPortal\n"); -#endif if (!sky) { //printf("Reading Skylander from portal.\n"); @@ -74,17 +69,24 @@ printf(">>> SkylanderIO::initWithPortal\n"); // printf("\nSkylander read from portal.\n"); } -#if DEBUG -printf("<<< SkylanderIO::initWithPortal\n"); -#endif +} + + +void SkylanderIO::initRawReadPortal(int number) throw (int) { + + + if (!sky) { + //printf("Reading Skylander from portal.\n"); + ReadPortal(buffer,number); + sky = new Skylander(buffer); + // printf("\nSkylander read from portal.\n"); + + } } void SkylanderIO::ReadPortal(unsigned char *s, int number) throw (int) { -#if DEBUG -printf(">>> SkylanderIO::ReadPortal\n"); -#endif unsigned char data[0x10]; unsigned char *ptr; @@ -108,15 +110,11 @@ printf(">>> SkylanderIO::ReadPortal\n"); } delete port; -#if DEBUG -printf("<<< SkylanderIO::ReadPortal\n"); -#endif } bool SkylanderIO::writeSkylanderToPortal(int number) throw (int) { bool bResult; - bool bNewSkylander = false; unsigned char data[0x10]; unsigned char old[1024]; @@ -155,7 +153,7 @@ bool SkylanderIO::writeSkylanderToPortal(int number) throw (int) if(crypt.IsAccessControlBlock(block) == selectAccessControlBlock) { changed = (memcmp(old + offset, skydata+offset,BLOCK_SIZE) != 0); if(changed) { - port->WriteBlock( block, skydata+offset, bNewSkylander); + port->WriteBlock( block, skydata+offset, number); } } } @@ -167,12 +165,61 @@ bool SkylanderIO::writeSkylanderToPortal(int number) throw (int) } +bool SkylanderIO::RawWriteSkylanderToPortal(int number) throw (int) +{ + bool bResult; + unsigned char data[0x10]; + + unsigned char old[1024]; + unsigned char skydata[1024]; + + Crypt crypt; + + if (sky) { + + PortalIO *port; + + ReadPortal(old,number); + + memcpy (skydata,sky->getData(),1024); + + printf("\nWriting Skylander to portal.\n"); + + port = new PortalIO(); + + + for(int i=0; i<2; i++) { + // two pass write + // write the access control blocks first + bool selectAccessControlBlock; + if(i == 0) { + selectAccessControlBlock = 1; + } else { + selectAccessControlBlock = 0; + } + + for(int block=0; block < 0x40; ++block) { + bool changed, OK; + int offset = block * BLOCK_SIZE; + if(crypt.IsAccessControlBlock(block) == selectAccessControlBlock) { + changed = (memcmp(old + offset, skydata+offset,BLOCK_SIZE) != 0); + if(changed) { + port->WriteBlock( block, skydata+offset, number); + } + } + } + } + + return true; + } + return false; +} + bool SkylanderIO::writeSkylanderToUnencryptedFile(char *name) throw (int) { if (sky) { WriteSkylanderFile(name,sky->getData()); } - return true; } bool SkylanderIO::writeSkylanderToEncryptedFile(char *name) throw (int) @@ -184,7 +231,6 @@ bool SkylanderIO::writeSkylanderToEncryptedFile(char *name) throw (int) EncryptBuffer(skydata); WriteSkylanderFile(name,skydata); } - return true; } @@ -279,7 +325,7 @@ void SkylanderIO::listSkylanders() { Skylander *sky; unsigned char data[0x10]; - + port = new PortalIO(); sky = new Skylander(buffer); @@ -288,6 +334,7 @@ void SkylanderIO::listSkylanders() { { memset(data,0,0x10); // must start with a read of block zero + port->ReadBlock(1, data, s); printf("%0d: %s\n",s,sky->toyName(data[0] + data[1] * 0x100)); diff --git a/fileio.h b/fileio.h index ce7746f..2e26752 100644 --- a/fileio.h +++ b/fileio.h @@ -23,6 +23,7 @@ class SkylanderIO { void initWithUnencryptedFile(char *) throw (int); void initWithEncryptedFile(char *) throw (int); void initWithPortal(int) throw (int); + void initRawReadPortal(int) throw (int); void listSkylanders(); @@ -31,6 +32,7 @@ class SkylanderIO { // void setSkylander(Skylander *); bool writeSkylanderToPortal(int) throw (int); + bool RawWriteSkylanderToPortal(int) throw (int); bool writeSkylanderToUnencryptedFile(char *) throw (int); bool writeSkylanderToEncryptedFile(char *) throw (int); @@ -57,4 +59,4 @@ class SkylanderIO { void EncryptBuffer(unsigned char* ); void DecryptBuffer(unsigned char* ); -}; \ No newline at end of file +}; diff --git a/hid_win.c b/hid_win.c index 5415bc0..daa7569 100644 --- a/hid_win.c +++ b/hid_win.c @@ -100,6 +100,7 @@ extern "C" { typedef BOOLEAN (__stdcall *HidD_GetSerialNumberString_)(HANDLE device, PVOID buffer, ULONG buffer_len); typedef BOOLEAN (__stdcall *HidD_GetManufacturerString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); typedef BOOLEAN (__stdcall *HidD_GetProductString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); + typedef BOOLEAN (__stdcall *HidD_SetOutputReport_)(HANDLE handle, PVOID data, ULONG length); typedef BOOLEAN (__stdcall *HidD_SetFeature_)(HANDLE handle, PVOID data, ULONG length); typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE handle, PVOID data, ULONG length); typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_index, PVOID buffer, ULONG buffer_len); @@ -112,6 +113,7 @@ extern "C" { static HidD_GetSerialNumberString_ HidD_GetSerialNumberString; static HidD_GetManufacturerString_ HidD_GetManufacturerString; static HidD_GetProductString_ HidD_GetProductString; + static HidD_SetOutputReport_ HidD_SetOutputReport; static HidD_SetFeature_ HidD_SetFeature; static HidD_GetFeature_ HidD_GetFeature; static HidD_GetIndexedString_ HidD_GetIndexedString; @@ -202,7 +204,7 @@ static int lookup_functions() RESOLVE(HidD_GetSerialNumberString); RESOLVE(HidD_GetManufacturerString); RESOLVE(HidD_GetProductString); - RESOLVE(HidD_SetFeature); + RESOLVE(HidD_SetOutputReport); RESOLVE(HidD_GetFeature); RESOLVE(HidD_GetIndexedString); RESOLVE(HidD_GetPreparsedData); @@ -605,7 +607,7 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char * { DWORD bytes_written; BOOL res; - + int wError; OVERLAPPED ol; unsigned char *buf; memset(&ol, 0, sizeof(ol)); @@ -627,23 +629,31 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char * memset(buf + length, 0, dev->output_report_length - length); length = dev->output_report_length; } - - res = WriteFile(dev->device_handle, buf, length, NULL, &ol); + + + res = WriteFile(dev->device_handle, buf, length, NULL, &ol); if (!res) { - if (GetLastError() != ERROR_IO_PENDING) { + wError = GetLastError(); + printf("%i\n", wError); + if (wError != ERROR_IO_PENDING) { /* WriteFile() failed. Return error. */ register_error(dev, "WriteFile"); bytes_written = -1; goto end_of_function; } } - + + /* Wait here until the write is done. This makes hid_write() synchronous. */ - res = GetOverlappedResult(dev->device_handle, &ol, &bytes_written, TRUE/*wait*/); + + res = GetOverlappedResult(dev->device_handle, &ol, &bytes_written, TRUE); + if (!res) { /* The Write operation failed. */ + wError = GetLastError(); + printf("%i", wError); register_error(dev, "WriteFile"); bytes_written = -1; goto end_of_function; @@ -739,6 +749,18 @@ int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonbloc return 0; /* Success */ } + +int HID_API_EXPORT HID_API_CALL hid_set_output_report(hid_device *dev, const unsigned char *data, size_t length) +{ + BOOL res = HidD_SetOutputReport(dev->device_handle, (PVOID)data, length); + if (!res) { + register_error(dev, "HidD_SetOutputReport"); + return -1; + } + + return length; +} + int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) { BOOL res = HidD_SetFeature(dev->device_handle, (PVOID)data, length); diff --git a/hidapi.h b/hidapi.h index e5bc2dc..23d6fb3 100644 --- a/hidapi.h +++ b/hidapi.h @@ -289,6 +289,8 @@ extern "C" { This function returns the actual number of bytes written and -1 on error. */ + int HID_API_EXPORT HID_API_CALL hid_set_output_report(hid_device *device, const unsigned char *data, size_t length); + int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length); /** @brief Get a feature report from a HID device. diff --git a/main.cpp b/main.cpp index 543282c..94cbc0f 100644 --- a/main.cpp +++ b/main.cpp @@ -20,10 +20,12 @@ void usage() "Reading/Writing:\n" "-i \tread skylander data from file, with option to decrypt the data.\n" "-p\t\tread skylander data from portal and decrypt the data.\n" + "-K\t\tread skylander data from portal without decrypting\n" "-s select which skylander.\n" "-d\t\tdecrypt the data read from the file.\n" "-o \twrite skylander data to .\n" "-a\t\twrite skylander data to automatic filename.\n" + "-W\t\twrite skylander data without encrypting\n" "-P\t\tencrypt and write skylander data to the portal.\n" "-e\t\tencrypt data when writing file.\n" "-D\t\tdump the data of a skylander to the display.\n" @@ -68,11 +70,11 @@ int main(int argc, char* argv[]) unsigned char *buffer, *original_data; bool OK, OK2; - bool encrypt,decrypt,portalIn,portalOut,dump,upgrade,flash,list,autoFile; + bool encrypt,decrypt,portalIn,portalOut,dump,upgrade,flash,list,autoFile,RawWrite,RawRead; char * inFile, *outFile; - const static char *legal_flags = "alFePpcDo:i:dM:X:H:C:L:R:s:"; + const static char *legal_flags = "alFWePpKcDo:i:dM:X:H:C:L:R:s:"; encrypt = false; decrypt = false; @@ -85,6 +87,8 @@ int main(int argc, char* argv[]) flash = false; list = false; autoFile = false; + RawWrite = false; + RawRead = false; unsigned int money, xp, hp, challenges, skillleft, skillright,skylander_number; bool pathleft, pathright; @@ -110,8 +114,10 @@ int main(int argc, char* argv[]) case 'd': decrypt = true; break; case 'P': portalOut = true; break; case 'p': portalIn = true; break; + case 'K': RawRead = true; break; case 'D': dump = true; break; case 'F': flash = true; break; + case 'W': RawWrite = true; break; case 'i': inFile = new char[strlen(optarg)+1]; strcpy(inFile,optarg); @@ -178,6 +184,7 @@ int main(int argc, char* argv[]) exit (0); } + if (list) { printf ("Listing Skylanders.\n\n"); @@ -188,13 +195,13 @@ int main(int argc, char* argv[]) } // validate command line options - if ( (!inFile && !portalIn) || (inFile && portalIn)) { + if ( (!inFile && !portalIn && !RawRead) || (inFile && portalIn)) { printf ("Must Choose One of: read from file -i or read from portal -p\n"); usage(); exit(0); } - if (!outFile && !portalOut && !dump) { + if (!outFile && !portalOut && !dump && !RawWrite) { printf ("Nothing to write. Choose file -o, portal -P or dump -D\n"); usage(); exit(0); @@ -220,6 +227,10 @@ int main(int argc, char* argv[]) if (portalIn) { skio->initWithPortal(skylander_number); } + if (RawRead) { + skio->initRawReadPortal(skylander_number); + } + if (inFile) { if (decrypt) { skio->initWithEncryptedFile(inFile); @@ -279,13 +290,8 @@ int main(int argc, char* argv[]) if (autoFile) { Skylander * sky; sky = skio->getSkylander(); - unsigned long num = sky->getSerial(); - unsigned long serial = ((num>>24)&0xff) | // move byte 3 to byte 0 - ((num<<8)&0xff0000) | // move byte 1 to byte 2 - ((num>>8)&0xff00) | // move byte 2 to byte 1 - ((num<<24)&0xff000000); // byte 0 to byte 3 - sprintf(outFile, "%s - %s - %08lX.dmp", sky->getToyTypeName(), sky->getPath(), serial); + sprintf(outFile, "%s.bin", sky->getToyTypeName()); printf("Saving to automatic filename: %s\n", outFile); } @@ -298,6 +304,9 @@ int main(int argc, char* argv[]) if (portalOut) { skio->writeSkylanderToPortal(skylander_number); } + if (RawWrite) { + skio->RawWriteSkylanderToPortal(skylander_number); + } delete skio; diff --git a/portalio_hidapi.cpp b/portalio_hidapi.cpp index affb754..a029ef3 100644 --- a/portalio_hidapi.cpp +++ b/portalio_hidapi.cpp @@ -1,7 +1,5 @@ #include "portalio.h" -#define DEBUG 1 - //Port usleep to windows #ifdef _WIN32 #include @@ -84,10 +82,6 @@ void PortalIO::OpenPortalHandle() throw (int) // Send a command to the portal void PortalIO::Write(RWBlock *pb) throw (int) { - -#if DEBUG - printf(">>> PortalIO::Write\n"); -#endif pb->buf[0] = 0; // Use report 0 /* @@ -97,46 +91,30 @@ void PortalIO::Write(RWBlock *pb) throw (int) { skio->fprinthex(stdout,pb->buf, 0x21); delete skio; */ - if (hid_write(hPortalHandle, pb->buf, 0x21) == -1) - { -#if DEBUG - printf("<<< PortalIO::Write throw 6\n"); -#endif + if (hid_set_output_report(hPortalHandle, pb->buf, 0x21) == -1) throw 6; - } -#if DEBUG - printf("<<< PortalIO::Write\n"); -#endif } bool PortalIO::CheckResponse (RWBlock *res, char expect) throw (int) { -#if DEBUG - printf(">>> PortalIO::CheckResponse\n"); -#endif int b = hid_read_timeout(hPortalHandle, res->buf, rw_buf_size, TIMEOUT); if(b<0) throw 8; - -#if DEBUG - printf("PortalIO::CheckResponse hid_read_timeout bytes read = %d\n",b); -#endif res->dwBytesTransferred = b; // this is here to debug the different responses from the portal. -#if DEBUG + /* SkylanderIO *skio; skio = new SkylanderIO(); printf("<<<\n"); skio->fprinthex(stdout,res->buf, 0x21); delete skio; -#endif - + */ // found wireless USB but portal is not connected if (res->buf[0] == 'Z') @@ -147,9 +125,6 @@ bool PortalIO::CheckResponse (RWBlock *res, char expect) throw (int) throw 11; -#if DEBUG - printf("<<< PortalIO::CheckResponse\n"); -#endif return (res->buf[0] != expect); } @@ -158,23 +133,16 @@ bool PortalIO::ReadBlock(unsigned int block, unsigned char data[0x10], int skyla RWBlock req, res; bool gotData; unsigned char followup; - -#if DEBUG - printf(">>> PortalIO:ReadBlock\n"); -#endif if(block >= 0x40) { -#if DEBUG - printf("<<< PortalIO:ReadBlock throw 7\n"); -#endif throw 7; } // Send query request - for(int attempt=0;attempt<15;attempt++) - { +for(int attempt=0;attempt<15;attempt++) +{ int i=0; gotData = false; @@ -192,7 +160,6 @@ bool PortalIO::ReadBlock(unsigned int block, unsigned char data[0x10], int skyla memset(&(res.buf), 0, rw_buf_size); - do { Write(&req); } while (CheckResponse(&res,'Q')); if(res.buf[0] == 'Q' && res.buf[2] == (unsigned char)block) { @@ -200,9 +167,6 @@ bool PortalIO::ReadBlock(unsigned int block, unsigned char data[0x10], int skyla if(res.buf[1] == followup) { /* got the query back with no error */ memcpy(data, res.buf + 3, 0x10); -#if DEBUG - printf("<<< PortalIO:ReadBlock\n"); -#endif return true; } } @@ -210,9 +174,6 @@ bool PortalIO::ReadBlock(unsigned int block, unsigned char data[0x10], int skyla } // retries -#if DEBUG - printf("<<< PortalIO:ReadBlock throw 8\n"); -#endif throw 8; } @@ -307,7 +268,7 @@ void PortalIO::SetPortalColor(unsigned char r, unsigned char g, unsigned char b) // Release hPortalInstance PortalIO::~PortalIO() { - ActivatePortal(0); + //ActivatePortal(0); hid_close(hPortalHandle); @@ -330,9 +291,10 @@ PortalIO::PortalIO() throw (int) OpenPortalHandle(); RestartPortal(); ActivatePortal(1); + Sleep(500); SetPortalColor(0xC8, 0xC8, 0xC8); - printf ("Portal Status: %d\n",PortalStatus()); + // printf ("Portal Status: %d\n",PortalStatus()); }