ESP32-BLE-Gamepad icon indicating copy to clipboard operation
ESP32-BLE-Gamepad copied to clipboard

Unity InputSystem Reportsize issue

Open QuiNz0r opened this issue 6 months ago • 22 comments

https://discussions.unity.com/t/custom-bluetooth-gamepad-not-recognized/1651504

Having exactly this issue. Everything is running newest version with minimal gamepad example from this repo.

Any idea? I really want to get this running. Setting button count to 16 doesn't help for me

QuiNz0r avatar Sep 15 '25 15:09 QuiNz0r

Interesting issue. I have not used Unity so I am guessing at alot of things here, but hoping some suggestion might help.

Did you delete the pairing from Unity between gamepad changes? Seems like Unity is using HIDAPI access and not using the Host OS provided interface. Thinking maybe changes you made to your sketch, might not be been picked up by the host interface, as many hosts cache BLE attribs - https://github.com/lemmingDev/ESP32-BLE-Gamepad/blob/master/TroubleshootingGuide.md#configuration-changes-not-taking-effect

Another idea, try a sketch that does not have any devices that have padding needs (buttons and specialButtons). If you interested, you can see this around

https://github.com/lemmingDev/ESP32-BLE-Gamepad/blob/71a1bcbaca57f079adafe4dbf6225ed314f62fcb/BleGamepad.cpp#L193

and

https://github.com/lemmingDev/ESP32-BLE-Gamepad/blob/71a1bcbaca57f079adafe4dbf6225ed314f62fcb/BleGamepad.cpp#L316

or make sure the button usage has zero padding, by keeping the button count to multiple of 8.

Other debugging things that could be done, is to verify the hidReportDescriptor, but I don't have an easy way to offer how to do this. See if I can find a way or maybe a test sketch, but let's see if the above helps in any way. It is possible that the hidReportDescriptor is not correct and the current host of support OS are dealing with this.

LeeNX avatar Sep 16 '25 07:09 LeeNX

  // Testing - Ask ChatGPT to convert it into a commented HID descriptor
  //Serial.println("------- HID DESCRIPTOR START -------");
  //for (int i = 0; i < BleGamepadInstance->hidReportDescriptorSize; i++)
  //{
  //    Serial.printf("%02x", customHidReportDescriptor[i]);
  //    Serial.println();
  //}
  //Serial.println("------- HID DESCRIPTOR END -------");

From line 2050 in BleGamepad.cpp there is some code you can uncomment to output the generated HID report descriptor to the serial monitor

lemmingDev avatar Sep 16 '25 11:09 lemmingDev

Interesting issue. I have not used Unity so I am guessing at alot of things here, but hoping some suggestion might help.

Did you delete the pairing from Unity between gamepad changes? Seems like Unity is using HIDAPI access and not using the Host OS provided interface. Thinking maybe changes you made to your sketch, might not be been picked up by the host interface, as many hosts cache BLE attribs - https://github.com/lemmingDev/ESP32-BLE-Gamepad/blob/master/TroubleshootingGuide.md#configuration-changes-not-taking-effect

Another idea, try a sketch that does not have any devices that have padding needs (buttons and specialButtons). If you interested, you can see this around

https://github.com/lemmingDev/ESP32-BLE-Gamepad/blob/71a1bcbaca57f079adafe4dbf6225ed314f62fcb/BleGamepad.cpp#L193

and

https://github.com/lemmingDev/ESP32-BLE-Gamepad/blob/71a1bcbaca57f079adafe4dbf6225ed314f62fcb/BleGamepad.cpp#L316

or make sure the button usage has zero padding, by keeping the button count to multiple of 8.

Other debugging things that could be done, is to verify the hidReportDescriptor, but I don't have an easy way to offer how to do this. See if I can find a way or maybe a test sketch, but let's see if the above helps in any way. It is possible that the hidReportDescriptor is not correct and the current host of support OS are dealing with this.

It's definitely not caching. I unpair cleanly and toggle Bluetooth and restart unity after every change.

When I play with button count until output report size is exactly 8 unity accepts the device but only as joystick not as gamepad (hid discriptor is still clearly gamepad) this doesn't work for me since Android doesn't accept hid joysticks.

There is a fork of this repo with an xinput Xbox controller "spoof" and it works right away in Unity and also Android. But with a lot of overhead I don't want by instantiating a reference of a custom class (also don't want that)

https://github.com/Mystfit/ESP32-BLE-CompositeHID

Maybe that's something where to look?

QuiNz0r avatar Sep 16 '25 11:09 QuiNz0r

  // Testing - Ask ChatGPT to convert it into a commented HID descriptor
  //Serial.println("------- HID DESCRIPTOR START -------");
  //for (int i = 0; i < BleGamepadInstance->hidReportDescriptorSize; i++)
  //{
  //    Serial.printf("%02x", customHidReportDescriptor[i]);
  //    Serial.println();
  //}
  //Serial.println("------- HID DESCRIPTOR END -------");

