KMDF USB Driver: WDF SetConfiguration API doesn't work for IAP2 interface descriptors

Hi,

I have a USB drive which advertises vendor specific IAP2 descriptors(See Table 1). With inhouse developed WDF based KMDF driver, I want to set IAP2 Interface by invoking SetConfiguration request. When I set the configuration for IAP2 interface, the driver gets reloaded and the device advertises new capabilies which has only BOT mode interfaces(See Table 2). Note: At any point of time the drive either advertises IAP2 descritpors or MSC descriptors only.

Table 1: //Only Vendor specific - IAP descriptors

Device Descriptor
	Configuration Descriptor
		IAP2 Interface Descritpr 0, AlternateSetting 0 (IAP2 Authentication interface - Has 2 EPs)
		IAP2 Interface Descritpr 1, AlternateSetting 0 (IAP2 EA interface - Has 0 Eps)
		IAP2 Interface Descritpr 1, AlternateSetting 1 (IAP2 EA interface - Has 2 Eps)

Table 2: //Only MSC - BOT mode descriptors

Device Descriptor
	Configuration Descriptor
		Interface Descritpr 0, AlternateSetting 0 (MSC interface for BOT mode - Has 2 EPs)

I have compiled below observations for the code changes to invoke SetConfiguration request.

Observation 1:

	WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams;
	WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_MULTIPLE_INTERFACES(&configParams, 0, NULL);
	status = WdfUsbTargetDeviceSelectConfig(pDeviceContext->UsbDevice, NULL, &configParams);

On invoking SetConfiguration with above settings, I notice back to back SetConfiguration Request and then SetInterface request. SetInterface packet contains request for IAP2 Interface=1, AlternateSetting=0. Both requests(SetConfiguration and SetInterface) are successful and the traces are captured in wireshark/lecory. However, immediately underlying USB stack seems to trigger a warm reset and the driver gets reloaded. Lecroy traces shows that the SetFeature was invoked for U1/U2 enable but Wireshark trace doesn't capture warm reset requests. Now, the device advertizes new capabilities which has MSC BOT mode configuration. SetConfiguration invocation for BOT mode is successful(See Table 2).

Observation 2:

    WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams;
    UCHAR numInterfaces = WdfUsbTargetDeviceGetNumInterfaces(pDeviceContext->UsbDevice); //Returns value=2
    PWDF_USB_INTERFACE_SETTING_PAIR settingPairs = ExAllocatePool2(
        POOL_FLAG_PAGED,
        sizeof(WDF_USB_INTERFACE_SETTING_PAIR) * numInterfaces,
        PnpPoolTag
    );

    pDeviceContext->UsbInterface = WdfUsbTargetDeviceGetInterface(pDeviceContext->UsbDevice, 0); //Retrieve interface=0
	BYTE NumOfSettings = WdfUsbInterfaceGetNumSettings(pDeviceContext->UsbInterface); //Returns value=1
	WdfUsbInterfaceGetDescriptor(pDeviceContext->UsbInterface, 0, &pDeviceContext->InterfaceDescriptor); //Retrieve descriptor for interface=0, AltSetting=0
            
	settingPairs[0].UsbInterface = pDeviceContext->UsbInterface;
	settingPairs[0].SettingIndex = 0;

    pDeviceContext->UsbInterface = WdfUsbTargetDeviceGetInterface(pDeviceContext->UsbDevice, 1); //Retrieve interface=1
	NumOfSettings = WdfUsbInterfaceGetNumSettings(pDeviceContext->UsbInterface); //Returns value=2
	WdfUsbInterfaceGetDescriptor(pDeviceContext->UsbInterface, 1, &pDeviceContext->InterfaceDescriptor); //Retrieve descriptor for interface=1, AltSetting=1
  
	settingPairs[1].UsbInterface = pDeviceContext->UsbInterface;
	settingPairs[1].SettingIndex = 1;   	

	WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_MULTIPLE_INTERFACES(&configParams, numInterfaces, settingPairs);
	status = WdfUsbTargetDeviceSelectConfig(pDeviceContext->UsbDevice, NULL, &configParams);

On invoking SetConfiguration with above settings, I notice back to back SetConfiguration Request and then SetInterface request. SetInterface packet contains request for IAP2 Interface=1, AlternateSetting=1. Both requests(SetConfiguration and SetInterface) requests are successful and the traces are captured in wireshark/lecory. However, immediately underlying USB stack seems to trigger a warm reset and the driver gets reloaded. Lecroy traces shows that the SetFeature was invoked for U1/U2 enable but Wireshark trace doesn't capture warm reset requests. Now, the device advertizes new capabilities which has MSC BOT mode configuration. SetConfiguration invocation for BOT mode is successful(See Table 2).

