GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_host_classes/src/ux_host_class_storage_entry.c Lines: 48 48 100.0 %
Date: 2026-03-06 18:57:10 Branches: 24 24 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
UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_MULC_ULONG(sizeof(UX_HOST_CLASS_STORAGE_MEDIA), UX_HOST_CLASS_STORAGE_MAX_MEDIA), UX_HOST_CLASS_STORAGE_MAX_MEDIA_mul_ovf)
33
34
/**************************************************************************/
35
/*                                                                        */
36
/*  FUNCTION                                               RELEASE        */
37
/*                                                                        */
38
/*    _ux_host_class_storage_entry                        PORTABLE C      */
39
/*                                                           6.1.10       */
40
/*  AUTHOR                                                                */
41
/*                                                                        */
42
/*    Chaoqiong Xiao, Microsoft Corporation                               */
43
/*                                                                        */
44
/*  DESCRIPTION                                                           */
45
/*                                                                        */
46
/*    This function is the entry point of the storage class. It will be   */
47
/*    called by the USBX stack enumeration module when there is a new     */
48
/*    USB disk on the bus or when the USB disk is removed.                */
49
/*                                                                        */
50
/*    Version 2.0 of the storage class only supports USB FAT media and    */
51
/*    not CD-ROM.                                                         */
52
/*                                                                        */
53
/*  INPUT                                                                 */
54
/*                                                                        */
55
/*    command                               Pointer to class command      */
56
/*                                                                        */
57
/*  OUTPUT                                                                */
58
/*                                                                        */
59
/*    Completion Status                                                   */
60
/*                                                                        */
61
/*  CALLS                                                                 */
62
/*                                                                        */
63
/*    _ux_host_class_storage_activate       Activate storage class        */
64
/*    _ux_host_class_storage_deactivate     Deactivate storage class      */
65
/*    _ux_utility_memory_allocate           Allocate memory block         */
66
/*    _ux_utility_memory_free               Free memory block             */
67
/*    _ux_utility_thread_create             Create storage class thread   */
68
/*    _ux_utility_thread_delete             Delete storage class thread   */
69
/*                                                                        */
70
/*  CALLED BY                                                             */
71
/*                                                                        */
72
/*    Host Stack                                                          */
73
/*                                                                        */
74
/**************************************************************************/
75
656
UINT  _ux_host_class_storage_entry(UX_HOST_CLASS_COMMAND *command)
76
{
77
78
UINT                        status;
79
UX_HOST_CLASS               *class_inst;
80
#if !defined(UX_HOST_STANDALONE)
81
UX_HOST_CLASS_STORAGE_EXT   *class_ext;
82
#endif
83
84
85
    /* The command request will tell us we need to do here, either a enumeration
86
       query, an activation or a deactivation.  */
87

656
    switch (command -> ux_host_class_command_request)
88
    {
89
90
422
    case UX_HOST_CLASS_COMMAND_QUERY:
91
92
        /* The query command is used to let the stack enumeration process know if we want to own
93
           this device or not.  */
94
422
        if ((command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_CSP) &&
95
142
                            (command -> ux_host_class_command_class == UX_HOST_CLASS_STORAGE_CLASS))
96
139
            return(UX_SUCCESS);
97
        else
98
283
            return(UX_NO_CLASS_MATCH);
99
100
141
    case UX_HOST_CLASS_COMMAND_ACTIVATE:
101
102
        /* We are assuming the device will mount. If this is the first activation of
103
           the storage class, we have to fire up one thread for the media insertion
104
           and acquire some memory for the media array.  */
105
106
        /* Get class.  */
107
141
        class_inst = command -> ux_host_class_command_class_ptr;
108
109
#if !defined(UX_HOST_STANDALONE)
110
111
        /* Allocate UX_HOST_CLASS_STORAGE_EXT.  */
112
141
        if (class_inst -> ux_host_class_ext == UX_NULL)
113
        {
114
115
            /* Need memory for extension fields.  */
116
46
            class_ext = _ux_utility_memory_allocate(UX_NO_ALIGN,
117
                                            UX_REGULAR_MEMORY,
118
                                            sizeof(UX_HOST_CLASS_STORAGE_EXT));
119
120
            /* Check completion status.  */
121
46
            if (class_ext == UX_NULL)
122
1
                return(UX_MEMORY_INSUFFICIENT);
123
124
            /* Create the storage class thread.  */
125
45
            status =  _ux_host_thread_create(&class_ext -> ux_host_class_thread,
126
                                    "ux_host_storage_thread",
127
                                    _ux_host_class_storage_thread_entry,
128
                                    (ULONG) (ALIGN_TYPE) class_inst,
129
45
                                    class_ext -> ux_host_class_thread_stack,
130
                                    UX_HOST_CLASS_STORAGE_THREAD_STACK_SIZE,
131
                                    UX_HOST_CLASS_STORAGE_THREAD_PRIORITY_CLASS,
132
                                    UX_HOST_CLASS_STORAGE_THREAD_PRIORITY_CLASS,
133
                                    UX_NO_TIME_SLICE, UX_DONT_START);
134
135
            /* Check the completion status.  */
136
45
            if (status != UX_SUCCESS)
137
            {
138
1
                _ux_utility_memory_free(class_ext);
139
1
                class_inst -> ux_host_class_ext = UX_NULL;
140
1
                return(UX_THREAD_ERROR);
141
            }
142
143
            /* Set thead ext ptr.  */
144
            UX_THREAD_EXTENSION_PTR_SET(&(class_ext -> ux_host_class_thread), class_inst);
145
146
            /* Save extension.  */
147
44
            class_inst -> ux_host_class_ext = (VOID *)class_ext;
148
        }
149
        else
150
        {
151
152
            /* Get storage class extension.  */
153
95
            class_ext = (UX_HOST_CLASS_STORAGE_EXT *)class_inst -> ux_host_class_ext;
154
        }
155
#endif
156
157
        /* Allocate some memory for the media structures used by UX_MEDIA (default FileX).  */
158
139
        if (class_inst -> ux_host_class_media == UX_NULL)
159
        {
160
161
            /* UX_HOST_CLASS_STORAGE_MAX_MEDIA*sizeof(UX_HOST_CLASS_STORAGE_MEDIA) overflow
162
            * is checked outside of function.
163
            */
164
44
            class_inst -> ux_host_class_media =
165
44
                    _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY,
166
                            UX_HOST_CLASS_STORAGE_MAX_MEDIA*sizeof(UX_HOST_CLASS_STORAGE_MEDIA));
167
168
            /* Check the completion status.  */
169
44
            if (class_inst -> ux_host_class_media == UX_NULL)
170
1
                return(UX_MEMORY_INSUFFICIENT);
171
        }
172
173
        /* Now that the extension pointer has been set, resume the thread.  */
174
138
        _ux_host_thread_resume(&class_ext -> ux_host_class_thread);
175
176
        /* The activate command is used when the device inserted has found a parent and
177
           is ready to complete the enumeration.   */
178
138
        status =  _ux_host_class_storage_activate(command);
179
180
        /* Return the completion status.  */
181
138
        return(status);
182
183
1
    case UX_HOST_CLASS_COMMAND_ACTIVATE_WAIT:
184
1
        return(UX_STATE_NEXT);
185
186
85
    case UX_HOST_CLASS_COMMAND_DEACTIVATE:
187
188
        /* The deactivate command is used when the device has been extracted either
189
           directly or when its parents has been extracted.  */
190
85
        status =  _ux_host_class_storage_deactivate(command);
191
192
        /* Return the completion status.  */
193
85
        return(status);
194
195
6
    case UX_HOST_CLASS_COMMAND_DESTROY:
196
197
        /* The destroy command is used when the class is unregistered.  */
198
199
        /* Get class.  */
200
6
        class_inst = command -> ux_host_class_command_class_ptr;
201
202
        /* Free allocated media structures.  */
203
6
        if (class_inst -> ux_host_class_media)
204
        {
205
2
            _ux_utility_memory_free(class_inst -> ux_host_class_media);
206
2
            class_inst -> ux_host_class_media = UX_NULL;
207
        }
208
209
#if !defined(UX_HOST_STANDALONE)
210
211
        /* Free class extension resources.  */
212
6
        if (class_inst -> ux_host_class_ext)
213
        {
214
215
            /* Get storage class extension.  */
216
3
            class_ext = (UX_HOST_CLASS_STORAGE_EXT *)class_inst -> ux_host_class_ext;
217
218
            /* Delete storage thread.  */
219
3
            _ux_host_thread_delete(&class_ext -> ux_host_class_thread);
220
221
            /* Free class extension memory.  */
222
3
            _ux_utility_memory_free(class_ext);
223
224
            /* Set extension pointer to NULL.  */
225
3
            class_inst -> ux_host_class_ext = UX_NULL;
226
        }
227
#endif
228
229
        /* Return success.  */
230
6
        return(UX_SUCCESS);
231
232
1
    default:
233
234
        /* Error trap. */
235
1
        _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED);
236
237
        /* If trace is enabled, insert this event into the trace buffer.  */
238
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0)
239
240
        /* Return an error.  */
241
1
        return(UX_FUNCTION_NOT_SUPPORTED);
242
    }
243
}
244