我有一个可以循环工作的硬件。它配备了专有的软件工具,让用户可以通过 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,如下面的屏幕截图所示(来自链接页面):
这种方法的一个重要问题是需要实现 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/PcapngUtils和 https://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/