/** * @brief Process SETUP packet * * @param None * * @return None * * @details Parse SETUP packet and perform the corresponding action. * */ void USBD_ProcessSetupPacket(void) { /* Get SETUP packet from USB buffer */ USBD_MemCopy(g_usbd_SetupPacket, (uint8_t *)USBD_BUF_BASE, 8); /* Check the request type */ switch(g_usbd_SetupPacket[0] & 0x60) { case REQ_STANDARD: // Standard { USBD_StandardRequest(); break; } case REQ_CLASS: // Class { if(g_usbd_pfnClassRequest != NULL) { g_usbd_pfnClassRequest(); } break; } case REQ_VENDOR: // Vendor { if(g_usbd_pfnVendorRequest != NULL) { g_usbd_pfnVendorRequest(); } break; } default: // reserved { /* Setup error, stall the device */ USBD_SET_EP_STALL(EP0); USBD_SET_EP_STALL(EP1); break; } } }
/** * @brief Process standard request * * @param None * * @return None * * @details Parse standard request and perform the corresponding action. * */ void USBD_StandardRequest(void) { /* clear global variables for new request */ g_usbd_CtrlInPointer = 0; g_usbd_CtrlInSize = 0; if(g_usbd_SetupPacket[0] & 0x80) /* request data transfer direction */ { // Device to host switch(g_usbd_SetupPacket[1]) { case GET_CONFIGURATION: { // Return current configuration setting /* Data stage */ M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0)) = g_usbd_UsbConfig; USBD_SET_DATA1(EP1); USBD_SET_PAYLOAD_LEN(EP1, 0); USBD_SET_DATA1(EP0); USBD_SET_PAYLOAD_LEN(EP0, 1); /* Status stage */ USBD_PrepareCtrlOut(0, 0); DBG_PRINTF("Get configuration\n"); break; } case GET_DESCRIPTOR: { USBD_GetDescriptor(); break; } case GET_INTERFACE: { // Return current interface setting /* Data stage */ M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0)) = g_usbd_UsbAltInterface; USBD_SET_DATA1(EP0); USBD_SET_PAYLOAD_LEN(EP0, 1); /* Status stage */ USBD_PrepareCtrlOut(0, 0); DBG_PRINTF("Get interface\n"); break; } case GET_STATUS: { // Device if(g_usbd_SetupPacket[0] == 0x80) { uint8_t u8Tmp; u8Tmp = 0; if(g_usbd_sInfo->gu8ConfigDesc[7] & 0x40) u8Tmp |= 1; // Self-Powered/Bus-Powered. if(g_usbd_sInfo->gu8ConfigDesc[7] & 0x20) u8Tmp |= (g_usbd_RemoteWakeupEn << 1); // Remote wake up M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0)) = u8Tmp; } // Interface else if(g_usbd_SetupPacket[0] == 0x81) M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0)) = 0; // Endpoint else if(g_usbd_SetupPacket[0] == 0x82) { uint8_t ep = g_usbd_SetupPacket[4] & 0xF; M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0)) = USBD_GetStall(ep) ? 1 : 0; } M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0) + 1) = 0; /* Data stage */ USBD_SET_DATA1(EP0); USBD_SET_PAYLOAD_LEN(EP0, 2); /* Status stage */ USBD_PrepareCtrlOut(0, 0); DBG_PRINTF("Get status\n"); break; } default: { /* Setup error, stall the device */ USBD_SET_EP_STALL(EP0); USBD_SET_EP_STALL(EP1); DBG_PRINTF("Unknown request. stall ctrl pipe.\n"); break; } } } else { // Host to device switch(g_usbd_SetupPacket[1]) { case CLEAR_FEATURE: { if(g_usbd_SetupPacket[2] == FEATURE_ENDPOINT_HALT) { int32_t epNum, i; /* EP number stall is not allow to be clear in MSC class "Error Recovery Test". a flag: g_u32EpStallLock is added to support it */ epNum = g_usbd_SetupPacket[4] & 0xF; for(i = 0; i < USBD_MAX_EP; i++) { if(((USBD->EP[i].CFG & 0xF) == epNum) && ((g_u32EpStallLock & (1 << i)) == 0)) { USBD->EP[i].CFGP &= ~USBD_CFGP_SSTALL_Msk; DBG_PRINTF("Clr stall ep%d %x\n",i, USBD->EP[i].CFGP); } } } else if(g_usbd_SetupPacket[2] == FEATURE_DEVICE_REMOTE_WAKEUP) g_usbd_RemoteWakeupEn = 0; /* Status stage */ USBD_SET_DATA1(EP0); USBD_SET_PAYLOAD_LEN(EP0, 0); DBG_PRINTF("Clear feature op %d\n", g_usbd_SetupPacket[2]); break; } case SET_ADDRESS: { g_usbd_UsbAddr = g_usbd_SetupPacket[2]; DBG_PRINTF("Set addr to %d\n", g_usbd_UsbAddr); // DATA IN for end of setup /* Status Stage */ USBD_SET_DATA1(EP0); USBD_SET_PAYLOAD_LEN(EP0, 0); break; } case SET_CONFIGURATION: { g_usbd_UsbConfig = g_usbd_SetupPacket[2]; if(g_usbd_pfnSetConfigCallback) g_usbd_pfnSetConfigCallback(); // DATA IN for end of setup /* Status stage */ USBD_SET_DATA1(EP0); USBD_SET_PAYLOAD_LEN(EP0, 0); DBG_PRINTF("Set config to %d\n", g_usbd_UsbConfig); break; } case SET_FEATURE: { if(g_usbd_SetupPacket[2] == FEATURE_ENDPOINT_HALT) { USBD_SetStall(g_usbd_SetupPacket[4] & 0xF); DBG_PRINTF("Set feature. stall ep %d\n", g_usbd_SetupPacket[4] & 0xF); } else if(g_usbd_SetupPacket[2] == FEATURE_DEVICE_REMOTE_WAKEUP) { g_usbd_RemoteWakeupEn = 1; DBG_PRINTF("Set feature. enable remote wakeup\n"); } /* Status stage */ USBD_SET_DATA1(EP0); USBD_SET_PAYLOAD_LEN(EP0, 0); break; } case SET_INTERFACE: { g_usbd_UsbAltInterface = g_usbd_SetupPacket[2]; if(g_usbd_pfnSetInterface != NULL) g_usbd_pfnSetInterface(); /* Status stage */ USBD_SET_DATA1(EP0); USBD_SET_PAYLOAD_LEN(EP0, 0); DBG_PRINTF("Set interface to %d\n", g_usbd_UsbAltInterface); break; } default: { /* Setup error, stall the device */ USBD_SET_EP_STALL(EP0); USBD_SET_EP_STALL(EP1); DBG_PRINTF("Unsupported request. stall ctrl pipe.\n"); break; } } } }
/** * @brief Process GetDescriptor request * * @param None * * @return None * * @details Parse GetDescriptor request and perform the corresponding action. * */ void USBD_GetDescriptor(void) { uint32_t u32Len; u32Len = 0; u32Len = g_usbd_SetupPacket[7]; u32Len <<= 8; u32Len += g_usbd_SetupPacket[6]; switch(g_usbd_SetupPacket[3]) { // Get Device Descriptor case DESC_DEVICE: { u32Len = Minimum(u32Len, LEN_DEVICE); DBG_PRINTF("Get device desc, %d\n", u32Len); USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8DevDesc, u32Len); USBD_PrepareCtrlOut(0, 0); break; } // Get Configuration Descriptor case DESC_CONFIG: { uint32_t u32TotalLen; u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[3]; u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[2] + (u32TotalLen << 8); DBG_PRINTF("Get config desc len %d, acture len %d\n", u32Len, u32TotalLen); u32Len = Minimum(u32Len, u32TotalLen); DBG_PRINTF("Minimum len %d\n", u32Len); USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8ConfigDesc, u32Len); USBD_PrepareCtrlOut(0, 0); break; } // Get HID Descriptor case DESC_HID: { int32_t i32IfNum; int32_t i32TotalSize; int32_t i32Idx; uint8_t *pu8HidDesc; int32_t i32Size = 0; // Get total size of configuration descriptor i32TotalSize = g_usbd_sInfo->gu8ConfigDesc[3]; i32TotalSize = (i32TotalSize << 8) | g_usbd_sInfo->gu8ConfigDesc[2]; // Get requested HID interface i32IfNum = g_usbd_SetupPacket[4]; // Search specified HID descriptor in configuration descritpor pu8HidDesc = NULL; i32Idx = 1; do{ // Search interface first and check HID class code (0x3) and check requested interface number if((g_usbd_sInfo->gu8ConfigDesc[i32Idx] == DESC_INTERFACE) && (g_usbd_sInfo->gu8ConfigDesc[i32Idx+4] == 0x3) && (g_usbd_sInfo->gu8ConfigDesc[i32Idx+1] == i32IfNum)) { // Calculate the offset of the requested HID descriptor in configuration descriptor i32Idx = i32Idx-1+g_usbd_sInfo->gu8ConfigDesc[i32Idx-1]; pu8HidDesc = (uint8_t *)&g_usbd_sInfo->gu8ConfigDesc[i32Idx]; i32Size = pu8HidDesc[0]; DBG_PRINTF("HID desc at if=%d, offset=%d\n", i32IfNum, i32Idx); break; } else i32Idx += g_usbd_sInfo->gu8ConfigDesc[i32Idx-1]; // Seek to next descriptor }while(i32Idx < i32TotalSize); if(pu8HidDesc) { u32Len = Minimum(u32Len, i32Size); USBD_PrepareCtrlIn(pu8HidDesc, u32Len); USBD_PrepareCtrlOut(0, 0); } else { // No any HID descriptor found. Just stall. USBD_SET_EP_STALL(EP0); USBD_SET_EP_STALL(EP1); DBG_PRINTF("No HID desc found. stall ctrl pipe\n"); } break; } // Get Report Descriptor case DESC_HID_RPT: { uint32_t u32RptDescLen; uint8_t *pu8RptDesc; if(g_usbd_pfnGetHidReportCallback) pu8RptDesc = g_usbd_pfnGetHidReportCallback(g_usbd_SetupPacket[4] ,&u32RptDescLen); else { pu8RptDesc = (uint8_t *)g_usbd_sInfo->gu8HidReportDesc; u32RptDescLen = u32Len; } if(pu8RptDesc) { u32Len = Minimum(u32Len, u32RptDescLen); DBG_PRINTF("Get report desc %d\n", u32Len); USBD_PrepareCtrlIn(pu8RptDesc, u32Len); USBD_PrepareCtrlOut(0, 0); } else { USBD_SET_EP_STALL(EP0); USBD_SET_EP_STALL(EP1); DBG_PRINTF("No HID report. stall ctrl pipe\n"); } break; } // Get String Descriptor case DESC_STRING: { // Get String Descriptor if(g_usbd_SetupPacket[2] < 4) { u32Len = Minimum(u32Len, g_usbd_sInfo->gu8StringDesc[g_usbd_SetupPacket[2]][0]); DBG_PRINTF("Get string desc %d\n", u32Len); USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8StringDesc[g_usbd_SetupPacket[2]], u32Len); USBD_PrepareCtrlOut(0, 0); break; } else { // Not support. Reply STALL. USBD_SET_EP_STALL(EP0); USBD_SET_EP_STALL(EP1); DBG_PRINTF("Unsupported string desc (%d). Stall ctrl pipe.\n", g_usbd_SetupPacket[2]); break; } } default: // Not support. Reply STALL. USBD_SET_EP_STALL(EP0); USBD_SET_EP_STALL(EP1); DBG_PRINTF("Unsupported get desc type. stall ctrl pipe\n"); break; } }
void MSC_ProcessCmd(void) { uint8_t u8Len; int32_t i; uint32_t Hcount, Dcount; if (g_u8EP3Ready) { g_u8EP3Ready = 0; if (g_u8BulkState == BULK_CBW) { u8Len = USBD_GET_PAYLOAD_LEN(EP3); /* Check Signature & length of CBW */ /* Bulk Out buffer */ if ((*(uint32_t *) ((uint32_t)USBD_BUF_BASE + g_u32BulkBuf0) != CBW_SIGNATURE) || (u8Len != 31)) { /* Invalid CBW */ g_u8Prevent = 1; USBD_SET_EP_STALL(EP2); USBD_SET_EP_STALL(EP3); USBD_LockEpStall((1 << EP2) | (1 << EP3)); return; } /* Get the CBW */ for (i = 0; i < u8Len; i++) *((uint8_t *) (&g_sCBW.dCBWSignature) + i) = *(uint8_t *)((uint32_t)USBD_BUF_BASE + g_u32BulkBuf0 + i); /* Prepare to echo the tag from CBW to CSW */ g_sCSW.dCSWTag = g_sCBW.dCBWTag; Hcount = g_sCBW.dCBWDataTransferLength; /* Parse Op-Code of CBW */ switch (g_sCBW.u8OPCode) { case UFI_PREVENT_ALLOW_MEDIUM_REMOVAL: { if (g_sCBW.au8Data[2] & 0x01) { g_au8SenseKey[0] = 0x05; //INVALID COMMAND g_au8SenseKey[1] = 0x24; g_au8SenseKey[2] = 0; g_u8Prevent = 1; } else g_u8Prevent = 0; g_u8BulkState = BULK_IN; MSC_AckCmd(); return; } case UFI_TEST_UNIT_READY: { if (Hcount != 0) { if (g_sCBW.bmCBWFlags == 0) /* Ho > Dn (Case 9) */ { g_u8Prevent = 1; USBD_SET_EP_STALL(EP3); g_sCSW.bCSWStatus = 0x1; g_sCSW.dCSWDataResidue = Hcount; } } else /* Hn == Dn (Case 1) */ { if (g_u8Remove) { g_sCSW.dCSWDataResidue = 0; g_sCSW.bCSWStatus = 1; g_au8SenseKey[0] = 0x02; /* Not ready */ g_au8SenseKey[1] = 0x3A; g_au8SenseKey[2] = 0; g_u8Prevent = 1; } else { g_sCSW.dCSWDataResidue = 0; g_sCSW.bCSWStatus = 0; } } g_u8BulkState = BULK_IN; MSC_AckCmd(); return; } case UFI_START_STOP: { if ((g_sCBW.au8Data[2] & 0x03) == 0x2) { g_u8Remove = 1; } } case UFI_VERIFY_10: { g_u8BulkState = BULK_IN; MSC_AckCmd(); return; } case UFI_REQUEST_SENSE: { if ((Hcount > 0) && (Hcount <= 18)) { MSC_RequestSense(); USBD_SET_PAYLOAD_LEN(EP2, Hcount); g_u8BulkState = BULK_IN; g_sCSW.bCSWStatus = 0; g_sCSW.dCSWDataResidue = 0; return; } else { USBD_SET_EP_STALL(EP2); g_u8Prevent = 1; g_sCSW.bCSWStatus = 0x01; g_sCSW.dCSWDataResidue = 0; g_u8BulkState = BULK_IN; MSC_AckCmd(); return; } } case UFI_READ_FORMAT_CAPACITY: { if (g_u32Length == 0) { g_u32Length = g_sCBW.dCBWDataTransferLength; g_u32Address = MassCMD_BUF; } MSC_ReadFormatCapacity(); g_u8BulkState = BULK_IN; if (g_u32Length > 0) { if (g_u32Length > EP2_MAX_PKT_SIZE) g_u8Size = EP2_MAX_PKT_SIZE; else g_u8Size = g_u32Length; /* Bulk IN buffer */ USBD_MemCopy((uint8_t *)(USBD_BUF_BASE + g_u32BulkBuf1), (uint8_t *)g_u32Address, g_u8Size); g_u32Address += g_u8Size; USBD_SET_EP_BUF_ADDR(EP2, g_u32BulkBuf0); MSC_Read(); } return; } case UFI_READ_CAPACITY: { if (g_u32Length == 0) { g_u32Length = g_sCBW.dCBWDataTransferLength; g_u32Address = MassCMD_BUF; } MSC_ReadCapacity(); g_u8BulkState = BULK_IN; if (g_u32Length > 0) { if (g_u32Length > EP2_MAX_PKT_SIZE) g_u8Size = EP2_MAX_PKT_SIZE; else g_u8Size = g_u32Length; /* Bulk IN buffer */ USBD_MemCopy((uint8_t *)((uint32_t)USBD_BUF_BASE + g_u32BulkBuf1), (uint8_t *)g_u32Address, g_u8Size); g_u32Address += g_u8Size; USBD_SET_EP_BUF_ADDR(EP2, g_u32BulkBuf0); MSC_Read(); } return; } case UFI_MODE_SELECT_6: case UFI_MODE_SELECT_10: { g_u32Length = g_sCBW.dCBWDataTransferLength; g_u32Address = MassCMD_BUF; if (g_u32Length > 0) { USBD_SET_PAYLOAD_LEN(EP3, EP3_MAX_PKT_SIZE); g_u8BulkState = BULK_OUT; } return; } case UFI_MODE_SENSE_6: { *(uint8_t *)((uint32_t)USBD_BUF_BASE + g_u32BulkBuf1+0) = 0x3; *(uint8_t *)((uint32_t)USBD_BUF_BASE + g_u32BulkBuf1+1) = 0x0; *(uint8_t *)((uint32_t)USBD_BUF_BASE + g_u32BulkBuf1+2) = 0x0; *(uint8_t *)((uint32_t)USBD_BUF_BASE + g_u32BulkBuf1+3) = 0x0; USBD_SET_PAYLOAD_LEN(EP2, 4); g_u8BulkState = BULK_IN; g_sCSW.bCSWStatus = 0; g_sCSW.dCSWDataResidue = Hcount - 4;; return; } case UFI_MODE_SENSE_10: { if (g_u32Length == 0) { g_u32Length = g_sCBW.dCBWDataTransferLength; g_u32Address = MassCMD_BUF; } MSC_ModeSense10(); g_u8BulkState = BULK_IN; if (g_u32Length > 0) { if (g_u32Length > EP2_MAX_PKT_SIZE) g_u8Size = EP2_MAX_PKT_SIZE; else g_u8Size = g_u32Length; /* Bulk IN buffer */ USBD_MemCopy((uint8_t *)((uint32_t)USBD_BUF_BASE + g_u32BulkBuf1), (uint8_t *)g_u32Address, g_u8Size); g_u32Address += g_u8Size; USBD_SET_EP_BUF_ADDR(EP2, g_u32BulkBuf0); MSC_Read(); } return; } case UFI_INQUIRY: { if ((Hcount > 0) && (Hcount <= 36)) { /* Bulk IN buffer */ USBD_MemCopy((uint8_t *)((uint32_t)USBD_BUF_BASE + g_u32BulkBuf1), (uint8_t *)g_au8InquiryID, Hcount); USBD_SET_PAYLOAD_LEN(EP2, Hcount); g_u8BulkState = BULK_IN; g_sCSW.bCSWStatus = 0; g_sCSW.dCSWDataResidue = 0; return; } else { USBD_SET_EP_STALL(EP2); g_u8Prevent = 1; g_sCSW.bCSWStatus = 0x01; g_sCSW.dCSWDataResidue = 0; g_u8BulkState = BULK_IN; MSC_AckCmd(); return; } } case UFI_READ_12: case UFI_READ_10: { /* Check if it is a new transfer */ if(g_u32Length == 0) { Dcount = (get_be32(&g_sCBW.au8Data[4])>>8) * 512; if (g_sCBW.bmCBWFlags == 0x80) /* IN */ { if (Hcount == Dcount) /* Hi == Di (Case 6)*/ { } else if (Hcount < Dcount) /* Hn < Di (Case 2) || Hi < Di (Case 7) */ { if (Hcount) /* Hi < Di (Case 7) */ { g_u8Prevent = 1; g_sCSW.bCSWStatus = 0x01; g_sCSW.dCSWDataResidue = 0; } else /* Hn < Di (Case 2) */ { g_u8Prevent = 1; g_sCSW.bCSWStatus = 0x01; g_sCSW.dCSWDataResidue = 0; g_u8BulkState = BULK_IN; MSC_AckCmd(); return; } } else if (Hcount > Dcount) /* Hi > Dn (Case 4) || Hi > Di (Case 5) */ { g_u8Prevent = 1; g_sCSW.bCSWStatus = 0x01; g_sCSW.dCSWDataResidue = 0; } } else /* Ho <> Di (Case 10) */ { g_u8Prevent = 1; USBD_SET_EP_STALL(EP3); g_sCSW.bCSWStatus = 0x01; g_sCSW.dCSWDataResidue = Hcount; g_u8BulkState = BULK_IN; MSC_AckCmd(); return; } } /* Get LBA address */ g_u32Address = get_be32(&g_sCBW.au8Data[0]); g_u32LbaAddress = g_u32Address * UDC_SECTOR_SIZE; g_u32Length = g_sCBW.dCBWDataTransferLength; g_u32BytesInStorageBuf = g_u32Length; i = g_u32Length; if (i > STORAGE_BUFFER_SIZE) i = STORAGE_BUFFER_SIZE; MSC_ReadMedia(g_u32Address * UDC_SECTOR_SIZE, i, (uint8_t *)STORAGE_DATA_BUF); g_u32BytesInStorageBuf = i; g_u32LbaAddress += i; g_u32Address = STORAGE_DATA_BUF; /* Indicate the next packet should be Bulk IN Data packet */ g_u8BulkState = BULK_IN; if (g_u32BytesInStorageBuf > 0) { /* Set the packet size */ if (g_u32BytesInStorageBuf > EP2_MAX_PKT_SIZE) g_u8Size = EP2_MAX_PKT_SIZE; else g_u8Size = g_u32BytesInStorageBuf; /* Prepare the first data packet (DATA1) */ /* Bulk IN buffer */ USBD_MemCopy((uint8_t *)((uint32_t)USBD_BUF_BASE + g_u32BulkBuf1), (uint8_t *)g_u32Address, g_u8Size); g_u32Address += g_u8Size; /* kick - start */ USBD_SET_EP_BUF_ADDR(EP2, g_u32BulkBuf1); /* Trigger to send out the data packet */ USBD_SET_PAYLOAD_LEN(EP2, g_u8Size); g_u32Length -= g_u8Size; g_u32BytesInStorageBuf -= g_u8Size; } return; } case UFI_WRITE_12: case UFI_WRITE_10: { if (g_u32Length == 0) { Dcount = (get_be32(&g_sCBW.au8Data[4])>>8) * 512; if (g_sCBW.bmCBWFlags == 0x00) /* OUT */ { if (Hcount == Dcount) /* Ho == Do (Case 12)*/ { g_sCSW.dCSWDataResidue = 0; g_sCSW.bCSWStatus = 0; } else if (Hcount < Dcount) /* Hn < Do (Case 3) || Ho < Do (Case 13) */ { g_u8Prevent = 1; g_sCSW.dCSWDataResidue = 0; g_sCSW.bCSWStatus = 0x1; if (Hcount == 0) /* Hn < Do (Case 3) */ { g_u8BulkState = BULK_IN; MSC_AckCmd(); return; } } else if (Hcount > Dcount) /* Ho > Do (Case 11) */ { g_u8Prevent = 1; g_sCSW.dCSWDataResidue = 0; g_sCSW.bCSWStatus = 0x1; } g_u32Length = g_sCBW.dCBWDataTransferLength; g_u32Address = STORAGE_DATA_BUF; g_u32DataFlashStartAddr = get_be32(&g_sCBW.au8Data[0]) * UDC_SECTOR_SIZE; } else /* Hi <> Do (Case 8) */ { g_u8Prevent = 1; g_sCSW.dCSWDataResidue = Hcount; g_sCSW.bCSWStatus = 0x1; USBD_SET_EP_STALL(EP2); g_u8BulkState = BULK_IN; MSC_AckCmd(); return; } } if ((g_u32Length > 0)) { USBD_SET_PAYLOAD_LEN(EP3, EP3_MAX_PKT_SIZE); g_u8BulkState = BULK_OUT; } return; } case UFI_READ_16: { USBD_SET_EP_STALL(EP2); g_u8Prevent = 1; g_sCSW.bCSWStatus = 0x01; g_sCSW.dCSWDataResidue = 0; g_u8BulkState = BULK_IN; MSC_AckCmd(); return; } default: { /* Unsupported command */ g_au8SenseKey[0] = 0x05; g_au8SenseKey[1] = 0x20; g_au8SenseKey[2] = 0x00; /* If CBW request for data phase, just return zero packet to end data phase */ if (g_sCBW.dCBWDataTransferLength > 0) { /* Data Phase, zero/short packet */ if ((g_sCBW.bmCBWFlags & 0x80) != 0) { /* Data-In */ g_u8BulkState = BULK_IN; USBD_SET_PAYLOAD_LEN(EP2, 0); } } else { /* Status Phase */ g_u8BulkState = BULK_IN; MSC_AckCmd(); } return; } }
/** * @brief Process GetDescriptor request * * @param None * * @return None * * @details Parse GetDescriptor request and perform the corresponding action. * */ void USBD_GetDescriptor(void) { uint32_t u32Len; u32Len = 0; u32Len = g_usbd_SetupPacket[7]; u32Len <<= 8; u32Len += g_usbd_SetupPacket[6]; switch(g_usbd_SetupPacket[3]) { // Get Device Descriptor case DESC_DEVICE: { u32Len = Minimum(u32Len, LEN_DEVICE); DBG_PRINTF("Get device desc, %d\n", u32Len); USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8DevDesc, u32Len); break; } // Get Configuration Descriptor case DESC_CONFIG: { uint32_t u32TotalLen; u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[3]; u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[2] + (u32TotalLen << 8); DBG_PRINTF("Get config desc len %d, acture len %d\n", u32Len, u32TotalLen); u32Len = Minimum(u32Len, u32TotalLen); DBG_PRINTF("Minimum len %d\n", u32Len); USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8ConfigDesc, u32Len); break; } // Get HID Descriptor case DESC_HID: { /* CV3.0 HID Class Descriptor Test, Need to indicate index of the HID Descriptor within gu8ConfigDescriptor, specifically HID Composite device. */ uint32_t u32ConfigDescOffset; // u32ConfigDescOffset is configuration descriptor offset (HID descriptor start index) u32Len = Minimum(u32Len, LEN_HID); DBG_PRINTF("Get HID desc, %d\n", u32Len); u32ConfigDescOffset = g_usbd_sInfo->gu32ConfigHidDescIdx[g_usbd_SetupPacket[4]]; USBD_PrepareCtrlIn((uint8_t *)&g_usbd_sInfo->gu8ConfigDesc[u32ConfigDescOffset], u32Len); break; } // Get Report Descriptor case DESC_HID_RPT: { DBG_PRINTF("Get HID report, %d\n", u32Len); u32Len = Minimum(u32Len, g_usbd_sInfo->gu32HidReportSize[g_usbd_SetupPacket[4]]); USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8HidReportDesc[g_usbd_SetupPacket[4]], u32Len); break; } // Get String Descriptor case DESC_STRING: { // Get String Descriptor if(g_usbd_SetupPacket[2] < 4) { u32Len = Minimum(u32Len, g_usbd_sInfo->gu8StringDesc[g_usbd_SetupPacket[2]][0]); DBG_PRINTF("Get string desc %d\n", u32Len); USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8StringDesc[g_usbd_SetupPacket[2]], u32Len); break; } else { // Not support. Reply STALL. USBD_SET_EP_STALL(EP0); USBD_SET_EP_STALL(EP1); DBG_PRINTF("Unsupported string desc (%d). Stall ctrl pipe.\n", g_usbd_SetupPacket[2]); break; } } default: // Not support. Reply STALL. USBD_SET_EP_STALL(EP0); USBD_SET_EP_STALL(EP1); DBG_PRINTF("Unsupported get desc type. stall ctrl pipe\n"); break; } }