Exemplo n.º 1
0
/**
* @brief  USBH_HID_ClassRequest 
*         The function is responsible for handling HID Class requests
*         for HID class.
* @param  pdev: Selected device
* @param  hdev: Selected device property
* @retval  USBH_Status :Response for USB Set Protocol request
*/
static USBH_Status USBH_HID_ClassRequest(USB_OTG_CORE_HANDLE *pdev , 
                                         void *phost)
{   
    USBH_HOST *pphost = phost;
    
  USBH_Status status         = USBH_BUSY;
  USBH_Status classReqStatus = USBH_BUSY;
  
  
  /* Switch HID state machine */
  switch (HID_Machine.ctl_state)
  {
  case HID_IDLE:  
  case HID_REQ_GET_HID_DESC:
    
    /* Get HID Desc */ 
    if (USBH_Get_HID_Descriptor (pdev, pphost, USB_HID_DESC_SIZE)== USBH_OK)
    {
      
      USBH_ParseHIDDesc(&HID_Desc, pdev->host.Rx_Buffer);
      HID_Machine.ctl_state = HID_REQ_GET_REPORT_DESC;
    }
    
    break;     
  case HID_REQ_GET_REPORT_DESC:
    
    
    /* Get Report Desc */ 
    if (USBH_Get_HID_ReportDescriptor(pdev , pphost, HID_Desc.wItemLength) == USBH_OK)
    {
      HID_Machine.ctl_state = HID_REQ_SET_IDLE;
    }
    
    break;
    
  case HID_REQ_SET_IDLE:
    
    classReqStatus = USBH_Set_Idle (pdev, pphost, 0, 0);
    
    /* set Idle */
    if (classReqStatus == USBH_OK)
    {
      HID_Machine.ctl_state = HID_REQ_SET_PROTOCOL;  
    }
    else if(classReqStatus == USBH_NOT_SUPPORTED) 
    {
      HID_Machine.ctl_state = HID_REQ_SET_PROTOCOL;        
    } 
    break; 
    
  case HID_REQ_SET_PROTOCOL:
    /* set protocol */
    if (USBH_Set_Protocol (pdev ,pphost, 0) == USBH_OK)
    {
      HID_Machine.ctl_state = HID_REQ_IDLE;
      
      /* all requests performed*/
      status = USBH_OK; 
    } 
    break;
    
  default:
    break;
  }
  
  return status; 
}
Exemplo n.º 2
0
void USBH_Dev_HID_EnumerationDone(USB_OTG_CORE_HANDLE *pcore, USBH_DEV *pdev)
{
	if (pdev->Usr_Data != 0) {
		free(pdev->Usr_Data);
		pdev->Usr_Data = 0;
	}

	uint8_t numIntf = pdev->device_prop.Cfg_Desc.bNumInterfaces;
	char isHid = 0;
	pdev->Usr_Data = calloc(1, sizeof(HID_Data_t));
	HID_Data_t* HID_Data = pdev->Usr_Data;
	HID_Data->io = calloc(numIntf, sizeof(USBH_DevIO_t*));
	HID_Data->ioIdx = 0;

	dbg_printf(DBGMODE_DEBUG, "USBH_Dev_HID_EnumerationDone, bNumInterfaces: %d\r\n", numIntf);

	for (int i = 0; i < numIntf; i++)
	{
		// filter out non-HID class interfaces
		if (pdev->device_prop.Itf_Desc[i].bInterfaceClass != 0x03) {
			continue;
		}

		isHid = 1;

		USBH_DevD2H_DataHandler_t dataHandler = 0;
		HID_Rpt_Parsing_Params_t* parser = 0;
		uint8_t parserEp = 0;

		if (pdev->device_prop.Dev_Desc.idVendor == SONY_VID && pdev->device_prop.Dev_Desc.idProduct == DUALSHOCK3_PID) {
			// DUALSHOCK3
			dataHandler = USBH_DS3_Data_Handler;
			dbg_printf(DBGMODE_TRACE, "Dualshock 3 Detected\r\n");
		}
		else if (pdev->device_prop.Dev_Desc.idVendor == SONY_VID && pdev->device_prop.Dev_Desc.idProduct == DUALSHOCK4_PID) {
			// DUALSHOCK4
			dataHandler = USBH_DS4_Data_Handler;
			HID_Data->init_handler = USBH_DS4_Init_Handler;
			HID_Data->deinit_handler = USBH_DS4_DeInit_Handler;
			HID_Data->custom_task = USBH_DS4_Task;
			dbg_printf(DBGMODE_TRACE, "Dualshock 4 Detected\r\n");
		}
		// TODO handle others, like Xbox controllers
		else {
			// other, probably keyboard or mouse
			parser = malloc(sizeof(HID_Rpt_Parsing_Params_t));
			dataHandler = HID_Default_Data_Handler;
		}

		uint8_t maxEP = ( (pdev->device_prop.Itf_Desc[i].bNumEndpoints <= USBH_MAX_NUM_ENDPOINTS) ?
						pdev->device_prop.Itf_Desc[i].bNumEndpoints :
						USBH_MAX_NUM_ENDPOINTS);

		// assign interrupt endpoints to channels, and polling parameters for the D2H endpoint
		// warning: assume 1 interrupt endpoint per direction
		for (int j = 0; j < maxEP; j++)
		{
			USBH_EpDesc_TypeDef* epDesc = &(pdev->device_prop.Ep_Desc[i][j]);
			if ((epDesc->bmAttributes & EP_TYPE_MSK) == USB_EP_TYPE_INTR)
			{
				if ((epDesc->bEndpointAddress & USB_EP_DIR_MSK) == USB_EP_DIR_IN)
				{
					HID_Data->io[i] = USBH_DevIO_Manager_New(pcore, pdev, epDesc,
#ifdef USBH_HID_ENABLE_DYNAMIC_HC_ALLOC
							1
#else
							0
#endif
							,
							dataHandler, parser
					);
					parserEp = epDesc->bEndpointAddress;
				}
			}
		}

		USBH_Status status;

		if (parser != 0)
		{
			USBH_HIDDesc_TypeDef hidDesc;

			status = USBH_Get_HID_Descriptor_Blocking (pcore, pdev, i);
			if (status == USBH_OK) {
				USBH_ParseHIDDesc(&hidDesc, pcore->host.Rx_Buffer);
				vcp_printf("%sI%d:C%d:HIDDesc:\r\n", USBH_Dev_DebugPrint(pdev, 0), i, USB_HID_DESC_SIZE);
				for (uint8_t k = 0; k < USB_HID_DESC_SIZE; k++) {
					vcp_printf(" 0x%02X", pcore->host.Rx_Buffer[k]);
				}
				vcp_printf("\r\n");
			}
			else {
				dbg_printf(DBGMODE_ERR, "USBH_Get_HID_Descriptor_Blocking failed status: 0x%04X\r\n", status);
				USBH_ErrorHandle(pcore, pdev, status);
				continue;
			}

			uint8_t repIdList[8] = { 0, 0, 0, 0, 0, 0, 0, 0};

			status = USBH_Get_HID_ReportDescriptor_Blocking(pcore , pdev, i, hidDesc.wItemLength);
			if (status == USBH_OK) {
				dbg_printf(DBGMODE_DEBUG, "USBH_Get_HID_ReportDescriptor_Blocking OK: 0x%04X\r\n", status);

				vcp_printf("%sI%d:C%d:ReptDesc:", USBH_Dev_DebugPrint(pdev, 0), i, hidDesc.wItemLength);
				for (uint8_t k = 0; k < hidDesc.wItemLength; k++) {
					vcp_printf(" 0x%02X", pcore->host.Rx_Buffer[k]);
				}
				vcp_printf("\r\n");

				HID_Rpt_Parsing_Params_Reset(parser);
				HID_Rpt_Desc_Parse(pcore->host.Rx_Buffer, hidDesc.wItemLength, parser, parserEp, repIdList);
				//dbg_printf(DBGMODE_DEBUG, "HID_Rpt_Desc_Parse Complete \r\n");
				HID_Rpt_Parsing_Params_Debug_Dump(parser);
			}
			else {
				dbg_printf(DBGMODE_ERR, "USBH_Get_HID_ReportDescriptor_Blocking failed status: 0x%04X\r\n", status);
				USBH_ErrorHandle(pcore, pdev, status);
				continue;
			}

			char hasSetIdle = 0;
			for (int ridIdx = 0; ridIdx < 8; ridIdx++)
			{
				uint8_t rid = repIdList[ridIdx];
				if (rid > 0)
				{
					hasSetIdle = 1;
					status = USBH_Set_Idle_Blocking (pcore, pdev, i, 0, rid);
					if (status == USBH_OK) {
						dbg_printf(DBGMODE_DEBUG, "USBH_Set_Idle_Blocking[%d] OK: 0x%04X\r\n", rid, status);
					}
					else if(status == USBH_NOT_SUPPORTED || status == USBH_STALL) {
						dbg_printf(DBGMODE_DEBUG, "USBH_Set_Idle_Blocking[%d] NOT SUPPORTED\r\n", rid);
					}
					else {
						dbg_printf(DBGMODE_ERR, "USBH_Set_Idle_Blocking[%d] failed status: 0x%04X\r\n", rid, status);
						USBH_ErrorHandle(pcore, pdev, status);
					}
				}

				// end of list
				if (rid == 0) {
					break;
				}
			}

			if (hasSetIdle == 0)
			{
				status = USBH_Set_Idle_Blocking (pcore, pdev, i, 0, 0);
				if (status == USBH_OK) {
					dbg_printf(DBGMODE_DEBUG, "USBH_Set_Idle_Blocking[only %d] OK: 0x%04X\r\n", 0, status);
				}
				else if(status == USBH_NOT_SUPPORTED || status == USBH_STALL) {
					dbg_printf(DBGMODE_DEBUG, "USBH_Set_Idle_Blocking[only %d] NOT SUPPORTED\r\n", 0);
				}
				else {
					dbg_printf(DBGMODE_ERR, "USBH_Set_Idle_Blocking[only %d] failed status: 0x%04X\r\n", 0, status);
					USBH_ErrorHandle(pcore, pdev, status);
				}
			}
		}

		if (pdev->device_prop.Dev_Desc.idVendor == SONY_VID && pdev->device_prop.Dev_Desc.idProduct == DUALSHOCK4_PID)
		{
			// TODO
		}
		else
		{
			status = USBH_Set_Protocol_Blocking(pcore, pdev, i, 0); // this sets the protocol = "report"
			if (status == USBH_OK) {
				dbg_printf(DBGMODE_DEBUG, "USBH_Set_Protocol_Blocking OK: 0x%04X\r\n", status);
			}
			else {
				dbg_printf(DBGMODE_ERR, "USBH_Set_Protocol_Blocking failed status: 0x%04X\r\n", status);
				USBH_ErrorHandle(pcore, pdev, status);
			}
		}
	}

	if (isHid == 0) {

		// none of the interfaces are HID
		free(pdev->Usr_Data);
		pdev->Usr_Data = 0;
		pdev->cb = &USBH_Dev_CB_Default; // this will cause the device to not be serviced
	}

	if (HID_Data->init_handler != 0) {
		HID_Data->init_handler(pcore, pdev);
	}

	USBH_Dev_HID_Cnt++;
}