Configuring a Composite HID Device

Discussion of keyboards, gamepads, joysticks and other input related peripherals.
dstevens
Posts: 11
Joined: Wed Jul 08, 2020 12:29 am
Been thanked: 1 time

Configuring a Composite HID Device

Unread post by dstevens »

I'm working on a custom USB adapter for an arcade fight stick based on a STM32F411.

The fight stick has 2 joysticks, 14 buttons, 2 spinners, and a trackball.

I've split the controls into three composite HID devices. 2 joysticks (with 7 buttons and 1 spinner each) and one mouse device for the trackball.

On Windows everything works great, but I can't get it working fully in MiSTer.

When I attempt to define the second joystick (using the system settings menu) the only buttons I can define are from the first joystick. It doesn't appear MiSTer is treating each composite device as a separate device.

I'm new to this so I hope I'm using the proper terminology. Any ideas what I should try next?

Thanks

EDIT: Here is the HID descriptor I'm using...

Code: Select all

0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
0x09, 0x04,        // Usage (Joystick)
0xA1, 0x01,        // Collection (Application)
0xA1, 0x00,        //   Collection (Physical)
0x85, 0x01,        //     Report ID (1)
0x05, 0x09,        //     Usage Page (Button)
0x19, 0x01,        //     Usage Minimum (0x01)
0x29, 0x08,        //     Usage Maximum (0x08)
0x15, 0x00,        //     Logical Minimum (0)
0x25, 0x01,        //     Logical Maximum (1)
0x95, 0x10,        //     Report Count (16)
0x75, 0x01,        //     Report Size (1)
0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x01,        //     Usage Page (Generic Desktop Ctrls)
0x09, 0x37,        //     Usage (Dial)
0x15, 0x80,        //     Logical Minimum (-128)
0x25, 0x7F,        //     Logical Maximum (127)
0x95, 0x01,        //     Report Count (1)
0x75, 0x08,        //     Report Size (8)
0x81, 0x06,        //     Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x38,        //     Usage (Wheel)
0x15, 0x00,        //     Logical Minimum (0)
0x26, 0xFF, 0x00,  //     Logical Maximum (255)
0x95, 0x01,        //     Report Count (1)
0x75, 0x08,        //     Report Size (8)
0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x01,        //     Usage Page (Generic Desktop Ctrls)
0x09, 0x01,        //     Usage (Pointer)
0xA1, 0x00,        //     Collection (Physical)
0x09, 0x30,        //       Usage (X)
0x09, 0x31,        //       Usage (Y)
0x15, 0xFF,        //       Logical Minimum (-1)
0x25, 0x01,        //       Logical Maximum (1)
0x95, 0x02,        //       Report Count (2)
0x75, 0x08,        //       Report Size (8)
0x81, 0x02,        //       Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0,              //     End Collection
0xC0,              //   End Collection
0xC0,              // End Collection

0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
0x09, 0x04,        // Usage (Joystick)
0xA1, 0x01,        // Collection (Application)
0xA1, 0x00,        //   Collection (Physical)
0x85, 0x02,        //     Report ID (2)
0x05, 0x09,        //     Usage Page (Button)
0x19, 0x01,        //     Usage Minimum (0x01)
0x29, 0x08,        //     Usage Maximum (0x08)
0x15, 0x00,        //     Logical Minimum (0)
0x25, 0x01,        //     Logical Maximum (1)
0x95, 0x10,        //     Report Count (16)
0x75, 0x01,        //     Report Size (1)
0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x01,        //     Usage Page (Generic Desktop Ctrls)
0x09, 0x37,        //     Usage (Dial)
0x15, 0x80,        //     Logical Minimum (-128)
0x25, 0x7F,        //     Logical Maximum (127)
0x95, 0x01,        //     Report Count (1)
0x75, 0x08,        //     Report Size (8)
0x81, 0x06,        //     Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x38,        //     Usage (Wheel)
0x15, 0x00,        //     Logical Minimum (0)
0x26, 0xFF, 0x00,  //     Logical Maximum (255)
0x95, 0x01,        //     Report Count (1)
0x75, 0x08,        //     Report Size (8)
0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x01,        //     Usage Page (Generic Desktop Ctrls)
0x09, 0x01,        //     Usage (Pointer)
0xA1, 0x00,        //     Collection (Physical)
0x09, 0x30,        //       Usage (X)
0x09, 0x31,        //       Usage (Y)
0x15, 0xFF,        //       Logical Minimum (-1)
0x25, 0x01,        //       Logical Maximum (1)
0x95, 0x02,        //       Report Count (2)
0x75, 0x08,        //       Report Size (8)
0x81, 0x02,        //       Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0,              //     End Collection
0xC0,              //   End Collection
0xC0,              // End Collection

0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
0x09, 0x02,        // Usage (Mouse)
0xA1, 0x01,        // Collection (Application)
0x09, 0x01,        //   Usage (Pointer)
0xA1, 0x00,        //   Collection (Physical)
0x85, 0x03,        //     Report ID (3)
0x05, 0x01,        //     Usage Page (Generic Desktop Ctrls)
0x09, 0x30,        //     Usage (X)
0x09, 0x31,        //     Usage (Y)
0x15, 0x81,        //     Logical Minimum (-127)
0x25, 0x7F,        //     Logical Maximum (127)
0x75, 0x08,        //     Report Size (8)
0x95, 0x02,        //     Report Count (2)
0x81, 0x06,        //     Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
0xC0,              //   End Collection
0xC0,              // End Collection
User avatar
amstan
Posts: 56
Joined: Sat Feb 12, 2022 8:08 am
Location: Mountain View, California
Has thanked: 5 times
Been thanked: 26 times
Contact:

Re: Configuring a Composite HID Device

Unread post by amstan »

I would do `evtest` over ssh and debug in there if you see each of the 3 devices.
dstevens
Posts: 11
Joined: Wed Jul 08, 2020 12:29 am
Been thanked: 1 time

Re: Configuring a Composite HID Device

Unread post by dstevens »

I made some progress. The joysticks / buttons / spinners all work. Mouse still doesn't work.

Apparently in Linux composite HID devices need the HID_QUIRK_MULTI_INPUT attribute set in drivers/hid/usbhid/hid-quirks.c to show up as multiple devices. I didn't want to recompile the kernel so for now I'm using the ID of a device already in the list.

EDIT: Scratch that. I get multiple devices now (using evtest on a raspberry pi) but in MiSTer joystick 1 and 2 seem to map to the same input. In other words pressing right with either joystick 1 or joystick 2 registers as a joystick 1 press.
User avatar
aberu
Core Developer
Posts: 1144
Joined: Tue Jun 09, 2020 8:34 pm
Location: Longmont, CO
Has thanked: 244 times
Been thanked: 388 times
Contact:

Re: Configuring a Composite HID Device

Unread post by aberu »

MiSTer support for dual joystick as "Player 1" and "Player 2" on one USB device is I think non-existent unless Sorg updated that the last time I looked into it. Pretty sure Player 1 gets bound to one ID and player 2 gets bound to another ID. The X-Arcade dual stick that people got working before worked because it showed up as two USB devices I think.
birdybro~
dstevens
Posts: 11
Joined: Wed Jul 08, 2020 12:29 am
Been thanked: 1 time

Re: Configuring a Composite HID Device

Unread post by dstevens »

Mentioning the X-Arcade dual stick was the hint needed. I was able to search how people got it working.

By setting no_merge_vid and no_merge_pid in MiSTer.ini to your composite device's vid/pid it will prevent the merging of input devices. So the joysticks are working now.

Now for the trackball...
bankshot
Posts: 66
Joined: Thu Dec 16, 2021 5:13 pm
Has thanked: 18 times
Been thanked: 29 times

Re: Configuring a Composite HID Device

Unread post by bankshot »

Hi dstevens,

