/** * @brief Handle HID Control process * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_MTP_Events (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_BUSY ; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; switch(MTP_Handle->events.state) { case MTP_EVENTS_INIT: if((phost->Timer & 1) == 0) { MTP_Handle->events.timer = phost->Timer; USBH_InterruptReceiveData(phost, (uint8_t *)&(MTP_Handle->events.container), MTP_Handle->NotificationEpSize, MTP_Handle->NotificationPipe); MTP_Handle->events.state = MTP_EVENTS_GETDATA ; } break; case MTP_EVENTS_GETDATA: if(USBH_LL_GetURBState(phost , MTP_Handle->NotificationPipe) == USBH_URB_DONE) { MTP_DecodeEvent(phost); } if(( phost->Timer - MTP_Handle->events.timer) >= MTP_Handle->events.poll) { MTP_Handle->events.timer = phost->Timer; USBH_InterruptReceiveData(phost, (uint8_t *)&(MTP_Handle->events.container), MTP_Handle->NotificationEpSize, MTP_Handle->NotificationPipe); } break; default: break; } return status; }
/** * @brief USBH_HID_Process * The function is for managing state machine for HID data transfers * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_OK; HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData; switch (HID_Handle->state) { case HID_INIT: HID_Handle->Init(phost); case HID_IDLE: if(USBH_HID_GetReport (phost, 0x01, 0, HID_Handle->pData, HID_Handle->length) == USBH_OK) { fifo_write(&HID_Handle->fifo, HID_Handle->pData, HID_Handle->length); HID_Handle->state = HID_SYNC; } break; case HID_SYNC: /* Sync with start of Even Frame */ if(phost->Timer & 1) { HID_Handle->state = HID_GET_DATA; } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif break; case HID_GET_DATA: USBH_InterruptReceiveData(phost, HID_Handle->pData, HID_Handle->length, HID_Handle->InPipe); HID_Handle->state = HID_POLL; HID_Handle->timer = phost->Timer; HID_Handle->DataReady = 0; break; case HID_POLL: if(USBH_LL_GetURBState(phost , HID_Handle->InPipe) == USBH_URB_DONE) { if(HID_Handle->DataReady == 0) { fifo_write(&HID_Handle->fifo, HID_Handle->pData, HID_Handle->length); HID_Handle->DataReady = 1; USBH_HID_EventCallback(phost); #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } } else if(USBH_LL_GetURBState(phost , HID_Handle->InPipe) == USBH_URB_STALL) /* IN Endpoint Stalled */ { /* Issue Clear Feature on interrupt IN endpoint */ if(USBH_ClrFeature(phost, HID_Handle->ep_addr) == USBH_OK) { /* Change state to issue next IN token */ HID_Handle->state = HID_GET_DATA; } } break; default: break; } return status; }
/** * @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; }
/** * @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; }
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); } } } }