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

No vibration support for the Stadia Controller #578

Closed
DJm00n opened this issue Jan 24, 2023 · 13 comments · Fixed by #620
Closed

No vibration support for the Stadia Controller #578

DJm00n opened this issue Jan 24, 2023 · 13 comments · Fixed by #620

Comments

@DJm00n
Copy link

DJm00n commented Jan 24, 2023

BlueRetro firmware version

v1.8.3

BlueRetro firmware specification

HW1

BlueRetro firmware variant

Universal

BlueRetro hardware type

External adapter with detachable cord

Manufacturer

BlueRetro Gaming Store

System used

Sony PlayStation 2

Bluetooth controller brand & name

No response

What is problem? (only list ONE problem per report)

Google Stadia Controller with latest firmware from https://stadia.google.com/controller (added Bluetooth LE HID over GATT support) does not have vibration support.

Here is structure that can be used to add such support (parsed out of its HID Report Descriptor):

typedef struct
{
  uint8_t  reportId;                                 // Report ID = 0x05 (5)
                                                     // Collection: CA:GamePad
  uint16_t PID_GamePadDcEnableActuators[2];          // Usage 0x000F0097: DC Enable Actuators, Value = 0 to 65535
} outputReport05_t;

This is how its done in Chromium:
https://github.com/chromium/chromium/blob/main/device/gamepad/hid_haptic_gamepad.h#L23-L69
https://github.com/chromium/chromium/blob/main/device/gamepad/hid_haptic_gamepad.cc#L50-L51

SDL implementation:
https://github.com/libsdl-org/SDL/blob/main/src/joystick/hidapi/SDL_hidapi_stadia.c#L108-L121

What did you expect to happen?

Haptic feedback should work with Google Stadia controller.

Attach files like logs or Bluetooth traces here

No response

@DJm00n
Copy link
Author

DJm00n commented Jan 24, 2023

Also you can add this info on the controller pairing guide page:

To pair your controller to a different device, press the Stadia button + the Y button for 2 seconds until the status light starts flashing orange. You can then follow the pairing instructions to connect the controller to a different device.

After you pair your controller to a device, it will blink white and connect automatically to the device when you turn it on. If your controller doesn't connect, repeat the steps above to connect to a device. If you still have trouble with Bluetooth, check the troubleshooting tips below or refer to the instructions for your device.

@N4Y33MM
Copy link

N4Y33MM commented Feb 10, 2023

How did you manage to get the controller working? When I connected mine all the button mappings are all over the place. eg. X is the screenshot button and circle is Y and the other A B buttons don't work. Would appreciate any help! thanks

@DJm00n
Copy link
Author

DJm00n commented Feb 10, 2023