From line 2050 in BleGamepad.cpp there is some code you can uncomment to output the generated HID report descriptor to the serial monitor

------ HID DESCRIPTOR START ------ 05 01 09 05 a1 01 85 03 05 09 19 01 29 15 25 01 95 05 75 01 81 02 95 01 75 03 81 01 05 01 09 30 09 31 16 00 80 26 ff 7f 75 10 95 02 81 06 09 38 15 81 25 7f 75 08 95 01 81 06 05 0c 0a 38 02 95 01 75 08 81 06 c0 ------ HID DESCRIPTOR END ------

This parse is from the minimal gamepad example with setbuttoncount to 16 (which is also default I think)

QuiNz0r avatar Sep 16 '25 11:09 QuiNz0r

And then when you provide chat gpt with those numbers and the prompt "convert to commented hid report descriptor", it gives:

// Usage Page (Generic Desktop)
0x05, 0x01,       // USAGE_PAGE (Generic Desktop)
// Usage (Game Pad)
0x09, 0x05,       // USAGE (Game Pad)
// Collection (Application)
0xA1, 0x01,       // COLLECTION (Application)
// Report ID (3)
0x85, 0x03,       //   REPORT_ID (3)

// --- Buttons ---
0x05, 0x09,       //   USAGE_PAGE (Button)
0x19, 0x01,       //   USAGE_MINIMUM (Button 1)
0x29, 0x15,       //   USAGE_MAXIMUM (Button 21)
0x25, 0x01,       //   LOGICAL_MAXIMUM (1)
0x95, 0x05,       //   REPORT_COUNT (5 buttons)
0x75, 0x01,       //   REPORT_SIZE (1 bit each)
0x81, 0x02,       //   INPUT (Data,Var,Abs) ; 5 button bits
0x95, 0x01,       //   REPORT_COUNT (1)
0x75, 0x03,       //   REPORT_SIZE (3 bits)
0x81, 0x01,       //   INPUT (Cnst,Ary,Abs) ; padding bits

// --- X and Y axes ---
0x05, 0x01,       //   USAGE_PAGE (Generic Desktop)
0x09, 0x30,       //   USAGE (X)
0x09, 0x31,       //   USAGE (Y)
0x16, 0x00, 0x80, //   LOGICAL_MINIMUM (-32768)
0x26, 0xFF, 0x7F, //   LOGICAL_MAXIMUM (32767)
0x75, 0x10,       //   REPORT_SIZE (16 bits)
0x95, 0x02,       //   REPORT_COUNT (2 axes)
0x81, 0x06,       //   INPUT (Data,Var,Rel)

// --- Z axis (wheel/rotation) ---
0x09, 0x38,       //   USAGE (Wheel)
0x15, 0x81,       //   LOGICAL_MINIMUM (-127)
0x25, 0x7F,       //   LOGICAL_MAXIMUM (127)
0x75, 0x08,       //   REPORT_SIZE (8 bits)
0x95, 0x01,       //   REPORT_COUNT (1)
0x81, 0x06,       //   INPUT (Data,Var,Rel)

// --- Hat switch (POV hat) ---
0x05, 0x0C,       //   USAGE_PAGE (Consumer Devices)
0x0A, 0x38, 0x02, //   USAGE (AC Pan) – often repurposed as POV hat
0x95, 0x01,       //   REPORT_COUNT (1)
0x75, 0x08,       //   REPORT_SIZE (8 bits)
0x81, 0x06,       //   INPUT (Data,Var,Rel)

// End Collection
0xC0              // END_COLLECTION

lemmingDev avatar Sep 16 '25 12:09 lemmingDev

And then when you provide chat gpt with those numbers and the prompt "convert to commented hid report descriptor", it gives:

// Usage Page (Generic Desktop)
0x05, 0x01,       // USAGE_PAGE (Generic Desktop)
// Usage (Game Pad)
0x09, 0x05,       // USAGE (Game Pad)
// Collection (Application)
0xA1, 0x01,       // COLLECTION (Application)
// Report ID (3)
0x85, 0x03,       //   REPORT_ID (3)

// --- Buttons ---
0x05, 0x09,       //   USAGE_PAGE (Button)
0x19, 0x01,       //   USAGE_MINIMUM (Button 1)
0x29, 0x15,       //   USAGE_MAXIMUM (Button 21)
0x25, 0x01,       //   LOGICAL_MAXIMUM (1)
0x95, 0x05,       //   REPORT_COUNT (5 buttons)
0x75, 0x01,       //   REPORT_SIZE (1 bit each)
0x81, 0x02,       //   INPUT (Data,Var,Abs) ; 5 button bits
0x95, 0x01,       //   REPORT_COUNT (1)
0x75, 0x03,       //   REPORT_SIZE (3 bits)
0x81, 0x01,       //   INPUT (Cnst,Ary,Abs) ; padding bits

