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

📄 wdu_lib.cpp

📁 采用windriver提供的API开发的D12应用程序源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
////////////////////////////////////////////////////////////////
// File - wdu_lib.c
//
// WinDriver USB API Declarations & Implementations
//
// Copyright (c) 2003 - 2006 Jungo Ltd.  http://www.jungo.com 
////////////////////////////////////////////////////////////////
#include "stdafx.h"
#ifdef __KERNEL_DRIVER__
    #include "kd.h"
#elif defined(_KERNEL_)
    #include "kpstdlib.h"
#endif
#include "wdu_lib.h"
#include "windrvr_events.h"
#include "status_strings.h"
#include "utils.h"
#include <stdarg.h>
#include <stdio.h>
#include "StdAfx.h"
// Print Functions

#if defined(__KERNEL__) && defined(WIN32)
    #pragma warning( disable :4013 4100)
#endif

#if !defined(TRACE)
int __cdecl TRACE(const char *fmt, ...) 
{ 
    #if defined(DEBUG)
        va_list argp;
        va_start(argp, fmt);
        vfprintf(stderr, fmt, argp);
        va_end(argp);
    #endif
    return 0;
}
#endif

#if !defined(ERR)
int __cdecl ERR(const char *fmt, ...) 
{ 
    #if defined(DEBUG)
        va_list argp;
        va_start(argp, fmt);
        fprintf(stderr, "WDERROR: ");
        vfprintf(stderr, fmt, argp);
        va_end(argp);
    #endif
    return 0;
}
#endif

// Structures

#define WDU_DEVLIST_TIMEOUT 30 // in seconds
#define WDU_TRANSFER_TIMEOUT 30000 // in msecs

typedef struct
{
    HANDLE hWD;
    WDU_EVENT_TABLE EventTable;
    HANDLE hEvents;
} DRIVER_CTX;
    
typedef struct
{
    DRIVER_CTX *pDriverCtx;
    WDU_DEVICE *pDevice; // not fixed size => ptr 
    DWORD dwUniqueID;
} DEVICE_CTX;

typedef struct _WDU_DEVICE_LIST_ITEM
{
    struct _WDU_DEVICE_LIST_ITEM *next;
    DEVICE_CTX *pDeviceCtx;
} WDU_DEVICE_LIST_ITEM; 

typedef struct
{
    WDU_DEVICE_LIST_ITEM *pHead;
    HANDLE hEvent;    
    int iRefCount;
} WDU_DEVICE_LIST;

WDU_DEVICE_LIST DevList; // global devices list

// Private Functions Prototypes

static DWORD AddDeviceToDevList(DEVICE_CTX *pDeviceCtx);
static DWORD RemoveDeviceFromDevList(DRIVER_CTX *pDriverCtx, DWORD dwUniqueID, DEVICE_CTX **ppDeviceCtx);
static DWORD RemoveAllDevicesFromDevList(DRIVER_CTX *pDriverCtx);
static DWORD FindDeviceByUniqueID(DRIVER_CTX *pDriverCtx, DWORD dwUniqueID, DEVICE_CTX **ppDeviceCtx);
static DWORD FindDeviceByCtx(DEVICE_CTX *pDeviceCtx);

// Translate WD_functions into IOCTLs

#define PARAMS_SET(param) Params.param = param
#define GET_HWD(h) (((DEVICE_CTX *)(h))->pDriverCtx->hWD)

// unique ID is passed in IOCTLs to identify the device/interface instead of
// hDevice like in the old API
#define PARAMS_INIT(T) \
    T Params; \
    BZERO(Params); \
    if (!hDevice || FindDeviceByCtx((DEVICE_CTX *)hDevice) != WD_STATUS_SUCCESS) \
        return WD_DEVICE_NOT_FOUND; \
    Params.dwUniqueID = ((DEVICE_CTX *)hDevice)->dwUniqueID;


DWORD DLLCALLCONV WDU_SetInterface(WDU_DEVICE_HANDLE hDevice, DWORD dwInterfaceNum,
    DWORD dwAlternateSetting)
{
    DWORD dwStatus;
    DWORD ifc_index;
    DEVICE_CTX *pDevCtx = (DEVICE_CTX*)hDevice;
    WDU_DEVICE *pDevice = pDevCtx->pDevice;
    PARAMS_INIT(WDU_SET_INTERFACE);
    PARAMS_SET(dwInterfaceNum);
    PARAMS_SET(dwAlternateSetting);
    dwStatus = WD_USetInterface(GET_HWD(hDevice), &Params);
    if (dwStatus)
    {
        ERR("WDU_SetInterface: Set interface (interface: %ld, alternate setting: %ld) failed:\n"
            "Error: 0x%lx (%s)\n", dwInterfaceNum, dwAlternateSetting, dwStatus, Stat2Str(dwStatus));
        return dwStatus;
    }

    for (ifc_index = 0; ifc_index < pDevice->pConfigs->dwNumInterfaces; ifc_index++)
    {
        if (pDevice->pActiveInterface[ifc_index]->pAlternateSettings[dwAlternateSetting].Descriptor.bInterfaceNumber == dwInterfaceNum)
            break;
    }
    // Update the active alternate setting
    pDevice->pActiveInterface[ifc_index]->pActiveAltSetting = 
        &pDevice->pActiveInterface[ifc_index]->pAlternateSettings[dwAlternateSetting];

    return WD_STATUS_SUCCESS;
}

// currently not implemented
DWORD DLLCALLCONV WDU_SetConfig(WDU_DEVICE_HANDLE hDevice, DWORD dwConfigNum);

DWORD DLLCALLCONV WDU_ResetPipe(WDU_DEVICE_HANDLE hDevice, DWORD dwPipeNum)
{
    PARAMS_INIT(WDU_RESET_PIPE);
    PARAMS_SET(dwPipeNum);
    return WD_UResetPipe(GET_HWD(hDevice), &Params);
}

// currently not implemented on WinCE and Linux
DWORD DLLCALLCONV WDU_ResetDevice(WDU_DEVICE_HANDLE hDevice, DWORD dwOptions)
{
    PARAMS_INIT(WDU_RESET_DEVICE);
    PARAMS_SET(dwOptions);
    return WD_UResetDevice(GET_HWD(hDevice), &Params);
}

// currently not implemented on WinCE and Linux
DWORD DLLCALLCONV WDU_Wakeup(WDU_DEVICE_HANDLE hDevice, DWORD dwOptions)
{
    PARAMS_INIT(WDU_WAKEUP);
    PARAMS_SET(dwOptions);
    return WD_UWakeup(GET_HWD(hDevice), &Params);
}

DWORD DLLCALLCONV WDU_Transfer(WDU_DEVICE_HANDLE hDevice, DWORD dwPipeNum, DWORD fRead, 
    DWORD dwOptions, PVOID pBuffer, DWORD dwBufferSize, PDWORD pdwBytesTransferred, 
    PBYTE pSetupPacket, DWORD dwTimeout)
{
    DWORD dwStatus;
    PARAMS_INIT(WDU_TRANSFER);
    PARAMS_SET(dwPipeNum);
    PARAMS_SET(fRead);
    PARAMS_SET(dwOptions);
    PARAMS_SET(pBuffer);
    PARAMS_SET(dwBufferSize);
    if (pSetupPacket)
        memcpy(&Params.SetupPacket, pSetupPacket, 8);
    PARAMS_SET(dwTimeout);
    dwStatus = WD_UTransfer(GET_HWD(hDevice), &Params);
    *pdwBytesTransferred = Params.dwBytesTransferred;
    return dwStatus;
}

DWORD DLLCALLCONV WDU_HaltTransfer(WDU_DEVICE_HANDLE hDevice, DWORD dwPipeNum)
{
    PARAMS_INIT(WDU_HALT_TRANSFER);
    PARAMS_SET(dwPipeNum);
    return WD_UHaltTransfer(GET_HWD(hDevice), &Params);
}

// User-mode wrappers for kernel functions

static void EventHandler(WD_EVENT *pEvent, void *pDriverContext);

