/*! * @brief Bulk out pipe callback function. * * This function serves as the callback function for bulk out pipe. * * @param handle The USB device handle. * @param message The endpoint callback message * @param callbackParam The parameter of the callback. * * @return A USB error code or kStatus_USB_Success. */ usb_status_t USB_DeviceCdcAcmBulkOut(usb_device_handle handle, usb_device_endpoint_callback_message_struct_t *message, void *callbackParam) { usb_status_t error = kStatus_USB_Error; if ((1 == s_cdcVcom.attach) && (1 == s_cdcVcom.startTransactions)) { s_recvSize = message->length; #if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \ defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) && \ defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U) s_waitForDataReceive = 0; USB0->INTEN |= USB_INTEN_SOFTOKEN_MASK; #endif if (!s_recvSize) { /* Schedule buffer for next receive event */ USB_DeviceRecvRequest(handle, USB_CDC_VCOM_BULK_OUT_ENDPOINT, s_currRecvBuf, s_usbBulkMaxPacketSize); #if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \ defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) && \ defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U) s_waitForDataReceive = 1; USB0->INTEN &= ~USB_INTEN_SOFTOKEN_MASK; #endif } } return error; }
/*! * @brief Bulk in pipe callback function. * * This function serves as the callback function for bulk in pipe. * * @param handle The USB device handle. * @param message The endpoint callback message * @param callbackParam The parameter of the callback. * * @return A USB error code or kStatus_USB_Success. */ usb_status_t USB_DeviceCdcAcmBulkIn(usb_device_handle handle, usb_device_endpoint_callback_message_struct_t *message, void *callbackParam) { usb_status_t error = kStatus_USB_Error; if ((message->length != 0) && (!(message->length % s_usbBulkMaxPacketSize))) { /* If the last packet is the size of endpoint, then send also zero-ended packet, ** meaning that we want to inform the host that we do not have any additional ** data, so it can flush the output. */ USB_DeviceSendRequest(handle, USB_CDC_VCOM_BULK_IN_ENDPOINT, NULL, 0); } else if ((1 == s_cdcVcom.attach) && (1 == s_cdcVcom.startTransactions)) { if ((message->buffer != NULL) || ((message->buffer == NULL) && (message->length == 0))) { /* User: add your own code for send complete event */ /* Schedule buffer for next receive event */ USB_DeviceRecvRequest(handle, USB_CDC_VCOM_BULK_OUT_ENDPOINT, s_currRecvBuf, s_usbBulkMaxPacketSize); #if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \ defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) && \ defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U) s_waitForDataReceive = 1; USB0->INTEN &= ~USB_INTEN_SOFTOKEN_MASK; #endif } } else { } return error; }
/*! * @brief Bulk IN endpoint callback function. * * This callback function is used to notify uplayer the tranfser result of a transfer. * This callback pointer is passed when the Bulk IN pipe initialized. * * @param handle The device handle. It equals the value returned from USB_DeviceInit. * @param event The result of the Bulk IN pipe transfer. * @param arg The paramter for this callback. It is same with * usb_device_endpoint_callback_struct_t::callbackParam. In the class, the value is the MSC class handle. * * @return A USB error code or kStatus_USB_Success. */ usb_status_t USB_DeviceMscBulkIn(usb_device_handle deviceHandle, usb_device_endpoint_callback_message_struct_t *event, void *arg) { usb_device_msc_csw_t *csw; usb_status_t error = kStatus_USB_Error; usb_device_msc_struct_t *mscHandle; mscHandle = &(g_deviceComposite->mscDisk.handle); if (event->length == USB_UNINITIALIZED_VAL_32) { return error; } if (mscHandle->transferRemaining >= event->length) { mscHandle->transferRemaining -= event->length; } if (mscHandle->needInStallFlag == 1) { mscHandle->needInStallFlag = 0; mscHandle->inEndpointStallFlag = 1; mscHandle->dataInFlag = 0; USB_DeviceStallEndpoint(deviceHandle, mscHandle->bulkInEndpoint); return error; } if ((!mscHandle->dataInFlag) && (event->length == USB_DEVICE_MSC_CSW_LENGTH)) { csw = (usb_device_msc_csw_t *)(event->buffer); } if (mscHandle->dataInFlag) { if (mscHandle->transferRemaining) { mscHandle->currentOffset += event->length; error = USB_DeviceMscSend(mscHandle); } if (!mscHandle->transferRemaining) { mscHandle->dataInFlag = 0; /*data transfer has been done, send the csw to host */ USB_DeviceSendRequest(deviceHandle, mscHandle->bulkInEndpoint, (uint8_t *)&mscHandle->g_mscCsw, USB_DEVICE_MSC_CSW_LENGTH); } } else if ((event->length == USB_DEVICE_MSC_CSW_LENGTH) && (csw->signature == USB_DEVICE_MSC_DCSWSIGNATURE)) { mscHandle->cbwValidFlag = 1; (void)USB_DeviceRecvRequest(deviceHandle, mscHandle->bulkOutEndpoint, (uint8_t *)&mscHandle->g_mscCbw, USB_DEVICE_MSC_CBW_LENGTH); mscHandle->cbwPrimeFlag = 1; } else { } return error; }
/*! * @brief Receive data through a specified endpoint. * * The function is used to receive data through a specified endpoint. * The function calls USB_DeviceRecvRequest internally. * * @param handle The msc class handle got from usb_device_class_config_struct_t::classHandle. * * @return A USB error code or kStatus_USB_Success. * * @note The return value just means if the receiving request is successful or not; the transfer done is notified by * USB_DeviceMscBulkOut. * Currently, only one transfer request can be supported for one specific endpoint. * If there is a specific requirement to support multiple transfer requests for one specific endpoint, the application * should implement a queue in the application level. * The subsequent transfer could begin only when the previous transfer is done (get notification through the endpoint * callback). */ usb_status_t USB_DeviceMscRecv(usb_device_msc_struct_t *mscHandle) { usb_status_t error = kStatus_USB_Success; usb_device_lba_app_struct_t lba; lba.offset = mscHandle->currentOffset; /*bulkOutBufferSize is the application buffer size, USB_DEVICE_MSC_MAX_RECV_TRANSFER_LENGTH is the max transfer length by the hardware, lba.size is the data pending for transfer ,select the minimum size to transfer ,the remaining will be transfer next time*/ lba.size = (mscHandle->bulkOutBufferSize > USB_DEVICE_MSC_MAX_RECV_TRANSFER_LENGTH) ? USB_DEVICE_MSC_MAX_RECV_TRANSFER_LENGTH : mscHandle->bulkOutBufferSize; lba.size = (mscHandle->transferRemaining > lba.size) ? lba.size : mscHandle->transferRemaining; /* whichever is smaller */ lba.buffer = g_deviceComposite->mscDisk.storageDisk + lba.offset; if (mscHandle->currentOffset < (mscHandle->totalLogicalBlockNumber * mscHandle->lengthOfEachLba)) { error = USB_DeviceRecvRequest(g_deviceComposite->deviceHandle, mscHandle->bulkOutEndpoint, lba.buffer, lba.size); } else { mscHandle->needOutStallFlag = 0; mscHandle->outEndpointStallFlag = 1; mscHandle->dataOutFlag = 0; mscHandle->stallStatus = (uint8_t)USB_DEVICE_MSC_STALL_IN_DATA; USB_DeviceStallEndpoint(g_deviceComposite->deviceHandle, mscHandle->bulkOutEndpoint); } return error; }
/* See virtual_com.h for documentation of this function. */ status_t USB_VcomReadBlocking(usb_device_handle baseAddr, uint8_t *buf, size_t count) { status_t error = kStatus_Success; size_t bufIndex = 0U, bytesToReceive = 0U; assert(count <= s_usbBulkMaxPacketSize); /* Waiting for the USB ready. */ while ((s_cdcVcom.attach != 1) || (s_cdcVcom.startTransactions != 1)) { __NOP(); }; do { /* If no receive request. */ if (s_recvSize <= 0) { if (kStatus_USB_Success != USB_DeviceRecvRequest(baseAddr, USB_CDC_VCOM_BULK_OUT_ENDPOINT, s_currRecvBuf, s_usbBulkMaxPacketSize)) { return kStatus_Fail; } s_currRecvIndex = 0; } /* Waiting for data received by virtual com. */ while (s_recvSize <= 0) { __NOP(); }; /* When receive request is error. */ if (0xFFFFFFFFU == s_recvSize) { /* Waiting for the USB ready and transfer started. */ while ((s_cdcVcom.attach != 1) || (s_cdcVcom.startTransactions != 1)) { __NOP(); }; s_recvSize = 0; } else { bytesToReceive = MIN(count, s_recvSize); memcpy((void *)&buf[bufIndex], s_currRecvBuf + s_currRecvIndex, bytesToReceive); count -= bytesToReceive; s_recvSize -= bytesToReceive; bufIndex += bytesToReceive; s_currRecvIndex += bytesToReceive; } } while (0U != count); return error; }
/*! * @brief Send the reponse to the host. * * This function is used to send the reponse to the host. * * There are two cases this function will be called. * Case one when a setup packet is received in control endpoint callback function: * 1. If there is not data phase in the setup transfer, the function will prime an IN transfer with the data * length is zero for status phase. * 2. If there is an IN data phase, the function will prime an OUT transfer with the actual length to need to * send for data phase. And then prime an IN transfer with the data length is zero for status phase. * 3. If there is an OUT data phase, the function will prime an IN transfer with the actual length to want to * receive for data phase. * * Case two when is not a setup packet received in control endpoint callback function: * 1. The function will prime an IN transfer with data length is zero for status phase. * * @param handle The device handle. It equals the value returned from USB_DeviceInit. * @param setup The pointer of the setup packet. * @param error The error code returned from the standard request fucntion. * @param stage The stage of the control transfer. * @param buffer It is an out parameter, is used to save the buffer address to response the host's request. * @param length It is an out parameter, the data length. * * @return A USB error code or kStatus_USB_Success. */ static usb_status_t USB_DeviceControlCallbackFeedback(usb_device_handle handle, usb_setup_struct_t *setup, usb_status_t error, usb_device_control_read_write_sequence_t stage, uint8_t **buffer, uint32_t *length) { usb_status_t errorCode = kStatus_USB_Error; uint8_t direction = USB_IN; if (kStatus_USB_InvalidRequest == error) { /* Stall the control pipe when the request is unsupported. */ if ((!((setup->bmRequestType & USB_REQUEST_TYPE_TYPE_MASK) == USB_REQUEST_TYPE_TYPE_STANDARD)) && ((setup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_OUT) && (setup->wLength) && (kUSB_DeviceControlPipeSetupStage == stage)) { direction = USB_OUT; } errorCode = USB_DeviceStallEndpoint( handle, (USB_CONTROL_ENDPOINT) | (uint8_t)((uint32_t)direction << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT)); } else { if (*length > setup->wLength) { *length = setup->wLength; } errorCode = USB_DeviceSendRequest(handle, (USB_CONTROL_ENDPOINT), *buffer, *length); if ((kStatus_USB_Success == errorCode) && (USB_REQUEST_TYPE_DIR_IN == (setup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK))) { errorCode = USB_DeviceRecvRequest(handle, (USB_CONTROL_ENDPOINT), (uint8_t *)NULL, 0U); } } return errorCode; }
/*! * @brief Control endpoint callback function. * * This callback function is used to notify uplayer the tranfser result of a transfer. * This callback pointer is passed when a sepcified endpoint initialied by calling API USB_DeviceInitEndpoint. * * @param handle The device handle. It equals the value returned from USB_DeviceInit. * @param message The result of a transfer, includes transfer buffer, transfer length and whether is in setup * phase for control pipe. * @param callbackParam The paramter for this callback. It is same with * usb_device_endpoint_callback_struct_t::callbackParam. * * @return A USB error code or kStatus_USB_Success. */ usb_status_t USB_DeviceControlCallback(usb_device_handle handle, usb_device_endpoint_callback_message_struct_t *message, void *callbackParam) { usb_setup_struct_t *deviceSetup; usb_device_common_class_struct_t *classHandle; uint8_t *buffer = (uint8_t *)NULL; uint32_t length = 0U; usb_status_t error = kStatus_USB_InvalidRequest; uint8_t state; if ((0xFFFFFFFFU == message->length) || (NULL == callbackParam)) { return error; } classHandle = (usb_device_common_class_struct_t *)callbackParam; deviceSetup = (usb_setup_struct_t *)&classHandle->setupBuffer[0]; USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state); if (message->isSetup) { if ((USB_SETUP_PACKET_SIZE != message->length) || (NULL == message->buffer)) { /* If a invalid setup is received, the control pipes should be de-init and init again. * Due to the IP can not meet this require, it is revesed for feature. */ /* USB_DeviceDeinitEndpoint(handle, USB_CONTROL_ENDPOINT | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT)); USB_DeviceDeinitEndpoint(handle, USB_CONTROL_ENDPOINT | (USB_OUT << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT)); USB_DeviceControlPipeInit(handle, callbackParam); */ return error; } /* Receive a setup request */ usb_setup_struct_t *setup = (usb_setup_struct_t *)(message->buffer); /* Copy the setup packet to the application buffer */ deviceSetup->wValue = USB_SHORT_FROM_LITTLE_ENDIAN(setup->wValue); deviceSetup->wIndex = USB_SHORT_FROM_LITTLE_ENDIAN(setup->wIndex); deviceSetup->wLength = USB_SHORT_FROM_LITTLE_ENDIAN(setup->wLength); deviceSetup->bRequest = setup->bRequest; deviceSetup->bmRequestType = setup->bmRequestType; if ((deviceSetup->bmRequestType & USB_REQUEST_TYPE_TYPE_MASK) == USB_REQUEST_TYPE_TYPE_STANDARD) { /* Handle the standard request */ if (s_UsbDeviceStandardRequest[deviceSetup->bRequest] != (usb_standard_request_callback_t)NULL) { error = s_UsbDeviceStandardRequest[deviceSetup->bRequest](classHandle, deviceSetup, &buffer, &length); } } else { if ((deviceSetup->wLength) && ((deviceSetup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_OUT)) { /* Class or vendor request with the OUT data phase. */ if ((deviceSetup->wLength) && ((deviceSetup->bmRequestType & USB_REQUEST_TYPE_TYPE_CLASS) == USB_REQUEST_TYPE_TYPE_CLASS)) { /* Get data buffer to receive the data from the host. */ usb_device_control_request_struct_t controlRequest; controlRequest.buffer = (uint8_t *)NULL; controlRequest.isSetup = 1U; controlRequest.setup = deviceSetup; controlRequest.length = deviceSetup->wLength; error = USB_DeviceClassEvent(handle, kUSB_DeviceClassEventClassRequest, &controlRequest); length = controlRequest.length; buffer = controlRequest.buffer; } else if ((deviceSetup->wLength) && ((deviceSetup->bmRequestType & USB_REQUEST_TYPE_TYPE_VENDOR) == USB_REQUEST_TYPE_TYPE_VENDOR)) { /* Get data buffer to receive the data from the host. */ usb_device_control_request_struct_t controlRequest; controlRequest.buffer = (uint8_t *)NULL; controlRequest.isSetup = 1U; controlRequest.setup = deviceSetup; controlRequest.length = deviceSetup->wLength; error = USB_DeviceClassCallback(handle, kUSB_DeviceEventVendorRequest, &controlRequest); length = controlRequest.length; buffer = controlRequest.buffer; } else { } if (kStatus_USB_Success == error) { /* Prime an OUT transfer */ error = USB_DeviceRecvRequest(handle, USB_CONTROL_ENDPOINT, buffer, deviceSetup->wLength); return error; } } else { /* Class or vendor request with the IN data phase. */ if (((deviceSetup->bmRequestType & USB_REQUEST_TYPE_TYPE_CLASS) == USB_REQUEST_TYPE_TYPE_CLASS)) { /* Get data buffer to response the host. */ usb_device_control_request_struct_t controlRequest; controlRequest.buffer = (uint8_t *)NULL; controlRequest.isSetup = 1U; controlRequest.setup = deviceSetup; controlRequest.length = deviceSetup->wLength; error = USB_DeviceClassEvent(handle, kUSB_DeviceClassEventClassRequest, &controlRequest); length = controlRequest.length; buffer = controlRequest.buffer; } else if (((deviceSetup->bmRequestType & USB_REQUEST_TYPE_TYPE_VENDOR) == USB_REQUEST_TYPE_TYPE_VENDOR)) { /* Get data buffer to response the host. */ usb_device_control_request_struct_t controlRequest; controlRequest.buffer = (uint8_t *)NULL; controlRequest.isSetup = 1U; controlRequest.setup = deviceSetup; controlRequest.length = deviceSetup->wLength; error = USB_DeviceClassCallback(handle, kUSB_DeviceEventVendorRequest, &controlRequest); length = controlRequest.length; buffer = controlRequest.buffer; } else { } } } /* Send the reponse to the host. */ error = USB_DeviceControlCallbackFeedback(handle, deviceSetup, error, kUSB_DeviceControlPipeSetupStage, &buffer, &length); } else if (kUSB_DeviceStateAddressing == state) { /* Set the device address to controller. */ error = s_UsbDeviceStandardRequest[deviceSetup->bRequest](classHandle, deviceSetup, &buffer, &length); } #if (defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)) && \ (defined(USB_DEVICE_CONFIG_EHCI_TEST_MODE) && (USB_DEVICE_CONFIG_EHCI_TEST_MODE > 0U)) else if (kUSB_DeviceStateTestMode == state) { uint8_t portTestControl = (uint8_t)(deviceSetup->wIndex >> 8); /* Set the controller.into test mode. */ error = USB_DeviceSetStatus(handle, kUSB_DeviceStatusTestMode, &portTestControl); }
/*! * @brief USB device callback function. * * This function handles the usb device specific requests. * * @param handle The USB device handle. * @param event The USB device event type. * @param param The parameter of the device specific request. * * @return A USB error code or kStatus_USB_Success. */ usb_status_t USB_DeviceCallback(usb_device_handle handle, uint32_t event, void *param) { usb_status_t error = kStatus_USB_Error; uint8_t *temp8 = (uint8_t *)param; switch (event) { case kUSB_DeviceEventBusReset: { USB_DeviceControlPipeInit(s_cdcVcom.deviceHandle); s_cdcVcom.attach = 0; #if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0) if (kStatus_USB_Success == USB_DeviceGetStatus(s_cdcVcom.deviceHandle, kUSB_DeviceStatusSpeed, &s_cdcVcom.speed)) { USB_DeviceSetSpeed(handle, s_cdcVcom.speed); } #endif } break; case kUSB_DeviceEventSetConfiguration: if (param) { s_cdcVcom.attach = 1; s_cdcVcom.currentConfiguration = *temp8; if (USB_CDC_VCOM_CONFIGURE_INDEX == (*temp8)) { usb_device_endpoint_init_struct_t epInitStruct; usb_device_endpoint_callback_struct_t endpointCallback; /* Initiailize endpoint for interrupt pipe */ endpointCallback.callbackFn = USB_DeviceCdcAcmInterruptIn; endpointCallback.callbackParam = handle; epInitStruct.zlt = 0; epInitStruct.transferType = USB_ENDPOINT_INTERRUPT; epInitStruct.endpointAddress = USB_CDC_VCOM_INTERRUPT_IN_ENDPOINT | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT); if (USB_SPEED_HIGH == s_cdcVcom.speed) { epInitStruct.maxPacketSize = HS_CDC_VCOM_INTERRUPT_IN_PACKET_SIZE; } else { epInitStruct.maxPacketSize = FS_CDC_VCOM_INTERRUPT_IN_PACKET_SIZE; } USB_DeviceInitEndpoint(s_cdcVcom.deviceHandle, &epInitStruct, &endpointCallback); /* Initiailize endpoints for bulk pipe */ endpointCallback.callbackFn = USB_DeviceCdcAcmBulkIn; endpointCallback.callbackParam = handle; epInitStruct.zlt = 0; epInitStruct.transferType = USB_ENDPOINT_BULK; epInitStruct.endpointAddress = USB_CDC_VCOM_BULK_IN_ENDPOINT | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT); if (USB_SPEED_HIGH == s_cdcVcom.speed) { epInitStruct.maxPacketSize = HS_CDC_VCOM_BULK_IN_PACKET_SIZE; } else { epInitStruct.maxPacketSize = FS_CDC_VCOM_BULK_IN_PACKET_SIZE; } USB_DeviceInitEndpoint(s_cdcVcom.deviceHandle, &epInitStruct, &endpointCallback); endpointCallback.callbackFn = USB_DeviceCdcAcmBulkOut; endpointCallback.callbackParam = handle; epInitStruct.zlt = 0; epInitStruct.transferType = USB_ENDPOINT_BULK; epInitStruct.endpointAddress = USB_CDC_VCOM_BULK_OUT_ENDPOINT | (USB_OUT << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT); if (USB_SPEED_HIGH == s_cdcVcom.speed) { epInitStruct.maxPacketSize = HS_CDC_VCOM_BULK_OUT_PACKET_SIZE; } else { epInitStruct.maxPacketSize = FS_CDC_VCOM_BULK_OUT_PACKET_SIZE; } USB_DeviceInitEndpoint(s_cdcVcom.deviceHandle, &epInitStruct, &endpointCallback); if (USB_SPEED_HIGH == s_cdcVcom.speed) { s_usbBulkMaxPacketSize = HS_CDC_VCOM_BULK_OUT_PACKET_SIZE; } else { s_usbBulkMaxPacketSize = FS_CDC_VCOM_BULK_OUT_PACKET_SIZE; } /* Schedule buffer for receive */ USB_DeviceRecvRequest(handle, USB_CDC_VCOM_BULK_OUT_ENDPOINT, s_currRecvBuf, s_usbBulkMaxPacketSize); } } break; default: break; } return error; }
usb_status_t USB_DeviceMscDiskConfigureEndpointStatus(usb_device_handle handle, uint8_t ep, uint8_t status) { usb_status_t error = kStatus_USB_Error; usb_device_msc_struct_t *mscHandle; mscHandle = &(g_deviceComposite->mscDisk.handle); if (status) { if ((USB_MSC_DISK_BULK_IN_ENDPOINT == (ep & USB_ENDPOINT_NUMBER_MASK)) && (ep & 0x80U)) { if (mscHandle->inEndpointStallFlag == 0) { mscHandle->inEndpointStallFlag = 1; error = USB_DeviceStallEndpoint(handle, ep); } } else if ((USB_MSC_DISK_BULK_OUT_ENDPOINT == (ep & USB_ENDPOINT_NUMBER_MASK)) && (ep & 0x80U)) { if (mscHandle->outEndpointStallFlag == 0) { mscHandle->outEndpointStallFlag = 1; error = USB_DeviceStallEndpoint(handle, ep); } } else { } } else { if ((USB_MSC_DISK_BULK_IN_ENDPOINT == (ep & USB_ENDPOINT_NUMBER_MASK)) && (ep & 0x80U)) { if (mscHandle->inEndpointStallFlag == 1) { mscHandle->inEndpointStallFlag = 0; error = USB_DeviceUnstallEndpoint(handle, ep); } } else if ((USB_MSC_DISK_BULK_OUT_ENDPOINT == (ep & USB_ENDPOINT_NUMBER_MASK)) && (ep & 0x80U)) { if (mscHandle->outEndpointStallFlag == 1) { mscHandle->outEndpointStallFlag = 0; error = USB_DeviceUnstallEndpoint(handle, ep); } } else { } } if (((mscHandle->stallStatus == USB_DEVICE_MSC_STALL_IN_CSW) || (mscHandle->stallStatus == USB_DEVICE_MSC_STALL_IN_DATA)) && (mscHandle->performResetDoneFlag != 1)) { if (mscHandle->cswPrimeFlag == 1) { USB_DeviceCancel(handle, mscHandle->bulkInEndpoint); } USB_DeviceSendRequest(handle, mscHandle->bulkInEndpoint, (uint8_t *)&mscHandle->g_mscCsw, USB_DEVICE_MSC_CSW_LENGTH); mscHandle->cswPrimeFlag = 0; mscHandle->stallStatus = 0; } if ((mscHandle->performResetDoneFlag == 1) && (mscHandle->inEndpointStallFlag == 0) && (mscHandle->outEndpointStallFlag == 0)) { mscHandle->performResetDoneFlag = 0; if (mscHandle->cswPrimeFlag == 1) { USB_DeviceCancel(handle, mscHandle->bulkInEndpoint); } USB_DeviceRecvRequest(handle, mscHandle->bulkOutEndpoint, (uint8_t *)&mscHandle->g_mscCbw, USB_DEVICE_MSC_CBW_LENGTH); mscHandle->cswPrimeFlag = 0; mscHandle->stallStatus = 0; } return error; }
/*! * @brief Initialize the endpoints of the msc class. * * This callback function is used to initialize the endpoints of the msc class. * * @return A USB error code or kStatus_USB_Success. */ usb_status_t USB_DeviceMscEndpointsInit(void) { usb_status_t error = kStatus_USB_Error; usb_device_endpoint_init_struct_t epInitStruct; usb_device_endpoint_callback_struct_t endpointCallback; usb_device_msc_struct_t *mscHandle; mscHandle = &(g_deviceComposite->mscDisk.handle); endpointCallback.callbackFn = USB_DeviceMscBulkIn; endpointCallback.callbackParam = (void *)mscHandle; epInitStruct.zlt = 0; epInitStruct.transferType = USB_ENDPOINT_BULK; epInitStruct.endpointAddress = USB_MSC_DISK_BULK_IN_ENDPOINT | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT); mscHandle->bulkInEndpoint = epInitStruct.endpointAddress; if (USB_SPEED_HIGH == g_deviceComposite->speed) { epInitStruct.maxPacketSize = HS_MSC_DISK_BULK_IN_PACKET_SIZE; } else { epInitStruct.maxPacketSize = FS_MSC_DISK_BULK_IN_PACKET_SIZE; } USB_DeviceInitEndpoint(g_deviceComposite->deviceHandle, &epInitStruct, &endpointCallback); endpointCallback.callbackFn = USB_DeviceMscBulkOut; endpointCallback.callbackParam = (void *)mscHandle; epInitStruct.zlt = 0; epInitStruct.transferType = USB_ENDPOINT_BULK; epInitStruct.endpointAddress = USB_MSC_DISK_BULK_OUT_ENDPOINT | (USB_OUT << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT); mscHandle->bulkOutEndpoint = epInitStruct.endpointAddress; if (USB_SPEED_HIGH == g_deviceComposite->speed) { epInitStruct.maxPacketSize = HS_MSC_DISK_BULK_OUT_PACKET_SIZE; } else { epInitStruct.maxPacketSize = FS_MSC_DISK_BULK_OUT_PACKET_SIZE; } USB_DeviceInitEndpoint(g_deviceComposite->deviceHandle, &epInitStruct, &endpointCallback); mscHandle->dataOutFlag = 0; mscHandle->dataInFlag = 0; mscHandle->outEndpointStallFlag = 0; mscHandle->inEndpointStallFlag = 0; mscHandle->needOutStallFlag = 0; mscHandle->needInStallFlag = 0; mscHandle->cbwValidFlag = 1; mscHandle->transferRemaining = 0; mscHandle->performResetRecover = 0; mscHandle->performResetDoneFlag = 0; mscHandle->stallStatus = 0; if (mscHandle->cbwPrimeFlag == 1) { USB_DeviceCancel(g_deviceComposite->deviceHandle, mscHandle->bulkOutEndpoint); } USB_DeviceRecvRequest(g_deviceComposite->deviceHandle, mscHandle->bulkOutEndpoint, (uint8_t *)&mscHandle->g_mscCbw, USB_DEVICE_MSC_CBW_LENGTH); mscHandle->cbwPrimeFlag = 1; return error; }