using EonaCat.HID.Helpers; using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Globalization; using System.Linq; using System.Reflection; using System.Windows.Forms; namespace EonaCat.HID.Analyzer { public partial class MainForm : Form { private const int WriteReportTimeout = 3000; private Device _device; private List _deviceList; public MainForm() { InitializeComponent(); } private void MainForm_Load(object sender, EventArgs e) { try { rtbEventLog.Font = new Font("Consolas", 9); } catch (Exception ex) { PopupException(ex.Message); } } private void MainForm_Shown(object sender, EventArgs e) { try { _deviceList = Devices.Enumerate().ToList(); UpdateDeviceList(); toolStripStatusLabel1.Text = "Please select device and click open to start."; } catch (Exception ex) { PopupException(ex.Message); } } private void AppendEventLog(string result, Color? color = null, bool appendNewLine = true) { var currentColor = color ?? Color.Black; if (appendNewLine) { result += Environment.NewLine; } // update from UI thread Invoke(new MethodInvoker(() => { rtbEventLog.SelectionStart = rtbEventLog.TextLength; rtbEventLog.SelectionLength = 0; rtbEventLog.SelectionColor = currentColor; rtbEventLog.AppendText(result); if (!rtbEventLog.Focused) { rtbEventLog.ScrollToCaret(); } })); } private void UpdateDeviceList() { dataGridView1.SelectionChanged -= DataGridView1_SelectionChanged; dataGridView1.Rows.Clear(); for (int i = 0; i < _deviceList.Count; i++) { Device device = _deviceList[i]; var deviceName = ""; var deviceManufacturer = ""; var deviceSerialNumber = ""; var info = device.Info; var capabilities = device.Capabilities; deviceName = device.ReadProductName(); deviceManufacturer = device.ReadManufacturer(); deviceSerialNumber = device.ReadSerialNumber(); var row = new string[] { (i + 1).ToString(), deviceName, deviceManufacturer, deviceSerialNumber, capabilities.InputReportByteLength.ToString(), capabilities.OutputReportByteLength.ToString(), capabilities.FeatureReportByteLength.ToString(), $"Vendor:{info.VendorId:X4} Product:{info.ProductId:X4} Revision:{info.Version:X4}", device.DevicePath }; dataGridView1.Rows.Add(row); } dataGridView1.SelectionChanged += DataGridView1_SelectionChanged; DataGridView1_SelectionChanged(this, null); } private void PopupException(string message, string caption = "Exception") { Invoke(new Action(() => { MessageBox.Show(message, caption, MessageBoxButtons.OK, MessageBoxIcon.Error); })); } private void NewToolStripMenuItem_Click(object sender, EventArgs e) { try { Process.Start(Assembly.GetExecutingAssembly().Location); } catch (Exception ex) { PopupException(ex.Message); } } private void ExitToolStripMenuItem_Click(object sender, EventArgs e) { try { this.Close(); } catch (Exception ex) { PopupException(ex.Message); } } private void AboutToolStripMenuItem_Click(object sender, EventArgs e) { try { HelpToolStripButton_Click(sender, e); } catch (Exception ex) { PopupException(ex.Message); } } private void ToolStripButtonReload_Click(object sender, EventArgs e) { try { _deviceList = Devices.Enumerate().ToList(); UpdateDeviceList(); } catch (Exception ex) { PopupException(ex.Message); } } private void ToolStripButtonFilter_Click(object sender, EventArgs e) { try { var str = toolStripTextBoxVidPid.Text.Split(':'); var vid = int.Parse(str[0], NumberStyles.AllowHexSpecifier); var pid = int.Parse(str[1], NumberStyles.AllowHexSpecifier); _deviceList = Devices.Enumerate(vid, pid).ToList(); UpdateDeviceList(); } catch (Exception ex) { PopupException(ex.Message); } } private void ToolStripButtonConnect_Click(object sender, EventArgs e) { ConnectToSelectedDevice(); } private void ConnectToSelectedDevice() { try { _device = _deviceList[dataGridView1.SelectedRows[0].Index]; if (_device == null) { throw new Exception("Could not find Hid USB Device with specified VID PID"); } // Open a device for reading and writing _device.OpenDevice(DeviceMode.Overlapped, DeviceMode.Overlapped, ShareMode.ShareRead | ShareMode.ShareWrite); _device.OnInserted += HidDevice_Inserted; _device.OnRemoved += HidDevice_Removed; _device.MonitorDeviceEvents = true; AppendEventLog($"Connected to device {_device.ReadProductName()}", Color.Green); } catch (Exception ex) { PopupException(ex.Message); } } private void ToolStripButtonClear_Click(object sender, EventArgs e) { try { rtbEventLog.Clear(); } catch (Exception ex) { PopupException(ex.Message); } } private void HelpToolStripButton_Click(object sender, EventArgs e) { try { var aboutbox = new AboutBox(); aboutbox.ShowDialog(); } catch (Exception ex) { PopupException(ex.Message); } } private void ButtonReadInput_Click(object sender, EventArgs e) { try { var len = _device.Capabilities.InputReportByteLength; if (len <= 0) { throw new Exception("This device has no Input Report support!"); } _device.ReadReport(Device_InputReportReceived); AppendEventLog("Hid Input Report Callback Started."); } catch (Exception ex) { PopupException(ex.Message); } } private void ButtonWriteOutput_Click(object sender, EventArgs e) { try { var hidReportId = byte.Parse(comboBoxReportId.Text); var buf = ByteHelper.HexStringToByteArray(textBoxWriteData.Text); var report = _device.CreateReport(); if (buf.Length > report.Data.Length) { throw new Exception("Output Report Length Exceed"); } report.ReportId = hidReportId; Array.Copy(buf, report.Data, buf.Length); _device.WriteReport(report, WriteReportTimeout); var str = string.Format("Tx Output Report [{0}] --> ID:{1}, {2}", report.Data.Length + 1, report.ReportId, ByteHelper.ByteArrayToHexString(report.Data)); AppendEventLog(str, Color.DarkGreen); } catch (Exception ex) { PopupException(ex.Message); } } private void ButtonReadFeature_Click(object sender, EventArgs e) { try { var hidReportId = byte.Parse(comboBoxReportId.Text); var len = _device.Capabilities.FeatureReportByteLength; if (len <= 0) { throw new Exception("This device has no Feature Report support!"); } _device.ReadFeatureData(out byte[] buf, hidReportId); var str = string.Format("Rx Feature Report [{0}] <-- {1}", buf.Length, ByteHelper.ByteArrayToHexString(buf)); AppendEventLog(str, Color.Blue); } catch (Exception ex) { PopupException(ex.Message); } } private void ButtonWriteFeature_Click(object sender, EventArgs e) { try { var hidReportId = byte.Parse(comboBoxReportId.Text); var buf = ByteHelper.HexStringToByteArray(textBoxWriteData.Text); var len = _device.Capabilities.FeatureReportByteLength; if (buf.Length > len) { throw new Exception("Write Feature Report Length Exceed"); } Array.Resize(ref buf, len); _device.WriteFeatureData(buf); var str = string.Format("Tx Feature Report [{0}] --> {1}", buf.Length, ByteHelper.ByteArrayToHexString(buf)); AppendEventLog(str, Color.DarkGreen); } catch (Exception ex) { PopupException(ex.Message); } } private void DataGridView1_SelectionChanged(object sender, EventArgs e) { try { if (dataGridView1.SelectedRows.Count <= 0) return; var index = dataGridView1.SelectedRows[0].Index; var devinfo = _deviceList[index].Info; toolStripTextBoxVidPid.Text = string.Format("{0:X4}:{1:X4}", devinfo.VendorId, devinfo.ProductId); } catch (Exception ex) { PopupException(ex.Message); } } private void HidDevice_Inserted() { try { var str = string.Format("Inserted Device --> VID {0:X4}, PID {0:X4}", _device.Info.VendorId, _device.Info.ProductId); AppendEventLog(str, Color.Orange); _device.ReadReport(Device_InputReportReceived); } catch (Exception ex) { PopupException(ex.Message); } } private void HidDevice_Removed() { try { var str = string.Format("Removed Device --> VID {0:X4}, PID {0:X4}", _device.Info.VendorId, _device.Info.ProductId); AppendEventLog(str); } catch (Exception ex) { PopupException(ex.Message); } } private void Device_InputReportReceived(Report report) { try { if (!_device.IsConnected || !_device.IsOpen || report.Data == null) return; var str = $"Rx Input Report [{report.Data.Length + 1}] <-- ID:{report.ReportId}, {ByteHelper.ByteArrayToHexString(report.Data)}"; AppendEventLog(str, Color.Blue); _device.ReadReport(Device_InputReportReceived); } catch (Exception ex) { PopupException(ex.Message); } } private void dataGridView1_DoubleClick(object sender, EventArgs e) { ConnectToSelectedDevice(); } } }