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

📄 usbd.cpp

📁 cayman提供的PXA270 wince下的bsp源码包
💻 CPP
📖 第 1 页 / 共 3 页
字号:
                fRet = LoadUSBClient(pDev, &bLoaded, pInterface);
                if (fRet && bLoaded) { // Driver Loaded for this interface.
                    if (pbActivatedFlag) 
                        *(pbActivatedFlag + iInterface) =1; // Set activated flags.
                }
                else
                    break;
            }
        }
        if (iInterface>=pConfig->Descriptor.bNumInterfaces) { // We success activate all the interface.
            *pfLoaded=TRUE;
        }
    }

    return fRet;
}


BOOL CloseUSBDevice(SDevice * pDev)
{
    EnterCriticalSection(&pDev->csSerializeNotifyRoutine);

    SNotifyList * pNotify = pDev->pNotifyList, *pNext;

    while(pNotify)
    {
        // It is possible that the client will call UnregisterNotificationRoutine(),
        // so don't touch pNotify after calling notify routine.
        pNext = pNotify->pNext;

        if (pNotify->lpNotifyRoutine) {
           DEBUGMSG(ZONE_LOADER,(TEXT("USBD: Calling client device detach proc\r\n")));
            (*pNotify->lpNotifyRoutine)(pNotify->lpvNotifyParameter,
                                        USB_CLOSE_DEVICE, NULL, NULL, NULL, NULL);
            DEBUGMSG(ZONE_LOADER,(TEXT("USBD: Returned from client device detach proc\r\n")));
        }
        pNotify = pNext;
    }

    LeaveCriticalSection(&pDev->csSerializeNotifyRoutine);

    return TRUE;
}

LPCUSB_ENDPOINT FindEndpoint(LPCUSB_INTERFACE lpInterface,
        UCHAR bEndpointAddress)
{
    UINT cEndpoints = lpInterface->Descriptor.bNumEndpoints;

    PCUSB_ENDPOINT pEndpoint = lpInterface->lpEndpoints;

    for(UINT iEndpoint = 0 ; iEndpoint < cEndpoints ; ++iEndpoint)
    {
        if(pEndpoint->Descriptor.bEndpointAddress == bEndpointAddress)
        {
            return pEndpoint;
        }
        ++pEndpoint;
    }

    return NULL;
}


// Routines to check for valid handles.  Since we don't have system handles,
// just pointers, we have to be careful about freeing memory when clients might
// potentially still hang on to the invalid pointers.  For example, a client
// driver might do a ClosePipe() and then later try to issue a transfer on
// the pipe.  It would be better if we returned an error saying the pipe was
// invalid, rather than partying on freed memory.
// To attempt to accomplish this, we use signatures in our handle structures,
// and place pipe and handle structures on free lists, and only free the memory
// when the device is removed, and the client driver has been unloaded.  Note
// that we are still open to the possibility of the handles being reused off of
// the free list -- this may cause strange behavior, but should not crash USBD.
//
// Additionally, keep a refcnt for each handle, which will be incremented while
// a handle is actively being used by USBD (i.e. when in a USBD call only).
BOOL ReferencePipeHandle(SPipe *pPipe)
{
    if (!pPipe)
    {
        DEBUGMSG(ZONE_WARNING,(TEXT("!USBD: NULL Pipe handle.\r\n")));
        return FALSE;
    }
    __try {
        if (pPipe->dwSig != VALID_PIPE_SIG) {
            DEBUGMSG(ZONE_WARNING,(TEXT("!USBD: Invalid Pipe handle 0x%X (sig 0x%X)\r\n"),
                                 pPipe,pPipe->dwSig));
            return FALSE;
        }
    } __except(EXCEPTION_EXECUTE_HANDLER) {
          DEBUGMSG(ZONE_ERROR,(TEXT("!USBD: Exception checking Pipe handle 0x%X\r\n"),pPipe));
          return FALSE;
    }
    InterlockedIncrement((long *)&pPipe->iRefCnt);
    return TRUE;
}
void DereferencePipeHandle(SPipe *pPipe)
{
    ASSERT(pPipe->iRefCnt > 0);
    InterlockedDecrement((long *)&pPipe->iRefCnt);
}

