EvtIoWrite not completed for Bulk endpoint

Hi All,

I’m handling a strange issue on the bulk transfer. I have a USB driver installing as the function driver of the USB device. It’s the bulk interface with one IN pipe and one out pipe. After configuring the device properly, the driver creates two queues one for EvtIoRead and one for EvtIoWrite. Meanwhile, I have an application talking to the driver and sending data to the bulk out endpoint. After the application calls the API WriteFile, the EvtIoWrite gets called and it forwards the original request to next level after formatting it with calling WdfUsbTargetPipeFormatRequestForWrite. However, I don’t see the completion routine gets called after that. It causes the application hangs there because I call the WriteFile synchronously. The out pipe handle is valid and the packet length is less than the maximum packet size. Does anyone know why and how can I solve it? Is it because I forward the original request instead of creating a new request? Thanks!

HRESULT CDevice::WriteDataToFip(const void* pvData, DWORD cbData)
{
WriteFile(m_fip_handle, pvData, cbData, &written, NULL))
}

The EvtIoWrite is as below:

void CDeviceExtension::EvtIoWrite(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length)
{
WDFMEMORY memory;
NTSTATUS status = WdfRequestRetrieveInputMemory(Request, &memory);
if (NT_SUCCESS(status))
{
CDeviceExtension* pThis = GetContext_CDeviceExtension(WdfIoQueueGetDevice(Queue));

WDFMEMORY_OFFSET offset;
offset.BufferOffset = 0;
offset.BufferLength = (Length > pThis->m_write_size) ? pThis->m_write_size : Length;

status = WdfUsbTargetPipeFormatRequestForWrite( pThis->m_out, Request, memory, &offset);
if (NT_SUCCESS(status))
{
SRequestContext* pCtxt = GetContext_SRequestContext(Request);
pCtxt->bytesNotYetTransfered = (ULONG)(Length - offset.BufferLength);
pCtxt->bytesTransfered = 0;
pCtxt->MaxPacketLength = (ULONG)pThis->m_write_size;

// Send the request asynchronously.
//
WdfRequestSetCompletionRoutine(Request, EvtRequestWriteComplete, NULL);
if (WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pThis->m_out), WDF_NO_SEND_OPTIONS) == FALSE)
{
status = WdfRequestGetStatus(Request);
}
}
}
}

if (!NT_SUCCESS(status))
{
WdfRequestCompleteWithInformation(Request, status, 0);
}
}

Also, I got the !wdfkd.wdflogdump as below:

0: kd> !wdflogdump SaiDA2AE.sys
Trace searchpath is:

Trace format prefix is: %7!u!: %!FUNC! -
Trying to extract TMF information from - C:\symstore\Wdf01000.pdb\910864B4254D480C94ABAE23F3EBE0662\Wdf01000.pdb
Gather log: Please wait, this may take a moment (reading 4024 bytes).
% read so far … 10, 20, 30, 100
There are 28 log entries
— start of log —
1: FxIFRStart - FxIFR logging started
2: FxPkgPnp::PnpEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering PnP State WdfDevStatePnpInit from WdfDevStatePnpObjectCreated
3: FxPkgPnp::Dispatch - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900, IRP_MJ_PNP, 0x00000000(IRP_MN_START_DEVICE) IRP 0xFFFFE00169127410
4: FxPkgPnp::PnpEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering PnP State WdfDevStatePnpInitStarting from WdfDevStatePnpInit
5: FxPkgPnp::PnpEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering PnP State WdfDevStatePnpHardwareAvailable from WdfDevStatePnpInitStarting
6: FxIoTarget::SubmitLocked - ignoring WDFIOTARGET 00001FFE96E57C18 state, sending WDFREQUEST FFFFD00022822CA0, state WdfIoTargetStarted
7: FxPkgPnp::PowerPolicyEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering power policy state WdfDevStatePwrPolStarting from WdfDevStatePwrPolObjectCreated
8: FxPowerIdleMachine::ProcessEventLocked - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering power idle state FxIdleStarted from FxIdleStopped
9: FxPkgPnp::PowerEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering Power State WdfDevStatePowerStartingCheckDeviceType from WdfDevStatePowerObjectCreated
10: FxPkgPnp::PowerEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering Power State WdfDevStatePowerD0Starting from WdfDevStatePowerStartingCheckDeviceType
11: FxPkgPnp::PowerEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering Power State WdfDevStatePowerD0StartingConnectInterrupt from WdfDevStatePowerD0Starting
12: FxPkgPnp::PowerEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering Power State WdfDevStatePowerD0StartingDmaEnable from WdfDevStatePowerD0StartingConnectInterrupt
13: FxPkgPnp::PowerEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering Power State WdfDevStatePowerD0StartingStartSelfManagedIo from WdfDevStatePowerD0StartingDmaEnable
14: FxPkgIo::ResumeProcessingForPower - Power resume all queues of WDFDEVICE 0x00001FFE96E873D8
15: FxPowerIdleMachine::ProcessEventLocked - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering power idle state FxIdleStartedPowerUp from FxIdleStarted
16: FxPowerIdleMachine::ProcessEventLocked - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering power idle state FxIdleDisabled from FxIdleStartedPowerUp
17: FxPkgPnp::PowerEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering Power State WdfDevStatePowerDecideD0State from WdfDevStatePowerD0StartingStartSelfManagedIo
18: FxPkgPnp::PowerEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering Power State WdfDevStatePowerD0 from WdfDevStatePowerDecideD0State
19: FxPkgPnp::PowerPolicyEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering power policy state WdfDevStatePwrPolStartingPoweredUp from WdfDevStatePwrPolStarting
20: FxPkgPnp::PowerPolicyEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering power policy state WdfDevStatePwrPolStartingSucceeded from WdfDevStatePwrPolStartingPoweredUp
21: FxPkgPnp::PowerPolicyEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering power policy state WdfDevStatePwrPolStartingDecideS0Wake from WdfDevStatePwrPolStartingSucceeded
22: FxPkgPnp::PowerPolicyEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering power policy state WdfDevStatePwrPolStarted from WdfDevStatePwrPolStartingDecideS0Wake
23: FxPowerIdleMachine::ProcessEventLocked - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering power idle state FxIdleDisabled from FxIdleDisabled
24: FxPkgPnp::PnpEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering PnP State WdfDevStatePnpEnableInterfaces from WdfDevStatePnpHardwareAvailable
25: FxPkgPnp::PnpEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering PnP State WdfDevStatePnpStarted from WdfDevStatePnpEnableInterfaces
26: FxPkgPnp::Dispatch - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900, IRP_MJ_PNP, 0x00000014(IRP_MN_QUERY_PNP_DEVICE_STATE) IRP 0xFFFFE00169127410
27: FxPkgFdo::HandleQueryPnpDeviceStateCompletion - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 returning PNP_DEVICE_STATE 0x0 IRP 0xFFFFE00169127410
28: FxPkgPnp::Dispatch - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900, IRP_MJ_PNP, 0x00000007(IRP_MN_QUERY_DEVICE_RELATIONS) type BusRelations IRP 0xFFFFE0016AF34AB0
---- end of log ----

If the io isn’t completing it sounds like device problem on the USB wire. Capture a USB etw log trace and see if it tells you anything

Bent from my phone


From: xxxxx@lists.osr.com on behalf of xxxxx@hotmail.com
Sent: Thursday, April 13, 2017 8:04:50 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] EvtIoWrite not completed for Bulk endpoint

Hi All,

I’m handling a strange issue on the bulk transfer. I have a USB driver installing as the function driver of the USB device. It’s the bulk interface with one IN pipe and one out pipe. After configuring the device properly, the driver creates two queues one for EvtIoRead and one for EvtIoWrite. Meanwhile, I have an application talking to the driver and sending data to the bulk out endpoint. After the application calls the API WriteFile, the EvtIoWrite gets called and it forwards the original request to next level after formatting it with calling WdfUsbTargetPipeFormatRequestForWrite. However, I don’t see the completion routine gets called after that. It causes the application hangs there because I call the WriteFile synchronously. The out pipe handle is valid and the packet length is less than the maximum packet size. Does anyone know why and how can I solve it? Is it because I forward the original request instead of creating a new request? Thanks!

HRESULT CDevice::WriteDataToFip(const void* pvData, DWORD cbData)
{
WriteFile(m_fip_handle, pvData, cbData, &written, NULL))
}

The EvtIoWrite is as below:

