]> git.proxmox.com Git - mirror_edk2.git/blame - 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
CommitLineData
4b1bf81c 1/** @file\r
2The module is used to implement Usb Io PPI interfaces.\r
3\r
506560e7 4Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved. <BR>\r
4b1bf81c 5 \r
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
22 \r
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
108 PeiUsbDev->MaxPacketSize0,\r
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
4b1bf81c 129 return Status;\r
130}\r
131\r
132/**\r
133 Submits bulk transfer to a bulk endpoint of a USB device.\r
134 \r
135 @param PeiServices The pointer of EFI_PEI_SERVICES.\r
136 @param This The pointer of PEI_USB_IO_PPI.\r
137 @param DeviceEndpoint Endpoint number and its direction in bit 7.\r
138 @param Data A pointer to the buffer of data to transmit \r
139 from or receive into.\r
140 @param DataLength The lenght of the data buffer.\r
141 @param Timeout Indicates the maximum time, in millisecond, which the\r
ca243131
FT
142 transfer is allowed to complete. If Timeout is 0, then\r
143 the caller must wait for the function to be completed\r
144 until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.\r
4b1bf81c 145\r
146 @retval EFI_SUCCESS The transfer was completed successfully.\r
147 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.\r
148 @retval EFI_INVALID_PARAMETER Parameters are invalid.\r
149 @retval EFI_TIMEOUT The transfer failed due to timeout.\r
150 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.\r
151\r
152**/\r
153EFI_STATUS\r
154EFIAPI\r
155PeiUsbBulkTransfer (\r
156 IN EFI_PEI_SERVICES **PeiServices,\r
157 IN PEI_USB_IO_PPI *This,\r
158 IN UINT8 DeviceEndpoint,\r
159 IN OUT VOID *Data,\r
160 IN OUT UINTN *DataLength,\r
161 IN UINTN Timeout\r
162 )\r
163{\r
164 EFI_STATUS Status;\r
165 PEI_USB_DEVICE *PeiUsbDev;\r
166 UINT32 TransferResult;\r
167 UINTN MaxPacketLength;\r
168 UINT8 DataToggle;\r
169 UINT8 OldToggle;\r
170 EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;\r
171 UINT8 EndpointIndex;\r
172 VOID *Data2[EFI_USB_MAX_BULK_BUFFER_NUM];\r
173\r
174 PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);\r
175\r
176 EndpointDescriptor = NULL;\r
177 EndpointIndex = 0;\r
178 Data2[0] = Data;\r
179 Data2[1] = NULL;\r
180\r
181 while (EndpointIndex < MAX_ENDPOINT) {\r
182 Status = PeiUsbGetEndpointDescriptor (PeiServices, This, EndpointIndex, &EndpointDescriptor);\r
183 if (EFI_ERROR (Status)) {\r
184 return EFI_INVALID_PARAMETER;\r
185 }\r
186\r
187 if (EndpointDescriptor->EndpointAddress == DeviceEndpoint) {\r
188 break;\r
189 }\r
190\r
191 EndpointIndex++;\r
192 }\r
193\r
194 if (EndpointIndex == MAX_ENDPOINT) {\r
195 return EFI_INVALID_PARAMETER;\r
196 }\r
197\r
198 MaxPacketLength = PeiUsbDev->EndpointDesc[EndpointIndex]->MaxPacketSize;\r
199 if ((PeiUsbDev->DataToggle & (1 << EndpointIndex)) != 0) {\r
200 DataToggle = 1;\r
201 } else {\r
202 DataToggle = 0;\r
203 }\r
204\r
205 OldToggle = DataToggle;\r
206\r
207 if (PeiUsbDev->Usb2HcPpi != NULL) {\r
208 Status = PeiUsbDev->Usb2HcPpi->BulkTransfer (\r
209 PeiServices,\r
210 PeiUsbDev->Usb2HcPpi,\r
211 PeiUsbDev->DeviceAddress,\r
212 DeviceEndpoint,\r
213 PeiUsbDev->DeviceSpeed,\r
214 MaxPacketLength,\r
215 Data2,\r
216 DataLength,\r
217 &DataToggle,\r
218 Timeout,\r
219 &(PeiUsbDev->Translator),\r
220 &TransferResult\r
221 );\r
222 } else {\r
223 Status = PeiUsbDev->UsbHcPpi->BulkTransfer (\r
224 PeiServices,\r
225 PeiUsbDev->UsbHcPpi,\r
226 PeiUsbDev->DeviceAddress,\r
227 DeviceEndpoint,\r
228 (UINT8) MaxPacketLength,\r
229 Data,\r
230 DataLength,\r
231 &DataToggle,\r
232 Timeout,\r
233 &TransferResult\r
234 );\r
235 }\r
236\r
237 if (OldToggle != DataToggle) {\r
506560e7 238 PeiUsbDev->DataToggle = (UINT16) (PeiUsbDev->DataToggle ^ (1 << EndpointIndex));\r
4b1bf81c 239 }\r
240\r
241 return Status;\r
242}\r
243\r
244/**\r
245 Get the usb interface descriptor.\r
246\r
247 @param PeiServices General-purpose services that are available to every PEIM.\r
248 @param This Indicates the PEI_USB_IO_PPI instance.\r
249 @param InterfaceDescriptor Request interface descriptor.\r
250\r
251\r
252 @retval EFI_SUCCESS Usb interface descriptor is obtained successfully.\r
253\r
254**/\r
255EFI_STATUS\r
256EFIAPI\r
257PeiUsbGetInterfaceDescriptor (\r
258 IN EFI_PEI_SERVICES **PeiServices,\r
259 IN PEI_USB_IO_PPI *This,\r
260 OUT EFI_USB_INTERFACE_DESCRIPTOR **InterfaceDescriptor\r
261 )\r
262{\r
263 PEI_USB_DEVICE *PeiUsbDev;\r
264 PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);\r
265 *InterfaceDescriptor = PeiUsbDev->InterfaceDesc;\r
266 return EFI_SUCCESS;\r
267}\r
268\r
269/**\r
270 Get the usb endpoint descriptor.\r
271\r
272 @param PeiServices General-purpose services that are available to every PEIM.\r
273 @param This Indicates the PEI_USB_IO_PPI instance.\r
274 @param EndpointIndex The valid index of the specified endpoint.\r
275 @param EndpointDescriptor Request endpoint descriptor.\r
276\r
277 @retval EFI_SUCCESS Usb endpoint descriptor is obtained successfully.\r
278 @retval EFI_NOT_FOUND Usb endpoint descriptor is NOT found.\r
279\r
280**/\r
281EFI_STATUS\r
282EFIAPI\r
283PeiUsbGetEndpointDescriptor (\r
284 IN EFI_PEI_SERVICES **PeiServices,\r
285 IN PEI_USB_IO_PPI *This,\r
286 IN UINT8 EndpointIndex,\r
287 OUT EFI_USB_ENDPOINT_DESCRIPTOR **EndpointDescriptor\r
288 )\r
289{\r
290 PEI_USB_DEVICE *PeiUsbDev;\r
291\r
292 PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);\r
293\r
294 ASSERT (EndpointDescriptor != NULL);\r
295\r
296 //\r
297 // The valid range of EndpointIndex is 0..15\r
298 // If EndpointIndex is lesser than 15 but larger than the number of interfaces,\r
299 // a EFI_NOT_FOUND should be returned\r
300 //\r
301 ASSERT (EndpointIndex <= 15);\r
302\r
303 if (EndpointIndex >= PeiUsbDev->InterfaceDesc->NumEndpoints) {\r
304 return EFI_NOT_FOUND;\r
305 }\r
306\r
307 *EndpointDescriptor = PeiUsbDev->EndpointDesc[EndpointIndex];\r
308\r
309 return EFI_SUCCESS;\r
310}\r
311\r
312/**\r
313 Reset the port and re-configure the usb device.\r
314\r
315 @param PeiServices General-purpose services that are available to every PEIM.\r
316 @param This Indicates the PEI_USB_IO_PPI instance.\r
317\r
318 @retval EFI_SUCCESS Usb device is reset and configured successfully.\r
319 @retval Others Other failure occurs.\r
320\r
321**/\r
322EFI_STATUS\r
323EFIAPI\r
324PeiUsbPortReset (\r
325 IN EFI_PEI_SERVICES **PeiServices,\r
326 IN PEI_USB_IO_PPI *This\r
327 )\r
328{\r
329 PEI_USB_DEVICE *PeiUsbDev;\r
330 EFI_STATUS Status;\r
331 UINT8 Address;\r
332\r
333 PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);\r
334\r
335 ResetRootPort (\r
336 PeiServices,\r
337 PeiUsbDev->UsbHcPpi,\r
338 PeiUsbDev->Usb2HcPpi,\r
339 PeiUsbDev->DeviceAddress,\r
340 0\r
341 );\r
342\r
343 //\r
344 // Set address\r
345 //\r
346 Address = PeiUsbDev->DeviceAddress;\r
347 PeiUsbDev->DeviceAddress = 0;\r
348\r
349 Status = PeiUsbSetDeviceAddress (\r
350 PeiServices,\r
351 This,\r
352 Address\r
353 );\r
354\r
355 if (EFI_ERROR (Status)) {\r
356 return Status;\r
357 }\r
358\r
359 PeiUsbDev->DeviceAddress = Address;\r
360\r
361 //\r
362 // Set default configuration\r
363 //\r
364 Status = PeiUsbSetConfiguration (\r
365 PeiServices,\r
366 This\r
367 );\r
368\r
369 return Status;\r
370}\r