DWORD DLLCALLCONV WDU_Init(WDU_DRIVER_HANDLE *phDriver, 
    WDU_MATCH_TABLE *pMatchTables, DWORD dwNumMatchTables, 
    WDU_EVENT_TABLE *pEventTable, const char *sLicense, DWORD dwOptions)
{
    DWORD dwStatus;
    DRIVER_CTX *pDriverCtx = NULL;
    WD_VERSION ver;
    WD_EVENT *event = NULL;
    WD_LICENSE lic;
   
    *phDriver = INVALID_HANDLE_VALUE;

    pDriverCtx = (DRIVER_CTX *) calloc(1, sizeof(DRIVER_CTX));
    if (!pDriverCtx)
    {
        ERR("WDU_Init: cannot malloc memory\n");
        dwStatus = WD_INSUFFICIENT_RESOURCES;
        goto Error;
    }

#if !defined(__KERNEL__)
    // init the device list event
    if (DevList.iRefCount == 0)
    {
        dwStatus = OsEventCreate(&DevList.hEvent);
        if (dwStatus)
        {
            ERR("WDU_Init: cannot create event: dwStatus (0x%lx) - %s\n", 
                dwStatus, Stat2Str(dwStatus));
            goto Error;
        }
        dwStatus = OsEventSignal(DevList.hEvent);
        if (dwStatus)
        {
            ERR("WDU_Init: error signaling device list event: dwStatus (0x%lx) - %s\n", 
                dwStatus, Stat2Str(dwStatus));
            OsEventClose(DevList.hEvent);
            goto Error;
        }
    }
    DevList.iRefCount++;
#endif
    
    pDriverCtx->hWD = INVALID_HANDLE_VALUE;
    pDriverCtx->hWD = WD_Open();

    // Check whether handle is valid and version OK
    if (pDriverCtx->hWD==INVALID_HANDLE_VALUE) 
    {
        ERR("WDU_Init: cannot open " WD_PROD_NAME " device\n");
        dwStatus = WD_SYSTEM_INTERNAL_ERROR;
        goto Error;
    }

    strcpy(lic.cLicense, sLicense);
    WD_License(pDriverCtx->hWD, &lic);

    BZERO(ver);
    dwStatus = WD_Version(pDriverCtx->hWD, &ver);
    if ((dwStatus != WD_STATUS_SUCCESS) || (ver.dwVer<WD_VER)) 
    {
        ERR("WDU_Init: incorrect " WD_PROD_NAME " version\n");
        if (!dwStatus)
            dwStatus = WD_INCORRECT_VERSION;
        goto Error;
    }

    pDriverCtx->EventTable = *pEventTable;

    if (pEventTable->pfDeviceAttach)
    {
        DWORD dwAction;
        dwAction = WD_INSERT |
            (pEventTable->pfDeviceDetach ?  WD_REMOVE : 0) |
            (pEventTable->pfPowerChange ? WD_POWER_CHANGED_D0 | 
                                        WD_POWER_CHANGED_D1 |
                                        WD_POWER_CHANGED_D2 |
                                        WD_POWER_CHANGED_D3 |
                                        WD_POWER_SYSTEM_WORKING |
                                        WD_POWER_SYSTEM_SLEEPING1 |
                                        WD_POWER_SYSTEM_SLEEPING2 |
                                        WD_POWER_SYSTEM_SLEEPING3 |
                                        WD_POWER_SYSTEM_HIBERNATE |
                                        WD_POWER_SYSTEM_SHUTDOWN : 0); 
        event = UsbEventCreate(pMatchTables, dwNumMatchTables, dwOptions,
            dwAction);
        if (!event)
        {
            ERR("WDU_Init: cannot malloc memory\n");
            dwStatus = WD_INSUFFICIENT_RESOURCES;
            goto Error;
        }

        dwStatus = EventRegister(&pDriverCtx->hEvents, pDriverCtx->hWD, event,
            EventHandler, pDriverCtx);
        if (dwStatus)
        {
            ERR("WDU_Init: EventRegister failed with dwStatus (0x%lx) - %s\n", 
                dwStatus, Stat2Str(dwStatus));
            goto Error;
        }
    }

    *phDriver = pDriverCtx;
    goto Exit;

Error:
    if (pDriverCtx)
        WDU_Uninit(pDriverCtx);
Exit:
    if (event)
        EventFree(event);
    return dwStatus;
}

void DLLCALLCONV WDU_Uninit(WDU_DRIVER_HANDLE hDriver)
{
    DRIVER_CTX *pDriverCtx = (DRIVER_CTX *)hDriver;

    if (pDriverCtx && hDriver != INVALID_HANDLE_VALUE)
    {
        if (pDriverCtx->hWD) 
        {
            if (pDriverCtx->hEvents)
                EventUnregister(pDriverCtx->hEvents);
            WD_Close(pDriverCtx->hWD);
        }
        RemoveAllDevicesFromDevList(pDriverCtx);
        free (pDriverCtx);
    }

#if !defined(__KERNEL__)
    DevList.iRefCount--;
    if (DevList.iRefCount == 0)
        OsEventClose(DevList.hEvent);
#endif
}