void CDeviceExtension::EvtIoWrite(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length)
{
WDFMEMORY memory;
NTSTATUS status = WdfRequestRetrieveInputMemory(Request, &memory);
if (NT_SUCCESS(status))
{
CDeviceExtension* pThis = GetContext_CDeviceExtension(WdfIoQueueGetDevice(Queue));

WDFMEMORY_OFFSET offset;
offset.BufferOffset = 0;
offset.BufferLength = (Length > pThis->m_write_size) ? pThis->m_write_size : Length;

status = WdfUsbTargetPipeFormatRequestForWrite( pThis->m_out, Request, memory, &offset);
if (NT_SUCCESS(status))
{
SRequestContext* pCtxt = GetContext_SRequestContext(Request);
pCtxt->bytesNotYetTransfered = (ULONG)(Length - offset.BufferLength);
pCtxt->bytesTransfered = 0;
pCtxt->MaxPacketLength = (ULONG)pThis->m_write_size;

// Send the request asynchronously.
//
WdfRequestSetCompletionRoutine(Request, EvtRequestWriteComplete, NULL);
if (WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pThis->m_out), WDF_NO_SEND_OPTIONS) == FALSE)
{
status = WdfRequestGetStatus(Request);
}
}
}
}

if (!NT_SUCCESS(status))
{
WdfRequestCompleteWithInformation(Request, status, 0);
}
}

Also, I got the !wdfkd.wdflogdump as below:

0: kd> !wdflogdump SaiDA2AE.sys
Trace searchpath is:

Trace format prefix is: %7!u!: %!FUNC! -
Trying to extract TMF information from - C:\symstore\Wdf01000.pdb\910864B4254D480C94ABAE23F3EBE0662\Wdf01000.pdb
Gather log: Please wait, this may take a moment (reading 4024 bytes).
% read so far … 10, 20, 30, 100
There are 28 log entries
— start of log —
1: FxIFRStart - FxIFR logging started
2: FxPkgPnp::PnpEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering PnP State WdfDevStatePnpInit from WdfDevStatePnpObjectCreated
3: FxPkgPnp::Dispatch - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900, IRP_MJ_PNP, 0x00000000(IRP_MN_START_DEVICE) IRP 0xFFFFE00169127410
4: FxPkgPnp::PnpEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering PnP State WdfDevStatePnpInitStarting from WdfDevStatePnpInit
5: FxPkgPnp::PnpEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering PnP State WdfDevStatePnpHardwareAvailable from WdfDevStatePnpInitStarting
6: FxIoTarget::SubmitLocked - ignoring WDFIOTARGET 00001FFE96E57C18 state, sending WDFREQUEST FFFFD00022822CA0, state WdfIoTargetStarted
7: FxPkgPnp::PowerPolicyEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering power policy state WdfDevStatePwrPolStarting from WdfDevStatePwrPolObjectCreated
8: FxPowerIdleMachine::ProcessEventLocked - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering power idle state FxIdleStarted from FxIdleStopped
9: FxPkgPnp::PowerEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering Power State WdfDevStatePowerStartingCheckDeviceType from WdfDevStatePowerObjectCreated
10: FxPkgPnp::PowerEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering Power State WdfDevStatePowerD0Starting from WdfDevStatePowerStartingCheckDeviceType
11: FxPkgPnp::PowerEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering Power State WdfDevStatePowerD0StartingConnectInterrupt from WdfDevStatePowerD0Starting
12: FxPkgPnp::PowerEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering Power State WdfDevStatePowerD0StartingDmaEnable from WdfDevStatePowerD0StartingConnectInterrupt
13: FxPkgPnp::PowerEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering Power State WdfDevStatePowerD0StartingStartSelfManagedIo from WdfDevStatePowerD0StartingDmaEnable
14: FxPkgIo::ResumeProcessingForPower - Power resume all queues of WDFDEVICE 0x00001FFE96E873D8
15: FxPowerIdleMachine::ProcessEventLocked - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering power idle state FxIdleStartedPowerUp from FxIdleStarted
16: FxPowerIdleMachine::ProcessEventLocked - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering power idle state FxIdleDisabled from FxIdleStartedPowerUp
17: FxPkgPnp::PowerEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering Power State WdfDevStatePowerDecideD0State from WdfDevStatePowerD0StartingStartSelfManagedIo
18: FxPkgPnp::PowerEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering Power State WdfDevStatePowerD0 from WdfDevStatePowerDecideD0State
19: FxPkgPnp::PowerPolicyEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering power policy state WdfDevStatePwrPolStartingPoweredUp from WdfDevStatePwrPolStarting
20: FxPkgPnp::PowerPolicyEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering power policy state WdfDevStatePwrPolStartingSucceeded from WdfDevStatePwrPolStartingPoweredUp
21: FxPkgPnp::PowerPolicyEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering power policy state WdfDevStatePwrPolStartingDecideS0Wake from WdfDevStatePwrPolStartingSucceeded
22: FxPkgPnp::PowerPolicyEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering power policy state WdfDevStatePwrPolStarted from WdfDevStatePwrPolStartingDecideS0Wake
23: FxPowerIdleMachine::ProcessEventLocked - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering power idle state FxIdleDisabled from FxIdleDisabled
24: FxPkgPnp::PnpEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering PnP State WdfDevStatePnpEnableInterfaces from WdfDevStatePnpHardwareAvailable
25: FxPkgPnp::PnpEnterNewState - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 entering PnP State WdfDevStatePnpStarted from WdfDevStatePnpEnableInterfaces
26: FxPkgPnp::Dispatch - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900, IRP_MJ_PNP, 0x00000014(IRP_MN_QUERY_PNP_DEVICE_STATE) IRP 0xFFFFE00169127410
27: FxPkgFdo::HandleQueryPnpDeviceStateCompletion - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900 returning PNP_DEVICE_STATE 0x0 IRP 0xFFFFE00169127410
28: FxPkgPnp::Dispatch - WDFDEVICE 0x00001FFE96E873D8 !devobj 0xFFFFE001690C7900, IRP_MJ_PNP, 0x00000007(IRP_MN_QUERY_DEVICE_RELATIONS) type BusRelations IRP 0xFFFFE0016AF34AB0
---- end of log ----


NTDEV is sponsored by OSR

Visit the list online at: https:

MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers!
Details at https:

To unsubscribe, visit the List Server section of OSR Online at https:</https:></https:></https:>

On Apr 13, 2017, at 11:04 PM, xxxxx@hotmail.com wrote:

I’m handling a strange issue on the bulk transfer. I have a USB driver installing as the function driver of the USB device. It’s the bulk interface with one IN pipe and one out pipe. After configuring the device properly, the driver creates two queues one for EvtIoRead and one for EvtIoWrite. Meanwhile, I have an application talking to the driver and sending data to the bulk out endpoint. After the application calls the API WriteFile, the EvtIoWrite gets called and it forwards the original request to next level after formatting it with calling WdfUsbTargetPipeFormatRequestForWrite. However, I don’t see the completion routine gets called after that. It causes the application hangs there because I call the WriteFile synchronously. The out pipe handle is valid and the packet length is less than the maximum packet size.

Drivers do not have worry about packet length. The host controller will chop your transfer up into packet-sized pieces for transmission on the wire.

Who is creating the SRequestContext? I see you trying to fetch the pointer, but I don’t see where you add that context to the request.

If this is all your “write” handler is going to do, you could have used WinUSB and avoided writing a driver altogether.

Is this brand-new hardware? Do you have any evidence that it actually works?

Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Thanks for the quick reply.

I also wrote a WinUsb application to do the same thing but the result is the same that the WriteFile never returns after I called it the first time the device plugs in. The API returns after I unplug the device. However, after the second time I plug in the device, the issue doesn’t happen.

I captured the USB etw log for the first time I plug in the device. It showed me a validation warning of the Dispatch URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER. The warning message is “Missing URB information, releasing dispatch message from endpoint USBCommonGlobals” and it shows me the type: Unknown type!

Using the usbview.exe, it shows me some errors in the interface descriptor of the bulk in and out endpoints. Is it the root cause the the value of bInterfaceSubClass is invalid for the bInterfaceClass 0xff? Thanks!

===>Interface Descriptor<===
bLength: 0x09
bDescriptorType: 0x04
bInterfaceNumber: 0x01
bAlternateSetting: 0x00
bNumEndpoints: 0x02
bInterfaceClass: 0xFF -> Vendor Specific Device
bInterfaceSubClass: 0x00
*!*CAUTION: This appears to be an invalid bInterfaceSubClass
bInterfaceProtocol: 0x00
iInterface: 0x06
English (United States) “Saitek FIP Data Pipes”
*!*CAUTION: 0xFF is a prerelease Class ID

On Apr 16, 2017, at 7:21 PM, xxxxx@hotmail.com wrote:

I also wrote a WinUsb application to do the same thing but the result is the same that the WriteFile never returns after I called it the first time the device plugs in. The API returns after I unplug the device. However, after the second time I plug in the device, the issue doesn’t happen.

I captured the USB etw log for the first time I plug in the device. It showed me a validation warning of the Dispatch URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER. The warning message is “Missing URB information, releasing dispatch message from endpoint USBCommonGlobals” and it shows me the type: Unknown type!

Using the usbview.exe, it shows me some errors in the interface descriptor of the bulk in and out endpoints. Is it the root cause the the value of bInterfaceSubClass is invalid for the bInterfaceClass 0xff? Thanks!

No. Frankly, nothing cares about that. Why don’t you post all of the config descriptor and we’ll take a closer look?

Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Here is the all of the descriptors from usbview.

[Port3] : USB Composite Device

—===>Device Information<===—
English product name: “Saitek Fip”

ConnectionStatus:
Current Config Value: 0x01 -> Device Bus Speed: High
Device Address: 0x0B
Open Pipes: 3

===>Endpoint Descriptor<===
bLength: 0x07
bDescriptorType: 0x05
bEndpointAddress: 0x83 -> Direction: IN - EndpointID: 3
bmAttributes: 0x03 -> Interrupt Transfer Type
wMaxPacketSize: 0x0040 = 1 transactions per microframe, 0x40 max bytes
bInterval: 0x07

===>Endpoint Descriptor<===
bLength: 0x07
bDescriptorType: 0x05
bEndpointAddress: 0x81 -> Direction: IN - EndpointID: 1
bmAttributes: 0x02 -> Bulk Transfer Type
wMaxPacketSize: 0x0200 = 0x200 max bytes
bInterval: 0x0A

===>Endpoint Descriptor<===
bLength: 0x07
bDescriptorType: 0x05
bEndpointAddress: 0x02 -> Direction: OUT - EndpointID: 2
bmAttributes: 0x02 -> Bulk Transfer Type
wMaxPacketSize: 0x0200 = 0x200 max bytes
bInterval: 0x0A

===>Device Descriptor<===
bLength: 0x12
bDescriptorType: 0x01
bcdUSB: 0x0200
bDeviceClass: 0x00 -> This is an Interface Class Defined Device
bDeviceSubClass: 0x00
bDeviceProtocol: 0x00
bMaxPacketSize0: 0x40 = (64) Bytes
idVendor: 0x06A3 = Saitek PLC
idProduct: 0xA2AE
bcdDevice: 0x0300
iManufacturer: 0x01
English (United States) “Saitek”
iProduct: 0x02
English (United States) “Saitek Fip”
iSerialNumber: 0x03
English (United States) “MZ05CF0D9C”
bNumConfigurations: 0x01

===>Configuration Descriptor<===
bLength: 0x09
bDescriptorType: 0x02
wTotalLength: 0x0039 -> Validated
bNumInterfaces: 0x02
bConfigurationValue: 0x01
iConfiguration: 0x04
English (United States) “Default Configuration”
bmAttributes: 0x80 -> Bus Powered
MaxPower: 0xFA = 500 mA

===>Interface Descriptor<===
bLength: 0x09
bDescriptorType: 0x04
bInterfaceNumber: 0x00
bAlternateSetting: 0x00
bNumEndpoints: 0x01
bInterfaceClass: 0x03 -> HID Interface Class
bInterfaceSubClass: 0x00
bInterfaceProtocol: 0x00
CAUTION: This may be an invalid bInterfaceProtocol
iInterface: 0x05
English (United States) “Saitek Flight Instrument Panel”

===>HID Descriptor<===
bLength: 0x09
bDescriptorType: 0x21
bcdHID: 0x0100
bCountryCode: 0x00
bNumDescriptors: 0x01
bDescriptorType: 0x22
wDescriptorLength: 0x0022

===>Endpoint Descriptor<===
bLength: 0x07
bDescriptorType: 0x05
bEndpointAddress: 0x83 -> Direction: IN - EndpointID: 3
bmAttributes: 0x03 -> Interrupt Transfer Type
wMaxPacketSize: 0x0040 = 1 transactions per microframe, 0x40 max bytes
bInterval: 0x07

===>Interface Descriptor<===
bLength: 0x09
bDescriptorType: 0x04
bInterfaceNumber: 0x01
bAlternateSetting: 0x00
bNumEndpoints: 0x02
bInterfaceClass: 0xFF -> Vendor Specific Device
bInterfaceSubClass: 0x00
*!*CAUTION: This appears to be an invalid bInterfaceSubClass
bInterfaceProtocol: 0x00
iInterface: 0x06
English (United States) “Saitek FIP Data Pipes”
*!*CAUTION: 0xFF is a prerelease Class ID

===>Endpoint Descriptor<===
bLength: 0x07
bDescriptorType: 0x05
bEndpointAddress: 0x81 -> Direction: IN - EndpointID: 1
bmAttributes: 0x02 -> Bulk Transfer Type
wMaxPacketSize: 0x0200 = 0x200 max bytes
bInterval: 0x0A

===>Endpoint Descriptor<===
bLength: 0x07
bDescriptorType: 0x05
bEndpointAddress: 0x02 -> Direction: OUT - EndpointID: 2
bmAttributes: 0x02 -> Bulk Transfer Type
wMaxPacketSize: 0x0200 = 0x200 max bytes
bInterval: 0x0A

better yet get a software or hardware usb analyzer (there is sort of one
included in the msft perf kit now) and figure out from that if your packet
is even getting to your endpoint. Right now you appear to be shooting in
the dark.

I think this still works:
https://blogs.msdn.microsoft.com/usbcoreblog/2014/09/02/capturing-usb-debug-traces/
but it has been a few years since I used it. Hardware analyzers are not
terribly expensive either.

Mark Roddy

On Mon, Apr 17, 2017 at 2:52 AM, Tim Roberts wrote:

> On Apr 16, 2017, at 7:21 PM, xxxxx@hotmail.com wrote:
> >
> > I also wrote a WinUsb application to do the same thing but the result is
> the same that the WriteFile never returns after I called it the first time
> the device plugs in. The API returns after I unplug the device. However,
> after the second time I plug in the device, the issue doesn’t happen.
> >
> > I captured the USB etw log for the first time I plug in the device. It
> showed me a validation warning of the Dispatch URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER.
> The warning message is “Missing URB information, releasing dispatch message
> from endpoint USBCommonGlobals” and it shows me the type: Unknown type!
> >
> > Using the usbview.exe, it shows me some errors in the interface
> descriptor of the bulk in and out endpoints. Is it the root cause the the
> value of bInterfaceSubClass is invalid for the bInterfaceClass 0xff? Thanks!
>
> No. Frankly, nothing cares about that. Why don’t you post all of the
> config descriptor and we’ll take a closer look?
> —
> Tim Roberts, xxxxx@probo.com
> Providenza & Boekelheide, Inc.
>
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list online at: http:> showlists.cfm?list=ntdev>
>
> MONTHLY seminars on crash dump analysis, WDF, Windows internals and
> software drivers!
> Details at http:
>
> To unsubscribe, visit the List Server section of OSR Online at <
> http://www.osronline.com/page.cfm?name=ListServer&gt;
></http:></http:>

xxxxx@hotmail.com wrote:

Here is the all of the descriptors from usbview.

Nothing unusual here. I’m guessing Doron’s original guess is correct:
your device is simply not accepting writes to the bulk pipe. Is it
possible there’s something you have to configure to tell it to listen?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Hi Tim,

The issue only happens the first time the device gets enumerated. After the issue happens, I unplugged it and plugged it again, the issue doesn’t happen again. The hardware USB analyzer doesn’t help here because it doesn’t get receive any packet yet. It seems it gets stuck in the host side driver stack. One more thing I forgot to mention is that the device is USB 2.0 device and plugged in the USB 3.0 port. Does it matter here?

Thanks,
Marshall

Hi Tim,

It’s weird that it only happens the first time the device gets enumerated. After I unplugged and plugged it in again, the issue won’t happen again. Using the hardware USB analyzer doesn’t help here because it gets stuck in the host driver stack. One another thing is that the device is USB2.0 and plugged in the USB 3.0 port. Does it matter here? Thanks.

Marshall

@Tim “Is it possible there’s something you have to configure to tell it to listen?”

Like doing a read at the far end for example. Seen that often enough.

@Tim I have seen many examples where a read needs to be established on the far end for a write to complete.

xxxxx@hotmail.com wrote:

It’s weird that it only happens the first time the device gets enumerated. After I unplugged and plugged it in again, the issue won’t happen again. Using the hardware USB analyzer doesn’t help here because it gets stuck in the host driver stack. One another thing is that the device is USB2.0 and plugged in the USB 3.0 port. Does it matter here?

It’s not supposed to, although I certainly had some unexplained problems
during the very early days of USB 3.0. How old is your hardware? What
brand is the USB host controller? What operating system are you using?
Does this happen on EVERY computer? Have you tried it on a USB 2.0
controller?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.