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
;
175 static const char* debugstr_usages(struct caps
*caps
)
179 char out
[12 * USAGE_MAX
];
181 if (caps
->usage_count
== 0)
184 for (i
= 0; i
< caps
->usage_count
; i
++)
185 sprintf(out
+ strlen(out
), "0x%x ", caps
->u
.NotRange
.Usage
[i
]);
186 return wine_dbg_sprintf("[ %s] ", out
);
189 return wine_dbg_sprintf("[0x%x - 0x%x]", caps
->u
.Range
.UsageMin
, caps
->u
.Range
.UsageMax
);
192 static const char* debugstr_stringindex(struct caps
*caps
)
194 if (!caps
->IsStringRange
)
195 return wine_dbg_sprintf("%i", caps
->u
.NotRange
.StringIndex
);
197 return wine_dbg_sprintf("[%i - %i]", caps
->u
.Range
.StringMin
, caps
->u
.Range
.StringMax
);
200 static const char* debugstr_designatorindex(struct caps
*caps
)
202 if (!caps
->IsDesignatorRange
)
203 return wine_dbg_sprintf("%i", caps
->u
.NotRange
.DesignatorIndex
);
205 return wine_dbg_sprintf("[%i - %i]", caps
->u
.Range
.DesignatorMin
, caps
->u
.Range
.DesignatorMax
);
208 static void debugstr_caps(const char* type
, struct caps
*caps
)
212 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",
224 debugstr_usages(caps
),
225 debugstr_stringindex(caps
),
226 debugstr_designatorindex(caps
),
230 static void debug_feature(struct feature
*feature
)
234 TRACE("[Feature type %s [%i]; %s; %s; %s; %s; %s; %s; %s; %s; %s]\n",
235 feature_string
[feature
->type
],
237 (feature
->isData
)?"Data":"Const",
238 (feature
->isArray
)?"Array":"Var",
239 (feature
->IsAbsolute
)?"Abs":"Rel",
240 (feature
->Wrap
)?"Wrap":"NoWrap",
241 (feature
->Linear
)?"Linear":"NonLinear",
242 (feature
->prefState
)?"PrefStat":"NoPrefState",
243 (feature
->HasNull
)?"HasNull":"NoNull",
244 (feature
->Volatile
)?"Volatile":"NonVolatile",
245 (feature
->BitField
)?"BitField":"Buffered");
247 debugstr_caps("Feature", &feature
->caps
);
250 static void debug_collection(struct collection
*collection
)
252 struct feature
*fentry
;
253 struct collection
*centry
;
256 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
));
257 debugstr_caps("Collection", &collection
->caps
);
258 LIST_FOR_EACH_ENTRY(fentry
, &collection
->features
, struct feature
, col_entry
)
259 debug_feature(fentry
);
260 LIST_FOR_EACH_ENTRY(centry
, &collection
->collections
, struct collection
, entry
)
261 debug_collection(centry
);
262 TRACE(">>> END Collection %i\n", collection
->index
);
266 static void debug_print_button_cap(const CHAR
* type
, WINE_HID_ELEMENT
*wine_element
)
268 if (!wine_element
->caps
.button
.IsRange
)
269 TRACE("%s Button: 0x%x/0x%04x: ReportId %i, startBit %i/1\n" , type
,
270 wine_element
->caps
.button
.UsagePage
,
271 wine_element
->caps
.button
.u
.NotRange
.Usage
,
272 wine_element
->caps
.value
.ReportID
,
273 wine_element
->valueStartBit
);
275 TRACE("%s Button: 0x%x/[0x%04x-0x%04x]: ReportId %i, startBit %i/%i\n" ,type
,
276 wine_element
->caps
.button
.UsagePage
,
277 wine_element
->caps
.button
.u
.Range
.UsageMin
,
278 wine_element
->caps
.button
.u
.Range
.UsageMax
,
279 wine_element
->caps
.value
.ReportID
,
280 wine_element
->valueStartBit
,
281 wine_element
->bitCount
);
284 static void debug_print_value_cap(const CHAR
* type
, WINE_HID_ELEMENT
*wine_element
)
286 TRACE("%s Value: 0x%x/0x%x: ReportId %i, IsAbsolute %i, HasNull %i, "
287 "Bit Size %i, ReportCount %i, UnitsExp %i, Units %i, "
288 "LogicalMin %i, Logical Max %i, PhysicalMin %i, "
289 "PhysicalMax %i -- StartBit %i/%i\n", type
,
290 wine_element
->caps
.value
.UsagePage
,
291 wine_element
->caps
.value
.u
.NotRange
.Usage
,
292 wine_element
->caps
.value
.ReportID
,
293 wine_element
->caps
.value
.IsAbsolute
,
294 wine_element
->caps
.value
.HasNull
,
295 wine_element
->caps
.value
.BitSize
,
296 wine_element
->caps
.value
.ReportCount
,
297 wine_element
->caps
.value
.UnitsExp
,
298 wine_element
->caps
.value
.Units
,
299 wine_element
->caps
.value
.LogicalMin
,
300 wine_element
->caps
.value
.LogicalMax
,
301 wine_element
->caps
.value
.PhysicalMin
,
302 wine_element
->caps
.value
.PhysicalMax
,
303 wine_element
->valueStartBit
,
304 wine_element
->bitCount
);
307 static void debug_print_element(const CHAR
* type
, WINE_HID_ELEMENT
*wine_element
)
309 if (wine_element
->ElementType
== ButtonElement
)
310 debug_print_button_cap(type
, wine_element
);
311 else if (wine_element
->ElementType
== ValueElement
)
312 debug_print_value_cap(type
, wine_element
);
314 TRACE("%s: UNKNOWN\n", type
);
317 static void debug_print_report(const char* type
, WINE_HID_REPORT
*report
)
320 TRACE("START Report %i <<< %s report : dwSize: %i elementCount: %i\n",
324 report
->elementCount
);
325 for (i
= 0; i
< report
->elementCount
; i
++)
326 debug_print_element(type
, &report
->Elements
[i
]);
327 TRACE(">>> END Report %i\n",report
->reportID
);
330 static void debug_print_preparsed(WINE_HIDP_PREPARSED_DATA
*data
)
336 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",
339 data
->caps
.UsagePage
,
340 data
->caps
.InputReportByteLength
,
341 data
->caps
.OutputReportByteLength
,
342 data
->caps
.FeatureReportByteLength
,
343 data
->caps
.NumberLinkCollectionNodes
,
344 data
->caps
.NumberInputButtonCaps
,
345 data
->caps
.NumberInputValueCaps
,
346 data
->caps
.NumberInputDataIndices
,
347 data
->caps
.NumberOutputButtonCaps
,
348 data
->caps
.NumberOutputValueCaps
,
349 data
->caps
.NumberOutputDataIndices
,
350 data
->caps
.NumberFeatureButtonCaps
,
351 data
->caps
.NumberFeatureValueCaps
,
352 data
->caps
.NumberFeatureDataIndices
,
353 data
->dwInputReportCount
,
354 data
->dwOutputReportCount
,
355 data
->dwFeatureReportCount
,
356 data
->dwOutputReportOffset
,
357 data
->dwFeatureReportOffset
);
359 r
= HID_INPUT_REPORTS(data
);
360 for (i
= 0; i
< data
->dwInputReportCount
; i
++)
362 debug_print_report("INPUT", r
);
363 r
= HID_NEXT_REPORT(data
, r
);
365 r
= HID_OUTPUT_REPORTS(data
);
366 for (i
= 0; i
< data
->dwOutputReportCount
; i
++)
368 debug_print_report("OUTPUT", r
);
369 r
= HID_NEXT_REPORT(data
, r
);
371 r
= HID_FEATURE_REPORTS(data
);
372 for (i
= 0; i
< data
->dwFeatureReportCount
; i
++)
374 debug_print_report("FEATURE", r
);
375 r
= HID_NEXT_REPORT(data
, r
);
377 TRACE(">>> END Preparsed Data\n");
381 static int getValue(int bsize
, int source
)
385 int outofrange
= 0x100;
392 for (i
= 1; i
< bsize
; i
++)
394 mask
= (mask
<<8) + 0xff;
395 negative
= (negative
<<8);
396 outofrange
= (outofrange
<<8);
398 value
= (source
&mask
);
400 value
= -1 * (outofrange
- value
);
404 static void parse_io_feature(unsigned int bSize
, int itemVal
, int bTag
,
405 unsigned int *feature_index
,
406 struct feature
*feature
)
414 feature
->isData
= ((itemVal
& INPUT_DATA_CONST
) == 0);
415 feature
->isArray
= ((itemVal
& INPUT_ARRAY_VAR
) == 0);
416 feature
->IsAbsolute
= ((itemVal
& INPUT_ABS_REL
) == 0);
417 feature
->Wrap
= ((itemVal
& INPUT_WRAP
) != 0);
418 feature
->Linear
= ((itemVal
& INPUT_LINEAR
) == 0);
419 feature
->prefState
= ((itemVal
& INPUT_PREFSTATE
) == 0);
420 feature
->HasNull
= ((itemVal
& INPUT_NULL
) != 0);
422 if (bTag
!= TAG_MAIN_INPUT
)
424 feature
->Volatile
= ((itemVal
& INPUT_VOLATILE
) != 0);
428 feature
->BitField
= ((itemVal
& INPUT_BITFIELD
) == 0);
430 feature
->index
= *feature_index
;
431 *feature_index
= *feature_index
+ 1;
435 static void parse_collection(unsigned int bSize
, int itemVal
,
436 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
->usage_count
= 0;
461 static int parse_descriptor(BYTE
*descriptor
, unsigned int index
, unsigned int length
, unsigned int *feature_index
, unsigned int *collection_index
, struct collection
*collection
, struct caps
*caps
, struct list
*features
)
464 for (i
= index
; i
< length
;)
466 BYTE b0
= descriptor
[i
++];
467 int bSize
= b0
& 0x03;
468 int bType
= (b0
>> 2) & 0x03;
469 int bTag
= (b0
>> 4) & 0x0F;
471 bSize
= (bSize
== 3) ? 4 : bSize
;
472 if (bType
== TAG_TYPE_RESERVED
&& bTag
== 0x0F && bSize
== 2 &&
475 /* Long data items: Should be unused */
476 ERR("Long Data Item, should be unused\n");
484 for (j
= 0; j
< bSize
; j
++)
488 itemVal
+= descriptor
[i
+ j
] << (8 * j
);
492 TRACE(" 0x%x[%i], type %i , tag %i, size %i, val %i\n",b0
,i
-1,bType
, bTag
, bSize
, itemVal
);
494 if (bType
== TAG_TYPE_MAIN
)
496 struct feature
*feature
;
500 feature
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*feature
));
501 list_add_tail(&collection
->features
, &feature
->col_entry
);
502 list_add_tail(features
, &feature
->entry
);
503 feature
->type
= HidP_Input
;
504 parse_io_feature(bSize
, itemVal
, bTag
, feature_index
, feature
);
505 feature
->caps
= *caps
;
506 feature
->collection
= collection
;
509 case TAG_MAIN_OUTPUT
:
510 feature
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*feature
));
511 list_add_tail(&collection
->features
, &feature
->col_entry
);
512 list_add_tail(features
, &feature
->entry
);
513 feature
->type
= HidP_Output
;
514 parse_io_feature(bSize
, itemVal
, bTag
, feature_index
, feature
);
515 feature
->caps
= *caps
;
516 feature
->collection
= collection
;
519 case TAG_MAIN_FEATURE
:
520 feature
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*feature
));
521 list_add_tail(&collection
->features
, &feature
->col_entry
);
522 list_add_tail(features
, &feature
->entry
);
523 feature
->type
= HidP_Feature
;
524 parse_io_feature(bSize
, itemVal
, bTag
, feature_index
, feature
);
525 feature
->caps
= *caps
;
526 feature
->collection
= collection
;
529 case TAG_MAIN_COLLECTION
:
531 struct collection
*subcollection
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct collection
));
532 list_add_tail(&collection
->collections
, &subcollection
->entry
);
533 subcollection
->parent
= collection
;
534 /* Only set our collection once...
535 We do not properly handle composite devices yet. */
536 if (*collection_index
== 0)
537 collection
->caps
= *caps
;
538 subcollection
->caps
= *caps
;
539 subcollection
->index
= *collection_index
;
540 *collection_index
= *collection_index
+ 1;
541 list_init(&subcollection
->features
);
542 list_init(&subcollection
->collections
);
545 parse_collection(bSize
, itemVal
, subcollection
);
547 i
= parse_descriptor(descriptor
, i
+1, length
, feature_index
, collection_index
, subcollection
, caps
, features
);
550 case TAG_MAIN_END_COLLECTION
:
553 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag
, bType
);
556 else if (bType
== TAG_TYPE_GLOBAL
)
560 case TAG_GLOBAL_USAGE_PAGE
:
561 caps
->UsagePage
= getValue(bSize
, itemVal
);
563 case TAG_GLOBAL_LOGICAL_MINIMUM
:
564 caps
->LogicalMin
= getValue(bSize
, itemVal
);
566 case TAG_GLOBAL_LOGICAL_MAXIMUM
:
567 caps
->LogicalMax
= getValue(bSize
, itemVal
);
569 case TAG_GLOBAL_PHYSICAL_MINIMUM
:
570 caps
->PhysicalMin
= getValue(bSize
, itemVal
);
572 case TAG_GLOBAL_PHYSICAL_MAXIMUM
:
573 caps
->PhysicalMax
= getValue(bSize
, itemVal
);
575 case TAG_GLOBAL_UNIT_EXPONENT
:
576 caps
->UnitsExp
= getValue(bSize
, itemVal
);
578 case TAG_GLOBAL_UNIT
:
579 caps
->Units
= getValue(bSize
, itemVal
);
581 case TAG_GLOBAL_REPORT_SIZE
:
582 caps
->BitSize
= getValue(bSize
, itemVal
);
584 case TAG_GLOBAL_REPORT_ID
:
585 caps
->ReportID
= getValue(bSize
, itemVal
);
587 case TAG_GLOBAL_REPORT_COUNT
:
588 caps
->ReportCount
= getValue(bSize
, itemVal
);
590 case TAG_GLOBAL_PUSH
:
591 FIXME("Unhandled Push\n");
594 FIXME("Unhandled Pop\n");
597 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag
, bType
);
600 else if (bType
== TAG_TYPE_LOCAL
)
604 case TAG_LOCAL_USAGE
:
605 if (caps
->usage_count
>= USAGE_MAX
)
606 FIXME("More than %i individual usages defined\n",USAGE_MAX
);
609 caps
->u
.NotRange
.Usage
[caps
->usage_count
++] = getValue(bSize
, itemVal
);
610 caps
->IsRange
= FALSE
;
613 case TAG_LOCAL_USAGE_MINIMUM
:
614 caps
->usage_count
= 1;
615 caps
->u
.Range
.UsageMin
= getValue(bSize
, itemVal
);
616 caps
->IsRange
= TRUE
;
618 case TAG_LOCAL_USAGE_MAXIMUM
:
619 caps
->usage_count
= 1;
620 caps
->u
.Range
.UsageMax
= getValue(bSize
, itemVal
);
621 caps
->IsRange
= TRUE
;
623 case TAG_LOCAL_DESIGNATOR_INDEX
:
624 caps
->u
.NotRange
.DesignatorIndex
= getValue(bSize
, itemVal
);
625 caps
->IsDesignatorRange
= FALSE
;
627 case TAG_LOCAL_DESIGNATOR_MINIMUM
:
628 caps
->u
.Range
.DesignatorMin
= getValue(bSize
, itemVal
);
629 caps
->IsDesignatorRange
= TRUE
;
631 case TAG_LOCAL_DESIGNATOR_MAXIMUM
:
632 caps
->u
.Range
.DesignatorMax
= getValue(bSize
, itemVal
);
633 caps
->IsDesignatorRange
= TRUE
;
635 case TAG_LOCAL_STRING_INDEX
:
636 caps
->u
.NotRange
.StringIndex
= getValue(bSize
, itemVal
);
637 caps
->IsStringRange
= FALSE
;
639 case TAG_LOCAL_STRING_MINIMUM
:
640 caps
->u
.Range
.StringMin
= getValue(bSize
, itemVal
);
641 caps
->IsStringRange
= TRUE
;
643 case TAG_LOCAL_STRING_MAXIMUM
:
644 caps
->u
.Range
.StringMax
= getValue(bSize
, itemVal
);
645 caps
->IsStringRange
= TRUE
;
647 case TAG_LOCAL_DELIMITER
:
648 caps
->Delim
= getValue(bSize
, itemVal
);
651 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag
, bType
);
655 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag
, bType
);
663 static inline void new_report(WINE_HID_REPORT
*wine_report
, struct feature
* feature
)
665 wine_report
->reportID
= feature
->caps
.ReportID
;
666 wine_report
->dwSize
= sizeof(*wine_report
) - sizeof(WINE_HID_ELEMENT
);
667 wine_report
->elementCount
= 0;
670 static void build_elements(WINE_HID_REPORT
*wine_report
, struct feature
* feature
, DWORD
*bitOffset
)
674 if (!feature
->isData
)
676 *bitOffset
= *bitOffset
+ (feature
->caps
.BitSize
* feature
->caps
.ReportCount
);
680 for (i
= 0; i
< feature
->caps
.usage_count
; i
++)
682 WINE_HID_ELEMENT
*wine_element
= &wine_report
->Elements
[wine_report
->elementCount
];
684 wine_element
->valueStartBit
= *bitOffset
;
685 if (feature
->caps
.UsagePage
== HID_USAGE_PAGE_BUTTON
)
687 wine_element
->ElementType
= ButtonElement
;
688 wine_element
->caps
.button
.UsagePage
= feature
->caps
.UsagePage
;
689 wine_element
->caps
.button
.ReportID
= feature
->caps
.ReportID
;
690 wine_element
->caps
.button
.BitField
= feature
->BitField
;
691 wine_element
->caps
.button
.IsRange
= feature
->caps
.IsRange
;
692 wine_element
->caps
.button
.IsStringRange
= feature
->caps
.IsStringRange
;
693 wine_element
->caps
.button
.IsDesignatorRange
= feature
->caps
.IsDesignatorRange
;
694 wine_element
->caps
.button
.IsAbsolute
= feature
->IsAbsolute
;
695 if (wine_element
->caps
.button
.IsRange
)
697 wine_element
->bitCount
= (feature
->caps
.u
.Range
.UsageMax
- feature
->caps
.u
.Range
.UsageMin
) + 1;
698 *bitOffset
= *bitOffset
+ wine_element
->bitCount
;
699 wine_element
->caps
.button
.u
.Range
.UsageMin
= feature
->caps
.u
.Range
.UsageMin
;
700 wine_element
->caps
.button
.u
.Range
.UsageMax
= feature
->caps
.u
.Range
.UsageMax
;
701 wine_element
->caps
.button
.u
.Range
.StringMin
= feature
->caps
.u
.Range
.StringMin
;
702 wine_element
->caps
.button
.u
.Range
.StringMax
= feature
->caps
.u
.Range
.StringMax
;
703 wine_element
->caps
.button
.u
.Range
.DesignatorMin
= feature
->caps
.u
.Range
.DesignatorMin
;
704 wine_element
->caps
.button
.u
.Range
.DesignatorMax
= feature
->caps
.u
.Range
.DesignatorMax
;
708 *bitOffset
= *bitOffset
+ 1;
709 wine_element
->bitCount
= 1;
710 wine_element
->caps
.button
.u
.NotRange
.Usage
= feature
->caps
.u
.NotRange
.Usage
[i
];
711 wine_element
->caps
.button
.u
.NotRange
.StringIndex
= feature
->caps
.u
.NotRange
.StringIndex
;
712 wine_element
->caps
.button
.u
.NotRange
.DesignatorIndex
= feature
->caps
.u
.NotRange
.DesignatorIndex
;
717 wine_element
->ElementType
= ValueElement
;
718 wine_element
->caps
.value
.UsagePage
= feature
->caps
.UsagePage
;
719 wine_element
->caps
.value
.ReportID
= feature
->caps
.ReportID
;
720 wine_element
->caps
.value
.BitField
= feature
->BitField
;
721 wine_element
->caps
.value
.IsRange
= feature
->caps
.IsRange
;
722 wine_element
->caps
.value
.IsStringRange
= feature
->caps
.IsStringRange
;
723 wine_element
->caps
.value
.IsDesignatorRange
= feature
->caps
.IsDesignatorRange
;
724 wine_element
->caps
.value
.IsAbsolute
= feature
->IsAbsolute
;
725 wine_element
->caps
.value
.HasNull
= feature
->HasNull
;
726 wine_element
->caps
.value
.BitSize
= feature
->caps
.BitSize
;
727 if (feature
->caps
.usage_count
> 1)
728 wine_element
->caps
.value
.ReportCount
= 1;
730 wine_element
->caps
.value
.ReportCount
= feature
->caps
.ReportCount
;
731 wine_element
->bitCount
= (feature
->caps
.BitSize
* wine_element
->caps
.value
.ReportCount
);
732 *bitOffset
= *bitOffset
+ wine_element
->bitCount
;
733 wine_element
->caps
.value
.UnitsExp
= feature
->caps
.UnitsExp
;
734 wine_element
->caps
.value
.Units
= feature
->caps
.Units
;
735 wine_element
->caps
.value
.LogicalMin
= feature
->caps
.LogicalMin
;
736 wine_element
->caps
.value
.LogicalMax
= feature
->caps
.LogicalMax
;
737 wine_element
->caps
.value
.PhysicalMin
= feature
->caps
.PhysicalMin
;
738 wine_element
->caps
.value
.PhysicalMax
= feature
->caps
.PhysicalMax
;
739 if (wine_element
->caps
.value
.IsRange
)
741 wine_element
->caps
.value
.u
.Range
.UsageMin
= feature
->caps
.u
.Range
.UsageMin
;
742 wine_element
->caps
.value
.u
.Range
.UsageMax
= feature
->caps
.u
.Range
.UsageMax
;
743 wine_element
->caps
.value
.u
.Range
.StringMin
= feature
->caps
.u
.Range
.StringMin
;
744 wine_element
->caps
.value
.u
.Range
.StringMax
= feature
->caps
.u
.Range
.StringMax
;
745 wine_element
->caps
.value
.u
.Range
.DesignatorMin
= feature
->caps
.u
.Range
.DesignatorMin
;
746 wine_element
->caps
.value
.u
.Range
.DesignatorMax
= feature
->caps
.u
.Range
.DesignatorMax
;
750 wine_element
->caps
.value
.u
.NotRange
.Usage
= feature
->caps
.u
.NotRange
.Usage
[i
];
751 wine_element
->caps
.value
.u
.NotRange
.StringIndex
= feature
->caps
.u
.NotRange
.StringIndex
;
752 wine_element
->caps
.value
.u
.NotRange
.DesignatorIndex
= feature
->caps
.u
.NotRange
.DesignatorIndex
;
756 wine_report
->elementCount
++;
760 static void count_elements(struct feature
* feature
, USHORT
*buttons
, USHORT
*values
)
762 if (feature
->caps
.UsagePage
== HID_USAGE_PAGE_BUTTON
)
764 if (feature
->caps
.IsRange
)
765 *buttons
= *buttons
+ 1;
767 *buttons
= *buttons
+ feature
->caps
.usage_count
;
771 if (feature
->caps
.IsRange
)
772 *values
= *values
+ 1;
774 *values
= *values
+ feature
->caps
.usage_count
;
778 static WINE_HIDP_PREPARSED_DATA
* build_PreparseData(
779 struct feature
**features
, int feature_count
,
780 struct feature
**input_features
, int i_count
,
781 struct feature
**output_features
, int o_count
,
782 struct feature
**feature_features
, int f_count
,
783 struct collection
*base_collection
)
785 WINE_HIDP_PREPARSED_DATA
*data
;
786 WINE_HID_REPORT
*wine_report
= NULL
;
787 DWORD bitOffset
, bitLength
;
788 unsigned int report_count
= 1;
790 unsigned int element_count
;
791 unsigned int size
= 0;
793 if (features
[0]->caps
.ReportID
!= 0)
795 unsigned int *report_ids
;
796 unsigned int cnt
= max(i_count
, o_count
);
797 cnt
= max(cnt
, f_count
);
798 report_ids
= HeapAlloc(GetProcessHeap(), 0 , sizeof(*report_ids
) * cnt
);
802 report_ids
[0] = input_features
[0]->caps
.ReportID
;
803 for (i
= 1; i
< i_count
; i
++)
806 unsigned int found
= FALSE
;
807 for (j
= 0; !found
&& j
< i_count
; j
++)
809 if (report_ids
[j
] == input_features
[i
]->caps
.ReportID
)
814 report_ids
[report_count
] = input_features
[i
]->caps
.ReportID
;
822 report_ids
[0] = output_features
[0]->caps
.ReportID
;
823 for (i
= 1; i
< o_count
; i
++)
826 unsigned int found
= FALSE
;
827 for (j
= 0; !found
&& j
< o_count
; j
++)
829 if (report_ids
[j
] == output_features
[i
]->caps
.ReportID
)
834 report_ids
[report_count
] = output_features
[i
]->caps
.ReportID
;
842 report_ids
[0] = feature_features
[0]->caps
.ReportID
;
843 for (i
= 1; i
< f_count
; i
++)
846 unsigned int found
= FALSE
;
847 for (j
= 0; !found
&& j
< f_count
; j
++)
849 if (report_ids
[j
] == feature_features
[i
]->caps
.ReportID
)
854 report_ids
[report_count
] = feature_features
[i
]->caps
.ReportID
;
859 HeapFree(GetProcessHeap(), 0, report_ids
);
863 if (o_count
) report_count
++;
864 if (f_count
) report_count
++;
868 for (i
= 0; i
< feature_count
; i
++)
869 element_count
+= features
[i
]->caps
.usage_count
;
871 size
= sizeof(WINE_HIDP_PREPARSED_DATA
) +
872 (element_count
* sizeof(WINE_HID_ELEMENT
)) +
873 (report_count
* sizeof(WINE_HID_REPORT
));
875 TRACE("%i reports %i elements -> size %i\n",report_count
, element_count
, size
);
877 data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
878 data
->magic
= HID_MAGIC
;
880 data
->caps
.Usage
= base_collection
->caps
.u
.NotRange
.Usage
[0];
881 data
->caps
.UsagePage
= base_collection
->caps
.UsagePage
;
883 wine_report
= data
->InputReports
;
887 new_report(wine_report
, input_features
[0]);
888 data
->dwInputReportCount
++;
890 if (input_features
[0]->caps
.ReportID
!= 0)
895 for (i
= 0; i
< i_count
; i
++)
897 if (input_features
[i
]->caps
.ReportID
!= wine_report
->reportID
)
899 wine_report
->dwSize
+= (sizeof(WINE_HID_ELEMENT
) * wine_report
->elementCount
);
900 wine_report
= (WINE_HID_REPORT
*)(((BYTE
*)wine_report
)+wine_report
->dwSize
);
901 new_report(wine_report
, input_features
[i
]);
902 data
->dwInputReportCount
++;
903 bitLength
= max(bitOffset
, bitLength
);
904 if (input_features
[i
]->caps
.ReportID
!= 0)
909 build_elements(wine_report
, input_features
[i
], &bitOffset
);
910 count_elements(input_features
[i
], &data
->caps
.NumberInputButtonCaps
,
911 &data
->caps
.NumberInputValueCaps
);
913 wine_report
->dwSize
+= (sizeof(WINE_HID_ELEMENT
) * wine_report
->elementCount
);
914 bitLength
= max(bitOffset
, bitLength
);
915 data
->caps
.InputReportByteLength
= ((bitLength
+ 7) & ~7)/8;
921 wine_report
= (WINE_HID_REPORT
*)(((BYTE
*)wine_report
)+wine_report
->dwSize
);
922 data
->dwOutputReportOffset
= (BYTE
*)wine_report
- (BYTE
*)data
->InputReports
;
923 new_report(wine_report
, output_features
[0]);
924 data
->dwOutputReportCount
++;
925 if (output_features
[0]->caps
.ReportID
!= 0)
930 for (i
= 0; i
< o_count
; i
++)
932 if (output_features
[i
]->caps
.ReportID
!= wine_report
->reportID
)
934 wine_report
->dwSize
+= (sizeof(WINE_HID_ELEMENT
) * wine_report
->elementCount
);
935 wine_report
= (WINE_HID_REPORT
*)(((BYTE
*)wine_report
)+wine_report
->dwSize
);
936 new_report(wine_report
, output_features
[i
]);
937 data
->dwOutputReportCount
++;
938 bitLength
= max(bitOffset
, bitLength
);
939 if (output_features
[0]->caps
.ReportID
!= 0)
944 build_elements(wine_report
, output_features
[i
], &bitOffset
);
945 count_elements(output_features
[i
], &data
->caps
.NumberOutputButtonCaps
,
946 &data
->caps
.NumberOutputValueCaps
);
948 wine_report
->dwSize
+= (sizeof(WINE_HID_ELEMENT
) * wine_report
->elementCount
);
949 bitLength
= max(bitOffset
, bitLength
);
950 data
->caps
.OutputReportByteLength
= ((bitLength
+ 7) & ~7)/8;
956 wine_report
= (WINE_HID_REPORT
*)(((BYTE
*)wine_report
)+wine_report
->dwSize
);
957 data
->dwFeatureReportOffset
= (BYTE
*)wine_report
- (BYTE
*)data
->InputReports
;
958 new_report(wine_report
, feature_features
[0]);
959 data
->dwFeatureReportCount
++;
960 if (feature_features
[0]->caps
.ReportID
!= 0)
965 for (i
= 0; i
< f_count
; i
++)
967 if (feature_features
[i
]->caps
.ReportID
!= wine_report
->reportID
)
969 wine_report
->dwSize
+= (sizeof(WINE_HID_ELEMENT
) * wine_report
->elementCount
);
970 wine_report
= (WINE_HID_REPORT
*)((BYTE
*)wine_report
+wine_report
->dwSize
);
971 new_report(wine_report
, feature_features
[i
]);
972 data
->dwFeatureReportCount
++;
973 bitLength
= max(bitOffset
, bitLength
);
974 if (feature_features
[0]->caps
.ReportID
!= 0)
979 build_elements(wine_report
, feature_features
[i
], &bitOffset
);
980 count_elements(feature_features
[i
], &data
->caps
.NumberFeatureButtonCaps
,
981 &data
->caps
.NumberFeatureValueCaps
);
983 bitLength
= max(bitOffset
, bitLength
);
984 data
->caps
.FeatureReportByteLength
= ((bitLength
+ 7) & ~7)/8;
990 static void free_collection(struct collection
*collection
)
992 struct feature
*fentry
, *fnext
;
993 struct collection
*centry
, *cnext
;
994 LIST_FOR_EACH_ENTRY_SAFE(centry
, cnext
, &collection
->collections
, struct collection
, entry
)
996 list_remove(¢ry
->entry
);
997 free_collection(centry
);
999 LIST_FOR_EACH_ENTRY_SAFE(fentry
, fnext
, &collection
->features
, struct feature
, col_entry
)
1001 list_remove(&fentry
->col_entry
);
1002 HeapFree(GetProcessHeap(), 0, fentry
);
1004 HeapFree(GetProcessHeap(), 0, collection
);
1007 static int compare_reports(const void *a
, const void* b
)
1009 struct feature
*f1
= *(struct feature
**)a
;
1010 struct feature
*f2
= *(struct feature
**)b
;
1011 int c
= (f1
->caps
.ReportID
- f2
->caps
.ReportID
);
1013 return (f1
->index
- f2
->index
);
1016 WINE_HIDP_PREPARSED_DATA
* ParseDescriptor(BYTE
*descriptor
, unsigned int length
)
1018 WINE_HIDP_PREPARSED_DATA
*data
= NULL
;
1019 struct collection
*base
;
1022 struct list features
;
1024 unsigned int feature_count
= 0;
1029 TRACE("Descriptor[%i]: ", length
);
1030 for (cidx
= 0; cidx
< length
; cidx
++)
1032 TRACE("%x ",descriptor
[cidx
]);
1033 if ((cidx
+1) % 80 == 0)
1039 list_init(&features
);
1041 base
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*base
));
1043 list_init(&base
->features
);
1044 list_init(&base
->collections
);
1045 memset(&caps
, 0, sizeof(caps
));
1048 parse_descriptor(descriptor
, 0, length
, &feature_count
, &cidx
, base
, &caps
, &features
);
1050 debug_collection(base
);
1055 struct feature
*entry
;
1056 struct feature
** sorted_features
;
1057 struct feature
** input_features
;
1058 struct feature
** output_features
;
1059 struct feature
** feature_features
;
1060 unsigned int i_count
, o_count
, f_count
;
1063 i_count
= o_count
= f_count
= 0;
1065 sorted_features
= HeapAlloc(GetProcessHeap(), 0, sizeof(*sorted_features
) * feature_count
);
1066 input_features
= HeapAlloc(GetProcessHeap(), 0, sizeof(*input_features
) * feature_count
);
1067 output_features
= HeapAlloc(GetProcessHeap(), 0, sizeof(*output_features
) * feature_count
);
1068 feature_features
= HeapAlloc(GetProcessHeap(), 0, sizeof(*feature_features
) * feature_count
);
1071 LIST_FOR_EACH_ENTRY(entry
, &features
, struct feature
, entry
)
1072 sorted_features
[i
++] = entry
;
1074 /* Sort features base on report if there are multiple reports */
1075 if (sorted_features
[0]->caps
.ReportID
!= 0)
1076 qsort(sorted_features
, feature_count
, sizeof(struct feature
*), compare_reports
);
1078 for (i
= 0; i
< feature_count
; i
++)
1080 switch (sorted_features
[i
]->type
)
1083 input_features
[i_count
] = sorted_features
[i
];
1087 output_features
[o_count
] = sorted_features
[i
];
1091 feature_features
[f_count
] = sorted_features
[i
];
1095 ERR("Unknown type %i\n",sorted_features
[i
]->type
);
1101 TRACE("DUMP FEATURES:\n");
1102 TRACE("----INPUT----\n");
1103 for (cidx
= 0; cidx
< i_count
; cidx
++)
1104 debug_feature(input_features
[cidx
]);
1105 TRACE("----OUTPUT----\n");
1106 for (cidx
= 0; cidx
< o_count
; cidx
++)
1107 debug_feature(output_features
[cidx
]);
1108 TRACE("----FEATURE----\n");
1109 for (cidx
= 0; cidx
< f_count
; cidx
++)
1110 debug_feature(feature_features
[cidx
]);
1113 data
= build_PreparseData(sorted_features
, feature_count
, input_features
, i_count
, output_features
, o_count
, feature_features
, f_count
, base
);
1115 debug_print_preparsed(data
);
1117 HeapFree(GetProcessHeap(), 0, sorted_features
);
1118 HeapFree(GetProcessHeap(), 0, input_features
);
1119 HeapFree(GetProcessHeap(), 0, output_features
);
1120 HeapFree(GetProcessHeap(), 0, feature_features
);
1123 free_collection(base
);
1124 /* We do not have to free the list as free_collection does all the work */