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 /** USBX Component */
15 /** */
16 /** Device CDC_ECM Class */
17 /** */
18 /**************************************************************************/
19 /**************************************************************************/
20
21 #define UX_SOURCE_CODE
22
23
24 /* Include necessary system files. */
25
26 #include "ux_api.h"
27 #include "ux_device_class_cdc_ecm.h"
28 #include "ux_device_stack.h"
29
30
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _ux_device_class_cdc_ecm_initialize PORTABLE C */
36 /* 6.2.0 */
37 /* AUTHOR */
38 /* */
39 /* Chaoqiong Xiao, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function initializes the USB CDC_ECM device. */
44 /* */
45 /* INPUT */
46 /* */
47 /* command Pointer to cdc_ecm command */
48 /* */
49 /* OUTPUT */
50 /* */
51 /* Completion Status */
52 /* */
53 /* CALLS */
54 /* */
55 /* _ux_utility_memory_allocate Allocate memory */
56 /* _ux_utility_memory_free Free memory */
57 /* _ux_utility_mutex_create Create Mutex */
58 /* _ux_device_mutex_delete Delete Mutex */
59 /* _ux_utility_event_flags_create Create Flag group */
60 /* _ux_utility_event_flags_delete Delete Flag group */
61 /* _ux_device_thread_create Create Thread */
62 /* _ux_device_thread_delete Delete Thread */
63 /* */
64 /* CALLED BY */
65 /* */
66 /* USBX Source Code */
67 /* */
68 /* RELEASE HISTORY */
69 /* */
70 /* DATE NAME DESCRIPTION */
71 /* */
72 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
73 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
74 /* verified memset and memcpy */
75 /* cases, used UX prefix to */
76 /* refer to TX symbols instead */
77 /* of using them directly, */
78 /* resulting in version 6.1 */
79 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
80 /* refined macros names, */
81 /* resulting in version 6.1.10 */
82 /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */
83 /* fixed standalone compile, */
84 /* resulting in version 6.1.11 */
85 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
86 /* fixed parameter/variable */
87 /* names conflict C++ keyword, */
88 /* resulting in version 6.1.12 */
89 /* 10-31-2022 Chaoqiong Xiao Modified comment(s), */
90 /* removed internal NX pool, */
91 /* resulting in version 6.2.0 */
92 /* */
93 /**************************************************************************/
_ux_device_class_cdc_ecm_initialize(UX_SLAVE_CLASS_COMMAND * command)94 UINT _ux_device_class_cdc_ecm_initialize(UX_SLAVE_CLASS_COMMAND *command)
95 {
96 #if defined(UX_DEVICE_STANDALONE)
97 UX_PARAMETER_NOT_USED(command);
98 return(UX_FUNCTION_NOT_SUPPORTED);
99 #else
100
101 UX_SLAVE_CLASS_CDC_ECM *cdc_ecm;
102 UX_SLAVE_CLASS_CDC_ECM_PARAMETER *cdc_ecm_parameter;
103 UX_SLAVE_CLASS *class_ptr;
104 UINT status;
105
106
107 /* Get the class container. */
108 class_ptr = command -> ux_slave_class_command_class_ptr;
109
110 /* Create an instance of the device cdc_ecm class. */
111 cdc_ecm = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_CDC_ECM));
112
113 /* Check for successful allocation. */
114 if (cdc_ecm == UX_NULL)
115 return(UX_MEMORY_INSUFFICIENT);
116
117 /* Create a mutex to protect the CDC_ECM thread and the application messing up the transmit queue. */
118 status = _ux_utility_mutex_create(&cdc_ecm -> ux_slave_class_cdc_ecm_mutex, "ux_slave_class_cdc_ecm_mutex");
119 if (status != UX_SUCCESS)
120 {
121 _ux_utility_memory_free(cdc_ecm);
122 return(UX_MUTEX_ERROR);
123 }
124
125 /* Assume good result. */
126 status = UX_SUCCESS;
127
128 /* Allocate some memory for the bulk out thread stack. */
129 cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread_stack =
130 _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE);
131 if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread_stack == UX_NULL)
132 status = (UX_MEMORY_INSUFFICIENT);
133
134 /* Allocate some memory for the interrupt thread stack. */
135 if (status == UX_SUCCESS)
136 {
137 cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread_stack =
138 _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE);
139
140 /* Check for successful allocation. */
141 if (cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread_stack == UX_NULL)
142 status = (UX_MEMORY_INSUFFICIENT);
143 }
144
145 /* Allocate some memory for the bulk in thread stack. */
146 if (status == UX_SUCCESS)
147 {
148 cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread_stack =
149 _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE);
150
151 /* Check for successful allocation. */
152 if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread_stack == UX_NULL)
153 status = (UX_MEMORY_INSUFFICIENT);
154 }
155
156 /* Interrupt endpoint treatment needs to be running in a different thread. So start
157 a new thread. We pass a pointer to the cdc_ecm instance to the new thread. This thread
158 does not start until we have a instance of the class. */
159 if (status == UX_SUCCESS)
160 {
161 status = _ux_device_thread_create(&cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread , "ux_slave_class_cdc_ecm_interrupt_thread",
162 _ux_device_class_cdc_ecm_interrupt_thread,
163 (ULONG) (ALIGN_TYPE) class_ptr, (VOID *) cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread_stack ,
164 UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS,
165 UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START);
166 if (status != UX_SUCCESS)
167 status = (UX_THREAD_ERROR);
168 }
169
170 UX_THREAD_EXTENSION_PTR_SET(&(cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread), class_ptr)
171
172 /* Check the creation of this thread. */
173 if (status == UX_SUCCESS)
174 {
175
176 /* Bulk endpoint treatment needs to be running in a different thread. So start
177 a new thread. We pass a pointer to the cdc_ecm instance to the new thread. This thread
178 does not start until we have a instance of the class. */
179 status = _ux_device_thread_create(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread , "ux_slave_class_cdc_ecm_bulkout_thread",
180 _ux_device_class_cdc_ecm_bulkout_thread,
181 (ULONG) (ALIGN_TYPE) class_ptr, (VOID *) cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread_stack ,
182 UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS,
183 UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START);
184 if (status != UX_SUCCESS)
185 status = (UX_THREAD_ERROR);
186 else
187 {
188
189 UX_THREAD_EXTENSION_PTR_SET(&(cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread), class_ptr)
190
191 /* Bulk endpoint treatment needs to be running in a different thread. So start
192 a new thread. We pass a pointer to the cdc_ecm instance to the new thread. This thread
193 does not start until we have a instance of the class. */
194 status = _ux_device_thread_create(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread , "ux_slave_class_cdc_ecm_bulkin_thread",
195 _ux_device_class_cdc_ecm_bulkin_thread,
196 (ULONG) (ALIGN_TYPE) class_ptr, (VOID *) cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread_stack ,
197 UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS,
198 UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START);
199 if (status != UX_SUCCESS)
200 status = (UX_THREAD_ERROR);
201 else
202 {
203
204 UX_THREAD_EXTENSION_PTR_SET(&(cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread), class_ptr)
205
206 /* Create a event flag group for the cdc_ecm class to synchronize with the event interrupt thread. */
207 status = _ux_utility_event_flags_create(&cdc_ecm -> ux_slave_class_cdc_ecm_event_flags_group, "ux_device_class_cdc_ecm_event_flag");
208 if (status != UX_SUCCESS)
209 status = (UX_EVENT_ERROR);
210 else
211 {
212
213 /* Save the address of the CDC_ECM instance inside the CDC_ECM container. */
214 class_ptr -> ux_slave_class_instance = (VOID *) cdc_ecm;
215
216 /* Get the pointer to the application parameters for the cdc_ecm class. */
217 cdc_ecm_parameter = command -> ux_slave_class_command_parameter;
218
219 /* Store the start and stop signals if needed by the application. */
220 cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_activate = cdc_ecm_parameter -> ux_slave_class_cdc_ecm_instance_activate;
221 cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_deactivate = cdc_ecm_parameter -> ux_slave_class_cdc_ecm_instance_deactivate;
222
223 /* Copy the local node ID. */
224 _ux_utility_memory_copy(cdc_ecm -> ux_slave_class_cdc_ecm_local_node_id, cdc_ecm_parameter -> ux_slave_class_cdc_ecm_parameter_local_node_id,
225 UX_DEVICE_CLASS_CDC_ECM_NODE_ID_LENGTH); /* Use case of memcpy is verified. */
226
227 /* Copy the remote node ID. */
228 _ux_utility_memory_copy(cdc_ecm -> ux_slave_class_cdc_ecm_remote_node_id, cdc_ecm_parameter -> ux_slave_class_cdc_ecm_parameter_remote_node_id,
229 UX_DEVICE_CLASS_CDC_ECM_NODE_ID_LENGTH); /* Use case of memcpy is verified. */
230
231 /* Store the rest of the parameters as they are in the local instance. */
232 _ux_utility_memory_copy(&cdc_ecm -> ux_slave_class_cdc_ecm_parameter, cdc_ecm_parameter, sizeof (UX_SLAVE_CLASS_CDC_ECM_PARAMETER)); /* Use case of memcpy is verified. */
233
234 return(UX_SUCCESS);
235 }
236
237 _ux_device_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread);
238 }
239
240 _ux_device_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread);
241 }
242
243 _ux_device_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread);
244 }
245
246 /* Free allocated resources. */
247
248 if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread_stack)
249 _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread_stack);
250 if (cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread_stack)
251 _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread_stack);
252 if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread_stack)
253 _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread_stack);
254 _ux_device_mutex_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_mutex);
255 _ux_utility_memory_free(cdc_ecm);
256
257 /* Return completion status. */
258 return(status);
259 #endif
260 }
261