void MSC_Write(void) { uint32_t lba, len; if (g_u32Length > EP3_MAX_PKT_SIZE) { if (USBD_GET_EP_BUF_ADDR(EP3) == g_u32BulkBuf0) { USBD_SET_EP_BUF_ADDR(EP3, g_u32BulkBuf1); USBD_SET_PAYLOAD_LEN(EP3, EP3_MAX_PKT_SIZE); USBD_MemCopy((uint8_t *)g_u32Address, (uint8_t *)((uint32_t)USBD_BUF_BASE + g_u32BulkBuf0), EP3_MAX_PKT_SIZE); } else { USBD_SET_EP_BUF_ADDR(EP3, g_u32BulkBuf0); USBD_SET_PAYLOAD_LEN(EP3, EP3_MAX_PKT_SIZE); USBD_MemCopy((uint8_t *)g_u32Address, (uint8_t *)((uint32_t)USBD_BUF_BASE + g_u32BulkBuf1), EP3_MAX_PKT_SIZE); } g_u32Address += EP3_MAX_PKT_SIZE; g_u32Length -= EP3_MAX_PKT_SIZE; /* Buffer full. Writer it to storage first. */ if (g_u32Address >= (STORAGE_DATA_BUF + STORAGE_BUFFER_SIZE)) { DataFlashWrite(g_u32DataFlashStartAddr, STORAGE_BUFFER_SIZE, (uint32_t)STORAGE_DATA_BUF); g_u32Address = STORAGE_DATA_BUF; g_u32DataFlashStartAddr += STORAGE_BUFFER_SIZE; } } else { if (USBD_GET_EP_BUF_ADDR(EP3) == g_u32BulkBuf0) USBD_MemCopy((uint8_t *)g_u32Address, (uint8_t *)((uint32_t)USBD_BUF_BASE + g_u32BulkBuf0), g_u32Length); else USBD_MemCopy((uint8_t *)g_u32Address, (uint8_t *)((uint32_t)USBD_BUF_BASE + g_u32BulkBuf1), g_u32Length); g_u32Address += g_u32Length; g_u32Length = 0; if ((g_sCBW.u8OPCode == UFI_WRITE_10) || (g_sCBW.u8OPCode == UFI_WRITE_12)) { lba = get_be32(&g_sCBW.au8Data[0]); len = g_sCBW.dCBWDataTransferLength; len = lba * UDC_SECTOR_SIZE + g_sCBW.dCBWDataTransferLength - g_u32DataFlashStartAddr; if (len) DataFlashWrite(g_u32DataFlashStartAddr, len, (uint32_t)STORAGE_DATA_BUF); } g_u8BulkState = BULK_IN; MSC_AckCmd(); } }
void MSC_ProcessCmd(void) { uint32_t i; if (g_u8BulkState == BULK_NORMAL) { g_u8BulkState = BULK_OUT; MSC_ReceiveCBW(g_u32MassBase); } if (g_u8BulkState == BULK_CBW) { /* Check Signature of CBW */ if ((*(uint32_t *)(g_u32MassBase) != CBW_SIGNATURE)) { g_u8BulkState = BULK_NORMAL; return; } /* Get the CBW */ for (i = 0; i < 31; i++) *((uint8_t *) (&g_sCBW.dCBWSignature) + i) = *(uint8_t *)(g_u32MassBase + i); /* Prepare to echo the tag from CBW to CSW */ g_sCSW.dCSWTag = g_sCBW.dCBWTag; /* Parse Op-Code of CBW */ switch (g_sCBW.u8OPCode) { case UFI_READ_10: { /* Get LBA address */ g_u32LbaAddress = get_be32(&g_sCBW.au8Data[0]) * USBD_SECTOR_SIZE; //MSC_ReadMedia(g_u32LbaAddress, g_sCBW.dCBWDataTransferLength, (uint8_t *)g_u32StorageBase); MSC_BulkIn(g_u32StorageBase+g_u32LbaAddress, g_sCBW.dCBWDataTransferLength); MSC_AckCmd(0); break; } case UFI_WRITE_10: { g_u32LbaAddress = get_be32(&g_sCBW.au8Data[0]) * USBD_SECTOR_SIZE; MSC_BulkOut(g_u32StorageBase+g_u32LbaAddress, g_sCBW.dCBWDataTransferLength); MSC_AckCmd(0); break; } 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; MSC_AckCmd(0); break; } case UFI_VERIFY_10: case UFI_START_STOP: case UFI_TEST_UNIT_READY: { MSC_AckCmd(0); break; } case UFI_REQUEST_SENSE: { MSC_RequestSense(); MSC_AckCmd(0); break; } case UFI_READ_FORMAT_CAPACITY: { MSC_ReadFormatCapacity(); MSC_AckCmd(0); break; } case UFI_READ_CAPACITY: { MSC_ReadCapacity(); MSC_AckCmd(0); break; } case UFI_MODE_SELECT_10: { MSC_BulkOut(g_u32StorageBase, g_sCBW.dCBWDataTransferLength); MSC_AckCmd(0); break; } case UFI_MODE_SENSE_10: { MSC_ModeSense10(); MSC_AckCmd(0); break; } case UFI_MODE_SENSE_6: { MSC_ModeSense6(); MSC_AckCmd(0); break; } case UFI_INQUIRY: { /* Bulk IN buffer */ USBD_MemCopy((uint8_t *)(g_u32MassBase), (uint8_t *)g_au8InquiryID, 36); MSC_BulkIn(g_u32MassBase, g_sCBW.dCBWDataTransferLength); MSC_AckCmd(0); break; } 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) MSC_AckCmd(g_sCBW.dCBWDataTransferLength); else MSC_AckCmd(0); } } } }
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; } }
void EP2_Handler(void) { g_u8EP2Ready = 1; MSC_AckCmd(); }