1 Attachment(s)
HID Nintendo Joy-Con gyro state
Hello everyone, I am adding Joy-Con support to my application and need some help.
I'm trying supplement my Xinput class directly, rather than use an emulation layer from HID to Xinput.
So far, I am able to get the first six bits from the report and determine the buttons being pressed.
It might be a challenge to read reports from both left and right joycons. I haven't figured that out how to do that smoothly yet. ???
Does anyone know if it is possible to get the gyro state from the report?
I can't find any documentation about this.
I created a Github repository for the project since I didn't see anything good there for HID in VB6.
https://github.com/WindowStations/HID-JoyCon-VB6
Re: HID Nintendo Joy-Con gyro state
Is the existing code working or....? Is there example of how to get what you want in any other language? I see there are HID Usages for gyros.
This looks wrong to me, for instance:
Code:
Private Sub GetDeviceCapabilities()
Dim ppData(29) As Byte
Dim ppDataString As Variant
Result = apiHidD_GetPreparsedData(HIDHandle, PreparsedData) 'Preparsed Data is a pointer to a routine-allocated buffer.
Result = apiRtlMoveMemory(ppData(0), PreparsedData, 30) 'Copy the data at PreparsedData into a byte array.
It returns PHIDP_PREPARSED_DATA *PreparsedData and your RtlMoveMemory def is As Any; so shouldn't it be apiRtlMoveMemory(ppData(0), ByVal PreparsedData,?
Btw if it helps, WinDevLib has everything from hidclass.h, hidusage.h, hidpi.h, and hidsdi.h... https://github.com/fafalone/WinDevLi.../wdAPIHID.twin
So rather than translating the APIs from scratch you just need to remove 'PtrSafe'.
Re: HID Nintendo Joy-Con gyro state
Thanks Fafalone! The existing HID sample goes all the way back to 1999-2005. It didn't work on Windows 11, until I kept the subscripts from being out of range etc.
GetDeviceCapabilities worked though. I haven't cleaned up the parameters yet.
I found a project on github that seems to read the gyro, but it had bugs. https://github.com/tomayac/joy-con-w.../src/joycon.js
I think I need to handshake with the device first. I was reading about the protocol Nintendo uses to communicate 1, 10, and 80 typically. If I send bit 1 to the first in the buffer, I get all sorts of data back, but I have no idea what it means without some reverse engineering it. I may have to create a vb.net dll to access and expose this better.
Thanks, I will check out your reference.
Re: HID Nintendo Joy-Con gyro state
There are some changes in the declarations of wdAPIHID.twin, for instance HIDP_VALUE_CAPS. I don't know if this is easily portable without knowing more. The function names are helpful. Thank you.
I did find a github that seems to indicate the need for a handshake, plus some additional command to enable accelerometer and gyroscope. By default, gyro-accel data is not sent in the report.
The purpose of this update is that it will help people with accessibility needs to interact with their computer. The Joy-Cons are very light, and they have a long battery life to stay on like a mouse device.
Re: HID Nintendo Joy-Con gyro state
Double-checked and my version of value caps is right; compared size and offsets vs a C++ scratch program's known-good values. The biggest issue is it's very, very easy to get confused with C/C++ Windows boolean types. BOOL is indeed 4-bytes, but BOOLEAN is actually a one-byte type: if you use 'Go to definition' on the header, you find it defined in winnt.h: typedef BYTE BOOLEAN; . There's also VARIANT_BOOL, which is the only one equivalent to VB6 Boolean; a 2-byte type. You're also missing ULONG UnitsExp; and ULONG Units; after the 5 Reserved2 integers.
And again with GetCapabilities... it works as in doesn't crash, or works as in you've verified the data is correct and not just a 4-byte address followed by random memory contents? (Or the right data but with the 4-byte address prepended, throwing alignment off?).
I don't have that hardware to play around with, but I'll look around for a C or C++ example of using HiD APIs for this-- those will be the most easily ported to VB6. DeviceIoControl-based solutions would also work.
Re: HID Nintendo Joy-Con gyro state
Ah yes, that makes sense, this sample was using the 1998 DDK. That particular type HIDP_VALUE_CAPS is not being used in the sample, so it may not be right, or just an older declaration. I'm curious to know the conversions/updates though. I appreciate your help and pointing me to the right spots.
I will have more time this weekend to flush this out. I got an output from that Getcapabilities function, but it maybe not all correct as you suggested.
I did receive data back from the device after writing a report, but I want to make sure the Getcapabilities function is returning correctly first before going too deep. Some of this challenge may be Nintendo specific, requiring the proper command to initiate the gyro and accel return.
Thanks!
Re: HID Nintendo Joy-Con gyro state
Checked the 98 DDK; it hasn't changed; there it's in SRC_HID_INC_HIDPI.H
Interested to follow your progress on this, be sure to keep us updated with what you find. The HiD APIs seem very complicated and unfriendly.
Re: HID Nintendo Joy-Con gyro state
Confirmed, there must be some kind of error in that type's declaration. I tracked down the original author Jan Axelson of Lakeview Research and found a few errors reported online in relation to this type and function. It is also never used in the samples associated with her book's digital section.
It's similar to the structure found in the vb.net sample, as if perhaps it was merely converted.
Code:
Friend Structure HidP_Value_Caps_NET
Friend UsagePage As Int16
Friend ReportID As Byte
Friend IsAlias As Int32
Friend BitField As Int16
Friend LinkCollection As Int16
Friend LinkUsage As Int16
Friend LinkUsagePage As Int16
Friend IsRange As Int32
Friend IsStringRange As Int32
Friend IsDesignatorRange As Int32
Friend IsAbsolute As Int32
Friend HasNull As Int32
Friend Reserved As Byte
Friend BitSize As Int16
Friend ReportCount As Int16
Friend Reserved2 As Int16
Friend Reserved3 As Int16
Friend Reserved4 As Int16
Friend Reserved5 As Int16
Friend Reserved6 As Int16
Friend LogicalMin As Int32
Friend LogicalMax As Int32
Friend PhysicalMin As Int32
Friend PhysicalMax As Int32
Friend UsageMin As Int16
Friend UsageMax As Int16
Friend StringMin As Int16
Friend StringMax As Int16
Friend DesignatorMin As Int16
Friend DesignatorMax As Int16
Friend DataIndexMin As Int16
Friend DataIndexMax As Int16
End Structure
Code:
Private Type HIDP_VALUE_CAPS
UsagePage As Integer
ReportID As Byte
IsAlias As Long
BitField As Integer
LinkCollection As Integer
LinkUsage As Integer
LinkUsagePage As Integer
IsRange As Long 'If IsRange is false, UsageMin is the Usage and UsageMax is unused.
IsStringRange As Long 'If IsStringRange is false, StringMin is the string index and StringMax is unused.
IsDesignatorRange As Long 'If IsDesignatorRange is false, DesignatorMin is the designator index and DesignatorMax is unused.
IsAbsolute As Long
HasNull As Long
Reserved As Byte
BitSize As Integer
ReportCount As Integer
Reserved2 As Integer
Reserved3 As Integer
Reserved4 As Integer
Reserved5 As Integer
Reserved6 As Integer
LogicalMin As Long
LogicalMax As Long
PhysicalMin As Long
PhysicalMax As Long
UsageMin As Integer
UsageMax As Integer
StringMin As Integer
StringMax As Integer
DesignatorMin As Integer
DesignatorMax As Integer
DataIndexMin As Integer
DataIndexMax As Integer
End Type
fafalone, there are more sample versions in C++ (6), and C# (05-12) with more of the functions shown, if you want to take a look.
http://www.janaxelson.com/hidpage.htm
Re: HID Nintendo Joy-Con gyro state
If you mix bytes with integers and longs in a type declaration there's gonna be a lot of padding in there. If your API functions expect a contiguous structure then you should put it all in a byte array.
Re: HID Nintendo Joy-Con gyro state
Thanks VanGoghGaming! I do remember that. These API are very particular. I'm having trouble with the declarations that faf referenced too.
Although, I've made lot's of progress and even started mapping out some of the commands a bit. I was reading that bluetooth was hard if not impossible to initiate the rumble function, but I can say that is not the case. I was not able to figure out the full handshake yet, but I used another program to initiate the handshake first. Only then certain commands are recognized by the application calling. A partial handshake is done by sending two writes sequentially. The order doesn't matter, but if involves 3, and 4 as the final bit of the commands written. The JoyCons can be individually disconnected with a final bit of 6, but you may then have to remove the JoyCon from Bluetooth if it becomes unresponsive. Yay. Then you have the pleasure of re-pairing your JoyCons once again. Fun.
VanGoghGaming, do you know of any good modules or code samples for interfacing with HID? VB6, VB.NET, or C# if possible. Thanks
Re: HID Nintendo Joy-Con gyro state
Quote:
Originally Posted by
VanGoghGaming
If you mix bytes with integers and longs in a type declaration there's gonna be a lot of padding in there. If your API functions expect a contiguous structure then you should put it all in a byte array.
Thanks, everything works correctly now! I finally got the 6-axis data from the JoyCons. Do you have any experience with device input code for games in VB6?
This code should work well with my 3D desktop interface.
1 Attachment(s)
Re: HID Nintendo Joy-Con gyro state
Updates to the HID sample:
1. Both JoyCons reporting smoothly without hanging the main UI.
2. IMU 6-axis report data can now be accessed.
3. Various modes and commands can be invoked with the write report function.
4. NFC/IR mode is also available, but I have not figured out how the data format is reporting.
The sample may be modified to interface with other HID devices, provided the Vendor Id and the Product Id is known.
EDIT bug fixed in detach