GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_host_classes/src/ux_host_class_storage_driver_entry.c Lines: 64 64 100.0 %
Date: 2026-03-06 18:57:10 Branches: 25 25 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
10
 **************************************************************************/
11
12
13
/**************************************************************************/
14
/**************************************************************************/
15
/**                                                                       */
16
/** USBX Component                                                        */
17
/**                                                                       */
18
/**   Storage Class                                                       */
19
/**                                                                       */
20
/**************************************************************************/
21
/**************************************************************************/
22
23
24
/* Include necessary system files.  */
25
26
#define UX_SOURCE_CODE
27
28
#include "ux_api.h"
29
#include "ux_host_class_storage.h"
30
#include "ux_host_stack.h"
31
32
33
/* Defined if FileX is not integrated in USBX
34
   and it's used as external module for file system.  */
35
36
/* #define UX_HOST_CLASS_STORAGE_EXT_FILEX */
37
38
#if defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
39
40
#ifdef FX_API_H /* For test, confirm FX is not included before.  */
41
#error fx_api.h should not be included in this mode
42
#endif
43
44
/* FX not integrated in UX, but used as external module.  */
45
#if defined(UX_HOST_CLASS_STORAGE_EXT_FILEX)
46
47
/* FX related things needs define here.  */
48
#include "fx_api.h"
49
#define UX_MEDIA                                    FX_MEDIA
50
VOID    _ux_host_class_storage_driver_entry(UX_MEDIA *media);
51
52
/* FX driver is available to support FX as external module.  */
53
#ifndef UX_HOST_CLASS_STORAGE_DRIVER_ENTRY_ENABLE
54
#define UX_HOST_CLASS_STORAGE_DRIVER_ENTRY_ENABLE
55
#endif
56
#endif
57
#else
58
59
/* FX driver is used for RTOS mode by default.  */
60
#ifndef UX_HOST_CLASS_STORAGE_DRIVER_ENTRY_ENABLE
61
#define UX_HOST_CLASS_STORAGE_DRIVER_ENTRY_ENABLE
62
#endif
63
#endif
64
65
66
#if defined(UX_HOST_CLASS_STORAGE_DRIVER_ENTRY_ENABLE)
67
/**************************************************************************/
68
/*                                                                        */
69
/*  FUNCTION                                               RELEASE        */
70
/*                                                                        */
71
/*    _ux_host_class_storage_driver_entry                 PORTABLE C      */
72
/*                                                           6.1.12       */
73
/*  AUTHOR                                                                */
74
/*                                                                        */
75
/*    Chaoqiong Xiao, Microsoft Corporation                               */
76
/*                                                                        */
77
/*  DESCRIPTION                                                           */
78
/*                                                                        */
79
/*    This function is the entry point for the FileX file system. All     */
80
/*    FileX driver I/O calls are are multiplexed here and rerouted to     */
81
/*    the proper USB storage class functions.                             */
82
/*                                                                        */
83
/*    When the entry is for storage with FX support (not in standalone    */
84
/*    mode, and with FileX), the FX media is openned in storage mount     */
85
/*    flow, and can be directly used in application after mounted.        */
86
/*                                                                        */
87
/*    When the entry is for no FX mode (FX in external module, and USBX   */
88
/*    is compiled without FileX integration), it is an example with       */
89
/*    disk partition support. In this case the FX media does not operate  */
90
/*    inside the storage flow. Actions are taken when application mounts  */
91
/*    media to FX_MEDIA and then have access to media APIs.               */
92
/*                                                                        */
93
/*    In no FX mode demo, it assumes media is managed with partition      */
94
/*    start from sector address of FX_MEDIA::fx_media_reserved_for_user.  */
95
/*                                                                        */
96
/*    The following links are not initialized in no FX mode, they must be */
97
/*    initialized before using the entry in no FX mode:                   */
98
/*    - FX_MEDIA::fx_media_reserved_for_user                              */
99
/*                                          Partition start sector inside */
100
/*                                          the whole storage media, must */
101
/*                                          set before media open         */
102
/*    - FX_MEDIA::fx_media_driver_info      Pointer to storage media,     */
103
/*                                          assigned while calling media  */
104
/*                                          open (fx_media_open)          */
105
/*                                                                        */
106
/*  INPUT                                                                 */
107
/*                                                                        */
108
/*    media                                 FileX media pointer           */
109
/*                                                                        */
110
/*  OUTPUT                                                                */
111
/*                                                                        */
112
/*    None                                                                */
113
/*                                                                        */
114
/*  CALLS                                                                 */
115
/*                                                                        */
116
/*    _ux_host_class_storage_sense_code_translate                         */
117
/*                                          Translate error status codes  */
118
/*    _ux_host_class_storage_media_read     Read sector(s)                */
119
/*    _ux_host_class_storage_media_write    Write sector(s)               */
120
/*    _ux_host_semaphore_get                Get protection semaphore      */
121
/*    _ux_host_semaphore_put                Release protection semaphore  */
122
/*                                                                        */
123
/*  CALLED BY                                                             */
124
/*                                                                        */
125
/*    FileX                                                               */
126
/*                                                                        */
127
/**************************************************************************/
128
1155
VOID  _ux_host_class_storage_driver_entry(FX_MEDIA *media)
129
{
130
131
UINT                            status;
132
UX_HOST_CLASS_STORAGE           *storage;
133
UX_HOST_CLASS_STORAGE_MEDIA     *storage_media;
134
ULONG                           partition_start;
135
136
137
    /* Get the pointers to the instances and partition start.  */
138
#if !defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
139
1155
    storage =  (UX_HOST_CLASS_STORAGE *) media -> fx_media_driver_info;
140
1155
    storage_media =  (UX_HOST_CLASS_STORAGE_MEDIA *) media -> fx_media_reserved_for_user;
141
1155
    partition_start = storage_media -> ux_host_class_storage_media_partition_start;
142
#else
143
    storage_media = (UX_HOST_CLASS_STORAGE_MEDIA *) media -> fx_media_driver_info;
144
    storage = storage_media -> ux_host_class_storage_media_storage;
145
    partition_start = (ULONG) media -> fx_media_reserved_for_user;
146
#endif
147
148
    /* Ensure the instance is valid.  */
149
1155
    if ((storage -> ux_host_class_storage_state !=  UX_HOST_CLASS_INSTANCE_LIVE) &&
150
545
        (storage -> ux_host_class_storage_state !=  UX_HOST_CLASS_INSTANCE_MOUNTING))
151
    {
152
153
        /* Class instance is invalid. Return an error!  */
154
155
        media -> fx_media_driver_status =  FX_PTR_ERROR;
155
155
        return;
156
    }
157
158
#if defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
159
160
    /* Ensure the media is valid.  */
161
    if ((storage_media -> ux_host_class_storage_media_storage != storage) ||
162
        (storage_media -> ux_host_class_storage_media_status != UX_USED))
163
    {
164
165
        /* Media instance is invalid.  */
166
        media -> fx_media_driver_status =  FX_PTR_ERROR;
167
        return;
168
    }
169
#endif
170
171
    /* Protect Thread reentry to this instance.  */
172
1000
    status = _ux_host_class_storage_lock(storage, UX_WAIT_FOREVER);
173
1000
    if (status != UX_SUCCESS)
174
    {
175
176
        /* Unable to lock, return an error.  */
177
14
        media -> fx_media_driver_status =  FX_INVALID_STATE;
178
14
        return;
179
    }
180
181
    /* Restore the LUN number from the media instance.  */
182
986
    storage -> ux_host_class_storage_lun =  storage_media -> ux_host_class_storage_media_lun;
183
184
    /* And the sector size.  */
185
986
    storage -> ux_host_class_storage_sector_size =
186
986
                storage_media -> ux_host_class_storage_media_sector_size;
187
188
#if defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
189
190
    /* Restore current used last sector number.  */
191
    storage -> ux_host_class_storage_last_sector_number =
192
                storage_media -> ux_host_class_storage_media_number_sectors - 1;
193
#endif
194
195
    /* Look at the request specified by the FileX caller.  */
196


986
    switch (media -> fx_media_driver_request)
197
    {
198
199
257
    case FX_DRIVER_READ:
200
201
        /* Read one or more sectors.  */
202
257
        status =  _ux_host_class_storage_media_read(storage,
203
257
                                media -> fx_media_driver_logical_sector + partition_start,
204
                                media -> fx_media_driver_sectors,
205
                                media -> fx_media_driver_buffer);
206
207
        /* Check completion status.  */
208
257
        if (status == UX_SUCCESS)
209
255
            media -> fx_media_driver_status =  FX_SUCCESS;
210
        else
211
        {
212
213
#if defined(UX_HOST_STANDALONE)
214
215
            /* Poll status.  */
216
            _ux_host_class_storage_media_check(storage);
217
#endif
218
219
2
            media -> fx_media_driver_status =
220
2
                _ux_host_class_storage_sense_code_translate(storage, status);
221
        }
222
257
        break;
223
224
225
352
    case FX_DRIVER_WRITE:
226
227
        /* Write one or more sectors.  */
228
352
        status =  _ux_host_class_storage_media_write(storage,
229
352
                                media -> fx_media_driver_logical_sector + partition_start,
230
                                media -> fx_media_driver_sectors,
231
                                media -> fx_media_driver_buffer);
232
233
        /* Check completion status.  */
234
352
        if (status == UX_SUCCESS)
235
351
            media -> fx_media_driver_status =  FX_SUCCESS;
236
        else
237
        {
238
239
#if defined(UX_HOST_STANDALONE)
240
241
            /* Poll status.  */
242
            _ux_host_class_storage_media_check(storage);
243
#endif
244
245
1
            media -> fx_media_driver_status =
246
1
                _ux_host_class_storage_sense_code_translate(storage,status);
247
        }
248
352
        break;
249
250
251
35
    case FX_DRIVER_FLUSH:
252
253
        /* Nothing to do. Just return a good status!  */
254
35
        media -> fx_media_driver_status =  FX_SUCCESS;
255
35
        break;
256
257
258
1
    case FX_DRIVER_ABORT:
259
260
        /* Nothing to do. Just return a good status!  */
261
1
        media -> fx_media_driver_status =  FX_SUCCESS;
262
1
        break;
263
264
265
156
    case FX_DRIVER_INIT:
266
267
#if defined(UX_HOST_STANDALONE)
268
269
            /* Poll status.  */
270
            _ux_host_class_storage_media_check(storage);
271
#endif
272
273
        /* Check for media protection.  We must do this operation here because FileX clears all the
274
           media fields before init.  */
275
156
        if (storage -> ux_host_class_storage_write_protected_media ==  UX_TRUE)
276
277
            /* The media is Write Protected. We tell FileX.  */
278
1
            media -> fx_media_driver_write_protect = UX_TRUE;
279
280
        /* This function always succeeds.  */
281
156
        media -> fx_media_driver_status =  FX_SUCCESS;
282
156
        break;
283
284
285
28
    case FX_DRIVER_UNINIT:
286
287
        /* Nothing to do. Just return a good status!  */
288
28
        media -> fx_media_driver_status =  FX_SUCCESS;
289
28
        break;
290
291
292
154
    case FX_DRIVER_BOOT_READ:
293
294
        /* Read the media boot sector.  */
295
154
        status =  _ux_host_class_storage_media_read(storage,
296
                partition_start, 1, media -> fx_media_driver_buffer);
297
298
        /* Check completion status.  */
299
154
        if (status == UX_SUCCESS)
300
153
            media -> fx_media_driver_status =  FX_SUCCESS;
301
        else
302
        {
303
304
#if defined(UX_HOST_STANDALONE)
305
306
            /* Poll status.  */
307
            _ux_host_class_storage_media_check(storage);
308
#endif
309
310
1
            media -> fx_media_driver_status =
311
1
                _ux_host_class_storage_sense_code_translate(storage,status);
312
        }
313
154
        break;
314
315
316
2
    case FX_DRIVER_BOOT_WRITE:
317
318
        /* Write the boot sector.  */
319
2
        status =  _ux_host_class_storage_media_write(storage,
320
                partition_start, 1, media -> fx_media_driver_buffer);
321
322
        /* Check completion status.  */
323
2
        if (status == UX_SUCCESS)
324
1
            media -> fx_media_driver_status =  FX_SUCCESS;
325
        else
326
        {
327
328
#if defined(UX_HOST_STANDALONE)
329
330
            /* Poll status.  */
331
            _ux_host_class_storage_media_check(storage);
332
#endif
333
334
1
            media -> fx_media_driver_status =
335
1
                _ux_host_class_storage_sense_code_translate(storage,status);
336
        }
337
2
        break;
338
339
340
1
    default:
341
342
        /* Invalid request from FileX */
343
1
        media -> fx_media_driver_status =  FX_IO_ERROR;
344
1
        break;
345
    }
346
347
    /* Unprotect thread reentry to this instance.  */
348
986
    _ux_host_class_storage_unlock(storage);
349
}
350
#endif