mac: Let IPhotoDataProvider::GetAlbumNames() return albums in a deterministic order.
[chromium-blink-merge.git] / device / hid / hid_report_descriptor.cc
blobf211eb468e639f3f9b6aed81916a1c3c2ea37eac
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.
5 #include "device/hid/hid_report_descriptor.h"
7 #include "base/stl_util.h"
9 namespace device {
11 namespace {
13 const int kBitsPerByte = 8;
15 } // namespace
17 HidReportDescriptor::HidReportDescriptor(const std::vector<uint8>& bytes) {
18 size_t header_index = 0;
19 HidReportDescriptorItem* item = NULL;
20 while (header_index < bytes.size()) {
21 item = new HidReportDescriptorItem(&bytes[header_index], item);
22 items_.push_back(linked_ptr<HidReportDescriptorItem>(item));
23 header_index += item->GetSize();
27 HidReportDescriptor::~HidReportDescriptor() {}
29 void HidReportDescriptor::GetDetails(
30 std::vector<HidCollectionInfo>* top_level_collections,
31 bool* has_report_id,
32 size_t* max_input_report_size,
33 size_t* max_output_report_size,
34 size_t* 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);
41 *has_report_id = false;
42 *max_input_report_size = 0;
43 *max_output_report_size = 0;
44 *max_feature_report_size = 0;
46 // Global tags data:
47 HidUsageAndPage::Page current_usage_page = HidUsageAndPage::kPageUndefined;
48 size_t current_report_count = 0;
49 size_t cached_report_count = 0;
50 size_t current_report_size = 0;
51 size_t cached_report_size = 0;
52 size_t current_input_report_size = 0;
53 size_t current_output_report_size = 0;
54 size_t current_feature_report_size = 0;
56 // Local tags data:
57 uint32_t current_usage = 0;
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;
65 switch (current_item->tag()) {
66 // Main tags:
67 case HidReportDescriptorItem::kTagCollection:
68 if (!current_item->parent() &&
69 (current_usage <= std::numeric_limits<uint16_t>::max())) {
70 // This is a top-level collection.
71 HidCollectionInfo collection;
72 collection.usage = HidUsageAndPage(
73 static_cast<uint16_t>(current_usage), current_usage_page);
74 top_level_collections->push_back(collection);
76 break;
77 case HidReportDescriptorItem::kTagInput:
78 current_input_report_size += current_report_count * current_report_size;
79 break;
80 case HidReportDescriptorItem::kTagOutput:
81 current_output_report_size +=
82 current_report_count * current_report_size;
83 break;
84 case HidReportDescriptorItem::kTagFeature:
85 current_feature_report_size +=
86 current_report_count * current_report_size;
87 break;
89 // Global tags:
90 case HidReportDescriptorItem::kTagUsagePage:
91 current_usage_page =
92 static_cast<HidUsageAndPage::Page>(current_item->GetShortData());
93 break;
94 case HidReportDescriptorItem::kTagReportId:
95 if (top_level_collections->size() > 0) {
96 // Store report ID.
97 top_level_collections->back().report_ids.insert(
98 current_item->GetShortData());
99 *has_report_id = true;
101 // Update max report sizes.
102 *max_input_report_size =
103 std::max(*max_input_report_size, current_input_report_size);
104 *max_output_report_size =
105 std::max(*max_output_report_size, current_output_report_size);
106 *max_feature_report_size =
107 std::max(*max_feature_report_size, current_feature_report_size);
109 // Reset the report sizes for the next report ID.
110 current_input_report_size = 0;
111 current_output_report_size = 0;
112 current_feature_report_size = 0;
114 break;
115 case HidReportDescriptorItem::kTagReportCount:
116 current_report_count = current_item->GetShortData();
117 break;
118 case HidReportDescriptorItem::kTagReportSize:
119 current_report_size = current_item->GetShortData();
120 break;
121 case HidReportDescriptorItem::kTagPush:
122 // Cache report count and size.
123 cached_report_count = current_report_count;
124 cached_report_size = current_report_size;
125 break;
126 case HidReportDescriptorItem::kTagPop:
127 // Restore cache.
128 current_report_count = cached_report_count;
129 current_report_size = cached_report_size;
130 // Reset cache.
131 cached_report_count = 0;
132 cached_report_size = 0;
133 break;
135 // Local tags:
136 case HidReportDescriptorItem::kTagUsage:
137 current_usage = current_item->GetShortData();
138 break;
140 default:
141 break;
145 // Update max report sizes
146 *max_input_report_size =
147 std::max(*max_input_report_size, current_input_report_size);
148 *max_output_report_size =
149 std::max(*max_output_report_size, current_output_report_size);
150 *max_feature_report_size =
151 std::max(*max_feature_report_size, current_feature_report_size);
153 // Convert bits into bytes
154 *max_input_report_size /= kBitsPerByte;
155 *max_output_report_size /= kBitsPerByte;
156 *max_feature_report_size /= kBitsPerByte;
159 } // namespace device