Add common GLFence::IsSupported() check
[chromium-blink-merge.git] / device / hid / hid_report_descriptor_unittest.cc
blob0d258891081ee2f5874c6cde8a249c7e0b434937
1 // Copyright (c) 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 <sstream>
7 #include "device/hid/hid_report_descriptor.h"
8 #include "testing/gmock/include/gmock/gmock.h"
9 #include "testing/gtest/include/gtest/gtest.h"
11 using namespace testing;
13 namespace device {
15 namespace {
17 std::ostream& operator<<(std::ostream& os,
18 const HidUsageAndPage::Page& usage_page) {
19 switch (usage_page) {
20 case HidUsageAndPage::kPageUndefined:
21 os << "Undefined";
22 break;
23 case HidUsageAndPage::kPageGenericDesktop:
24 os << "Generic Desktop";
25 break;
26 case HidUsageAndPage::kPageSimulation:
27 os << "Simulation";
28 break;
29 case HidUsageAndPage::kPageVirtualReality:
30 os << "Virtual Reality";
31 break;
32 case HidUsageAndPage::kPageSport:
33 os << "Sport";
34 break;
35 case HidUsageAndPage::kPageGame:
36 os << "Game";
37 break;
38 case HidUsageAndPage::kPageKeyboard:
39 os << "Keyboard";
40 break;
41 case HidUsageAndPage::kPageLed:
42 os << "Led";
43 break;
44 case HidUsageAndPage::kPageButton:
45 os << "Button";
46 break;
47 case HidUsageAndPage::kPageOrdinal:
48 os << "Ordinal";
49 break;
50 case HidUsageAndPage::kPageTelephony:
51 os << "Telephony";
52 break;
53 case HidUsageAndPage::kPageConsumer:
54 os << "Consumer";
55 break;
56 case HidUsageAndPage::kPageDigitizer:
57 os << "Digitizer";
58 break;
59 case HidUsageAndPage::kPagePidPage:
60 os << "Pid Page";
61 break;
62 case HidUsageAndPage::kPageUnicode:
63 os << "Unicode";
64 break;
65 case HidUsageAndPage::kPageAlphanumericDisplay:
66 os << "Alphanumeric Display";
67 break;
68 case HidUsageAndPage::kPageMedicalInstruments:
69 os << "Medical Instruments";
70 break;
71 case HidUsageAndPage::kPageMonitor0:
72 os << "Monitor 0";
73 break;
74 case HidUsageAndPage::kPageMonitor1:
75 os << "Monitor 1";
76 break;
77 case HidUsageAndPage::kPageMonitor2:
78 os << "Monitor 2";
79 break;
80 case HidUsageAndPage::kPageMonitor3:
81 os << "Monitor 3";
82 break;
83 case HidUsageAndPage::kPagePower0:
84 os << "Power 0";
85 break;
86 case HidUsageAndPage::kPagePower1:
87 os << "Power 1";
88 break;
89 case HidUsageAndPage::kPagePower2:
90 os << "Power 2";
91 break;
92 case HidUsageAndPage::kPagePower3:
93 os << "Power 3";
94 break;
95 case HidUsageAndPage::kPageBarCodeScanner:
96 os << "Bar Code Scanner";
97 break;
98 case HidUsageAndPage::kPageScale:
99 os << "Scale";
100 break;
101 case HidUsageAndPage::kPageMagneticStripeReader:
102 os << "Magnetic Stripe Reader";
103 break;
104 case HidUsageAndPage::kPageReservedPointOfSale:
105 os << "Reserved Point Of Sale";
106 break;
107 case HidUsageAndPage::kPageCameraControl:
108 os << "Camera Control";
109 break;
110 case HidUsageAndPage::kPageArcade:
111 os << "Arcade";
112 break;
113 case HidUsageAndPage::kPageVendor:
114 os << "Vendor";
115 break;
116 case HidUsageAndPage::kPageMediaCenter:
117 os << "Media Center";
118 break;
119 default:
120 NOTREACHED();
121 break;
123 return os;
126 std::ostream& operator<<(std::ostream& os,
127 const HidUsageAndPage& usage_and_page) {
128 os << "Usage Page: " << usage_and_page.usage_page << ", Usage: "
129 << "0x" << std::hex << std::uppercase << usage_and_page.usage;
130 return os;
133 std::ostream& operator<<(std::ostream& os,
134 const HidReportDescriptorItem::Tag& tag) {
135 switch (tag) {
136 case HidReportDescriptorItem::kTagDefault:
137 os << "Default";
138 break;
139 case HidReportDescriptorItem::kTagInput:
140 os << "Input";
141 break;
142 case HidReportDescriptorItem::kTagOutput:
143 os << "Output";
144 break;
145 case HidReportDescriptorItem::kTagFeature:
146 os << "Feature";
147 break;
148 case HidReportDescriptorItem::kTagCollection:
149 os << "Collection";
150 break;
151 case HidReportDescriptorItem::kTagEndCollection:
152 os << "End Collection";
153 break;
154 case HidReportDescriptorItem::kTagUsagePage:
155 os << "Usage Page";
156 break;
157 case HidReportDescriptorItem::kTagLogicalMinimum:
158 os << "Logical Minimum";
159 break;
160 case HidReportDescriptorItem::kTagLogicalMaximum:
161 os << "Logical Maximum";
162 break;
163 case HidReportDescriptorItem::kTagPhysicalMinimum:
164 os << "Physical Minimum";
165 break;
166 case HidReportDescriptorItem::kTagPhysicalMaximum:
167 os << "Physical Maximum";
168 break;
169 case HidReportDescriptorItem::kTagUnitExponent:
170 os << "Unit Exponent";
171 break;
172 case HidReportDescriptorItem::kTagUnit:
173 os << "Unit";
174 break;
175 case HidReportDescriptorItem::kTagReportSize:
176 os << "Report Size";
177 break;
178 case HidReportDescriptorItem::kTagReportId:
179 os << "Report ID";
180 break;
181 case HidReportDescriptorItem::kTagReportCount:
182 os << "Report Count";
183 break;
184 case HidReportDescriptorItem::kTagPush:
185 os << "Push";
186 break;
187 case HidReportDescriptorItem::kTagPop:
188 os << "Pop";
189 break;
190 case HidReportDescriptorItem::kTagUsage:
191 os << "Usage";
192 break;
193 case HidReportDescriptorItem::kTagUsageMinimum:
194 os << "Usage Minimum";
195 break;
196 case HidReportDescriptorItem::kTagUsageMaximum:
197 os << "Usage Maximum";
198 break;
199 case HidReportDescriptorItem::kTagDesignatorIndex:
200 os << "Designator Index";
201 break;
202 case HidReportDescriptorItem::kTagDesignatorMinimum:
203 os << "Designator Minimum";
204 break;
205 case HidReportDescriptorItem::kTagDesignatorMaximum:
206 os << "Designator Maximum";
207 break;
208 case HidReportDescriptorItem::kTagStringIndex:
209 os << "String Index";
210 break;
211 case HidReportDescriptorItem::kTagStringMinimum:
212 os << "String Minimum";
213 break;
214 case HidReportDescriptorItem::kTagStringMaximum:
215 os << "String Maximum";
216 break;
217 case HidReportDescriptorItem::kTagDelimiter:
218 os << "Delimeter";
219 break;
220 case HidReportDescriptorItem::kTagLong:
221 os << "Long";
222 break;
223 default:
224 NOTREACHED();
225 break;
228 return os;
231 std::ostream& operator<<(std::ostream& os,
232 const HidReportDescriptorItem::ReportInfo& data) {
233 if (data.data_or_constant)
234 os << "Con";
235 else
236 os << "Dat";
237 if (data.array_or_variable)
238 os << "|Arr";
239 else
240 os << "|Var";
241 if (data.absolute_or_relative)
242 os << "|Abs";
243 else
244 os << "|Rel";
245 if (data.wrap)
246 os << "|Wrp";
247 else
248 os << "|NoWrp";
249 if (data.linear)
250 os << "|NoLin";
251 else
252 os << "|Lin";
253 if (data.preferred)
254 os << "|NoPrf";
255 else
256 os << "|Prf";
257 if (data.null)
258 os << "|Null";
259 else
260 os << "|NoNull";
261 if (data.bit_field_or_buffer)
262 os << "|Buff";
263 else
264 os << "|BitF";
265 return os;
268 std::ostream& operator<<(std::ostream& os,
269 const HidReportDescriptorItem::CollectionType& type) {
270 switch (type) {
271 case HidReportDescriptorItem::kCollectionTypePhysical:
272 os << "Physical";
273 break;
274 case HidReportDescriptorItem::kCollectionTypeApplication:
275 os << "Application";
276 break;
277 case HidReportDescriptorItem::kCollectionTypeLogical:
278 os << "Logical";
279 break;
280 case HidReportDescriptorItem::kCollectionTypeReport:
281 os << "Report";
282 break;
283 case HidReportDescriptorItem::kCollectionTypeNamedArray:
284 os << "Named Array";
285 break;
286 case HidReportDescriptorItem::kCollectionTypeUsageSwitch:
287 os << "Usage Switch";
288 break;
289 case HidReportDescriptorItem::kCollectionTypeUsageModifier:
290 os << "Usage Modifier";
291 break;
292 case HidReportDescriptorItem::kCollectionTypeReserved:
293 os << "Reserved";
294 break;
295 case HidReportDescriptorItem::kCollectionTypeVendor:
296 os << "Vendor";
297 break;
298 default:
299 NOTREACHED();
300 break;
302 return os;
305 std::ostream& operator<<(std::ostream& os,
306 const HidReportDescriptorItem& item) {
307 HidReportDescriptorItem::Tag item_tag = item.tag();
308 uint32_t data = item.GetShortData();
310 std::ostringstream sstr;
311 sstr << item_tag;
312 sstr << " (";
314 long pos = sstr.tellp();
315 switch (item_tag) {
316 case HidReportDescriptorItem::kTagDefault:
317 case HidReportDescriptorItem::kTagEndCollection:
318 case HidReportDescriptorItem::kTagPush:
319 case HidReportDescriptorItem::kTagPop:
320 case HidReportDescriptorItem::kTagLong:
321 break;
323 case HidReportDescriptorItem::kTagCollection:
324 sstr << HidReportDescriptorItem::GetCollectionTypeFromValue(data);
325 break;
327 case HidReportDescriptorItem::kTagInput:
328 case HidReportDescriptorItem::kTagOutput:
329 case HidReportDescriptorItem::kTagFeature:
330 sstr << (HidReportDescriptorItem::ReportInfo&)data;
331 break;
333 case HidReportDescriptorItem::kTagUsagePage:
334 sstr << (HidUsageAndPage::Page)data;
335 break;
337 case HidReportDescriptorItem::kTagUsage:
338 case HidReportDescriptorItem::kTagReportId:
339 sstr << "0x" << std::hex << std::uppercase << data;
340 break;
342 default:
343 sstr << data;
344 break;
346 if (pos == sstr.tellp()) {
347 std::string str = sstr.str();
348 str.erase(str.end() - 2, str.end());
349 os << str;
350 } else {
351 os << sstr.str() << ")";
354 return os;
357 const char kIndentStep[] = " ";
359 std::ostream& operator<<(std::ostream& os,
360 const HidReportDescriptor& descriptor) {
361 for (std::vector<linked_ptr<HidReportDescriptorItem> >::const_iterator
362 items_iter = descriptor.items().begin();
363 items_iter != descriptor.items().end();
364 ++items_iter) {
365 linked_ptr<HidReportDescriptorItem> item = *items_iter;
366 size_t indentLevel = item->GetDepth();
367 for (size_t i = 0; i < indentLevel; i++)
368 os << kIndentStep;
369 os << *item.get() << std::endl;
371 return os;
374 // See 'E.6 Report Descriptor (Keyboard)'
375 // in HID specifications (v1.11)
376 const uint8_t kKeyboard[] = {
377 0x05, 0x01, 0x09, 0x06, 0xA1, 0x01, 0x05, 0x07, 0x19, 0xE0, 0x29,
378 0xE7, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02,
379 0x95, 0x01, 0x75, 0x08, 0x81, 0x01, 0x95, 0x05, 0x75, 0x01, 0x05,
380 0x08, 0x19, 0x01, 0x29, 0x05, 0x91, 0x02, 0x95, 0x01, 0x75, 0x03,
381 0x91, 0x01, 0x95, 0x06, 0x75, 0x08, 0x15, 0x00, 0x25, 0x65, 0x05,
382 0x07, 0x19, 0x00, 0x29, 0x65, 0x81, 0x00, 0xC0};
384 // See 'E.10 Report Descriptor (Mouse)'
385 // in HID specifications (v1.11)
386 const uint8_t kMouse[] = {0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01, 0xA1,
387 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03, 0x15, 0x00,
388 0x25, 0x01, 0x95, 0x03, 0x75, 0x01, 0x81, 0x02, 0x95,
389 0x01, 0x75, 0x05, 0x81, 0x01, 0x05, 0x01, 0x09, 0x30,
390 0x09, 0x31, 0x15, 0x81, 0x25, 0x7F, 0x75, 0x08, 0x95,
391 0x02, 0x81, 0x06, 0xC0, 0xC0};
393 const uint8_t kLogitechUnifyingReceiver[] = {
394 0x06, 0x00, 0xFF, 0x09, 0x01, 0xA1, 0x01, 0x85, 0x10, 0x75, 0x08,
395 0x95, 0x06, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x09, 0x01, 0x81, 0x00,
396 0x09, 0x01, 0x91, 0x00, 0xC0, 0x06, 0x00, 0xFF, 0x09, 0x02, 0xA1,
397 0x01, 0x85, 0x11, 0x75, 0x08, 0x95, 0x13, 0x15, 0x00, 0x26, 0xFF,
398 0x00, 0x09, 0x02, 0x81, 0x00, 0x09, 0x02, 0x91, 0x00, 0xC0, 0x06,
399 0x00, 0xFF, 0x09, 0x04, 0xA1, 0x01, 0x85, 0x20, 0x75, 0x08, 0x95,
400 0x0E, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x09, 0x41, 0x81, 0x00, 0x09,
401 0x41, 0x91, 0x00, 0x85, 0x21, 0x95, 0x1F, 0x15, 0x00, 0x26, 0xFF,
402 0x00, 0x09, 0x42, 0x81, 0x00, 0x09, 0x42, 0x91, 0x00, 0xC0};
404 } // namespace
406 class HidReportDescriptorTest : public testing::Test {
408 protected:
409 virtual void SetUp() OVERRIDE { descriptor_ = NULL; }
411 virtual void TearDown() OVERRIDE {
412 if (descriptor_) {
413 delete descriptor_;
417 public:
418 void ParseDescriptor(const std::string& expected,
419 const uint8_t* bytes,
420 size_t size) {
421 descriptor_ = new HidReportDescriptor(bytes, size);
423 std::stringstream actual;
424 actual << *descriptor_;
426 std::cout << "HID report descriptor:" << std::endl;
427 std::cout << actual.str();
429 // TODO(jracle@logitech.com): refactor string comparison in favor of
430 // testing individual fields.
431 ASSERT_EQ(expected, actual.str());
434 void GetTopLevelCollections(const std::vector<HidUsageAndPage>& expected,
435 const uint8_t* bytes,
436 size_t size) {
437 descriptor_ = new HidReportDescriptor(bytes, size);
439 std::vector<HidUsageAndPage> actual;
440 descriptor_->GetTopLevelCollections(&actual);
442 std::cout << "HID top-level collections:" << std::endl;
443 for (std::vector<HidUsageAndPage>::const_iterator iter = actual.begin();
444 iter != actual.end();
445 ++iter) {
446 std::cout << *iter << std::endl;
449 ASSERT_THAT(actual, ContainerEq(expected));
452 private:
453 HidReportDescriptor* descriptor_;
456 TEST_F(HidReportDescriptorTest, ParseDescriptor_Keyboard) {
457 const char expected[] = {
458 "Usage Page (Generic Desktop)\n"
459 "Usage (0x6)\n"
460 "Collection (Physical)\n"
461 " Usage Page (Keyboard)\n"
462 " Usage Minimum (224)\n"
463 " Usage Maximum (231)\n"
464 " Logical Minimum (0)\n"
465 " Logical Maximum (1)\n"
466 " Report Size (1)\n"
467 " Report Count (8)\n"
468 " Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
469 " Report Count (1)\n"
470 " Report Size (8)\n"
471 " Input (Con|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
472 " Report Count (5)\n"
473 " Report Size (1)\n"
474 " Usage Page (Led)\n"
475 " Usage Minimum (1)\n"
476 " Usage Maximum (5)\n"
477 " Output (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
478 " Report Count (1)\n"
479 " Report Size (3)\n"
480 " Output (Con|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
481 " Report Count (6)\n"
482 " Report Size (8)\n"
483 " Logical Minimum (0)\n"
484 " Logical Maximum (101)\n"
485 " Usage Page (Keyboard)\n"
486 " Usage Minimum (0)\n"
487 " Usage Maximum (101)\n"
488 " Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
489 "End Collection\n"};
491 ParseDescriptor(std::string(expected), kKeyboard, sizeof(kKeyboard));
494 TEST_F(HidReportDescriptorTest, TopLevelCollections_Keyboard) {
495 HidUsageAndPage expected[] = {
496 HidUsageAndPage(0x06, HidUsageAndPage::kPageGenericDesktop)};
498 GetTopLevelCollections(std::vector<HidUsageAndPage>(
499 expected, expected + ARRAYSIZE_UNSAFE(expected)),
500 kKeyboard,
501 sizeof(kKeyboard));
504 TEST_F(HidReportDescriptorTest, ParseDescriptor_Mouse) {
505 const char expected[] = {
506 "Usage Page (Generic Desktop)\n"
507 "Usage (0x2)\n"
508 "Collection (Physical)\n"
509 " Usage (0x1)\n"
510 " Collection (Physical)\n"
511 " Usage Page (Button)\n"
512 " Usage Minimum (1)\n"
513 " Usage Maximum (3)\n"
514 " Logical Minimum (0)\n"
515 " Logical Maximum (1)\n"
516 " Report Count (3)\n"
517 " Report Size (1)\n"
518 " Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
519 " Report Count (1)\n"
520 " Report Size (5)\n"
521 " Input (Con|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
522 " Usage Page (Generic Desktop)\n"
523 " Usage (0x30)\n"
524 " Usage (0x31)\n"
525 " Logical Minimum (129)\n"
526 " Logical Maximum (127)\n"
527 " Report Size (8)\n"
528 " Report Count (2)\n"
529 " Input (Dat|Arr|Abs|NoWrp|Lin|Prf|NoNull|BitF)\n"
530 " End Collection\n"
531 "End Collection\n"};
533 ParseDescriptor(std::string(expected), kMouse, sizeof(kMouse));
536 TEST_F(HidReportDescriptorTest, TopLevelCollections_Mouse) {
537 HidUsageAndPage expected[] = {
538 HidUsageAndPage(0x02, HidUsageAndPage::kPageGenericDesktop)};
540 GetTopLevelCollections(std::vector<HidUsageAndPage>(
541 expected, expected + ARRAYSIZE_UNSAFE(expected)),
542 kMouse,
543 sizeof(kMouse));
546 TEST_F(HidReportDescriptorTest, ParseDescriptor_LogitechUnifyingReceiver) {
547 const char expected[] = {
548 "Usage Page (Vendor)\n"
549 "Usage (0x1)\n"
550 "Collection (Physical)\n"
551 " Report ID (0x10)\n"
552 " Report Size (8)\n"
553 " Report Count (6)\n"
554 " Logical Minimum (0)\n"
555 " Logical Maximum (255)\n"
556 " Usage (0x1)\n"
557 " Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
558 " Usage (0x1)\n"
559 " Output (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
560 "End Collection\n"
561 "Usage Page (Vendor)\n"
562 "Usage (0x2)\n"
563 "Collection (Physical)\n"
564 " Report ID (0x11)\n"
565 " Report Size (8)\n"
566 " Report Count (19)\n"
567 " Logical Minimum (0)\n"
568 " Logical Maximum (255)\n"
569 " Usage (0x2)\n"
570 " Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
571 " Usage (0x2)\n"
572 " Output (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
573 "End Collection\n"
574 "Usage Page (Vendor)\n"
575 "Usage (0x4)\n"
576 "Collection (Physical)\n"
577 " Report ID (0x20)\n"
578 " Report Size (8)\n"
579 " Report Count (14)\n"
580 " Logical Minimum (0)\n"
581 " Logical Maximum (255)\n"
582 " Usage (0x41)\n"
583 " Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
584 " Usage (0x41)\n"
585 " Output (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
586 " Report ID (0x21)\n"
587 " Report Count (31)\n"
588 " Logical Minimum (0)\n"
589 " Logical Maximum (255)\n"
590 " Usage (0x42)\n"
591 " Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
592 " Usage (0x42)\n"
593 " Output (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
594 "End Collection\n"};
596 ParseDescriptor(std::string(expected),
597 kLogitechUnifyingReceiver,
598 sizeof(kLogitechUnifyingReceiver));
601 TEST_F(HidReportDescriptorTest, TopLevelCollections_LogitechUnifyingReceiver) {
602 HidUsageAndPage expected[] = {
603 HidUsageAndPage(0x01, HidUsageAndPage::kPageVendor),
604 HidUsageAndPage(0x02, HidUsageAndPage::kPageVendor),
605 HidUsageAndPage(0x04, HidUsageAndPage::kPageVendor), };
607 GetTopLevelCollections(std::vector<HidUsageAndPage>(
608 expected, expected + ARRAYSIZE_UNSAFE(expected)),
609 kLogitechUnifyingReceiver,
610 sizeof(kLogitechUnifyingReceiver));
613 } // namespace device