19.1.1 Driver Binding Protocol Supported()

The USB host controller driver must implement the EFI_DRIVER_BINDING_PROTOCOL containing the Supported(), Start(), and Stop() services. The Driver Binding Protocol is installed into the Handle Database in the drive entry point.

The Supported() service evaluates the ControllerHandle that is passed in to check if the ControllerHandle represents a USB host controller that the USB host controller driver knows how to manage. The typical method of implementing this evaluation is for the USB host controller driver to retrieve the PCI configuration header from this controller and check the Class Code field and possibly other fields such as the Device ID and Vendor ID. If all these fields match the values that the USB host controller driver knows how to manage, the Supported() service returns EFI_SUCCESS. Otherwise, the Supported() service returns EFI_UNSUPPORTED.

The following example shows an example of the Supported() service for the USB host controller driver managing a PCI controller with Class code 0x30c.

First, it attempts to open the PCI I/O Protocol EFI_OPEN_PROTOCOL_BY_DRIVER. If the PCI I/O Protocol cannot be opened, then the USB host controller driver does not support the controller specified by ControllerHandle. If the PCI I/O Protocol is opened, the services of the PCI I/O Protocol are used to read the Class Code from the PCI configuration header. The PCI I/O Protocol is always closed with CloseProtocol(), and EFI_SUCCESS is returned if the Class Code fields match.

Example 204-Supported() service for USB host controller driver
#include <Uefi.h>
#include <Protocol/DriverBinding.h> #include <Protocol/PciIo.h>
#include <IndustryStandard/Pci.h>
#include <Library/UefiBootServicesTableLib.h>

EFI_STATUS
EFIAPI
AbcSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   ControllerHandle,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath   OPTIONAL
  )
{
  EFI_STATUS           Status;
  EFI_PCI_IO_PROTOCOL  *PciIo;
  UINT8 PciClass[3];

  //
  // Open the PCI I/O Protocol on ControllerHandle
  //
  Status = gBS->OpenProtocol (
                  ControllerHandle,
                  &gEfiPciIoProtocolGuid,
                  (VOID **)&PciIo,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Read the 3 bytes of class code information from the PCI configuration header
  // at offset 0x09
  //
  Status = PciIo->Pci.Read (
                        PciIo, // This
                        EfiPciIoWidthUint8, // Width
                        PCI_CLASSCODE_OFFSET,
                        // Offset sizeof (PciClass),
                        // Count &PciClass
                        // Buffer
                        );
  if (EFI_ERROR (Status)) {
    goto Done;
  }

  //
  // Test whether the class code is for a USB UHCI controller
  //
  if ((PciClass[2] != PCI_CLASS_SERIAL) || (PciClass[1] != PCI_CLASS_SERIAL_USB) ||
      (PciClass[0] != PCI_IF_UHCI) ) {
    Status = EFI_UNSUPPORTED;
  }

Done:
  //
  // Close the PCI I/O Protocol
  //
  gBS->CloseProtocol (
         ControllerHandle,
         &gEfiPciIoProtocolGuid,
         This->DriverBindingHandle,
         ControllerHandle
         );

  return Status;
}