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

Unify layouts #37

Open
krisrok opened this issue Aug 23, 2021 · 18 comments
Open

Unify layouts #37

krisrok opened this issue Aug 23, 2021 · 18 comments

Comments

@krisrok
Copy link

krisrok commented Aug 23, 2021

Let's try to identify layouts (omitting buttons):

  • 2SS (SpaceNavigatorHID)
    • tested by me (and presumably @PatHightree ?) using SpaceNavigator Compact, VID: 0x256f, PID: 0xc635
    • 2 reports:
      • report id 1 = translation XZY
      • report id 2 = rotation XZY
      • Z and Y swapped both times
  • 1S (SpaceNavigatorWirelessHID and SpaceNavigatorEnterpriseHID)
    • is wireless tested? enterprised tested by @JiapengChi (hardware ids outstanding).
    • 1 report:
      • report id 1 = translation XZY and rotation XYZ
      • Z and Y swapped for translation only
  • 1SS (forked SpaceNavigatorWirelessHID)
    • tested by two colleagues of mine (one of which is @ThomasRiml) using Universal Receiver, VID: 0x256f, PID: 0xc652
    • 1 report:
      • report id 1 = translation XZY and rotation XZY
      • Z and Y swapped both times

I've named them using report count (1/2) and if both parts are swapped (SS) or just one (S).

Interestingly, other implemenations do not have such distinctions regarding axis order, e.g. in FreeGLUT nor in FreeCAD.

@PatHightree
Copy link
Owner

As this data is going to to be subject to change, I think it might be better to put it on a wiki page instead

@krisrok
Copy link
Author

krisrok commented Aug 23, 2021

Valid point. Another layout (like a table) would be great too, but for now: https://github.com/PatHightree/SpaceNavigator/wiki/Layout-differences

Could you please add your IDs and what you've tested?

Let's keep it this issue here for now as we need some place to discuss going forward. What really baffles me is the other applications' implementations. They are so straightforward. I wonder how they behave with all those different devices though.

@PatHightree
Copy link
Owner

I had no knowledge of those implementations, it looks like those are full applications, not plugins.
That means they have access to the windows message pump, which is another (more conventional) mechanism for 3dconnexion to deliver its navigation data to apps. This probably means that the device differences are abstracted away.

@krisrok
Copy link
Author

krisrok commented Aug 23, 2021

At least the GLUT one uses HID input as well. I stumbled upon this implementation via this project's wiki.
Also, dropping the VIDs and PIDs into google yields some results :)

About the resource I just linked i wanted to add: At least the SpaceMouse Compact info there seems to be incorrect, i have the exact same one (judging by VID and PID) but I receive 2 reports not just the 1 containing both translation and rotation.
So, as usual, you have to use this info gathered on this wiki with a grain of salt but it has some great pointers.

@krisrok
Copy link
Author

krisrok commented Aug 23, 2021

This python implementation also uses the same layout for all supported devices: Translation XYZ, Rotation XZY (Pitch Roll Yaw)...
Even for models that have different layouts in our codebase. But again, I wonder how that works out in reality. Maybe there is some mapping in another layer on top of that (like a config).

@krisrok
Copy link
Author

krisrok commented Aug 24, 2021

Thanks for reworking the wiki page.

I've added a separate section for the Universal Receiver because it might be a special beast. Please see open questions.

We just need more input about the devices from different sources. @JiapengChi please chime in :)

@PatHightree
Copy link
Owner

I made a post on the 3dconnexion forum, asking outright for the HID details of the different hardware variations
The post is waiting for review (I lost my old login) I'll link it here when it gets posted.

@PatHightree
Copy link
Owner

Here's the thread https://forum.3dconnexion.com/viewtopic.php?f=19&t=40919

Got a very interesting reply, it might very well be possible to read the data layout from the device at runtime and interpret the data accordingly. A sample implementation is forthcoming.

@krisrok
Copy link
Author

krisrok commented Aug 24, 2021

Wow, ok. That's interesting indeed!

