Is two-way raw HID + Joystick + Serial possible?

Status
Not open for further replies.

codegoose

New member
Hello there,

I am having trouble finding concrete information on this subject.

I have a project in which I need to support a 3rd party software that communicates with my device over the serial port. The trouble is that I also need to communicate with my device at the same time. I thought that using raw HID would be the best solution so I am thinking of this:

  • Two-way raw HID for some data exchange from our software.
  • Serial port to receive input from the 3rd party software.
  • HID Joystick device for the OS to interpret.

The device is to act as a joystick while receiving data over serial and performing other data exchange through what I imagine to be Raw HID.

I've been trying to get this working on an Arduino Leonardo but I'm having a very hard time understanding the structure of the HID report descriptors and how to add Raw HID support on top of the joystick functionality.

When I try to add this functionality I either cause the input from the HID joystick to stop being registered in Windows or I break the ability of hidapi (https://github.com/signal11/hidapi) to send data to the device. It either returns "there is a device connected to this system that is not functioning" or "incorrect function". This leads me to believe that having Raw HID, Serial and a Joystick at the same time is simply not supported at the OS level but I'm not sure if that's case or if I'm messing something up. I can't find any code samples that do that. I'm assuming because it's so specific.

I wanted to buy a Teensy because of the availability of Teensyduino. Primarily, I saw that it supports several configurations:

teensyduino_sc1_mini.png

Essentially what I would need is Raw HID + Serial + Joystick.

[1]Is that something that is even possible?

That's my primary question, but for further elaboration:

I have considered that alternatively I could just use the Dual Serial option and in that case I guess my question would be "[2]Is Dual Serial + Joystick possible?" but opening the USB through the VID/PID/SERIAL# and talking that way seems like a much cleaner solution to me than opening every serial port on the system and trying to do a handshake with each one.

I haven't been able to get Raw HID working on the Leonardo because I can't find any info on how to use USB_Send/Recv and NicoHood's HID-Project appears to have a broken RawHID implementation in which sending data back the PC doesn't work for some reason I can't get it to work or find much info on why it could possibly not work.
 
Yes, these are possible on 32 bit Teensy, but you will need to edit usb_desc.h to create the combination of interfaces you want.

See the extensive comments in that file for instructions.

For old 8 bit Teensy, the hardware is limited to a small number of endpoints which can only work in 1 direction. Most of these probably won't fit. The old code also lacks a nice way to reconfigure like usb_desc.h, so making a different combination of interfaces is a lot more work.
 
Ok, just looked at the old AVR datasheet. Haven't done much with Teensy 2.0 lately... kind of a trip down memory lane.

Raw HID + Serial + Joystick definitely can not work on Teensy 2.0. Unlike the newer Teensy models where non-control USB endpoints can work in both directions, on Teensy 2.0 you get only 5 unidirectional non-control endpoints. Serial needs 3, RawHID needs 2, and Joystick needs 1. The hardware simply does not have enough endpoints.

Teensy 4.0 gives 6 endpoints for general use, and because they're bidirectional, Serial needs only 2, RawHID needs only 1, and Joystick needs 1. The USB also runs at 480 Mbit/sec rather than only 12, and Cortex-M7 processor is about 300 times faster than AVR, and you have 400X larger RAM... which makes programming more complex projects much easier.
 
My Teensy 4.1 got here this morning and with your help I've been able to get it working, so thank you for that.

For future reference, I made these changes:

I added these lines in boards.txt:

Code:
teensy41.menu.usb.superdevice1=XXX
teensy41.menu.usb.superdevice1.build.usbtype=USB_SUPER_DEVICE_1
teensy41.menu.usb.superdevice1.fake_serial=superdevice1

I added another entry in usb_desc.h:

Code:
#elif defined(USB_SUPER_DEVICE_1)

  #define VENDOR_ID		0x16C0
  #define PRODUCT_ID		0x0476
  #define RAWHID_USAGE_PAGE	0xFFAB  // recommended: 0xFF00 to 0xFFFF
  #define RAWHID_USAGE		0x0200  // recommended: 0x0100 to 0xFFFF
  #define DEVICE_CLASS		0xEF
  #define DEVICE_SUBCLASS	0x02
  #define DEVICE_PROTOCOL	0x01
  #define MANUFACTURER_NAME	XXX
  #define MANUFACTURER_NAME_LEN	11
  #define PRODUCT_NAME		XXX
  #define PRODUCT_NAME_LEN	13
  #define EP0_SIZE		64
  #define NUM_ENDPOINTS         5
  #define NUM_INTERFACE		4
  #define CDC_IAD_DESCRIPTOR	1
  #define CDC_STATUS_INTERFACE	0
  #define CDC_DATA_INTERFACE	1	// Serial
  #define CDC_ACM_ENDPOINT	1
  #define CDC_RX_ENDPOINT       2
  #define CDC_TX_ENDPOINT       2
  #define CDC_ACM_SIZE          16
  #define CDC_RX_SIZE_480       512
  #define CDC_TX_SIZE_480       512
  #define CDC_RX_SIZE_12        64
  #define CDC_TX_SIZE_12        64
  #define RAWHID_INTERFACE      2	// RawHID
  #define RAWHID_TX_ENDPOINT    3
  #define RAWHID_TX_SIZE        64
  #define RAWHID_TX_INTERVAL    1
  #define RAWHID_RX_ENDPOINT    4
  #define RAWHID_RX_SIZE        64
  #define RAWHID_RX_INTERVAL    1
  #define JOYSTICK_INTERFACE    3	// Joystick
  #define JOYSTICK_ENDPOINT     5
  #define JOYSTICK_SIZE         12	//  12 = normal, 64 = extreme joystick
  #define JOYSTICK_INTERVAL     1
  #define ENDPOINT1_CONFIG	ENDPOINT_RECEIVE_UNUSED + ENDPOINT_TRANSMIT_INTERRUPT
  #define ENDPOINT2_CONFIG	ENDPOINT_RECEIVE_BULK + ENDPOINT_TRANSMIT_BULK
  #define ENDPOINT3_CONFIG	ENDPOINT_RECEIVE_UNUSED + ENDPOINT_TRANSMIT_INTERRUPT
  #define ENDPOINT4_CONFIG	ENDPOINT_RECEIVE_INTERRUPT + ENDPOINT_TRANSMIT_UNUSED
  #define ENDPOINT5_CONFIG	ENDPOINT_RECEIVE_UNUSED + ENDPOINT_TRANSMIT_INTERRUPT

#endif

I wasn't really entirely sure what I was doing but all features appear to be functioning nominally, lol
 
Status
Not open for further replies.
Back
Top