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