Just had a longer look at InputDevice.description.capabilities and it seems to contain everything we need. Why didn't we notice before?!
The capabilities even get displayed nicely formatted through InputDebugger->Device->HID Descriptor. There you can see the correct usages, e.g. Element 2's usage is "0x32 (Z)", so this is Translation.Z. Great!
This in turn means InputSystem comes with a HIDParser and such to decipher the usages etc, see here: InputSystem\Plugins\HID\HIDParser.cs

Those classes are internal though, but we could copy the bits we need or try and use reflection to get a nicely parsed HID descriptor object.

@krisrok
Copy link
Author

krisrok commented Aug 24, 2021

Ok I guess it works all without internal APIs. Here's a quick test adopted from HIDDescriptorWindow:

var descriptor = HIDDeviceDescriptor.FromJson(device.description.capabilities);
foreach(var element in descriptor.elements)
{
    string usagePageString = HID.UsagePageToString(element.usagePage);
    string usageString = HID.UsageToString(element.usagePage, element.usage);

    Debug.Log(string.Format("Usage Page: 0x{0:X} ({1})", (uint)element.usagePage, usagePageString));
    if (usageString != null)
        Debug.Log(string.Format("Usage: 0x{0:X} ({1})", element.usage, usageString));
    else
        Debug.Log(string.Format("Usage: 0x{0:X}", element.usage));
}

The usage combined with other element info about reportId, offset and size should be enough to piece a layout together at runtime I think.

@JiapengChi
Copy link
Contributor

@krisrok Sorry for replying late.

The SpaceMouses I am using are the following:
SpaceMouse Wireless and SpaceMouse Enterprise

The Enterprise one can only work with wire, and the wireless one comes with a receiver, which I am not sure is a universal receiver or not.

The pull request #34 is to fix the bugs with the two devices above, I am not sure that it can work well with the previous generation products. What kind of SpaceMouse you are using?

For the Y axis, could you point out that which part of the code you have questions about?

Thanks!

@JiapengChi
Copy link
Contributor

Thanks for reworking the wiki page.

I've added a separate section for the Universal Receiver because it might be a special beast. Please see open questions.

We just need more input about the devices from different sources. @JiapengChi please chime in :)

I will add the information later.

@PatHightree
Copy link
Owner

@JiapengChi Thanks, it would be great if you can you add your device info to the table on this page
https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/manual/Layouts.html#layout-builders

@krisrok Great work!
It's a shame that I used the attributes approach to configure the data layout in the driver, which is totally non-flexible.
I think the solution is to use the LayoutBuilder api to create the data layout by script.
As described over here https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/manual/Layouts.html#layout-builders

@krisrok
Copy link
Author

krisrok commented Aug 24, 2021

I think the solution is to use the LayoutBuilder api to create the data layout by script.

Yep, I just finished reading up on that, too! 👍

@krisrok
Copy link
Author

krisrok commented Aug 24, 2021

Here‘s outlined what should work for us:
https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/api/UnityEngine.InputSystem.InputSystem.html#UnityEngine_InputSystem_InputSystem_onFindLayoutForDevice

Be sure to read the whole thing though, it has some caveats.

@krisrok
Copy link
Author

krisrok commented Aug 25, 2021

"Some caveats" does not do justice at all. I've tried to implement this beast but one blocker follows the next. Here's an outline of it so far:
https://forum.unity.com/threads/onfindlayoutfordevice-for-auto-assigned-layouts.1161377/

@PatHightree
Copy link
Owner

One of the mods at 3dconnexion forum sent me a c++ example of how HID api can be used to interpret the HID descriptor.
Might come in handy if the layout builder is too uncooperative.
HIDTest_descriptor_reader.zip

This was referenced Aug 31, 2024
@PatHightree
Copy link
Owner

Update:
I recently found out that @krisrok has implemented constructing dynamic layouts based on HID descriptors.
His code has been pulled into this repo on the unify_layouts_2 branch and I'll work on integrating it and hopefully it can become the foundation of the driver.
However, there is a caveat, the universal wireless receiver is not supported. I don't expect it to be supported in the future either because it's technical complexity and the fact that I don't have a wireless device to develop/test with.

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

No branches or pull requests

3 participants