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 |