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 /** Host Stack */
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_stack.h"
29
30
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _ux_host_stack_class_register PORTABLE C */
36 /* 6.1 */
37 /* AUTHOR */
38 /* */
39 /* Chaoqiong Xiao, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function registers a USB class to the USB stack. The Class */
44 /* must specify an entry point for the USB stack to send commands */
45 /* such as: */
46 /* */
47 /* UX_HOST_CLASS_COMMAND_QUERY */
48 /* UX_HOST_CLASS_COMMAND_ACTIVATE */
49 /* UX_HOST_CLASS_COMMAND_DESTROY */
50 /* */
51 /* Note: The C string of class_name must be NULL-terminated and the */
52 /* length of it (without the NULL-terminator itself) must be no larger */
53 /* than UX_MAX_CLASS_NAME_LENGTH. */
54 /* */
55 /* INPUT */
56 /* */
57 /* class_name Name of class */
58 /* class_entry_function Entry function of the class */
59 /* */
60 /* OUTPUT */
61 /* */
62 /* Completion Status */
63 /* */
64 /* CALLS */
65 /* */
66 /* _ux_utility_string_length_check Check C string and return */
67 /* length if null-terminated */
68 /* _ux_utility_memory_copy Copy memory block */
69 /* */
70 /* CALLED BY */
71 /* */
72 /* Application */
73 /* USBX Components */
74 /* */
75 /* RELEASE HISTORY */
76 /* */
77 /* DATE NAME DESCRIPTION */
78 /* */
79 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
80 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
81 /* optimized based on compile */
82 /* definitions, verified */
83 /* memset and memcpy cases, */
84 /* resulting in version 6.1 */
85 /* */
86 /**************************************************************************/
_ux_host_stack_class_register(UCHAR * class_name,UINT (* class_entry_function)(struct UX_HOST_CLASS_COMMAND_STRUCT *))87 UINT _ux_host_stack_class_register(UCHAR *class_name,
88 UINT (*class_entry_function)(struct UX_HOST_CLASS_COMMAND_STRUCT *))
89 {
90
91 UX_HOST_CLASS *class_inst;
92 #if !defined(UX_NAME_REFERENCED_BY_POINTER)
93 UINT status;
94 UINT class_name_length = 0;
95 #endif
96 #if UX_MAX_CLASS_DRIVER > 1
97 ULONG class_index;
98 #endif
99
100 /* If trace is enabled, insert this event into the trace buffer. */
101 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_CLASS_REGISTER, class_name, class_entry_function, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0)
102
103 #if !defined(UX_NAME_REFERENCED_BY_POINTER)
104 /* Get the length of the class name (exclude null-terminator). */
105 status = _ux_utility_string_length_check(class_name, &class_name_length, UX_MAX_CLASS_NAME_LENGTH);
106 if (status)
107 return(status);
108 #endif
109
110 /* Get first class. */
111 class_inst = _ux_system_host -> ux_system_host_class_array;
112
113 #if UX_MAX_CLASS_DRIVER > 1
114 /* We need to parse the class table to find an empty spot. */
115 for (class_index = 0; class_index < _ux_system_host -> ux_system_host_max_class; class_index++)
116 {
117 #endif
118
119 /* Check if this class is already used. */
120 if (class_inst -> ux_host_class_status == UX_UNUSED)
121 {
122
123 #if defined(UX_NAME_REFERENCED_BY_POINTER)
124 class_inst -> ux_host_class_name = (const UCHAR *) class_name;
125 #else
126
127 /* We have found a free container for the class. Copy the name (with null-terminator). */
128 _ux_utility_memory_copy(class_inst -> ux_host_class_name, class_name, class_name_length + 1); /* Use case of memcpy is verified. */
129 #endif
130
131 /* Memorize the entry function of this class. */
132 class_inst -> ux_host_class_entry_function = class_entry_function;
133
134 /* Mark it as used. */
135 class_inst -> ux_host_class_status = UX_USED;
136
137 /* Return successful completion. */
138 return(UX_SUCCESS);
139 }
140
141 /* Do a sanity check to make sure the class is not already installed by
142 mistake. To verify this, we simple check for the class entry point. */
143 else
144 {
145
146 /* Check for an already installed class entry function. */
147 if(class_inst -> ux_host_class_entry_function == class_entry_function)
148 {
149
150 /* Error trap. */
151 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_INIT, UX_HOST_CLASS_ALREADY_INSTALLED);
152
153 /* If trace is enabled, insert this event into the trace buffer. */
154 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_ALREADY_INSTALLED, class_name, 0, 0, UX_TRACE_ERRORS, 0, 0)
155
156 /* Yes, return an error. */
157 return(UX_HOST_CLASS_ALREADY_INSTALLED);
158 }
159 }
160 #if UX_MAX_CLASS_DRIVER > 1
161 /* Move to the next class. */
162 class_inst ++;
163 }
164 #endif
165
166 /* If trace is enabled, insert this event into the trace buffer. */
167 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_ARRAY_FULL, class_name, 0, 0, UX_TRACE_ERRORS, 0, 0)
168
169 /* Error trap. */
170 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_INIT, UX_MEMORY_ARRAY_FULL);
171
172 /* No more entries in the class table. */
173 return(UX_MEMORY_ARRAY_FULL);
174 }
175
176
177 /**************************************************************************/
178 /* */
179 /* FUNCTION RELEASE */
180 /* */
181 /* _uxe_host_stack_class_register PORTABLE C */
182 /* 6.3.0 */
183 /* AUTHOR */
184 /* */
185 /* Chaoqiong Xiao, Microsoft Corporation */
186 /* */
187 /* DESCRIPTION */
188 /* */
189 /* This function checks errors in host stack class register function */
190 /* call. */
191 /* */
192 /* INPUT */
193 /* */
194 /* class_name Name of class */
195 /* class_entry_function Entry function of the class */
196 /* */
197 /* OUTPUT */
198 /* */
199 /* None */
200 /* */
201 /* CALLS */
202 /* */
203 /* _ux_host_stack_class_instance_get Host stack class instance get */
204 /* */
205 /* CALLED BY */
206 /* */
207 /* Application */
208 /* */
209 /* RELEASE HISTORY */
210 /* */
211 /* DATE NAME DESCRIPTION */
212 /* */
213 /* 10-31-2023 Chaoqiong Xiao Initial Version 6.3.0 */
214 /* */
215 /**************************************************************************/
_uxe_host_stack_class_register(UCHAR * class_name,UINT (* class_entry_function)(struct UX_HOST_CLASS_COMMAND_STRUCT *))216 UINT _uxe_host_stack_class_register(UCHAR *class_name,
217 UINT (*class_entry_function)(struct UX_HOST_CLASS_COMMAND_STRUCT *))
218 {
219
220 /* Sanity checks. */
221 if ((class_name == UX_NULL) || (class_entry_function == UX_NULL))
222 return(UX_INVALID_PARAMETER);
223
224 /* Invoke class register function. */
225 return(_ux_host_stack_class_register(class_name, class_entry_function));
226 }
227