// --- X and Y axes ---
0x05, 0x01,       //   USAGE_PAGE (Generic Desktop)
0x09, 0x30,       //   USAGE (X)
0x09, 0x31,       //   USAGE (Y)
0x16, 0x00, 0x80, //   LOGICAL_MINIMUM (-32768)
0x26, 0xFF, 0x7F, //   LOGICAL_MAXIMUM (32767)
0x75, 0x10,       //   REPORT_SIZE (16 bits)
0x95, 0x02,       //   REPORT_COUNT (2 axes)
0x81, 0x06,       //   INPUT (Data,Var,Rel)

// --- Z axis (wheel/rotation) ---
0x09, 0x38,       //   USAGE (Wheel)
0x15, 0x81,       //   LOGICAL_MINIMUM (-127)
0x25, 0x7F,       //   LOGICAL_MAXIMUM (127)
0x75, 0x08,       //   REPORT_SIZE (8 bits)
0x95, 0x01,       //   REPORT_COUNT (1)
0x81, 0x06,       //   INPUT (Data,Var,Rel)

// --- Hat switch (POV hat) ---
0x05, 0x0C,       //   USAGE_PAGE (Consumer Devices)
0x0A, 0x38, 0x02, //   USAGE (AC Pan) – often repurposed as POV hat
0x95, 0x01,       //   REPORT_COUNT (1)
0x75, 0x08,       //   REPORT_SIZE (8 bits)
0x81, 0x06,       //   INPUT (Data,Var,Rel)

// End Collection
0xC0              // END_COLLECTION

Yes sorry I pasted it in another converter and this looks fine? I suspected axis ranges at first from another google search but setting them to half size and positive only didn't help

QuiNz0r avatar Sep 16 '25 12:09 QuiNz0r

You don't edit this file directly to change the values

Check out a number of the examples to see how to change axes min and button count etc

Important - Every time you change something, you need to delete the Bluetooth controller and then repair

lemmingDev avatar Sep 16 '25 12:09 lemmingDev

ChatGPT got it a little wrong

Here is GROK's attempt

Might still have errors

Are you sure it's the default example with 16 buttons?

// HID Report Descriptor
0x05, 0x01,        // Usage Page (Generic Desktop Controls)
0x09, 0x05,        // Usage (Game Pad)
0xA1, 0x01,        // Collection (Application)
0x85, 0x03,        //   Report ID (3)
0x05, 0x09,        //   Usage Page (Button)
0x19, 0x01,        //   Usage Minimum (Button 1)
0x29, 0x05,        //   Usage Maximum (Button 5)
0x15, 0x00,        //   Logical Minimum (0)
0x25, 0x01,        //   Logical Maximum (1)
0x95, 0x05,        //   Report Count (5)
0x75, 0x01,        //   Report Size (1)
0x81, 0x02,        //   Input (Data, Variable, Absolute) - 5 buttons, 1 bit each
0x95, 0x01,        //   Report Count (1)
0x75, 0x03,        //   Report Size (3)
0x81, 0x01,        //   Input (Constant) - 3-bit padding
0x05, 0x01,        //   Usage Page (Generic Desktop Controls)
0x09, 0x30,        //   Usage (X)
0x09, 0x31,        //   Usage (Y)
0x16, 0x00, 0x80,  //   Logical Minimum (-32768)
0x26, 0xFF, 0x7F,  //   Logical Maximum (32767)
0x75, 0x10,        //   Report Size (16)
0x95, 0x02,        //   Report Count (2)
0x81, 0x06,        //   Input (Data, Variable, Relative) - X and Y axes, 16 bits each
0x09, 0x38,        //   Usage (Wheel)
0x15, 0x81,        //   Logical Minimum (-127)
0x25, 0x7F,        //   Logical Maximum (127)
0x75, 0x08,        //   Report Size (8)
0x95, 0x01,        //   Report Count (1)
0x81, 0x06,        //   Input (Data, Variable, Relative) - Wheel, 8 bits
0x05, 0x0C,        //   Usage Page (Consumer)
0x0A, 0x38, 0x02,  //   Usage (AC Pan)
0x95, 0x01,        //   Report Count (1)
0x75, 0x08,        //   Report Size (8)
0x81, 0x06,        //   Input (Data, Variable, Relative) - AC Pan, 8 bits
0xC0               // End Collection

lemmingDev avatar Sep 16 '25 12:09 lemmingDev

ChatGPT got it a little wrong

Here is GROK's attempt

Might still have errors

Are you sure it's the default example with 16 buttons?

