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
)
445 collection
->type
= itemVal
;
447 if (itemVal
>= 0x07 && itemVal
<= 0x7F) {
448 ERR(" (Reserved 0x%x )\n", itemVal
);
450 else if (itemVal
>= 0x80 && itemVal
<= 0xFF) {
451 ERR(" (Vendor Defined 0x%x )\n", itemVal
);
456 static void new_caps(struct caps
*caps
)
459 caps
->IsStringRange
= 0;
460 caps
->IsDesignatorRange
= 0;
461 caps
->usage_count
= 0;
464 static int parse_descriptor(BYTE
*descriptor
, unsigned int index
, unsigned int length
,
465 unsigned int *feature_index
, unsigned int *collection_index
,
466 struct collection
*collection
, struct caps
*caps
,
467 struct list
*features
, struct list
*stack
)
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 feature
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*feature
));
507 list_add_tail(&collection
->features
, &feature
->col_entry
);
508 list_add_tail(features
, &feature
->entry
);
509 feature
->type
= HidP_Input
;
510 parse_io_feature(bSize
, itemVal
, bTag
, feature_index
, feature
);
511 feature
->caps
= *caps
;
512 feature
->collection
= collection
;
515 case TAG_MAIN_OUTPUT
:
516 feature
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*feature
));
517 list_add_tail(&collection
->features
, &feature
->col_entry
);
518 list_add_tail(features
, &feature
->entry
);
519 feature
->type
= HidP_Output
;
520 parse_io_feature(bSize
, itemVal
, bTag
, feature_index
, feature
);
521 feature
->caps
= *caps
;
522 feature
->collection
= collection
;
525 case TAG_MAIN_FEATURE
:
526 feature
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*feature
));
527 list_add_tail(&collection
->features
, &feature
->col_entry
);
528 list_add_tail(features
, &feature
->entry
);
529 feature
->type
= HidP_Feature
;
530 parse_io_feature(bSize
, itemVal
, bTag
, feature_index
, feature
);
531 feature
->caps
= *caps
;
532 feature
->collection
= collection
;
535 case TAG_MAIN_COLLECTION
:
537 struct collection
*subcollection
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct collection
));
538 list_add_tail(&collection
->collections
, &subcollection
->entry
);
539 subcollection
->parent
= collection
;
540 /* Only set our collection once...
541 We do not properly handle composite devices yet. */
542 if (*collection_index
== 0)
543 collection
->caps
= *caps
;
544 subcollection
->caps
= *caps
;
545 subcollection
->index
= *collection_index
;
546 *collection_index
= *collection_index
+ 1;
547 list_init(&subcollection
->features
);
548 list_init(&subcollection
->collections
);
551 parse_collection(bSize
, itemVal
, subcollection
);
553 i
= parse_descriptor(descriptor
, i
+1, length
, feature_index
, collection_index
, subcollection
, caps
, features
, stack
);
556 case TAG_MAIN_END_COLLECTION
:
559 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag
, bType
);
562 else if (bType
== TAG_TYPE_GLOBAL
)
566 case TAG_GLOBAL_USAGE_PAGE
:
567 caps
->UsagePage
= getValue(bSize
, itemVal
, FALSE
);
569 case TAG_GLOBAL_LOGICAL_MINIMUM
:
570 caps
->LogicalMin
= getValue(bSize
, itemVal
, TRUE
);
572 case TAG_GLOBAL_LOGICAL_MAXIMUM
:
573 caps
->LogicalMax
= getValue(bSize
, itemVal
, TRUE
);
575 case TAG_GLOBAL_PHYSICAL_MINIMUM
:
576 caps
->PhysicalMin
= getValue(bSize
, itemVal
, TRUE
);
578 case TAG_GLOBAL_PHYSICAL_MAXIMUM
:
579 caps
->PhysicalMax
= getValue(bSize
, itemVal
, TRUE
);
581 case TAG_GLOBAL_UNIT_EXPONENT
:
582 caps
->UnitsExp
= getValue(bSize
, itemVal
, TRUE
);
584 case TAG_GLOBAL_UNIT
:
585 caps
->Units
= getValue(bSize
, itemVal
, TRUE
);
587 case TAG_GLOBAL_REPORT_SIZE
:
588 caps
->BitSize
= getValue(bSize
, itemVal
, FALSE
);
590 case TAG_GLOBAL_REPORT_ID
:
591 caps
->ReportID
= getValue(bSize
, itemVal
, FALSE
);
593 case TAG_GLOBAL_REPORT_COUNT
:
594 caps
->ReportCount
= getValue(bSize
, itemVal
, FALSE
);
596 case TAG_GLOBAL_PUSH
:
598 struct caps_stack
*saved
= HeapAlloc(GetProcessHeap(), 0, sizeof(*saved
));
601 list_add_tail(stack
, &saved
->entry
);
607 struct caps_stack
*saved
;
609 tail
= list_tail(stack
);
612 saved
= LIST_ENTRY(tail
, struct caps_stack
, entry
);
615 HeapFree(GetProcessHeap(), 0, saved
);
618 ERR("Pop but no stack!\n");
622 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag
, bType
);
625 else if (bType
== TAG_TYPE_LOCAL
)
629 case TAG_LOCAL_USAGE
:
630 if (caps
->usage_count
>= USAGE_MAX
)
631 FIXME("More than %i individual usages defined\n",USAGE_MAX
);
634 caps
->u
.NotRange
.Usage
[caps
->usage_count
++] = getValue(bSize
, itemVal
, FALSE
);
635 caps
->IsRange
= FALSE
;
638 case TAG_LOCAL_USAGE_MINIMUM
:
639 caps
->usage_count
= 1;
640 caps
->u
.Range
.UsageMin
= getValue(bSize
, itemVal
, FALSE
);
641 caps
->IsRange
= TRUE
;
643 case TAG_LOCAL_USAGE_MAXIMUM
:
644 caps
->usage_count
= 1;
645 caps
->u
.Range
.UsageMax
= getValue(bSize
, itemVal
, FALSE
);
646 caps
->IsRange
= TRUE
;
648 case TAG_LOCAL_DESIGNATOR_INDEX
:
649 caps
->u
.NotRange
.DesignatorIndex
= getValue(bSize
, itemVal
, FALSE
);
650 caps
->IsDesignatorRange
= FALSE
;
652 case TAG_LOCAL_DESIGNATOR_MINIMUM
:
653 caps
->u
.Range
.DesignatorMin
= getValue(bSize
, itemVal
, FALSE
);
654 caps
->IsDesignatorRange
= TRUE
;
656 case TAG_LOCAL_DESIGNATOR_MAXIMUM
:
657 caps
->u
.Range
.DesignatorMax
= getValue(bSize
, itemVal
, FALSE
);
658 caps
->IsDesignatorRange
= TRUE
;
660 case TAG_LOCAL_STRING_INDEX
:
661 caps
->u
.NotRange
.StringIndex
= getValue(bSize
, itemVal
, FALSE
);
662 caps
->IsStringRange
= FALSE
;
664 case TAG_LOCAL_STRING_MINIMUM
:
665 caps
->u
.Range
.StringMin
= getValue(bSize
, itemVal
, FALSE
);
666 caps
->IsStringRange
= TRUE
;
668 case TAG_LOCAL_STRING_MAXIMUM
:
669 caps
->u
.Range
.StringMax
= getValue(bSize
, itemVal
, FALSE
);
670 caps
->IsStringRange
= TRUE
;
672 case TAG_LOCAL_DELIMITER
:
673 caps
->Delim
= getValue(bSize
, itemVal
, FALSE
);
676 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag
, bType
);
680 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag
, bType
);
688 static inline void new_report(WINE_HID_REPORT
*wine_report
, struct feature
* feature
)
690 wine_report
->reportID
= feature
->caps
.ReportID
;
691 wine_report
->dwSize
= sizeof(*wine_report
) - sizeof(WINE_HID_ELEMENT
);
692 wine_report
->elementCount
= 0;
695 static void build_elements(WINE_HID_REPORT
*wine_report
, struct feature
* feature
, DWORD
*bitOffset
, unsigned int *data_index
)
699 if (!feature
->isData
)
701 *bitOffset
= *bitOffset
+ (feature
->caps
.BitSize
* feature
->caps
.ReportCount
);
705 for (i
= 0; i
< feature
->caps
.usage_count
; i
++)
707 WINE_HID_ELEMENT
*wine_element
= &wine_report
->Elements
[wine_report
->elementCount
];
709 wine_element
->valueStartBit
= *bitOffset
;
710 if (feature
->caps
.UsagePage
== HID_USAGE_PAGE_BUTTON
)
712 wine_element
->ElementType
= ButtonElement
;
713 wine_element
->caps
.button
.UsagePage
= feature
->caps
.UsagePage
;
714 wine_element
->caps
.button
.ReportID
= feature
->caps
.ReportID
;
715 wine_element
->caps
.button
.BitField
= feature
->BitField
;
716 wine_element
->caps
.button
.IsRange
= feature
->caps
.IsRange
;
717 wine_element
->caps
.button
.IsStringRange
= feature
->caps
.IsStringRange
;
718 wine_element
->caps
.button
.IsDesignatorRange
= feature
->caps
.IsDesignatorRange
;
719 wine_element
->caps
.button
.IsAbsolute
= feature
->IsAbsolute
;
720 if (wine_element
->caps
.button
.IsRange
)
722 wine_element
->bitCount
= (feature
->caps
.u
.Range
.UsageMax
- feature
->caps
.u
.Range
.UsageMin
) + 1;
723 *bitOffset
= *bitOffset
+ wine_element
->bitCount
;
724 wine_element
->caps
.button
.u
.Range
.UsageMin
= feature
->caps
.u
.Range
.UsageMin
;
725 wine_element
->caps
.button
.u
.Range
.UsageMax
= feature
->caps
.u
.Range
.UsageMax
;
726 wine_element
->caps
.button
.u
.Range
.StringMin
= feature
->caps
.u
.Range
.StringMin
;
727 wine_element
->caps
.button
.u
.Range
.StringMax
= feature
->caps
.u
.Range
.StringMax
;
728 wine_element
->caps
.button
.u
.Range
.DesignatorMin
= feature
->caps
.u
.Range
.DesignatorMin
;
729 wine_element
->caps
.button
.u
.Range
.DesignatorMax
= feature
->caps
.u
.Range
.DesignatorMax
;
730 wine_element
->caps
.button
.u
.Range
.DataIndexMin
= *data_index
;
731 wine_element
->caps
.button
.u
.Range
.DataIndexMax
= *data_index
+ wine_element
->bitCount
- 1;
732 *data_index
= *data_index
+ wine_element
->bitCount
;
736 *bitOffset
= *bitOffset
+ 1;
737 wine_element
->bitCount
= 1;
738 wine_element
->caps
.button
.u
.NotRange
.Usage
= feature
->caps
.u
.NotRange
.Usage
[i
];
739 wine_element
->caps
.button
.u
.NotRange
.StringIndex
= feature
->caps
.u
.NotRange
.StringIndex
;
740 wine_element
->caps
.button
.u
.NotRange
.DesignatorIndex
= feature
->caps
.u
.NotRange
.DesignatorIndex
;
741 wine_element
->caps
.button
.u
.NotRange
.DataIndex
= *data_index
;
742 *data_index
= *data_index
+ 1;
747 wine_element
->ElementType
= ValueElement
;
748 wine_element
->caps
.value
.UsagePage
= feature
->caps
.UsagePage
;
749 wine_element
->caps
.value
.ReportID
= feature
->caps
.ReportID
;
750 wine_element
->caps
.value
.BitField
= feature
->BitField
;
751 wine_element
->caps
.value
.IsRange
= feature
->caps
.IsRange
;
752 wine_element
->caps
.value
.IsStringRange
= feature
->caps
.IsStringRange
;
753 wine_element
->caps
.value
.IsDesignatorRange
= feature
->caps
.IsDesignatorRange
;
754 wine_element
->caps
.value
.IsAbsolute
= feature
->IsAbsolute
;
755 wine_element
->caps
.value
.HasNull
= feature
->HasNull
;
756 wine_element
->caps
.value
.BitSize
= feature
->caps
.BitSize
;
757 if (feature
->caps
.usage_count
> 1)
759 if (feature
->caps
.ReportCount
> feature
->caps
.usage_count
)
760 wine_element
->caps
.value
.ReportCount
= feature
->caps
.ReportCount
/ feature
->caps
.usage_count
;
762 wine_element
->caps
.value
.ReportCount
= 1;
765 wine_element
->caps
.value
.ReportCount
= feature
->caps
.ReportCount
;
766 wine_element
->bitCount
= (feature
->caps
.BitSize
* wine_element
->caps
.value
.ReportCount
);
767 *bitOffset
= *bitOffset
+ wine_element
->bitCount
;
768 wine_element
->caps
.value
.UnitsExp
= feature
->caps
.UnitsExp
;
769 wine_element
->caps
.value
.Units
= feature
->caps
.Units
;
770 wine_element
->caps
.value
.LogicalMin
= feature
->caps
.LogicalMin
;
771 wine_element
->caps
.value
.LogicalMax
= feature
->caps
.LogicalMax
;
772 wine_element
->caps
.value
.PhysicalMin
= feature
->caps
.PhysicalMin
;
773 wine_element
->caps
.value
.PhysicalMax
= feature
->caps
.PhysicalMax
;
774 if (wine_element
->caps
.value
.IsRange
)
776 wine_element
->caps
.value
.u
.Range
.UsageMin
= feature
->caps
.u
.Range
.UsageMin
;
777 wine_element
->caps
.value
.u
.Range
.UsageMax
= feature
->caps
.u
.Range
.UsageMax
;
778 wine_element
->caps
.value
.u
.Range
.StringMin
= feature
->caps
.u
.Range
.StringMin
;
779 wine_element
->caps
.value
.u
.Range
.StringMax
= feature
->caps
.u
.Range
.StringMax
;
780 wine_element
->caps
.value
.u
.Range
.DesignatorMin
= feature
->caps
.u
.Range
.DesignatorMin
;
781 wine_element
->caps
.value
.u
.Range
.DesignatorMax
= feature
->caps
.u
.Range
.DesignatorMax
;
782 wine_element
->caps
.value
.u
.Range
.DataIndexMin
= *data_index
;
783 wine_element
->caps
.value
.u
.Range
.DataIndexMax
= *data_index
+
784 (wine_element
->caps
.value
.u
.Range
.UsageMax
-
785 wine_element
->caps
.value
.u
.Range
.UsageMin
);
786 *data_index
= *data_index
+
787 (wine_element
->caps
.value
.u
.Range
.UsageMax
-
788 wine_element
->caps
.value
.u
.Range
.UsageMin
) + 1;
792 wine_element
->caps
.value
.u
.NotRange
.Usage
= feature
->caps
.u
.NotRange
.Usage
[i
];
793 wine_element
->caps
.value
.u
.NotRange
.StringIndex
= feature
->caps
.u
.NotRange
.StringIndex
;
794 wine_element
->caps
.value
.u
.NotRange
.DesignatorIndex
= feature
->caps
.u
.NotRange
.DesignatorIndex
;
795 wine_element
->caps
.value
.u
.NotRange
.DataIndex
= *data_index
;
796 *data_index
= *data_index
+ 1;
800 wine_report
->elementCount
++;
804 static void count_elements(struct feature
* feature
, USHORT
*buttons
, USHORT
*values
)
806 if (feature
->caps
.UsagePage
== HID_USAGE_PAGE_BUTTON
)
808 if (feature
->caps
.IsRange
)
809 *buttons
= *buttons
+ 1;
811 *buttons
= *buttons
+ feature
->caps
.usage_count
;
815 if (feature
->caps
.IsRange
)
816 *values
= *values
+ 1;
818 *values
= *values
+ feature
->caps
.usage_count
;
822 static WINE_HIDP_PREPARSED_DATA
* build_PreparseData(
823 struct feature
**features
, int feature_count
,
824 struct feature
**input_features
, int i_count
,
825 struct feature
**output_features
, int o_count
,
826 struct feature
**feature_features
, int f_count
,
827 struct collection
*base_collection
)
829 WINE_HIDP_PREPARSED_DATA
*data
;
830 WINE_HID_REPORT
*wine_report
= NULL
;
831 DWORD bitOffset
, bitLength
;
832 unsigned int report_count
= 1;
834 unsigned int element_count
;
835 unsigned int size
= 0;
836 unsigned int data_index
;
838 if (features
[0]->caps
.ReportID
!= 0)
840 unsigned int *report_ids
;
841 unsigned int cnt
= max(i_count
, o_count
);
842 cnt
= max(cnt
, f_count
);
843 report_ids
= HeapAlloc(GetProcessHeap(), 0 , sizeof(*report_ids
) * cnt
);
847 report_ids
[0] = input_features
[0]->caps
.ReportID
;
848 for (i
= 1; i
< i_count
; i
++)
851 unsigned int found
= FALSE
;
852 for (j
= 0; !found
&& j
< i_count
; j
++)
854 if (report_ids
[j
] == input_features
[i
]->caps
.ReportID
)
859 report_ids
[report_count
] = input_features
[i
]->caps
.ReportID
;
867 report_ids
[0] = output_features
[0]->caps
.ReportID
;
868 for (i
= 1; i
< o_count
; i
++)
871 unsigned int found
= FALSE
;
872 for (j
= 0; !found
&& j
< o_count
; j
++)
874 if (report_ids
[j
] == output_features
[i
]->caps
.ReportID
)
879 report_ids
[report_count
] = output_features
[i
]->caps
.ReportID
;
887 report_ids
[0] = feature_features
[0]->caps
.ReportID
;
888 for (i
= 1; i
< f_count
; i
++)
891 unsigned int found
= FALSE
;
892 for (j
= 0; !found
&& j
< f_count
; j
++)
894 if (report_ids
[j
] == feature_features
[i
]->caps
.ReportID
)
899 report_ids
[report_count
] = feature_features
[i
]->caps
.ReportID
;
904 HeapFree(GetProcessHeap(), 0, report_ids
);
908 if (o_count
) report_count
++;
909 if (f_count
) report_count
++;
913 for (i
= 0; i
< feature_count
; i
++)
914 element_count
+= features
[i
]->caps
.usage_count
;
916 size
= sizeof(WINE_HIDP_PREPARSED_DATA
) +
917 (element_count
* sizeof(WINE_HID_ELEMENT
)) +
918 (report_count
* sizeof(WINE_HID_REPORT
));
920 TRACE("%i reports %i elements -> size %i\n",report_count
, element_count
, size
);
922 data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
923 data
->magic
= HID_MAGIC
;
925 data
->caps
.Usage
= base_collection
->caps
.u
.NotRange
.Usage
[0];
926 data
->caps
.UsagePage
= base_collection
->caps
.UsagePage
;
928 wine_report
= data
->InputReports
;
933 new_report(wine_report
, input_features
[0]);
934 data
->dwInputReportCount
++;
936 /* Room for the reportID */
939 for (i
= 0; i
< i_count
; i
++)
941 if (input_features
[i
]->caps
.ReportID
!= wine_report
->reportID
)
943 wine_report
->dwSize
+= (sizeof(WINE_HID_ELEMENT
) * wine_report
->elementCount
);
944 wine_report
= (WINE_HID_REPORT
*)(((BYTE
*)wine_report
)+wine_report
->dwSize
);
945 new_report(wine_report
, input_features
[i
]);
946 data
->dwInputReportCount
++;
947 bitLength
= max(bitOffset
, bitLength
);
950 build_elements(wine_report
, input_features
[i
], &bitOffset
, &data_index
);
951 count_elements(input_features
[i
], &data
->caps
.NumberInputButtonCaps
,
952 &data
->caps
.NumberInputValueCaps
);
954 wine_report
->dwSize
+= (sizeof(WINE_HID_ELEMENT
) * wine_report
->elementCount
);
955 bitLength
= max(bitOffset
, bitLength
);
956 data
->caps
.InputReportByteLength
= ((bitLength
+ 7) & ~7)/8;
957 data
->caps
.NumberInputDataIndices
= data_index
;
964 wine_report
= (WINE_HID_REPORT
*)(((BYTE
*)wine_report
)+wine_report
->dwSize
);
965 data
->dwOutputReportOffset
= (BYTE
*)wine_report
- (BYTE
*)data
->InputReports
;
966 new_report(wine_report
, output_features
[0]);
967 data
->dwOutputReportCount
++;
970 for (i
= 0; i
< o_count
; i
++)
972 if (output_features
[i
]->caps
.ReportID
!= wine_report
->reportID
)
974 wine_report
->dwSize
+= (sizeof(WINE_HID_ELEMENT
) * wine_report
->elementCount
);
975 wine_report
= (WINE_HID_REPORT
*)(((BYTE
*)wine_report
)+wine_report
->dwSize
);
976 new_report(wine_report
, output_features
[i
]);
977 data
->dwOutputReportCount
++;
978 bitLength
= max(bitOffset
, bitLength
);
981 build_elements(wine_report
, output_features
[i
], &bitOffset
, &data_index
);
982 count_elements(output_features
[i
], &data
->caps
.NumberOutputButtonCaps
,
983 &data
->caps
.NumberOutputValueCaps
);
985 wine_report
->dwSize
+= (sizeof(WINE_HID_ELEMENT
) * wine_report
->elementCount
);
986 bitLength
= max(bitOffset
, bitLength
);
987 data
->caps
.OutputReportByteLength
= ((bitLength
+ 7) & ~7)/8;
988 data
->caps
.NumberOutputDataIndices
= data_index
;
995 wine_report
= (WINE_HID_REPORT
*)(((BYTE
*)wine_report
)+wine_report
->dwSize
);
996 data
->dwFeatureReportOffset
= (BYTE
*)wine_report
- (BYTE
*)data
->InputReports
;
997 new_report(wine_report
, feature_features
[0]);
998 data
->dwFeatureReportCount
++;
1001 for (i
= 0; i
< f_count
; i
++)
1003 if (feature_features
[i
]->caps
.ReportID
!= wine_report
->reportID
)
1005 wine_report
->dwSize
+= (sizeof(WINE_HID_ELEMENT
) * wine_report
->elementCount
);
1006 wine_report
= (WINE_HID_REPORT
*)((BYTE
*)wine_report
+wine_report
->dwSize
);
1007 new_report(wine_report
, feature_features
[i
]);
1008 data
->dwFeatureReportCount
++;
1009 bitLength
= max(bitOffset
, bitLength
);
1012 build_elements(wine_report
, feature_features
[i
], &bitOffset
, &data_index
);
1013 count_elements(feature_features
[i
], &data
->caps
.NumberFeatureButtonCaps
,
1014 &data
->caps
.NumberFeatureValueCaps
);
1016 bitLength
= max(bitOffset
, bitLength
);
1017 data
->caps
.FeatureReportByteLength
= ((bitLength
+ 7) & ~7)/8;
1018 data
->caps
.NumberFeatureDataIndices
= data_index
;
1024 static void free_collection(struct collection
*collection
)
1026 struct feature
*fentry
, *fnext
;
1027 struct collection
*centry
, *cnext
;
1028 LIST_FOR_EACH_ENTRY_SAFE(centry
, cnext
, &collection
->collections
, struct collection
, entry
)
1030 list_remove(¢ry
->entry
);
1031 free_collection(centry
);
1033 LIST_FOR_EACH_ENTRY_SAFE(fentry
, fnext
, &collection
->features
, struct feature
, col_entry
)
1035 list_remove(&fentry
->col_entry
);
1036 HeapFree(GetProcessHeap(), 0, fentry
);
1038 HeapFree(GetProcessHeap(), 0, collection
);
1041 static int compare_reports(const void *a
, const void* b
)
1043 struct feature
*f1
= *(struct feature
**)a
;
1044 struct feature
*f2
= *(struct feature
**)b
;
1045 int c
= (f1
->caps
.ReportID
- f2
->caps
.ReportID
);
1047 return (f1
->index
- f2
->index
);
1050 WINE_HIDP_PREPARSED_DATA
* ParseDescriptor(BYTE
*descriptor
, unsigned int length
)
1052 WINE_HIDP_PREPARSED_DATA
*data
= NULL
;
1053 struct collection
*base
;
1056 struct list features
;
1057 struct list caps_stack
;
1059 unsigned int feature_count
= 0;
1064 TRACE("Descriptor[%i]: ", length
);
1065 for (cidx
= 0; cidx
< length
; cidx
++)
1067 TRACE("%x ",descriptor
[cidx
]);
1068 if ((cidx
+1) % 80 == 0)
1074 list_init(&features
);
1075 list_init(&caps_stack
);
1077 base
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*base
));
1079 list_init(&base
->features
);
1080 list_init(&base
->collections
);
1081 memset(&caps
, 0, sizeof(caps
));
1084 parse_descriptor(descriptor
, 0, length
, &feature_count
, &cidx
, base
, &caps
, &features
, &caps_stack
);
1086 debug_collection(base
);
1088 if (!list_empty(&caps_stack
))
1090 struct caps_stack
*entry
, *cursor
;
1091 ERR("%i unpopped device caps on the stack\n", list_count(&caps_stack
));
1092 LIST_FOR_EACH_ENTRY_SAFE(entry
, cursor
, &caps_stack
, struct caps_stack
, entry
)
1094 list_remove(&entry
->entry
);
1095 HeapFree(GetProcessHeap(), 0, entry
);
1102 struct feature
*entry
;
1103 struct feature
** sorted_features
;
1104 struct feature
** input_features
;
1105 struct feature
** output_features
;
1106 struct feature
** feature_features
;
1107 unsigned int i_count
, o_count
, f_count
;
1110 i_count
= o_count
= f_count
= 0;
1112 sorted_features
= HeapAlloc(GetProcessHeap(), 0, sizeof(*sorted_features
) * feature_count
);
1113 input_features
= HeapAlloc(GetProcessHeap(), 0, sizeof(*input_features
) * feature_count
);
1114 output_features
= HeapAlloc(GetProcessHeap(), 0, sizeof(*output_features
) * feature_count
);
1115 feature_features
= HeapAlloc(GetProcessHeap(), 0, sizeof(*feature_features
) * feature_count
);
1118 LIST_FOR_EACH_ENTRY(entry
, &features
, struct feature
, entry
)
1119 sorted_features
[i
++] = entry
;
1121 /* Sort features base on report if there are multiple reports */
1122 if (sorted_features
[0]->caps
.ReportID
!= 0)
1123 qsort(sorted_features
, feature_count
, sizeof(struct feature
*), compare_reports
);
1125 for (i
= 0; i
< feature_count
; i
++)
1127 switch (sorted_features
[i
]->type
)
1130 input_features
[i_count
] = sorted_features
[i
];
1134 output_features
[o_count
] = sorted_features
[i
];
1138 feature_features
[f_count
] = sorted_features
[i
];
1142 ERR("Unknown type %i\n",sorted_features
[i
]->type
);
1148 TRACE("DUMP FEATURES:\n");
1149 TRACE("----INPUT----\n");
1150 for (cidx
= 0; cidx
< i_count
; cidx
++)
1151 debug_feature(input_features
[cidx
]);
1152 TRACE("----OUTPUT----\n");
1153 for (cidx
= 0; cidx
< o_count
; cidx
++)
1154 debug_feature(output_features
[cidx
]);
1155 TRACE("----FEATURE----\n");
1156 for (cidx
= 0; cidx
< f_count
; cidx
++)
1157 debug_feature(feature_features
[cidx
]);
1160 data
= build_PreparseData(sorted_features
, feature_count
, input_features
, i_count
, output_features
, o_count
, feature_features
, f_count
, base
);
1162 debug_print_preparsed(data
);
1164 HeapFree(GetProcessHeap(), 0, sorted_features
);
1165 HeapFree(GetProcessHeap(), 0, input_features
);
1166 HeapFree(GetProcessHeap(), 0, output_features
);
1167 HeapFree(GetProcessHeap(), 0, feature_features
);
1170 free_collection(base
);
1171 /* We do not have to free the list as free_collection does all the work */