19.3.2 Driver Binding Protocol Start() and Stop()

The Start() service of the Driver Binding Protocol for a USB device driver opens the USB I/O Protocol with an attribute of EFI_OPEN_PROTOCOL_BY_DRIVER. The service then installs the I/O abstraction protocol for the USB device or host controller onto the handle on which the EFI_USB_IO_PROTOCOL is installed.

19.3.2.1 Example using a USB mass storage device

This discussion provides detailed guidance on how to implement a USB device driver. It uses a USB mass storage device as an example. For example, suppose this mass storage device has the following four endpoints:

  • One control endpoint
  • One interrupt endpoint
  • Two bulk endpoints

For the interrupt endpoint, it is synchronous. For the bulk endpoints, one is an input endpoint and the other is an output endpoint. The following discussions cover how to implement the Start() and Stop() driver binding protocol services and UEFI Block I/O protocol.

This example shows a portion of the private context data structure for a USB mass storage device driver. See Chapter 8 of this guide for more information about design guidelines for private context data structures.

Example 207-USB mass storage driver private context data structure
#include <Uefi.h>
#include <Protocol/UsbIo.h>
#include <Protocol/BlockIo.h>

typedef struct {
  UINT64 Signature;

  EFI_BLOCK_IO_PROTOCOL           BlockIO;
  EFI_USB_IO_PROTOCOL             *UsbIo;

  EFI_USB_INTERFACE_DESCRIPTOR    InterfaceDescriptor;
  EFI_USB_ENDPOINT_DESCRIPTOR     BulkInEndpointDescriptor;
  EFI_USB_ENDPOINT_DESCRIPTOR     BulkOutEndpointDescriptor;
  EFI_USB_ENDPOINT_DESCRIPTOR     InterruptEndpointDescriptor;

} USB_MASS_STORAGE_DEVICE;

19.3.2.2 Example implementing Driver Binding Start()

The following steps are performed in the Driver Binding Protocol Start() service.

  1. Open the USB I/O Protocol on ControllerHandle EFI_OPEN_PROTOCOL_BY_DRIVER.
  2. Get the interface descriptor using the ##### EFI_USB_IO_PROTOCOL.UsbGetInterfaceDescriptor() service.
  3. Prepare the private data structure. This private data structure is in type USB_MASS_STORAGE_DEVICE and has fields for the interface descriptor, endpoint descriptor, and others. This step allocates memory for the private data structure and does the required initializations-for example, setting up the Signature, UsbIo, and InterfaceDescriptor fields.
  4. Parse the interface descriptor. In this step, the USB device driver parses the InterfaceDescriptor that was obtained in step 2, and verifies that all bulk and interrupt endpoints exit. The NumEndpoints field in InterfaceDescriptor indicates how many endpoints are in this USB interface. Next, the endpoint descriptors are retrieved one by one by using the UsbGetEndpointDescriptor() service. Then, the Attributes and EndpointAddress fields in EndpointDescriptor are evaluated to determine the type of endpoint.
  5. Install the Block I/O protocol.

19.3.2.3 Example implementing Driver Binding Stop()

The Driver Binding Protocol Stop() service performs the reverse steps of the Start() service. Continuing with the previous example, the Stop() service uninstalls the Block I/O Protocol and closes the USB I/O Protocol. It also frees various allocated resources such as the private data structure.