USB ConfigFS + FunctionFS: read() of endpoint bundles packets

I want to use the iMX7-SOM as a vendor specific device (gadget) on a Windows10-PC with WINUSB driver.

I configured the gadget with libusbgx, mounted the functionfs at /ffs and wrote the descriptors to /ffs/ep0. The device is enumerated as expected and I get the commands on endpoint 0 (like “BIND”, “ENABLE”, “DISABLE” etc.).

So far so good…

My problem is the reading from endpoint 1.

I open it with

int ep_fd = open("/ffs/ep1", O_RDONLY);

and read from it with

unsigned char buffer[65535];

int ret = read(ep_fd, buffer, sizeof(buffer));

The read() returns only every 4 received USB-packets. It doesn’t matter wether I send 4 data packet or 1 data and 3 zero-packets. The size of the packets is also irrelevant.

At least none of the data is lost :wink:

Does anybody know how I can/must configure the endpoint that the read() returns after every single received packet?

Best regards,
Mowlwurf

hi @Mowlwurf

Could you provide the software version of your module? Which carrier board are you using?

The read() returns only every 4 received USB-packets. It doesn’t matter wether I send 4 data packet or 1 data and 3 zero-packets. The size of the packets is also irrelevant.

I don’t get you. So you are always getting the fourth USB packets or you are getting always four packets?

Does anybody know how I can/must configure the endpoint that the read() returns after every single received packet?

How are you sending the packets?

Best regards,
Jaski

Could you provide the software version of your module? Which carrier board are you using?

I’m using BSP v2.8 and a Colibri evaluation board V3.2B

I don’t get you. So you are always getting the fourth USB packets or you are getting always four packets?

How are you sending the packets?

I’m sending single packets (bulk) with a software tool from Thesycon (link). The packet has eg. 12 Bytes and I have to send it 4 times that the read() function returns. When this happens the return value of read() is 48 - so I’m receiving all 4 sent packets but only bundled.

Best regards,
Mowlwurf

hi @Mowlwurf

Thanks for the Information. We are working on this issue and will come tomorrow back to you.

Best regards,
Jaski

Hi @Mowlwurf

I was not able to create and configure the gadget with functionfs. Could you tell me, how you did you create and bind the gadget? Could you also share your .schema file?
Thanks.

Here are a minimal project and my .schema file: files

hi @Mowlwurf

Thanks for the files. We will come back to you within this week.

Best regards,
Jaski

I was out of office in the last two weeks.
Is there anything new on this?

Best regards,
Mowlwurf

Hi,
I was also out of office for two weeks. I will come back to you once I have more Information.

Dear @Mowlwurf,

Thank you for your patience.

I am working on this issue, probably I will get back to you next week.

Did you use https://www.thesycon.de/eng/usbio.shtml tool on Windows 10. However, I am trying to test with Linux Host machine.

Hi raja.tx,

good to hear that you are working on it.

Yes, I am using the Thesycon tool you mentioned.

Dear @Mowlwurf,

Still, we are working on this. we got “USBIO Development Kit Demo Request” from Thesycon, Could you share which application you used on the Windows 10 side, Did you do any modification there?

Also, share the imx7 device-side test application with source code with us. It will help us to reproduce the issue quickly.

Here is a test application for the Colibri iMX7D 1GB V1.1A as a Eclipse project: link. Start the app on the SOM and connect it to the Windows 10-PC with a USB cable.

The device will be enumerated as a “CANFDbase” in the Device Manager with the WinUsb driver. Right-click on it and replace this driver with the Thesycon USBIO driver: link

The device should now be listed as “USBIO Device: VID=0D1D PID=0020” in the Device Manager

The USBIO-Tool of Thesycon I’m using ist the “USBIOAPP_x64.exe” with the following workflow:

  1. Tab “Device” → “Scan for USBIO devices”
  2. Click on “Device0” and “Open”
  3. Tab “Descriptors” → “Get Device Descriptor”
  4. Tab “Configuration” → “Set Configuration 0”
  5. Tab “Pipes” → Choose “0x01 Bulk OUT” and “Read from File and Write to Pipe”
  6. In the new Window: Tab “Write from File to Pipe” → “Browse” and choose this file (12 Bytes Command)

You have to click at least 4 times on “Start Writing” until the read() of Endpoint 1 returns and prints out “48 Bytes read”.

In the meantime I discovered the following thing: The size of my receive buffer is 64 kB aligned to 4 bytes.

When I reduce this size to 20 kB then the read() returns after every sent packet as it should be.

When I change the buffer size to 21 kB then the read () returns after every second sent packet.

Is there a limitation in the linux usb driver stack I have to consider?

Hi @Mowlwurf

Thanks very much for your Input.
@raja.tx is on vacation today. He will answer you next week.

Best regards,
Jaski

Dear @Mowlwurf,

Thank you for the detailed information, we are able to reproduce the issue as described. Also, we are able to see issue on iMX6. We are debugging with kernel and Could you wait for a few more days, we will get back you as soon as we have something to share with you.

It’s great that you can reproduce the error.
Of course I can wait a few more days. I’m looking forward to something good from you.

Dear @Mowlwurf,

Thank you for your patience. Sorry, I don’t have concrete information why it behaves like this, still, I am searching and debugging into Linux source to find that.

Meanwhile, I found in a few class driver code, 8K buffer is used in the read thread.

Search USB_BUFSIZE in the following links

Could you set your read buffer to 8K size and do the test.

If you need larger memory read buffer on your userspace application then you can create a separate thread for keep reading USB data and put it into the pool of buffers or larger size FIFO and that you would process in other threads of your application.

Let you know as soon as we find concrete information. Let us know if you have any questions on this.

As I wrote in the comment of Aug 28: as long as the receive buffer is not bigger than 20 kB the read() returns every sent packet as it should be.

Dear @Mowlwurf,

Thank you for your reply and patience.

Still, we are not able to find the root cause of the problem, it is nowhere documented and going through USB stack source code is hectic.

Is that 8KB buffer size fixing the issue?

Do you any specific requirement to use a bigger buffer size(> 20KB).

There is a workaround to create bigger buffer and put data into that on userspace application thread. Is this workaround not suitable for you?