OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 #include <sstream> |
| 6 |
| 7 #include "device/hid/hid_report_descriptor.h" |
| 8 #include "testing/gmock/include/gmock/gmock.h" |
| 9 #include "testing/gtest/include/gtest/gtest.h" |
| 10 |
| 11 using namespace testing; |
| 12 |
| 13 namespace device { |
| 14 |
| 15 namespace { |
| 16 |
| 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; |
| 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[] = { |
| 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}; |
| 383 |
| 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}; |
| 392 |
| 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}; |
| 403 |
| 404 } // namespace |
| 405 |
| 406 class HidReportDescriptorTest : public testing::Test { |
| 407 |
| 408 protected: |
| 409 virtual void SetUp() OVERRIDE { descriptor_ = NULL; } |
| 410 |
| 411 virtual void TearDown() OVERRIDE { |
| 412 if (descriptor_) { |
| 413 delete descriptor_; |
| 414 } |
| 415 } |
| 416 |
| 417 public: |
| 418 void ParseDescriptor(const std::string& expected, |
| 419 const uint8_t* bytes, |
| 420 size_t size) { |
| 421 descriptor_ = new HidReportDescriptor(bytes, size); |
| 422 |
| 423 std::stringstream actual; |
| 424 actual << *descriptor_; |
| 425 |
| 426 std::cout << "HID report descriptor:" << std::endl; |
| 427 std::cout << actual.str(); |
| 428 |
| 429 // TODO(jracle@logitech.com): refactor string comparison in favor of |
| 430 // testing individual fields. |
| 431 ASSERT_EQ(expected, actual.str()); |
| 432 } |
| 433 |
| 434 void GetTopLevelCollections(const std::vector<HidUsageAndPage>& expected, |
| 435 const uint8_t* bytes, |
| 436 size_t size) { |
| 437 descriptor_ = new HidReportDescriptor(bytes, size); |
| 438 |
| 439 std::vector<HidUsageAndPage> actual; |
| 440 descriptor_->GetTopLevelCollections(&actual); |
| 441 |
| 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; |
| 447 } |
| 448 |
| 449 ASSERT_THAT(actual, ContainerEq(expected)); |
| 450 } |
| 451 |
| 452 private: |
| 453 HidReportDescriptor* descriptor_; |
| 454 }; |
| 455 |
| 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"}; |
| 490 |
| 491 ParseDescriptor(std::string(expected), kKeyboard, sizeof(kKeyboard)); |
| 492 } |
| 493 |
| 494 TEST_F(HidReportDescriptorTest, TopLevelCollections_Keyboard) { |
| 495 HidUsageAndPage expected[] = { |
| 496 HidUsageAndPage(0x06, HidUsageAndPage::kPageGenericDesktop)}; |
| 497 |
| 498 GetTopLevelCollections(std::vector<HidUsageAndPage>( |
| 499 expected, expected + ARRAYSIZE_UNSAFE(expected)), |
| 500 kKeyboard, |
| 501 sizeof(kKeyboard)); |
| 502 } |
| 503 |
| 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"}; |
| 532 |
| 533 ParseDescriptor(std::string(expected), kMouse, sizeof(kMouse)); |
| 534 } |
| 535 |
| 536 TEST_F(HidReportDescriptorTest, TopLevelCollections_Mouse) { |
| 537 HidUsageAndPage expected[] = { |
| 538 HidUsageAndPage(0x02, HidUsageAndPage::kPageGenericDesktop)}; |
| 539 |
| 540 GetTopLevelCollections(std::vector<HidUsageAndPage>( |
| 541 expected, expected + ARRAYSIZE_UNSAFE(expected)), |
| 542 kMouse, |
| 543 sizeof(kMouse)); |
| 544 } |
| 545 |
| 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"}; |
| 595 |
| 596 ParseDescriptor(std::string(expected), |
| 597 kLogitechUnifyingReceiver, |
| 598 sizeof(kLogitechUnifyingReceiver)); |
| 599 } |
| 600 |
| 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 |
OLD | NEW |