📄 ezusb_lib.c
字号:
//////////////////////////////////////////////////////////////////////
// File - EzUsb_lib.c
//
// Library for accessing the EZ-USB device.
// Accesses the hardware via WinDriver functions.
//
// Copyright (c) 2003 - 2004 Jungo Ltd. http://www.jungo.com
//
//////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include "../../include/wdu_lib.h"
#include "../../include/status_strings.h"
#include "../../include/utils.h"
#include "ezusb_lib.h"
// Implementation of the Firmware download starts here.
#include "Vend_Ax.h"
#if !defined(ERR)
#define ERR printf
#endif
#if !defined(TRACE)
#define TRACE printf
#endif
#define MAX_FILE_SIZE 1024 * 8
#define TGT_IMG_SIZE 0x10000 // 64KB (65,536 Byte) target image
#define TGT_SEG_SIZE 16 // 16 byte segments
#define DEFAULT_TIMEOUT 10000
BYTE BlkBuf[MAX_FILE_SIZE];
BYTE VenBuf[MAX_FILE_SIZE];
DWORD Offset, Len;
char sInfoString[4000];
typedef struct
{
DWORD TAddr; // Target Address
DWORD HAddr; // Host Address
DWORD Size; // block size
DWORD Stat; // status
PCHAR pData; // data bytes
} MemSeg;
typedef struct
{
CHAR data[TGT_IMG_SIZE]; // target image store
} TMemImg;
typedef struct
{
TMemImg *pImg;
int nSeg; // segment count
MemSeg pSeg[TGT_IMG_SIZE/TGT_SEG_SIZE]; // info about segments
} TMemCache;
int FileToString(TMemCache* pMemCache, CHAR *pHexFileName);
BOOL DownloadIntelHex(HANDLE hDev, BOOL IsFx2);
BOOL DownLoadBuf(HANDLE hDev, DWORD address, DWORD length, void *buffer,
BYTE bRequest);
DWORD ResetBit(HANDLE hDev, int DoReset, BOOL IsFx2);
BOOL DLLCALLCONV CypressDeviceAttach(WDU_DEVICE_HANDLE hDevice,
WDU_DEVICE *pDeviceInfo, PVOID pUserData)
{
BOOL bAcceptControl;
DEVICE_CONTEXT *pDevCtx = (DEVICE_CONTEXT *)pUserData;
if (pDeviceInfo->pActiveInterface->pActiveAltSetting->Descriptor.bInterfaceNumber !=
(BYTE)pDevCtx->dwInterfaceNum)
{
// This is not the requested interface
TRACE("CypressDeviceAttach: received attach but for wrong interface - control is rejected\n");
return FALSE;
}
if (pDevCtx->hDev)
{
TRACE("CypressDeviceAttach: received another attach - control is rejected "
"because only one device control is supported\n");
return FALSE;
}
pDevCtx->hDev = hDevice;
if (!CopyDeviceFromTable(&pDevCtx->cypressDevice, cypressDevices, dwCypressDevices,
pDeviceInfo->Descriptor.idVendor, pDeviceInfo->Descriptor.idProduct))
{
// this should never happen because the match tables passed to
// WDU_Init() are exactly as the devices in cypressDevices
ERR("CypressDeviceAttach: internal error - got unidentified device attach\n");
return FALSE;
}
pDevCtx->dwAttachError = WDU_SetInterface(pDevCtx->hDev, pDevCtx->dwInterfaceNum, pDevCtx->dwAlternateSetting);
if (pDevCtx->dwAttachError)
{
ERR("CypressDeviceAttach: WDU_SetInterface failed (num. %d, alternate %d) device 0x%x: error 0x%x (\"%s\")\n",
pDevCtx->dwInterfaceNum, pDevCtx->dwAlternateSetting, pDevCtx->hDev,
pDevCtx->dwAttachError, Stat2Str(pDevCtx->dwAttachError));
pDevCtx->hDev = 0;
bAcceptControl = FALSE;
}
else
{
TRACE("CypressDeviceAttach: received and accepted attach for:\n"
" vendor id 0x%x, product id 0x%x, device handle 0x%x\n",
pDeviceInfo->Descriptor.idVendor, pDeviceInfo->Descriptor.idProduct,
pDevCtx->hDev);
bAcceptControl = TRUE;
}
OsEventSignal(pDevCtx->hEvent);
return bAcceptControl;
}
void DLLCALLCONV CypressDeviceDetach(WDU_DEVICE_HANDLE hDevice, PVOID pUserData)
{
DEVICE_CONTEXT *pDevCtx = (DEVICE_CONTEXT *)pUserData;
pDevCtx->hDev = 0;
memset(&pDevCtx->cypressDevice, 0, sizeof(pDevCtx->cypressDevice));
TRACE("CypressDeviceDetach: received detach for device handle 0x%x\n", hDevice);
}
BOOL DownloadFirmware(HANDLE hDev, PCHAR pHexFileName, BOOL IsFx2)
{
BYTE *pbuf = BlkBuf;
BYTE *pVenbuf = VenBuf;
TMemCache *pMemCache;
DWORD dwNumRead;
BOOL rc = FALSE;
int i;
sInfoString[0] = '\0';
pMemCache = (TMemCache *)malloc(sizeof(TMemCache));
if (!pMemCache)
{
sprintf(sInfoString, "DownloadFirmware: Insufficient resources\n");
goto Exit;
}
pMemCache->pImg = (TMemImg *)malloc(TGT_IMG_SIZE);
if (!pMemCache->pImg)
{
sprintf(sInfoString, "DownloadFirmware: Insufficient resources\n");
goto Exit;
}
dwNumRead = FileToString(pMemCache, pHexFileName);
if (!dwNumRead)
goto Exit;
// check for high mem first, load loader first if necessary
for (i=0; i<pMemCache->nSeg; i++)
{
if (pMemCache->pSeg[i].TAddr >= 0x2000)
{
if (!DownloadIntelHex(hDev, IsFx2))
goto Exit;
break;
}
}
// load all high mem first
for (i=0; i<pMemCache->nSeg; i++)
{
if (pMemCache->pSeg[i].TAddr >= 0x2000)
{
memcpy(pVenbuf, pMemCache->pSeg[i].pData, pMemCache->pSeg[i].Size);
if (!DownLoadBuf(hDev, pMemCache->pSeg[i].TAddr,
pMemCache->pSeg[i].Size, pVenbuf, 0xA3))
{
goto Exit;
}
}
}
ResetBit(hDev, 1, IsFx2);
// load all low mem last
for (i=0; i<pMemCache->nSeg; i++)
{
if (pMemCache->pSeg[i].TAddr < 0x2000)
{
memcpy(pbuf, pMemCache->pSeg[i].pData, pMemCache->pSeg[i].Size);
Len = pMemCache->pSeg[i].Size;
Offset = pMemCache->pSeg[i].TAddr;
if (!DownLoadBuf(hDev, Offset, Len, pbuf, 0xA0))
goto Exit;
}
}
ResetBit(hDev, 0, IsFx2);
rc = TRUE;
Exit:
if (pMemCache)
{
if (pMemCache->pImg)
free(pMemCache->pImg);
free(pMemCache);
}
return rc;
}
#define MAXSTR 256 // Maximum length of Intel Hex file string
// 4K Control EP0 transfer limit imposed by OS
#define MAX_EP0_XFER_SIZE (1024*4)
int FileToString(TMemCache* pMemCache, CHAR *pHexFileName)
{
FILE *fp;
int i, curSeg, recType, cnt;
int CNTFIELD, ADDRFIELD, RECFIELD, DATAFIELD;
CHAR str[MAXSTR];
DWORD byte, addr, totalRead;
PCHAR ptr;
fp = fopen(pHexFileName, "rb");
if (!fp)
{
sprintf(sInfoString, "Can't open %s file.\n"
"Please make sure that the file exists in the specified location\n",
pHexFileName);
return 0;
}
// offsets of fields within record -- may change later due to "spaces"
// setting
CNTFIELD = 1;
ADDRFIELD = 3;
RECFIELD = 7;
DATAFIELD = 9;
addr = 0;
curSeg = 0;
totalRead = 0;
pMemCache->nSeg = 0;
while (fgets(str, MAXSTR, fp))
{
if (str[0]!=':')
return 0;
if (str[1]==' ') // get the record type
{
CNTFIELD = 1 + 1;
ADDRFIELD = 3 + 2;
RECFIELD = 7 + 3;
DATAFIELD = 9 + 4;
}
sscanf(str+RECFIELD, "%2x", &recType);
ptr = (PCHAR)pMemCache->pImg;
switch(recType)
{
case 2: // seg record
sscanf(str+DATAFIELD, "%4x", &curSeg);
curSeg *= 0x10;
break;
case 0: // data record
sscanf(str+CNTFIELD, "%2x", &cnt);
sscanf(str+ADDRFIELD, "%4x", &addr);
if (addr>=TGT_IMG_SIZE)
{
sprintf(sInfoString, "Error loading file: address out of "
"range\n");
return 0;
}
ptr += addr; // get pointer to location in image
if (pMemCache->nSeg &&
(pMemCache->pSeg[pMemCache->nSeg-1].TAddr ==
addr - pMemCache->pSeg[pMemCache->nSeg-1].Size) &&
(pMemCache->pSeg[pMemCache->nSeg-1].Size + cnt <=
MAX_EP0_XFER_SIZE))
{
// if the segment is contiguous to the last segment,
// and it's not too big yet append to previous segment
pMemCache->pSeg[pMemCache->nSeg-1].Size += cnt;
}
else
{
// start a new segment
pMemCache->pSeg[pMemCache->nSeg].TAddr = addr;
pMemCache->pSeg[pMemCache->nSeg].Size = cnt;
pMemCache->pSeg[pMemCache->nSeg].pData = ptr;
pMemCache->nSeg++;
}
for (i=0; i<cnt; i++)
{
sscanf(str+DATAFIELD+i*2, "%2x", &byte);
*(ptr + i) = (CHAR)byte;
totalRead++;
}
break;
case 1: //end record
fclose(fp);
return totalRead;
default:
break;
}
}
if (fp)
fclose(fp);
return 0; // missing end record
}
BOOL DownloadIntelHex(HANDLE hDev, BOOL IsFx2)
{
BYTE* pbuf = BlkBuf;
BYTE* ptmp = NULL;
PINTEL_HEX_RECORD ptr = IsFx2 ? Vend_Ax_Fx2 : Vend_Ax;
ResetBit(hDev, 1, IsFx2);
while (ptr->Type==0) //load low mem
{
if (ptmp && // continue a segment
Offset+Len==(DWORD)ptr->Address &&
Len+ptr->Length<=MAX_EP0_XFER_SIZE)
{
memcpy(ptmp, ptr->Data, ptr->Length);
Len += ptr->Length;
ptmp += ptr->Length;
}
else // start a new segment
{
if (ptmp) // send previous segment first
{
if (!DownLoadBuf(hDev, Offset, Len, pbuf, 0xA0))
return FALSE;
}
ptmp = pbuf;
memcpy(ptmp, ptr->Data, ptr->Length);
Len = ptr->Length;
Offset = ptr->Address;
ptmp += ptr->Length;
}
ptr++;
}
if (ptmp) // send final segment
{
if (!DownLoadBuf(hDev, Offset, Len, pbuf, 0xA0))
return FALSE;
}
ResetBit(hDev, 0, IsFx2);
return TRUE;
}
// The download will be split into CHUNK_SIZE pieces and
// downloaded with multiple setup transfers.
// CHUNK_SIZE should not exceed 64 bytes, as larger transfers can
// result in data corruption when other USB devices are present.
#define CHUNK_SIZE 64
BOOL DownLoadBuf(HANDLE hDev, DWORD address, DWORD length, void *buffer,
BYTE bRequest)
{
BYTE SetupPacket[8];
DWORD dwBytesTransferred, i, size, chunkCount;
DWORD dwStatus, dwOptions = 0;
void *cur;
chunkCount = (length + CHUNK_SIZE - 1) / CHUNK_SIZE;
for (i=0; i<chunkCount; i++)
{
if (i==chunkCount-1 && length % CHUNK_SIZE)
size = length % CHUNK_SIZE;
else
size = CHUNK_SIZE;
SetupPacket[0] = 0x40;
SetupPacket[1] = bRequest;
SetupPacket[2] = (BYTE)((address + i*CHUNK_SIZE) & 0xFF);
SetupPacket[3] = (BYTE)(((address + i*CHUNK_SIZE) & 0xFF00) >> 8);
SetupPacket[4] = 0;
SetupPacket[5] = 0;
SetupPacket[6] = (BYTE) size & 0xFF;
SetupPacket[7] = (BYTE) (size & 0xFF00) >> 8;
cur = (PVOID)((DWORD)buffer + i*CHUNK_SIZE);
dwStatus = WDU_TransferDefaultPipe(hDev, FALSE, dwOptions, cur, size,
&dwBytesTransferred, SetupPacket, DEFAULT_TIMEOUT);
}
if (dwStatus)
{
sprintf(sInfoString, "DownLoadBuf: WDU_TransferDefaultPipe failed with status 0x%x - %s\n",
dwStatus, Stat2Str(dwStatus));
return FALSE;
}
return TRUE;
}
#define CPUCS_REG_EZUSB 0x7F92
#define CPUCS_REG_FX2 0xE600
DWORD ResetBit(HANDLE hDev, int DoReset, BOOL IsFx2)
{
BYTE reset = (BYTE)DoReset;
BYTE SetupPacket[8];
DWORD dwBytesTransferred;
DWORD dwCpucs = IsFx2 ? CPUCS_REG_FX2 : CPUCS_REG_EZUSB;
sInfoString[0] = '\0';
SetupPacket[0] = 0x40;
SetupPacket[1] = 0xA0;
SetupPacket[2] = (BYTE)(dwCpucs & 0xFF);
SetupPacket[3] = (BYTE)((dwCpucs & 0xFF00) >> 8);
SetupPacket[4] = 0;
SetupPacket[5] = 0;
SetupPacket[6] = 1;
SetupPacket[7] = 0;
return WDU_TransferDefaultPipe(hDev, FALSE, 0, &reset, 1,
&dwBytesTransferred, SetupPacket, DEFAULT_TIMEOUT);
}
char *ReadFirmwareFileName(const char *pcDefaultFileName)
{
char *sFileName;
#if defined(WINCE)
unsigned short swFileName[1024];
#endif
char *tmp;
sFileName = (char *)malloc(1024);
if (!sFileName)
{
ERR("ReadFirmwareFileName: failed allocating memory\n");
return NULL;
}
sFileName[0] = '\0';
#if defined(WIN32)
// get directory
#if defined(WINCE)
GetModuleFileName(NULL, swFileName, 1024);
sprintf(sFileName, "%S", swFileName);
#else
GetModuleFileName(NULL, sFileName, 1024);
#endif
tmp = strrchr(sFileName, '\\');
if (tmp)
tmp[0] = '\0'; // remove module name
tmp = strrchr(sFileName, '\\');
if (tmp)
tmp[1] = '\0'; // go back one directory
else
sFileName[0] = '\0';
#endif
printf("Please enter firmware file name.\n");
if(strcmp(pcDefaultFileName, ""))
printf("Default: %s\n", pcDefaultFileName);
printf(" > ");
fgets(sFileName, 1024, stdin);
if (strlen(sFileName) > 1)
sFileName[strlen(sFileName) - 1] = '\0'; // remove \n
else
strcpy(sFileName, pcDefaultFileName);
return sFileName;
}
BOOL CopyDeviceFromTable(CYPRESS_DEVICE *dstDevice, CYPRESS_DEVICE cypressDevices[],
const DWORD dwDevicesNum, USHORT idVendor, USHORT idProduct)
{
DWORD i;
// find & copy this device's details from cypressDevices table
for (i=0; i<dwDevicesNum; i++)
{
if (cypressDevices[i].wVendorId==idVendor &&
cypressDevices[i].wProductId==idProduct)
{
*dstDevice = cypressDevices[i];
break;
}
}
if (i==dwDevicesNum)
{
ERR("CopyDeviceFromTable: received unrecognized device (0x%x/0x%x)\n",
idVendor, idProduct);
return FALSE;
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -