rkDevelopTool: initial commit

Signed-off-by: liuyi <liuyi@rock-chips.com>
This commit is contained in:
liuyi 2017-03-07 16:12:52 +08:00
commit 76af099afc
21 changed files with 5173 additions and 0 deletions

117
DefineHeader.h Normal file
View File

@ -0,0 +1,117 @@
#ifndef DEFINE_HEADER
#define DEFINE_HEADER
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <sys/stat.h>
#include <dirent.h>
#include <time.h>
#include <unistd.h>
#include <iconv.h>
#include <wchar.h>
#include <errno.h>
#include <pthread.h>
#include <libusb.h>
#include "Property.hpp"
#include <list>
#include <vector>
#include <set>
#include <string>
#include <sstream>
#include <algorithm>
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<STRUCT_RKDEVICE_DESC> RKDEVICE_DESC_SET;
typedef RKDEVICE_DESC_SET::iterator device_list_iter;
typedef vector<string> STRING_VECTOR;
typedef vector<UINT> UINT_VECTOR;
typedef vector<STRUCT_CONFIG_ITEM> 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

21
Endian.h Normal file
View File

@ -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

24
Makefile Normal file
View File

@ -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

94
Property.hpp Normal file
View File

@ -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 <assert.h>
#include <stdlib.h>
#if !defined INC_PROPERTY_HPP
#define INC_PROPERTY_HPP
#define READ_ONLY 1
#define WRITE_ONLY 2
#define READ_WRITE 3
template<typename Container, typename ValueType, int nPropType>
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

314
RKBoot.cpp Normal file
View File

@ -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;i<ucCount;i++)
{
PSTRUCT_RKBOOT_ENTRY pEntry;
pEntry = (PSTRUCT_RKBOOT_ENTRY)(m_BootData+dwOffset+(ucSize*i));
char szName[20];
WCHAR_To_char(pEntry->szName,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<len;i++)
{
memcpy(dst,src,2);
src++;
dst++;
}
}
void CRKBoot::WCHAR_To_char(WCHAR *src,char *dst,int len)
{
int i;
memset(dst,0,len*sizeof(char));
for (i=0;i<len;i++)
{
memcpy(dst,src,1);
src++;
dst++;
}
}

91
RKBoot.h Normal file
View File

@ -0,0 +1,91 @@
#ifndef RKBOOT_HEADER
#define RKBOOT_HEADER
#include "DefineHeader.h"
#define BOOT_RESERVED_SIZE 57
#pragma pack(1)
typedef struct {
UINT uiTag;
USHORT usSize;
DWORD dwVersion;
DWORD dwMergeVersion;
STRUCT_RKTIME stReleaseTime;
ENUM_RKDEVICE_TYPE emSupportChip;
UCHAR uc471EntryCount;
DWORD dw471EntryOffset;
UCHAR uc471EntrySize;
UCHAR uc472EntryCount;
DWORD dw472EntryOffset;
UCHAR uc472EntrySize;
UCHAR ucLoaderEntryCount;
DWORD dwLoaderEntryOffset;
UCHAR ucLoaderEntrySize;
UCHAR ucSignFlag;
UCHAR ucRc4Flag;
UCHAR reserved[BOOT_RESERVED_SIZE];
} STRUCT_RKBOOT_HEAD, *PSTRUCT_RKBOOT_HEAD;
typedef struct {
UCHAR ucSize;
ENUM_RKBOOTENTRY emType;
WCHAR szName[20];
DWORD dwDataOffset;
DWORD dwDataSize;
DWORD dwDataDelay;
} STRUCT_RKBOOT_ENTRY, *PSTRUCT_RKBOOT_ENTRY;
#pragma pack()
class CRKBoot {
public:
bool GetRc4DisableFlag();
property<CRKBoot, bool, READ_ONLY> Rc4DisableFlag;
bool GetSignFlag();
property<CRKBoot, bool, READ_ONLY> SignFlag;
UINT GetVersion();
property<CRKBoot, UINT, READ_ONLY> Version;
UINT GetMergeVersion();
property<CRKBoot, UINT, READ_ONLY> MergeVersion;
STRUCT_RKTIME GetReleaseTime();
property<CRKBoot, STRUCT_RKTIME, READ_ONLY> ReleaseTime;
ENUM_RKDEVICE_TYPE GetSupportDevice();
property<CRKBoot, ENUM_RKDEVICE_TYPE, READ_ONLY> SupportDevice;
unsigned char GetEntry471Count();
property<CRKBoot, unsigned char, READ_ONLY> Entry471Count;
unsigned char GetEntry472Count();
property<CRKBoot, unsigned char, READ_ONLY> Entry472Count;
unsigned char GetEntryLoaderCount();
property<CRKBoot, unsigned char, READ_ONLY> 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

710
RKComm.cpp Normal file
View File

@ -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;
}

170
RKComm.h Normal file
View File

@ -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

643
RKDevice.cpp Normal file
View File

@ -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("<LAYER %s> 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("<LAYER %s> 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("<LAYER %s> 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("<LAYER %s> 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("<LAYER %s> INFO:FlashInfo:%s", m_layerName, strFlashInfo.c_str());
}
} else {
if (m_pLog) {
m_pLog->Record("<LAYER %s> 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("<LAYER %s> 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("<LAYER %s> 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("<LAYER %s> 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("<LAYER %s> 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("<LAYER %s> 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("<LAYER %s> 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("<LAYER %s> 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("<LAYER %s> 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("<LAYER %s> 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("<LAYER %s> 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("<LAYER %s> 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("<LAYER %s> 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("<LAYER %s> 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("<LAYER %s> 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("<LAYER %s> ERROR:EraseAllBlocks-->EraseEmmcBlock failed,RetCode(%d)", m_layerName, iRet);
}
return -1;
}
if (!EraseEmmc()) {
if (m_pLog) {
m_pLog->Record("<LAYER %s> 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("<LAYER %s> 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;
}

128
RKDevice.h Normal file
View File

@ -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<CRKDevice, USHORT, READ_WRITE> VendorID;
USHORT GetProductID();
void SetProductID(USHORT value);
property<CRKDevice, USHORT, READ_WRITE> ProductID;
ENUM_RKDEVICE_TYPE GetDeviceType();
void SetDeviceType(ENUM_RKDEVICE_TYPE value);
property<CRKDevice, ENUM_RKDEVICE_TYPE, READ_WRITE> DeviceType;
ENUM_RKUSB_TYPE GetUsbType();
void SetUsbType(ENUM_RKUSB_TYPE value);
property<CRKDevice, ENUM_RKUSB_TYPE, READ_WRITE> UsbType;
char *GetLayerName();
void SetLayerName(char *value);
property<CRKDevice, char *, READ_WRITE> LayerName;
DWORD GetLocationID();
void SetLocationID(DWORD value);
property<CRKDevice, DWORD, READ_WRITE> LocationID;
USHORT GetBcdUsb();
void SetBcdUsb(USHORT value);
property<CRKDevice, USHORT, READ_WRITE> BcdUsb;
ENUM_OS_TYPE GetOsType();
void SetOsType(ENUM_OS_TYPE value);
property<CRKDevice, ENUM_OS_TYPE, READ_WRITE> OsType;
CRKLog *GetLogObjectPointer();
property<CRKDevice, CRKLog *, READ_ONLY> LogObjectPointer;
CRKComm *GetCommObjectPointer();
property<CRKDevice, CRKComm *, READ_ONLY> CommObjectPointer;
void SetCallBackPointer(ProgressPromptCB value);
property<CRKDevice, ProgressPromptCB, WRITE_ONLY> 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

298
RKImage.cpp Normal file
View File

@ -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;
}

77
RKImage.h Normal file
View File

@ -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<CRKImage, UINT, READ_ONLY> Version;
UINT GetMergeVersion();
property<CRKImage, UINT, READ_ONLY> MergeVersion;
STRUCT_RKTIME GetReleaseTime();
property<CRKImage, STRUCT_RKTIME, READ_ONLY> ReleaseTime;
ENUM_RKDEVICE_TYPE GetSupportDevice();
property<CRKImage, ENUM_RKDEVICE_TYPE, READ_ONLY> SupportDevice;
ENUM_OS_TYPE GetOsType();
property<CRKImage, ENUM_OS_TYPE, READ_ONLY> OsType;
unsigned short GetBackupSize();
property<CRKImage, unsigned short, READ_ONLY> BackupSize;
UINT GetBootOffset();
property<CRKImage, UINT, READ_ONLY> BootOffset;
UINT GetBootSize();
property<CRKImage, UINT, READ_ONLY> BootSize;
UINT GetFWOffset();
property<CRKImage, UINT, READ_ONLY> FWOffset;
long long GetFWSize();
property<CRKImage, long long, READ_ONLY> FWSize;
bool GetSignFlag();
property<CRKImage, bool, READ_ONLY> 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

121
RKLog.cpp Normal file
View File

@ -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;
}
}
}

41
RKLog.h Normal file
View File

@ -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<CRKLog, string, READ_ONLY> LogSavePath;
property<CRKLog, bool, READ_WRITE> 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

614
RKScan.cpp Normal file
View File

@ -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;
}
}

52
RKScan.h Normal file
View File

@ -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<STRUCT_DEVICE_CONFIG> RKDEVICE_CONFIG_SET;
class CRKScan
{
public:
UINT GetMSC_TIMEOUT();
void SetMSC_TIMEOUT(UINT value);
property<CRKScan, UINT, READ_WRITE> MSC_TIMEOUT;
UINT GetRKUSB_TIMEOUT();
void SetRKUSB_TIMEOUT(UINT value);
property<CRKScan, UINT, READ_WRITE> RKUSB_TIMEOUT;
int GetDEVICE_COUNTS();
property<CRKScan, int, READ_ONLY> 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

17
Readme.txt Normal file
View File

@ -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

0
config.ini Normal file
View File

362
crc.cpp Normal file
View File

@ -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<ulSize; i++)
nAccum = (nAccum<<8)^gTable_Crc32[(nAccum>>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<len; x++){
i = (i+1) % 256;
j = (j + S[i]) % 256;
temp = S[i];
S[i] = S[j];
S[j] = temp;
t = (S[i] + (S[j] % 256)) % 256;
buf[x] = buf[x] ^ S[t];
}
}
void bch_encode(unsigned char* encode_in, unsigned char* encode_out)
{
UINT i,j;
bool feed_back;
UINT bch1=0;
UINT bch2=0;
UINT bch3=0;
UINT bch4=0;
for (i=0;i<515;i++)
{
for (j=0;j<8;j++)
{
feed_back = (bch1&1) ^ ((encode_in[i]>>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<<j)*i)%nn;
gen_roots_true[Temp] = 1;
}
}
rr = 0; // Count thenumber of parity check bits
for (i = 0; i < nn; i++)
{
if (gen_roots_true[i] == 1)
{
rr++;
gen_roots[rr] = i;
}
}
// Compute generator polynomial based on its roots
gg[0] = 2 ; // g(x) = (X + alpha) initially
gg[1] = 1 ;
for (i = 2; i <= rr; i++)
{
gg[i] = 1 ;
for (j = i - 1; j > 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 ;
}

339
license.txt Normal file
View File

@ -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.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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.
<signature of Ty Coon>, 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.

940
main.cpp Normal file
View File

@ -0,0 +1,940 @@
/*
* (C) Copyright 2017 Fuzhou Rockchip Electronics Co., Ltd
* Seth Liu 2017.03.01
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <unistd.h>
#include <dirent.h>
#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 <Loader>\r\n");
printf("ReadLBA: RL <BeginSec> <SectorLen> <File>\r\n");
printf("WriteLBA: WL <BeginSec> <File>\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, "<LocationID=%x> 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;
}