How to use Bulk Out endpoint

General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
Post Reply
Posts: 6
Joined: Thu Apr 21, 2016 1:25 pm

How to use Bulk Out endpoint

Post by fcapozzi » Thu May 05, 2016 5:29 pm

Hi, i am working on a device that has two bulk endpoint in and out other than control 0 endpoint.
This is the configuration descriptor taken from (Device Monitoring Studio)

Configuration Descriptor
Number of interfaces: 1
Configuration value: 0x1
Attributes: Bus powered
Max power: 50 mA

Interface Descriptor: 0, Alternate setting: 0
Number of endpoints: 2
Interface class: 0xfe - Application Specific Interface
Interface subclass: 0x3 - Test and Measurement
Interface protocol: 0x0 - Unknown
Endpoint address 0x1, Input, Bulk, max packet size: 64 bytes
Endpoint address 0x2, Output, Bulk, max packet size: 64 bytes

I enabled the usb usbFunctionWriteOut in the usbconfig

/* Define this to 1 if you want to use interrupt-out (or bulk out) endpoints.
* You must implement the function usbFunctionWriteOut() which receives all
* interrupt/bulk data sent to any endpoint other than 0. The endpoint number
* can be found in 'usbRxToken'.

but when i send bulk data using usbtool
this function is never called.

in the usbdrv.c seems that usbRxToken is never <0x10

if(usbRxToken < 0x10){ /* OUT to endpoint != 0: endpoint number in usbRxToken */
usbFunctionWriteOut(data, len);

Anyone can explain how to use bulk out transfer ?
Tnx, Fabio.

Posts: 6
Joined: Thu Apr 21, 2016 1:25 pm

Re: How to use Bulk Out endpoint

Post by fcapozzi » Fri May 20, 2016 8:24 pm

Hi All, few days are elapsed without answer .. btw i've done other experiments and this is what i found :

Basically the mechanism for receiving OUT data on endpoint different than 0 is based on function usbFunctionWriteOut()
This function works perfectly when the endpoint is having the type declared to be 0x03 (interrupt) but is never called when the type is 0x02 (bulk).

For answer on endpoint different than 0 it is necessary to define USB_CFG_HAVE_INTRIN_ENDPOINT then check if the interrupt is available with the function usbInterruptIsready() and then use the usbSetInterrupt() passing two arguments, a pointer to the data buffer and the lenght of the message to send that has to be max 8 Byte. As before this works when the enpoint is type 0x03 interrupt and does not work if the endpoint is declared of type 0x02.

I found many examples on the net that use endpoints declared bulk (0x02) which are supposed to work, but actually does not ... or ... under certain condition they sometimes work. This depend on the operating system. Sometimes when the operating system see a bulk endpoint declared in a descriptor of a low speed device it transforms the enpoint in interrupt. So usb call from the host are directed to interrupt enpoints and so they are correctly handled by vUSB. It seems that is the bulk endpoint that is working but is not actually the case.

A big problem is when using a VirtualBox virtual machine. I describe you my setup.

I have a Apple iMac El Capitan that has under VirtualBox 5.0.20 a Windows 7 virtual machine running. In this case the Imac see the attached device as Low Speed but Windows 7 believe that the attached device is full speed because it does not talk directly with the hardware but it talks with an abstraction Layer provided by VirtualBox that does not pass correctly the speed information. In this case the bulk endpoints are never transformed in interrupt endpoint by Windows 7 so the system call to libusb to exchange messages IN and OUT fails with this messages

C:\vusb-20121206\examples\usbtool>usbtool -e 0x81 bulk in
USB error: libusb0-dll:err [_usb_reap_async] reaping request failed, win error: Un dispositivo collegato al sistema non è in funzione.

Same story is on Linux since VirtualBox presents the device as full speed and this prevents automatic conversion from bulk to interrupt endpoint.

If in the same program i simply change the enpoint type from 0x02 to 0x03 the same command complete correctly

C:\Users\Fabio\Desktop\vusb-20121206\examples\usbtool>usbtool -e 0x81 bulk in
0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e 0x3f

So it seems that in a native system without any virtualization bulk and interrupt enpoint are the same .. Actually in many part of vUSB firmware documentation is referred the "Bulk/interrupt enpoints" as a unique entity as if it does not care to much. Unfortunately this is not the case if the specific class host software check specifically for enpoint type. Let me do an example.

I was testing the vUSB firmware for implementing a USBTMC compliant device (USB Time and Measurement Class) that is commonly used by many commercial instruments as Oscilloscope, Waveform Generator and so on. The class specification says that is necessary to have a bulk in and a bulk out endpoint so i implemented a device that use bulk endpoints. On a Linux virtual machine it does not work because the system does not transform the endpoint in interrupt and so libusb0 fail sending bulk data.
On a native system the endpoint are changed in interrupts but the kernel usbtmc module simply does not send any data to the endpoints since the os has attached them as interrupt.

So to make a long story short ... bulk interrupts should not be used in a low speed device since this cause trouble.
This is what i found so far .. but .. if someone have different finding i will be happy to know and share knowledge.

Enjoy, Fabio,


Re: How to use Bulk Out endpoint

Post by Guest » Thu Nov 24, 2016 7:19 pm

Fabio, any ideas regarding my issue? Or it's the same one?

Post Reply