📄 usbehcdeventhandler.c
字号:
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); pQTDTail = (pUSB_EHCD_QTD)pRequestInfo->pTail; pQTDHead = (pUSB_EHCD_QTD)pRequestInfo->pHead; /* 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)); /* This condition will check the following * 1. All the TDs for the request are completed successfully. * 2. If any of the TD is completed with a size which is less * than that expected.(short packet) * 3. Any of the TD is completed with error * If any of the above conditions are valid, the TDs are added * to the free list and the callback for the request is called. */ if (0 == (USB_EHCD_GET_BITFIELD(QTD, pQTDHead->uTransferInfo, TOKEN_STATUS)& USB_EHCD_QTD_STATUS_ACTIVE)) { /* To hold the temporary pointer of the QTD */ pUSB_EHCD_QTD pQTDTempHead = NULL; /* Flag to indicate whether the request is completed */ BOOLEAN bRequestCompleted = FALSE; /* If the tail of the request QTD is completed, then the * request is completed */ if (0 == (USB_EHCD_GET_BITFIELD(QTD, pQTDTail->uTransferInfo, TOKEN_STATUS)& USB_EHCD_QTD_STATUS_ACTIVE)) { bRequestCompleted = TRUE; /* Update the temporary pointer with the value of the tail. * This is required to update the status of the URB. */ pTempQTD = pQTDTail; } /* Whole of the request is not completed */ else { /* 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(QTD, pQTDTempHead->uTransferInfo, TOKEN_STATUS)& USB_EHCD_QTD_STATUS_ACTIVE)) { /* Check if the TD has transferred data * less than expected 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(QTD, pQTDTempHead->uTransferInfo, TOKEN_STATUS)& USB_EHCD_QTD_STATUS_HALTED)) || (0 != USB_EHCD_GET_BITFIELD( 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; } } } /* 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 number of bytes transferred */ usbEhcdUpdateNonIsochBytesTransferred( pQTDHead, pQTDTail, &pRequestInfo->pUrb->uTransferLength); /* Update the status of the URB */ usbEhcdUpdateNonIsochStatus( (UINT8)USB_EHCD_GET_BITFIELD(QTD, pTempQTD->uTransferInfo, TOKEN_STATUS), pRequestInfo->pUrb, &uHalted); /* 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)) { /* Set the endpoint's halted bit */ pHCDPipe->bIsHalted = 1; } /* 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(QH, pHCDPipe->pQH->uNextQtdPointer, USB_EHCD_INVALID_LINK, NEXTQTD_POINTER_T); /* Update the HC's next pointer */ USB_EHCD_SET_BITFIELD(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(QH, pHCDPipe->pQH->uNextQtdPointer, USB_EHCD_INVALID_LINK, NEXTQTD_POINTER_T); } else /* The endpoint's halt bit is not set */ { /* Update the HC's next pointer */ USB_EHCD_SET_BITFIELD( QH, pHCDPipe->pQH->uNextQtdPointer, (((unsigned) USB_EHCD_CONVERT_TO_PCI(pHCDPipe->pQH->pQTD)) >> 5), NEXTQTD_POINTER); /* Indicate that this is an invalid element * in the list */ USB_EHCD_SET_BITFIELD(QH, pHCDPipe->pQH->uNextQtdPointer, USB_EHCD_VALID_LINK, NEXTQTD_POINTER_T); } } /* If HCD is halted, clear the halt * condition on the pipe */ if (1 == uHalted) { /* Clear the halt conditions on the pipe */ USB_EHCD_SET_BITFIELD(QH, pHCDPipe->pQH->uTransferInfo, 0, TRANSFERINFO_STATUS); } /* Flush the contents of the cache to the RAM */ CACHE_DMA_FLUSH(pHCDPipe->pQH, sizeof(USB_EHCD_QH)); /* Flush the contents of the cache to the RAM */ CACHE_DMA_INVALIDATE(pHCDPipe->pQH, sizeof(USB_EHCD_QH)); } else { /* This check might be redundant as the controller always * processes the first request queued. Need to check * whether this needs to be retained */ /* Search for the request in the list */ for (pTempRequestInfo = pHCDPipe->pRequestQueueHead; (NULL != pTempRequestInfo) && (pTempRequestInfo->pNext != pRequestInfo); pTempRequestInfo = pTempRequestInfo->pNext); /* If the temporary request pointer is NULL, * it is an error */ OS_ASSERT(NULL != pTempRequestInfo); /* Update the next pointers */ pTempRequestInfo->pNext = pRequestInfo->pNext; } /* Remove the request from the Endpoint list - End */ /* Update the temp pointer which is used for freeing */ pTempRequestInfo = pRequestInfo; /* Update the request pointer */ pRequestInfo = pRequestInfo->pListRequest; /* Release the event */ OS_RELEASE_EVENT(pEHCDData->RequestSynchEventID); /* If the endpoint is halted, inform the USBD of the error */ if (pHCDPipe->bIsHalted) { uWvalue = (((UINT16)(pHCDPipe->uEndpointDir) << 15) | ((UINT16)(pHCDPipe->uEndpointType) << 11)| ((UINT16)(pHCDPipe->uAddress) << 4) | ((UINT16)(pHCDPipe->uEndpointAddress & USB_EHCD_ENDPOINT_TYPE_MASK))); /* Inform USBD about the error */ /* check if the function is NOT null and call the function */ if (NULL != g_USBDRequestFunctions.clearTTRequest) { g_USBDRequestFunctions.clearTTRequest ( g_EHCDHandle, pEHCDData->uBusIndex, USB_EHCD_GET_BITFIELD(QH, pHCDPipe->pQH->uEndPointCapabilities, ENDPOINT_CAPABILITIES_HUB_ADDR), USB_EHCD_GET_BITFIELD(QH, pHCDPipe->pQH->uEndPointCapabilities, ENDPOINT_CAPABILITIES_PORT_NUMBER), ((pHCDPipe->uAddress << 8) | pHCDPipe->uEndpointAddress), (VOID *)pHCDPipe ); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -