Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 4 of 4

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

  1. #1
    Junior Member
    Join Date
    Sep 2021
    Posts
    2

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

    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:

    Click image for larger version. 

Name:	teensyduino_sc1_mini.png 
Views:	5 
Size:	27.4 KB 
ID:	25846

    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.

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    24,787
    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.

  3. #3
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    24,787
    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.

  4. #4
    Junior Member
    Join Date
    Sep 2021
    Posts
    2

    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

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •