Num Bytes transferred over USB Interrupt Pipe

Hi All,
I am writing a UMDF2.0 based usb driver, following the umdf2_fx2 sample driver provided in MSDN.
I have configured the TransferLength of the Interrupt pipe and the continuous reader as follows :
{
WDF_USB_CONTINUOUS_READER_CONFIG contReaderConfig;

WDF_USB_CONTINUOUS_READER_CONFIG_INIT(&contReaderConfig,
OsrFxEvtUsbInterruptPipeReadComplete,
DeviceContext, // Context
2048); // TransferLength

contReaderConfig.EvtUsbTargetPipeReadersFailed = OsrFxEvtUsbInterruptReadersFailed;
contReaderConfig.HeaderLength = 0;
contReaderConfig.TrailerLength = 0;
contReaderConfig.NumPendingReads = 2;

status = WdfUsbTargetPipeConfigContinuousReader(DeviceContext->InterruptPipe,
&contReaderConfig);

}
My continuous reader is as follows :

VOID OsrFxEvtUsbInterruptPipeReadComplete(
WDFUSBPIPE Pipe,
WDFMEMORY Buffer,
size_t NumBytesTransferred,
WDFCONTEXT Context
)
{
PVOID requestBuffer;
requestBuffer = WdfMemoryGetBuffer(Buffer, NULL);

if (Pipe == pDeviceContext->InterruptPipe)
{
TraceEvents(TRACE_LEVEL_WARNING, DBG_INIT,"OsrFxEvtUsbInterruptPipeReadComplete Byte Read %d ", NumBytesTransferred);
}
}
The issue that I am facing is that, NumBytesTransferred is always set to max TransferLength configured, i.e 2048. , even though the pipe is transferring only few bytes of data.
I was expecting this value to be actual Number of Bytes transferred on the Pipe.
Similar is the case when a control setup packet is transferred from Device to Host, using below APi?s

{
WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memDesc,
(PVOID)msg,//(PVOID)test,
msg_size);

status = WdfUsbTargetDeviceSendControlTransferSynchronously(
DevContext->UsbDevice,
WDF_NO_HANDLE, // Optional WDFREQUEST
&sendOptions,
&controlSetupPacket,
&memDesc,
&bytesTransferred);

}
bytesTransferred is always reported as the TransferLength configured on this pipe. However as per MSDN it should be
BytesTransferred [out, optional]
A pointer to a location that receives the number of bytes that are transferred.
Could you please help/ suggest , how to debug this further ? Am I missing any configuration.
Note : When I capture the USB traffic using Wireshark, I could see the actual number of Bytes transferred over the pipe, which is way less than reported value.

To add further on this, i checked the usb etl log :

log using Netmon.
I am getting 2 packets on interrupt transfer.
One with UCX_ETW_EVENT_COMPLETE_URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER_PARTIAL_DATA and another one with
UCX_ETW_EVENT_DISPATCH_URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
?
8 of 0 success In 175 11:23:32 AM 12/5/2016 21.6787930 (7032) UsbUcx UsbUcx:Complete URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER with partial data
2048 In 176 11:23:32 AM 12/5/2016 21.6788811 (5940) UsbUcx UsbUcx:Dispatch URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER

The actual data is in Frame having UCX_ETW_EVENT_COMPLETE_URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER_PARTIAL_DATA with proper buffer length. However in continuous reader i am getting the buffer length from packet ( UCX_ETW_EVENT_DISPATCH_URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER )

Is there something which i am missing ?

Is the call returns STATUS_PENDING, the information about bytes transferred is only available in the completion data.

I assume Continuous readers are callbacks which are called when there are data available on interrupt pipes. How do we get the completion status for those transfer ?
Is there any API available ?

The callback is called upon a successful transfer, no NTSTATUS is passed to the callback.

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Monday, December 5, 2016 9:14 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Num Bytes transferred over USB Interrupt Pipe

I assume Continuous readers are callbacks which are called when there are data available on interrupt pipes. How do we get the completion status for those transfer ?
Is there any API available ?


NTDEV is sponsored by OSR

Visit the list online at: http:

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:</http:></http:></http:>

xxxxx@gmail.com wrote:

The issue that I am facing is that, NumBytesTransferred is always set to max TransferLength configured, i.e 2048. , even though the pipe is transferring only few bytes of data.
I was expecting this value to be actual Number of Bytes transferred on the Pipe.

What is the endpoint’s max packet size? If, for example, your
endpoint’s max packet size is 8 (which is not uncommon for an interrupt
pipe), then as long as your device keeps sending packets of 8 bytes,
your read request will not complete until all 2048 bytes have been
read. Interrupt and bulk read requests complete when (A) the whole
transfer buffer is filled, or (B) the device sends back a packet shorter
than the endpoint maximum.

Similar is the case when a control setup packet is transferred from Device to Host, using below APi?s
{
WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memDesc,
(PVOID)msg,//(PVOID)test,
msg_size);

status = WdfUsbTargetDeviceSendControlTransferSynchronously(
DevContext->UsbDevice,
WDF_NO_HANDLE, // Optional WDFREQUEST
&sendOptions,
&controlSetupPacket,
&memDesc,
&bytesTransferred);

}
bytesTransferred is always reported as the TransferLength configured on this pipe.

It is somewhat unusual to have a control transfer return a short packet,
although it is allowed. I’m not sure what you mean by “TransferLength
configured on this pipe”. The kernel will set the wLength field equal
to the size of your memory descriptor, and that’s what you should get
back. The bytesTransferred value is copied straight from the
TransferBufferLength field of the URB, and that gets updated with the
actual data length as read.


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

> Interrupt and bulk read requests complete when (A) the whole transfer buffer is filled, or (B) the device sends back a packet shorter than the endpoint maximum.

To be pedantic, if your last packet size is endpoint max packet size and the transfer is finished, you need to send a subsequent zero length packet (ZLP) to satisfy the requirement that you send a packet shorter than the EP max.

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Monday, December 5, 2016 10:33 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Num Bytes transferred over USB Interrupt Pipe

xxxxx@gmail.com wrote:
> The issue that I am facing is that, NumBytesTransferred is always set to max TransferLength configured, i.e 2048. , even though the pipe is transferring only few bytes of data.
> I was expecting this value to be actual Number of Bytes transferred on the Pipe.

What is the endpoint’s max packet size? If, for example, your endpoint’s max packet size is 8 (which is not uncommon for an interrupt pipe), then as long as your device keeps sending packets of 8 bytes, your read request will not complete until all 2048 bytes have been read. Interrupt and bulk read requests complete when (A) the whole transfer buffer is filled, or (B) the device sends back a packet shorter than the endpoint maximum.

> Similar is the case when a control setup packet is transferred from
> Device to Host, using below APi?s {
> WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memDesc,
> (PVOID)msg,//(PVOID)test,
>
> msg_size);
>
> status = WdfUsbTargetDeviceSendControlTransferSynchronously(
> DevContext->UsbDevice,
> WDF_NO_HANDLE, // Optional WDFREQUEST
> &sendOptions,
> &controlSetupPacket,
> &memDesc,
> &bytesTransferred);
>
> }
> bytesTransferred is always reported as the TransferLength configured on this pipe.

It is somewhat unusual to have a control transfer return a short packet, although it is allowed. I’m not sure what you mean by “TransferLength configured on this pipe”. The kernel will set the wLength field equal to the size of your memory descriptor, and that’s what you should get back. The bytesTransferred value is copied straight from the TransferBufferLength field of the URB, and that gets updated with the actual data length as read.


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


NTDEV is sponsored by OSR

Visit the list online at: http:

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:</http:></http:></http:>

Doron Holan wrote:

> Interrupt and bulk read requests complete when (A) the whole transfer buffer is filled, or (B) the device sends back a packet shorter than the endpoint maximum.
To be pedantic, if your last packet size is endpoint max packet size and the transfer is finished, you need to send a subsequent zero length packet (ZLP) to satisfy the requirement that you send a packet shorter than the EP max.

Well, the read request will still complete as soon as the buffer fills,
even without a ZLP. The ZLP is only necessary if the actual transfer is
smaller than the buffer AND happens to be an even multiple of the
endpoint size.


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

