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 /**************************************************************************/
15 /**                                                                       */
16 /** USBX Component                                                        */
17 /**                                                                       */
18 /**   Host Stack                                                          */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 
24 /* Include necessary system files.  */
25 
26 #define UX_SOURCE_CODE
27 
28 #include "ux_api.h"
29 #include "ux_host_stack.h"
30 
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _ux_host_stack_configuration_enumerate              PORTABLE C      */
37 /*                                                           6.1          */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Chaoqiong Xiao, Microsoft Corporation                               */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function reads the configuration descriptor, creates the       */
45 /*    configuration container(s) for the device, and enumerates all found */
46 /*    configurations.                                                     */
47 /*                                                                        */
48 /*    At this stage, only the containers for each subcomponents are       */
49 /*    linked. No configuration, interface or endpoints are active unless  */
50 /*    a class issues a SET_CONFIGURATION.                                 */
51 /*                                                                        */
52 /*  INPUT                                                                 */
53 /*                                                                        */
54 /*    device                                Pointer to device             */
55 /*                                                                        */
56 /*  OUTPUT                                                                */
57 /*                                                                        */
58 /*    Completion Status                                                   */
59 /*                                                                        */
60 /*  CALLS                                                                 */
61 /*                                                                        */
62 /*    _ux_host_stack_configuration_descriptor_parse                       */
63 /*                                          Parse configuration descriptor*/
64 /*    _ux_host_stack_configuration_instance_delete                        */
65 /*                                          Delete configuration instance */
66 /*    _ux_host_stack_new_configuration_create                             */
67 /*                                          Create new configuration      */
68 /*    _ux_host_stack_transfer_request       Process transfer request      */
69 /*    _ux_utility_descriptor_parse          Parse descriptor              */
70 /*    _ux_utility_memory_allocate           Allocate block of memory      */
71 /*    _ux_utility_memory_free               Free block of memory          */
72 /*                                                                        */
73 /*  CALLED BY                                                             */
74 /*                                                                        */
75 /*    USBX Components                                                     */
76 /*                                                                        */
77 /*  RELEASE HISTORY                                                       */
78 /*                                                                        */
79 /*    DATE              NAME                      DESCRIPTION             */
80 /*                                                                        */
81 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
82 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
83 /*                                            resulting in version 6.1    */
84 /*                                                                        */
85 /**************************************************************************/
_ux_host_stack_configuration_enumerate(UX_DEVICE * device)86 UINT  _ux_host_stack_configuration_enumerate(UX_DEVICE *device)
87 {
88 
89 UX_TRANSFER         *transfer_request;
90 UINT                status =  UX_ERROR;
91 UCHAR *             descriptor;
92 UX_ENDPOINT         *control_endpoint;
93 UX_CONFIGURATION    *configuration;
94 ULONG               nb_configurations;
95 ULONG               configuration_index;
96 
97     /* If trace is enabled, insert this event into the trace buffer.  */
98     UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_CONFIGURATION_ENUMERATE, device, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0)
99 
100     /* Retrieve the pointer to the control endpoint and its transfer_request.  */
101     control_endpoint =  &device -> ux_device_control_endpoint;
102     transfer_request =  &control_endpoint -> ux_endpoint_transfer_request;
103 
104     /* Need to allocate memory for the configuration descriptor the first time we read
105        only the configuration descriptor when we have the configuration descriptor, we have
106        the length of the entire configuration\interface\endpoint descriptors.  */
107     descriptor =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_CONFIGURATION_DESCRIPTOR_LENGTH);
108     if (descriptor == UX_NULL)
109         return(UX_MEMORY_INSUFFICIENT);
110 
111     /* There maybe multiple configurations for this device.  */
112     nb_configurations =  device -> ux_device_descriptor.bNumConfigurations;
113 
114     /* Parse all the configurations attached to the device. We start with the first index.
115        The index and the actual configuration value may be different according to the USB specification!  */
116     for (configuration_index = 0; configuration_index < nb_configurations; configuration_index++)
117     {
118 
119         /* Create a transfer_request for the GET_DESCRIPTOR request.  */
120         transfer_request -> ux_transfer_request_data_pointer =      descriptor;
121         transfer_request -> ux_transfer_request_requested_length =  UX_CONFIGURATION_DESCRIPTOR_LENGTH;
122         transfer_request -> ux_transfer_request_function =          UX_GET_DESCRIPTOR;
123         transfer_request -> ux_transfer_request_type =              UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE;
124         transfer_request -> ux_transfer_request_value =             configuration_index | (UINT)(UX_CONFIGURATION_DESCRIPTOR_ITEM << 8);
125         transfer_request -> ux_transfer_request_index =             0;
126 
127         /* Send request to HCD layer.  */
128         status =  _ux_host_stack_transfer_request(transfer_request);
129 
130         /* Check for correct transfer and entire descriptor returned.  */
131         if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == UX_CONFIGURATION_DESCRIPTOR_LENGTH))
132         {
133 
134             /* Allocate some memory for the container of this descriptor.  */
135             configuration =  _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_CONFIGURATION));
136 
137             /* Check to see if the block was allocated.  */
138             if (configuration != UX_NULL)
139             {
140 
141                 /* This configuration must be linked to the device.  */
142                 _ux_host_stack_new_configuration_create(device, configuration);
143 
144                 /* The descriptor is in a packed format, parse it locally.  */
145                 _ux_utility_descriptor_parse(descriptor, _ux_system_configuration_descriptor_structure,
146                                     UX_CONFIGURATION_DESCRIPTOR_ENTRIES, (UCHAR *) &configuration -> ux_configuration_descriptor);
147 
148                 /* Parse the device descriptor so that we can retrieve the length
149                     of the entire configuration.  */
150                 status =  _ux_host_stack_configuration_descriptor_parse(device, configuration, configuration_index);
151 
152                 /* Check the completion status.  */
153                 if (status != UX_SUCCESS)
154                 {
155                     /* Error, delete the configuration instance.  */
156                     _ux_host_stack_configuration_instance_delete(configuration);
157                 }
158             }
159             else
160             {
161 
162                 /* Cannot allocate configuration memory. Abort enumeration */
163                 status =  UX_MEMORY_INSUFFICIENT;
164 
165                 break;
166             }
167         }
168         else
169         {
170 
171             /* Error trap. */
172             _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_DESCRIPTOR_CORRUPTED);
173 
174             /* If trace is enabled, insert this event into the trace buffer.  */
175             UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0)
176 
177             /* The device descriptor does not contain the right amount of data. Maybe corruption.  */
178             status =  UX_DESCRIPTOR_CORRUPTED;
179 
180             break;
181         }
182 
183     }
184 
185     /* Free all used resources.  */
186     _ux_utility_memory_free(descriptor);
187 
188     /* Return completion status.  */
189     return(status);
190 }
191 
192