Writing Device Drivers

Registering Drivers to Gain Device Access

Two of the first calls into the USBA 2.0 framework by a client driver are calls to the usb_client_attach(9F) function and the usb_get_dev_data(9F) function. These two calls come from the client driver's attach(9E) entry point. You must call the usb_client_attach(9F) function before you call the usb_get_dev_data(9F) function.

The usb_client_attach(9F) function registers a client driver with the USBA 2.0 framework. The usb_client_attach(9F) function enforces versioning. All client driver source files must start with the following lines:

#define USBDRV_MAJOR_VER        2
#define USBDRV_MINOR_VER        minor-version
#include <sys/usb/usba.h>

The value of minor-version must be less than or equal to USBA_MINOR_VER. The symbol USBA_MINOR_VER is defined in the <sys/usb/usbai.h> header file. The <sys/usb/usbai.h> header file is included by the <sys/usb/usba.h> header file.

USBDRV_VERSION is a macro that generates the version number from USBDRV_MAJOR_VERSION and USBDRV_MINOR_VERSION. The second argument to usb_client_attach() must be USBDRV_VERSION. The usb_client_attach() function fails if the second argument is not USBDRV_VERSION or if USBDRV_VERSION reflects an invalid version. This restriction ensures programming interface compatibility.

The usb_get_dev_data() function returns information that is required for proper USB device management. For example, the usb_get_dev_data() function returns the following information:

The call to the usb_get_dev_data() function is mandatory. Calling usb_get_dev_data() is the only way to retrieve the default control pipe and retrieve the iblock_cookie required for mutex initialization.

After calling usb_get_dev_data(), the client driver's attach(9E) routine typically copies the desired descriptors and data from the descriptor tree to the driver's soft state. Endpoint descriptors copied to the soft state are used later to open pipes to those endpoints. The attach(9E) routine usually calls usb_free_descr_tree(9F) to free the descriptor tree after copying descriptors. Alternatively, you might choose to keep the descriptor tree and not copy the descriptors.

Specify one of the following three parse levels to the usb_get_dev_data(9F) function to request the breadth of the descriptor tree you want returned. You need greater tree breadth if your driver needs to bind to more of the device.

The client driver's detach(9E) routine must call the usb_free_dev_data(9F) function to release all resources allocated by theusb_get_dev_data() function. The usb_free_dev_data() function accepts handles where the descriptor tree has already been freed with the usb_free_descr_tree() function. The client driver's detach() routine also must call the usb_client_detach(9F) function to release all resources allocated by the usb_client_attach(9F) function.