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