]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Usb/UsbBusPei/UsbIoPeim.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusPei / UsbIoPeim.c
1 /** @file
2 The module is used to implement Usb Io PPI interfaces.
3
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved. <BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "UsbPeim.h"
11 #include "PeiUsbLib.h"
12
13 /**
14 Submits control transfer to a target USB device.
15
16 @param PeiServices The pointer of EFI_PEI_SERVICES.
17 @param This The pointer of PEI_USB_IO_PPI.
18 @param Request USB device request to send.
19 @param Direction Specifies the data direction for the data stage.
20 @param Timeout Indicates the maximum timeout, in millisecond. If Timeout
21 is 0, then the caller must wait for the function to be
22 completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
23 @param Data Data buffer to be transmitted or received from USB device.
24 @param DataLength The size (in bytes) of the data buffer.
25
26 @retval EFI_SUCCESS Transfer was completed successfully.
27 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
28 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
29 @retval EFI_TIMEOUT Transfer failed due to timeout.
30 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
31
32 **/
33 EFI_STATUS
34 EFIAPI
35 PeiUsbControlTransfer (
36 IN EFI_PEI_SERVICES **PeiServices,
37 IN PEI_USB_IO_PPI *This,
38 IN EFI_USB_DEVICE_REQUEST *Request,
39 IN EFI_USB_DATA_DIRECTION Direction,
40 IN UINT32 Timeout,
41 IN OUT VOID *Data, OPTIONAL
42 IN UINTN DataLength OPTIONAL
43 )
44 {
45 EFI_STATUS Status;
46 PEI_USB_DEVICE *PeiUsbDev;
47 UINT32 TransferResult;
48 EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;
49 UINT8 EndpointIndex;
50
51 PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
52
53 EndpointDescriptor = NULL;
54 EndpointIndex = 0;
55
56 if ((Request->Request == USB_REQ_CLEAR_FEATURE) &&
57 (Request->RequestType == USB_DEV_CLEAR_FEATURE_REQ_TYPE_E) &&
58 (Request->Value == USB_FEATURE_ENDPOINT_HALT)) {
59 //
60 // Request->Index is the Endpoint Address, use it to get the Endpoint Index.
61 //
62 while (EndpointIndex < MAX_ENDPOINT) {
63 Status = PeiUsbGetEndpointDescriptor (PeiServices, This, EndpointIndex, &EndpointDescriptor);
64 if (EFI_ERROR (Status)) {
65 return EFI_INVALID_PARAMETER;
66 }
67
68 if (EndpointDescriptor->EndpointAddress == Request->Index) {
69 break;
70 }
71
72 EndpointIndex++;
73 }
74
75 if (EndpointIndex == MAX_ENDPOINT) {
76 return EFI_INVALID_PARAMETER;
77 }
78 }
79
80 if (PeiUsbDev->Usb2HcPpi != NULL) {
81 Status = PeiUsbDev->Usb2HcPpi->ControlTransfer (
82 PeiServices,
83 PeiUsbDev->Usb2HcPpi,
84 PeiUsbDev->DeviceAddress,
85 PeiUsbDev->DeviceSpeed,
86 PeiUsbDev->MaxPacketSize0,
87 Request,
88 Direction,
89 Data,
90 &DataLength,
91 Timeout,
92 &(PeiUsbDev->Translator),
93 &TransferResult
94 );
95 } else {
96 Status = PeiUsbDev->UsbHcPpi->ControlTransfer (
97 PeiServices,
98 PeiUsbDev->UsbHcPpi,
99 PeiUsbDev->DeviceAddress,
100 PeiUsbDev->DeviceSpeed,
101 (UINT8) PeiUsbDev->MaxPacketSize0,
102 Request,
103 Direction,
104 Data,
105 &DataLength,
106 Timeout,
107 &TransferResult
108 );
109 }
110
111 //
112 // Reset the endpoint toggle when endpoint stall is cleared
113 //
114 if ((Request->Request == USB_REQ_CLEAR_FEATURE) &&
115 (Request->RequestType == USB_DEV_CLEAR_FEATURE_REQ_TYPE_E) &&
116 (Request->Value == USB_FEATURE_ENDPOINT_HALT)) {
117 if ((PeiUsbDev->DataToggle & (1 << EndpointIndex)) != 0) {
118 PeiUsbDev->DataToggle = (UINT16) (PeiUsbDev->DataToggle ^ (1 << EndpointIndex));
119 }
120 }
121
122 DEBUG ((EFI_D_INFO, "PeiUsbControlTransfer: %r\n", Status));
123 return Status;
124 }
125
126 /**
127 Submits bulk transfer to a bulk endpoint of a USB device.
128
129 @param PeiServices The pointer of EFI_PEI_SERVICES.
130 @param This The pointer of PEI_USB_IO_PPI.
131 @param DeviceEndpoint Endpoint number and its direction in bit 7.
132 @param Data A pointer to the buffer of data to transmit
133 from or receive into.
134 @param DataLength The lenght of the data buffer.
135 @param Timeout Indicates the maximum time, in millisecond, which the
136 transfer is allowed to complete. If Timeout is 0, then
137 the caller must wait for the function to be completed
138 until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
139
140 @retval EFI_SUCCESS The transfer was completed successfully.
141 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
142 @retval EFI_INVALID_PARAMETER Parameters are invalid.
143 @retval EFI_TIMEOUT The transfer failed due to timeout.
144 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
145
146 **/
147 EFI_STATUS
148 EFIAPI
149 PeiUsbBulkTransfer (
150 IN EFI_PEI_SERVICES **PeiServices,
151 IN PEI_USB_IO_PPI *This,
152 IN UINT8 DeviceEndpoint,
153 IN OUT VOID *Data,
154 IN OUT UINTN *DataLength,
155 IN UINTN Timeout
156 )
157 {
158 EFI_STATUS Status;
159 PEI_USB_DEVICE *PeiUsbDev;
160 UINT32 TransferResult;
161 UINTN MaxPacketLength;
162 UINT8 DataToggle;
163 UINT8 OldToggle;
164 EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;
165 UINT8 EndpointIndex;
166 VOID *Data2[EFI_USB_MAX_BULK_BUFFER_NUM];
167
168 PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
169
170 EndpointDescriptor = NULL;
171 EndpointIndex = 0;
172 Data2[0] = Data;
173 Data2[1] = NULL;
174
175 while (EndpointIndex < MAX_ENDPOINT) {
176 Status = PeiUsbGetEndpointDescriptor (PeiServices, This, EndpointIndex, &EndpointDescriptor);
177 if (EFI_ERROR (Status)) {
178 return EFI_INVALID_PARAMETER;
179 }
180
181 if (EndpointDescriptor->EndpointAddress == DeviceEndpoint) {
182 break;
183 }
184
185 EndpointIndex++;
186 }
187
188 if (EndpointIndex == MAX_ENDPOINT) {
189 return EFI_INVALID_PARAMETER;
190 }
191
192 MaxPacketLength = PeiUsbDev->EndpointDesc[EndpointIndex]->MaxPacketSize;
193 if ((PeiUsbDev->DataToggle & (1 << EndpointIndex)) != 0) {
194 DataToggle = 1;
195 } else {
196 DataToggle = 0;
197 }
198
199 OldToggle = DataToggle;
200
201 if (PeiUsbDev->Usb2HcPpi != NULL) {
202 Status = PeiUsbDev->Usb2HcPpi->BulkTransfer (
203 PeiServices,
204 PeiUsbDev->Usb2HcPpi,
205 PeiUsbDev->DeviceAddress,
206 DeviceEndpoint,
207 PeiUsbDev->DeviceSpeed,
208 MaxPacketLength,
209 Data2,
210 DataLength,
211 &DataToggle,
212 Timeout,
213 &(PeiUsbDev->Translator),
214 &TransferResult
215 );
216 } else {
217 Status = PeiUsbDev->UsbHcPpi->BulkTransfer (
218 PeiServices,
219 PeiUsbDev->UsbHcPpi,
220 PeiUsbDev->DeviceAddress,
221 DeviceEndpoint,
222 (UINT8) MaxPacketLength,
223 Data,
224 DataLength,
225 &DataToggle,
226 Timeout,
227 &TransferResult
228 );
229 }
230
231 if (OldToggle != DataToggle) {
232 PeiUsbDev->DataToggle = (UINT16) (PeiUsbDev->DataToggle ^ (1 << EndpointIndex));
233 }
234
235 DEBUG ((EFI_D_INFO, "PeiUsbBulkTransfer: %r\n", Status));
236 return Status;
237 }
238
239 /**
240 Get the usb interface descriptor.
241
242 @param PeiServices General-purpose services that are available to every PEIM.
243 @param This Indicates the PEI_USB_IO_PPI instance.
244 @param InterfaceDescriptor Request interface descriptor.
245
246
247 @retval EFI_SUCCESS Usb interface descriptor is obtained successfully.
248
249 **/
250 EFI_STATUS
251 EFIAPI
252 PeiUsbGetInterfaceDescriptor (
253 IN EFI_PEI_SERVICES **PeiServices,
254 IN PEI_USB_IO_PPI *This,
255 OUT EFI_USB_INTERFACE_DESCRIPTOR **InterfaceDescriptor
256 )
257 {
258 PEI_USB_DEVICE *PeiUsbDev;
259 PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
260 *InterfaceDescriptor = PeiUsbDev->InterfaceDesc;
261 return EFI_SUCCESS;
262 }
263
264 /**
265 Get the usb endpoint descriptor.
266
267 @param PeiServices General-purpose services that are available to every PEIM.
268 @param This Indicates the PEI_USB_IO_PPI instance.
269 @param EndpointIndex The valid index of the specified endpoint.
270 @param EndpointDescriptor Request endpoint descriptor.
271
272 @retval EFI_SUCCESS Usb endpoint descriptor is obtained successfully.
273 @retval EFI_NOT_FOUND Usb endpoint descriptor is NOT found.
274
275 **/
276 EFI_STATUS
277 EFIAPI
278 PeiUsbGetEndpointDescriptor (
279 IN EFI_PEI_SERVICES **PeiServices,
280 IN PEI_USB_IO_PPI *This,
281 IN UINT8 EndpointIndex,
282 OUT EFI_USB_ENDPOINT_DESCRIPTOR **EndpointDescriptor
283 )
284 {
285 PEI_USB_DEVICE *PeiUsbDev;
286
287 PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
288
289 ASSERT (EndpointDescriptor != NULL);
290
291 //
292 // The valid range of EndpointIndex is 0..15
293 // If EndpointIndex is lesser than 15 but larger than the number of interfaces,
294 // a EFI_NOT_FOUND should be returned
295 //
296 ASSERT (EndpointIndex <= 15);
297
298 if (EndpointIndex >= PeiUsbDev->InterfaceDesc->NumEndpoints) {
299 return EFI_NOT_FOUND;
300 }
301
302 *EndpointDescriptor = PeiUsbDev->EndpointDesc[EndpointIndex];
303
304 return EFI_SUCCESS;
305 }
306
307 /**
308 Reset the port and re-configure the usb device.
309
310 @param PeiServices General-purpose services that are available to every PEIM.
311 @param This Indicates the PEI_USB_IO_PPI instance.
312
313 @retval EFI_SUCCESS Usb device is reset and configured successfully.
314 @retval Others Other failure occurs.
315
316 **/
317 EFI_STATUS
318 EFIAPI
319 PeiUsbPortReset (
320 IN EFI_PEI_SERVICES **PeiServices,
321 IN PEI_USB_IO_PPI *This
322 )
323 {
324 PEI_USB_DEVICE *PeiUsbDev;
325 EFI_STATUS Status;
326 UINT8 Address;
327
328 PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
329
330 ResetRootPort (
331 PeiServices,
332 PeiUsbDev->UsbHcPpi,
333 PeiUsbDev->Usb2HcPpi,
334 PeiUsbDev->DeviceAddress,
335 0
336 );
337
338 //
339 // Set address
340 //
341 Address = PeiUsbDev->DeviceAddress;
342 PeiUsbDev->DeviceAddress = 0;
343
344 Status = PeiUsbSetDeviceAddress (
345 PeiServices,
346 This,
347 Address
348 );
349
350 if (EFI_ERROR (Status)) {
351 return Status;
352 }
353
354 PeiUsbDev->DeviceAddress = Address;
355
356 //
357 // Set default configuration
358 //
359 Status = PeiUsbSetConfiguration (
360 PeiServices,
361 This
362 );
363
364 return Status;
365 }