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 void parse_io_feature(unsigned int bSize
, int itemVal
, int bTag
, unsigned int *feature_index
, struct feature
*feature
)
412 feature
->isData
= ((itemVal
& INPUT_DATA_CONST
) == 0);
413 feature
->isArray
= ((itemVal
& INPUT_ARRAY_VAR
) == 0);
414 feature
->IsAbsolute
= ((itemVal
& INPUT_ABS_REL
) == 0);
415 feature
->Wrap
= ((itemVal
& INPUT_WRAP
) != 0);
416 feature
->Linear
= ((itemVal
& INPUT_LINEAR
) == 0);
417 feature
->prefState
= ((itemVal
& INPUT_PREFSTATE
) == 0);
418 feature
->HasNull
= ((itemVal
& INPUT_NULL
) != 0);
420 if (bTag
!= TAG_MAIN_INPUT
)
422 feature
->Volatile
= ((itemVal
& INPUT_VOLATILE
) != 0);
426 feature
->BitField
= ((itemVal
& INPUT_BITFIELD
) == 0);
428 feature
->index
= *feature_index
;
429 *feature_index
= *feature_index
+ 1;
433 void parse_collection(unsigned int bSize
, int itemVal
, struct collection
*collection
)
439 collection
->type
= itemVal
;
441 if (itemVal
>= 0x07 && itemVal
<= 0x7F) {
442 ERR(" (Reserved 0x%x )\n", itemVal
);
444 else if (itemVal
>= 0x80 && itemVal
<= 0xFF) {
445 ERR(" (Vendor Defined 0x%x )\n", itemVal
);
450 static void new_caps(struct caps
*caps
)
453 caps
->IsStringRange
= 0;
454 caps
->IsDesignatorRange
= 0;
455 caps
->usage_count
= 0;
458 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
)
461 for (i
= index
; i
< length
;)
463 BYTE b0
= descriptor
[i
++];
464 int bSize
= b0
& 0x03;
465 int bType
= (b0
>> 2) & 0x03;
466 int bTag
= (b0
>> 4) & 0x0F;
468 bSize
= (bSize
== 3) ? 4 : bSize
;
469 if (bType
== TAG_TYPE_RESERVED
&& bTag
== 0x0F && bSize
== 2 &&
472 /* Long data items: Should be unused */
473 ERR("Long Data Item, should be unused\n");
481 for (j
= 0; j
< bSize
; j
++)
485 itemVal
+= descriptor
[i
+ j
] << (8 * j
);
489 TRACE(" 0x%x[%i], type %i , tag %i, size %i, val %i\n",b0
,i
-1,bType
, bTag
, bSize
, itemVal
);
491 if (bType
== TAG_TYPE_MAIN
)
493 struct feature
*feature
;
497 feature
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*feature
));
498 list_add_tail(&collection
->features
, &feature
->col_entry
);
499 list_add_tail(features
, &feature
->entry
);
500 feature
->type
= HidP_Input
;
501 parse_io_feature(bSize
, itemVal
, bTag
, feature_index
, feature
);
502 feature
->caps
= *caps
;
503 feature
->collection
= collection
;
506 case TAG_MAIN_OUTPUT
:
507 feature
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*feature
));
508 list_add_tail(&collection
->features
, &feature
->col_entry
);
509 list_add_tail(features
, &feature
->entry
);
510 feature
->type
= HidP_Output
;
511 parse_io_feature(bSize
, itemVal
, bTag
, feature_index
, feature
);
512 feature
->caps
= *caps
;
513 feature
->collection
= collection
;
516 case TAG_MAIN_FEATURE
:
517 feature
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*feature
));
518 list_add_tail(&collection
->features
, &feature
->col_entry
);
519 list_add_tail(features
, &feature
->entry
);
520 feature
->type
= HidP_Feature
;
521 parse_io_feature(bSize
, itemVal
, bTag
, feature_index
, feature
);
522 feature
->caps
= *caps
;
523 feature
->collection
= collection
;
526 case TAG_MAIN_COLLECTION
:
528 struct collection
*subcollection
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct collection
));
529 list_add_tail(&collection
->collections
, &subcollection
->entry
);
530 subcollection
->parent
= collection
;
531 /* Only set our collection once...
532 We do not properly handle composite devices yet. */
533 if (*collection_index
== 0)
534 collection
->caps
= *caps
;
535 subcollection
->caps
= *caps
;
536 subcollection
->index
= *collection_index
;
537 *collection_index
= *collection_index
+ 1;
538 list_init(&subcollection
->features
);
539 list_init(&subcollection
->collections
);
542 parse_collection(bSize
, itemVal
, subcollection
);
544 i
= parse_descriptor(descriptor
, i
+1, length
, feature_index
, collection_index
, subcollection
, caps
, features
);
547 case TAG_MAIN_END_COLLECTION
:
550 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag
, bType
);
553 else if (bType
== TAG_TYPE_GLOBAL
)
557 case TAG_GLOBAL_USAGE_PAGE
:
558 caps
->UsagePage
= getValue(bSize
, itemVal
);
560 case TAG_GLOBAL_LOGICAL_MINIMUM
:
561 caps
->LogicalMin
= getValue(bSize
, itemVal
);
563 case TAG_GLOBAL_LOGICAL_MAXIMUM
:
564 caps
->LogicalMax
= getValue(bSize
, itemVal
);
566 case TAG_GLOBAL_PHYSICAL_MINIMUM
:
567 caps
->PhysicalMin
= getValue(bSize
, itemVal
);
569 case TAG_GLOBAL_PHYSICAL_MAXIMUM
:
570 caps
->PhysicalMax
= getValue(bSize
, itemVal
);
572 case TAG_GLOBAL_UNIT_EXPONENT
:
573 caps
->UnitsExp
= getValue(bSize
, itemVal
);
575 case TAG_GLOBAL_UNIT
:
576 caps
->Units
= getValue(bSize
, itemVal
);
578 case TAG_GLOBAL_REPORT_SIZE
:
579 caps
->BitSize
= getValue(bSize
, itemVal
);
581 case TAG_GLOBAL_REPORT_ID
:
582 caps
->ReportID
= getValue(bSize
, itemVal
);
584 case TAG_GLOBAL_REPORT_COUNT
:
585 caps
->ReportCount
= getValue(bSize
, itemVal
);
587 case TAG_GLOBAL_PUSH
:
588 FIXME("Unhandled Push\n");
591 FIXME("Unhandled Pop\n");
594 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag
, bType
);
597 else if (bType
== TAG_TYPE_LOCAL
)
601 case TAG_LOCAL_USAGE
:
602 if (caps
->usage_count
>= USAGE_MAX
)
603 FIXME("More than %i individual usages defined\n",USAGE_MAX
);
606 caps
->u
.NotRange
.Usage
[caps
->usage_count
++] = getValue(bSize
, itemVal
);
607 caps
->IsRange
= FALSE
;
610 case TAG_LOCAL_USAGE_MINIMUM
:
611 caps
->usage_count
= 1;
612 caps
->u
.Range
.UsageMin
= getValue(bSize
, itemVal
);
613 caps
->IsRange
= TRUE
;
615 case TAG_LOCAL_USAGE_MAXIMUM
:
616 caps
->usage_count
= 1;
617 caps
->u
.Range
.UsageMax
= getValue(bSize
, itemVal
);
618 caps
->IsRange
= TRUE
;
620 case TAG_LOCAL_DESIGNATOR_INDEX
:
621 caps
->u
.NotRange
.DesignatorIndex
= getValue(bSize
, itemVal
);
622 caps
->IsDesignatorRange
= FALSE
;
624 case TAG_LOCAL_DESIGNATOR_MINIMUM
:
625 caps
->u
.Range
.DesignatorMin
= getValue(bSize
, itemVal
);
626 caps
->IsDesignatorRange
= TRUE
;
628 case TAG_LOCAL_DESIGNATOR_MAXIMUM
:
629 caps
->u
.Range
.DesignatorMax
= getValue(bSize
, itemVal
);
630 caps
->IsDesignatorRange
= TRUE
;
632 case TAG_LOCAL_STRING_INDEX
:
633 caps
->u
.NotRange
.StringIndex
= getValue(bSize
, itemVal
);
634 caps
->IsStringRange
= FALSE
;
636 case TAG_LOCAL_STRING_MINIMUM
:
637 caps
->u
.Range
.StringMin
= getValue(bSize
, itemVal
);
638 caps
->IsStringRange
= TRUE
;
640 case TAG_LOCAL_STRING_MAXIMUM
:
641 caps
->u
.Range
.StringMax
= getValue(bSize
, itemVal
);
642 caps
->IsStringRange
= TRUE
;
644 case TAG_LOCAL_DELIMITER
:
645 caps
->Delim
= getValue(bSize
, itemVal
);
648 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag
, bType
);
652 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag
, bType
);
660 static inline void new_report(WINE_HID_REPORT
*wine_report
, struct feature
* feature
)
662 wine_report
->reportID
= feature
->caps
.ReportID
;
663 wine_report
->dwSize
= sizeof(*wine_report
) - sizeof(WINE_HID_ELEMENT
);
664 wine_report
->elementCount
= 0;
667 static void build_elements(WINE_HID_REPORT
*wine_report
, struct feature
* feature
, DWORD
*bitOffset
)
671 if (!feature
->isData
)
673 *bitOffset
= *bitOffset
+ (feature
->caps
.BitSize
* feature
->caps
.ReportCount
);
677 for (i
= 0; i
< feature
->caps
.usage_count
; i
++)
679 WINE_HID_ELEMENT
*wine_element
= &wine_report
->Elements
[wine_report
->elementCount
];
681 wine_element
->valueStartBit
= *bitOffset
;
682 if (feature
->caps
.UsagePage
== HID_USAGE_PAGE_BUTTON
)
684 wine_element
->ElementType
= ButtonElement
;
685 wine_element
->caps
.button
.UsagePage
= feature
->caps
.UsagePage
;
686 wine_element
->caps
.button
.ReportID
= feature
->caps
.ReportID
;
687 wine_element
->caps
.button
.BitField
= feature
->BitField
;
688 wine_element
->caps
.button
.IsRange
= feature
->caps
.IsRange
;
689 wine_element
->caps
.button
.IsStringRange
= feature
->caps
.IsStringRange
;
690 wine_element
->caps
.button
.IsDesignatorRange
= feature
->caps
.IsDesignatorRange
;
691 wine_element
->caps
.button
.IsAbsolute
= feature
->IsAbsolute
;
692 if (wine_element
->caps
.button
.IsRange
)
694 wine_element
->bitCount
= (feature
->caps
.u
.Range
.UsageMax
- feature
->caps
.u
.Range
.UsageMin
) + 1;
695 *bitOffset
= *bitOffset
+ wine_element
->bitCount
;
696 wine_element
->caps
.button
.u
.Range
.UsageMin
= feature
->caps
.u
.Range
.UsageMin
;
697 wine_element
->caps
.button
.u
.Range
.UsageMax
= feature
->caps
.u
.Range
.UsageMax
;
698 wine_element
->caps
.button
.u
.Range
.StringMin
= feature
->caps
.u
.Range
.StringMin
;
699 wine_element
->caps
.button
.u
.Range
.StringMax
= feature
->caps
.u
.Range
.StringMax
;
700 wine_element
->caps
.button
.u
.Range
.DesignatorMin
= feature
->caps
.u
.Range
.DesignatorMin
;
701 wine_element
->caps
.button
.u
.Range
.DesignatorMax
= feature
->caps
.u
.Range
.DesignatorMax
;
705 *bitOffset
= *bitOffset
+ 1;
706 wine_element
->bitCount
= 1;
707 wine_element
->caps
.button
.u
.NotRange
.Usage
= feature
->caps
.u
.NotRange
.Usage
[i
];
708 wine_element
->caps
.button
.u
.NotRange
.StringIndex
= feature
->caps
.u
.NotRange
.StringIndex
;
709 wine_element
->caps
.button
.u
.NotRange
.DesignatorIndex
= feature
->caps
.u
.NotRange
.DesignatorIndex
;
714 wine_element
->ElementType
= ValueElement
;
715 wine_element
->caps
.value
.UsagePage
= feature
->caps
.UsagePage
;
716 wine_element
->caps
.value
.ReportID
= feature
->caps
.ReportID
;
717 wine_element
->caps
.value
.BitField
= feature
->BitField
;
718 wine_element
->caps
.value
.IsRange
= feature
->caps
.IsRange
;
719 wine_element
->caps
.value
.IsStringRange
= feature
->caps
.IsStringRange
;
720 wine_element
->caps
.value
.IsDesignatorRange
= feature
->caps
.IsDesignatorRange
;
721 wine_element
->caps
.value
.IsAbsolute
= feature
->IsAbsolute
;
722 wine_element
->caps
.value
.HasNull
= feature
->HasNull
;
723 wine_element
->caps
.value
.BitSize
= feature
->caps
.BitSize
;
724 if (feature
->caps
.usage_count
> 1)
725 wine_element
->caps
.value
.ReportCount
= 1;
727 wine_element
->caps
.value
.ReportCount
= feature
->caps
.ReportCount
;
728 wine_element
->bitCount
= (feature
->caps
.BitSize
* wine_element
->caps
.value
.ReportCount
);
729 *bitOffset
= *bitOffset
+ wine_element
->bitCount
;
730 wine_element
->caps
.value
.UnitsExp
= feature
->caps
.UnitsExp
;
731 wine_element
->caps
.value
.Units
= feature
->caps
.Units
;
732 wine_element
->caps
.value
.LogicalMin
= feature
->caps
.LogicalMin
;
733 wine_element
->caps
.value
.LogicalMax
= feature
->caps
.LogicalMax
;
734 wine_element
->caps
.value
.PhysicalMin
= feature
->caps
.PhysicalMin
;
735 wine_element
->caps
.value
.PhysicalMax
= feature
->caps
.PhysicalMax
;
736 if (wine_element
->caps
.value
.IsRange
)
738 wine_element
->caps
.value
.u
.Range
.UsageMin
= feature
->caps
.u
.Range
.UsageMin
;
739 wine_element
->caps
.value
.u
.Range
.UsageMax
= feature
->caps
.u
.Range
.UsageMax
;
740 wine_element
->caps
.value
.u
.Range
.StringMin
= feature
->caps
.u
.Range
.StringMin
;
741 wine_element
->caps
.value
.u
.Range
.StringMax
= feature
->caps
.u
.Range
.StringMax
;
742 wine_element
->caps
.value
.u
.Range
.DesignatorMin
= feature
->caps
.u
.Range
.DesignatorMin
;
743 wine_element
->caps
.value
.u
.Range
.DesignatorMax
= feature
->caps
.u
.Range
.DesignatorMax
;
747 wine_element
->caps
.value
.u
.NotRange
.Usage
= feature
->caps
.u
.NotRange
.Usage
[i
];
748 wine_element
->caps
.value
.u
.NotRange
.StringIndex
= feature
->caps
.u
.NotRange
.StringIndex
;
749 wine_element
->caps
.value
.u
.NotRange
.DesignatorIndex
= feature
->caps
.u
.NotRange
.DesignatorIndex
;
753 wine_report
->elementCount
++;
757 static void count_elements(struct feature
* feature
, USHORT
*buttons
, USHORT
*values
)
759 if (feature
->caps
.UsagePage
== HID_USAGE_PAGE_BUTTON
)
761 if (feature
->caps
.IsRange
)
762 *buttons
= *buttons
+ 1;
764 *buttons
= *buttons
+ feature
->caps
.usage_count
;
768 if (feature
->caps
.IsRange
)
769 *values
= *values
+ 1;
771 *values
= *values
+ feature
->caps
.usage_count
;
775 WINE_HIDP_PREPARSED_DATA
* build_PreparseData(
776 struct feature
**features
, int feature_count
,
777 struct feature
**input_features
, int i_count
,
778 struct feature
**output_features
, int o_count
,
779 struct feature
**feature_features
, int f_count
,
780 struct collection
*base_collection
)
782 WINE_HIDP_PREPARSED_DATA
*data
;
783 WINE_HID_REPORT
*wine_report
= NULL
;
784 DWORD bitOffset
, bitLength
;
785 unsigned int report_count
= 1;
787 unsigned int element_count
;
788 unsigned int size
= 0;
790 if (features
[0]->caps
.ReportID
!= 0)
792 unsigned int *report_ids
;
793 unsigned int cnt
= max(i_count
, o_count
);
794 cnt
= max(cnt
, f_count
);
795 report_ids
= HeapAlloc(GetProcessHeap(), 0 , sizeof(*report_ids
) * cnt
);
799 report_ids
[0] = input_features
[0]->caps
.ReportID
;
800 for (i
= 1; i
< i_count
; i
++)
803 unsigned int found
= FALSE
;
804 for (j
= 0; !found
&& j
< i_count
; j
++)
806 if (report_ids
[j
] == input_features
[i
]->caps
.ReportID
)
811 report_ids
[report_count
] = input_features
[i
]->caps
.ReportID
;
819 report_ids
[0] = output_features
[0]->caps
.ReportID
;
820 for (i
= 1; i
< o_count
; i
++)
823 unsigned int found
= FALSE
;
824 for (j
= 0; !found
&& j
< o_count
; j
++)
826 if (report_ids
[j
] == output_features
[i
]->caps
.ReportID
)
831 report_ids
[report_count
] = output_features
[i
]->caps
.ReportID
;
839 report_ids
[0] = feature_features
[0]->caps
.ReportID
;
840 for (i
= 1; i
< f_count
; i
++)
843 unsigned int found
= FALSE
;
844 for (j
= 0; !found
&& j
< f_count
; j
++)
846 if (report_ids
[j
] == feature_features
[i
]->caps
.ReportID
)
851 report_ids
[report_count
] = feature_features
[i
]->caps
.ReportID
;
856 HeapFree(GetProcessHeap(), 0, report_ids
);
860 if (o_count
) report_count
++;
861 if (f_count
) report_count
++;
865 for (i
= 0; i
< feature_count
; i
++)
866 element_count
+= features
[i
]->caps
.usage_count
;
868 size
= sizeof(WINE_HIDP_PREPARSED_DATA
) +
869 (element_count
* sizeof(WINE_HID_ELEMENT
)) +
870 (report_count
* sizeof(WINE_HID_REPORT
));
872 TRACE("%i reports %i elements -> size %i\n",report_count
, element_count
, size
);
874 data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
875 data
->magic
= HID_MAGIC
;
877 data
->caps
.Usage
= base_collection
->caps
.u
.NotRange
.Usage
[0];
878 data
->caps
.UsagePage
= base_collection
->caps
.UsagePage
;
880 wine_report
= data
->InputReports
;
884 new_report(wine_report
, input_features
[0]);
885 data
->dwInputReportCount
++;
887 if (input_features
[0]->caps
.ReportID
!= 0)
892 for (i
= 0; i
< i_count
; i
++)
894 if (input_features
[i
]->caps
.ReportID
!= wine_report
->reportID
)
896 wine_report
->dwSize
+= (sizeof(WINE_HID_ELEMENT
) * wine_report
->elementCount
);
897 wine_report
= (WINE_HID_REPORT
*)(((BYTE
*)wine_report
)+wine_report
->dwSize
);
898 new_report(wine_report
, input_features
[i
]);
899 data
->dwInputReportCount
++;
900 bitLength
= max(bitOffset
, bitLength
);
901 if (input_features
[i
]->caps
.ReportID
!= 0)
906 build_elements(wine_report
, input_features
[i
], &bitOffset
);
907 count_elements(input_features
[i
], &data
->caps
.NumberInputButtonCaps
,
908 &data
->caps
.NumberInputValueCaps
);
910 wine_report
->dwSize
+= (sizeof(WINE_HID_ELEMENT
) * wine_report
->elementCount
);
911 bitLength
= max(bitOffset
, bitLength
);
912 data
->caps
.InputReportByteLength
= ((bitLength
+ 7) & ~7)/8;
918 wine_report
= (WINE_HID_REPORT
*)(((BYTE
*)wine_report
)+wine_report
->dwSize
);
919 data
->dwOutputReportOffset
= (BYTE
*)wine_report
- (BYTE
*)data
->InputReports
;
920 new_report(wine_report
, output_features
[0]);
921 data
->dwOutputReportCount
++;
922 if (output_features
[0]->caps
.ReportID
!= 0)
927 for (i
= 0; i
< o_count
; i
++)
929 if (output_features
[i
]->caps
.ReportID
!= wine_report
->reportID
)
931 wine_report
->dwSize
+= (sizeof(WINE_HID_ELEMENT
) * wine_report
->elementCount
);
932 wine_report
= (WINE_HID_REPORT
*)(((BYTE
*)wine_report
)+wine_report
->dwSize
);
933 new_report(wine_report
, output_features
[i
]);
934 data
->dwOutputReportCount
++;
935 bitLength
= max(bitOffset
, bitLength
);
936 if (output_features
[0]->caps
.ReportID
!= 0)
941 build_elements(wine_report
, output_features
[i
], &bitOffset
);
942 count_elements(output_features
[i
], &data
->caps
.NumberOutputButtonCaps
,
943 &data
->caps
.NumberOutputValueCaps
);
945 wine_report
->dwSize
+= (sizeof(WINE_HID_ELEMENT
) * wine_report
->elementCount
);
946 bitLength
= max(bitOffset
, bitLength
);
947 data
->caps
.OutputReportByteLength
= ((bitLength
+ 7) & ~7)/8;
953 wine_report
= (WINE_HID_REPORT
*)(((BYTE
*)wine_report
)+wine_report
->dwSize
);
954 data
->dwFeatureReportOffset
= (BYTE
*)wine_report
- (BYTE
*)data
->InputReports
;
955 new_report(wine_report
, feature_features
[0]);
956 data
->dwFeatureReportCount
++;
957 if (feature_features
[0]->caps
.ReportID
!= 0)
962 for (i
= 0; i
< f_count
; i
++)
964 if (feature_features
[i
]->caps
.ReportID
!= wine_report
->reportID
)
966 wine_report
->dwSize
+= (sizeof(WINE_HID_ELEMENT
) * wine_report
->elementCount
);
967 wine_report
= (WINE_HID_REPORT
*)((BYTE
*)wine_report
)+wine_report
->dwSize
;
968 new_report(wine_report
, feature_features
[i
]);
969 data
->dwFeatureReportCount
++;
970 bitLength
= max(bitOffset
, bitLength
);
971 if (feature_features
[0]->caps
.ReportID
!= 0)
976 build_elements(wine_report
, feature_features
[i
], &bitOffset
);
977 count_elements(feature_features
[i
], &data
->caps
.NumberFeatureButtonCaps
,
978 &data
->caps
.NumberFeatureValueCaps
);
980 bitLength
= max(bitOffset
, bitLength
);
981 data
->caps
.FeatureReportByteLength
= ((bitLength
+ 7) & ~7)/8;
987 static void free_collection(struct collection
*collection
)
989 struct feature
*fentry
, *fnext
;
990 struct collection
*centry
, *cnext
;
991 LIST_FOR_EACH_ENTRY_SAFE(centry
, cnext
, &collection
->collections
, struct collection
, entry
)
993 list_remove(¢ry
->entry
);
994 free_collection(centry
);
996 LIST_FOR_EACH_ENTRY_SAFE(fentry
, fnext
, &collection
->features
, struct feature
, col_entry
)
998 list_remove(&fentry
->col_entry
);
999 HeapFree(GetProcessHeap(), 0, fentry
);
1001 HeapFree(GetProcessHeap(), 0, collection
);
1004 static int compare_reports(const void *a
, const void* b
)
1006 struct feature
*f1
= *(struct feature
**)a
;
1007 struct feature
*f2
= *(struct feature
**)b
;
1008 int c
= (f1
->caps
.ReportID
- f2
->caps
.ReportID
);
1010 return (f1
->index
- f2
->index
);
1013 WINE_HIDP_PREPARSED_DATA
* ParseDescriptor(BYTE
*descriptor
, unsigned int length
)
1015 WINE_HIDP_PREPARSED_DATA
*data
= NULL
;
1016 struct collection
*base
;
1019 struct list features
;
1021 unsigned int feature_count
= 0;
1026 TRACE("Descriptor[%i]: ", length
);
1027 for (cidx
= 0; cidx
< length
; cidx
++)
1028 TRACE("%x ",descriptor
[cidx
]);
1032 list_init(&features
);
1034 base
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*base
));
1036 list_init(&base
->features
);
1037 list_init(&base
->collections
);
1038 memset(&caps
, 0, sizeof(caps
));
1041 parse_descriptor(descriptor
, 0, length
, &feature_count
, &cidx
, base
, &caps
, &features
);
1043 debug_collection(base
);
1048 struct feature
*entry
;
1049 struct feature
** sorted_features
;
1050 struct feature
** input_features
;
1051 struct feature
** output_features
;
1052 struct feature
** feature_features
;
1053 unsigned int i_count
, o_count
, f_count
;
1056 i_count
= o_count
= f_count
= 0;
1058 sorted_features
= HeapAlloc(GetProcessHeap(), 0, sizeof(*sorted_features
) * feature_count
);
1059 input_features
= HeapAlloc(GetProcessHeap(), 0, sizeof(*input_features
) * feature_count
);
1060 output_features
= HeapAlloc(GetProcessHeap(), 0, sizeof(*output_features
) * feature_count
);
1061 feature_features
= HeapAlloc(GetProcessHeap(), 0, sizeof(*feature_features
) * feature_count
);
1064 LIST_FOR_EACH_ENTRY(entry
, &features
, struct feature
, entry
)
1065 sorted_features
[i
++] = entry
;
1067 /* Sort features base on report if there are multiple reports */
1068 if (sorted_features
[0]->caps
.ReportID
!= 0)
1069 qsort(sorted_features
, feature_count
, sizeof(struct feature
*), compare_reports
);
1071 for (i
= 0; i
< feature_count
; i
++)
1073 switch (sorted_features
[i
]->type
)
1076 input_features
[i_count
] = sorted_features
[i
];
1080 output_features
[o_count
] = sorted_features
[i
];
1084 feature_features
[f_count
] = sorted_features
[i
];
1088 ERR("Unknown type %i\n",sorted_features
[i
]->type
);
1094 TRACE("DUMP FEATURES:\n");
1095 TRACE("----INPUT----\n");
1096 for (cidx
= 0; cidx
< i_count
; cidx
++)
1097 debug_feature(input_features
[cidx
]);
1098 TRACE("----OUTPUT----\n");
1099 for (cidx
= 0; cidx
< o_count
; cidx
++)
1100 debug_feature(output_features
[cidx
]);
1101 TRACE("----FEATURE----\n");
1102 for (cidx
= 0; cidx
< f_count
; cidx
++)
1103 debug_feature(feature_features
[cidx
]);
1106 data
= build_PreparseData(sorted_features
, feature_count
, input_features
, i_count
, output_features
, o_count
, feature_features
, f_count
, base
);
1108 debug_print_preparsed(data
);
1110 HeapFree(GetProcessHeap(), 0, sorted_features
);
1111 HeapFree(GetProcessHeap(), 0, input_features
);
1112 HeapFree(GetProcessHeap(), 0, output_features
);
1113 HeapFree(GetProcessHeap(), 0, feature_features
);
1116 free_collection(base
);
1117 /* We do not have to free the list as free_collection does all the work */