Home | History | Annotate | Download | only in hid
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "device/hid/hid_report_descriptor_item.h"
      6 
      7 #include <stdlib.h>
      8 
      9 #include "base/logging.h"
     10 #include "device/hid/hid_usage_and_page.h"
     11 
     12 namespace device {
     13 
     14 namespace {
     15 
     16 struct Header {
     17   uint8_t size : 2;
     18   uint8_t type : 2;
     19   uint8_t tag : 4;
     20 };
     21 
     22 }  // namespace
     23 
     24 HidReportDescriptorItem::HidReportDescriptorItem(
     25     const uint8_t* bytes,
     26     HidReportDescriptorItem* previous)
     27     : previous_(previous), next_(NULL), parent_(NULL), shortData_(0) {
     28   Header* header = (Header*)&bytes[0];
     29   tag_ = (Tag)(header->tag << 2 | header->type);
     30 
     31   if (IsLong()) {
     32     // In a long item, payload size is the second byte.
     33     payload_size_ = bytes[1];
     34   } else {
     35     payload_size_ = header->size;
     36     DCHECK(payload_size_ <= sizeof(shortData_));
     37     memcpy(&shortData_, &bytes[GetHeaderSize()], payload_size());
     38   }
     39 
     40   if (previous) {
     41     DCHECK(!previous->next_);
     42     previous->next_ = this;
     43     switch (previous->tag()) {
     44       case kTagCollection:
     45         parent_ = previous;
     46         break;
     47       default:
     48         break;
     49     }
     50     if (!parent_) {
     51       switch (tag()) {
     52         case kTagEndCollection:
     53           if (previous->parent()) {
     54             parent_ = previous->parent()->parent();
     55           }
     56           break;
     57         default:
     58           parent_ = previous->parent();
     59           break;
     60       }
     61     }
     62   }
     63 }
     64 
     65 size_t HidReportDescriptorItem::GetDepth() const {
     66   HidReportDescriptorItem* parent_item = parent();
     67   if (parent_item)
     68     return parent_item->GetDepth() + 1;
     69   return 0;
     70 }
     71 
     72 bool HidReportDescriptorItem::IsLong() const { return tag() == kTagLong; }
     73 
     74 size_t HidReportDescriptorItem::GetHeaderSize() const {
     75   return IsLong() ? 3 : 1;
     76 }
     77 
     78 size_t HidReportDescriptorItem::GetSize() const {
     79   return GetHeaderSize() + payload_size();
     80 }
     81 
     82 uint32_t HidReportDescriptorItem::GetShortData() const {
     83   DCHECK(!IsLong());
     84   return shortData_;
     85 }
     86 
     87 HidReportDescriptorItem::CollectionType
     88 HidReportDescriptorItem::GetCollectionTypeFromValue(uint32_t value) {
     89   switch (value) {
     90     case 0x00:
     91       return kCollectionTypePhysical;
     92     case 0x01:
     93       return kCollectionTypeApplication;
     94     case 0x02:
     95       return kCollectionTypeLogical;
     96     case 0x03:
     97       return kCollectionTypeReport;
     98     case 0x04:
     99       return kCollectionTypeNamedArray;
    100     case 0x05:
    101       return kCollectionTypeUsageSwitch;
    102     case 0x06:
    103       return kCollectionTypeUsageModifier;
    104     default:
    105       break;
    106   }
    107   if (0x80 < value && value < 0xFF)
    108     return kCollectionTypeVendor;
    109   return kCollectionTypeReserved;
    110 }
    111 
    112 }  // namespace device
    113