| Index: device/hid/hid_report_descriptor.h
|
| diff --git a/device/hid/hid_report_descriptor.h b/device/hid/hid_report_descriptor.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..fa01717702ae79270e74ed5060043302b211898f
|
| --- /dev/null
|
| +++ b/device/hid/hid_report_descriptor.h
|
| @@ -0,0 +1,810 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#ifndef DEVICE_HID_HID_REPORT_DESCRIPTOR_H_
|
| +#define DEVICE_HID_HID_REPORT_DESCRIPTOR_H_
|
| +
|
| +#include <sstream>
|
| +#include <vector>
|
| +
|
| +#include "base/basictypes.h"
|
| +#include "device/hid/hid_usage_and_page.h"
|
| +
|
| +namespace device {
|
| +
|
| +// An element of a HID report descriptor.
|
| +class HidReportDescriptorItem {
|
| +
|
| +#pragma pack (push, 1)
|
| +
|
| +public:
|
| + enum Type {
|
| + kTypeMain = 0,
|
| + kTypeGlobal = 1,
|
| + kTypeLocal = 2,
|
| + kTypeReserved = 3
|
| + };
|
| +
|
| +private:
|
| + // Tags
|
| +
|
| + enum MainTag {
|
| + kMainTagDefault = 0x00, // 0000
|
| + kMainTagInput = 0x08, // 1000
|
| + kMainTagOutput = 0x09, // 1001
|
| + kMainTagFeature = 0x0B, // 1011
|
| + kMainTagCollection = 0x0A, // 1010
|
| + kMainTagEndCollection = 0x0C // 1100
|
| + };
|
| +
|
| + enum GlobalTag {
|
| + kGlobalTagUsagePage = 0x00, // 0000
|
| + kGlobalTagLogicalMinimum = 0x01, // 0001
|
| + kGlobalTagLogicalMaximum = 0x02, // 0010
|
| + kGlobalTagPhysicalMinimum = 0x03, // 0011
|
| + kGlobalTagPhysicalMaximum = 0x04, // 0100
|
| + kGlobalTagUnitExponent = 0x05, // 0101
|
| + kGlobalTagUnit = 0x06, // 0110
|
| + kGlobalTagReportSize = 0x07, // 0111
|
| + kGlobalTagReportId = 0x08, // 1000
|
| + kGlobalTagReportCount = 0x09, // 1001
|
| + kGlobalTagPush = 0x0A, // 1010
|
| + kGlobalTagPop = 0x0B // 1011
|
| + };
|
| +
|
| + enum LocalTag {
|
| + kLocalTagUsage = 0x00, // 0000
|
| + kLocalTagUsageMinimum = 0x01, // 0001
|
| + kLocalTagUsageMaximum = 0x02, // 0010
|
| + kLocalTagDesignatorIndex = 0x03, // 0011
|
| + kLocalTagDesignatorMinimum = 0x04, // 0100
|
| + kLocalTagDesignatorMaximum = 0x05, // 0101
|
| + kLocalTagStringIndex = 0x07, // 0111
|
| + kLocalTagStringMinimum = 0x08, // 1000
|
| + kLocalTagStringMaximum = 0x09, // 1001
|
| + kLocalTagDelimiter = 0x0A // 1010
|
| + };
|
| +
|
| + enum ReservedTag {
|
| + kReservedTagLong = 0xF // 1111
|
| + };
|
| +
|
| +public:
|
| + enum Tag {
|
| + kTagDefault = kMainTagDefault << 2 | kTypeMain,
|
| + kTagInput = kMainTagInput << 2 | kTypeMain,
|
| + kTagOutput = kMainTagOutput << 2 | kTypeMain,
|
| + kTagFeature = kMainTagFeature << 2 | kTypeMain,
|
| + kTagCollection = kMainTagCollection << 2 | kTypeMain,
|
| + kTagEndCollection = kMainTagEndCollection << 2 | kTypeMain,
|
| + kTagUsagePage = kGlobalTagUsagePage << 2 | kTypeGlobal,
|
| + kTagLogicalMinimum = kGlobalTagLogicalMinimum << 2 | kTypeGlobal,
|
| + kTagLogicalMaximum = kGlobalTagLogicalMaximum << 2 | kTypeGlobal,
|
| + kTagPhysicalMinimum = kGlobalTagPhysicalMinimum << 2 | kTypeGlobal,
|
| + kTagPhysicalMaximum = kGlobalTagPhysicalMaximum << 2 | kTypeGlobal,
|
| + kTagUnitExponent = kGlobalTagUnitExponent << 2 | kTypeGlobal,
|
| + kTagUnit = kGlobalTagUnit << 2 | kTypeGlobal,
|
| + kTagReportSize = kGlobalTagReportSize << 2 | kTypeGlobal,
|
| + kTagReportId = kGlobalTagReportId << 2 | kTypeGlobal,
|
| + kTagReportCount = kGlobalTagReportCount << 2 | kTypeGlobal,
|
| + kTagPush = kGlobalTagPush << 2 | kTypeGlobal,
|
| + kTagPop = kGlobalTagPop << 2 | kTypeGlobal,
|
| + kTagUsage = kLocalTagUsage << 2 | kTypeLocal,
|
| + kTagUsageMinimum = kLocalTagUsageMinimum << 2 | kTypeLocal,
|
| + kTagUsageMaximum = kLocalTagUsageMaximum << 2 | kTypeLocal,
|
| + kTagDesignatorIndex = kLocalTagDesignatorIndex << 2 | kTypeLocal,
|
| + kTagDesignatorMinimum = kLocalTagDesignatorMinimum << 2 | kTypeLocal,
|
| + kTagDesignatorMaximum = kLocalTagDesignatorMaximum << 2 | kTypeLocal,
|
| + kTagStringIndex = kLocalTagStringIndex << 2 | kTypeLocal,
|
| + kTagStringMinimum = kLocalTagStringMinimum << 2 | kTypeLocal,
|
| + kTagStringMaximum = kLocalTagStringMaximum << 2 | kTypeLocal,
|
| + kTagDelimiter = kLocalTagDelimiter << 2 | kTypeLocal,
|
| + kTagLong = kReservedTagLong << 2 | kTypeReserved
|
| + };
|
| +
|
| +private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const Tag& tag) {
|
| + switch (tag) {
|
| + case kTagDefault:
|
| + os << "Default";
|
| + break;
|
| + case kTagInput:
|
| + os << "Input";
|
| + break;
|
| + case kTagOutput:
|
| + os << "Output";
|
| + break;
|
| + case kTagFeature:
|
| + os << "Feature";
|
| + break;
|
| + case kTagCollection:
|
| + os << "Collection";
|
| + break;
|
| + case kTagEndCollection:
|
| + os << "End Collection";
|
| + break;
|
| + case kTagUsagePage:
|
| + os << "Usage Page";
|
| + break;
|
| + case kTagLogicalMinimum:
|
| + os << "Logical Minimum";
|
| + break;
|
| + case kTagLogicalMaximum:
|
| + os << "Logical Maximum";
|
| + break;
|
| + case kTagPhysicalMinimum:
|
| + os << "Physical Minimum";
|
| + break;
|
| + case kTagPhysicalMaximum:
|
| + os << "Physical Maximum";
|
| + break;
|
| + case kTagUnitExponent:
|
| + os << "Unit Exponent";
|
| + break;
|
| + case kTagUnit:
|
| + os << "Unit";
|
| + break;
|
| + case kTagReportSize:
|
| + os << "Report Size";
|
| + break;
|
| + case kTagReportId:
|
| + os << "Report ID";
|
| + break;
|
| + case kTagReportCount:
|
| + os << "Report Count";
|
| + break;
|
| + case kTagPush:
|
| + os << "Push";
|
| + break;
|
| + case kTagPop:
|
| + os << "Pop";
|
| + break;
|
| + case kTagUsage:
|
| + os << "Usage";
|
| + break;
|
| + case kTagUsageMinimum:
|
| + os << "Usage Minimum";
|
| + break;
|
| + case kTagUsageMaximum:
|
| + os << "Usage Maximum";
|
| + break;
|
| + case kTagDesignatorIndex:
|
| + os << "Designator Index";
|
| + break;
|
| + case kTagDesignatorMinimum:
|
| + os << "Designator Minimum";
|
| + break;
|
| + case kTagDesignatorMaximum:
|
| + os << "Designator Maximum";
|
| + break;
|
| + case kTagStringIndex:
|
| + os << "String Index";
|
| + break;
|
| + case kTagStringMinimum:
|
| + os << "String Minimum";
|
| + break;
|
| + case kTagStringMaximum:
|
| + os << "String Maximum";
|
| + break;
|
| + case kTagDelimiter:
|
| + os << "Delimeter";
|
| + break;
|
| + case kTagLong:
|
| + os << "Long";
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + break;
|
| + }
|
| +
|
| + return os;
|
| + };
|
| +
|
| +public:
|
| + // Headers
|
| +
|
| + struct Header {
|
| + uint8_t size : 2;
|
| + uint8_t type : 2;
|
| + uint8_t tag : 4;
|
| + };
|
| +
|
| + struct LongHeader {
|
| + Header short_header;
|
| + uint8_t data_size;
|
| + uint8_t long_item_tag;
|
| + };
|
| +
|
| + // Data
|
| +
|
| + // (Short) Main items
|
| +
|
| + struct Default {
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const Default& data) {
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct Input_Output_Feature {
|
| + uint8_t data_or_constant:1;
|
| + uint8_t array_or_variable:1;
|
| + uint8_t absolute_or_relative:1;
|
| + uint8_t wrap:1;
|
| + uint8_t linear:1;
|
| + uint8_t preferred:1;
|
| + uint8_t null:1;
|
| + uint8_t reserved_1:1;
|
| + uint8_t bit_field_or_buffer:1;
|
| + uint8_t reserved_2:1;
|
| +
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const Input_Output_Feature& data) {
|
| + if (data.data_or_constant)
|
| + os << "Con";
|
| + else
|
| + os << "Dat";
|
| + if (data.array_or_variable)
|
| + os << "|Arr";
|
| + else
|
| + os << "|Var";
|
| + if (data.absolute_or_relative)
|
| + os << "|Abs";
|
| + else
|
| + os << "|Rel";
|
| + if (data.wrap)
|
| + os << "|Wrp";
|
| + else
|
| + os << "|NoWrp";
|
| + if (data.linear)
|
| + os << "|NoLin";
|
| + else
|
| + os << "|Lin";
|
| + if (data.preferred)
|
| + os << "|NoPrf";
|
| + else
|
| + os << "|Prf";
|
| + if (data.null)
|
| + os << "|Null";
|
| + else
|
| + os << "|NoNull";
|
| + if (data.bit_field_or_buffer)
|
| + os << "|Buff";
|
| + else
|
| + os << "|BitF";
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct Collection {
|
| +
|
| + enum CollectionType {
|
| + kCollectionTypePhysical,
|
| + kCollectionTypeApplication,
|
| + kCollectionTypeLogical,
|
| + kCollectionTypeReport,
|
| + kCollectionTypeNamedArray,
|
| + kCollectionTypeUsageSwitch,
|
| + kCollectionTypeUsageModifier,
|
| + kCollectionTypeReserved,
|
| + kCollectionTypeVendor
|
| + };
|
| +
|
| + uint8_t value;
|
| +
|
| + CollectionType collectionType() const {
|
| + switch (value) {
|
| + case 0x00:
|
| + return kCollectionTypePhysical;
|
| + case 0x01:
|
| + return kCollectionTypePhysical;
|
| + case 0x02:
|
| + return kCollectionTypePhysical;
|
| + case 0x03:
|
| + return kCollectionTypePhysical;
|
| + case 0x04:
|
| + return kCollectionTypePhysical;
|
| + case 0x05:
|
| + return kCollectionTypePhysical;
|
| + case 0x06:
|
| + return kCollectionTypePhysical;
|
| + default:
|
| + break;
|
| + }
|
| +
|
| + if (0x80 < value && value < 0xFF)
|
| + return kCollectionTypeVendor;
|
| +
|
| + return kCollectionTypeReserved;
|
| + }
|
| +
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const Collection& data) {
|
| + switch (data.collectionType()) {
|
| + case kCollectionTypePhysical:
|
| + os << "Physical";
|
| + break;
|
| + case kCollectionTypeApplication:
|
| + os << "Application";
|
| + break;
|
| + case kCollectionTypeLogical:
|
| + os << "Logical";
|
| + break;
|
| + case kCollectionTypeReport:
|
| + os << "Report";
|
| + break;
|
| + case kCollectionTypeNamedArray:
|
| + os << "Named Array";
|
| + break;
|
| + case kCollectionTypeUsageSwitch:
|
| + os << "Usage Switch";
|
| + break;
|
| + case kCollectionTypeUsageModifier:
|
| + os << "Usage Modifier";
|
| + break;
|
| + case kCollectionTypeReserved:
|
| + os << "Reserved";
|
| + break;
|
| + case kCollectionTypeVendor:
|
| + os << "Vendor";
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + break;
|
| + }
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct EndCollection {
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const EndCollection& data) {
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + // (Short) Global Items
|
| +
|
| + struct UsagePage {
|
| + uint16_t value;
|
| +
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const UsagePage& data) {
|
| + HidUsageAndPage::Page page = (HidUsageAndPage::Page)data.value;
|
| + os << page;
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct LogicalMinimum {
|
| + int32_t value;
|
| +
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const LogicalMinimum& data) {
|
| + os << data.value;
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct LogicalMaximum {
|
| + int32_t value;
|
| +
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const LogicalMaximum& data) {
|
| + os << data.value;
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct PhysicalMinimum {
|
| + int32_t value;
|
| +
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const PhysicalMinimum& data) {
|
| + os << data.value;
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct PhysicalMaximum {
|
| + int32_t value;
|
| +
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const PhysicalMaximum& data) {
|
| + os << data.value;
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct UnitExponent {
|
| + uint32_t value;
|
| +
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const UnitExponent& data) {
|
| + os << data.value;
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct Unit {
|
| + uint32_t value;
|
| +
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const Unit& data) {
|
| + os << data.value;
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct ReportSize {
|
| + uint32_t value;
|
| +
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const ReportSize& data) {
|
| + os << data.value;
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct ReportId {
|
| + uint32_t value;
|
| +
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const ReportId& data) {
|
| + os << "0x" << std::hex << std::uppercase << data.value;
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct ReportCount {
|
| + uint32_t value;
|
| +
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const ReportCount& data) {
|
| + os << data.value;
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct Push {
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const Push& data) {
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct Pop {
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const Pop& data) {
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + // (Short) Local Items
|
| +
|
| + struct Usage {
|
| + uint16_t value;
|
| +
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const Usage& data) {
|
| + os << "0x" << std::hex << std::uppercase << data.value;
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct UsageMinimum {
|
| + uint16_t value;
|
| +
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const UsageMinimum& data) {
|
| + os << "0x" << std::hex << std::uppercase << data.value;
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct UsageMaximum {
|
| + uint16_t value;
|
| +
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const UsageMaximum& data) {
|
| + os << "0x" << std::hex << std::uppercase << data.value;
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct DesignatorIndex {
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const DesignatorIndex& data) {
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct DesignatorMinimum {
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const DesignatorMinimum& data) {
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct DesignatorMaximum {
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const DesignatorMaximum& data) {
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct StringIndex {
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const StringIndex& data) {
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct StringMinimum {
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const StringMinimum& data) {
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct StringMaximum {
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const StringMaximum& data) {
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + struct Delimiter {
|
| + private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const Delimiter& data) {
|
| + return os;
|
| + }
|
| + };
|
| +
|
| + // (Long) Reserved items
|
| + // nothing for now
|
| +
|
| + // Data union
|
| +
|
| + struct Data {
|
| + union u {
|
| + // (Short) Main items
|
| + Default none;
|
| + Input_Output_Feature input;
|
| + Input_Output_Feature output;
|
| + Input_Output_Feature feature;
|
| + Collection collection;
|
| + EndCollection end_collection;
|
| + // (Short) Global items
|
| + UsagePage usage_page;
|
| + LogicalMinimum logical_minimum;
|
| + LogicalMaximum logical_maximum;
|
| + PhysicalMinimum physical_minimum;
|
| + PhysicalMaximum physical_maximum;
|
| + UnitExponent unit_exponent;
|
| + Unit unit;
|
| + ReportSize report_size;
|
| + ReportId report_id;
|
| + ReportCount report_count;
|
| + Push push;
|
| + Pop pop;
|
| + // (Short) Local items
|
| + Usage usage;
|
| + UsageMinimum usage_minimum;
|
| + UsageMaximum usage_maximum;
|
| + DesignatorIndex designator_index;
|
| + DesignatorMinimum designator_minimum;
|
| + DesignatorMaximum designator_maximum;
|
| + StringIndex string_index;
|
| + StringMinimum string_minimum;
|
| + StringMaximum string_maximum;
|
| + Delimiter delimiter;
|
| + // (Long) Reserved items
|
| + // nothing for now
|
| + };
|
| + };
|
| +
|
| +#pragma pack (pop)
|
| +
|
| + HidReportDescriptorItem(const uint8_t* bytes,
|
| + HidReportDescriptorItem* previous = NULL);
|
| + ~HidReportDescriptorItem();
|
| +
|
| + HidReportDescriptorItem* previous() const { return previous_; };
|
| + HidReportDescriptorItem* next() const { return next_; };
|
| + HidReportDescriptorItem* parent() const { return parent_; };
|
| + size_t depth() const;
|
| +
|
| + bool isLong() const;
|
| + size_t headerSize() const;
|
| + size_t payloadSize() const;
|
| + size_t size() const;
|
| +
|
| + Header* header() const;
|
| + LongHeader* longHeader() const;
|
| +
|
| + Tag tag() const;
|
| + Data* data() const;
|
| +
|
| +private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const HidReportDescriptorItem& item) {
|
| + Tag tg = item.tag();
|
| + Data* dt = item.data();
|
| +
|
| + std::ostringstream sstr;
|
| + sstr << tg;
|
| + sstr << " (";
|
| +
|
| + long pos = sstr.tellp();
|
| + switch (tg) {
|
| + case kTagDefault:
|
| + sstr << *(Default*)dt;
|
| + break;
|
| + case kTagInput:
|
| + case kTagOutput:
|
| + case kTagFeature:
|
| + sstr << *(Input_Output_Feature*)dt;
|
| + break;
|
| + case kTagCollection:
|
| + sstr << *(Collection*)dt;
|
| + break;
|
| + case kTagEndCollection:
|
| + sstr << *(EndCollection*)dt;
|
| + break;
|
| + case kTagUsagePage:
|
| + sstr << *(UsagePage*)dt;
|
| + break;
|
| + case kTagLogicalMinimum:
|
| + sstr << *(LogicalMinimum*)dt;
|
| + break;
|
| + case kTagLogicalMaximum:
|
| + sstr << *(LogicalMaximum*)dt;
|
| + break;
|
| + case kTagPhysicalMinimum:
|
| + sstr << *(PhysicalMinimum*)dt;
|
| + break;
|
| + case kTagPhysicalMaximum:
|
| + sstr << *(PhysicalMaximum*)dt;
|
| + break;
|
| + case kTagUnitExponent:
|
| + sstr << *(UnitExponent*)dt;
|
| + break;
|
| + case kTagUnit:
|
| + sstr << *(Unit*)dt;
|
| + break;
|
| + case kTagReportSize:
|
| + sstr << *(ReportSize*)dt;
|
| + break;
|
| + case kTagReportId:
|
| + sstr << *(ReportId*)dt;
|
| + break;
|
| + case kTagReportCount:
|
| + sstr << *(ReportCount*)dt;
|
| + break;
|
| + case kTagPush:
|
| + sstr << *(Push*)dt;
|
| + break;
|
| + case kTagPop:
|
| + sstr << *(Pop*)dt;
|
| + break;
|
| + case kTagUsage:
|
| + sstr << *(Usage*)dt;
|
| + break;
|
| + case kTagUsageMinimum:
|
| + sstr << *(UsageMinimum*)dt;
|
| + break;
|
| + case kTagUsageMaximum:
|
| + sstr << *(UsageMaximum*)dt;
|
| + break;
|
| + case kTagDesignatorIndex:
|
| + sstr << *(DesignatorIndex*)dt;
|
| + break;
|
| + case kTagDesignatorMinimum:
|
| + sstr << *(DesignatorMinimum*)dt;
|
| + break;
|
| + case kTagDesignatorMaximum:
|
| + sstr << *(DesignatorMaximum*)dt;
|
| + break;
|
| + case kTagStringIndex:
|
| + sstr << *(StringIndex*)dt;
|
| + break;
|
| + case kTagStringMinimum:
|
| + sstr << *(StringMinimum*)dt;
|
| + break;
|
| + case kTagStringMaximum:
|
| + sstr << *(StringMaximum*)dt;
|
| + break;
|
| + case kTagDelimiter:
|
| + sstr << *(Delimiter*)dt;
|
| + break;
|
| + case kTagLong:
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + break;
|
| + }
|
| +
|
| + if (pos == sstr.tellp()) {
|
| + std::string str = sstr.str();
|
| + str.erase(str.end() - 2, str.end());
|
| + os << str;
|
| + } else {
|
| + os << sstr.str() << ")";
|
| + }
|
| +
|
| + return os;
|
| + }
|
| +
|
| + const uint8_t* bytes_;
|
| + HidReportDescriptorItem* previous_;
|
| + HidReportDescriptorItem* next_;
|
| + HidReportDescriptorItem* parent_;
|
| +};
|
| +
|
| +// HID report descriptor.
|
| +// See section 6.2.2 of HID specifications (v1.11).
|
| +class HidReportDescriptor {
|
| +
|
| +private:
|
| + static const char kIndentChar;
|
| +
|
| +public:
|
| + HidReportDescriptor(const uint8_t* bytes, size_t size);
|
| + ~HidReportDescriptor();
|
| +
|
| + const std::vector<HidReportDescriptorItem*>& items() const;
|
| + std::vector<HidUsageAndPage> topLevelCollections() const;
|
| +
|
| +private:
|
| + friend std::ostream& operator<<(std::ostream& os,
|
| + const HidReportDescriptor& descriptor) {
|
| + for (std::vector<HidReportDescriptorItem*>::const_iterator items_iter =
|
| + descriptor.items_.begin();
|
| + items_iter != descriptor.items_.end();
|
| + ++items_iter) {
|
| + HidReportDescriptorItem* item = *items_iter;
|
| + size_t indentLevel = item->depth();
|
| + for (size_t i = 0; i < indentLevel; i++)
|
| + os << kIndentChar;
|
| + os << *item << std::endl;
|
| + }
|
| + return os;
|
| + }
|
| +
|
| + const uint8_t* bytes_;
|
| + size_t size_;
|
| + std::vector<HidReportDescriptorItem*> items_;
|
| +};
|
| +
|
| +} // namespace device
|
| +
|
| +#endif // DEVICE_HID_HID_REPORT_DESCRIPTOR_H_
|
|
|