//Poll a interrupt queue,check if the queue has been processed. //Please note it's a blocking poll,since HelloX's event mechanism is adopted. void* EHCIPollIntQueue(struct usb_device *dev,struct int_queue *queue) { DWORD dwResult = 0; void* pRet = NULL; dwResult = WaitForThisObjectEx(queue->hEvent, 5); //Wait for 5 millionseconds. switch (dwResult) { case OBJECT_WAIT_RESOURCE: if (INT_QUEUE_STATUS_COMPLETED == queue->dwStatus) { pRet = queue->first->buffer; } break; case OBJECT_WAIT_TIMEOUT: case OBJECT_WAIT_DELETED: case OBJECT_WAIT_FAILED: //Just for debugging. if (_ehciQueueIntHandler(queue)) { pRet = queue->first->buffer; debug("%s: Transimit success,int queue status = %X,overlay token = %X,qTD token = %X.\r\n", __func__, queue->dwStatus, queue->first->qh_overlay.qt_token, queue->tds->qt_token); return pRet; } else { debug("%s: Transmit failed,int queue status = %X,overlay_tok = %X,qTD_tok = %X.\r\n", __func__, queue->dwStatus, queue->current->qh_overlay.qt_token, queue->tds[queue->current - queue->first].qt_token); return pRet; } queue->dwStatus = INT_QUEUE_STATUS_CANCELED; break; default: BUG(); break; } return pRet; }
//Start USB isochronous transfer. BOOL usbStartISOXfer(__USB_ISO_DESCRIPTOR* pIsoDesc) { __COMMON_USB_CONTROLLER* pCommCtrl = NULL; struct iTD* pitd = NULL; struct usb_device* pUsbDev = NULL; struct ehci_ctrl* pEhciCtrl = NULL; DWORD dwResult = 0; BOOL bResult = FALSE; //int transact = 0; if (NULL == pIsoDesc) { goto __TERMINAL; } pCommCtrl = pIsoDesc->pCtrl; pUsbDev = pIsoDesc->pPhyDev->lpPrivateInfo; if ((NULL == pCommCtrl) || (NULL == pUsbDev)) { BUG(); } pitd = pIsoDesc->itdArray; pEhciCtrl = pCommCtrl->pUsbCtrl; if ((NULL == pitd) || (NULL == pEhciCtrl)) { BUG(); } //Set descriptor's status accordingly. pIsoDesc->status = USB_ISODESC_STATUS_INPROCESS; ResetEvent(pIsoDesc->hEvent); #if 0 //Set the act bit of each transaction(s) iTD descriptor,so controller will process it. for (int transact = 0; transact < 8; transact++) { if (0 == pitd->transaction[transact]) //Reach the end. { break; } pitd->transaction[transact] |= ITD_TRANS_STATUS_SET(ITD_TRANS_STATUS_ACT); //Just for debugging.__Fill_iTD should be called here... pitd->transaction[0] &= 0xF000FFFF; pitd->transaction[0] |= ITD_TRANS_XLEN_SET(pIsoDesc->bufflength); } #endif //Fill iTD's all variable fields. __Fill_iTD(pIsoDesc, pitd, pIsoDesc->direction, pIsoDesc->buffer, pIsoDesc->bufflength, pIsoDesc->endpoint, pIsoDesc->maxPacketSize, pIsoDesc->multi); flush_dcache_range((unsigned long)pitd, ALIGN_END_ADDR(struct iTD, pitd, 1)); //Start periodic schedule if not yet. WaitForThisObject(pEhciCtrl->hMutex); if (pEhciCtrl->periodic_schedules == 0) { ehci_enable_periodic(pEhciCtrl); pEhciCtrl->periodic_schedules++; } ReleaseMutex(pEhciCtrl->hMutex); //Pending on the descriptor to wait the arrival of data. dwResult = WaitForThisObjectEx(pIsoDesc->hEvent, USB_DEFAULT_XFER_TIMEOUT); switch (dwResult) { case OBJECT_WAIT_RESOURCE: if (USB_ISODESC_STATUS_COMPLETED == pIsoDesc->status) { bResult = TRUE; break; } if (USB_ISODESC_STATUS_ERROR == pIsoDesc->status) { //Try to restore from error. //IsoClearError(pIsoDesc); //Clear the act bit. pitd->transaction[0] &= ~0x80000000; pitd->transaction[1] &= ~0x80000000; pitd->transaction[2] &= ~0x80000000; pitd->transaction[3] &= ~0x80000000; pitd->transaction[4] &= ~0x80000000; pitd->transaction[5] &= ~0x80000000; pitd->transaction[6] &= ~0x80000000; pitd->transaction[7] &= ~0x80000000; flush_dcache_range((unsigned long)pitd, ALIGN_END_ADDR(struct iTD, pitd, 1)); break; } BUG(); break; case OBJECT_WAIT_TIMEOUT: case OBJECT_WAIT_FAILED: //Set status as canceled. pIsoDesc->status = USB_ISODESC_STATUS_CANCELED; //Clear the act bit. pitd->transaction[0] &= ~0x80000000; pitd->transaction[1] &= ~0x80000000; pitd->transaction[2] &= ~0x80000000; pitd->transaction[3] &= ~0x80000000; pitd->transaction[4] &= ~0x80000000; pitd->transaction[5] &= ~0x80000000; pitd->transaction[6] &= ~0x80000000; pitd->transaction[7] &= ~0x80000000; flush_dcache_range((unsigned long)pitd, ALIGN_END_ADDR(struct iTD, pitd, 1)); _hx_printf("%s:iTD timed out.\r\n", __func__); break; case OBJECT_WAIT_DELETED: BUG(); //Should not occur. break; default: _hx_printf("%s:unexcepted timeout waiting's return value[%d].\r\n", __func__, dwResult); BUG(); }