📄 usbehcdeventhandler.c
字号:
/* Flag to indicate whether the request is completed */ BOOLEAN bRequestCompleted = FALSE; UINT32 uBusIndex = 0; /* Index of the host controller */ UINT16 uWvalue =0; /* WindView Instrumentation */ USB_HCD_LOG_EVENT( USB_EHCI_WV_EVENT_HANDLER, "usbEhcdProcessTransferCompletion() starts", USB_EHCD_WV_FILTER); OS_LOG_MESSAGE_LOW(EHCD,"usbEhcdProcessTransferCompletion - Entry\n",0,0,0,0); /* Check the validity of the parameter */ if (NULL == pEHCDData) { OS_LOG_MESSAGE_HIGH(EHCD,"usbEhcdProcessTransferCompletion - Parameter is not valid\n",0,0,0,0); return; } /* Retrieve the bus index */ uBusIndex = pEHCDData->uBusIndex; /* Exclusively access the request list */ OS_WAIT_FOR_EVENT(pEHCDData->RequestSynchEventID,OS_WAIT_INFINITE); /* * This loop searches the list of requests * and identifies the requests which are completed */ for (pRequestInfo = pEHCDData->pRequestQueueHead; (NULL != pRequestInfo);) { /* Reset the request completed flag */ bRequestCompleted = FALSE; /* Assert if the pipe pointer is not valid */ OS_ASSERT(NULL != pRequestInfo->pHCDPipe); /* Assert if the URB pointer is not valid */ OS_ASSERT(NULL != pRequestInfo->pUrb); /* Check if it is a non-isochronous request */ if (USBHST_ISOCHRONOUS_TRANSFER != pRequestInfo->pHCDPipe->uEndpointType) { /* Pointer to the tail of Queue TD */ pUSB_EHCD_QTD pQTDTail = NULL; /* Pointer to the head of Queue TD */ pUSB_EHCD_QTD pQTDHead = NULL; /* Pointer to the temporary QH */ pUSB_EHCD_QTD pTempQTD = NULL; /* Get the tail of the TD list */ pQTDTail = (pUSB_EHCD_QTD)pRequestInfo->pTail; /* Get the head of the TD list */ pQTDHead = (pUSB_EHCD_QTD)pRequestInfo->pHead; /* Assert if the head or tail is invalid */ OS_ASSERT(NULL != pQTDHead); OS_ASSERT(NULL != pQTDTail); /* Invalidate the cache */ CACHE_DMA_INVALIDATE(pQTDTail, sizeof(USB_EHCD_QTD)); CACHE_DMA_INVALIDATE(pQTDHead, sizeof(USB_EHCD_QTD)); /* Added only for debug. needs to be removed after the testing */ /* Assert if the QH is not valid */ OS_ASSERT(NULL != pRequestInfo->pHCDPipe->pQH); /* Assert if the URB is invalid */ OS_ASSERT(NULL != pRequestInfo->pUrb); CACHE_DMA_INVALIDATE(pRequestInfo->pHCDPipe->pQH, sizeof(USB_EHCD_QH)); /* If the tail of the request is completed, the whole request is * completed */ if (0 == (USB_EHCD_GET_BITFIELD(uBusIndex, QTD, pQTDTail->uTransferInfo, TOKEN_STATUS)& USB_EHCD_QTD_STATUS_ACTIVE)) { /* Update the request completed flag */ bRequestCompleted = TRUE; /* Update the temporary pointer with the value of the tail. * This is required to update the status of the URB. */ pTempQTD = pQTDTail; } else { /* Check if the head is completed. If the head is completed, * there are 3 cases to be handled. * 1. The request is not handled * 2. The request has resulted in a transfer size which is * is less than the expected size * 3. The transfer has resulted in an error. */ if (0 == (USB_EHCD_GET_BITFIELD(uBusIndex, QTD, pQTDHead->uTransferInfo, TOKEN_STATUS)& USB_EHCD_QTD_STATUS_ACTIVE)) { /* To hold the temporary pointer of the QTD */ pUSB_EHCD_QTD pQTDTempHead = NULL; /* Copy the head onto the temporary pointer. This is * done to avoid changing the actual head pointer which * is used further down the code */ pQTDTempHead = pQTDHead; /* Check if any of the requests have completed with * halted bit set or with a size which is less * than that expected. */ for (; pQTDTempHead != pQTDTail; pQTDTempHead = pTempQTD) { /* Store the next pointer temporarily */ pTempQTD = (pUSB_EHCD_QTD)pQTDTempHead->pNext; /* Invalidate the cache */ CACHE_DMA_INVALIDATE(pTempQTD, sizeof(USB_EHCD_QTD)); /* Check if the QTD is completed */ if (0 == (USB_EHCD_GET_BITFIELD(uBusIndex, QTD, pQTDTempHead->uTransferInfo, TOKEN_STATUS)& USB_EHCD_QTD_STATUS_ACTIVE)) { /* Check if the TD has transferred data * less than expected (this can happen only * for a non-control transfer request) or * if the request has halted. The request is * completed if this condition is true. */ if ((USB_EHCD_QTD_STATUS_HALTED == (USB_EHCD_GET_BITFIELD(uBusIndex, QTD, pQTDTempHead->uTransferInfo, TOKEN_STATUS)& USB_EHCD_QTD_STATUS_HALTED)) || ((USBHST_CONTROL_TRANSFER != pRequestInfo->pHCDPipe->uEndpointType) && (0 != USB_EHCD_GET_BITFIELD(uBusIndex, QTD, pQTDTempHead->uTransferInfo, TOKEN_TOTAL_BYTES_TO_TRANSFER)))) { bRequestCompleted = TRUE; /* Update the temporary pointer so that it * can be used for updating the status of * the URB */ pTempQTD = pQTDTempHead; break; } } /* The request is not completed */ else { bRequestCompleted = FALSE; break; } }/* End of for () */ }/* End of if () */ }/* End of else */ /* If the request is not completed, goto the next element * in the HCD request list. */ if (FALSE == bRequestCompleted) { pPreRequestInfo = pRequestInfo; pRequestInfo = pRequestInfo->pListRequest; continue; } /* Update the non isochronous status and the number of * bytes transferred for the request */ usbEhcdUpdateNonIsochStatusAndBytes(uBusIndex, pQTDHead, pQTDTail, pRequestInfo->pUrb); /* Remove the request from the HCD list - Start */ /* This is the head element */ if (pRequestInfo == pEHCDData->pRequestQueueHead) { /* Update the head of the request list */ pEHCDData->pRequestQueueHead = pRequestInfo->pListRequest; /* Update the tail to NULL if the head is NULL */ if (NULL == pEHCDData->pRequestQueueHead) { pEHCDData->pRequestQueueTail = NULL; } } else { /* Update the next element in the request list */ pPreRequestInfo->pListRequest = pRequestInfo->pListRequest; /* If List Request for PreRequest is NULL, the update * Tail to prev request */ if (NULL == pPreRequestInfo->pListRequest) { pEHCDData->pRequestQueueTail = pPreRequestInfo; } } /* Remove the request from the HCD list - End */ /* Remove the request from the Endpoint list - Start */ /* Extract the pipe pointer for the request */ pHCDPipe = pRequestInfo->pHCDPipe; /* Check if it is a non-periodic and full/low speed endpoint * and the request has resulted in a Time out error */ if ((USBHST_INTERRUPT_TRANSFER != pRequestInfo->pHCDPipe->uEndpointType) && (USBHST_HIGH_SPEED != pRequestInfo->pHCDPipe->uSpeed) && (USBHST_TIMEOUT == pRequestInfo->pUrb->nStatus)) { /* Inform USBD about the error */ /* check if the function is NOT null and call the function */ if (NULL != g_USBDRequestFunctions.clearTTRequest) { /* Set the endpoint's halted bit */ pHCDPipe->bIsHalted = 1; /* Form the wValue which needs to be passed for the ClearTTBuffer * standard request */ uWvalue = (((UINT16)(pHCDPipe->uEndpointDir) << 15) | ((UINT16)(pHCDPipe->uEndpointType) << 11)| ((UINT16)(pHCDPipe->uAddress) << 4) | ((UINT16)(pHCDPipe->uEndpointAddress & USB_EHCD_ENDPOINT_TYPE_MASK))); /* Release the synchronization event */ OS_RELEASE_EVENT(pEHCDData->RequestSynchEventID); /* Call the callback function to issue a ClearTTBuffer * standard request */ g_USBDRequestFunctions.clearTTRequest ( g_EHCDHandle, uBusIndex, USB_EHCD_GET_BITFIELD( uBusIndex, QH, pHCDPipe->pQH->uEndPointCapabilities, ENDPOINT_CAPABILITIES_HUB_ADDR), (pHCDPipe->uHubInfo & 0xFF), uWvalue, (VOID *)pHCDPipe ); /* Acquire the event */ OS_WAIT_FOR_EVENT(pEHCDData->RequestSynchEventID, OS_WAIT_INFINITE); } } /* Check if it is the head element */ if (pRequestInfo == pHCDPipe->pRequestQueueHead) { /* * If it is the only element, * update the head and tail pointers to NULL. */ if (pRequestInfo == pHCDPipe->pRequestQueueTail) { pHCDPipe->pRequestQueueTail = NULL; pHCDPipe->pRequestQueueHead = NULL; pHCDPipe->pQH->pQTD = NULL; /* Indicate that there are no elements in the list */ USB_EHCD_SET_BITFIELD(uBusIndex, QH, pHCDPipe->pQH->uNextQtdPointer, USB_EHCD_INVALID_LINK, NEXTQTD_POINTER_T); /* Update the HC's next pointer */ USB_EHCD_SET_BITFIELD(uBusIndex, QH, pHCDPipe->pQH->uNextQtdPointer, (unsigned)NULL, NEXTQTD_POINTER) ; /* Flush the cache contents to the RAM */ CACHE_DMA_FLUSH(pHCDPipe->pQH, sizeof(USB_EHCD_QH)); /* Invalidate the cache contents */ CACHE_DMA_INVALIDATE(pHCDPipe->pQH, sizeof(USB_EHCD_QH)); } /* Update the head element */ else { pHCDPipe->pRequestQueueHead = pRequestInfo->pNext; pHCDPipe->pQH->pQTD = (pUSB_EHCD_QTD)pRequestInfo->pNext->pHead; /* If the pipe's halted bit is set, clear the halt * condition on the pipe */ if (pHCDPipe->bIsHalted) { /* Indicate that this is an invalid element * in the list */ USB_EHCD_SET_BITFIELD(uBusIndex, QH, pHCDPipe->pQH->uNextQtdPointer, USB_EHCD_INVALID_LINK, NEXTQTD_POINTER_T);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -