Example #1
0
/* Assumed peripheral address is already set */
byte USB::ctrlStatus( byte ep, boolean direction, unsigned int nak_limit )
{
    byte rcode;
    if( direction ) { //GET
        rcode = dispatchPkt( tokOUTHS, ep, nak_limit );
    }
    else {
        rcode = dispatchPkt( tokINHS, ep, nak_limit );
    }
    return( rcode );
}
Example #2
0
/* 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 )
}
Example #4
0
/* 01-0f    =   non-zero HRSLT  */
byte USB::ctrlReq( byte addr, byte ep, byte bmReqType, byte bRequest, byte wValLo, byte wValHi, unsigned int wInd, unsigned int nbytes, char* dataptr, unsigned int nak_limit )
{
    boolean direction = false;     //request direction, IN or OUT
    byte rcode;
    SETUP_PKT setup_pkt;

    regWr( rPERADDR, addr );                    //set peripheral address
    if( bmReqType & 0x80 ) {
        direction = true;                       //determine request direction
    }
    /* fill in setup packet */
    setup_pkt.ReqType_u.bmRequestType = bmReqType;
    setup_pkt.bRequest = bRequest;
    setup_pkt.wVal_u.wValueLo = wValLo;
    setup_pkt.wVal_u.wValueHi = wValHi;
    setup_pkt.wIndex = wInd;
    setup_pkt.wLength = nbytes;
    bytesWr( rSUDFIFO, 8, ( char *)&setup_pkt );    //transfer to setup packet FIFO
    rcode = dispatchPkt( tokSETUP, ep, nak_limit );            //dispatch packet
    //Serial.println("Setup packet");   //DEBUG
    if( rcode ) {                                   //return HRSLT if not zero
        Serial.print("Setup packet error: ");
        Serial.print( rcode, HEX );
        return( rcode );
    }
    //Serial.println( direction, HEX );
    if( dataptr != NULL ) {                         //data stage, if present
        rcode = ctrlData( addr, ep, nbytes, dataptr, direction );
    }
    if( rcode ) {   //return error
        Serial.print("Data packet error: ");
        Serial.print( rcode, HEX );
        return( rcode );
    }
    rcode = ctrlStatus( ep, direction );                //status stage
    return( rcode );
}
Example #5
0
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);
}
Example #6
0
/* 01-0f    =   non-zero HRSLT  */
uint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,
        uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p) {
        bool direction = false; //request direction, IN or OUT
        uint8_t rcode;
        SETUP_PKT setup_pkt;

        EpInfo *pep = NULL;
        uint16_t nak_limit = 0;

        rcode = SetAddress(addr, ep, &pep, nak_limit);

        if(rcode)
                return rcode;

        direction = ((bmReqType & 0x80) > 0);

        /* fill in setup packet */
        setup_pkt.ReqType_u.bmRequestType = bmReqType;
        setup_pkt.bRequest = bRequest;
        setup_pkt.wVal_u.wValueLo = wValLo;
        setup_pkt.wVal_u.wValueHi = wValHi;
        setup_pkt.wIndex = wInd;
        setup_pkt.wLength = total;

        bytesWr(rSUDFIFO, 8, (uint8_t*) & setup_pkt); //transfer to setup packet FIFO

        rcode = dispatchPkt(tokSETUP, ep, nak_limit); //dispatch packet

        if(rcode) //return HRSLT if not zero
                return ( rcode);

        if(dataptr != NULL) //data stage, if present
        {
                if(direction) //IN transfer
                {
                        uint16_t left = total;

                        pep->bmRcvToggle = 1; //bmRCVTOG1;

                        while(left) {
                                // Bytes read into buffer
                                uint16_t read = nbytes;
                                //uint16_t read = (left<nbytes) ? left : nbytes;

                                rcode = InTransfer(pep, nak_limit, &read, dataptr);
                                if(rcode == hrTOGERR) {
                                        // yes, we flip it wrong here so that next time it is actually correct!
                                        pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
                                        continue;
                                }

                                if(rcode)
                                        return rcode;

                                // Invoke callback function if inTransfer completed successfully and callback function pointer is specified
                                if(!rcode && p)
                                        ((USBReadParser*)p)->Parse(read, dataptr, total - left);

                                left -= read;

                                if(read < nbytes)
                                        break;
                        }
                } else //OUT transfer
                {
                        pep->bmSndToggle = 1; //bmSNDTOG1;
                        rcode = OutTransfer(pep, nak_limit, nbytes, dataptr);
                }
                if(rcode) //return error
                        return ( rcode);
        }
        // Status stage
        return dispatchPkt((direction) ? tokOUTHS : tokINHS, ep, nak_limit); //GET if direction
}
Example #7
0
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);
}
Example #8
0
/* 01-0f    =   non-zero HRSLT  */
uint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,
        uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p) {
        bool direction = false; //request direction, IN or OUT
        uint8_t rcode;
        SETUP_PKT setup_pkt;
        USB_OTG_CORE_HANDLE *pdev = coreConfig;
        URB_STATE URB_Status = URB_IDLE;

        EpInfo *pep = NULL;
        uint16_t nak_limit = 0;
/* the address are set by HC functions as 0*/
        rcode = SetAddress(addr, ep, &pep, nak_limit);

        if (rcode)
			return rcode;

        direction = ((bmReqType & 0x80) > 0);

        /* fill in setup packet */
        setup_pkt.ReqType_u.bmRequestType = bmReqType;
        setup_pkt.bRequest = bRequest;
        setup_pkt.wVal_u.wValueLo = wValLo;
        setup_pkt.wVal_u.wValueHi = wValHi;
        setup_pkt.wIndex = wInd;
        setup_pkt.wLength = total;

//        bytesWr(rSUDFIFO, 8, (uint8_t*) & setup_pkt); //transfer to setup packet FIFO
        // *pep points to EP0 (HC0-out, HC1-in)
        if(addr != 0) {	// in case hid->setAddr() called, we should reset or reuse hid's addr. suck..
        	if(pdev->host.hc[pep->hcNumOut].dev_addr != addr)
				pdev->host.hc[pep->hcNumOut].dev_addr = addr;
				//USBH_Modify_Channel (pdev, pep->hcNumOut, addr, 0, 0, 0, 0);
			if(pdev->host.hc[pep->hcNumIn].dev_addr != addr)
				pdev->host.hc[pep->hcNumIn].dev_addr = addr;
				//USBH_Modify_Channel (pdev, pep->hcNumIn, addr, 0, 0, 0, 0);
        }


        rcode = dispatchPkt(tokSETUP, ep, nak_limit, (uint8_t *)&setup_pkt, sizeof(setup_pkt), pep->hcNumOut); //dispatch packet

        if (rcode) //return HRSLT if not zero
			return ( rcode);

        if (dataptr != NULL) //data stage, if present
        {
			if (direction) //IN transfer
			{
				uint16_t left = total;
#if 1
				//pep->bmRcvToggle = 1; //bmRCVTOG1;
				pdev->host.hc[pep->hcNumIn].toggle_in = 0x1;
				pep->bmRcvToggle = pdev->host.hc[pep->hcNumIn].toggle_in;

				uint16_t read = total;	//nbytes;
				rcode = InTransfer(pep, nak_limit, &read, dataptr);

				// Invoke callback function if inTransfer completed successfully and callback function pointer is specified
				if (!rcode && p)
					((USBReadParser*)p)->Parse(read, dataptr, total - left);

#else
				while (left) {
					// Bytes read into buffer
					uint16_t read = nbytes;
					//uint16_t read = (left<nbytes) ? left : nbytes;

					pdev->host.hc[pep->hcNumIn].toggle_in = 0x1;
					rcode = InTransfer(pep, nak_limit, &read, dataptr);

/*
					if (rcode == hrTOGERR) {
							// yes, we flip it wrong here so that next time it is actually correct!
							pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
							continue;
					}
*/
					if (rcode)
						return rcode;

					// Invoke callback function if inTransfer completed successfully and callback function pointer is specified
					if (!rcode && p)
						((USBReadParser*)p)->Parse(read, dataptr, total - left);

					left -= read;

					if (read < nbytes)
						break;
				}
#endif
                } else //OUT transfer
                {
					//pep->bmSndToggle = 1; //bmSNDTOG1;
					pdev->host.hc[pep->hcNumOut].toggle_out = 0x1;
					pep->bmSndToggle = pdev->host.hc[pep->hcNumOut].toggle_out;
					rcode = OutTransfer(pep, nak_limit, nbytes, dataptr);
			}
			if (rcode) //return error
				return ( rcode);
        }
        // Status stage
        return dispatchPkt((direction) ? tokOUTHS : tokINHS, ep, nak_limit, NULL, 0, (direction) ? pep->hcNumOut : pep->hcNumIn);	//GET if direction
}