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;
}