using System.Reactive.Subjects; using HidLibrary; namespace HidSliders.Hid { public class HidInterface { private IHidDevice? _device; private Subject _sliderUpdate = new(); private Subject> _buttonsUpdate = new(); public IObservable SliderObservable => _sliderUpdate; public IObservable> ButtonsObservable => _buttonsUpdate; public bool ConnectDevice(int vendorId, int devId) { var enumerator = new HidEnumerator(); IEnumerable hidDevices = enumerator.Enumerate(vendorId, [devId]); _device = hidDevices.FirstOrDefault(); if (_device is { IsConnected: true }) { _device.OpenDevice(); _device.MonitorDeviceEvents = true; _device.ReadReport(OnReport); _device.Removed += DeviceOnRemoved; _device.Inserted += DeviceOnInserted; } return _device?.IsConnected ?? false; } private void DeviceOnInserted() { _sliderUpdate = new Subject(); _buttonsUpdate = new Subject>(); } private void DeviceOnRemoved() { _sliderUpdate.OnCompleted(); _buttonsUpdate.OnCompleted(); } private void ReadSliders(byte[] reportSliderBytes) { var reportChunk = new byte[4]; var sliderValues = new int[5]; for (int i = 0; i < 5; i++) { Array.Copy(reportSliderBytes, i * 2, reportChunk, 0, 2); sliderValues[i] = BitConverter.ToInt32(reportChunk); } _sliderUpdate.OnNext(sliderValues); } private void ReadButtons(byte[] reportButtonBytes) { if (reportButtonBytes.Length != 8) { throw new ArgumentException("incoming report data was not padded to 8 bytes"); } var buttonLong = BitConverter.ToInt64(reportButtonBytes); _buttonsUpdate.OnNext(MixerButtonHelper.GetSetFlags(buttonLong)); } private void ReadReport(byte[] reportBytes) { var buttons = new byte[8]; var sliders = new byte[10]; Array.Copy(reportBytes, 0, buttons, 0, 6); Array.Copy(reportBytes, 6, sliders, 0, 10); ReadSliders(sliders); ReadButtons(buttons); } private void OnReport(HidReport report) { if (!_device!.IsConnected) return; ReadReport(report.Data); _device!.ReadReport(OnReport); } } }