USB: how transmit more than wMaxPacketSize of bulk data in one submission ? - Linux
This is a discussion on USB: how transmit more than wMaxPacketSize of bulk data in one submission ? - Linux ; Hi fellows,
I'm confused about the different size aspects, when setting up a USB
transmission. Here's a brief example of what I want:
bulk_size is 512 bytes (USB 2.0) (endpoint->wMaxPacketSize)
data size is 1000 bytes
From LDD I learnt, that ...

- Forum
- OS Forums
- Linux
- USB: how transmit more than wMaxPacketSize of bulk data in one submission ?
-
USB: how transmit more than wMaxPacketSize of bulk data in one submission ?
Hi fellows,
I'm confused about the different size aspects, when setting up a USB
transmission. Here's a brief example of what I want:
bulk_size is 512 bytes (USB 2.0) (endpoint->wMaxPacketSize)
data size is 1000 bytes
From LDD I learnt, that it should be possible to set up the URB so that all
data are delivered in one bunch and the core parts between the submission
and the completion callback do the division and transmissions in adequate
blocks.
So I want to hand over to the URB a buffer containing the 1000 bytes,
and receive an alertion (completion callback handler), when all 1000 bytes
are out.
To transmit 512 bytes, I would do this:
-------------------------
urb = usb_alloc_urb(0,GFP_KERNEL);
buf = usb_buffer_alloc (udev, bulk_size, GFP_KERNEL, &urb->transfer_dma);
memcpy(buf,data,bulk_size);
usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(..), buf, bulk_size,
callback,dev);
urb->transfer_buffer_length = bulk_size;
usb_submit_urb(urb, GFP_KERNEL);
and then, in callback handler (or at least after that):
usb_buffer_free(udev, bulk_size, buf, urb->transfer_dma);
usb_free_urb(urb);
------------------------------
Please check the '?'s. What must be filled in? Are my guesses ok?
urb = usb_alloc_urb(0,GFP_KERNEL);
buf = usb_buffer_alloc (udev, ?data_size?, GFP_KERNEL, &urb->transfer_dma);
memcpy(buf,data,?data_size?);
usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(..), buf, ?data_size?,
callback,dev);
urb->transfer_buffer_length = ?bulk_size?;
usb_submit_urb(urb, GFP_KERNEL);
and then, in callback handler (or at least after that):
usb_buffer_free(udev, ?data_size?, buf, urb->transfer_dma);
usb_free_urb(urb);
------------------------------
What happens after submission?
First packet goes out. And then?
Is the second packet (with the rest of the data) automatically set up and
submitted internally, before the callback handler is launched?
Or is any further action required from my side?
I'd appreciate, if anybody could shed some light onto this.
Bernhard
-
Re: USB: how transmit more than wMaxPacketSize of bulk data in one submission ?
Bernhard Holzmayer writes:
> I'm confused about the different size aspects, when setting up a USB
> transmission. Here's a brief example of what I want:
>
> bulk_size is 512 bytes (USB 2.0) (endpoint->wMaxPacketSize)
> data size is 1000 bytes
>
> From LDD I learnt, that it should be possible to set up the URB so that all
> data are delivered in one bunch and the core parts between the submission
> and the completion callback do the division and transmissions in adequate
> blocks.
Actually, the hardware (ie the host controller) is supposed to frame
user data into USB bulk packets.
[...]
> Please check the '?'s. What must be filled in? Are my guesses ok?
> urb = usb_alloc_urb(0,GFP_KERNEL);
> buf = usb_buffer_alloc (udev, ?data_size?, GFP_KERNEL, &urb->transfer_dma);
> memcpy(buf,data,?data_size?);
> usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(..), buf, ?data_size?,
> callback,dev);
> urb->transfer_buffer_length = ?bulk_size?;
This will result in requesting a transfer of 512 octets.
> What happens after submission?
The USB spec will tell you this in sufficient detail.
> First packet goes out. And then?
If there is is data left in the URB, insofar the host controller knows
this (which it doesn't, because you lied to him about your intentions),
the next packet will go out.
-
Re: USB: how transmit more than wMaxPacketSize of bulk data in one submission ?
On Wed, 11 Oct 2006 09:05:38 +0200, Bernhard Holzmayer
wrote:
>Hi fellows,
>
>I'm confused about the different size aspects, when setting up a USB
>transmission. Here's a brief example of what I want:
>
>bulk_size is 512 bytes (USB 2.0) (endpoint->wMaxPacketSize)
>data size is 1000 bytes
>
>From LDD I learnt, that it should be possible to set up the URB so that all
>data are delivered in one bunch and the core parts between the submission
>and the completion callback do the division and transmissions in adequate
>blocks.
>So I want to hand over to the URB a buffer containing the 1000 bytes,
>and receive an alertion (completion callback handler), when all 1000 bytes
>are out.
>
>To transmit 512 bytes, I would do this:
> -------------------------
>urb = usb_alloc_urb(0,GFP_KERNEL);
>buf = usb_buffer_alloc (udev, bulk_size, GFP_KERNEL, &urb->transfer_dma);
>memcpy(buf,data,bulk_size);
>usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(..), buf, bulk_size,
>callback,dev);
>urb->transfer_buffer_length = bulk_size;
>usb_submit_urb(urb, GFP_KERNEL);
>
>and then, in callback handler (or at least after that):
>usb_buffer_free(udev, bulk_size, buf, urb->transfer_dma);
>usb_free_urb(urb);
> ------------------------------
>Please check the '?'s. What must be filled in? Are my guesses ok?
>urb = usb_alloc_urb(0,GFP_KERNEL);
>buf = usb_buffer_alloc (udev, ?data_size?, GFP_KERNEL, &urb->transfer_dma);
>memcpy(buf,data,?data_size?);
>usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(..), buf, ?data_size?,
>callback,dev);
>urb->transfer_buffer_length = ?bulk_size?;
>usb_submit_urb(urb, GFP_KERNEL);
>
>and then, in callback handler (or at least after that):
>usb_buffer_free(udev, ?data_size?, buf, urb->transfer_dma);
>usb_free_urb(urb);
> ------------------------------
>What happens after submission?
>First packet goes out. And then?
>Is the second packet (with the rest of the data) automatically set up and
>submitted internally, before the callback handler is launched?
>Or is any further action required from my side?
>
So you are writing a driver, right? My advice is don't. There are good
userspace tools with none of the agonies of Kernel debugging and
oopses etc.
Ok, you really want to do a driver. I hope it is not premature
optimization, but you really really want to do a driver. In that case
read LDD3 a couple more times. Try to find an existing kernel driver
doing something similar to what you want to do, start with that.
Urbs have a simple rule - one submission one callback. The USB core
splits the data into as many packets are required. When they are all
done you get one callback. Checking error statuses are critical in a
USB driver.
Luck, Steve
There is no "x" in my email address.
-
Re: USB: how transmit more than wMaxPacketSize of bulk data in one submission ?
Rainer Weikusat wrote:
> Bernhard Holzmayer writes:
>> I'm confused about the different size aspects, when setting up a USB
>> transmission. Here's a brief example of what I want:
>>
>> bulk_size is 512 bytes (USB 2.0) (endpoint->wMaxPacketSize)
>> data size is 1000 bytes
>>
>> From LDD I learnt, that it should be possible to set up the URB so that
>> all data are delivered in one bunch and the core parts between the
>> submission and the completion callback do the division and transmissions
>> in adequate blocks.
>
> Actually, the hardware (ie the host controller) is supposed to frame
> user data into USB bulk packets.
>
> [...]
>
>> Please check the '?'s. What must be filled in? Are my guesses ok?
>> urb = usb_alloc_urb(0,GFP_KERNEL);
>> buf = usb_buffer_alloc (udev, ?data_size?, GFP_KERNEL,
>> &urb->transfer_dma); memcpy(buf,data,?data_size?);
>> usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(..), buf, ?data_size?,
>> callback,dev);
>> urb->transfer_buffer_length = ?bulk_size?;
>
> This will result in requesting a transfer of 512 octets.
Though I filled urb with data_size ?
>
>> What happens after submission?
>
> The USB spec will tell you this in sufficient detail.
Depends. My question aimed at the treatment of the URB.
>
>> First packet goes out. And then?
>
> If there is is data left in the URB, insofar the host controller knows
> this (which it doesn't, because you lied to him about your intentions),
> the next packet will go out.
So what's the solution to tell it the truth?
urb->transfer_buffer_length = data_size ??
You see my problem?
I agree, that it's up to the host-controller to fragment my data.
But do I have to tell it the packet size for the fragments?
Sounds silly, but it's not obvious (to me), if data_size>bulk_size
Bernhard
-
Re: USB: how transmit more than wMaxPacketSize of bulk data in one submission ?
Steve Calfee wrote:
>
> So you are writing a driver, right? My advice is don't. There are good
> userspace tools with none of the agonies of Kernel debugging and
> oopses etc.
I agree. Did userspace drivers before (libusb) - but isn't acceptable
here...
>
> Ok, you really want to do a driver.
No: not want - just have to! Self-made hardware needs this driver.
> I hope it is not premature
> optimization, but you really really want to do a driver. In that case
> read LDD3 a couple more times. Try to find an existing kernel driver
> doing something similar to what you want to do, start with that.
Good advice. Doing so most of my time... :-)
>
> Urbs have a simple rule - one submission one callback.
All right - I expected this - and seems correct.
> The USB core
> splits the data into as many packets are required. When they are all
> done you get one callback.
That's my point: since I increased the size of the urb buffer, I don't
receive a callback anymore. That's why I wanted to make sure that I got
everything right before taking into account the other end of USB.
> Checking error statuses are critical in a USB driver.
I experience this piece of wisdom for some time now ...
>
> Luck, Steve
>
-
Re: USB: how transmit more than wMaxPacketSize of bulk data in one submission ?
Bernhard Holzmayer writes:
[...]
>>> What happens after submission?
>>
>> The USB spec will tell you this in sufficient detail.
> Depends. My question aimed at the treatment of the URB.
You have basically two options:
- read the spec and the source to determine the answer
yourself
- just accept reality as it is
Which, in this case, means that that the transfer_buffer_length is the
length of the buffer you wish to transfer and that fragmentation,
insofar needed, is handled by the host controller, and fragmentation,
insofar introduced by the HCD implementation 'for some reason', is
handled by the HCD (host controller driver).
-
Re: USB: how transmit more than wMaxPacketSize of bulk data in one submission ?
Steve Calfee writes:
[...]
> Urbs have a simple rule - one submission one callback. The USB core
> splits the data into as many packets are required.
Strictly speaking, this is not true. The 'USB core' splits the data
into as many 'transfer descriptors' as it desires (exception: UHCI)
and the host controller handles fragmentation imposed by the USB
itself.
-
Re: USB: how transmit more than wMaxPacketSize of bulk data in one submission ?
On Wed, 11 Oct 2006 09:05:38 +0200, Bernhard Holzmayer
wrote:
>Hi fellows,
>
>I'm confused about the different size aspects, when setting up a USB
>transmission. Here's a brief example of what I want:
>
>bulk_size is 512 bytes (USB 2.0) (endpoint->wMaxPacketSize)
>data size is 1000 bytes
>
>From LDD I learnt, that it should be possible to set up the URB so that all
>data are delivered in one bunch and the core parts between the submission
>and the completion callback do the division and transmissions in adequate
>blocks.
>So I want to hand over to the URB a buffer containing the 1000 bytes,
>and receive an alertion (completion callback handler), when all 1000 bytes
>are out.
>
>To transmit 512 bytes, I would do this:
> -------------------------
>urb = usb_alloc_urb(0,GFP_KERNEL);
>buf = usb_buffer_alloc (udev, bulk_size, GFP_KERNEL, &urb->transfer_dma);
>memcpy(buf,data,bulk_size);
>usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(..), buf, bulk_size,
>callback,dev);
>urb->transfer_buffer_length = bulk_size;
>usb_submit_urb(urb, GFP_KERNEL);
>
>and then, in callback handler (or at least after that):
>usb_buffer_free(udev, bulk_size, buf, urb->transfer_dma);
>usb_free_urb(urb);
> ------------------------------
>Please check the '?'s. What must be filled in? Are my guesses ok?
>urb = usb_alloc_urb(0,GFP_KERNEL);
>buf = usb_buffer_alloc (udev, ?data_size?, GFP_KERNEL, &urb->transfer_dma);
>memcpy(buf,data,?data_size?);
>usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(..), buf, ?data_size?,
>callback,dev);
>urb->transfer_buffer_length = ?bulk_size?;
>usb_submit_urb(urb, GFP_KERNEL);
>
>and then, in callback handler (or at least after that):
>usb_buffer_free(udev, ?data_size?, buf, urb->transfer_dma);
>usb_free_urb(urb);
> ------------------------------
>What happens after submission?
>First packet goes out. And then?
>Is the second packet (with the rest of the data) automatically set up and
>submitted internally, before the callback handler is launched?
>Or is any further action required from my side?
>
So you are writing a driver, right? My advice is don't. There are good
userspace tools with none of the agonies of Kernel debugging and
oopses etc.
Ok, you really want to do a driver. I hope it is not premature
optimization, but you really really want to do a driver. In that case
read LDD3 a couple more times. Try to find an existing kernel driver
doing something similar to what you want to do, start with that.
Urbs have a simple rule - one submission one callback. The USB core
splits the data into as many packets are required. When they are all
done you get one callback. Checking error statuses are critical in a
USB driver.
Luck, Steve
There is no "x" in my email address.
-
Re: USB: how transmit more than wMaxPacketSize of bulk data in one submission ?
On Wed, 11 Oct 2006 09:05:38 +0200, Bernhard Holzmayer
wrote:
>Hi fellows,
>
>I'm confused about the different size aspects, when setting up a USB
>transmission. Here's a brief example of what I want:
>
>bulk_size is 512 bytes (USB 2.0) (endpoint->wMaxPacketSize)
>data size is 1000 bytes
>
>From LDD I learnt, that it should be possible to set up the URB so that all
>data are delivered in one bunch and the core parts between the submission
>and the completion callback do the division and transmissions in adequate
>blocks.
>So I want to hand over to the URB a buffer containing the 1000 bytes,
>and receive an alertion (completion callback handler), when all 1000 bytes
>are out.
>
>To transmit 512 bytes, I would do this:
> -------------------------
>urb = usb_alloc_urb(0,GFP_KERNEL);
>buf = usb_buffer_alloc (udev, bulk_size, GFP_KERNEL, &urb->transfer_dma);
>memcpy(buf,data,bulk_size);
>usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(..), buf, bulk_size,
>callback,dev);
>urb->transfer_buffer_length = bulk_size;
>usb_submit_urb(urb, GFP_KERNEL);
>
>and then, in callback handler (or at least after that):
>usb_buffer_free(udev, bulk_size, buf, urb->transfer_dma);
>usb_free_urb(urb);
> ------------------------------
>Please check the '?'s. What must be filled in? Are my guesses ok?
>urb = usb_alloc_urb(0,GFP_KERNEL);
>buf = usb_buffer_alloc (udev, ?data_size?, GFP_KERNEL, &urb->transfer_dma);
>memcpy(buf,data,?data_size?);
>usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(..), buf, ?data_size?,
>callback,dev);
>urb->transfer_buffer_length = ?bulk_size?;
>usb_submit_urb(urb, GFP_KERNEL);
>
>and then, in callback handler (or at least after that):
>usb_buffer_free(udev, ?data_size?, buf, urb->transfer_dma);
>usb_free_urb(urb);
> ------------------------------
>What happens after submission?
>First packet goes out. And then?
>Is the second packet (with the rest of the data) automatically set up and
>submitted internally, before the callback handler is launched?
>Or is any further action required from my side?
>
So you are writing a driver, right? My advice is don't. There are good
userspace tools with none of the agonies of Kernel debugging and
oopses etc.
Ok, you really want to do a driver. I hope it is not premature
optimization, but you really really want to do a driver. In that case
read LDD3 a couple more times. Try to find an existing kernel driver
doing something similar to what you want to do, start with that.
Urbs have a simple rule - one submission one callback. The USB core
splits the data into as many packets are required. When they are all
done you get one callback. Checking error statuses are critical in a
USB driver.
Luck, Steve
There is no "x" in my email address.
-
Re: USB: how transmit more than wMaxPacketSize of bulk data in one submission ?
Bernhard Holzmayer wrote:
>
> I'm confused about the different size aspects...
Thank you, fellows, for your response.
Gave me some additional insight, but could not really help me,
because my problem was not that of fragmentation etc.
Instead, I had a silly pointer issue:
positioning to the end with ptr=ptr+sizeof(*ptr) failed,
since ptr was of a struct type,
and I just forgot to cast it like in
ptr=(type) ((void*)ptr+sizeof(*ptr))
Caused confusion on USB receiver - and missing callback.
After that modification, my transmissions work pretty well again,
independent of their length.
Silly enough. My confusion came, since I didn't receive the callback
anymore ...
Bernhard
-
Re: USB: how transmit more than wMaxPacketSize of bulk data in one submission ?
Bernhard Holzmayer writes:
[...]
> Instead, I had a silly pointer issue:
> positioning to the end with ptr=ptr+sizeof(*ptr) failed,
> since ptr was of a struct type,
> and I just forgot to cast it like in
> ptr=(type) ((void*)ptr+sizeof(*ptr))
According to C, this construct has undefined behaviour (it is a "gcc
extension") and the correct way would be to use a char * instead.
But this is pointless, because
(char *)p + sizeof(*p) == p + 1
JFTR.
-
Re: USB: how transmit more than wMaxPacketSize of bulk data in onesubmission ?
Bernhard Holzmayer wrote:
> Bernhard Holzmayer wrote:
>
>
>>I'm confused about the different size aspects...
>
>
> Thank you, fellows, for your response.
> Gave me some additional insight, but could not really help me,
> because my problem was not that of fragmentation etc.
>
> Instead, I had a silly pointer issue:
> positioning to the end with ptr=ptr+sizeof(*ptr) failed,
> since ptr was of a struct type,
> and I just forgot to cast it like in
> ptr=(type) ((void*)ptr+sizeof(*ptr))
> Caused confusion on USB receiver - and missing callback.
What's wrong with a simple 'p++' instead?
(Please remember that pointer arithmetic is done
in units of the pointer's target type size).
--
Tauno Voipio
tauno voipio (at) iki fi
-
Re: USB: how transmit more than wMaxPacketSize of bulk data in one submission ?
Tauno Voipio writes:
> Bernhard Holzmayer wrote:
>> Bernhard Holzmayer wrote:
>>
>>>I'm confused about the different size aspects...
>> Thank you, fellows, for your response.
>> Gave me some additional insight, but could not really help me,
>> because my problem was not that of fragmentation etc.
>> Instead, I had a silly pointer issue: positioning to the end with
>> ptr=ptr+sizeof(*ptr) failed, since ptr was of a struct type,
>> and I just forgot to cast it like in
>> ptr=(type) ((void*)ptr+sizeof(*ptr))
>> Caused confusion on USB receiver - and missing callback.
>
> What's wrong with a simple 'p++' instead?
>
> (Please remember that pointer arithmetic is done
> in units of the pointer's target type size).
Probably the same that is wrong with letting the hardware
care about the framing: too simple.
>
-
Re: USB: how transmit more than wMaxPacketSize of bulk data in one submission ?
Sorry, I'm in delay ... but I'll respond just to point a few issues out.
Rainer Weikusat wrote:
> Tauno Voipio writes:
>> Bernhard Holzmayer wrote:
>>> Bernhard Holzmayer wrote:
>>>
>>>>I'm confused about the different size aspects...
I told you that I've been confused.
Confusion means that there is a piece of truth in what I can see, but
there's a fog or cloud which hides it so much that I'm not sure if I'm on
the right track. This is why I asked for some orientation...
>>> Thank you, fellows, for your response.
>>> Gave me some additional insight, but could not really help me,
>>> because my problem was not that of fragmentation etc.
>>> Instead, I had a silly pointer issue
If I had known this before, I wouldn't have asked different questions.
>>> : positioning to the end with ptr=ptr+sizeof(*ptr) failed,
>>> since ptr was of a struct type,
>>> and I just forgot to cast it like in
>>> ptr=(type) ((void*)ptr+sizeof(*ptr))
It was not so obvious, because
a) the pointers deal with opaque types in reality (container lists etc.) and
the offset has to be calculated at runtime.
b) the existing code had been successfully tested under different
circumstances. I didn't expect the adaptation to cause trouble here.
c) the strange thing was that the device on the other end didn't respond
properly, so at a certain point the transfer broke. This caused me to look
into the wrong direction...
>>> Caused confusion on USB receiver - and missing callback.
>>
>> What's wrong with a simple 'p++' instead?
Nothing. Indeed I'd prefer that, but it may fail or at least become
unreadable if you have to deal with
>>
>> (Please remember that pointer arithmetic is done
>> in units of the pointer's target type size).
>
>
> Probably the same that is wrong with letting the hardware
> care about the framing: too simple.
> >
You may be right. If not the example code had contained a buffer length
equal to the endpoint's packet size, I'd not have thought about it.
If not my pointer arithmetic algorithm had been too complex, I'd have seen
the obvious '+1' issue,
and so on...
It has been my experience, that other people tend to see such mistakes
easier than the developer. That's why I posted here.
I was quite sure that other USB programmer's would not think so awkward as I
did.
Your hints gave me enough reason to trust that piece of URB-procession so
much, that I started to investigate further around until I found the
pointer bug. That's what I love about these newsgroups.
Bernhard