Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(542)

Unified Diff: device/hid/hid_report_descriptor.cc

Issue 317783010: chrome.hid: enrich model with report IDs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Enrich JavaScript model (no incoming report filter) Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: device/hid/hid_report_descriptor.cc
diff --git a/device/hid/hid_report_descriptor.cc b/device/hid/hid_report_descriptor.cc
index f2cb0f4901f10419b16079c372e2391d7d4bd40b..00e16cf5aeed29e4cee030ffcd477020addbb03f 100644
--- a/device/hid/hid_report_descriptor.cc
+++ b/device/hid/hid_report_descriptor.cc
@@ -8,6 +8,12 @@
namespace device {
+namespace {
+
+const int kOneByte = 8;
Ken Rockot(use gerrit already) 2014/06/06 20:04:43 How about "kBitsPerByte"
jracle (use Gerrit) 2014/06/07 12:56:21 +2! On 2014/06/06 20:04:43, Ken Rockot wrote:
+
+} // namespace
+
HidReportDescriptor::HidReportDescriptor(const uint8_t* bytes, size_t size) {
size_t header_index = 0;
HidReportDescriptorItem* item = NULL;
@@ -21,41 +27,147 @@ HidReportDescriptor::HidReportDescriptor(const uint8_t* bytes, size_t size) {
HidReportDescriptor::~HidReportDescriptor() {}
void HidReportDescriptor::GetTopLevelCollections(
- std::vector<HidUsageAndPage>* topLevelCollections) {
- DCHECK(topLevelCollections);
- STLClearObject(topLevelCollections);
+ std::vector<HidCollectionInfo>* top_level_collections,
+ int* max_input_report_size,
+ int* max_output_report_size,
+ int* max_feature_report_size) {
+ DCHECK(top_level_collections);
+ DCHECK(max_input_report_size);
+ DCHECK(max_output_report_size);
+ DCHECK(max_feature_report_size);
+ STLClearObject(top_level_collections);
+
+ *max_input_report_size = 0;
+ *max_output_report_size = 0;
+ *max_feature_report_size = 0;
+
+ // Global tags data:
+ HidUsageAndPage::Page current_usage_page = HidUsageAndPage::kPageUndefined;
+ int current_report_count = 0;
+ int cached_report_count = 0;
+ int current_report_size = 0;
+ int cached_report_size = 0;
+ int current_input_report_size = 0;
+ int current_output_report_size = 0;
+ int current_feature_report_size = 0;
+
+ // Local tags data:
+ uint16_t current_usage = 0;
for (std::vector<linked_ptr<HidReportDescriptorItem> >::const_iterator
items_iter = items().begin();
items_iter != items().end();
++items_iter) {
- linked_ptr<HidReportDescriptorItem> item = *items_iter;
-
- bool isTopLevelCollection =
- item->tag() == HidReportDescriptorItem::kTagCollection &&
- item->parent() == NULL;
-
- if (isTopLevelCollection) {
- uint16_t collection_usage = 0;
- HidUsageAndPage::Page collection_usage_page =
- HidUsageAndPage::kPageUndefined;
-
- HidReportDescriptorItem* usage = item->previous();
- if (usage && usage->tag() == HidReportDescriptorItem::kTagUsage) {
- collection_usage = usage->GetShortData();
- }
-
- HidReportDescriptorItem* usage_page = usage->previous();
- if (usage_page &&
- usage_page->tag() == HidReportDescriptorItem::kTagUsagePage) {
- collection_usage_page =
- (HidUsageAndPage::Page)usage_page->GetShortData();
- }
-
- topLevelCollections->push_back(
- HidUsageAndPage(collection_usage, collection_usage_page));
+ linked_ptr<HidReportDescriptorItem> current_item = *items_iter;
+
+ switch (current_item->tag()) {
Ken Rockot(use gerrit already) 2014/06/06 20:04:43 In general this is awesome. I wish it were a littl
jracle (use Gerrit) 2014/06/07 12:56:21 Thanks, I'm also a bit uncomfortable with it, but
+ // Main tags:
+ case HidReportDescriptorItem::kTagCollection:
+ if (!current_item->parent()) {
+ // This is a top-level collection.
+ HidCollectionInfo collection;
+ collection.usage = HidUsageAndPage(current_usage, current_usage_page);
+ top_level_collections->push_back(collection);
+ }
+ break;
+ case HidReportDescriptorItem::kTagInput:
+ current_input_report_size += current_report_count * current_report_size;
+ break;
+ case HidReportDescriptorItem::kTagOutput:
+ current_output_report_size +=
+ current_report_count * current_report_size;
+ break;
+ case HidReportDescriptorItem::kTagFeature:
+ current_feature_report_size +=
+ current_report_count * current_report_size;
+ break;
+
+ // Global tags:
+ case HidReportDescriptorItem::kTagUsagePage:
+ current_usage_page =
+ (HidUsageAndPage::Page)current_item->GetShortData();
+ break;
+ case HidReportDescriptorItem::kTagReportId:
+ if (top_level_collections->size() > 0) {
+ // Store report ID.
+ top_level_collections->back().report_ids.insert(
+ current_item->GetShortData());
+
+ // We need to increase report sizes by report ID field length.
+ if (current_input_report_size > 0)
+ current_input_report_size += kOneByte;
+ if (current_output_report_size > 0)
+ current_output_report_size += kOneByte;
+ if (current_feature_report_size > 0)
+ current_feature_report_size += kOneByte;
+
+ // Update max report sizes.
+ *max_input_report_size =
+ std::max(*max_input_report_size, current_input_report_size);
+ *max_output_report_size =
+ std::max(*max_output_report_size, current_output_report_size);
+ *max_feature_report_size =
+ std::max(*max_feature_report_size, current_feature_report_size);
+
+ // Set report sizes to be 1-byte long (report ID field).
+ current_input_report_size = 0;
+ current_output_report_size = 0;
+ current_feature_report_size = 0;
+ }
+ break;
+ case HidReportDescriptorItem::kTagReportCount:
+ current_report_count = current_item->GetShortData();
+ break;
+ case HidReportDescriptorItem::kTagReportSize:
+ current_report_size = current_item->GetShortData();
+ break;
+ case HidReportDescriptorItem::kTagPush:
+ // Cache report count and size.
+ cached_report_count = current_report_count;
+ cached_report_size = current_report_size;
+ break;
+ case HidReportDescriptorItem::kTagPop:
+ // Restore cache.
+ current_report_count = cached_report_count;
+ current_report_size = cached_report_size;
+ // Reset cache.
+ cached_report_count = 0;
+ cached_report_size = 0;
+ break;
+
+ // Local tags:
+ case HidReportDescriptorItem::kTagUsage:
+ current_usage = current_item->GetShortData();
+ break;
+
+ default:
+ break;
}
}
+
+ if (top_level_collections->size() > 0 &&
+ top_level_collections->back().report_ids.size() > 0) {
+ // We need to increase report sizes by report ID field length.
+ if (current_input_report_size > 0)
+ current_input_report_size += kOneByte;
+ if (current_output_report_size > 0)
+ current_output_report_size += kOneByte;
+ if (current_feature_report_size > 0)
+ current_feature_report_size += kOneByte;
+ }
+
+ // Update max report sizes
+ *max_input_report_size =
+ std::max(*max_input_report_size, current_input_report_size);
+ *max_output_report_size =
+ std::max(*max_output_report_size, current_output_report_size);
+ *max_feature_report_size =
+ std::max(*max_feature_report_size, current_feature_report_size);
+
+ // Convert bits into bytes
+ *max_input_report_size /= kOneByte;
+ *max_output_report_size /= kOneByte;
+ *max_feature_report_size /= kOneByte;
}
} // namespace device

Powered by Google App Engine
This is Rietveld 408576698