/** * @brief USBH_InterruptReceiveData * Receives the Device Response to the Interrupt IN token * @param pcore: Selected Core Peripheral * @param buff: Buffer pointer in which the response needs to be copied * @param length: Length of the data to be received * @param hc_num: Host channel Number * @retval Status. */ USBH_Status USBH_InterruptReceiveData( USB_OTG_CORE_HANDLE *pcore, uint8_t *buff, uint8_t length, uint8_t hc_num) { pcore->host.hc[hc_num].ep_is_in = 1; pcore->host.hc[hc_num].xfer_buff = buff; pcore->host.hc[hc_num].xfer_len = length; if(pcore->host.hc[hc_num].toggle_in == 0) { pcore->host.hc[hc_num].data_pid = HC_PID_DATA0; } else { pcore->host.hc[hc_num].data_pid = HC_PID_DATA1; } /* toggle DATA PID */ pcore->host.hc[hc_num].toggle_in ^= 1; HCD_SubmitRequest (pcore , hc_num); return USBH_OK; }
/** * @brief USBH_InterruptSendData * Sends the data on Interrupt OUT Endpoint * @param pdev: Selected device * @param buff: Buffer pointer from where the data needs to be copied * @param length: Length of the data to be sent * @param hc_num: Host channel Number * @retval Status. */ USBH_Status USBH_InterruptSendData( USB_OTG_CORE_HANDLE *pdev, uint8_t *buff, uint8_t length, uint8_t hc_num) { pdev->host.hc[hc_num].ep_is_in = 0; pdev->host.hc[hc_num].xfer_buff = buff; pdev->host.hc[hc_num].xfer_len = length; if(pdev->host.hc[hc_num].toggle_in == 0) { pdev->host.hc[hc_num].data_pid = HC_PID_DATA0; } else { pdev->host.hc[hc_num].data_pid = HC_PID_DATA1; } pdev->host.hc[hc_num].toggle_in ^= 1; HCD_SubmitRequest (pdev , hc_num); return USBH_OK; }
/** * @brief USBH_CtlSendData * Sends a data Packet to the Device * @param pdev: Selected device * @param buff: Buffer pointer from which the Data will be sent to Device * @param length: Length of the data to be sent * @param hc_num: Host channel Number * @retval Status */ USBH_Status USBH_CtlSendData ( USB_OTG_CORE_HANDLE *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num) { pdev->host.hc[hc_num].ep_is_in = 0; pdev->host.hc[hc_num].xfer_buff = buff; pdev->host.hc[hc_num].xfer_len = length; if ( length == 0 ) { /* For Status OUT stage, Length==0, Status Out PID = 1 */ pdev->host.hc[hc_num].toggle_out = 1; } /* Set the Data Toggle bit as per the Flag */ if ( pdev->host.hc[hc_num].toggle_out == 0) { /* Put the PID 0 */ pdev->host.hc[hc_num].data_pid = HC_PID_DATA0; } else { /* Put the PID 1 */ pdev->host.hc[hc_num].data_pid = HC_PID_DATA1 ; } HCD_SubmitRequest (pdev , hc_num); return USBH_OK; }
/** * @brief USBH_InterruptReceiveData * Receives the Device Response to the Interrupt IN token * @param pdev: Selected device * @param buff: Buffer pointer in which the response needs to be copied * @param length: Length of the data to be received * @param hc_num: Host channel Number * @retval Status. */ USBH_Status USB::USBH_InterruptReceiveData(uint8_t *buff, uint8_t length, uint8_t hc_num) { //TODO: merge this function with InTransfer USB_OTG_CORE_HANDLE *pdev = coreConfig; pdev->host.hc[hc_num].ep_is_in = 1; pdev->host.hc[hc_num].xfer_buff = buff; pdev->host.hc[hc_num].xfer_len = length; if(pdev->host.hc[hc_num].toggle_in == 0) { pdev->host.hc[hc_num].data_pid = HC_PID_DATA0; } else { pdev->host.hc[hc_num].data_pid = HC_PID_DATA1; } /* toggle DATA PID */ pdev->host.hc[hc_num].toggle_in ^= 1; HCD_SubmitRequest (pdev , hc_num); return USBH_OK; }
/** * @brief USBH_CtlSendSetup * Sends the Setup Packet to the Device * @param pdev: Selected device * @param buff: Buffer pointer from which the Data will be send to Device * @param hc_num: Host channel Number * @retval Status */ USBH_Status USBH_CtlSendSetup ( USB_OTG_CORE_HANDLE *pdev, uint8_t *buff, uint8_t hc_num){ pdev->host.hc[hc_num].ep_is_in = 0; pdev->host.hc[hc_num].data_pid = HC_PID_SETUP; pdev->host.hc[hc_num].xfer_buff = buff; pdev->host.hc[hc_num].xfer_len = USBH_SETUP_PKT_SIZE; return (USBH_Status)HCD_SubmitRequest (pdev , hc_num); }
/** * @brief USBH_IsocSendData * Sends the data on Isochronous OUT Endpoint * @param pdev: Selected device * @param buff: Buffer pointer from where the data needs to be copied * @param length: Length of the data to be sent * @param hc_num: Host channel Number * @retval Status. */ USBH_Status USBH_IsocSendData( USB_OTG_CORE_HANDLE *pdev, uint8_t *buff, uint32_t length, uint8_t hc_num) { pdev->host.hc[hc_num].ep_is_in = 0; pdev->host.hc[hc_num].xfer_buff = buff; pdev->host.hc[hc_num].xfer_len = length; pdev->host.hc[hc_num].data_pid = HC_PID_DATA0; HCD_SubmitRequest (pdev , hc_num); return USBH_OK; }
/** * @brief USBH_CtlReceiveData * Receives the Device Response to the Setup Packet * @param pdev: Selected device * @param buff: Buffer pointer in which the response needs to be copied * @param length: Length of the data to be received * @param hc_num: Host channel Number * @retval Status. */ USBH_Status USBH_CtlReceiveData(USB_OTG_CORE_HANDLE *pdev, uint8_t* buff, uint16_t length, uint8_t hc_num) { pdev->host.hc[hc_num].ep_is_in = 1; pdev->host.hc[hc_num].data_pid = HC_PID_DATA1; pdev->host.hc[hc_num].xfer_buff = buff; pdev->host.hc[hc_num].xfer_len = length; HCD_SubmitRequest (pdev , hc_num); return USBH_OK; }
/** * @brief USBH_IsocReceiveData * Receives the Device Response to the Isochronous IN token * @param pcore: Selected Core Peripheral * @param buff: Buffer pointer in which the response needs to be copied * @param length: Length of the data to be received * @param hc_num: Host channel Number * @retval Status. */ USBH_Status USBH_IsocReceiveData( USB_OTG_CORE_HANDLE *pcore, uint8_t *buff, uint32_t length, uint8_t hc_num) { pcore->host.hc[hc_num].ep_is_in = 1; pcore->host.hc[hc_num].xfer_buff = buff; pcore->host.hc[hc_num].xfer_len = length; pcore->host.hc[hc_num].data_pid = HC_PID_DATA0; HCD_SubmitRequest (pcore , hc_num); return USBH_OK; }
/** * @brief USBH_BulkSendData * Sends the Bulk Packet to the device * @param pcore: Selected Core Peripheral * @param buff: Buffer pointer from which the Data will be sent to Device * @param length: Length of the data to be sent * @param hc_num: Host channel Number * @retval Status */ USBH_Status USBH_BulkSendData ( USB_OTG_CORE_HANDLE *pcore, uint8_t *buff, uint16_t length, uint8_t hc_num) { pcore->host.hc[hc_num].ep_is_in = 0; pcore->host.hc[hc_num].xfer_buff = buff; pcore->host.hc[hc_num].xfer_len = length; /* Set the Data Toggle bit as per the Flag */ if ( pcore->host.hc[hc_num].toggle_out == 0) { /* Put the PID 0 */ pcore->host.hc[hc_num].data_pid = HC_PID_DATA0; } else { /* Put the PID 1 */ pcore->host.hc[hc_num].data_pid = HC_PID_DATA1 ; } HCD_SubmitRequest (pcore , hc_num); return USBH_OK; }
/** * @brief USBH_CtlSendData * Sends a data Packet to the Device * @param pdev: Selected device * @param buff: Buffer pointer from which the Data will be sent to Device * @param length: Length of the data to be sent * @param hc_num: Host channel Number * @retval Status */ USBH_Status USBH_CtlSendData ( USB_OTG_CORE_HANDLE *pdev, uint8_t *buff, uint8_t length, uint8_t hc_num) { pdev->host.hc[hc_num].ep_is_in = 0; pdev->host.hc[hc_num].xfer_buff = buff; pdev->host.hc[hc_num].xfer_len = length; if(HCD_GetURB_State(pdev) == URB_DONE) { /* Toggle the Bit fore previous successful Transaction */ pdev->host.hc[hc_num].toggle_out ^= 1; } if ( length == 0 ) { /* For Status OUT stage, Length==0, Status Out PID = 1 */ pdev->host.hc[hc_num].toggle_out = 1; } /* Set the Data Toggle bit as per the Flag */ if ( pdev->host.hc[hc_num].toggle_out == 0) { /* Put the PID 0 */ pdev->host.hc[hc_num].data_pid = HC_PID_DATA0; } else { /* Put the PID 1 */ pdev->host.hc[hc_num].data_pid = HC_PID_DATA1 ; } HCD_SubmitRequest (pdev , hc_num); return USBH_OK; }
/* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout */ uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit, uint8_t *data_p = NULL, uint16_t nbytes = 0, uint8_t hcnum = 0) { unsigned long timeout = millis() + USB_XFER_TIMEOUT; //unsigned long timeout2 = timeout; uint8_t tmpdata; uint8_t rcode = hrSUCCESS; uint8_t retry_count = 0; uint16_t nak_count = 0; USB_OTG_CORE_HANDLE *pdev = coreConfig; uint8_t pid = 0; pdev->host.hc[hcnum].nak_count = 0; pdev->host.hc[hcnum].nak_limit = nak_limit; while (timeout > millis()) { //regWr(rHXFR, (token | ep)); //launch the transfer if(token == tokSETUP) { USBH_CtlSendSetup(pdev, data_p, hcnum); //timeout2 = millis() + 10; } else { if(token == tokOUTHS) { pdev->host.hc[hcnum].toggle_out = 0x1; pdev->host.hc[hcnum].ep_is_in = 0; pid = HC_PID_DATA1; } else if (token == tokINHS) { pdev->host.hc[hcnum].toggle_in = 0x1; pdev->host.hc[hcnum].ep_is_in = 1; pid = HC_PID_DATA1; } else if (token == tokIN){ pdev->host.hc[hcnum].ep_is_in = 1; pid = (pdev->host.hc[hcnum].toggle_in)? HC_PID_DATA1 : HC_PID_DATA0; } else { pdev->host.hc[hcnum].ep_is_in = 0; pid = (pdev->host.hc[hcnum].toggle_out)? HC_PID_DATA1 : HC_PID_DATA0; }/* if(pid == HC_PID_DATA0) { STM_EVAL_LEDToggle(LED1); delay_ms(1); STM_EVAL_LEDToggle(LED1); delay_ms(1); STM_EVAL_LEDToggle(LED1); } if(pid == HC_PID_DATA1) { STM_EVAL_LEDToggle(LED1); delay_ms(1); STM_EVAL_LEDToggle(LED1); delay_ms(1); STM_EVAL_LEDToggle(LED1); delay_ms(1); STM_EVAL_LEDToggle(LED1); }*/ pdev->host.hc[hcnum].data_pid = pid; pdev->host.hc[hcnum].xfer_buff = data_p; pdev->host.hc[hcnum].xfer_len = nbytes; HCD_SubmitRequest(pdev, hcnum); } rcode = USB_ERROR_TRANSFER_TIMEOUT; while (timeout > millis()) //wait for transfer completion { tmpdata = HCD_GetURB_State(pdev, hcnum); //regRd(rHIRQ); if (tmpdata != URB_IDLE) { //& bmHXFRDNIRQ) { //regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt rcode = 0x00; break; } if (pdev->host.ConnSts == 0) { rcode = hrJERR; return rcode; } /* else { //todo: because in bt case, there are two in ep (int-in, bulk-in), that we need to check hid/msc case either. rcode = HCD_GetHCState(pdev, hcnum); if(rcode == hrNAK) { nak_count++; if (nak_limit && (nak_count == nak_limit)) return (rcode); uint8_t eptype = pdev->host.hc[hcnum].ep_type; if (eptype == EP_TYPE_INTR) { break; } else if ((eptype == EP_TYPE_CTRL) || (eptype == EP_TYPE_BULK)) { // re-activate the channel USB_OTG_HCCHAR_TypeDef hcchar; hcchar.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[hcnum]->HCCHAR); hcchar.b.chen = 1; hcchar.b.chdis = 0; USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hcnum]->HCCHAR, hcchar.d32); delay_us(200); } } }*/ } //if (rcode != 0x00) //exit if timeout // return ( rcode); rcode = HCD_GetHCState(pdev, hcnum); //(regRd(rHRSL) & 0x0f); //analyze transfer result switch (rcode) { case hrNAK: //todo: if timeout above with nak, we need to consider the next xfer. nak_count = pdev->host.hc[hcnum].nak_count; if (nak_limit && (nak_count == nak_limit)) return (rcode); break; case hrTIMEOUT: retry_count++; if (retry_count == USB_RETRY_LIMIT) return (rcode); break; default: return (rcode); } }//while( timeout > millis() return ( rcode); }
uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data) { uint8_t rcode = hrSUCCESS, retry_count; uint8_t *data_p = data; //local copy of the data pointer uint16_t bytes_tosend, nak_count; uint16_t bytes_left = nbytes, last_bytesleft = nbytes; USB_OTG_CORE_HANDLE *pdev = coreConfig; uint32_t hcnum = pep->hcNumOut; uint8_t maxpktsize = pep->maxPktSize; if (maxpktsize < 1 || maxpktsize > 64) return USB_ERROR_INVALID_MAX_PKT_SIZE; if(maxpktsize != pdev->host.hc[hcnum].max_packet) pdev->host.hc[hcnum].max_packet = maxpktsize; #if 0 pdev->host.hc[hcnum].ep_is_in = 0; pdev->host.hc[hcnum].xfer_buff = data; //buff; pdev->host.hc[hcnum].xfer_len = nbytes; //length; if(nbytes == 0) { /* For Status OUT stage, Length==0, Status Out PID = 1 */ pdev->host.hc[hcnum].toggle_out = 1; } /* Set the Data Toggle bit as per the Flag */ if ( pdev->host.hc[hcnum].toggle_out == 0) { /* Put the PID 0 */ pdev->host.hc[hcnum].data_pid = HC_PID_DATA0; } else { /* Put the PID 1 */ pdev->host.hc[hcnum].data_pid = HC_PID_DATA1 ; } HCD_SubmitRequest (pdev, hcnum); #else unsigned long timeout = millis() + USB_XFER_TIMEOUT; //regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value pdev->host.hc[hcnum].ep_is_in = 0; pdev->host.hc[hcnum].xfer_buff = data; //buff; pdev->host.hc[hcnum].xfer_len = nbytes; //length; if(nbytes == 0) { /* For Status OUT stage, Length==0, Status Out PID = 1 */ pdev->host.hc[hcnum].toggle_out = 1; } /* Set the Data Toggle bit as per the Flag */ if ( pdev->host.hc[hcnum].toggle_out == 0) { /* Put the PID 0 */ pdev->host.hc[hcnum].data_pid = HC_PID_DATA0; } else { /* Put the PID 1 */ pdev->host.hc[hcnum].data_pid = HC_PID_DATA1 ; } retry_count = 0; nak_count = 0; while (bytes_left) { // we send all data at once due to large fifo //bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left; //bytesWr(rSNDFIFO, bytes_tosend, data_p); //filling output FIFO //regWr(rSNDBC, bytes_tosend); //set number of bytes //regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet HCD_SubmitRequest(pdev, hcnum); PollStatus: rcode = USB_ERROR_TRANSFER_TIMEOUT; while (timeout > millis()) //while (!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ { rcode = HCD_GetURB_State(pdev, hcnum); //regRd(rHIRQ); if (rcode != URB_IDLE) { //& bmHXFRDNIRQ) { //regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ rcode = 0x00; break; } } if(rcode != 0x00) return rcode; // todo: return for what rcode = HCD_GetHCState(pdev, hcnum); //(regRd(rHRSL) & 0x0f); //while (rcode && (timeout > millis())) { // we don't need pulling here because we already did it above switch (rcode) { case hrNAK: nak_count++; //maybe a NOT_READY happens if (nak_limit && (nak_count == nak_limit)) goto breakout; /* else if (URB_NOTREADY == HCD_GetURB_State(pdev, hcnum)) { USB_OTG_HCCHAR_TypeDef hcchar; hcchar.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[hcnum]->HCCHAR); if(hcchar.b.eptype == EP_TYPE_BULK) { pdev->host.URB_State[hcnum] = URB_IDLE; // re-activate the channel hcchar.b.chen = 1; hcchar.b.chdis = 0; USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hcnum]->HCCHAR, hcchar.d32); STM_EVAL_LEDToggle(LED1); goto PollStatus; //return ( rcode); } }*/ break; case hrTIMEOUT: retry_count++; if (retry_count == USB_RETRY_LIMIT) goto breakout; //return ( rcode); break; case hrTOGERR: // yes, we flip it wrong here so that next time it is actually correct! //pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; //regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value printf("\nOutTransfer - togerr"); //break; default: goto breakout; }//switch( rcode /* process NAK according to Host out NAK bug */ /* uint32_t *addr; uint32_t i; for(addr = (uint32_t *)0x50000000, i = 0; i < 0x12; addr++, i++) { printf("\naddr(%x) = %x", addr, *addr); }*/ USB_OTG_HCTSIZn_TypeDef hctsiz; hctsiz.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[hcnum]->HCTSIZ); bytes_left = hctsiz.b.pktcnt << 6; if(last_bytesleft != bytes_left) { last_bytesleft = bytes_left; pdev->host.hc[hcnum].xfer_buff = data + nbytes - bytes_left; pdev->host.hc[hcnum].xfer_len = bytes_left; if(((nbytes - bytes_left) >> 6) & 0x1) { // if sent odd times packets pdev->host.hc[hcnum].toggle_out ^= 0x1; pdev->host.hc[hcnum].data_pid = (pdev->host.hc[hcnum].toggle_out) ? HC_PID_DATA1 : HC_PID_DATA0; } pdev->host.hc[hcnum].isEvenTimesToggle = 0; // will be re-calculate in HCD_SubmitRequest retry_count = 0; nak_count = 0; } //regWr(rSNDBC, 0); //regWr(rSNDFIFO, *data_p); //regWr(rSNDBC, bytes_tosend); //regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet //while (!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ //regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ //rcode = (regRd(rHRSL) & 0x0f); //}//while( rcode && .... // bytes_left seems never decreasing to 0 //bytes_left -= bytes_tosend; //data_p += bytes_tosend; }//while( bytes_left...
uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data) { uint8_t rcode = 0; uint8_t pktsize; uint16_t nbytes = *nbytesptr; //printf("Requesting %i bytes ", nbytes); uint16_t maxpktsize = pep->maxPktSize; USB_OTG_CORE_HANDLE *pdev = coreConfig; uint32_t hcnum = pep->hcNumIn; //pdev->host.hc_num_in; #if 0 // get all packets via rx fifo pdev->host.hc[hcnum].data_pid = (pdev->host.hc[hcnum].toggle_in) ? HC_PID_DATA1 : HC_PID_DATA0; pdev->host.hc[hcnum].ep_is_in = 1; pdev->host.hc[hcnum].xfer_buff = data; pdev->host.hc[hcnum].xfer_len = nbytes; HCD_SubmitRequest(pdev, hcnum); #else // get one packet per transfer. //*nbytesptr = 0; // 1. means how many bytes was received. // 2. on stm32, we receive all data at once, so we don't need to count this var. if(maxpktsize != pdev->host.hc[hcnum].max_packet) pdev->host.hc[hcnum].max_packet = maxpktsize; uint8_t ep_addr = pep->epAddr & 0x7F; // todo: dont like this, will remove "&0x7f" if(ep_addr != pdev->host.hc[hcnum].ep_num) pdev->host.hc[hcnum].ep_num = ep_addr; //USBH_Modify_Channel(pdev, hcnum, 0, ep_addr, 0, 0, 0); if(pep->bmRcvToggle != pdev->host.hc[hcnum].toggle_in) // for hid composite pdev->host.hc[hcnum].toggle_in = pep->bmRcvToggle; while (1) // use a 'return' to exit this loop { rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit, data, nbytes, hcnum); //IN packet to EP-'endpoint'. Function takes care of NAKS. if (rcode == hrTOGERR) { // yes, we flip it wrong here so that next time it is actually correct! // pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; // regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value STM_EVAL_LEDToggle(LED3); //pdev->host.hc[hcnum].toggle_in ^= 0x1; //btd hci case printf("\nInXfer - toggle err, hc num=%d", hcnum); // will meet toggle error here? todo: sometimes once unplugged device, there is small chance that Poll still works here. //continue; } if (rcode) { //printf("\r\n>>>>>>>> Problem! dispatchPkt %d", rcode); break; //should be 0, indicating ACK. Else return error code. } /* check for RCVDAVIRQ and generate error if not present */ /* the only case when absence of RCVDAVIRQ makes sense is when toggle error occurred. Need to add handling for that */ // if ((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) { //printf(">>>>>>>> Problem! NO RCVDAVIRQ!\r\n"); // rcode = 0xf0; //receive error // break; // } // pktsize = regRd(rRCVBC); //number of received bytes //printf("Got %i bytes \r\n", pktsize); // This would be OK, but... //assert(pktsize <= nbytes); // if (pktsize > nbytes) { // This can happen. Use of assert on Arduino locks up the Arduino. // So I will trim the value, and hope for the best. //printf(">>>>>>>> Problem! Wanted %i bytes but got %i.\r\n", nbytes, pktsize); // pktsize = nbytes; // } // int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr); // if (mem_left < 0) // mem_left = 0; // data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data); // regWr(rHIRQ, bmRCVDAVIRQ); // Clear the IRQ & free the buffer // *nbytesptr += pktsize; // add this packet's byte count to total transfer length /* The transfer is complete under two conditions: */ /* 1. The device sent a short packet (L.T. maxPacketSize) */ /* 2. 'nbytes' have been transferred. */ //if ((pktsize < maxpktsize) || (*nbytesptr >= nbytes)) // have we transferred 'nbytes' bytes? { // thanks to large fifo on stm32, we don't need packet by packet handling. // Save toggle value // the toggle is flipped at interrupt handler. //pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0; pep->bmRcvToggle = pdev->host.hc[hcnum].toggle_in; //save last toggle //printf("\r\n"); rcode = 0; break; } // if } //while( 1 ) #endif return ( rcode); }