| 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..f32bb29b76f7108b6c574ff327222c64b7958bef
|
| --- /dev/null
|
| +++ b/device/hid/hid_report_descriptor.cc
|
| @@ -0,0 +1,154 @@
|
| +// 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) {
|
| + 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)
|
| + 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
|
|
|