📄 usbd.cpp
字号:
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 + -