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