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 UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_MULC_ULONG(sizeof(UX_SLAVE_CLASS), UX_MAX_SLAVE_CLASS_DRIVER), UX_MAX_SLAVE_CLASS_DRIVER_mul_ovf)
31 
32 /* Define the names of all the USB Classes of USBX.  */
33 
34 UCHAR _ux_system_slave_class_storage_name[] =                               "ux_slave_class_storage";
35 UCHAR _ux_system_slave_class_cdc_acm_name[] =                               "ux_slave_class_cdc_acm";
36 UCHAR _ux_system_slave_class_dpump_name[] =                                 "ux_slave_class_dpump";
37 UCHAR _ux_system_slave_class_pima_name[] =                                  "ux_slave_class_pima";
38 UCHAR _ux_system_slave_class_hid_name[] =                                   "ux_slave_class_hid";
39 UCHAR _ux_system_slave_class_rndis_name[] =                                 "ux_slave_class_rndis";
40 UCHAR _ux_system_slave_class_cdc_ecm_name[] =                               "ux_slave_class_cdc_ecm";
41 UCHAR _ux_system_slave_class_dfu_name[] =                                   "ux_slave_class_dfu";
42 UCHAR _ux_system_slave_class_audio_name[] =                                 "ux_slave_class_audio";
43 
44 UCHAR _ux_system_device_class_printer_name[] =                              "ux_device_class_printer";
45 UCHAR _ux_system_device_class_ccid_name[] =                                 "ux_device_class_ccid";
46 UCHAR _ux_system_device_class_video_name[] =                                "ux_device_class_video";
47 
48 /* Define USBX Host variable.  */
49 UX_SYSTEM_SLAVE *_ux_system_slave;
50 
51 /**************************************************************************/
52 /*                                                                        */
53 /*  FUNCTION                                               RELEASE        */
54 /*                                                                        */
55 /*    _ux_device_stack_initialize                         PORTABLE C      */
56 /*                                                           6.3.0        */
57 /*  AUTHOR                                                                */
58 /*                                                                        */
59 /*    Chaoqiong Xiao, Microsoft Corporation                               */
60 /*                                                                        */
61 /*  DESCRIPTION                                                           */
62 /*                                                                        */
63 /*    This function initializes the generic portion of the device side of */
64 /*    USBX.                                                               */
65 /*                                                                        */
66 /*  INPUT                                                                 */
67 /*                                                                        */
68 /*    device_framework_high_speed           Pointer to high speed FW      */
69 /*    device_framework_length_high_speed    Length of high speed FW       */
70 /*    device_framework_full_speed           Pointer to full speed FW      */
71 /*    device_framework_length_full_speed    Length of full speed FW       */
72 /*    string_framework                      Pointer to string FW          */
73 /*    string_framework_length               Length of string FW           */
74 /*    language_id_framework                 Pointer to language ID FW     */
75 /*    language_id_framework_length          Length of language ID FW      */
76 /*    (ux_system_slave_change_function)     Pointer to callback function  */
77 /*                                            for device changes          */
78 /*                                                                        */
79 /*  OUTPUT                                                                */
80 /*                                                                        */
81 /*    Completion Status                                                   */
82 /*                                                                        */
83 /*  CALLS                                                                 */
84 /*                                                                        */
85 /*    _ux_utility_memory_allocate           Allocate memory               */
86 /*    _ux_utility_memory_free               Free memory                   */
87 /*    _ux_utility_semaphore_create          Create semaphore              */
88 /*    _ux_utility_semaphore_delete          Delete semaphore              */
89 /*                                                                        */
90 /*  CALLED BY                                                             */
91 /*                                                                        */
92 /*    Application                                                         */
93 /*                                                                        */
94 /*  RELEASE HISTORY                                                       */
95 /*                                                                        */
96 /*    DATE              NAME                      DESCRIPTION             */
97 /*                                                                        */
98 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
99 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
100 /*                                            optimized based on compile  */
101 /*                                            definitions,                */
102 /*                                            resulting in version 6.1    */
103 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
104 /*                                            added standalone support,   */
105 /*                                            added printer support,      */
106 /*                                            resulting in version 6.1.10 */
107 /*  04-25-2022     Chaoqiong Xiao           Modified comment(s),          */
108 /*                                            added CCID support,         */
109 /*                                            added video support,        */
110 /*                                            resulting in version 6.1.11 */
111 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s),          */
112 /*                                            added a new mode to manage  */
113 /*                                            endpoint buffer in classes, */
114 /*                                            resulting in version 6.3.0  */
115 /*                                                                        */
116 /**************************************************************************/
_ux_device_stack_initialize(UCHAR * device_framework_high_speed,ULONG device_framework_length_high_speed,UCHAR * device_framework_full_speed,ULONG device_framework_length_full_speed,UCHAR * string_framework,ULONG string_framework_length,UCHAR * language_id_framework,ULONG language_id_framework_length,UINT (* ux_system_slave_change_function)(ULONG))117 UINT  _ux_device_stack_initialize(UCHAR * device_framework_high_speed, ULONG device_framework_length_high_speed,
118                                   UCHAR * device_framework_full_speed, ULONG device_framework_length_full_speed,
119                                   UCHAR * string_framework, ULONG string_framework_length,
120                                   UCHAR * language_id_framework, ULONG language_id_framework_length,
121                                   UINT (*ux_system_slave_change_function)(ULONG))
122 {
123 UX_SLAVE_DEVICE                 *device;
124 UX_SLAVE_ENDPOINT               *endpoints_pool;
125 UX_SLAVE_INTERFACE              *interfaces_pool;
126 UX_SLAVE_TRANSFER               *transfer_request;
127 UINT                            status;
128 ULONG                           interfaces_found;
129 ULONG                           endpoints_found;
130 #if !defined(UX_DEVICE_INITIALIZE_FRAMEWORK_SCAN_DISABLE)
131 ULONG                           max_interface_number;
132 ULONG                           local_interfaces_found;
133 ULONG                           local_endpoints_found;
134 ULONG                           endpoints_in_interface_found;
135 UCHAR                           *device_framework;
136 ULONG                           device_framework_length;
137 UCHAR                           descriptor_type;
138 ULONG                           descriptor_length;
139 #endif
140 UCHAR                           *memory;
141 
142     /* If trace is enabled, insert this event into the trace buffer.  */
143     UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_INITIALIZE, 0, 0, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0)
144 
145     /* Get the pointer to the device. */
146     device =  &_ux_system_slave -> ux_system_slave_device;
147 
148     /* Store the high speed device framework address and length in the project structure.  */
149     _ux_system_slave -> ux_system_slave_device_framework_high_speed =             device_framework_high_speed;
150     _ux_system_slave -> ux_system_slave_device_framework_length_high_speed =      device_framework_length_high_speed;
151 
152     /* Store the string framework address and length in the project structure.  */
153     _ux_system_slave -> ux_system_slave_device_framework_full_speed =             device_framework_full_speed;
154     _ux_system_slave -> ux_system_slave_device_framework_length_full_speed =      device_framework_length_full_speed;
155 
156     /* Store the string framework address and length in the project structure.  */
157     _ux_system_slave -> ux_system_slave_string_framework =                         string_framework;
158     _ux_system_slave -> ux_system_slave_string_framework_length =                  string_framework_length;
159 
160     /* Store the language ID list in the project structure.  */
161     _ux_system_slave -> ux_system_slave_language_id_framework =                 language_id_framework;
162     _ux_system_slave -> ux_system_slave_language_id_framework_length =          language_id_framework_length;
163 
164     /* Store the max number of slave class drivers in the project structure.  */
165     UX_SYSTEM_DEVICE_MAX_CLASS_SET(UX_MAX_SLAVE_CLASS_DRIVER);
166 
167     /* Store the device state change function callback.  */
168     _ux_system_slave -> ux_system_slave_change_function =  ux_system_slave_change_function;
169 
170     /* Allocate memory for the classes.
171      * sizeof(UX_SLAVE_CLASS) * UX_MAX_SLAVE_CLASS_DRIVER) overflow is checked
172      * outside of the function.
173      */
174     memory =  _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS) * UX_MAX_SLAVE_CLASS_DRIVER);
175     if (memory == UX_NULL)
176         return(UX_MEMORY_INSUFFICIENT);
177 
178     /* Save this memory allocation in the USBX project.  */
179     _ux_system_slave -> ux_system_slave_class_array =  (UX_SLAVE_CLASS *) ((void *) memory);
180 
181     /* Allocate some memory for the Control Endpoint.  First get the address of the transfer request for the
182        control endpoint. */
183     transfer_request =  &device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request;
184 
185     /* Acquire a buffer for the size of the endpoint.  */
186     transfer_request -> ux_slave_transfer_request_data_pointer =
187           _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH);
188 
189     /* Ensure we have enough memory.  */
190     if (transfer_request -> ux_slave_transfer_request_data_pointer == UX_NULL)
191         status = UX_MEMORY_INSUFFICIENT;
192     else
193         status = UX_SUCCESS;
194 
195 #if defined(UX_DEVICE_INITIALIZE_FRAMEWORK_SCAN_DISABLE)
196 
197     /* No scan, just assign predefined value.  */
198     interfaces_found = UX_MAX_SLAVE_INTERFACES;
199     endpoints_found = UX_MAX_DEVICE_ENDPOINTS;
200 #else
201 
202     /* Reset all values we are using during the scanning of the framework.  */
203     interfaces_found                   =  0;
204     endpoints_found                    =  0;
205     max_interface_number               =  0;
206 
207     /* Go on to scan interfaces if no error.  */
208     if (status == UX_SUCCESS)
209     {
210 
211         /* We need to determine the maximum number of interfaces and endpoints declared in the device framework.
212         This mechanism requires that both framework behave the same way regarding the number of interfaces
213         and endpoints.  */
214         device_framework        =  _ux_system_slave -> ux_system_slave_device_framework_full_speed;
215         device_framework_length =  _ux_system_slave -> ux_system_slave_device_framework_length_full_speed;
216 
217         /* Reset all values we are using during the scanning of the framework.  */
218         local_interfaces_found             =  0;
219         local_endpoints_found              =  0;
220         endpoints_in_interface_found       =  0;
221 
222         /* Parse the device framework and locate interfaces and endpoint descriptor(s).  */
223         while (device_framework_length != 0)
224         {
225 
226             /* Get the length of this descriptor.  */
227             descriptor_length =  (ULONG) *device_framework;
228 
229             /* And its type.  */
230             descriptor_type =  *(device_framework + 1);
231 
232             /* Check if this is an endpoint descriptor.  */
233             switch(descriptor_type)
234             {
235 
236             case UX_INTERFACE_DESCRIPTOR_ITEM:
237 
238                 /* Check if this is alternate setting 0. If not, do not add another interface found.
239                 If this is alternate setting 0, reset the endpoints count for this interface.  */
240                 if (*(device_framework + 3) == 0)
241                 {
242 
243                     /* Add the cumulated number of endpoints in the previous interface.  */
244                     local_endpoints_found += endpoints_in_interface_found;
245 
246                     /* Read the number of endpoints for this alternate setting.  */
247                     endpoints_in_interface_found = (ULONG) *(device_framework + 4);
248 
249                     /* Increment the number of interfaces found in the current configuration.  */
250                     local_interfaces_found++;
251                 }
252                 else
253                 {
254 
255                     /* Compare the number of endpoints found in this non 0 alternate setting.  */
256                     if (endpoints_in_interface_found < (ULONG) *(device_framework + 4))
257 
258                         /* Adjust the number of maximum endpoints in this interface.  */
259                         endpoints_in_interface_found = (ULONG) *(device_framework + 4);
260                 }
261 
262                 /* Check and update max interface number.  */
263                 if (*(device_framework + 2) > max_interface_number)
264                     max_interface_number = *(device_framework + 2);
265 
266                 break;
267 
268             case UX_CONFIGURATION_DESCRIPTOR_ITEM:
269 
270                 /* Check if the number of interfaces found in this configuration is the maximum so far. */
271                 if (local_interfaces_found > interfaces_found)
272 
273                     /* We need to adjust the number of maximum interfaces.  */
274                     interfaces_found =  local_interfaces_found;
275 
276                 /* We have a new configuration. We need to reset the number of local interfaces. */
277                 local_interfaces_found =  0;
278 
279                 /* Add the cumulated number of endpoints in the previous interface.  */
280                 local_endpoints_found += endpoints_in_interface_found;
281 
282                 /* Check if the number of endpoints found in the previous configuration is the maximum so far. */
283                 if (local_endpoints_found > endpoints_found)
284 
285                     /* We need to adjust the number of maximum endpoints.  */
286                     endpoints_found =  local_endpoints_found;
287 
288                 /* We have a new configuration. We need to reset the number of local endpoints. */
289                 local_endpoints_found         =  0;
290                 endpoints_in_interface_found  =  0;
291 
292                 break;
293 
294             default:
295                 break;
296             }
297 
298             /* Adjust what is left of the device framework.  */
299             device_framework_length -=  descriptor_length;
300 
301             /* Point to the next descriptor.  */
302             device_framework +=  descriptor_length;
303         }
304 
305         /* Add the cumulated number of endpoints in the previous interface.  */
306         local_endpoints_found += endpoints_in_interface_found;
307 
308         /* Check if the number of endpoints found in the previous interface is the maximum so far. */
309         if (local_endpoints_found > endpoints_found)
310 
311             /* We need to adjust the number of maximum endpoints.  */
312             endpoints_found =  local_endpoints_found;
313 
314 
315         /* Check if the number of interfaces found in this configuration is the maximum so far. */
316         if (local_interfaces_found > interfaces_found)
317 
318             /* We need to adjust the number of maximum interfaces.  */
319             interfaces_found =  local_interfaces_found;
320 
321         /* We do a sanity check on the finding. At least there must be one interface but endpoints are
322         not necessary.  */
323         if (interfaces_found == 0)
324         {
325 
326             /* Error trap. */
327             _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_INIT, UX_DESCRIPTOR_CORRUPTED);
328 
329             /* If trace is enabled, insert this event into the trace buffer.  */
330             UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, device_framework, 0, 0, UX_TRACE_ERRORS, 0, 0)
331 
332             status = UX_DESCRIPTOR_CORRUPTED;
333         }
334 
335         /* We do a sanity check on the finding. Max interface number should not exceed limit.  */
336         if (status == UX_SUCCESS &&
337             max_interface_number >= UX_MAX_SLAVE_INTERFACES)
338         {
339 
340             /* Error trap. */
341             _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_INIT, UX_MEMORY_INSUFFICIENT);
342 
343             /* If trace is enabled, insert this event into the trace buffer.  */
344             UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, device_framework, 0, 0, UX_TRACE_ERRORS, 0, 0)
345 
346             status = UX_MEMORY_INSUFFICIENT;
347         }
348     }
349 #endif
350 
351     /* Go on to allocate interfaces pool if no error.  */
352     if (status == UX_SUCCESS)
353     {
354 
355         /* Memorize both pool sizes.  */
356         device -> ux_slave_device_interfaces_pool_number = interfaces_found;
357         device -> ux_slave_device_endpoints_pool_number  = endpoints_found;
358 
359         /* We assign a pool for the interfaces.  */
360         interfaces_pool =  _ux_utility_memory_allocate_mulc_safe(UX_NO_ALIGN, UX_REGULAR_MEMORY, interfaces_found, sizeof(UX_SLAVE_INTERFACE));
361         if (interfaces_pool == UX_NULL)
362             status = UX_MEMORY_INSUFFICIENT;
363         else
364 
365             /* Save the interface pool address in the device container.  */
366             device -> ux_slave_device_interfaces_pool =  interfaces_pool;
367     }
368 
369     /* Do we need an endpoint pool ?  */
370     if (endpoints_found != 0 && status == UX_SUCCESS)
371     {
372 
373         /* We assign a pool for the endpoints.  */
374         endpoints_pool =  _ux_utility_memory_allocate_mulc_safe(UX_NO_ALIGN, UX_REGULAR_MEMORY, endpoints_found, sizeof(UX_SLAVE_ENDPOINT));
375         if (endpoints_pool == UX_NULL)
376             status = UX_MEMORY_INSUFFICIENT;
377         else
378         {
379 
380             /* Save the endpoint pool address in the device container.  */
381             device -> ux_slave_device_endpoints_pool =  endpoints_pool;
382 
383             /* We need to assign a transfer buffer to each endpoint. Each endpoint is assigned the
384             maximum buffer size.  We also assign the semaphore used by the endpoint to synchronize transfer
385             completion. */
386             while (endpoints_pool < (device -> ux_slave_device_endpoints_pool + endpoints_found))
387             {
388 
389 #if UX_DEVICE_ENDPOINT_BUFFER_OWNER == 0
390 
391                 /* Obtain some memory.  */
392                 endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer =
393                                 _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, UX_SLAVE_REQUEST_DATA_MAX_LENGTH);
394 
395                 /* Ensure we could allocate memory.  */
396                 if (endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer == UX_NULL)
397                 {
398                     status = UX_MEMORY_INSUFFICIENT;
399                     break;
400                 }
401 #endif
402 
403                 /* Create the semaphore for the endpoint.  */
404                 status =  _ux_device_semaphore_create(&endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_semaphore,
405                                                     "ux_transfer_request_semaphore", 0);
406 
407                 /* Check completion status.  */
408                 if (status != UX_SUCCESS)
409                 {
410                     status = UX_SEMAPHORE_ERROR;
411                     break;
412                 }
413 
414                 /* Next endpoint.  */
415                 endpoints_pool++;
416             }
417         }
418     }
419     else
420         endpoints_pool = UX_NULL;
421 
422     /* Return successful completion.  */
423     if (status == UX_SUCCESS)
424         return(UX_SUCCESS);
425 
426     /* Free resources when there is error.  */
427 
428     /* Free device -> ux_slave_device_endpoints_pool.  */
429     if (endpoints_pool)
430     {
431 
432         /* In error cases creating endpoint resources, endpoints_pool is endpoint that failed.
433          * Previously allocated things should be freed.  */
434         while(endpoints_pool >= device -> ux_slave_device_endpoints_pool)
435         {
436 
437             /* Delete ux_slave_transfer_request_semaphore.  */
438             if (_ux_device_semaphore_created(&endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_semaphore))
439                 _ux_device_semaphore_delete(&endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_semaphore);
440 
441 #if UX_DEVICE_ENDPOINT_BUFFER_OWNER == 0
442 
443             /* Free ux_slave_transfer_request_data_pointer buffer.  */
444             if (endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer)
445                 _ux_utility_memory_free(endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer);
446 #endif
447 
448             /* Move to previous endpoint.  */
449             endpoints_pool --;
450         }
451 
452         _ux_utility_memory_free(device -> ux_slave_device_endpoints_pool);
453     }
454 
455     /* Free device -> ux_slave_device_interfaces_pool.  */
456     if (device -> ux_slave_device_interfaces_pool)
457         _ux_utility_memory_free(device -> ux_slave_device_interfaces_pool);
458 
459     /* Free device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer.  */
460     if (device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer)
461         _ux_utility_memory_free(device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer);
462 
463     /* Free _ux_system_slave -> ux_system_slave_class_array.  */
464     _ux_utility_memory_free(_ux_system_slave -> ux_system_slave_class_array);
465 
466     /* Return completion status.  */
467     return(status);
468 }
469 
470 
471 /**************************************************************************/
472 /*                                                                        */
473 /*  FUNCTION                                               RELEASE        */
474 /*                                                                        */
475 /*    _uxe_device_stack_initialize                        PORTABLE C      */
476 /*                                                           6.3.0        */
477 /*  AUTHOR                                                                */
478 /*                                                                        */
479 /*    Chaoqiong Xiao, Microsoft Corporation                               */
480 /*                                                                        */
481 /*  DESCRIPTION                                                           */
482 /*                                                                        */
483 /*    This function checks errors in device stack initialization          */
484 /*    function call.                                                      */
485 /*                                                                        */
486 /*  INPUT                                                                 */
487 /*                                                                        */
488 /*    class_name                            Name of class                 */
489 /*    class_function_entry                  Class entry function          */
490 /*                                                                        */
491 /*  OUTPUT                                                                */
492 /*                                                                        */
493 /*    None                                                                */
494 /*                                                                        */
495 /*  CALLS                                                                 */
496 /*                                                                        */
497 /*    _ux_device_stack_initialize           Device Stack Initialize       */
498 /*                                                                        */
499 /*  CALLED BY                                                             */
500 /*                                                                        */
501 /*    Application                                                         */
502 /*                                                                        */
503 /*  RELEASE HISTORY                                                       */
504 /*                                                                        */
505 /*    DATE              NAME                      DESCRIPTION             */
506 /*                                                                        */
507 /*  10-31-2023     Chaoqiong Xiao           Initial Version 6.3.0         */
508 /*                                                                        */
509 /**************************************************************************/
_uxe_device_stack_initialize(UCHAR * device_framework_high_speed,ULONG device_framework_length_high_speed,UCHAR * device_framework_full_speed,ULONG device_framework_length_full_speed,UCHAR * string_framework,ULONG string_framework_length,UCHAR * language_id_framework,ULONG language_id_framework_length,UINT (* ux_system_slave_change_function)(ULONG))510 UINT  _uxe_device_stack_initialize(UCHAR * device_framework_high_speed, ULONG device_framework_length_high_speed,
511                                   UCHAR * device_framework_full_speed, ULONG device_framework_length_full_speed,
512                                   UCHAR * string_framework, ULONG string_framework_length,
513                                   UCHAR * language_id_framework, ULONG language_id_framework_length,
514                                   UINT (*ux_system_slave_change_function)(ULONG))
515 {
516 
517     /* Sanity checks.  */
518     if (((device_framework_high_speed == UX_NULL) && (device_framework_length_high_speed != 0)) ||
519         (device_framework_full_speed == UX_NULL) || (device_framework_length_full_speed == 0) ||
520         ((string_framework == UX_NULL) && (string_framework_length != 0)) ||
521         (language_id_framework == UX_NULL) || (language_id_framework_length == 0))
522         return(UX_INVALID_PARAMETER);
523 
524     /* Invoke stack initialize function.  */
525     return(_ux_device_stack_initialize(device_framework_high_speed, device_framework_length_high_speed,
526                                        device_framework_full_speed, device_framework_length_full_speed,
527                                        string_framework, string_framework_length,
528                                        language_id_framework, language_id_framework_length,
529                                        ux_system_slave_change_function));
530 }
531