Let me know if you have any luck with the trackball as a separate HID. My 2-player arcade stick w/ trackball unit has just the trackball as its own separate HID/USB device from the stick and all the buttons. Because of this, the trackball is useless because it has no buttons associated with it. MiSTer does not let you combine controls from multiple HIDs within the same core at the same time. Because of this, my only choice is to replace the brain of the entire arcade stick to one that I can somehow integrate with the rest of the controls on the same HID. The trackball will need to be hacked and I'm having trouble finding good info on how to do this.
dstevens
Posts: 11
Joined: Wed Jul 08, 2020 12:29 am
Been thanked: 1 time

Re: Configuring a Composite HID Device

Unread post by dstevens »

bankshot wrote: Sat Feb 19, 2022 12:50 am Let me know if you have any luck with the trackball as a separate HID. My 2-player arcade stick w/ trackball unit has just the trackball as its own separate HID/USB device from the stick and all the buttons. Because of this, the trackball is useless because it has no buttons associated with it. MiSTer does not let you combine controls from multiple HIDs within the same core at the same time. Because of this, my only choice is to replace the brain of the entire arcade stick to one that I can somehow integrate with the rest of the controls on the same HID. The trackball will need to be hacked and I'm having trouble finding good info on how to do this.
I had the same issue, and I wanted to add a couple of spinners for the Atari 7800/2600 core. I also like the idea of one controller for everything.

I'm using a Micro Center Atari Fight Stick. The included trackball had it's own embedded controller. I replaced the 2.5" trackball with a SuzoHapp 3" trackball (no embedded controller). It is almost a perfect fit. The bolt pattern is identical, but I had to widen the ball opening by maybe a millimeter.

I did get the mouse working. Under Linux (not Mac or Windows) the Mouse HID descriptor appears to require some buttons defined otherwise it doesn't work without a custom driver.

Unfortunately I'm not happy with the performance. I think I'm flooding the USB buffer with too much data. Before adding mouse and spinners the latency seemed great. With spinners and the trackball all moving at the same time I see slowdowns.

I'm likely doing some dumb things so there is still hope.

EDIT: Yeah dumb things confirmed. I had the pulses per revolution for the spinners set to 20 instead of 1200 so I was sending way more data than necessary.
bankshot
Posts: 66
Joined: Thu Dec 16, 2021 5:13 pm
Has thanked: 18 times
Been thanked: 29 times

Re: Configuring a Composite HID Device

Unread post by bankshot »

Ok now it makes sense, I have the same Micro Center arcade stick as you. I ended up purchasing a Teensy 3.5 board from Micro Center as well to replace the Xinmo board and was going to wire the trackball to that, if I could figure out how to remove the embedded controller from the stock trackball. Theoretically, I could get all needed controls on the same HID.

Where did you end up installing your spinners?
dstevens
Posts: 11
Joined: Wed Jul 08, 2020 12:29 am
Been thanked: 1 time

Re: Configuring a Composite HID Device

Unread post by dstevens »

I replaced one of the white buttons on each side of the trackball for the spinners. It's not ideal, but about the best I could do with the existing layout.
dstevens
Posts: 11
Joined: Wed Jul 08, 2020 12:29 am
Been thanked: 1 time

Re: Configuring a Composite HID Device

Unread post by dstevens »

bankshot wrote: Sun Feb 20, 2022 3:17 am I ended up purchasing a Teensy 3.5 board from Micro Center as well to replace the Xinmo board and was going to wire the trackball to that, if I could figure out how to remove the embedded controller from the stock trackball. Theoretically, I could get all needed controls on the same HID.
After more testing I'm not sure composite HID devices is they way to go. While I can get everything to play nicely with MiSTer by splitting the controls into three HID devices I noticed the mouse movement would slow down if the spinners were moving. Correcting the spinner's PPR helped, but didn't solve it completely.

The issue is you can't send multiple HID reports in a single USB update they must be sent serially. If there are changes for all three devices the best case latency goes from 1ms to 3ms.

Combining all the controls into a single HID device solves the latency issue, but I couldn't map the controls from a single device into both "Player 1" and "Player 2". The mouse was separated out though.

