1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** USBX Component */
17 /** */
18 /** Device Stack */
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_stack.h"
30
31
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _ux_device_stack_class_register PORTABLE C */
37 /* 6.1 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function registers a slave class to the slave stack. */
45 /* */
46 /* Note: The C string of class_name must be NULL-terminated and the */
47 /* length of it (without the NULL-terminator itself) must be no larger */
48 /* than UX_MAX_CLASS_NAME_LENGTH. */
49 /* */
50 /* INPUT */
51 /* */
52 /* class_name Name of class */
53 /* class_function_entry Class entry function */
54 /* configuration_number Configuration # for this class*/
55 /* interface_number Interface # for this class */
56 /* parameter Parameter specific for class */
57 /* */
58 /* OUTPUT */
59 /* */
60 /* Completion Status */
61 /* */
62 /* CALLS */
63 /* */
64 /* _ux_utility_string_length_check Check C string and return */
65 /* its length if null-terminated */
66 /* _ux_utility_memory_copy Memory copy */
67 /* */
68 /* CALLED BY */
69 /* */
70 /* Application */
71 /* */
72 /* RELEASE HISTORY */
73 /* */
74 /* DATE NAME DESCRIPTION */
75 /* */
76 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
77 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
78 /* optimized based on compile */
79 /* definitions, verified */
80 /* memset and memcpy cases, */
81 /* resulting in version 6.1 */
82 /* */
83 /**************************************************************************/
_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)84 UINT _ux_device_stack_class_register(UCHAR *class_name,
85 UINT (*class_entry_function)(struct UX_SLAVE_CLASS_COMMAND_STRUCT *),
86 ULONG configuration_number,
87 ULONG interface_number,
88 VOID *parameter)
89 {
90
91 UX_SLAVE_CLASS *class_inst;
92 UINT status;
93 UX_SLAVE_CLASS_COMMAND command;
94 UINT class_name_length = 0;
95 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
96 ULONG class_index;
97 #endif
98
99
100 /* Get the length of the class name (exclude null-terminator). */
101 status = _ux_utility_string_length_check(class_name, &class_name_length, UX_MAX_CLASS_NAME_LENGTH);
102 if (status)
103 return(status);
104
105 /* If trace is enabled, insert this event into the trace buffer. */
106 UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_CLASS_REGISTER, class_name, interface_number, parameter, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0)
107
108 /* Get first class. */
109 class_inst = _ux_system_slave -> ux_system_slave_class_array;
110
111 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
112 /* We need to parse the class table to find an empty spot. */
113 for (class_index = 0; class_index < _ux_system_slave -> ux_system_slave_max_class; class_index++)
114 {
115 #endif
116
117 /* Check if this class is already used. */
118 if (class_inst -> ux_slave_class_status == UX_UNUSED)
119 {
120
121 #if defined(UX_NAME_REFERENCED_BY_POINTER)
122 class_inst -> ux_slave_class_name = (const UCHAR *)class_name;
123 #else
124 /* We have found a free container for the class. Copy the name (with null-terminator). */
125 _ux_utility_memory_copy(class_inst -> ux_slave_class_name, class_name, class_name_length + 1); /* Use case of memcpy is verified. */
126 #endif
127
128 /* Memorize the entry function of this class. */
129 class_inst -> ux_slave_class_entry_function = class_entry_function;
130
131 /* Memorize the pointer to the application parameter. */
132 class_inst -> ux_slave_class_interface_parameter = parameter;
133
134 /* Memorize the configuration number on which this instance will be called. */
135 class_inst -> ux_slave_class_configuration_number = configuration_number;
136
137 /* Memorize the interface number on which this instance will be called. */
138 class_inst -> ux_slave_class_interface_number = interface_number;
139
140 /* Build all the fields of the Class Command to initialize the class. */
141 command.ux_slave_class_command_request = UX_SLAVE_CLASS_COMMAND_INITIALIZE;
142 command.ux_slave_class_command_parameter = parameter;
143 command.ux_slave_class_command_class_ptr = class_inst;
144
145 /* Call the class initialization routine. */
146 status = class_entry_function(&command);
147
148 /* Check the status. */
149 if (status != UX_SUCCESS)
150 return(status);
151
152 /* Make this class used now. */
153 class_inst -> ux_slave_class_status = UX_USED;
154
155 /* Return successful completion. */
156 return(UX_SUCCESS);
157 }
158
159 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
160 /* Move to the next class. */
161 class_inst ++;
162 }
163 #endif
164
165 /* No more entries in the class table. */
166 return(UX_MEMORY_INSUFFICIENT);
167 }
168
169