// HID Report Descriptor
0x05, 0x01,        // Usage Page (Generic Desktop Controls)
0x09, 0x05,        // Usage (Game Pad)
0xA1, 0x01,        // Collection (Application)
0x85, 0x03,        //   Report ID (3)
0x05, 0x09,        //   Usage Page (Button)
0x19, 0x01,        //   Usage Minimum (Button 1)
0x29, 0x05,        //   Usage Maximum (Button 5)
0x15, 0x00,        //   Logical Minimum (0)
0x25, 0x01,        //   Logical Maximum (1)
0x95, 0x05,        //   Report Count (5)
0x75, 0x01,        //   Report Size (1)
0x81, 0x02,        //   Input (Data, Variable, Absolute) - 5 buttons, 1 bit each
0x95, 0x01,        //   Report Count (1)
0x75, 0x03,        //   Report Size (3)
0x81, 0x01,        //   Input (Constant) - 3-bit padding
0x05, 0x01,        //   Usage Page (Generic Desktop Controls)
0x09, 0x30,        //   Usage (X)
0x09, 0x31,        //   Usage (Y)
0x16, 0x00, 0x80,  //   Logical Minimum (-32768)
0x26, 0xFF, 0x7F,  //   Logical Maximum (32767)
0x75, 0x10,        //   Report Size (16)
0x95, 0x02,        //   Report Count (2)
0x81, 0x06,        //   Input (Data, Variable, Relative) - X and Y axes, 16 bits each
0x09, 0x38,        //   Usage (Wheel)
0x15, 0x81,        //   Logical Minimum (-127)
0x25, 0x7F,        //   Logical Maximum (127)
0x75, 0x08,        //   Report Size (8)
0x95, 0x01,        //   Report Count (1)
0x81, 0x06,        //   Input (Data, Variable, Relative) - Wheel, 8 bits
0x05, 0x0C,        //   Usage Page (Consumer)
0x0A, 0x38, 0x02,  //   Usage (AC Pan)
0x95, 0x01,        //   Report Count (1)
0x75, 0x08,        //   Report Size (8)
0x81, 0x06,        //   Input (Data, Variable, Relative) - AC Pan, 8 bits
0xC0               // End Collection

Yes it's the default Gamepad.ino example in the example directory of this repo. Directly built to an espressif esp32-c3

Newest Unity version with newest input system package and it throws the stack overflow error in the link in my issue above

I must admit I'm very surprised nobody encountered this issue yet. Weirdly it works fine in the windows gamepad inspector but you cannot develop for unity with it at all

QuiNz0r avatar Sep 16 '25 13:09 QuiNz0r

I definitely narrowed the issue down: it's the hat aka DPad. If I setHatCount to 1 it give me the error, if I set it to 0. and output report size is multiple of 8 it works fine but gets detected as Joystick (need gamepad detection for android)

It's definitely an issue with this library and the hat

QuiNz0r avatar Sep 16 '25 20:09 QuiNz0r

I made a PR - https://github.com/lemmingDev/ESP32-BLE-Gamepad/pull/293 to dump the HID descriptor at the start of the sketch with a build env. Should make for a little easier debugging. When I was looking at a general gamepad, I was wondering about the DPADs, but it was a little late, so I did not look further into this.

Is there an issue open with the Unity InputSystem, other than the community discussion?

Looking to see if I can track down a HID analyser, just to confirm all is good.

LeeNX avatar Sep 17 '25 07:09 LeeNX

I made a PR - https://github.com/lemmingDev/ESP32-BLE-Gamepad/pull/293 to dump the HID descriptor at the start of the sketch with a build env. Should make for a little easier debugging. When I was looking at a general gamepad, I was wondering about the DPADs, but it was a little late, so I did not look further into this.

Is there an issue open with the Unity InputSystem, other than the community discussion?

Looking to see if I can track down a HID analyser, just to confirm all is good.

Thanks any help is appreciated. Not that I know of, no.

However I noticed in the Unity documentation that all generic gamepads are considered joystick. Only Xbox controllers with known PId and layout are considered gamepad.

My goal is to make a esp ble gamepad that works on android and windows in an unity app that I also develop. I tried everything and many other forks I can't make it work >.<

QuiNz0r avatar Sep 17 '25 08:09 QuiNz0r

Thanks any help is appreciated. Not that I know of, no.

Welcome, it's an interesting problem.

However I noticed in the Unity documentation that all generic gamepads are considered joystick. Only Xbox controllers with known PId and layout are considered gamepad.

Then that might be a short coming of the Unity InputSystem, again, worth opening an issue with the Unity tool, that way it could be tracked and possible resolved.

You could try and use the XBox VID/PID in ESP32-BLE-Gamepad, but that could cause other problems.

Otherwise, https://github.com/Mystfit/ESP32-BLE-CompositeHID is the way to go, as it's meant to emulate the XBox controller.

