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 /** Device Stack */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define UX_SOURCE_CODE
23
24
25 /* Include necessary system files. */
26
27 #include "ux_api.h"
28 #include "ux_device_stack.h"
29
30
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _ux_device_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 slave class to the slave stack. */
44 /* */
45 /* Note: The C string of class_name must be NULL-terminated and the */
46 /* length of it (without the NULL-terminator itself) must be no larger */
47 /* than UX_MAX_CLASS_NAME_LENGTH. */
48 /* */
49 /* INPUT */
50 /* */
51 /* class_name Name of class */
52 /* class_function_entry Class entry function */
53 /* configuration_number Configuration # for this class*/
54 /* interface_number Interface # for this class */
55 /* parameter Parameter specific for class */
56 /* */
57 /* OUTPUT */
58 /* */
59 /* Completion Status */
60 /* */
61 /* CALLS */
62 /* */
63 /* _ux_utility_string_length_check Check C string and return */
64 /* its length if null-terminated */
65 /* _ux_utility_memory_copy Memory copy */
66 /* */
67 /* CALLED BY */
68 /* */
69 /* Application */
70 /* */
71 /* RELEASE HISTORY */
72 /* */
73 /* DATE NAME DESCRIPTION */
74 /* */
75 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
76 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
77 /* optimized based on compile */
78 /* definitions, verified */
79 /* memset and memcpy cases, */
80 /* resulting in version 6.1 */
81 /* */
82 /**************************************************************************/
_ux_device_stack_class_register(UCHAR * class_name,UINT (* class_entry_function)(struct UX_SLAVE_CLASS_COMMAND_STRUCT *),ULONG configuration_number,ULONG interface_number,VOID * parameter)83 UINT _ux_device_stack_class_register(UCHAR *class_name,
84 UINT (*class_entry_function)(struct UX_SLAVE_CLASS_COMMAND_STRUCT *),
85 ULONG configuration_number,
86 ULONG interface_number,
87 VOID *parameter)
88 {
89
90 UX_SLAVE_CLASS *class_inst;
91 UINT status;
92 UX_SLAVE_CLASS_COMMAND command;
93 UINT class_name_length = 0;
94 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
95 ULONG class_index;
96 #endif
97
98
99 /* Get the length of the class name (exclude null-terminator). */
100 status = _ux_utility_string_length_check(class_name, &class_name_length, UX_MAX_CLASS_NAME_LENGTH);
101 if (status)
102 return(status);
103
104 /* If trace is enabled, insert this event into the trace buffer. */
105 UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_CLASS_REGISTER, class_name, interface_number, parameter, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0)
106
107 /* Get first class. */
108 class_inst = _ux_system_slave -> ux_system_slave_class_array;
109
110 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
111 /* We need to parse the class table to find an empty spot. */
112 for (class_index = 0; class_index < _ux_system_slave -> ux_system_slave_max_class; class_index++)
113 {
114 #endif
115
116 /* Check if this class is already used. */
117 if (class_inst -> ux_slave_class_status == UX_UNUSED)
118 {
119
120 #if defined(UX_NAME_REFERENCED_BY_POINTER)
121 class_inst -> ux_slave_class_name = (const UCHAR *)class_name;
122 #else
123 /* We have found a free container for the class. Copy the name (with null-terminator). */
124 _ux_utility_memory_copy(class_inst -> ux_slave_class_name, class_name, class_name_length + 1); /* Use case of memcpy is verified. */
125 #endif
126
127 /* Memorize the entry function of this class. */
128 class_inst -> ux_slave_class_entry_function = class_entry_function;
129
130 /* Memorize the pointer to the application parameter. */
131 class_inst -> ux_slave_class_interface_parameter = parameter;
132
133 /* Memorize the configuration number on which this instance will be called. */
134 class_inst -> ux_slave_class_configuration_number = configuration_number;
135
136 /* Memorize the interface number on which this instance will be called. */
137 class_inst -> ux_slave_class_interface_number = interface_number;
138
139 /* Build all the fields of the Class Command to initialize the class. */
140 command.ux_slave_class_command_request = UX_SLAVE_CLASS_COMMAND_INITIALIZE;
141 command.ux_slave_class_command_parameter = parameter;
142 command.ux_slave_class_command_class_ptr = class_inst;
143
144 /* Call the class initialization routine. */
145 status = class_entry_function(&command);
146
147 /* Check the status. */
148 if (status != UX_SUCCESS)
149 return(status);
150
151 /* Make this class used now. */
152 class_inst -> ux_slave_class_status = UX_USED;
153
154 /* Return successful completion. */
155 return(UX_SUCCESS);
156 }
157
158 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
159 /* Move to the next class. */
160 class_inst ++;
161 }
162 #endif
163
164 /* No more entries in the class table. */
165 return(UX_MEMORY_INSUFFICIENT);
166 }
167
168
169 /**************************************************************************/
170 /* */
171 /* FUNCTION RELEASE */
172 /* */
173 /* _uxe_device_stack_class_register PORTABLE C */
174 /* 6.3.0 */
175 /* AUTHOR */
176 /* */
177 /* Chaoqiong Xiao, Microsoft Corporation */
178 /* */
179 /* DESCRIPTION */
180 /* */
181 /* This function checks errors in device stack class register function */
182 /* call. */
183 /* */
184 /* INPUT */
185 /* */
186 /* class_name Name of class */
187 /* class_function_entry Class entry function */
188 /* configuration_number Configuration # for this class*/
189 /* interface_number Interface # for this class */
190 /* parameter Parameter specific for class */
191 /* */
192 /* OUTPUT */
193 /* */
194 /* None */
195 /* */
196 /* CALLS */
197 /* */
198 /* _ux_device_stack_class_register Class register */
199 /* */
200 /* CALLED BY */
201 /* */
202 /* Application */
203 /* */
204 /* RELEASE HISTORY */
205 /* */
206 /* DATE NAME DESCRIPTION */
207 /* */
208 /* 10-31-2023 Chaoqiong Xiao Initial Version 6.3.0 */
209 /* */
210 /**************************************************************************/
_uxe_device_stack_class_register(UCHAR * class_name,UINT (* class_entry_function)(struct UX_SLAVE_CLASS_COMMAND_STRUCT *),ULONG configuration_number,ULONG interface_number,VOID * parameter)211 UINT _uxe_device_stack_class_register(UCHAR *class_name,
212 UINT (*class_entry_function)(struct UX_SLAVE_CLASS_COMMAND_STRUCT *),
213 ULONG configuration_number,
214 ULONG interface_number,
215 VOID *parameter)
216 {
217
218 /* Sanity checks. */
219 if ((class_name == UX_NULL) || (class_entry_function == UX_NULL))
220 return(UX_INVALID_PARAMETER);
221
222 /* Invoke class register function. */
223 return(_ux_device_stack_class_register(class_name, class_entry_function,
224 configuration_number, interface_number, parameter));
225 }
226