OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "device/hid/hid_report_descriptor.h" | 5 #include "device/hid/hid_report_descriptor.h" |
6 | 6 |
7 #include "base/stl_util.h" | 7 #include "base/stl_util.h" |
8 | 8 |
9 namespace device { | 9 namespace device { |
10 | 10 |
11 namespace { | |
12 | |
13 const int kBitsPerByte = 8; | |
14 | |
15 } // namespace | |
16 | |
17 HidReportDescriptor::HidReportDescriptor(const uint8_t* bytes, size_t size) { | 11 HidReportDescriptor::HidReportDescriptor(const uint8_t* bytes, size_t size) { |
18 size_t header_index = 0; | 12 size_t header_index = 0; |
19 HidReportDescriptorItem* item = NULL; | 13 HidReportDescriptorItem* item = NULL; |
20 while (header_index < size) { | 14 while (header_index < size) { |
21 item = new HidReportDescriptorItem(&bytes[header_index], item); | 15 item = new HidReportDescriptorItem(&bytes[header_index], item); |
22 items_.push_back(linked_ptr<HidReportDescriptorItem>(item)); | 16 items_.push_back(linked_ptr<HidReportDescriptorItem>(item)); |
23 header_index += item->GetSize(); | 17 header_index += item->GetSize(); |
24 } | 18 } |
25 } | 19 } |
26 | 20 |
27 HidReportDescriptor::~HidReportDescriptor() {} | 21 HidReportDescriptor::~HidReportDescriptor() {} |
28 | 22 |
29 void HidReportDescriptor::GetDetails( | 23 void HidReportDescriptor::GetTopLevelCollections( |
30 std::vector<HidCollectionInfo>* top_level_collections, | 24 std::vector<HidUsageAndPage>* topLevelCollections) { |
31 int* max_input_report_size, | 25 DCHECK(topLevelCollections); |
32 int* max_output_report_size, | 26 STLClearObject(topLevelCollections); |
33 int* max_feature_report_size) { | |
34 DCHECK(top_level_collections); | |
35 DCHECK(max_input_report_size); | |
36 DCHECK(max_output_report_size); | |
37 DCHECK(max_feature_report_size); | |
38 STLClearObject(top_level_collections); | |
39 | |
40 *max_input_report_size = 0; | |
41 *max_output_report_size = 0; | |
42 *max_feature_report_size = 0; | |
43 | |
44 // Global tags data: | |
45 HidUsageAndPage::Page current_usage_page = HidUsageAndPage::kPageUndefined; | |
46 int current_report_count = 0; | |
47 int cached_report_count = 0; | |
48 int current_report_size = 0; | |
49 int cached_report_size = 0; | |
50 int current_input_report_size = 0; | |
51 int current_output_report_size = 0; | |
52 int current_feature_report_size = 0; | |
53 | |
54 // Local tags data: | |
55 uint16_t current_usage = 0; | |
56 | 27 |
57 for (std::vector<linked_ptr<HidReportDescriptorItem> >::const_iterator | 28 for (std::vector<linked_ptr<HidReportDescriptorItem> >::const_iterator |
58 items_iter = items().begin(); | 29 items_iter = items().begin(); |
59 items_iter != items().end(); | 30 items_iter != items().end(); |
60 ++items_iter) { | 31 ++items_iter) { |
61 linked_ptr<HidReportDescriptorItem> current_item = *items_iter; | 32 linked_ptr<HidReportDescriptorItem> item = *items_iter; |
62 | 33 |
63 switch (current_item->tag()) { | 34 bool isTopLevelCollection = |
64 // Main tags: | 35 item->tag() == HidReportDescriptorItem::kTagCollection && |
65 case HidReportDescriptorItem::kTagCollection: | 36 item->parent() == NULL; |
66 if (!current_item->parent()) { | |
67 // This is a top-level collection. | |
68 HidCollectionInfo collection; | |
69 collection.usage = HidUsageAndPage(current_usage, current_usage_page); | |
70 top_level_collections->push_back(collection); | |
71 } | |
72 break; | |
73 case HidReportDescriptorItem::kTagInput: | |
74 current_input_report_size += current_report_count * current_report_size; | |
75 break; | |
76 case HidReportDescriptorItem::kTagOutput: | |
77 current_output_report_size += | |
78 current_report_count * current_report_size; | |
79 break; | |
80 case HidReportDescriptorItem::kTagFeature: | |
81 current_feature_report_size += | |
82 current_report_count * current_report_size; | |
83 break; | |
84 | 37 |
85 // Global tags: | 38 if (isTopLevelCollection) { |
86 case HidReportDescriptorItem::kTagUsagePage: | 39 uint16_t collection_usage = 0; |
87 current_usage_page = | 40 HidUsageAndPage::Page collection_usage_page = |
88 (HidUsageAndPage::Page)current_item->GetShortData(); | 41 HidUsageAndPage::kPageUndefined; |
89 break; | |
90 case HidReportDescriptorItem::kTagReportId: | |
91 if (top_level_collections->size() > 0) { | |
92 // Store report ID. | |
93 top_level_collections->back().report_ids.insert( | |
94 current_item->GetShortData()); | |
95 | 42 |
96 // We need to increase report sizes by report ID field length. | 43 HidReportDescriptorItem* usage = item->previous(); |
97 if (current_input_report_size > 0) | 44 if (usage && usage->tag() == HidReportDescriptorItem::kTagUsage) { |
98 current_input_report_size += kBitsPerByte; | 45 collection_usage = usage->GetShortData(); |
99 if (current_output_report_size > 0) | 46 } |
100 current_output_report_size += kBitsPerByte; | |
101 if (current_feature_report_size > 0) | |
102 current_feature_report_size += kBitsPerByte; | |
103 | 47 |
104 // Update max report sizes. | 48 HidReportDescriptorItem* usage_page = usage->previous(); |
105 *max_input_report_size = | 49 if (usage_page && |
106 std::max(*max_input_report_size, current_input_report_size); | 50 usage_page->tag() == HidReportDescriptorItem::kTagUsagePage) { |
107 *max_output_report_size = | 51 collection_usage_page = |
108 std::max(*max_output_report_size, current_output_report_size); | 52 (HidUsageAndPage::Page)usage_page->GetShortData(); |
109 *max_feature_report_size = | 53 } |
110 std::max(*max_feature_report_size, current_feature_report_size); | |
111 | 54 |
112 // Set report sizes to be 1-byte long (report ID field). | 55 topLevelCollections->push_back( |
113 current_input_report_size = 0; | 56 HidUsageAndPage(collection_usage, collection_usage_page)); |
114 current_output_report_size = 0; | |
115 current_feature_report_size = 0; | |
116 } | |
117 break; | |
118 case HidReportDescriptorItem::kTagReportCount: | |
119 current_report_count = current_item->GetShortData(); | |
120 break; | |
121 case HidReportDescriptorItem::kTagReportSize: | |
122 current_report_size = current_item->GetShortData(); | |
123 break; | |
124 case HidReportDescriptorItem::kTagPush: | |
125 // Cache report count and size. | |
126 cached_report_count = current_report_count; | |
127 cached_report_size = current_report_size; | |
128 break; | |
129 case HidReportDescriptorItem::kTagPop: | |
130 // Restore cache. | |
131 current_report_count = cached_report_count; | |
132 current_report_size = cached_report_size; | |
133 // Reset cache. | |
134 cached_report_count = 0; | |
135 cached_report_size = 0; | |
136 break; | |
137 | |
138 // Local tags: | |
139 case HidReportDescriptorItem::kTagUsage: | |
140 current_usage = current_item->GetShortData(); | |
141 break; | |
142 | |
143 default: | |
144 break; | |
145 } | 57 } |
146 } | 58 } |
147 | |
148 if (top_level_collections->size() > 0 && | |
149 top_level_collections->back().report_ids.size() > 0) { | |
150 // We need to increase report sizes by report ID field length. | |
151 if (current_input_report_size > 0) | |
152 current_input_report_size += kBitsPerByte; | |
153 if (current_output_report_size > 0) | |
154 current_output_report_size += kBitsPerByte; | |
155 if (current_feature_report_size > 0) | |
156 current_feature_report_size += kBitsPerByte; | |
157 } | |
158 | |
159 // Update max report sizes | |
160 *max_input_report_size = | |
161 std::max(*max_input_report_size, current_input_report_size); | |
162 *max_output_report_size = | |
163 std::max(*max_output_report_size, current_output_report_size); | |
164 *max_feature_report_size = | |
165 std::max(*max_feature_report_size, current_feature_report_size); | |
166 | |
167 // Convert bits into bytes | |
168 *max_input_report_size /= kBitsPerByte; | |
169 *max_output_report_size /= kBitsPerByte; | |
170 *max_feature_report_size /= kBitsPerByte; | |
171 } | 59 } |
172 | 60 |
173 } // namespace device | 61 } // namespace device |
OLD | NEW |