static void EventHandler(WD_EVENT *pEvent, void *pDriverContext)
{
    DRIVER_CTX *pDriverCtx = (DRIVER_CTX *)pDriverContext;
    DEVICE_CTX *pDeviceCtx, *pDummyDeviceCtx;
    WDU_DEVICE_HANDLE hDevice;
    BOOL bControlDevice = FALSE, bChangePower;
    DWORD dwStatus;

    TRACE("EventHandler: got event 0x%lx handle %p\n", pEvent->dwAction, pEvent->handle);
    switch (pEvent->dwAction)
    {
    case WD_INSERT:
        // create device context
        pDeviceCtx = (DEVICE_CTX *)calloc(1, sizeof(DEVICE_CTX));
        if (!pDeviceCtx)
        {
            ERR("EventHandler: cannot alloc memory\n");
            return;
        }
        
        // DEVICE_CTX * is used as WDU_DEVICE_HANDLE 
        hDevice = pDeviceCtx; 

        pDeviceCtx->dwUniqueID = pEvent->u.Usb.dwUniqueID;
        pDeviceCtx->pDriverCtx = pDriverCtx;

        // add the device handle to the device list for future IOCTLs
        dwStatus = AddDeviceToDevList(pDeviceCtx);
        if (dwStatus)
        {
            free(pDeviceCtx);
            return;
        }

        // get device info
        dwStatus = WDU_GetDeviceInfo(hDevice, &pDeviceCtx->pDevice);
        if (dwStatus)
        {
            ERR("EventHandler: unable to get device info for device"
                " handle %p dwUniqueID 0x%lx\n", 
                hDevice, pDeviceCtx->dwUniqueID);
            RemoveDeviceFromDevList(pDriverCtx, pEvent->u.Usb.dwUniqueID, &pDummyDeviceCtx);
            free(pDeviceCtx);
            return;
        }

        bControlDevice = pDriverCtx->EventTable.pfDeviceAttach(hDevice, 
            pDeviceCtx->pDevice, pDriverCtx->EventTable.pUserData);
        if (!bControlDevice)
        {
            TRACE("EventHandler: bControlDevice==FALSE; pDriverCtx %p\n", pDriverCtx);
            RemoveDeviceFromDevList(pDriverCtx, pEvent->u.Usb.dwUniqueID, &pDummyDeviceCtx);
            WDU_PutDeviceInfo(pDeviceCtx->pDevice);
            free(pDeviceCtx);
        }

        pEvent->dwOptions |= bControlDevice ? WD_ACCEPT_CONTROL : 0;
        break;
    case WD_REMOVE:
        dwStatus = RemoveDeviceFromDevList(pDriverCtx, pEvent->u.Usb.dwUniqueID, &pDeviceCtx);
        if (dwStatus)
            // device is not mine or may has been closed by WDU_Uninit
            break;

        // DEVICE_CTX * is used as WDU_DEVICE_HANDLE
        pDriverCtx->EventTable.pfDeviceDetach((WDU_DEVICE_HANDLE) pDeviceCtx, pDriverCtx->EventTable.pUserData);

        WDU_PutDeviceInfo(pDeviceCtx->pDevice);
        free(pDeviceCtx);

        break;
    case WD_POWER_CHANGED_D0:
    case WD_POWER_CHANGED_D1:
    case WD_POWER_CHANGED_D2:
    case WD_POWER_CHANGED_D3:
    case WD_POWER_SYSTEM_WORKING:
    case WD_POWER_SYSTEM_SLEEPING1:
    case WD_POWER_SYSTEM_SLEEPING2:
    case WD_POWER_SYSTEM_SLEEPING3:
    case WD_POWER_SYSTEM_HIBERNATE:
    case WD_POWER_SYSTEM_SHUTDOWN:
        dwStatus = FindDeviceByUniqueID(pDriverCtx, pEvent->u.Usb.dwUniqueID, &pDeviceCtx);
        if (dwStatus)
        {
            // device is not mine or may have been closed by WDU_Uninit
            break;
        }

        bChangePower = pDriverCtx->EventTable.pfPowerChange((WDU_DEVICE_HANDLE) pDeviceCtx, pEvent->dwAction, 
            pDriverCtx->EventTable.pUserData);
        // XXX return in the event structure if the user says it's ok to change power
        //  (not implemented yet)
        break;
    }
}

// ppDeviceInfo is set to point to an allocated buffer containing the info.
// The caller should free the buffer after the use by calling 
// WDU_PutDeviceInfo()
DWORD DLLCALLCONV WDU_GetDeviceInfo(WDU_DEVICE_HANDLE hDevice, WDU_DEVICE **ppDeviceInfo)
{
    DWORD dwStatus;

    PARAMS_INIT(WDU_GET_DEVICE_DATA);
    // first call with pBuf NULL, return dwBytes
    dwStatus = WD_UGetDeviceData(GET_HWD(hDevice), &Params);
    if (dwStatus != WD_STATUS_SUCCESS)
        return dwStatus;
    *ppDeviceInfo = (WDU_DEVICE *) malloc(Params.dwBytes);
    if (!ppDeviceInfo)
    {
        ERR("WDU_GetDeviceInfo: cannot alloc memory\n");
        return WD_INSUFFICIENT_RESOURCES;
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -