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
26 #define NONAMELESSUNION
29 #include "wine/debug.h"
30 #include "wine/list.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(hid
);
36 /* Flags that are defined in the document
37 "Device Class Definition for Human Interface Devices" */
39 INPUT_DATA_CONST
= 0x01, /* Data (0) | Constant (1) */
40 INPUT_ARRAY_VAR
= 0x02, /* Array (0) | Variable (1) */
41 INPUT_ABS_REL
= 0x04, /* Absolute (0) | Relative (1) */
42 INPUT_WRAP
= 0x08, /* No Wrap (0) | Wrap (1) */
43 INPUT_LINEAR
= 0x10, /* Linear (0) | Non Linear (1) */
44 INPUT_PREFSTATE
= 0x20, /* Preferred State (0) | No Preferred (1) */
45 INPUT_NULL
= 0x40, /* No Null position (0) | Null state(1) */
46 INPUT_VOLATILE
= 0x80, /* Non Volatile (0) | Volatile (1) */
47 INPUT_BITFIELD
= 0x100 /* Bit Field (0) | Buffered Bytes (1) */
58 TAG_MAIN_INPUT
= 0x08,
59 TAG_MAIN_OUTPUT
= 0x09,
60 TAG_MAIN_FEATURE
= 0x0B,
61 TAG_MAIN_COLLECTION
= 0x0A,
62 TAG_MAIN_END_COLLECTION
= 0x0C
66 TAG_GLOBAL_USAGE_PAGE
= 0x0,
67 TAG_GLOBAL_LOGICAL_MINIMUM
,
68 TAG_GLOBAL_LOGICAL_MAXIMUM
,
69 TAG_GLOBAL_PHYSICAL_MINIMUM
,
70 TAG_GLOBAL_PHYSICAL_MAXIMUM
,
71 TAG_GLOBAL_UNIT_EXPONENT
,
73 TAG_GLOBAL_REPORT_SIZE
,
75 TAG_GLOBAL_REPORT_COUNT
,
81 TAG_LOCAL_USAGE
= 0x0,
82 TAG_LOCAL_USAGE_MINIMUM
,
83 TAG_LOCAL_USAGE_MAXIMUM
,
84 TAG_LOCAL_DESIGNATOR_INDEX
,
85 TAG_LOCAL_DESIGNATOR_MINIMUM
,
86 TAG_LOCAL_DESIGNATOR_MAXIMUM
,
87 TAG_LOCAL_STRING_INDEX
,
88 TAG_LOCAL_STRING_MINIMUM
,
89 TAG_LOCAL_STRING_MAXIMUM
,
94 static const char* const feature_string
[] =
95 { "Input", "Output", "Feature" };
110 BOOLEAN IsStringRange
;
111 BOOLEAN IsDesignatorRange
;
112 unsigned int usage_count
;
119 USHORT DesignatorMin
;
120 USHORT DesignatorMax
;
123 USAGE Usage
[USAGE_MAX
];
127 USHORT DesignatorIndex
;
137 struct list col_entry
;
140 HIDP_REPORT_TYPE type
;
152 struct collection
*collection
;
155 static const char* const collection_string
[] = {
170 struct collection
*parent
;
171 struct list features
;
172 struct list collections
;
180 static const char* debugstr_usages(struct caps
*caps
)
184 char out
[12 * USAGE_MAX
];
186 if (caps
->usage_count
== 0)
189 for (i
= 0; i
< caps
->usage_count
; i
++)
190 sprintf(out
+ strlen(out
), "0x%x ", caps
->u
.NotRange
.Usage
[i
]);
191 return wine_dbg_sprintf("[ %s] ", out
);
194 return wine_dbg_sprintf("[0x%x - 0x%x]", caps
->u
.Range
.UsageMin
, caps
->u
.Range
.UsageMax
);
197 static const char* debugstr_stringindex(struct caps
*caps
)
199 if (!caps
->IsStringRange
)
200 return wine_dbg_sprintf("%i", caps
->u
.NotRange
.StringIndex
);
202 return wine_dbg_sprintf("[%i - %i]", caps
->u
.Range
.StringMin
, caps
->u
.Range
.StringMax
);
205 static const char* debugstr_designatorindex(struct caps
*caps
)
207 if (!caps
->IsDesignatorRange
)
208 return wine_dbg_sprintf("%i", caps
->u
.NotRange
.DesignatorIndex
);
210 return wine_dbg_sprintf("[%i - %i]", caps
->u
.Range
.DesignatorMin
, caps
->u
.Range
.DesignatorMax
);
213 static void debugstr_caps(const char* type
, struct caps
*caps
)
217 TRACE("(%s Caps: UsagePage 0x%x; LogicalMin %i; LogicalMax %i; PhysicalMin %i; PhysicalMax %i; UnitsExp %i; Units %i; BitSize %i; ReportID %i; ReportCount %i; Usage %s; StringIndex %s; DesignatorIndex %s; Delim %i;)\n",
229 debugstr_usages(caps
),
230 debugstr_stringindex(caps
),
231 debugstr_designatorindex(caps
),
235 static void debug_feature(struct feature
*feature
)
239 TRACE("[Feature type %s [%i]; %s; %s; %s; %s; %s; %s; %s; %s; %s]\n",
240 feature_string
[feature
->type
],
242 (feature
->isData
)?"Data":"Const",
243 (feature
->isArray
)?"Array":"Var",
244 (feature
->IsAbsolute
)?"Abs":"Rel",
245 (feature
->Wrap
)?"Wrap":"NoWrap",
246 (feature
->Linear
)?"Linear":"NonLinear",
247 (feature
->prefState
)?"PrefStat":"NoPrefState",
248 (feature
->HasNull
)?"HasNull":"NoNull",
249 (feature
->Volatile
)?"Volatile":"NonVolatile",
250 (feature
->BitField
)?"BitField":"Buffered");
252 debugstr_caps("Feature", &feature
->caps
);
255 static void debug_collection(struct collection
*collection
)
257 struct feature
*fentry
;
258 struct collection
*centry
;
261 TRACE("START Collection %i <<< %s, parent: %p, %i features, %i collections\n", collection
->index
, collection_string
[collection
->type
], collection
->parent
, list_count(&collection
->features
), list_count(&collection
->collections
));
262 debugstr_caps("Collection", &collection
->caps
);
263 LIST_FOR_EACH_ENTRY(fentry
, &collection
->features
, struct feature
, col_entry
)
264 debug_feature(fentry
);
265 LIST_FOR_EACH_ENTRY(centry
, &collection
->collections
, struct collection
, entry
)
266 debug_collection(centry
);
267 TRACE(">>> END Collection %i\n", collection
->index
);
271 static void debug_print_button_cap(const CHAR
* type
, WINE_HID_ELEMENT
*wine_element
)
273 if (!wine_element
->caps
.button
.IsRange
)
274 TRACE("%s Button: 0x%x/0x%04x: ReportId %i, startBit %i/1\n" , type
,
275 wine_element
->caps
.button
.UsagePage
,
276 wine_element
->caps
.button
.u
.NotRange
.Usage
,
277 wine_element
->caps
.value
.ReportID
,
278 wine_element
->valueStartBit
);
280 TRACE("%s Button: 0x%x/[0x%04x-0x%04x]: ReportId %i, startBit %i/%i\n" ,type
,
281 wine_element
->caps
.button
.UsagePage
,
282 wine_element
->caps
.button
.u
.Range
.UsageMin
,
283 wine_element
->caps
.button
.u
.Range
.UsageMax
,
284 wine_element
->caps
.value
.ReportID
,
285 wine_element
->valueStartBit
,
286 wine_element
->bitCount
);
289 static void debug_print_value_cap(const CHAR
* type
, WINE_HID_ELEMENT
*wine_element
)
291 TRACE("%s Value: 0x%x/0x%x: ReportId %i, IsAbsolute %i, HasNull %i, "
292 "Bit Size %i, ReportCount %i, UnitsExp %i, Units %i, "
293 "LogicalMin %i, Logical Max %i, PhysicalMin %i, "
294 "PhysicalMax %i -- StartBit %i/%i\n", type
,
295 wine_element
->caps
.value
.UsagePage
,
296 wine_element
->caps
.value
.u
.NotRange
.Usage
,
297 wine_element
->caps
.value
.ReportID
,
298 wine_element
->caps
.value
.IsAbsolute
,
299 wine_element
->caps
.value
.HasNull
,
300 wine_element
->caps
.value
.BitSize
,
301 wine_element
->caps
.value
.ReportCount
,
302 wine_element
->caps
.value
.UnitsExp
,
303 wine_element
->caps
.value
.Units
,
304 wine_element
->caps
.value
.LogicalMin
,
305 wine_element
->caps
.value
.LogicalMax
,
306 wine_element
->caps
.value
.PhysicalMin
,
307 wine_element
->caps
.value
.PhysicalMax
,
308 wine_element
->valueStartBit
,
309 wine_element
->bitCount
);
312 static void debug_print_element(const CHAR
* type
, WINE_HID_ELEMENT
*wine_element
)
314 if (wine_element
->ElementType
== ButtonElement
)
315 debug_print_button_cap(type
, wine_element
);
316 else if (wine_element
->ElementType
== ValueElement
)
317 debug_print_value_cap(type
, wine_element
);
319 TRACE("%s: UNKNOWN\n", type
);
322 static void debug_print_report(const char* type
, WINE_HID_REPORT
*report
)
325 TRACE("START Report %i <<< %s report : dwSize: %i elementCount: %i\n",
329 report
->elementCount
);
330 for (i
= 0; i
< report
->elementCount
; i
++)
331 debug_print_element(type
, &report
->Elements
[i
]);
332 TRACE(">>> END Report %i\n",report
->reportID
);
335 static void debug_print_preparsed(WINE_HIDP_PREPARSED_DATA
*data
)
341 TRACE("START PREPARSED Data <<< dwSize: %i Usage: %i, UsagePage: %i, InputReportByteLength: %i, tOutputReportByteLength: %i, FeatureReportByteLength: %i, NumberLinkCollectionNodes: %i, NumberInputButtonCaps: %i, NumberInputValueCaps: %i,NumberInputDataIndices: %i, NumberOutputButtonCaps: %i, NumberOutputValueCaps: %i, NumberOutputDataIndices: %i, NumberFeatureButtonCaps: %i, NumberFeatureValueCaps: %i, NumberFeatureDataIndices: %i, dwInputReportCount: %i, dwOutputReportCount: %i, dwFeatureReportCount: %i, dwOutputReportOffset: %i, dwFeatureReportOffset: %i\n",
344 data
->caps
.UsagePage
,
345 data
->caps
.InputReportByteLength
,
346 data
->caps
.OutputReportByteLength
,
347 data
->caps
.FeatureReportByteLength
,
348 data
->caps
.NumberLinkCollectionNodes
,
349 data
->caps
.NumberInputButtonCaps
,
350 data
->caps
.NumberInputValueCaps
,
351 data
->caps
.NumberInputDataIndices
,
352 data
->caps
.NumberOutputButtonCaps
,
353 data
->caps
.NumberOutputValueCaps
,
354 data
->caps
.NumberOutputDataIndices
,
355 data
->caps
.NumberFeatureButtonCaps
,
356 data
->caps
.NumberFeatureValueCaps
,
357 data
->caps
.NumberFeatureDataIndices
,
358 data
->dwInputReportCount
,
359 data
->dwOutputReportCount
,
360 data
->dwFeatureReportCount
,
361 data
->dwOutputReportOffset
,
362 data
->dwFeatureReportOffset
);
364 r
= HID_INPUT_REPORTS(data
);
365 for (i
= 0; i
< data
->dwInputReportCount
; i
++)
367 debug_print_report("INPUT", r
);
368 r
= HID_NEXT_REPORT(data
, r
);
370 r
= HID_OUTPUT_REPORTS(data
);
371 for (i
= 0; i
< data
->dwOutputReportCount
; i
++)
373 debug_print_report("OUTPUT", r
);
374 r
= HID_NEXT_REPORT(data
, r
);
376 r
= HID_FEATURE_REPORTS(data
);
377 for (i
= 0; i
< data
->dwFeatureReportCount
; i
++)
379 debug_print_report("FEATURE", r
);
380 r
= HID_NEXT_REPORT(data
, r
);
382 TRACE(">>> END Preparsed Data\n");
386 static int getValue(int bsize
, int source
, BOOL allow_negative
)
390 int outofrange
= 0x100;
397 for (i
= 1; i
< bsize
; i
++)
399 mask
= (mask
<<8) + 0xff;
400 negative
= (negative
<<8);
401 outofrange
= (outofrange
<<8);
403 value
= (source
&mask
);
404 if (allow_negative
&& value
&negative
)
405 value
= -1 * (outofrange
- value
);
409 static void parse_io_feature(unsigned int bSize
, int itemVal
, int bTag
,
410 unsigned int *feature_index
,
411 struct feature
*feature
)
419 feature
->isData
= ((itemVal
& INPUT_DATA_CONST
) == 0);
420 feature
->isArray
= ((itemVal
& INPUT_ARRAY_VAR
) == 0);
421 feature
->IsAbsolute
= ((itemVal
& INPUT_ABS_REL
) == 0);
422 feature
->Wrap
= ((itemVal
& INPUT_WRAP
) != 0);
423 feature
->Linear
= ((itemVal
& INPUT_LINEAR
) == 0);
424 feature
->prefState
= ((itemVal
& INPUT_PREFSTATE
) == 0);
425 feature
->HasNull
= ((itemVal
& INPUT_NULL
) != 0);
427 if (bTag
!= TAG_MAIN_INPUT
)
429 feature
->Volatile
= ((itemVal
& INPUT_VOLATILE
) != 0);
433 feature
->BitField
= ((itemVal
& INPUT_BITFIELD
) == 0);
435 feature
->index
= *feature_index
;
436 *feature_index
= *feature_index
+ 1;
440 static void parse_collection(unsigned int bSize
, int itemVal
,
441 struct collection
*collection
)
447 collection
->type
= itemVal
;
449 if (itemVal
>= 0x07 && itemVal
<= 0x7F) {
450 ERR(" (Reserved 0x%x )\n", itemVal
);
452 else if (itemVal
>= 0x80 && itemVal
<= 0xFF) {
453 ERR(" (Vendor Defined 0x%x )\n", itemVal
);
458 static void new_caps(struct caps
*caps
)
461 caps
->IsStringRange
= 0;
462 caps
->IsDesignatorRange
= 0;
463 caps
->usage_count
= 0;
466 static int parse_descriptor(BYTE
*descriptor
, unsigned int index
, unsigned int length
,
467 unsigned int *feature_index
, unsigned int *collection_index
,
468 struct collection
*collection
, struct caps
*caps
,
469 struct list
*features
, struct list
*stack
)
472 for (i
= index
; i
< length
;)
474 BYTE b0
= descriptor
[i
++];
475 int bSize
= b0
& 0x03;
476 int bType
= (b0
>> 2) & 0x03;
477 int bTag
= (b0
>> 4) & 0x0F;
479 bSize
= (bSize
== 3) ? 4 : bSize
;
480 if (bType
== TAG_TYPE_RESERVED
&& bTag
== 0x0F && bSize
== 2 &&
483 /* Long data items: Should be unused */
484 ERR("Long Data Item, should be unused\n");
492 for (j
= 0; j
< bSize
; j
++)
496 itemVal
+= descriptor
[i
+ j
] << (8 * j
);
500 TRACE(" 0x%x[%i], type %i , tag %i, size %i, val %i\n",b0
,i
-1,bType
, bTag
, bSize
, itemVal
);
502 if (bType
== TAG_TYPE_MAIN
)
504 struct feature
*feature
;
508 feature
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*feature
));
509 list_add_tail(&collection
->features
, &feature
->col_entry
);
510 list_add_tail(features
, &feature
->entry
);
511 feature
->type
= HidP_Input
;
512 parse_io_feature(bSize
, itemVal
, bTag
, feature_index
, feature
);
513 feature
->caps
= *caps
;
514 feature
->collection
= collection
;
517 case TAG_MAIN_OUTPUT
:
518 feature
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*feature
));
519 list_add_tail(&collection
->features
, &feature
->col_entry
);
520 list_add_tail(features
, &feature
->entry
);
521 feature
->type
= HidP_Output
;
522 parse_io_feature(bSize
, itemVal
, bTag
, feature_index
, feature
);
523 feature
->caps
= *caps
;
524 feature
->collection
= collection
;
527 case TAG_MAIN_FEATURE
:
528 feature
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*feature
));
529 list_add_tail(&collection
->features
, &feature
->col_entry
);
530 list_add_tail(features
, &feature
->entry
);
531 feature
->type
= HidP_Feature
;
532 parse_io_feature(bSize
, itemVal
, bTag
, feature_index
, feature
);
533 feature
->caps
= *caps
;
534 feature
->collection
= collection
;
537 case TAG_MAIN_COLLECTION
:
539 struct collection
*subcollection
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct collection
));
540 list_add_tail(&collection
->collections
, &subcollection
->entry
);
541 subcollection
->parent
= collection
;
542 /* Only set our collection once...
543 We do not properly handle composite devices yet. */
544 if (*collection_index
== 0)
545 collection
->caps
= *caps
;
546 subcollection
->caps
= *caps
;
547 subcollection
->index
= *collection_index
;
548 *collection_index
= *collection_index
+ 1;
549 list_init(&subcollection
->features
);
550 list_init(&subcollection
->collections
);
553 parse_collection(bSize
, itemVal
, subcollection
);
555 i
= parse_descriptor(descriptor
, i
+1, length
, feature_index
, collection_index
, subcollection
, caps
, features
, stack
);
558 case TAG_MAIN_END_COLLECTION
:
561 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag
, bType
);
564 else if (bType
== TAG_TYPE_GLOBAL
)
568 case TAG_GLOBAL_USAGE_PAGE
:
569 caps
->UsagePage
= getValue(bSize
, itemVal
, FALSE
);
571 case TAG_GLOBAL_LOGICAL_MINIMUM
:
572 caps
->LogicalMin
= getValue(bSize
, itemVal
, TRUE
);
574 case TAG_GLOBAL_LOGICAL_MAXIMUM
:
575 caps
->LogicalMax
= getValue(bSize
, itemVal
, TRUE
);
577 case TAG_GLOBAL_PHYSICAL_MINIMUM
:
578 caps
->PhysicalMin
= getValue(bSize
, itemVal
, TRUE
);
580 case TAG_GLOBAL_PHYSICAL_MAXIMUM
:
581 caps
->PhysicalMax
= getValue(bSize
, itemVal
, TRUE
);
583 case TAG_GLOBAL_UNIT_EXPONENT
:
584 caps
->UnitsExp
= getValue(bSize
, itemVal
, TRUE
);
586 case TAG_GLOBAL_UNIT
:
587 caps
->Units
= getValue(bSize
, itemVal
, TRUE
);
589 case TAG_GLOBAL_REPORT_SIZE
:
590 caps
->BitSize
= getValue(bSize
, itemVal
, FALSE
);
592 case TAG_GLOBAL_REPORT_ID
:
593 caps
->ReportID
= getValue(bSize
, itemVal
, FALSE
);
595 case TAG_GLOBAL_REPORT_COUNT
:
596 caps
->ReportCount
= getValue(bSize
, itemVal
, FALSE
);
598 case TAG_GLOBAL_PUSH
:
600 struct caps_stack
*saved
= HeapAlloc(GetProcessHeap(), 0, sizeof(*saved
));
603 list_add_tail(stack
, &saved
->entry
);
609 struct caps_stack
*saved
;
611 tail
= list_tail(stack
);
614 saved
= LIST_ENTRY(tail
, struct caps_stack
, entry
);
617 HeapFree(GetProcessHeap(), 0, saved
);
620 ERR("Pop but no stack!\n");
624 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag
, bType
);
627 else if (bType
== TAG_TYPE_LOCAL
)
631 case TAG_LOCAL_USAGE
:
632 if (caps
->usage_count
>= USAGE_MAX
)
633 FIXME("More than %i individual usages defined\n",USAGE_MAX
);
636 caps
->u
.NotRange
.Usage
[caps
->usage_count
++] = getValue(bSize
, itemVal
, FALSE
);
637 caps
->IsRange
= FALSE
;
640 case TAG_LOCAL_USAGE_MINIMUM
:
641 caps
->usage_count
= 1;
642 caps
->u
.Range
.UsageMin
= getValue(bSize
, itemVal
, FALSE
);
643 caps
->IsRange
= TRUE
;
645 case TAG_LOCAL_USAGE_MAXIMUM
:
646 caps
->usage_count
= 1;
647 caps
->u
.Range
.UsageMax
= getValue(bSize
, itemVal
, FALSE
);
648 caps
->IsRange
= TRUE
;
650 case TAG_LOCAL_DESIGNATOR_INDEX
:
651 caps
->u
.NotRange
.DesignatorIndex
= getValue(bSize
, itemVal
, FALSE
);
652 caps
->IsDesignatorRange
= FALSE
;
654 case TAG_LOCAL_DESIGNATOR_MINIMUM
:
655 caps
->u
.Range
.DesignatorMin
= getValue(bSize
, itemVal
, FALSE
);
656 caps
->IsDesignatorRange
= TRUE
;
658 case TAG_LOCAL_DESIGNATOR_MAXIMUM
:
659 caps
->u
.Range
.DesignatorMax
= getValue(bSize
, itemVal
, FALSE
);
660 caps
->IsDesignatorRange
= TRUE
;
662 case TAG_LOCAL_STRING_INDEX
:
663 caps
->u
.NotRange
.StringIndex
= getValue(bSize
, itemVal
, FALSE
);
664 caps
->IsStringRange
= FALSE
;
666 case TAG_LOCAL_STRING_MINIMUM
:
667 caps
->u
.Range
.StringMin
= getValue(bSize
, itemVal
, FALSE
);
668 caps
->IsStringRange
= TRUE
;
670 case TAG_LOCAL_STRING_MAXIMUM
:
671 caps
->u
.Range
.StringMax
= getValue(bSize
, itemVal
, FALSE
);
672 caps
->IsStringRange
= TRUE
;
674 case TAG_LOCAL_DELIMITER
:
675 caps
->Delim
= getValue(bSize
, itemVal
, FALSE
);
678 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag
, bType
);
682 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag
, bType
);
690 static inline void new_report(WINE_HID_REPORT
*wine_report
, struct feature
* feature
)
692 wine_report
->reportID
= feature
->caps
.ReportID
;
693 wine_report
->dwSize
= sizeof(*wine_report
) - sizeof(WINE_HID_ELEMENT
);
694 wine_report
->elementCount
= 0;
697 static void build_elements(WINE_HID_REPORT
*wine_report
, struct feature
* feature
, DWORD
*bitOffset
, unsigned int *data_index
)
701 if (!feature
->isData
)
703 *bitOffset
= *bitOffset
+ (feature
->caps
.BitSize
* feature
->caps
.ReportCount
);
707 for (i
= 0; i
< feature
->caps
.usage_count
; i
++)
709 WINE_HID_ELEMENT
*wine_element
= &wine_report
->Elements
[wine_report
->elementCount
];
711 wine_element
->valueStartBit
= *bitOffset
;
712 if (feature
->caps
.UsagePage
== HID_USAGE_PAGE_BUTTON
)
714 wine_element
->ElementType
= ButtonElement
;
715 wine_element
->caps
.button
.UsagePage
= feature
->caps
.UsagePage
;
716 wine_element
->caps
.button
.ReportID
= feature
->caps
.ReportID
;
717 wine_element
->caps
.button
.BitField
= feature
->BitField
;
718 wine_element
->caps
.button
.IsRange
= feature
->caps
.IsRange
;
719 wine_element
->caps
.button
.IsStringRange
= feature
->caps
.IsStringRange
;
720 wine_element
->caps
.button
.IsDesignatorRange
= feature
->caps
.IsDesignatorRange
;
721 wine_element
->caps
.button
.IsAbsolute
= feature
->IsAbsolute
;
722 if (wine_element
->caps
.button
.IsRange
)
724 wine_element
->bitCount
= (feature
->caps
.u
.Range
.UsageMax
- feature
->caps
.u
.Range
.UsageMin
) + 1;
725 *bitOffset
= *bitOffset
+ wine_element
->bitCount
;
726 wine_element
->caps
.button
.u
.Range
.UsageMin
= feature
->caps
.u
.Range
.UsageMin
;
727 wine_element
->caps
.button
.u
.Range
.UsageMax
= feature
->caps
.u
.Range
.UsageMax
;
728 wine_element
->caps
.button
.u
.Range
.StringMin
= feature
->caps
.u
.Range
.StringMin
;
729 wine_element
->caps
.button
.u
.Range
.StringMax
= feature
->caps
.u
.Range
.StringMax
;
730 wine_element
->caps
.button
.u
.Range
.DesignatorMin
= feature
->caps
.u
.Range
.DesignatorMin
;
731 wine_element
->caps
.button
.u
.Range
.DesignatorMax
= feature
->caps
.u
.Range
.DesignatorMax
;
732 wine_element
->caps
.button
.u
.Range
.DataIndexMin
= *data_index
;
733 wine_element
->caps
.button
.u
.Range
.DataIndexMax
= *data_index
+ wine_element
->bitCount
- 1;
734 *data_index
= *data_index
+ wine_element
->bitCount
;
738 *bitOffset
= *bitOffset
+ 1;
739 wine_element
->bitCount
= 1;
740 wine_element
->caps
.button
.u
.NotRange
.Usage
= feature
->caps
.u
.NotRange
.Usage
[i
];
741 wine_element
->caps
.button
.u
.NotRange
.StringIndex
= feature
->caps
.u
.NotRange
.StringIndex
;
742 wine_element
->caps
.button
.u
.NotRange
.DesignatorIndex
= feature
->caps
.u
.NotRange
.DesignatorIndex
;
743 wine_element
->caps
.button
.u
.NotRange
.DataIndex
= *data_index
;
744 *data_index
= *data_index
+ 1;
749 wine_element
->ElementType
= ValueElement
;
750 wine_element
->caps
.value
.UsagePage
= feature
->caps
.UsagePage
;
751 wine_element
->caps
.value
.ReportID
= feature
->caps
.ReportID
;
752 wine_element
->caps
.value
.BitField
= feature
->BitField
;
753 wine_element
->caps
.value
.IsRange
= feature
->caps
.IsRange
;
754 wine_element
->caps
.value
.IsStringRange
= feature
->caps
.IsStringRange
;
755 wine_element
->caps
.value
.IsDesignatorRange
= feature
->caps
.IsDesignatorRange
;
756 wine_element
->caps
.value
.IsAbsolute
= feature
->IsAbsolute
;
757 wine_element
->caps
.value
.HasNull
= feature
->HasNull
;
758 wine_element
->caps
.value
.BitSize
= feature
->caps
.BitSize
;
759 if (feature
->caps
.usage_count
> 1)
761 if (feature
->caps
.ReportCount
> feature
->caps
.usage_count
)
762 wine_element
->caps
.value
.ReportCount
= feature
->caps
.ReportCount
/ feature
->caps
.usage_count
;
764 wine_element
->caps
.value
.ReportCount
= 1;
767 wine_element
->caps
.value
.ReportCount
= feature
->caps
.ReportCount
;
768 wine_element
->bitCount
= (feature
->caps
.BitSize
* wine_element
->caps
.value
.ReportCount
);
769 *bitOffset
= *bitOffset
+ wine_element
->bitCount
;
770 wine_element
->caps
.value
.UnitsExp
= feature
->caps
.UnitsExp
;
771 wine_element
->caps
.value
.Units
= feature
->caps
.Units
;
772 wine_element
->caps
.value
.LogicalMin
= feature
->caps
.LogicalMin
;
773 wine_element
->caps
.value
.LogicalMax
= feature
->caps
.LogicalMax
;
774 wine_element
->caps
.value
.PhysicalMin
= feature
->caps
.PhysicalMin
;
775 wine_element
->caps
.value
.PhysicalMax
= feature
->caps
.PhysicalMax
;
776 if (wine_element
->caps
.value
.IsRange
)
778 wine_element
->caps
.value
.u
.Range
.UsageMin
= feature
->caps
.u
.Range
.UsageMin
;
779 wine_element
->caps
.value
.u
.Range
.UsageMax
= feature
->caps
.u
.Range
.UsageMax
;
780 wine_element
->caps
.value
.u
.Range
.StringMin
= feature
->caps
.u
.Range
.StringMin
;
781 wine_element
->caps
.value
.u
.Range
.StringMax
= feature
->caps
.u
.Range
.StringMax
;
782 wine_element
->caps
.value
.u
.Range
.DesignatorMin
= feature
->caps
.u
.Range
.DesignatorMin
;
783 wine_element
->caps
.value
.u
.Range
.DesignatorMax
= feature
->caps
.u
.Range
.DesignatorMax
;
784 wine_element
->caps
.value
.u
.Range
.DataIndexMin
= *data_index
;
785 wine_element
->caps
.value
.u
.Range
.DataIndexMax
= *data_index
+
786 (wine_element
->caps
.value
.u
.Range
.UsageMax
-
787 wine_element
->caps
.value
.u
.Range
.UsageMin
);
788 *data_index
= *data_index
+
789 (wine_element
->caps
.value
.u
.Range
.UsageMax
-
790 wine_element
->caps
.value
.u
.Range
.UsageMin
) + 1;
794 wine_element
->caps
.value
.u
.NotRange
.Usage
= feature
->caps
.u
.NotRange
.Usage
[i
];
795 wine_element
->caps
.value
.u
.NotRange
.StringIndex
= feature
->caps
.u
.NotRange
.StringIndex
;
796 wine_element
->caps
.value
.u
.NotRange
.DesignatorIndex
= feature
->caps
.u
.NotRange
.DesignatorIndex
;
797 wine_element
->caps
.value
.u
.NotRange
.DataIndex
= *data_index
;
798 *data_index
= *data_index
+ 1;
802 wine_report
->elementCount
++;
806 static void count_elements(struct feature
* feature
, USHORT
*buttons
, USHORT
*values
)
808 if (feature
->caps
.UsagePage
== HID_USAGE_PAGE_BUTTON
)
810 if (feature
->caps
.IsRange
)
811 *buttons
= *buttons
+ 1;
813 *buttons
= *buttons
+ feature
->caps
.usage_count
;
817 if (feature
->caps
.IsRange
)
818 *values
= *values
+ 1;
820 *values
= *values
+ feature
->caps
.usage_count
;
824 static WINE_HIDP_PREPARSED_DATA
* build_PreparseData(
825 struct feature
**features
, int feature_count
,
826 struct feature
**input_features
, int i_count
,
827 struct feature
**output_features
, int o_count
,
828 struct feature
**feature_features
, int f_count
,
829 struct collection
*base_collection
)
831 WINE_HIDP_PREPARSED_DATA
*data
;
832 WINE_HID_REPORT
*wine_report
= NULL
;
833 DWORD bitOffset
, bitLength
;
834 unsigned int report_count
= 1;
836 unsigned int element_count
;
837 unsigned int size
= 0;
838 unsigned int data_index
;
840 if (features
[0]->caps
.ReportID
!= 0)
842 unsigned int *report_ids
;
843 unsigned int cnt
= max(i_count
, o_count
);
844 cnt
= max(cnt
, f_count
);
845 report_ids
= HeapAlloc(GetProcessHeap(), 0 , sizeof(*report_ids
) * cnt
);
849 report_ids
[0] = input_features
[0]->caps
.ReportID
;
850 for (i
= 1; i
< i_count
; i
++)
853 unsigned int found
= FALSE
;
854 for (j
= 0; !found
&& j
< i_count
; j
++)
856 if (report_ids
[j
] == input_features
[i
]->caps
.ReportID
)
861 report_ids
[report_count
] = input_features
[i
]->caps
.ReportID
;
869 report_ids
[0] = output_features
[0]->caps
.ReportID
;
870 for (i
= 1; i
< o_count
; i
++)
873 unsigned int found
= FALSE
;
874 for (j
= 0; !found
&& j
< o_count
; j
++)
876 if (report_ids
[j
] == output_features
[i
]->caps
.ReportID
)
881 report_ids
[report_count
] = output_features
[i
]->caps
.ReportID
;
889 report_ids
[0] = feature_features
[0]->caps
.ReportID
;
890 for (i
= 1; i
< f_count
; i
++)
893 unsigned int found
= FALSE
;
894 for (j
= 0; !found
&& j
< f_count
; j
++)
896 if (report_ids
[j
] == feature_features
[i
]->caps
.ReportID
)
901 report_ids
[report_count
] = feature_features
[i
]->caps
.ReportID
;
906 HeapFree(GetProcessHeap(), 0, report_ids
);
910 if (o_count
) report_count
++;
911 if (f_count
) report_count
++;
915 for (i
= 0; i
< feature_count
; i
++)
916 element_count
+= features
[i
]->caps
.usage_count
;
918 size
= sizeof(WINE_HIDP_PREPARSED_DATA
) +
919 (element_count
* sizeof(WINE_HID_ELEMENT
)) +
920 (report_count
* sizeof(WINE_HID_REPORT
));
922 TRACE("%i reports %i elements -> size %i\n",report_count
, element_count
, size
);
924 data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
925 data
->magic
= HID_MAGIC
;
927 data
->caps
.Usage
= base_collection
->caps
.u
.NotRange
.Usage
[0];
928 data
->caps
.UsagePage
= base_collection
->caps
.UsagePage
;
930 wine_report
= data
->InputReports
;
935 new_report(wine_report
, input_features
[0]);
936 data
->dwInputReportCount
++;
938 /* Room for the reportID */
941 for (i
= 0; i
< i_count
; i
++)
943 if (input_features
[i
]->caps
.ReportID
!= wine_report
->reportID
)
945 wine_report
->dwSize
+= (sizeof(WINE_HID_ELEMENT
) * wine_report
->elementCount
);
946 wine_report
= (WINE_HID_REPORT
*)(((BYTE
*)wine_report
)+wine_report
->dwSize
);
947 new_report(wine_report
, input_features
[i
]);
948 data
->dwInputReportCount
++;
949 bitLength
= max(bitOffset
, bitLength
);
952 build_elements(wine_report
, input_features
[i
], &bitOffset
, &data_index
);
953 count_elements(input_features
[i
], &data
->caps
.NumberInputButtonCaps
,
954 &data
->caps
.NumberInputValueCaps
);
956 wine_report
->dwSize
+= (sizeof(WINE_HID_ELEMENT
) * wine_report
->elementCount
);
957 bitLength
= max(bitOffset
, bitLength
);
958 data
->caps
.InputReportByteLength
= ((bitLength
+ 7) & ~7)/8;
959 data
->caps
.NumberInputDataIndices
= data_index
;
966 wine_report
= (WINE_HID_REPORT
*)(((BYTE
*)wine_report
)+wine_report
->dwSize
);
967 data
->dwOutputReportOffset
= (BYTE
*)wine_report
- (BYTE
*)data
->InputReports
;
968 new_report(wine_report
, output_features
[0]);
969 data
->dwOutputReportCount
++;
972 for (i
= 0; i
< o_count
; i
++)
974 if (output_features
[i
]->caps
.ReportID
!= wine_report
->reportID
)
976 wine_report
->dwSize
+= (sizeof(WINE_HID_ELEMENT
) * wine_report
->elementCount
);
977 wine_report
= (WINE_HID_REPORT
*)(((BYTE
*)wine_report
)+wine_report
->dwSize
);
978 new_report(wine_report
, output_features
[i
]);
979 data
->dwOutputReportCount
++;
980 bitLength
= max(bitOffset
, bitLength
);
983 build_elements(wine_report
, output_features
[i
], &bitOffset
, &data_index
);
984 count_elements(output_features
[i
], &data
->caps
.NumberOutputButtonCaps
,
985 &data
->caps
.NumberOutputValueCaps
);
987 wine_report
->dwSize
+= (sizeof(WINE_HID_ELEMENT
) * wine_report
->elementCount
);
988 bitLength
= max(bitOffset
, bitLength
);
989 data
->caps
.OutputReportByteLength
= ((bitLength
+ 7) & ~7)/8;
990 data
->caps
.NumberOutputDataIndices
= data_index
;
997 wine_report
= (WINE_HID_REPORT
*)(((BYTE
*)wine_report
)+wine_report
->dwSize
);
998 data
->dwFeatureReportOffset
= (BYTE
*)wine_report
- (BYTE
*)data
->InputReports
;
999 new_report(wine_report
, feature_features
[0]);
1000 data
->dwFeatureReportCount
++;
1003 for (i
= 0; i
< f_count
; i
++)
1005 if (feature_features
[i
]->caps
.ReportID
!= wine_report
->reportID
)
1007 wine_report
->dwSize
+= (sizeof(WINE_HID_ELEMENT
) * wine_report
->elementCount
);
1008 wine_report
= (WINE_HID_REPORT
*)((BYTE
*)wine_report
+wine_report
->dwSize
);
1009 new_report(wine_report
, feature_features
[i
]);
1010 data
->dwFeatureReportCount
++;
1011 bitLength
= max(bitOffset
, bitLength
);
1014 build_elements(wine_report
, feature_features
[i
], &bitOffset
, &data_index
);
1015 count_elements(feature_features
[i
], &data
->caps
.NumberFeatureButtonCaps
,
1016 &data
->caps
.NumberFeatureValueCaps
);
1018 bitLength
= max(bitOffset
, bitLength
);
1019 data
->caps
.FeatureReportByteLength
= ((bitLength
+ 7) & ~7)/8;
1020 data
->caps
.NumberFeatureDataIndices
= data_index
;
1026 static void free_collection(struct collection
*collection
)
1028 struct feature
*fentry
, *fnext
;
1029 struct collection
*centry
, *cnext
;
1030 LIST_FOR_EACH_ENTRY_SAFE(centry
, cnext
, &collection
->collections
, struct collection
, entry
)
1032 list_remove(¢ry
->entry
);
1033 free_collection(centry
);
1035 LIST_FOR_EACH_ENTRY_SAFE(fentry
, fnext
, &collection
->features
, struct feature
, col_entry
)
1037 list_remove(&fentry
->col_entry
);
1038 HeapFree(GetProcessHeap(), 0, fentry
);
1040 HeapFree(GetProcessHeap(), 0, collection
);
1043 static int compare_reports(const void *a
, const void* b
)
1045 struct feature
*f1
= *(struct feature
**)a
;
1046 struct feature
*f2
= *(struct feature
**)b
;
1047 int c
= (f1
->caps
.ReportID
- f2
->caps
.ReportID
);
1049 return (f1
->index
- f2
->index
);
1052 WINE_HIDP_PREPARSED_DATA
* ParseDescriptor(BYTE
*descriptor
, unsigned int length
)
1054 WINE_HIDP_PREPARSED_DATA
*data
= NULL
;
1055 struct collection
*base
;
1058 struct list features
;
1059 struct list caps_stack
;
1061 unsigned int feature_count
= 0;
1066 TRACE("Descriptor[%i]: ", length
);
1067 for (cidx
= 0; cidx
< length
; cidx
++)
1069 TRACE("%x ",descriptor
[cidx
]);
1070 if ((cidx
+1) % 80 == 0)
1076 list_init(&features
);
1077 list_init(&caps_stack
);
1079 base
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*base
));
1081 list_init(&base
->features
);
1082 list_init(&base
->collections
);
1083 memset(&caps
, 0, sizeof(caps
));
1086 parse_descriptor(descriptor
, 0, length
, &feature_count
, &cidx
, base
, &caps
, &features
, &caps_stack
);
1088 debug_collection(base
);
1090 if (!list_empty(&caps_stack
))
1092 struct caps_stack
*entry
, *cursor
;
1093 ERR("%i unpopped device caps on the stack\n", list_count(&caps_stack
));
1094 LIST_FOR_EACH_ENTRY_SAFE(entry
, cursor
, &caps_stack
, struct caps_stack
, entry
)
1096 list_remove(&entry
->entry
);
1097 HeapFree(GetProcessHeap(), 0, entry
);
1104 struct feature
*entry
;
1105 struct feature
** sorted_features
;
1106 struct feature
** input_features
;
1107 struct feature
** output_features
;
1108 struct feature
** feature_features
;
1109 unsigned int i_count
, o_count
, f_count
;
1112 i_count
= o_count
= f_count
= 0;
1114 sorted_features
= HeapAlloc(GetProcessHeap(), 0, sizeof(*sorted_features
) * feature_count
);
1115 input_features
= HeapAlloc(GetProcessHeap(), 0, sizeof(*input_features
) * feature_count
);
1116 output_features
= HeapAlloc(GetProcessHeap(), 0, sizeof(*output_features
) * feature_count
);
1117 feature_features
= HeapAlloc(GetProcessHeap(), 0, sizeof(*feature_features
) * feature_count
);
1120 LIST_FOR_EACH_ENTRY(entry
, &features
, struct feature
, entry
)
1121 sorted_features
[i
++] = entry
;
1123 /* Sort features base on report if there are multiple reports */
1124 if (sorted_features
[0]->caps
.ReportID
!= 0)
1125 qsort(sorted_features
, feature_count
, sizeof(struct feature
*), compare_reports
);
1127 for (i
= 0; i
< feature_count
; i
++)
1129 switch (sorted_features
[i
]->type
)
1132 input_features
[i_count
] = sorted_features
[i
];
1136 output_features
[o_count
] = sorted_features
[i
];
1140 feature_features
[f_count
] = sorted_features
[i
];
1144 ERR("Unknown type %i\n",sorted_features
[i
]->type
);
1150 TRACE("DUMP FEATURES:\n");
1151 TRACE("----INPUT----\n");
1152 for (cidx
= 0; cidx
< i_count
; cidx
++)
1153 debug_feature(input_features
[cidx
]);
1154 TRACE("----OUTPUT----\n");
1155 for (cidx
= 0; cidx
< o_count
; cidx
++)
1156 debug_feature(output_features
[cidx
]);
1157 TRACE("----FEATURE----\n");
1158 for (cidx
= 0; cidx
< f_count
; cidx
++)
1159 debug_feature(feature_features
[cidx
]);
1162 data
= build_PreparseData(sorted_features
, feature_count
, input_features
, i_count
, output_features
, o_count
, feature_features
, f_count
, base
);
1164 debug_print_preparsed(data
);
1166 HeapFree(GetProcessHeap(), 0, sorted_features
);
1167 HeapFree(GetProcessHeap(), 0, input_features
);
1168 HeapFree(GetProcessHeap(), 0, output_features
);
1169 HeapFree(GetProcessHeap(), 0, feature_features
);
1172 free_collection(base
);
1173 /* We do not have to free the list as free_collection does all the work */