Using USB Continous Reader for continuously reading BULK IN data?

Hi Everyone,
I wanted to know if using the USB Continuous Reader for reading a continuous stream of USB BULK IN data from the device is the right implementation for reading continuous data received from a device?

Our device sends Continuous data to the host across the BULK IN endpoint. All of these data is of significance and require host processing to be done. With the usage of the Continuous Reader, we seem to be experiencing some data loss.

Is Continuous Reader implementation for reading Continuous data from the BULK IN endpoint the correct implementation?

For reading continuous streaming ISO data, the Continuous Reader is not used. There is a different mechanism for reading a Continuous Streaming ISO data as I saw in the driver samples in WDK.

The data that we are receiving from our device through the BULK IN endpoint is actually Audio data but this data is coming in as BULK IN rather then ISO IN due to some limitations in implementation in our USB device.

So, the rate at which data is supposed to be coming in the USB Bus is equivalent to the rate of the ISO IN data but its just getting received through the BULK IN endpoint.

Are there constraints in the USB Continuous Reader implementation for which data can’t be read from the device at faster rates? If so, what is the alternate solution of reading fast data from the USB device through the BULK IN endpoint? If not, what changes need to be done in the Continuous Reader implementation to acheive faster rate? I tried changing the NumPendingReads in the WDF_USB_CONTINUOUS_READER_CONFIG structure to 3 to increase the data rate but looks like it still drops data. Also changing this field does not ensure ordered data delivery and we require ordered delivery.

Is there any way I can achieve data read through the BULK IN endpoint at a faster rate as in ISO-IN? Will following the same mechanism as reading data from the ISO-IN help get the desired data rate?

Thanks
Monisha

Monisha Barooah wrote:

Hi Everyone,
I wanted to know if using the USB Continuous Reader for reading a
continuous stream of USB BULK IN data from the device is the right
implementation for reading continuous data received from a device?

It’s kind of an odd question, because that’s exactly what it was
designed for.

Our device sends Continuous data to the host across the BULK IN
endpoint. All of these data is of significance and require host
processing to be done. With the usage of the Continuous Reader, we
seem to be experiencing some data loss.

What kind of driver? KMDF? UMDF? WinUSB?

For reading continuous streaming ISO data, the Continuous Reader is
not used. There is a different mechanism for reading a Continuous
Streaming ISO data as I saw in the driver samples in WDK.

Right; the continuous reader does not support isochronous pipes because
the packet and buffering formats are different.

The data that we are receiving from our device through the BULK IN
endpoint is actually Audio data but this data is coming in as BULK IN
rather then ISO IN due to some limitations in implementation in our
USB device.

So, the rate at which data is supposed to be coming in the USB Bus is
equivalent to the rate of the ISO IN data but its just getting
received through the BULK IN endpoint.

Is this a USB 2.0 device, so bulk packets are 512 bytes? Does your
device send partial packets, or does it wait until it has all 512
bytes? How much data are you producing? How have you configured the
continuous reader?

I tried changing the *NumPendingReads *in the
WDF_USB_CONTINUOUS_READER_CONFIG structure to 3 to increase the data
rate but looks like it still drops data. Also changing this field does
not ensure ordered data delivery and we require ordered delivery.

How much user-mode processing are you doing? Are you getting the
buffers turned around fast enough that the reader never runs out?

Is there any way I can achieve data read through the BULK IN endpoint
at a faster rate as in ISO-IN? Will following the same mechanism as
reading data from the ISO-IN help get the desired data rate?

As long as you keep feeding empty buffers, there should be no dropouts.


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

Hi Tim,
Thanks for your response.

Please find my responses below.

Date: Mon, 7 Nov 2011 12:47:12 -0800
From: xxxxx@probo.com
To: xxxxx@lists.osr.com
Subject: Re: [ntdev] Using USB Continous Reader for continuously reading BULK IN data?

Monisha Barooah wrote:
> Hi Everyone,
> I wanted to know if using the USB Continuous Reader for reading a
> continuous stream of USB BULK IN data from the device is the right
> implementation for reading continuous data received from a device?

It’s kind of an odd question, because that’s exactly what it was
designed for.

By continuous data I meant that data is sent by the device continuously. The USB bus is under full utilization all the time due to the continuous frames sent to the host from the device.

> Our device sends Continuous data to the host across the BULK IN
> endpoint. All of these data is of significance and require host
> processing to be done. With the usage of the Continuous Reader, we
> seem to be experiencing some data loss.

