我有一个可以循环工作的硬件。它配备了专有的软件工具,让用户可以通过 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 提出任何建议。或者,也许有一个更适合我需求的不同库?