Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / device / hid / hid_report_descriptor_unittest.cc
index 0d25889..0cce2e6 100644 (file)
@@ -14,392 +14,272 @@ namespace device {
 
 namespace {
 
-std::ostream& operator<<(std::ostream& os,
-                         const HidUsageAndPage::Page& usage_page) {
-  switch (usage_page) {
-    case HidUsageAndPage::kPageUndefined:
-      os << "Undefined";
-      break;
-    case HidUsageAndPage::kPageGenericDesktop:
-      os << "Generic Desktop";
-      break;
-    case HidUsageAndPage::kPageSimulation:
-      os << "Simulation";
-      break;
-    case HidUsageAndPage::kPageVirtualReality:
-      os << "Virtual Reality";
-      break;
-    case HidUsageAndPage::kPageSport:
-      os << "Sport";
-      break;
-    case HidUsageAndPage::kPageGame:
-      os << "Game";
-      break;
-    case HidUsageAndPage::kPageKeyboard:
-      os << "Keyboard";
-      break;
-    case HidUsageAndPage::kPageLed:
-      os << "Led";
-      break;
-    case HidUsageAndPage::kPageButton:
-      os << "Button";
-      break;
-    case HidUsageAndPage::kPageOrdinal:
-      os << "Ordinal";
-      break;
-    case HidUsageAndPage::kPageTelephony:
-      os << "Telephony";
-      break;
-    case HidUsageAndPage::kPageConsumer:
-      os << "Consumer";
-      break;
-    case HidUsageAndPage::kPageDigitizer:
-      os << "Digitizer";
-      break;
-    case HidUsageAndPage::kPagePidPage:
-      os << "Pid Page";
-      break;
-    case HidUsageAndPage::kPageUnicode:
-      os << "Unicode";
-      break;
-    case HidUsageAndPage::kPageAlphanumericDisplay:
-      os << "Alphanumeric Display";
-      break;
-    case HidUsageAndPage::kPageMedicalInstruments:
-      os << "Medical Instruments";
-      break;
-    case HidUsageAndPage::kPageMonitor0:
-      os << "Monitor 0";
-      break;
-    case HidUsageAndPage::kPageMonitor1:
-      os << "Monitor 1";
-      break;
-    case HidUsageAndPage::kPageMonitor2:
-      os << "Monitor 2";
-      break;
-    case HidUsageAndPage::kPageMonitor3:
-      os << "Monitor 3";
-      break;
-    case HidUsageAndPage::kPagePower0:
-      os << "Power 0";
-      break;
-    case HidUsageAndPage::kPagePower1:
-      os << "Power 1";
-      break;
-    case HidUsageAndPage::kPagePower2:
-      os << "Power 2";
-      break;
-    case HidUsageAndPage::kPagePower3:
-      os << "Power 3";
-      break;
-    case HidUsageAndPage::kPageBarCodeScanner:
-      os << "Bar Code Scanner";
-      break;
-    case HidUsageAndPage::kPageScale:
-      os << "Scale";
-      break;
-    case HidUsageAndPage::kPageMagneticStripeReader:
-      os << "Magnetic Stripe Reader";
-      break;
-    case HidUsageAndPage::kPageReservedPointOfSale:
-      os << "Reserved Point Of Sale";
-      break;
-    case HidUsageAndPage::kPageCameraControl:
-      os << "Camera Control";
-      break;
-    case HidUsageAndPage::kPageArcade:
-      os << "Arcade";
-      break;
-    case HidUsageAndPage::kPageVendor:
-      os << "Vendor";
-      break;
-    case HidUsageAndPage::kPageMediaCenter:
-      os << "Media Center";
-      break;
-    default:
-      NOTREACHED();
-      break;
-  }
-  return os;
-}
-
-std::ostream& operator<<(std::ostream& os,
-                         const HidUsageAndPage& usage_and_page) {
-  os << "Usage Page: " << usage_and_page.usage_page << ", Usage: "
-     << "0x" << std::hex << std::uppercase << usage_and_page.usage;
-  return os;
-}
-
-std::ostream& operator<<(std::ostream& os,
-                         const HidReportDescriptorItem::Tag& tag) {
-  switch (tag) {
-    case HidReportDescriptorItem::kTagDefault:
-      os << "Default";
-      break;
-    case HidReportDescriptorItem::kTagInput:
-      os << "Input";
-      break;
-    case HidReportDescriptorItem::kTagOutput:
-      os << "Output";
-      break;
-    case HidReportDescriptorItem::kTagFeature:
-      os << "Feature";
-      break;
-    case HidReportDescriptorItem::kTagCollection:
-      os << "Collection";
-      break;
-    case HidReportDescriptorItem::kTagEndCollection:
-      os << "End Collection";
-      break;
-    case HidReportDescriptorItem::kTagUsagePage:
-      os << "Usage Page";
-      break;
-    case HidReportDescriptorItem::kTagLogicalMinimum:
-      os << "Logical Minimum";
-      break;
-    case HidReportDescriptorItem::kTagLogicalMaximum:
-      os << "Logical Maximum";
-      break;
-    case HidReportDescriptorItem::kTagPhysicalMinimum:
-      os << "Physical Minimum";
-      break;
-    case HidReportDescriptorItem::kTagPhysicalMaximum:
-      os << "Physical Maximum";
-      break;
-    case HidReportDescriptorItem::kTagUnitExponent:
-      os << "Unit Exponent";
-      break;
-    case HidReportDescriptorItem::kTagUnit:
-      os << "Unit";
-      break;
-    case HidReportDescriptorItem::kTagReportSize:
-      os << "Report Size";
-      break;
-    case HidReportDescriptorItem::kTagReportId:
-      os << "Report ID";
-      break;
-    case HidReportDescriptorItem::kTagReportCount:
-      os << "Report Count";
-      break;
-    case HidReportDescriptorItem::kTagPush:
-      os << "Push";
-      break;
-    case HidReportDescriptorItem::kTagPop:
-      os << "Pop";
-      break;
-    case HidReportDescriptorItem::kTagUsage:
-      os << "Usage";
-      break;
-    case HidReportDescriptorItem::kTagUsageMinimum:
-      os << "Usage Minimum";
-      break;
-    case HidReportDescriptorItem::kTagUsageMaximum:
-      os << "Usage Maximum";
-      break;
-    case HidReportDescriptorItem::kTagDesignatorIndex:
-      os << "Designator Index";
-      break;
-    case HidReportDescriptorItem::kTagDesignatorMinimum:
-      os << "Designator Minimum";
-      break;
-    case HidReportDescriptorItem::kTagDesignatorMaximum:
-      os << "Designator Maximum";
-      break;
-    case HidReportDescriptorItem::kTagStringIndex:
-      os << "String Index";
-      break;
-    case HidReportDescriptorItem::kTagStringMinimum:
-      os << "String Minimum";
-      break;
-    case HidReportDescriptorItem::kTagStringMaximum:
-      os << "String Maximum";
-      break;
-    case HidReportDescriptorItem::kTagDelimiter:
-      os << "Delimeter";
-      break;
-    case HidReportDescriptorItem::kTagLong:
-      os << "Long";
-      break;
-    default:
-      NOTREACHED();
-      break;
-  }
-
-  return os;
-}
-
-std::ostream& operator<<(std::ostream& os,
-                         const HidReportDescriptorItem::ReportInfo& data) {
-  if (data.data_or_constant)
-    os << "Con";
-  else
-    os << "Dat";
-  if (data.array_or_variable)
-    os << "|Arr";
-  else
-    os << "|Var";
-  if (data.absolute_or_relative)
-    os << "|Abs";
-  else
-    os << "|Rel";
-  if (data.wrap)
-    os << "|Wrp";
-  else
-    os << "|NoWrp";
-  if (data.linear)
-    os << "|NoLin";
-  else
-    os << "|Lin";
-  if (data.preferred)
-    os << "|NoPrf";
-  else
-    os << "|Prf";
-  if (data.null)
-    os << "|Null";
-  else
-    os << "|NoNull";
-  if (data.bit_field_or_buffer)
-    os << "|Buff";
-  else
-    os << "|BitF";
-  return os;
-}
-
-std::ostream& operator<<(std::ostream& os,
-                         const HidReportDescriptorItem::CollectionType& type) {
-  switch (type) {
-    case HidReportDescriptorItem::kCollectionTypePhysical:
-      os << "Physical";
-      break;
-    case HidReportDescriptorItem::kCollectionTypeApplication:
-      os << "Application";
-      break;
-    case HidReportDescriptorItem::kCollectionTypeLogical:
-      os << "Logical";
-      break;
-    case HidReportDescriptorItem::kCollectionTypeReport:
-      os << "Report";
-      break;
-    case HidReportDescriptorItem::kCollectionTypeNamedArray:
-      os << "Named Array";
-      break;
-    case HidReportDescriptorItem::kCollectionTypeUsageSwitch:
-      os << "Usage Switch";
-      break;
-    case HidReportDescriptorItem::kCollectionTypeUsageModifier:
-      os << "Usage Modifier";
-      break;
-    case HidReportDescriptorItem::kCollectionTypeReserved:
-      os << "Reserved";
-      break;
-    case HidReportDescriptorItem::kCollectionTypeVendor:
-      os << "Vendor";
-      break;
-    default:
-      NOTREACHED();
-      break;
-  }
-  return os;
-}
-
-std::ostream& operator<<(std::ostream& os,
-                         const HidReportDescriptorItem& item) {
-  HidReportDescriptorItem::Tag item_tag = item.tag();
-  uint32_t data = item.GetShortData();
-
-  std::ostringstream sstr;
-  sstr << item_tag;
-  sstr << " (";
-
-  long pos = sstr.tellp();
-  switch (item_tag) {
-    case HidReportDescriptorItem::kTagDefault:
-    case HidReportDescriptorItem::kTagEndCollection:
-    case HidReportDescriptorItem::kTagPush:
-    case HidReportDescriptorItem::kTagPop:
-    case HidReportDescriptorItem::kTagLong:
-      break;
-
-    case HidReportDescriptorItem::kTagCollection:
-      sstr << HidReportDescriptorItem::GetCollectionTypeFromValue(data);
-      break;
-
-    case HidReportDescriptorItem::kTagInput:
-    case HidReportDescriptorItem::kTagOutput:
-    case HidReportDescriptorItem::kTagFeature:
-      sstr << (HidReportDescriptorItem::ReportInfo&)data;
-      break;
-
-    case HidReportDescriptorItem::kTagUsagePage:
-      sstr << (HidUsageAndPage::Page)data;
-      break;
-
-    case HidReportDescriptorItem::kTagUsage:
-    case HidReportDescriptorItem::kTagReportId:
-      sstr << "0x" << std::hex << std::uppercase << data;
-      break;
-
-    default:
-      sstr << data;
-      break;
-  }
-  if (pos == sstr.tellp()) {
-    std::string str = sstr.str();
-    str.erase(str.end() - 2, str.end());
-    os << str;
-  } else {
-    os << sstr.str() << ")";
-  }
-
-  return os;
-}
-
-const char kIndentStep[] = " ";
-
-std::ostream& operator<<(std::ostream& os,
-                         const HidReportDescriptor& descriptor) {
-  for (std::vector<linked_ptr<HidReportDescriptorItem> >::const_iterator
-           items_iter = descriptor.items().begin();
-       items_iter != descriptor.items().end();
-       ++items_iter) {
-    linked_ptr<HidReportDescriptorItem> item = *items_iter;
-    size_t indentLevel = item->GetDepth();
-    for (size_t i = 0; i < indentLevel; i++)
-      os << kIndentStep;
-    os << *item.get() << std::endl;
-  }
-  return os;
-}
+// Digitizer descriptor from HID descriptor tool
+// http://www.usb.org/developers/hidpage/dt2_4.zip
+const uint8_t kDigitizer[] = {
+    0x05, 0x0d,        // Usage Page (Digitizer)
+    0x09, 0x01,        // Usage (0x1)
+    0xa1, 0x01,        // Collection (Application)
+    0x85, 0x01,        //  Report ID (0x1)
+    0x09, 0x21,        //  Usage (0x21)
+    0xa1, 0x00,        //  Collection (Physical)
+    0x05, 0x01,        //   Usage Page (Generic Desktop)
+    0x09, 0x30,        //   Usage (0x30)
+    0x09, 0x31,        //   Usage (0x31)
+    0x75, 0x10,        //   Report Size (16)
+    0x95, 0x02,        //   Report Count (2)
+    0x15, 0x00,        //   Logical Minimum (0)
+    0x26, 0xe0, 0x2e,  //   Logical Maximum (12000)
+    0x35, 0x00,        //   Physical Minimum (0)
+    0x45, 0x0c,        //   Physical Maximum (12)
+    0x65, 0x13,        //   Unit (19)
+    0x55, 0x00,        //   Unit Exponent (0)
+    0xa4,              //   Push
+    0x81, 0x02,        //   Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0x05, 0x0d,        //   Usage Page (Digitizer)
+    0x09, 0x32,        //   Usage (0x32)
+    0x09, 0x44,        //   Usage (0x44)
+    0x09, 0x42,        //   Usage (0x42)
+    0x15, 0x00,        //   Logical Minimum (0)
+    0x25, 0x01,        //   Logical Maximum (1)
+    0x35, 0x00,        //   Physical Minimum (0)
+    0x45, 0x01,        //   Physical Maximum (1)
+    0x75, 0x01,        //   Report Size (1)
+    0x95, 0x03,        //   Report Count (3)
+    0x65, 0x00,        //   Unit (0)
+    0x81, 0x02,        //   Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0x95, 0x01,        //   Report Count (1)
+    0x75, 0x05,        //   Report Size (5)
+    0x81, 0x03,        //   Input (Con|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0xc0,              //  End Collection
+    0x85, 0x02,        //  Report ID (0x2)
+    0x09, 0x20,        //  Usage (0x20)
+    0xa1, 0x00,        //  Collection (Physical)
+    0xb4,              //   Pop
+    0xa4,              //   Push
+    0x09, 0x30,        //   Usage (0x30)
+    0x09, 0x31,        //   Usage (0x31)
+    0x81, 0x02,        //   Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0x05, 0x0d,        //   Usage Page (Digitizer)
+    0x09, 0x32,        //   Usage (0x32)
+    0x15, 0x00,        //   Logical Minimum (0)
+    0x25, 0x01,        //   Logical Maximum (1)
+    0x35, 0x00,        //   Physical Minimum (0)
+    0x45, 0x01,        //   Physical Maximum (1)
+    0x65, 0x00,        //   Unit (0)
+    0x75, 0x01,        //   Report Size (1)
+    0x81, 0x02,        //   Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0x05, 0x09,        //   Usage Page (Button)
+    0x19, 0x00,        //   Usage Minimum (0)
+    0x29, 0x10,        //   Usage Maximum (16)
+    0x25, 0x10,        //   Logical Maximum (16)
+    0x75, 0x05,        //   Report Size (5)
+    0x81, 0x40,        //   Input (Dat|Var|Rel|NoWrp|Lin|Prf|Null|BitF)
+    0x75, 0x02,        //   Report Size (2)
+    0x81, 0x01,        //   Input (Con|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0xc0,              //  End Collection
+    0x85, 0x03,        //  Report ID (0x3)
+    0x05, 0x0d,        //  Usage Page (Digitizer)
+    0x09, 0x20,        //  Usage (0x20)
+    0xa1, 0x00,        //  Collection (Physical)
+    0xb4,              //   Pop
+    0x09, 0x30,        //   Usage (0x30)
+    0x09, 0x31,        //   Usage (0x31)
+    0x81, 0x02,        //   Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0x05, 0x0d,        //   Usage Page (Digitizer)
+    0x09, 0x32,        //   Usage (0x32)
+    0x09, 0x44,        //   Usage (0x44)
+    0x75, 0x01,        //   Report Size (1)
+    0x15, 0x00,        //   Logical Minimum (0)
+    0x25, 0x01,        //   Logical Maximum (1)
+    0x35, 0x00,        //   Physical Minimum (0)
+    0x45, 0x01,        //   Physical Maximum (1)
+    0x65, 0x00,        //   Unit (0)
+    0x81, 0x02,        //   Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0x95, 0x06,        //   Report Count (6)
+    0x81, 0x03,        //   Input (Con|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0x09, 0x30,        //   Usage (0x30)
+    0x15, 0x00,        //   Logical Minimum (0)
+    0x25, 0x7f,        //   Logical Maximum (127)
+    0x35, 0x00,        //   Physical Minimum (0)
+    0x45, 0x2d,        //   Physical Maximum (45)
+    0x67, 0x11, 0xe1,  //   Unit (57617)
+    0x00, 0x00,        //   Default
+    0x55, 0x04,        //   Unit Exponent (4)
+    0x75, 0x08,        //   Report Size (8)
+    0x95, 0x01,        //   Report Count (1)
+    0x81, 0x12,        //   Input (Dat|Arr|Rel|NoWrp|NoLin|Prf|NoNull|BitF)
+    0xc0,              //  End Collection
+    0xc0               // End Collection
+};
 
-// See 'E.6 Report Descriptor (Keyboard)'
-// in HID specifications (v1.11)
+// Keyboard descriptor from HID descriptor tool
+// http://www.usb.org/developers/hidpage/dt2_4.zip
 const uint8_t kKeyboard[] = {
-    0x05, 0x01, 0x09, 0x06, 0xA1, 0x01, 0x05, 0x07, 0x19, 0xE0, 0x29,
-    0xE7, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02,
-    0x95, 0x01, 0x75, 0x08, 0x81, 0x01, 0x95, 0x05, 0x75, 0x01, 0x05,
-    0x08, 0x19, 0x01, 0x29, 0x05, 0x91, 0x02, 0x95, 0x01, 0x75, 0x03,
-    0x91, 0x01, 0x95, 0x06, 0x75, 0x08, 0x15, 0x00, 0x25, 0x65, 0x05,
-    0x07, 0x19, 0x00, 0x29, 0x65, 0x81, 0x00, 0xC0};
+    0x05, 0x01,  // Usage Page (Generic Desktop)
+    0x09, 0x06,  // Usage (0x6)
+    0xa1, 0x01,  // Collection (Application)
+    0x05, 0x07,  //  Usage Page (Keyboard)
+    0x19, 0xe0,  //  Usage Minimum (224)
+    0x29, 0xe7,  //  Usage Maximum (231)
+    0x15, 0x00,  //  Logical Minimum (0)
+    0x25, 0x01,  //  Logical Maximum (1)
+    0x75, 0x01,  //  Report Size (1)
+    0x95, 0x08,  //  Report Count (8)
+    0x81, 0x02,  //  Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0x95, 0x01,  //  Report Count (1)
+    0x75, 0x08,  //  Report Size (8)
+    0x81, 0x03,  //  Input (Con|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0x95, 0x05,  //  Report Count (5)
+    0x75, 0x01,  //  Report Size (1)
+    0x05, 0x08,  //  Usage Page (Led)
+    0x19, 0x01,  //  Usage Minimum (1)
+    0x29, 0x05,  //  Usage Maximum (5)
+    0x91, 0x02,  //  Output (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0x95, 0x01,  //  Report Count (1)
+    0x75, 0x03,  //  Report Size (3)
+    0x91, 0x03,  //  Output (Con|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0x95, 0x06,  //  Report Count (6)
+    0x75, 0x08,  //  Report Size (8)
+    0x15, 0x00,  //  Logical Minimum (0)
+    0x25, 0x65,  //  Logical Maximum (101)
+    0x05, 0x07,  //  Usage Page (Keyboard)
+    0x19, 0x00,  //  Usage Minimum (0)
+    0x29, 0x65,  //  Usage Maximum (101)
+    0x81, 0x00,  //  Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0xc0         // End Collection
+};
 
-// See 'E.10 Report Descriptor (Mouse)'
-// in HID specifications (v1.11)
-const uint8_t kMouse[] = {0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01, 0xA1,
-                          0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03, 0x15, 0x00,
-                          0x25, 0x01, 0x95, 0x03, 0x75, 0x01, 0x81, 0x02, 0x95,
-                          0x01, 0x75, 0x05, 0x81, 0x01, 0x05, 0x01, 0x09, 0x30,
-                          0x09, 0x31, 0x15, 0x81, 0x25, 0x7F, 0x75, 0x08, 0x95,
-                          0x02, 0x81, 0x06, 0xC0, 0xC0};
+// Monitor descriptor from HID descriptor tool
+// http://www.usb.org/developers/hidpage/dt2_4.zip
+const uint8_t kMonitor[] = {
+    0x05, 0x80,        // Usage Page (Monitor 0)
+    0x09, 0x01,        // Usage (0x1)
+    0xa1, 0x01,        // Collection (Application)
+    0x85, 0x01,        //  Report ID (0x1)
+    0x15, 0x00,        //  Logical Minimum (0)
+    0x26, 0xff, 0x00,  //  Logical Maximum (255)
+    0x75, 0x08,        //  Report Size (8)
+    0x95, 0x80,        //  Report Count (128)
+    0x09, 0x02,        //  Usage (0x2)
+    0xb2, 0x02, 0x01,  //  Feature (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|Buff)
+    0x85, 0x02,        //  Report ID (0x2)
+    0x95, 0xf3,        //  Report Count (243)
+    0x09, 0x03,        //  Usage (0x3)
+    0xb2, 0x02, 0x01,  //  Feature (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|Buff)
+    0x85, 0x03,        //  Report ID (0x3)
+    0x05, 0x82,        //  Usage Page (Monitor 2)
+    0x95, 0x01,        //  Report Count (1)
+    0x75, 0x10,        //  Report Size (16)
+    0x26, 0xc8, 0x00,  //  Logical Maximum (200)
+    0x09, 0x10,        //  Usage (0x10)
+    0xb1, 0x02,        //  Feature (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0x85, 0x04,        //  Report ID (0x4)
+    0x25, 0x64,        //  Logical Maximum (100)
+    0x09, 0x12,        //  Usage (0x12)
+    0xb1, 0x02,        //  Feature (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0x95, 0x06,        //  Report Count (6)
+    0x26, 0xff, 0x00,  //  Logical Maximum (255)
+    0x09, 0x16,        //  Usage (0x16)
+    0x09, 0x18,        //  Usage (0x18)
+    0x09, 0x1a,        //  Usage (0x1A)
+    0x09, 0x6c,        //  Usage (0x6C)
+    0x09, 0x6e,        //  Usage (0x6E)
+    0x09, 0x70,        //  Usage (0x70)
+    0xb1, 0x02,        //  Feature (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0x85, 0x05,        //  Report ID (0x5)
+    0x25, 0x7f,        //  Logical Maximum (127)
+    0x09, 0x20,        //  Usage (0x20)
+    0x09, 0x22,        //  Usage (0x22)
+    0x09, 0x30,        //  Usage (0x30)
+    0x09, 0x32,        //  Usage (0x32)
+    0x09, 0x42,        //  Usage (0x42)
+    0x09, 0x44,        //  Usage (0x44)
+    0xb1, 0x02,        //  Feature (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0xc0               // End Collection
+};
 
+// Mouse descriptor from HID descriptor tool
+// http://www.usb.org/developers/hidpage/dt2_4.zip
+const uint8_t kMouse[] = {
+    0x05, 0x01,  // Usage Page (Generic Desktop)
+    0x09, 0x02,  // Usage (0x2)
+    0xa1, 0x01,  // Collection (Application)
+    0x09, 0x01,  //  Usage (0x1)
+    0xa1, 0x00,  //  Collection (Physical)
+    0x05, 0x09,  //   Usage Page (Button)
+    0x19, 0x01,  //   Usage Minimum (1)
+    0x29, 0x03,  //   Usage Maximum (3)
+    0x15, 0x00,  //   Logical Minimum (0)
+    0x25, 0x01,  //   Logical Maximum (1)
+    0x95, 0x03,  //   Report Count (3)
+    0x75, 0x01,  //   Report Size (1)
+    0x81, 0x02,  //   Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0x95, 0x01,  //   Report Count (1)
+    0x75, 0x05,  //   Report Size (5)
+    0x81, 0x03,  //   Input (Con|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0x05, 0x01,  //   Usage Page (Generic Desktop)
+    0x09, 0x30,  //   Usage (0x30)
+    0x09, 0x31,  //   Usage (0x31)
+    0x15, 0x81,  //   Logical Minimum (129)
+    0x25, 0x7f,  //   Logical Maximum (127)
+    0x75, 0x08,  //   Report Size (8)
+    0x95, 0x02,  //   Report Count (2)
+    0x81, 0x06,  //   Input (Dat|Arr|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0xc0,        //  End Collection
+    0xc0         // End Collection
+};
+
+// Logitech Unifying receiver descriptor
 const uint8_t kLogitechUnifyingReceiver[] = {
-    0x06, 0x00, 0xFF, 0x09, 0x01, 0xA1, 0x01, 0x85, 0x10, 0x75, 0x08,
-    0x95, 0x06, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x09, 0x01, 0x81, 0x00,
-    0x09, 0x01, 0x91, 0x00, 0xC0, 0x06, 0x00, 0xFF, 0x09, 0x02, 0xA1,
-    0x01, 0x85, 0x11, 0x75, 0x08, 0x95, 0x13, 0x15, 0x00, 0x26, 0xFF,
-    0x00, 0x09, 0x02, 0x81, 0x00, 0x09, 0x02, 0x91, 0x00, 0xC0, 0x06,
-    0x00, 0xFF, 0x09, 0x04, 0xA1, 0x01, 0x85, 0x20, 0x75, 0x08, 0x95,
-    0x0E, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x09, 0x41, 0x81, 0x00, 0x09,
-    0x41, 0x91, 0x00, 0x85, 0x21, 0x95, 0x1F, 0x15, 0x00, 0x26, 0xFF,
-    0x00, 0x09, 0x42, 0x81, 0x00, 0x09, 0x42, 0x91, 0x00, 0xC0};
+    0x06, 0x00, 0xFF,  // Usage Page (Vendor)
+    0x09, 0x01,        // Usage (0x1)
+    0xA1, 0x01,        // Collection (Application)
+    0x85, 0x10,        //  Report ID (0x10)
+    0x75, 0x08,        //  Report Size (8)
+    0x95, 0x06,        //  Report Count (6)
+    0x15, 0x00,        //  Logical Minimum (0)
+    0x26, 0xFF, 0x00,  //  Logical Maximum (255)
+    0x09, 0x01,        //  Usage (0x1)
+    0x81, 0x00,        //  Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0x09, 0x01,        //  Usage (0x1)
+    0x91, 0x00,        //  Output (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0xC0,              // End Collection
+    0x06, 0x00, 0xFF,  // Usage Page (Vendor)
+    0x09, 0x02,        // Usage (0x2)
+    0xA1, 0x01,        // Collection (Application)
+    0x85, 0x11,        //  Report ID (0x11)
+    0x75, 0x08,        //  Report Size (8)
+    0x95, 0x13,        //  Report Count (19)
+    0x15, 0x00,        //  Logical Minimum (0)
+    0x26, 0xFF, 0x00,  //  Logical Maximum (255)
+    0x09, 0x02,        //  Usage (0x2)
+    0x81, 0x00,        //  Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0x09, 0x02,        //  Usage (0x2)
+    0x91, 0x00,        //  Output (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0xC0,              // End Collection
+    0x06, 0x00, 0xFF,  // Usage Page (Vendor)
+    0x09, 0x04,        // Usage (0x4)
+    0xA1, 0x01,        // Collection (Application)
+    0x85, 0x20,        //  Report ID (0x20)
+    0x75, 0x08,        //  Report Size (8)
+    0x95, 0x0E,        //  Report Count (14)
+    0x15, 0x00,        //  Logical Minimum (0)
+    0x26, 0xFF, 0x00,  //  Logical Maximum (255)
+    0x09, 0x41,        //  Usage (0x41)
+    0x81, 0x00,        //  Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0x09, 0x41,        //  Usage (0x41)
+    0x91, 0x00,        //  Output (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0x85, 0x21,        //  Report ID (0x21)
+    0x95, 0x1F,        //  Report Count (31)
+    0x15, 0x00,        //  Logical Minimum (0)
+    0x26, 0xFF, 0x00,  //  Logical Maximum (255)
+    0x09, 0x42,        //  Usage (0x42)
+    0x81, 0x00,        //  Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0x09, 0x42,        //  Usage (0x42)
+    0x91, 0x00,        //  Output (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0xC0               // End Collection
+};
 
 }  // namespace
 
