Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Rumble Support for generic devices #620

Merged
merged 2 commits into from
Feb 25, 2023

Conversation

JPZV
Copy link
Contributor

@JPZV JPZV commented Feb 23, 2023

This adds support for generic HID controllers to have rumble Support (#611)

Every device which reports usages from 0F 95 to 0F 9C will be marked as a rumble-capable device (hid_parser.c#L196) along with 0F 50, 0F 70, 0F 7C and 0F A7 (hid_parser.c#L197).

Please note that there is no effect support, so usages from 0F 99 to 0F 9C have no use.

The way it works is by getting the Maximum and the Minimum value for the report. In case the Rumble State is off, then the BlueRetro will send the minimum value to every usage. Otherwise, it'll send the maximum value multiplied by a multiplier constant (its value is from 0.0 to 1.0. I leave it there just in case) or the value from fb_data.

This should work with generic controllers like the Stadia one, Chinese clones/alternatives, and projects like my BluControl (TBA) an BluN64, without needing to integrate them separately.

Main Changes:

  • Added RUMBLE report id
  • Added USAGE_GEN_PHYS_INPUT Usage Page
  • Moved HID_MI_OUTPUT to the block of HID_MI_INPUT (hid_parser.c#L392)
  • Implemented the feedback functions for generic HID controllers

Tested with:

  • Config: HW1 GameCube
  • Console: Nintendo Wii
  • Game: Super Smash Bros Brawl
  • HomeBrew: GameCube Controller Tester
  • Controller: Generic one based on BluControl

There shouldn't be any breaking change as I didn't touch anything related to the current functionalities. Also, I didn't note any type of input lag, and I tried to simplify as much as I could.

If you have any question or feedback, please let me know

@JPZV
Copy link
Contributor Author

JPZV commented Feb 24, 2023

Note: The reason about pytest failling is because (I think) it originally didn't count about BlueRetro printing an Output usage.

Below is the test Descriptor parsed by USB Descriptor and Request Parser, and I marked both Output which were ignored on previous version of BlueRetro:

Test Descriptor
0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
0x09, 0x06,        // Usage (Keyboard)
0xA1, 0x01,        // Collection (Application)
0x85, 0x01,        //   Report ID (1)
0x75, 0x01,        //   Report Size (1)
0x95, 0x08,        //   Report Count (8)
0x05, 0x07,        //   Usage Page (Kbrd/Keypad)
0x19, 0xE0,        //   Usage Minimum (0xE0)
0x29, 0xE7,        //   Usage Maximum (0xE7)
0x15, 0x00,        //   Logical Minimum (0)
0x25, 0x01,        //   Logical Maximum (1)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x95, 0x01,        //   Report Count (1)
0x75, 0x08,        //   Report Size (8)
0x81, 0x03,        //   Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x95, 0x05,        //   Report Count (5)
0x75, 0x01,        //   Report Size (1)
0x05, 0x08,        //   Usage Page (LEDs)
0x19, 0x01,        //   Usage Minimum (Num Lock)
0x29, 0x05,        //   Usage Maximum (Kana)
0x91, 0x02, /////////   Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x95, 0x01,        //   Report Count (1)
0x75, 0x03,        //   Report Size (3)
0x91, 0x03, /////////   Output (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x95, 0x06,        //   Report Count (6)
0x75, 0x08,        //   Report Size (8)
0x15, 0x00,        //   Logical Minimum (0)
0x26, 0xFF, 0x00,  //   Logical Maximum (255)
0x05, 0x07,        //   Usage Page (Kbrd/Keypad)
0x19, 0x00,        //   Usage Minimum (0x00)
0x29, 0xFF,        //   Usage Maximum (0xFF)
0x81, 0x00,        //   Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0,              // End Collection
0x05, 0x0C,        // Usage Page (Consumer)
0x09, 0x01,        // Usage (Consumer Control)
0xA1, 0x01,        // Collection (Application)
0x85, 0x02,        //   Report ID (2)
0x15, 0x00,        //   Logical Minimum (0)
0x25, 0x01,        //   Logical Maximum (1)
0x75, 0x01,        //   Report Size (1)
0x95, 0x16,        //   Report Count (22)
0x0A, 0xB1, 0x01,  //   Usage (AL Screen Saver)
0x0A, 0x23, 0x02,  //   Usage (AC Home)
0x0A, 0xAE, 0x01,  //   Usage (AL Keyboard Layout)
0x0A, 0x8A, 0x01,  //   Usage (AL Email Reader)
0x09, 0x40,        //   Usage (Menu)
0x09, 0x6F,        //   Usage (0x6F)
0x0A, 0x21, 0x02,  //   Usage (AC Search)
0x09, 0xB6,        //   Usage (Scan Previous Track)
0x09, 0xCD,        //   Usage (Play/Pause)
0x09, 0xB5,        //   Usage (Scan Next Track)
0x09, 0xE2,        //   Usage (Mute)
0x09, 0xEA,        //   Usage (Volume Decrement)
0x09, 0xE9,        //   Usage (Volume Increment)
0x09, 0x30,        //   Usage (Power)
0x0A, 0x83, 0x01,  //   Usage (AL Consumer Control Configuration)
0x0A, 0x24, 0x02,  //   Usage (AC Back)
0x0A, 0x06, 0x03,  //   Usage (0x0306)
0x0A, 0x08, 0x03,  //   Usage (0x0308)
0x0A, 0x01, 0x03,  //   Usage (0x0301)
0x0A, 0x83, 0x01,  //   Usage (AL Consumer Control Configuration)
0x0A, 0x0A, 0x03,  //   Usage (0x030A)
0x09, 0x70,        //   Usage (0x70)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x95, 0x01,        //   Report Count (1)
0x75, 0x02,        //   Report Size (2)
0x81, 0x03,        //   Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0,              // End Collection

// 147 bytes

I didn't change the pytest files because I think that should be done by the maintainers after they accept the Pull, but it's just about updating the expecting string to 1 07E0 0 8 0801 16 5 0700 24 8, 0700 32 8, 0700 40 8, 0700 48 8, 0700 56 8, 0700 64 8, rtype: 0 dtype: 0 sub: 0 (the only thing that changes is the addition of 0801 16 5 and the consecutive offsets)

@darthcloud
Copy link
Owner

It's minor but in my view a PR should make sure if they affect the test result expectation to modify them to the new expectation.

This look really good. Does that make both left & right motor work in a sensible way?

I wonder if that would work better than whatever I make for xbox?

With an extra commit to fix the test, I would merge this.

@JPZV
Copy link
Contributor Author

JPZV commented Feb 25, 2023

It's minor but in my view a PR should make sure if they affect the test result expectation to modify them to the new expectation.

Yeah, I think the same. My guess is that the test didn't expect to read an output usage so that's why it's failing now, as BlueRetro printed an output that were ignored before. (As you can see, before every output usage would be completely ignored, while now it'll be threated as the same way as an input)

This look really good. Does that make both left & right motor work in a sensible way?

It should, but I need more devices to test it. My code assumes that every report field is a motor, so if there are five rumble motors, they all will be turned on/off in the same way.

Right now BlueRetro doesn't pass much information to handle them separately. But I tried to use them all, like the delay, the cycle count, and the duration. Some of them I get from BlueRetro itself while the others are from Max/Min values.

I wonder if that would work better than whatever I make for xbox?

I actually based my code from the Xbox one, and I thought the exactly the same, but, again, I don't have any Xbox One controller so I cannot test it neither.

With an extra commit to fix the test, I would merge this.

As I said before, the only thing to "fix" the test should be to update the expected output adding the new Output usage

@darthcloud
Copy link
Owner

Yes I know, I would expect you to be the one to modify that. You are the owner of the PR and it's failing the test ;)

@JPZV
Copy link
Contributor Author

JPZV commented Feb 25, 2023

Ok, I modified the expected output according to what I get with a BlueRetro running on a ESP32 and with a BT Device with the exactly the same descriptor as the test. Right now it should be doing the test and I hope it should end successfully

@darthcloud
Copy link
Owner

Ok I will look at more closely later, It doesn't make sense for the report # 1 usage offset to change IMHO.

The rumble stuff should be like in another report.

@JPZV
Copy link
Contributor Author

JPZV commented Feb 25, 2023

I think the output is on report # 1 because they're declared before changing the ID.

image

As you can see, all of the inputs (Red) and both Outputs (Blue) are on the same Report (Yellow/1) as the Report 2 was declared after (Orange).

About getting rumble from another report, that's completely from the device's side, as the manufacture defines the structure. For example, in Stadia, Google didn't use Collections while Microsoft did. The same thing for Output reports. In a perfect world, yes indeed, those reports should be in a different report, but you know where we live right now ¯_(ツ)_/¯

@darthcloud
Copy link
Owner

Sorry for my confusion, in my mind the LEDs output case was handled properly all along. So I was surprised when I saw it popping in and shifting all other key usage bit range by one bytes.

That means keyboard where kind of broken since day one but it was kind of ok since having the Leds byte as the first key didn't make anything, and missing the last key just reduced the amount of simultaneous key press by one.

Anyway your PR fix this!

@darthcloud darthcloud linked an issue Feb 25, 2023 that may be closed by this pull request
@darthcloud darthcloud merged commit 501e623 into darthcloud:master Feb 25, 2023
@darthcloud
Copy link
Owner

Thanks again for the PR!

@JPZV
Copy link
Contributor Author

JPZV commented Feb 25, 2023

No problem! I'm very happy to support this amazing project!!!

@DJm00n
Copy link

DJm00n commented Feb 26, 2023

Wow. Nice! Thank you @JPZV! I'll give it a try with my Stadia Controller.

@DJm00n
Copy link

DJm00n commented Feb 26, 2023

@JPZV Seems vibration still not working with Stadia Controller. See #578.

@JPZV JPZV deleted the gen-rumble-pr branch February 26, 2023 21:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

No vibration support for the Stadia Controller
3 participants