Sending data to custom HID device
I managed to implement the custom HID device in Unity Input System and I can read from it easily. But how to send data back to the HID device?
This is the IInputDeviceCommandInfo
implementation I have:
[StructLayout(LayoutKind.Explicit)]
internal struct MyControlCommand : IInputDeviceCommandInfo
{
public static FourCC Type { get { return new FourCC("HIDO"); } }
[FieldOffset(0)]
public byte res;
[FieldOffset(1)]
public byte magic;
[FieldOffset(2)]
public byte DataType;
[FieldOffset(3)]
public short Data;
public FourCC typeStatic
{
get { return Type; }
}
public static MyControlCommand Create(byte dataType, short data)
{
return new MyControlCommand
{
magic = 0x7e,
DataType = dataType,
Data = data
};
}
}
I wanted to send these bytes:
0x00
0x7e
0x04
0xfff
So I use:
var c = MyControlCommand.Create(0x04, 0xfff);
var res = current.ExecuteCommand(ref c);
but the res
variable is -1
(unsuccessful).
I managed to communicate with the device (above bytes worked fine) using HidSharp library and my own HID implementation, but Unity is stubborn...
Thanks for help!
Also - my device is sending data only if user interacts with it, presses button or rotates knob.
Answer by thewall37 · Feb 03 at 05:46 PM
Ok, that was not an easy problem to solve:
The problem was that IInputDeviceCommandInfo
does not force user to implement Field(0)
to be an InputDeviceCommand
. InputDeviceCommand
must be added at Field(0) offset and other fields must be shifted respectively.
The second problem was that my device required different size of the output data. OS probably checks if the sizes matches (the one reported by the descriptor in capabilities.outputReportSize
and the one actually to be sent).
So I have added missing fields in the struct and it works:
[StructLayout(LayoutKind.Explicit, Size = kSize)]
internal struct Command2 : IInputDeviceCommandInfo
{
public static FourCC Type => new FourCC('H', 'I', 'D', 'O');
public FourCC typeStatic => Type;
internal const int kSize = InputDeviceCommand.BaseCommandSize + 31; //<---- calculate manually
[FieldOffset(0)] public InputDeviceCommand baseCommand; // <--- required, overlaps the rest, that's the trick to avoid Marshalling struct to byte array, that I use
[FieldOffset(InputDeviceCommand.BaseCommandSize + 0)] public byte zero; // <--- don't know why
[FieldOffset(InputDeviceCommand.BaseCommandSize + 1)] public byte magic;
[FieldOffset(InputDeviceCommand.BaseCommandSize + 2)] public byte reportId;
[FieldOffset(InputDeviceCommand.BaseCommandSize + 3)] public short payload;
public static Command2 Create(byte id, short payload)
{
return new Command2
{
baseCommand = new InputDeviceCommand(Type, kSize),
magic = 0x7e,
reportId = id,
payload = payload
};
}
}
I hope someone will benefit from this.
Your answer
Follow this Question
Related Questions
XR Input: primary2DAxis always returns 0 1 Answer
XR Input: primary2DAxis always returns 0 1 Answer
C# cant find a class auto generated by unity 2 Answers
i need help making a dash ability for my endless runner game 2 Answers
how can i make device clock system using datetime and make life system? 0 Answers