GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_device_classes/src/ux_device_class_storage_initialize.c Lines: 54 74 73.0 %
Date: 2026-03-06 18:57:10 Branches: 25 52 48.1 %

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
/**   Device Storage Class                                                */
19
/**                                                                       */
20
/**************************************************************************/
21
/**************************************************************************/
22
23
#define UX_SOURCE_CODE
24
25
26
/* Include necessary system files.  */
27
28
#include "ux_api.h"
29
#include "ux_device_class_storage.h"
30
#include "ux_device_stack.h"
31
32
/* Define the Slave Storage Class Inquiry data : DO NOT CHANGE THE LENGTH OF THESE ITEMS */
33
34
UCHAR _ux_system_slave_class_storage_vendor_id[] =                          "Eclipse ";
35
UCHAR _ux_system_slave_class_storage_product_id[] =                         "USBX storage dev";
36
UCHAR _ux_system_slave_class_storage_product_rev[] =                        "2000";
37
UCHAR _ux_system_slave_class_storage_product_serial[] =                     "12345678901234567890";
38
39
/**************************************************************************/
40
/*                                                                        */
41
/*  FUNCTION                                               RELEASE        */
42
/*                                                                        */
43
/*    _ux_device_class_storage_initialize                 PORTABLE C      */
44
/*                                                           6.3.0        */
45
/*  AUTHOR                                                                */
46
/*                                                                        */
47
/*    Chaoqiong Xiao, Microsoft Corporation                               */
48
/*                                                                        */
49
/*  DESCRIPTION                                                           */
50
/*                                                                        */
51
/*    This function initializes the USB storage device.                   */
52
/*                                                                        */
53
/*  INPUT                                                                 */
54
/*                                                                        */
55
/*    command                               Pointer to storage command    */
56
/*                                                                        */
57
/*  OUTPUT                                                                */
58
/*                                                                        */
59
/*    Completion Status                                                   */
60
/*                                                                        */
61
/*  CALLS                                                                 */
62
/*                                                                        */
63
/*    _ux_utility_memory_allocate           Allocate memory               */
64
/*    _ux_utility_memory_free               Free memory                   */
65
/*    _ux_device_thread_create              Create thread                 */
66
/*    _ux_device_thread_delete              Delete thread                 */
67
/*                                                                        */
68
/*  CALLED BY                                                             */
69
/*                                                                        */
70
/*    Device Storage Class                                                */
71
/*                                                                        */
72
/**************************************************************************/
73
51
UINT  _ux_device_class_storage_initialize(UX_SLAVE_CLASS_COMMAND *command)
74
{
75
76
51
UINT                                    status = UX_SUCCESS;
77
UX_SLAVE_CLASS_STORAGE                  *storage;
78
UX_SLAVE_CLASS_STORAGE_PARAMETER        *storage_parameter;
79
UX_SLAVE_CLASS                          *class_inst;
80
ULONG                                   lun_index;
81
82
83
    /* Get the pointer to the application parameters for the storage class.  */
84
51
    storage_parameter =  command -> ux_slave_class_command_parameter;
85
86
    /* Ensure the number of LUN declared by the caller does not exceed the
87
       max number allowed for LUN storage.  */
88
51
    if (storage_parameter -> ux_slave_class_storage_parameter_number_lun > UX_MAX_SLAVE_LUN)
89
1
        return UX_ERROR;
90
91
    /* Get the class container.  */
92
50
    class_inst =  command -> ux_slave_class_command_class_ptr;
93
94
    /* Create an instance of the device storage class.  */
95
50
    storage =  _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_STORAGE));
96
97
    /* Check for successful allocation.  */
98
50
    if (storage == UX_NULL)
99
2
        return(UX_MEMORY_INSUFFICIENT);
100
101
#if UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1
102
103
    /* Allocate bulk endpoint buffer.  */
104
    UX_ASSERT(!UX_DEVICE_CLASS_STORAGE_ENDPOINT_BUFFER_SIZE_CALC_OVERFLOW);
105
    storage -> ux_device_class_storage_endpoint_buffer = _ux_utility_memory_allocate(UX_NO_ALIGN,
106
                UX_CACHE_SAFE_MEMORY, UX_DEVICE_CLASS_STORAGE_ENDPOINT_BUFFER_SIZE);
107
#else
108
48
    status = UX_SUCCESS;
109
#endif
110
111
#if !defined(UX_DEVICE_STANDALONE)
112
113
    /* Allocate some memory for the thread stack. */
114
48
    if (status == UX_SUCCESS)
115
    {
116
48
        class_inst -> ux_slave_class_thread_stack = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE);
117
118
        /* If it's OK, create thread.  */