Observation 3:

    WDF_USB_CONTROL_SETUP_PACKET wdfusbcontrolsetupacket;
	WDF_USB_BMREQUEST_RECIPIENT bmRequestRecepient = BmRequestToDevice;
	WDF_USB_BMREQUEST_DIRECTION bmRequestDirection = BMREQUEST_HOST_TO_DEVICE;
	ULONG bytestransfered;
	WDF_USB_CONTROL_SETUP_PACKET_INIT(&wdfusbcontrolsetupacket, bmRequestDirection, bmRequestRecepient, 0x09, 1, 0);
	status = WdfUsbTargetDeviceSendControlTransferSynchronously(
		pDeviceContext->UsbDevice,
		WDF_NO_HANDLE,
		NULL,
		&wdfusbcontrolsetupacket,
		NULL,
		&bytestransfered
	);

On invoking SetConfiguration with above settings, I notice only SetConfiguration Request provided there is no breakpoint added in windbg. The invocation is successful and the traces are captured in wireshark/lecory. However, immediately underlying USB stack seems to trigger a warm reset and the driver gets reloaded. Both lecroy and Wireshark trace doesn't capture warm reset SetFeature requests. Now, the device advertizes new capabilities which has MSC BOT mode configuration. SetConfiguration invocation for BOT mode is successful(See Table 2).

Observation 4:

    WDF_USB_CONTROL_SETUP_PACKET wdfusbcontrolsetupacket;
	WDF_USB_BMREQUEST_RECIPIENT bmRequestRecepient = BmRequestToDevice;
	WDF_USB_BMREQUEST_DIRECTION bmRequestDirection = BMREQUEST_HOST_TO_DEVICE;
	ULONG bytestransfered;
	WDF_USB_CONTROL_SETUP_PACKET_INIT(&wdfusbcontrolsetupacket, bmRequestDirection, bmRequestRecepient, 0x09, 1, 0);
	status = WdfUsbTargetDeviceSendControlTransferSynchronously(
		pDeviceContext->UsbDevice,
		WDF_NO_HANDLE,
		NULL,
		&wdfusbcontrolsetupacket,
		NULL,
		&bytestransfered
	);

On invoking SetConfiguration with above settings, if I add debug breakpoint in windbg just before I invoke WdfUsbTargetDeviceSendControlTransferSynchronously then on some instances WdfUsbTargetDeviceSendControlTransferSynchronously will fail with Status = 0xc000000e(IRP USBD_STATUS: USBD_STATUS_INVALID_PARAMETER (0x80000300)) or status = 0xc0000001(USBD_STATUS_XACT_ERROR (0xc0000011)). Lecroy doesn't capture the SetConfiguration packet for IAP2 descriptor, however wireshark captures it. Driver gets reloaded and the device advertises BOT capabilities. SetConfiguration is successful for BOT mode(See Table 2).

Observation 5:

    WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE(&configParams);
	status = WdfUsbTargetDeviceSelectConfig(pDeviceContext->UsbDevice, WDF_NO_OBJECT_ATTRIBUTES, &configParams);

On invoking SetConfiguration with above settings, WdfUsbTargetDeviceSelectConfig request fails. Both wireshark and lecory doesn't capture traces for SetConfiguration.

Can someone please help in giving any clues for below questions.

  1. Any possible reasons for WarmReset getting triggered by some underlying USB stack layer and why I am unable to set IAP2 configuration via SetConfiguration request persistently.
  2. Why WdfUsbTargetDeviceSendControlTransferSynchronously returns Status = 0xc000000e(IRP USBD_STATUS: USBD_STATUS_INVALID_PARAMETER (0x80000300)) or status = 0xc0000001(USBD_STATUS_XACT_ERROR (0xc0000011)) on adding a debug breakpoints in windbg.
  3. Why SetConfiguration with WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE doesn't work

Thanks

[mods: Moved this from WinDbg to a NTDEV, where more WDF USB folks are likely to see it]

As a rule, a driver does not survive a SetConfiguration request that changes the configuration number. SetConfiguration usually results in a different set of interfaces, and since it is the interfaces that dictate the set of drivers, all of the existing drivers are all unloaded and a new set are loaded. You may need to have your driver detect the configuration when you are loaded and decide your progress forward that way.

@Tim_Roberts - Thanks for your reply.

There is only one configuration available and multiple IAP2 interfaces under this configuration. I will have to change among the interfaces under the same configuration.

When the USB drive is connected to IPhone device in USB_HOST_MODE, the MFI authentication has be done over IPA2 Interface=0 AltSetting=0. Once the authentication is successful, I have to switch the interface to Interface=1 AltSetting=1 to start the data transfer and set Interface=1 AltSetting=0 to stop the data transfer.
In an IAP2 session, on multiple occasions I will have to switch among the interfaces to perform authentication, start/stop data streams.

How would you suggest to detect the configuration of the interface when the driver is loaded? Are there any APIs which will help?

Thanks

In that case, you just do a SetInterface, not a SetConfiguration. SetInterface allows you to change the current interface and alternate setting.

Is your driver handling the composite device, so that you "own" all the interfaces?