Multi-config USB devices and Windows


(This post was temporarily unavailable during some of the recent MSDN Blogs site changes.)

 

Part of the USB device framework is the ability of a device to expose “configurations,” mutually exclusive definitions of what the device can do. Each configuration exposes its own:

·        Set of USB interfaces and endpoints,

·        Device power requirements, and

·        Class- or device-specific information.

 

If the device has multiple configurations, they can be very similar or very different, but software must choose one of them in order for the device to work. Often we see the first configuration chosen (and by “first” I mean the one defined by the configuration descriptor at index 0). A frequently asked question is: What does it take to influence this choice of configuration value made in software? Let’s take a look at each software component.

 

ü  The USB core stack supports devices with multiple configurations. Client drivers can select any of the device’s configurations. MSDN reference

 

·        The USBCCGP composite device driver has support for multiple device configurations, with a few caveats. MSDN reference

  1. USBCCGP will not load on a multi-config device by default because the hub driver doesn’t create a “USB\COMPOSITE” PNP ID for a composite device if it has multiple configurations. However, you can write your own INF that matches a device-specific PNP ID to get USBCCGP to load as your device’s function driver.
  2. To select a configuration other than index 0, you must set registry settings as specified in “Selecting the Configuration for a Composite USB Device”. During enumeration, USBCCGP will first attempt to select the configuration whose descriptor is found at the specified “original” index. If the attempt fails, normally due to the configuration requiring more than 100mA while the device’s upstream hub has only bus power, then USBCCGP attempts to select the configuration found at the specified “alternate” index instead.
  3. Drivers that are clients of USBCCGP cannot change the device’s configuration value.

 

·        KMDF itself can be used by the device’s function driver; however, KMDF’s USB I/O Target functionality does not support any device configuration other than the first.

 

×    WinUSB does not support any device configuration other than the first.

 

·        Class drivers often lack support for multiple device configurations. If your device implements a class defined by a USB class specification, please refer to the specification and the relevant Microsoft documentation for a definitive answer.

 

To sum up, if you are writing your own driver for your device, you can freely choose the device’s configuration at runtime, though if you do so you cannot use some of KMDF’s USB features. Otherwise, unless your device’s class supports multiple configurations, you need to use USBCCGP’s selection mechanism, outlined above, to bring multiple configurations into play.

 

– Philip Ries

 

Comments (3)

  1. Does WinXP support USB multi-config? says:

    Dear Philip:

    We are implement multi-confg in WinXP and found it is not working.

    Is Windows XP support this feature?

    Thanks.

    B.R     Fred from Faraday tech

  2. ksg says:

    Hi

    Is there any plan to include the Multi-config in kmdf framework?

    This feature is really needed.

  3. Makarand Sonare says:

    Selecting the non-default configuration is not directly supported by KMDF. But you can use WDM style code in your KMDF driver to select any configuration other than the 1st configuration. Once that's done rest of the KMDF functionality is available similar to the default configuration.

    I recently implemented Multi-Config support in a driver this way:

    1. Use WdfUsbTargetDeviceCreateUrb to create an URB

           status = WdfUsbTargetDeviceCreateUrb(DeviceExtension->UsbDevice,

               WDF_NO_OBJECT_ATTRIBUTES,

               &memory,

               &Urb);

    2. Use UsbBuildGetDescriptorRequest(USB_CONFIGURATION_DESCRIPTOR_TYPE) to build a control descriptor for retrieving the configuration descriptor. This way you can retrieve any configuration supported by the device.

    for (Config = 0; Config < NumConfigs; Config++)

    {

                           UsbBuildGetDescriptorRequest(Urb,

                               sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),

                               USB_CONFIGURATION_DESCRIPTOR_TYPE,

                               Config, 0, ConfigurationDescriptor,

                               NULL, Size, NULL);

    }

    3. Once you have the configuration descriptor, you can use USBD_CreateConfigurationRequestEx to build a select config URB. Refer msdn.microsoft.com/…/ff539029(v=vs.85).aspx

    4. Call WdfUsbTargetDeviceSelectConfig to use the URB created above to select the configuration.

               WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_URB(&configParams, Urb);

               status = WdfUsbTargetDeviceSelectConfig(DeviceExtension->UsbDevice,

                                    WDF_NO_OBJECT_ATTRIBUTES, &configParams);

    Once the configuration is selected, rest of the KMDF APIs can be used to retrieve the interfaces, configured pipes. Frameworks would have created Io Targets for the configured pipes, so you can use WdfIoTarget API to send IO requests to the pipe Io Targets.