@N4Y33MM just installed v1.8.2-6-gb4538b1 (regular 1.8.2 doesn't have it yet) and updated controller firmware at stadia.google.com/controller. Works ok on my PS2.

@DJm00n
Copy link
Author

DJm00n commented Feb 19, 2023

@N4Y33MM v1.8.3 is out.

@N4Y33MM
Copy link

N4Y33MM commented Feb 19, 2023

Edit: All working now perfectly!

@N4Y33MM v1.8.3 is out.

Thankss! Will test it out appreciate it

@DJm00n
Copy link
Author

DJm00n commented Feb 26, 2023

I uploaded v1.8.3-3-g63a4153_hw1 fimware to my Blueretro and to test vibration with Stadia Controller.

I have used padtest tool on PS2:

To test vibration, hold :triangle: , then move the left joystick down for the strong motor (that seems to have 96 positions), or press :dpad-ud: on the directional pad for the weak motor (that has 2 positions).

Result: no vibration at all with Stadia Controller.

@darthcloud please reopen this issue.

PS: I have also tried to pair a PS5 DualSense controller to compare and vibration seems working fine with it (but both "motors" feels the same - that it is expected #20).

@JPZV
Copy link
Contributor

JPZV commented Feb 26, 2023

@DJm00n Just to check: In BlueRetro.io, on Advanced Config, all your control have the "Rumble Only" accessory, right?

If you can, please comment the raw HID Report from your Stadia connected by Bluetooth. It's easiest to get it on Linux using HidRaw Dump

@DJm00n
Copy link
Author

DJm00n commented Feb 26, 2023

@JPZV just checked "Advanced Config" - yes "Rumble" is selected:
image

Here is report Stadia Controller report descriptor (it is same in USB and Bluetooth LE connection modes): https://github.com/DJm00n/ControllersInfo/blob/master/stadiacontroller/stadiacontroller_bluetoothle_hid_report_descriptor.txt

@JPZV
Copy link
Contributor

JPZV commented Feb 26, 2023

Sadly I don't have any Stadia controller, and getting one on this side of the world (Chile) is nearly impossible. But I tried to use almost the same HID report from a Stadia Controller on my new project, and it works perfectly on a Wii with a ESP32 with BlueRetro connected to the GameCube controller ports.

Here is the HID report from my controller. If you pay attention at the end, you'll find it's likely the same as the Stadia controller.

HID Report
//--------------------------------------------------------------------------------
// Decoded Application Collection
//--------------------------------------------------------------------------------

/*
05 01        (GLOBAL) USAGE_PAGE         0x0001 Generic Desktop Page 
09 05        (LOCAL)  USAGE              0x00010005 Game Pad (Application Collection)  
A1 01        (MAIN)   COLLECTION         0x01 Application (Usage=0x00010005: Page=Generic Desktop Page, Usage=Game Pad, Type=Application Collection)
85 04          (GLOBAL) REPORT_ID          0x04 (4)  
05 09          (GLOBAL) USAGE_PAGE         0x0009 Button Page 
15 00          (GLOBAL) LOGICAL_MINIMUM    0x00 (0)  <-- Info: Consider replacing 15 00 with 14
25 01          (GLOBAL) LOGICAL_MAXIMUM    0x01 (1)  
75 01          (GLOBAL) REPORT_SIZE        0x01 (1) Number of bits per field  
19 01          (LOCAL)  USAGE_MINIMUM      0x00090001 Button 1 Primary/trigger (Selector, On/Off Control, Momentary Control, or One Shot Control)  
29 0D          (LOCAL)  USAGE_MAXIMUM      0x0009000D Button 13 (Selector, On/Off Control, Momentary Control, or One Shot Control)  
95 0D          (GLOBAL) REPORT_COUNT       0x0D (13) Number of fields  
81 02          (MAIN)   INPUT              0x00000002 (13 fields x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap 
75 01          (GLOBAL) REPORT_SIZE        0x01 (1) Number of bits per field <-- Redundant: REPORT_SIZE is already 1 
95 03          (GLOBAL) REPORT_COUNT       0x03 (3) Number of fields  
81 03          (MAIN)   INPUT              0x00000003 (3 fields x 1 bit) 1=Constant 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap 
15 00          (GLOBAL) LOGICAL_MINIMUM    0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
25 01          (GLOBAL) LOGICAL_MAXIMUM    0x01 (1) <-- Redundant: LOGICAL_MAXIMUM is already 1 
75 01          (GLOBAL) REPORT_SIZE        0x01 (1) Number of bits per field <-- Redundant: REPORT_SIZE is already 1 
05 01          (GLOBAL) USAGE_PAGE         0x0001 Generic Desktop Page 
95 01          (GLOBAL) REPORT_COUNT       0x01 (1) Number of fields  
09 3E          (LOCAL)  USAGE              0x0001003E Select (On/Off Control)  
81 02          (MAIN)   INPUT              0x00000002 (1 field x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap 
75 01          (GLOBAL) REPORT_SIZE        0x01 (1) Number of bits per field <-- Redundant: REPORT_SIZE is already 1 
95 07          (GLOBAL) REPORT_COUNT       0x07 (7) Number of fields  
81 03          (MAIN)   INPUT              0x00000003 (7 fields x 1 bit) 1=Constant 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap 
A1 00          (MAIN)   COLLECTION         0x00 Physical (Usage=0x0: Page=, Usage=, Type=) <-- Error: COLLECTION must be preceded by a known USAGE <-- Warning: USAGE type should be CP (Physical Collection)
05 01            (GLOBAL) USAGE_PAGE         0x0001 Generic Desktop Page <-- Redundant: USAGE_PAGE is already 0x0001
09 39            (LOCAL)  USAGE              0x00010039 Hat switch (Dynamic Value)  
15 01            (GLOBAL) LOGICAL_MINIMUM    0x01 (1)  
25 08            (GLOBAL) LOGICAL_MAXIMUM    0x08 (8)  
35 00            (GLOBAL) PHYSICAL_MINIMUM   0x00 (0)  <-- Info: Consider replacing 35 00 with 34
46 3B01          (GLOBAL) PHYSICAL_MAXIMUM   0x013B (315)  
65 12            (GLOBAL) UNIT               0x12 Rotation in radians [1 rad units] (2=System=SI Rotation, 1=Rotation=Radians)  
75 08            (GLOBAL) REPORT_SIZE        0x08 (8) Number of bits per field  
95 01            (GLOBAL) REPORT_COUNT       0x01 (1) Number of fields  
81 42            (MAIN)   INPUT              0x00000042 (1 field x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 1=Null 0=NonVolatile 0=Bitmap 
C0             (MAIN)   END_COLLECTION     Physical  <-- Warning: Physical units are still in effect PHYSICAL(MIN=0,MAX=315) UNIT(0x00000012,EXP=0)
05 0F          (GLOBAL) USAGE_PAGE         0x000F Physical Interface Device Page 
85 05          (GLOBAL) REPORT_ID          0x05 (5)  
09 97          (LOCAL)  USAGE              0x000F0097 DC Enable Actuators (Selector)  
15 00          (GLOBAL) LOGICAL_MINIMUM    0x00 (0)  <-- Info: Consider replacing 15 00 with 14
27 FFFF0000    (GLOBAL) LOGICAL_MAXIMUM    0x0000FFFF (65535)  
75 10          (GLOBAL) REPORT_SIZE        0x10 (16) Number of bits per field  
95 02          (GLOBAL) REPORT_COUNT       0x02 (2) Number of fields  
91 02          (MAIN)   OUTPUT             0x00000002 (2 fields x 16 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap 
C0           (MAIN)   END_COLLECTION     Application  <-- Warning: Physical units are still in effect PHYSICAL(MIN=0,MAX=315) UNIT(0x00000012,EXP=0)
*/

// All structure fields should be byte-aligned...
#pragma pack(push,1)

//--------------------------------------------------------------------------------
// Button Page inputReport 04 (Device --> Host)
//--------------------------------------------------------------------------------

typedef struct
{
  uint8_t  reportId;                                 // Report ID = 0x04 (4)
                                                     // Collection: CA:GamePad
  uint8_t  BTN_GamePadButton1 : 1;                   // Usage 0x00090001: Button 1 Primary/trigger, Value = 0 to 1
  uint8_t  BTN_GamePadButton2 : 1;                   // Usage 0x00090002: Button 2 Secondary, Value = 0 to 1
  uint8_t  BTN_GamePadButton3 : 1;                   // Usage 0x00090003: Button 3 Tertiary, Value = 0 to 1
  uint8_t  BTN_GamePadButton4 : 1;                   // Usage 0x00090004: Button 4, Value = 0 to 1
  uint8_t  BTN_GamePadButton5 : 1;                   // Usage 0x00090005: Button 5, Value = 0 to 1
  uint8_t  BTN_GamePadButton6 : 1;                   // Usage 0x00090006: Button 6, Value = 0 to 1
  uint8_t  BTN_GamePadButton7 : 1;                   // Usage 0x00090007: Button 7, Value = 0 to 1
  uint8_t  BTN_GamePadButton8 : 1;                   // Usage 0x00090008: Button 8, Value = 0 to 1
  uint8_t  BTN_GamePadButton9 : 1;                   // Usage 0x00090009: Button 9, Value = 0 to 1
  uint8_t  BTN_GamePadButton10 : 1;                  // Usage 0x0009000A: Button 10, Value = 0 to 1
  uint8_t  BTN_GamePadButton11 : 1;                  // Usage 0x0009000B: Button 11, Value = 0 to 1
  uint8_t  BTN_GamePadButton12 : 1;                  // Usage 0x0009000C: Button 12, Value = 0 to 1
  uint8_t  BTN_GamePadButton13 : 1;                  // Usage 0x0009000D: Button 13, Value = 0 to 1
  uint8_t  : 1;                                      // Pad
  uint8_t  : 1;                                      // Pad
  uint8_t  : 1;                                      // Pad
  uint8_t  GD_GamePadSelect : 1;                     // Usage 0x0001003E: Select, Value = 0 to 1
  uint8_t  : 1;                                      // Pad
  uint8_t  : 1;                                      // Pad
  uint8_t  : 1;                                      // Pad
  uint8_t  : 1;                                      // Pad
  uint8_t  : 1;                                      // Pad
  uint8_t  : 1;                                      // Pad
  uint8_t  : 1;                                      // Pad
                                                     // Collection: CA:GamePad CP:
  uint8_t  GD_GamePadHatSwitch;                      // Usage 0x00010039: Hat switch, Value = 1 to 8, Physical = (Value - 1) x 45 in rad
} inputReport04_t;


//--------------------------------------------------------------------------------
// Physical Interface Device Page outputReport 05 (Device <-- Host)
//--------------------------------------------------------------------------------

typedef struct
{
  uint8_t  reportId;                                 // Report ID = 0x05 (5)
                                                     // Collection: CA:GamePad
  uint16_t PID_GamePadDcEnableActuators[2];          // Usage 0x000F0097: DC Enable Actuators, Value = 0 to 65535, Physical = Value x 21 / 4369 in rad
} outputReport05_t;

#pragma pack(pop)

Could you test the Stadia Controller on a GameCube/Wii with a BlueRetro on it? Just in case.

Meanwhile, I'll try to add BlueRetro to a PS2 that I've lying around. I want to see if this is an issue from the console side or from the Controller's. Also, I'll do more research about how Stadia manages the reports for rumbling.

@DJm00n
Copy link
Author

DJm00n commented Feb 26, 2023

I not familiar with a BLE stack but it could be related with the several ways how output report data can be transfered:

image
image

https://www.bluetooth.com/specifications/specs/human-interface-device-service-1-0/

This if may be related:
https://github.com/bluez/bluez/blob/a1736d8990ff56bba453ff81a25156316bdd118f/profiles/input/hog-lib.c#L806-L812

Another clue:
https://github.com/nrfconnect/sdk-nrf/blob/860a4fe038c9edcdd53d05285f82f2aa35a49d05/applications/nrf_desktop/src/modules/hid_forward.c#L1204-L1226

It was also found that the Stadia Controller vibration does not work on Windows via BLE, but do work on Linux and macOS - libsdl-org/SDL#7224

@DJm00n
Copy link
Author

DJm00n commented Feb 26, 2023

Could you test the Stadia Controller on a GameCube/Wii with a BlueRetro on it? Just in case.

I don't have Wii or GameCube...

@JPZV
Copy link
Contributor

JPZV commented Feb 27, 2023

Sadly it's beyond my capabilities, as DarthCloud made his own integration for BT handling AFAIK

If someone is able to integrate the HidD_SetOutputReport homologue, then the only next thing to do would be to add an if on bluetooth/hidp/generic.c#L14 similar to the one used on bluez.

Meanwhile, I think this issue should be reopened. I hope this is the only device to not work with my code

@darthcloud
Copy link
Owner

Open a new fresh bug with current state of affair.

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 a pull request may close this issue.

4 participants