/** * @brief USBD_SetAddress * Set device address * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_SetAddress(USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req) { uint8_t dev_addr; if ((req->wIndex == 0) && (req->wLength == 0)) { dev_addr = (uint8_t)(req->wValue) & 0x7F; if (pdev->dev.device_status == USB_OTG_CONFIGURED) { USBD_CtlError(pdev , req); } else { pdev->dev.device_address = dev_addr; DCD_EP_SetAddress(pdev, dev_addr); USBD_CtlSendStatus(pdev); if (dev_addr != 0) { pdev->dev.device_status = USB_OTG_ADDRESSED; } else { pdev->dev.device_status = USB_OTG_DEFAULT; } } } else { USBD_CtlError(pdev , req); } }
/** * @brief USBD_SetAddress * Set device address * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_SetAddress(USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) { uint8_t dev_addr; if ((req->wIndex == 0) && (req->wLength == 0)) { dev_addr = (uint8_t)(req->wValue) & 0x7F; if (pdev->dev_state == USBD_STATE_CONFIGURED) { USBD_CtlError(pdev , req); } else { pdev->dev_address = dev_addr; USBD_LL_SetUSBAddress(pdev, dev_addr); USBD_CtlSendStatus(pdev); if (dev_addr != 0) { pdev->dev_state = USBD_STATE_ADDRESSED; } else { pdev->dev_state = USBD_STATE_DEFAULT; } } } else { USBD_CtlError(pdev , req); } }
/** * @brief USBD_StdItfReq * Handle standard usb interface requests * @param pdev: device instance * @param req: usb request * @retval status */ USBD_StatusTypeDef USBD_StdItfReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) { USBD_StatusTypeDef ret = USBD_OK; switch (pdev->dev_state) { case USBD_STATE_CONFIGURED: if (LOBYTE(req->wIndex) <= USBD_MAX_NUM_INTERFACES) { pdev->pClass->Setup (pdev, req); if((req->wLength == 0)&& (ret == USBD_OK)) { USBD_CtlSendStatus(pdev); } } else { USBD_CtlError(pdev , req); } break; default: USBD_CtlError(pdev , req); break; } return USBD_OK; }
/** * @brief USBD_StdItfReq * Handle standard usb interface requests * @param pdev: device instance * @param req: usb request * @retval status */ USBD_StatusTypeDef USBD_StdItfReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) { USBD_StatusTypeDef ret = USBD_OK; switch (pdev->dev_state) { case USBD_STATE_CONFIGURED: if (LOBYTE(req->wIndex) <= USBD_MAX_NUM_INTERFACES) { pdev->pEventSource->UsbEventSender.raiseEvent(stm32plus::usb::DeviceClassSdkSetupEvent(*req)); if((req->wLength == 0)&& (ret == USBD_OK)) { USBD_CtlSendStatus(pdev); } } else { USBD_CtlError(pdev , req); } break; default: USBD_CtlError(pdev , req); break; } return USBD_OK; }
/** * @brief USBD_DataOutStage * Handle data out stage * @param pdev: device instance * @param epnum: endpoint index * @retval status */ static uint8_t USBD_DataOutStage(USB_CORE_HANDLE *pdev , uint8_t epnum) { USB_EP *ep; if(epnum == 0) { ep = &pdev->dev.out_ep[0]; if ( pdev->dev.device_state == USB_EP0_DATA_OUT) { if(ep->rem_data_len > ep->maxpacket) { ep->rem_data_len -= ep->maxpacket; USBD_CtlContinueRx (pdev, ep->xfer_buff, MIN(ep->rem_data_len ,ep->maxpacket)); } else { if((pdev->dev.class_cb->EP0_RxReady != NULL)&& (pdev->dev.device_status == USB_CONFIGURED)) { pdev->dev.class_cb->EP0_RxReady(pdev); } USBD_CtlSendStatus(pdev); } } } else if((pdev->dev.class_cb->DataOut != NULL)&& (pdev->dev.device_status == USB_CONFIGURED)) { pdev->dev.class_cb->DataOut(pdev, epnum); } return USBD_OK; }
/** * @brief USBD_StdItfReq * Handle standard usb interface requests * @param pdev: USB OTG device instance * @param req: usb request * @retval status */ USBD_Status USBD_StdItfReq (USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req) { USBD_Status ret = USBD_OK; switch (pdev->dev.device_status) { case USB_OTG_CONFIGURED: if (LOBYTE(req->wIndex) <= USBD_ITF_MAX_NUM) { pdev->dev.class_cb->Setup (pdev, req); if((req->wLength == 0)&& (ret == USBD_OK)) { USBD_CtlSendStatus(pdev); } } else { USBD_CtlError(pdev , req); } break; default: USBD_CtlError(pdev , req); break; } return ret; }
/** * @brief USBD_DataOutStage * Handle data out stage * @param pdev: device instance * @param epnum: endpoint index * @retval status */ static uint8_t USBD_DataOutStage ( USB_OTG_CORE_HANDLE *pdev , uint8_t epnum ) { USB_OTG_EP *ep; if ( epnum == 0 ) { ep = &pdev->dev.out_ep[0]; if ( pdev->dev.device_state == USB_OTG_EP0_DATA_OUT ) { if ( ep->rem_data_len > ep->maxpacket ) { ep->rem_data_len -= ep->maxpacket; if ( pdev->cfg.dma_enable == 1 ) { /* in slave mode this, is handled by the RxSTSQLvl ISR */ ep->xfer_buff += ep->maxpacket; } USBD_CtlContinueRx ( pdev, ep->xfer_buff, MIN ( ep->rem_data_len ,ep->maxpacket ) ); } else { if ( ( pdev->dev.class_cb->EP0_RxReady != NULL ) && ( pdev->dev.device_status == USB_OTG_CONFIGURED ) ) { pdev->dev.class_cb->EP0_RxReady ( pdev ); } USBD_CtlSendStatus ( pdev ); } } } else if ( ( pdev->dev.class_cb->DataOut != NULL ) && ( pdev->dev.device_status == USB_OTG_CONFIGURED ) ) { pdev->dev.class_cb->DataOut ( pdev, epnum ); } return USBD_OK; }
/** * @brief USBD_SetFeature * Handle Set device feature request * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_SetFeature(USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req) { USB_OTG_DCTL_TypeDef dctl; uint8_t test_mode = 0; if (req->wValue == USB_FEATURE_REMOTE_WAKEUP) { pdev->dev.DevRemoteWakeup = 1; pdev->dev.class_cb->Setup (pdev, req); USBD_CtlSendStatus(pdev); } else if ((req->wValue == USB_FEATURE_TEST_MODE) && ((req->wIndex & 0xFF) == 0)) { dctl.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DCTL); test_mode = req->wIndex >> 8; switch (test_mode) { case 1: // TEST_J dctl.b.tstctl = 1; break; case 2: // TEST_K dctl.b.tstctl = 2; break; case 3: // TEST_SE0_NAK dctl.b.tstctl = 3; break; case 4: // TEST_PACKET dctl.b.tstctl = 4; break; case 5: // TEST_FORCE_ENABLE dctl.b.tstctl = 5; break; } SET_TEST_MODE = dctl; pdev->dev.test_mode = 1; USBD_CtlSendStatus(pdev); }
/** * @brief USBD_SetFeature * Handle Set device feature request * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_SetFeature(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) { if (req->wValue == USB_FEATURE_REMOTE_WAKEUP) { pdev->dev_remote_wakeup = 1; pdev->pClass->Setup(pdev, req); USBD_CtlSendStatus(pdev); } }
/** * @brief USBD_SetFeature * Handle Set device feature request * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_SetFeature(USB_CORE_HANDLE *pdev, USB_SETUP_REQ *req) { if (req->wValue == USB_FEATURE_REMOTE_WAKEUP) { pdev->dev.DevRemoteWakeup = 1; pdev->dev.class_cb->Setup (pdev, req); USBD_CtlSendStatus(pdev); } }
/** * @brief USBD_SetFeature * Handle Set device feature request * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_SetFeature(USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) { if (req->wValue == USB_FEATURE_REMOTE_WAKEUP) { pdev->dev_remote_wakeup = 1; pdev->pEventSource->UsbEventSender.raiseEvent(stm32plus::usb::DeviceClassSdkSetupEvent(*req)); USBD_CtlSendStatus(pdev); } }
/** * @brief USBD_ClrFeature * Handle clear device feature request * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_ClrFeature(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) { switch (pdev->dev_state) { case USBD_STATE_ADDRESSED: case USBD_STATE_CONFIGURED: if (req->wValue == USB_FEATURE_REMOTE_WAKEUP) { pdev->dev_remote_wakeup = 0; pdev->pClass->Setup(pdev, req); USBD_CtlSendStatus(pdev); } break; default : USBD_CtlError(pdev, req); break; } }
/** * @brief USBD_DataOutStage * Handle data OUT stage * @param pdev: device instance * @param epnum: endpoint index * @retval status */ USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata) { USBD_EndpointTypeDef *pep; if(epnum == 0) { pep = &pdev->ep_out[0]; if ( pdev->ep0_state == USBD_EP0_DATA_OUT) { if(pep->rem_length > pep->maxpacket) { pep->rem_length -= pep->maxpacket; USBD_CtlContinueRx (pdev, pdata, MIN(pep->rem_length ,pep->maxpacket)); } else { uint8_t intf; for (intf =0; intf < USBD_MAX_NUM_INTERFACES; intf++) { if(usbd_is_valid_intf(pdev, intf) && (pdev->interfacesClass[intf].pClass->EP0_RxReady != NULL)&& (pdev->dev_state == USBD_STATE_CONFIGURED)) { ((EP0_RxReady_t)PIC(pdev->interfacesClass[intf].pClass->EP0_RxReady))(pdev); } } USBD_CtlSendStatus(pdev); } } } else { uint8_t intf; for (intf =0; intf < USBD_MAX_NUM_INTERFACES; intf++) { if( usbd_is_valid_intf(pdev, intf) && (pdev->interfacesClass[intf].pClass->DataOut != NULL)&& (pdev->dev_state == USBD_STATE_CONFIGURED)) { ((DataOut_t)PIC(pdev->interfacesClass[intf].pClass->DataOut))(pdev, epnum, pdata); } } } return USBD_OK; }
/** * @brief USBD_ClrFeature * Handle clear device feature request * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_ClrFeature(USB_CORE_HANDLE *pdev, USB_SETUP_REQ *req) { switch (pdev->dev.device_status) { case USB_ADDRESSED: case USB_CONFIGURED: if (req->wValue == USB_FEATURE_REMOTE_WAKEUP) { pdev->dev.DevRemoteWakeup = 0; pdev->dev.class_cb->Setup (pdev, req); USBD_CtlSendStatus(pdev); } break; default : USBD_CtlError(pdev , req); break; } }
/** * @brief USBD_ClrFeature * Handle clear device feature request * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_ClrFeature(USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) { switch (pdev->dev_state) { case USBD_STATE_ADDRESSED: case USBD_STATE_CONFIGURED: if (req->wValue == USB_FEATURE_REMOTE_WAKEUP) { pdev->dev_remote_wakeup = 0; pdev->pEventSource->UsbEventSender.raiseEvent(stm32plus::usb::DeviceClassSdkSetupEvent(*req)); USBD_CtlSendStatus(pdev); } break; default : USBD_CtlError(pdev , req); break; } }
/** * @brief USBD_DataOutStage * Handle data OUT stage * @param pdev: device instance * @param epnum: endpoint index * @retval status */ USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata) { USBD_EndpointTypeDef *pep; if(epnum == 0) { pep = &pdev->ep_out[0]; if ( pdev->ep0_state == USBD_EP0_DATA_OUT) { if(pep->rem_length > pep->maxpacket) { pep->rem_length -= pep->maxpacket; USBD_CtlContinueRx (pdev, pdata, MIN(pep->rem_length ,pep->maxpacket)); } else { if((pdev->pClass->EP0_RxReady != NULL)&& (pdev->dev_state == USBD_STATE_CONFIGURED)) { pdev->pClass->EP0_RxReady(pdev); } USBD_CtlSendStatus(pdev); } } } else if((pdev->pClass->DataOut != NULL)&& (pdev->dev_state == USBD_STATE_CONFIGURED)) { pdev->pClass->DataOut(pdev, epnum); } return USBD_OK; }
/** * @brief USBD_SetAddress * Set device address * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_SetAddress(USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req) { uint8_t dev_addr; if ((req->wIndex == 0) && (req->wLength == 0)) { dev_addr = (uint8_t)(req->wValue) & 0x7F; if (pdev->dev.device_status == USB_OTG_CONFIGURED) { dbg_printf(DBGMODE_ERR, "USBD_SetAddress error, already configured device, file " __FILE__ ":%d\r\n", __LINE__); //USBD_CtlError(pdev , req); } //else { pdev->dev.device_address = dev_addr; DCD_EP_SetAddress(pdev, dev_addr); USBD_CtlSendStatus(pdev); if (dev_addr != 0) { pdev->dev.device_status = USB_OTG_ADDRESSED; } else { //pdev->dev.device_status = USB_OTG_DEFAULT; } } } else { dbg_printf(DBGMODE_ERR, "USBD_SetAddress Stall, bad wIndex 0x%04X or wLength 0x%04X, file " __FILE__ ":%d\r\n", req->wIndex, req->wLength, __LINE__); USBD_CtlError(pdev , req); } }
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; }
/** * @brief USBD_SetConfig * Handle Set device configuration request * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_SetConfig(USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req) { static uint8_t cfgidx; cfgidx = (uint8_t)(req->wValue); if (cfgidx > USBD_CFG_MAX_NUM ) { dbg_printf(DBGMODE_ERR, "USBD_SetConfig Stall, bad cfgidx 0x%04X, file " __FILE__ ":%d\r\n", req->wValue, __LINE__); USBD_CtlError(pdev , req); } else { switch (pdev->dev.device_status) { case USB_OTG_ADDRESSED: if (cfgidx) { pdev->dev.device_config = cfgidx; pdev->dev.device_status = USB_OTG_CONFIGURED; USBD_SetCfg(pdev , cfgidx); USBD_CtlSendStatus(pdev); } else { USBD_CtlSendStatus(pdev); } break; case USB_OTG_CONFIGURED: if (cfgidx == 0) { pdev->dev.device_status = USB_OTG_ADDRESSED; pdev->dev.device_config = cfgidx; USBD_ClrCfg(pdev , cfgidx); USBD_CtlSendStatus(pdev); } else if (cfgidx != pdev->dev.device_config) { /* Clear old configuration */ USBD_ClrCfg(pdev , pdev->dev.device_config); /* set new configuration */ pdev->dev.device_config = cfgidx; USBD_SetCfg(pdev , cfgidx); USBD_CtlSendStatus(pdev); } else { USBD_CtlSendStatus(pdev); } break; default: dbg_printf(DBGMODE_ERR, "USBD_SetConfig Stall, unknown device_status 0x%02X, file " __FILE__ ":%d\r\n", pdev->dev.device_status, __LINE__); USBD_CtlError(pdev , req); break; } } }
/** * @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; }
/** * @brief USBD_SetConfig * Handle Set device configuration request * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_SetConfig(USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) { static uint8_t cfgidx; cfgidx = (uint8_t)(req->wValue); if (cfgidx > USBD_MAX_NUM_CONFIGURATION ) { USBD_CtlError(pdev , req); } else { switch (pdev->dev_state) { case USBD_STATE_ADDRESSED: if (cfgidx) { pdev->dev_config = cfgidx; pdev->dev_state = USBD_STATE_CONFIGURED; if(USBD_SetClassConfig(pdev , cfgidx) == USBD_FAIL) { USBD_CtlError(pdev , req); return; } USBD_CtlSendStatus(pdev); } else { USBD_CtlSendStatus(pdev); } break; case USBD_STATE_CONFIGURED: if (cfgidx == 0) { pdev->dev_state = USBD_STATE_ADDRESSED; pdev->dev_config = cfgidx; USBD_ClrClassConfig(pdev , cfgidx); USBD_CtlSendStatus(pdev); } else if (cfgidx != pdev->dev_config) { /* Clear old configuration */ USBD_ClrClassConfig(pdev , pdev->dev_config); /* set new configuration */ pdev->dev_config = cfgidx; if(USBD_SetClassConfig(pdev , cfgidx) == USBD_FAIL) { USBD_CtlError(pdev , req); return; } USBD_CtlSendStatus(pdev); } else { USBD_CtlSendStatus(pdev); } break; default: USBD_CtlError(pdev , req); break; } } }
/** * @brief USBD_CDC_Setup * Handle the CDC specific requests * @param pdev: instance * @param req: usb requests * @retval status */ static uint8_t USBD_CDC_Setup (void *pdev, USB_SETUP_REQ *req) { dbgwdg_feed(); uint16_t len=USB_CDC_DESC_SIZ; uint8_t *pbuf=USBD_CDC_ConfigDescriptor + 9; switch (req->bmRequest & USB_REQ_TYPE_MASK) { /* CDC Class Requests -------------------------------*/ case USB_REQ_TYPE_CLASS : /* Check if the request is a data setup packet */ if (req->wLength > 0) { /* Check if the request is Device-to-Host */ if (req->bmRequest & 0x80) { // nothing to do //VCP_Ctrl(req->bRequest, CmdBuff, req->wLength); if (req->bRequest == CDC_GET_LINE_CODING) { memcpy(USBD_CDC_CMD_Buff, &cdc_linecoding, req->wLength); } /* Send the data to the host */ USBD_CtlSendData (pdev, USBD_CDC_CMD_Buff, req->wLength); } else /* Host-to-Device request */ { /* Set the value of the current command to be processed */ // nothing to do //cdcCmd = req->bRequest; //cdcLen = req->wLength; /* Prepare the reception of the buffer over EP0 Next step: the received data will be managed in USBD_CDC_EP0_TxSent() function. */ USBD_CtlPrepareRx (pdev, USBD_CDC_CMD_Buff, req->wLength); } } else { // nothing to do //VCP_Ctrl(req->bRequest, NULL, 0); USBD_CtlSendStatus(pdev); } return USBD_OK; /* Standard Requests -------------------------------*/ case USB_REQ_TYPE_STANDARD: switch (req->bRequest) { case USB_REQ_GET_DESCRIPTOR: if( (req->wValue >> 8) == CDC_DESCRIPTOR_TYPE) { pbuf = USBD_CDC_ConfigDescriptor + 9 + (9 * USBD_ITF_MAX_NUM); len = MIN(USB_CDC_DESC_SIZ , req->wLength); } USBD_CtlSendData (pdev, pbuf, len); break; case USB_REQ_GET_INTERFACE : USBD_CtlSendData (pdev, (uint8_t *)&USBD_CDC_AltSet, 1); break; case USB_REQ_SET_INTERFACE : if ((uint8_t)(req->wValue) < USBD_ITF_MAX_NUM) { USBD_CDC_AltSet = (uint8_t)(req->wValue); } else { USBD_CtlError (pdev, req); dbg_printf(DBGMODE_ERR, "CDC Stall, USB_REQ_SET_INTERFACE, unknown wValue 0x%04X, file " __FILE__ ":%d\r\n", req->wValue, __LINE__); } break; } default: USBD_CtlError (pdev, req); dbg_printf(DBGMODE_ERR, "CDC Stall, unknown bmRequest 0x%02X, file " __FILE__ ":%d\r\n", req->bmRequest, __LINE__); return USBD_FAIL; } return USBD_OK; }
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; }
/** * @brief USBD_StdEPReq * Handle standard usb endpoint requests * @param pdev: device instance * @param req: usb request * @retval status */ USBD_StatusTypeDef USBD_StdEPReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) { uint8_t ep_addr; USBD_StatusTypeDef ret = USBD_OK; USBD_EndpointTypeDef *pep; ep_addr = LOBYTE(req->wIndex); switch (req->bRequest) { case USB_REQ_SET_FEATURE : switch (pdev->dev_state) { case USBD_STATE_ADDRESSED: if ((ep_addr != 0x00) && (ep_addr != 0x80)) { USBD_LL_StallEP(pdev , ep_addr); } break; case USBD_STATE_CONFIGURED: if (req->wValue == USB_FEATURE_EP_HALT) { if ((ep_addr != 0x00) && (ep_addr != 0x80)) { USBD_LL_StallEP(pdev , ep_addr); } } pdev->pEventSource->UsbEventSender.raiseEvent(stm32plus::usb::DeviceClassSdkSetupEvent(*req)); USBD_CtlSendStatus(pdev); break; default: USBD_CtlError(pdev , req); break; } break; case USB_REQ_CLEAR_FEATURE : switch (pdev->dev_state) { case USBD_STATE_ADDRESSED: if ((ep_addr != 0x00) && (ep_addr != 0x80)) { USBD_LL_StallEP(pdev , ep_addr); } break; case USBD_STATE_CONFIGURED: if (req->wValue == USB_FEATURE_EP_HALT) { if ((ep_addr & 0x7F) != 0x00) { USBD_LL_ClearStallEP(pdev , ep_addr); pdev->pEventSource->UsbEventSender.raiseEvent(stm32plus::usb::DeviceClassSdkSetupEvent(*req)); } USBD_CtlSendStatus(pdev); } break; default: USBD_CtlError(pdev , req); break; } break; case USB_REQ_GET_STATUS: switch (pdev->dev_state) { case USBD_STATE_ADDRESSED: if ((ep_addr & 0x7F) != 0x00) { USBD_LL_StallEP(pdev , ep_addr); } break; case USBD_STATE_CONFIGURED: pep = ((ep_addr & 0x80) == 0x80) ? &pdev->ep_in[ep_addr & 0x7F]:\ &pdev->ep_out[ep_addr & 0x7F]; if(USBD_LL_IsStallEP(pdev, ep_addr)) { pep->status = 0x0001; } else { pep->status = 0x0000; } USBD_CtlSendData (pdev, (uint8_t *)&pep->status, 2); break; default: USBD_CtlError(pdev , req); break; } break; default: break; } return ret; }
//-------------------------------------------------------------- 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; }
//-------------------------------------------------------------- static void USBD_SetConfig(USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req) { static uint8_t cfgidx; cfgidx = (uint8_t)(req->wValue); if (cfgidx > USBD_CFG_MAX_NUM ) { USBD_CtlError(pdev , req); } else { switch (pdev->dev.device_status) { case USB_OTG_ADDRESSED: if (cfgidx) { pdev->dev.device_config = cfgidx; pdev->dev.device_status = USB_OTG_CONFIGURED; USBD_SetCfg(pdev , cfgidx); USBD_CtlSendStatus(pdev); } else { USBD_CtlSendStatus(pdev); } break; case USB_OTG_CONFIGURED: if (cfgidx == 0) { pdev->dev.device_status = USB_OTG_ADDRESSED; pdev->dev.device_config = cfgidx; USBD_ClrCfg(pdev , cfgidx); USBD_CtlSendStatus(pdev); } else if (cfgidx != pdev->dev.device_config) { /* Clear old configuration */ USBD_ClrCfg(pdev , pdev->dev.device_config); /* set new configuration */ pdev->dev.device_config = cfgidx; USBD_SetCfg(pdev , cfgidx); USBD_CtlSendStatus(pdev); } else { USBD_CtlSendStatus(pdev); } break; default: USBD_CtlError(pdev , req); break; } } }
/** * @brief USBD_StdEPReq * Handle standard usb endpoint requests * @param pdev: device instance * @param req: usb request * @retval status */ USBD_StatusTypeDef USBD_StdEPReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) { uint8_t ep_addr; USBD_StatusTypeDef ret = USBD_OK; USBD_EndpointTypeDef *pep; ep_addr = LOBYTE(req->wIndex); /* Check if it is a class request */ if ((req->bmRequest & 0x60) == 0x20) { pdev->pClass->Setup (pdev, req); return USBD_OK; } switch (req->bRequest) { case USB_REQ_SET_FEATURE : switch (pdev->dev_state) { case USBD_STATE_ADDRESSED: if ((ep_addr != 0x00) && (ep_addr != 0x80)) { USBD_LL_StallEP(pdev , ep_addr); } break; case USBD_STATE_CONFIGURED: if (req->wValue == USB_FEATURE_EP_HALT) { if ((ep_addr != 0x00) && (ep_addr != 0x80)) { USBD_LL_StallEP(pdev , ep_addr); } } pdev->pClass->Setup (pdev, req); USBD_CtlSendStatus(pdev); break; default: USBD_CtlError(pdev , req); break; } break; case USB_REQ_CLEAR_FEATURE : switch (pdev->dev_state) { case USBD_STATE_ADDRESSED: if ((ep_addr != 0x00) && (ep_addr != 0x80)) { USBD_LL_StallEP(pdev , ep_addr); } break; case USBD_STATE_CONFIGURED: if (req->wValue == USB_FEATURE_EP_HALT) { if ((ep_addr & 0x7F) != 0x00) { USBD_LL_ClearStallEP(pdev , ep_addr); pdev->pClass->Setup (pdev, req); } USBD_CtlSendStatus(pdev); } break; default: USBD_CtlError(pdev , req); break; } break; case USB_REQ_GET_STATUS: switch (pdev->dev_state) { case USBD_STATE_ADDRESSED: if ((ep_addr & 0x7F) != 0x00) { USBD_LL_StallEP(pdev , ep_addr); } break; case USBD_STATE_CONFIGURED: pep = ((ep_addr & 0x80) == 0x80) ? &pdev->ep_in[ep_addr & 0x7F]:\ &pdev->ep_out[ep_addr & 0x7F]; if(USBD_LL_IsStallEP(pdev, ep_addr)) { pep->status = 0x0001; } else { pep->status = 0x0000; } USBD_CtlSendData (pdev, (uint8_t *)&pep->status, 2); break; default: USBD_CtlError(pdev , req); break; } break; default: break; } return ret; }