1

I'm trying to create a Gadget using FunctionFS and the FS driver. My gadget is composed of two functions with the following configurations:

Function 1:
Interface 0:
     Endpoint BULK OUT 0x01
     Endpoint BULK IN 0x81

Function 2:
Interface 0 Alternate setting 0:
     No Endpoint
Interface 0 Alternate setting 1:
     Endpoint BULK OUT 0x02
     Endpoint BULK IN 0x82

The gadget runs on an IMX8 board. The OS is a Debian with a kernel 4.14.98.

Everything works fine until I activate the alternate setting 1 in Function 2 using libusb's libusb_set_interface_alt_setting from another computer. libusb shows no error but the exchanged USB packets show that a STALL has been returned from the board. There is also no debug information in the kernel logs concerning the STALL. This problem is not due to libusb as I have the same issue (and STALL) if I connect the gadget to another board not relying on libusb to communicate.

I tried changing the USB descriptors (endpoint addresses, alternate setting in function 1) and the code (when I open the endpoints, using one function instead of two) but nothing changes the outcome. I also looked in the kernel source code to figure where the error is but have found no obvious places that could create a STALL.

Anybody else having faced a similar issue or having any idea on how I could figure out what's happening? I really would appreciate the help.

Julien
  • 21
  • 3

1 Answers1

1

I figured it out, so I'll put the answer here in case somebody else faces this problem.

FunctionFS (f_fs.c) does not completely support alternate settings. The implementation has the code to change to another alternate setting (ffs_func_set_alt(...)) but it requires another function used by composite (composite.c) to identify which alternate setting is currently in use (ffs_func_get_alt(...)). When a SET_INTERFACE is received by the device, the function composite_setup(...) in composite.c checks if the get_alt function is implemented. If it is not and the alternate setting to activate is not zero, it returns an error.

If you want to use FunctionFS with alternate settings, the only way is to create your own gadget function by using FunctionFS as a base and write the missing ffs_func_get_alt. For inspiration on how to write it, take a look at the f_uvc function. Once that is done, copy the new module to the kernel and modify the Makefiles, Kconfig and modules.order to add the module in the compilation process. That should give you a module you can select in the kernel .config file.

I tested this solution and it works fine. It's also not too hard to modify the kernel to add a function. There are plenty of guides on internet for that.

Good luck :)

Julien
  • 21
  • 3