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