Part I Designing Device Drivers for the Solaris Platform
1. Overview of Solaris Device Drivers
2. Solaris Kernel and Device Tree
5. Managing Events and Queueing Tasks
7. Device Access: Programmed I/O
10. Mapping Device and Kernel Memory
14. Layered Driver Interface (LDI)
Part II Designing Specific Kinds of Device Drivers
15. Drivers for Character Devices
18. SCSI Host Bus Adapter Drivers
19. Drivers for Network Devices
USB in the Solaris Environment
How USB Devices Appear to the System
USB Devices and the Solaris Device Tree
Before the Client Driver Is Attached
Registering Drivers to Gain Device Access
Synchronous and Asynchronous Transfers and Callbacks
Device Configuration Facilities
Multiple-Configuration Devices
Modifying or Getting the Alternate Setting
Retrieving a String Descriptor
Getting Device, Interface, or Endpoint Status
Getting the Bus Address of a Device
Part III Building a Device Driver
21. Compiling, Loading, Packaging, and Testing Drivers
22. Debugging, Testing, and Tuning Device Drivers
23. Recommended Coding Practices
B. Summary of Solaris DDI/DKI Services
C. Making a Device Driver 64-Bit Ready
This section discusses binding a driver to a device. It discusses compatible device names for devices with single interfaces and devices with multiple interfaces.
A USB device can support multiple configurations. Only one configuration is active at any given time. The active configuration is called the current configuration.
A configuration can have more than one interface, possibly with intervening interface-associations that group two or more interfaces for a function. All interfaces of a configuration are active simultaneously. Different interfaces might be operated by different device drivers.
An interface can represent itself to the host system in different ways by using alternate settings. Only one alternate setting is active for any given interface.
Each alternate setting provides device access through endpoints. Each endpoint has a specific purpose. The host system communicates with the device by establishing a communication channel to an endpoint. This communication channel is called a pipe.
If a USB device has one configuration, one interface, and device class zero, the device is represented as a single device node. If a USB device has multiple interfaces, the device is represented as a hierarchical device structure. In a hierarchical device structure, the device node for each interface is a child of the top-level device node. An example of a device with multiple interfaces is an audio device that presents simultaneously to the host computer both an audio control interface and an audio streaming interface. The audio control interface and the audio streaming interface each could be controlled by its own driver.
The Solaris software builds an ordered list of compatible device names for USB binding based on identification information kept within each device. This information includes device class, subclass, vendor ID, product ID, revision, and protocol. See http://www.usb.org/home for a list of USB classes and subclasses.
This name hierarchy enables binding to a general driver if a more device-specific driver is not available. An example of a general driver is a class-specific driver. Device names that begin with usbif designate single interface devices. See Example 20-1 for examples. The USBA 2.0 framework defines all compatible names for a device. Use the prtconf command to display these device names, as shown in Example 20-2.
The following example shows an example of compatible device names for a USB mouse device. This mouse device represents a combined node entirely operated by a single driver. The USBA 2.0 framework gives this device node the names shown in the example, in the order shown.
Example 20-1 USB Mouse Compatible Device Names
1. 'usb430,100.102' Vendor 430, product 100, revision 102 2. 'usb430,100' Vendor 430, product 100 3. 'usbif430,class3.1.2' Vendor 430, class 3, subclass 1, protocol 2 4. 'usbif430,class3.1' Vendor 430, class 3, subclass 1 5. 'usbif430,class3' Vendor 430, class 3 6. 'usbif,class3.1.2' Class 3, subclass 1, protocol 2 7. 'usbif,class3.1' Class 3, subclass 1 8. 'usbif,class3' Class 3
Note that the names in the above example progress from the most specific to the most general. Entry 1 binds only to a particular revision of a specific product from a particular vendor. Entries 3, 4, and 5 are for class 3 devices manufactured by vendor 430. Entries 6, 7, and 8 are for class 3 devices from any vendor. The binding process looks for a match on the name from the top name down. To bind, drivers must be added to the system with an alias that matches one of these names. To get a list of compatible device names to which to bind when you add your driver, check the compatible property of the device in the output from the prtconf -vp command.
The following example shows compatible property lists for a keyboard and a mouse. Use the prtconf -D command to display the bound driver.
Example 20-2 Compatible Device Names Shown by the Print Configuration Command
# prtconf -vD | grep compatible compatible: 'usb430,5.200' + 'usb430,5' + 'usbif430,class3.1.1' + 'usbif430,class3.1' + 'usbif430,class3' + 'usbif,class3.1.1' + 'usbif,class3.1' + 'usbif,class3' compatible: 'usb2222,2071.200' + 'usb2222,2071' + 'usbif2222,class3.1.2' + 'usbif2222,class3.1' + 'usbif2222,class3' + 'usbif,class3.1.2' + 'usbif,class3.1' + 'usbif,class3'
Use the most specific name you can to more accurately identify a driver for a device or group of devices. To bind drivers written for a specific revision of a specific product, use the most specific name match possible. For example, if you have a USB mouse driver written by vendor 430 for revision 102 of their product 100, use the following command to add that driver to the system:
add_drv -n -i '"usb430,100.102"' specific_mouse_driver
To add a driver written for any USB mouse (class 3, subclass 1, protocol 2) from vendor 430, use the following command:
add_drv -n -i '"usbif430,class3.1.2"' more_generic_mouse_driver
If you install both of these drivers and then connect a compatible device, the system binds the correct driver to the connected device. For example, if you install both of these drivers and then connect a vendor 430, model 100, revision 102 device, this device is bound to specific_mouse_driver. If you connect a vendor 430, model 98 device, this device is bound to more_generic_mouse_driver. If you connect a mouse from another vendor, this device also is bound to more_generic_mouse_driver. If multiple drivers are available for a specific device, the driver binding framework selects the driver with the first matching compatible name in the compatible names list.
Composite devices are devices that support multiple interfaces. Composite devices have a list of compatible names for each interface. This compatible names list ensures that the best available driver is bound to the interface. The most general multiple interface entry is usb,device.
For a USB audio composite device, the compatible names are as follows:
1. 'usb471,101.100' Vendor 471, product 101, revision 100 2. 'usb471,101' Vendor 471, product 101 3. 'usb,device' Generic USB device
The name usb,device is a compatible name that represents any whole USB device. The usb_mid(7D) driver (USB multiple-interface driver) binds to the usb,device device node if no other driver has claimed the whole device. The usb_mid driver creates a child device node for each interface of the physical device. The usb_mid driver also generates a set of compatible names for each interface. Each of these generated compatible names begins with usbif. The system then uses these generated compatible names to find the best driver for each interface. In this way, different interfaces of one physical device can be bound to different drivers.
For example, the usb_mid driver binds to a multiple-interface audio device through the usb,device node name of that audio device. The usb_mid driver then creates interface-specific device nodes. Each of these interface-specific device nodes has its own compatible name list. For an audio control interface node, the compatible name list might look like the list shown in the following example.
Example 20-3 USB Audio Compatible Device Names
1. 'usbif471,101.100.config1.0' Vend 471, prod 101, rev 100, cnfg 1, iface 0 2. 'usbif471,101.config1.0' Vend 471, product 101, config 1, interface 0 3. 'usbif471,class1.1.0' Vend 471, class 1, subclass 1, protocol 0 4. 'usbif471,class1.1' Vend 471, class 1, subclass 1 5. 'usbif471,class1' Vend 471, class 1 6. 'usbif,class1.1.0' Class 1, subclass 1, protocol 0 7. 'usbif,class1.1' Class 1, subclass 1 8. 'usbif,class1' Class 1
Use the following command to bind a vendor-specific, device-specific client driver named vendor_model_audio_usb to the vendor-specific, device-specific configuration 1, interface 0 interface compatible name shown in Example 20-3.
add_drv -n -i '"usbif471,101.config1.0"' vendor_model_audio_usb
Use the following command to bind a class driver named audio_class_usb_if_driver to the more general class 1, subclass 1 interface compatible name shown in Example 20-3:
add_drv -n -i '"usbif,class1.1"' audio_class_usb_if_driver
Use the prtconf -D command to show a list of devices and their drivers. In the following example, the prtconf -D command shows that the usb_mid driver manages the audio device. The usb_mid driver is splitting the audio device into interfaces. Each interface is indented under the audio device name. For each interface shown in the indented list, the prtconf -D command shows which driver manages the interface.
audio, instance #0 (driver name: usb_mid) sound-control, instance #2 (driver name: usb_ac) sound, instance #2 (driver name: usb_as) input, instance #8 (driver name: hid)
The file /etc/driver_aliases contains entries for the bindings that already exist on a system. Each line of the /etc/driver_aliases file shows a driver name, followed by a space, followed by a device name. Use this file to check existing device driver bindings.
Note - Do not edit the /etc/driver_aliases file manually. Use the add_drv(1M) command to establish a binding. Use the update_drv(1M) command to change a binding.