summaryrefslogtreecommitdiffstats
path: root/chromium/device/hid/hid_report_descriptor_item.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/device/hid/hid_report_descriptor_item.cc')
-rw-r--r--chromium/device/hid/hid_report_descriptor_item.cc112
1 files changed, 112 insertions, 0 deletions
diff --git a/chromium/device/hid/hid_report_descriptor_item.cc b/chromium/device/hid/hid_report_descriptor_item.cc
new file mode 100644
index 00000000000..bdd03ce0ebd
--- /dev/null
+++ b/chromium/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