/** * @brief USBD_SetupStage * Handle the setup stage * @param pdev: device instance * @retval status */ static uint8_t USBD_SetupStage(USB_CORE_HANDLE *pdev) { USB_SETUP_REQ req; USBD_ParseSetupRequest(pdev , &req); switch (req.bmRequest & 0x1F) { case USB_REQ_RECIPIENT_DEVICE: USBD_StdDevReq (pdev, &req); break; case USB_REQ_RECIPIENT_INTERFACE: USBD_StdItfReq(pdev, &req); break; case USB_REQ_RECIPIENT_ENDPOINT: USBD_StdEPReq(pdev, &req); break; default: DCD_EP_Stall(pdev , req.bmRequest & 0x80); break; } return USBD_OK; }
static void MSC_BOT_Abort (USB_OTG_CORE_HANDLE *pdev) { if ((MSC_BOT_cbw.bmFlags == 0) && (MSC_BOT_cbw.dDataLength != 0) && (MSC_BOT_Status == BOT_STATE_NORMAL) ) { DCD_EP_Stall(pdev, MSC_OUT_EP ); } DCD_EP_Stall(pdev, MSC_IN_EP); if(MSC_BOT_Status == BOT_STATE_ERROR) { DCD_EP_PrepareRx (pdev, MSC_OUT_EP, (uint8_t *)&MSC_BOT_cbw, BOT_CBW_LENGTH); } }
void MSC_BOT_CplClrFeature (USB_OTG_CORE_HANDLE *pdev, uint8_t epnum) { if(MSC_BOT_Status == BOT_STATE_ERROR ) { /* Bad CBW Signature */ DCD_EP_Stall(pdev, MSC_IN_EP); MSC_BOT_Status = BOT_STATE_NORMAL; } else if(((epnum & 0x80) == 0x80) && ( MSC_BOT_Status != BOT_STATE_RECOVERY)) { MSC_BOT_SendCSW (pdev, CSW_CMD_FAILED); } }
/** * @brief USBD_SetupStage * Handle the setup stage * @param pdev: device instance * @retval status */ static uint8_t USBD_SetupStage(USB_OTG_CORE_HANDLE *pdev) { USB_SETUP_REQ req; USBD_ParseSetupRequest(pdev , &req); // this is a filter that passes all setup packets to the usb_passthrough code //* if (USBPT_Is_Active != 0) { USBD_Status s = USBPTD_SetupStage(pdev, &req); if (s == USBD_OK) { return USBD_OK; } } //*/ switch (req.bmRequest & 0x1F) { case USB_REQ_RECIPIENT_DEVICE: USBD_StdDevReq (pdev, &req); break; case USB_REQ_RECIPIENT_INTERFACE: USBD_StdItfReq(pdev, &req); break; case USB_REQ_RECIPIENT_ENDPOINT: USBD_StdEPReq(pdev, &req); break; default: //pdev->dev.cb->Setup (pdev, &req); dbg_printf(DBGMODE_ERR, "\r\n USBD_SetupStage Stall, unknown bmRequest 0x%02X, file " __FILE__ ":%d\r\n", req.bmRequest, __LINE__); DCD_EP_Stall(pdev , req.bmRequest & 0x80); break; } return USBD_OK; }
//-------------------------------------------------------------- USBD_Status USBD_StdEPReq (USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req) { uint8_t ep_addr; USBD_Status ret = USBD_OK; ep_addr = LOBYTE(req->wIndex); switch (req->bRequest) { case USB_REQ_SET_FEATURE : switch (pdev->dev.device_status) { case USB_OTG_ADDRESSED: if ((ep_addr != 0x00) && (ep_addr != 0x80)) { DCD_EP_Stall(pdev , ep_addr); } break; case USB_OTG_CONFIGURED: if (req->wValue == USB_FEATURE_EP_HALT) { if ((ep_addr != 0x00) && (ep_addr != 0x80)) { DCD_EP_Stall(pdev , ep_addr); } } pdev->dev.class_cb->Setup (pdev, req); USBD_CtlSendStatus(pdev); break; default: USBD_CtlError(pdev , req); break; } break; case USB_REQ_CLEAR_FEATURE : switch (pdev->dev.device_status) { case USB_OTG_ADDRESSED: if ((ep_addr != 0x00) && (ep_addr != 0x80)) { DCD_EP_Stall(pdev , ep_addr); } break; case USB_OTG_CONFIGURED: if (req->wValue == USB_FEATURE_EP_HALT) { if ((ep_addr != 0x00) && (ep_addr != 0x80)) { DCD_EP_ClrStall(pdev , ep_addr); pdev->dev.class_cb->Setup (pdev, req); } USBD_CtlSendStatus(pdev); } break; default: USBD_CtlError(pdev , req); break; } break; case USB_REQ_GET_STATUS: switch (pdev->dev.device_status) { case USB_OTG_ADDRESSED: if ((ep_addr != 0x00) && (ep_addr != 0x80)) { DCD_EP_Stall(pdev , ep_addr); } break; case USB_OTG_CONFIGURED: if ((ep_addr & 0x80)== 0x80) { if(pdev->dev.in_ep[ep_addr & 0x7F].is_stall) { USBD_ep_status = 0x0001; } else { USBD_ep_status = 0x0000; } } else if ((ep_addr & 0x80)== 0x00) { if(pdev->dev.out_ep[ep_addr].is_stall) { USBD_ep_status = 0x0001; } else { USBD_ep_status = 0x0000; } } USBD_CtlSendData (pdev, (uint8_t *)&USBD_ep_status, 2); break; default: USBD_CtlError(pdev , req); break; } break; default: break; } return ret; }
/** * @brief USBD_StdEPReq * Handle standard usb endpoint requests * @param pdev: USB OTG device instance * @param req: usb request * @retval status */ USBD_Status USBD_StdEPReq (USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req) { uint8_t ep_addr; USBD_Status ret = USBD_OK; ep_addr = LOBYTE(req->wIndex); switch (req->bRequest) { case USB_REQ_SET_FEATURE : switch (pdev->dev.device_status) { case USB_OTG_ADDRESSED: if ((ep_addr != 0x00) && (ep_addr != 0x80)) { dbg_printf(DBGMODE_ERR, "USBD_StdEPReq Stall, bad EP op before config is set, ep 0x%02X, dev_status 0x%02X, file " __FILE__ ":%d\r\n", ep_addr, pdev->dev.device_status, __LINE__); DCD_EP_Stall(pdev , ep_addr); } break; case USB_OTG_CONFIGURED: if (req->wValue == USB_FEATURE_EP_HALT) { if ((ep_addr != 0x00) && (ep_addr != 0x80)) { dbg_printf(DBGMODE_DEBUG, "USBD_StdEPReq Stall, USB_REQ_SET_FEATURE USB_FEATURE_EP_HALT, file " __FILE__ ":%d\r\n", __LINE__); DCD_EP_Stall(pdev , ep_addr); } } pdev->dev.cb->Setup (pdev, req); USBD_CtlSendStatus(pdev); break; default: dbg_printf(DBGMODE_DEBUG, "USBD_StdEPReq Stall, unknown device_status 0x%02X, file " __FILE__ ":%d\r\n", pdev->dev.device_status, __LINE__); USBD_CtlError(pdev , req); break; } break; case USB_REQ_CLEAR_FEATURE : switch (pdev->dev.device_status) { case USB_OTG_ADDRESSED: if ((ep_addr != 0x00) && (ep_addr != 0x80)) { dbg_printf(DBGMODE_ERR, "USBD_StdEPReq Stall, bad EP op before config is set, ep 0x%02X, dev_status 0x%02X, file " __FILE__ ":%d\r\n", ep_addr, pdev->dev.device_status, __LINE__); DCD_EP_Stall(pdev , ep_addr); } break; case USB_OTG_CONFIGURED: if (req->wValue == USB_FEATURE_EP_HALT) { if ((ep_addr != 0x00) && (ep_addr != 0x80)) { DCD_EP_ClrStall(pdev , ep_addr); pdev->dev.cb->Setup (pdev, req); } USBD_CtlSendStatus(pdev); } break; default: dbg_printf(DBGMODE_DEBUG, "USBD_StdEPReq Stall, unknown device_status 0x%02X, file " __FILE__ ":%d\r\n", pdev->dev.device_status, __LINE__); USBD_CtlError(pdev , req); break; } break; case USB_REQ_GET_STATUS: switch (pdev->dev.device_status) { case USB_OTG_ADDRESSED: if ((ep_addr != 0x00) && (ep_addr != 0x80)) { dbg_printf(DBGMODE_ERR, "USBD_StdEPReq Stall, bad EP op before config is set, ep 0x%02X, dev_status 0x%02X, file " __FILE__ ":%d\r\n", ep_addr, pdev->dev.device_status, __LINE__); DCD_EP_Stall(pdev , ep_addr); } break; case USB_OTG_CONFIGURED: if ((ep_addr & 0x80)== 0x80) { if(pdev->dev.in_ep[ep_addr & 0x7F].is_stall) { USBD_ep_status = 0x0001; } else { USBD_ep_status = 0x0000; } } else if ((ep_addr & 0x80)== 0x00) { if(pdev->dev.out_ep[ep_addr].is_stall) { USBD_ep_status = 0x0001; } else { USBD_ep_status = 0x0000; } } USBD_CtlSendData (pdev, (uint8_t *)&USBD_ep_status, 2); break; default: dbg_printf(DBGMODE_DEBUG, "USBD_StdEPReq Stall, unknown bRequest 0x%02X, file " __FILE__ ":%d\r\n", req->bRequest, __LINE__); USBD_CtlError(pdev , req); break; } break; default: break; } return ret; }
void USBD_CtlError( USB_CORE_HANDLE *pdev, USB_SETUP_REQ *req) { DCD_EP_Stall(pdev , 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; }