//--------------------------------------------------------------
USBH_Status USBH_Get_CfgDesc(USB_OTG_CORE_HANDLE *pdev, 
                             USBH_HOST           *phost,                      
                             uint16_t length)

{
  USBH_Status status;
  uint16_t index = 0;
  
  if((status = USBH_GetDescriptor(pdev,
                                  phost,
                                  USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD,                          
                                  USB_DESC_CONFIGURATION, 
                                  pdev->host.Rx_Buffer,
                                  length)) == USBH_OK)
  {
    /*save Cfg descriptor for class parsing usage */
    for( ; index < length ; index ++)
    {
      USBH_CfgDesc[index] = pdev->host.Rx_Buffer[index];
    }
    
    /* Commands successfully sent and Response Received  */       
    USBH_ParseCfgDesc (&phost->device_prop.Cfg_Desc,
                       phost->device_prop.Itf_Desc,
                       phost->device_prop.Ep_Desc, 
                       pdev->host.Rx_Buffer,
                       length); 
    
  }
  return status;
}
예제 #2
0
/**
  * @brief  USBH_Get_CfgDesc
  *         Issues Configuration Descriptor to the device. Once the response 
  *         received, it parses the configuartion descriptor and updates the 
  *         status.
  * @param  phost: Host Handle
  * @param  length: Length of the descriptor
  * @retval USBH Status
  */
USBH_StatusTypeDef USBH_Get_CfgDesc(USBH_HandleTypeDef *phost,                      
                             uint16_t length)

{
  USBH_StatusTypeDef status;
  uint8_t *pData;
#if (USBH_KEEP_CFG_DESCRIPTOR == 1)  
  pData = phost->device.CfgDesc_Raw;
#else
  pData = phost->device.Data;
#endif  
  if((status = USBH_GetDescriptor(phost,
                                  USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD,                          
                                  USB_DESC_CONFIGURATION, 
                                  pData,
                                  length)) == USBH_OK)
  {
    
    /* Commands successfully sent and Response Received  */       
    USBH_ParseCfgDesc (&phost->device.CfgDesc,
                       pData,
                       length); 
    
  }
  return status;
}
예제 #3
0
/**
 * @brief  USBH_Get_CfgDesc
 *         Issues Configuration Descriptor to the device. Once the response
 *         received, it parses the configuration descriptor and updates the
 *         status.
 * @param  pdev: Selected device
 * @param  cfg_desc: Configuration Descriptor address
 * @param  itf_desc: Interface Descriptor address
 * @param  ep_desc: Endpoint Descriptor address
 * @param  length: Length of the descriptor
 * @retval Status
 */
USBH_Status USBH_Get_CfgDesc(USB_OTG_CORE_HANDLE *pdev,
                             USBH_HOST           *phost,
                             uint16_t length)

