⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ezusb_lib.c

📁 the sourse of EZUSB (for c )
💻 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 + -