I havent configured explictly max packet size for endpoints. So the default value should be good.
The data returned in Continuous reader is 12 bytes, but the NumBytesTransferred is always set to 2048.

Since my interrupt pipe can read variable length data, how do i make sure, how much data to read from the buffer ?

Regards
Mukesh

ZLP should be sent from the device side, and i guess its sending it properly, as the same device is returning proper number of bytes in Completion parameter, when used with WinUSB API.

Issue is when i use UMDF 2.0 Native USB api’s continuous reader.

continuous readers are just a reader configured for Interrupt pipe, and should return the actual no of bytes available in Buffer, not the complete buffer length. Is my thinking correct ?

Thank you for being more specifically pedantic :slight_smile:

Get Outlook for Android


From: xxxxx@lists.osr.com on behalf of Tim Roberts
Sent: Monday, December 5, 2016 10:47:06 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Num Bytes transferred over USB Interrupt Pipe

Doron Holan wrote:
>> Interrupt and bulk read requests complete when (A) the whole transfer buffer is filled, or (B) the device sends back a packet shorter than the endpoint maximum.
> To be pedantic, if your last packet size is endpoint max packet size and the transfer is finished, you need to send a subsequent zero length packet (ZLP) to satisfy the requirement that you send a packet shorter than the EP max.

Well, the read request will still complete as soon as the buffer fills,
even without a ZLP. The ZLP is only necessary if the actual transfer is
smaller than the buffer AND happens to be an even multiple of the
endpoint size.


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


NTDEV is sponsored by OSR

Visit the list online at: http:

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:</http:></http:></http:>

For an interrupt pipe, you should not be using WdfUsbTargetDeviceSendControlTransferSynchronously.

Use WdfUsbTargetDeviceSendUrbSynchronously.

xxxxx@gmail.com wrote:

I havent configured explictly max packet size for endpoints. So the default value should be good.

I’m not sure you get how this works. This is specified by the device.
The configuration descriptor from the device gives the max packet size
for every endpoint, in the same descriptor where it identifies bulk vs
interrupt vs isochronous. That’s also where the repeat rate for
interrupt pipes is specified. There is no “default”, and it’s not a
choice you make in the driver.

You can dump the configuration descriptor in your driver to find this,
or you can use usbview.

The data returned in Continuous reader is 12 bytes, but the NumBytesTransferred is always set to 2048.

Again, if the endpoint descriptor specifies the max packet size at 12
bytes, this is all as expected.

Since my interrupt pipe can read variable length data, how do i make sure, how much data to read from the buffer ?

This is all part of the USB convention. When the device sends a full
packet (that is, the endpoint’s maximum packet size), that is considered
to be one part of a larger “transfer”. The transfer is not completed
until the buffer fills, or a packet shorter than the maximum gets sent.

If you need to send responses of various sizes, then the max packet size
in the descriptor should be set to a large number. If the max packet
size is 512, for example, and the device sends a packet of 12 bytes,
that will end the current transfer. Your 2048-byte buffer will contain
12 bytes, and then you’ll have to submit another.


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

@Tim, Doron ,
Could you please help me or give any pointers to check the actual data length (and not the buffer length) in continuous reader ?

WdfUsbTargetDeviceSendUrbSynchronously is available only for KMDF driver.
I am following the windows sample driver umdf2_fx2, so believe we can use the WdfUsbTargetDeviceSendControlTransferSynchronously.

“If you need to send responses of various sizes, then the max packet size
in the descriptor should be set to a large number. If the max packet
size is 512, for example, and the device sends a packet of 12 bytes,
that will end the current transfer. Your 2048-byte buffer will contain
12 bytes, and then you’ll have to submit another.”

The buffer is having 12bytes data only, but the numofBytesreturned is set to 512, as per above example. How do i know in the continuous reader if the actual data is only 12 bytes or more or complete 512bytes is the actual data ? Buffer is all zeroed out, which can be a valid data. So how much buffer length i should access to read the actual data ? This is the reason i need actual NumBytesTransferred, to restrict my read to only those many bytes in buffer.

