HidD_SetFeature() 效果很好,HidD_GetFeature() 因 ERROR_CRC (23) 而失败。啥可能导致这种情况?

Posted

技术标签:

【中文标题】HidD_SetFeature() 效果很好,HidD_GetFeature() 因 ERROR_CRC (23) 而失败。啥可能导致这种情况?【英文标题】:HidD_SetFeature() works great, HidD_GetFeature() fails with ERROR_CRC (23). What could cause this?HidD_SetFeature() 效果很好,HidD_GetFeature() 因 ERROR_CRC (23) 而失败。什么可能导致这种情况? 【发布时间】:2012-11-19 03:28:37 【问题描述】:

我正在开发一个 USB 设备作为标准 HID 键盘,并在报告描述符中添加了一个 8 字节的功能报告;我正在编写一个主机应用程序来配置设备。我正在尝试调整精彩的 HidLibrary 以利用 hid.dll 中的 HidD_GetFeature() 函数。

在我开始发布 c# 代码之前,我会说我已经使用 SimpleHidWrite 实用程序以及 Get 和 Set Feature 命令成功地测试了我的固件,所以我相当有信心这不是问题。

封装在 HidLibrary API 中的 HidD_SetFeature() 函数运行良好。我可以向设备写入 8 个字节,并且我已经使用 SimpleHidWrite 工具验证了它们是否存储正确。但是,我无法使用 HidD_GetFeature() 将这些字节拉回,我不知道为什么。

以下是我认为相关的细节。

首先,带有值的库中内置的 CreateFile 调用:

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    internal static IntPtr CreateFile(
        string lpFileName,
        uint dwDesiredAccess,
        int dwShareMode,
        ref HidLibrary.NativeMethods.SECURITY_ATTRIBUTES lpSecurityAttributes,
        int dwCreationDisposition,
        int dwFlagsAndAttributes,
        int hTemplateFile);

在哪里(使用测试 vid/pid):

lpFileName = "\\?\hid#vid_03eb&pid_2042#7&1fef463f&0&0000#4d1e55b2-f16f-11cf-88cb-001111000030"
dwDesiredAccess = 0
dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE (0x01 | 0x02)
lpSecurityAttributes =  bInheritHandle = true, lpSecurityDescriptor = 0, nLength = 12 
dwCreationDisposition = OPEN_EXISTING (3)
dwFlagsAndAttributes = 0
hTemplateFile = 0

导入定义:

[DllImport("hid.dll", SetLastError = true)]
    static internal extern bool HidD_GetFeature(IntPtr hidDeviceObject, ref byte[] lpReportBuffer, int reportBufferLength);

最后,我正在创建的 API 方法当前在 HidD_GetFeature() 调用中失败,错误为 23 (ERROR_CRC):

    public bool ReadFeatureData(byte reportId, out byte[] data)
    
        if (_deviceCapabilities.FeatureReportByteLength <= 0)
        
            data = new byte[0];
            return false;
        
        // FeatureReportByteLength returns 9 (byte 0 is the report id and 8 bytes for the actual report length)
        data = new byte[_deviceCapabilities.FeatureReportByteLength];

        //yields a 9-byte array
        var buffer = this.CreateFeatureInputBuffer(); 
        buffer[0] = reportId;

        IntPtr hidHandle = IntPtr.Zero;
        bool success = false;
        try
        
            // Performs the CreateFile call above resulting in an IntPtr handle
            hidHandle = OpenDeviceIO(_devicePath, NativeMethods.ACCESS_NONE);

            success = NativeMethods.HidD_GetFeature(hidHandle, ref buffer, buffer.Length);
            // at this point, success is false, and buffer has gone from 9 bytes to 1

            if(success)
            
                Array.Copy(buffer, 0, data, 0, Math.Min(data.Length, _deviceCapabilities.FeatureReportByteLength));
            
            else
            
                //Yes, i know casting to a byte isn't good here; it's dirty but helping me debug for now
                data[0] = (byte)Marshal.GetLastWin32Error(); //returns 23 (verified, actual) - ERROR_CRC
            

        
        catch (Exception exception)
        
            throw new Exception(string.Format("Error accessing HID device '0'.", _devicePath), exception);
        
        finally
        
            if (hidHandle != IntPtr.Zero)
                CloseDeviceIO(hidHandle);
        

        return success;
    

我了解到在使用键盘和鼠标等系统设备时存在一些问题,这些问题可能会或可能不会在此处播放,但是我知道可以按照我尝试的方式与设备进行交互,因为我可以使用 SimpleHidWrite 做到这一点。也就是说,我没有排除任何可能性,欢迎任何想法。

如果我需要提供更多信息,请告诉我。

【问题讨论】:

【参考方案1】:

我认为这个声明可能是问题所在。

[DllImport("hid.dll", SetLastError = true)]
    static internal extern bool HidD_GetFeature(IntPtr hidDeviceObject, ref byte[] lpReportBuffer, int reportBufferLength);

尝试将 lpReportBuffer ref 参数更改为 out,或完全省略它。

【讨论】:

ref 更改为out 不起作用,但简单地省略它就可以了。谢谢!【参考方案2】:

是的,您的声明是问题所在。

使用:

    [DllImport("hid.dll", SetLastError = true)]
    protected static extern bool HidD_GetFeature(   IntPtr hDevInfo,
                                                    Byte[] lpReportBuffer, 
                                                    Int32 ReportBufferLength);

否:参考或输出

【讨论】:

以上是关于HidD_SetFeature() 效果很好,HidD_GetFeature() 因 ERROR_CRC (23) 而失败。啥可能导致这种情况?的主要内容,如果未能解决你的问题,请参考以下文章

无法挂钩回调函数?

Hi-C文库制备的连接酶连接效果

什么是 Hi/Lo 算法?

hihocoder 1513 小Hi的烦恼——bitset

3.8 tkinter 事件绑定的参数传递

清理垃圾