GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: core/src/ux_device_stack_initialize.c Lines: 110 117 94.0 %
Date: 2024-12-12 17:16:36 Branches: 61 77 79.2 %

Line Branch Exec Source
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
/**************************************************************************/
117
377
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
377
    device =  &_ux_system_slave -> ux_system_slave_device;
147
148
    /* Store the high speed device framework address and length in the project structure.  */
149
377
    _ux_system_slave -> ux_system_slave_device_framework_high_speed =             device_framework_high_speed;
150
377
    _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
377
    _ux_system_slave -> ux_system_slave_device_framework_full_speed =             device_framework_full_speed;
154
377
    _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
377
    _ux_system_slave -> ux_system_slave_string_framework =                         string_framework;
158
377
    _ux_system_slave -> ux_system_slave_string_framework_length =                  string_framework_length;
159
160
    /* Store the language ID list in the project structure.  */
161
377
    _ux_system_slave -> ux_system_slave_language_id_framework =                 language_id_framework;
162
377
    _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
377
    UX_SYSTEM_DEVICE_MAX_CLASS_SET(UX_MAX_SLAVE_CLASS_DRIVER);
166
167
    /* Store the device state change function callback.  */
168
377
    _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
377
    memory =  _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS) * UX_MAX_SLAVE_CLASS_DRIVER);
175
377
    if (memory == UX_NULL)
176
1
        return(UX_MEMORY_INSUFFICIENT);
177
178
    /* Save this memory allocation in the USBX project.  */
179
376
    _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
376
    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
376
    transfer_request -> ux_slave_transfer_request_data_pointer =
187
376
          _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
376
    if (transfer_request -> ux_slave_transfer_request_data_pointer == UX_NULL)
191
1
        status = UX_MEMORY_INSUFFICIENT;
192
    else
193
375
        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
376
    interfaces_found                   =  0;
204
376
    endpoints_found                    =  0;
205
376
    max_interface_number               =  0;
206
207
    /* Go on to scan interfaces if no error.  */
208
376
    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
375
        device_framework        =  _ux_system_slave -> ux_system_slave_device_framework_full_speed;
215
375
        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
375
        local_interfaces_found             =  0;
219
375
        local_endpoints_found              =  0;
220
375
        endpoints_in_interface_found       =  0;
221
222
        /* Parse the device framework and locate interfaces and endpoint descriptor(s).  */
223
3468
        while (device_framework_length != 0)
224
        {
225
226
            /* Get the length of this descriptor.  */
227
3093
            descriptor_length =  (ULONG) *device_framework;
228
229
            /* And its type.  */
230
3093
            descriptor_type =  *(device_framework + 1);
231
232
            /* Check if this is an endpoint descriptor.  */
233
3093
            switch(descriptor_type)
234
            {
235
236
661
            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
661
                if (*(device_framework + 3) == 0)
241
                {
242
243
                    /* Add the cumulated number of endpoints in the previous interface.  */
244
559
                    local_endpoints_found += endpoints_in_interface_found;
245
246
                    /* Read the number of endpoints for this alternate setting.  */
247
559
                    endpoints_in_interface_found = (ULONG) *(device_framework + 4);
248
249
                    /* Increment the number of interfaces found in the current configuration.  */
250
559
                    local_interfaces_found++;
251
                }
252
                else
253
                {
254
255
                    /* Compare the number of endpoints found in this non 0 alternate setting.  */
256
102
                    if (endpoints_in_interface_found < (ULONG) *(device_framework + 4))
257
258
                        /* Adjust the number of maximum endpoints in this interface.  */
259
94
                        endpoints_in_interface_found = (ULONG) *(device_framework + 4);
260
                }
261
262
                /* Check and update max interface number.  */
263
661
                if (*(device_framework + 2) > max_interface_number)
264
294
                    max_interface_number = *(device_framework + 2);
265
266
661
                break;
267
268
388
            case UX_CONFIGURATION_DESCRIPTOR_ITEM:
269
270
                /* Check if the number of interfaces found in this configuration is the maximum so far. */
271
388
                if (local_interfaces_found > interfaces_found)
272
273
                    /* We need to adjust the number of maximum interfaces.  */
274
8
                    interfaces_found =  local_interfaces_found;
275
276
                /* We have a new configuration. We need to reset the number of local interfaces. */
277
388
                local_interfaces_found =  0;
278
279
                /* Add the cumulated number of endpoints in the previous interface.  */
280
388
                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
388
                if (local_endpoints_found > endpoints_found)
284
285
                    /* We need to adjust the number of maximum endpoints.  */
286
11
                    endpoints_found =  local_endpoints_found;
287
288
                /* We have a new configuration. We need to reset the number of local endpoints. */
289
388
                local_endpoints_found         =  0;
290
388
                endpoints_in_interface_found  =  0;
291
292
388
                break;
293
294
2044
            default:
295
2044
                break;
296
            }
297
298
            /* Adjust what is left of the device framework.  */
299
3093
            device_framework_length -=  descriptor_length;
300
301
            /* Point to the next descriptor.  */
302
3093
            device_framework +=  descriptor_length;
303
        }
