/* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error, fe USB xfer timeout */ byte USB::inTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit ) { byte rcode; byte pktsize; byte maxpktsize = devtable[ addr ].epinfo[ ep ].MaxPktSize; unsigned int xfrlen = 0; regWr( rHCTL, devtable[ addr ].epinfo[ ep ].rcvToggle ); //set toggle value while( 1 ) { // use a 'return' to exit this loop rcode = dispatchPkt( tokIN, ep, nak_limit ); //IN packet to EP-'endpoint'. Function takes care of NAKS. if( rcode ) { return( rcode ); //should be 0, indicating ACK. Else return error code. } /* check for RCVDAVIRQ and generate error if not present */ /* the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that */ if(( regRd( rHIRQ ) & bmRCVDAVIRQ ) == 0 ) { return ( 0xf0 ); //receive error } pktsize = regRd( rRCVBC ); //number of received bytes data = bytesRd( rRCVFIFO, pktsize, data ); regWr( rHIRQ, bmRCVDAVIRQ ); // Clear the IRQ & free the buffer xfrlen += 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 ) || (xfrlen >= nbytes )) { // have we transferred 'nbytes' bytes? if( regRd( rHRSL ) & bmRCVTOGRD ) { //save toggle value devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG1; } else { devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG0; } return( 0 ); } }//while( 1 ) }
uint8_t UsbHost_::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data) { uint8_t rcode = 0; uint8_t pktsize; uint16_t nbytes = *nbytesptr; uint8_t maxpktsize = pep->maxPktSize; *nbytesptr = 0; regWr( rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0 ); //set toggle value while( 1 ) // use a 'return' to exit this loop { rcode = dispatchPkt( tokIN, pep->epAddr, nak_limit ); //IN packet to EP-'endpoint'. Function takes care of NAKS. if( rcode ) { #if 0 if ((rcode != 0x04) && (rcode != 0x0d)) { USBTRACE2("\ndispatchPkt error: ", rcode); } #endif return( rcode ); //should be 0, indicating ACK. Else return error code. } /* check for RCVDAVIRQ and generate error if not present */ /* the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that */ if(( regRd( rHIRQ ) & bmRCVDAVIRQ ) == 0 ) return ( 0xf0 ); //receive error pktsize = regRd( rRCVBC ); //number of received bytes assert(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? { // Save toggle value pep->bmRcvToggle = (( regRd( rHRSL ) & bmRCVTOGRD )) ? 1 : 0; return( 0 ); } // if } //while( 1 ) }
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); uint8_t maxpktsize = pep->maxPktSize; *nbytesptr = 0; regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value // use a 'break' to exit this loop while(1) { rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //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 continue; } if(rcode) { //printf(">>>>>>>> Problem! dispatchPkt %2.2x\r\n", 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? { // Save toggle value pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0; //printf("\r\n"); rcode = 0; break; } // if } //while( 1 ) return ( rcode); }