.net - 编写一个监听 USB 端口的小实用工具,需要建议

标签 .net usb libusbdotnet

我有一个可以循环工作的硬件。它配备了专有的软件工具,让用户可以通过 USB 从 PC 控制它。用户定义每个周期的长度。在每个周期开始时,软件工具通过USB快速向硬件发出一系列命令,然后进入空闲模式,等待下一个周期。

还有第二个硬件需要与第一个硬件同步。基本上,当向硬件 #1 发出上述一系列命令时,硬件 #2 也应该执行其操作。

硬件 #2 带有 API 和 SDK 等等。硬件 #1 没有 - 只有这个工具可以让您定义周期的长度。

鉴于这一切,我们决定实现这一目标的最简单方法是监听硬件 #1 使用的 USB 端口,以便每次检测到硬件 #2 上的流量时也会发出其指令。我在硬件 #1 的 USB 端口上使用了一个监控应用程序,其流量看起来非常简单:在一个周期开始时是快速而短暂的连续数据包,然后在下一个周期之前什么也没有。

这个想法是编写一个基于 Windows 的小型实用程序应用程序,该应用程序将监听硬件 #1 的 USB 端口,并在每次检测到周期时向硬件 #2 发出 API 调用。理想情况下,它应该是一个 .NET 应用程序,因为就编写 Windows 代码而言,我对它最熟悉。

困难的部分是编写用于监听硬件 #1 的 USB 端口的代码。另外,我无法始终访问硬件 #1,因此我使用普通 USB 键盘和鼠标作为替代品。此时的目标是简单地检测键盘或鼠标 USB 端口上的流量。

到目前为止,我已经尝试了在网络上找到的两个库 - LibUsbDotNet 和 Usb.Net。两者中的任何一个我都无法实现目标。

我什至无法让 Usb.Net 读取数据包...

LibUsbDotNet 似乎劫持了流量 - 因此,如果我在记事本或 Word 中的键盘上键入,字母不会出现在那里,而我的应用程序会成功读取数据包。将拦截的数据包写回到端口没有帮助。

这是我在 LibUsbDotNet 中使用的代码。它基本上是库的示例,稍作修改即可与我的键盘一起使用。

// 1118 = Vendor Id, 1872 = Product Id
UsbDeviceFinder MyUsbFinder = new UsbDeviceFinder(1118, 1872);

ErrorCode ec = ErrorCode.None;

try
{
    // Find and open the usb device.
    MyUsbDevice = UsbDevice.OpenUsbDevice(MyUsbFinder);

    // If the device is open and ready
    if (MyUsbDevice == null) throw new Exception("Device Not Found.");

    // If this is a "whole" usb device (libusb-win32, linux libusb-1.0)
    // it exposes an IUsbDevice interface. If not (WinUSB) the 
    // 'wholeUsbDevice' variable will be null indicating this is 
    // an interface of a device; it does not require or support 
    // configuration and interface selection.
    IUsbDevice wholeUsbDevice = MyUsbDevice as IUsbDevice;
    if (!ReferenceEquals(wholeUsbDevice, null))
    {
        // This is a "whole" USB device. Before it can be used, 
        // the desired configuration and interface must be selected.

        // Select config #1
        wholeUsbDevice.SetConfiguration(1);

        // Claim interface #0.
        wholeUsbDevice.ClaimInterface(0);
    }

    // open read endpoint 1.
    UsbEndpointReader reader = MyUsbDevice.OpenEndpointReader(ReadEndpointID.Ep01);

    // keyboard communicates in packets of size 8
    byte[] readBuffer = new byte[8];
    while (ec == ErrorCode.None)
    {
        int bytesRead;

        // If the device hasn't sent data in the last 5 seconds,
        // a timeout error (ec = IoTimedOut) will occur. 
        ec = reader.Read(readBuffer, 5000, out bytesRead);

        if (bytesRead == 0) throw new Exception(string.Format("{0}:No more bytes!", ec));
        Console.WriteLine("{0} bytes read", bytesRead);

        // Write that output to the console.
        foreach (byte b in readBuffer) Console.Write("{0} ", b);
        Console.WriteLine();
    }

    Console.WriteLine("\r\nDone!\r\n");
}
catch (Exception ex)
{
    Console.WriteLine();
    Console.WriteLine((ec != ErrorCode.None? ec + ":" : String.Empty) + ex.Message);
}
finally
{
    if (MyUsbDevice != null)
    {
        if (MyUsbDevice.IsOpen)
        {
            // If this is a "whole" usb device (libusb-win32, linux libusb-1.0)
            // it exposes an IUsbDevice interface. If not (WinUSB) the 
            // 'wholeUsbDevice' variable will be null indicating this is 
            // an interface of a device; it does not require or support 
            // configuration and interface selection.
            IUsbDevice wholeUsbDevice = MyUsbDevice as IUsbDevice;
            if (!ReferenceEquals(wholeUsbDevice, null))
            {
                // Release interface #0.
                wholeUsbDevice.ReleaseInterface(0);
            }

            MyUsbDevice.Close();
        }
        MyUsbDevice = null;

        // Free usb resources
        UsbDevice.Exit();

    }

    // Wait for user input..
    Console.ReadKey();
}

