Index: device/hid/hid_report_descriptor.cc |
diff --git a/device/hid/hid_report_descriptor.cc b/device/hid/hid_report_descriptor.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..de6e710ada5f7190647f2182a0fcf82b7acc254f |
--- /dev/null |
+++ b/device/hid/hid_report_descriptor.cc |
@@ -0,0 +1,152 @@ |
+// 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.h" |
+ |
+#include <stdlib.h> |
+ |
+#include <algorithm> |
+ |
+using namespace std; |
+ |
+namespace device { |
+ |
+HidReportDescriptorItem::HidReportDescriptorItem( |
+ const uint8_t* bytes, |
+ HidReportDescriptorItem* previous) |
+ : bytes_(bytes), previous_(previous), parent_(NULL) { |
+ |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
Sorry - I guess the auto-format tool does not do t
jracle (use Gerrit)
2014/04/16 16:39:19
Oh sorry, got it now.
|
+ if (previous) { |
+ |
+ 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; |
+ } |
+ } |
+ } |
+} |
+ |
+HidReportDescriptorItem::~HidReportDescriptorItem() {} |
+ |
+size_t HidReportDescriptorItem::depth() const { |
+ HidReportDescriptorItem* parnt = parent(); |
+ if (parnt) |
Ken Rockot(use gerrit already)
2014/04/15 21:18:37
Please rename parnt. As a general rule, always pre
jracle (use Gerrit)
2014/04/16 16:39:19
Sorry, was done in separate CL. I violated my own
|
+ return parnt->depth() + 1; |
+ return 0; |
+} |
+ |
+bool HidReportDescriptorItem::isLong() const { return tag() == kTagLong; } |
+ |
+size_t HidReportDescriptorItem::headerSize() const { return isLong() ? 3 : 1; } |
+ |
+size_t HidReportDescriptorItem::payloadSize() const { |
+ return isLong() ? longHeader()->data_size : header()->size; |
+} |
+ |
+size_t HidReportDescriptorItem::size() const { |
+ return headerSize() + payloadSize(); |
+} |
+ |
+HidReportDescriptorItem::Header* HidReportDescriptorItem::header() const { |
+ return (HidReportDescriptorItem::Header*)(&bytes_[0]); |
+} |
+ |
+HidReportDescriptorItem::LongHeader* HidReportDescriptorItem::longHeader() |
+ const { |
+ DCHECK(isLong()); |
+ return (HidReportDescriptorItem::LongHeader*)(&bytes_[0]); |
+} |
+ |
+HidReportDescriptorItem::Tag HidReportDescriptorItem::tag() const { |
+ return (HidReportDescriptorItem::Tag)(header()->tag << 2 | header()->type); |
+} |
+ |
+HidReportDescriptorItem::Data* HidReportDescriptorItem::data() const { |
+ void* data = malloc(sizeof(HidReportDescriptorItem::Data)); |
+ memset(data, 0, sizeof(data)); |
+ memcpy(data, &bytes_[headerSize()], payloadSize()); |
+ return (HidReportDescriptorItem::Data*)data; |
+} |
+ |
+HidReportDescriptor::HidReportDescriptor(const uint8_t* bytes, size_t size) |
+ : bytes_(bytes), size_(size) { |
+ size_t header_index = 0; |
+ HidReportDescriptorItem* item = NULL; |
+ while (header_index < size_) { |
+ item = new HidReportDescriptorItem(&bytes_[header_index], item); |
+ items_.push_back(item); |
+ header_index += item->size(); |
+ } |
+} |
+ |
+const char HidReportDescriptor::kIndentChar = ' '; |
+ |
+HidReportDescriptor::~HidReportDescriptor() { |
+ for (vector<HidReportDescriptorItem*>::const_iterator items_iter = |
+ items_.begin(); |
+ items_iter != items_.end(); |
+ ++items_iter) { |
+ delete *items_iter; |
+ } |
+ items_.clear(); |
+} |
+ |
+const std::vector<HidReportDescriptorItem*>& HidReportDescriptor::items() |
+ const { |
+ return items_; |
+} |
+ |
+std::vector<HidUsageAndPage> HidReportDescriptor::topLevelCollections() const { |
+ |
+ std::vector<HidUsageAndPage> tlcs; |
+ |
+ for (std::vector<HidReportDescriptorItem*>::const_iterator items_iter = |
+ items_.begin(); |
+ items_iter != items_.end(); |
+ ++items_iter) { |
+ HidReportDescriptorItem* item = *items_iter; |
+ |
+ bool isTopLevelCollection = |
+ item->tag() == HidReportDescriptorItem::kTagCollection && |
+ item->parent() == NULL; |
+ |
+ if (isTopLevelCollection) { |
+ HidReportDescriptorItem* usage = item->previous(); |
+ HidReportDescriptorItem* usage_page = usage->previous(); |
+ |
+ HidUsageAndPage usage_and_page; |
+ if (usage && usage->tag() == HidReportDescriptorItem::kTagUsage) { |
+ usage_and_page.usage = |
+ ((HidReportDescriptorItem::Usage*)usage->data())->value; |
+ } |
+ if (usage_page && |
+ usage_page->tag() == HidReportDescriptorItem::kTagUsagePage) { |
+ usage_and_page.usage_page = |
+ ((HidReportDescriptorItem::UsagePage*)usage_page->data())->value; |
+ } |
+ tlcs.push_back(usage_and_page); |
+ } |
+ } |
+ |
+ return tlcs; |
+} |
+ |
+} // namespace device |