// 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 #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 kCollectionTypeApplication; case 0x02: return kCollectionTypeLogical; case 0x03: return kCollectionTypeReport; case 0x04: return kCollectionTypeNamedArray; case 0x05: return kCollectionTypeUsageSwitch; case 0x06: return kCollectionTypeUsageModifier; default: break; } if (0x80 < value && value < 0xFF) return kCollectionTypeVendor; return kCollectionTypeReserved; } } // namespace device