304
305
        /* Add the cumulated number of endpoints in the previous interface.  */
306
375
        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
375
        if (local_endpoints_found > endpoints_found)
310
311
            /* We need to adjust the number of maximum endpoints.  */
312
363
            endpoints_found =  local_endpoints_found;
313
314
315
        /* Check if the number of interfaces found in this configuration is the maximum so far. */
316
375
        if (local_interfaces_found > interfaces_found)
317
318
            /* We need to adjust the number of maximum interfaces.  */
319
368
            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
375
        if (interfaces_found == 0)
324
        {
325
326
            /* Error trap. */
327
1
            _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
1
            status = UX_DESCRIPTOR_CORRUPTED;
333
        }
334
335
        /* We do a sanity check on the finding. Max interface number should not exceed limit.  */
336

375
        if (status == UX_SUCCESS &&
337
            max_interface_number >= UX_MAX_SLAVE_INTERFACES)
338
        {
339
340
            /* Error trap. */
341
1
            _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
1
            status = UX_MEMORY_INSUFFICIENT;
347
        }
348
    }
349
#endif
350
351
    /* Go on to allocate interfaces pool if no error.  */
352
376
    if (status == UX_SUCCESS)
353
    {
354
355
        /* Memorize both pool sizes.  */
356
373
        device -> ux_slave_device_interfaces_pool_number = interfaces_found;
357
373
        device -> ux_slave_device_endpoints_pool_number  = endpoints_found;
358
359
        /* We assign a pool for the interfaces.  */
360
373
        interfaces_pool =  _ux_utility_memory_allocate_mulc_safe(UX_NO_ALIGN, UX_REGULAR_MEMORY, interfaces_found, sizeof(UX_SLAVE_INTERFACE));
361
373
        if (interfaces_pool == UX_NULL)
362
1
            status = UX_MEMORY_INSUFFICIENT;
363
        else
364
365
            /* Save the interface pool address in the device container.  */
366
372
            device -> ux_slave_device_interfaces_pool =  interfaces_pool;
367
    }
368
369
    /* Do we need an endpoint pool ?  */
370

376
    if (endpoints_found != 0 && status == UX_SUCCESS)
371
    {
372
373
        /* We assign a pool for the endpoints.  */
374
365
        endpoints_pool =  _ux_utility_memory_allocate_mulc_safe(UX_NO_ALIGN, UX_REGULAR_MEMORY, endpoints_found, sizeof(UX_SLAVE_ENDPOINT));
375
365
        if (endpoints_pool == UX_NULL)
376
1
            status = UX_MEMORY_INSUFFICIENT;
377
        else
378
        {
379
380
            /* Save the endpoint pool address in the device container.  */
381
364
            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
1121
            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
763
                endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer =
393
763
                                _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
763
                if (endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer == UX_NULL)
397
                {
398
3
                    status = UX_MEMORY_INSUFFICIENT;
399
3
                    break;
400
                }
401
#endif
402
403
                /* Create the semaphore for the endpoint.  */
404
760
                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
760
                if (status != UX_SUCCESS)
409
                {
410
3
                    status = UX_SEMAPHORE_ERROR;
411
3
                    break;
412
                }
413
414
                /* Next endpoint.  */
415
757
                endpoints_pool++;
416
            }
417
        }
418
    }
419
    else
420
11
        endpoints_pool = UX_NULL;
421
422
    /* Return successful completion.  */
423
376
    if (status == UX_SUCCESS)
424
365
        return(UX_SUCCESS);
425
426
    /* Free resources when there is error.  */
427
428
    /* Free device -> ux_slave_device_endpoints_pool.  */
429
11
    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
18
        while(endpoints_pool >= device -> ux_slave_device_endpoints_pool)
435
        {
436
437
            /* Delete ux_slave_transfer_request_semaphore.  */
438
12
            if (_ux_device_semaphore_created(&endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_semaphore))
439
6
                _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
12
            if (endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer)
445
9
                _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
12
            endpoints_pool --;
450
        }
451
452
6
        _ux_utility_memory_free(device -> ux_slave_device_endpoints_pool);
453
    }
454
455
    /* Free device -> ux_slave_device_interfaces_pool.  */
456
11
    if (device -> ux_slave_device_interfaces_pool)
457
9
        _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
11
    if (device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer)
461
10
        _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
11
    _ux_utility_memory_free(_ux_system_slave -> ux_system_slave_class_array);
465
466
    /* Return completion status.  */
467
11
    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
/**************************************************************************/
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
}