{
    USBH_Status status, result;

    if((status = USBH_GetDescriptor(pdev,
                                    phost,
                                    USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD,
                                    USB_DESC_CONFIGURATION,
                                    Cfg_Rx_Buffer,
                                    length)) == USBH_OK)
    {
        /* Commands successfully sent and Response Received  */
        result = USBH_ParseCfgDesc (&phost->device_prop.Cfg_Desc,
                                    phost->device_prop.Itf_Desc,
                                    phost->device_prop.Ep_Desc,
                                    Cfg_Rx_Buffer,
                                    length);
        if (result != USBH_OK)  status= result;


    }
    return status;
}
예제 #4
0
uint8_t USBPTD_SetupStage(USB_OTG_CORE_HANDLE* pcore, USB_SETUP_REQ* req)
{
	// store for later use from another function
	memcpy(USBPT_LastSetupPacket, pcore->dev.setup_packet, 24);

	// print for monitoring
	USBPT_printf("\b\r\n USBPT:SETUP:");
	for (uint8_t i = 0; i < 8; i++) {
		USBPT_printf(" 0x%02X", USBPT_LastSetupPacket[i]);
	}
	USBPT_printf("\r\n");

	// prepare to be sent to the device
	memcpy(USBPT_Dev->Control.setup.d8, USBPT_LastSetupPacket, 8);

	// set address must be handled explicitly
	if ((req->bmRequest & 0x7F) == (USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD) && req->bRequest == USB_REQ_SET_ADDRESS)
	{
		// let the internal code handle it for the device interface
		USBD_StdDevReq(pcore, req);

		// pass it to the downstream device
		USBH_CtlReq_Blocking(&USB_OTG_Core_host, USBPT_Dev, 0, 0, 100);
		USBD_CtlSendStatus(pcore);

		// modifiy our host channel to match
		USBPT_Dev->device_prop.address = (uint8_t)(req->wValue) & 0x7F;
		USBH_Modify_Channel (&USB_OTG_Core_host,
							USBPT_Dev->Control.hc_num_in,
							USBPT_Dev->device_prop.address,
							0,
							0,
							0);
		USBH_Modify_Channel (&USB_OTG_Core_host,
							USBPT_Dev->Control.hc_num_out,
							USBPT_Dev->device_prop.address,
							0,
							0,
							0);

		// modify all other channels to match
		for (uint8_t i = 0; i < USBPTH_MAX_LISTENERS; i++)
		{
			USBPTH_HC_EP_t* pl = &USBPTH_Listeners[i];
			uint8_t hc = pl->hc;
			if (hc != 0 && hc != HC_ERROR) // if listener is actually allocated
			{
				USBH_EpDesc_TypeDef* epDesc = pl->epDesc;
				uint8_t epType = 0;
				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;
				}
				else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_CTRL) {
					epType = EP_TYPE_CTRL;
				}

				USBH_Modify_Channel(	&USB_OTG_Core_host,
										USBPTH_Listeners[i].hc,
										USBPT_Dev->device_prop.address,
										USBPT_Dev->device_prop.speed,
										epType,
										USBPTH_Listeners[i].epDesc->wMaxPacketSize);
			}
		}
		// note: out direction channels are dynamically allocated only when needed
		// so we don't need to modify those channel addresses

		return USBD_OK;
	}

	// no data means we can just directly relay the data
	if (req->wLength == 0) {
		USBH_CtlReq_Blocking(&USB_OTG_Core_host, USBPT_Dev, 0, 0, 100);
		USBD_CtlSendStatus(pcore);
		return USBD_OK;
	}

	// there is extra data later
	USBPT_CtrlDataLen = req->wLength;
	if (USBPT_CtrlData != 0) free(USBPT_CtrlData);
	USBPT_CtrlData = malloc(USBPT_CtrlDataLen);

	USBH_Status status;

	// wait until previous req is finished
	delay_1ms_cnt = 100;
	while (delay_1ms_cnt > 0 &&
			USBPT_Dev->Control.state != CTRL_COMPLETE &&
			USBPT_Dev->Control.state != CTRL_IDLE &&
			USBPT_Dev->Control.state != CTRL_ERROR &&
			USBPT_Dev->Control.state != CTRL_STALLED);
	{
		status = USBH_HandleControl(&USB_OTG_Core_host, USBPT_Dev);
	}

	// finalize previous ctrl req
	if (USBPT_Dev->RequestState == CMD_WAIT) {
		USBH_CtlReq(&USB_OTG_Core_host, USBPT_Dev, 0 , 0 );
	}

	// prepare new setup
	USBH_SubmitSetupRequest(USBPT_Dev, USBPT_CtrlData, USBPT_CtrlDataLen);
	USBPT_Dev->RequestState = CMD_WAIT;
	USBH_CtlSendSetup (&USB_OTG_Core_host, USBPT_Dev->Control.setup.d8, USBPT_Dev->Control.hc_num_out);
	USBPT_Dev->Control.state = CTRL_SETUP_WAIT;
	USBPT_Dev->Control.timer = HCD_GetCurrentFrame(pcore);
	USBPT_Dev->Control.timeout = 50;

	if ((req->bmRequest & 0x80) == 0)
	{ // H2D
		// we need to obtain the data from EP0_RxReady first
		USBD_CtlPrepareRx (pcore, USBPT_CtrlData, USBPT_CtrlDataLen);
		return USBD_OK;
	}
	else
	{ // D2H

		// wait for request to finish
		delay_1ms_cnt = 100;
		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)
		{
			// timeout
			dbg_printf(DBGMODE_ERR, "USBPT Setup Timed Out \r\n");
			USBD_CtlSendStatus(pcore); // we reply with nothing to simulate a timeout
			return USBH_OK;
		}
		else if (status == USBH_OK)
		{
			// all good, send back the data
			USBD_CtlSendData (pcore, USBPT_CtrlData, USBPT_CtrlDataLen);

			// handle config descriptors specially, we need to know what channels to open based on endpoints
			if ((req->bmRequest & 0x7F) == (USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD) &&
					req->bRequest == USB_REQ_GET_DESCRIPTOR &&
					req->wValue == USB_DESC_CONFIGURATION &&
					req->wLength > USB_CONFIGURATION_DESC_SIZE)
			{
				// this is a full length configuration descriptor
				// we need this info to open as many D2H endpoints to channels
				USBH_ParseCfgDesc(&USBPT_Dev->device_prop.Cfg_Desc,
									USBPT_Dev->device_prop.Itf_Desc,
									USBPT_Dev->device_prop.Ep_Desc,
									USBPT_CtrlData,
									USBPT_CtrlDataLen);

				USBPTH_OutEPCnt = 0;
				USBPT_GeneralInDataLen = 0;
				for (uint8_t i = 0; i < USBPT_Dev->device_prop.Cfg_Desc.bNumInterfaces && i < USBH_MAX_NUM_INTERFACES; i++)
				{
					for (uint8_t j = 0; j < USBPT_Dev->device_prop.Itf_Desc[i].bNumEndpoints && j < USBH_MAX_NUM_ENDPOINTS; j++)
					{
						USBH_EpDesc_TypeDef* epDesc = &USBPT_Dev->device_prop.Ep_Desc[i][j];
						for (uint8_t k = 0; k < USBPTH_MAX_LISTENERS; k++)
						{
							if ((epDesc->bEndpointAddress & USB_EP_DIR_MSK) == USB_D2H && USBPTH_Listeners[k].used == 0)
							{
								USBPTH_Listeners[k].epDesc = epDesc;
								uint8_t epType = 0;
								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;
								}
								else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_CTRL) {
									epType = EP_TYPE_CTRL;
								}

								USBH_Open_Channel(	&USB_OTG_Core_host,
													&(USBPTH_Listeners[k].hc),
													epDesc->bEndpointAddress,
													USBPT_Dev->device_prop.address,
													USBPT_Dev->device_prop.speed,
													epType,
													USBPTH_Listeners[k].epDesc->wMaxPacketSize);

								if (USBPTH_Listeners[k].hc >= 0)
								{
									USBPTH_Listeners[k].used = 1;
									DCD_EP_Open(&USB_OTG_Core_dev, epDesc->bEndpointAddress, epDesc->wMaxPacketSize, epType);

									if (epDesc->wMaxPacketSize > USBPT_GeneralInDataMax) {
										USBPT_GeneralInDataMax = epDesc->wMaxPacketSize;
									}
								}
							}
						}

						if ((epDesc->bEndpointAddress & 0x80) == USB_H2D)
						{
							USBPTH_OutEPCnt++;
						}
					}
				}

				if (USBPT_GeneralInData != 0) free(USBPT_GeneralInData); // release memory if previously allocated
				USBPT_GeneralInData = malloc(USBPT_GeneralInDataMax); // only allocate the memory we need

				if (USBPTH_OutEP != 0) free(USBPTH_OutEP); // release memory if previously allocated
				USBPTH_OutEP = malloc(sizeof(USBH_EpDesc_TypeDef*) * USBPTH_OutEPCnt); // only allocate the memory we need

				uint8_t ec = 0;
				for (uint8_t i = 0; i < USBPT_Dev->device_prop.Cfg_Desc.bNumInterfaces && i < USBH_MAX_NUM_INTERFACES; i++)
				{
					for (uint8_t j = 0; j < USBPT_Dev->device_prop.Itf_Desc[i].bNumEndpoints && j < USBH_MAX_NUM_ENDPOINTS; j++)
					{
						USBH_EpDesc_TypeDef* epDesc = &USBPT_Dev->device_prop.Ep_Desc[i][j];
						if ((epDesc->bEndpointAddress & 0x80) == USB_H2D) {
							// only save the H2D direction endpoints
							USBPTH_OutEP[ec] = epDesc;
							ec++;
						}
					}
				}
			}
			return USBH_OK;
		}
		else
		{
			if (status == USBH_STALL || status == USBH_NOT_SUPPORTED) {
				dbg_printf(DBGMODE_ERR, "USBPT Setup Stalled \r\n");
				USBD_CtlError(pcore , req);
				return USBH_OK;
			}
		}

		return USBD_OK;
	}

	dbg_printf(DBGMODE_ERR, "USBPT Setup Unhandled Error \r\n");
	USBD_CtlError(pcore , req);

	return USBD_OK;
}