eclipse-threadx / usbx

Eclipse ThreadX - USBX is a high-performance USB host, device, and on-the-go (OTG) embedded stack, that is fully integrated with Eclipse ThreadX RTOS
https://github.com/eclipse-threadx/rtos-docs/blob/main/rtos-docs/usbx/index.md
MIT License
148 stars 88 forks source link

Composite device with two HID interfaces #85

Closed sw2mrc closed 1 year ago

sw2mrc commented 1 year ago

Greetings!

MCU is STM32F746, and USBX library version is 6.1.10.

I have two separate programs with MCU working as USB device, functioning either as a HID keyboard or as a HID mouse and they work fine; however the requirement is to support both functions simultaneously in one device. Each function is modeled as an interface -- for keyboard, interface class/subclass/proto is 3/1/1 (hid/boot/kbd), and for mouse it is 3/1/2 (hid/boot/mouse). Each interface has its own function specific HID Report Descriptor.

The composite device does not fully function - only the interface that was supplied to ux_device_stack_class_register works and the other one enumerates but unable send its HID Report descriptor or its HID Report. I have tried many options:

  1. Changing UX_MAX_SLAVE_CLASS_DRIVER does not work
  2. ux_device_stack_class_register was called twice with cfg and interface params (1,0), and (1,1), the call fails with error 18 (thread creation error)

Is there a way to register interfaces as HID, each supporting different subclass/protocol and having their own HID Report descriptors?

After looking at the signature of ux_device_stack_class_register, it seems like more than one interface supporting CDC-ACM would be an issue as well.

Best Regards..

xiaocq2001 commented 1 year ago

It's right that you increase UX_MAX_SLAVE_CLASS_DRIVER and call _register twice with cfg and interface 1, 0 and 1, 1.

Also you should check UX_MAX_SLAVE_INTERFACES to see if it is larger than the max interface number.

But it's strange that the second registration fails, can you check why it fails? Note _txe_thread_create actually do the checks to report thread creation errors.

sw2mrc commented 1 year ago

Yes, i will follow your advice and report back. Meanwhile I have two questions, and your clarifications would be appreciated.

  1. I found 3 definitions in ux_user.h file: UX_MAX_CLASS_DRIVER, UX_MAX_SLAVE_CLASS_DRIVER, UX_MAX_SLAVE_INTERFACES, and the distinction between the first two are not clear to me. Suppose the USB device supports 1 mass-storage function, 2 HID functions (one keyboard, one mouse) and 4 CDC-ACM functions, then UX_MAX_SLAVE_INTERFACES needs to be at least equal to bNumInterfaces field of the configuration descriptor right? how about the other two?
  2. Is there a callback or other mechanism to know if the host retrieved HID Report Descriptor (not HID Report)? this will alert device to send in boot protocol format or report format.

Best Regards..

xiaocq2001 commented 1 year ago

1. UX_MAX_CLASS_DRIVER is for host but not device, so for your case only UX_MAX_SLAVE_CLASS_DRIVER, UX_MAX_SLAVE_INTERFACES are considered.

For the composite device you described, number of interfaces is 1 + 2 1 + 4 2 = 11, assume interface number is 0 to 10, UX_MAX_SLAVE_INTERFACES is 11. Number of class driver to register is 1 + 21 + 41 = 7.

2. Current working protocol can be accessed through ux_device_class_hid_protocol_get, protocol is changed when host send SET_PROTOCOL request.

xiaocq2001 commented 1 year ago

1. UX_MAX_CLASS_DRIVER is for host. Your case is device so only UX_MAX_SLAVE_CLASS_DRIVER, UX_MAX_SLAVE_INTERFACES are considered. In your supposed example the number of interfaces is 1 + 2 + 4 * 2 = 11, assuming the interfaces numbers are in sequence, from 0 to 10, the UX_MAX_SLAVE_INTERFACES is 11. In this case UX_MAX_SLAVE_CLASS_DRIVER should be large enough for all function registration, that is, 1 + 2 + 4 = 7.

2. Current running protocol is accessed from ux_device_class_hid_protocol_get, the value is actually changed when host sending SET_PROTOCOL request.

sw2mrc commented 1 year ago

due to a CubeMX issue, the value defined for UX_MAX_SLAVE_INTERFACES was getting commented out in header file, and once that was taken care of, the issue went away and registration of second HID goes thru.

Thanks again for your clarifications and help. Have a good weekend!