What kind of driver? KMDF? UMDF? WinUSB?

Its a KMDF driver.

> For reading continuous streaming ISO data, the Continuous Reader is
> not used. There is a different mechanism for reading a Continuous
> Streaming ISO data as I saw in the driver samples in WDK.

Right; the continuous reader does not support isochronous pipes because
the packet and buffering formats are different.

Does the other mechanism support reading of BULK IN packets as well?

> The data that we are receiving from our device through the BULK IN
> endpoint is actually Audio data but this data is coming in as BULK IN
> rather then ISO IN due to some limitations in implementation in our
> USB device.
>
> So, the rate at which data is supposed to be coming in the USB Bus is
> equivalent to the rate of the ISO IN data but its just getting
> received through the BULK IN endpoint.

Is this a USB 2.0 device, so bulk packets are 512 bytes? Does your
device send partial packets, or does it wait until it has all 512
bytes? How much data are you producing? How have you configured the
continuous reader?

Its a USB1.1 device having BULK Max sizes of 64 bytes. The devices sends frame sizes of 3136 bytes across the BULK IN endpoint. These are spread across a lot of BULK IN packets of max size 64 bytes.
The following configurations have been done for the contiguous reader:
WDF_USB_CONTINUOUS_READER_CONFIG_INIT(&contReaderConfig,
EvtUsbBulkPipeReadComplete,
DeviceContext, // Context
3136); // TransferLength

contReaderConfig.NumPendingReads = 1; //so that the packets are ordered.

status = WdfUsbTargetPipeConfigContinuousReader(DeviceContext->BulkPipe,
&contReaderConfig);
if (!NT_SUCCESS(status)) {
KdPrint ((" Configuration for Continuous ReaderForvBulk IN EndPoint failed %x\n", status));
return status;
}

Are any more configurations required?

If NumPendingReads is changed to 3, there is still data loss.

> I tried changing the *NumPendingReads *in the
> WDF_USB_CONTINUOUS_READER_CONFIG structure to 3 to increase the data
> rate but looks like it still drops data. Also changing this field does
> not ensure ordered data delivery and we require ordered delivery.

How much user-mode processing are you doing? Are you getting the
buffers turned around fast enough that the reader never runs out?

A queue has been used for the data. The Reader adds the 3136 sized frames to the tail of the queue and schedules a workitem for further processing. In the context of the Workitem, the priority of the thread is increased to 31(Highest priority) and then the workitem fetches data from the head of the queue, does the required processing and sends processed data to user mode applications.

> Is there any way I can achieve data read through the BULK IN endpoint
> at a faster rate as in ISO-IN? Will following the same mechanism as
> reading data from the ISO-IN help get the desired data rate?

As long as you keep feeding empty buffers, there should be no dropouts.

I think there are empty buffers as the queue size is very high and I never observe the queue becoming empty to drop data. Are there are any other internal buffers which the reader uses which needs to be taken care of? Am I programming the reader the correct way? Seems okay to me. But you could give your views.

I believe if on the software side, things are taken care of appropriately, issues could be in the way data is read from the device…maybe we need to read data much more faster. I tried increasing the TransferLength to (3136 * 3) but that kind of slowed down the system and we were still observing data losses. The ISO transfers are periodic transfers and the ISO IN tokens are sent across the USB bus from the host in a periodic manner determined by the USB Host Controller on the Host side. I guess we would need to maintain the same rate of issuing the tokens for the BULK INs as well.

Is there anyway, the data loss can be resolved? Any suggestions?

Thanks
Monisha


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


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Monisha Barooah wrote:

By continuous data I meant that data is sent by the device
continuously. The USB bus is under full utilization all the time due
to the continuous frames sent to the host from the device.

Well, sort of. Remember that a USB device NEVER initiates data transfer
in USB. The host is in control; a USB device can only send when the
host tells it to send, and then the device gets to send one packet. The
host will only trigger the device if it has an I/O request waiting.

> Right; the continuous reader does not support isochronous pipes because
> the packet and buffering formats are different.

Does the other mechanism support reading of BULK IN packets as well?

I’m not sure what you mean. Bulk and interrupt pipes work one way,
isochronous pipes work another. The continuous reader supports the
bulk/interrupt method.

Its a USB1.1 device having BULK Max sizes of 64 bytes. The devices
sends frame sizes of 3136 bytes across the BULK IN endpoint. These are
spread across a lot of BULK IN packets of max size 64 bytes.