如何修改它,以便它不拦截数据包,而只是检测它们,同时让它们传递到预期目的地?

欢迎向 Usb.Net 或 LibUsbDotNet 提出任何建议。或者,也许,一个更适合我的需求的不同库?

最佳答案

USB 流量嗅探不如实际的端到端 USB 设备控制那么常见,因此可用于帮助完成此类事情的库数量有点少。您可能需要做一些调整以适应可用的选项。

一种简单的方法是 https://desowin.org/usbpcap/ :命令行版本可以实时输出到stdout,如下面的屏幕截图所示(来自链接页面):

screenshot

这种方法的一个重要问题是需要实现 Pcap 数据格式,我强烈怀疑您最终将不得不自己做,因为所有确实存在的 Pcap 解析实现(包括for .NET)都是针对(再次)更流行的使用 Pcap 捕获网络数据的案例场景。

但是,在你 panic 之前,我建议这是一个潜在可行的解决方案,因为整个格式文档似乎适合两个和一个小位 A4 页(我检查了打印预览:D):https://desowin.org/usbpcap/captureformat.html - 此外,官方 Pcap 格式引用位于 https://wiki.wireshark.org/Development/LibpcapFileFormat (由 USBPcap 站点链接)也明显不是特别密集。​​

您可以使用 USBPcap 从文件中输出测试数据,然后只需花时间迭代正确解析文件即可。

同样,您还可以访问设备并保存一些流量转储,以便以后按照您自己的节奏进行解析,我怀疑这可能非常实用。

我发现了几个(稍微有点腐烂的:))C# 链接,它们可能有助于帮助您编写自己的 Pcap 解析器:https://github.com/ryrychj/PcapngUtilshttps://formats.kaitai.io/pcap/csharp.html .


在搜索过程中,我还偶然发现了其他一些线索。

第一个是 https://sourceforge.net/projects/usbsnoop/ ,我发现它已移至 https://github.com/SnoopWare/usbsnoop/ 。这实际上非常有趣,因为它实现了自己的内核驱动程序来进行捕获。我很高兴我发现了这一点 - Server 2003 之前的 Windows 没有 USB 嗅探支持,但这可以追溯到 Windows 2000(当然还有最近的 Windows 10),了解这一点很有趣,即使只是琐事。 (我曾经想在设备和一些旧软件之间进行一些我自己的 USB 嗅探,并且认为 Win2K VM 将是最轻量级的方法,直到我了解了限制。)对于您的目的来说可能不太实用;前端 UI 似乎不支持记录到文件。

发生的另一件有趣的事情是发现 https://www.codeproject.com/Questions/204396/USB-Sniffer-protocol - 第 3 篇文章产生了投诉“你为什么要回答这个问题,这篇文章已经有两年了”,其中包含指向不再解析的域的链接。网络文件馆只有一份链接页面的副本,地址为 http://web.archive.org/web/20140127164835/www.tellmeword.com/dh9ic/usb_sniffer_(source_code) - 下载(镜像的)也被存档了!哈!我不知道它们是否有用,或者它们使用的技术是否已被弃用等等。

虽然我认为以上都是 C 语言。

关于.net - 编写一个监听 USB 端口的小实用工具,需要建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57295661/

相关文章:

objective-c - 连接特定 USB 设备时自动打开 OS X 应用程序

terminal - 如何从要在 VM 中使用的 mac 中弹出 USB 设备(无图标)

c# - 使用ASP.NET Core的跨平台USB通信

c/libusb-0.1 : why is usb_release_interface() failing?

c# - LibUSBDotNet:使用 USB 设备一段时间后出现奇怪的错误

c# - 具有 WPF ListView 的 MouseOver 大纲

c# - 如果打开它们的应用程序崩溃,打开的 DDE channel 会发生什么情况?

.net - 奇怪的反序列化错误,子对象没有完全反序列化

.net - 如何调试具有使用app.config文件的.net互操作项目的VB6项目?

c++ - 如何让 C++ 从 USB 端口(如串行端口)执行 I/O