Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Generating gamepad layout from auto-generated HID layout

Discussion in 'Input System' started by Rene-Damm, Jul 13, 2018.

  1. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    This is a continuation from Input System Update. Just moved to separate thread.

    Ah I see. Hat switches are indeed not supported by the HID layout generator yet. The problem is that the HID spec doesn't specify how exactly the switch works. So it can be an enumeration (DualShocks do that, for example) or a bitfield (the XInput HID driver does that, for example). It's not super difficult to support the most common setups. Just needs a little more code than the axis and button code paths that are there ATM. I've added a TODO to the list and will bump it up in priority.

    There's
    Code (CSharp):
    1. HID.hidDescriptor
    .

    Hmm, not quite sure what's going on there. Looking at your code, it looks like it should work.

    BTW for this

    Code (CSharp):
    1. if (InputSystem.TryLoadLayout(device.layout).extendsLayout.Equals("HID"))
    2.  
    3. // An easier check is
    4. if (device is HID)
     
    MechEthan and eugene4552 like this.
  2. eugene4552

    eugene4552

    Joined:
    Jun 28, 2018
    Posts:
    4
    Thanks:)
    However, I discovered one more little problem: when I replug my gamepad, HID.hidDescriptor.elements array becomes null.

    Also I discovered that device.ReadValueAsObject() returns first 8 bytes from my keyboard. As far as I understood, this is because of the same value of currentStatePtr property (173669288 both for keyboard and gamepad)
    KeyboardMemAddress.png
    GamepadMemAddress.png

    After some digging I found the following code:

    Code (CSharp):
    1.  private unsafe DoubleBuffers SetUpDeviceToBufferMappings(InputDevice[] devices, ref IntPtr bufferPtr, uint sizePerBuffer, uint mappingTableSizePerBuffer)
    2.         {
    3.             var front = bufferPtr;
    4.             var back = new IntPtr(bufferPtr.ToInt64() + sizePerBuffer);
    5.             var mappings = (void**)new IntPtr(bufferPtr.ToInt64() + sizePerBuffer * 2).ToPointer();  // Put mapping table at end.
    6.             bufferPtr = new IntPtr(bufferPtr.ToInt64() + sizePerBuffer * 2 + mappingTableSizePerBuffer);
    7.  
    8.             var buffers = new DoubleBuffers {deviceToBufferMapping = mappings};
    9.  
    10.             for (var i = 0; i < devices.Length; ++i)
    11.             {
    12.                 var deviceIndex = devices[i].m_DeviceIndex;
    13.  
    14.                 buffers.SetFrontBuffer(deviceIndex, front);
    15.                 buffers.SetBackBuffer(deviceIndex, back);
    16.             }
    17.  
    18.             return buffers;
    19.         }
    It turns out that all devices' buffers start from the same memory address, right?

    (device is HID) looks more elegant, thanks