119
48
        if (class_inst -> ux_slave_class_thread_stack != UX_NULL)
120
121
            /* This instance needs to be running in a different thread. So start
122
            a new thread. We pass a pointer to the class to the new thread.  This thread
123
            does not start until we have a instance of the class. */
124
46
            status =  _ux_device_thread_create(&class_inst -> ux_slave_class_thread, "ux_slave_storage_thread",
125
                        _ux_device_class_storage_thread,
126
                        (ULONG) (ALIGN_TYPE) class_inst, (VOID *) class_inst -> ux_slave_class_thread_stack,
127
                        UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS,
128
                        UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START);
129
        else
130
2
            status = UX_MEMORY_INSUFFICIENT;
131
    }
132
#else
133
134
    /* Save tasks run entry.  */
135
    class_inst -> ux_slave_class_task_function = _ux_device_class_storage_tasks_run;
136
#endif
137
138
    /* If thread resources allocated, go on.  */
139
48
    if (status == UX_SUCCESS)
140
    {
141
142
        UX_THREAD_EXTENSION_PTR_SET(&(class_inst -> ux_slave_class_thread), class_inst)
143
144
        /* Store the number of LUN declared.  */
145
45
        storage -> ux_slave_class_storage_number_lun = storage_parameter -> ux_slave_class_storage_parameter_number_lun;
146
147
        /* Copy each individual LUN parameters.  */
148
103
        for (lun_index = 0; lun_index < storage -> ux_slave_class_storage_number_lun; lun_index++)
149
        {
150
151
            /* Check block length size. */
152
59
            if (storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_block_length > UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE)
153
            {
154
                /* Cannot proceed.  */
155
1
                status = (UX_MEMORY_INSUFFICIENT);
156
1
                break;
157
            }
158
159
            /* Store all the application parameter information about the media.  */
160
58
            storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_last_lba       = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_last_lba;
161
58
            storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_block_length   = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_block_length;
162
58
            storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_type           = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_type;
163
58
            storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_removable_flag = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_removable_flag;
164
58
            storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_read_only_flag = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_read_only_flag;
165
58
            storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_read           = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_read;
166
58
            storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_flush          = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_flush;
167
58
            storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_write          = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_write;
168
58
            storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_status         = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_status;
169
58
            storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_notification   = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_notification;
170
58
            storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_start_stop     = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_start_stop;
171
        }
172
173
        /* If it's OK, complete it.  */
174
45
        if (status == UX_SUCCESS)
175
        {
176
177
            /* Store the start and stop signals if needed by the application.  */
178
44
            storage -> ux_slave_class_storage_instance_activate = storage_parameter -> ux_slave_class_storage_instance_activate;
179
44
            storage -> ux_slave_class_storage_instance_deactivate = storage_parameter -> ux_slave_class_storage_instance_deactivate;
180
181
            /* Store the vendor id, product id, product revision and product serial.  */
182
44
            if (storage_parameter -> ux_slave_class_storage_parameter_vendor_id)
183
1
                storage -> ux_slave_class_storage_vendor_id = storage_parameter -> ux_slave_class_storage_parameter_vendor_id;
184
            else
185
43
                storage -> ux_slave_class_storage_vendor_id = _ux_system_slave_class_storage_vendor_id;
186
187
44
            if (storage_parameter -> ux_slave_class_storage_parameter_product_id)
188
1
                storage -> ux_slave_class_storage_product_id = storage_parameter -> ux_slave_class_storage_parameter_product_id;
189
            else
190
43
                storage -> ux_slave_class_storage_product_id = _ux_system_slave_class_storage_product_id;
191
192
44
            if (storage_parameter -> ux_slave_class_storage_parameter_product_rev)
193
1
                storage -> ux_slave_class_storage_product_rev = storage_parameter -> ux_slave_class_storage_parameter_product_rev;
194
            else
195
43
                storage -> ux_slave_class_storage_product_rev = _ux_system_slave_class_storage_product_rev;
196
197
44
            if (storage_parameter -> ux_slave_class_storage_parameter_product_serial)
198
1
                storage -> ux_slave_class_storage_product_serial = storage_parameter -> ux_slave_class_storage_parameter_product_serial;
199
            else
200
43
                storage -> ux_slave_class_storage_product_serial = _ux_system_slave_class_storage_product_serial;
201
202
            /* Save the address of the STORAGE instance inside the STORAGE container.  */
203
44
            class_inst -> ux_slave_class_instance = (VOID *) storage;
204
205
44
            return(UX_SUCCESS);
206
        }
207
208
        /* Free thread resources.  */
209
1
        _ux_device_thread_delete(&class_inst -> ux_slave_class_thread);
210
    }
