From 76af099afcbcafd97801028de2ba3421d3c12865 Mon Sep 17 00:00:00 2001 From: liuyi Date: Tue, 7 Mar 2017 16:12:52 +0800 Subject: [PATCH] rkDevelopTool: initial commit Signed-off-by: liuyi --- DefineHeader.h | 117 ++++++ Endian.h | 21 ++ Makefile | 24 ++ Property.hpp | 94 +++++ RKBoot.cpp | 314 +++++++++++++++++ RKBoot.h | 91 +++++ RKComm.cpp | 710 +++++++++++++++++++++++++++++++++++++ RKComm.h | 170 +++++++++ RKDevice.cpp | 643 +++++++++++++++++++++++++++++++++ RKDevice.h | 128 +++++++ RKImage.cpp | 298 ++++++++++++++++ RKImage.h | 77 ++++ RKLog.cpp | 121 +++++++ RKLog.h | 41 +++ RKScan.cpp | 614 ++++++++++++++++++++++++++++++++ RKScan.h | 52 +++ Readme.txt | 17 + config.ini | 0 crc.cpp | 362 +++++++++++++++++++ license.txt | 339 ++++++++++++++++++ main.cpp | 940 +++++++++++++++++++++++++++++++++++++++++++++++++ 21 files changed, 5173 insertions(+) create mode 100644 DefineHeader.h create mode 100644 Endian.h create mode 100644 Makefile create mode 100644 Property.hpp create mode 100644 RKBoot.cpp create mode 100644 RKBoot.h create mode 100644 RKComm.cpp create mode 100644 RKComm.h create mode 100644 RKDevice.cpp create mode 100644 RKDevice.h create mode 100644 RKImage.cpp create mode 100644 RKImage.h create mode 100644 RKLog.cpp create mode 100644 RKLog.h create mode 100644 RKScan.cpp create mode 100644 RKScan.h create mode 100644 Readme.txt create mode 100644 config.ini create mode 100644 crc.cpp create mode 100644 license.txt create mode 100644 main.cpp 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; +}