Exemplo n.º 1
0
/**
* @brief  USBH_HID_Handle 
*         The function is for managing state machine for HID data transfers 
* @param  pdev: Selected device
* @param  hdev: Selected device property
* @retval USBH_Status
*/
static USBH_Status USBH_HID_Handle(USB_OTG_CORE_HANDLE *pdev , 
                                   void   *phost)
{
  USBH_HOST *pphost = phost;
  USBH_Status status = USBH_OK;
  
  switch (HID_Machine.state)
  {
    
  case HID_IDLE:
    HID_Machine.cb->Init();
    HID_Machine.state = HID_SYNC;
    
  case HID_SYNC:

    /* Sync with start of Even Frame */
    if(USB_OTG_IsEvenFrame(pdev) == TRUE)
    {
      HID_Machine.state = HID_GET_DATA;  
    }
    break;
    
  case HID_GET_DATA:

    USBH_InterruptReceiveData(pdev, 
                              HID_Machine.buff,
                              HID_Machine.length,
                              HID_Machine.hc_num_in);
    start_toggle = 1;
    
    HID_Machine.state = HID_POLL;
    HID_Machine.timer = HCD_GetCurrentFrame(pdev);
    break;
    
  case HID_POLL:
    if(( HCD_GetCurrentFrame(pdev) - HID_Machine.timer) >= HID_Machine.poll)
    {
      HID_Machine.state = HID_GET_DATA;
    }
    else if(HCD_GetURB_State(pdev , HID_Machine.hc_num_in) == URB_DONE)
    {
      if(start_toggle == 1) /* handle data once */
      {
        start_toggle = 0;
        HID_Machine.cb->Decode(HID_Machine.buff);
      }
    }
    else if(HCD_GetURB_State(pdev, HID_Machine.hc_num_in) == URB_STALL) /* IN Endpoint Stalled */
    {
      
      /* Issue Clear Feature on interrupt IN endpoint */ 
      if( (USBH_ClrFeature(pdev, 
                           pphost,
                           HID_Machine.ep_addr,
                           HID_Machine.hc_num_in)) == USBH_OK)
      {
        /* Change state to issue next IN token */
        HID_Machine.state = HID_GET_DATA;
        
      }
      
    }      
    break;
    
  default:
    break;
  }
  return status;
}
Exemplo n.º 2
0
/**
* @brief  USBH_HID_Handle 
*         The function is for managing state machine for HID data transfers 
* @param  pdev: Selected device
* @param  hdev: Selected device property
* @retval USBH_Status
*/
static USBH_Status USBH_HID_Handle(USB_OTG_CORE_HANDLE *pdev , 
                                   void   *phost)
{
  USBH_HOST *pphost = phost;
  HID_Machine_TypeDef *HID_Machine = &HID_Machines[pdev->cfg.coreID];
  USBH_Status status = USBH_OK;
  
  switch (HID_Machine->state)
  {
    
  case HID_IDLE:
    HID_Machine->cb->Init(pdev->cfg.coreID,pphost->device_prop.Dev_Desc.idVendor,pphost->device_prop.Dev_Desc.idProduct);
    HID_Machine->state = HID_SYNC;
    
  case HID_SYNC:

    /* Sync with start of Even Frame */
    if(USB_OTG_IsEvenFrame(pdev) == TRUE)
    {
      HID_Machine->state = HID_GET_DATA;  
    }
    break;
    
  case HID_GET_DATA:

    USBH_InterruptReceiveData(pdev, 
                              HID_Machine->buff,
                              HID_Machine->length,
                              HID_Machine->hc_num_in);
    start_toggles[pdev->cfg.coreID] = 1;
    
    HID_Machine->state = HID_POLL;
    HID_Machine->timer = HCD_GetCurrentFrame(pdev);
    break;
    
  case HID_POLL:
    if(( HCD_GetCurrentFrame(pdev) - HID_Machine->timer) >= HID_Machine->poll)
    {
      HID_Machine->state = HID_GET_DATA;
    }
    else if(HCD_GetURB_State(pdev , HID_Machine->hc_num_in) == URB_DONE)
    {
      if(start_toggles[pdev->cfg.coreID] == 1) /* handle data once */
      {
        start_toggles[pdev->cfg.coreID] = 0;
        HID_Machine->cb->Decode(pdev->cfg.coreID,HID_Machine->buff);
      }
    }
    else if(HCD_GetURB_State(pdev, HID_Machine->hc_num_in) == URB_STALL) /* IN Endpoint Stalled */
    {
      
      /* Issue Clear Feature on interrupt IN endpoint */ 
      if( (USBH_ClrFeature(pdev, 
                           pphost,
                           HID_Machine->ep_addr,
                           HID_Machine->hc_num_in)) == USBH_OK)
      {
        /* Change state to issue next IN token */
        HID_Machine->state = HID_GET_DATA;
        
      }
      
    }      
    break;
    
  default:
    break;
  }
  return status;
}
Exemplo n.º 3
0
void USBPT_Work()
{
	if (USBPT_Has_Dev == 0)
	{
		if (HCD_IsDeviceConnected(&USB_OTG_Core_host) != 0)
		{
			USBPT_printf("USBPT Device Connecting \r\n");

			if (USBH_Open_Channel(	&USB_OTG_Core_host,
					&(USBPT_Dev->Control.hc_num_in),
					0x80,
					USBPT_Dev->device_prop.address, // still 0 at this point
					USBPT_Dev->device_prop.speed,
					EP_TYPE_CTRL,
					USBPT_Dev->Control.ep0size) == HC_OK
				&&
				USBH_Open_Channel(	&USB_OTG_Core_host,
					&(USBPT_Dev->Control.hc_num_out),
					0x00,
					USBPT_Dev->device_prop.address, // still 0 at this point
					USBPT_Dev->device_prop.speed,
					EP_TYPE_CTRL,
					USBPT_Dev->Control.ep0size) == HC_OK
			) {
				DCD_DevConnect(&USB_OTG_Core_dev);
				USBPT_Has_Dev = 1;
			}
			else
			{
				dbg_printf(DBGMODE_ERR, "USBPT Unable to allocate control EP HC \r\n");
			}
		}
		else
		{
			return;
		}
	}
	else
	{
		if (HCD_IsDeviceConnected(&USB_OTG_Core_host) == 0)
		{
			USBPT_printf("USBPT Device Disconnecting \r\n");
			USBD_DeInit(&USB_OTG_Core_dev);
			DCD_DevDisconnect(&USB_OTG_Core_dev);
			USBPT_Has_Dev = 0;

			for (uint8_t i = 0; i < USBPTH_MAX_LISTENERS; i++)
			{
				USBH_Free_Channel(&USB_OTG_Core_host, &(USBPTH_Listeners[i].hc));
			}

			USBH_Free_Channel(&USB_OTG_Core_host, &(USBPT_Dev->Control.hc_num_out));
			USBH_Free_Channel(&USB_OTG_Core_host, &(USBPT_Dev->Control.hc_num_in));
		}
	}

	for (uint8_t i = 0; i < USBPTH_MAX_LISTENERS; i++)
	{
		USBPTH_HC_EP_t* pl = &USBPTH_Listeners[i];
		int8_t hc = USBPTH_Listeners[i].hc;
		if (hc >= 0) // if listener is actually allocated
		{
			USBH_EpDesc_TypeDef* epDesc = pl->epDesc;
			uint8_t epnum = epDesc->bEndpointAddress;
			uint8_t epType = 0;
			USBPT_GeneralInDataLen = epDesc->wMaxPacketSize;

			// try to send read tokens only on even frames
			if (USB_OTG_IsEvenFrame(&USB_OTG_Core_host) == 0) continue;

			dbg_trace();

			// attempt to start the read, check the read type first
			if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_INTR) {
				epType = EP_TYPE_INTR;
				USBH_InterruptReceiveData(&USB_OTG_Core_host, USBPT_GeneralInData, USBPT_GeneralInDataLen, hc);
			}
			else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_BULK) {
				epType = EP_TYPE_BULK;
				USBH_BulkReceiveData(&USB_OTG_Core_host, USBPT_GeneralInData, USBPT_GeneralInDataLen, hc);
			}
			else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_ISOC) {
				epType = EP_TYPE_ISOC;
				USBH_IsocReceiveData(&USB_OTG_Core_host, USBPT_GeneralInData, USBPT_GeneralInDataLen, hc);
			}

			// now we wait for a reply, or maybe there isn't one
			USBH_Status status;
			char sent = 0;
			delay_1ms_cnt = 100;
			do
			{
				URB_STATE us = HCD_GetURB_State(&USB_OTG_Core_host, hc);
				if (us == URB_DONE)
				{
					// data was indeed received

					// print it to the serial port for monitoring
					USBPT_printf("USBPT:IN:EP0x%02X:", epnum);
					for (uint16_t c = 0; c < USBPT_GeneralInDataLen; c++) {
						USBPT_printf(" 0x%02X", USBPT_GeneralInData[c]);
					}
					USBPT_printf("\r\n");

					// relay the data to the host
					DCD_EP_Tx(&USB_OTG_Core_dev, epnum, USBPT_GeneralInData, USBPT_GeneralInDataLen);
					sent = 1;
					break;
				}
				else if (us == URB_ERROR) {
					dbg_printf(DBGMODE_ERR, "DataIn Error on EP 0x%02X \r\n", epnum);
					break;
				}
				else if (us == URB_STALL) {
					dbg_printf(DBGMODE_ERR, "DataIn Stalled EP 0x%02X \r\n", epnum);
					break;
				}
				else if (us == URB_NOTREADY) {
					// NAK, no data
					break;
				}
			}
			while (delay_1ms_cnt > 0);

			if (delay_1ms_cnt == 0) {
				dbg_printf(DBGMODE_ERR, "DataIn Read Timed Out EP 0x%02X \r\n", epnum);
			}
		}
	}
}
//--------------------------------------------------------------
USB_OTG_STS USB_OTG_HC_StartXfer(USB_OTG_CORE_HANDLE *pdev , uint8_t hc_num)
{
  USB_OTG_STS status = USB_OTG_OK;
  USB_OTG_HCCHAR_TypeDef   hcchar;
  USB_OTG_HCTSIZn_TypeDef  hctsiz;
  USB_OTG_HNPTXSTS_TypeDef hnptxsts; 
  USB_OTG_HPTXSTS_TypeDef  hptxsts; 
  USB_OTG_GINTMSK_TypeDef  intmsk;
  uint16_t                 len_words = 0;   
  
  uint16_t num_packets;
  uint16_t max_hc_pkt_count;
  
  max_hc_pkt_count = 256;
  hctsiz.d32 = 0;
  hcchar.d32 = 0;
  intmsk.d32 = 0;
  
  /* Compute the expected number of packets associated to the transfer */
  if (pdev->host.hc[hc_num].xfer_len > 0)
  {
    num_packets = (pdev->host.hc[hc_num].xfer_len + \
      pdev->host.hc[hc_num].max_packet - 1) / pdev->host.hc[hc_num].max_packet;
    
    if (num_packets > max_hc_pkt_count)
    {
      num_packets = max_hc_pkt_count;
      pdev->host.hc[hc_num].xfer_len = num_packets * \
        pdev->host.hc[hc_num].max_packet;
    }
  }
  else
  {
    num_packets = 1;
  }
  if (pdev->host.hc[hc_num].ep_is_in)
  {
    pdev->host.hc[hc_num].xfer_len = num_packets * \
      pdev->host.hc[hc_num].max_packet;
  }
  /* Initialize the HCTSIZn register */
  hctsiz.b.xfersize = pdev->host.hc[hc_num].xfer_len;
  hctsiz.b.pktcnt = num_packets;
  hctsiz.b.pid = pdev->host.hc[hc_num].data_pid;
  USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCTSIZ, hctsiz.d32);
  
  if (pdev->cfg.dma_enable == 1)
  {
    USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCDMA, (unsigned int)pdev->host.hc[hc_num].xfer_buff);
  }
  
  
  hcchar.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[hc_num]->HCCHAR);
  hcchar.b.oddfrm = USB_OTG_IsEvenFrame(pdev);
  
  /* Set host channel enable */
  hcchar.b.chen = 1;
  hcchar.b.chdis = 0;
  USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCCHAR, hcchar.d32);
  
  if (pdev->cfg.dma_enable == 0) /* Slave mode */
  {  
    if((pdev->host.hc[hc_num].ep_is_in == 0) && 
       (pdev->host.hc[hc_num].xfer_len > 0))
    {
      switch(pdev->host.hc[hc_num].ep_type) 
      {
        /* Non periodic transfer */
      case EP_TYPE_CTRL:
      case EP_TYPE_BULK:
        
        hnptxsts.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->HNPTXSTS);
        len_words = (pdev->host.hc[hc_num].xfer_len + 3) / 4;
        
        /* check if there is enough space in FIFO space */
        if(len_words > hnptxsts.b.nptxfspcavail)
        {
          /* need to process data in nptxfempty interrupt */
          intmsk.b.nptxfempty = 1;
          USB_OTG_MODIFY_REG32( &pdev->regs.GREGS->GINTMSK, 0, intmsk.d32);  
        }
        
        break;
        /* Periodic transfer */
      case EP_TYPE_INTR:
      case EP_TYPE_ISOC:
        hptxsts.d32 = USB_OTG_READ_REG32(&pdev->regs.HREGS->HPTXSTS);
        len_words = (pdev->host.hc[hc_num].xfer_len + 3) / 4;
        /* check if there is enough space in FIFO space */
        if(len_words > hptxsts.b.ptxfspcavail) /* split the transfer */
        {
          /* need to process data in ptxfempty interrupt */
          intmsk.b.ptxfempty = 1;
          USB_OTG_MODIFY_REG32( &pdev->regs.GREGS->GINTMSK, 0, intmsk.d32);  
        }
        break;
        
      default:
        break;
      }
      
      /* Write packet into the Tx FIFO. */
      USB_OTG_WritePacket(pdev, 
                          pdev->host.hc[hc_num].xfer_buff , 
                          hc_num, pdev->host.hc[hc_num].xfer_len);
    }
  }
  return status;
}
Exemplo n.º 5
0
uint8_t USBPTD_DataOut           (void *pcore , uint8_t epnum)
{
	USB_OTG_CORE_HANDLE* pcore_ = (USB_OTG_CORE_HANDLE*)pcore;
	DCD_DEV* pdev = &(pcore_->dev);
	uint8_t* data;
	uint16_t wLength;

	if (epnum == 0x00)
	{ // CTRL REQ
		wLength = USBPT_CtrlDataLen;
		data = USBPT_CtrlData;
	}
	else
	{
		wLength = pdev->out_ep[epnum].xfer_count;
		data = pdev->out_ep[epnum].xfer_buff;
	}

	// print to monitor
	USBPT_printf("USBPT:OUT:EP0x%02X:", epnum);
	for (uint16_t i = 0; i < wLength; i++) {
		USBPT_printf(" 0x%02X", data[i]);
	}
	USBPT_printf("\r\n");

	if (epnum == 0x00)
	{ // CTRL REQ

		USBH_Status status;
		delay_1ms_cnt = 100;

		// wait for transfer complete
		do
		{
			status = USBH_CtlReq(&USB_OTG_Core_host, USBPT_Dev, USBPT_CtrlData , USBPT_CtrlDataLen );
			if (status == USBH_OK || status == USBH_FAIL || status == USBH_STALL || status == USBH_NOT_SUPPORTED) {
				break;
			}
			else
			{
				status = USBH_HandleControl(&USB_OTG_Core_host, USBPT_Dev);
				if (status == USBH_FAIL || status == USBH_STALL || status == USBH_NOT_SUPPORTED) {
					break;
				}
			}
		}
		while (delay_1ms_cnt > 0);

		if (delay_1ms_cnt == 0) {
			dbg_printf(DBGMODE_ERR, "USBPTD_DataOut timed out while sending to device, status: 0x%04X \r\n", status);
			USBD_CtlError(pcore , 0);
			return USBD_FAIL;
		}
		else if (status != USBH_OK) {
			dbg_printf(DBGMODE_ERR, "USBPTD_DataOut failed to send to device, status: 0x%04X \r\n", status);
			USBD_CtlError(pcore , 0);
			return USBD_FAIL;
		}
		else { // everything is OK
			USBD_CtlSendStatus(pcore);
			return USBD_OK;
		}
	}
	else
	{
		wLength = pdev->out_ep[epnum].xfer_count;
		data = pdev->out_ep[epnum].xfer_buff;

		// allocate memory needed
		if (USBPT_GeneralOutData != 0) free(USBPT_GeneralOutData);
		USBPT_GeneralOutDataLen = wLength;
		USBPT_GeneralOutData = malloc(wLength);
		memcpy(USBPT_GeneralOutData, data, USBPT_GeneralOutDataLen);

		USBH_EpDesc_TypeDef* epDesc = 0;
		for (uint8_t i = 0; i < USBPTH_OutEPCnt; i++)
		{
			// look for appropriate EP
			if (USBPTH_OutEP[i]->bEndpointAddress == epnum) {
				epDesc = USBPTH_OutEP[i];
				break;
			}
		}

		if (epDesc != 0) // EP found
		{
			uint8_t epType = 0;
			int8_t hc = -1;
			if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_INTR) {
				epType = EP_TYPE_INTR;
			}
			else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_BULK) {
				epType = EP_TYPE_BULK;
			}
			else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_ISOC) {
				epType = EP_TYPE_ISOC;
			}

			// dynamically allocate host channel for use
			if (USBH_Open_Channel(	&USB_OTG_Core_host,
									&hc,
									epnum,
									USBPT_Dev->device_prop.address,
									USBPT_Dev->device_prop.speed,
									epType,
									epDesc->wMaxPacketSize) == HC_OK)
			{

				// try to only send on even frame
				volatile uint32_t syncTries = 0x7FFFFFFF;
				while (USB_OTG_IsEvenFrame(&USB_OTG_Core_host) == 0 && syncTries--) __NOP();

				// send using appropriate method
				switch (epType)
				{
					case EP_TYPE_INTR:
						USBH_InterruptSendData(&USB_OTG_Core_host, USBPT_GeneralOutData, USBPT_GeneralOutDataLen, hc);
						break;
					case EP_TYPE_BULK:
						USBH_BulkSendData(&USB_OTG_Core_host, USBPT_GeneralOutData, USBPT_GeneralOutDataLen, hc);
						break;
					case EP_TYPE_ISOC:
						USBH_IsocSendData(&USB_OTG_Core_host, USBPT_GeneralOutData, USBPT_GeneralOutDataLen, hc);
						break;
					default:
						break;
				}

				// wait until done sending
				USBH_Status status;
				delay_1ms_cnt = 100;
				do
				{
					URB_STATE us = HCD_GetURB_State(&USB_OTG_Core_host, hc);
					if (us == URB_DONE) {
						break;
					}
					else if (us == URB_ERROR) {
						dbg_printf(DBGMODE_ERR, "USBPTD_DataOut Send Error on EP 0x%02X \r\n", epnum);
						DCD_EP_Stall(pcore, epnum);
						break;
					}
					else if (us == URB_STALL) {
						dbg_printf(DBGMODE_ERR, "USBPTD_DataOut Stalled EP 0x%02X \r\n", epnum);
						DCD_EP_Stall(pcore, epnum);
						break;
					}
				}
				while (delay_1ms_cnt > 0);

				if (delay_1ms_cnt == 0) {
					dbg_printf(DBGMODE_ERR, "USBPTD_DataOut Send Timed Out EP 0x%02X \r\n", epnum);
				}

				// free the channel to be used by something else later
				USBH_Free_Channel(&USB_OTG_Core_host, &hc);
			}
			else
			{
				dbg_printf(DBGMODE_ERR, "USBPTD_DataOut Failed to Alloc HC for EP 0x%02X \r\n", epnum);
			}

		}
		else
		{
			dbg_printf(DBGMODE_ERR, "USBPTD_DataOut No Such EP 0x%02X \r\n", epnum);
		}

		return USBD_OK;
	}

	return USBD_OK;
}