Reads and writes HID reports.
        public bool TryGetReport(ReportType type, byte id, out Report report)
        {
            for (int i = 0; i < Reports.Count; i++)
            {
                report = Reports[i];
                if (report.Type == type && report.ID == id) { return true; }
            }

            report = null; return false;
        }
        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;
        }