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_device_descriptor_read               PORTABLE C      */
37 /*                                                           6.1.10       */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Chaoqiong Xiao, Microsoft Corporation                               */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function reads the device descriptor.                          */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    device                                Pointer to device             */
49 /*                                                                        */
50 /*  OUTPUT                                                                */
51 /*                                                                        */
52 /*    Completion Status                                                   */
53 /*                                                                        */
54 /*  CALLS                                                                 */
55 /*                                                                        */
56 /*    _ux_host_stack_transfer_request       Process transfer request      */
57 /*    _ux_utility_descriptor_parse          Parse descriptor              */
58 /*    _ux_utility_memory_allocate           Allocate memory block         */
59 /*    _ux_utility_memory_free               Free memory block             */
60 /*                                                                        */
61 /*  CALLED BY                                                             */
62 /*                                                                        */
63 /*    USBX Components                                                     */
64 /*                                                                        */
65 /*  RELEASE HISTORY                                                       */
66 /*                                                                        */
67 /*    DATE              NAME                      DESCRIPTION             */
68 /*                                                                        */
69 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
70 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
71 /*                                            resulting in version 6.1    */
72 /*  10-15-2021     Chaoqiong Xiao           Modified comment(s),          */
73 /*                                            added bMaxPacketSize0 check,*/
74 /*                                            resulting in version 6.1.9  */
75 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
76 /*                                            added standalone support,   */
77 /*                                            added class code checking,  */
78 /*                                            resulting in version 6.1.10 */
79 /*                                                                        */
80 /**************************************************************************/
_ux_host_stack_device_descriptor_read(UX_DEVICE * device)81 UINT  _ux_host_stack_device_descriptor_read(UX_DEVICE *device)
82 {
83 
84 UX_TRANSFER     *transfer_request;
85 UINT            status;
86 UCHAR *         descriptor;
87 UX_ENDPOINT     *control_endpoint;
88 
89     /* If trace is enabled, insert this event into the trace buffer.  */
90     UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_DEVICE_DESCRIPTOR_READ, device, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0)
91 
92     /* Retrieve the pointer to the control endpoint.  */
93     control_endpoint =  &device -> ux_device_control_endpoint;
94     transfer_request =  &control_endpoint -> ux_endpoint_transfer_request;
95 
96     /* Need to allocate memory for the descriptor.  */
97     descriptor =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_DEVICE_DESCRIPTOR_LENGTH);
98     if (descriptor == UX_NULL)
99         return(UX_MEMORY_INSUFFICIENT);
100 
101     /* Create a transfer_request for the GET_DESCRIPTOR request. The first transfer_request asks
102        for the first 8 bytes only. This way we will know the real MaxPacketSize
103        value for the control endpoint.  */
104     transfer_request -> ux_transfer_request_data_pointer =      descriptor;
105     transfer_request -> ux_transfer_request_requested_length =  8;
106     transfer_request -> ux_transfer_request_function =          UX_GET_DESCRIPTOR;
107     transfer_request -> ux_transfer_request_type =              UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE;
108     transfer_request -> ux_transfer_request_value =             UX_DEVICE_DESCRIPTOR_ITEM << 8;
109     transfer_request -> ux_transfer_request_index =             0;
110 
111 #if defined(UX_HOST_STANDALONE)
112     device -> ux_device_enum_trans = transfer_request;
113     status = UX_SUCCESS;
114     return(status);
115 #else
116 
117     /* Send request to HCD layer.  */
118     status =  _ux_host_stack_transfer_request(transfer_request);
119 
120     /* Check for correct transfer and entire descriptor returned.  */
121     if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == 8))
122     {
123 
124         /* Parse the device descriptor and create the local descriptor.  */
125         _ux_utility_descriptor_parse(descriptor, _ux_system_device_descriptor_structure, UX_DEVICE_DESCRIPTOR_ENTRIES,
126                                                                                 (UCHAR *) &device -> ux_device_descriptor);
127     }
128     else
129     {
130 
131         /* Free all used resources.  */
132         _ux_utility_memory_free(descriptor);
133 
134         /* Return completion status.  */
135         return(status);
136     }
137 
138     /* Validate the bMaxPacketSize0.  */
139     if (device -> ux_device_descriptor.bMaxPacketSize0 != 8 &&
140         device -> ux_device_descriptor.bMaxPacketSize0 != 16 &&
141         device -> ux_device_descriptor.bMaxPacketSize0 != 32 &&
142         device -> ux_device_descriptor.bMaxPacketSize0 != 64)
143     {
144         _ux_utility_memory_free(descriptor);
145         return(UX_DESCRIPTOR_CORRUPTED);
146     }
147 
148 #if defined(UX_HOST_DEVICE_CLASS_CODE_VALIDATION_ENABLE)
149 
150     /* Validate the USB-IF bDeviceClass class code.  */
151     switch(device -> ux_device_descriptor.bDeviceClass)
152     {
153     case 0x00: /* Fall through.  */
154     case 0x02: /* Fall through.  */
155     case 0x09: /* Fall through.  */
156     case 0x11: /* Fall through.  */
157     case 0xDC: /* Fall through.  */
158     case 0xEF: /* Fall through.  */
159     case 0xFF:
160         break;
161     default:
162 
163         /* Invalid device class code.  */
164         _ux_utility_memory_free(descriptor);
165         return(UX_DESCRIPTOR_CORRUPTED);
166     }
167 #endif
168 
169     /* Update the max packet size value for the endpoint.  */
170     control_endpoint -> ux_endpoint_descriptor.wMaxPacketSize =  device -> ux_device_descriptor.bMaxPacketSize0;
171 
172     /* Create a transfer_request for the GET_DESCRIPTOR request. This time, we have the complete length */
173     transfer_request -> ux_transfer_request_data_pointer =      descriptor;
174     transfer_request -> ux_transfer_request_requested_length =  UX_DEVICE_DESCRIPTOR_LENGTH;
175     transfer_request -> ux_transfer_request_function =          UX_GET_DESCRIPTOR;
176     transfer_request -> ux_transfer_request_type =              UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE;
177     transfer_request -> ux_transfer_request_value =             UX_DEVICE_DESCRIPTOR_ITEM << 8;
178     transfer_request -> ux_transfer_request_index =             0;
179     transfer_request -> ux_transfer_request_packet_length =     device -> ux_device_descriptor.bMaxPacketSize0;
180 
181     /* Send request to HCD layer.  */
182     status =  _ux_host_stack_transfer_request(transfer_request);
183 
184     /* Check for correct transfer and entire descriptor returned.  */
185     if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == UX_DEVICE_DESCRIPTOR_LENGTH))
186     {
187 
188         /* Parse the device descriptor and create the local descriptor.  */
189         _ux_utility_descriptor_parse(descriptor, _ux_system_device_descriptor_structure, UX_DEVICE_DESCRIPTOR_ENTRIES,
190                                                                     (UCHAR *) &device -> ux_device_descriptor);
191     }
192     else
193     {
194 
195         /* Error trap. */
196         _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_DESCRIPTOR_CORRUPTED);
197 
198         /* If trace is enabled, insert this event into the trace buffer.  */
199         UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0)
200 
201         /* The device descriptor does not contain the right amount of data. Maybe corruption.  */
202         status =  UX_DESCRIPTOR_CORRUPTED;
203     }
204 
205     /* Free all used resources.  */
206     _ux_utility_memory_free(descriptor);
207 
208     /* Return completion status.  */
209     return(status);
210 #endif
211 }
212 
213