/** * @brief usbd_cdc_Setup * Handle the CDC specific requests * @param pdev: instance * @param req: usb requests * @retval status */ static uint8_t usbd_cdc_msc_Setup (void *pdev, USB_SETUP_REQ *req) { uint16_t len=USB_CDC_MSC_DESC_SIZ; uint8_t *pbuf=usbd_cdc_msc_CfgDesc + 9; switch (req->bmRequest & USB_REQ_TYPE_MASK) { /* CDC Class Requests -------------------------------*/ case USB_REQ_TYPE_CLASS : switch (req->bRequest) { case BOT_GET_MAX_LUN : if((req->wValue == 0) && (req->wLength == 1) && ((req->bmRequest & 0x80) == 0x80)) { USBD_MSC_MaxLun = USBD_STORAGE_fops->GetMaxLun(); if(USBD_MSC_MaxLun > 0) { USBD_CtlSendData (pdev, &USBD_MSC_MaxLun, 1); } else { USBD_CtlError(pdev , req); return USBD_FAIL; } } else { USBD_CtlError(pdev , req); return USBD_FAIL; } break; case BOT_RESET : if((req->wValue == 0) && (req->wLength == 0) && ((req->bmRequest & 0x80) != 0x80)) { MSC_BOT_Reset(pdev); } else { USBD_CtlError(pdev , req); return USBD_FAIL; } break; // CDC default: /* Check if the request is a data setup packet */ if (req->wLength) { /* Check if the request is Device-to-Host */ if (req->bmRequest & 0x80) { /* Get the data to be sent to Host from interface layer */ APP_FOPS.pIf_Ctrl(req->bRequest, CmdBuff, req->wLength); /* Send the data to the host */ USBD_CtlSendData (pdev, CmdBuff, req->wLength); } else /* Host-to-Device requeset */ { /* Set the value of the current command to be processed */ 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, CmdBuff, req->wLength); } } else /* No Data request */ { /* Transfer the command to the interface layer */ APP_FOPS.pIf_Ctrl(req->bRequest, NULL, 0); // check for DTE present changes - NEZ if (req->bRequest == SET_CONTROL_LINE_STATE) { USB_DTE_Present = req->wValue & 0x01; if (!USB_DTE_Present) { DCD_EP_Flush (pdev, CDC_IN_EP); USB_Tx_State = 0; } } } return USBD_OK; break; // default } break; // case USB_REQ_TYPE_CLASS /* Standard Requests -------------------------------*/ case USB_REQ_TYPE_STANDARD: switch (req->bRequest) { case USB_REQ_GET_DESCRIPTOR: if( (req->wValue >> 8) == CDC_DESCRIPTOR_TYPE) { #ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED pbuf = usbd_cdc_Desc; #else pbuf = usbd_cdc_msc_CfgDesc + 9 + (9 * USBD_ITF_MAX_NUM); #endif len = MIN(USB_CDC_MSC_DESC_SIZ , req->wLength); } USBD_CtlSendData (pdev, pbuf, len); break; case USB_REQ_GET_INTERFACE : if ((uint8_t)req->wValue == CDC_IN_EP || (uint8_t)req->wValue == CDC_OUT_EP) { USBD_CtlSendData (pdev, (uint8_t *)&usbd_cdc_AltSet, 1); } else { USBD_CtlSendData (pdev, &USBD_MSC_AltSet, 1); break; } break; case USB_REQ_SET_INTERFACE : if ((uint8_t)req->wValue == CDC_IN_EP || (uint8_t)req->wValue == CDC_OUT_EP) { if ((uint8_t)(req->wValue) < USBD_ITF_MAX_NUM) { usbd_cdc_AltSet = (uint8_t)(req->wValue); } else { /* Call the error management function (command will be nacked */ USBD_CtlError (pdev, req); } } else { USBD_MSC_AltSet = (uint8_t)(req->wValue); } break; case USB_REQ_CLEAR_FEATURE: /* Flush the FIFO and Clear the stall status */ DCD_EP_Flush(pdev, (uint8_t)req->wIndex); /* Re-activate the EP */ DCD_EP_Close (pdev , (uint8_t)req->wIndex); if((((uint8_t)req->wIndex) & 0x80) == 0x80) { DCD_EP_Open(pdev, ((uint8_t)req->wIndex), MSC_EPIN_SIZE, USB_OTG_EP_BULK); } else { DCD_EP_Open(pdev, ((uint8_t)req->wIndex), MSC_EPOUT_SIZE, USB_OTG_EP_BULK); } /* Handle BOT error */ MSC_BOT_CplClrFeature(pdev, (uint8_t)req->wIndex); break; } } return USBD_OK; }
/** * @brief USBD_GetDescriptor * Handle Get Descriptor requests * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_GetDescriptor(USB_CORE_HANDLE *pdev, USB_SETUP_REQ *req) { uint16_t len; uint8_t *pbuf; switch (req->wValue >> 8) { #ifdef LPM_ENABLED case USB_DESC_TYPE_BOS: pbuf = pdev->dev.usr_device->GetBOSDescriptor(pdev->dev.speed, &len); break; #endif case USB_DESC_TYPE_DEVICE: pbuf = pdev->dev.usr_device->GetDeviceDescriptor(pdev->dev.speed, &len); if (req->wLength == 64) { len = 8; } break; case USB_DESC_TYPE_CONFIGURATION: pbuf = (uint8_t *)pdev->dev.class_cb->GetConfigDescriptor(pdev->dev.speed, &len); pdev->dev.pConfig_descriptor = pbuf; break; case USB_DESC_TYPE_STRING: switch ((uint8_t)(req->wValue)) { case USBD_IDX_LANGID_STR: pbuf = pdev->dev.usr_device->GetLangIDStrDescriptor(pdev->dev.speed, &len); break; case USBD_IDX_MFC_STR: pbuf = pdev->dev.usr_device->GetManufacturerStrDescriptor(pdev->dev.speed, &len); break; case USBD_IDX_PRODUCT_STR: pbuf = pdev->dev.usr_device->GetProductStrDescriptor(pdev->dev.speed, &len); break; case USBD_IDX_SERIAL_STR: pbuf = pdev->dev.usr_device->GetSerialStrDescriptor(pdev->dev.speed, &len); break; case USBD_IDX_CONFIG_STR: pbuf = pdev->dev.usr_device->GetConfigurationStrDescriptor(pdev->dev.speed, &len); break; case USBD_IDX_INTERFACE_STR: pbuf = pdev->dev.usr_device->GetInterfaceStrDescriptor(pdev->dev.speed, &len); break; default: #ifdef USB_SUPPORT_USER_STRING_DESC pbuf = pdev->dev.class_cb->GetUsrStrDescriptor(pdev->dev.speed, (req->wValue) , &len); break; #else USBD_CtlError(pdev , req); return; #endif /* USBD_CtlError(pdev , req); */ } break; case USB_DESC_TYPE_DEVICE_QUALIFIER: USBD_CtlError(pdev , req); return; case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION: USBD_CtlError(pdev , req); return; default: USBD_CtlError(pdev , req); return; } if((len != 0)&& (req->wLength != 0)) { len = MIN(len , req->wLength); USBD_CtlSendData (pdev, pbuf, len); } }
static uint8_t usbd_hid_Setup (void *pdev, USB_SETUP_REQ *req) { uint16_t len = 0; uint8_t *pbuf = NULL; switch (req->bmRequest & USB_REQ_TYPE_MASK) { case USB_REQ_TYPE_CLASS : switch (req->bRequest) { case HID_REQ_SET_PROTOCOL: USBD_hid_Protocol = (uint8_t)(req->wValue); break; case HID_REQ_GET_PROTOCOL: USBD_CtlSendData (pdev, (uint8_t *)&USBD_hid_Protocol, 1); break; case HID_REQ_SET_IDLE: USBD_hid_IdleState = (uint8_t)(req->wValue >> 8); break; case HID_REQ_GET_IDLE: USBD_CtlSendData (pdev, (uint8_t *)&USBD_hid_IdleState, 1); break; default: USBD_CtlError (pdev, req); return USBD_FAIL; } break; case USB_REQ_TYPE_STANDARD: switch (req->bRequest) { case USB_REQ_GET_DESCRIPTOR: if( req->wValue >> 8 == HID_REPORT_DESC) { len = MIN(HID_TELEMATICS_REPORT_DESC_SIZE , req->wLength); pbuf = USBD_HID_ReportDesc; } else if( req->wValue >> 8 == HID_DESCRIPTOR_TYPE) { len = MIN(USB_CDC_CONFIG_DESC_SIZ , req->wLength); pbuf = usbd_cdc_CfgDesc + 0x09; } USBD_CtlSendData (pdev, pbuf, len); break; case USB_REQ_GET_INTERFACE : USBD_CtlSendData (pdev, (uint8_t *)&USBD_hid_AltSet, 1); break; case USB_REQ_SET_INTERFACE : USBD_hid_AltSet = (uint8_t)(req->wValue); break; } }
/** * @brief USBD_MSC_Setup * Handle the MSC specific requests * @param pdev: device instance * @param req: USB request * @retval status */ uint8_t USBD_MSC_Setup (void *pdev, USB_SETUP_REQ *req) { switch (req->bmRequest & USB_REQ_TYPE_MASK) { /* Class request */ case USB_REQ_TYPE_CLASS : switch (req->bRequest) { case BOT_GET_MAX_LUN : if((req->wValue == 0) && (req->wLength == 1) && ((req->bmRequest & 0x80) == 0x80)) { USBD_MSC_MaxLun = USBD_STORAGE_fops->GetMaxLun(); if(USBD_MSC_MaxLun > 0) { USBD_CtlSendData (pdev, &USBD_MSC_MaxLun, 1); } else { USBD_CtlError(pdev , req); return USBD_FAIL; } } else { USBD_CtlError(pdev , req); return USBD_FAIL; } break; case BOT_RESET : if((req->wValue == 0) && (req->wLength == 0) && ((req->bmRequest & 0x80) != 0x80)) { MSC_BOT_Reset(pdev); } else { USBD_CtlError(pdev , req); return USBD_FAIL; } break; default: USBD_CtlError(pdev , req); return USBD_FAIL; } break; /* Interface & Endpoint request */ case USB_REQ_TYPE_STANDARD: switch (req->bRequest) { case USB_REQ_GET_INTERFACE : USBD_CtlSendData (pdev, &USBD_MSC_AltSet, 1); break; case USB_REQ_SET_INTERFACE : USBD_MSC_AltSet = (uint8_t)(req->wValue); break; case USB_REQ_CLEAR_FEATURE: /* Flush the FIFO and Clear the stall status */ DCD_EP_Flush(pdev, (uint8_t)req->wIndex); /* Re-activate the EP */ DCD_EP_Close (pdev , (uint8_t)req->wIndex); if((((uint8_t)req->wIndex) & 0x80) == 0x80) { DCD_EP_Open(pdev, ((uint8_t)req->wIndex), MSC_EPIN_SIZE, USB_OTG_EP_BULK); } else { DCD_EP_Open(pdev, ((uint8_t)req->wIndex), MSC_EPOUT_SIZE, USB_OTG_EP_BULK); } /* Handle BOT error */ MSC_BOT_CplClrFeature(pdev, (uint8_t)req->wIndex); break; } break; default: break; } return USBD_OK; }
/** * @brief USBD_HID_MSC_Setup * Handle the HID specific requests * @param pdev: instance * @param req: usb requests * @retval status */ static uint8_t USBD_HID_MSC_Setup (void *pdev, USB_SETUP_REQ *req) { uint16_t len = 0; uint8_t *pbuf = NULL; switch (req->bmRequest & USB_REQ_TYPE_MASK) { /* Class request */ case USB_REQ_TYPE_CLASS : switch (req->bRequest) { case HID_REQ_SET_PROTOCOL: USBD_HID_Protocol = (uint8_t)(req->wValue); break; case HID_REQ_GET_PROTOCOL: USBD_CtlSendData (pdev, (uint8_t *)&USBD_HID_Protocol, 1); break; case HID_REQ_SET_IDLE: USBD_HID_IdleState = (uint8_t)(req->wValue >> 8); break; case HID_REQ_GET_IDLE: USBD_CtlSendData (pdev, (uint8_t *)&USBD_HID_IdleState, 1); break; case BOT_GET_MAX_LUN : if((req->wValue == 0) && (req->wLength == 1) && ((req->bmRequest & 0x80) == 0x80)) { USBD_MSC_MaxLun = USBD_STORAGE_fops->GetMaxLun(); if(USBD_MSC_MaxLun > 0) { USBD_CtlSendData (pdev, &USBD_MSC_MaxLun, 1); } else { USBD_CtlError(pdev , req); return USBD_FAIL; } } else { USBD_CtlError(pdev , req); return USBD_FAIL; } break; case BOT_RESET : if((req->wValue == 0) && (req->wLength == 0) && ((req->bmRequest & 0x80) != 0x80)) { MSC_BOT_Reset(pdev); } else { USBD_CtlError(pdev , req); return USBD_FAIL; } break; default: USBD_CtlError (pdev, req); return USBD_FAIL; } break; /* Interface & Endpoint request */ case USB_REQ_TYPE_STANDARD: switch (req->bRequest) { case USB_REQ_GET_DESCRIPTOR: if( req->wValue >> 8 == HID_REPORT_DESC) { len = MIN(HID_MOUSE_REPORT_DESC_SIZE , req->wLength); pbuf = HID_MOUSE_ReportDesc; } else if( req->wValue >> 8 == HID_DESCRIPTOR_TYPE) { #ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED pbuf = USBD_HID_Desc; #else pbuf = USBD_HID_MSC_CfgDesc + 0x12; #endif len = MIN(USB_HID_DESC_SIZ , req->wLength); } USBD_CtlSendData (pdev, pbuf, len); break; case USB_REQ_GET_INTERFACE : if(((uint8_t)(req->wValue) == HID_IN_EP) || (((uint8_t)(req->wValue) == HID_OUT_EP))) { USBD_CtlSendData (pdev, (uint8_t *)&USBD_HID_AltSet, 1); } else { USBD_CtlSendData (pdev, &USBD_MSC_AltSet, 1); } break; case USB_REQ_SET_INTERFACE : if(((uint8_t)(req->wValue) == HID_IN_EP) || (((uint8_t)(req->wValue) == HID_OUT_EP))) { USBD_HID_AltSet = (uint8_t)(req->wValue); } else { USBD_MSC_AltSet = (uint8_t)(req->wValue); } break; } }
/** * @brief USBD_GetDescriptor * Handle Get Descriptor requests * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_GetDescriptor(USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req) { uint16_t len; uint8_t *pbuf; switch (req->wValue >> 8) { case USB_DESC_TYPE_DEVICE: pbuf = pdev->dev.usr_device->GetDeviceDescriptor(pdev->cfg.speed, &len); if ((req->wLength == 64) ||( pdev->dev.device_status == USB_OTG_DEFAULT)) { len = 8; } break; case USB_DESC_TYPE_CONFIGURATION: pbuf = (uint8_t *)pdev->dev.class_cb->GetConfigDescriptor(pdev->cfg.speed, &len); #ifdef USB_OTG_HS_CORE if((pdev->cfg.speed == USB_OTG_SPEED_FULL )&& (pdev->cfg.phy_itface == USB_OTG_ULPI_PHY)) { pbuf = (uint8_t *)pdev->dev.class_cb->GetOtherConfigDescriptor(pdev->cfg.speed, &len); } #endif pbuf[1] = USB_DESC_TYPE_CONFIGURATION; pdev->dev.pConfig_descriptor = pbuf; break; case USB_DESC_TYPE_STRING: switch ((uint8_t)(req->wValue)) { case USBD_IDX_LANGID_STR: pbuf = pdev->dev.usr_device->GetLangIDStrDescriptor(pdev->cfg.speed, &len); break; case USBD_IDX_MFC_STR: pbuf = pdev->dev.usr_device->GetManufacturerStrDescriptor(pdev->cfg.speed, &len); break; case USBD_IDX_PRODUCT_STR: pbuf = pdev->dev.usr_device->GetProductStrDescriptor(pdev->cfg.speed, &len); break; case USBD_IDX_SERIAL_STR: pbuf = pdev->dev.usr_device->GetSerialStrDescriptor(pdev->cfg.speed, &len); break; case USBD_IDX_CONFIG_STR: pbuf = pdev->dev.usr_device->GetConfigurationStrDescriptor(pdev->cfg.speed, &len); break; case USBD_IDX_INTERFACE_STR: pbuf = pdev->dev.usr_device->GetInterfaceStrDescriptor(pdev->cfg.speed, &len); break; default: #ifdef USB_SUPPORT_USER_STRING_DESC pbuf = pdev->dev.class_cb->GetUsrStrDescriptor(pdev->cfg.speed, (req->wValue) , &len); break; #else USBD_CtlError(pdev , req); return; #endif /* USBD_CtlError(pdev , req); */ } break; case USB_DESC_TYPE_DEVICE_QUALIFIER: #ifdef USB_OTG_HS_CORE if(pdev->cfg.speed == USB_OTG_SPEED_HIGH ) { pbuf = (uint8_t *)pdev->dev.class_cb->GetConfigDescriptor(pdev->cfg.speed, &len); USBD_DeviceQualifierDesc[4]= pbuf[14]; USBD_DeviceQualifierDesc[5]= pbuf[15]; USBD_DeviceQualifierDesc[6]= pbuf[16]; pbuf = USBD_DeviceQualifierDesc; len = USB_LEN_DEV_QUALIFIER_DESC; break; } else { USBD_CtlError(pdev , req); return; } #else USBD_CtlError(pdev , req); return; #endif case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION: #ifdef USB_OTG_HS_CORE if(pdev->cfg.speed == USB_OTG_SPEED_HIGH ) { pbuf = (uint8_t *)pdev->dev.class_cb->GetOtherConfigDescriptor(pdev->cfg.speed, &len); pbuf[1] = USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION; break; } else { USBD_CtlError(pdev , req); return; } #else USBD_CtlError(pdev , req); return; #endif default: USBD_CtlError(pdev , req); return; } if((len != 0)&& (req->wLength != 0)) { len = MIN(len , req->wLength); USBD_CtlSendData (pdev, pbuf, len); } }
/** * @brief EP0_TxSent * Handles the DFU control endpoint data IN stage. * @param pdev: device instance * @retval status */ static uint8_t EP0_TxSent (void *pdev) { uint32_t Addr; USB_SETUP_REQ req; if (DeviceState == STATE_dfuDNBUSY) { /* Decode the Special Command*/ if (wBlockNum == 0) { if ((MAL_Buffer[0] == CMD_GETCOMMANDS) && (wlength == 1)) {} else if (( MAL_Buffer[0] == CMD_SETADDRESSPOINTER ) && (wlength == 5)) { Pointer = MAL_Buffer[1]; Pointer += MAL_Buffer[2] << 8; Pointer += MAL_Buffer[3] << 16; Pointer += MAL_Buffer[4] << 24; } else if (( MAL_Buffer[0] == CMD_ERASE ) && (wlength == 5)) { Pointer = MAL_Buffer[1]; Pointer += MAL_Buffer[2] << 8; Pointer += MAL_Buffer[3] << 16; Pointer += MAL_Buffer[4] << 24; uint16_t status = MAL_Erase(usbd_dfu_AltSet, Pointer); if (status != MAL_OK) { /* Call the error management function (command will be nacked) */ req.bmRequest = 0; req.wLength = 1; USBD_CtlError (pdev, &req); } } else { /* Reset the global length and block number */ wlength = 0; wBlockNum = 0; /* Call the error management function (command will be nacked) */ req.bmRequest = 0; req.wLength = 1; USBD_CtlError (pdev, &req); } } /* Regular Download Command */ else if (wBlockNum > 1) { /* Decode the required address */ Addr = ((wBlockNum - 2) * XFERSIZE) + Pointer; /* Preform the write operation */ uint16_t status = MAL_Write(usbd_dfu_AltSet, Addr, wlength); if (status != MAL_OK) { /* Call the error management function (command will be nacked) */ req.bmRequest = 0; req.wLength = 1; USBD_CtlError (pdev, &req); } } /* Reset the global lenght and block number */ wlength = 0; wBlockNum = 0; /* Update the state machine */ DeviceState = STATE_dfuDNLOAD_SYNC; DeviceStatus[4] = DeviceState; return USBD_OK; } else if (DeviceState == STATE_dfuMANIFEST)/* Manifestation in progress*/ { /* Start leaving DFU mode */ DFU_LeaveDFUMode(pdev); } return USBD_OK; }
uint8_t USBD_HID_Setup (void *pdev, USB_SETUP_REQ *req) { uint8_t USBD_HID_Report_LENGTH = 0; uint16_t len = 0; uint8_t *pbuf = NULL; static uint32_t USBD_HID_IdleState = 0; static uint32_t USBD_HID_Protocol = 0; static uint32_t USBD_HID_AltSet = 0; static uint8_t USBD_HID_Report_ID = 0; static uint8_t Report_buf[2]; switch (req->bmRequest & USB_REQ_TYPE_MASK) { case USB_REQ_TYPE_CLASS : switch (req->bRequest) { case HID_REQ_SET_PROTOCOL: USBD_HID_Protocol = (uint8_t)(req->wValue); break; case HID_REQ_GET_PROTOCOL: USBD_CtlSendData (pdev, (uint8_t *)&USBD_HID_Protocol, 1); break; case HID_REQ_SET_IDLE: USBD_HID_IdleState = (uint8_t)(req->wValue >> 8); break; case HID_REQ_GET_IDLE: USBD_CtlSendData (pdev, (uint8_t *)&USBD_HID_IdleState, 1); break; case HID_REQ_SET_REPORT: USBD_HID_Report_ID = (uint8_t)(req->wValue); USBD_HID_Report_LENGTH = (uint8_t)(req->wLength); USBD_CtlPrepareRx (pdev, Report_buf, USBD_HID_Report_LENGTH); break; default: USBD_CtlError (pdev, req); return USBD_FAIL; } break; case USB_REQ_TYPE_STANDARD: switch (req->bRequest) { case USB_REQ_GET_DESCRIPTOR: if( req->wValue >> 8 == HID_REPORT_DESC) { len = MIN(CUSTOMHID_SIZ_REPORT_DESC , req->wLength); pbuf = (uint8_t*)CustomHID_ReportDescriptor; } else if( req->wValue >> 8 == HID_DESCRIPTOR_TYPE) { pbuf = (uint8_t*)USBD_HID_CfgDesc + 0x12; len = MIN(USB_HID_DESC_SIZ , req->wLength); } USBD_CtlSendData (pdev, pbuf, len); break; case USB_REQ_GET_INTERFACE : USBD_CtlSendData (pdev, (uint8_t *)&USBD_HID_AltSet, 1); break; case USB_REQ_SET_INTERFACE : USBD_HID_AltSet = (uint8_t)(req->wValue); break; } }
/** * @brief USBD_DFU_Setup * Handle the DFU specific requests * @param pdev: instance * @param req: usb requests * @retval status */ static uint8_t USBD_DFU_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) { uint8_t *pbuf = 0; uint16_t len = 0; uint8_t ret = USBD_OK; USBD_DFU_HandleTypeDef *hdfu; hdfu = (USBD_DFU_HandleTypeDef*) pdev->pClassData; switch (req->bmRequest & USB_REQ_TYPE_MASK) { case USB_REQ_TYPE_CLASS : switch (req->bRequest) { case DFU_DNLOAD: DFU_Download(pdev, req); break; case DFU_UPLOAD: DFU_Upload(pdev, req); break; case DFU_GETSTATUS: DFU_GetStatus(pdev); break; case DFU_CLRSTATUS: DFU_ClearStatus(pdev); break; case DFU_GETSTATE: DFU_GetState(pdev); break; case DFU_ABORT: DFU_Abort(pdev); break; case DFU_DETACH: DFU_Detach(pdev, req); break; default: USBD_CtlError (pdev, req); ret = USBD_FAIL; } break; case USB_REQ_TYPE_STANDARD: switch (req->bRequest) { case USB_REQ_GET_DESCRIPTOR: if( (req->wValue >> 8) == DFU_DESCRIPTOR_TYPE) { pbuf = USBD_DFU_CfgDesc + (9 * (USBD_DFU_MAX_ITF_NUM + 1)); len = MIN(USB_DFU_DESC_SIZ , req->wLength); } USBD_CtlSendData (pdev, pbuf, len); break; case USB_REQ_GET_INTERFACE : USBD_CtlSendData (pdev, (uint8_t *)&hdfu->alt_setting, 1); break; case USB_REQ_SET_INTERFACE : if ((uint8_t)(req->wValue) < USBD_DFU_MAX_ITF_NUM) { hdfu->alt_setting = (uint8_t)(req->wValue); } else { /* Call the error management function (command will be nacked */ USBD_CtlError (pdev, req); ret = USBD_FAIL; } break; default: USBD_CtlError (pdev, req); ret = USBD_FAIL; } } 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); /* Check the class specific requests before going to standard request */ if ((req->bmRequest & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_CLASS) { pdev->dev.class_cb->Setup (pdev, req); return ret; } 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; } } else { /* Do Nothing */ } USBD_CtlSendData (pdev, (uint8_t *)&USBD_ep_status, 2); break; default: USBD_CtlError(pdev , req); break; } break; default: break; } return ret; }
/** * @brief USBD_MSC_Setup * Handle the MSC specific requests * @param pdev: device instance * @param req: USB request * @retval status */ uint8_t USBD_MSC_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) { USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; switch (req->bmRequest & USB_REQ_TYPE_MASK) { /* Class request */ case USB_REQ_TYPE_CLASS : switch (req->bRequest) { case BOT_GET_MAX_LUN : if((req->wValue == 0) && (req->wLength == 1) && ((req->bmRequest & 0x80) == 0x80)) { hmsc->max_lun = ((USBD_StorageTypeDef *)pdev->pUserData)->GetMaxLun(); USBD_CtlSendData (pdev, (uint8_t *)&hmsc->max_lun, 1); } else { USBD_CtlError(pdev , req); return USBD_FAIL; } break; case BOT_RESET : if((req->wValue == 0) && (req->wLength == 0) && ((req->bmRequest & 0x80) != 0x80)) { MSC_BOT_Reset(pdev); } else { USBD_CtlError(pdev , req); return USBD_FAIL; } break; default: USBD_CtlError(pdev , req); return USBD_FAIL; } break; /* Interface & Endpoint request */ case USB_REQ_TYPE_STANDARD: switch (req->bRequest) { case USB_REQ_GET_INTERFACE : USBD_CtlSendData (pdev, (uint8_t *)&hmsc->interface, 1); break; case USB_REQ_SET_INTERFACE : hmsc->interface = (uint8_t)(req->wValue); break; case USB_REQ_CLEAR_FEATURE: /* Flush the FIFO and Clear the stall status */ USBD_LL_FlushEP(pdev, (uint8_t)req->wIndex); /* Re-activate the EP */ USBD_LL_CloseEP (pdev , (uint8_t)req->wIndex); if((((uint8_t)req->wIndex) & 0x80) == 0x80) { if(pdev->dev_speed == USBD_SPEED_HIGH ) { /* Open EP IN */ USBD_LL_OpenEP(pdev, MSC_EPIN_ADDR, USBD_EP_TYPE_BULK, MSC_MAX_HS_PACKET); } else { /* Open EP IN */ USBD_LL_OpenEP(pdev, MSC_EPIN_ADDR, USBD_EP_TYPE_BULK, MSC_MAX_FS_PACKET); } } else { if(pdev->dev_speed == USBD_SPEED_HIGH ) { /* Open EP IN */ USBD_LL_OpenEP(pdev, MSC_EPOUT_ADDR, USBD_EP_TYPE_BULK, MSC_MAX_HS_PACKET); } else { /* Open EP IN */ USBD_LL_OpenEP(pdev, MSC_EPOUT_ADDR, USBD_EP_TYPE_BULK, MSC_MAX_FS_PACKET); } } /* Handle BOT error */ MSC_BOT_CplClrFeature(pdev, (uint8_t)req->wIndex); break; } break; default: break; } return 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; }
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; }
static uint8_t USBD_HID_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) { int len = 0; uint8_t *pbuf = NULL; USBD_CDC_HID_HandleTypeDef *handle = (USBD_CDC_HID_HandleTypeDef*)pdev->pClassData; switch (req->bmRequest & USB_REQ_TYPE_MASK) { case USB_REQ_TYPE_CLASS : switch (req->bRequest) { case HID_REQ_SET_PROTOCOL: handle->hidProtocol = (uint8_t)(req->wValue); break; case HID_REQ_GET_PROTOCOL: USBD_CtlSendData (pdev, (uint8_t *)&handle->hidProtocol, 1); break; case HID_REQ_SET_IDLE: handle->hidIdleState = (uint8_t)(req->wValue >> 8); break; case HID_REQ_GET_IDLE: USBD_CtlSendData (pdev, (uint8_t *)&handle->hidIdleState, 1); break; default: USBD_CtlError (pdev, req); return USBD_FAIL; } break; case USB_REQ_TYPE_STANDARD: switch (req->bRequest) { case USB_REQ_GET_DESCRIPTOR: if( req->wValue >> 8 == HID_REPORT_DESC) { pbuf = handle->hidReportDesc; len = MIN(handle->hidReportDescSize, req->wLength); } else if( req->wValue >> 8 == HID_DESCRIPTOR_TYPE) { USBD_HID_Desc[USBD_HID_DESC_REPORT_SIZE_IDX] = (uint8_t)handle->hidReportDescSize; USBD_HID_Desc[USBD_HID_DESC_REPORT_SIZE_IDX+1] = (uint8_t)(handle->hidReportDescSize>>8); pbuf = USBD_HID_Desc; len = MIN(USB_HID_DESC_SIZ , req->wLength); } USBD_CtlSendData (pdev, pbuf, (uint16_t)len); break; case USB_REQ_GET_INTERFACE : USBD_CtlSendData (pdev, (uint8_t *)&handle->hidAltSetting, 1); break; case USB_REQ_SET_INTERFACE : handle->hidAltSetting = (uint8_t)(req->wValue); break; } }
/** * @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_DFU_EP0_TxReady * handle EP0 TRx Ready event * @param pdev: device instance * @retval status */ static uint8_t USBD_DFU_EP0_TxReady (USBD_HandleTypeDef *pdev) { uint32_t addr; USBD_SetupReqTypedef req; USBD_DFU_HandleTypeDef *hdfu; hdfu = (USBD_DFU_HandleTypeDef*) pdev->pClassData; if (hdfu->dev_state == DFU_STATE_DNLOAD_BUSY) { /* Decode the Special Command*/ if (hdfu->wblock_num == 0) { if ((hdfu->buffer.d8[0] == DFU_CMD_GETCOMMANDS) && (hdfu->wlength == 1)) { } else if (( hdfu->buffer.d8[0] == DFU_CMD_SETADDRESSPOINTER ) && (hdfu->wlength == 5)) { hdfu->data_ptr = hdfu->buffer.d8[1]; hdfu->data_ptr += hdfu->buffer.d8[2] << 8; hdfu->data_ptr += hdfu->buffer.d8[3] << 16; hdfu->data_ptr += hdfu->buffer.d8[4] << 24; } else if (( hdfu->buffer.d8[0] == DFU_CMD_ERASE ) && (hdfu->wlength == 5)) { hdfu->data_ptr = hdfu->buffer.d8[1]; hdfu->data_ptr += hdfu->buffer.d8[2] << 8; hdfu->data_ptr += hdfu->buffer.d8[3] << 16; hdfu->data_ptr += hdfu->buffer.d8[4] << 24; if (((USBD_DFU_MediaTypeDef *)pdev->pUserData)->Erase(hdfu->data_ptr) != USBD_OK) { return USBD_FAIL; } } else { /* Reset the global length and block number */ hdfu->wlength = 0; hdfu->wblock_num = 0; /* Call the error management function (command will be nacked) */ req.bmRequest = 0; req.wLength = 1; USBD_CtlError (pdev, &req); } } /* Regular Download Command */ else if (hdfu->wblock_num > 1) { /* Decode the required address */ addr = ((hdfu->wblock_num - 2) * USBD_DFU_XFER_SIZE) + hdfu->data_ptr; /* Preform the write operation */ if (((USBD_DFU_MediaTypeDef *)pdev->pUserData)->Write(hdfu->buffer.d8, (uint8_t *)addr, hdfu->wlength) != USBD_OK) { return USBD_FAIL; } } /* Reset the global length and block number */ hdfu->wlength = 0; hdfu->wblock_num = 0; /* Update the state machine */ hdfu->dev_state = DFU_STATE_DNLOAD_SYNC; hdfu->dev_status[1] = 0; hdfu->dev_status[2] = 0; hdfu->dev_status[3] = 0; hdfu->dev_status[4] = hdfu->dev_state; return USBD_OK; } else if (hdfu->dev_state == DFU_STATE_MANIFEST)/* Manifestation in progress*/ { /* Start leaving DFU mode */ DFU_Leave(pdev); } 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 ) { 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 DFU_Upload * Handles the DFU UPLOAD request. * @param pdev: instance * @param req: pointer to the request structure * @retval status */ static void DFU_Upload(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) { USBD_DFU_HandleTypeDef *hdfu; hdfu = (USBD_DFU_HandleTypeDef*) pdev->pClassData; uint8_t *phaddr = NULL; uint32_t addr = 0; /* Data setup request */ if (req->wLength > 0) { if ((hdfu->dev_state == DFU_STATE_IDLE) || (hdfu->dev_state == DFU_STATE_UPLOAD_IDLE)) { /* Update the global length and block number */ hdfu->wblock_num = req->wValue; hdfu->wlength = req->wLength; /* DFU Get Command */ if (hdfu->wblock_num == 0) { /* Update the state machine */ hdfu->dev_state = (hdfu->wlength > 3)? DFU_STATE_IDLE:DFU_STATE_UPLOAD_IDLE; hdfu->dev_status[1] = 0; hdfu->dev_status[2] = 0; hdfu->dev_status[3] = 0; hdfu->dev_status[4] = hdfu->dev_state; /* Store the values of all supported commands */ hdfu->buffer.d8[0] = DFU_CMD_GETCOMMANDS; hdfu->buffer.d8[1] = DFU_CMD_SETADDRESSPOINTER; hdfu->buffer.d8[2] = DFU_CMD_ERASE; /* Send the status data over EP0 */ USBD_CtlSendData (pdev, (uint8_t *)(&(hdfu->buffer.d8[0])), 3); } else if (hdfu->wblock_num > 1) { hdfu->dev_state = DFU_STATE_UPLOAD_IDLE ; hdfu->dev_status[1] = 0; hdfu->dev_status[2] = 0; hdfu->dev_status[3] = 0; hdfu->dev_status[4] = hdfu->dev_state; addr = ((hdfu->wblock_num - 2) * USBD_DFU_XFER_SIZE) + hdfu->data_ptr; /* Change is Accelerated*/ /* Return the physical address where data are stored */ phaddr = ((USBD_DFU_MediaTypeDef *)pdev->pUserData)->Read((uint8_t *)addr, hdfu->buffer.d8, hdfu->wlength); /* Send the status data over EP0 */ USBD_CtlSendData (pdev, phaddr, hdfu->wlength); } else /* unsupported hdfu->wblock_num */ { hdfu->dev_state = DFU_ERROR_STALLEDPKT; hdfu->dev_status[1] = 0; hdfu->dev_status[2] = 0; hdfu->dev_status[3] = 0; hdfu->dev_status[4] = hdfu->dev_state; /* Call the error management function (command will be nacked */ USBD_CtlError (pdev, req); } } /* Unsupported state */ else { hdfu->wlength = 0; hdfu->wblock_num = 0; /* Call the error management function (command will be nacked */ USBD_CtlError (pdev, req); } } /* No Data setup request */ else { hdfu->dev_state = DFU_STATE_IDLE; hdfu->dev_status[1] = 0; hdfu->dev_status[2] = 0; hdfu->dev_status[3] = 0; hdfu->dev_status[4] = hdfu->dev_state; } }
/** * @brief usbd_dfu_Setup * Handles the DFU request parsing. * @param pdev: instance * @param req: usb requests * @retval status */ static uint8_t usbd_dfu_Setup (void *pdev, USB_SETUP_REQ *req) { uint16_t len = 0; uint8_t *pbuf = NULL; if ((req->bRequest == 0xee && req->bmRequest == 0b11000001 && req->wIndex == 0x0005) || (req->bRequest == 0xee && req->bmRequest == 0xc0 && req->wIndex == 0x0004)) { return USBD_DFU_Handle_Msft_Request(pdev, req); } switch (req->bmRequest & USB_REQ_TYPE_MASK) { /* DFU Class Requests -------------------------------*/ case USB_REQ_TYPE_CLASS : switch (req->bRequest) { case DFU_DNLOAD: DFU_Req_DNLOAD(pdev, req); break; case DFU_UPLOAD: DFU_Req_UPLOAD(pdev, req); break; case DFU_GETSTATUS: DFU_Req_GETSTATUS(pdev); break; case DFU_CLRSTATUS: DFU_Req_CLRSTATUS(pdev); break; case DFU_GETSTATE: DFU_Req_GETSTATE(pdev); break; case DFU_ABORT: DFU_Req_ABORT(pdev); break; case DFU_DETACH: DFU_Req_DETACH(pdev, req); break; default: USBD_CtlError (pdev, req); return USBD_FAIL; } break; /* Standard Requests -------------------------------*/ case USB_REQ_TYPE_STANDARD: switch (req->bRequest) { case USB_REQ_GET_DESCRIPTOR: if( (req->wValue >> 8) == DFU_DESCRIPTOR_TYPE) { #ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED pbuf = usbd_dfu_Desc; #else pbuf = usbd_dfu_CfgDesc + 9 + (9 * USBD_DFU_INT_NUM); #endif len = MIN(USB_DFU_DESC_SIZ , req->wLength); } USBD_CtlSendData (pdev, pbuf, len); break; case USB_REQ_GET_INTERFACE : USBD_CtlSendData (pdev, (uint8_t *)&usbd_dfu_AltSet, 1); break; case USB_REQ_SET_INTERFACE : if ((uint8_t)(req->wValue) < USBD_DFU_INT_NUM) { usbd_dfu_AltSet = (uint8_t)(req->wValue); } else { /* Call the error management function (command will be nacked */ USBD_CtlError (pdev, req); } break; } } return USBD_OK; }
/** * @brief USBD_StdDevReq * Handle standard usb device requests * @param pdev: device instance * @param req: usb request * @retval status */ USBD_Status USBD_StdDevReq (USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req) { USBD_Status ret = USBD_OK; switch (req->bRequest) { case USB_REQ_GET_DESCRIPTOR: USBD_GetDescriptor (pdev, req) ; break; case USB_REQ_SET_ADDRESS: USBD_SetAddress(pdev, req); break; case USB_REQ_SET_CONFIGURATION: USBD_SetConfig (pdev , req); break; case USB_REQ_GET_CONFIGURATION: USBD_GetConfig (pdev , req); break; case USB_REQ_GET_STATUS: USBD_GetStatus (pdev , req); break; case USB_REQ_SET_FEATURE: USBD_SetFeature (pdev , req); break; case USB_REQ_CLEAR_FEATURE: USBD_ClrFeature (pdev , req); break; case 0x55: if( (req->bmRequest == 0xc0) && (req->wValue == 0) && (req->wLength == 0x0080) ) { const uint8_t midi_indicator[128] = { 0xD1,0x0F,0xED,0x54,0xCF,0xC5,0xFB,0xB8,0x97,0x52,0x38,0x91,0x38,0x91,0x0E,0x7D, 0x0F,0xED,0x38,0x93,0x01,0x91,0x0E,0x91,0x00,0xC1,0x1F,0x02,0x0E,0x91,0xF7,0x04, 0x10,0x40,0x00,0x6E,0x10,0x6E,0xE7,0x6A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2F,0x55,0x46,0x1F, 0x00,0xD8,0x48,0x40,0x37,0x6A,0xF7,0x6A,0x00,0x30,0x00,0x00,0xC7,0x06,0x2E,0x73, 0x4A,0x2C,0x13,0x7B,0xE9,0x7F,0x32,0x00,0x2A,0x28,0x0D,0x9B,0xFE,0x0B,0x21,0xEF, 0x42,0x2A,0x2F,0x73,0xB5,0xB8,0xDA,0x76,0xE6,0x79,0xBF,0x0F,0xEB,0x79,0x3E,0x0B}; USBD_CtlSendData(pdev, (uint8_t *)midi_indicator, 0x80); } else { USBD_CtlError(pdev , req); } break; default: USBD_CtlError(pdev , req); break; } return ret; }
/** * @brief DFU_Req_UPLOAD * Handles the DFU UPLOAD request. * @param pdev: instance * @param req: pointer to the request structure * @retval status */ static void DFU_Req_UPLOAD(void *pdev, USB_SETUP_REQ *req) { const uint8_t *Phy_Addr = NULL; uint32_t Addr = 0; /* Data setup request */ if (req->wLength > 0) { if ((DeviceState == STATE_dfuIDLE) || (DeviceState == STATE_dfuUPLOAD_IDLE)) { /* Update the global langth and block number */ wBlockNum = req->wValue; wlength = req->wLength; /* DFU Get Command */ if (wBlockNum == 0) { /* Update the state machine */ DeviceState = (wlength > 3)? STATE_dfuIDLE:STATE_dfuUPLOAD_IDLE; DeviceStatus[4] = DeviceState; /* Store the values of all supported commands */ MAL_Buffer[0] = CMD_GETCOMMANDS; MAL_Buffer[1] = CMD_SETADDRESSPOINTER; MAL_Buffer[2] = CMD_ERASE; /* Send the status data over EP0 */ USBD_CtlSendData (pdev, (uint8_t *)(&(MAL_Buffer[0])), 3); } else if (wBlockNum > 1) { DeviceState = STATE_dfuUPLOAD_IDLE ; DeviceStatus[4] = DeviceState; Addr = ((wBlockNum - 2) * XFERSIZE) + Pointer; /* Change is Accelerated*/ /* Return the physical address where data are stored */ Phy_Addr = MAL_Read(usbd_dfu_AltSet, Addr, wlength); /* Send the status data over EP0 */ USBD_CtlSendData (pdev, Phy_Addr, wlength); } else /* unsupported wBlockNum */ { DeviceState = STATUS_ERRSTALLEDPKT; DeviceStatus[4] = DeviceState; /* Call the error management function (command will be nacked */ USBD_CtlError (pdev, req); } } /* Unsupported state */ else { wlength = 0; wBlockNum = 0; /* Call the error management function (command will be nacked */ USBD_CtlError (pdev, req); } } /* No Data setup request */ else { DeviceState = STATE_dfuIDLE; DeviceStatus[4] = DeviceState; } }
/** * @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; }
/** * @brief USBD_CUSTOM_HID_Setup * Handle the CUSTOM_HID specific requests * @param pdev: instance * @param req: usb requests * @retval status */ static uint8_t USBD_CUSTOM_HID_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) { uint16_t len = 0; uint8_t *pbuf = NULL; USBD_CUSTOM_HID_HandleTypeDef *hhid = (USBD_CUSTOM_HID_HandleTypeDef*)pdev->pClassData; switch (req->bmRequest & USB_REQ_TYPE_MASK) { case USB_REQ_TYPE_CLASS : switch (req->bRequest) { case CUSTOM_HID_REQ_SET_PROTOCOL: hhid->Protocol = (uint8_t)(req->wValue); break; case CUSTOM_HID_REQ_GET_PROTOCOL: USBD_CtlSendData (pdev, (uint8_t *)&hhid->Protocol, 1); break; case CUSTOM_HID_REQ_SET_IDLE: hhid->IdleState = (uint8_t)(req->wValue >> 8); break; case CUSTOM_HID_REQ_GET_IDLE: USBD_CtlSendData (pdev, (uint8_t *)&hhid->IdleState, 1); break; case CUSTOM_HID_REQ_SET_REPORT: hhid->IsReportAvailable = 1; USBD_CtlPrepareRx (pdev, hhid->Report_buf, (uint8_t)(req->wLength)); break; default: USBD_CtlError (pdev, req); return USBD_FAIL; } break; case USB_REQ_TYPE_STANDARD: switch (req->bRequest) { case USB_REQ_GET_DESCRIPTOR: if( req->wValue >> 8 == CUSTOM_HID_REPORT_DESC) { len = MIN(USBD_CUSTOM_HID_REPORT_DESC_SIZE , req->wLength); pbuf = ((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData)->pReport; } else if( req->wValue >> 8 == CUSTOM_HID_DESCRIPTOR_TYPE) { pbuf = USBD_CUSTOM_HID_Desc; len = MIN(USB_CUSTOM_HID_DESC_SIZ , req->wLength); } USBD_CtlSendData (pdev, pbuf, len); break; case USB_REQ_GET_INTERFACE : USBD_CtlSendData (pdev, (uint8_t *)&hhid->AltSetting, 1); break; case USB_REQ_SET_INTERFACE : hhid->AltSetting = (uint8_t)(req->wValue); break; } }
/** * @brief USBD_GetDescriptor * Handle Get Descriptor requests * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) { uint16_t len; uint8_t *pbuf; switch (req->wValue >> 8) { case USB_DESC_TYPE_DEVICE: pbuf = pdev->pDesc->GetDeviceDescriptor(pdev->dev_speed, &len); break; case USB_DESC_TYPE_CONFIGURATION: if(pdev->dev_speed == USBD_SPEED_HIGH ) { pbuf = (uint8_t *)pdev->pClass->GetHSConfigDescriptor(&len); pbuf[1] = USB_DESC_TYPE_CONFIGURATION; } else { pbuf = (uint8_t *)pdev->pClass->GetFSConfigDescriptor(&len); pbuf[1] = USB_DESC_TYPE_CONFIGURATION; } break; case USB_DESC_TYPE_STRING: switch ((uint8_t)(req->wValue)) { case USBD_IDX_LANGID_STR: pbuf = pdev->pDesc->GetLangIDStrDescriptor(pdev->dev_speed, &len); break; case USBD_IDX_MFC_STR: pbuf = pdev->pDesc->GetManufacturerStrDescriptor(pdev->dev_speed, &len); break; case USBD_IDX_PRODUCT_STR: pbuf = pdev->pDesc->GetProductStrDescriptor(pdev->dev_speed, &len); break; case USBD_IDX_SERIAL_STR: pbuf = pdev->pDesc->GetSerialStrDescriptor(pdev->dev_speed, &len); break; case USBD_IDX_CONFIG_STR: pbuf = pdev->pDesc->GetConfigurationStrDescriptor(pdev->dev_speed, &len); break; case USBD_IDX_INTERFACE_STR: pbuf = pdev->pDesc->GetInterfaceStrDescriptor(pdev->dev_speed, &len); break; default: #if (USBD_SUPPORT_USER_STRING == 1) pbuf = pdev->pClass->GetUsrStrDescriptor(pdev, (req->wValue) , &len); break; #else USBD_CtlError(pdev , req); return; #endif } break; case USB_DESC_TYPE_DEVICE_QUALIFIER: if(pdev->dev_speed == USBD_SPEED_HIGH ) { pbuf = (uint8_t *)pdev->pClass->GetDeviceQualifierDescriptor(&len); break; } else { USBD_CtlError(pdev , req); return; } case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION: if(pdev->dev_speed == USBD_SPEED_HIGH ) { pbuf = (uint8_t *)pdev->pClass->GetOtherSpeedConfigDescriptor(&len); pbuf[1] = USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION; break; } else { USBD_CtlError(pdev , req); return; } default: USBD_CtlError(pdev , req); return; } if((len != 0)&& (req->wLength != 0)) { len = MIN(len , req->wLength); USBD_CtlSendData (pdev, pbuf, len); } }
/** * @brief USBD_StdEPReq * Handle standard usb endpoint requests * @param pdev: USB device instance * @param req: usb request * @retval status */ USBD_Status USBD_StdEPReq (USB_CORE_HANDLE *pdev, USB_SETUP_REQ *req) { uint8_t ep_addr; uint32_t USBD_ep_status = 0; 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_ADDRESSED: if ((ep_addr != 0x00) && (ep_addr != 0x80)) { DCD_EP_Stall(pdev , ep_addr); } break; case USB_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_ADDRESSED: if ((ep_addr != 0x00) && (ep_addr != 0x80)) { DCD_EP_Stall(pdev , ep_addr); } break; case USB_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_ADDRESSED: if ((ep_addr != 0x00) && (ep_addr != 0x80)) { DCD_EP_Stall(pdev , ep_addr); } break; case USB_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: 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; }
static uint8_t usbd_cdc_Setup (void *pdev, USB_SETUP_REQ *req) { uint16_t len=USB_CDC_DESC_SIZ; uint8_t *pbuf=usbd_cdc_CfgDesc + 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) { /* Check if the request is Device-to-Host */ if (req->bmRequest & 0x80) { /* Get the data to be sent to Host from interface layer */ APP_FOPS.pIf_Ctrl(req->bRequest, CmdBuff, req->wLength); /* Send the data to the host */ USBD_CtlSendData (pdev, CmdBuff, req->wLength); } else /* Host-to-Device requeset */ { /* Set the value of the current command to be processed */ 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, CmdBuff, req->wLength); } } else /* No Data request */ { /* Transfer the command to the interface layer */ APP_FOPS.pIf_Ctrl(req->bRequest, NULL, 0); } return USBD_OK; default: USBD_CtlError (pdev, req); return USBD_FAIL; /* Standard Requests -------------------------------*/ case USB_REQ_TYPE_STANDARD: switch (req->bRequest) { case USB_REQ_GET_DESCRIPTOR: if( (req->wValue >> 8) == CDC_DESCRIPTOR_TYPE) { #ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED pbuf = usbd_cdc_Desc; #else pbuf = usbd_cdc_CfgDesc + 9 + (9 * USBD_ITF_MAX_NUM); #endif 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 { /* Call the error management function (command will be nacked */ USBD_CtlError (pdev, req); } break; } } return USBD_OK; }
/** * @brief USBD_GetDescriptor * Handle Get Descriptor requests * @param pdev: device instance * @param req: usb request * @retval status */ static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) { uint16_t len; uint8_t *pbuf; switch (req->wValue >> 8) { case USB_DESC_TYPE_DEVICE: pbuf = pdev->pDesc->GetDeviceDescriptor(pdev->dev_speed, &len); break; case USB_DESC_TYPE_CONFIGURATION: if(pdev->dev_speed == USBD_SPEED_HIGH ) { stm32plus::usb::DeviceClassSdkGetConfigurationDescriptorEvent event( stm32plus::usb::DeviceClassSdkGetConfigurationDescriptorEvent::Type::HIGH_SPEED); pdev->pEventSource->UsbEventSender.raiseEvent(event); pbuf=event.descriptor; len=event.length; pbuf[1] = USB_DESC_TYPE_CONFIGURATION; } else { stm32plus::usb::DeviceClassSdkGetConfigurationDescriptorEvent event( stm32plus::usb::DeviceClassSdkGetConfigurationDescriptorEvent::Type::FULL_SPEED); pdev->pEventSource->UsbEventSender.raiseEvent(event); pbuf=event.descriptor; len=event.length; pbuf[1] = USB_DESC_TYPE_CONFIGURATION; } break; case USB_DESC_TYPE_STRING: switch ((uint8_t)(req->wValue)) { case USBD_IDX_LANGID_STR: pbuf = pdev->pDesc->GetLangIDStrDescriptor(pdev->dev_speed, &len); break; case USBD_IDX_MFC_STR: pbuf = pdev->pDesc->GetManufacturerStrDescriptor(pdev->dev_speed, &len); break; case USBD_IDX_PRODUCT_STR: pbuf = pdev->pDesc->GetProductStrDescriptor(pdev->dev_speed, &len); break; case USBD_IDX_SERIAL_STR: pbuf = pdev->pDesc->GetSerialStrDescriptor(pdev->dev_speed, &len); break; case USBD_IDX_CONFIG_STR: pbuf = pdev->pDesc->GetConfigurationStrDescriptor(pdev->dev_speed, &len); break; case USBD_IDX_INTERFACE_STR: pbuf = pdev->pDesc->GetInterfaceStrDescriptor(pdev->dev_speed, &len); break; default: #if (USBD_SUPPORT_USER_STRING == 1) pbuf = pdev->pClass->GetUsrStrDescriptor(pdev, (req->wValue) , &len); break; #else USBD_CtlError(pdev , req); return; #endif } break; case USB_DESC_TYPE_DEVICE_QUALIFIER: if(pdev->dev_speed == USBD_SPEED_HIGH ) { stm32plus::usb::DeviceClassSdkGetDeviceQualifierDescriptorEvent event; pdev->pEventSource->UsbEventSender.raiseEvent(event); pbuf = (uint8_t *)event.descriptor; len = event.length; break; } else { USBD_CtlError(pdev , req); return; } case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION: if(pdev->dev_speed == USBD_SPEED_HIGH ) { stm32plus::usb::DeviceClassSdkGetConfigurationDescriptorEvent event( stm32plus::usb::DeviceClassSdkGetConfigurationDescriptorEvent::Type::OTHER_SPEED); pdev->pEventSource->UsbEventSender.raiseEvent(event); pbuf=event.descriptor; len=event.length; pbuf[1] = USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION; break; } else { USBD_CtlError(pdev , req); return; } default: USBD_CtlError(pdev , req); return; } if((len != 0)&& (req->wLength != 0)) { len = MIN(len , req->wLength); USBD_CtlSendData (pdev, pbuf, len); } }
/** * @brief USBD_HID_Setup * Handle the HID specific requests * @param pdev: instance * @param req: usb requests * @retval status */ static uint8_t USBD_HID_Setup (void *pdev, USB_SETUP_REQ *req) { uint16_t len = 0; uint8_t *pbuf = NULL; switch (req->bmRequest & USB_REQ_TYPE_MASK) { case USB_REQ_TYPE_CLASS : switch (req->bRequest) { case HID_REQ_SET_PROTOCOL: USBD_HID_Protocol = (uint8_t)(req->wValue); break; case HID_REQ_GET_PROTOCOL: USBD_CtlSendData (pdev, (uint8_t *)&USBD_HID_Protocol, 1); break; case HID_REQ_SET_IDLE: USBD_HID_IdleState = (uint8_t)(req->wValue >> 8); break; case HID_REQ_GET_IDLE: USBD_CtlSendData (pdev, (uint8_t *)&USBD_HID_IdleState, 1); break; default: USBD_CtlError (pdev, req); return USBD_FAIL; } break; case USB_REQ_TYPE_STANDARD: switch (req->bRequest) { case USB_REQ_GET_DESCRIPTOR: if( req->wValue >> 8 == HID_REPORT_DESC) { len = MIN(HID_MOUSE_REPORT_DESC_SIZE , req->wLength); pbuf = HID_MOUSE_ReportDesc; } else if( req->wValue >> 8 == HID_DESCRIPTOR_TYPE) { //#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED // pbuf = USBD_HID_Desc; //#else pbuf = USBD_HID_CfgDesc + 0x12; //#endif len = MIN(USB_HID_DESC_SIZ , req->wLength); } USBD_CtlSendData (pdev, pbuf, len); break; case USB_REQ_GET_INTERFACE : USBD_CtlSendData (pdev, (uint8_t *)&USBD_HID_AltSet, 1); break; case USB_REQ_SET_INTERFACE : USBD_HID_AltSet = (uint8_t)(req->wValue); break; } }
/** * @brief USBD_AUDIO_Setup * Handle the AUDIO specific requests * @param pdev: instance * @param req: usb requests * @retval status */ static uint8_t USBD_AUDIO_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) { USBD_AUDIO_HandleTypeDef *haudio; uint16_t len; uint8_t *pbuf; uint8_t ret = USBD_OK; haudio = pdev->pClassData; switch (req->bmRequest & USB_REQ_TYPE_MASK) { case USB_REQ_TYPE_CLASS : switch (req->bRequest) { case AUDIO_REQ_GET_CUR: AUDIO_REQ_GetCurrent(pdev, req); break; case AUDIO_REQ_SET_CUR: AUDIO_REQ_SetCurrent(pdev, req); break; default: USBD_CtlError (pdev, req); ret = USBD_FAIL; } break; case USB_REQ_TYPE_STANDARD: switch (req->bRequest) { case USB_REQ_GET_DESCRIPTOR: if( (req->wValue >> 8) == AUDIO_DESCRIPTOR_TYPE) { pbuf = USBD_AUDIO_CfgDesc + 18; len = MIN(USB_AUDIO_DESC_SIZ , req->wLength); USBD_CtlSendData (pdev, pbuf, len); } break; case USB_REQ_GET_INTERFACE : USBD_CtlSendData (pdev, (uint8_t *)haudio->alt_setting, 1); break; case USB_REQ_SET_INTERFACE : if ((uint8_t)(req->wValue) <= USBD_MAX_NUM_INTERFACES) { haudio->alt_setting = (uint8_t)(req->wValue); } else { /* Call the error management function (command will be nacked */ USBD_CtlError (pdev, req); } break; default: USBD_CtlError (pdev, req); ret = USBD_FAIL; } } return ret; }