Is that actually what you see? Does the device really buffer up 3136
bytes before it sends anything? For example, what happens if you get a
bulk read request when you only have 32 bytes in your buffer? Do you
send the short packet? Or do you wait until a full packet is
available? The question is important. As long as the device sends full
(64 byte) packets, the current transfer will continue. As soon as you
send a short packet, the whole 3136-byte transfer is terminated. Unless
you have another request already waiting, your device won’t be given a
chance to send any more data.

The following configurations have been done for the contiguous reader:
*WDF_USB_CONTINUOUS_READER_CONFIG_INIT(&contReaderConfig,
EvtUsbBulkPipeReadComplete,
DeviceContext, // Context
3136); // TransferLength*
**
*contReaderConfig.NumPendingReads = 1; //so that the packets are
ordered.*

Your concern about ordering is not real. Your transfer will span almost
50 bulk packets over 3 milliseconds. There is no possible way (in the
real world) that you could receive completed transfers out of order.
Because a single read only takes 3 ms, there is also no possible way you
can hope to do a round trip to user-mode and back in between. You
absolutely need to raise that number. You might try 10.

**If NumPendingReads is changed to 3, there is still data loss.

3 still only spans 9 ms. That’s shorter than the user-mode scheduling
interval.

You know, you could do all of this without a custom driver by using WinUSB.

A queue has been used for the data. The Reader adds the 3136 sized
frames to the tail of the queue and schedules a workitem for further
processing. In the context of the Workitem, the priority of the thread
is increased to 31(Highest priority) and then the workitem fetches
data from the head of the queue, does the required processing and
sends processed data to user mode applications.

Screwing with the thread priority is, in almost every case, a bad idea.
If you can’t keep up at a normal priority, then it doesn’t really matter
how much buffering you have.

So, you copy the data out of the continuous reader’s buffers
immediately, and then hand it back for more processing. You don’t hold
on to the buffers?

I think there are empty buffers as the queue size is very high and I
never observe the queue becoming empty to drop data. Are there are any
other internal buffers which the reader uses which needs to be taken
care of?

There are no buffers in the USB stack.

I believe if on the software side, things are taken care of
appropriately, issues could be in the way data is read from the
device…maybe we need to read data much more faster. I tried
increasing the *TransferLength *to (3136 * 3) but that kind of slowed
down the system and we were still observing data losses. The ISO
transfers are periodic transfers and the ISO IN tokens are sent across
the USB bus from the host in a periodic manner determined by the USB
Host Controller on the Host side.

With a bulk pipe, the host controller will send IN tokens continuously
until the transfer is complete. The transfer will be complete when
either the number of bytes is satisfied, or a short packet is sent.


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

Hi Tim,
Thanks for your responses.

Date: Mon, 7 Nov 2011 13:39:44 -0800
From: xxxxx@probo.com
To: xxxxx@lists.osr.com
Subject: Re: [ntdev] Using USB Continous Reader for continuously reading BULK IN data?

Monisha Barooah wrote:
>
> By continuous data I meant that data is sent by the device
> continuously. The USB bus is under full utilization all the time due
> to the continuous frames sent to the host from the device.

Well, sort of. Remember that a USB device NEVER initiates data transfer
in USB. The host is in control; a USB device can only send when the
host tells it to send, and then the device gets to send one packet. The
host will only trigger the device if it has an I/O request waiting.

Yes, I agree.

> > Right; the continuous reader does not support isochronous pipes because
> > the packet and buffering formats are different.
>
> Does the other mechanism support reading of BULK IN packets as well?

I’m not sure what you mean. Bulk and interrupt pipes work one way,
isochronous pipes work another. The continuous reader supports the
bulk/interrupt method.

I was wondering if there was any other way I could read the continuous BULK IN data from the device other than using continuous reader.

> Its a USB1.1 device having BULK Max sizes of 64 bytes. The devices
> sends frame sizes of 3136 bytes across the BULK IN endpoint. These are
> spread across a lot of BULK IN packets of max size 64 bytes.

Is that actually what you see? Does the device really buffer up 3136
bytes before it sends anything? For example, what happens if you get a
bulk read request when you only have 32 bytes in your buffer? Do you
send the short packet? Or do you wait until a full packet is
available? The question is important. As long as the device sends full
(64 byte) packets, the current transfer will continue. As soon as you
send a short packet, the whole 3136-byte transfer is terminated. Unless
you have another request already waiting, your device won’t be given a
chance to send any more data.

