I have a piece of hardware that works in cycles. It comes with a proprietary software tool that lets user control it from PC via USB. User defines how long each cycle is. At the beginning of each cycle the software tool rapidly issues a series of commands to the hardware via USB and then goes into the idle mode, awaiting next cycle.
There's a second piece of hardware that needs to be synched with the first one. Basically, when the aforementioned series of commands is issued to hardware #1, hardware #2 should do its thing too.
Hardware #2 comes with API and SDK and whatnot. Hardware #1 does not - there's only this tool where you can define how long your cycle will be.
In view of all this, it's been decided that the easiest way to achieve this will be by listening on USB port that hardware #1 uses so that each time traffic on it is detected hardware #2 is issued its directives too. I've used a monitoring app on hardware #1's USB port and its traffic looks pretty simple: it's a rapid and short succession of packets at the very beginning of a cycle and then nothing until the next cycle.
The idea is to write a small Windows-based utility app that will listen on hardware #1's USB port and issue an API call to hardware #2 every time it detects a cycle. Ideally, it should be a .NET app, cause I'm familiar it with the most, as far as writing Windows-code goes.
The difficult part is writing the code for listening on hardware #1's USB port. Also, I don't have access to hardware #1 at all times, so I use plain USB keyboard and mouse as its substitutes. At this point the goal is to simply detect traffic on keyboard or mouse USB ports.
So far I have attempted two libraries I found on the web - LibUsbDotNet and Usb.Net. I haven't been able to achieve the goal with either of the two.
I can't get Usb.Net to even read the packets...
And LibUsbDotNet seems to hijack the traffic - so if I type on a keyboard in a notepad or Word, letters don't appear there, while my app successfully reads the packets. Writing intercepted packets back to the port doesn't help.
Here's the code that I use with LibUsbDotNet. It's basically library's example, slightly modified to work with my keyboard.
// 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();
}
How do I modify this so that it doesn't intercept the packets but simply detects them while letting them pass through to their intended destination?
Any advice is welcome with either Usb.Net or LibUsbDotNet. Or, perhaps, a different library that better suits my needs?

Have you considered acting as a "man in the middle" (MitM) for the USB device?
From what you're saying, you can already consume the USB data, but that's it, the "signal" "dies" with your program. You might want to act as a virtual USB device for your device's software to connect to and pass along any data you get to that virtual USB device you set up. Saying this another way, your software acts as a bridge to pass all the data between the device and the device's driver/software, and you also use the data however you need.
The following answer asks how to do that. The accepted answer seems to not be actionable anymore, as the software is deprecated, but the Answer by Yaron Shani seems to still be updated as of 2 months ago.
How to emulate USB devices?
The full project is designed to be a virtual PC, but the link in the Answer goes directly to the USB emulation section.
https://github.com/qemu/qemu
https://github.com/qemu/qemu/tree/master/hw/usb
Relevant documentation for the USB emulation.
https://qemu.weilnetz.de/doc/qemu-doc.html#pcsys_005fusb
It seems like this is a command line utility, but I know there are ways to run command lines from C#. The below is an example of how to run the USB emulation from a command line.
https://station.eciton.net/qemu-usb-host-device-pass-through.html
And here's a SO Question that explains how to use command line commands with C#.
Run Command Prompt Commands
There could be a downside to this, or several in fact. If there's a time dependency (as in it needs millisecond or less response times) or there's encryption on the communication, you might be out of luck. The time delay might not matter with a keyboard, but if it's critical to the device or how the software works, you could be out of luck or see odd errors that are difficult to track down. Also, some software is designed to prevent virtual devices from being a MitM so data can't be stolen from it. You may also have issues with trying to get the device software to discover your emulated USB device instead of the real device.
This probably isn't what you'd hoped for in an answer, but since you don't have any other suggestions, I don't know what to tell you besides "Good luck!"