My goal is to make a esp ble gamepad that works on android and windows in an unity app that I also develop. I tried everything and many other forks I can't make it work >.<

Sounds like an interesting project. Hopefully you will find a working solution and possible showcase.

LeeNX avatar Sep 17 '25 08:09 LeeNX

So I got it to work. It's not a reportsize issue.

You must set hatSize to 0 and map whatever controller or physical dpad you have to normal buttons.

Also be careful your ble broadcast information (devicename, version etc.) is short. If it's too long android will ignore your device before initially pairing.

Please add this info to the readme or the default gamepad example.

Out of the box it won't work with Unity and its input system as long as hatSize is not 0

QuiNz0r avatar Sep 17 '25 12:09 QuiNz0r

So I got it to work.

Congratulations! Well done for sticking with the problem and coming to a working solution.

It's not a reportsize issue.

Again, interesting ... Should open an issue for mis-reporting via the Unity Input System.

You must set hatSize to 0 and map whatever controller or physical dpad you have to normal buttons.

I was looking at other hatSize descriptions, and some odd devices are 4 nibbles, vs ESP32BLE-Gamepad at a full byte. I wonder if Unity is not processing with hard coded values. As Windows, Linux and Mac are happy with the current Hat setup, not sure anybody would investigate further.

Also be careful your ble broadcast information (devicename, version etc.) is short. If it's too long android will ignore your device before initially pairing.

I believe this is a known limitation of BLE advertising. I am not sure it's something that can be fixed in the library. I wonder if a warning could be emitted or something. Basically the BLE advertising is 31 bytes big including the headers (control data), which testings shows there is only really 28 bytes. I found this out while playing with different advertising setup - https://github.com/lemmingDev/ESP32-BLE-Gamepad/issues/266

Please add this info to the readme or the default gamepad example.

Welcome to make a PR with updates info, maybe in something like the TroubleShooting or something.

Out of the box it won't work with Unity and its input system as long as hatSize is not 0

I would think that Unity Input System should get an issue for this. Could even reference this issue. Adding a note to every sketch that has a Hat would seem the wrong way about resolving this oddity.

LeeNX avatar Sep 17 '25 14:09 LeeNX

Rabbit hole notification

Anybody looking to investigate further, might be able to start with the Unity Issue Tracker or even look in Unity-Technologies InputSystem Github repo

Though as noted above, this could be a rabbit hole!

LeeNX avatar Sep 17 '25 14:09 LeeNX

There are a few different ways hats can be reported to the OS, and this library has tried most of them over the years

I forget why we chose this current method. Perhaps for compatibility with other OS's to Windows.

Can't remember, it's been so long.

Current setup is using angle position, which Unity may not like

Logical Min (1) Logical Max (8) Physical Min (0) Physical Max (315) Unit (SI Rot : Ang Pos)

I could try changing it to a different method

lemmingDev avatar Sep 17 '25 21:09 lemmingDev

There are a few different ways hats can be reported to the OS, and this library has tried most of them over the years

I forget why we chose this current method. Perhaps for compatibility with other OS's to Windows.

Can't remember, it's been so long.

Current setup is using angle position, which Unity may not like

Logical Min (1) Logical Max (8) Physical Min (0) Physical Max (315) Unit (SI Rot : Ang Pos)

I could try changing it to a different method

Sure why not I can test. Or just download unity, create urp 3d project and open inputmansger and look at console output if it throws dpad error

QuiNz0r avatar Sep 17 '25 21:09 QuiNz0r

following the advice on this thread, I was getting the same gnarly input errors in unity (like weird StackOverflow exceptions).

I used a BleGamepadConfiguration to change my ble config to eliminate the hat, like so:

bleGamepadConfig.setHatSwitchCount(0);

And suddenly Unity is happy with it in the new input manager system.

some of the unity errors we saw:

