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