I think the only way to accomplish what I want is to combine everything into a single HID device and write a custom driver that splits everything into 2 gamepads and a mouse.
bankshot
Posts: 66
Joined: Thu Dec 16, 2021 5:13 pm
Has thanked: 18 times
Been thanked: 29 times

Re: Configuring a Composite HID Device

Unread post by bankshot »

Thanks a bunch for reporting your findings! Did you happen to try mapping all of the controls to the standard MAME keyboard input commands? Others have reported success in doing this on their custom controllers and I wonder if it would make an improvement to your situation. It's the route I was going to take when I get around to uploading the code on my Teensy 3.5.
thorr
Top Contributor
Posts: 1101
Joined: Mon Jul 06, 2020 9:37 pm
Has thanked: 537 times
Been thanked: 252 times

Re: Configuring a Composite HID Device

Unread post by thorr »

You guys are farther along than I am, so I appreciate the information above as I am sure I will refer to it. I have been busy with life, but need to get back to finishing my arcade cabinet.

Using the keyboard could/should work in at least some or many situations with arcade cores as long as they support the Mame keyboard layout. You can test this by using a keyboard and see if you can get it to move both the players around. I know it works with Mario Bros. so start there and then try other things. Then once tested, you can program the Teensy/Arduino to send keyboard keys instead of being a joystick. The limitation is this is only for arcade games. If you want to use two players with a console, I don't think the keyboard trick works.

I want ultimate flexibility so I have been thinking of ways to work around the MiSTer's input limitations. One of my goals is to be able to use both joysticks as one controller so I can play SNES Super Smash TV with two joysticks (acting as direction pad and ABXY buttons). I am thinking about different scenarios for how I will hook things up, but I have come to this plan so far:
- Have different Arduinos / USB connections for each control (each joystick, spinner, etc.). This is what the MiSTer wants, so it should make it happy most of the time. I will have to plug in multiple USB cables, but oh well.
- I may use a switch or a button combination to change the behavior of a single arduino for each joystick so it would either send keyboard strokes or joystick directions. If both act as a keyboard, that is ok coming from different devices. With both joysticks acting as a keyboard, that will solve my Super Smash TV problem by mapping the controls to the keyboard inputs before playing the game.
- I am building multiple control panels for the various games, so I probably will not need all this flexibility in most cases.

I am curious what games use two spinners. I had no plans for this. Atari paddle games makes sense though if that is the reason.

I wish the MiSTer's input system could care less about devices, and each control (Player 1 - Up, Player 2 - Up, etc.) could be mapped from anything, anywhere. Like how Mame does it. It would solve so many problems for people trying to build custom controllers for all these systems/cores.
dstevens
Posts: 11
Joined: Wed Jul 08, 2020 12:29 am
Been thanked: 1 time

Re: Configuring a Composite HID Device

Unread post by dstevens »

The spinners and trackball are definitely the complicating factors. If those aren't a concern mapping to a keyboard seems like a great approach.

I'm probably trying to talk myself in doing it, but I think using a custom driver gives you the greatest flexibility.

You get the latency benefits of a single HID update then you can split it to any control combination that makes sense on the linux side. You could even write it so you could change devices schemes on the fly. I'm getting ahead of myself. Let's see if I can write a simple device driver first.
thorr
Top Contributor
Posts: 1101
Joined: Mon Jul 06, 2020 9:37 pm
Has thanked: 537 times
Been thanked: 252 times

Re: Configuring a Composite HID Device

Unread post by thorr »

If you can somehow make all this work well with one USB connection, that would be amazing and greatly appreciated by many. Good luck!
bankshot
Posts: 66
Joined: Thu Dec 16, 2021 5:13 pm
Has thanked: 18 times
Been thanked: 29 times

Re: Configuring a Composite HID Device

Unread post by bankshot »

Well thorr I can tell you that Super Smash TV is my wife's favorite SNES game and we play it almost daily. She's happy playing it with the default SNES layout on a PS4 controller, but I cannot stand it. So right now I am using the PS4 analog sticks for movement and firing when we play. I'll let you know what I come up with on the arcade stick front.
thorr
Top Contributor
Posts: 1101
Joined: Mon Jul 06, 2020 9:37 pm
Has thanked: 537 times
Been thanked: 252 times