// Validate device handle.  We don't need to refcnt these, since client drivers
// can't close them.
BOOL ValidateDeviceHandle(SDevice *pDev)
{
    __try {
        if (pDev->dwSig != VALID_DEVICE_SIG) {
            DEBUGMSG(ZONE_WARNING,(TEXT("!USBD: Invalid device handle 0x%X (sig 0x%X)\r\n"),
                                 pDev,pDev->dwSig));
            return FALSE;
        }
    } __except(EXCEPTION_EXECUTE_HANDLER) {
          DEBUGMSG(ZONE_ERROR,(TEXT("!USBD: Exception checking device handle 0x%X\r\n"),pDev));
          return FALSE;
    }
    return TRUE;
}

// Validate and lock transfer handle
BOOL ReferenceTransferHandle(STransfer *pTransfer)
{
    __try {
        if (pTransfer->dwSig != VALID_TRANSFER_SIG) {
            DEBUGMSG(ZONE_WARNING,(TEXT("!USBD: Invalid transfer handle 0x%X (sig 0x%X)\r\n"),
                                 pTransfer,pTransfer->dwSig));
            return FALSE;
        }
    } __except(EXCEPTION_EXECUTE_HANDLER) {
          DEBUGMSG(ZONE_ERROR,(TEXT("!USBD: Exception checking transfer handle 0x%X\r\n"),pTransfer));
          return FALSE;
    }
    InterlockedIncrement((long *)&pTransfer->iRefCnt);
    return TRUE;
}

void DereferenceTransferHandle(STransfer *pTransfer)
{
    ASSERT(pTransfer->iRefCnt > 0);
    InterlockedDecrement((long *)&pTransfer->iRefCnt);
}

// Get a pipe handle off of the device free list, or allocate and init a new one.
SPipe *GetPipeObject(SDevice *pDev)
{
    SPipe *pPipe = NULL;
    EnterCriticalSection(&pDev->csPipeLock);
    if (pDev->pFreePipeList) {
        pPipe = pDev->pFreePipeList;
        pDev->pFreePipeList = pPipe->pNext;
    }
    LeaveCriticalSection(&pDev->csPipeLock);
    if (pPipe == NULL) {
        pPipe = new SPipe;
        if (pPipe == NULL)
            return NULL;
        memset(pPipe,0,sizeof(SPipe));
        pPipe->pDevice = pDev;
        InitializeCriticalSection(&pPipe->csTransferLock);
    }
    pPipe->dwSig = VALID_PIPE_SIG;
    ASSERT(pPipe->iRefCnt == 0);
    return pPipe;
}
// Put a pipe handle back on the free list for the device. First, make
// sure no one is still referencing it.
void FreePipeObject(SPipe *pPipe)
{
    ULONG iTry=0;
    SDevice *pDev = pPipe->pDevice;
    pPipe->dwSig = FREE_PIPE_SIG;

    // Wait for refcnt to go to 0
    while (pPipe->iRefCnt && (iTry++<10)) {
        DEBUGMSG(ZONE_WARNING,
                 (TEXT("USBD:FreePipeObject(0x%X), waiting for refcnt:%u, try:%u\r\n"),
                 pPipe,pPipe->iRefCnt,iTry));
        Sleep(500);
    }
    if (pPipe->iRefCnt)
    {
        // Someone won't let go of resource, don't stick it on free list...
        DEBUGMSG(ZONE_ERROR,(TEXT("!USBD:FreePipeObject(0x%X) timed out waiting for refcnt!\r\n"),pPipe));
        ASSERT(FALSE);
        return;
    }

    EnterCriticalSection(&pDev->csPipeLock);
    pPipe->pNext = pDev->pFreePipeList;
    pDev->pFreePipeList = pPipe;
    LeaveCriticalSection(&pDev->csPipeLock);
}

// Free memory and system resources associated with a pipe handle
void FreePipeObjectMem(SPipe *pPipe)
{
    DeleteCriticalSection(&pPipe->csTransferLock);
    delete pPipe;
}

// Get a transfer handle off of the pipe free list.
STransfer * GetTransferObject(SPipe *pPipe, DWORD dwIsochFrames)
{
    STransfer *pTransfer=NULL;

    EnterCriticalSection(&pPipe->csTransferLock);
    if (pPipe->pFreeTransferList) {
        pTransfer = pPipe->pFreeTransferList;
        pPipe->pFreeTransferList = pTransfer->pNext;
    }
    LeaveCriticalSection(&pPipe->csTransferLock);

    if (pTransfer == NULL) {
        // Allocate a new transfer struct and set it up
        pTransfer = new STransfer;
        if (pTransfer == NULL)
            return NULL;
        memset(pTransfer,0,sizeof(STransfer));
        InitializeCriticalSection(&pTransfer->csWaitObject);
        pTransfer->pPipe = pPipe;
    }

    ASSERT(pTransfer->iRefCnt == 0);

    // If array lengths aren't big enough, free old arrays and allocate
    // new ones. Typically, isoch transfers on the same pipe will
    // use the same # of frames, so this path should usually only
    // be taken for newly allocated transfer structs.
    if (pTransfer->cFrames < dwIsochFrames) {
        if(pTransfer->adwIsochErrors) {
            delete [] pTransfer->adwIsochErrors;
            pTransfer->adwIsochErrors = NULL;
        }
        if(pTransfer->adwIsochLengths) {
            delete [] pTransfer->adwIsochLengths;
            pTransfer->adwIsochLengths = NULL;
        }
        pTransfer->cFrames = dwIsochFrames;
        if (dwIsochFrames) {
            pTransfer->adwIsochErrors = new DWORD[dwIsochFrames];
            pTransfer->adwIsochLengths = new DWORD[dwIsochFrames];
            if ((pTransfer->adwIsochErrors == NULL) ||
                (pTransfer->adwIsochLengths == NULL)) {
                FreeTransferObjectMem(pTransfer);
                return NULL;
            }
        }
    }
    // OK, flag handle as valid
    pTransfer->dwSig = VALID_TRANSFER_SIG;
    return pTransfer;
}

// Put transfer handle on pipe free list
void FreeTransferObject(STransfer *pTransfer)
{
    ULONG iTry=0;
    SPipe *pPipe = pTransfer->pPipe;
    // Mark transfer as freed for ReferenceTransferHandle().  Watch for race condition
    // if two threads are trying to close simultaneously (typically happens in device
    // detach processing).
    EnterCriticalSection(&pPipe->csTransferLock);
    if (pTransfer->dwSig != VALID_TRANSFER_SIG) {
        DEBUGMSG(ZONE_WARNING,(TEXT("USBD:FreeTransferObject(0x%X), already free, refcnt:%u\r\n"),
                               pTransfer,pTransfer->iRefCnt));
        LeaveCriticalSection(&pPipe->csTransferLock);
        return;
    }
    pTransfer->dwSig = FREE_TRANSFER_SIG;
    LeaveCriticalSection(&pPipe->csTransferLock);

    // Wait for refcnt to go to 0
    while (pTransfer->iRefCnt && (++iTry < 10)) {
        DEBUGMSG(ZONE_WARNING,
                 (TEXT("USBD:FreeTransferObject(0x%X), waiting for refcnt:%u, try:%u\r\n"),
                 pTransfer,pTransfer->iRefCnt,iTry));
        Sleep(500);
    }

    if (pTransfer->iRefCnt)
    {
        // Someone won't let go of resource, don't stick it on free list...
        DEBUGMSG(ZONE_ERROR,(TEXT("!USBD:FreeTransferObject(0x%X) timed out waiting for refcnt!\r\n"),pTransfer));
        ASSERT(FALSE);
        return;
    }

    if (pTransfer->pWait)
    {
        FreeWaitObject(pTransfer->pWait);
        pTransfer->pWait = NULL;
    }
    EnterCriticalSection(&pPipe->csTransferLock);
    pTransfer->pNext = pPipe->pFreeTransferList;
    pPipe->pFreeTransferList = pTransfer;
    LeaveCriticalSection(&pPipe->csTransferLock);
}

// Free memory and resources held by transfer object.  Must
// have been fully initialized in GetTransferObject().
void FreeTransferObjectMem(STransfer *pTransfer)
{
    DeleteCriticalSection(&pTransfer->csWaitObject);
    if(pTransfer->adwIsochErrors)
        delete [] pTransfer->adwIsochErrors;
    if(pTransfer->adwIsochLengths)
        delete [] pTransfer->adwIsochLengths;
    delete pTransfer;
}

SWait * GetWaitObject()
{
    SWait * pWait = new SWait;

    if (pWait == NULL)
        return NULL;

    pWait->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

    if(pWait->hEvent == NULL)
    {
        delete pWait;
        pWait = NULL;
    }
    return pWait;
}


BOOL FreeWaitObject(SWait * pWait)
{
    if(pWait)
    {
        if(pWait->hEvent)
            CloseHandle(pWait->hEvent);
        delete pWait;
    }

    return TRUE;
}

⌨️ 快捷键说明

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