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