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 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_acm.h"
28 #include "ux_device_stack.h"
29
30
31 #if UX_OVERFLOW_CHECK_MULC_ULONG(UX_THREAD_STACK_SIZE, 2)
32 #error UX_THREAD_STACK_SIZE too large
33 #endif
34
35 /**************************************************************************/
36 /* */
37 /* FUNCTION RELEASE */
38 /* */
39 /* _ux_device_class_cdc_acm_initialize PORTABLE C */
40 /* 6.1.12 */
41 /* AUTHOR */
42 /* */
43 /* Chaoqiong Xiao, Microsoft Corporation */
44 /* */
45 /* DESCRIPTION */
46 /* */
47 /* This function initializes the USB CDC device. */
48 /* */
49 /* INPUT */
50 /* */
51 /* command Pointer to cdc_acm command */
52 /* */
53 /* OUTPUT */
54 /* */
55 /* Completion Status */
56 /* */
57 /* CALLS */
58 /* */
59 /* _ux_utility_memory_allocate Allocate memory */
60 /* _ux_utility_memory_free Free memory */
61 /* _ux_utility_mutex_create Create mutex */
62 /* _ux_device_mutex_delete Delete mutex */
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 /* resulting in version 6.1 */
75 /* 04-02-2021 Chaoqiong Xiao Modified comment(s), */
76 /* added macro to disable */
77 /* transmission support, */
78 /* moved transmission resource */
79 /* allocate to here (init), */
80 /* resulting in version 6.1.6 */
81 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
82 /* added standalone support, */
83 /* resulting in version 6.1.10 */
84 /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */
85 /* resulting in version 6.1.11 */
86 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
87 /* fixed parameter/variable */
88 /* names conflict C++ keyword, */
89 /* resulting in version 6.1.12 */
90 /* */
91 /**************************************************************************/
_ux_device_class_cdc_acm_initialize(UX_SLAVE_CLASS_COMMAND * command)92 UINT _ux_device_class_cdc_acm_initialize(UX_SLAVE_CLASS_COMMAND *command)
93 {
94
95 UX_SLAVE_CLASS_CDC_ACM *cdc_acm;
96 UX_SLAVE_CLASS_CDC_ACM_PARAMETER *cdc_acm_parameter;
97 UX_SLAVE_CLASS *class_ptr;
98 #if !defined(UX_DEVICE_STANDALONE)
99 UINT status;
100 #endif
101
102 /* Get the class container. */
103 class_ptr = command -> ux_slave_class_command_class_ptr;
104
105 /* Create an instance of the device cdc_acm class. */
106 cdc_acm = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_CDC_ACM));
107
108 /* Check for successful allocation. */
109 if (cdc_acm == UX_NULL)
110 return(UX_MEMORY_INSUFFICIENT);
111
112 /* Save the address of the CDC instance inside the CDC container. */
113 class_ptr -> ux_slave_class_instance = (VOID *) cdc_acm;
114
115 /* Get the pointer to the application parameters for the cdc_acm class. */
116 cdc_acm_parameter = command -> ux_slave_class_command_parameter;
117
118 /* Store the start and stop signals if needed by the application. */
119 cdc_acm -> ux_slave_class_cdc_acm_parameter.ux_slave_class_cdc_acm_instance_activate = cdc_acm_parameter -> ux_slave_class_cdc_acm_instance_activate;
120 cdc_acm -> ux_slave_class_cdc_acm_parameter.ux_slave_class_cdc_acm_instance_deactivate = cdc_acm_parameter -> ux_slave_class_cdc_acm_instance_deactivate;
121 cdc_acm -> ux_slave_class_cdc_acm_parameter.ux_slave_class_cdc_acm_parameter_change = cdc_acm_parameter -> ux_slave_class_cdc_acm_parameter_change;
122
123 #if !defined(UX_DEVICE_STANDALONE)
124
125 /* Create the Mutex for each endpoint as multiple threads cannot access each pipe at the same time. */
126 status = _ux_utility_mutex_create(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_in_mutex, "ux_slave_class_cdc_acm_in_mutex");
127
128 /* Check Mutex creation error. */
129 if(status != UX_SUCCESS)
130 {
131
132 /* Free the resources. */
133 _ux_utility_memory_free(cdc_acm);
134
135 /* Return fatal error. */
136 return(UX_MUTEX_ERROR);
137 }
138
139 /* Out Mutex. */
140 status = _ux_utility_mutex_create(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_out_mutex, "ux_slave_class_cdc_acm_out_mutex");
141
142 /* Check Mutex creation error. */
143 if(status != UX_SUCCESS)
144 {
145
146 /* Delete the endpoint IN mutex. */
147 _ux_device_mutex_delete(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_in_mutex);
148
149 /* Free the resources. */
150 _ux_utility_memory_free(cdc_acm);
151
152 /* Return fatal error. */
153 return(UX_MUTEX_ERROR);
154 }
155
156 #endif
157
158 /* Update the line coding fields with default values. */
159 cdc_acm -> ux_slave_class_cdc_acm_baudrate = UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_BAUDRATE;
160 cdc_acm -> ux_slave_class_cdc_acm_stop_bit = UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_STOP_BIT;
161 cdc_acm -> ux_slave_class_cdc_acm_parity = UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_PARITY;
162 cdc_acm -> ux_slave_class_cdc_acm_data_bit = UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_DATA_BIT;
163
164 #ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE
165
166 #if defined(UX_DEVICE_STANDALONE)
167
168 /* Set task function. */
169 class_ptr -> ux_slave_class_task_function = _ux_device_class_cdc_acm_tasks_run;
170 #else
171
172 /* We need to prepare the 2 threads for sending and receiving. */
173 /* Allocate some memory for the bulk out and in thread stack. */
174 cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack =
175 _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE * 2);
176
177 /* Check for successful allocation. */
178 if (cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack == UX_NULL)
179
180 /* Return the status to the caller. */
181 status = (UX_MEMORY_INSUFFICIENT);
182
183 /* If success, go on to create event flags. */
184 if (status == UX_SUCCESS)
185 {
186
187 /* Allocate some memory for the bulk in thread stack. */
188 cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread_stack =
189 cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack + UX_THREAD_STACK_SIZE;
190
191 /* Create a event flag group for the cdc_acm class to synchronize with the application writing event . */
192 status = _ux_utility_event_flags_create(
193 &cdc_acm -> ux_slave_class_cdc_acm_event_flags_group,
194 "ux_device_class_cdc_acm_event_flag");
195
196 /* Check status. */
197 if (status != UX_SUCCESS)
198 {
199 status = (UX_EVENT_ERROR);
200 }
201 }
202
203 /* If success, go on to create bulkin thread. */
204 if (status == UX_SUCCESS)
205 {
206
207 /* Bulk endpoint treatment needs to be running in a different thread. So start
208 a new thread. We pass a pointer to the cdc_acm instance to the new thread. This thread
209 does not start until we have a instance of the class. */
210 status = _ux_utility_thread_create(
211 &cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread,
212 "ux_slave_class_cdc_acm_bulkin_thread",
213 _ux_device_class_cdc_acm_bulkin_thread,
214 (ULONG) (ALIGN_TYPE) cdc_acm,
215 (VOID *) cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread_stack,
216 UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS,
217 UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START);
218
219 /* Check the creation of this thread. */
220 if (status != UX_SUCCESS)
221 {
222 status = (UX_THREAD_ERROR);
223 }
224 else
225 {
226 UX_THREAD_EXTENSION_PTR_SET(
227 &(cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread), cdc_acm)
228 }
229 }
230
231 /* If success, go on to create bulkout thread. */
232 if (status == UX_SUCCESS)
233 {
234
235 /* Bulk endpoint treatment needs to be running in a different thread. So start
236 a new thread. We pass a pointer to the cdc_acm instance to the new thread. This thread
237 does not start until we have a instance of the class. */
238 status = _ux_utility_thread_create(
239 &cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread,
240 "ux_slave_class_cdc_acm_bulkout_thread",
241 _ux_device_class_cdc_acm_bulkout_thread,
242 (ULONG) (ALIGN_TYPE) cdc_acm,
243 (VOID *) cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack,
244 UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS,
245 UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START);
246
247 /* Check the creation of this thread. */
248 if (status != UX_SUCCESS)
249 {
250 status = (UX_THREAD_ERROR);
251 }
252 else
253 {
254 UX_THREAD_EXTENSION_PTR_SET(
255 &(cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread), cdc_acm)
256 }
257 }
258
259 /* Check error. */
260 if (status != UX_SUCCESS)
261 {
262
263 /* Free resources and return error. */
264 if (cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread.tx_thread_id)
265 _ux_utility_thread_delete(&cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread);
266 if (cdc_acm -> ux_slave_class_cdc_acm_event_flags_group.tx_event_flags_group_id)
267 _ux_utility_event_flags_delete(&cdc_acm -> ux_slave_class_cdc_acm_event_flags_group);
268 if (cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack)
269 _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack);
270 _ux_device_mutex_delete(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_in_mutex);
271 _ux_device_mutex_delete(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_out_mutex);
272 _ux_utility_memory_free(cdc_acm);
273 return(status);
274 }
275
276 #endif
277 #endif
278
279 /* Return completion status. */
280 return(UX_SUCCESS);
281 }
282
283