1 /** @file
2 Common Libarary  for PEI USB.
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   Get a given usb descriptor.
22 
23   @param  PeiServices        General-purpose services that are available to every PEIM.
24   @param  UsbIoPpi           Indicates the PEI_USB_IO_PPI instance.
25   @param  Value              Request Value.
26   @param  Index              Request Index.
27   @param  DescriptorLength   Request descriptor Length.
28   @param  Descriptor         Request descriptor.
29 
30 
31   @retval EFI_SUCCESS        Usb descriptor is obtained successfully.
32   @retval EFI_DEVICE_ERROR   Cannot get the usb descriptor due to a hardware error.
33   @retval Others             Other failure occurs.
34 
35 **/
36 EFI_STATUS
PeiUsbGetDescriptor(IN EFI_PEI_SERVICES ** PeiServices,IN PEI_USB_IO_PPI * UsbIoPpi,IN UINT16 Value,IN UINT16 Index,IN UINT16 DescriptorLength,OUT VOID * Descriptor)37 PeiUsbGetDescriptor (
38   IN  EFI_PEI_SERVICES         **PeiServices,
39   IN  PEI_USB_IO_PPI           *UsbIoPpi,
40   IN  UINT16                   Value,
41   IN  UINT16                   Index,
42   IN  UINT16                   DescriptorLength,
43   OUT VOID                     *Descriptor
44   )
45 {
46   EFI_USB_DEVICE_REQUEST  DevReq;
47 
48   ASSERT (UsbIoPpi != NULL);
49 
50   DevReq.RequestType  = USB_DEV_GET_DESCRIPTOR_REQ_TYPE;
51   DevReq.Request      = USB_DEV_GET_DESCRIPTOR;
52   DevReq.Value        = Value;
53   DevReq.Index        = Index;
54   DevReq.Length       = DescriptorLength;
55 
56   return UsbIoPpi->UsbControlTransfer (
57                      PeiServices,
58                      UsbIoPpi,
59                      &DevReq,
60                      EfiUsbDataIn,
61                      PcdGet32 (PcdUsbTransferTimeoutValue),
62                      Descriptor,
63                      DescriptorLength
64                      );
65 }
66 
67 /**
68   Set a usb device with a specified address.
69 
70   @param  PeiServices        General-purpose services that are available to every PEIM.
71   @param  UsbIoPpi           Indicates the PEI_USB_IO_PPI instance.
72   @param  AddressValue       The address to assign.
73 
74   @retval EFI_SUCCESS        Usb device address is set successfully.
75   @retval EFI_DEVICE_ERROR   Cannot set the usb address due to a hardware error.
76   @retval Others             Other failure occurs.
77 
78 **/
79 EFI_STATUS
PeiUsbSetDeviceAddress(IN EFI_PEI_SERVICES ** PeiServices,IN PEI_USB_IO_PPI * UsbIoPpi,IN UINT16 AddressValue)80 PeiUsbSetDeviceAddress (
81   IN EFI_PEI_SERVICES         **PeiServices,
82   IN PEI_USB_IO_PPI           *UsbIoPpi,
83   IN UINT16                   AddressValue
84   )
85 {
86   EFI_USB_DEVICE_REQUEST  DevReq;
87 
88   ASSERT (UsbIoPpi != NULL);
89 
90   DevReq.RequestType  = USB_DEV_SET_ADDRESS_REQ_TYPE;
91   DevReq.Request      = USB_DEV_SET_ADDRESS;
92   DevReq.Value        = AddressValue;
93   DevReq.Index        = 0;
94   DevReq.Length       = 0;
95 
96   return UsbIoPpi->UsbControlTransfer (
97                      PeiServices,
98                      UsbIoPpi,
99                      &DevReq,
100                      EfiUsbNoData,
101                      PcdGet32 (PcdUsbTransferTimeoutValue),
102                      NULL,
103                      0
104                      );
105 }
106 
107 /**
108   Clear a given usb feature.
109 
110   @param  PeiServices       General-purpose services that are available to every PEIM.
111   @param  UsbIoPpi          Indicates the PEI_USB_IO_PPI instance.
112   @param  Recipient         The recipient of ClearFeature Request, should be one of Device/Interface/Endpoint.
113   @param  Value             Request Value.
114   @param  Target            Request Index.
115 
116   @retval EFI_SUCCESS       Usb feature is cleared successfully.
117   @retval EFI_DEVICE_ERROR  Cannot clear the usb feature due to a hardware error.
118   @retval Others            Other failure occurs.
119 
120 **/
121 EFI_STATUS
PeiUsbClearDeviceFeature(IN EFI_PEI_SERVICES ** PeiServices,IN PEI_USB_IO_PPI * UsbIoPpi,IN EFI_USB_RECIPIENT Recipient,IN UINT16 Value,IN UINT16 Target)122 PeiUsbClearDeviceFeature (
123   IN EFI_PEI_SERVICES         **PeiServices,
124   IN PEI_USB_IO_PPI           *UsbIoPpi,
125   IN EFI_USB_RECIPIENT        Recipient,
126   IN UINT16                   Value,
127   IN UINT16                   Target
128   )
129 {
130   EFI_USB_DEVICE_REQUEST  DevReq;
131 
132   ASSERT (UsbIoPpi != NULL);
133 
134   switch (Recipient) {
135   case EfiUsbDevice:
136     DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_D;
137     break;
138 
139   case EfiUsbInterface:
140     DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_I;
141     break;
142 
143   case EfiUsbEndpoint:
144     DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_E;
145     break;
146   }
147 
148   DevReq.Request      = USB_DEV_CLEAR_FEATURE;
149   DevReq.Value        = Value;
150   DevReq.Index        = Target;
151   DevReq.Length       = 0;
152 
153   return UsbIoPpi->UsbControlTransfer (
154                      PeiServices,
155                      UsbIoPpi,
156                      &DevReq,
157                      EfiUsbNoData,
158                      PcdGet32 (PcdUsbTransferTimeoutValue),
159                      NULL,
160                      0
161                      );
162 }
163 
164 /**
165   Configure a usb device to Configuration 1.
166 
167   @param  PeiServices        General-purpose services that are available to every PEIM.
168   @param  UsbIoPpi           Indicates the PEI_USB_IO_PPI instance.
169 
170   @retval EFI_SUCCESS       Usb device is set to use Configuration 1 successfully.
171   @retval EFI_DEVICE_ERROR  Cannot set the usb device due to a hardware error.
172   @retval Others            Other failure occurs.
173 
174 **/
175 EFI_STATUS
PeiUsbSetConfiguration(IN EFI_PEI_SERVICES ** PeiServices,IN PEI_USB_IO_PPI * UsbIoPpi)176 PeiUsbSetConfiguration (
177   IN EFI_PEI_SERVICES         **PeiServices,
178   IN PEI_USB_IO_PPI           *UsbIoPpi
179   )
180 {
181   EFI_USB_DEVICE_REQUEST  DevReq;
182   ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
183 
184   DevReq.RequestType  = USB_DEV_SET_CONFIGURATION_REQ_TYPE;
185   DevReq.Request      = USB_DEV_SET_CONFIGURATION;
186   DevReq.Value        = 1;
187 
188   return UsbIoPpi->UsbControlTransfer (
189                      PeiServices,
190                      UsbIoPpi,
191                      &DevReq,
192                      EfiUsbNoData,
193                      PcdGet32 (PcdUsbTransferTimeoutValue),
194                      NULL,
195                      0
196                      );
197 }
198 
199 /**
200   Clear Endpoint Halt.
201 
202   @param  PeiServices       General-purpose services that are available to every PEIM.
203   @param  UsbIoPpi          Indicates the PEI_USB_IO_PPI instance.
204   @param  EndpointAddress   The endpoint address.
205 
206   @retval EFI_SUCCESS       Endpoint halt is cleared successfully.
207   @retval EFI_DEVICE_ERROR  Cannot clear the endpoint halt status due to a hardware error.
208   @retval Others            Other failure occurs.
209 
210 **/
211 EFI_STATUS
PeiUsbClearEndpointHalt(IN EFI_PEI_SERVICES ** PeiServices,IN PEI_USB_IO_PPI * UsbIoPpi,IN UINT8 EndpointAddress)212 PeiUsbClearEndpointHalt (
213   IN EFI_PEI_SERVICES         **PeiServices,
214   IN PEI_USB_IO_PPI           *UsbIoPpi,
215   IN UINT8                    EndpointAddress
216   )
217 {
218   EFI_STATUS                    Status;
219   EFI_USB_INTERFACE_DESCRIPTOR  *InterfaceDesc;
220   EFI_USB_ENDPOINT_DESCRIPTOR   *EndpointDescriptor;
221   UINT8                         EndpointIndex;
222 
223 
224   //
225   // Check its interface
226   //
227   Status = UsbIoPpi->UsbGetInterfaceDescriptor (
228                       PeiServices,
229                       UsbIoPpi,
230                       &InterfaceDesc
231                       );
232   if (EFI_ERROR (Status)) {
233     return Status;
234   }
235   for (EndpointIndex = 0; EndpointIndex < InterfaceDesc->NumEndpoints; EndpointIndex++) {
236     Status = UsbIoPpi->UsbGetEndpointDescriptor (PeiServices, UsbIoPpi, EndpointIndex, &EndpointDescriptor);
237     if (EFI_ERROR (Status)) {
238       return EFI_INVALID_PARAMETER;
239     }
240 
241     if (EndpointDescriptor->EndpointAddress == EndpointAddress) {
242       break;
243     }
244   }
245 
246   if (EndpointIndex == InterfaceDesc->NumEndpoints) {
247     return EFI_INVALID_PARAMETER;
248   }
249 
250   Status = PeiUsbClearDeviceFeature (
251             PeiServices,
252             UsbIoPpi,
253             EfiUsbEndpoint,
254             EfiUsbEndpointHalt,
255             EndpointAddress
256             );
257 
258   return Status;
259 }
260 
261 /**
262   Judge if the port is connected with a usb device or not.
263 
264   @param  PortStatus  The usb port status gotten.
265 
266   @retval TRUE        A usb device is connected with the port.
267   @retval FALSE       No usb device is connected with the port.
268 
269 **/
270 BOOLEAN
IsPortConnect(IN UINT16 PortStatus)271 IsPortConnect (
272   IN UINT16  PortStatus
273   )
274 {
275   //
276   // return the bit 0 value of PortStatus
277   //
278   if ((PortStatus & USB_PORT_STAT_CONNECTION) != 0) {
279     return TRUE;
280   } else {
281     return FALSE;
282   }
283 }
284 
285 /**
286   Judge if the port is connected with a low-speed usb device or not.
287 
288   @param  PortStatus  The usb port status gotten.
289 
290   @retval TRUE        A low-speed usb device is connected with the port.
291   @retval FALSE       No low-speed usb device is connected with the port.
292 
293 **/
294 BOOLEAN
IsPortLowSpeedDeviceAttached(IN UINT16 PortStatus)295 IsPortLowSpeedDeviceAttached (
296   IN UINT16  PortStatus
297   )
298 {
299   //
300   // return the bit 9 value of PortStatus
301   //
302   if ((PortStatus & USB_PORT_STAT_LOW_SPEED) != 0) {
303     return TRUE;
304   } else {
305     return FALSE;
306   }
307 }
308 
309 /**
310   Judge if the port is in "connection change" status or not.
311 
312   @param  PortChangeStatus  The usb port change status gotten.
313 
314   @retval TRUE              The port is in "connection change" status.
315   @retval FALSE             The port is NOT in "connection change" status.
316 
317 **/
318 BOOLEAN
IsPortConnectChange(IN UINT16 PortChangeStatus)319 IsPortConnectChange (
320   IN UINT16  PortChangeStatus
321   )
322 {
323   //
324   // return the bit 0 value of PortChangeStatus
325   //
326   if ((PortChangeStatus & USB_PORT_STAT_C_CONNECTION) != 0) {
327     return TRUE;
328   } else {
329     return FALSE;
330   }
331 }
332