从C#调用HidP_GetButtonCaps例程时出错

问题描述 投票:2回答:2

我花了几个小时,但仍然不明白为什么在C#中使用Interop时,从Hid.dll调用HidP_GetButtonCaps例程失败(为什么)。>

我正在列出设备并尝试获取ButtonCaps等。但是,当调用HidP_GetButtonCaps(或HidP_GetValueCaps)时,extern函数将返回HIDP_STATUS_INVALID_REPORT_TYPE错误。而且我只是不明白...此例程中的报告类型参数是一个枚举值,它怎么会失败???

这里是一些代码摘录。我不会放所有东西,因为它很长。当然,如果需要提供更多详细信息,我将其添加。

代码中有注释“ // REMARK”,这是注释内容:-备注1:hidDevice对象参数来自另一种方法。我知道在调试模式下检查内容时,“ DevicePath”,“ preparsedData”和“ 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;
    }

外部方法:

    [DllImport("hid.dll", SetLastError = true)]
    [SecurityPermission(SecurityAction.Assert, Unrestricted = true)]
    static extern int HidP_GetButtonCaps([MarshalAs(UnmanagedType.U2)] HIDP_REPORT_TYPE ReportType, ref HIDP_BUTTON_CAPS[] ButtonCaps, ref ushort ButtonCapsLength, IntPtr PreparsedData);

方法调用:

    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#中使用Interop时,调用HidP_GetButtonCaps例程(从hid.dll)失败。我正在列出设备并尝试获取ButtonCaps等。 ...

interop dllimport hid
2个回答
1
投票

确定发现问题...经常是愚蠢的错误。


0
投票

我遇到了同样的例外。我认为在CLR中尝试通过联合将数据自动编组到结构时存在问题。也许。我写了自己的拆包方法,似乎已经解决了问题。

© www.soinside.com 2019 - 2024. All rights reserved.