Could not create a device for '{"vendorId":58626,"productId":43981,"usa... (HID)' (exception: System.StackOverflowException: The requested operation caused a stack overflow.
  at (wrapper managed-to-native) System.Object.__icall_wrapper_ves_icall_array_new_specific(intptr,int)
  at System.Array.Resize[T] (T[]& array, System.Int32 newSize) [0x00029] in <d6e80b37d98246a5859a00c653f9fdf3>:0 
  at UnityEngine.InputSystem.Layouts.InputDeviceBuilder.AddChildren (UnityEngine.InputSystem.InputDevice+ControlBitRangeNode& parent, UnityEngine.InputSystem.InputDevice+ControlBitRangeNode left, UnityEngine.InputSystem.InputDevice+ControlBitRangeNode right) [0x00020] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\Devices\InputDeviceBuilder.cs:1154 
  at UnityEngine.InputSystem.Layouts.InputDeviceBuilder.InsertControlBitRangeNode (UnityEngine.InputSystem.InputDevice+ControlBitRangeNode& parent, UnityEngine.InputSystem.InputControl control, System.Int32& controlIndiciesNextFreeIndex, System.UInt16 startOffset) [0x0002d] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\Devices\InputDeviceBuilder.cs:989 
Could not create a device for '{"vendorId":58626,"productId":43981,"usa... (HID)' (exception: System.InvalidOperationException: Cannot instantiate device layout 'Dpad' as child of '/E502-ABCD'; devices must be added at root
  at UnityEngine.InputSystem.Layouts.InputDeviceBuilder.InstantiateLayout (UnityEngine.InputSystem.Layouts.InputControlLayout layout, UnityEngine.InputSystem.Utilities.InternedString variants, UnityEngine.InputSystem.Utilities.InternedString name, UnityEngine.InputSystem.InputControl parent) [0x002ee] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\Devices\InputDeviceBuilder.cs:254 
  at UnityEngine.InputSystem.Layouts.InputDeviceBuilder.InstantiateLayout (UnityEngine.InputSystem.Utilities.InternedString layout, UnityEngine.InputSystem.Utilities.InternedString variants, UnityEngine.InputSystem.Utilities.InternedString name, UnityEngine.InputSystem.InputControl parent) [0x0000c] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\Devices\InputDeviceBuilder.cs:126 
  at UnityEngine.InputSystem.Layouts.InputDeviceBuilder.AddChildControl (UnityEngine.InputSystem.Layouts.InputControlLayout layout, UnityEngine.InputSystem.Utilities.InternedString variants, UnityEngine.InputSystem.InputControl parent, System.Boolean& haveChildrenUsingStateFromOtherControls, UnityEngine.InputSystem.Layouts.InputControlLayout+ControlItem controlItem, System.Int32 childIndex, System.String nameOverride) [0x00085] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\Devices\InputDeviceBuilder.cs:412 
  at UnityEngine.InputSystem.Layouts.InputDeviceBuilder.AddChildControls (UnityEngine.InputSystem.Layouts.InputControlLayout layout, UnityEngine.InputSystem.Utilities.InternedString variants, UnityEngine.InputSystem.InputControl parent, System.Boolean& haveChildrenUsingStateFromOtherControls) [0x001f6] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\Devices\InputDeviceBuilder.cs:350 
  at UnityEngine.InputSystem.Layouts.InputDeviceBuilder.InstantiateLayout (UnityEngine.InputSystem.Layouts.InputControlLayout layout, UnityEngine.InputSystem.Utilities.InternedString variants, UnityEngine.InputSystem.Utilities.InternedString name, UnityEngine.InputSystem.InputControl parent) [0x002a6] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\Devices\InputDeviceBuilder.cs:234 
  at UnityEngine.InputSystem.Layouts.InputDeviceBuilder.InstantiateLayout (UnityEngine.InputSystem.Utilities.InternedString layout, UnityEngine.InputSystem.Utilities.InternedString variants, UnityEngine.InputSystem.Utilities.InternedString name, UnityEngine.InputSystem.InputControl parent) [0x0000c] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\Devices\InputDeviceBuilder.cs:126 
  at UnityEngine.InputSystem.Layouts.InputDeviceBuilder.Setup (UnityEngine.InputSystem.Utilities.InternedString layout, UnityEngine.InputSystem.Utilities.InternedString variants, UnityEngine.InputSystem.Layouts.InputDeviceDescription deviceDescription) [0x0000b] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\Devices\InputDeviceBuilder.cs:52 
  at UnityEngine.InputSystem.InputDevice.Build[TDevice] (System.String layoutName, System.String layoutVariants, UnityEngine.InputSystem.Layouts.InputDeviceDescription deviceDescription, System.Boolean noPrecompiledLayouts) [0x0007b] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\Devices\InputDevice.cs:1017 
  at UnityEngine.InputSystem.InputManager.AddDevice (UnityEngine.InputSystem.Utilities.InternedString layout, System.Int32 deviceId, System.String deviceName, UnityEngine.InputSystem.Layouts.InputDeviceDescription deviceDescription, UnityEngine.InputSystem.InputDevice+DeviceFlags deviceFlags, UnityEngine.InputSystem.Utilities.InternedString variants) [0x00000] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\InputManager.cs:1181 
  at UnityEngine.InputSystem.InputManager.AddDevice (UnityEngine.InputSystem.Layouts.InputDeviceDescription description, System.Boolean throwIfNoLayoutFound, System.String deviceName, System.Int32 deviceId, UnityEngine.InputSystem.InputDevice+DeviceFlags deviceFlags) [0x00075] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\InputManager.cs:1344 
  at UnityEngine.InputSystem.InputManager.OnNativeDeviceDiscovered (System.Int32 deviceId, System.String deviceDescriptor) [0x000c9] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\InputManager.cs:2518 )
UnityEngine.InputSystem.InputManager:OnNativeDeviceDiscovered (int,string)
UnityEngineInternal.Input.NativeInputSystem:NotifyDeviceDiscovered (int,string)

Unity 6.0

hope that helps someone else WAY down the rabbit hole, as we were :)

