commit 76af099afcbcafd97801028de2ba3421d3c12865 Author: liuyi Date: Tue Mar 7 16:12:52 2017 +0800 rkDevelopTool: initial commit Signed-off-by: liuyi diff --git a/DefineHeader.h b/DefineHeader.h new file mode 100644 index 0000000..a8caa33 --- /dev/null +++ b/DefineHeader.h @@ -0,0 +1,117 @@ +#ifndef DEFINE_HEADER +#define DEFINE_HEADER +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Property.hpp" +#include +#include +#include +#include +#include +#include +using namespace std; +typedef unsigned char BYTE, *PBYTE; +typedef unsigned char UCHAR; +typedef unsigned short WCHAR; +typedef unsigned short USHORT; +typedef unsigned int UINT; +typedef unsigned int DWORD; + +typedef enum{ + RKNONE_DEVICE = 0, + RK27_DEVICE = 0x10, + RKCAYMAN_DEVICE, + RK28_DEVICE = 0x20, + RK281X_DEVICE, + RKPANDA_DEVICE, + RKNANO_DEVICE = 0x30, + RKSMART_DEVICE, + RKCROWN_DEVICE = 0x40, + RK29_DEVICE = 0x50, + RK292X_DEVICE, + RK30_DEVICE = 0x60, + RK30B_DEVICE, + RK31_DEVICE = 0x70, + RK32_DEVICE = 0x80 +} ENUM_RKDEVICE_TYPE; +typedef enum{ + RK_OS = 0, + ANDROID_OS = 0x1 +} ENUM_OS_TYPE; + +typedef enum{ + RKUSB_NONE = 0x0, + RKUSB_MASKROM = 0x01, + RKUSB_LOADER = 0x02, + RKUSB_MSC = 0x04 +} ENUM_RKUSB_TYPE; +typedef enum{ + ENTRY471 = 1, + ENTRY472 = 2, + ENTRYLOADER = 4 +} ENUM_RKBOOTENTRY; + +#pragma pack(1) +typedef struct{ + USHORT usYear; + BYTE ucMonth; + BYTE ucDay; + BYTE ucHour; + BYTE ucMinute; + BYTE ucSecond; +} STRUCT_RKTIME, *PSTRUCT_RKTIME; + +typedef struct{ + char szItemName[20]; + char szItemValue[256]; +} STRUCT_CONFIG_ITEM, *PSTRUCT_CONFIG_ITEM; +typedef struct _STRUCT_RKDEVICE_DESC{ + USHORT usVid; + USHORT usPid; + USHORT usbcdUsb; + UINT uiLocationID; + ENUM_RKUSB_TYPE emUsbType; + ENUM_RKDEVICE_TYPE emDeviceType; + void *pUsbHandle; +} STRUCT_RKDEVICE_DESC, *PSTRUCT_RKDEVICE_DESC; +#pragma pack() +typedef list RKDEVICE_DESC_SET; +typedef RKDEVICE_DESC_SET::iterator device_list_iter; +typedef vector STRING_VECTOR; +typedef vector UINT_VECTOR; +typedef vector CONFIG_ITEM_VECTOR; +typedef enum{ + TESTDEVICE_PROGRESS, + DOWNLOADIMAGE_PROGRESS, + CHECKIMAGE_PROGRESS, + TAGBADBLOCK_PROGRESS, + TESTBLOCK_PROGRESS, + ERASEFLASH_PROGRESS, + ERASESYSTEM_PROGRESS, + LOWERFORMAT_PROGRESS, + ERASEUSERDATA_PROGRESS +} ENUM_PROGRESS_PROMPT; + +typedef enum{ + CALL_FIRST, + CALL_MIDDLE, + CALL_LAST +} ENUM_CALL_STEP; + +typedef void (*ProgressPromptCB)(DWORD deviceLayer, ENUM_PROGRESS_PROMPT promptID, long long totalValue, long long currentValue, ENUM_CALL_STEP emCall); + +bool WideStringToString(wchar_t *pszSrc, char *&pszDest); +bool StringToWideString(char *pszSrc, wchar_t *&pszDest); +#endif \ No newline at end of file diff --git a/Endian.h b/Endian.h new file mode 100644 index 0000000..316bac9 --- /dev/null +++ b/Endian.h @@ -0,0 +1,21 @@ +#ifndef ENDIAN_HEADER +#define ENDIAN_HEADER + +#define Endian16_Swap(value) (((((unsigned short)value) << 8) & 0xFF00)|\ + ((((unsigned short)value) >> 8) & 0x00FF)) + +#define Endian32_Swap(value) (((((unsigned int)value) << 24) & 0xFF000000) |\ + ((((unsigned int)value) << 8) & 0x00FF0000) |\ + ((((unsigned int)value) >> 8) & 0x0000FF00) |\ + ((((unsigned int)value) >> 24) & 0x000000FF)) + +#define EndianS16_LtoB(value) ((short)Endian16_Swap(value)) +#define EndianS16_BtoL(value) ((short)Endian16_Swap(value)) +#define EndianU16_LtoB(value) ((unsigned short)Endian16_Swap(value)) +#define EndianU16_BtoL(value) ((unsigned short)Endian16_Swap(value)) +#define EndianS32_LtoB(value) ((int)Endian32_Swap(value)) +#define EndianS32_BtoL(value) ((int)Endian32_Swap(value)) +#define EndianU32_LtoB(value) ((unsigned int)Endian32_Swap(value)) +#define EndianU32_BtoL(value) ((unsigned int)Endian32_Swap(value)) + +#endif diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a858370 --- /dev/null +++ b/Makefile @@ -0,0 +1,24 @@ +# Simple Makefile for RK Flash Tool + +CC = g++ +LD = $(CC) +CXXFLAGS = -O2 -Wall -fno-strict-aliasing -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE -I/usr/local/include/libusb-1.0 +LDFLAGS = -L/usr/local/lib -Wl,-Bstatic -lusb-1.0 -Wl,-Bdynamic -lrt -lpthread + + +PROGS = $(patsubst %.cpp,%.o, $(wildcard *.cpp)) + +rkDevelopTool: $(PROGS) + $(CC) $(CXXFLAGS) $^ -o rkDevelopTool $(LDFLAGS) + +install: $(PROGS) + install -d -m 0755 /usr/local/bin + install -m 0755 ./rkDevelopTool /usr/local/bin + +clean: + rm $(PROGS) ./rkDevelopTool + +uninstall: + cd /usr/local/bin && rm -f ./rkDevelopTool + + diff --git a/Property.hpp b/Property.hpp new file mode 100644 index 0000000..ddc7894 --- /dev/null +++ b/Property.hpp @@ -0,0 +1,94 @@ +//-- Property.hpp -- + +/*-------------------------------------------------------------------------- + Class Library + + Copyrights Emad Barsoum (ebarsoum@msn.com) 2003. All rights reserved. + ________________________________________________________________ + + + PROJECT : General + MODULE : property + FILENAME : Property.hpp + BUILD : 1 + + History of Modifications: + + Date(dd/mm/yyyy)Person Description + ---- ------ ----------- + 25/03/2003 Emad Barsoum Initial design and coding + + CLASS NAME: property + VERSION: 1.0 + + DESCRIPTION: + This class try to simulate property for C++, using template technique. + + LICENSE: + You are free to change or modify or redistribute the code, just keep the header. + And you can use this class in any application you want without any warranty. +*/ +#include +#include +#if !defined INC_PROPERTY_HPP +#define INC_PROPERTY_HPP + +#define READ_ONLY 1 +#define WRITE_ONLY 2 +#define READ_WRITE 3 + +template +class property +{ +public: + property() + { + m_cObject = NULL; + Set = NULL; + Get = NULL; + } + //-- This to set a pointer to the class that contain the property -- + void setContainer(Container* cObject) + { + m_cObject = cObject; + } + //-- Set the set member function that will change the value -- + void setter(void (Container::*pSet)(ValueType value)) + { + if((nPropType == WRITE_ONLY) || (nPropType == READ_WRITE)) + Set = pSet; + else + Set = NULL; + } + //-- Set the get member function that will retrieve the value -- + void getter(ValueType (Container::*pGet)()) + { + if((nPropType == READ_ONLY) || (nPropType == READ_WRITE)) + Get = pGet; + else + Get = NULL; + } + //-- Overload the '=' sign to set the value using the set member -- + ValueType operator =(const ValueType& value) + { + assert(m_cObject != NULL); + assert(Set != NULL); + (m_cObject->*Set)(value); + return value; + } + + //-- To make possible to cast the property class to the internal type -- + operator ValueType() + { + assert(m_cObject != NULL); + assert(Get != NULL); + return (m_cObject->*Get)(); + } + +private: + Container* m_cObject;//-- Pointer to the module that contain the property -- + void (Container::*Set)(ValueType value);//-- Pointer to set member function -- + ValueType (Container::*Get)();//-- Pointer to get member function -- +}; + +#endif \ No newline at end of file diff --git a/RKBoot.cpp b/RKBoot.cpp new file mode 100644 index 0000000..36550ec --- /dev/null +++ b/RKBoot.cpp @@ -0,0 +1,314 @@ +/* + * (C) Copyright 2017 Fuzhou Rockchip Electronics Co., Ltd + * Seth Liu 2017.03.01 + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "RKBoot.h" +extern UINT CRC_32(PBYTE pData, UINT ulSize); +bool CRKBoot::GetRc4DisableFlag() +{ + return m_bRc4Disable; +} +bool CRKBoot::GetSignFlag() +{ + return m_bSignFlag; +} +DWORD CRKBoot::GetVersion() +{ + return m_version; +} +DWORD CRKBoot::GetMergeVersion() +{ + return m_mergeVersion; +} +STRUCT_RKTIME CRKBoot::GetReleaseTime() +{ + return m_releaseTime; +} +ENUM_RKDEVICE_TYPE CRKBoot::GetSupportDevice() +{ + return m_supportDevice; +} +UCHAR CRKBoot::GetEntry471Count() +{ + return m_471Count; +} +UCHAR CRKBoot::GetEntry472Count() +{ + return m_472Count; +} +UCHAR CRKBoot::GetEntryLoaderCount() +{ + return m_loaderCount; +} +bool CRKBoot::CrcCheck() +{ + UINT*pOldCrc,ulNewCrc; + pOldCrc = (UINT*)(m_BootData+(m_BootSize-4)); + ulNewCrc = CRC_32(m_BootData,m_BootSize-4); + return (*pOldCrc==ulNewCrc)?true:false; +} +bool CRKBoot::SaveEntryFile(ENUM_RKBOOTENTRY type,UCHAR ucIndex,string fileName) +{ + DWORD dwOffset; + UCHAR ucCount,ucSize; + switch ( type ) + { + case ENTRY471: + dwOffset = m_471Offset; + ucCount = m_471Count; + ucSize = m_471Size; + break; + case ENTRY472: + dwOffset = m_472Offset; + ucCount = m_472Count; + ucSize = m_472Size; + break; + case ENTRYLOADER: + dwOffset = m_loaderOffset; + ucCount = m_loaderCount; + ucSize = m_loaderSize; + break; + default: + return false; + } + if (ucIndex >= ucCount) + { + return false; + } + PSTRUCT_RKBOOT_ENTRY pEntry; + pEntry = (PSTRUCT_RKBOOT_ENTRY)(m_BootData+dwOffset+(ucSize*ucIndex)); + FILE *file=NULL; + file = fopen(fileName.c_str(),"wb+"); + if ( !file ) + { + return false; + } + fwrite(m_BootData+pEntry->dwDataOffset,1,pEntry->dwDataSize,file); + fclose(file); + return true; +} +bool CRKBoot::GetEntryProperty(ENUM_RKBOOTENTRY type,UCHAR ucIndex,DWORD &dwSize,DWORD &dwDelay,char *pName) +{ + DWORD dwOffset; + UCHAR ucCount,ucSize; + switch ( type ) + { + case ENTRY471: + dwOffset = m_471Offset; + ucCount = m_471Count; + ucSize = m_471Size; + break; + case ENTRY472: + dwOffset = m_472Offset; + ucCount = m_472Count; + ucSize = m_472Size; + break; + case ENTRYLOADER: + dwOffset = m_loaderOffset; + ucCount = m_loaderCount; + ucSize = m_loaderSize;//Loader长度生成时已经512对齐 + break; + default: + return false; + } + if (ucIndex >= ucCount) + { + return false; + } + PSTRUCT_RKBOOT_ENTRY pEntry; + pEntry = (PSTRUCT_RKBOOT_ENTRY)(m_BootData+dwOffset+(ucSize*ucIndex)); + dwDelay = pEntry->dwDataDelay; + dwSize = pEntry->dwDataSize; + if (pName) + { + WCHAR_To_char(pEntry->szName,pName,20); + } + return true; +} +bool CRKBoot::GetEntryData(ENUM_RKBOOTENTRY type,UCHAR ucIndex,PBYTE lpData) +{ + DWORD dwOffset; + UCHAR ucCount,ucSize; + switch ( type ) + { + case ENTRY471: + dwOffset = m_471Offset; + ucCount = m_471Count; + ucSize = m_471Size; + break; + case ENTRY472: + dwOffset = m_472Offset; + ucCount = m_472Count; + ucSize = m_472Size; + break; + case ENTRYLOADER: + dwOffset = m_loaderOffset; + ucCount = m_loaderCount; + ucSize = m_loaderSize; + break; + default: + return false; + } + if (ucIndex >= ucCount) + { + return false; + } + PSTRUCT_RKBOOT_ENTRY pEntry; + pEntry = (PSTRUCT_RKBOOT_ENTRY)(m_BootData+dwOffset+(ucSize*ucIndex)); + memcpy(lpData,m_BootData+pEntry->dwDataOffset,pEntry->dwDataSize); + return true; +} +char CRKBoot::GetIndexByName(ENUM_RKBOOTENTRY type,char *pName) +{ + DWORD dwOffset; + UCHAR ucCount,ucSize; + switch ( type ) + { + case ENTRY471: + dwOffset = m_471Offset; + ucCount = m_471Count; + ucSize = m_471Size; + break; + case ENTRY472: + dwOffset = m_472Offset; + ucCount = m_472Count; + ucSize = m_472Size; + break; + case ENTRYLOADER: + dwOffset = m_loaderOffset; + ucCount = m_loaderCount; + ucSize = m_loaderSize; + break; + default: + return -1; + } + + for (UCHAR i=0;iszName,szName,20); + + if (strcasecmp(pName,szName)==0) + { + return i; + } + } + return -1; +} +CRKBoot::~CRKBoot() +{ + if (m_BootData!=NULL) + { + delete []m_BootData; + } +} + +CRKBoot::CRKBoot(PBYTE lpBootData,DWORD dwBootSize,bool &bCheck) +{ + Rc4DisableFlag.setContainer(this); + Rc4DisableFlag.getter(&CRKBoot::GetRc4DisableFlag); + SignFlag.setContainer(this); + SignFlag.getter(&CRKBoot::GetSignFlag); + Version.setContainer(this); + Version.getter(&CRKBoot::GetVersion); + MergeVersion.setContainer(this); + MergeVersion.getter(&CRKBoot::GetMergeVersion); + ReleaseTime.setContainer(this); + ReleaseTime.getter(&CRKBoot::GetReleaseTime); + SupportDevice.setContainer(this); + SupportDevice.getter(&CRKBoot::GetSupportDevice); + Entry471Count.setContainer(this); + Entry471Count.getter(&CRKBoot::GetEntry471Count); + Entry472Count.setContainer(this); + Entry472Count.getter(&CRKBoot::GetEntry472Count); + EntryLoaderCount.setContainer(this); + EntryLoaderCount.getter(&CRKBoot::GetEntryLoaderCount); + bCheck = true; + if (lpBootData!=NULL) + { + m_BootData=lpBootData; + m_BootSize=dwBootSize; + bCheck=CrcCheck(); + if (!bCheck) + { + return; + } + PSTRUCT_RKBOOT_HEAD pBootHead; + pBootHead = (PSTRUCT_RKBOOT_HEAD)(m_BootData); + if ( pBootHead->uiTag!=0x544F4F42) + { + bCheck=false; + return; + } + if (pBootHead->ucRc4Flag) + { + m_bRc4Disable = true; + } + else + m_bRc4Disable = false; + if (pBootHead->ucSignFlag=='S') + { + m_bSignFlag = true; + } + else + m_bSignFlag = false; + m_version = pBootHead->dwVersion; + m_mergeVersion = pBootHead->dwMergeVersion; + m_BootHeadSize = pBootHead->usSize; + m_releaseTime.usYear = pBootHead->stReleaseTime.usYear; + m_releaseTime.ucMonth = pBootHead->stReleaseTime.ucMonth; + m_releaseTime.ucDay = pBootHead->stReleaseTime.ucDay; + m_releaseTime.ucHour = pBootHead->stReleaseTime.ucHour; + m_releaseTime.ucMinute = pBootHead->stReleaseTime.ucMinute; + m_releaseTime.ucSecond = pBootHead->stReleaseTime.ucSecond; + m_supportDevice = pBootHead->emSupportChip; + + m_471Offset = pBootHead->dw471EntryOffset; + m_471Count = pBootHead->uc471EntryCount; + m_471Size = pBootHead->uc471EntrySize; + + m_472Offset = pBootHead->dw472EntryOffset; + m_472Count = pBootHead->uc472EntryCount; + m_472Size = pBootHead->uc472EntrySize; + + m_loaderOffset = pBootHead->dwLoaderEntryOffset; + m_loaderCount = pBootHead->ucLoaderEntryCount; + m_loaderSize = pBootHead->ucLoaderEntrySize; + + memcpy(m_crc,m_BootData+(m_BootSize-4),4); + } + else + { + bCheck = false; + m_BootData=NULL; + } +} +void CRKBoot::WCHAR_To_wchar(WCHAR *src,wchar_t *dst,int len) +{ + int i; + memset(dst,0,len*sizeof(wchar_t)); + for (i=0;i Rc4DisableFlag; + bool GetSignFlag(); + property SignFlag; + UINT GetVersion(); + property Version; + UINT GetMergeVersion(); + property MergeVersion; + STRUCT_RKTIME GetReleaseTime(); + property ReleaseTime; + ENUM_RKDEVICE_TYPE GetSupportDevice(); + property SupportDevice; + unsigned char GetEntry471Count(); + property Entry471Count; + unsigned char GetEntry472Count(); + property Entry472Count; + unsigned char GetEntryLoaderCount(); + property EntryLoaderCount; + bool CrcCheck(); + bool SaveEntryFile(ENUM_RKBOOTENTRY type, UCHAR ucIndex, string fileName); + bool GetEntryProperty(ENUM_RKBOOTENTRY type, UCHAR ucIndex, DWORD &dwSize, DWORD &dwDelay, char *pName = NULL); + char GetIndexByName(ENUM_RKBOOTENTRY type, char *pName); + bool GetEntryData(ENUM_RKBOOTENTRY type, UCHAR ucIndex, PBYTE lpData); + CRKBoot(PBYTE lpBootData, DWORD dwBootSize, bool &bCheck); + ~CRKBoot(); +protected: +private: + bool m_bRc4Disable; + bool m_bSignFlag; + DWORD m_version; + DWORD m_mergeVersion; + STRUCT_RKTIME m_releaseTime; + ENUM_RKDEVICE_TYPE m_supportDevice; + DWORD m_471Offset; + UCHAR m_471Size; + UCHAR m_471Count; + DWORD m_472Offset; + UCHAR m_472Size; + UCHAR m_472Count; + DWORD m_loaderOffset; + UCHAR m_loaderSize; + UCHAR m_loaderCount; + BYTE m_crc[4]; + PBYTE m_BootData; + DWORD m_BootSize; + USHORT m_BootHeadSize; + void WCHAR_To_wchar(WCHAR *src, wchar_t *dst, int len); + void WCHAR_To_char(WCHAR *src, char *dst, int len); +}; + +#endif \ No newline at end of file diff --git a/RKComm.cpp b/RKComm.cpp new file mode 100644 index 0000000..f5fd998 --- /dev/null +++ b/RKComm.cpp @@ -0,0 +1,710 @@ +/* + * (C) Copyright 2017 Fuzhou Rockchip Electronics Co., Ltd + * Seth Liu 2017.03.01 + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "RKComm.h" +#include "RKLog.h" +#include "Endian.h" +extern unsigned short CRC_CCITT(unsigned char* p, UINT CalculateNumber); +CRKComm::CRKComm(CRKLog *pLog) +{ + memset(&m_deviceDesc,0,sizeof(STRUCT_RKDEVICE_DESC)); + m_log = pLog; +} +CRKComm::~CRKComm() +{ +} + +CRKUsbComm::CRKUsbComm(STRUCT_RKDEVICE_DESC devDesc, CRKLog *pLog, bool &bRet):CRKComm(pLog) +{ + bRet = InitializeUsb(devDesc); +} +CRKUsbComm::~CRKUsbComm() +{ + UninitializeUsb(); +} + +bool CRKUsbComm::InitializeUsb(STRUCT_RKDEVICE_DESC devDesc) +{ + m_pUsbHandle = NULL; + m_pipeBulkIn = m_pipeBulkOut = 0; + m_interfaceNum = -1; + if (!devDesc.pUsbHandle) { + return false; + } + memcpy(&m_deviceDesc, &devDesc, sizeof(STRUCT_RKDEVICE_DESC)); + int iRet; + iRet = libusb_open((libusb_device *)devDesc.pUsbHandle, (libusb_device_handle **)&m_pUsbHandle); + if (iRet!=0) { + if (m_log) { + m_log->Record("Error:InitializeUsb-->open device failed,err=%d", iRet); + } + return false; + } + struct libusb_config_descriptor *pConfigDesc=NULL; + iRet = libusb_get_active_config_descriptor((libusb_device *)devDesc.pUsbHandle, &pConfigDesc); + if (iRet!=0) { + if (m_log) { + m_log->Record("Error:InitializeUsb-->get device config descriptor failed, err=%d", iRet); + } + return false; + } + int i, j, k; + const struct libusb_interface *pInterface; + const struct libusb_endpoint_descriptor *pEndpointDesc; + const struct libusb_interface_descriptor *pInterfaceDesc; + for(i = 0; i < pConfigDesc->bNumInterfaces; i++) { + pInterface = pConfigDesc->interface + i; + for(j = 0; j < pInterface->num_altsetting; j++) { + pInterfaceDesc = pInterface->altsetting+j; + if (m_deviceDesc.emUsbType == RKUSB_MSC) { + if( (pInterfaceDesc->bInterfaceClass != 8) || (pInterfaceDesc->bInterfaceSubClass != 6) || (pInterfaceDesc->bInterfaceProtocol != 0x50)) + continue; + } + else + { + if( (pInterfaceDesc->bInterfaceClass != 0xff) || (pInterfaceDesc->bInterfaceSubClass != 6) || (pInterfaceDesc->bInterfaceProtocol != 5)) + continue; + } + for(k = 0; k < pInterfaceDesc->bNumEndpoints; k++) { + pEndpointDesc = pInterfaceDesc->endpoint+k; + if ((pEndpointDesc->bEndpointAddress & 0x80) == 0) { + if (m_pipeBulkOut == 0) + m_pipeBulkOut = pEndpointDesc->bEndpointAddress; + } + else { + if (m_pipeBulkIn == 0) + m_pipeBulkIn = pEndpointDesc->bEndpointAddress; + } + if ((m_pipeBulkIn != 0) && (m_pipeBulkOut != 0)) {//found it + m_interfaceNum = i; + libusb_free_config_descriptor(pConfigDesc); + iRet = libusb_claim_interface((libusb_device_handle *)m_pUsbHandle, m_interfaceNum); + if (iRet != 0) { + if (m_log) { + m_log->Record("Error:libusb_claim_interface failed,err=%d", iRet); + } + return false; + } + return true; + } + } + } + } + libusb_free_config_descriptor(pConfigDesc); + return false; +} +void CRKUsbComm::UninitializeUsb() +{ + if (m_pUsbHandle) { + libusb_close((libusb_device_handle *)m_pUsbHandle); + m_pUsbHandle = NULL; + } + memset(&m_deviceDesc, 0, sizeof(STRUCT_RKDEVICE_DESC)); + m_pipeBulkIn = m_pipeBulkOut = 0; + return ; +} +bool CRKUsbComm::Reset_Usb_Config(STRUCT_RKDEVICE_DESC devDesc) +{ + bool bRet; + UninitializeUsb(); + bRet = InitializeUsb(devDesc); + return bRet; +} +bool CRKUsbComm::Reset_Usb_Device() +{ + int iRet = -1; + if (m_pUsbHandle) { + iRet=libusb_reset_device((libusb_device_handle *)m_pUsbHandle); + } + return (iRet == 0) ? true : false; +} + +bool CRKUsbComm::RKU_Read(BYTE* lpBuffer, DWORD dwSize) +{ + int iRet; + int nRead; + iRet = libusb_bulk_transfer((libusb_device_handle *)m_pUsbHandle, m_pipeBulkIn, lpBuffer, dwSize, &nRead, CMD_TIMEOUT); + if (iRet!=0) { + if (m_log) { + m_log->Record("Error:RKU_Read failed,err=%d", iRet); + } + return false; + } + if (nRead != (int)dwSize) { + if (m_log) { + m_log->Record("Error:RKU_Read failed, size=%d, read=%d", dwSize, nRead); + } + return false; + } + return true; +} + +bool CRKUsbComm::RKU_Write(BYTE* lpBuffer, DWORD dwSize) +{ + int iRet; + int nWrite; + iRet = libusb_bulk_transfer((libusb_device_handle *)m_pUsbHandle, m_pipeBulkOut, lpBuffer, dwSize, &nWrite, CMD_TIMEOUT); + if (iRet != 0) { + if (m_log) { + m_log->Record("Error:RKU_Write failed, err=%d", iRet); + } + return false; + } + if (nWrite != (int)dwSize) { + if (m_log) { + m_log->Record("Error:RKU_Write failed, size=%d, read=%d", dwSize, nWrite); + } + return false; + } + return true; +} +int CRKUsbComm::RandomInteger(int low, int high) +{ + int k; + double d; + + d = (double)rand() / ((double)RAND_MAX + 1); + k = (int)(d * (high - low + 1)); + return (low + k); +} +DWORD CRKUsbComm::MakeCBWTag() +{ + DWORD tag = 0; + int i = 0; + + for(i=0; i<4; i++){ + tag <<= 8; + tag += RandomInteger(0, 0xFF); + } + return tag; +} +void CRKUsbComm::InitializeCBW(PCBW pCBW, USB_OPERATION_CODE code) +{ + memset(pCBW,0, sizeof(CBW)); + + pCBW->dwCBWSignature = CBW_SIGN; + pCBW->dwCBWTag = MakeCBWTag(); + pCBW->cbwcb.ucOperCode = code; + + switch(code) { + case TEST_UNIT_READY: /* Test Unit Ready : 0 */ + case READ_FLASH_ID: /* Read Flash ID : 1 */ + case READ_FLASH_INFO: + case READ_CHIP_INFO: + case READ_EFUSE: + pCBW->ucCBWFlags= DIRECTION_IN; + pCBW->ucCBWCBLength = 0x06; + break; + case DEVICE_RESET: /* Reset Device : 0xff */ + case ERASE_SYSTEMDISK: + case SET_RESET_FLAG: + pCBW->ucCBWFlags = DIRECTION_OUT; + pCBW->ucCBWCBLength = 0x06; + break; + case TEST_BAD_BLOCK: /* Test Bad Block : 3 */ + case READ_SECTOR: /* Read Pages : 4 */ + case READ_LBA: /* Read Pages : 4 */ + case READ_SDRAM: /* Write Pages : 15 */ + case READ_SPI_FLASH: + case READ_NEW_EFUSE: + pCBW->ucCBWFlags = DIRECTION_IN; + pCBW->ucCBWCBLength = 0x0a; + break; + case WRITE_SECTOR: /* Write Pages : 5 */ + case WRITE_LBA: /* Write Pages : 15 */ + case WRITE_SDRAM: /* Write Pages : 15 */ + case EXECUTE_SDRAM: + case ERASE_NORMAL: /* Erase Blocks : 6 */ + case ERASE_FORCE: /* Read Spare : 11 */ + case WRITE_EFUSE: + case WRITE_SPI_FLASH: + case WRITE_NEW_EFUSE: + pCBW->ucCBWFlags = DIRECTION_OUT; + pCBW->ucCBWCBLength = 0x0a; + break; + default: + break; + } +} + + +bool CRKUsbComm::RKU_ClearBuffer(CBW& cbw, CSW& csw) +{ + DWORD dwReadBytes=0; + DWORD dwTotalRead=0; + int iTryCount; + iTryCount = 3; + do { + dwReadBytes = RKU_Read_EX((BYTE*)&csw, sizeof(CSW) ); + + if (UFI_CHECK_SIGN(cbw,csw)) + { + return true; + } + if (dwReadBytes != sizeof(CSW)) + { + iTryCount--; + sleep(3); + } + dwTotalRead += dwReadBytes; + if (dwTotalRead >= MAX_CLEAR_LEN) + { + break; + } + }while ( iTryCount > 0 ); + return false; +} + +DWORD CRKUsbComm::RKU_Read_EX(BYTE* lpBuffer, DWORD dwSize) +{ + int iRet; + int nRead; + iRet = libusb_bulk_transfer((libusb_device_handle *)m_pUsbHandle, m_pipeBulkIn, lpBuffer, dwSize, &nRead, 5000); + if (iRet != 0) { + if (m_log) { + m_log->Record("Error:RKU_Read_EX failed, err=%d", iRet); + } + return 0; + } + return nRead; +} + +int CRKUsbComm::RKU_EraseBlock(BYTE ucFlashCS, DWORD dwPos, DWORD dwCount, BYTE ucEraseType) +{ + if ((m_deviceDesc.emUsbType != RKUSB_LOADER) && (m_deviceDesc.emUsbType != RKUSB_MASKROM)) { + if (m_log) { + m_log->Record("Error:RKU_EraseBlock failed,device not support"); + } + return ERR_DEVICE_NOT_SUPPORT; + } + CBW cbw; + CSW csw; + USHORT usCount; + usCount = dwCount; + if(dwCount > MAX_ERASE_BLOCKS) + return ERR_CROSS_BORDER; + + InitializeCBW(&cbw, (USB_OPERATION_CODE)ucEraseType); + cbw.ucCBWLUN = ucFlashCS; + cbw.cbwcb.dwAddress = EndianU32_LtoB(dwPos); + cbw.cbwcb.usLength = EndianU16_LtoB(usCount); + + if(!RKU_Write((BYTE *)&cbw, sizeof(CBW))) + { + return ERR_DEVICE_WRITE_FAILED; + } + + if(!RKU_Read((BYTE *)&csw, sizeof(CSW))) + { + return ERR_DEVICE_READ_FAILED; + } + + if( !UFI_CHECK_SIGN(cbw, csw) ) + return ERR_CMD_NOTMATCH; + + if(csw.ucCSWStatus == 1) + return ERR_FOUND_BAD_BLOCK; + + return ERR_SUCCESS; +} +int CRKUsbComm::RKU_ReadChipInfo(BYTE* lpBuffer) +{ + if ((m_deviceDesc.emUsbType != RKUSB_LOADER) && (m_deviceDesc.emUsbType != RKUSB_MASKROM)) { + if (m_log) { + m_log->Record("Error:RKU_ReadChipInfo failed,device not support"); + } + return ERR_DEVICE_NOT_SUPPORT; + } + + CBW cbw; + CSW csw; + + InitializeCBW(&cbw, READ_CHIP_INFO); + + if(!RKU_Write((BYTE *)&cbw, sizeof(CBW))) + { + return ERR_DEVICE_WRITE_FAILED; + } + + if(!RKU_Read(lpBuffer, 16)) + { + return ERR_DEVICE_READ_FAILED; + } + + if(!RKU_Read( (BYTE *)&csw, sizeof(CSW))) + { + return ERR_DEVICE_READ_FAILED; + } + + if( !UFI_CHECK_SIGN(cbw, csw) ) + return ERR_CMD_NOTMATCH; + + return ERR_SUCCESS; +} +int CRKUsbComm::RKU_ReadFlashID(BYTE* lpBuffer) +{ + if ((m_deviceDesc.emUsbType != RKUSB_LOADER) && (m_deviceDesc.emUsbType != RKUSB_MASKROM)) { + if (m_log) { + m_log->Record("Error:RKU_ReadChipInfo failed,device not support"); + } + return ERR_DEVICE_NOT_SUPPORT; + } + + CBW cbw; + CSW csw; + + InitializeCBW(&cbw, READ_FLASH_ID); + + if(!RKU_Write((BYTE *)&cbw, sizeof(CBW))) + { + return ERR_DEVICE_WRITE_FAILED; + } + + if(!RKU_Read(lpBuffer, 5)) + { + return ERR_DEVICE_READ_FAILED; + } + + if(!RKU_Read( (BYTE *)&csw, sizeof(CSW))) + { + return ERR_DEVICE_READ_FAILED; + } + + if( !UFI_CHECK_SIGN(cbw, csw) ) + return ERR_CMD_NOTMATCH; + + return ERR_SUCCESS; +} +int CRKUsbComm::RKU_ReadFlashInfo(BYTE* lpBuffer, UINT *puiRead) +{ + if ((m_deviceDesc.emUsbType != RKUSB_LOADER) && (m_deviceDesc.emUsbType != RKUSB_MASKROM)) { + if (m_log) { + m_log->Record("Error:RKU_ReadFlashInfo failed,device not support"); + } + return ERR_DEVICE_NOT_SUPPORT; + } + CBW cbw; + CSW csw; + + InitializeCBW(&cbw, READ_FLASH_INFO); + + if(!RKU_Write((BYTE *)&cbw, sizeof(CBW))) + { + return ERR_DEVICE_WRITE_FAILED; + } + + DWORD dwRead; + dwRead = RKU_Read_EX(lpBuffer, 512); + if ((dwRead < 11) || (dwRead > 512)) + { + return ERR_DEVICE_READ_FAILED; + } + if (puiRead) + { + *puiRead = dwRead; + } +/* + if(!RKU_Read(hDev, lpBuffer, 11)) + { + return ERR_DEVICE_READ_FAILED; + } +*/ + if(!RKU_Read((BYTE *)&csw, sizeof(CSW))) + { + return ERR_DEVICE_READ_FAILED; + } + + if( !UFI_CHECK_SIGN(cbw, csw) ) + return ERR_CMD_NOTMATCH; + + return ERR_SUCCESS; +} +int CRKUsbComm::RKU_ReadLBA(DWORD dwPos, DWORD dwCount, BYTE* lpBuffer, BYTE bySubCode) +{ + if ((m_deviceDesc.emUsbType != RKUSB_LOADER) && (m_deviceDesc.emUsbType != RKUSB_MASKROM)) { + if (m_log) { + m_log->Record("Error:RKU_ReadLBA failed,device not support"); + } + return ERR_DEVICE_NOT_SUPPORT; + } + CBW cbw; + CSW csw; + USHORT wSectorSize; + USHORT usSectorLen; + wSectorSize = 512; + usSectorLen=dwCount; + + InitializeCBW(&cbw, READ_LBA); + cbw.cbwcb.dwAddress = EndianU32_LtoB(dwPos); + cbw.cbwcb.usLength = EndianU16_LtoB(usSectorLen); + cbw.cbwcb.ucReserved = bySubCode; + + if(!RKU_Write((BYTE *)&cbw, sizeof(CBW))) + { + return ERR_DEVICE_WRITE_FAILED; + } + DWORD dwTotal; + dwTotal = usSectorLen * wSectorSize; + + if(!RKU_Read(lpBuffer, dwTotal)) + { + return ERR_DEVICE_READ_FAILED; + } + + if(!RKU_Read((BYTE*)&csw, sizeof(CSW))) + { + return ERR_DEVICE_READ_FAILED; + } + + if( !UFI_CHECK_SIGN(cbw, csw) ) + return ERR_CMD_NOTMATCH; + + if(csw.ucCSWStatus == 1) + return ERR_FAILED; + + return ERR_SUCCESS; +} + +int CRKUsbComm::RKU_ResetDevice(BYTE bySubCode) +{ + if ((m_deviceDesc.emUsbType != RKUSB_LOADER) && (m_deviceDesc.emUsbType != RKUSB_MASKROM)) { + if (m_log) { + m_log->Record("Error:RKU_ResetDevice failed,device not support"); + } + return ERR_DEVICE_NOT_SUPPORT; + } + + CBW cbw; + CSW csw; + + InitializeCBW(&cbw, DEVICE_RESET); + cbw.cbwcb.ucReserved = bySubCode; + + if(!RKU_Write((BYTE *)&cbw, sizeof(CBW))) + { + return ERR_DEVICE_WRITE_FAILED; + } + + if(!RKU_Read((BYTE *)&csw, sizeof(CSW))) + { + return ERR_DEVICE_READ_FAILED; + } + + if( !UFI_CHECK_SIGN(cbw, csw) ) { + bool bRet; + bRet = RKU_ClearBuffer(cbw, csw); + if (!bRet) { + return ERR_CMD_NOTMATCH; + } + } + + if(csw.ucCSWStatus == 1) + return ERR_FAILED; + + return ERR_SUCCESS; +} + +int CRKUsbComm::RKU_TestDeviceReady(DWORD *dwTotal, DWORD *dwCurrent, BYTE bySubCode) +{ + if ((m_deviceDesc.emUsbType != RKUSB_LOADER) && (m_deviceDesc.emUsbType != RKUSB_MASKROM)) { + if (m_log) { + m_log->Record("Error:RKU_TestDeviceReady failed,device not support"); + } + return ERR_DEVICE_NOT_SUPPORT; + } + CBW cbw; + CSW csw; + + InitializeCBW(&cbw, TEST_UNIT_READY); + + cbw.cbwcb.ucReserved = bySubCode; + if(!RKU_Write( (BYTE *)&cbw, sizeof(CBW))) { + return ERR_DEVICE_WRITE_FAILED; + } + + if(!RKU_Read( (BYTE *)&csw, sizeof(CSW))) { + return ERR_DEVICE_READ_FAILED; + } + + if( !UFI_CHECK_SIGN(cbw, csw) ) { + bool bRet; + bRet = RKU_ClearBuffer(cbw ,csw); + if (!bRet) { + return ERR_CMD_NOTMATCH; + } + } + + if ((dwTotal!=NULL)&&(dwCurrent!=NULL)) { + *dwCurrent = (csw.dwCBWDataResidue >>16); + *dwTotal = (csw.dwCBWDataResidue & 0x0000FFFF); + + *dwTotal = EndianU16_BtoL(*dwTotal); + *dwCurrent = EndianU16_BtoL(*dwCurrent); + } + if(csw.ucCSWStatus == 1) { + return ERR_DEVICE_UNREADY; + } + + return ERR_DEVICE_READY; +} +int CRKUsbComm::RKU_WriteLBA(DWORD dwPos, DWORD dwCount, BYTE* lpBuffer, BYTE bySubCode) +{ + if ((m_deviceDesc.emUsbType != RKUSB_LOADER) && (m_deviceDesc.emUsbType != RKUSB_MASKROM)) { + if (m_log) { + m_log->Record("Error:RKU_WriteLBA failed,device not support"); + } + return ERR_DEVICE_NOT_SUPPORT; + } + CBW cbw; + CSW csw; + USHORT wSectorSize; + USHORT usCount; + wSectorSize = 512; + usCount = dwCount; + DWORD dwTotal = usCount * wSectorSize; + + InitializeCBW(&cbw, WRITE_LBA); + cbw.cbwcb.dwAddress = EndianU32_LtoB(dwPos); + cbw.cbwcb.usLength = EndianU16_LtoB(usCount); + cbw.cbwcb.ucReserved = bySubCode; + if(!RKU_Write( (BYTE *)&cbw, sizeof(CBW))) { + return ERR_DEVICE_WRITE_FAILED; + } + + if(!RKU_Write( lpBuffer, dwTotal)) { + return ERR_DEVICE_WRITE_FAILED; + } + + if(!RKU_Read( (BYTE *)&csw, sizeof(CSW))) { + return ERR_DEVICE_READ_FAILED; + } + + if( !UFI_CHECK_SIGN(cbw, csw) ) + return ERR_CMD_NOTMATCH; + + if(csw.ucCSWStatus == 1) + return ERR_FAILED; + + return ERR_SUCCESS; +} +int CRKUsbComm::RKU_WriteSector(DWORD dwPos, DWORD dwCount, BYTE *lpBuffer) +{ + if ((m_deviceDesc.emUsbType != RKUSB_LOADER) && (m_deviceDesc.emUsbType != RKUSB_MASKROM)) { + if (m_log) { + m_log->Record("Error:RKU_WriteSector failed,device not support"); + } + return ERR_DEVICE_NOT_SUPPORT; + } + CBW cbw; + CSW csw; + USHORT wSectorSize; + USHORT usCount; + usCount=dwCount; + if(usCount > 32) + return ERR_CROSS_BORDER; + + wSectorSize = 528; + InitializeCBW(&cbw, WRITE_SECTOR); + cbw.cbwcb.dwAddress = EndianU32_LtoB(dwPos); + cbw.cbwcb.usLength = EndianU16_LtoB(usCount); + + if(!RKU_Write( (BYTE *)&cbw, sizeof(CBW))) { + return ERR_DEVICE_WRITE_FAILED; + } + + if(!RKU_Write( lpBuffer, usCount * wSectorSize)) { + return ERR_DEVICE_WRITE_FAILED; + } + + if(!RKU_Read( (BYTE *)&csw, sizeof(CSW))) { + return ERR_DEVICE_READ_FAILED; + } + + if( !UFI_CHECK_SIGN(cbw, csw) ) + return ERR_CMD_NOTMATCH; + + if(csw.ucCSWStatus == 1) + return ERR_FAILED; + + return ERR_SUCCESS; +} + + +int CRKUsbComm::RKU_DeviceRequest(DWORD dwRequest, BYTE *lpBuffer, DWORD dwDataSize) +{ + if (m_deviceDesc.emUsbType != RKUSB_MASKROM) { + if (m_log) { + m_log->Record("Error:RKU_DeviceRequest failed,device not support"); + } + return ERR_DEVICE_NOT_SUPPORT; + } + if ((dwRequest != 0x0471) && (dwRequest != 0x0472)) { + if (m_log) { + m_log->Record("Error:RKU_DeviceRequest failed,request not support"); + } + return ERR_REQUEST_NOT_SUPPORT; + } + + bool bSendPendPacket = false; + USHORT crcValue = 0xffff; + BYTE *pData = NULL; + pData = new BYTE[dwDataSize + 5]; + memset(pData, 0, dwDataSize + 5); + memcpy(pData, lpBuffer, dwDataSize); + + switch(dwDataSize % 4096) { + case 4095: + ++dwDataSize; + break; + case 4094: + bSendPendPacket = true; + break; + case 0: + default: + break; + } + + crcValue = CRC_CCITT(pData, dwDataSize); + pData[dwDataSize] = (crcValue & 0xff00) >> 8; + pData[dwDataSize+1] = crcValue & 0x00ff; + dwDataSize += 2; + + UINT nSendBytes = 0; + DWORD dwTotalSended = 0; + int iRet; + + while(dwTotalSended < dwDataSize) { + nSendBytes = ( (dwDataSize - dwTotalSended) > 4096) ? 4096 : (dwDataSize - dwTotalSended); + iRet = libusb_control_transfer((libusb_device_handle *)m_pUsbHandle, 0x40, 0xC, 0, dwRequest, pData + dwTotalSended, nSendBytes, CMD_TIMEOUT); + if (iRet != (int)nSendBytes) { + if (m_log) { + m_log->Record("Error:RKU_DeviceRequest-->DeviceRequest vendor=0x%x failed, err=%d",dwRequest, iRet); + } + delete []pData; + return ERR_REQUEST_FAIL; + } + dwTotalSended += nSendBytes; + } + + if(bSendPendPacket) { + BYTE ucFillByte = 0; + iRet = libusb_control_transfer((libusb_device_handle *)m_pUsbHandle, 0x40, 0xC, 0, dwRequest, &ucFillByte, 1, CMD_TIMEOUT); + if (iRet != 0) { + if (m_log) { + m_log->Record("Error:RKU_DeviceRequest-->DeviceRequest vendor=0x%x failed, err=%d", dwRequest, iRet); + } + delete []pData; + return ERR_REQUEST_FAIL; + } + } + + delete []pData; + + return ERR_SUCCESS; +} + + diff --git a/RKComm.h b/RKComm.h new file mode 100644 index 0000000..47d1379 --- /dev/null +++ b/RKComm.h @@ -0,0 +1,170 @@ +#ifndef RKCOMM_HEADER +#define RKCOMM_HEADER +#include "DefineHeader.h" +typedef enum { + USB_BULK_READ = 0, + USB_BULK_WRITE, + USB_CONTROL, +} USB_ACCESS_TYPE; +typedef enum { + TU_NONE_SUBCODE = 0, + TU_ERASESYSTEM_SUBCODE = 0xFE, + TU_LOWERFORMAT_SUBCODE = 0xFD, + TU_ERASEUSERDATA_SUBCODE = 0xFB, + TU_GETUSERSECTOR_SUBCODE = 0xF9 +} TESTUNIT_SUBCODE; +typedef enum{ + RST_NONE_SUBCODE = 0, + RST_RESETMSC_SUBCODE, + RST_POWEROFF_SUBCODE, + RST_RESETMASKROM_SUBCODE, + RST_DISCONNECTRESET_SUBCODE +} RESET_SUBCODE; +typedef enum{ + RWMETHOD_IMAGE = 0, + RWMETHOD_LBA +} RW_SUBCODE; + +typedef enum { + TEST_UNIT_READY = 0, + READ_FLASH_ID = 0x01, + TEST_BAD_BLOCK = 0x03, + READ_SECTOR = 0x04, + WRITE_SECTOR = 0x05, + ERASE_NORMAL = 0x06, + ERASE_FORCE = 0x0B, + READ_LBA = 0x14, + WRITE_LBA = 0x15, + ERASE_SYSTEMDISK = 0x16, + READ_SDRAM = 0x17, + WRITE_SDRAM = 0x18, + EXECUTE_SDRAM = 0x19, + READ_FLASH_INFO = 0x1A, + READ_CHIP_INFO = 0x1B, + SET_RESET_FLAG = 0x1E, + WRITE_EFUSE = 0x1F, + READ_EFUSE = 0x20, + READ_SPI_FLASH = 0x21, + WRITE_SPI_FLASH = 0x22, + WRITE_NEW_EFUSE = 0x23, + READ_NEW_EFUSE = 0x24, + DEVICE_RESET = 0xFF +} USB_OPERATION_CODE; + +#pragma pack(1) + +typedef struct { + BYTE ucOperCode; + BYTE ucReserved; + DWORD dwAddress; + BYTE ucReserved2; + USHORT usLength; + BYTE ucReserved3[7]; +} CBWCB, *PCBWCB; + +typedef struct { + DWORD dwCBWSignature; + DWORD dwCBWTag; + DWORD dwCBWTransferLength; + BYTE ucCBWFlags; + BYTE ucCBWLUN; + BYTE ucCBWCBLength; + CBWCB cbwcb; +} CBW, *PCBW; + +typedef struct { + DWORD dwCSWSignature; + DWORD dwCSWTag; + DWORD dwCBWDataResidue; + BYTE ucCSWStatus; +} CSW, *PCSW; + +#pragma pack() +#define CMD_TIMEOUT 0 +#define CBW_SIGN 0x43425355 /* "USBC" */ +#define CSW_SIGN 0x53425355 /* "USBS" */ + +#define DIRECTION_OUT 0x00 +#define DIRECTION_IN 0x80 +#define MAX_TEST_BLOCKS 512 +#define MAX_ERASE_BLOCKS 128 +#define MAX_CLEAR_LEN 16*1024 + +#ifndef ERR_SUCCESS +#define ERR_SUCCESS 0 +#endif +#define ERR_DEVICE_READY 0 +#define ERR_DEVICE_OPEN_FAILED -1 +#define ERR_CSW_OPEN_FAILED -2 +#define ERR_DEVICE_WRITE_FAILED -3 +#define ERR_DEVICE_READ_FAILED -4 +#define ERR_CMD_NOTMATCH -5 +#define ERR_DEVICE_UNREADY -6 +#define ERR_FOUND_BAD_BLOCK -7 +#define ERR_FAILED -8 +#define ERR_CROSS_BORDER -9 +#define ERR_DEVICE_NOT_SUPPORT -10 +#define ERR_REQUEST_NOT_SUPPORT -11 +#define ERR_REQUEST_FAIL -12 +#define ERR_BUFFER_NOT_ENOUGH -13 +#define UFI_CHECK_SIGN(cbw, csw) ((CSW_SIGN == (csw).dwCSWSignature) && ((csw).dwCSWTag == (cbw).dwCBWTag)) + +class CRKLog; +class CRKComm +{ +public: + virtual int RKU_EraseBlock(BYTE ucFlashCS, DWORD dwPos, DWORD dwCount, BYTE ucEraseType) = 0; + virtual int RKU_ReadChipInfo(BYTE *lpBuffer) = 0; + virtual int RKU_ReadFlashID(BYTE *lpBuffer) = 0; + virtual int RKU_ReadFlashInfo(BYTE *lpBuffer, UINT *puiRead = NULL) = 0; + virtual int RKU_ReadLBA(DWORD dwPos, DWORD dwCount, BYTE *lpBuffer, BYTE bySubCode = RWMETHOD_IMAGE) = 0; + virtual int RKU_ResetDevice(BYTE bySubCode = RST_NONE_SUBCODE) = 0; + virtual int RKU_TestDeviceReady(DWORD *dwTotal = NULL, DWORD *dwCurrent = NULL, BYTE bySubCode = TU_NONE_SUBCODE) = 0; + virtual int RKU_WriteLBA(DWORD dwPos, DWORD dwCount, BYTE *lpBuffer, BYTE bySubCode = RWMETHOD_IMAGE) = 0; + virtual int RKU_WriteSector(DWORD dwPos, DWORD dwCount, BYTE *lpBuffer) = 0; + virtual int RKU_DeviceRequest(DWORD dwRequest, BYTE *lpBuffer, DWORD dwDataSize) = 0; + virtual bool Reset_Usb_Config(STRUCT_RKDEVICE_DESC devDesc) = 0; + virtual bool Reset_Usb_Device() = 0; + CRKComm(CRKLog *pLog); + virtual ~CRKComm(); +protected: + STRUCT_RKDEVICE_DESC m_deviceDesc; + CRKLog *m_log; +private: + virtual bool RKU_Write(BYTE *lpBuffer, DWORD dwSize) = 0; + virtual bool RKU_Read(BYTE *lpBuffer, DWORD dwSize) = 0; +}; +class CRKUsbComm:public CRKComm +{ +public: + virtual int RKU_EraseBlock(BYTE ucFlashCS, DWORD dwPos, DWORD dwCount, BYTE ucEraseType); + virtual int RKU_ReadChipInfo(BYTE *lpBuffer); + virtual int RKU_ReadFlashID(BYTE *lpBuffer); + virtual int RKU_ReadFlashInfo(BYTE *lpBuffer, UINT *puiRead = NULL); + virtual int RKU_ReadLBA(DWORD dwPos, DWORD dwCount, BYTE *lpBuffer, BYTE bySubCode = RWMETHOD_IMAGE); + virtual int RKU_ResetDevice(BYTE bySubCode = RST_NONE_SUBCODE); + virtual int RKU_TestDeviceReady(DWORD *dwTotal = NULL, DWORD *dwCurrent = NULL, BYTE bySubCode = TU_NONE_SUBCODE); + virtual int RKU_WriteLBA(DWORD dwPos, DWORD dwCount, BYTE *lpBuffer, BYTE bySubCode = RWMETHOD_IMAGE); + virtual int RKU_WriteSector(DWORD dwPos, DWORD dwCount, BYTE *lpBuffer); + virtual int RKU_DeviceRequest(DWORD dwRequest, BYTE *lpBuffer, DWORD dwDataSize); + CRKUsbComm(STRUCT_RKDEVICE_DESC devDesc, CRKLog *pLog, bool &bRet); + virtual ~CRKUsbComm(); + virtual bool Reset_Usb_Config(STRUCT_RKDEVICE_DESC devDesc); + virtual bool Reset_Usb_Device(); +private: + void *m_pUsbHandle; + unsigned char m_pipeBulkIn; + unsigned char m_pipeBulkOut; + int m_interfaceNum; + virtual bool RKU_Write(BYTE *lpBuffer, DWORD dwSize); + virtual bool RKU_Read(BYTE *lpBuffer, DWORD dwSize); + bool InitializeUsb(STRUCT_RKDEVICE_DESC devDesc); + void UninitializeUsb(); + bool RKU_ClearBuffer(CBW &cbw, CSW &csw); + DWORD RKU_Read_EX(BYTE *lpBuffer, DWORD dwSize); + void InitializeCBW(PCBW pCBW, USB_OPERATION_CODE code); + int RandomInteger(int low, int high); + DWORD MakeCBWTag(); +}; + +#endif \ No newline at end of file diff --git a/RKDevice.cpp b/RKDevice.cpp new file mode 100644 index 0000000..ac5e830 --- /dev/null +++ b/RKDevice.cpp @@ -0,0 +1,643 @@ +/* + * (C) Copyright 2017 Fuzhou Rockchip Electronics Co., Ltd + * Seth Liu 2017.03.01 + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "RKDevice.h" + +const char* szManufName[] = +{ + "SAMSUNG", + "TOSHIBA", + "HYNIX", + "INFINEON", + "MICRON", + "RENESAS", + "ST", + "INTEL" +}; + +void CRKDevice::SetVendorID(USHORT value) +{ + m_vid = value; +} +void CRKDevice::SetProductID(USHORT value) +{ + m_pid = value; +} +void CRKDevice::SetDeviceType(ENUM_RKDEVICE_TYPE value) +{ + m_device = value; +} +void CRKDevice::SetOsType(ENUM_OS_TYPE value) +{ + m_os = value; +} + +void CRKDevice::SetUsbType(ENUM_RKUSB_TYPE value) +{ + m_usb = value; +} +void CRKDevice::SetBcdUsb(USHORT value) +{ + m_bcdUsb = value; +} +void CRKDevice::SetLayerName(char *value) +{ + strcpy(m_layerName,value); +} +void CRKDevice::SetLocationID(DWORD value) +{ + m_locationID = value; +} + +void CRKDevice::SetCallBackPointer(ProgressPromptCB value) +{ + if (value) + { + m_callBackProc = value; + } +} +CRKLog* CRKDevice::GetLogObjectPointer() +{ + return m_pLog; +} + +CRKComm* CRKDevice::GetCommObjectPointer() +{ + return m_pComm; +} + +USHORT CRKDevice::GetVendorID() +{ + return m_vid; +} +USHORT CRKDevice::GetProductID() +{ + return m_pid; +} +ENUM_RKDEVICE_TYPE CRKDevice::GetDeviceType() +{ + return m_device; +} +ENUM_OS_TYPE CRKDevice::GetOsType() +{ + return m_os; +} + +ENUM_RKUSB_TYPE CRKDevice::GetUsbType() +{ + return m_usb; +} + +USHORT CRKDevice::GetBcdUsb() +{ + return m_bcdUsb; +} +DWORD CRKDevice::GetLocationID() +{ + return m_locationID; +} +char* CRKDevice::GetLayerName() +{ + return m_layerName; +} + +string CRKDevice::GetLayerString(DWORD dwLocationID) +{ + char szLocation[32] = "\0"; + sprintf(szLocation, "%d-%d", dwLocationID >> 8, dwLocationID & 0xff); + return szLocation; +} + +CRKDevice::CRKDevice(STRUCT_RKDEVICE_DESC &device) +{ + VendorID.setContainer(this); + VendorID.getter(&CRKDevice::GetVendorID); + VendorID.setter(&CRKDevice::SetVendorID); + + ProductID.setContainer(this); + ProductID.getter(&CRKDevice::GetProductID); + ProductID.setter(&CRKDevice::SetProductID); + + DeviceType.setContainer(this); + DeviceType.getter(&CRKDevice::GetDeviceType); + DeviceType.setter(&CRKDevice::SetDeviceType); + + UsbType.setContainer(this); + UsbType.getter(&CRKDevice::GetUsbType); + UsbType.setter(&CRKDevice::SetUsbType); + + LayerName.setContainer(this); + LayerName.getter(&CRKDevice::GetLayerName); + LayerName.setter(&CRKDevice::SetLayerName); + + BcdUsb.setContainer(this); + BcdUsb.getter(&CRKDevice::GetBcdUsb); + BcdUsb.setter(&CRKDevice::SetBcdUsb); + + LocationID.setContainer(this); + LocationID.getter(&CRKDevice::GetLocationID); + LocationID.setter(&CRKDevice::SetLocationID); + + OsType.setContainer(this); + OsType.getter(&CRKDevice::GetOsType); + OsType.setter(&CRKDevice::SetOsType); + + LogObjectPointer.setContainer(this); + LogObjectPointer.getter(&CRKDevice::GetLogObjectPointer); + + CommObjectPointer.setContainer(this); + CommObjectPointer.getter(&CRKDevice::GetCommObjectPointer); + + CallBackPointer.setContainer(this); + CallBackPointer.setter(&CRKDevice::SetCallBackPointer); + + m_vid = device.usVid; + m_pid = device.usPid; + m_usb = device.emUsbType; + m_device = device.emDeviceType; + m_bcdUsb = device.usbcdUsb; + m_locationID = device.uiLocationID; + strcpy(m_layerName, GetLayerString(m_locationID).c_str()); + + memset(m_flashInfo.blockState, 0, IDBLOCK_TOP); + m_flashInfo.usPhyBlokcPerIDB = 1; + m_flashInfo.uiSecNumPerIDB = 0; + m_callBackProc = NULL; + m_chipData = NULL; + m_pImage = NULL; + m_pLog = NULL; + m_pComm = NULL; + m_pFlashInfoData = NULL; + m_usFlashInfoDataLen = 0; + m_usFlashInfoDataOffset = 0; + m_bEmmc = false; +} +CRKDevice::~CRKDevice() +{ + if (m_pComm) { + delete m_pComm; + m_pComm = NULL; + } + if (m_chipData) { + delete []m_chipData; + m_chipData = NULL; + } + + if (m_pFlashInfoData) { + delete []m_pFlashInfoData; + m_pFlashInfoData = NULL; + } +} +bool CRKDevice::SetObject(CRKImage *pImage, CRKComm *pComm, CRKLog *pLog) +{ + if (!pComm) { + return false; + } + m_pImage = pImage; + m_pComm = pComm; + m_pLog = pLog; + if (m_pImage) { + m_os = m_pImage->OsType; + } else + m_os = RK_OS; + return true; +} +int CRKDevice::EraseEmmcBlock(UCHAR ucFlashCS, DWORD dwPos, DWORD dwCount) +{ + int sectorOffset,nWrittenBlcok,iRet; + BYTE emptyData[4 * (SECTOR_SIZE+SPARE_SIZE)]; + memset(emptyData, 0xff, 4 * (SECTOR_SIZE + SPARE_SIZE)); + nWrittenBlcok = 0; + while (dwCount > 0) { + sectorOffset = (ucFlashCS * m_flashInfo.uiBlockNum + dwPos + nWrittenBlcok) * m_flashInfo.uiSectorPerBlock; + iRet = m_pComm->RKU_WriteSector(sectorOffset, 4, emptyData); + if ((iRet != ERR_SUCCESS) && (iRet != ERR_FOUND_BAD_BLOCK)) { + if (m_pLog) { + m_pLog->Record(" ERROR:EraseEmmcBlock-->RKU_WriteSector failed, RetCode(%d)", m_layerName, iRet); + } + return iRet; + } + dwCount--; + nWrittenBlcok++; + } + return ERR_SUCCESS; +} +int CRKDevice::EraseEmmcByWriteLBA(DWORD dwSectorPos, DWORD dwCount) +{ + int nWritten,iRet; + BYTE emptyData[32 * SECTOR_SIZE]; + memset(emptyData, 0xff, 32 * SECTOR_SIZE); + + while (dwCount > 0) { + nWritten = (dwCount < 32) ? dwCount : 32; + iRet = m_pComm->RKU_WriteLBA(dwSectorPos, nWritten, emptyData); + if (iRet != ERR_SUCCESS) { + if (m_pLog) { + m_pLog->Record(" ERROR:EraseEmmcByWriteLBA-->RKU_WriteLBA failed, RetCode(%d)", m_layerName, iRet); + } + return iRet; + } + dwCount -= nWritten; + dwSectorPos += nWritten; + } + return ERR_SUCCESS; +} +bool CRKDevice::EraseEmmc() +{ + UINT uiCount, uiEraseCount, uiSectorOffset; + int iRet = ERR_SUCCESS, iLoopTimes = 0; + uiCount = m_flashInfo.uiFlashSize; + + DWORD dwLayerID; + dwLayerID = m_locationID; + ENUM_CALL_STEP emCallStep = CALL_FIRST; + uiEraseCount = 4; + while (uiEraseCount < uiCount) { + uiSectorOffset = uiEraseCount * 2048; + if (uiEraseCount>8) { + iRet = EraseEmmcByWriteLBA(uiSectorOffset, 32); + } else + iRet = EraseEmmcByWriteLBA(uiSectorOffset, 2048); + if (iRet != ERR_SUCCESS) { + if (m_pLog) { + m_pLog->Record(" ERROR:EraseEmmc-->EraseEmmcByWriteLBA failed, RetCode(%d)", m_layerName, iRet); + } + return false; + } + uiEraseCount++; + iLoopTimes++; + if (iLoopTimes%8 == 0) { + if (m_callBackProc) { + m_callBackProc(dwLayerID, ERASEFLASH_PROGRESS, uiCount, uiEraseCount, emCallStep); + emCallStep = CALL_MIDDLE; + } + } + } + if (m_callBackProc) { + emCallStep = CALL_LAST; + m_callBackProc(dwLayerID, ERASEFLASH_PROGRESS, uiCount, uiCount, emCallStep); + } + return true; +} +bool CRKDevice::GetFlashInfo() +{ + STRUCT_FLASHINFO_CMD info; + BYTE flashID[5]; + int iRet; + UINT uiRead; + iRet = m_pComm->RKU_ReadFlashInfo((PBYTE)&info, &uiRead); + if( ERR_SUCCESS == iRet ) { + if ((info.usBlockSize == 0) || (info.bPageSize == 0)) { + if (m_pLog) { + m_pLog->Record(" ERROR:GetFlashInfo-->RKU_ReadFlashInfo failed,pagesize or blocksize is zero", m_layerName); + } + return false; + } + if (info.bManufCode <= 7) { + strcpy(m_flashInfo.szManufacturerName, szManufName[info.bManufCode]); + } else { + strcpy(m_flashInfo.szManufacturerName, "UNKNOWN"); + } + m_flashInfo.uiFlashSize = info.uiFlashSize / 2 / 1024; + m_flashInfo.uiPageSize = info.bPageSize / 2; + m_flashInfo.usBlockSize = info.usBlockSize / 2; + m_flashInfo.bECCBits = info.bECCBits; + m_flashInfo.bAccessTime = info.bAccessTime; + m_flashInfo.uiBlockNum = m_flashInfo.uiFlashSize * 1024 / m_flashInfo.usBlockSize; + m_flashInfo.uiSectorPerBlock = info.usBlockSize; + m_flashInfo.bFlashCS = info.bFlashCS; + m_flashInfo.usValidSecPerBlock = (info.usBlockSize / info.bPageSize) * 4; + if (m_pFlashInfoData) { + delete []m_pFlashInfoData; + m_pFlashInfoData = NULL; + } + m_usFlashInfoDataLen = BYTE2SECTOR(uiRead); + m_pFlashInfoData = new BYTE[SECTOR_SIZE * m_usFlashInfoDataLen]; + memset(m_pFlashInfoData, 0, SECTOR_SIZE * m_usFlashInfoDataLen); + memcpy(m_pFlashInfoData, (PBYTE)&info, uiRead); + if (m_pLog) { + string strFlashInfo; + m_pLog->PrintBuffer(strFlashInfo, m_pFlashInfoData, 11); + m_pLog->Record(" INFO:FlashInfo:%s", m_layerName, strFlashInfo.c_str()); + } + } else { + if (m_pLog) { + m_pLog->Record(" ERROR:GetFlashInfo-->RKU_ReadFlashInfo failed, RetCode(%d)", m_layerName, iRet); + } + return false; + } + iRet = m_pComm->RKU_ReadFlashID(flashID); + if( ERR_SUCCESS == iRet ) { + DWORD *pID = (DWORD *)flashID; + if (*pID==0x434d4d45)/*emmc*/ { + m_bEmmc = true; + } else + m_bEmmc = false; + } else { + if (m_pLog) { + m_pLog->Record(" ERROR:GetFlashInfo-->RKU_ReadFlashID failed, RetCode(%d)", m_layerName, iRet); + } + return false; + } + return true; +} +bool CRKDevice::TestDevice() +{ + int iResult, iTryCount; + DWORD dwTotal, dwCurrent, dwLayerID; + dwLayerID = m_locationID; + ENUM_CALL_STEP emCallStep = CALL_FIRST; + do { + iTryCount = 3; + while (iTryCount > 0) { + iResult = m_pComm->RKU_TestDeviceReady(&dwTotal, &dwCurrent); + if ((iResult == ERR_SUCCESS) || (iResult == ERR_DEVICE_UNREADY)) { + break; + } + if (m_pLog) { + m_pLog->Record(" ERROR:TestDevice-->RKU_TestDeviceReady failed, RetCode(%d)", m_layerName, iResult); + } + iTryCount--; + sleep(1); + } + if (iTryCount <= 0) { + return false; + } + + if (iResult == ERR_SUCCESS) { + if (emCallStep == CALL_MIDDLE) { + if (m_callBackProc) { + dwCurrent = dwTotal; + emCallStep = CALL_LAST; + m_callBackProc(dwLayerID, TESTDEVICE_PROGRESS, dwTotal, dwCurrent, emCallStep); + } + } + break; + } + if (dwCurrent>dwTotal) { + if (m_pLog) { + m_pLog->Record(" ERROR:TestDevice-->RKU_TestDeviceReady failed,Total=%d, Current=%d", m_layerName, dwTotal, dwCurrent); + } + return false; + } + if (UsbType == RKUSB_LOADER) { + if (dwTotal == 0) { + if (m_pLog) + { + m_pLog->Record(" ERROR:TestDevice-->RKU_TestDeviceReady failed, Total is zero", m_layerName); + } + return false; + } + } + if (m_callBackProc) + { + m_callBackProc(dwLayerID, TESTDEVICE_PROGRESS, dwTotal, dwCurrent, emCallStep); + emCallStep = CALL_MIDDLE; + } + sleep(1); + }while(iResult == ERR_DEVICE_UNREADY); + return true; +} +bool CRKDevice::ResetDevice() +{ + int iRet; + iRet = m_pComm->RKU_ResetDevice(); + if (iRet == ERR_SUCCESS) { + return true; + } else { + bool bRet = false; + if ((iRet == -2) || (iRet == -4)) { + bRet = true; + } + if (m_pLog) { + m_pLog->Record(" ERROR:ResetDevice-->RKU_ResetDevice failed, RetCode(%d)", m_layerName, iRet); + } + return bRet; + } +} + +bool CRKDevice::PowerOffDevice() +{ + int iRet; + iRet = m_pComm->RKU_ResetDevice(RST_POWEROFF_SUBCODE); + if (iRet == ERR_SUCCESS) { + return true; + } else { + if (m_pLog) { + m_pLog->Record(" ERROR:PowerOffDevice-->RKU_ResetDevice failed, RetCode(%d)", m_layerName, iRet); + } + return false; + } +} +bool CRKDevice::CheckChip() +{ + int iRet; + BYTE bChipInfo[CHIPINFO_LEN]; + ENUM_RKDEVICE_TYPE curDeviceType = RKNONE_DEVICE; + memset(bChipInfo, 0, CHIPINFO_LEN); + iRet = m_pComm->RKU_ReadChipInfo(bChipInfo); + if (iRet == ERR_SUCCESS) { + if (!m_chipData) { + m_chipData = new BYTE[CHIPINFO_LEN]; + } + memset(m_chipData, 0, CHIPINFO_LEN); + memcpy(m_chipData, bChipInfo, CHIPINFO_LEN); + DWORD *pValue; + pValue = (DWORD *)(&bChipInfo[0]); + + if ((ENUM_RKDEVICE_TYPE)(*pValue) == m_device) { + return true; + } + if (*pValue == 0x524B3237) { + curDeviceType = RK27_DEVICE; + } else if (*pValue == 0x32373341) { + curDeviceType = RKCAYMAN_DEVICE; + } else if (*pValue == 0x524B3238) { + curDeviceType = RK28_DEVICE; + } else if (*pValue == 0x32383158) { + curDeviceType = RK281X_DEVICE; + } else if (*pValue == 0x32383242) { + curDeviceType = RKPANDA_DEVICE; + } else if (*pValue == 0x32393058) { + curDeviceType = RK29_DEVICE; + } else if (*pValue == 0x32393258) { + curDeviceType = RK292X_DEVICE; + } else if (*pValue == 0x33303041) { + curDeviceType = RK30_DEVICE; + } else if (*pValue == 0x33313041) { + curDeviceType = RK30B_DEVICE; + } else if (*pValue == 0x33313042) { + curDeviceType = RK31_DEVICE; + } else if (*pValue == 0x33323041) { + curDeviceType = RK32_DEVICE; + } else if (*pValue == 0x32363243) { + curDeviceType = RKSMART_DEVICE; + } else if (*pValue == 0x6E616E6F) { + curDeviceType = RKNANO_DEVICE; + } else if (*pValue == 0x4E4F5243) { + curDeviceType = RKCROWN_DEVICE; + } + + if (curDeviceType == m_device){ + return true; + } else { + if (m_pLog) { + m_pLog->Record(" ERROR:CheckChip-->Chip is not match, firmware(0x%x), device(0x%x)", m_layerName, m_device, *pValue); + } + return false; + } + } + else { + if (m_pLog) { + m_pLog->Record(" ERROR:CheckChip-->RKU_ReadChipInfo failed,RetCode(%d)", m_layerName, iRet); + } + return false; + } +} + +int CRKDevice::DownloadBoot() +{ + UCHAR i; + DWORD dwSize, dwDelay; + PBYTE pBuffer = NULL; + for ( i = 0; i < m_pImage->m_bootObject->Entry471Count; i++ ) { + if ( !m_pImage->m_bootObject->GetEntryProperty(ENTRY471, i, dwSize, dwDelay) ) { + if (m_pLog) { + m_pLog->Record(" ERROR:DownloadBoot-->GetEntry471Property failed,index(%d)", m_layerName, i); + } + return -2; + } + if (dwSize>0) { + pBuffer = new BYTE[dwSize]; + if ( !m_pImage->m_bootObject->GetEntryData(ENTRY471, i, pBuffer) ) { + if (m_pLog) { + m_pLog->Record(" ERROR:DownloadBoot-->GetEntry471Data failed,index(%d)", m_layerName, i); + } + delete []pBuffer; + return -3; + } + if ( !Boot_VendorRequest(0x0471,pBuffer,dwSize) ) { + if (m_pLog) { + m_pLog->Record(" ERROR:DownloadBoot-->Boot_VendorRequest471 failed,index(%d)", m_layerName, i); + } + delete []pBuffer; + return -4; + } + delete []pBuffer; + pBuffer = NULL; + if (dwDelay>0) { + usleep(dwDelay * 1000); + } + + } + } + + for ( i=0; i < m_pImage->m_bootObject->Entry472Count; i++ ) { + if ( !m_pImage->m_bootObject->GetEntryProperty(ENTRY472, i, dwSize, dwDelay) ) { + if (m_pLog) { + m_pLog->Record(" ERROR:DownloadBoot-->GetEntry472Property failed,index(%d)", m_layerName, i); + } + return -2; + } + if (dwSize > 0) { + pBuffer = new BYTE[dwSize]; + if ( !m_pImage->m_bootObject->GetEntryData(ENTRY472, i, pBuffer) ) { + if (m_pLog) { + m_pLog->Record(" ERROR:DownloadBoot-->GetEntry472Data failed,index(%d)", m_layerName, i); + } + delete []pBuffer; + return -3; + } + if ( !Boot_VendorRequest(0x0472, pBuffer, dwSize) ) { + if (m_pLog) { + m_pLog->Record(" ERROR:DownloadBoot-->Boot_VendorRequest472 failed,index(%d)", m_layerName, i); + } + delete []pBuffer; + return -4; + } + delete []pBuffer; + pBuffer = NULL; + if (dwDelay > 0) { + usleep(dwDelay * 1000); + } + } + } + sleep(1); + return 0; + +} +bool CRKDevice::Boot_VendorRequest( DWORD requestCode, PBYTE pBuffer, DWORD dwDataSize) +{ + int iRet; + iRet = m_pComm->RKU_DeviceRequest(requestCode, pBuffer, dwDataSize); + return (iRet == ERR_SUCCESS) ? true : false; +} +int CRKDevice::EraseAllBlocks() +{ + int i; + UINT uiBlockCount; + int iRet = ERR_SUCCESS, iErasePos = 0, iEraseBlockNum = 0, iEraseTimes = 0, iCSIndex = 0; + BYTE bCSCount = 0; + for (i = 0; i < 8; i++) { + if ( m_flashInfo.bFlashCS & (1 << i) ) { + bCSCount++; + } + } + DWORD dwLayerID; + dwLayerID = LocationID; + ENUM_CALL_STEP emCallStep = CALL_FIRST; + if (m_bEmmc) { + iRet = EraseEmmcBlock(0, 0, IDBLOCK_TOP); + if (iRet != ERR_SUCCESS) { + if (m_pLog) { + m_pLog->Record(" ERROR:EraseAllBlocks-->EraseEmmcBlock failed,RetCode(%d)", m_layerName, iRet); + } + return -1; + } + if (!EraseEmmc()) { + if (m_pLog) { + m_pLog->Record(" ERROR:EraseAllBlocks-->EraseEmmc failed", m_layerName); + } + return -1; + } + return 0; + } + for (i = 0; i < 8; i++) { + if ( m_flashInfo.bFlashCS & (1 << i) ) { + uiBlockCount = m_flashInfo.uiBlockNum; + iErasePos = 0; + iEraseTimes = 0; + while (uiBlockCount > 0) { + iEraseBlockNum = (uiBlockCount < MAX_ERASE_BLOCKS) ? uiBlockCount : MAX_ERASE_BLOCKS; + iRet = m_pComm->RKU_EraseBlock(i, iErasePos, iEraseBlockNum, ERASE_FORCE); + if ((iRet != ERR_SUCCESS) && (iRet != ERR_FOUND_BAD_BLOCK)) { + if (m_pLog) { + m_pLog->Record(" ERROR:EraseAllBlocks-->RKU_EraseBlock failed,RetCode(%d)", m_layerName, iRet); + } + return -1; + } + iErasePos += iEraseBlockNum; + uiBlockCount -= iEraseBlockNum; + iEraseTimes++; + if (iEraseTimes % 8 == 0) { + if (m_callBackProc) { + m_callBackProc(dwLayerID, ERASEFLASH_PROGRESS, m_flashInfo.uiBlockNum * bCSCount, iCSIndex * m_flashInfo.uiBlockNum + iErasePos, emCallStep); + emCallStep = CALL_MIDDLE; + } + } + } + iCSIndex++; + } + } + + if (m_callBackProc) { + emCallStep = CALL_LAST; + m_callBackProc(dwLayerID, ERASEFLASH_PROGRESS, m_flashInfo.uiBlockNum * bCSCount, iCSIndex * m_flashInfo.uiBlockNum, emCallStep); + } + return 0; +} + diff --git a/RKDevice.h b/RKDevice.h new file mode 100644 index 0000000..515c109 --- /dev/null +++ b/RKDevice.h @@ -0,0 +1,128 @@ +#ifndef RKDEVICE_HEADER +#define RKDEVICE_HEADER +#include "RKImage.h" +#include "RKComm.h" +#include "RKLog.h" +#include "DefineHeader.h" + +#define SECTOR_SIZE 512 +#define PAGE_SIZE 2048 +#define SPARE_SIZE 16 +#define CHIPINFO_LEN 16 +#define IDBLOCK_TOP 50 + +#define CALC_UNIT(a, b) ((a > 0) ? ((a - 1) / b + 1) : (a)) +#define BYTE2SECTOR(x) (CALC_UNIT(x, SECTOR_SIZE)) +#define PAGEALIGN(x) (CALC_UNIT(x, 4)) + +#pragma pack(1) +typedef struct _STRUCT_FLASH_INFO { + char szManufacturerName[16]; + UINT uiFlashSize; + USHORT usBlockSize; + UINT uiPageSize; + UINT uiSectorPerBlock; + BYTE blockState[IDBLOCK_TOP]; + UINT uiBlockNum; + BYTE bECCBits; + BYTE bAccessTime; + BYTE bFlashCS; + USHORT usValidSecPerBlock; + USHORT usPhyBlokcPerIDB; + UINT uiSecNumPerIDB; +} STRUCT_FLASH_INFO, *PSTRUCT_FLASH_INFO; +typedef struct _STRUCT_FLASHINFO_CMD { + UINT uiFlashSize; + USHORT usBlockSize; + BYTE bPageSize; + BYTE bECCBits; + BYTE bAccessTime; + BYTE bManufCode; + BYTE bFlashCS; + BYTE reserved[501]; +} STRUCT_FLASHINFO_CMD, *PSTRUCT_FLASHINFO_CMD; +#pragma pack() + +class CRKDevice +{ +public: + USHORT GetVendorID(); + void SetVendorID(USHORT value); + property VendorID; + + USHORT GetProductID(); + void SetProductID(USHORT value); + property ProductID; + + ENUM_RKDEVICE_TYPE GetDeviceType(); + void SetDeviceType(ENUM_RKDEVICE_TYPE value); + property DeviceType; + + ENUM_RKUSB_TYPE GetUsbType(); + void SetUsbType(ENUM_RKUSB_TYPE value); + property UsbType; + + char *GetLayerName(); + void SetLayerName(char *value); + property LayerName; + + DWORD GetLocationID(); + void SetLocationID(DWORD value); + property LocationID; + + USHORT GetBcdUsb(); + void SetBcdUsb(USHORT value); + property BcdUsb; + + ENUM_OS_TYPE GetOsType(); + void SetOsType(ENUM_OS_TYPE value); + property OsType; + + CRKLog *GetLogObjectPointer(); + property LogObjectPointer; + + CRKComm *GetCommObjectPointer(); + property CommObjectPointer; + + void SetCallBackPointer(ProgressPromptCB value); + property CallBackPointer; + + int DownloadBoot(); + bool TestDevice(); + bool ResetDevice(); + bool PowerOffDevice(); + bool CheckChip(); + bool GetFlashInfo(); + int EraseAllBlocks(); + bool SetObject(CRKImage *pImage, CRKComm *pComm, CRKLog *pLog); + string GetLayerString(DWORD dwLocationID); + CRKDevice(STRUCT_RKDEVICE_DESC &device); + ~CRKDevice(); +protected: + STRUCT_FLASH_INFO m_flashInfo; + PBYTE m_pFlashInfoData; + USHORT m_usFlashInfoDataOffset; + USHORT m_usFlashInfoDataLen; + PBYTE m_chipData; + CRKImage *m_pImage; + CRKComm *m_pComm; + CRKLog *m_pLog; + ProgressPromptCB m_callBackProc; + bool m_bEmmc; + int EraseEmmcBlock(UCHAR ucFlashCS, DWORD dwPos, DWORD dwCount); + int EraseEmmcByWriteLBA(DWORD dwSectorPos, DWORD dwCount); + bool EraseEmmc(); + bool Boot_VendorRequest(DWORD requestCode, PBYTE pBuffer, DWORD dwDataSize); +private: + USHORT m_vid; + USHORT m_pid; + ENUM_RKDEVICE_TYPE m_device; + ENUM_OS_TYPE m_os; + ENUM_RKUSB_TYPE m_usb; + UINT m_locationID; + USHORT m_bcdUsb; +protected: + char m_layerName[32]; +}; + +#endif \ No newline at end of file diff --git a/RKImage.cpp b/RKImage.cpp new file mode 100644 index 0000000..7774354 --- /dev/null +++ b/RKImage.cpp @@ -0,0 +1,298 @@ +/* + * (C) Copyright 2017 Fuzhou Rockchip Electronics Co., Ltd + * Seth Liu 2017.03.01 + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include "RKImage.h" + +DWORD CRKImage::GetVersion() +{ + return m_version; +} +DWORD CRKImage::GetMergeVersion() +{ + return m_mergeVersion; +} +STRUCT_RKTIME CRKImage::GetReleaseTime() +{ + return m_releaseTime; +} +ENUM_RKDEVICE_TYPE CRKImage::GetSupportDevice() +{ + return m_supportDevice; +} +ENUM_OS_TYPE CRKImage::GetOsType() +{ + UINT *pOsType; + pOsType = (UINT *)&m_reserved[4]; + return (ENUM_OS_TYPE)*pOsType; +} + +USHORT CRKImage::GetBackupSize() +{ + USHORT *pBackupSize; + pBackupSize = (USHORT *)&m_reserved[12]; + return *pBackupSize; +} +DWORD CRKImage::GetBootOffset() +{ + return m_bootOffset; +} +DWORD CRKImage::GetBootSize() +{ + return m_bootSize; +} +DWORD CRKImage::GetFWOffset() +{ + return m_fwOffset; +} +long long CRKImage::GetFWSize() +{ + return m_fwSize; +} +bool CRKImage::SaveBootFile(string filename) +{ + FILE *file = NULL; + int iRead; + file = fopen(filename.c_str(), "wb+"); + if (!file) { + return false; + } + BYTE buffer[1024]; + DWORD dwBufferSize = 1024; + DWORD dwBootSize = m_bootSize; + DWORD dwReadSize; + fseek(m_pFile, m_bootOffset, SEEK_SET); + do { + dwReadSize = (dwBootSize >= 1024) ? dwBufferSize : dwBootSize; + iRead = fread(buffer, 1, dwReadSize, m_pFile); + if (iRead != (int)dwReadSize) { + fclose(file); + return false; + } + fwrite(buffer, 1, dwReadSize, file); + dwBootSize -= dwReadSize; + } while(dwBootSize > 0); + fclose(file); + return true; +} +bool CRKImage::SaveFWFile(string filename) +{ + FILE *file = NULL; + int iRead; + file = fopen(filename.c_str(), "wb+"); + if (!file) { + return false; + } + BYTE buffer[1024]; + DWORD dwBufferSize = 1024; + long long dwFWSize = m_fwSize; + DWORD dwReadSize; + fseeko(m_pFile, m_fwOffset, SEEK_SET); + do { + dwReadSize = (dwFWSize >= 1024) ? dwBufferSize : dwFWSize; + iRead = fread(buffer, 1, dwReadSize, m_pFile); + if (iRead != (int)dwReadSize) { + fclose(file); + return false; + } + fwrite(buffer, 1, dwReadSize, file); + dwFWSize -= dwReadSize; + } while (dwFWSize > 0); + fclose(file); + return true; +} +bool CRKImage::GetData(long long dwOffset, DWORD dwSize, PBYTE lpBuffer) +{ + if ( (dwOffset < 0) || (dwSize == 0) ) { + return false; + } + if ( dwOffset+dwSize > m_fileSize) { + return false; + } + fseeko(m_pFile, dwOffset, SEEK_SET); + UINT uiActualRead; + uiActualRead = fread(lpBuffer,1, dwSize, m_pFile); + if (dwSize != uiActualRead){ + return false; + } + return true; +} +void CRKImage::GetReservedData(PBYTE &lpData, USHORT &usSize) +{ + lpData = m_reserved; + usSize = IMAGE_RESERVED_SIZE; +} + +CRKImage::CRKImage(string filename, bool &bCheck) +{ + Version.setContainer(this); + Version.getter(&CRKImage::GetVersion); + MergeVersion.setContainer(this); + MergeVersion.getter(&CRKImage::GetMergeVersion); + ReleaseTime.setContainer(this); + ReleaseTime.getter(&CRKImage::GetReleaseTime); + SupportDevice.setContainer(this); + SupportDevice.getter(&CRKImage::GetSupportDevice); + OsType.setContainer(this); + OsType.getter(&CRKImage::GetOsType); + BackupSize.setContainer(this); + BackupSize.getter(&CRKImage::GetBackupSize); + BootOffset.setContainer(this); + BootOffset.getter(&CRKImage::GetBootOffset); + BootSize.setContainer(this); + BootSize.getter(&CRKImage::GetBootSize); + FWOffset.setContainer(this); + FWOffset.getter(&CRKImage::GetFWOffset); + FWSize.setContainer(this); + FWSize.getter(&CRKImage::GetFWSize); + SignFlag.setContainer(this); + SignFlag.getter(&CRKImage::GetSignFlag); + struct stat statBuf; + m_bootObject = NULL; + m_pFile = NULL; + m_bSignFlag = false; + + m_signMd5Size = 0; + memset(m_md5, 0, 32); + memset(m_signMd5, 0, 256); + + char szName[256]; + strcpy(szName, filename.c_str()); + if(stat(szName, &statBuf) < 0) { + bCheck = false; + return; + } + if (S_ISDIR(statBuf.st_mode)) { + bCheck = false; + return; + } + m_fileSize = statBuf.st_size; + + bool bOnlyBootFile=false; + transform(filename.begin(), filename.end(), filename.begin(), (int(*)(int))tolower); + if (filename.find(".bin") != string::npos) { + bOnlyBootFile = true; + } + + m_pFile = fopen(szName, "rb"); + if (!m_pFile) { + bCheck = false; + return; + } + + int nMd5DataSize, iRead; + long long ulFwSize; + STRUCT_RKIMAGE_HEAD imageHead; + if (!bOnlyBootFile) { + fseeko(m_pFile, 0, SEEK_SET); + iRead = fread((PBYTE)(&imageHead), 1, sizeof(STRUCT_RKIMAGE_HEAD), m_pFile); + if (iRead != sizeof(STRUCT_RKIMAGE_HEAD)) { + bCheck = false; + return; + } + if ( imageHead.uiTag != 0x57464B52 ) { + bCheck = false; + return; + } + if ((imageHead.reserved[14] == 'H') && (imageHead.reserved[15] == 'I')) { + ulFwSize = *((DWORD *)(&imageHead.reserved[16])); + ulFwSize <<= 32; + ulFwSize += imageHead.dwFWOffset; + ulFwSize += imageHead.dwFWSize; + } else + ulFwSize = imageHead.dwFWOffset + imageHead.dwFWSize; + nMd5DataSize = GetImageSize() - ulFwSize; + if (nMd5DataSize >= 160) { + m_bSignFlag = true; + m_signMd5Size = nMd5DataSize - 32; + fseeko(m_pFile, ulFwSize, SEEK_SET); + iRead = fread(m_md5, 1, 32, m_pFile); + if (iRead != 32) { + bCheck = false; + return; + } + iRead = fread(m_signMd5, 1, nMd5DataSize - 32, m_pFile); + if (iRead != (nMd5DataSize - 32)) { + bCheck = false; + return; + } + } else { + fseeko(m_pFile, -32, SEEK_END); + iRead = fread(m_md5, 1, 32, m_pFile); + if (iRead != 32) { + bCheck = false; + return; + } + } + + m_version = imageHead.dwVersion; + m_mergeVersion = imageHead.dwMergeVersion; + m_releaseTime.usYear = imageHead.stReleaseTime.usYear; + m_releaseTime.ucMonth = imageHead.stReleaseTime.ucMonth; + m_releaseTime.ucDay = imageHead.stReleaseTime.ucDay; + m_releaseTime.ucHour = imageHead.stReleaseTime.ucHour; + m_releaseTime.ucMinute = imageHead.stReleaseTime.ucMinute; + m_releaseTime.ucSecond = imageHead.stReleaseTime.ucSecond; + m_supportDevice = imageHead.emSupportChip; + m_bootOffset = imageHead.dwBootOffset; + m_bootSize = imageHead.dwBootSize; + m_fwOffset = imageHead.dwFWOffset; + m_fwSize = ulFwSize - m_fwOffset; + memcpy(m_reserved, imageHead.reserved, IMAGE_RESERVED_SIZE); + } else { + m_bootOffset = 0; + m_bootSize = m_fileSize; + } + + PBYTE lpBoot; + lpBoot = new BYTE[m_bootSize]; + fseeko(m_pFile, m_bootOffset, SEEK_SET); + iRead = fread(lpBoot, 1, m_bootSize, m_pFile); + if (iRead != (int)m_bootSize) { + bCheck = false; + return; + } + bool bRet; + m_bootObject = new CRKBoot(lpBoot, m_bootSize, bRet); + if (!bRet) { + bCheck = false; + return; + } + if (bOnlyBootFile) { + m_supportDevice = m_bootObject->SupportDevice; + UINT *pOsType; + pOsType = (UINT *)&m_reserved[4]; + *pOsType = (UINT)RK_OS; + fclose(m_pFile); + m_pFile = NULL; + } + bCheck = true; +} +CRKImage::~CRKImage() +{ + if (m_pFile) { + fclose(m_pFile); + m_pFile = NULL; + } + if (m_bootObject) { + delete m_bootObject; + m_bootObject = NULL; + } +} + +long long CRKImage::GetImageSize() +{ + return m_fileSize; +} +int CRKImage::GetMd5Data(PBYTE &lpMd5, PBYTE &lpSignMd5) +{ + lpMd5 = m_md5; + lpSignMd5 = m_signMd5; + return m_signMd5Size; +} +bool CRKImage::GetSignFlag() +{ + return m_bSignFlag; +} \ No newline at end of file diff --git a/RKImage.h b/RKImage.h new file mode 100644 index 0000000..af7c703 --- /dev/null +++ b/RKImage.h @@ -0,0 +1,77 @@ +#ifndef RKIMAGE_HEADER +#define RKIMAGE_HEADER +#include "DefineHeader.h" +#include "RKBoot.h" +#define IMAGE_RESERVED_SIZE 61 +#pragma pack(1) +typedef struct { + UINT uiTag; + USHORT usSize; + DWORD dwVersion; + DWORD dwMergeVersion; + STRUCT_RKTIME stReleaseTime; + ENUM_RKDEVICE_TYPE emSupportChip; + DWORD dwBootOffset; + DWORD dwBootSize; + DWORD dwFWOffset; + DWORD dwFWSize; + BYTE reserved[IMAGE_RESERVED_SIZE]; +} STRUCT_RKIMAGE_HEAD, *PSTRUCT_RKIMAGE_HEAD; +#pragma pack() +class CRKImage +{ +public: + UINT GetVersion(); + property Version; + UINT GetMergeVersion(); + property MergeVersion; + STRUCT_RKTIME GetReleaseTime(); + property ReleaseTime; + ENUM_RKDEVICE_TYPE GetSupportDevice(); + property SupportDevice; + ENUM_OS_TYPE GetOsType(); + property OsType; + + unsigned short GetBackupSize(); + property BackupSize; + UINT GetBootOffset(); + property BootOffset; + UINT GetBootSize(); + property BootSize; + UINT GetFWOffset(); + property FWOffset; + long long GetFWSize(); + property FWSize; + bool GetSignFlag(); + property SignFlag; + + CRKBoot *m_bootObject; + bool SaveBootFile(string filename); + bool SaveFWFile(string filename); + bool GetData(long long dwOffset, DWORD dwSize, PBYTE lpBuffer); + void GetReservedData(PBYTE &lpData, USHORT &usSize); + int GetMd5Data(PBYTE &lpMd5, PBYTE &lpSignMd5); + long long GetImageSize(); + CRKImage(string filename, bool &bCheck); + ~CRKImage(); +protected: + +private: + DWORD m_version; + DWORD m_mergeVersion; + STRUCT_RKTIME m_releaseTime; + ENUM_RKDEVICE_TYPE m_supportDevice; + DWORD m_bootOffset; + DWORD m_bootSize; + DWORD m_fwOffset; + long long m_fwSize; + + BYTE m_md5[32]; + BYTE m_signMd5[256]; + BYTE m_reserved[IMAGE_RESERVED_SIZE]; + bool m_bSignFlag; + int m_signMd5Size; + FILE *m_pFile; + long long m_fileSize; +}; +#endif \ No newline at end of file diff --git a/RKLog.cpp b/RKLog.cpp new file mode 100644 index 0000000..c90ad71 --- /dev/null +++ b/RKLog.cpp @@ -0,0 +1,121 @@ +/* + * (C) Copyright 2017 Fuzhou Rockchip Electronics Co., Ltd + * Seth Liu 2017.03.01 + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include "RKLog.h" +int file_stat(string strPath) +{ + struct stat statBuf; + int ret; + ret = stat(strPath.c_str(), &statBuf); + if (ret != 0) { + return STAT_NOT_EXIST; + } + if (S_ISDIR(statBuf.st_mode)) + return STAT_DIR; + return STAT_FILE; +} +string CRKLog::GetLogSavePath() +{ + return m_path; +} +bool CRKLog::GetEnableLog() +{ + return m_enable; +} +void CRKLog::SetEnableLog(bool bEnable) +{ + m_enable = bEnable; +} + +CRKLog::CRKLog(string logFilePath, string logFileName, bool enable) +{ + LogSavePath.setContainer(this); + LogSavePath.getter(&CRKLog::GetLogSavePath); + + EnableLog.setContainer(this); + EnableLog.getter(&CRKLog::GetEnableLog); + EnableLog.setter(&CRKLog::SetEnableLog); + + if (!opendir(logFilePath.c_str())) { + m_path = ""; + } else { + if (logFilePath[logFilePath.size() - 1] != '/') { + logFilePath += '/'; + } + m_path = logFilePath; + } + if (logFileName.size() <= 0) { + m_name = "Log"; + } else + m_name = logFileName; + m_enable = enable; + +} +CRKLog::~CRKLog() +{ +} +void CRKLog::Record(const char *lpFmt,...) +{ +/************************* 输出到日志 ***********************/ + char szBuf[1024] = ""; + GET_FMT_STRING(lpFmt, szBuf); + if ((m_enable) && (m_path.size() > 0)) + { + Write( szBuf); + } +} +bool CRKLog::Write(string text) +{ + time_t now; + struct tm timeNow; + char szDateTime[100]; + string strName; + FILE *file=NULL; + time(&now); + localtime_r(&now, &timeNow); + sprintf(szDateTime, "%04d-%02d-%02d.txt", timeNow.tm_year + 1900, timeNow.tm_mon + 1, timeNow.tm_mday); + strName = m_path + m_name+szDateTime; + + try { + file = fopen(strName.c_str(), "ab+"); + if (!file) { + return false; + } + sprintf(szDateTime, "%02d:%02d:%02d \t", timeNow.tm_hour, timeNow.tm_min, timeNow.tm_sec); + text = szDateTime + text + "\r\n"; + fwrite(text.c_str(), 1, text.size() * sizeof(char), file); + fclose(file); + } catch (...) { + fclose(file); + return false; + } + return true; +} +bool CRKLog::SaveBuffer(string fileName, PBYTE lpBuffer, DWORD dwSize) +{ + FILE *file; + file = fopen(fileName.c_str(), "wb+"); + if (!file) { + return false; + } + fwrite(lpBuffer, 1, dwSize, file); + fclose(file); + return true; +} +void CRKLog::PrintBuffer(string &strOutput, PBYTE lpBuffer, DWORD dwSize, UINT uiLineCount) +{ + UINT i,count; + char strHex[32]; + strOutput = ""; + for (i = 0, count = 0; i < dwSize; i++, count++) { + sprintf(strHex, "%X", lpBuffer[i]); + strOutput = strOutput + " " + strHex; + if (count >= uiLineCount) { + strOutput += "\r\n"; + count = 0; + } + } +} \ No newline at end of file diff --git a/RKLog.h b/RKLog.h new file mode 100644 index 0000000..61a7fd3 --- /dev/null +++ b/RKLog.h @@ -0,0 +1,41 @@ +#ifndef RKLOG_HEADER +#define RKLOG_HEADER +#include "DefineHeader.h" + +#define GET_FMT_STRING(fmt, buf) \ + { \ + va_list args; \ + va_start(args, fmt); \ + vsnprintf(buf, sizeof(buf)-1, fmt, args); \ + va_end(args); \ + buf[sizeof(buf)-1] = 0x00; \ +}; + +class CRKLog +{ +public: + string GetLogSavePath(); + bool GetEnableLog(); + void SetEnableLog(bool bEnable); + property LogSavePath; + property EnableLog; + CRKLog(string logFilePath, string logFileName, bool enable = true); + ~CRKLog(); + bool SaveBuffer(string fileName, PBYTE lpBuffer, DWORD dwSize); + void PrintBuffer(string &strOutput, PBYTE lpBuffer, DWORD dwSize, UINT uiLineCount = 16); + void Record(const char *lpFmt, ...); + +protected: +private: + string m_path; + string m_name; + bool m_enable; + bool Write(string text); +}; +typedef enum { + STAT_NOT_EXIST = 0, + STAT_FILE, + STAT_DIR +} ENUM_FILE_STAT; +int file_stat(string strPath); +#endif \ No newline at end of file diff --git a/RKScan.cpp b/RKScan.cpp new file mode 100644 index 0000000..1cd8f50 --- /dev/null +++ b/RKScan.cpp @@ -0,0 +1,614 @@ +/* + * (C) Copyright 2017 Fuzhou Rockchip Electronics Co., Ltd + * Seth Liu 2017.03.01 + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "RKScan.h" +#define BUSID(id) ((id & 0x0000FF00) >> 8) +int CRKScan::GetDEVICE_COUNTS() +{ + return m_list.size(); +} + +UINT CRKScan::GetMSC_TIMEOUT() +{ + return m_waitMscSecond; +} + +UINT CRKScan::GetRKUSB_TIMEOUT() +{ + return m_waitRKusbSecond; +} + +void CRKScan::SetMSC_TIMEOUT(UINT value) +{ + m_waitMscSecond = value; +} + +void CRKScan::SetRKUSB_TIMEOUT(UINT value) +{ + m_waitRKusbSecond = value; +} + +CRKScan::CRKScan(UINT uiMscTimeout, UINT uiRKusbTimeout) +{ + DEVICE_COUNTS.setContainer(this); + DEVICE_COUNTS.getter(&CRKScan::GetDEVICE_COUNTS); + + MSC_TIMEOUT.setContainer(this); + MSC_TIMEOUT.getter(&CRKScan::GetMSC_TIMEOUT); + MSC_TIMEOUT.setter(&CRKScan::SetMSC_TIMEOUT); + + RKUSB_TIMEOUT.setContainer(this); + RKUSB_TIMEOUT.getter(&CRKScan::GetRKUSB_TIMEOUT); + RKUSB_TIMEOUT.setter(&CRKScan::SetRKUSB_TIMEOUT); + + m_waitMscSecond = uiMscTimeout; + m_waitRKusbSecond = uiRKusbTimeout; + m_log = NULL; + m_list.clear(); + m_deviceConfigSet.clear(); + m_deviceMscConfigSet.clear(); +} +bool CRKScan::FindRockusbVidPid(ENUM_RKDEVICE_TYPE type, USHORT &usVid, USHORT &usPid) +{ + UINT i; + bool bRet = false; + for (i = 0; i < m_deviceConfigSet.size(); i++) { + if (m_deviceConfigSet[i].emDeviceType == type) { + usVid = m_deviceConfigSet[i].usVid; + usPid = m_deviceConfigSet[i].usPid; + bRet = true; + break; + } + } + return bRet; +} +void CRKScan::AddRockusbVidPid(USHORT newVid, USHORT newPid, USHORT oldVid, USHORT oldPid) +{ + if ((newVid == 0) || (newPid == 0) || (oldVid == 0) || (oldPid == 0)) { + return; + } + STRUCT_DEVICE_CONFIG config; + unsigned int i; + for (i = 0; i < m_deviceConfigSet.size(); i++) { + if ((m_deviceConfigSet[i].usVid == oldVid) && (m_deviceConfigSet[i].usPid == oldPid)) { + config.usVid = newVid; + config.usPid = newPid; + config.emDeviceType = m_deviceConfigSet[i].emDeviceType; + break; + } + } + if (i < m_deviceConfigSet.size()) + m_deviceConfigSet.push_back(config); +} + +void CRKScan::SetVidPid(USHORT mscVid, USHORT mscPid) +{ + STRUCT_DEVICE_CONFIG config; + m_deviceConfigSet.clear(); + + config.emDeviceType = RK27_DEVICE; + config.usPid = 0x3201; + config.usVid = 0x071B; + m_deviceConfigSet.push_back(config); + + config.emDeviceType = RK28_DEVICE; + config.usPid = 0x3228; + config.usVid = 0x071B; + m_deviceConfigSet.push_back(config); + + config.emDeviceType = RKNANO_DEVICE; + config.usPid = 0x3226; + config.usVid = 0x071B; + m_deviceConfigSet.push_back(config); + + config.emDeviceType = RKCROWN_DEVICE; + config.usPid = 0x261A; + config.usVid = 0x2207; + m_deviceConfigSet.push_back(config); + + config.emDeviceType = RK281X_DEVICE; + config.usPid = 0x281A; + config.usVid = 0x2207; + m_deviceConfigSet.push_back(config); + + config.emDeviceType = RKCAYMAN_DEVICE; + config.usPid = 0x273A; + config.usVid = 0x2207; + m_deviceConfigSet.push_back(config); + + config.emDeviceType = RK29_DEVICE; + config.usPid = 0x290A; + config.usVid = 0x2207; + m_deviceConfigSet.push_back(config); + + config.emDeviceType = RKPANDA_DEVICE; + config.usPid = 0x282B; + config.usVid = 0x2207; + m_deviceConfigSet.push_back(config); + + config.emDeviceType = RKSMART_DEVICE; + config.usPid = 0x262C; + config.usVid = 0x2207; + m_deviceConfigSet.push_back(config); + + config.emDeviceType = RK292X_DEVICE; + config.usPid = 0x292A; + config.usVid = 0x2207; + m_deviceConfigSet.push_back(config); + + config.emDeviceType = RK30_DEVICE; + config.usPid = 0x300A; + config.usVid = 0x2207; + m_deviceConfigSet.push_back(config); + + config.emDeviceType = RK30B_DEVICE; + config.usPid = 0x300B; + config.usVid = 0x2207; + m_deviceConfigSet.push_back(config); + + config.emDeviceType = RK31_DEVICE; + config.usPid = 0x310B; + config.usVid = 0x2207; + m_deviceConfigSet.push_back(config); + + config.emDeviceType = RK32_DEVICE; + config.usPid = 0x320A; + config.usVid = 0x2207; + m_deviceConfigSet.push_back(config); + + m_deviceMscConfigSet.clear(); + + config.emDeviceType = RKNONE_DEVICE; + config.usPid = 0x3203; + config.usVid = 0x071B; + m_deviceMscConfigSet.push_back(config); + + config.emDeviceType = RKNONE_DEVICE; + config.usPid = 0x3205; + config.usVid = 0x071B; + m_deviceMscConfigSet.push_back(config); + + config.emDeviceType = RKNONE_DEVICE; + config.usPid = 0x2910; + config.usVid = 0x0BB4; + m_deviceMscConfigSet.push_back(config); + + config.emDeviceType = RKNONE_DEVICE; + config.usPid = 0x0000; + config.usVid = 0x2207; + m_deviceMscConfigSet.push_back(config); + + config.emDeviceType = RKNONE_DEVICE; + config.usPid = 0x0010; + config.usVid = 0x2207; + m_deviceMscConfigSet.push_back(config); + + if ((mscVid != 0) || (mscPid != 0)) { + if (FindConfigSetPos(m_deviceMscConfigSet, mscVid, mscPid) == -1) { + config.emDeviceType = RKNONE_DEVICE; + config.usPid = mscPid; + config.usVid = mscVid; + m_deviceMscConfigSet.push_back(config); + } + } +} +int CRKScan::FindWaitSetPos(const RKDEVICE_CONFIG_SET &waitDeviceSet, USHORT vid, USHORT pid) +{ + int pos=-1; + UINT i; + for ( i = 0; i < waitDeviceSet.size(); i++ ) { + if ( (vid == waitDeviceSet[i].usVid) && (pid == waitDeviceSet[i].usPid) ) { + pos = i; + break; + } + } + return pos; +} +int CRKScan::FindConfigSetPos(RKDEVICE_CONFIG_SET &devConfigSet, USHORT vid, USHORT pid) +{ + int pos = -1; + UINT i; + for ( i = 0; i < devConfigSet.size(); i++ ) { + if ( (vid == devConfigSet[i].usVid) && (pid == devConfigSet[i].usPid) ) { + pos = i; + break; + } + } + return pos; +} +void CRKScan::EnumerateUsbDevice(RKDEVICE_DESC_SET &list, UINT &uiTotalMatchDevices) +{ + STRUCT_RKDEVICE_DESC desc; + struct libusb_device_descriptor descriptor; + int ret,i,cnt; + + uiTotalMatchDevices = 0; + libusb_device **pDevs = NULL; + libusb_device *dev; + ret = libusb_get_device_list(NULL, &pDevs); + if (ret < 0) { + if (m_log) + m_log->Record("Error:EnumerateUsbDevice-->get_device_list failed,err=%d!", ret); + return; + } + cnt = ret; + for (i = 0; i < cnt; i++) { + dev = pDevs[i]; + if (dev) { + ret = libusb_get_device_descriptor (dev, &descriptor); + if (ret < 0) { + libusb_free_device_list(pDevs, 1); + if (m_log) + m_log->Record("Error:EnumerateUsbDevice-->get_device_descriptor failed,err=%d!", ret); + return; + } + desc.emDeviceType = RKNONE_DEVICE; + desc.emUsbType = RKUSB_NONE; + desc.pUsbHandle = (void *)dev; + desc.usbcdUsb = descriptor.bcdUSB; + desc.usVid = descriptor.idVendor; + desc.usPid = descriptor.idProduct; + desc.uiLocationID = libusb_get_bus_number(dev); + desc.uiLocationID <<= 8; + desc.uiLocationID += libusb_get_port_number(dev); + libusb_ref_device(dev); + uiTotalMatchDevices++; + list.push_back(desc); + } + + } + libusb_free_device_list(pDevs, 1); + +} + +void CRKScan::FreeDeviceList(RKDEVICE_DESC_SET &list) +{ + device_list_iter iter; + for (iter = list.begin(); iter != list.end(); iter++) { + if ((*iter).pUsbHandle) { + libusb_unref_device((libusb_device *)((*iter).pUsbHandle)); + (*iter).pUsbHandle = NULL; + } + } + list.clear(); +} +bool CRKScan::IsRockusbDevice(ENUM_RKDEVICE_TYPE &type, USHORT vid, USHORT pid) +{ + int iPos; + iPos = FindConfigSetPos(m_deviceConfigSet, vid, pid); + if (iPos != -1) { + type = m_deviceConfigSet[iPos].emDeviceType; + return true; + } + if (vid == 0x2207) { + if ((pid >> 8) > 0) { + type = RKNONE_DEVICE; + return true; + } + } + return false; +} +int CRKScan::Search(UINT type) +{ + device_list_iter iter,new_iter; + ENUM_RKDEVICE_TYPE devType; + UINT uiTotalDevice; + int iPos; + + FreeDeviceList(m_list); + EnumerateUsbDevice( m_list, uiTotalDevice ); + + for ( iter = m_list.begin(); iter != m_list.end(); ) { + if( (iPos = FindConfigSetPos(m_deviceMscConfigSet, (*iter).usVid, (*iter).usPid)) != -1 ) { + (*iter).emDeviceType = RKNONE_DEVICE; + iter++; + continue; + } else if (IsRockusbDevice(devType, (*iter).usVid, (*iter).usPid) ) { + (*iter).emDeviceType = devType; + iter++; + continue; + } else { + if ((*iter).pUsbHandle) { + libusb_unref_device((libusb_device *)((*iter).pUsbHandle)); + (*iter).pUsbHandle = NULL; + } + iter = m_list.erase(iter); + uiTotalDevice--; + } + } + + if (m_list.size() <= 0) { + return 0; + } + + if ( (type & RKUSB_MASKROM) == 0 ) { + for ( iter = m_list.begin(); iter != m_list.end(); ) { + if( (IsRockusbDevice(devType, (*iter).usVid, (*iter).usPid)) && (((*iter).usbcdUsb & 0x1) == 0) ) { + if ((*iter).pUsbHandle) { + libusb_unref_device((libusb_device *)((*iter).pUsbHandle)); + (*iter).pUsbHandle = NULL; + } + iter = m_list.erase(iter); + uiTotalDevice--; + } else { + iter++; + continue; + } + } + } + if (m_list.size() <= 0) { + return 0; + } + + if ( (type & RKUSB_LOADER) == 0 ) { + for ( iter = m_list.begin(); iter != m_list.end(); ) { + if( (IsRockusbDevice(devType, (*iter).usVid, (*iter).usPid)) && (((*iter).usbcdUsb & 0x1) == 1) ) { + if ((*iter).pUsbHandle) { + libusb_unref_device((libusb_device *)((*iter).pUsbHandle)); + (*iter).pUsbHandle = NULL; + } + iter = m_list.erase(iter); + uiTotalDevice--; + } else { + iter++; + continue; + } + } + } + if (m_list.size() <= 0) { + return 0; + } + + if ( (type & RKUSB_MSC) == 0 ) { + for ( iter = m_list.begin(); iter != m_list.end(); ) { + if(FindConfigSetPos(m_deviceMscConfigSet, (*iter).usVid, (*iter).usPid) != -1) { + if ((*iter).pUsbHandle) { + libusb_unref_device((libusb_device *)((*iter).pUsbHandle)); + (*iter).pUsbHandle = NULL; + } + iter = m_list.erase(iter); + uiTotalDevice--; + } else { + iter++; + continue; + } + } + } + if (m_list.size() <= 0) { + return 0; + } + + for ( iter = m_list.begin(); iter != m_list.end(); iter++ ) { + if (FindConfigSetPos(m_deviceMscConfigSet, (*iter).usVid, (*iter).usPid) != -1) { + (*iter).emUsbType = RKUSB_MSC; + } else { + USHORT usTemp; + usTemp = (*iter).usbcdUsb; + usTemp= usTemp & 0x1; + if ( usTemp == 0 ) + (*iter).emUsbType = RKUSB_MASKROM; + else + (*iter).emUsbType = RKUSB_LOADER; + } + } + return m_list.size(); +} +bool CRKScan::MutexWait(UINT_VECTOR &vecExistedDevice, STRUCT_RKDEVICE_DESC &device, ENUM_RKUSB_TYPE usbType, USHORT usVid, USHORT usPid) +{ + device_list_iter iter; + int uiWaitSecond; + int iFoundCount = 0; + UINT iRet,i; + bool bFound = false; + if (usbType == RKUSB_MSC) + uiWaitSecond = m_waitMscSecond; + else + uiWaitSecond = m_waitRKusbSecond; + time_t tmInit, tmNow; + time(&tmInit); + device.uiLocationID = 0; + while( difftime(time(&tmNow), tmInit) <= uiWaitSecond ) { + iRet = Search(RKUSB_MASKROM | RKUSB_LOADER | RKUSB_MSC); + if ( iRet == vecExistedDevice.size() + 1 ) { + for (i = 0; i < vecExistedDevice.size(); i++) { + for (iter = m_list.begin(); iter != m_list.end(); ) { + if ((*iter).uiLocationID == vecExistedDevice[i]) { + iter = m_list.erase(iter); + } else + iter++; + } + } + if (m_list.size() != 1) { + device.uiLocationID = 0; + iFoundCount = 0; + } else { + iter = m_list.begin(); + if (device.uiLocationID == 0) { + iFoundCount++; + device.uiLocationID = (*iter).uiLocationID; + } else { + if (device.uiLocationID == (*iter).uiLocationID) { + iFoundCount++; + } else { + device.uiLocationID = 0; + iFoundCount = 0; + } + } + } + } else { + device.uiLocationID = 0; + iFoundCount = 0; + } + if (iFoundCount >= 10) { + bFound = true; + break; + } + } + if (!bFound) { + return false; + } + bFound = Wait(device, usbType, usVid, usPid); + return bFound; +} + +bool CRKScan::MutexWaitPrepare(UINT_VECTOR &vecExistedDevice, DWORD uiOfflineDevice) +{ + int iRet, iRet2; + device_list_iter iter; + time_t timeInit, timeNow; + time(&timeInit); + iRet = iRet2 =0; + while ((time(&timeNow) - timeInit) <= 3) { + iRet = Search(RKUSB_MASKROM | RKUSB_LOADER | RKUSB_MSC); + usleep(20000); + iRet2 = Search(RKUSB_MASKROM | RKUSB_LOADER | RKUSB_MSC); + if (iRet2 == iRet) { + break; + } + } + if ((iRet <= 0) || (iRet2 != iRet)) { + return false; + } + vecExistedDevice.clear(); + bool bFound = false; + for ( iter = m_list.begin(); iter != m_list.end(); iter++ ) { + if ((*iter).uiLocationID != uiOfflineDevice) { + vecExistedDevice.push_back((*iter).uiLocationID); + } else + bFound = true; + } + if (!bFound) { + return false; + } + return true; + +} + +bool CRKScan::Wait(STRUCT_RKDEVICE_DESC &device, ENUM_RKUSB_TYPE usbType, USHORT usVid, USHORT usPid) +{ + RKDEVICE_DESC_SET deviceList; + ENUM_RKUSB_TYPE curDeviceType; + ENUM_RKDEVICE_TYPE devType; + device_list_iter iter; + UINT totalDevice; + int uiWaitSecond; + int iFoundCount = 0; + bool bRet = false; + if (usbType == RKUSB_MSC) + uiWaitSecond = m_waitMscSecond; + else + uiWaitSecond = m_waitRKusbSecond; + time_t tmInit, tmNow; + time(&tmInit); + while( difftime(time(&tmNow), tmInit) <= uiWaitSecond ) { + FreeDeviceList(deviceList); + EnumerateUsbDevice(deviceList, totalDevice); + for ( iter = deviceList.begin(); iter != deviceList.end(); iter++ ) { + if ((BUSID((*iter).uiLocationID) != BUSID(device.uiLocationID)) || + ((BUSID((*iter).uiLocationID) == BUSID(device.uiLocationID)) && ((*iter).uiLocationID >= device.uiLocationID))) { + if ((usVid != 0) || (usPid != 0)) { + if ( ((*iter).usVid != usVid) || ((*iter).usPid != usPid) ) + continue; + } + if (IsRockusbDevice(devType, (*iter).usVid, (*iter).usPid)) { + if ( ((*iter).usbcdUsb & 0x0001) == 0 ) + curDeviceType = RKUSB_MASKROM; + else + curDeviceType = RKUSB_LOADER; + } else if ( FindConfigSetPos(m_deviceMscConfigSet, (*iter).usVid, (*iter).usPid) != -1 ) { + curDeviceType = RKUSB_MSC; + } else + curDeviceType = RKUSB_NONE; + + if ( curDeviceType == usbType ) { + iFoundCount++; + break; + } + } + } + if ( iter == deviceList.end() ) { + iFoundCount = 0; + } + if ( iFoundCount >= 8 ) { + device.usVid = (*iter).usVid; + device.usPid = (*iter).usPid; + device.uiLocationID = (*iter).uiLocationID; + device.pUsbHandle= (*iter).pUsbHandle; + device.emUsbType = usbType; + device.usbcdUsb = (*iter).usbcdUsb; + libusb_ref_device((libusb_device *)device.pUsbHandle); + + if (usbType == RKUSB_MSC) { + device.emDeviceType = RKNONE_DEVICE; + } else { + if (IsRockusbDevice(devType, device.usVid, device.usPid)) + device.emDeviceType = devType; + } + bRet = true; + break; + } + usleep(50000); + } + + FreeDeviceList(deviceList); + return bRet; +} +int CRKScan::GetPos(UINT locationID) +{ + device_list_iter iter; + int pos = 0; + bool bFound = false; + for (iter = m_list.begin(); iter != m_list.end(); iter++) { + if (locationID == (*iter).uiLocationID) { + bFound=true; + break; + } + pos++; + } + return (bFound ? pos : -1); +} +bool CRKScan::GetDevice(STRUCT_RKDEVICE_DESC &device, int pos) +{ + if ( (pos < 0) || (pos >= (int)m_list.size()) ) { + return false; + } + device_list_iter iter; + for (iter = m_list.begin(); iter != m_list.end(); iter++) { + if (pos == 0) { + break; + } + pos--; + } + device.usVid = (*iter).usVid; + device.usPid = (*iter).usPid; + device.emDeviceType = (*iter).emDeviceType; + device.emUsbType = (*iter).emUsbType; + device.uiLocationID = (*iter).uiLocationID; + device.pUsbHandle= (*iter).pUsbHandle; + device.usbcdUsb = (*iter).usbcdUsb; + return true; +} + +bool CRKScan::SetLogObject(CRKLog *pLog) +{ + if (pLog) { + if (m_log) { + delete m_log; + } + m_log = pLog; + } else + return false; + return true; +} +CRKScan::~CRKScan() +{ + FreeDeviceList(m_list); + if (m_log) { + delete m_log; + m_log = NULL; + } +} diff --git a/RKScan.h b/RKScan.h new file mode 100644 index 0000000..44f1f55 --- /dev/null +++ b/RKScan.h @@ -0,0 +1,52 @@ +#ifndef RKSCAN_HEADER +#define RKSCAN_HEADER +#include "DefineHeader.h" +#include "RKLog.h" + +typedef struct { + USHORT usVid; + USHORT usPid; + ENUM_RKDEVICE_TYPE emDeviceType; +} STRUCT_DEVICE_CONFIG, *PSTRUCT_DEVICE_CONFIG; + +typedef vector RKDEVICE_CONFIG_SET; +class CRKScan +{ +public: + UINT GetMSC_TIMEOUT(); + void SetMSC_TIMEOUT(UINT value); + property MSC_TIMEOUT; + + UINT GetRKUSB_TIMEOUT(); + void SetRKUSB_TIMEOUT(UINT value); + property RKUSB_TIMEOUT; + + int GetDEVICE_COUNTS(); + property DEVICE_COUNTS; + + CRKScan(UINT uiMscTimeout = 30, UINT uiRKusbTimeout = 20); + void SetVidPid(USHORT mscVid = 0, USHORT mscPid = 0); + void AddRockusbVidPid(USHORT newVid, USHORT newPid, USHORT oldVid, USHORT oldPid); + bool FindRockusbVidPid(ENUM_RKDEVICE_TYPE type, USHORT &usVid, USHORT &usPid); + int Search(UINT type); + bool Wait(STRUCT_RKDEVICE_DESC &device, ENUM_RKUSB_TYPE usbType, USHORT usVid = 0, USHORT usPid = 0); + bool MutexWaitPrepare(UINT_VECTOR &vecExistedDevice, DWORD uiOfflineDevice); + bool MutexWait(UINT_VECTOR &vecExistedDevice, STRUCT_RKDEVICE_DESC &device, ENUM_RKUSB_TYPE usbType, USHORT usVid = 0, USHORT usPid = 0); + int GetPos(UINT locationID); + bool GetDevice(STRUCT_RKDEVICE_DESC &device, int pos); + bool SetLogObject(CRKLog *pLog); + ~CRKScan(); +private: + UINT m_waitRKusbSecond; + UINT m_waitMscSecond; + CRKLog *m_log; + RKDEVICE_DESC_SET m_list; + RKDEVICE_CONFIG_SET m_deviceConfigSet; + RKDEVICE_CONFIG_SET m_deviceMscConfigSet; + int FindConfigSetPos(RKDEVICE_CONFIG_SET &devConfigSet, USHORT vid, USHORT pid); + int FindWaitSetPos(const RKDEVICE_CONFIG_SET &waitDeviceSet, USHORT vid, USHORT pid); + void EnumerateUsbDevice(RKDEVICE_DESC_SET &list, UINT &uiTotalMatchDevices); + void FreeDeviceList(RKDEVICE_DESC_SET &list); + bool IsRockusbDevice(ENUM_RKDEVICE_TYPE &type, USHORT vid, USHORT pid); +}; +#endif \ No newline at end of file diff --git a/Readme.txt b/Readme.txt new file mode 100644 index 0000000..df94fdb --- /dev/null +++ b/Readme.txt @@ -0,0 +1,17 @@ +rkDevelopTool gives you a simple way to read/write rockusb device.let's start. + +compile and install +1 download libusb source from https://github.com/libusb/libusb.git +2 go into root of libusb +3 ./autogen.sh (libudev must be installed by apt-get install libudev1 or run cmd "./configure --disable-udev") +4 make && make install +5 go into root of rkDevelopTool +6 make && make install + +rkDeveloptool usage,input "rkDevelopTool -h" to see + +example: +1.download kernel.img +./rkDevelopTool db RKXXLoader.bin //download usbcode to device +./rkDevelopTool wl 0x8000 kernel.img //0x8000 is base of kernel partition,unit is sector. +./rkDevelopTool rd //reset device \ No newline at end of file diff --git a/config.ini b/config.ini new file mode 100644 index 0000000..e69de29 diff --git a/crc.cpp b/crc.cpp new file mode 100644 index 0000000..73de7c2 --- /dev/null +++ b/crc.cpp @@ -0,0 +1,362 @@ +/* + * (C) Copyright 2017 Fuzhou Rockchip Electronics Co., Ltd + * Seth Liu 2017.03.01 + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include "DefineHeader.h" +UINT gTable_Crc32[256] = +{//crfc32 factor 0x04C10DB7 + 0x00000000, 0x04c10db7, 0x09821b6e, 0x0d4316d9, + 0x130436dc, 0x17c53b6b, 0x1a862db2, 0x1e472005, + 0x26086db8, 0x22c9600f, 0x2f8a76d6, 0x2b4b7b61, + 0x350c5b64, 0x31cd56d3, 0x3c8e400a, 0x384f4dbd, + 0x4c10db70, 0x48d1d6c7, 0x4592c01e, 0x4153cda9, + 0x5f14edac, 0x5bd5e01b, 0x5696f6c2, 0x5257fb75, + 0x6a18b6c8, 0x6ed9bb7f, 0x639aada6, 0x675ba011, + 0x791c8014, 0x7ddd8da3, 0x709e9b7a, 0x745f96cd, + 0x9821b6e0, 0x9ce0bb57, 0x91a3ad8e, 0x9562a039, + 0x8b25803c, 0x8fe48d8b, 0x82a79b52, 0x866696e5, + 0xbe29db58, 0xbae8d6ef, 0xb7abc036, 0xb36acd81, + 0xad2ded84, 0xa9ece033, 0xa4aff6ea, 0xa06efb5d, + 0xd4316d90, 0xd0f06027, 0xddb376fe, 0xd9727b49, + 0xc7355b4c, 0xc3f456fb, 0xceb74022, 0xca764d95, + 0xf2390028, 0xf6f80d9f, 0xfbbb1b46, 0xff7a16f1, + 0xe13d36f4, 0xe5fc3b43, 0xe8bf2d9a, 0xec7e202d, + 0x34826077, 0x30436dc0, 0x3d007b19, 0x39c176ae, + 0x278656ab, 0x23475b1c, 0x2e044dc5, 0x2ac54072, + 0x128a0dcf, 0x164b0078, 0x1b0816a1, 0x1fc91b16, + 0x018e3b13, 0x054f36a4, 0x080c207d, 0x0ccd2dca, + 0x7892bb07, 0x7c53b6b0, 0x7110a069, 0x75d1adde, + 0x6b968ddb, 0x6f57806c, 0x621496b5, 0x66d59b02, + 0x5e9ad6bf, 0x5a5bdb08, 0x5718cdd1, 0x53d9c066, + 0x4d9ee063, 0x495fedd4, 0x441cfb0d, 0x40ddf6ba, + 0xaca3d697, 0xa862db20, 0xa521cdf9, 0xa1e0c04e, + 0xbfa7e04b, 0xbb66edfc, 0xb625fb25, 0xb2e4f692, + 0x8aabbb2f, 0x8e6ab698, 0x8329a041, 0x87e8adf6, + 0x99af8df3, 0x9d6e8044, 0x902d969d, 0x94ec9b2a, + 0xe0b30de7, 0xe4720050, 0xe9311689, 0xedf01b3e, + 0xf3b73b3b, 0xf776368c, 0xfa352055, 0xfef42de2, + 0xc6bb605f, 0xc27a6de8, 0xcf397b31, 0xcbf87686, + 0xd5bf5683, 0xd17e5b34, 0xdc3d4ded, 0xd8fc405a, + 0x6904c0ee, 0x6dc5cd59, 0x6086db80, 0x6447d637, + 0x7a00f632, 0x7ec1fb85, 0x7382ed5c, 0x7743e0eb, + 0x4f0cad56, 0x4bcda0e1, 0x468eb638, 0x424fbb8f, + 0x5c089b8a, 0x58c9963d, 0x558a80e4, 0x514b8d53, + 0x25141b9e, 0x21d51629, 0x2c9600f0, 0x28570d47, + 0x36102d42, 0x32d120f5, 0x3f92362c, 0x3b533b9b, + 0x031c7626, 0x07dd7b91, 0x0a9e6d48, 0x0e5f60ff, + 0x101840fa, 0x14d94d4d, 0x199a5b94, 0x1d5b5623, + 0xf125760e, 0xf5e47bb9, 0xf8a76d60, 0xfc6660d7, + 0xe22140d2, 0xe6e04d65, 0xeba35bbc, 0xef62560b, + 0xd72d1bb6, 0xd3ec1601, 0xdeaf00d8, 0xda6e0d6f, + 0xc4292d6a, 0xc0e820dd, 0xcdab3604, 0xc96a3bb3, + 0xbd35ad7e, 0xb9f4a0c9, 0xb4b7b610, 0xb076bba7, + 0xae319ba2, 0xaaf09615, 0xa7b380cc, 0xa3728d7b, + 0x9b3dc0c6, 0x9ffccd71, 0x92bfdba8, 0x967ed61f, + 0x8839f61a, 0x8cf8fbad, 0x81bbed74, 0x857ae0c3, + 0x5d86a099, 0x5947ad2e, 0x5404bbf7, 0x50c5b640, + 0x4e829645, 0x4a439bf2, 0x47008d2b, 0x43c1809c, + 0x7b8ecd21, 0x7f4fc096, 0x720cd64f, 0x76cddbf8, + 0x688afbfd, 0x6c4bf64a, 0x6108e093, 0x65c9ed24, + 0x11967be9, 0x1557765e, 0x18146087, 0x1cd56d30, + 0x02924d35, 0x06534082, 0x0b10565b, 0x0fd15bec, + 0x379e1651, 0x335f1be6, 0x3e1c0d3f, 0x3add0088, + 0x249a208d, 0x205b2d3a, 0x2d183be3, 0x29d93654, + 0xc5a71679, 0xc1661bce, 0xcc250d17, 0xc8e400a0, + 0xd6a320a5, 0xd2622d12, 0xdf213bcb, 0xdbe0367c, + 0xe3af7bc1, 0xe76e7676, 0xea2d60af, 0xeeec6d18, + 0xf0ab4d1d, 0xf46a40aa, 0xf9295673, 0xfde85bc4, + 0x89b7cd09, 0x8d76c0be, 0x8035d667, 0x84f4dbd0, + 0x9ab3fbd5, 0x9e72f662, 0x9331e0bb, 0x97f0ed0c, + 0xafbfa0b1, 0xab7ead06, 0xa63dbbdf, 0xa2fcb668, + 0xbcbb966d, 0xb87a9bda, 0xb5398d03, 0xb1f880b4, +}; +#define rr_max 104 /* Number of parity checks, rr = deg[g(x)] */ +#define parallel 8 //bit count +#define mm 13//limit count +#define nn 8191//code size +#define kk 4120//info length +#define tt 8//correct count + +#define tt2 2*tt +UINT s[tt2+1]; // Syndrome values + +UINT rr;//redundant length // BCH code parameters + + +UINT p[mm + 1]; +UINT alpha_to[nn+1], index_of[nn+1] ; // Galois field +UINT gg[rr_max+1] ; // Generator polynomial + +UINT ggx1=0; +UINT ggx2=0; +UINT ggx3=0; +UINT ggx4=0; +// get crc32 value +UINT CRC_32(unsigned char* pData, UINT ulSize) +{ + UINT i; + UINT nAccum = 0; + + for ( i=0; i>24)^(*pData++)]; + return nAccum; +} +#define CRC16_CCITT 0x1021 //CRC operator +void CRCBuildTable16(unsigned short aPoly , unsigned short *crcTable) +{ + unsigned short i, j; + unsigned short nData; + unsigned short nAccum; + + for (i = 0; i < 256; i++) + { + nData = (unsigned short)(i << 8); + nAccum = 0; + for (j = 0; j < 8; j++) + { + if ((nData ^ nAccum) & 0x8000) + nAccum = (nAccum << 1) ^ aPoly; + else + nAccum <<= 1; + nData <<= 1; + } + crcTable[i] = nAccum; + } +} + +unsigned short CRC_16(unsigned char* aData, UINT aSize) +{ + UINT i; + unsigned short nAccum = 0; + unsigned short crcTable[256]; + + CRCBuildTable16(CRC16_CCITT , crcTable); + for (i = 0; i < aSize; i++) + nAccum = (nAccum << 8) ^ crcTable[(nAccum >> 8) ^ *aData++]; + + return nAccum; +} + +void P_RC4(unsigned char* buf, unsigned short len) +{ + unsigned char S[256],K[256],temp; + unsigned short i,j,t,x; + unsigned char key[16]={124,78,3,4,85,5,9,7,45,44,123,56,23,13,23,17}; + + j = 0; + for(i=0; i<256; i++){ + S[i] = (unsigned char)i; + j&=0x0f; + K[i] = key[j]; + j++; + } + + j = 0; + for(i=0; i<256; i++){ + j = (j + S[i] + K[i]) % 256; + temp = S[i]; + S[i] = S[j]; + S[j] = temp; + } + + i = j = 0; + for(x=0; x>j) & 1); + bch1=((bch1>>1)|((bch2&1)*0x80000000))^(ggx1*feed_back); + bch2=((bch2>>1)|((bch3&1)*0x80000000))^(ggx2*feed_back); + bch3=((bch3>>1)|((bch4&1)*0x80000000))^(ggx3*feed_back); + bch4=(((bch4>>1)^(ggx4*feed_back))) | (feed_back*0x80); + } + } + + //********Handle FF*********************** + bch1 = ~(bch1 ^ 0xad6273b1); + bch2 = ~(bch2 ^ 0x348393d2); + bch3 = ~(bch3 ^ 0xe6ebed3c); + bch4 = ~(bch4 ^ 0xc8); + //********************************************* + + for (i=0;i<515;i++) + encode_out[i] = encode_in[i]; + encode_out[515] = bch1&0x000000ff; + encode_out[516] = (bch1&0x0000ff00)>>8; + encode_out[517] = (bch1&0x00ff0000)>>16; + encode_out[518] = (bch1&0xff000000)>>24; + encode_out[519] = bch2&0x000000ff; + encode_out[520] = (bch2&0x0000ff00)>>8; + encode_out[521] = (bch2&0x00ff0000)>>16; + encode_out[522] = (bch2&0xff000000)>>24; + encode_out[523] = bch3&0x000000ff; + encode_out[524] = (bch3&0x0000ff00)>>8; + encode_out[525] = (bch3&0x00ff0000)>>16; + encode_out[526] = (bch3&0xff000000)>>24; + encode_out[527] = bch4&0x000000ff; +} + +#define poly16_CCITT 0x1021 /* crc-ccitt mask */ + +unsigned short CRC_Calculate(unsigned short crc, unsigned char ch) +{ + UINT i; + for(i=0x80; i!=0; i>>=1) + { + if((crc & 0x8000) != 0) + { + crc <<= 1; + crc ^= poly16_CCITT; + } + else + crc <<= 1; + if((ch & i)!=0) + crc ^= poly16_CCITT; + } + return crc; +} +unsigned short CRC_CCITT(unsigned char* p, UINT CalculateNumber) +{ + unsigned short crc = 0xffff; + while(CalculateNumber--) + { + crc = CRC_Calculate(crc, *p); + p++; + } + return crc; +} +void gen_poly() +{ + UINT gen_roots[nn + 1], gen_roots_true[nn + 1] ; // Roots of generator polynomial + UINT i, j, Temp ; + +// Initialization of gen_roots + for (i = 0; i <= nn; i++) + { gen_roots_true[i] = 0; + gen_roots[i] = 0; + } + +// Cyclotomic cosets of gen_roots + for (i = 1; i <= 2*tt ; i++) + { + for (j = 0; j < mm; j++) + { + Temp = ((1< 0; j--) + if (gg[j] != 0) + gg[j] = gg[j-1]^ alpha_to[(index_of[gg[j]] + index_of[alpha_to[gen_roots[i]]]) % nn] ; + else + gg[j] = gg[j-1] ; + gg[0] = alpha_to[(index_of[gg[0]] + index_of[alpha_to[gen_roots[i]]]) % nn] ; + } + +ggx1 = gg[103] | (gg[102]<<1) | (gg[101]<<2) | (gg[100]<<3) | (gg[99]<<4) |(gg[98]<<5)| (gg[97]<<6)|(gg[96]<<7) + | (gg[95]<<8) | (gg[94]<<9) | (gg[93]<<10) | (gg[92]<<11) |(gg[91]<<12)| (gg[90]<<13)|(gg[89]<<14) |(gg[88]<<15) + | (gg[87]<<16) | (gg[86]<<17) | (gg[85]<<18) | (gg[84]<<19) | (gg[83]<<20) |(gg[82]<<21)| (gg[81]<<22)|(gg[80]<<23) + | (gg[79]<<24) | (gg[78]<<25) | (gg[77]<<26) | (gg[76]<<27) |(gg[75]<<28)| (gg[74]<<29)|(gg[73]<<30) |(gg[72]<<31); +ggx2 = gg[71] | (gg[70]<<1) | (gg[69]<<2) | (gg[68]<<3) | (gg[67]<<4) |(gg[66]<<5)| (gg[65]<<6)|(gg[64]<<7) + | (gg[63]<<8) | (gg[62]<<9) | (gg[61]<<10) | (gg[60]<<11) |(gg[59]<<12)| (gg[58]<<13)|(gg[57]<<14) |(gg[56]<<15) + | (gg[55]<<16) | (gg[54]<<17) | (gg[53]<<18) | (gg[52]<<19) | (gg[51]<<20) |(gg[50]<<21)| (gg[49]<<22)|(gg[48]<<23) + | (gg[47]<<24) | (gg[46]<<25) | (gg[45]<<26) | (gg[44]<<27) |(gg[43]<<28)| (gg[42]<<29)|(gg[41]<<30) |(gg[40]<<31); +ggx3 = gg[39] | (gg[38]<<1) | (gg[37]<<2) | (gg[36]<<3) | (gg[35]<<4) |(gg[34]<<5)| (gg[33]<<6)|(gg[32]<<7) + | (gg[31]<<8) | (gg[30]<<9) | (gg[29]<<10) | (gg[28]<<11) |(gg[27]<<12)| (gg[26]<<13)|(gg[25]<<14) |(gg[24]<<15) + | (gg[23]<<16) | (gg[22]<<17) | (gg[21]<<18) | (gg[20]<<19) | (gg[19]<<20) |(gg[18]<<21)| (gg[17]<<22)|(gg[16]<<23) + | (gg[15]<<24) | (gg[14]<<25) | (gg[13]<<26) | (gg[12]<<27) |(gg[11]<<28)| (gg[10]<<29)|(gg[9]<<30) |(gg[8]<<31); +ggx4 = gg[7] | (gg[6]<<1) | (gg[5]<<2) | (gg[4]<<3) | (gg[3]<<4) |(gg[2]<<5)| (gg[1]<<6); + +} + +void generate_gf() +{ + UINT i; + UINT mask ; // Register states + + // Primitive polynomials + for (i = 1; i < mm; i++) + p[i] = 0; + p[0] = p[mm] = 1; + if (mm == 2) p[1] = 1; + else if (mm == 3) p[1] = 1; + else if (mm == 4) p[1] = 1; + else if (mm == 5) p[2] = 1; + else if (mm == 6) p[1] = 1; + else if (mm == 7) p[1] = 1; + else if (mm == 8) p[4] = p[5] = p[6] = 1; + else if (mm == 9) p[4] = 1; + else if (mm == 10) p[3] = 1; + else if (mm == 11) p[2] = 1; + else if (mm == 12) p[3] = p[4] = p[7] = 1; + else if (mm == 13) p[1] = p[2] = p[3] = p[5] = p[7] = p[8] = p[10] = 1; // 25AF + else if (mm == 14) p[2] = p[4] = p[6] = p[7] = p[8] = 1; // 41D5 + else if (mm == 15) p[1] = 1; + else if (mm == 16) p[2] = p[3] = p[5] = 1; + else if (mm == 17) p[3] = 1; + else if (mm == 18) p[7] = 1; + else if (mm == 19) p[1] = p[5] = p[6] = 1; + else if (mm == 20) p[3] = 1; + // Galois field implementation with shift registers + // Ref: L&C, Chapter 6.7, pp. 217 + mask = 1 ; + alpha_to[mm] = 0 ; + for (i = 0; i < mm; i++) + { + alpha_to[i] = mask ; + index_of[alpha_to[i]] = i ; + if (p[i] != 0) + alpha_to[mm] ^= mask ; + mask <<= 1 ; + } + + index_of[alpha_to[mm]] = mm ; + mask >>= 1 ; + for (i = mm + 1; i < nn; i++) + { + if (alpha_to[i-1] >= mask) + alpha_to[i] = alpha_to[mm] ^ ((alpha_to[i-1] ^ mask) << 1) ; + else + alpha_to[i] = alpha_to[i-1] << 1 ; + + index_of[alpha_to[i]] = i ; + } + index_of[0] = -1 ; +} \ No newline at end of file diff --git a/license.txt b/license.txt new file mode 100644 index 0000000..25e216a --- /dev/null +++ b/license.txt @@ -0,0 +1,339 @@ +GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..c90586b --- /dev/null +++ b/main.cpp @@ -0,0 +1,940 @@ +/* + * (C) Copyright 2017 Fuzhou Rockchip Electronics Co., Ltd + * Seth Liu 2017.03.01 + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include "DefineHeader.h" +#include "RKLog.h" +#include "RKScan.h" +#include "RKComm.h" +#include "RKDevice.h" +#include "RKImage.h" +extern const char *szManufName[]; +CRKLog *g_pLogObject=NULL; +CONFIG_ITEM_VECTOR g_ConfigItemVec; +#define DEFAULT_RW_LBA 128 +#define CURSOR_MOVEUP_LINE(n) printf("%c[%dA", 0x1B, n) +#define CURSOR_DEL_LINE printf("%c[2K", 0x1B) +#define CURSOR_MOVE_HOME printf("%c[H", 0x1B) +#define CURSOR_CLEAR_SCREEN printf("%c[2J", 0x1B) +#define ERROR_COLOR_ATTR printf("%c[30;41m", 0x1B); +#define NORMAL_COLOR_ATTR printf("%c[37;40m", 0x1B); +void usage() +{ + printf("\r\n---------------------Tool Usage ---------------------\r\n"); + printf("Help: -H\r\n"); + printf("Version: -V\r\n"); + printf("DownloadBoot: DB \r\n"); + printf("ReadLBA: RL \r\n"); + printf("WriteLBA: WL \r\n"); + printf("EraseFlash: EF \r\n"); + printf("TestDevice: TD\r\n"); + printf("ResetDevice: RD [subcode]\r\n"); + printf("ReadFlashID: RID\r\n"); + printf("ReadFlashInfo: RFI\r\n"); + printf("ReadChipInfo: RCI\r\n"); + printf("-------------------------------------------------------\r\n\r\n"); +} +void ProgressInfoProc(DWORD deviceLayer, ENUM_PROGRESS_PROMPT promptID, long long totalValue, long long currentValue, ENUM_CALL_STEP emCall) +{ + string strInfoText=""; + char szText[256]; + switch (promptID) { + case TESTDEVICE_PROGRESS: + sprintf(szText, "Test Device Total(%lld),Current(%lld)", totalValue, currentValue); + strInfoText = szText; + break; + case LOWERFORMAT_PROGRESS: + sprintf(szText, "Lowerformat Device Total(%lld),Current(%lld)", totalValue, currentValue); + strInfoText = szText; + break; + case DOWNLOADIMAGE_PROGRESS: + sprintf(szText, "Download Image Total(%lldK),Current(%lldK)", totalValue/1024, currentValue/1024); + strInfoText = szText; + break; + case CHECKIMAGE_PROGRESS: + sprintf(szText, "Check Image Total(%lldK),Current(%lldK)", totalValue/1024, currentValue/1024); + strInfoText = szText; + break; + case TAGBADBLOCK_PROGRESS: + sprintf(szText, "Tag Bad Block Total(%lld),Current(%lld)", totalValue, currentValue); + strInfoText = szText; + break; + case TESTBLOCK_PROGRESS: + sprintf(szText, "Test Block Total(%lld),Current(%lld)", totalValue, currentValue); + strInfoText = szText; + break; + case ERASEFLASH_PROGRESS: + sprintf(szText, "Erase Flash Total(%lld),Current(%lld)", totalValue, currentValue); + strInfoText = szText; + break; + case ERASESYSTEM_PROGRESS: + sprintf(szText, "Erase System partition Total(%lld),Current(%lld)", totalValue, currentValue); + strInfoText = szText; + break; + case ERASEUSERDATA_PROGRESS: + sprintf(szText, " Erase Userdata partition Total(%lld),Current(%lld)",deviceLayer,totalValue, currentValue); + strInfoText = szText; + break; + } + if (strInfoText.size() > 0){ + CURSOR_MOVEUP_LINE(1); + CURSOR_DEL_LINE; + printf("%s\r\n", strInfoText.c_str()); + } + if (emCall == CALL_LAST) + deviceLayer = 0; +} + +char *strupr(char *szSrc) +{ + char *p = szSrc; + while(*p){ + if ((*p >= 'a') && (*p <= 'z')) + *p = *p - 'a' + 'A'; + p++; + } + return szSrc; +} +void PrintData(PBYTE pData, int nSize) +{ + char szPrint[17] = "\0"; + int i; + for( i = 0; i < nSize; i++){ + if(i % 16 == 0){ + if(i / 16 > 0) + printf(" %s\r\n", szPrint); + printf("%08d ", i / 16); + } + printf("%02X ", pData[i]); + szPrint[i%16] = isprint(pData[i]) ? pData[i] : '.'; + } + if(i / 16 > 0) + printf(" %s\r\n", szPrint); +} + +bool StringToWideString(char *pszSrc, wchar_t *&pszDest) +{ + if (!pszSrc) + return false; + int nSrcLen = strlen(pszSrc); + int nDestLen = nSrcLen * 2; + + pszDest = NULL; + pszDest = new wchar_t[nDestLen]; + if (!pszDest) + return false; + nDestLen = nDestLen * sizeof(wchar_t); + memset(pszDest, 0, nDestLen); + int iRet; + iconv_t cd; + cd = iconv_open("UTF-32", "UTF-8"); + if((iconv_t)-1 == cd) { + delete []pszDest; + pszDest = NULL; + return false; + } + char *pIn, *pOut; + pIn = (char *)pszSrc; + pOut = (char *)pszDest; + + iRet = iconv(cd, (char **)&pIn, (size_t *)&nSrcLen, (char **)&pOut, (size_t *)&nDestLen); + + if(iRet == -1) { + delete []pszDest; + pszDest = NULL; + iconv_close(cd); + return false; + } + + iconv_close(cd); + + return true; +} +bool WideStringToString(wchar_t *pszSrc, char *&pszDest) +{ + if (!pszSrc) + return false; + int nSrcLen = wcslen(pszSrc); + int nDestLen = nSrcLen * 2; + nSrcLen = nSrcLen * sizeof(wchar_t); + pszDest = NULL; + pszDest = new char[nDestLen]; + if (!pszDest) + return false; + memset(pszDest, 0, nDestLen); + int iRet; + iconv_t cd; + cd = iconv_open("UTF-8", "UTF-32"); + + if((iconv_t)-1 == cd) { + delete []pszDest; + pszDest = NULL; + return false; + } + char *pIn, *pOut; + pIn = (char *)pszSrc; + pOut = (char *)pszDest; + iRet = iconv(cd, (char **)&pIn, (size_t *)&nSrcLen, (char **)&pOut, (size_t *)&nDestLen); + + if(iRet == -1) { + delete []pszDest; + pszDest = NULL; + iconv_close(cd); + return false; + } + + iconv_close(cd); + + return true; +} +int find_config_item(const char *pszName) +{ + unsigned int i; + for(i = 0; i < g_ConfigItemVec.size(); i++){ + if (strcasecmp(pszName, g_ConfigItemVec[i].szItemName) == 0){ + return i; + } + } + return -1; +} + +bool parse_config(char *pConfig, CONFIG_ITEM_VECTOR &vecItem) +{ + + stringstream configStream(pConfig); + string strLine, strItemName, strItemValue; + string::size_type line_size,pos; + STRUCT_CONFIG_ITEM item; + vecItem.clear(); + while (!configStream.eof()){ + getline(configStream, strLine); + line_size = strLine.size(); + if (line_size == 0) + continue; + if (strLine[line_size-1] == '\r'){ + strLine = strLine.substr(0, line_size-1); + } + pos = strLine.find("="); + if (pos == string::npos){ + continue; + } + strItemName = strLine.substr(0, pos); + strItemValue = strLine.substr(pos + 1); + strItemName.erase(0, strItemName.find_first_not_of(" ")); + strItemName.erase(strItemName.find_last_not_of(" ") + 1); + strItemValue.erase(0, strItemValue.find_first_not_of(" ")); + strItemValue.erase(strItemValue.find_last_not_of(" ") + 1); + if ((strItemName.size() > 0) && (strItemValue.size() > 0)){ + strcpy(item.szItemName, strItemName.c_str()); + strcpy(item.szItemValue, strItemValue.c_str()); + vecItem.push_back(item); + } + } + return true; + +} +bool parse_config_file(const char *pConfigFile, CONFIG_ITEM_VECTOR &vecItem) +{ + FILE *file = NULL; + file = fopen(pConfigFile, "rb"); + if( !file ){ + if (g_pLogObject) + g_pLogObject->Record("parse_config_file failed,err=%d,can't open file: %s\r\n", errno, pConfigFile); + return false; + } + int iFileSize; + fseek(file, 0, SEEK_END); + iFileSize = ftell(file); + fseek(file, 0, SEEK_SET); + char *pConfigBuf = NULL; + pConfigBuf = new char[iFileSize + 1]; + if (!pConfigBuf){ + fclose(file); + return false; + } + memset(pConfigBuf, 0, iFileSize + 1); + int iRead; + iRead = fread(pConfigBuf, 1, iFileSize, file); + if (iRead != iFileSize){ + if (g_pLogObject) + g_pLogObject->Record("parse_config_file failed,err=%d, read=%d, total=%d\r\n", errno, iRead, iFileSize); + fclose(file); + delete []pConfigBuf; + return false; + } + fclose(file); + bool bRet; + bRet = parse_config(pConfigBuf, vecItem); + delete []pConfigBuf; + return bRet; +} + +bool check_device_type(STRUCT_RKDEVICE_DESC &dev, UINT uiSupportType) +{ + if ((dev.emUsbType & uiSupportType) == dev.emUsbType) + return true; + else + { + ERROR_COLOR_ATTR; + printf("The Device did not support this operation!"); + NORMAL_COLOR_ATTR; + printf("\r\n"); + return false; + } +} + +bool download_boot(STRUCT_RKDEVICE_DESC &dev, char *szLoader) +{ + if (!check_device_type(dev, RKUSB_MASKROM)) + return false; + CRKImage *pImage = NULL; + CRKBoot *pBoot = NULL; + bool bRet, bSuccess = false; + int iRet; + + pImage = new CRKImage(szLoader, bRet); + if (!bRet){ + ERROR_COLOR_ATTR; + printf("Open loader failed,exit download boot!"); + NORMAL_COLOR_ATTR; + printf("\r\n"); + return bSuccess; + } else { + pBoot = (CRKBoot *)pImage->m_bootObject; + CRKComm *pComm = NULL; + CRKDevice *pDevice = NULL; + + dev.emDeviceType = pBoot->SupportDevice; + pComm = new CRKUsbComm(dev, g_pLogObject, bRet); + if (!bRet) { + if (pImage) + delete pImage; + ERROR_COLOR_ATTR; + printf("Creating Comm Object failed!"); + NORMAL_COLOR_ATTR; + printf("\r\n"); + return bSuccess; + } + + pDevice = new CRKDevice(dev); + if (!pDevice) { + if (pImage) + delete pImage; + if (pComm) + delete pComm; + ERROR_COLOR_ATTR; + printf("Creating device object failed!"); + NORMAL_COLOR_ATTR; + printf("\r\n"); + return bSuccess; + } + + pDevice->SetObject(pImage, pComm, g_pLogObject); + printf("Download boot...\r\n"); + iRet = pDevice->DownloadBoot(); + + CURSOR_MOVEUP_LINE(1); + CURSOR_DEL_LINE; + if (iRet == 0) { + pComm->Reset_Usb_Device(); + CRKScan *pScan = NULL; + pScan = new CRKScan(); + if (pScan) { + pScan->SetVidPid(); + pScan->Wait(dev, RKUSB_MASKROM, dev.usVid, dev.usPid); + delete pScan; + } + bSuccess = true; + printf("Download boot ok.\r\n"); + } + else + printf("Download boot failed!\r\n"); + + if (pImage) + delete pImage; + if(pDevice) + delete pDevice; + } + return bSuccess; +} +bool erase_flash(STRUCT_RKDEVICE_DESC &dev) +{ + if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM)) + return false; + CRKImage *pImage = NULL; + bool bRet, bSuccess = false; + int iRet; + CRKScan *pScan = NULL; + pScan = new CRKScan(); + pScan->SetVidPid(); + + CRKComm *pComm = NULL; + CRKDevice *pDevice = NULL; + + pComm = new CRKUsbComm(dev, g_pLogObject, bRet); + if (!bRet) { + if (pScan) + delete pScan; + ERROR_COLOR_ATTR; + printf("Creating Comm Object failed!"); + NORMAL_COLOR_ATTR; + printf("\r\n"); + return bSuccess; + } + + pDevice = new CRKDevice(dev); + if (!pDevice) { + if (pComm) + delete pComm; + if (pScan) + delete pScan; + ERROR_COLOR_ATTR; + printf("Creating device object failed!"); + NORMAL_COLOR_ATTR; + printf("\r\n"); + return bSuccess; + } + + pDevice->SetObject(pImage, pComm, g_pLogObject); + pDevice->CallBackPointer = ProgressInfoProc; + + printf("Start to erase flash...\r\n"); + iRet = pDevice->EraseAllBlocks(); + if (pDevice) + delete pDevice; + + if (iRet == 0) { + if (pScan) { + pScan->SetVidPid(); + pScan->Wait(dev, RKUSB_MASKROM, dev.usVid, dev.usPid); + delete pScan; + } + CURSOR_MOVEUP_LINE(1); + CURSOR_DEL_LINE; + bSuccess = true; + printf("Erase flash ok.\r\n"); + } + + return bSuccess; +} + +bool test_device(STRUCT_RKDEVICE_DESC &dev) +{ + if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM)) + return false; + CRKUsbComm *pComm = NULL; + bool bRet, bSuccess = false; + int iRet; + pComm = new CRKUsbComm(dev, g_pLogObject, bRet); + if (bRet) { + iRet = pComm->RKU_TestDeviceReady(); + if (iRet != ERR_SUCCESS) { + if (g_pLogObject) + g_pLogObject->Record("Error:RKU_TestDeviceReady failed,err=%d", iRet); + printf("Test Device Fail!\r\n"); + } else { + bSuccess = true; + printf("Test Device OK.\r\n"); + } + } else { + printf("Test Device quit,Creating comm object failed!\r\n"); + } + if (pComm) { + delete pComm; + pComm = NULL; + } + return bSuccess; +} +bool reset_device(STRUCT_RKDEVICE_DESC &dev, BYTE subCode = RST_NONE_SUBCODE) +{ + if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM)) + return false; + CRKUsbComm *pComm = NULL; + bool bRet, bSuccess = false; + int iRet; + pComm = new CRKUsbComm(dev, g_pLogObject, bRet); + if (bRet) { + iRet = pComm->RKU_ResetDevice(subCode); + if (iRet != ERR_SUCCESS) { + if (g_pLogObject) + g_pLogObject->Record("Error:RKU_ResetDevice failed,err=%d", iRet); + printf("Reset Device Fail!\r\n"); + } else { + bSuccess = true; + printf("Reset Device OK.\r\n"); + } + } else { + printf("Reset Device quit,Creating comm object failed!\r\n"); + } + if (pComm) { + delete pComm; + pComm = NULL; + } + return bSuccess; +} + +bool read_flash_id(STRUCT_RKDEVICE_DESC &dev) +{ + CRKUsbComm *pComm = NULL; + bool bRet, bSuccess = false; + int iRet; + if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM)) + return bSuccess; + + pComm = new CRKUsbComm(dev, g_pLogObject, bRet); + if (bRet) { + BYTE flashID[5]; + iRet = pComm->RKU_ReadFlashID(flashID); + if (iRet != ERR_SUCCESS) { + if (g_pLogObject) + g_pLogObject->Record("Error:RKU_ReadFlashID failed,err=%d", iRet); + printf("Read flash ID Fail!\r\n"); + } else { + printf("Flash ID:%02X %02X %02X %02X %02X \r\n", flashID[0], flashID[1], flashID[2], flashID[3], flashID[4]); + bSuccess = true; + } + } else { + printf("Read flash ID quit,Creating comm object failed!\r\n"); + } + if (pComm) { + delete pComm; + pComm = NULL; + } + return bSuccess; +} +bool read_flash_info(STRUCT_RKDEVICE_DESC &dev) +{ + CRKUsbComm *pComm = NULL; + bool bRet, bSuccess = false; + int iRet; + if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM)) + return bSuccess; + + pComm = new CRKUsbComm(dev, g_pLogObject, bRet); + if (bRet) { + STRUCT_FLASHINFO_CMD info; + UINT uiRead; + iRet = pComm->RKU_ReadFlashInfo((BYTE *)&info, &uiRead); + if (iRet != ERR_SUCCESS) { + if (g_pLogObject) + g_pLogObject->Record("Error:RKU_ReadFlashInfo failed,err=%d", iRet); + printf("Read flash Info Fail!\r\n"); + } else { + printf("Flash Info:\r\n"); + if (info.bManufCode <= 7) { + printf("\tManufacturer: %s,value=%02X\r\n", szManufName[info.bManufCode], info.bManufCode); + } + else + printf("\tManufacturer: %s,value=%02X\r\n", "Unknown", info.bManufCode); + + printf("\tFlash Size: %dMB\r\n", info.uiFlashSize / 2 / 1024); + printf("\tBlock Size: %dKB\r\n", info.usBlockSize / 2); + printf("\tPage Size: %dKB\r\n", info.bPageSize / 2); + printf("\tECC Bits: %d\r\n", info.bECCBits); + printf("\tAccess Time: %d\r\n", info.bAccessTime); + printf("\tFlash CS: "); + for(int i = 0; i < 8; i++) { + if( info.bFlashCS & (1 << i) ) + printf("Flash<%d> ", i); + } + printf("\r\n"); + bSuccess = true; + } + }else { + printf("Read flash Info quit,Creating comm object failed!\r\n"); + } + if (pComm) { + delete pComm; + pComm = NULL; + } + return bSuccess; +} +bool read_chip_info(STRUCT_RKDEVICE_DESC &dev) +{ + CRKUsbComm *pComm = NULL; + bool bRet, bSuccess = false; + int iRet; + if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM)) + return bSuccess; + + pComm = new CRKUsbComm(dev, g_pLogObject, bRet); + if (bRet) { + BYTE chipInfo[16]; + iRet = pComm->RKU_ReadChipInfo(chipInfo); + if (iRet != ERR_SUCCESS) { + if (g_pLogObject) + g_pLogObject->Record("Error:RKU_ReadChipInfo failed,err=%d", iRet); + printf("Read Chip Info Fail!\r\n"); + } else { + string strChipInfo; + g_pLogObject->PrintBuffer(strChipInfo, chipInfo, 16, 16); + printf("Chip Info:%s\r\n", strChipInfo.c_str()); + bSuccess = true; + } + } else { + printf("Read Chip Info quit,Creating comm object failed!\r\n"); + } + if (pComm) { + delete pComm; + pComm = NULL; + } + return bSuccess; +} +bool read_lba(STRUCT_RKDEVICE_DESC &dev, UINT uiBegin, UINT uiLen, char *szFile) +{ + if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM)) + return false; + CRKUsbComm *pComm = NULL; + FILE *file = NULL; + bool bRet, bFirst = true, bSuccess = false; + int iRet; + UINT iTotalRead = 0,iRead = 0; + int nSectorSize = 512; + BYTE pBuf[nSectorSize * DEFAULT_RW_LBA]; + pComm = new CRKUsbComm(dev, g_pLogObject, bRet); + if (bRet) { + if(szFile) { + file = fopen(szFile, "wb+"); + if( !file ) { + printf("Read LBA failed,err=%d,can't open file: %s\r\n", errno, szFile); + goto Exit_ReadLBA; + } + } + + while(uiLen > 0) { + memset(pBuf, 0, nSectorSize * DEFAULT_RW_LBA); + iRead = (uiLen >= DEFAULT_RW_LBA) ? DEFAULT_RW_LBA : uiLen; + iRet = pComm->RKU_ReadLBA( uiBegin + iTotalRead, iRead, pBuf); + if(ERR_SUCCESS == iRet) { + uiLen -= iRead; + iTotalRead += iRead; + + if(szFile) { + fwrite(pBuf, 1, iRead * nSectorSize, file); + if (bFirst){ + if (iTotalRead >= 1024) + printf("Read LBA from file (%d%%)\r\n", (iTotalRead / 1024) * 100 / ((uiLen + iTotalRead) / 1024)); + else + printf("Read LBA from file %d%%)\r\n", iTotalRead * 100 / (uiLen + iTotalRead)); + bFirst = false; + } else { + CURSOR_MOVEUP_LINE(1); + CURSOR_DEL_LINE; + if (iTotalRead >= 1024) + printf("Read LBA from file (%d%%)\r\n", (iTotalRead / 1024) * 100 / ((uiLen + iTotalRead) / 1024)); + else + printf("Read LBA from file %d%%)\r\n", iTotalRead * 100 / (uiLen + iTotalRead)); + } + } + else + PrintData(pBuf, nSectorSize * iRead); + } else { + if (g_pLogObject) + g_pLogObject->Record("Error:RKU_ReadLBA failed,err=%d", iRet); + + printf("Read LBA failed!\r\n"); + goto Exit_ReadLBA; + } + } + bSuccess = true; + } else { + printf("Read LBA quit,Creating comm object failed!\r\n"); + } +Exit_ReadLBA: + if (pComm) { + delete pComm; + pComm = NULL; + } + if (file) + fclose(file); + return bSuccess; +} +bool write_lba(STRUCT_RKDEVICE_DESC &dev, UINT uiBegin, char *szFile) +{ + if (!check_device_type(dev, RKUSB_LOADER | RKUSB_MASKROM)) + return false; + CRKUsbComm *pComm = NULL; + FILE *file = NULL; + bool bRet, bFirst = true, bSuccess = false; + int iRet; + long long iTotalWrite = 0, iFileSize = 0; + UINT iWrite = 0, iRead = 0; + UINT uiLen; + int nSectorSize = 512; + BYTE pBuf[nSectorSize * DEFAULT_RW_LBA]; + + pComm = new CRKUsbComm(dev, g_pLogObject, bRet); + if (bRet) { + file = fopen(szFile, "rb"); + if( !file ) { + printf("Write LBA failed,err=%d,can't open file: %s\r\n", errno, szFile); + goto Exit_WriteLBA; + } + + iRet = fseeko(file, 0, SEEK_END); + iFileSize = ftello(file); + fseeko(file, 0, SEEK_SET); + while(iTotalWrite < iFileSize) { + memset(pBuf, 0, nSectorSize * DEFAULT_RW_LBA); + iWrite = iRead= fread(pBuf, 1, nSectorSize * DEFAULT_RW_LBA, file); + if ((int)iRead != nSectorSize * DEFAULT_RW_LBA) { + printf("Write LBA failed,err=%d,read=%d,total=%d!\r\n", errno, iRead, nSectorSize * DEFAULT_RW_LBA); + goto Exit_WriteLBA; + } + uiLen = ((iWrite % 512) == 0) ? (iWrite / 512) : (iWrite / 512 + 1); + iRet = pComm->RKU_WriteLBA( uiBegin, uiLen, pBuf); + if(ERR_SUCCESS == iRet) { + uiBegin += uiLen; + iTotalWrite += iWrite; + if (bFirst) { + if (iTotalWrite >= 1024) + printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024)); + else + printf("Write LBA from file %lld%%)\r\n", iTotalWrite * 100 / iFileSize); + bFirst = false; + } else { + CURSOR_MOVEUP_LINE(1); + CURSOR_DEL_LINE; + printf("Write LBA from file (%lld%%)\r\n", (iTotalWrite / 1024) * 100 / (iFileSize / 1024)); + } + } else { + if (g_pLogObject) + g_pLogObject->Record("Error:RKU_WriteLBA failed,err=%d", iRet); + + printf("Write LBA failed!\r\n"); + goto Exit_WriteLBA; + } + } + bSuccess = true; + } else { + printf("Write LBA quit,Creating comm object failed!\r\n"); + } +Exit_WriteLBA: + if (pComm) { + delete pComm; + pComm = NULL; + } + if (file) + fclose(file); + return bSuccess; +} + +void split_item(STRING_VECTOR &vecItems, char *pszItems) +{ + string strItem; + char szItem[100]; + char *pos = NULL, *pStart; + pStart = pszItems; + pos = strchr(pStart, ','); + while(pos != NULL) { + memset(szItem, 0, 100); + strncpy(szItem, pStart, pos - pStart); + strItem = szItem; + vecItems.push_back(strItem); + pStart = pos + 1; + if (*pStart == 0) + break; + pos = strchr(pStart, ','); + } + if (strlen(pStart) > 0) { + memset(szItem, 0, 100); + strncpy(szItem, pStart, strlen(pStart)); + strItem = szItem; + vecItems.push_back(strItem); + } +} +bool handle_command(int argc, char* argv[], CRKScan *pScan) +{ + string strCmd; + strCmd = argv[1]; + ssize_t cnt; + bool bRet,bSuccess = false; + int ret; + STRUCT_RKDEVICE_DESC dev; + + transform(strCmd.begin(), strCmd.end(), strCmd.begin(), (int(*)(int))toupper); + if(strcmp(strCmd.c_str(), "-H") == 0) { + usage(); + return true; + } else if(strcmp(strCmd.c_str(), "-V") == 0) { + printf("rkDevelopTool ver 1.0\r\n"); + return true; + } + cnt = pScan->Search(RKUSB_MASKROM | RKUSB_LOADER); + if (cnt < 1) { + ERROR_COLOR_ATTR; + printf("No found any rockusb device,please plug device in!"); + NORMAL_COLOR_ATTR; + printf("\r\n"); + return bSuccess; + } else if (cnt > 1) { + ERROR_COLOR_ATTR; + printf("Found many rockusb devices,please plug device out!"); + NORMAL_COLOR_ATTR; + printf("\r\n"); + return bSuccess; + } + + bRet = pScan->GetDevice(dev, 0); + if (!bRet) { + ERROR_COLOR_ATTR; + printf("Getting information of rockusb device failed!"); + NORMAL_COLOR_ATTR; + printf("\r\n"); + return bSuccess; + } + + if(strcmp(strCmd.c_str(), "RD") == 0) { + if ((argc != 2) && (argc != 3)) + printf("Parameter of [RD] command is invalid,please check help!\r\n"); + else { + if (argc == 2) + bSuccess = reset_device(dev); + else { + UINT uiSubCode; + char *pszEnd; + uiSubCode = strtoul(argv[2], &pszEnd, 0); + if (*pszEnd) + printf("Subcode is invalid,please check!\r\n"); + else { + if (uiSubCode <= 5) + bSuccess = reset_device(dev, uiSubCode); + else + printf("Subcode is invalid,please check!\r\n"); + } + } + } + } else if(strcmp(strCmd.c_str(), "TD") == 0) { + bSuccess = test_device(dev); + } else if (strcmp(strCmd.c_str(), "RID") == 0) {//Read Flash ID + bSuccess = read_flash_id(dev); + } else if (strcmp(strCmd.c_str(), "RFI") == 0){//Read Flash Info + bSuccess = read_flash_info(dev); + } else if (strcmp(strCmd.c_str(), "RCI") == 0) {//Read Chip Info + bSuccess = read_chip_info(dev); + } else if(strcmp(strCmd.c_str(), "DB") == 0) { + if (argc > 2) { + string strLoader; + strLoader = argv[2]; + bSuccess = download_boot(dev, (char *)strLoader.c_str()); + } else if (argc == 2) { + ret = find_config_item("loader"); + if (ret == -1) + printf("No found loader item from config!\r\n"); + else + bSuccess = download_boot(dev, g_ConfigItemVec[ret].szItemValue); + } else + printf("Parameter of [DB] command is invalid,please check help!\r\n"); + } else if(strcmp(strCmd.c_str(), "EF") == 0) { + if (argc == 2) { + bSuccess = erase_flash(dev); + } else + printf("Parameter of [EF] command is invalid,please check help!\r\n"); + } else if(strcmp(strCmd.c_str(), "WL") == 0) { + if (argc == 4) { + UINT uiBegin; + char *pszEnd; + uiBegin = strtoul(argv[2], &pszEnd, 0); + if (*pszEnd) + printf("Begin is invalid,please check!\r\n"); + else + bSuccess = write_lba(dev, uiBegin, argv[3]); + } else + printf("Parameter of [WL] command is invalid,please check help!\r\n"); + } else if (strcmp(strCmd.c_str(), "RL") == 0) {//Read LBA + char *pszEnd; + UINT uiBegin, uiLen; + if (argc != 5) + printf("Parameter of [RL] command is invalid,please check help!\r\n"); + else { + uiBegin = strtoul(argv[2], &pszEnd, 0); + if (*pszEnd) + printf("Begin is invalid,please check!\r\n"); + else { + uiLen = strtoul(argv[3], &pszEnd, 0); + if (*pszEnd) + printf("Len is invalid,please check!\r\n"); + else { + bSuccess = read_lba(dev, uiBegin, uiLen, argv[4]); + } + } + } + } else { + printf("command is invalid,please press upgrade_tool -h to check usage!\r\n"); + } + return bSuccess; +} + + + +int main(int argc, char* argv[]) +{ + CRKScan *pScan = NULL; + int ret; + char szProgramProcPath[100]; + char szProgramDir[256]; + string strLogDir,strConfigFile; + struct stat statBuf; + + g_ConfigItemVec.clear(); + sprintf(szProgramProcPath, "/proc/%d/exe", getpid()); + if (readlink(szProgramProcPath, szProgramDir, 256) == -1) + strcpy(szProgramDir, "."); + else { + char *pSlash; + pSlash = strrchr(szProgramDir, '/'); + if (pSlash) + *pSlash = '\0'; + } + strLogDir = szProgramDir; + strLogDir += "/log/"; + strConfigFile = szProgramDir; + strConfigFile += "/config.ini"; + if (opendir(strLogDir.c_str()) == NULL) + mkdir(strLogDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH); + g_pLogObject = new CRKLog(strLogDir.c_str(), "log"); + + if(stat(strConfigFile.c_str(), &statBuf) < 0) { + if (g_pLogObject) { + g_pLogObject->Record("Error:failed to stat config.ini,err=%d", errno); + } + } else if (S_ISREG(statBuf.st_mode)) { + parse_config_file(strConfigFile.c_str(), g_ConfigItemVec); + } + + ret = libusb_init(NULL); + if (ret < 0) { + if (g_pLogObject) { + g_pLogObject->Record("Error:libusb_init failed,err=%d", ret); + delete g_pLogObject; + } + return -1; + } + + pScan = new CRKScan(); + if (!pScan) { + if (g_pLogObject) { + g_pLogObject->Record("Error:failed to Create object for searching device"); + delete g_pLogObject; + } + libusb_exit(NULL); + return -2; + } + pScan->SetVidPid(); + + if (argc == 1) + usage(); + else if (!handle_command(argc, argv, pScan)) + return -0xFF; + if (pScan) + delete pScan; + if (g_pLogObject) + delete g_pLogObject; + libusb_exit(NULL); + return 0; +}