1 /** @file
2 
3   The library provides the USB Standard Device Requests defined
4   in Usb specification 9.4 section.
5 
6   Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR>
7   This program and the accompanying materials are
8   licensed and made available under the terms and conditions of
9   the BSD License which accompanies this distribution.  The full
10   text of the license may be found at
11   http://opensource.org/licenses/bsd-license.php.
12 
13   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 
16 **/
17 
18 #include "UefiUsbLibInternal.h"
19 
20 
21 /**
22   Get the descriptor of the specified USB device.
23 
24   Submit a USB get descriptor request for the USB device specified by UsbIo, Value,
25   and Index, and return the descriptor in the buffer specified by Descriptor.
26   The status of the transfer is returned in Status.
27   If UsbIo is NULL, then ASSERT().
28   If Descriptor is NULL, then ASSERT().
29   If Status is NULL, then ASSERT().
30 
31   @param  UsbIo             A pointer to the USB I/O Protocol instance for the specific USB target.
32   @param  Value             The device request value.
33   @param  Index             The device request index.
34   @param  DescriptorLength  The size, in bytes, of Descriptor.
35   @param  Descriptor        A pointer to the descriptor buffer to get.
36   @param  Status            A pointer to the status of the transfer.
37 
38   @retval EFI_SUCCESS           The request executed successfully.
39   @retval EFI_OUT_OF_RESOURCES  The request could not be completed because the
40                                 buffer specified by DescriptorLength and Descriptor
41                                 is not large enough to hold the result of the request.
42   @retval EFI_TIMEOUT           A timeout occurred executing the request.
43   @retval EFI_DEVICE_ERROR      The request failed due to a device error. The transfer
44                                 status is returned in Status.
45 
46 **/
47 EFI_STATUS
48 EFIAPI
UsbGetDescriptor(IN EFI_USB_IO_PROTOCOL * UsbIo,IN UINT16 Value,IN UINT16 Index,IN UINT16 DescriptorLength,OUT VOID * Descriptor,OUT UINT32 * Status)49 UsbGetDescriptor (
50   IN  EFI_USB_IO_PROTOCOL     *UsbIo,
51   IN  UINT16                  Value,
52   IN  UINT16                  Index,
53   IN  UINT16                  DescriptorLength,
54   OUT VOID                    *Descriptor,
55   OUT UINT32                  *Status
56   )
57 {
58   EFI_USB_DEVICE_REQUEST  DevReq;
59 
60   ASSERT (UsbIo != NULL);
61   ASSERT (Descriptor != NULL);
62   ASSERT (Status != NULL);
63 
64   ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
65 
66   DevReq.RequestType  = USB_DEV_GET_DESCRIPTOR_REQ_TYPE;
67   DevReq.Request      = USB_REQ_GET_DESCRIPTOR;
68   DevReq.Value        = Value;
69   DevReq.Index        = Index;
70   DevReq.Length       = DescriptorLength;
71 
72   return UsbIo->UsbControlTransfer (
73                   UsbIo,
74                   &DevReq,
75                   EfiUsbDataIn,
76                   PcdGet32 (PcdUsbTransferTimeoutValue),
77                   Descriptor,
78                   DescriptorLength,
79                   Status
80                   );
81 }
82 
83 
84 /**
85   Set the descriptor of the specified USB device.
86 
87   Submit a USB set descriptor request for the USB device specified by UsbIo,
88   Value, and Index, and set the descriptor using the buffer specified by DesriptorLength
89   and Descriptor.  The status of the transfer is returned in Status.
90   If UsbIo is NULL, then ASSERT().
91   If Descriptor is NULL, then ASSERT().
92   If Status is NULL, then ASSERT().
93 
94   @param  UsbIo             A pointer to the USB I/O Protocol instance for the specific USB target.
95   @param  Value             The device request value.
96   @param  Index             The device request index.
97   @param  DescriptorLength  The size, in bytes, of Descriptor.
98   @param  Descriptor        A pointer to the descriptor buffer to set.
99   @param  Status            A pointer to the status of the transfer.
100 
101   @retval  EFI_SUCCESS       The request executed successfully.
102   @retval  EFI_TIMEOUT       A timeout occurred executing the request.
103   @retval  EFI_DEVICE_ERROR  The request failed due to a device error.
104                              The transfer status is returned in Status.
105 
106 **/
107 EFI_STATUS
108 EFIAPI
UsbSetDescriptor(IN EFI_USB_IO_PROTOCOL * UsbIo,IN UINT16 Value,IN UINT16 Index,IN UINT16 DescriptorLength,IN VOID * Descriptor,OUT UINT32 * Status)109 UsbSetDescriptor (
110   IN  EFI_USB_IO_PROTOCOL     *UsbIo,
111   IN  UINT16                  Value,
112   IN  UINT16                  Index,
113   IN  UINT16                  DescriptorLength,
114   IN  VOID                    *Descriptor,
115   OUT UINT32                  *Status
116   )
117 {
118   EFI_USB_DEVICE_REQUEST  DevReq;
119 
120   ASSERT (UsbIo != NULL);
121   ASSERT (Descriptor != NULL);
122   ASSERT (Status != NULL);
123 
124   ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
125 
126   DevReq.RequestType  = USB_DEV_SET_DESCRIPTOR_REQ_TYPE;
127   DevReq.Request      = USB_REQ_SET_DESCRIPTOR;
128   DevReq.Value        = Value;
129   DevReq.Index        = Index;
130   DevReq.Length       = DescriptorLength;
131 
132   return UsbIo->UsbControlTransfer (
133                   UsbIo,
134                   &DevReq,
135                   EfiUsbDataOut,
136                   PcdGet32 (PcdUsbTransferTimeoutValue),
137                   Descriptor,
138                   DescriptorLength,
139                   Status
140                   );
141 }
142 
143 
144 /**
145   Get the interface setting of the specified USB device.
146 
147   Submit a USB get interface request for the USB device specified by UsbIo,
148   and Interface, and place the result in the buffer specified by AlternateSetting.
149   The status of the transfer is returned in Status.
150   If UsbIo is NULL, then ASSERT().
151   If AlternateSetting is NULL, then ASSERT().
152   If Status is NULL, then ASSERT().
153 
154   @param  UsbIo             A pointer to the USB I/O Protocol instance for the specific USB target.
155   @param  Interface         The interface index value.
156   @param  AlternateSetting  A pointer to the alternate setting to be retrieved.
157   @param  Status            A pointer to the status of the transfer.
158 
159   @retval EFI_SUCCESS       The request executed successfully.
160   @retval EFI_TIMEOUT       A timeout occurred executing the request.
161   @retval EFI_DEVICE_ERROR  The request failed due to a device error.
162                             The transfer status is returned in Status.
163 
164 **/
165 EFI_STATUS
166 EFIAPI
UsbGetInterface(IN EFI_USB_IO_PROTOCOL * UsbIo,IN UINT16 Interface,OUT UINT16 * AlternateSetting,OUT UINT32 * Status)167 UsbGetInterface (
168   IN  EFI_USB_IO_PROTOCOL     *UsbIo,
169   IN  UINT16                  Interface,
170   OUT UINT16                  *AlternateSetting,
171   OUT UINT32                  *Status
172   )
173 {
174   EFI_USB_DEVICE_REQUEST  DevReq;
175 
176   ASSERT (UsbIo != NULL);
177   ASSERT (AlternateSetting != NULL);
178   ASSERT (Status != NULL);
179 
180   *AlternateSetting = 0;
181 
182   ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
183 
184   DevReq.RequestType  = USB_DEV_GET_INTERFACE_REQ_TYPE;
185   DevReq.Request      = USB_REQ_GET_INTERFACE;
186   DevReq.Index        = Interface;
187   DevReq.Length       = 1;
188 
189   return UsbIo->UsbControlTransfer (
190                   UsbIo,
191                   &DevReq,
192                   EfiUsbDataIn,
193                   PcdGet32 (PcdUsbTransferTimeoutValue),
194                   AlternateSetting,
195                   1,
196                   Status
197                   );
198 }
199 
200 
201 /**
202   Set the interface setting of the specified USB device.
203 
204   Submit a USB set interface request for the USB device specified by UsbIo, and
205   Interface, and set the alternate setting to the value specified by AlternateSetting.
206   The status of the transfer is returned in Status.
207   If UsbIo is NULL, then ASSERT().
208   If Status is NULL, then ASSERT().
209 
210   @param  UsbIo             A pointer to the USB I/O Protocol instance for the specific USB target.
211   @param  Interface         The interface index value.
212   @param  AlternateSetting  The alternate setting to be set.
213   @param  Status            A pointer to the status of the transfer.
214 
215   @retval EFI_SUCCESS  The request executed successfully.
216   @retval EFI_TIMEOUT  A timeout occurred executing the request.
217   @retval EFI_SUCCESS  The request failed due to a device error.
218                        The transfer status is returned in Status.
219 
220 **/
221 EFI_STATUS
222 EFIAPI
UsbSetInterface(IN EFI_USB_IO_PROTOCOL * UsbIo,IN UINT16 Interface,IN UINT16 AlternateSetting,OUT UINT32 * Status)223 UsbSetInterface (
224   IN  EFI_USB_IO_PROTOCOL     *UsbIo,
225   IN  UINT16                  Interface,
226   IN  UINT16                  AlternateSetting,
227   OUT UINT32                  *Status
228   )
229 {
230   EFI_USB_DEVICE_REQUEST  DevReq;
231 
232   ASSERT (UsbIo != NULL);
233   ASSERT (Status != NULL);
234 
235   ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
236 
237   DevReq.RequestType  = USB_DEV_SET_INTERFACE_REQ_TYPE;
238   DevReq.Request      = USB_REQ_SET_INTERFACE;
239   DevReq.Value        = AlternateSetting;
240   DevReq.Index        = Interface;
241 
242   return UsbIo->UsbControlTransfer (
243                   UsbIo,
244                   &DevReq,
245                   EfiUsbNoData,
246                   PcdGet32 (PcdUsbTransferTimeoutValue),
247                   NULL,
248                   0,
249                   Status
250                   );
251 }
252 
253 
254 /**
255   Get the device configuration.
256 
257   Submit a USB get configuration request for the USB device specified by UsbIo
258   and place the result in the buffer specified by ConfigurationValue. The status
259   of the transfer is returned in Status.
260   If UsbIo is NULL, then ASSERT().
261   If ConfigurationValue is NULL, then ASSERT().
262   If Status is NULL, then ASSERT().
263 
264   @param  UsbIo               A pointer to the USB I/O Protocol instance for the specific USB target.
265   @param  ConfigurationValue  A pointer to the device configuration to be retrieved.
266   @param  Status              A pointer to the status of the transfer.
267 
268   @retval EFI_SUCCESS        The request executed successfully.
269   @retval EFI_TIMEOUT        A timeout occurred executing the request.
270   @retval EFI_DEVICE_ERROR   The request failed due to a device error.
271                              The transfer status is returned in Status.
272 
273 **/
274 EFI_STATUS
275 EFIAPI
UsbGetConfiguration(IN EFI_USB_IO_PROTOCOL * UsbIo,OUT UINT16 * ConfigurationValue,OUT UINT32 * Status)276 UsbGetConfiguration (
277   IN  EFI_USB_IO_PROTOCOL     *UsbIo,
278   OUT UINT16                  *ConfigurationValue,
279   OUT UINT32                  *Status
280   )
281 {
282   EFI_USB_DEVICE_REQUEST  DevReq;
283 
284   ASSERT (UsbIo != NULL);
285   ASSERT (ConfigurationValue != NULL);
286   ASSERT (Status != NULL);
287 
288   *ConfigurationValue = 0;
289 
290   ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
291 
292   DevReq.RequestType  = USB_DEV_GET_CONFIGURATION_REQ_TYPE;
293   DevReq.Request      = USB_REQ_GET_CONFIG;
294   DevReq.Length       = 1;
295 
296   return UsbIo->UsbControlTransfer (
297                   UsbIo,
298                   &DevReq,
299                   EfiUsbDataIn,
300                   PcdGet32 (PcdUsbTransferTimeoutValue),
301                   ConfigurationValue,
302                   1,
303                   Status
304                   );
305 }
306 
307 
308 /**
309   Set the device configuration.
310 
311   Submit a USB set configuration request for the USB device specified by UsbIo
312   and set the device configuration to the value specified by ConfigurationValue.
313   The status of the transfer is returned in Status.
314   If UsbIo is NULL, then ASSERT().
315   If Status is NULL, then ASSERT().
316 
317   @param  UsbIo               A pointer to the USB I/O Protocol instance for the specific USB target.
318   @param  ConfigurationValue  The device configuration value to be set.
319   @param  Status              A pointer to the status of the transfer.
320 
321   @retval EFI_SUCCESS       The request executed successfully.
322   @retval EFI_TIMEOUT       A timeout occurred executing the request.
323   @retval EFI_DEVICE_ERROR  The request failed due to a device error.
324                             The transfer status is returned in Status.
325 
326 **/
327 EFI_STATUS
328 EFIAPI
UsbSetConfiguration(IN EFI_USB_IO_PROTOCOL * UsbIo,IN UINT16 ConfigurationValue,OUT UINT32 * Status)329 UsbSetConfiguration (
330   IN  EFI_USB_IO_PROTOCOL     *UsbIo,
331   IN  UINT16                  ConfigurationValue,
332   OUT UINT32                  *Status
333   )
334 {
335   EFI_USB_DEVICE_REQUEST  DevReq;
336 
337   ASSERT (UsbIo != NULL);
338   ASSERT (Status != NULL);
339 
340   ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
341 
342   DevReq.RequestType  = USB_DEV_SET_CONFIGURATION_REQ_TYPE;
343   DevReq.Request      = USB_REQ_SET_CONFIG;
344   DevReq.Value        = ConfigurationValue;
345 
346   return UsbIo->UsbControlTransfer (
347                   UsbIo,
348                   &DevReq,
349                   EfiUsbNoData,
350                   PcdGet32 (PcdUsbTransferTimeoutValue),
351                   NULL,
352                   0,
353                   Status
354                   );
355 }
356 
357 
358 /**
359   Set the specified feature of the specified device.
360 
361   Submit a USB set device feature request for the USB device specified by UsbIo,
362   Recipient, and Target to the value specified by Value.  The status of the
363   transfer is returned in Status.
364   If UsbIo is NULL, then ASSERT().
365   If Status is NULL, then ASSERT().
366 
367   @param  UsbIo      A pointer to the USB I/O Protocol instance for the specific USB target.
368   @param  Recipient  The USB data recipient type (i.e. Device, Interface, Endpoint).
369                      Type USB_TYPES_DEFINITION is defined in the MDE Package Industry
370                      Standard include file Usb.h.
371   @param  Value      The value of the feature to be set.
372   @param  Target     The index of the device to be set.
373   @param  Status     A pointer to the status of the transfer.
374 
375   @retval EFI_SUCCESS       The request executed successfully.
376   @retval EFI_TIMEOUT       A timeout occurred executing the request.
377   @retval EFI_DEVICE_ERROR  The request failed due to a device error.
378                             The transfer status is returned in Status.
379 
380 **/
381 EFI_STATUS
382 EFIAPI
UsbSetFeature(IN EFI_USB_IO_PROTOCOL * UsbIo,IN USB_TYPES_DEFINITION Recipient,IN UINT16 Value,IN UINT16 Target,OUT UINT32 * Status)383 UsbSetFeature (
384   IN  EFI_USB_IO_PROTOCOL     *UsbIo,
385   IN  USB_TYPES_DEFINITION    Recipient,
386   IN  UINT16                  Value,
387   IN  UINT16                  Target,
388   OUT UINT32                  *Status
389   )
390 {
391   EFI_USB_DEVICE_REQUEST  DevReq;
392 
393   ASSERT (UsbIo != NULL);
394   ASSERT (Status != NULL);
395 
396   ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
397 
398   switch (Recipient) {
399 
400   case USB_TARGET_DEVICE:
401     DevReq.RequestType = USB_DEV_SET_FEATURE_REQ_TYPE_D;
402     break;
403 
404   case USB_TARGET_INTERFACE:
405     DevReq.RequestType = USB_DEV_SET_FEATURE_REQ_TYPE_I;
406     break;
407 
408   case USB_TARGET_ENDPOINT:
409     DevReq.RequestType = USB_DEV_SET_FEATURE_REQ_TYPE_E;
410     break;
411 
412   default:
413     break;
414   }
415   //
416   // Fill device request, see USB1.1 spec
417   //
418   DevReq.Request  = USB_REQ_SET_FEATURE;
419   DevReq.Value    = Value;
420   DevReq.Index    = Target;
421 
422 
423   return UsbIo->UsbControlTransfer (
424                   UsbIo,
425                   &DevReq,
426                   EfiUsbNoData,
427                   PcdGet32 (PcdUsbTransferTimeoutValue),
428                   NULL,
429                   0,
430                   Status
431                   );
432 }
433 
434 
435 /**
436   Clear the specified feature of the specified device.
437 
438   Submit a USB clear device feature request for the USB device specified by UsbIo,
439   Recipient, and Target to the value specified by Value.  The status of the transfer
440   is returned in Status.
441   If UsbIo is NULL, then ASSERT().
442   If Status is NULL, then ASSERT().
443 
444   @param  UsbIo      A pointer to the USB I/O Protocol instance for the specific USB target.
445   @param  Recipient  The USB data recipient type (i.e. Device, Interface, Endpoint).
446                      Type USB_TYPES_DEFINITION is defined in the MDE Package Industry Standard
447                      include file Usb.h.
448   @param  Value      The value of the feature to be cleared.
449   @param  Target     The index of the device to be cleared.
450   @param  Status     A pointer to the status of the transfer.
451 
452   @retval EFI_SUCCESS       The request executed successfully.
453   @retval EFI_TIMEOUT       A timeout occurred executing the request.
454   @retval EFI_DEVICE_ERROR  The request failed due to a device error.
455                             The transfer status is returned in Status.
456 
457 **/
458 EFI_STATUS
459 EFIAPI
UsbClearFeature(IN EFI_USB_IO_PROTOCOL * UsbIo,IN USB_TYPES_DEFINITION Recipient,IN UINT16 Value,IN UINT16 Target,OUT UINT32 * Status)460 UsbClearFeature (
461   IN  EFI_USB_IO_PROTOCOL     *UsbIo,
462   IN  USB_TYPES_DEFINITION    Recipient,
463   IN  UINT16                  Value,
464   IN  UINT16                  Target,
465   OUT UINT32                  *Status
466   )
467 {
468   EFI_USB_DEVICE_REQUEST  DevReq;
469 
470   ASSERT (UsbIo != NULL);
471   ASSERT (Status != NULL);
472 
473 
474   ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
475 
476   switch (Recipient) {
477 
478   case USB_TARGET_DEVICE:
479     DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_D;
480     break;
481 
482   case USB_TARGET_INTERFACE:
483     DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_I;
484     break;
485 
486   case USB_TARGET_ENDPOINT:
487     DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_E;
488     break;
489 
490   default:
491     break;
492   }
493   //
494   // Fill device request, see USB1.1 spec
495   //
496   DevReq.Request  = USB_REQ_CLEAR_FEATURE;
497   DevReq.Value    = Value;
498   DevReq.Index    = Target;
499 
500 
501   return UsbIo->UsbControlTransfer (
502                   UsbIo,
503                   &DevReq,
504                   EfiUsbNoData,
505                   PcdGet32 (PcdUsbTransferTimeoutValue),
506                   NULL,
507                   0,
508                   Status
509                   );
510 }
511 
512 
513 /**
514   Get the status of the specified device.
515 
516   Submit a USB device get status request for the USB device specified by UsbIo,
517   Recipient, and Target and place the result in the buffer specified by DeviceStatus.
518   The status of the transfer is returned in Status.
519   If UsbIo is NULL, then ASSERT().
520   If DeviceStatus is NULL, then ASSERT().
521   If Status is NULL, then ASSERT().
522 
523   @param  UsbIo         A pointer to the USB I/O Protocol instance for the specific USB target.
524   @param  Recipient     The USB data recipient type (i.e. Device, Interface, Endpoint).
525                         Type USB_TYPES_DEFINITION is defined in the MDE Package Industry Standard
526                         include file Usb.h.
527   @param  Target        The index of the device to be get the status of.
528   @param  DeviceStatus  A pointer to the device status to be retrieved.
529   @param  Status        A pointer to the status of the transfer.
530 
531   @retval EFI_SUCCESS       The request executed successfully.
532   @retval EFI_TIMEOUT       A timeout occurred executing the request.
533   @retval EFI_DEVICE_ERROR  The request failed due to a device error.
534                             The transfer status is returned in Status.
535 
536 **/
537 EFI_STATUS
538 EFIAPI
UsbGetStatus(IN EFI_USB_IO_PROTOCOL * UsbIo,IN USB_TYPES_DEFINITION Recipient,IN UINT16 Target,OUT UINT16 * DeviceStatus,OUT UINT32 * Status)539 UsbGetStatus (
540   IN  EFI_USB_IO_PROTOCOL     *UsbIo,
541   IN  USB_TYPES_DEFINITION    Recipient,
542   IN  UINT16                  Target,
543   OUT UINT16                  *DeviceStatus,
544   OUT UINT32                  *Status
545   )
546 {
547   EFI_USB_DEVICE_REQUEST  DevReq;
548 
549   ASSERT (UsbIo != NULL);
550   ASSERT (DeviceStatus != NULL);
551   ASSERT (Status != NULL);
552 
553   ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
554 
555   switch (Recipient) {
556 
557   case USB_TARGET_DEVICE:
558     DevReq.RequestType = USB_DEV_GET_STATUS_REQ_TYPE_D;
559     break;
560 
561   case USB_TARGET_INTERFACE:
562     DevReq.RequestType = USB_DEV_GET_STATUS_REQ_TYPE_I;
563     break;
564 
565   case USB_TARGET_ENDPOINT:
566     DevReq.RequestType = USB_DEV_GET_STATUS_REQ_TYPE_E;
567     break;
568 
569   default:
570     break;
571   }
572   //
573   // Fill device request, see USB1.1 spec
574   //
575   DevReq.Request  = USB_REQ_GET_STATUS;
576   DevReq.Value    = 0;
577   DevReq.Index    = Target;
578   DevReq.Length   = 2;
579 
580   return UsbIo->UsbControlTransfer (
581                   UsbIo,
582                   &DevReq,
583                   EfiUsbDataIn,
584                   PcdGet32 (PcdUsbTransferTimeoutValue),
585                   DeviceStatus,
586                   2,
587                   Status
588                   );
589 }
590 
591 
592 /**
593   Clear halt feature of the specified usb endpoint.
594 
595   Retrieve the USB endpoint descriptor specified by UsbIo and EndPoint.
596   If the USB endpoint descriptor can not be retrieved, then return EFI_NOT_FOUND.
597   If the endpoint descriptor is found, then clear the halt feature of this USB endpoint.
598   The status of the transfer is returned in Status.
599   If UsbIo is NULL, then ASSERT().
600   If Status is NULL, then ASSERT().
601 
602   @param  UsbIo     A pointer to the USB I/O Protocol instance for the specific USB target.
603   @param  Endpoint  The endpoint address.
604   @param  Status    A pointer to the status of the transfer.
605 
606   @retval EFI_SUCCESS       The request executed successfully.
607   @retval EFI_TIMEOUT       A timeout occurred executing the request.
608   @retval EFI_DEVICE_ERROR  The request failed due to a device error.
609                             The transfer status is returned in Status.
610   @retval EFI_NOT_FOUND     The specified USB endpoint descriptor can not be found
611 
612 **/
613 EFI_STATUS
614 EFIAPI
UsbClearEndpointHalt(IN EFI_USB_IO_PROTOCOL * UsbIo,IN UINT8 Endpoint,OUT UINT32 * Status)615 UsbClearEndpointHalt (
616   IN  EFI_USB_IO_PROTOCOL     *UsbIo,
617   IN  UINT8                   Endpoint,
618   OUT UINT32                  *Status
619   )
620 {
621   EFI_STATUS                    Result;
622   EFI_USB_ENDPOINT_DESCRIPTOR   EndpointDescriptor;
623   EFI_USB_INTERFACE_DESCRIPTOR  InterfaceDescriptor;
624   UINT8                         Index;
625 
626   ASSERT (UsbIo != NULL);
627   ASSERT (Status != NULL);
628 
629   ZeroMem (&EndpointDescriptor, sizeof (EFI_USB_ENDPOINT_DESCRIPTOR));
630   //
631   // First seach the endpoint descriptor for that endpoint addr
632   //
633   Result = UsbIo->UsbGetInterfaceDescriptor (
634                     UsbIo,
635                     &InterfaceDescriptor
636                     );
637   if (EFI_ERROR (Result)) {
638     return Result;
639   }
640 
641   for (Index = 0; Index < InterfaceDescriptor.NumEndpoints; Index++) {
642     Result = UsbIo->UsbGetEndpointDescriptor (
643                       UsbIo,
644                       Index,
645                       &EndpointDescriptor
646                       );
647     if (EFI_ERROR (Result)) {
648       continue;
649     }
650 
651     if (EndpointDescriptor.EndpointAddress == Endpoint) {
652       break;
653     }
654   }
655 
656   if (Index == InterfaceDescriptor.NumEndpoints) {
657     //
658     // No such endpoint
659     //
660     return EFI_NOT_FOUND;
661   }
662 
663   Result = UsbClearFeature (
664             UsbIo,
665             USB_TARGET_ENDPOINT,
666             USB_FEATURE_ENDPOINT_HALT,
667             EndpointDescriptor.EndpointAddress,
668             Status
669             );
670 
671   return Result;
672 }
673