/*************************************************************************** * Copyright (c) 2024 Microsoft Corporation * Copyright (c) 2026-present Eclipse ThreadX contributors * * This program and the accompanying materials are made available under the * terms of the MIT License which is available at * https://opensource.org/licenses/MIT. * * SPDX-License-Identifier: MIT **************************************************************************/ /**************************************************************************/ /**************************************************************************/ /** */ /** USBX Component */ /** */ /** Storage Class */ /** */ /**************************************************************************/ /**************************************************************************/ /* Include necessary system files. */ #define UX_SOURCE_CODE #include "ux_api.h" #include "ux_host_class_storage.h" #include "ux_host_stack.h" #if !defined(UX_HOST_STANDALONE) /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_host_class_storage_device_initialize PORTABLE C */ /* 6.3.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function initializes the USB storage device. */ /* */ /* This function is for RTOS mode. */ /* */ /* INPUT */ /* */ /* storage Pointer to storage class */ /* */ /* OUTPUT */ /* */ /* Completion Status */ /* */ /* CALLS */ /* */ /* _ux_host_class_storage_device_reset Reset device */ /* _ux_host_class_storage_max_lun_get Get maximum number of LUNs */ /* _ux_host_class_storage_media_characteristics_get */ /* Get media characteristics */ /* _ux_host_class_storage_media_format_capacity_get */ /* Get format capacity */ /* _ux_host_class_storage_media_mount Mount the media */ /* _ux_utility_delay_ms Delay ms */ /* */ /* CALLED BY */ /* */ /* Storage Class */ /* */ /**************************************************************************/ UINT _ux_host_class_storage_device_initialize(UX_HOST_CLASS_STORAGE *storage) { UINT status; ULONG lun_index; #if defined(UX_HOST_CLASS_STORAGE_NO_FILEX) UX_HOST_CLASS_STORAGE_MEDIA *storage_media; UX_HOST_CLASS *class_inst; UINT inst_index; #endif /* Get the maximum number of LUN (Bulk Only device only, other device will set the LUN number to 0). */ status = _ux_host_class_storage_max_lun_get(storage); if (status != UX_SUCCESS) return(status); /* We need to wait for some device to settle. The INTUIX Flash disk is an example of these device who fail the first Inquiry command if sent too quickly. The timing does not have to be precise so we use the thread sleep function. The default sleep value is 2 seconds. */ _ux_utility_delay_ms(UX_HOST_CLASS_STORAGE_DEVICE_INIT_DELAY); #if defined(UX_HOST_CLASS_STORAGE_NO_FILEX) /* We need the class container. */ class_inst = storage -> ux_host_class_storage_class; #endif /* Each LUN must be parsed and mounted. */ for (lun_index = 0; lun_index <= storage -> ux_host_class_storage_max_lun; lun_index++) { /* Set the LUN into the storage instance. */ storage -> ux_host_class_storage_lun = lun_index; /* Get the media type supported by this storage device. */ status = _ux_host_class_storage_media_characteristics_get(storage); if (status == UX_HOST_CLASS_MEDIA_NOT_SUPPORTED) { /* Unsupported device. */ /* Error trap. */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_MEDIA_NOT_SUPPORTED); /* If trace is enabled, insert this event into the trace buffer. */ UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_MEDIA_NOT_SUPPORTED, storage, 0, 0, UX_TRACE_ERRORS, 0, 0) continue; } if (status != UX_SUCCESS) return(status); /* Get the format capacity of this storage device. */ status = _ux_host_class_storage_media_format_capacity_get(storage); if (status != UX_SUCCESS) return(status); /* Store the LUN type in the LUN type array. */ storage -> ux_host_class_storage_lun_types[lun_index] = storage -> ux_host_class_storage_media_type; /* Check the media type. We support regular FAT drives and optical drives. No CD-ROM support in this release. */ switch (storage -> ux_host_class_storage_media_type) { case UX_HOST_CLASS_STORAGE_MEDIA_FAT_DISK: /* Fall through. */ case UX_HOST_CLASS_STORAGE_MEDIA_OPTICAL_DISK: /* Fall through. */ case UX_HOST_CLASS_STORAGE_MEDIA_IOMEGA_CLICK: #if !defined(UX_HOST_CLASS_STORAGE_NO_FILEX) /* the ux_host_class_storage_mounted_partitions_count is needed to avoid infinite recursive loops when mounting extended partions. The value is checked against the UX_HOST_CLASS_STORAGE_MAX_PARTITIONS_COUNT */ storage -> ux_host_class_storage_mounted_partitions_count = 0; /* Try to read the device media in search for a partition table or boot sector. We are at the root of the disk, so use sector 0 as the starting point. */ _ux_host_class_storage_media_mount(storage, 0); #endif break; case UX_HOST_CLASS_STORAGE_MEDIA_CDROM: default: /* In the case of CD-ROM, we do no need to mount any file system yet. The application can read sectors directly. */ break; } #if defined(UX_HOST_CLASS_STORAGE_NO_FILEX) /* Find a free media slot for inserted media. */ storage_media = (UX_HOST_CLASS_STORAGE_MEDIA *) class_inst -> ux_host_class_media; for (inst_index = 0; inst_index < UX_HOST_CLASS_STORAGE_MAX_MEDIA; storage_media ++, inst_index++) { /* Find an unused storage media slot. */ if (storage_media -> ux_host_class_storage_media_status != UX_USED) { /* Use this free storage media slot. */ storage_media -> ux_host_class_storage_media_status = UX_USED; storage_media -> ux_host_class_storage_media_storage = storage; /* Save media information. */ storage_media -> ux_host_class_storage_media_lun = (UCHAR)storage -> ux_host_class_storage_lun; storage_media -> ux_host_class_storage_media_sector_size = (USHORT)storage -> ux_host_class_storage_sector_size; storage_media -> ux_host_class_storage_media_number_sectors = storage -> ux_host_class_storage_last_sector_number + 1; /* Invoke callback for media insertion. */ if (_ux_system_host -> ux_system_host_change_function != UX_NULL) { /* Call system change function. */ _ux_system_host -> ux_system_host_change_function(UX_STORAGE_MEDIA_INSERTION, storage -> ux_host_class_storage_class, (VOID *) storage_media); } /* Media inserted in slot, done. */ break; } } #endif } /* Some LUNs may succeed and some may fail. For simplicity's sake, we just return success. The storage thread will try to remount the ones that failed. */ return(UX_SUCCESS); } #endif