Re: Configuring a Composite HID Device

Unread post by thorr »

I had it working at one point on my custom arcade control panel and it was amazing. It is worth the effort just for this one game!
User avatar
sonik
Posts: 91
Joined: Sun May 09, 2021 3:31 pm
Location: Brazil
Has thanked: 15 times
Been thanked: 17 times

Re: Configuring a Composite HID Device

Unread post by sonik »

dstevens wrote: Tue Feb 15, 2022 9:23 pm I'm working on a custom USB adapter for an arcade fight stick based on a STM32F411.

The fight stick has 2 joysticks, 14 buttons, 2 spinners, and a trackball.

I've split the controls into three composite HID devices. 2 joysticks (with 7 buttons and 1 spinner each) and one mouse device for the trackball.

On Windows everything works great, but I can't get it working fully in MiSTer.

Hi!

Did you found a fix for it?
Mister stopped working with my "single interface with composite HID" adapter too.
It works with mister and kernel up to 20210711. Later versions have this problem of only supporting the first device.
dstevens
Posts: 11
Joined: Wed Jul 08, 2020 12:29 am
Been thanked: 1 time

Re: Configuring a Composite HID Device

Unread post by dstevens »

sonik wrote: Mon Mar 07, 2022 2:48 pm Did you found a fix for it?
Mister stopped working with my "single interface with composite HID" adapter too.
It works with mister and kernel up to 20210711. Later versions have this problem of only supporting the first device.
Check to see if no_merge_vid and no_merge_pid in MiSTer.ini is set to your composite device's vid/pid.

That is what fixed it for me.
User avatar
sonik
Posts: 91
Joined: Sun May 09, 2021 3:31 pm
Location: Brazil
Has thanked: 15 times
Been thanked: 17 times

Re: Configuring a Composite HID Device

Unread post by sonik »

Your adapter is still working on lates mister version?

the no_merge is when mister treats all devices as one. my problem is that currently it only detects the first device and ignore the rest.
dstevens
Posts: 11
Joined: Wed Jul 08, 2020 12:29 am
Been thanked: 1 time

Re: Configuring a Composite HID Device

Unread post by dstevens »

I changed my approach so I don't have an easy way to test. I'm no longer use a composite hid device, I'm sending all the data through a single raw hid device and splitting it into multiple devices in a linux driver.

That said it was working in mid February and my MiSTer was up to date so the kernel was likely newer than 20210711.
User avatar
sonik
Posts: 91
Joined: Sun May 09, 2021 3:31 pm
Location: Brazil
Has thanked: 15 times
Been thanked: 17 times

Re: Configuring a Composite HID Device

Unread post by sonik »

Nice.
BTW I've got my adapter working just now. Enabled a quirk on u-boot.txt
usbhid.quirks=0x0000:0x0000:0x040

Without it, mister only responds to the first device of the composite descriptor.
Kwoken
Posts: 1
Joined: Mon May 23, 2022 6:25 pm

Re: Configuring a Composite HID Device

Unread post by Kwoken »

Not having much luck here. I have a Chewlix, wired into a single USB adaptor (which works fine with Windows), but I'm unable to get my Mister to see any of the 2nd player's buttons (inc. 2p start), and it sees the 2p joystick as 1p.

I've tried the nomerge commands and I've tried adding a u-boot.txt with the quirk you used (@sonik). Is it just a case of adding this text file in that Linux folder, or is there more to it?

I've tried the default codes, and switching the pid/vid codes to match the hex code I see in the controller config, on the Jamma/no merge lines, but it:
a/ didn't change anything with the 2p controls
b/ made the 1p controls act weird, e.g. my menu shortcut (btn3+1p start) would trigger auto fire mode.

I'm quite new to this level of jiggery pokery to get things working, but I hope I've just overlooked something. Would really appreciate any help (my wife really misses 2p Bubble Bobble).

Cheers!
Post Reply