maybe related: ? https://discussions.unity.com/t/custom-bluetooth-gamepad-not-recognized/1651504/5 https://discussions.unity.com/t/custom-inputdevice-fails-to-create-when-dpad-is-defined/945933/2 https://issuetracker.unity3d.com/issues/stack-overflow-exception-when-using-a-custom-bluetooth-controller-with-blegamepad-library-on-esp32 https://discussions.unity.com/t/getting-stack-overflow-error-with-new-input-system/774708

binary1230 avatar Oct 15 '25 04:10 binary1230

following the advice on this thread, I was getting the same gnarly input errors in unity (like weird StackOverflow exceptions).

I used a BleGamepadConfiguration to change my ble config to eliminate the hat, like so:

bleGamepadConfig.setHatSwitchCount(0);

And suddenly Unity is happy with it in the new input manager system.

some of the unity errors we saw:

Could not create a device for '{"vendorId":58626,"productId":43981,"usa... (HID)' (exception: System.StackOverflowException: The requested operation caused a stack overflow.
  at (wrapper managed-to-native) System.Object.__icall_wrapper_ves_icall_array_new_specific(intptr,int)
  at System.Array.Resize[T] (T[]& array, System.Int32 newSize) [0x00029] in <d6e80b37d98246a5859a00c653f9fdf3>:0 
  at UnityEngine.InputSystem.Layouts.InputDeviceBuilder.AddChildren (UnityEngine.InputSystem.InputDevice+ControlBitRangeNode& parent, UnityEngine.InputSystem.InputDevice+ControlBitRangeNode left, UnityEngine.InputSystem.InputDevice+ControlBitRangeNode right) [0x00020] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\Devices\InputDeviceBuilder.cs:1154 
  at UnityEngine.InputSystem.Layouts.InputDeviceBuilder.InsertControlBitRangeNode (UnityEngine.InputSystem.InputDevice+ControlBitRangeNode& parent, UnityEngine.InputSystem.InputControl control, System.Int32& controlIndiciesNextFreeIndex, System.UInt16 startOffset) [0x0002d] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\Devices\InputDeviceBuilder.cs:989 
Could not create a device for '{"vendorId":58626,"productId":43981,"usa... (HID)' (exception: System.InvalidOperationException: Cannot instantiate device layout 'Dpad' as child of '/E502-ABCD'; devices must be added at root
  at UnityEngine.InputSystem.Layouts.InputDeviceBuilder.InstantiateLayout (UnityEngine.InputSystem.Layouts.InputControlLayout layout, UnityEngine.InputSystem.Utilities.InternedString variants, UnityEngine.InputSystem.Utilities.InternedString name, UnityEngine.InputSystem.InputControl parent) [0x002ee] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\Devices\InputDeviceBuilder.cs:254 
  at UnityEngine.InputSystem.Layouts.InputDeviceBuilder.InstantiateLayout (UnityEngine.InputSystem.Utilities.InternedString layout, UnityEngine.InputSystem.Utilities.InternedString variants, UnityEngine.InputSystem.Utilities.InternedString name, UnityEngine.InputSystem.InputControl parent) [0x0000c] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\Devices\InputDeviceBuilder.cs:126 
  at UnityEngine.InputSystem.Layouts.InputDeviceBuilder.AddChildControl (UnityEngine.InputSystem.Layouts.InputControlLayout layout, UnityEngine.InputSystem.Utilities.InternedString variants, UnityEngine.InputSystem.InputControl parent, System.Boolean& haveChildrenUsingStateFromOtherControls, UnityEngine.InputSystem.Layouts.InputControlLayout+ControlItem controlItem, System.Int32 childIndex, System.String nameOverride) [0x00085] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\Devices\InputDeviceBuilder.cs:412 
  at UnityEngine.InputSystem.Layouts.InputDeviceBuilder.AddChildControls (UnityEngine.InputSystem.Layouts.InputControlLayout layout, UnityEngine.InputSystem.Utilities.InternedString variants, UnityEngine.InputSystem.InputControl parent, System.Boolean& haveChildrenUsingStateFromOtherControls) [0x001f6] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\Devices\InputDeviceBuilder.cs:350 
  at UnityEngine.InputSystem.Layouts.InputDeviceBuilder.InstantiateLayout (UnityEngine.InputSystem.Layouts.InputControlLayout layout, UnityEngine.InputSystem.Utilities.InternedString variants, UnityEngine.InputSystem.Utilities.InternedString name, UnityEngine.InputSystem.InputControl parent) [0x002a6] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\Devices\InputDeviceBuilder.cs:234 
  at UnityEngine.InputSystem.Layouts.InputDeviceBuilder.InstantiateLayout (UnityEngine.InputSystem.Utilities.InternedString layout, UnityEngine.InputSystem.Utilities.InternedString variants, UnityEngine.InputSystem.Utilities.InternedString name, UnityEngine.InputSystem.InputControl parent) [0x0000c] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\Devices\InputDeviceBuilder.cs:126 
  at UnityEngine.InputSystem.Layouts.InputDeviceBuilder.Setup (UnityEngine.InputSystem.Utilities.InternedString layout, UnityEngine.InputSystem.Utilities.InternedString variants, UnityEngine.InputSystem.Layouts.InputDeviceDescription deviceDescription) [0x0000b] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\Devices\InputDeviceBuilder.cs:52 
  at UnityEngine.InputSystem.InputDevice.Build[TDevice] (System.String layoutName, System.String layoutVariants, UnityEngine.InputSystem.Layouts.InputDeviceDescription deviceDescription, System.Boolean noPrecompiledLayouts) [0x0007b] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\Devices\InputDevice.cs:1017 
  at UnityEngine.InputSystem.InputManager.AddDevice (UnityEngine.InputSystem.Utilities.InternedString layout, System.Int32 deviceId, System.String deviceName, UnityEngine.InputSystem.Layouts.InputDeviceDescription deviceDescription, UnityEngine.InputSystem.InputDevice+DeviceFlags deviceFlags, UnityEngine.InputSystem.Utilities.InternedString variants) [0x00000] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\InputManager.cs:1181 
  at UnityEngine.InputSystem.InputManager.AddDevice (UnityEngine.InputSystem.Layouts.InputDeviceDescription description, System.Boolean throwIfNoLayoutFound, System.String deviceName, System.Int32 deviceId, UnityEngine.InputSystem.InputDevice+DeviceFlags deviceFlags) [0x00075] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\InputManager.cs:1344 
  at UnityEngine.InputSystem.InputManager.OnNativeDeviceDiscovered (System.Int32 deviceId, System.String deviceDescriptor) [0x000c9] in .\Library\PackageCache\com.unity.inputsystem@7fe8299111a7\InputSystem\InputManager.cs:2518 )
UnityEngine.InputSystem.InputManager:OnNativeDeviceDiscovered (int,string)
UnityEngineInternal.Input.NativeInputSystem:NotifyDeviceDiscovered (int,string)

Unity 6.0

hope that helps someone else WAY down the rabbit hole, as we were :)

