2 * HID descriptor parsing
4 * Copyright (C) 2015 Aric Stewart
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define NONAMELESSUNION
27 #include "wine/debug.h"
28 #include "wine/list.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(hid
);
32 /* Flags that are defined in the document
33 "Device Class Definition for Human Interface Devices" */
35 INPUT_DATA_CONST
= 0x01, /* Data (0) | Constant (1) */
36 INPUT_ARRAY_VAR
= 0x02, /* Array (0) | Variable (1) */
37 INPUT_ABS_REL
= 0x04, /* Absolute (0) | Relative (1) */
38 INPUT_WRAP
= 0x08, /* No Wrap (0) | Wrap (1) */
39 INPUT_LINEAR
= 0x10, /* Linear (0) | Non Linear (1) */
40 INPUT_PREFSTATE
= 0x20, /* Preferred State (0) | No Preferred (1) */
41 INPUT_NULL
= 0x40, /* No Null position (0) | Null state(1) */
42 INPUT_VOLATILE
= 0x80, /* Non Volatile (0) | Volatile (1) */
43 INPUT_BITFIELD
= 0x100 /* Bit Field (0) | Buffered Bytes (1) */
54 TAG_MAIN_INPUT
= 0x08,
55 TAG_MAIN_OUTPUT
= 0x09,
56 TAG_MAIN_FEATURE
= 0x0B,
57 TAG_MAIN_COLLECTION
= 0x0A,
58 TAG_MAIN_END_COLLECTION
= 0x0C
62 TAG_GLOBAL_USAGE_PAGE
= 0x0,
63 TAG_GLOBAL_LOGICAL_MINIMUM
,
64 TAG_GLOBAL_LOGICAL_MAXIMUM
,
65 TAG_GLOBAL_PHYSICAL_MINIMUM
,
66 TAG_GLOBAL_PHYSICAL_MAXIMUM
,
67 TAG_GLOBAL_UNIT_EXPONENT
,
69 TAG_GLOBAL_REPORT_SIZE
,
71 TAG_GLOBAL_REPORT_COUNT
,
77 TAG_LOCAL_USAGE
= 0x0,
78 TAG_LOCAL_USAGE_MINIMUM
,
79 TAG_LOCAL_USAGE_MAXIMUM
,
80 TAG_LOCAL_DESIGNATOR_INDEX
,
81 TAG_LOCAL_DESIGNATOR_MINIMUM
,
82 TAG_LOCAL_DESIGNATOR_MAXIMUM
,
83 TAG_LOCAL_STRING_INDEX
,
84 TAG_LOCAL_STRING_MINIMUM
,
85 TAG_LOCAL_STRING_MAXIMUM
,
90 static const char* const feature_string
[] =
91 { "Input", "Output", "Feature" };
106 BOOLEAN IsStringRange
;
107 BOOLEAN IsDesignatorRange
;
114 USHORT DesignatorMin
;
115 USHORT DesignatorMax
;
122 USHORT DesignatorIndex
;
134 HIDP_REPORT_TYPE type
;
146 struct collection
*collection
;
149 static const char* const collection_string
[] = {
164 struct collection
*parent
;
165 struct list features
;
166 struct list collections
;
174 static const char* debugstr_usages(struct caps
*caps
)
177 return wine_dbg_sprintf("[0x%x]", caps
->u
.NotRange
.Usage
);
179 return wine_dbg_sprintf("[0x%x - 0x%x]", caps
->u
.Range
.UsageMin
, caps
->u
.Range
.UsageMax
);
182 static const char* debugstr_stringindex(struct caps
*caps
)
184 if (!caps
->IsStringRange
)
185 return wine_dbg_sprintf("%i", caps
->u
.NotRange
.StringIndex
);
187 return wine_dbg_sprintf("[%i - %i]", caps
->u
.Range
.StringMin
, caps
->u
.Range
.StringMax
);
190 static const char* debugstr_designatorindex(struct caps
*caps
)
192 if (!caps
->IsDesignatorRange
)
193 return wine_dbg_sprintf("%i", caps
->u
.NotRange
.DesignatorIndex
);
195 return wine_dbg_sprintf("[%i - %i]", caps
->u
.Range
.DesignatorMin
, caps
->u
.Range
.DesignatorMax
);
198 static void debugstr_caps(const char* type
, struct caps
*caps
)
202 TRACE("(%s Caps: UsagePage 0x%x; LogicalMin %i; LogicalMax %i; PhysicalMin %i; "
203 "PhysicalMax %i; UnitsExp %i; Units %i; BitSize %i; ReportID %i; ReportCount %i; "
204 "Usage %s; StringIndex %s; DesignatorIndex %s; Delim %i;)\n",
216 debugstr_usages(caps
),
217 debugstr_stringindex(caps
),
218 debugstr_designatorindex(caps
),
222 static void debug_feature(struct feature
*feature
)
226 TRACE("[Feature type %s [%i]; %s; %s; %s; %s; %s; %s; %s; %s; %s]\n",
227 feature_string
[feature
->type
],
229 (feature
->isData
)?"Data":"Const",
230 (feature
->isArray
)?"Array":"Var",
231 (feature
->IsAbsolute
)?"Abs":"Rel",
232 (feature
->Wrap
)?"Wrap":"NoWrap",
233 (feature
->Linear
)?"Linear":"NonLinear",
234 (feature
->prefState
)?"PrefStat":"NoPrefState",
235 (feature
->HasNull
)?"HasNull":"NoNull",
236 (feature
->Volatile
)?"Volatile":"NonVolatile",
237 (feature
->BitField
)?"BitField":"Buffered");
239 debugstr_caps("Feature", &feature
->caps
);
242 static void debug_collection(struct collection
*collection
)
244 struct feature
*fentry
;
245 struct collection
*centry
;
248 TRACE("START Collection %i <<< %s, parent: %p, %i features, %i collections\n",
249 collection
->index
, collection_string
[collection
->type
], collection
->parent
,
250 list_count(&collection
->features
), list_count(&collection
->collections
));
251 debugstr_caps("Collection", &collection
->caps
);
252 LIST_FOR_EACH_ENTRY(fentry
, &collection
->features
, struct feature
, entry
)
253 debug_feature(fentry
);
254 LIST_FOR_EACH_ENTRY(centry
, &collection
->collections
, struct collection
, entry
)
255 debug_collection(centry
);
256 TRACE(">>> END Collection %i\n", collection
->index
);
260 static void debug_print_button_cap(const CHAR
* type
, WINE_HID_ELEMENT
*wine_element
)
262 if (!wine_element
->caps
.button
.IsRange
)
263 TRACE("%s Button: 0x%x/0x%04x: ReportId %i, startBit %i/1\n" , type
,
264 wine_element
->caps
.button
.UsagePage
,
265 wine_element
->caps
.button
.u
.NotRange
.Usage
,
266 wine_element
->caps
.value
.ReportID
,
267 wine_element
->valueStartBit
);
269 TRACE("%s Button: 0x%x/[0x%04x-0x%04x]: ReportId %i, startBit %i/%i\n" ,type
,
270 wine_element
->caps
.button
.UsagePage
,
271 wine_element
->caps
.button
.u
.Range
.UsageMin
,
272 wine_element
->caps
.button
.u
.Range
.UsageMax
,
273 wine_element
->caps
.value
.ReportID
,
274 wine_element
->valueStartBit
,
275 wine_element
->bitCount
);
278 static void debug_print_value_cap(const CHAR
* type
, WINE_HID_ELEMENT
*wine_element
)
280 TRACE("%s Value: 0x%x/0x%x: ReportId %i, IsAbsolute %i, HasNull %i, "
281 "Bit Size %i, ReportCount %i, UnitsExp %i, Units %i, "
282 "LogicalMin %i, Logical Max %i, PhysicalMin %i, "
283 "PhysicalMax %i -- StartBit %i/%i\n", type
,
284 wine_element
->caps
.value
.UsagePage
,
285 wine_element
->caps
.value
.u
.NotRange
.Usage
,
286 wine_element
->caps
.value
.ReportID
,
287 wine_element
->caps
.value
.IsAbsolute
,
288 wine_element
->caps
.value
.HasNull
,
289 wine_element
->caps
.value
.BitSize
,
290 wine_element
->caps
.value
.ReportCount
,
291 wine_element
->caps
.value
.UnitsExp
,
292 wine_element
->caps
.value
.Units
,
293 wine_element
->caps
.value
.LogicalMin
,
294 wine_element
->caps
.value
.LogicalMax
,
295 wine_element
->caps
.value
.PhysicalMin
,
296 wine_element
->caps
.value
.PhysicalMax
,
297 wine_element
->valueStartBit
,
298 wine_element
->bitCount
);
301 static void debug_print_element(const CHAR
* type
, WINE_HID_ELEMENT
*wine_element
)
303 if (wine_element
->ElementType
== ButtonElement
)
304 debug_print_button_cap(type
, wine_element
);
305 else if (wine_element
->ElementType
== ValueElement
)
306 debug_print_value_cap(type
, wine_element
);
308 TRACE("%s: UNKNOWN\n", type
);
311 static void debug_print_report(const char* type
, WINE_HIDP_PREPARSED_DATA
*data
,
312 WINE_HID_REPORT
*report
)
314 WINE_HID_ELEMENT
*elem
= HID_ELEMS(data
);
316 TRACE("START Report %i <<< %s report : bitSize: %i elementCount: %i\n",
320 report
->elementCount
);
321 for (i
= 0; i
< report
->elementCount
; i
++)
323 debug_print_element(type
, &elem
[report
->elementIdx
+ i
]);
325 TRACE(">>> END Report %i\n",report
->reportID
);
328 static void debug_print_preparsed(WINE_HIDP_PREPARSED_DATA
*data
)
333 TRACE("START PREPARSED Data <<< dwSize: %i Usage: %i, UsagePage: %i, "
334 "InputReportByteLength: %i, tOutputReportByteLength: %i, "
335 "FeatureReportByteLength: %i, NumberLinkCollectionNodes: %i, "
336 "NumberInputButtonCaps: %i, NumberInputValueCaps: %i, "
337 "NumberInputDataIndices: %i, NumberOutputButtonCaps: %i, "
338 "NumberOutputValueCaps: %i, NumberOutputDataIndices: %i, "
339 "NumberFeatureButtonCaps: %i, NumberFeatureValueCaps: %i, "
340 "NumberFeatureDataIndices: %i, reportCount[HidP_Input]: %i, "
341 "reportCount[HidP_Output]: %i, reportCount[HidP_Feature]: %i, "
342 "elementOffset: %i\n",
345 data
->caps
.UsagePage
,
346 data
->caps
.InputReportByteLength
,
347 data
->caps
.OutputReportByteLength
,
348 data
->caps
.FeatureReportByteLength
,
349 data
->caps
.NumberLinkCollectionNodes
,
350 data
->caps
.NumberInputButtonCaps
,
351 data
->caps
.NumberInputValueCaps
,
352 data
->caps
.NumberInputDataIndices
,
353 data
->caps
.NumberOutputButtonCaps
,
354 data
->caps
.NumberOutputValueCaps
,
355 data
->caps
.NumberOutputDataIndices
,
356 data
->caps
.NumberFeatureButtonCaps
,
357 data
->caps
.NumberFeatureValueCaps
,
358 data
->caps
.NumberFeatureDataIndices
,
359 data
->reportCount
[HidP_Input
],
360 data
->reportCount
[HidP_Output
],
361 data
->reportCount
[HidP_Feature
],
362 data
->elementOffset
);
364 end
= data
->reportCount
[HidP_Input
];
365 for (i
= 0; i
< end
; i
++)
367 debug_print_report("INPUT", data
, &data
->reports
[i
]);
369 end
+= data
->reportCount
[HidP_Output
];
372 debug_print_report("OUTPUT", data
, &data
->reports
[i
]);
374 end
+= data
->reportCount
[HidP_Feature
];
375 for (i
= 0; i
< end
; i
++)
377 debug_print_report("FEATURE", data
, &data
->reports
[i
]);
379 TRACE(">>> END Preparsed Data\n");
383 static int getValue(int bsize
, int source
, BOOL allow_negative
)
387 int outofrange
= 0x100;
394 for (i
= 1; i
< bsize
; i
++)
396 mask
= (mask
<<8) + 0xff;
397 negative
= (negative
<<8);
398 outofrange
= (outofrange
<<8);
400 value
= (source
&mask
);
401 if (allow_negative
&& value
&negative
)
402 value
= -1 * (outofrange
- value
);
406 static void parse_io_feature(unsigned int bSize
, int itemVal
, int bTag
,
407 unsigned int *feature_index
,
408 struct feature
*feature
)
416 feature
->isData
= ((itemVal
& INPUT_DATA_CONST
) == 0);
417 feature
->isArray
= ((itemVal
& INPUT_ARRAY_VAR
) == 0);
418 feature
->IsAbsolute
= ((itemVal
& INPUT_ABS_REL
) == 0);
419 feature
->Wrap
= ((itemVal
& INPUT_WRAP
) != 0);
420 feature
->Linear
= ((itemVal
& INPUT_LINEAR
) == 0);
421 feature
->prefState
= ((itemVal
& INPUT_PREFSTATE
) == 0);
422 feature
->HasNull
= ((itemVal
& INPUT_NULL
) != 0);
424 if (bTag
!= TAG_MAIN_INPUT
)
426 feature
->Volatile
= ((itemVal
& INPUT_VOLATILE
) != 0);
430 feature
->BitField
= ((itemVal
& INPUT_BITFIELD
) == 0);
432 feature
->index
= *feature_index
;
433 *feature_index
= *feature_index
+ 1;
437 static void parse_collection(unsigned int bSize
, int itemVal
,
438 struct collection
*collection
)
442 collection
->type
= itemVal
;
444 if (itemVal
>= 0x07 && itemVal
<= 0x7F) {
445 ERR(" (Reserved 0x%x )\n", itemVal
);
447 else if (itemVal
>= 0x80 && itemVal
<= 0xFF) {
448 ERR(" (Vendor Defined 0x%x )\n", itemVal
);
453 static void new_caps(struct caps
*caps
)
456 caps
->IsStringRange
= 0;
457 caps
->IsDesignatorRange
= 0;
458 caps
->u
.NotRange
.Usage
= 0;
461 static int parse_descriptor(BYTE
*descriptor
, unsigned int index
, unsigned int length
,
462 unsigned int *feature_index
, unsigned int *collection_index
,
463 struct collection
*collection
, struct caps
*caps
,
470 for (i
= index
; i
< length
;)
472 BYTE b0
= descriptor
[i
++];
473 int bSize
= b0
& 0x03;
474 int bType
= (b0
>> 2) & 0x03;
475 int bTag
= (b0
>> 4) & 0x0F;
477 bSize
= (bSize
== 3) ? 4 : bSize
;
478 if (bType
== TAG_TYPE_RESERVED
&& bTag
== 0x0F && bSize
== 2 &&
481 /* Long data items: Should be unused */
482 ERR("Long Data Item, should be unused\n");
490 for (j
= 0; j
< bSize
; j
++)
494 itemVal
+= descriptor
[i
+ j
] << (8 * j
);
498 TRACE(" 0x%x[%i], type %i , tag %i, size %i, val %i\n",b0
,i
-1,bType
, bTag
, bSize
, itemVal
);
500 if (bType
== TAG_TYPE_MAIN
)
502 struct feature
*feature
;
506 case TAG_MAIN_OUTPUT
:
507 case TAG_MAIN_FEATURE
:
508 for (j
= 0; j
< caps
->ReportCount
; j
++)
510 feature
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*feature
));
511 list_add_tail(&collection
->features
, &feature
->entry
);
512 if (bTag
== TAG_MAIN_INPUT
)
513 feature
->type
= HidP_Input
;
514 else if (bTag
== TAG_MAIN_OUTPUT
)
515 feature
->type
= HidP_Output
;
517 feature
->type
= HidP_Feature
;
518 parse_io_feature(bSize
, itemVal
, bTag
, feature_index
, feature
);
520 caps
->u
.NotRange
.Usage
= usages
[j
];
521 feature
->caps
= *caps
;
522 feature
->caps
.ReportCount
= 1;
523 feature
->collection
= collection
;
524 if (j
+1 >= usages_top
)
526 feature
->caps
.ReportCount
+= caps
->ReportCount
- (j
+ 1);
533 case TAG_MAIN_COLLECTION
:
535 struct collection
*subcollection
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct collection
));
536 list_add_tail(&collection
->collections
, &subcollection
->entry
);
537 subcollection
->parent
= collection
;
538 /* Only set our collection once...
539 We do not properly handle composite devices yet. */
542 caps
->u
.NotRange
.Usage
= usages
[usages_top
-1];
545 if (*collection_index
== 0)
546 collection
->caps
= *caps
;
547 subcollection
->caps
= *caps
;
548 subcollection
->index
= *collection_index
;
549 *collection_index
= *collection_index
+ 1;
550 list_init(&subcollection
->features
);
551 list_init(&subcollection
->collections
);
554 parse_collection(bSize
, itemVal
, subcollection
);
556 i
= parse_descriptor(descriptor
, i
+1, length
, feature_index
, collection_index
, subcollection
, caps
, stack
);
559 case TAG_MAIN_END_COLLECTION
:
562 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag
, bType
);
565 else if (bType
== TAG_TYPE_GLOBAL
)
569 case TAG_GLOBAL_USAGE_PAGE
:
570 caps
->UsagePage
= getValue(bSize
, itemVal
, FALSE
);
572 case TAG_GLOBAL_LOGICAL_MINIMUM
:
573 caps
->LogicalMin
= getValue(bSize
, itemVal
, TRUE
);
575 case TAG_GLOBAL_LOGICAL_MAXIMUM
:
576 caps
->LogicalMax
= getValue(bSize
, itemVal
, TRUE
);
578 case TAG_GLOBAL_PHYSICAL_MINIMUM
:
579 caps
->PhysicalMin
= getValue(bSize
, itemVal
, TRUE
);
581 case TAG_GLOBAL_PHYSICAL_MAXIMUM
:
582 caps
->PhysicalMax
= getValue(bSize
, itemVal
, TRUE
);
584 case TAG_GLOBAL_UNIT_EXPONENT
:
585 caps
->UnitsExp
= getValue(bSize
, itemVal
, TRUE
);
587 case TAG_GLOBAL_UNIT
:
588 caps
->Units
= getValue(bSize
, itemVal
, TRUE
);
590 case TAG_GLOBAL_REPORT_SIZE
:
591 caps
->BitSize
= getValue(bSize
, itemVal
, FALSE
);
593 case TAG_GLOBAL_REPORT_ID
:
594 caps
->ReportID
= getValue(bSize
, itemVal
, FALSE
);
596 case TAG_GLOBAL_REPORT_COUNT
:
597 caps
->ReportCount
= getValue(bSize
, itemVal
, FALSE
);
599 case TAG_GLOBAL_PUSH
:
601 struct caps_stack
*saved
= HeapAlloc(GetProcessHeap(), 0, sizeof(*saved
));
604 list_add_tail(stack
, &saved
->entry
);
610 struct caps_stack
*saved
;
612 tail
= list_tail(stack
);
615 saved
= LIST_ENTRY(tail
, struct caps_stack
, entry
);
618 HeapFree(GetProcessHeap(), 0, saved
);
621 ERR("Pop but no stack!\n");
625 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag
, bType
);
628 else if (bType
== TAG_TYPE_LOCAL
)
632 case TAG_LOCAL_USAGE
:
633 if (usages_top
== sizeof(usages
))
634 ERR("More than 256 individual usages defined\n");
637 usages
[usages_top
++] = getValue(bSize
, itemVal
, FALSE
);
638 caps
->IsRange
= FALSE
;
641 case TAG_LOCAL_USAGE_MINIMUM
:
642 caps
->u
.Range
.UsageMin
= getValue(bSize
, itemVal
, FALSE
);
643 caps
->IsRange
= TRUE
;
645 case TAG_LOCAL_USAGE_MAXIMUM
:
646 caps
->u
.Range
.UsageMax
= getValue(bSize
, itemVal
, FALSE
);
647 caps
->IsRange
= TRUE
;
649 case TAG_LOCAL_DESIGNATOR_INDEX
:
650 caps
->u
.NotRange
.DesignatorIndex
= getValue(bSize
, itemVal
, FALSE
);
651 caps
->IsDesignatorRange
= FALSE
;
653 case TAG_LOCAL_DESIGNATOR_MINIMUM
:
654 caps
->u
.Range
.DesignatorMin
= getValue(bSize
, itemVal
, FALSE
);
655 caps
->IsDesignatorRange
= TRUE
;
657 case TAG_LOCAL_DESIGNATOR_MAXIMUM
:
658 caps
->u
.Range
.DesignatorMax
= getValue(bSize
, itemVal
, FALSE
);
659 caps
->IsDesignatorRange
= TRUE
;
661 case TAG_LOCAL_STRING_INDEX
:
662 caps
->u
.NotRange
.StringIndex
= getValue(bSize
, itemVal
, FALSE
);
663 caps
->IsStringRange
= FALSE
;
665 case TAG_LOCAL_STRING_MINIMUM
:
666 caps
->u
.Range
.StringMin
= getValue(bSize
, itemVal
, FALSE
);
667 caps
->IsStringRange
= TRUE
;
669 case TAG_LOCAL_STRING_MAXIMUM
:
670 caps
->u
.Range
.StringMax
= getValue(bSize
, itemVal
, FALSE
);
671 caps
->IsStringRange
= TRUE
;
673 case TAG_LOCAL_DELIMITER
:
674 caps
->Delim
= getValue(bSize
, itemVal
, FALSE
);
677 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag
, bType
);
681 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag
, bType
);
689 static void build_elements(WINE_HID_REPORT
*wine_report
, WINE_HID_ELEMENT
*elems
,
690 struct feature
* feature
, USHORT
*data_index
)
692 WINE_HID_ELEMENT
*wine_element
= elems
+ wine_report
->elementIdx
+ wine_report
->elementCount
;
694 if (!feature
->isData
)
696 wine_report
->bitSize
+= feature
->caps
.BitSize
* feature
->caps
.ReportCount
;
700 wine_element
->valueStartBit
= wine_report
->bitSize
;
701 if (feature
->caps
.BitSize
== 1)
703 wine_element
->ElementType
= ButtonElement
;
704 wine_element
->caps
.button
.UsagePage
= feature
->caps
.UsagePage
;
705 wine_element
->caps
.button
.ReportID
= feature
->caps
.ReportID
;
706 wine_element
->caps
.button
.BitField
= feature
->BitField
;
707 wine_element
->caps
.button
.LinkCollection
= feature
->collection
->index
;
708 wine_element
->caps
.button
.LinkUsage
= feature
->collection
->caps
.u
.NotRange
.Usage
;
709 wine_element
->caps
.button
.LinkUsagePage
= feature
->collection
->caps
.UsagePage
;
710 wine_element
->caps
.button
.IsRange
= feature
->caps
.IsRange
;
711 wine_element
->caps
.button
.IsStringRange
= feature
->caps
.IsStringRange
;
712 wine_element
->caps
.button
.IsDesignatorRange
= feature
->caps
.IsDesignatorRange
;
713 wine_element
->caps
.button
.IsAbsolute
= feature
->IsAbsolute
;
714 if (wine_element
->caps
.button
.IsRange
)
716 wine_element
->bitCount
= (feature
->caps
.u
.Range
.UsageMax
- feature
->caps
.u
.Range
.UsageMin
) + 1;
717 wine_report
->bitSize
+= wine_element
->bitCount
;
718 wine_element
->caps
.button
.u
.Range
.UsageMin
= feature
->caps
.u
.Range
.UsageMin
;
719 wine_element
->caps
.button
.u
.Range
.UsageMax
= feature
->caps
.u
.Range
.UsageMax
;
720 wine_element
->caps
.button
.u
.Range
.StringMin
= feature
->caps
.u
.Range
.StringMin
;
721 wine_element
->caps
.button
.u
.Range
.StringMax
= feature
->caps
.u
.Range
.StringMax
;
722 wine_element
->caps
.button
.u
.Range
.DesignatorMin
= feature
->caps
.u
.Range
.DesignatorMin
;
723 wine_element
->caps
.button
.u
.Range
.DesignatorMax
= feature
->caps
.u
.Range
.DesignatorMax
;
724 wine_element
->caps
.button
.u
.Range
.DataIndexMin
= *data_index
;
725 wine_element
->caps
.button
.u
.Range
.DataIndexMax
= *data_index
+ wine_element
->bitCount
- 1;
726 *data_index
= *data_index
+ wine_element
->bitCount
;
730 wine_report
->bitSize
++;
731 wine_element
->bitCount
= 1;
732 wine_element
->caps
.button
.u
.NotRange
.Usage
= feature
->caps
.u
.NotRange
.Usage
;
733 wine_element
->caps
.button
.u
.NotRange
.Reserved1
= feature
->caps
.u
.NotRange
.Usage
;
734 wine_element
->caps
.button
.u
.NotRange
.StringIndex
= feature
->caps
.u
.NotRange
.StringIndex
;
735 wine_element
->caps
.button
.u
.NotRange
.Reserved2
= feature
->caps
.u
.NotRange
.StringIndex
;
736 wine_element
->caps
.button
.u
.NotRange
.DesignatorIndex
= feature
->caps
.u
.NotRange
.DesignatorIndex
;
737 wine_element
->caps
.button
.u
.NotRange
.Reserved3
= feature
->caps
.u
.NotRange
.DesignatorIndex
;
738 wine_element
->caps
.button
.u
.NotRange
.DataIndex
= *data_index
;
739 wine_element
->caps
.button
.u
.NotRange
.Reserved4
= *data_index
;
740 *data_index
= *data_index
+ 1;
745 wine_element
->ElementType
= ValueElement
;
746 wine_element
->caps
.value
.UsagePage
= feature
->caps
.UsagePage
;
747 wine_element
->caps
.value
.ReportID
= feature
->caps
.ReportID
;
748 wine_element
->caps
.value
.BitField
= feature
->BitField
;
749 wine_element
->caps
.value
.LinkCollection
= feature
->collection
->index
;
750 wine_element
->caps
.value
.LinkUsage
= feature
->collection
->caps
.u
.NotRange
.Usage
;
751 wine_element
->caps
.value
.LinkUsagePage
= feature
->collection
->caps
.UsagePage
;
752 wine_element
->caps
.value
.IsRange
= feature
->caps
.IsRange
;
753 wine_element
->caps
.value
.IsStringRange
= feature
->caps
.IsStringRange
;
754 wine_element
->caps
.value
.IsDesignatorRange
= feature
->caps
.IsDesignatorRange
;
755 wine_element
->caps
.value
.IsAbsolute
= feature
->IsAbsolute
;
756 wine_element
->caps
.value
.HasNull
= feature
->HasNull
;
757 wine_element
->caps
.value
.BitSize
= feature
->caps
.BitSize
;
758 wine_element
->caps
.value
.ReportCount
= feature
->caps
.ReportCount
;
759 wine_element
->bitCount
= (feature
->caps
.BitSize
* wine_element
->caps
.value
.ReportCount
);
760 wine_report
->bitSize
+= wine_element
->bitCount
;
761 wine_element
->caps
.value
.UnitsExp
= feature
->caps
.UnitsExp
;
762 wine_element
->caps
.value
.Units
= feature
->caps
.Units
;
763 wine_element
->caps
.value
.LogicalMin
= feature
->caps
.LogicalMin
;
764 wine_element
->caps
.value
.LogicalMax
= feature
->caps
.LogicalMax
;
765 wine_element
->caps
.value
.PhysicalMin
= feature
->caps
.PhysicalMin
;
766 wine_element
->caps
.value
.PhysicalMax
= feature
->caps
.PhysicalMax
;
767 if (wine_element
->caps
.value
.IsRange
)
769 wine_element
->caps
.value
.u
.Range
.UsageMin
= feature
->caps
.u
.Range
.UsageMin
;
770 wine_element
->caps
.value
.u
.Range
.UsageMax
= feature
->caps
.u
.Range
.UsageMax
;
771 wine_element
->caps
.value
.u
.Range
.StringMin
= feature
->caps
.u
.Range
.StringMin
;
772 wine_element
->caps
.value
.u
.Range
.StringMax
= feature
->caps
.u
.Range
.StringMax
;
773 wine_element
->caps
.value
.u
.Range
.DesignatorMin
= feature
->caps
.u
.Range
.DesignatorMin
;
774 wine_element
->caps
.value
.u
.Range
.DesignatorMax
= feature
->caps
.u
.Range
.DesignatorMax
;
775 wine_element
->caps
.value
.u
.Range
.DataIndexMin
= *data_index
;
776 wine_element
->caps
.value
.u
.Range
.DataIndexMax
= *data_index
+
777 (wine_element
->caps
.value
.u
.Range
.UsageMax
-
778 wine_element
->caps
.value
.u
.Range
.UsageMin
);
779 *data_index
= *data_index
+
780 (wine_element
->caps
.value
.u
.Range
.UsageMax
-
781 wine_element
->caps
.value
.u
.Range
.UsageMin
) + 1;
785 wine_element
->caps
.value
.u
.NotRange
.Usage
= feature
->caps
.u
.NotRange
.Usage
;
786 wine_element
->caps
.value
.u
.NotRange
.Reserved1
= feature
->caps
.u
.NotRange
.Usage
;
787 wine_element
->caps
.value
.u
.NotRange
.StringIndex
= feature
->caps
.u
.NotRange
.StringIndex
;
788 wine_element
->caps
.value
.u
.NotRange
.Reserved2
= feature
->caps
.u
.NotRange
.StringIndex
;
789 wine_element
->caps
.value
.u
.NotRange
.DesignatorIndex
= feature
->caps
.u
.NotRange
.DesignatorIndex
;
790 wine_element
->caps
.value
.u
.NotRange
.Reserved3
= feature
->caps
.u
.NotRange
.DesignatorIndex
;
791 wine_element
->caps
.value
.u
.NotRange
.DataIndex
= *data_index
;
792 wine_element
->caps
.value
.u
.NotRange
.Reserved4
= *data_index
;
793 *data_index
= *data_index
+ 1;
796 wine_report
->elementCount
++;
799 static void count_elements(struct feature
* feature
, USHORT
*buttons
, USHORT
*values
)
801 if (!feature
->isData
)
804 if (feature
->caps
.BitSize
== 1)
814 int report_elem_count
[3][256];
817 BOOL report_created
[3][256];
820 static void create_preparse_ctx(const struct collection
*base
, struct preparse_ctx
*ctx
)
823 struct collection
*c
;
825 LIST_FOR_EACH_ENTRY(f
, &base
->features
, struct feature
, entry
)
828 ctx
->report_elem_count
[f
->type
][f
->caps
.ReportID
]++;
829 if (ctx
->report_elem_count
[f
->type
][f
->caps
.ReportID
] != 1)
831 ctx
->report_count
[f
->type
]++;
834 LIST_FOR_EACH_ENTRY(c
, &base
->collections
, struct collection
, entry
)
835 create_preparse_ctx(c
, ctx
);
838 static void preparse_collection(const struct collection
*root
, const struct collection
*base
,
839 WINE_HIDP_PREPARSED_DATA
*data
, struct preparse_ctx
*ctx
)
841 WINE_HID_ELEMENT
*elem
= HID_ELEMS(data
);
842 WINE_HID_LINK_COLLECTION_NODE
*nodes
= HID_NODES(data
);
844 struct collection
*c
;
847 LIST_FOR_EACH_ENTRY(f
, &base
->features
, struct feature
, entry
)
849 WINE_HID_REPORT
*report
;
851 if (!ctx
->report_created
[f
->type
][f
->caps
.ReportID
])
853 ctx
->report_created
[f
->type
][f
->caps
.ReportID
] = TRUE
;
854 data
->reportIdx
[f
->type
][f
->caps
.ReportID
] = data
->reportCount
[f
->type
]++;
855 if (f
->type
> 0) data
->reportIdx
[f
->type
][f
->caps
.ReportID
] += ctx
->report_count
[0];
856 if (f
->type
> 1) data
->reportIdx
[f
->type
][f
->caps
.ReportID
] += ctx
->report_count
[1];
858 report
= &data
->reports
[data
->reportIdx
[f
->type
][f
->caps
.ReportID
]];
859 report
->reportID
= f
->caps
.ReportID
;
860 /* Room for the reportID */
862 report
->elementIdx
= ctx
->elem_alloc
;
863 ctx
->elem_alloc
+= ctx
->report_elem_count
[f
->type
][f
->caps
.ReportID
];
866 report
= &data
->reports
[data
->reportIdx
[f
->type
][f
->caps
.ReportID
]];
870 build_elements(report
, elem
, f
, &data
->caps
.NumberInputDataIndices
);
871 count_elements(f
, &data
->caps
.NumberInputButtonCaps
, &data
->caps
.NumberInputValueCaps
);
872 data
->caps
.InputReportByteLength
=
873 max(data
->caps
.InputReportByteLength
, (report
->bitSize
+ 7) / 8);
876 build_elements(report
, elem
, f
, &data
->caps
.NumberOutputDataIndices
);
877 count_elements(f
, &data
->caps
.NumberOutputButtonCaps
, &data
->caps
.NumberOutputValueCaps
);
878 data
->caps
.OutputReportByteLength
=
879 max(data
->caps
.OutputReportByteLength
, (report
->bitSize
+ 7) / 8);
882 build_elements(report
, elem
, f
, &data
->caps
.NumberFeatureDataIndices
);
883 count_elements(f
, &data
->caps
.NumberFeatureButtonCaps
, &data
->caps
.NumberFeatureValueCaps
);
884 data
->caps
.FeatureReportByteLength
=
885 max(data
->caps
.FeatureReportByteLength
, (report
->bitSize
+ 7) / 8);
892 nodes
[base
->index
].LinkUsagePage
= base
->caps
.UsagePage
;
893 nodes
[base
->index
].LinkUsage
= base
->caps
.u
.NotRange
.Usage
;
894 nodes
[base
->index
].Parent
= base
->parent
== root
? 0 : base
->parent
->index
;
895 nodes
[base
->index
].CollectionType
= base
->type
;
896 nodes
[base
->index
].IsAlias
= 0;
898 if ((entry
= list_head(&base
->collections
)))
899 nodes
[base
->index
].FirstChild
= LIST_ENTRY(entry
, struct collection
, entry
)->index
;
902 LIST_FOR_EACH_ENTRY(c
, &base
->collections
, struct collection
, entry
)
904 preparse_collection(root
, c
, data
, ctx
);
906 if ((entry
= list_next(&base
->collections
, &c
->entry
)))
907 nodes
[c
->index
].NextSibling
= LIST_ENTRY(entry
, struct collection
, entry
)->index
;
908 if (root
!= base
) nodes
[base
->index
].NumberOfChildren
++;
912 static WINE_HIDP_PREPARSED_DATA
* build_PreparseData(struct collection
*base_collection
, unsigned int node_count
)
914 WINE_HIDP_PREPARSED_DATA
*data
;
915 unsigned int report_count
;
918 struct preparse_ctx ctx
;
919 unsigned int element_off
;
920 unsigned int nodes_offset
;
922 memset(&ctx
, 0, sizeof(ctx
));
923 create_preparse_ctx(base_collection
, &ctx
);
925 report_count
= ctx
.report_count
[HidP_Input
] + ctx
.report_count
[HidP_Output
]
926 + ctx
.report_count
[HidP_Feature
];
927 element_off
= FIELD_OFFSET(WINE_HIDP_PREPARSED_DATA
, reports
[report_count
]);
928 size
= element_off
+ (ctx
.elem_count
* sizeof(WINE_HID_ELEMENT
));
931 size
+= node_count
* sizeof(WINE_HID_LINK_COLLECTION_NODE
);
933 data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
934 data
->magic
= HID_MAGIC
;
936 data
->caps
.Usage
= base_collection
->caps
.u
.NotRange
.Usage
;
937 data
->caps
.UsagePage
= base_collection
->caps
.UsagePage
;
938 data
->caps
.NumberLinkCollectionNodes
= node_count
;
939 data
->elementOffset
= element_off
;
940 data
->nodesOffset
= nodes_offset
;
942 preparse_collection(base_collection
, base_collection
, data
, &ctx
);
946 static void free_collection(struct collection
*collection
)
948 struct feature
*fentry
, *fnext
;
949 struct collection
*centry
, *cnext
;
950 LIST_FOR_EACH_ENTRY_SAFE(centry
, cnext
, &collection
->collections
, struct collection
, entry
)
952 list_remove(¢ry
->entry
);
953 free_collection(centry
);
955 LIST_FOR_EACH_ENTRY_SAFE(fentry
, fnext
, &collection
->features
, struct feature
, entry
)
957 list_remove(&fentry
->entry
);
958 HeapFree(GetProcessHeap(), 0, fentry
);
960 HeapFree(GetProcessHeap(), 0, collection
);
963 WINE_HIDP_PREPARSED_DATA
* ParseDescriptor(BYTE
*descriptor
, unsigned int length
)
965 WINE_HIDP_PREPARSED_DATA
*data
= NULL
;
966 struct collection
*base
;
969 struct list caps_stack
;
971 unsigned int feature_count
= 0;
976 TRACE("Descriptor[%i]: ", length
);
977 for (cidx
= 0; cidx
< length
; cidx
++)
979 TRACE("%x ",descriptor
[cidx
]);
980 if ((cidx
+1) % 80 == 0)
986 list_init(&caps_stack
);
988 base
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*base
));
990 list_init(&base
->features
);
991 list_init(&base
->collections
);
992 memset(&caps
, 0, sizeof(caps
));
995 parse_descriptor(descriptor
, 0, length
, &feature_count
, &cidx
, base
, &caps
, &caps_stack
);
997 debug_collection(base
);
999 if (!list_empty(&caps_stack
))
1001 struct caps_stack
*entry
, *cursor
;
1002 ERR("%i unpopped device caps on the stack\n", list_count(&caps_stack
));
1003 LIST_FOR_EACH_ENTRY_SAFE(entry
, cursor
, &caps_stack
, struct caps_stack
, entry
)
1005 list_remove(&entry
->entry
);
1006 HeapFree(GetProcessHeap(), 0, entry
);
1010 data
= build_PreparseData(base
, cidx
);
1011 debug_print_preparsed(data
);
1012 free_collection(base
);