1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** USBX Component                                                        */
16 /**                                                                       */
17 /**   Storage Class                                                       */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 
23 /* Include necessary system files.  */
24 
25 #define UX_SOURCE_CODE
26 
27 #include "ux_api.h"
28 #include "ux_host_class_storage.h"
29 #include "ux_host_stack.h"
30 
31 
32 #if !defined(UX_HOST_STANDALONE)
33 /**************************************************************************/
34 /*                                                                        */
35 /*  FUNCTION                                               RELEASE        */
36 /*                                                                        */
37 /*    _ux_host_class_storage_device_initialize            PORTABLE C      */
38 /*                                                           6.3.0        */
39 /*  AUTHOR                                                                */
40 /*                                                                        */
41 /*    Chaoqiong Xiao, Microsoft Corporation                               */
42 /*                                                                        */
43 /*  DESCRIPTION                                                           */
44 /*                                                                        */
45 /*    This function initializes the USB storage device.                   */
46 /*                                                                        */
47 /*    This function is for RTOS mode.                                     */
48 /*                                                                        */
49 /*  INPUT                                                                 */
50 /*                                                                        */
51 /*    storage                               Pointer to storage class      */
52 /*                                                                        */
53 /*  OUTPUT                                                                */
54 /*                                                                        */
55 /*    Completion Status                                                   */
56 /*                                                                        */
57 /*  CALLS                                                                 */
58 /*                                                                        */
59 /*    _ux_host_class_storage_device_reset   Reset device                  */
60 /*    _ux_host_class_storage_max_lun_get    Get maximum number of LUNs    */
61 /*    _ux_host_class_storage_media_characteristics_get                    */
62 /*                                          Get media characteristics     */
63 /*    _ux_host_class_storage_media_format_capacity_get                    */
64 /*                                          Get format capacity           */
65 /*    _ux_host_class_storage_media_mount    Mount the media               */
66 /*    _ux_utility_delay_ms                  Delay ms                      */
67 /*                                                                        */
68 /*  CALLED BY                                                             */
69 /*                                                                        */
70 /*    Storage Class                                                       */
71 /*                                                                        */
72 /*  RELEASE HISTORY                                                       */
73 /*                                                                        */
74 /*    DATE              NAME                      DESCRIPTION             */
75 /*                                                                        */
76 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
77 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
78 /*                                            added option to disable FX  */
79 /*                                            media integration,          */
80 /*                                            resulting in version 6.1    */
81 /*  08-02-2021     Wen Wang                 Modified comment(s),          */
82 /*                                            fixed logic of creating     */
83 /*                                            multiple storage media,     */
84 /*                                            resulting in version 6.1.8  */
85 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
86 /*                                            improved media insert/eject */
87 /*                                            management without FX,      */
88 /*                                            resulting in version 6.1.10 */
89 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s),          */
90 /*                                            moved class/sub/protocol    */
91 /*                                            check and endpoints get     */
92 /*                                            into _activate function,    */
93 /*                                            resulting in version 6.3.0  */
94 /*                                                                        */
95 /**************************************************************************/
_ux_host_class_storage_device_initialize(UX_HOST_CLASS_STORAGE * storage)96 UINT  _ux_host_class_storage_device_initialize(UX_HOST_CLASS_STORAGE *storage)
97 {
98 
99 UINT                            status;
100 ULONG                           lun_index;
101 #if defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
102 UX_HOST_CLASS_STORAGE_MEDIA     *storage_media;
103 UX_HOST_CLASS                   *class_inst;
104 UINT                            inst_index;
105 #endif
106 
107 
108     /* Get the maximum number of LUN (Bulk Only device only, other device
109        will set the LUN number to 0).  */
110     status =  _ux_host_class_storage_max_lun_get(storage);
111     if (status != UX_SUCCESS)
112         return(status);
113 
114     /* We need to wait for some device to settle. The INTUIX Flash disk is an example of
115        these device who fail the first Inquiry command if sent too quickly.
116        The timing does not have to be precise so we use the thread sleep function.
117        The default sleep value is 2 seconds.  */
118     _ux_utility_delay_ms(UX_HOST_CLASS_STORAGE_DEVICE_INIT_DELAY);
119 
120 #if defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
121     /* We need the class container.  */
122     class_inst =  storage -> ux_host_class_storage_class;
123 #endif
124 
125     /* Each LUN must be parsed and mounted.  */
126     for (lun_index = 0; lun_index <= storage -> ux_host_class_storage_max_lun; lun_index++)
127     {
128 
129         /* Set the LUN into the storage instance.  */
130         storage -> ux_host_class_storage_lun =  lun_index;
131 
132         /* Get the media type supported by this storage device.  */
133         status =  _ux_host_class_storage_media_characteristics_get(storage);
134         if (status == UX_HOST_CLASS_MEDIA_NOT_SUPPORTED)
135         {
136             /* Unsupported device.  */
137 
138             /* Error trap. */
139             _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_MEDIA_NOT_SUPPORTED);
140 
141             /* If trace is enabled, insert this event into the trace buffer.  */
142             UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_MEDIA_NOT_SUPPORTED, storage, 0, 0, UX_TRACE_ERRORS, 0, 0)
143 
144             continue;
145         }
146         if (status != UX_SUCCESS)
147             return(status);
148 
149         /* Get the format capacity of this storage device.  */
150         status =  _ux_host_class_storage_media_format_capacity_get(storage);
151         if (status != UX_SUCCESS)
152             return(status);
153 
154         /* Store the LUN type in the LUN type array. */
155         storage -> ux_host_class_storage_lun_types[lun_index] = storage -> ux_host_class_storage_media_type;
156 
157         /* Check the media type. We support regular FAT drives and optical drives.
158            No CD-ROM support in this release.  */
159         switch (storage -> ux_host_class_storage_media_type)
160         {
161 
162         case UX_HOST_CLASS_STORAGE_MEDIA_FAT_DISK:
163             /* Fall through.  */
164         case UX_HOST_CLASS_STORAGE_MEDIA_OPTICAL_DISK:
165             /* Fall through.  */
166         case UX_HOST_CLASS_STORAGE_MEDIA_IOMEGA_CLICK:
167 
168 #if !defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
169             /* Try to read the device media in search for a partition table or boot sector.
170                We are at the root of the disk, so use sector 0 as the starting point.  */
171             _ux_host_class_storage_media_mount(storage, 0);
172 #endif
173             break;
174 
175         case UX_HOST_CLASS_STORAGE_MEDIA_CDROM:
176         default:
177 
178            /* In the case of CD-ROM, we do no need to mount any file system yet. The application
179               can read sectors directly.  */
180 
181             break;
182         }
183 
184 #if defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
185 
186         /* Find a free media slot for inserted media.  */
187         storage_media =  (UX_HOST_CLASS_STORAGE_MEDIA *) class_inst -> ux_host_class_media;
188         for (inst_index = 0; inst_index < UX_HOST_CLASS_STORAGE_MAX_MEDIA;
189             storage_media ++, inst_index++)
190         {
191 
192             /* Find an unused storage media slot.  */
193             if (storage_media -> ux_host_class_storage_media_status != UX_USED)
194             {
195 
196                 /* Use this free storage media slot.  */
197                 storage_media -> ux_host_class_storage_media_status = UX_USED;
198                 storage_media -> ux_host_class_storage_media_storage = storage;
199 
200                 /* Save media information.  */
201                 storage_media -> ux_host_class_storage_media_lun = (UCHAR)storage -> ux_host_class_storage_lun;
202                 storage_media -> ux_host_class_storage_media_sector_size = (USHORT)storage -> ux_host_class_storage_sector_size;
203                 storage_media -> ux_host_class_storage_media_number_sectors = storage -> ux_host_class_storage_last_sector_number + 1;
204 
205                 /* Invoke callback for media insertion.  */
206                 if (_ux_system_host -> ux_system_host_change_function != UX_NULL)
207                 {
208 
209                     /* Call system change function.  */
210                     _ux_system_host ->  ux_system_host_change_function(UX_STORAGE_MEDIA_INSERTION,
211                                         storage -> ux_host_class_storage_class, (VOID *) storage_media);
212                 }
213 
214                 /* Media inserted in slot, done.  */
215                 break;
216             }
217         }
218 #endif
219     }
220 
221     /* Some LUNs may succeed and some may fail. For simplicity's sake, we just
222        return success. The storage thread will try to remount the ones that failed.  */
223     return(UX_SUCCESS);
224 }
225 #endif
226