211
212
#if !defined(UX_DEVICE_STANDALONE)
213
4
    if (class_inst -> ux_slave_class_thread_stack != UX_NULL)
214
2
        _ux_utility_memory_free(&class_inst -> ux_slave_class_thread_stack);
215
#endif
216
217
#if UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1
218
    if (storage -> ux_device_class_storage_endpoint_buffer != UX_NULL)
219
        _ux_utility_memory_free(storage -> ux_device_class_storage_endpoint_buffer);
220
#endif
221
222
    /* Free instance.  */
223
4
    _ux_utility_memory_free(storage);
224
225
    /* Return completion status.  */
226
4
    return(status);
227
}
228
229
230
/**************************************************************************/
231
/*                                                                        */
232
/*  FUNCTION                                               RELEASE        */
233
/*                                                                        */
234
/*    _uxe_device_class_storage_initialize                PORTABLE C      */
235
/*                                                           6.3.0        */
236
/*  AUTHOR                                                                */
237
/*                                                                        */
238
/*    Chaoqiong Xiao, Microsoft Corporation                               */
239
/*                                                                        */
240
/*  DESCRIPTION                                                           */
241
/*                                                                        */
242
/*    This function checks errors in storage initialization function call.*/
243
/*                                                                        */
244
/*  INPUT                                                                 */
245
/*                                                                        */
246
/*    command                               Pointer to storage command    */
247
/*                                                                        */
248
/*  OUTPUT                                                                */
249
/*                                                                        */
250
/*    Completion Status                                                   */
251
/*                                                                        */
252
/*  CALLS                                                                 */
253
/*                                                                        */
254
/*    _ux_device_class_storage_initialize     Initialize storage instance */
255
/*                                                                        */
256
/*  CALLED BY                                                             */
257
/*                                                                        */
258
/*    Application                                                         */
259
/*                                                                        */
260
/**************************************************************************/
261
UINT  _uxe_device_class_storage_initialize(UX_SLAVE_CLASS_COMMAND *command)
262
{
263
264
UX_SLAVE_CLASS_STORAGE_PARAMETER        *storage_parameter;
265
UINT                                    i;
266
267
    /* Get the pointer to the application parameters for the storage class.  */
268
    storage_parameter =  command -> ux_slave_class_command_parameter;
269
270
    /* Sanity checks.  */
271
    if ((storage_parameter -> ux_slave_class_storage_parameter_number_lun > UX_MAX_SLAVE_LUN) ||
272
        ((storage_parameter -> ux_slave_class_storage_parameter_vendor_id != UX_NULL) &&
273
        ( _ux_utility_string_length_get(storage_parameter -> ux_slave_class_storage_parameter_vendor_id) != 8)) ||
274
        ((storage_parameter -> ux_slave_class_storage_parameter_product_id != UX_NULL) &&
275
        ( _ux_utility_string_length_get(storage_parameter -> ux_slave_class_storage_parameter_product_id) != 16)) ||
276
        ((storage_parameter -> ux_slave_class_storage_parameter_product_rev != UX_NULL) &&
277
        ( _ux_utility_string_length_get(storage_parameter -> ux_slave_class_storage_parameter_product_rev) != 4)) ||
278
        ((storage_parameter -> ux_slave_class_storage_parameter_product_serial != UX_NULL) &&
279
        ( _ux_utility_string_length_get(storage_parameter -> ux_slave_class_storage_parameter_product_serial) != 20)))
280
        return(UX_INVALID_PARAMETER);
281
282
    for (i = 0; i < storage_parameter -> ux_slave_class_storage_parameter_number_lun; i ++)
283
    {
284
        if ((storage_parameter -> ux_slave_class_storage_parameter_lun[i].
285
                            ux_slave_class_storage_media_read == UX_NULL) ||
286
            (storage_parameter -> ux_slave_class_storage_parameter_lun[i].
287
                            ux_slave_class_storage_media_write == UX_NULL) ||
288
            (storage_parameter -> ux_slave_class_storage_parameter_lun[i].
289
                            ux_slave_class_storage_media_status == UX_NULL)
290
#if defined(UX_SLAVE_CLASS_STORAGE_INCLUDE_MMC)
291
            || (storage_parameter -> ux_slave_class_storage_parameter_lun[i].
292
                            ux_slave_class_storage_media_notification == UX_NULL)
293
#endif
294
           )
295
        {
296
            return(UX_INVALID_PARAMETER);
297
        }
298
    }
299
300
    /* Invoke storage initialize function.  */
301
    return(_ux_device_class_storage_initialize(command));
302
}