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

Side by Side Diff: device/hid/hid_report_descriptor.h

Issue 225513005: chrome.hid : enrich device info with Top-Level collections usages (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: enrich device info with hid usages Created 6 years, 8 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 unified diff | Download patch
OLDNEW
(Empty)
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 #ifndef DEVICE_HID_HID_REPORT_DESCRIPTOR_H_
6 #define DEVICE_HID_HID_REPORT_DESCRIPTOR_H_
7
8 #include <sstream>
9 #include <vector>
10
11 #include "base/basictypes.h"
12 #include "device/hid/hid_usage_and_page.h"
13
14 namespace device {
15
16 // An element of a HID report descriptor.
17 class HidReportDescriptorItem {
18
19 #pragma pack (push, 1)
20
21 public:
22 enum Type {
23 kTypeMain = 0,
24 kTypeGlobal = 1,
25 kTypeLocal = 2,
26 kTypeReserved = 3
27 };
28
29 private:
30 // Tags
31
32 enum MainTag {
33 kMainTagDefault = 0x00, // 0000
34 kMainTagInput = 0x08, // 1000
35 kMainTagOutput = 0x09, // 1001
36 kMainTagFeature = 0x0B, // 1011
37 kMainTagCollection = 0x0A, // 1010
38 kMainTagEndCollection = 0x0C // 1100
39 };
40
41 enum GlobalTag {
42 kGlobalTagUsagePage = 0x00, // 0000
43 kGlobalTagLogicalMinimum = 0x01, // 0001
44 kGlobalTagLogicalMaximum = 0x02, // 0010
45 kGlobalTagPhysicalMinimum = 0x03, // 0011
46 kGlobalTagPhysicalMaximum = 0x04, // 0100
47 kGlobalTagUnitExponent = 0x05, // 0101
48 kGlobalTagUnit = 0x06, // 0110
49 kGlobalTagReportSize = 0x07, // 0111
50 kGlobalTagReportId = 0x08, // 1000
51 kGlobalTagReportCount = 0x09, // 1001
52 kGlobalTagPush = 0x0A, // 1010
53 kGlobalTagPop = 0x0B // 1011
54 };
55
56 enum LocalTag {
57 kLocalTagUsage = 0x00, // 0000
58 kLocalTagUsageMinimum = 0x01, // 0001
59 kLocalTagUsageMaximum = 0x02, // 0010
60 kLocalTagDesignatorIndex = 0x03, // 0011
61 kLocalTagDesignatorMinimum = 0x04, // 0100
62 kLocalTagDesignatorMaximum = 0x05, // 0101
63 kLocalTagStringIndex = 0x07, // 0111
64 kLocalTagStringMinimum = 0x08, // 1000
65 kLocalTagStringMaximum = 0x09, // 1001
66 kLocalTagDelimiter = 0x0A // 1010
67 };
68
69 enum ReservedTag {
70 kReservedTagLong = 0xF // 1111
71 };
72
73 public:
74 enum Tag {
75 kTagDefault = kMainTagDefault << 2 | kTypeMain,
76 kTagInput = kMainTagInput << 2 | kTypeMain,
77 kTagOutput = kMainTagOutput << 2 | kTypeMain,
78 kTagFeature = kMainTagFeature << 2 | kTypeMain,
79 kTagCollection = kMainTagCollection << 2 | kTypeMain,
80 kTagEndCollection = kMainTagEndCollection << 2 | kTypeMain,
81 kTagUsagePage = kGlobalTagUsagePage << 2 | kTypeGlobal,
82 kTagLogicalMinimum = kGlobalTagLogicalMinimum << 2 | kTypeGlobal,
83 kTagLogicalMaximum = kGlobalTagLogicalMaximum << 2 | kTypeGlobal,
84 kTagPhysicalMinimum = kGlobalTagPhysicalMinimum << 2 | kTypeGlobal,
85 kTagPhysicalMaximum = kGlobalTagPhysicalMaximum << 2 | kTypeGlobal,
86 kTagUnitExponent = kGlobalTagUnitExponent << 2 | kTypeGlobal,
87 kTagUnit = kGlobalTagUnit << 2 | kTypeGlobal,
88 kTagReportSize = kGlobalTagReportSize << 2 | kTypeGlobal,
89 kTagReportId = kGlobalTagReportId << 2 | kTypeGlobal,
90 kTagReportCount = kGlobalTagReportCount << 2 | kTypeGlobal,
91 kTagPush = kGlobalTagPush << 2 | kTypeGlobal,
92 kTagPop = kGlobalTagPop << 2 | kTypeGlobal,
93 kTagUsage = kLocalTagUsage << 2 | kTypeLocal,
94 kTagUsageMinimum = kLocalTagUsageMinimum << 2 | kTypeLocal,
95 kTagUsageMaximum = kLocalTagUsageMaximum << 2 | kTypeLocal,
96 kTagDesignatorIndex = kLocalTagDesignatorIndex << 2 | kTypeLocal,
97 kTagDesignatorMinimum = kLocalTagDesignatorMinimum << 2 | kTypeLocal,
98 kTagDesignatorMaximum = kLocalTagDesignatorMaximum << 2 | kTypeLocal,
99 kTagStringIndex = kLocalTagStringIndex << 2 | kTypeLocal,
100 kTagStringMinimum = kLocalTagStringMinimum << 2 | kTypeLocal,
101 kTagStringMaximum = kLocalTagStringMaximum << 2 | kTypeLocal,
102 kTagDelimiter = kLocalTagDelimiter << 2 | kTypeLocal,
103 kTagLong = kReservedTagLong << 2 | kTypeReserved
104 };
105
106 private:
107 friend std::ostream& operator<<(std::ostream& os,
108 const Tag& tag) {
109 switch (tag) {
110 case kTagDefault:
111 os << "Default";
112 break;
113 case kTagInput:
114 os << "Input";
115 break;
116 case kTagOutput:
117 os << "Output";
118 break;
119 case kTagFeature:
120 os << "Feature";
121 break;
122 case kTagCollection:
123 os << "Collection";
124 break;
125 case kTagEndCollection:
126 os << "End Collection";
127 break;
128 case kTagUsagePage:
129 os << "Usage Page";
130 break;
131 case kTagLogicalMinimum:
132 os << "Logical Minimum";
133 break;
134 case kTagLogicalMaximum:
135 os << "Logical Maximum";
136 break;
137 case kTagPhysicalMinimum:
138 os << "Physical Minimum";
139 break;
140 case kTagPhysicalMaximum:
141 os << "Physical Maximum";
142 break;
143 case kTagUnitExponent:
144 os << "Unit Exponent";
145 break;
146 case kTagUnit:
147 os << "Unit";
148 break;
149 case kTagReportSize:
150 os << "Report Size";
151 break;
152 case kTagReportId:
153 os << "Report ID";
154 break;
155 case kTagReportCount:
156 os << "Report Count";
157 break;
158 case kTagPush:
159 os << "Push";
160 break;
161 case kTagPop:
162 os << "Pop";
163 break;
164 case kTagUsage:
165 os << "Usage";
166 break;
167 case kTagUsageMinimum:
168 os << "Usage Minimum";
169 break;
170 case kTagUsageMaximum:
171 os << "Usage Maximum";
172 break;
173 case kTagDesignatorIndex:
174 os << "Designator Index";
175 break;
176 case kTagDesignatorMinimum:
177 os << "Designator Minimum";
178 break;
179 case kTagDesignatorMaximum:
180 os << "Designator Maximum";
181 break;
182 case kTagStringIndex:
183 os << "String Index";
184 break;
185 case kTagStringMinimum:
186 os << "String Minimum";
187 break;
188 case kTagStringMaximum:
189 os << "String Maximum";
190 break;
191 case kTagDelimiter:
192 os << "Delimeter";
193 break;
194 case kTagLong:
195 os << "Long";
196 break;
197 default:
198 NOTREACHED();
199 break;
200 }
201
202 return os;
203 };
204
205 public:
206 // Headers
207
208 struct Header {
209 uint8_t size : 2;
210 uint8_t type : 2;
211 uint8_t tag : 4;
212 };
213
214 struct LongHeader {
215 Header short_header;
216 uint8_t data_size;
217 uint8_t long_item_tag;
218 };
219
220 // Data
221
222 // (Short) Main items
223
224 struct Default {
225 private:
226 friend std::ostream& operator<<(std::ostream& os,
227 const Default& data) {
228 return os;
229 }
230 };
231
232 struct Input_Output_Feature {
233 uint8_t data_or_constant:1;
234 uint8_t array_or_variable:1;
235 uint8_t absolute_or_relative:1;
236 uint8_t wrap:1;
237 uint8_t linear:1;
238 uint8_t preferred:1;
239 uint8_t null:1;
240 uint8_t reserved_1:1;
241 uint8_t bit_field_or_buffer:1;
242 uint8_t reserved_2:1;
243
244 private:
245 friend std::ostream& operator<<(std::ostream& os,
246 const Input_Output_Feature& data) {
247 if (data.data_or_constant)
248 os << "Con";
249 else
250 os << "Dat";
251 if (data.array_or_variable)
252 os << "|Arr";
253 else
254 os << "|Var";
255 if (data.absolute_or_relative)
256 os << "|Abs";
257 else
258 os << "|Rel";
259 if (data.wrap)
260 os << "|Wrp";
261 else
262 os << "|NoWrp";
263 if (data.linear)
264 os << "|NoLin";
265 else
266 os << "|Lin";
267 if (data.preferred)
268 os << "|NoPrf";
269 else
270 os << "|Prf";
271 if (data.null)
272 os << "|Null";
273 else
274 os << "|NoNull";
275 if (data.bit_field_or_buffer)
276 os << "|Buff";
277 else
278 os << "|BitF";
279 return os;
280 }
281 };
282
283 struct Collection {
284
285 enum CollectionType {
286 kCollectionTypePhysical,
287 kCollectionTypeApplication,
288 kCollectionTypeLogical,
289 kCollectionTypeReport,
290 kCollectionTypeNamedArray,
291 kCollectionTypeUsageSwitch,
292 kCollectionTypeUsageModifier,
293 kCollectionTypeReserved,
294 kCollectionTypeVendor
295 };
296
297 uint8_t value;
298
299 CollectionType collectionType() const {
300 switch (value) {
301 case 0x00:
302 return kCollectionTypePhysical;
303 case 0x01:
304 return kCollectionTypePhysical;
305 case 0x02:
306 return kCollectionTypePhysical;
307 case 0x03:
308 return kCollectionTypePhysical;
309 case 0x04:
310 return kCollectionTypePhysical;
311 case 0x05:
312 return kCollectionTypePhysical;
313 case 0x06:
314 return kCollectionTypePhysical;
315 default:
316 break;
317 }
318
319 if (0x80 < value && value < 0xFF)
320 return kCollectionTypeVendor;
321
322 return kCollectionTypeReserved;
323 }
324
325 private:
326 friend std::ostream& operator<<(std::ostream& os,
327 const Collection& data) {
328 switch (data.collectionType()) {
329 case kCollectionTypePhysical:
330 os << "Physical";
331 break;
332 case kCollectionTypeApplication:
333 os << "Application";
334 break;
335 case kCollectionTypeLogical:
336 os << "Logical";
337 break;
338 case kCollectionTypeReport:
339 os << "Report";
340 break;
341 case kCollectionTypeNamedArray:
342 os << "Named Array";
343 break;
344 case kCollectionTypeUsageSwitch:
345 os << "Usage Switch";
346 break;
347 case kCollectionTypeUsageModifier:
348 os << "Usage Modifier";
349 break;
350 case kCollectionTypeReserved:
351 os << "Reserved";
352 break;
353 case kCollectionTypeVendor:
354 os << "Vendor";
355 break;
356 default:
357 NOTREACHED();
358 break;
359 }
360 return os;
361 }
362 };
363
364 struct EndCollection {
365 private:
366 friend std::ostream& operator<<(std::ostream& os,
367 const EndCollection& data) {
368 return os;
369 }
370 };
371
372 // (Short) Global Items
373
374 struct UsagePage {
375 uint16_t value;
376
377 private:
378 friend std::ostream& operator<<(std::ostream& os,
379 const UsagePage& data) {
380 HidUsageAndPage::Page page = (HidUsageAndPage::Page)data.value;
381 os << page;
382 return os;
383 }
384 };
385
386 struct LogicalMinimum {
387 int32_t value;
388
389 private:
390 friend std::ostream& operator<<(std::ostream& os,
391 const LogicalMinimum& data) {
392 os << data.value;
393 return os;
394 }
395 };
396
397 struct LogicalMaximum {
398 int32_t value;
399
400 private:
401 friend std::ostream& operator<<(std::ostream& os,
402 const LogicalMaximum& data) {
403 os << data.value;
404 return os;
405 }
406 };
407
408 struct PhysicalMinimum {
409 int32_t value;
410
411 private:
412 friend std::ostream& operator<<(std::ostream& os,
413 const PhysicalMinimum& data) {
414 os << data.value;
415 return os;
416 }
417 };
418
419 struct PhysicalMaximum {
420 int32_t value;
421
422 private:
423 friend std::ostream& operator<<(std::ostream& os,
424 const PhysicalMaximum& data) {
425 os << data.value;
426 return os;
427 }
428 };
429
430 struct UnitExponent {
431 uint32_t value;
432
433 private:
434 friend std::ostream& operator<<(std::ostream& os,
435 const UnitExponent& data) {
436 os << data.value;
437 return os;
438 }
439 };
440
441 struct Unit {
442 uint32_t value;
443
444 private:
445 friend std::ostream& operator<<(std::ostream& os,
446 const Unit& data) {
447 os << data.value;
448 return os;
449 }
450 };
451
452 struct ReportSize {
453 uint32_t value;
454
455 private:
456 friend std::ostream& operator<<(std::ostream& os,
457 const ReportSize& data) {
458 os << data.value;
459 return os;
460 }
461 };
462
463 struct ReportId {
464 uint32_t value;
465
466 private:
467 friend std::ostream& operator<<(std::ostream& os,
468 const ReportId& data) {
469 os << "0x" << std::hex << std::uppercase << data.value;
470 return os;
471 }
472 };
473
474 struct ReportCount {
475 uint32_t value;
476
477 private:
478 friend std::ostream& operator<<(std::ostream& os,
479 const ReportCount& data) {
480 os << data.value;
481 return os;
482 }
483 };
484
485 struct Push {
486 private:
487 friend std::ostream& operator<<(std::ostream& os,
488 const Push& data) {
489 return os;
490 }
491 };
492
493 struct Pop {
494 private:
495 friend std::ostream& operator<<(std::ostream& os,
496 const Pop& data) {
497 return os;
498 }
499 };
500
501 // (Short) Local Items
502
503 struct Usage {
504 uint16_t value;
505
506 private:
507 friend std::ostream& operator<<(std::ostream& os,
508 const Usage& data) {
509 os << "0x" << std::hex << std::uppercase << data.value;
510 return os;
511 }
512 };
513
514 struct UsageMinimum {
515 uint16_t value;
516
517 private:
518 friend std::ostream& operator<<(std::ostream& os,
519 const UsageMinimum& data) {
520 os << "0x" << std::hex << std::uppercase << data.value;
521 return os;
522 }
523 };
524
525 struct UsageMaximum {
526 uint16_t value;
527
528 private:
529 friend std::ostream& operator<<(std::ostream& os,
530 const UsageMaximum& data) {
531 os << "0x" << std::hex << std::uppercase << data.value;
532 return os;
533 }
534 };
535
536 struct DesignatorIndex {
537 private:
538 friend std::ostream& operator<<(std::ostream& os,
539 const DesignatorIndex& data) {
540 return os;
541 }
542 };
543
544 struct DesignatorMinimum {
545 private:
546 friend std::ostream& operator<<(std::ostream& os,
547 const DesignatorMinimum& data) {
548 return os;
549 }
550 };
551
552 struct DesignatorMaximum {
553 private:
554 friend std::ostream& operator<<(std::ostream& os,
555 const DesignatorMaximum& data) {
556 return os;
557 }
558 };
559
560 struct StringIndex {
561 private:
562 friend std::ostream& operator<<(std::ostream& os,
563 const StringIndex& data) {
564 return os;
565 }
566 };
567
568 struct StringMinimum {
569 private:
570 friend std::ostream& operator<<(std::ostream& os,
571 const StringMinimum& data) {
572 return os;
573 }
574 };
575
576 struct StringMaximum {
577 private:
578 friend std::ostream& operator<<(std::ostream& os,
579 const StringMaximum& data) {
580 return os;
581 }
582 };
583
584 struct Delimiter {
585 private:
586 friend std::ostream& operator<<(std::ostream& os,
587 const Delimiter& data) {
588 return os;
589 }
590 };
591
592 // (Long) Reserved items
593 // nothing for now
594
595 // Data union
596
597 struct Data {
598 union u {
599 // (Short) Main items
600 Default none;
601 Input_Output_Feature input;
602 Input_Output_Feature output;
603 Input_Output_Feature feature;
604 Collection collection;
605 EndCollection end_collection;
606 // (Short) Global items
607 UsagePage usage_page;
608 LogicalMinimum logical_minimum;
609 LogicalMaximum logical_maximum;
610 PhysicalMinimum physical_minimum;
611 PhysicalMaximum physical_maximum;
612 UnitExponent unit_exponent;
613 Unit unit;
614 ReportSize report_size;
615 ReportId report_id;
616 ReportCount report_count;
617 Push push;
618 Pop pop;
619 // (Short) Local items
620 Usage usage;
621 UsageMinimum usage_minimum;
622 UsageMaximum usage_maximum;
623 DesignatorIndex designator_index;
624 DesignatorMinimum designator_minimum;
625 DesignatorMaximum designator_maximum;
626 StringIndex string_index;
627 StringMinimum string_minimum;
628 StringMaximum string_maximum;
629 Delimiter delimiter;
630 // (Long) Reserved items
631 // nothing for now
632 };
633 };
634
635 #pragma pack (pop)
636
637 HidReportDescriptorItem(const uint8_t* bytes,
638 HidReportDescriptorItem* previous = NULL);
639 ~HidReportDescriptorItem();
640
641 HidReportDescriptorItem* previous() const { return previous_; };
642 HidReportDescriptorItem* next() const { return next_; };
643 HidReportDescriptorItem* parent() const { return parent_; };
644 size_t depth() const;
645
646 bool isLong() const;
647 size_t headerSize() const;
648 size_t payloadSize() const;
649 size_t size() const;
650
651 Header* header() const;
652 LongHeader* longHeader() const;
653
654 Tag tag() const;
655 Data* data() const;
656
657 private:
658 friend std::ostream& operator<<(std::ostream& os,
659 const HidReportDescriptorItem& item) {
660 Tag tg = item.tag();
661 Data* dt = item.data();
662
663 std::ostringstream sstr;
664 sstr << tg;
665 sstr << " (";
666
667 long pos = sstr.tellp();
668 switch (tg) {
669 case kTagDefault:
670 sstr << *(Default*)dt;
671 break;
672 case kTagInput:
673 case kTagOutput:
674 case kTagFeature:
675 sstr << *(Input_Output_Feature*)dt;
676 break;
677 case kTagCollection:
678 sstr << *(Collection*)dt;
679 break;
680 case kTagEndCollection:
681 sstr << *(EndCollection*)dt;
682 break;
683 case kTagUsagePage:
684 sstr << *(UsagePage*)dt;
685 break;
686 case kTagLogicalMinimum:
687 sstr << *(LogicalMinimum*)dt;
688 break;
689 case kTagLogicalMaximum:
690 sstr << *(LogicalMaximum*)dt;
691 break;
692 case kTagPhysicalMinimum:
693 sstr << *(PhysicalMinimum*)dt;
694 break;
695 case kTagPhysicalMaximum:
696 sstr << *(PhysicalMaximum*)dt;
697 break;
698 case kTagUnitExponent:
699 sstr << *(UnitExponent*)dt;
700 break;
701 case kTagUnit:
702 sstr << *(Unit*)dt;
703 break;
704 case kTagReportSize:
705 sstr << *(ReportSize*)dt;
706 break;
707 case kTagReportId:
708 sstr << *(ReportId*)dt;
709 break;
710 case kTagReportCount:
711 sstr << *(ReportCount*)dt;
712 break;
713 case kTagPush:
714 sstr << *(Push*)dt;
715 break;
716 case kTagPop:
717 sstr << *(Pop*)dt;
718 break;
719 case kTagUsage:
720 sstr << *(Usage*)dt;
721 break;
722 case kTagUsageMinimum:
723 sstr << *(UsageMinimum*)dt;
724 break;
725 case kTagUsageMaximum:
726 sstr << *(UsageMaximum*)dt;
727 break;
728 case kTagDesignatorIndex:
729 sstr << *(DesignatorIndex*)dt;
730 break;
731 case kTagDesignatorMinimum:
732 sstr << *(DesignatorMinimum*)dt;
733 break;
734 case kTagDesignatorMaximum:
735 sstr << *(DesignatorMaximum*)dt;
736 break;
737 case kTagStringIndex:
738 sstr << *(StringIndex*)dt;
739 break;
740 case kTagStringMinimum:
741 sstr << *(StringMinimum*)dt;
742 break;
743 case kTagStringMaximum:
744 sstr << *(StringMaximum*)dt;
745 break;
746 case kTagDelimiter:
747 sstr << *(Delimiter*)dt;
748 break;
749 case kTagLong:
750 break;
751 default:
752 NOTREACHED();
753 break;
754 }
755
756 if (pos == sstr.tellp()) {
757 std::string str = sstr.str();
758 str.erase(str.end() - 2, str.end());
759 os << str;
760 } else {
761 os << sstr.str() << ")";
762 }
763
764 return os;
765 }
766
767 const uint8_t* bytes_;
768 HidReportDescriptorItem* previous_;
769 HidReportDescriptorItem* next_;
770 HidReportDescriptorItem* parent_;
771 };
772
773 // HID report descriptor.
774 // See section 6.2.2 of HID specifications (v1.11).
775 class HidReportDescriptor {
776
777 private:
778 static const char kIndentChar;
779
780 public:
781 HidReportDescriptor(const uint8_t* bytes, size_t size);
782 ~HidReportDescriptor();
783
784 const std::vector<HidReportDescriptorItem*>& items() const;
785 std::vector<HidUsageAndPage> topLevelCollections() const;
786
787 private:
788 friend std::ostream& operator<<(std::ostream& os,
789 const HidReportDescriptor& descriptor) {
790 for (std::vector<HidReportDescriptorItem*>::const_iterator items_iter =
791 descriptor.items_.begin();
792 items_iter != descriptor.items_.end();
793 ++items_iter) {
794 HidReportDescriptorItem* item = *items_iter;
795 size_t indentLevel = item->depth();
796 for (size_t i = 0; i < indentLevel; i++)
797 os << kIndentChar;
798 os << *item << std::endl;
799 }
800 return os;
801 }
802
803 const uint8_t* bytes_;
804 size_t size_;
805 std::vector<HidReportDescriptorItem*> items_;
806 };
807
808 } // namespace device
809
810 #endif // DEVICE_HID_HID_REPORT_DESCRIPTOR_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698