maybe related: ? https://discussions.unity.com/t/custom-bluetooth-gamepad-not-recognized/1651504/5 https://discussions.unity.com/t/custom-inputdevice-fails-to-create-when-dpad-is-defined/945933/2 https://issuetracker.unity3d.com/issues/stack-overflow-exception-when-using-a-custom-bluetooth-controller-with-blegamepad-library-on-esp32 https://discussions.unity.com/t/getting-stack-overflow-error-with-new-input-system/774708

I continued to debug this bs for weeks and found out for me it was the OpenXR plugin overwriting dpad functionality internally and silently for xr controllers. I have a hack monobehavior to fix it if you want it I paste later

QuiNz0r avatar Oct 15 '25 05:10 QuiNz0r

We're using openXR too, so yeah I bet it's the same thing.

We're good for this project but, if you have a fix you don't mind sharing, I'm sure others digging down the rabbit hole would appreciate :)

Maybe gotta submit an upstream bug report to openXR somehow

binary1230 avatar Oct 15 '25 14:10 binary1230

So again this happens because of OpenXR overriding dpad functionality for whatever reason.

Fix (hacky, optimize it yourself):


void Update()
{
        if (InputSystem.GetNameOfBaseLayout("DPad") == "XRController")
        {
            FixOpenXRBidningOverride();
        }
}

void FixOpenXRBidningOverride()
{
        Debug.Log("Fixing OpenXR Binding Override");

        //Save a list of all added Devices
        List<InputDevice> addedDevices = new List<InputDevice>();

        foreach (InputDevice _device in InputSystem.devices)
        {
            if (_device.added == true)
            {
                addedDevices.Add(_device);
            }
        }

        InputSystem.RemoveLayout("DPad");
        InputSystem.RegisterLayout<UnityEngine.InputSystem.Controls.DpadControl>("DPad");

        //Re-add, reset, and make current all devices that were removed
        foreach (InputDevice _device in addedDevices)
        {
            if (_device.added == false)
            {
                InputSystem.AddDevice(_device);
                InputSystem.ResetDevice(_device);
                _device.MakeCurrent();
            }
        }
}

QuiNz0r avatar Oct 15 '25 14:10 QuiNz0r