if you look to the osrusbfx2 interrupt code you will see this:

In the continuous reader configuration:

WDF_USB_CONTINUOUS_READER_CONFIG_INIT(&contReaderConfig,
OsrFxEvtUsbInterruptPipeReadComplete,
DeviceContext, // Context
sizeof(UCHAR)); // TransferLength

And then in the OsrFxEvtUsbInterruptPipeReadComplete callback, you have:

assert(NumBytesTransferred == sizeof(UCHAR));

For you, the assertion would be:

assert(NumBytesTransferred == 2048);

https://github.com/Microsoft/Windows-driver-samples/blob/master/usb/umdf2_fx2/driver/interrupt.c

You want to call WdfUsbTargetPipeWriteSynchronously for sending a transfer on the interrupt pipe. The third parameter, NumBytesTransferred, indicates how many bytes were transferred (not the max buffer size)

Get Outlook for Android


From: xxxxx@lists.osr.com on behalf of xxxxx@gmail.com
Sent: Monday, December 5, 2016 11:46:25 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Num Bytes transferred over USB Interrupt Pipe

@Tim, Doron ,
Could you please help me or give any pointers to check the actual data length (and not the buffer length) in continuous reader ?

WdfUsbTargetDeviceSendUrbSynchronously is available only for KMDF driver.
I am following the windows sample driver umdf2_fx2, so believe we can use the WdfUsbTargetDeviceSendControlTransferSynchronously.


NTDEV is sponsored by OSR

Visit the list online at: http:

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:</http:></http:></http:>

Sorry if i am not able to convey the message properly.

I cant use “assert(NumBytesTransferred == 2048);”, as this will always check for the NumBytesTransferred = 2048. My interrupt pipe can receive less value like 8 bytes, 12 bytes.
And thats perfectly ok for the driver. However i want that number of bytes to be reflected properly in NumBytesTransferred.

In WDF_USB_CONTINUOUS_READER_CONFIG_INIT, i configure the transferLength to be the Max data that i can receive on this Pipe, but need not always get the Max. If i receive a shorter packet, the actual size should be reflected in the NumBytesTransferred.

That is how the cont reader works. If it isn’t working this way your device isn’t doing the right thing on the USB wire

Get Outlook for Android


From: xxxxx@lists.osr.com on behalf of xxxxx@gmail.com
Sent: Monday, December 5, 2016 8:18:52 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Num Bytes transferred over USB Interrupt Pipe

Sorry if i am not able to convey the message properly.

I cant use “assert(NumBytesTransferred == 2048);”, as this will always check for the NumBytesTransferred = 2048. My interrupt pipe can receive less value like 8 bytes, 12 bytes.
And thats perfectly ok for the driver. However i want that number of bytes to be reflected properly in NumBytesTransferred.

In WDF_USB_CONTINUOUS_READER_CONFIG_INIT, i configure the transferLength to be the Max data that i can receive on this Pipe, but need not always get the Max. If i receive a shorter packet, the actual size should be reflected in the NumBytesTransferred.


NTDEV is sponsored by OSR

Visit the list online at: http:

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:</http:></http:></http:>

xxxxx@gmail.com wrote:

I cant use “assert(NumBytesTransferred == 2048);”, as this will always check for the NumBytesTransferred = 2048. My interrupt pipe can receive less value like 8 bytes, 12 bytes.
And thats perfectly ok for the driver. However i want that number of bytes to be reflected properly in NumBytesTransferred.

In WDF_USB_CONTINUOUS_READER_CONFIG_INIT, i configure the transferLength to be the Max data that i can receive on this Pipe, but need not always get the Max. If i receive a shorter packet, the actual size should be reflected in the NumBytesTransferred.

You still seem to be missing the point. You (the driver) do not get to
decide “the max data that I can receive on this pipe”. That piece of
information is specified by the device, in its descriptors. The fact
that you have STILL not showed us your descriptors leads me to suspect
that you don’t know what the endpoint’s maximum packet size is, and
without that piece of information, it is absolutely impossible to debug
your problem. The behavior will depend on the endpoint descriptor.


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