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..2d06b08641e54d844328f3ecde099b60dc311ba8 |
--- /dev/null |
+++ b/device/hid/hid_report_descriptor.h |
@@ -0,0 +1,803 @@ |
+// 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 { |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
I think this is large enough that it deserves its
jracle (use Gerrit)
2014/04/16 16:39:19
Sure, done.
|
+ |
+#pragma pack(push, 1) |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
Please do not use packed structs to map onto a dat
jracle (use Gerrit)
2014/04/16 16:39:19
Got your point, I will refactor in next patch set.
|
+ |
+ public: |
+ enum Type { |
+ kTypeMain = 0, |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
Please move Type into the next public block since
|
+ kTypeGlobal = 1, |
+ kTypeLocal = 2, |
+ kTypeReserved = 3 |
+ }; |
+ |
+ private: |
+ // Tags |
+ |
+ enum MainTag { |
+ kMainTagDefault = 0x00, // 0000 |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
As these are only used internally, please move the
|
+ 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) { |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
Please do not inline this, and in fact it doesn't
jracle (use Gerrit)
2014/04/16 16:39:19
Done
|
+ 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 { |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
I'm jumping around this CL a lot as I get a better
jracle (use Gerrit)
2014/04/16 16:39:19
Got it, no point to show those details. Confusing.
|
+ 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 { |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
Default what? A more descriptive name may be in or
jracle (use Gerrit)
2014/04/16 16:39:19
Oops. Not meaningful.
|
+ private: |
+ friend std::ostream& operator<<(std::ostream& os, const Default& data) { |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
See the comment in Input_Output_Feature about movi
jracle (use Gerrit)
2014/04/16 16:39:19
Indeed.
|
+ return os; |
+ } |
+ }; |
+ |
+ struct Input_Output_Feature { |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
InputOutputFeature, please
|
+ uint8_t data_or_constant : 1; |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
Same as previous comments. I know it's a lot of fi
|
+ 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) { |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
Please do not inline this. In fact once again, thi
|
+ 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 { |
+ |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
Whitespace
|
+ enum CollectionType { |
+ kCollectionTypePhysical, |
+ kCollectionTypeApplication, |
+ kCollectionTypeLogical, |
+ kCollectionTypeReport, |
+ kCollectionTypeNamedArray, |
+ kCollectionTypeUsageSwitch, |
+ kCollectionTypeUsageModifier, |
+ kCollectionTypeReserved, |
+ kCollectionTypeVendor |
+ }; |
+ |
+ uint8_t value; |
+ |
+ CollectionType collectionType() const { |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
Please do not inline this. Same goes for the rest
|
+ 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 { |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
There's a lot of code duplication going on here an
|
+ 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); |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
Please, no default argument values. Please specify
jracle (use Gerrit)
2014/04/16 16:39:19
Done
|
+ ~HidReportDescriptorItem(); |
+ |
+ HidReportDescriptorItem* previous() const { |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
Please make it clear that neither this item nor th
|
+ return previous_; |
+ }; |
+ HidReportDescriptorItem* next() const { |
+ return next_; |
+ }; |
+ HidReportDescriptorItem* parent() const { |
+ return parent_; |
+ }; |
+ size_t depth() const; |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
GetDepth() please. Lowercase names are for trivial
|
+ |
+ bool isLong() const; |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
IsLong() please.
|
+ size_t headerSize() const; |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
GetHeaderSize() please.
|
+ size_t payloadSize() const; |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
GetPayloadSize() please.
|
+ size_t size() const; |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
GetSize()
Also because none of these are trivial
|
+ |
+ Header* header() const; |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
This (and longHeader) make me extremely uncomforta
jracle (use Gerrit)
2014/04/16 16:39:19
Now private in next patch-set, and accessed by val
|
+ LongHeader* longHeader() const; |
+ |
+ Tag tag() const; |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
GetTag() please.
|
+ Data* data() const; |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
Since Data is a POD type, and you can change it so
jracle (use Gerrit)
2014/04/16 16:39:19
Data is actually known only for short items.
It ha
|
+ |
+ private: |
+ friend std::ostream& operator<<(std::ostream& os, |
+ const HidReportDescriptorItem& item) { |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
Please see base/strings/stringprintf.h for the bas
jracle (use Gerrit)
2014/04/16 16:39:19
This I didn't catch yet, can you handle it in a ne
|
+ 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; |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
items is a trivial accessor; please feel free to i
jracle (use Gerrit)
2014/04/16 16:39:19
OK
|
+ std::vector<HidUsageAndPage> topLevelCollections() const; |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
GetTopLevelCollections() please. This is not a tri
jracle (use Gerrit)
2014/04/16 16:39:19
OK
|
+ |
+ private: |
+ friend std::ostream& operator<<(std::ostream& os, |
+ const HidReportDescriptor& descriptor) { |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
Please do not inline this definition. In fact it d
|
+ 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_; |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
Please use linked_ptr here
std::vector<linked_ptr
jracle (use Gerrit)
2014/04/16 16:39:19
Indeed
|
+}; |
+ |
+} // namespace device |
+ |
+#endif // DEVICE_HID_HID_REPORT_DESCRIPTOR_H_ |