@@ -415,199 +295,144 @@ class HidReportDescriptorTest : public testing::Test {
   }
 
  public:
-  void ParseDescriptor(const std::string& expected,
-                       const uint8_t* bytes,
-                       size_t size) {
+  void ValidateDetails(
+      const std::vector<HidCollectionInfo>& expected_collections,
+      const bool expected_has_report_id,
+      const int expected_max_input_report_size,
+      const int expected_max_output_report_size,
+      const int expected_max_feature_report_size,
+      const uint8_t* bytes,
+      size_t size) {
     descriptor_ = new HidReportDescriptor(bytes, size);
 
-    std::stringstream actual;
-    actual << *descriptor_;
-
-    std::cout << "HID report descriptor:" << std::endl;
-    std::cout << actual.str();
-
-    // TODO(jracle@logitech.com): refactor string comparison in favor of
-    // testing individual fields.
-    ASSERT_EQ(expected, actual.str());
-  }
-
-  void GetTopLevelCollections(const std::vector<HidUsageAndPage>& expected,
-                              const uint8_t* bytes,
-                              size_t size) {
-    descriptor_ = new HidReportDescriptor(bytes, size);
-
-    std::vector<HidUsageAndPage> actual;
-    descriptor_->GetTopLevelCollections(&actual);
-
-    std::cout << "HID top-level collections:" << std::endl;
-    for (std::vector<HidUsageAndPage>::const_iterator iter = actual.begin();
-         iter != actual.end();
-         ++iter) {
-      std::cout << *iter << std::endl;
+    std::vector<HidCollectionInfo> actual_collections;
+    bool actual_has_report_id;
+    int actual_max_input_report_size;
+    int actual_max_output_report_size;
+    int actual_max_feature_report_size;
+    descriptor_->GetDetails(&actual_collections,
+                            &actual_has_report_id,
+                            &actual_max_input_report_size,
+                            &actual_max_output_report_size,
+                            &actual_max_feature_report_size);
+
+    ASSERT_EQ(expected_collections.size(), actual_collections.size());
+
+    std::vector<HidCollectionInfo>::const_iterator actual_collections_iter =
+        actual_collections.begin();
+    std::vector<HidCollectionInfo>::const_iterator expected_collections_iter =
+        expected_collections.begin();
+
+    while (expected_collections_iter != expected_collections.end() &&
+           actual_collections_iter != actual_collections.end()) {
+      HidCollectionInfo expected_collection = *expected_collections_iter;
+      HidCollectionInfo actual_collection = *actual_collections_iter;
+
+      ASSERT_EQ(expected_collection.usage.usage_page,
+                actual_collection.usage.usage_page);
+      ASSERT_EQ(expected_collection.usage.usage, actual_collection.usage.usage);
+      ASSERT_THAT(actual_collection.report_ids,
+                  ContainerEq(expected_collection.report_ids));
+
+      expected_collections_iter++;
+      actual_collections_iter++;
     }
 
-    ASSERT_THAT(actual, ContainerEq(expected));
+    ASSERT_EQ(expected_has_report_id, actual_has_report_id);
+    ASSERT_EQ(expected_max_input_report_size, actual_max_input_report_size);
+    ASSERT_EQ(expected_max_output_report_size, actual_max_output_report_size);
+    ASSERT_EQ(expected_max_feature_report_size, actual_max_feature_report_size);
   }
 
  private:
   HidReportDescriptor* descriptor_;
 };
 
-TEST_F(HidReportDescriptorTest, ParseDescriptor_Keyboard) {
-  const char expected[] = {
-      "Usage Page (Generic Desktop)\n"
-      "Usage (0x6)\n"
-      "Collection (Physical)\n"
-      " Usage Page (Keyboard)\n"
-      " Usage Minimum (224)\n"
-      " Usage Maximum (231)\n"
-      " Logical Minimum (0)\n"
-      " Logical Maximum (1)\n"
-      " Report Size (1)\n"
-      " Report Count (8)\n"
-      " Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
-      " Report Count (1)\n"
-      " Report Size (8)\n"
-      " Input (Con|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
-      " Report Count (5)\n"
-      " Report Size (1)\n"
-      " Usage Page (Led)\n"
-      " Usage Minimum (1)\n"
-      " Usage Maximum (5)\n"
-      " Output (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
-      " Report Count (1)\n"
-      " Report Size (3)\n"
-      " Output (Con|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
-      " Report Count (6)\n"
-      " Report Size (8)\n"
-      " Logical Minimum (0)\n"
-      " Logical Maximum (101)\n"
-      " Usage Page (Keyboard)\n"
-      " Usage Minimum (0)\n"
-      " Usage Maximum (101)\n"
-      " Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
-      "End Collection\n"};
-
-  ParseDescriptor(std::string(expected), kKeyboard, sizeof(kKeyboard));
+TEST_F(HidReportDescriptorTest, ValidateDetails_Digitizer) {
+  HidCollectionInfo digitizer;
+  digitizer.usage = HidUsageAndPage(0x01, HidUsageAndPage::kPageDigitizer);
+  digitizer.report_ids.insert(1);
+  digitizer.report_ids.insert(2);
+  digitizer.report_ids.insert(3);
+  HidCollectionInfo expected[] = {digitizer};
+  ValidateDetails(std::vector<HidCollectionInfo>(
+                      expected, expected + ARRAYSIZE_UNSAFE(expected)),
+                  true,
+                  6,
+                  0,
+                  0,
+                  kDigitizer,
+                  sizeof(kDigitizer));
 }
 
-TEST_F(HidReportDescriptorTest, TopLevelCollections_Keyboard) {
-  HidUsageAndPage expected[] = {
-      HidUsageAndPage(0x06, HidUsageAndPage::kPageGenericDesktop)};
-
-  GetTopLevelCollections(std::vector<HidUsageAndPage>(
-                             expected, expected + ARRAYSIZE_UNSAFE(expected)),
-                         kKeyboard,
-                         sizeof(kKeyboard));
+TEST_F(HidReportDescriptorTest, ValidateDetails_Keyboard) {
+  HidCollectionInfo keyboard;
+  keyboard.usage = HidUsageAndPage(0x06, HidUsageAndPage::kPageGenericDesktop);
+  HidCollectionInfo expected[] = {keyboard};
+  ValidateDetails(std::vector<HidCollectionInfo>(
+                      expected, expected + ARRAYSIZE_UNSAFE(expected)),
+                  false,
+                  8,
+                  1,
+                  0,
+                  kKeyboard,
+                  sizeof(kKeyboard));
 }
 
-TEST_F(HidReportDescriptorTest, ParseDescriptor_Mouse) {
-  const char expected[] = {
-      "Usage Page (Generic Desktop)\n"
-      "Usage (0x2)\n"
-      "Collection (Physical)\n"
-      " Usage (0x1)\n"
-      " Collection (Physical)\n"
-      "  Usage Page (Button)\n"
-      "  Usage Minimum (1)\n"
-      "  Usage Maximum (3)\n"
-      "  Logical Minimum (0)\n"
-      "  Logical Maximum (1)\n"
-      "  Report Count (3)\n"
-      "  Report Size (1)\n"
-      "  Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
-      "  Report Count (1)\n"
-      "  Report Size (5)\n"
-      "  Input (Con|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
-      "  Usage Page (Generic Desktop)\n"
-      "  Usage (0x30)\n"
-      "  Usage (0x31)\n"
-      "  Logical Minimum (129)\n"
-      "  Logical Maximum (127)\n"
-      "  Report Size (8)\n"
-      "  Report Count (2)\n"
-      "  Input (Dat|Arr|Abs|NoWrp|Lin|Prf|NoNull|BitF)\n"
-      " End Collection\n"
-      "End Collection\n"};
-
-  ParseDescriptor(std::string(expected), kMouse, sizeof(kMouse));
+TEST_F(HidReportDescriptorTest, ValidateDetails_Monitor) {
+  HidCollectionInfo monitor;
+  monitor.usage = HidUsageAndPage(0x01, HidUsageAndPage::kPageMonitor0);
+  monitor.report_ids.insert(1);
+  monitor.report_ids.insert(2);
+  monitor.report_ids.insert(3);
+  monitor.report_ids.insert(4);
+  monitor.report_ids.insert(5);
+  HidCollectionInfo expected[] = {monitor};
+  ValidateDetails(std::vector<HidCollectionInfo>(
+                      expected, expected + ARRAYSIZE_UNSAFE(expected)),
+                  true,
+                  0,
+                  0,
+                  243,
+                  kMonitor,
+                  sizeof(kMonitor));
 }
 
-TEST_F(HidReportDescriptorTest, TopLevelCollections_Mouse) {
-  HidUsageAndPage expected[] = {
-      HidUsageAndPage(0x02, HidUsageAndPage::kPageGenericDesktop)};
-
-  GetTopLevelCollections(std::vector<HidUsageAndPage>(
-                             expected, expected + ARRAYSIZE_UNSAFE(expected)),
-                         kMouse,
-                         sizeof(kMouse));
+TEST_F(HidReportDescriptorTest, ValidateDetails_Mouse) {
+  HidCollectionInfo mouse;
+  mouse.usage = HidUsageAndPage(0x02, HidUsageAndPage::kPageGenericDesktop);
+  HidCollectionInfo expected[] = {mouse};
+  ValidateDetails(std::vector<HidCollectionInfo>(
+                      expected, expected + ARRAYSIZE_UNSAFE(expected)),
+                  false,
+                  3,
+                  0,
+                  0,
+                  kMouse,
+                  sizeof(kMouse));
 }
 
-TEST_F(HidReportDescriptorTest, ParseDescriptor_LogitechUnifyingReceiver) {
-  const char expected[] = {
-      "Usage Page (Vendor)\n"
-      "Usage (0x1)\n"
-      "Collection (Physical)\n"
-      " Report ID (0x10)\n"
-      " Report Size (8)\n"
-      " Report Count (6)\n"
-      " Logical Minimum (0)\n"
-      " Logical Maximum (255)\n"
-      " Usage (0x1)\n"
-      " Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
-      " Usage (0x1)\n"
-      " Output (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
-      "End Collection\n"
-      "Usage Page (Vendor)\n"
-      "Usage (0x2)\n"
-      "Collection (Physical)\n"
-      " Report ID (0x11)\n"
-      " Report Size (8)\n"
-      " Report Count (19)\n"
-      " Logical Minimum (0)\n"
-      " Logical Maximum (255)\n"
-      " Usage (0x2)\n"
-      " Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
-      " Usage (0x2)\n"
-      " Output (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
-      "End Collection\n"
-      "Usage Page (Vendor)\n"
-      "Usage (0x4)\n"
-      "Collection (Physical)\n"
-      " Report ID (0x20)\n"
-      " Report Size (8)\n"
-      " Report Count (14)\n"
-      " Logical Minimum (0)\n"
-      " Logical Maximum (255)\n"
-      " Usage (0x41)\n"
-      " Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
-      " Usage (0x41)\n"
-      " Output (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
-      " Report ID (0x21)\n"
-      " Report Count (31)\n"
-      " Logical Minimum (0)\n"
-      " Logical Maximum (255)\n"
-      " Usage (0x42)\n"
-      " Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
-      " Usage (0x42)\n"
-      " Output (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n"
-      "End Collection\n"};
-
-  ParseDescriptor(std::string(expected),
+TEST_F(HidReportDescriptorTest, ValidateDetails_LogitechUnifyingReceiver) {
+  HidCollectionInfo hidpp_short;
+  hidpp_short.usage = HidUsageAndPage(0x01, HidUsageAndPage::kPageVendor);
+  hidpp_short.report_ids.insert(0x10);
+  HidCollectionInfo hidpp_long;
+  hidpp_long.usage = HidUsageAndPage(0x02, HidUsageAndPage::kPageVendor);
+  hidpp_long.report_ids.insert(0x11);
+  HidCollectionInfo hidpp_dj;
+  hidpp_dj.usage = HidUsageAndPage(0x04, HidUsageAndPage::kPageVendor);
+  hidpp_dj.report_ids.insert(0x20);
+  hidpp_dj.report_ids.insert(0x21);
+
+  HidCollectionInfo expected[] = {hidpp_short, hidpp_long, hidpp_dj};
+  ValidateDetails(std::vector<HidCollectionInfo>(
+                      expected, expected + ARRAYSIZE_UNSAFE(expected)),
+                  true,
+                  31,
+                  31,
+                  0,
                   kLogitechUnifyingReceiver,
                   sizeof(kLogitechUnifyingReceiver));
 }
 
-TEST_F(HidReportDescriptorTest, TopLevelCollections_LogitechUnifyingReceiver) {
-  HidUsageAndPage expected[] = {
-      HidUsageAndPage(0x01, HidUsageAndPage::kPageVendor),
-      HidUsageAndPage(0x02, HidUsageAndPage::kPageVendor),
-      HidUsageAndPage(0x04, HidUsageAndPage::kPageVendor), };
-
-  GetTopLevelCollections(std::vector<HidUsageAndPage>(
-                             expected, expected + ARRAYSIZE_UNSAFE(expected)),
-                         kLogitechUnifyingReceiver,
-                         sizeof(kLogitechUnifyingReceiver));
-}
-
 }  // namespace device