| OLD | NEW |
| 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 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 | 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 <sstream> | 5 #include <sstream> |
| 6 | 6 |
| 7 #include "device/hid/hid_report_descriptor.h" | 7 #include "device/hid/hid_report_descriptor.h" |
| 8 #include "testing/gmock/include/gmock/gmock.h" | 8 #include "testing/gmock/include/gmock/gmock.h" |
| 9 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
| 10 | 10 |
| 11 using namespace testing; | 11 using namespace testing; |
| 12 | 12 |
| 13 namespace device { | 13 namespace device { |
| 14 | 14 |
| 15 namespace { | 15 namespace { |
| 16 | 16 |
| 17 std::ostream& operator<<(std::ostream& os, | 17 // Digitizer descriptor from HID descriptor tool |
| 18 const HidUsageAndPage::Page& usage_page) { | 18 // http://www.usb.org/developers/hidpage/dt2_4.zip |
| 19 switch (usage_page) { | 19 const uint8_t kDigitizer[] = { |
| 20 case HidUsageAndPage::kPageUndefined: | 20 0x05, 0x0d, // Usage Page (Digitizer) |
| 21 os << "Undefined"; | 21 0x09, 0x01, // Usage (0x1) |
| 22 break; | 22 0xa1, 0x01, // Collection (Application) |
| 23 case HidUsageAndPage::kPageGenericDesktop: | 23 0x85, 0x01, // Report ID (0x1) |
| 24 os << "Generic Desktop"; | 24 0x09, 0x21, // Usage (0x21) |
| 25 break; | 25 0xa1, 0x00, // Collection (Physical) |
| 26 case HidUsageAndPage::kPageSimulation: | 26 0x05, 0x01, // Usage Page (Generic Desktop) |
| 27 os << "Simulation"; | 27 0x09, 0x30, // Usage (0x30) |
| 28 break; | 28 0x09, 0x31, // Usage (0x31) |
| 29 case HidUsageAndPage::kPageVirtualReality: | 29 0x75, 0x10, // Report Size (16) |
| 30 os << "Virtual Reality"; | 30 0x95, 0x02, // Report Count (2) |
| 31 break; | 31 0x15, 0x00, // Logical Minimum (0) |
| 32 case HidUsageAndPage::kPageSport: | 32 0x26, 0xe0, 0x2e, // Logical Maximum (12000) |
| 33 os << "Sport"; | 33 0x35, 0x00, // Physical Minimum (0) |
| 34 break; | 34 0x45, 0x0c, // Physical Maximum (12) |
| 35 case HidUsageAndPage::kPageGame: | 35 0x65, 0x13, // Unit (19) |
| 36 os << "Game"; | 36 0x55, 0x00, // Unit Exponent (0) |
| 37 break; | 37 0xa4, // Push |
| 38 case HidUsageAndPage::kPageKeyboard: | 38 0x81, 0x02, // Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 39 os << "Keyboard"; | 39 0x05, 0x0d, // Usage Page (Digitizer) |
| 40 break; | 40 0x09, 0x32, // Usage (0x32) |
| 41 case HidUsageAndPage::kPageLed: | 41 0x09, 0x44, // Usage (0x44) |
| 42 os << "Led"; | 42 0x09, 0x42, // Usage (0x42) |
| 43 break; | 43 0x15, 0x00, // Logical Minimum (0) |
| 44 case HidUsageAndPage::kPageButton: | 44 0x25, 0x01, // Logical Maximum (1) |
| 45 os << "Button"; | 45 0x35, 0x00, // Physical Minimum (0) |
| 46 break; | 46 0x45, 0x01, // Physical Maximum (1) |
| 47 case HidUsageAndPage::kPageOrdinal: | 47 0x75, 0x01, // Report Size (1) |
| 48 os << "Ordinal"; | 48 0x95, 0x03, // Report Count (3) |
| 49 break; | 49 0x65, 0x00, // Unit (0) |
| 50 case HidUsageAndPage::kPageTelephony: | 50 0x81, 0x02, // Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 51 os << "Telephony"; | 51 0x95, 0x01, // Report Count (1) |
| 52 break; | 52 0x75, 0x05, // Report Size (5) |
| 53 case HidUsageAndPage::kPageConsumer: | 53 0x81, 0x03, // Input (Con|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 54 os << "Consumer"; | 54 0xc0, // End Collection |
| 55 break; | 55 0x85, 0x02, // Report ID (0x2) |
| 56 case HidUsageAndPage::kPageDigitizer: | 56 0x09, 0x20, // Usage (0x20) |
| 57 os << "Digitizer"; | 57 0xa1, 0x00, // Collection (Physical) |
| 58 break; | 58 0xb4, // Pop |
| 59 case HidUsageAndPage::kPagePidPage: | 59 0xa4, // Push |
| 60 os << "Pid Page"; | 60 0x09, 0x30, // Usage (0x30) |
| 61 break; | 61 0x09, 0x31, // Usage (0x31) |
| 62 case HidUsageAndPage::kPageUnicode: | 62 0x81, 0x02, // Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 63 os << "Unicode"; | 63 0x05, 0x0d, // Usage Page (Digitizer) |
| 64 break; | 64 0x09, 0x32, // Usage (0x32) |
| 65 case HidUsageAndPage::kPageAlphanumericDisplay: | 65 0x15, 0x00, // Logical Minimum (0) |
| 66 os << "Alphanumeric Display"; | 66 0x25, 0x01, // Logical Maximum (1) |
| 67 break; | 67 0x35, 0x00, // Physical Minimum (0) |
| 68 case HidUsageAndPage::kPageMedicalInstruments: | 68 0x45, 0x01, // Physical Maximum (1) |
| 69 os << "Medical Instruments"; | 69 0x65, 0x00, // Unit (0) |
| 70 break; | 70 0x75, 0x01, // Report Size (1) |
| 71 case HidUsageAndPage::kPageMonitor0: | 71 0x81, 0x02, // Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 72 os << "Monitor 0"; | 72 0x05, 0x09, // Usage Page (Button) |
| 73 break; | 73 0x19, 0x00, // Usage Minimum (0) |
| 74 case HidUsageAndPage::kPageMonitor1: | 74 0x29, 0x10, // Usage Maximum (16) |
| 75 os << "Monitor 1"; | 75 0x25, 0x10, // Logical Maximum (16) |
| 76 break; | 76 0x75, 0x05, // Report Size (5) |
| 77 case HidUsageAndPage::kPageMonitor2: | 77 0x81, 0x40, // Input (Dat|Var|Rel|NoWrp|Lin|Prf|Null|BitF) |
| 78 os << "Monitor 2"; | 78 0x75, 0x02, // Report Size (2) |
| 79 break; | 79 0x81, 0x01, // Input (Con|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 80 case HidUsageAndPage::kPageMonitor3: | 80 0xc0, // End Collection |
| 81 os << "Monitor 3"; | 81 0x85, 0x03, // Report ID (0x3) |
| 82 break; | 82 0x05, 0x0d, // Usage Page (Digitizer) |
| 83 case HidUsageAndPage::kPagePower0: | 83 0x09, 0x20, // Usage (0x20) |
| 84 os << "Power 0"; | 84 0xa1, 0x00, // Collection (Physical) |
| 85 break; | 85 0xb4, // Pop |
| 86 case HidUsageAndPage::kPagePower1: | 86 0x09, 0x30, // Usage (0x30) |
| 87 os << "Power 1"; | 87 0x09, 0x31, // Usage (0x31) |
| 88 break; | 88 0x81, 0x02, // Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 89 case HidUsageAndPage::kPagePower2: | 89 0x05, 0x0d, // Usage Page (Digitizer) |
| 90 os << "Power 2"; | 90 0x09, 0x32, // Usage (0x32) |
| 91 break; | 91 0x09, 0x44, // Usage (0x44) |
| 92 case HidUsageAndPage::kPagePower3: | 92 0x75, 0x01, // Report Size (1) |
| 93 os << "Power 3"; | 93 0x15, 0x00, // Logical Minimum (0) |
| 94 break; | 94 0x25, 0x01, // Logical Maximum (1) |
| 95 case HidUsageAndPage::kPageBarCodeScanner: | 95 0x35, 0x00, // Physical Minimum (0) |
| 96 os << "Bar Code Scanner"; | 96 0x45, 0x01, // Physical Maximum (1) |
| 97 break; | 97 0x65, 0x00, // Unit (0) |
| 98 case HidUsageAndPage::kPageScale: | 98 0x81, 0x02, // Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 99 os << "Scale"; | 99 0x95, 0x06, // Report Count (6) |
| 100 break; | 100 0x81, 0x03, // Input (Con|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 101 case HidUsageAndPage::kPageMagneticStripeReader: | 101 0x09, 0x30, // Usage (0x30) |
| 102 os << "Magnetic Stripe Reader"; | 102 0x15, 0x00, // Logical Minimum (0) |
| 103 break; | 103 0x25, 0x7f, // Logical Maximum (127) |
| 104 case HidUsageAndPage::kPageReservedPointOfSale: | 104 0x35, 0x00, // Physical Minimum (0) |
| 105 os << "Reserved Point Of Sale"; | 105 0x45, 0x2d, // Physical Maximum (45) |
| 106 break; | 106 0x67, 0x11, 0xe1, // Unit (57617) |
| 107 case HidUsageAndPage::kPageCameraControl: | 107 0x00, 0x00, // Default |
| 108 os << "Camera Control"; | 108 0x55, 0x04, // Unit Exponent (4) |
| 109 break; | 109 0x75, 0x08, // Report Size (8) |
| 110 case HidUsageAndPage::kPageArcade: | 110 0x95, 0x01, // Report Count (1) |
| 111 os << "Arcade"; | 111 0x81, 0x12, // Input (Dat|Arr|Rel|NoWrp|NoLin|Prf|NoNull|BitF) |
| 112 break; | 112 0xc0, // End Collection |
| 113 case HidUsageAndPage::kPageVendor: | 113 0xc0 // End Collection |
| 114 os << "Vendor"; | 114 }; |
| 115 break; | 115 |
| 116 case HidUsageAndPage::kPageMediaCenter: | 116 // Keyboard descriptor from HID descriptor tool |
| 117 os << "Media Center"; | 117 // http://www.usb.org/developers/hidpage/dt2_4.zip |
| 118 break; | |
| 119 default: | |
| 120 NOTREACHED(); | |
| 121 break; | |
| 122 } | |
| 123 return os; | |
| 124 } | |
| 125 | |
| 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; | |
| 131 } | |
| 132 | |
| 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; | |
| 226 } | |
| 227 | |
| 228 return os; | |
| 229 } | |
| 230 | |
| 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; | |
| 266 } | |
| 267 | |
| 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; | |
| 301 } | |
| 302 return os; | |
| 303 } | |
| 304 | |
| 305 std::ostream& operator<<(std::ostream& os, | |
| 306 const HidReportDescriptorItem& item) { | |
| 307 HidReportDescriptorItem::Tag item_tag = item.tag(); | |
| 308 uint32_t data = item.GetShortData(); | |
| 309 | |
| 310 std::ostringstream sstr; | |
| 311 sstr << item_tag; | |
| 312 sstr << " ("; | |
| 313 | |
| 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; | |
| 322 | |
| 323 case HidReportDescriptorItem::kTagCollection: | |
| 324 sstr << HidReportDescriptorItem::GetCollectionTypeFromValue(data); | |
| 325 break; | |
| 326 | |
| 327 case HidReportDescriptorItem::kTagInput: | |
| 328 case HidReportDescriptorItem::kTagOutput: | |
| 329 case HidReportDescriptorItem::kTagFeature: | |
| 330 sstr << (HidReportDescriptorItem::ReportInfo&)data; | |
| 331 break; | |
| 332 | |
| 333 case HidReportDescriptorItem::kTagUsagePage: | |
| 334 sstr << (HidUsageAndPage::Page)data; | |
| 335 break; | |
| 336 | |
| 337 case HidReportDescriptorItem::kTagUsage: | |
| 338 case HidReportDescriptorItem::kTagReportId: | |
| 339 sstr << "0x" << std::hex << std::uppercase << data; | |
| 340 break; | |
| 341 | |
| 342 default: | |
| 343 sstr << data; | |
| 344 break; | |
| 345 } | |
| 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() << ")"; | |
| 352 } | |
| 353 | |
| 354 return os; | |
| 355 } | |
| 356 | |
| 357 const char kIndentStep[] = " "; | |
| 358 | |
| 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; | |
| 370 } | |
| 371 return os; | |
| 372 } | |
| 373 | |
| 374 // See 'E.6 Report Descriptor (Keyboard)' | |
| 375 // in HID specifications (v1.11) | |
| 376 const uint8_t kKeyboard[] = { | 118 const uint8_t kKeyboard[] = { |
| 377 0x05, 0x01, 0x09, 0x06, 0xA1, 0x01, 0x05, 0x07, 0x19, 0xE0, 0x29, | 119 0x05, 0x01, // Usage Page (Generic Desktop) |
| 378 0xE7, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, | 120 0x09, 0x06, // Usage (0x6) |
| 379 0x95, 0x01, 0x75, 0x08, 0x81, 0x01, 0x95, 0x05, 0x75, 0x01, 0x05, | 121 0xa1, 0x01, // Collection (Application) |
| 380 0x08, 0x19, 0x01, 0x29, 0x05, 0x91, 0x02, 0x95, 0x01, 0x75, 0x03, | 122 0x05, 0x07, // Usage Page (Keyboard) |
| 381 0x91, 0x01, 0x95, 0x06, 0x75, 0x08, 0x15, 0x00, 0x25, 0x65, 0x05, | 123 0x19, 0xe0, // Usage Minimum (224) |
| 382 0x07, 0x19, 0x00, 0x29, 0x65, 0x81, 0x00, 0xC0}; | 124 0x29, 0xe7, // Usage Maximum (231) |
| 383 | 125 0x15, 0x00, // Logical Minimum (0) |
| 384 // See 'E.10 Report Descriptor (Mouse)' | 126 0x25, 0x01, // Logical Maximum (1) |
| 385 // in HID specifications (v1.11) | 127 0x75, 0x01, // Report Size (1) |
| 386 const uint8_t kMouse[] = {0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01, 0xA1, | 128 0x95, 0x08, // Report Count (8) |
| 387 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03, 0x15, 0x00, | 129 0x81, 0x02, // Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 388 0x25, 0x01, 0x95, 0x03, 0x75, 0x01, 0x81, 0x02, 0x95, | 130 0x95, 0x01, // Report Count (1) |
| 389 0x01, 0x75, 0x05, 0x81, 0x01, 0x05, 0x01, 0x09, 0x30, | 131 0x75, 0x08, // Report Size (8) |
| 390 0x09, 0x31, 0x15, 0x81, 0x25, 0x7F, 0x75, 0x08, 0x95, | 132 0x81, 0x03, // Input (Con|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 391 0x02, 0x81, 0x06, 0xC0, 0xC0}; | 133 0x95, 0x05, // Report Count (5) |
| 392 | 134 0x75, 0x01, // Report Size (1) |
| 135 0x05, 0x08, // Usage Page (Led) |
| 136 0x19, 0x01, // Usage Minimum (1) |
| 137 0x29, 0x05, // Usage Maximum (5) |
| 138 0x91, 0x02, // Output (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 139 0x95, 0x01, // Report Count (1) |
| 140 0x75, 0x03, // Report Size (3) |
| 141 0x91, 0x03, // Output (Con|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 142 0x95, 0x06, // Report Count (6) |
| 143 0x75, 0x08, // Report Size (8) |
| 144 0x15, 0x00, // Logical Minimum (0) |
| 145 0x25, 0x65, // Logical Maximum (101) |
| 146 0x05, 0x07, // Usage Page (Keyboard) |
| 147 0x19, 0x00, // Usage Minimum (0) |
| 148 0x29, 0x65, // Usage Maximum (101) |
| 149 0x81, 0x00, // Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 150 0xc0 // End Collection |
| 151 }; |
| 152 |
| 153 // Monitor descriptor from HID descriptor tool |
| 154 // http://www.usb.org/developers/hidpage/dt2_4.zip |
| 155 const uint8_t kMonitor[] = { |
| 156 0x05, 0x80, // Usage Page (Monitor 0) |
| 157 0x09, 0x01, // Usage (0x1) |
| 158 0xa1, 0x01, // Collection (Application) |
| 159 0x85, 0x01, // Report ID (0x1) |
| 160 0x15, 0x00, // Logical Minimum (0) |
| 161 0x26, 0xff, 0x00, // Logical Maximum (255) |
| 162 0x75, 0x08, // Report Size (8) |
| 163 0x95, 0x80, // Report Count (128) |
| 164 0x09, 0x02, // Usage (0x2) |
| 165 0xb2, 0x02, 0x01, // Feature (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|Buff) |
| 166 0x85, 0x02, // Report ID (0x2) |
| 167 0x95, 0xf3, // Report Count (243) |
| 168 0x09, 0x03, // Usage (0x3) |
| 169 0xb2, 0x02, 0x01, // Feature (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|Buff) |
| 170 0x85, 0x03, // Report ID (0x3) |
| 171 0x05, 0x82, // Usage Page (Monitor 2) |
| 172 0x95, 0x01, // Report Count (1) |
| 173 0x75, 0x10, // Report Size (16) |
| 174 0x26, 0xc8, 0x00, // Logical Maximum (200) |
| 175 0x09, 0x10, // Usage (0x10) |
| 176 0xb1, 0x02, // Feature (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 177 0x85, 0x04, // Report ID (0x4) |
| 178 0x25, 0x64, // Logical Maximum (100) |
| 179 0x09, 0x12, // Usage (0x12) |
| 180 0xb1, 0x02, // Feature (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 181 0x95, 0x06, // Report Count (6) |
| 182 0x26, 0xff, 0x00, // Logical Maximum (255) |
| 183 0x09, 0x16, // Usage (0x16) |
| 184 0x09, 0x18, // Usage (0x18) |
| 185 0x09, 0x1a, // Usage (0x1A) |
| 186 0x09, 0x6c, // Usage (0x6C) |
| 187 0x09, 0x6e, // Usage (0x6E) |
| 188 0x09, 0x70, // Usage (0x70) |
| 189 0xb1, 0x02, // Feature (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 190 0x85, 0x05, // Report ID (0x5) |
| 191 0x25, 0x7f, // Logical Maximum (127) |
| 192 0x09, 0x20, // Usage (0x20) |
| 193 0x09, 0x22, // Usage (0x22) |
| 194 0x09, 0x30, // Usage (0x30) |
| 195 0x09, 0x32, // Usage (0x32) |
| 196 0x09, 0x42, // Usage (0x42) |
| 197 0x09, 0x44, // Usage (0x44) |
| 198 0xb1, 0x02, // Feature (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 199 0xc0 // End Collection |
| 200 }; |
| 201 |
| 202 // Mouse descriptor from HID descriptor tool |
| 203 // http://www.usb.org/developers/hidpage/dt2_4.zip |
| 204 const uint8_t kMouse[] = { |
| 205 0x05, 0x01, // Usage Page (Generic Desktop) |
| 206 0x09, 0x02, // Usage (0x2) |
| 207 0xa1, 0x01, // Collection (Application) |
| 208 0x09, 0x01, // Usage (0x1) |
| 209 0xa1, 0x00, // Collection (Physical) |
| 210 0x05, 0x09, // Usage Page (Button) |
| 211 0x19, 0x01, // Usage Minimum (1) |
| 212 0x29, 0x03, // Usage Maximum (3) |
| 213 0x15, 0x00, // Logical Minimum (0) |
| 214 0x25, 0x01, // Logical Maximum (1) |
| 215 0x95, 0x03, // Report Count (3) |
| 216 0x75, 0x01, // Report Size (1) |
| 217 0x81, 0x02, // Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 218 0x95, 0x01, // Report Count (1) |
| 219 0x75, 0x05, // Report Size (5) |
| 220 0x81, 0x03, // Input (Con|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 221 0x05, 0x01, // Usage Page (Generic Desktop) |
| 222 0x09, 0x30, // Usage (0x30) |
| 223 0x09, 0x31, // Usage (0x31) |
| 224 0x15, 0x81, // Logical Minimum (129) |
| 225 0x25, 0x7f, // Logical Maximum (127) |
| 226 0x75, 0x08, // Report Size (8) |
| 227 0x95, 0x02, // Report Count (2) |
| 228 0x81, 0x06, // Input (Dat|Arr|Abs|NoWrp|Lin|Prf|NoNull|BitF) |
| 229 0xc0, // End Collection |
| 230 0xc0 // End Collection |
| 231 }; |
| 232 |
| 233 // Logitech Unifying receiver descriptor |
| 393 const uint8_t kLogitechUnifyingReceiver[] = { | 234 const uint8_t kLogitechUnifyingReceiver[] = { |
| 394 0x06, 0x00, 0xFF, 0x09, 0x01, 0xA1, 0x01, 0x85, 0x10, 0x75, 0x08, | 235 0x06, 0x00, 0xFF, // Usage Page (Vendor) |
| 395 0x95, 0x06, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x09, 0x01, 0x81, 0x00, | 236 0x09, 0x01, // Usage (0x1) |
| 396 0x09, 0x01, 0x91, 0x00, 0xC0, 0x06, 0x00, 0xFF, 0x09, 0x02, 0xA1, | 237 0xA1, 0x01, // Collection (Application) |
| 397 0x01, 0x85, 0x11, 0x75, 0x08, 0x95, 0x13, 0x15, 0x00, 0x26, 0xFF, | 238 0x85, 0x10, // Report ID (0x10) |
| 398 0x00, 0x09, 0x02, 0x81, 0x00, 0x09, 0x02, 0x91, 0x00, 0xC0, 0x06, | 239 0x75, 0x08, // Report Size (8) |
| 399 0x00, 0xFF, 0x09, 0x04, 0xA1, 0x01, 0x85, 0x20, 0x75, 0x08, 0x95, | 240 0x95, 0x06, // Report Count (6) |
| 400 0x0E, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x09, 0x41, 0x81, 0x00, 0x09, | 241 0x15, 0x00, // Logical Minimum (0) |
| 401 0x41, 0x91, 0x00, 0x85, 0x21, 0x95, 0x1F, 0x15, 0x00, 0x26, 0xFF, | 242 0x26, 0xFF, 0x00, // Logical Maximum (255) |
| 402 0x00, 0x09, 0x42, 0x81, 0x00, 0x09, 0x42, 0x91, 0x00, 0xC0}; | 243 0x09, 0x01, // Usage (0x1) |
| 244 0x81, 0x00, // Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 245 0x09, 0x01, // Usage (0x1) |
| 246 0x91, 0x00, // Output (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 247 0xC0, // End Collection |
| 248 0x06, 0x00, 0xFF, // Usage Page (Vendor) |
| 249 0x09, 0x02, // Usage (0x2) |
| 250 0xA1, 0x01, // Collection (Application) |
| 251 0x85, 0x11, // Report ID (0x11) |
| 252 0x75, 0x08, // Report Size (8) |
| 253 0x95, 0x13, // Report Count (19) |
| 254 0x15, 0x00, // Logical Minimum (0) |
| 255 0x26, 0xFF, 0x00, // Logical Maximum (255) |
| 256 0x09, 0x02, // Usage (0x2) |
| 257 0x81, 0x00, // Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 258 0x09, 0x02, // Usage (0x2) |
| 259 0x91, 0x00, // Output (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 260 0xC0, // End Collection |
| 261 0x06, 0x00, 0xFF, // Usage Page (Vendor) |
| 262 0x09, 0x04, // Usage (0x4) |
| 263 0xA1, 0x01, // Collection (Application) |
| 264 0x85, 0x20, // Report ID (0x20) |
| 265 0x75, 0x08, // Report Size (8) |
| 266 0x95, 0x0E, // Report Count (14) |
| 267 0x15, 0x00, // Logical Minimum (0) |
| 268 0x26, 0xFF, 0x00, // Logical Maximum (255) |
| 269 0x09, 0x41, // Usage (0x41) |
| 270 0x81, 0x00, // Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 271 0x09, 0x41, // Usage (0x41) |
| 272 0x91, 0x00, // Output (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 273 0x85, 0x21, // Report ID (0x21) |
| 274 0x95, 0x1F, // Report Count (31) |
| 275 0x15, 0x00, // Logical Minimum (0) |
| 276 0x26, 0xFF, 0x00, // Logical Maximum (255) |
| 277 0x09, 0x42, // Usage (0x42) |
| 278 0x81, 0x00, // Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 279 0x09, 0x42, // Usage (0x42) |
| 280 0x91, 0x00, // Output (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF) |
| 281 0xC0 // End Collection |
| 282 }; |
| 403 | 283 |
| 404 } // namespace | 284 } // namespace |
| 405 | 285 |
| 406 class HidReportDescriptorTest : public testing::Test { | 286 class HidReportDescriptorTest : public testing::Test { |
| 407 | 287 |
| 408 protected: | 288 protected: |
| 409 virtual void SetUp() OVERRIDE { descriptor_ = NULL; } | 289 virtual void SetUp() OVERRIDE { descriptor_ = NULL; } |
| 410 | 290 |
| 411 virtual void TearDown() OVERRIDE { | 291 virtual void TearDown() OVERRIDE { |
| 412 if (descriptor_) { | 292 if (descriptor_) { |
| 413 delete descriptor_; | 293 delete descriptor_; |
| 414 } | 294 } |
| 415 } | 295 } |
| 416 | 296 |
| 417 public: | 297 public: |
| 418 void ParseDescriptor(const std::string& expected, | 298 void ValidateDetails( |
| 419 const uint8_t* bytes, | 299 const std::vector<HidCollectionInfo>& expected_collections, |
| 420 size_t size) { | 300 const int expected_max_input_report_size, |
| 301 const int expected_max_output_report_size, |
| 302 const int expected_max_feature_report_size, |
| 303 const uint8_t* bytes, |
| 304 size_t size) { |
| 421 descriptor_ = new HidReportDescriptor(bytes, size); | 305 descriptor_ = new HidReportDescriptor(bytes, size); |
| 422 | 306 |
| 423 std::stringstream actual; | 307 std::vector<HidCollectionInfo> actual_collections; |
| 424 actual << *descriptor_; | 308 int actual_max_input_report_size; |
| 309 int actual_max_output_report_size; |
| 310 int actual_max_feature_report_size; |
| 311 descriptor_->GetDetails(&actual_collections, |
| 312 &actual_max_input_report_size, |
| 313 &actual_max_output_report_size, |
| 314 &actual_max_feature_report_size); |
| 425 | 315 |
| 426 std::cout << "HID report descriptor:" << std::endl; | 316 ASSERT_EQ(expected_collections.size(), actual_collections.size()); |
| 427 std::cout << actual.str(); | |
| 428 | 317 |
| 429 // TODO(jracle@logitech.com): refactor string comparison in favor of | 318 std::vector<HidCollectionInfo>::const_iterator actual_collections_iter = |
| 430 // testing individual fields. | 319 actual_collections.begin(); |
| 431 ASSERT_EQ(expected, actual.str()); | 320 std::vector<HidCollectionInfo>::const_iterator expected_collections_iter = |
| 432 } | 321 expected_collections.begin(); |
| 433 | 322 |
| 434 void GetTopLevelCollections(const std::vector<HidUsageAndPage>& expected, | 323 while (expected_collections_iter != expected_collections.end() && |
| 435 const uint8_t* bytes, | 324 actual_collections_iter != actual_collections.end()) { |
| 436 size_t size) { | 325 HidCollectionInfo expected_collection = *expected_collections_iter; |
| 437 descriptor_ = new HidReportDescriptor(bytes, size); | 326 HidCollectionInfo actual_collection = *actual_collections_iter; |
| 438 | 327 |
| 439 std::vector<HidUsageAndPage> actual; | 328 ASSERT_EQ(expected_collection.usage.usage_page, |
| 440 descriptor_->GetTopLevelCollections(&actual); | 329 actual_collection.usage.usage_page); |
| 330 ASSERT_EQ(expected_collection.usage.usage, actual_collection.usage.usage); |
| 331 ASSERT_THAT(actual_collection.report_ids, |
| 332 ContainerEq(expected_collection.report_ids)); |
| 441 | 333 |
| 442 std::cout << "HID top-level collections:" << std::endl; | 334 expected_collections_iter++; |
| 443 for (std::vector<HidUsageAndPage>::const_iterator iter = actual.begin(); | 335 actual_collections_iter++; |
| 444 iter != actual.end(); | |
| 445 ++iter) { | |
| 446 std::cout << *iter << std::endl; | |
| 447 } | 336 } |
| 448 | 337 |
| 449 ASSERT_THAT(actual, ContainerEq(expected)); | 338 ASSERT_EQ(expected_max_input_report_size, actual_max_input_report_size); |
| 339 ASSERT_EQ(expected_max_output_report_size, actual_max_output_report_size); |
| 340 ASSERT_EQ(expected_max_feature_report_size, actual_max_feature_report_size); |
| 450 } | 341 } |
| 451 | 342 |
| 452 private: | 343 private: |
| 453 HidReportDescriptor* descriptor_; | 344 HidReportDescriptor* descriptor_; |
| 454 }; | 345 }; |
| 455 | 346 |
| 456 TEST_F(HidReportDescriptorTest, ParseDescriptor_Keyboard) { | 347 TEST_F(HidReportDescriptorTest, ValidateDetails_Digitizer) { |
| 457 const char expected[] = { | 348 HidCollectionInfo digitizer; |
| 458 "Usage Page (Generic Desktop)\n" | 349 digitizer.usage = HidUsageAndPage(0x01, HidUsageAndPage::kPageDigitizer); |
| 459 "Usage (0x6)\n" | 350 digitizer.report_ids.insert(1); |
| 460 "Collection (Physical)\n" | 351 digitizer.report_ids.insert(2); |
| 461 " Usage Page (Keyboard)\n" | 352 digitizer.report_ids.insert(3); |
| 462 " Usage Minimum (224)\n" | 353 HidCollectionInfo expected[] = {digitizer}; |
| 463 " Usage Maximum (231)\n" | 354 ValidateDetails(std::vector<HidCollectionInfo>( |
| 464 " Logical Minimum (0)\n" | 355 expected, expected + ARRAYSIZE_UNSAFE(expected)), |
| 465 " Logical Maximum (1)\n" | 356 7, |
| 466 " Report Size (1)\n" | 357 0, |
| 467 " Report Count (8)\n" | 358 0, |
| 468 " Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n" | 359 kDigitizer, |
| 469 " Report Count (1)\n" | 360 sizeof(kDigitizer)); |
| 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"}; | |
| 490 | |
| 491 ParseDescriptor(std::string(expected), kKeyboard, sizeof(kKeyboard)); | |
| 492 } | 361 } |
| 493 | 362 |
| 494 TEST_F(HidReportDescriptorTest, TopLevelCollections_Keyboard) { | 363 TEST_F(HidReportDescriptorTest, ValidateDetails_Keyboard) { |
| 495 HidUsageAndPage expected[] = { | 364 HidCollectionInfo keyboard; |
| 496 HidUsageAndPage(0x06, HidUsageAndPage::kPageGenericDesktop)}; | 365 keyboard.usage = HidUsageAndPage(0x06, HidUsageAndPage::kPageGenericDesktop); |
| 497 | 366 HidCollectionInfo expected[] = {keyboard}; |
| 498 GetTopLevelCollections(std::vector<HidUsageAndPage>( | 367 ValidateDetails(std::vector<HidCollectionInfo>( |
| 499 expected, expected + ARRAYSIZE_UNSAFE(expected)), | 368 expected, expected + ARRAYSIZE_UNSAFE(expected)), |
| 500 kKeyboard, | 369 8, |
| 501 sizeof(kKeyboard)); | 370 1, |
| 371 0, |
| 372 kKeyboard, |
| 373 sizeof(kKeyboard)); |
| 502 } | 374 } |
| 503 | 375 |
| 504 TEST_F(HidReportDescriptorTest, ParseDescriptor_Mouse) { | 376 TEST_F(HidReportDescriptorTest, ValidateDetails_Monitor) { |
| 505 const char expected[] = { | 377 HidCollectionInfo monitor; |
| 506 "Usage Page (Generic Desktop)\n" | 378 monitor.usage = HidUsageAndPage(0x01, HidUsageAndPage::kPageMonitor0); |
| 507 "Usage (0x2)\n" | 379 monitor.report_ids.insert(1); |
| 508 "Collection (Physical)\n" | 380 monitor.report_ids.insert(2); |
| 509 " Usage (0x1)\n" | 381 monitor.report_ids.insert(3); |
| 510 " Collection (Physical)\n" | 382 monitor.report_ids.insert(4); |
| 511 " Usage Page (Button)\n" | 383 monitor.report_ids.insert(5); |
| 512 " Usage Minimum (1)\n" | 384 HidCollectionInfo expected[] = {monitor}; |
| 513 " Usage Maximum (3)\n" | 385 ValidateDetails(std::vector<HidCollectionInfo>( |
| 514 " Logical Minimum (0)\n" | 386 expected, expected + ARRAYSIZE_UNSAFE(expected)), |
| 515 " Logical Maximum (1)\n" | 387 0, |
| 516 " Report Count (3)\n" | 388 0, |
| 517 " Report Size (1)\n" | 389 244, |
| 518 " Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)\n" | 390 kMonitor, |
| 519 " Report Count (1)\n" | 391 sizeof(kMonitor)); |
| 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"}; | |
| 532 | |
| 533 ParseDescriptor(std::string(expected), kMouse, sizeof(kMouse)); | |
| 534 } | 392 } |
| 535 | 393 |
| 536 TEST_F(HidReportDescriptorTest, TopLevelCollections_Mouse) { | 394 TEST_F(HidReportDescriptorTest, ValidateDetails_Mouse) { |
| 537 HidUsageAndPage expected[] = { | 395 HidCollectionInfo mouse; |
| 538 HidUsageAndPage(0x02, HidUsageAndPage::kPageGenericDesktop)}; | 396 mouse.usage = HidUsageAndPage(0x02, HidUsageAndPage::kPageGenericDesktop); |
| 539 | 397 HidCollectionInfo expected[] = {mouse}; |
| 540 GetTopLevelCollections(std::vector<HidUsageAndPage>( | 398 ValidateDetails(std::vector<HidCollectionInfo>( |
| 541 expected, expected + ARRAYSIZE_UNSAFE(expected)), | 399 expected, expected + ARRAYSIZE_UNSAFE(expected)), |
| 542 kMouse, | 400 3, |
| 543 sizeof(kMouse)); | 401 0, |
| 402 0, |
| 403 kMouse, |
| 404 sizeof(kMouse)); |
| 544 } | 405 } |
| 545 | 406 |
| 546 TEST_F(HidReportDescriptorTest, ParseDescriptor_LogitechUnifyingReceiver) { | 407 TEST_F(HidReportDescriptorTest, ValidateDetails_LogitechUnifyingReceiver) { |
| 547 const char expected[] = { | 408 HidCollectionInfo hidpp_short; |
| 548 "Usage Page (Vendor)\n" | 409 hidpp_short.usage = HidUsageAndPage(0x01, HidUsageAndPage::kPageVendor); |
| 549 "Usage (0x1)\n" | 410 hidpp_short.report_ids.insert(0x10); |
| 550 "Collection (Physical)\n" | 411 HidCollectionInfo hidpp_long; |
| 551 " Report ID (0x10)\n" | 412 hidpp_long.usage = HidUsageAndPage(0x02, HidUsageAndPage::kPageVendor); |
| 552 " Report Size (8)\n" | 413 hidpp_long.report_ids.insert(0x11); |
| 553 " Report Count (6)\n" | 414 HidCollectionInfo hidpp_dj; |
| 554 " Logical Minimum (0)\n" | 415 hidpp_dj.usage = HidUsageAndPage(0x04, HidUsageAndPage::kPageVendor); |
| 555 " Logical Maximum (255)\n" | 416 hidpp_dj.report_ids.insert(0x20); |
| 556 " Usage (0x1)\n" | 417 hidpp_dj.report_ids.insert(0x21); |
| 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"}; | |
| 595 | 418 |
| 596 ParseDescriptor(std::string(expected), | 419 HidCollectionInfo expected[] = {hidpp_short, hidpp_long, hidpp_dj}; |
| 420 ValidateDetails(std::vector<HidCollectionInfo>( |
| 421 expected, expected + ARRAYSIZE_UNSAFE(expected)), |
| 422 32, |
| 423 32, |
| 424 0, |
| 597 kLogitechUnifyingReceiver, | 425 kLogitechUnifyingReceiver, |
| 598 sizeof(kLogitechUnifyingReceiver)); | 426 sizeof(kLogitechUnifyingReceiver)); |
| 599 } | 427 } |
| 600 | 428 |
| 601 TEST_F(HidReportDescriptorTest, TopLevelCollections_LogitechUnifyingReceiver) { | |
| 602 HidUsageAndPage expected[] = { | |
| 603 HidUsageAndPage(0x01, HidUsageAndPage::kPageVendor), | |
| 604 HidUsageAndPage(0x02, HidUsageAndPage::kPageVendor), | |
| 605 HidUsageAndPage(0x04, HidUsageAndPage::kPageVendor), }; | |
| 606 | |
| 607 GetTopLevelCollections(std::vector<HidUsageAndPage>( | |
| 608 expected, expected + ARRAYSIZE_UNSAFE(expected)), | |
| 609 kLogitechUnifyingReceiver, | |
| 610 sizeof(kLogitechUnifyingReceiver)); | |
| 611 } | |
| 612 | |
| 613 } // namespace device | 429 } // namespace device |
| OLD | NEW |