Я потратил часы и до сих пор не могу понять, почему вызов метода HidP_GetButtonCaps (из hid.dll) терпит неудачу при использовании Interop в C#.Ошибка при вызове процедуры HidP_GetButtonCaps с C#
Я перечисляю устройства и пытаюсь получить ButtonCaps и так далее. Но при вызове HidP_GetButtonCaps (или HidP_GetValueCaps) функция extern возвращает ошибку HIDP_STATUS_INVALID_REPORT_TYPE. И я просто не понимаю ... параметр типа отчета в этой подпрограмме - значение перечисления, как он может терпеть неудачу?
Вот несколько примеров кода. Я не стану все, потому что это долго. Конечно, если нужно добавить больше деталей, я добавлю.
В коде "// REMARK" есть комментарии: - Замечание 1: параметр объекта hidDevice исходит из другого метода. Я знаю, что содержимое полей «DevicePath», «prepsedData» и «ButtonCaps» корректно проверяется в режиме отладки. - Замечание 2: здесь у меня есть проблема. Я пробовал 3 разных способа аргумента: с объектом HIDP_REPORT_TYPE, непосредственно с HIDP_REPORT_TYPE.HidP_Input или «0», и это не имеет никакого значения ...
Большое спасибо за помощь.
структуры, константы, перечисления ...:
public enum HIDP_REPORT_TYPE : ushort
{
HidP_Input,
HidP_Output,
HidP_Feature
}
public struct ButtonCapsRange
{
public ushort UsageMin;
public ushort UsageMax;
public ushort StringMin;
public ushort StringMax;
public ushort DesignatorMin;
public ushort DesignatorMax;
public ushort DataIndexMin;
public ushort DataIndexMax;
}
public struct ButtonCapsNotRange
{
public ushort Usage;
public ushort Reserved1;
public ushort StringIndex;
public ushort Reserved2;
public ushort DesignatorIndex;
public ushort Reserved3;
public ushort DataIndex;
public ushort Reserved4;
}
[StructLayout(LayoutKind.Explicit)]
public struct HIDP_BUTTON_CAPS
{
[FieldOffset(0)]
public ushort UsagePage;
[FieldOffset(2)]
public byte ReportID;
[FieldOffset(3)]
public bool IsAlias;
[FieldOffset(4)]
public ushort BitField;
[FieldOffset(6)]
public ushort LinkCollection;
[FieldOffset(8)]
public ushort LinkUsage;
[FieldOffset(10)]
public ushort LinkUsagePage;
[FieldOffset(12)]
public bool IsRange;
[FieldOffset(13)]
public bool IsStringRange;
[FieldOffset(14)]
public bool IsDesignatorRange;
[FieldOffset(15)]
public bool IsAbsolute;
[FieldOffset(16)]
public uint[] Reserved;
[FieldOffset(16 + 10 * 4)]
public ButtonCapsRange Range;
[FieldOffset(16 + 10 * 4)]
public ButtonCapsNotRange NotRange;
}
public struct HID_DEVICE
{
public String DevicePath;
public IntPtr pHidDevice; // A file handle to the hid device.
public bool OpenedForRead;
public bool OpenedForWrite;
public bool OpenedOverlapped;
public bool OpenedExclusive;
public IntPtr Ppd; // The opaque parser info describing this device
public HIDP_CAPS Caps; // The Capabilities of this hid device.
public HIDD_ATTRIBUTES Attributes;
public byte[] pInputReportBuffer;
public HID_DATA[] InputData; // array of hid data structures
public ulong InputDataLength; // Num elements in this array.
public HIDP_BUTTON_CAPS[] pInputButtonCaps;
public HIDP_VALUE_CAPS[] pInputValueCaps;
public byte[] pOutputReportBuffer;
public HID_DATA[] pOutputData;
public ulong OutputDataLength;
public HIDP_BUTTON_CAPS[] pOutputButtonCaps;
public HIDP_VALUE_CAPS[] pOutputValueCaps;
public byte[] pFeatureReportBuffer;
public HID_DATA[] pFeatureData;
public ulong FeatureDataLength;
public HIDP_BUTTON_CAPS[] pFeatureButtonCaps;
public HIDP_VALUE_CAPS[] pFeatureValueCaps;
}
внешние методы:
вызова метода:
private static bool FillDeviceInfo(ref HID_DEVICE hidDevice)
{
//REMARK 1
ulong numValues;
ushort numCaps;
HIDP_BUTTON_CAPS[] buttonCaps;
HIDP_VALUE_CAPS[] valueCaps;
HID_DATA[] data;
ulong i;
ushort usage;
uint dataIdx;
hidDevice.pInputReportBuffer = new byte[hidDevice.Caps.InputReportByteLength];
buttonCaps = new HIDP_BUTTON_CAPS[hidDevice.Caps.NumberInputButtonCaps];
//for(int a=0;a<buttonCaps.Length ;a++)
// buttonCaps[a].Reserved = new uint[10];
hidDevice.pInputButtonCaps = buttonCaps;
valueCaps = new HIDP_VALUE_CAPS[hidDevice.Caps.NumberInputValueCaps];
hidDevice.pInputValueCaps = valueCaps;
numCaps = hidDevice.Caps.NumberInputButtonCaps;
if (numCaps > 0)
{
//REMARK 2
HIDP_REPORT_TYPE reportType = HIDP_REPORT_TYPE.HidP_Input;
int val = (HidP_GetButtonCaps(reportType, ref buttonCaps, ref numCaps, hidDevice.Ppd));
if (HIDP_STATUS_SUCCESS != val)
{
return false;
}
}
//other stuff and retur true at end
}
У вас есть рабочее приложение C#, читающее состояние геймпада? Я ищу, как сумасшедший, для альтернативы DirectInput, чтобы выполнить это, и эта тема тем ближе, когда я нашел решение. Необходимо включить этот файл «hid.dll» вместе с файлами приложения? Или это стандартная dll для Windows? –
Привет, вы можете просто сделать ссылку на dll. Например: [DllImport («hid.dll», SetLastError = true)] [SecurityPermission (SecurityAction.Assert, Unrestricted = true)] static extern void HidD_GetHidGuid (ref Guid guid); У меня нет рабочего приложения, читающего состояние геймпада, мое приложение считывает входные данные с сырым сенсорным экраном. Я могу поделиться им с вами, если это поможет. – Pierre