Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / device / hid / hid_report_descriptor.cc
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.h"
6
7 #include "base/stl_util.h"
8
9 namespace device {
10
11 namespace {
12
13 const int kBitsPerByte = 8;
14
15 }  // namespace
16
17 HidReportDescriptor::HidReportDescriptor(const uint8_t* bytes, size_t size) {
18   size_t header_index = 0;
19   HidReportDescriptorItem* item = NULL;
20   while (header_index < size) {
21     item = new HidReportDescriptorItem(&bytes[header_index], item);
22     items_.push_back(linked_ptr<HidReportDescriptorItem>(item));
23     header_index += item->GetSize();
24   }
25 }
26
27 HidReportDescriptor::~HidReportDescriptor() {}
28
29 void HidReportDescriptor::GetDetails(
30     std::vector<HidCollectionInfo>* top_level_collections,
31     bool* has_report_id,
32     int* max_input_report_size,
33     int* max_output_report_size,
34     int* max_feature_report_size) {
35   DCHECK(top_level_collections);
36   DCHECK(max_input_report_size);
37   DCHECK(max_output_report_size);
38   DCHECK(max_feature_report_size);
39   STLClearObject(top_level_collections);
40
41   *has_report_id = false;
42   *max_input_report_size = 0;
43   *max_output_report_size = 0;
44   *max_feature_report_size = 0;
45
46   // Global tags data:
47   HidUsageAndPage::Page current_usage_page = HidUsageAndPage::kPageUndefined;
48   int current_report_count = 0;
49   int cached_report_count = 0;
50   int current_report_size = 0;
51   int cached_report_size = 0;
52   int current_input_report_size = 0;
53   int current_output_report_size = 0;
54   int current_feature_report_size = 0;
55
56   // Local tags data:
57   uint16_t current_usage = 0;
58
59   for (std::vector<linked_ptr<HidReportDescriptorItem> >::const_iterator
60            items_iter = items().begin();
61        items_iter != items().end();
62        ++items_iter) {
63     linked_ptr<HidReportDescriptorItem> current_item = *items_iter;
64
65     switch (current_item->tag()) {
66       // Main tags:
67       case HidReportDescriptorItem::kTagCollection:
68         if (!current_item->parent()) {
69           // This is a top-level collection.
70           HidCollectionInfo collection;
71           collection.usage = HidUsageAndPage(current_usage, current_usage_page);
72           top_level_collections->push_back(collection);
73         }
74         break;
75       case HidReportDescriptorItem::kTagInput:
76         current_input_report_size += current_report_count * current_report_size;
77         break;
78       case HidReportDescriptorItem::kTagOutput:
79         current_output_report_size +=
80             current_report_count * current_report_size;
81         break;
82       case HidReportDescriptorItem::kTagFeature:
83         current_feature_report_size +=
84             current_report_count * current_report_size;
85         break;
86
87       // Global tags:
88       case HidReportDescriptorItem::kTagUsagePage:
89         current_usage_page =
90             (HidUsageAndPage::Page)current_item->GetShortData();
91         break;
92       case HidReportDescriptorItem::kTagReportId:
93         if (top_level_collections->size() > 0) {
94           // Store report ID.
95           top_level_collections->back().report_ids.insert(
96               current_item->GetShortData());
97           *has_report_id = true;
98
99           // Update max report sizes.
100           *max_input_report_size =
101               std::max(*max_input_report_size, current_input_report_size);
102           *max_output_report_size =
103               std::max(*max_output_report_size, current_output_report_size);
104           *max_feature_report_size =
105               std::max(*max_feature_report_size, current_feature_report_size);
106
107           // Reset the report sizes for the next report ID.
108           current_input_report_size = 0;
109           current_output_report_size = 0;
110           current_feature_report_size = 0;
111         }
112         break;
113       case HidReportDescriptorItem::kTagReportCount:
114         current_report_count = current_item->GetShortData();
115         break;
116       case HidReportDescriptorItem::kTagReportSize:
117         current_report_size = current_item->GetShortData();
118         break;
119       case HidReportDescriptorItem::kTagPush:
120         // Cache report count and size.
121         cached_report_count = current_report_count;
122         cached_report_size = current_report_size;
123         break;
124       case HidReportDescriptorItem::kTagPop:
125         // Restore cache.
126         current_report_count = cached_report_count;
127         current_report_size = cached_report_size;
128         // Reset cache.
129         cached_report_count = 0;
130         cached_report_size = 0;
131         break;
132
133       // Local tags:
134       case HidReportDescriptorItem::kTagUsage:
135         current_usage = current_item->GetShortData();
136         break;
137
138       default:
139         break;
140     }
141   }
142
143   // Update max report sizes
144   *max_input_report_size =
145       std::max(*max_input_report_size, current_input_report_size);
146   *max_output_report_size =
147       std::max(*max_output_report_size, current_output_report_size);
148   *max_feature_report_size =
149       std::max(*max_feature_report_size, current_feature_report_size);
150
151   // Convert bits into bytes
152   *max_input_report_size /= kBitsPerByte;
153   *max_output_report_size /= kBitsPerByte;
154   *max_feature_report_size /= kBitsPerByte;
155 }
156
157 }  // namespace device