使用C#进行通用HID访问 - 无法读取所有数据包

时间:2017-11-26 15:46:46

标签: c# wpf windows-10 hid

我有一个自定义HID设备(传感器)每1ms传输一次数据。

数据在PC上接收而不会丢失数据包,这通过使用USBlyzer分析USB流量来确认。我在C#中编写了一个简单的代码,使用WPF以1ms的更新速率读取Windows 10下的数据。每个数据包中都包含16位索引,以检查是否已收到所有数据包。调试信息显示程序在前5-10秒内读取所有数据包,有时会持续更长时间。但是,在许多情况下,在正确读取的第一秒后,更新速率下降,现在每隔5到10毫秒检测一次数据包。

应用程序优先级设置为高。重新启动HID初始化时,正常读取速度将在接下来的5到10秒内返回。

是否可以建议一种在不丢失单个数据包的情况下读取所有数据的方法?

下面我列出了代码示例:

// HID初始化:

    private async Task<Boolean> InitHid()
    {
        try
        {
            isHid = false;
            string hidDeviceSelector = HidDevice.GetDeviceSelector(usagePage, usageId, vendorId, productId);

              hidDeviceInformationCollection = await DeviceInformation.FindAllAsync(hidDeviceSelector);
            if (hidDeviceInformationCollection.Count > 0)
            {
                hidDevice = await HidDevice.FromIdAsync(hidDeviceInformationCollection.ElementAt(0).Id, FileAccessMode.ReadWrite);
                if (hidDevice != null)
                {
                    // construct a HID output report to send to the device
                    isHid = true;
                    Debug.WriteLine("InitHid ok");

                    if (!isRegInputReportEventsHid)
                    {
                        // Registration  Input Report Events from HID
                        hidDevice.InputReportReceived += HandleInputReportRecieved;
                        isRegInputReportEventsHid = true;
                    }

                }
            }
        }
        catch
        {
            isHid = false;
            Debug.WriteLine("InitHid false err");
        }
        return isHid;
    }

//接收数据和分析丢失数据包的主要代码:

private void HandleInputReportRecieved(
        HidDevice sender,
        HidInputReportReceivedEventArgs args)
    {
        HidInputReport inputReport = args.Report;
        IBuffer buffer = inputReport.Data;
        DataReader dr = DataReader.FromBuffer(buffer);
        byte[] bytes = new byte[inputReport.Data.Length];
        dr.ReadBytes(bytes);

        int diffSensor = (unt16)((uint)bytes[4] * 256 + (uint)bytes[5]);

        if (testhid != (diffSensor-1))
        {
            Debug.WriteLine("Testhid {0} difi {1}; ", testhid, diffSensor);
        }

        testhid = diffSensor;

    }

1 个答案:

答案 0 :(得分:0)

您在这里提到的库开始工作很棘手。您可能想看看使用Windows API。该API基本上是在基于事件的编程还不算什么的时候构建的,并且基于任务的异步模式还没有被充实。如果要使其正常运行,则基本上需要使用任务完成源来缩小差距,以基于任务的异步领域。我要做的是在阅读后创建一个新的TaskCompletionSource:

代码在这里:https://github.com/MelbourneDeveloper/Hid.Net/blob/master/Hid.Net.UWP/UWPHidDevice.cs

        public async Task<byte[]> ReadAsync()
        {
            if (_IsReading)
            {
                throw new Exception("Reentry");
            }

            lock (_Chunks)
            {
                if (_Chunks.Count > 0)
                {
                    var retVal = _Chunks[0];
                    Tracer?.Trace(false, retVal);
                    _Chunks.RemoveAt(0);
                    return retVal;
                }
            }

            _IsReading = true;
            _TaskCompletionSource = new TaskCompletionSource<byte[]>();
            return await _TaskCompletionSource.Task;
}

然后,当设备获得报告时,我在完成源上设置结果:

      private void _HidDevice_InputReportReceived(HidDevice sender, HidInputReportReceivedEventArgs args)
        {
            if (!_IsReading)
            {
                lock (_Chunks)
                {
                    var bytes = InputReportToBytes(args);
                    _Chunks.Add(bytes);
                }
            }
            else
            {
                var bytes = InputReportToBytes(args);

                _IsReading = false;

                _TaskCompletionSource.SetResult(bytes);
            }
}

但是,使用基本的Windows API更加容易,因为您可以简单地使用基于任务的异步调用它们,然后您的代码将在所有版本的Windows(不仅是Windows 10)上运行。Microsoft可能会在Windows 10中升级其Hid API。在某些时候,但是与此同时,他们的API很笨拙。

尝试一下: https://github.com/MelbourneDeveloper/Hid.Net/blob/master/Hid.Net/Windows/WindowsHIDDevice.cs