Index: device/hid/hid_report_descriptor_item.cc |
diff --git a/device/hid/hid_report_descriptor_item.cc b/device/hid/hid_report_descriptor_item.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..bdd03ce0ebd351619db48252c09d39b963455af2 |
--- /dev/null |
+++ b/device/hid/hid_report_descriptor_item.cc |
@@ -0,0 +1,112 @@ |
+// 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. |
+ |
+#include "device/hid/hid_report_descriptor_item.h" |
+ |
+#include <stdlib.h> |
+ |
+#include "base/logging.h" |
+#include "device/hid/hid_usage_and_page.h" |
+ |
+namespace device { |
+ |
+namespace { |
+ |
+struct Header { |
+ uint8_t size : 2; |
+ uint8_t type : 2; |
+ uint8_t tag : 4; |
+}; |
+ |
+} // namespace |
+ |
+HidReportDescriptorItem::HidReportDescriptorItem( |
+ const uint8_t* bytes, |
+ HidReportDescriptorItem* previous) |
+ : previous_(previous), next_(NULL), parent_(NULL), shortData_(0) { |
+ Header* header = (Header*)&bytes[0]; |
+ tag_ = (Tag)(header->tag << 2 | header->type); |
+ |
+ if (IsLong()) { |
+ // In a long item, payload size is the second byte. |
+ payload_size_ = bytes[1]; |
+ } else { |
+ payload_size_ = header->size; |
+ DCHECK(payload_size_ <= sizeof(shortData_)); |
+ memcpy(&shortData_, &bytes[GetHeaderSize()], payload_size()); |
+ } |
+ |
+ if (previous) { |
+ DCHECK(!previous->next_); |
+ previous->next_ = this; |
+ switch (previous->tag()) { |
+ case kTagCollection: |
+ parent_ = previous; |
+ break; |
+ default: |
+ break; |
+ } |
+ if (!parent_) { |
+ switch (tag()) { |
+ case kTagEndCollection: |
+ if (previous->parent()) { |
+ parent_ = previous->parent()->parent(); |
+ } |
+ break; |
+ default: |
+ parent_ = previous->parent(); |
+ break; |
+ } |
+ } |
+ } |
+} |
+ |
+size_t HidReportDescriptorItem::GetDepth() const { |
+ HidReportDescriptorItem* parent_item = parent(); |
+ if (parent_item) |
+ return parent_item->GetDepth() + 1; |
+ return 0; |
+} |
+ |
+bool HidReportDescriptorItem::IsLong() const { return tag() == kTagLong; } |
+ |
+size_t HidReportDescriptorItem::GetHeaderSize() const { |
+ return IsLong() ? 3 : 1; |
+} |
+ |
+size_t HidReportDescriptorItem::GetSize() const { |
+ return GetHeaderSize() + payload_size(); |
+} |
+ |
+uint32_t HidReportDescriptorItem::GetShortData() const { |
+ DCHECK(!IsLong()); |
+ return shortData_; |
+} |
+ |
+HidReportDescriptorItem::CollectionType |
+HidReportDescriptorItem::GetCollectionTypeFromValue(uint32_t value) { |
+ 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; |
+} |
+ |
+} // namespace device |