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 |
11 HidReportDescriptor::HidReportDescriptor(const uint8_t* bytes, size_t size) { | 17 HidReportDescriptor::HidReportDescriptor(const uint8_t* bytes, size_t size) { |
12 size_t header_index = 0; | 18 size_t header_index = 0; |
13 HidReportDescriptorItem* item = NULL; | 19 HidReportDescriptorItem* item = NULL; |
14 while (header_index < size) { | 20 while (header_index < size) { |
15 item = new HidReportDescriptorItem(&bytes[header_index], item); | 21 item = new HidReportDescriptorItem(&bytes[header_index], item); |
16 items_.push_back(linked_ptr<HidReportDescriptorItem>(item)); | 22 items_.push_back(linked_ptr<HidReportDescriptorItem>(item)); |
17 header_index += item->GetSize(); | 23 header_index += item->GetSize(); |
18 } | 24 } |
19 } | 25 } |
20 | 26 |
21 HidReportDescriptor::~HidReportDescriptor() {} | 27 HidReportDescriptor::~HidReportDescriptor() {} |
22 | 28 |
23 void HidReportDescriptor::GetTopLevelCollections( | 29 void HidReportDescriptor::GetDetails( |
24 std::vector<HidUsageAndPage>* topLevelCollections) { | 30 std::vector<HidCollectionInfo>* top_level_collections, |
25 DCHECK(topLevelCollections); | 31 int* max_input_report_size, |
26 STLClearObject(topLevelCollections); | 32 int* max_output_report_size, |
| 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; |
27 | 56 |
28 for (std::vector<linked_ptr<HidReportDescriptorItem> >::const_iterator | 57 for (std::vector<linked_ptr<HidReportDescriptorItem> >::const_iterator |
29 items_iter = items().begin(); | 58 items_iter = items().begin(); |
30 items_iter != items().end(); | 59 items_iter != items().end(); |
31 ++items_iter) { | 60 ++items_iter) { |
32 linked_ptr<HidReportDescriptorItem> item = *items_iter; | 61 linked_ptr<HidReportDescriptorItem> current_item = *items_iter; |
33 | 62 |
34 bool isTopLevelCollection = | 63 switch (current_item->tag()) { |
35 item->tag() == HidReportDescriptorItem::kTagCollection && | 64 // Main tags: |
36 item->parent() == NULL; | 65 case HidReportDescriptorItem::kTagCollection: |
| 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; |
37 | 84 |
38 if (isTopLevelCollection) { | 85 // Global tags: |
39 uint16_t collection_usage = 0; | 86 case HidReportDescriptorItem::kTagUsagePage: |
40 HidUsageAndPage::Page collection_usage_page = | 87 current_usage_page = |
41 HidUsageAndPage::kPageUndefined; | 88 (HidUsageAndPage::Page)current_item->GetShortData(); |
| 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()); |
42 | 95 |
43 HidReportDescriptorItem* usage = item->previous(); | 96 // We need to increase report sizes by report ID field length. |
44 if (usage && usage->tag() == HidReportDescriptorItem::kTagUsage) { | 97 if (current_input_report_size > 0) |
45 collection_usage = usage->GetShortData(); | 98 current_input_report_size += kBitsPerByte; |
46 } | 99 if (current_output_report_size > 0) |
| 100 current_output_report_size += kBitsPerByte; |
| 101 if (current_feature_report_size > 0) |
| 102 current_feature_report_size += kBitsPerByte; |
47 | 103 |
48 HidReportDescriptorItem* usage_page = usage->previous(); | 104 // Update max report sizes. |
49 if (usage_page && | 105 *max_input_report_size = |
50 usage_page->tag() == HidReportDescriptorItem::kTagUsagePage) { | 106 std::max(*max_input_report_size, current_input_report_size); |
51 collection_usage_page = | 107 *max_output_report_size = |
52 (HidUsageAndPage::Page)usage_page->GetShortData(); | 108 std::max(*max_output_report_size, current_output_report_size); |
53 } | 109 *max_feature_report_size = |
| 110 std::max(*max_feature_report_size, current_feature_report_size); |
54 | 111 |
55 topLevelCollections->push_back( | 112 // Set report sizes to be 1-byte long (report ID field). |
56 HidUsageAndPage(collection_usage, collection_usage_page)); | 113 current_input_report_size = 0; |
| 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; |
57 } | 145 } |
58 } | 146 } |
| 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; |
59 } | 171 } |
60 | 172 |
61 } // namespace device | 173 } // namespace device |
OLD | NEW |