/** * @brief Repeat Control OUT pipe * * @param None * * @return None * * @details This function processes the successive Control OUT transfer. * */ void USBD_CtrlOut(void) { uint32_t u32Size; DBG_PRINTF("Ctrl Out Ack %d\n", g_usbd_CtrlOutSize); if(g_usbd_CtrlOutSize < g_usbd_CtrlOutSizeLimit) { u32Size = USBD_GET_PAYLOAD_LEN(EP1); USBD_MemCopy((uint8_t *)g_usbd_CtrlOutPointer, (uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP1), u32Size); g_usbd_CtrlOutPointer += u32Size; g_usbd_CtrlOutSize += u32Size; if(g_usbd_CtrlOutSize < g_usbd_CtrlOutSizeLimit) USBD_SET_PAYLOAD_LEN(EP1, g_usbd_CtrlMaxPktSize); } }
void VCOM_TransferData(void) { int32_t i, i32Len; /* Check wether USB is ready for next packet or not*/ if(gu32TxSize == 0) { /* Check wether we have new COM Rx data to send to USB or not */ if(comRbytes) { i32Len = comRbytes; if(i32Len > EP2_MAX_PKT_SIZE) i32Len = EP2_MAX_PKT_SIZE; for(i = 0; i < i32Len; i++) { gRxBuf[i] = comRbuf[comRhead++]; if(comRhead >= RXBUFSIZE) comRhead = 0; } __set_PRIMASK(1); comRbytes -= i32Len; __set_PRIMASK(0); gu32TxSize = i32Len; USBD_MemCopy((uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP2)), (uint8_t *)gRxBuf, i32Len); USBD_SET_PAYLOAD_LEN(EP2, i32Len); } else { /* Prepare a zero packet if previous packet size is EP2_MAX_PKT_SIZE and no more data to send at this moment to note Host the transfer has been done */ i32Len = USBD_GET_PAYLOAD_LEN(EP2); if(i32Len == EP2_MAX_PKT_SIZE) USBD_SET_PAYLOAD_LEN(EP2, 0); } } /* Process the Bulk out data when bulk out data is ready. */ if(gi8BulkOutReady && (gu32RxSize <= TXBUFSIZE - comTbytes)) { for(i = 0; i < gu32RxSize; i++) { comTbuf[comTtail++] = gpu8RxBuf[i]; if(comTtail >= TXBUFSIZE) comTtail = 0; } __set_PRIMASK(1); comTbytes += gu32RxSize; __set_PRIMASK(0); gu32RxSize = 0; gi8BulkOutReady = 0; /* Clear bulk out ready flag */ /* Ready to get next BULK out */ USBD_SET_PAYLOAD_LEN(EP3, EP3_MAX_PKT_SIZE); } /* Process the software Tx FIFO */ if(comTbytes) { /* Check if Tx is working */ if((UART0->IER & UART_IER_THRE_IE_Msk) == 0) { /* Send one bytes out */ UART0->THR = comTbuf[comThead++]; if(comThead >= TXBUFSIZE) comThead = 0; __set_PRIMASK(1); comTbytes--; __set_PRIMASK(0); /* Enable Tx Empty Interrupt. (Trigger first one) */ UART0->IER |= UART_IER_THRE_IE_Msk; } } }
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 VCOM_TransferData(void) { int32_t i, i32Len; /* Check whether USB is ready for next packet or not */ if(gu32TxSize0 == 0) { /* Check whether we have new COM Rx data to send to USB or not */ if(comRbytes0) { i32Len = comRbytes0; if(i32Len > EP2_MAX_PKT_SIZE) i32Len = EP2_MAX_PKT_SIZE; for(i = 0; i < i32Len; i++) { gRxBuf0[i] = comRbuf0[comRhead0++]; if(comRhead0 >= RXBUFSIZE) comRhead0 = 0; } __set_PRIMASK(1); comRbytes0 -= i32Len; __set_PRIMASK(0); gu32TxSize0 = i32Len; USBD_MemCopy((uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP2)), (uint8_t *)gRxBuf0, i32Len); USBD_SET_PAYLOAD_LEN(EP2, i32Len); } else { /* Prepare a zero packet if previous packet size is EP2_MAX_PKT_SIZE and no more data to send at this moment to note Host the transfer has been done */ i32Len = USBD_GET_PAYLOAD_LEN(EP2); if(i32Len == EP2_MAX_PKT_SIZE) USBD_SET_PAYLOAD_LEN(EP2, 0); } } if(gu32TxSize1 == 0) { /* Check whether we have new COM Rx data to send to USB or not */ if(comRbytes1) { i32Len = comRbytes1; if(i32Len > EP7_MAX_PKT_SIZE) i32Len = EP7_MAX_PKT_SIZE; for(i = 0; i < i32Len; i++) { gRxBuf1[i] = comRbuf1[comRhead1++]; if(comRhead1 >= RXBUFSIZE) comRhead1 = 0; } __set_PRIMASK(1); comRbytes1 -= i32Len; __set_PRIMASK(0); gu32TxSize1 = i32Len; USBD_MemCopy((uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP7)), (uint8_t *)gRxBuf1, i32Len); USBD_SET_PAYLOAD_LEN(EP7, i32Len); } else { /* Prepare a zero packet if previous packet size is EP7_MAX_PKT_SIZE and no more data to send at this moment to note Host the transfer has been done */ i32Len = USBD_GET_PAYLOAD_LEN(EP7); if(i32Len == EP7_MAX_PKT_SIZE) USBD_SET_PAYLOAD_LEN(EP7, 0); } } /* Process the Bulk out data when bulk out data is ready. */ if(gi8BulkOutReady0 && (gu32RxSize0 <= TXBUFSIZE - comTbytes0)) { for(i = 0; i < gu32RxSize0; i++) { comTbuf0[comTtail0++] = gpu8RxBuf0[i]; if(comTtail0 >= TXBUFSIZE) comTtail0 = 0; } __set_PRIMASK(1); comTbytes0 += gu32RxSize0; __set_PRIMASK(0); gu32RxSize0 = 0; gi8BulkOutReady0 = 0; /* Clear bulk out ready flag */ /* Ready to get next BULK out */ USBD_SET_PAYLOAD_LEN(EP3, EP3_MAX_PKT_SIZE); } if(gi8BulkOutReady1 && (gu32RxSize1 <= TXBUFSIZE - comTbytes1)) { for(i = 0; i < gu32RxSize1; i++) { comTbuf1[comTtail1++] = gpu8RxBuf1[i]; if(comTtail1 >= TXBUFSIZE) comTtail1 = 0; } __set_PRIMASK(1); comTbytes1 += gu32RxSize1; __set_PRIMASK(0); gu32RxSize1 = 0; gi8BulkOutReady1 = 0; /* Clear bulk out ready flag */ /* Ready to get next BULK out */ USBD_SET_PAYLOAD_LEN(EP6, EP6_MAX_PKT_SIZE); } /* Process the software Tx FIFO */ if(comTbytes0) { /* Check if Tx is working */ if((UART0->INTEN & UART_INTEN_THREIEN_Msk) == 0) { /* Send one bytes out */ UART0->DAT = comTbuf0[comThead0++]; if(comThead0 >= TXBUFSIZE) comThead0 = 0; __set_PRIMASK(1); comTbytes0--; __set_PRIMASK(0); /* Enable Tx Empty Interrupt. (Trigger first one) */ UART0->INTEN |= UART_INTEN_THREIEN_Msk; } } if(comTbytes1) { /* Check if Tx is working */ if((UART1->INTEN & UART_INTEN_THREIEN_Msk) == 0) { /* Send one bytes out */ UART1->DAT = comTbuf1[comThead1++]; if(comThead1 >= TXBUFSIZE) comThead1 = 0; __set_PRIMASK(1); comTbytes1--; __set_PRIMASK(0); /* Enable Tx Empty Interrupt. (Trigger first one) */ UART1->INTEN |= UART_INTEN_THREIEN_Msk; } } }