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