The device is continuously sending framesizes of 3136 bytes. Data coming in 3136 sizes is sent by the device and is expected by the host. There is no way device sends data less than that as it is continuously monitoring and sending Audio data through the BULK IN endpoints.

> The following configurations have been done for the contiguous reader:
> *WDF_USB_CONTINUOUS_READER_CONFIG_INIT(&contReaderConfig,
> EvtUsbBulkPipeReadComplete,
> DeviceContext, // Context
> 3136); // TransferLength*
> **
> *contReaderConfig.NumPendingReads = 1; //so that the packets are
> ordered.*

Your concern about ordering is not real. Your transfer will span almost
50 bulk packets over 3 milliseconds. There is no possible way (in the
real world) that you could receive completed transfers out of order.
Because a single read only takes 3 ms, there is also no possible way you
can hope to do a round trip to user-mode and back in between. You
absolutely need to raise that number. You might try 10.

Yes, should do that.

> **If NumPendingReads is changed to 3, there is still data loss.

3 still only spans 9 ms. That’s shorter than the user-mode scheduling
interval.

You know, you could do all of this without a custom driver by using WinUSB.

> A queue has been used for the data. The Reader adds the 3136 sized
> frames to the tail of the queue and schedules a workitem for further
> processing. In the context of the Workitem, the priority of the thread
> is increased to 31(Highest priority) and then the workitem fetches
> data from the head of the queue, does the required processing and
> sends processed data to user mode applications.

Screwing with the thread priority is, in almost every case, a bad idea.
If you can’t keep up at a normal priority, then it doesn’t really matter
how much buffering you have.

I agree thats not a good way of altering thread priority. It was in the driver code I started working with.
I should remove the forced change in priority of the thread.

So, you copy the data out of the continuous reader’s buffers
immediately, and then hand it back for more processing. You don’t hold
on to the buffers?

> I think there are empty buffers as the queue size is very high and I
> never observe the queue becoming empty to drop data. Are there are any
> other internal buffers which the reader uses which needs to be taken
> care of?

There are no buffers in the USB stack.

> I believe if on the software side, things are taken care of
> appropriately, issues could be in the way data is read from the
> device…maybe we need to read data much more faster. I tried
> increasing the *TransferLength *to (3136 * 3) but that kind of slowed
> down the system and we were still observing data losses. The ISO
> transfers are periodic transfers and the ISO IN tokens are sent across
> the USB bus from the host in a periodic manner determined by the USB
> Host Controller on the Host side.

With a bulk pipe, the host controller will send IN tokens continuously
until the transfer is complete. The transfer will be complete when
either the number of bytes is satisfied, or a short packet is sent.

I think I should check for the short packet stuff as well.


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


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Monisha Barooah wrote:

> > Does the other mechanism support reading of BULK IN packets as well?
>
> I’m not sure what you mean. Bulk and interrupt pipes work one way,
> isochronous pipes work another. The continuous reader supports the
> bulk/interrupt method.

I was wondering if there was any other way I could read the continuous
BULK IN data from the device other than using continuous reader.

Sure, there is. You don’t have to use the continuous reader – it’s
just a convenience. You can create and submit the read requests
individually. It’s not clear that you’ll gain anything. The continuous
reader contains the combined experience of Microsoft’s USB engineers on
the best way to do continuous transfers.

The device is continuously sending framesizes of 3136 bytes. Data
coming in 3136 sizes is sent by the device and is expected by the
host. There is no way device sends data less than that as it is
continuously monitoring and sending Audio data through the BULK IN
endpoints.

OK. I’m just trying to point out ways this kind of process can go
wrong. I don’t know what kind of USB chip you are using, but there are
several ways these chips are built. Typically, there is a FIFO on the
chip. You shove bytes into the FIFO at one end, and the USB engine
pulls packets out the other. Now, let’s say you are in the process of
shoving your 3,136 bytes into the FIFO. If you happen to have copied 24
bytes in when the USB engine gets an IN token, a poorly designed USB
chip might ship out the 24 bytes that have accumulated, while more bytes
get shoved in at the other end. That would result in a short packet,
and a terminated transaction.

Now, in the real world, most of these chips have a separate mechanism to
“commit” the data in the FIFO, so that nothing goes out until a full
packet is present or some “commit” signal is asserted, but you need to
know how your chip works to make sure you’re handling that properly.


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