public byte[] GetReportDescriptor() { var bytes = new List <byte>(); EncodedItem.EncodeItems(_items, bytes); return(bytes.ToArray()); }
private static HidDevice GetFromUsages(IEnumerable <HidDevice> devices, uint usagePage, uint usage) { foreach (var dev in devices) { try { var raw = dev.GetRawReportDescriptor(); var usages = EncodedItem.DecodeItems(raw, 0, raw.Length).Where(t => t.TagForGlobal == GlobalItemTag.UsagePage); if (usages.Any(g => g.ItemType == ItemType.Global && g.DataValue == usagePage)) { if (usages.Any(l => l.ItemType == ItemType.Local && l.DataValue == usage)) { return(dev); } } } catch { //failed to get the report descriptor, skip } } return(null); }
/// <summary> /// Parses a raw HID report descriptor. /// </summary> /// <param name="buffer">The buffer containing the report descriptor.</param> void ParseRawReportDescriptor(byte[] buffer) { Throw.If.Null(buffer, "buffer"); var items = EncodedItem.DecodeItems(buffer, 0, buffer.Length); ParseEncodedItems(items); }
/// <summary> /// Parses a single <see cref="EncodedItem"/>. /// Call this repeatedly for every item to completely decode a report descriptor. /// </summary> /// <param name="item">The item to parse.</param> public void Parse(EncodedItem item) { if (item == null) { throw new ArgumentNullException("item"); } uint value = item.DataValue; switch (item.Type) { case ItemType.Main: ParseMain(item.TagForMain, value); LocalItemState.Clear(); break; case ItemType.Local: switch (item.TagForLocal) { case LocalItemTag.Usage: case LocalItemTag.UsageMinimum: case LocalItemTag.UsageMaximum: if (value <= 0xffff) { value |= GetGlobalItemValue(GlobalItemTag.UsagePage) << 16; } break; } LocalItemState.Add(new KeyValuePair <LocalItemTag, uint> (item.TagForLocal, value)); break; case ItemType.Global: switch (item.TagForGlobal) { case GlobalItemTag.Push: GlobalItemStateStack.Add(new Dictionary <GlobalItemTag, EncodedItem> (GlobalItemState)); break; case GlobalItemTag.Pop: GlobalItemStateStack.RemoveAt(GlobalItemState.Count - 1); break; default: switch (item.TagForGlobal) { case GlobalItemTag.ReportID: ReportsUseID = true; break; } GlobalItemState[item.TagForGlobal] = item; break; } break; } }
void ParseDataMain(MainItemTag tag, uint value, out LocalIndexes indexes) { ReportSegment segment = new ReportSegment(); segment.Flags = (DataMainItemFlags)value; segment.Parent = CurrentCollection; segment.ElementCount = (int)GetGlobalItemValue(GlobalItemTag.ReportCount); segment.ElementSize = (int)GetGlobalItemValue(GlobalItemTag.ReportSize); segment.Unit = new Units.Unit(GetGlobalItemValue(GlobalItemTag.Unit)); segment.UnitExponent = Units.Unit.DecodeExponent(GetGlobalItemValue(GlobalItemTag.UnitExponent)); indexes = segment.Indexes; EncodedItem logicalMinItem = GetGlobalItem(GlobalItemTag.LogicalMinimum); EncodedItem logicalMaxItem = GetGlobalItem(GlobalItemTag.LogicalMaximum); segment.LogicalIsSigned = (logicalMinItem != null && logicalMinItem.DataValueMayBeNegative) || (logicalMaxItem != null && logicalMaxItem.DataValueMayBeNegative); int logicalMinimum = logicalMinItem == null ? 0 : segment.LogicalIsSigned ? logicalMinItem.DataValueSigned : (int)logicalMinItem.DataValue; int logicalMaximum = logicalMaxItem == null ? 0 : segment.LogicalIsSigned ? logicalMaxItem.DataValueSigned : (int)logicalMaxItem.DataValue; int physicalMinimum = (int)GetGlobalItemValue(GlobalItemTag.PhysicalMinimum); int physicalMaximum = (int)GetGlobalItemValue(GlobalItemTag.PhysicalMaximum); if (!IsGlobalItemSet(GlobalItemTag.PhysicalMinimum) || !IsGlobalItemSet(GlobalItemTag.PhysicalMaximum) || (physicalMinimum == 0 && physicalMaximum == 0)) { physicalMinimum = logicalMinimum; physicalMaximum = logicalMaximum; } segment.LogicalMinimum = logicalMinimum; segment.LogicalMaximum = logicalMaximum; segment.PhysicalMinimum = physicalMinimum; segment.PhysicalMaximum = physicalMaximum; Report report; ReportType reportType = tag == MainItemTag.Output ? ReportType.Output : tag == MainItemTag.Feature ? ReportType.Feature : ReportType.Input; uint reportID = GetGlobalItemValue(GlobalItemTag.ReportID); if (!TryGetReport(reportType, (byte)reportID, out report)) { report = new Report() { ID = (byte)reportID, Type = reportType }; Reports.Add(report); } segment.Report = report; }
/// <summary> /// Parses a single <see cref="EncodedItem"/>. /// Call this repeatedly for every item to completely decode a report descriptor. /// </summary> /// <param name="item">The item to parse.</param> void ParseEncodedItem(EncodedItem item) { Throw.If.Null(item, "item"); uint value = item.DataValue; switch (item.ItemType) { case ItemType.Main: ParseMain(item.TagForMain, value); State.LocalItemState.Clear(); break; case ItemType.Local: switch (item.TagForLocal) { case LocalItemTag.Usage: case LocalItemTag.UsageMinimum: case LocalItemTag.UsageMaximum: if (value <= 0xffff) { value |= State.GetGlobalItemValue(GlobalItemTag.UsagePage) << 16; } break; } State.LocalItemState.Add(new KeyValuePair <LocalItemTag, uint>(item.TagForLocal, value)); break; case ItemType.Global: switch (item.TagForGlobal) { case GlobalItemTag.Push: State.GlobalItemStateStack.Add(new Dictionary <GlobalItemTag, EncodedItem>(State.GlobalItemState)); break; case GlobalItemTag.Pop: State.GlobalItemStateStack.RemoveAt(State.GlobalItemState.Count - 1); break; default: switch (item.TagForGlobal) { case GlobalItemTag.ReportID: ReportsUseID = true; break; } State.GlobalItemState[item.TagForGlobal] = item; break; } break; } }
private static bool VerifyUsageAndUsagePage(this HidDevice device, uint usagePage, uint usage) { try { var rawReportDescriptor = device.GetRawReportDescriptor(); var items = EncodedItem.DecodeItems(rawReportDescriptor, 0, rawReportDescriptor.Length).Where(t => t.TagForGlobal == GlobalItemTag.UsagePage); return(items.Any(item => item.ItemType == ItemType.Global && item.DataValue == usagePage) && items.Any(item => item.ItemType == ItemType.Local && item.DataValue == usage)); } catch { return(false); } }
public void AddGlobalItemSigned(GlobalItemTag globalItemTag, int dataValue) { uint oldDataValue; if (_globals.TryGetValue(globalItemTag, out oldDataValue) && oldDataValue == (uint)dataValue) { return; } _globals[globalItemTag] = (uint)dataValue; var item = new EncodedItem() { ItemType = ItemType.Global, TagForGlobal = globalItemTag, DataValueSigned = dataValue }; _items.Add(item); }
public uint GetGlobalItemValue(GlobalItemTag tag) { EncodedItem item = GetGlobalItem(tag); return(item != null ? item.DataValue : 0); }
void ParseMainData(MainItemTag tag, uint value) { DataItem dataItem = new DataItem(); dataItem.Flags = (DataItemFlags)value; dataItem.ParentItem = State.CurrentCollectionItem; dataItem.ElementCount = (int)State.GetGlobalItemValue(GlobalItemTag.ReportCount); dataItem.ElementBits = (int)State.GetGlobalItemValue(GlobalItemTag.ReportSize); dataItem.Unit = new Units.Unit(State.GetGlobalItemValue(GlobalItemTag.Unit)); dataItem.UnitExponent = Units.Unit.DecodeExponent(State.GetGlobalItemValue(GlobalItemTag.UnitExponent)); EncodedItem logicalMinItem = State.GetGlobalItem(GlobalItemTag.LogicalMinimum); EncodedItem logicalMaxItem = State.GetGlobalItem(GlobalItemTag.LogicalMaximum); dataItem.IsLogicalSigned = !dataItem.IsArray && ((logicalMinItem != null ? logicalMinItem.DataValue : 0) > (logicalMaxItem != null ? logicalMaxItem.DataValue : 0)); int logicalMinimum = logicalMinItem == null ? 0 : dataItem.IsLogicalSigned ? logicalMinItem.DataValueSigned : (int)logicalMinItem.DataValue; int logicalMaximum = logicalMaxItem == null ? 0 : dataItem.IsLogicalSigned ? logicalMaxItem.DataValueSigned : (int)logicalMaxItem.DataValue; EncodedItem physicalMinItem = State.GetGlobalItem(GlobalItemTag.PhysicalMinimum); EncodedItem physicalMaxItem = State.GetGlobalItem(GlobalItemTag.PhysicalMaximum); bool isPhysicalSigned = !dataItem.IsArray && ((physicalMinItem != null ? physicalMinItem.DataValue : 0) > (physicalMaxItem != null ? physicalMaxItem.DataValue : 0)); int physicalMinimum = physicalMinItem == null ? 0 : isPhysicalSigned ? physicalMinItem.DataValueSigned : (int)physicalMinItem.DataValue; int physicalMaximum = physicalMaxItem == null ? 0 : isPhysicalSigned ? physicalMaxItem.DataValueSigned : (int)physicalMaxItem.DataValue; if (physicalMinimum == 0 && physicalMaximum == 0) { physicalMinimum = logicalMinimum; physicalMaximum = logicalMaximum; } dataItem.LogicalMinimum = logicalMinimum; dataItem.LogicalMaximum = logicalMaximum; dataItem.RawPhysicalMinimum = physicalMinimum; dataItem.RawPhysicalMaximum = physicalMaximum; Report report; ReportType reportType = tag == MainItemTag.Output ? ReportType.Output : tag == MainItemTag.Feature ? ReportType.Feature : ReportType.Input; uint reportID = State.GetGlobalItemValue(GlobalItemTag.ReportID); if (!TryGetReport(reportType, (byte)reportID, out report)) { report = new Report() { ReportID = (byte)reportID, ReportType = reportType }; Reports.Add(report); var collection = State.CurrentCollectionItem; while (collection != null && !(collection is DeviceItem)) { collection = collection.ParentItem; } if (collection is DeviceItem) { ((DeviceItem)collection).Reports.Add(report); } } report.DataItems.Add(dataItem); ParseMainIndexes(dataItem); }
static void Main(string[] args) { HidSharpDiagnostics.EnableTracing = true; HidSharpDiagnostics.PerformStrictChecks = true; var list = DeviceList.Local; list.Changed += (sender, e) => Console.WriteLine("Device list changed."); var allDeviceList = list.GetAllDevices().ToArray(); Console.WriteLine("All device list:"); foreach (Device dev in allDeviceList) { Console.WriteLine(dev.ToString() + " @ " + dev.DevicePath); } var stopwatch = Stopwatch.StartNew(); var hidDeviceList = list.GetHidDevices().ToArray(); Console.WriteLine("Complete device list (took {0} ms to get {1} devices):", stopwatch.ElapsedMilliseconds, hidDeviceList.Length); foreach (HidDevice dev in hidDeviceList) { if (dev.VendorID != 0x2341) { continue; } Console.WriteLine(dev.DevicePath); //Console.WriteLine(string.Join(",", dev.GetDevicePathHierarchy())); // TODO Console.WriteLine(dev); try { Console.WriteLine(string.Format("Max Lengths: Input {0}, Output {1}, Feature {2}", dev.GetMaxInputReportLength(), dev.GetMaxOutputReportLength(), dev.GetMaxFeatureReportLength())); } catch (UnauthorizedAccessException e) { Console.WriteLine(e); Console.WriteLine(); continue; } try { Console.WriteLine("Serial Ports: {0}", string.Join(",", dev.GetSerialPorts())); } catch { Console.WriteLine("Serial Ports: Unknown on this platform."); } try { var rawReportDescriptor = dev.GetRawReportDescriptor(); Console.WriteLine("Report Descriptor:"); Console.WriteLine(" {0} ({1} bytes)", string.Join(" ", rawReportDescriptor.Select(d => d.ToString("X2"))), rawReportDescriptor.Length); int indent = 0; foreach (var element in EncodedItem.DecodeItems(rawReportDescriptor, 0, rawReportDescriptor.Length)) { if (element.ItemType == ItemType.Main && element.TagForMain == MainItemTag.EndCollection) { indent -= 2; } Console.WriteLine(" {0}{1}", new string(' ', indent), element); if (element.ItemType == ItemType.Main && element.TagForMain == MainItemTag.Collection) { indent += 2; } } var reportDescriptor = dev.GetReportDescriptor(); // Lengths should match. Debug.Assert(dev.GetMaxInputReportLength() == reportDescriptor.MaxInputReportLength); Debug.Assert(dev.GetMaxOutputReportLength() == reportDescriptor.MaxOutputReportLength); Debug.Assert(dev.GetMaxFeatureReportLength() == reportDescriptor.MaxFeatureReportLength); foreach (var deviceItem in reportDescriptor.DeviceItems) { foreach (var usage in deviceItem.Usages.GetAllValues()) { Console.WriteLine(string.Format("Usage: {0:X4} {1}", usage, (Usage)usage)); } foreach (var report in deviceItem.Reports) { Console.WriteLine(string.Format("{0}: ReportID={1}, Length={2}, Items={3}", report.ReportType, report.ReportID, report.Length, report.DataItems.Count)); foreach (var dataItem in report.DataItems) { Console.WriteLine(string.Format(" {0} Elements x {1} Bits, Units: {2}, Expected Usage Type: {3}, Flags: {4}, Usages: {5}", dataItem.ElementCount, dataItem.ElementBits, dataItem.Unit.System, dataItem.ExpectedUsageType, dataItem.Flags, string.Join(", ", dataItem.Usages.GetAllValues().Select(usage => usage.ToString("X4") + " " + ((Usage)usage).ToString())))); } } { Console.WriteLine("Opening device for 20 seconds..."); HidStream hidStream; if (dev.TryOpen(out hidStream)) { hidStream.ReadTimeout = Timeout.Infinite; using (hidStream) { var inputReportBuffer = new byte[dev.GetMaxInputReportLength()]; var inputReceiver = reportDescriptor.CreateHidDeviceInputReceiver(); var inputParser = deviceItem.CreateDeviceItemInputParser(); inputReceiver.Received += (sender, e) => { Report report; while (inputReceiver.TryRead(inputReportBuffer, 0, out report)) { // Parse the report if possible. // This will return false if (for example) the report applies to a different DeviceItem. if (inputParser.TryParseReport(inputReportBuffer, 0, report)) { // If you are using Windows Forms, you could call BeginInvoke here to marshal the results // to your main thread. WriteDeviceItemInputParserResult(inputParser); } } }; inputReceiver.Start(hidStream); Thread.Sleep(60000); } Console.WriteLine("Closed device."); } else { Console.WriteLine("Failed to open device."); } Console.WriteLine(); } } Console.WriteLine(); } catch (Exception e) { Console.WriteLine(e); } } Console.WriteLine("Press a key to exit..."); Console.Read(); }
/// <summary> /// Parses a single <see cref="EncodedItem"/>. /// Call this repeatedly for every item to completely decode a report descriptor. /// </summary> /// <param name="item">The item to parse.</param> public void Parse(EncodedItem item) { if (item == null) { throw new ArgumentNullException("item"); } uint value = item.DataValue; switch (item.Type) { case ItemType.Main: ParseMain(item.TagForMain, value); LocalItemState.Clear(); break; case ItemType.Local: switch (item.TagForLocal) { case LocalItemTag.Usage: case LocalItemTag.UsageMinimum: case LocalItemTag.UsageMaximum: if (value <= 0xffff) { value |= GetGlobalItemValue(GlobalItemTag.UsagePage) << 16; } break; } LocalItemState.Add(new KeyValuePair<LocalItemTag, uint>(item.TagForLocal, value)); break; case ItemType.Global: switch (item.TagForGlobal) { case GlobalItemTag.Push: GlobalItemStateStack.Add(new Dictionary<GlobalItemTag, EncodedItem>(GlobalItemState)); break; case GlobalItemTag.Pop: GlobalItemStateStack.RemoveAt(GlobalItemState.Count - 1); break; default: switch (item.TagForGlobal) { case GlobalItemTag.ReportID: ReportsUseID = true; break; } GlobalItemState[item.TagForGlobal] = item; break; } break; } }
private void PrintfHidDeviceInfo() { HidDevice[] devices = DeviceList.Local.GetHidDevices(1111, 4755).ToArray(); foreach (HidDevice dev in devices) { Console.WriteLine("-----------------------------"); Console.WriteLine("{0}, {1}", dev, dev.DevicePath); try { Console.WriteLine(string.Format("Max Lengths: Input {0}, Output {1}, Feature {2}", dev.GetMaxInputReportLength(), dev.GetMaxOutputReportLength(), dev.GetMaxFeatureReportLength())); } catch (UnauthorizedAccessException e) { Console.WriteLine(e); continue; } try { var rawReportDescriptor = dev.GetRawReportDescriptor(); Console.WriteLine("Report Descriptor:"); Console.WriteLine(" {0} ({1} bytes)", string.Join(" ", rawReportDescriptor.Select(d => d.ToString("X2"))), rawReportDescriptor.Length); int indent = 0; foreach (EncodedItem element in EncodedItem.DecodeItems(rawReportDescriptor, 0, rawReportDescriptor.Length)) { if (element.ItemType == ItemType.Main && element.TagForMain == MainItemTag.EndCollection) { indent -= 4; } Console.WriteLine(" {0}{1}", new string(' ', indent), element); if (element.ItemType == ItemType.Main && element.TagForMain == MainItemTag.Collection) { indent += 4; } } var reportDescriptor = dev.GetReportDescriptor(); foreach (DeviceItem deviceItem in reportDescriptor.DeviceItems) { if (InputParser == null) { InputParser = deviceItem.CreateDeviceItemInputParser(); } foreach (var usage in deviceItem.Usages.GetAllValues()) { Console.WriteLine(string.Format("Usage: {0:X4} {1}", usage, (Usage)usage)); } foreach (var report in deviceItem.Reports) { Console.WriteLine(string.Format("{0}: ReportID={1}, Length={2}, Items={3}", report.ReportType, report.ReportID, report.Length, report.DataItems.Count)); foreach (DataItem dataItem in report.DataItems) { Console.WriteLine(string.Format(" {0} Elements x {1} Bits, Units: {2}, Expected Usage Type: {3}, Flags: {4}, Usages: {5} TotalBits: {6}", dataItem.ElementCount, dataItem.ElementBits, dataItem.Unit.System, dataItem.ExpectedUsageType, dataItem.Flags, string.Join(", ", dataItem.Usages.GetAllValues().Select(usage => usage.ToString("X4") + " " + ((Usage)usage).ToString())), dataItem.TotalBits)); } } //tryOpen } } catch (Exception ex) { Console.WriteLine("Exception:::{0}", ex); } } }
static void Main(string[] args) { //Trace.Listeners.Clear(); //Trace.Listeners.Add(new ConsoleTraceListener()); HidSharpDiagnostics.EnableTracing = true; HidSharpDiagnostics.PerformStrictChecks = true; var list = DeviceList.Local; list.Changed += (sender, e) => Console.WriteLine("Device list changed."); //Console.WriteLine("Beginning discovery."); //using (list.BeginBleDiscovery()) { var allDeviceList = list.GetAllDevices().ToArray(); Console.WriteLine("All device list:"); foreach (Device dev in allDeviceList) { Console.WriteLine(dev.ToString() + " @ " + dev.DevicePath); /* * if (dev is HidDevice) * { * foreach (var serialPort in * (((HidDevice)dev).GetSerialPorts())) * { * Console.WriteLine(" " + serialPort); * } * } */ } var bleDeviceList = list.GetBleDevices().ToArray(); Console.WriteLine("BLE device list:"); foreach (BleDevice dev in bleDeviceList) { Console.WriteLine(dev.ToString() + "@" + dev.DevicePath); foreach (var service in dev.GetServices()) { Console.WriteLine(string.Format("\tService: {0}", service.Uuid)); foreach (var characteristic in service.GetCharacteristics()) { Console.WriteLine(string.Format("\t\tCharacteristic: {0} (Properties: {1})", characteristic.Uuid, characteristic.Properties)); foreach (var descriptor in characteristic.GetDescriptors()) { Console.WriteLine(string.Format("\t\t\tDescriptor: {0}", descriptor.Uuid)); } } if (service.Uuid == new BleUuid("63dc0001-fa35-4205-b09f-0fc6072ec515")) { try { using (var svc = dev.Open(service)) { Console.WriteLine("Opened!"); BleCharacteristic rx = null; foreach (var ch in service.GetCharacteristics()) { Console.WriteLine(string.Format("{0} = {1}", ch.Uuid, ch.IsReadable ? string.Join(" ", svc.ReadCharacteristic(ch)) : "N/A")); foreach (var d in ch.GetDescriptors()) { Console.WriteLine(string.Format("\t{0} = {1}", d.Uuid, string.Join(" ", svc.ReadDescriptor(d)))); } if (BleCccd.Notification != svc.ReadCccd(ch)) { svc.WriteCccd(ch, BleCccd.Notification); } if (ch.Uuid == new BleUuid("63dc0002-fa35-4205-b09f-0fc6072ec515")) { rx = ch; } } Action beginReadEvent = null; AsyncCallback endReadEvent = null; beginReadEvent = () => { svc.BeginReadEvent(endReadEvent, null); }; endReadEvent = ar => { BleEvent @event; try { @event = svc.EndReadEvent(ar); } catch (ObjectDisposedException) { Console.WriteLine("closed"); return; } catch (TimeoutException) { Console.WriteLine("timed out"); @event = default(BleEvent); } if (@event.Value != null) { Console.WriteLine(string.Format("{0} -> {1}", @event.Characteristic, string.Join(" ", @event.Value.Select(x => x.ToString())))); if (rx != null) { Console.WriteLine("writing"); svc.WriteCharacteristicWithoutResponse(rx, new[] { (byte)0xdd, (byte)1, (byte)'A' }); } } beginReadEvent(); }; beginReadEvent(); Thread.Sleep(30000); } } catch (Exception e) { Console.WriteLine(e.ToString()); } } } } Console.WriteLine(); Console.WriteLine("Press any key"); Console.ReadKey(); Console.WriteLine(); } //Console.WriteLine("Ending discovery."); /* * var serialDeviceList = list.GetSerialDevices().ToArray(); * Console.WriteLine("Serial device list:"); * foreach (SerialDevice dev in serialDeviceList) * { * Console.WriteLine(dev.DevicePath); * } * * Console.WriteLine(); */ var stopwatch = Stopwatch.StartNew(); var hidDeviceList = list.GetHidDevices().ToArray(); Console.WriteLine("Complete device list (took {0} ms to get {1} devices):", stopwatch.ElapsedMilliseconds, hidDeviceList.Length); foreach (HidDevice dev in hidDeviceList) { Console.WriteLine(dev.DevicePath); //Console.WriteLine(string.Join(",", dev.GetDevicePathHierarchy())); // TODO Console.WriteLine(dev); try { Console.WriteLine(string.Format("Max Lengths: Input {0}, Output {1}, Feature {2}", dev.GetMaxInputReportLength(), dev.GetMaxOutputReportLength(), dev.GetMaxFeatureReportLength())); } catch (UnauthorizedAccessException e) { Console.WriteLine(e); Console.WriteLine(); continue; } try { Console.WriteLine("Serial Ports: {0}", string.Join(",", dev.GetSerialPorts())); } catch { Console.WriteLine("Serial Ports: Unknown on this platform."); } try { var rawReportDescriptor = dev.GetRawReportDescriptor(); Console.WriteLine("Report Descriptor:"); Console.WriteLine(" {0} ({1} bytes)", string.Join(" ", rawReportDescriptor.Select(d => d.ToString("X2"))), rawReportDescriptor.Length); int indent = 0; foreach (var element in EncodedItem.DecodeItems(rawReportDescriptor, 0, rawReportDescriptor.Length)) { if (element.ItemType == ItemType.Main && element.TagForMain == MainItemTag.EndCollection) { indent -= 2; } Console.WriteLine(" {0}{1}", new string(' ', indent), element); if (element.ItemType == ItemType.Main && element.TagForMain == MainItemTag.Collection) { indent += 2; } } var reportDescriptor = dev.GetReportDescriptor(); // Lengths should match. Debug.Assert(dev.GetMaxInputReportLength() == reportDescriptor.MaxInputReportLength); Debug.Assert(dev.GetMaxOutputReportLength() == reportDescriptor.MaxOutputReportLength); Debug.Assert(dev.GetMaxFeatureReportLength() == reportDescriptor.MaxFeatureReportLength); foreach (var deviceItem in reportDescriptor.DeviceItems) { foreach (var usage in deviceItem.Usages.GetAllValues()) { Console.WriteLine(string.Format("Usage: {0:X4} {1}", usage, (Usage)usage)); } foreach (var report in deviceItem.Reports) { Console.WriteLine(string.Format("{0}: ReportID={1}, Length={2}, Items={3}", report.ReportType, report.ReportID, report.Length, report.DataItems.Count)); foreach (var dataItem in report.DataItems) { Console.WriteLine(string.Format(" {0} Elements x {1} Bits, Units: {2}, Expected Usage Type: {3}, Flags: {4}, Usages: {5}", dataItem.ElementCount, dataItem.ElementBits, dataItem.Unit.System, dataItem.ExpectedUsageType, dataItem.Flags, string.Join(", ", dataItem.Usages.GetAllValues().Select(usage => usage.ToString("X4") + " " + ((Usage)usage).ToString())))); } } { Console.WriteLine("Opening device for 20 seconds..."); HidStream hidStream; if (dev.TryOpen(out hidStream)) { Console.WriteLine("Opened device."); hidStream.ReadTimeout = Timeout.Infinite; using (hidStream) { var inputReportBuffer = new byte[dev.GetMaxInputReportLength()]; var inputReceiver = reportDescriptor.CreateHidDeviceInputReceiver(); var inputParser = deviceItem.CreateDeviceItemInputParser(); #if SINGLE_THREADED_WAITHANDLE_APPROACH inputReceiver.Start(hidStream); int startTime = Environment.TickCount; while (true) { if (inputReceiver.WaitHandle.WaitOne(1000)) { if (!inputReceiver.IsRunning) { break; } // Disconnected? Report report; while (inputReceiver.TryRead(inputReportBuffer, 0, out report)) { // Parse the report if possible. // This will return false if (for example) the report applies to a different DeviceItem. if (inputParser.TryParseReport(inputReportBuffer, 0, report)) { WriteDeviceItemInputParserResult(inputParser); } } } uint elapsedTime = (uint)(Environment.TickCount - startTime); if (elapsedTime >= 20000) { break; } // Stay open for 20 seconds. } #elif SINGLE_THREADED_POLLING_APPROACH inputReceiver.Start(hidStream); int startTime = Environment.TickCount; while (true) { if (!inputReceiver.IsRunning) { break; } // Disconnected? Report report; // Periodically check if the receiver has any reports. while (inputReceiver.TryRead(inputReportBuffer, 0, out report)) { // Parse the report if possible. // This will return false if (for example) the report applies to a different DeviceItem. if (inputParser.TryParseReport(inputReportBuffer, 0, report)) { WriteDeviceItemInputParserResult(inputParser); } } } uint elapsedTime = (uint)(Environment.TickCount - startTime); if (elapsedTime >= 20000) { break; } // Stay open for 20 seconds. #elif THREAD_POOL_RECEIVED_EVENT_APPROACH inputReceiver.Received += (sender, e) => { Report report; while (inputReceiver.TryRead(inputReportBuffer, 0, out report)) { // Parse the report if possible. // This will return false if (for example) the report applies to a different DeviceItem. if (inputParser.TryParseReport(inputReportBuffer, 0, report)) { // If you are using Windows Forms, you could call BeginInvoke here to marshal the results // to your main thread. WriteDeviceItemInputParserResult(inputParser); } } }; inputReceiver.Start(hidStream); Thread.Sleep(20000); #elif RAW_APPROACH IAsyncResult ar = null; int startTime = Environment.TickCount; while (true) { if (ar == null) { ar = hidStream.BeginRead(inputReportBuffer, 0, inputReportBuffer.Length, null, null); } if (ar != null) { if (ar.IsCompleted) { int byteCount = hidStream.EndRead(ar); ar = null; if (byteCount > 0) { string hexOfBytes = string.Join(" ", inputReportBuffer.Take(byteCount).Select(b => b.ToString("X2"))); Console.WriteLine(" {0}", hexOfBytes); } } else { ar.AsyncWaitHandle.WaitOne(1000); } } uint elapsedTime = (uint)(Environment.TickCount - startTime); if (elapsedTime >= 20000) { break; } // Stay open for 20 seconds. } #else #error "Choose an approach for the example." #endif } Console.WriteLine("Closed device."); } else { Console.WriteLine("Failed to open device."); } Console.WriteLine(); } } Console.WriteLine(); } catch (Exception e) { Console.WriteLine(e); } } Console.WriteLine("Press a key to exit..."); Console.ReadKey(); }