예제 #1
0
/**
  * @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;
}
예제 #2
0
/**
  * @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;
}
예제 #3
0
/**
  * @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;
}
예제 #4
0
/**
  * @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;
}
예제 #5
0
/**
  * @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);   
}
예제 #6
0
/**
  * @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;
}
예제 #7
0
/**
  * @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;
  
}
예제 #8
0
/**
  * @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;
}
예제 #9
0
/**
  * @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;
}
예제 #10
0
/**
  * @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;
}
예제 #11
0
/* 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);
}
예제 #12
0
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...
예제 #13
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);
}