Use 3DConnexion™ SpaceMice in vvvv gamma via HID instead of their driver. Uses HidLibrary by Mike O’Brien.

Tested only with SpaceMouse Wireless®. Either connected through the Universal Receiver (PID C652) or via USB-cable (PID C62E).

But should work also with SpaceMouse Compact® (PID C635)

Will only work properly if the 3DConnexion driver isn’t active, so either uninstall or otherwise make sure it is not running (remove it from autostart for example).

Development sponsored by Studio JHH

To use latest version, install via nuget

nuget install VL.Devices.SpaceMouseHID


Hey, @devvvs the library this is based on uses tasks for reading reports from devices.
Using it in vvvv caused a lot of strange issues, like vvvv starting to compile but never finishing and crashes (I asked @Elias some time ago in the chat). I now got it to work somehow but would really appreciate some feedback if this implementation is “correct” and/or what could be improved.

could it be done like this?

i don’t have such a device and am unsure about some things (does it really need that blockcopy thing? all the isasigned checks) so i left them away because i can’t check them anyway. Also this doesn’t periodically retrigger or check if the device is connected.

so, this patch might be too naive and oversimplified. but i’d be interested if the general setup (all in the cache region) would work at all?

VL.Devices.SpaceMouseHID_sebl.vl (147.5 KB)

Hey @sebl; Just tried it, it does not work as should here.
Once the Cache region is triggered the device is opened and, I get some data now and then, but not as i expect.
Any wishes to test?

It’s a really fast way for converting. But you are right in this case it’s most likely overkill.

I had it go boom some times during development. Might not be needed now in its “finished state” but also doesn’t hurt I guess. The first one is also used to check if a device is connected or not. If not the thing periodically checks for a device.

Unfortunately it doesn’t. The ReadReportAsync task only runs once (when the device is used, e.g. you push a button), so the observable also only triggers once. That’s why I force the Cache with the On Data of the HoldLatest to create a new task, which runs for the next interaction and so on.

There is also a ReadReport callback (region) which gets executed when a report arrives.

I but I couldn’t figure out how to properly use it in VL. As soon as the region is used in the patch (and a device is connected) vvvv starts to behave strangely.

In the C# it’s something like this:

public bool OpenDevice()
    device = HidDevices.Enumerate(VendorId, ProductId).FirstOrDefault();

    if (device != null)

        device.MonitorDeviceEvents = true;


        return true;

     return false


private void OnReport(HidReport report)
    if (report.Data.Length >= 12)



The ParseTransforms doesn’t work, at least the values it returns are not correct.

As a sidenote (I think I mentioned this before recently) the whole async / reactive / observable / task stuff
is desperately in need of some good documentation. Same goes for resources / providers. All I had to go by were two forum posts by @robotanton .


true. it’s not possible to create that callback region…

maybe it works in 22.5?

Which options did you choose in the nodebrowser to get that node?
When selecting ReadReport and then Callback, I got that region in the screenshot posted above.

Ah, maybe we both have one part of the puzzle…
I clicked on ReadReport Node in category hiddevice and then choose the overload with the callback and the timeout

The Region I used has HIDDevice as input and it kind of works in a sense, it is executed when a Report arrives. But like I said before vvvv also starts to act up then. Whenever the patch is changed even slightly, like for example by moving a node, vvvv starts compiling (gray progress bar) and never finishes.