d3d11/tests: Port test_create_rasterizer_state() from d3d10core.
[wine/multimedia.git] / dlls / hidclass.sys / descriptor.c
blob6f8e45ef5d33384ce41cb95f33e943ff7e4dd2f4
1 /*
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
21 #include "config.h"
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #define NONAMELESSUNION
27 #include "hid.h"
29 #include "wine/debug.h"
30 #include "wine/list.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(hid);
34 #define USAGE_MAX 10
36 enum {
37 INPUT_DATA = 0x01,
38 INPUT_ARRAY = 0x02,
39 INPUT_ABS = 0x04,
40 INPUT_WRAP = 0x08,
41 INPUT_LINEAR = 0x10,
42 INPUT_PREFSTATE = 0x20,
43 INPUT_NULL = 0x40,
44 INPUT_VOLATILE = 0x80,
45 INPUT_BITFIELD = 0x100
48 enum {
49 TAG_TYPE_MAIN = 0x0,
50 TAG_TYPE_GLOBAL,
51 TAG_TYPE_LOCAL,
52 TAG_TYPE_RESERVED,
55 enum {
56 TAG_MAIN_INPUT = 0x08,
57 TAG_MAIN_OUTPUT = 0x09,
58 TAG_MAIN_FEATURE = 0x0B,
59 TAG_MAIN_COLLECTION = 0x0A,
60 TAG_MAIN_END_COLLECTION = 0x0C
63 enum {
64 TAG_GLOBAL_USAGE_PAGE = 0x0,
65 TAG_GLOBAL_LOGICAL_MINIMUM,
66 TAG_GLOBAL_LOGICAL_MAXIMUM,
67 TAG_GLOBAL_PHYSICAL_MINIMUM,
68 TAG_GLOBAL_PHYSICAL_MAXIMUM,
69 TAG_GLOBAL_UNIT_EXPONENT,
70 TAG_GLOBAL_UNIT,
71 TAG_GLOBAL_REPORT_SIZE,
72 TAG_GLOBAL_REPORT_ID,
73 TAG_GLOBAL_REPORT_COUNT,
74 TAG_GLOBAL_PUSH,
75 TAG_GLOBAL_POP
78 enum {
79 TAG_LOCAL_USAGE = 0x0,
80 TAG_LOCAL_USAGE_MINIMUM,
81 TAG_LOCAL_USAGE_MAXIMUM,
82 TAG_LOCAL_DESIGNATOR_INDEX,
83 TAG_LOCAL_DESIGNATOR_MINIMUM,
84 TAG_LOCAL_DESIGNATOR_MAXIMUM,
85 TAG_LOCAL_STRING_INDEX,
86 TAG_LOCAL_STRING_MINIMUM,
87 TAG_LOCAL_STRING_MAXIMUM,
88 TAG_LOCAL_DELIMITER
92 static const char* const feature_string[] =
93 { "Input", "Output", "Feature" };
95 struct caps {
96 USAGE UsagePage;
97 LONG LogicalMin;
98 LONG LogicalMax;
99 LONG PhysicalMin;
100 LONG PhysicalMax;
101 ULONG UnitsExp;
102 ULONG Units;
103 USHORT BitSize;
104 UCHAR ReportID;
105 USHORT ReportCount;
107 BOOLEAN IsRange;
108 BOOLEAN IsStringRange;
109 BOOLEAN IsDesignatorRange;
110 unsigned int usage_count;
111 union {
112 struct {
113 USAGE UsageMin;
114 USAGE UsageMax;
115 USHORT StringMin;
116 USHORT StringMax;
117 USHORT DesignatorMin;
118 USHORT DesignatorMax;
119 } Range;
120 struct {
121 USAGE Usage[USAGE_MAX];
122 USAGE Reserved1;
123 USHORT StringIndex;
124 USHORT Reserved2;
125 USHORT DesignatorIndex;
126 USHORT Reserved3;
127 } NotRange;
128 } DUMMYUNIONNAME;
130 int Delim;
133 struct feature {
134 struct list entry;
135 struct list col_entry;
136 struct caps caps;
138 HIDP_REPORT_TYPE type;
139 BOOLEAN isData;
140 BOOLEAN isArray;
141 BOOLEAN IsAbsolute;
142 BOOLEAN Wrap;
143 BOOLEAN Linear;
144 BOOLEAN prefState;
145 BOOLEAN HasNull;
146 BOOLEAN Volatile;
147 BOOLEAN BitField;
149 unsigned int index;
150 struct collection *collection;
153 static const char* const collection_string[] = {
154 "Physical",
155 "Application",
156 "Logical",
157 "Report",
158 "Named Array",
159 "Usage Switch",
160 "Usage Modifier",
163 struct collection {
164 struct list entry;
165 struct caps caps;
166 unsigned int index;
167 unsigned int type;
168 struct collection *parent;
169 struct list features;
170 struct list collections;
173 static const char* debugstr_usages(struct caps *caps)
175 if (!caps->IsRange)
177 char out[12 * USAGE_MAX];
178 unsigned int i;
179 if (caps->usage_count == 0)
180 return "[ none ]";
181 out[0] = 0;
182 for (i = 0; i < caps->usage_count; i++)
183 sprintf(out + strlen(out), "0x%x ", caps->u.NotRange.Usage[i]);
184 return wine_dbg_sprintf("[ %s] ", out);
186 else
187 return wine_dbg_sprintf("[0x%x - 0x%x]", caps->u.Range.UsageMin, caps->u.Range.UsageMax);
190 static const char* debugstr_stringindex(struct caps *caps)
192 if (!caps->IsStringRange)
193 return wine_dbg_sprintf("%i", caps->u.NotRange.StringIndex);
194 else
195 return wine_dbg_sprintf("[%i - %i]", caps->u.Range.StringMin, caps->u.Range.StringMax);
198 static const char* debugstr_designatorindex(struct caps *caps)
200 if (!caps->IsDesignatorRange)
201 return wine_dbg_sprintf("%i", caps->u.NotRange.DesignatorIndex);
202 else
203 return wine_dbg_sprintf("[%i - %i]", caps->u.Range.DesignatorMin, caps->u.Range.DesignatorMax);
206 static void debugstr_caps(const char* type, struct caps *caps)
208 if (!caps)
209 return;
210 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",
211 type,
212 caps->UsagePage,
213 caps->LogicalMin,
214 caps->LogicalMax,
215 caps->PhysicalMin,
216 caps->PhysicalMax,
217 caps->UnitsExp,
218 caps->Units,
219 caps->BitSize,
220 caps->ReportID,
221 caps->ReportCount,
222 debugstr_usages(caps),
223 debugstr_stringindex(caps),
224 debugstr_designatorindex(caps),
225 caps->Delim);
228 static void debug_feature(struct feature *feature)
230 if (!feature)
231 return;
232 TRACE("[Feature type %s [%i]; %s; %s; %s; %s; %s; %s; %s; %s; %s]\n",
233 feature_string[feature->type],
234 feature->index,
235 (feature->isData)?"Data":"Const",
236 (feature->isArray)?"Array":"Var",
237 (feature->IsAbsolute)?"Abs":"Rel",
238 (feature->Wrap)?"Wrap":"NoWrap",
239 (feature->Linear)?"Linear":"NonLinear",
240 (feature->prefState)?"PrefStat":"NoPrefState",
241 (feature->HasNull)?"HasNull":"NoNull",
242 (feature->Volatile)?"Volatile":"NonVolatile",
243 (feature->BitField)?"BitField":"Buffered");
245 debugstr_caps("Feature", &feature->caps);
248 static void debug_collection(struct collection *collection)
250 struct feature *fentry;
251 struct collection *centry;
252 if (TRACE_ON(hid))
254 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));
255 debugstr_caps("Collection", &collection->caps);
256 LIST_FOR_EACH_ENTRY(fentry, &collection->features, struct feature, col_entry)
257 debug_feature(fentry);
258 LIST_FOR_EACH_ENTRY(centry, &collection->collections, struct collection, entry)
259 debug_collection(centry);
260 TRACE(">>> END Collection %i\n", collection->index);
264 static void debug_print_button_cap(const CHAR * type, WINE_HID_ELEMENT *wine_element)
266 if (!wine_element->caps.button.IsRange)
267 TRACE("%s Button: 0x%x/0x%04x: ReportId %i, startBit %i/1\n" , type,
268 wine_element->caps.button.UsagePage,
269 wine_element->caps.button.u.NotRange.Usage,
270 wine_element->caps.value.ReportID,
271 wine_element->valueStartBit);
272 else
273 TRACE("%s Button: 0x%x/[0x%04x-0x%04x]: ReportId %i, startBit %i/%i\n" ,type,
274 wine_element->caps.button.UsagePage,
275 wine_element->caps.button.u.Range.UsageMin,
276 wine_element->caps.button.u.Range.UsageMax,
277 wine_element->caps.value.ReportID,
278 wine_element->valueStartBit,
279 wine_element->bitCount);
282 static void debug_print_value_cap(const CHAR * type, WINE_HID_ELEMENT *wine_element)
284 TRACE("%s Value: 0x%x/0x%x: ReportId %i, IsAbsolute %i, HasNull %i, "
285 "Bit Size %i, ReportCount %i, UnitsExp %i, Units %i, "
286 "LogicalMin %i, Logical Max %i, PhysicalMin %i, "
287 "PhysicalMax %i -- StartBit %i/%i\n", type,
288 wine_element->caps.value.UsagePage,
289 wine_element->caps.value.u.NotRange.Usage,
290 wine_element->caps.value.ReportID,
291 wine_element->caps.value.IsAbsolute,
292 wine_element->caps.value.HasNull,
293 wine_element->caps.value.BitSize,
294 wine_element->caps.value.ReportCount,
295 wine_element->caps.value.UnitsExp,
296 wine_element->caps.value.Units,
297 wine_element->caps.value.LogicalMin,
298 wine_element->caps.value.LogicalMax,
299 wine_element->caps.value.PhysicalMin,
300 wine_element->caps.value.PhysicalMax,
301 wine_element->valueStartBit,
302 wine_element->bitCount);
305 static void debug_print_element(const CHAR* type, WINE_HID_ELEMENT *wine_element)
307 if (wine_element->ElementType == ButtonElement)
308 debug_print_button_cap(type, wine_element);
309 else if (wine_element->ElementType == ValueElement)
310 debug_print_value_cap(type, wine_element);
311 else
312 TRACE("%s: UNKNOWN\n", type);
315 static void debug_print_report(const char* type, WINE_HID_REPORT *report)
317 unsigned int i;
318 TRACE("START Report %i <<< %s report : dwSize: %i elementCount: %i\n",
319 report->reportID,
320 type,
321 report->dwSize,
322 report->elementCount);
323 for (i = 0; i < report->elementCount; i++)
324 debug_print_element(type, &report->Elements[i]);
325 TRACE(">>> END Report %i\n",report->reportID);
328 static void debug_print_preparsed(WINE_HIDP_PREPARSED_DATA *data)
330 unsigned int i;
331 WINE_HID_REPORT *r;
332 if (TRACE_ON(hid))
334 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",
335 data->dwSize,
336 data->caps.Usage,
337 data->caps.UsagePage,
338 data->caps.InputReportByteLength,
339 data->caps.OutputReportByteLength,
340 data->caps.FeatureReportByteLength,
341 data->caps.NumberLinkCollectionNodes,
342 data->caps.NumberInputButtonCaps,
343 data->caps.NumberInputValueCaps,
344 data->caps.NumberInputDataIndices,
345 data->caps.NumberOutputButtonCaps,
346 data->caps.NumberOutputValueCaps,
347 data->caps.NumberOutputDataIndices,
348 data->caps.NumberFeatureButtonCaps,
349 data->caps.NumberFeatureValueCaps,
350 data->caps.NumberFeatureDataIndices,
351 data->dwInputReportCount,
352 data->dwOutputReportCount,
353 data->dwFeatureReportCount,
354 data->dwOutputReportOffset,
355 data->dwFeatureReportOffset);
357 r = HID_INPUT_REPORTS(data);
358 for (i = 0; i < data->dwInputReportCount; i++)
360 debug_print_report("INPUT", r);
361 r = HID_NEXT_REPORT(data, r);
363 r = HID_OUTPUT_REPORTS(data);
364 for (i = 0; i < data->dwOutputReportCount; i++)
366 debug_print_report("OUTPUT", r);
367 r = HID_NEXT_REPORT(data, r);
369 r = HID_FEATURE_REPORTS(data);
370 for (i = 0; i < data->dwFeatureReportCount; i++)
372 debug_print_report("FEATURE", r);
373 r = HID_NEXT_REPORT(data, r);
375 TRACE(">>> END Preparsed Data\n");
379 static int getValue(int bsize, int source)
381 int mask = 0xff;
382 int negative = 0x80;
383 int outofrange = 0x100;
384 int value;
385 unsigned int i;
387 if (bsize == 4)
388 return source;
390 for (i = 1; i < bsize; i++)
392 mask = (mask<<8) + 0xff;
393 negative = (negative<<8);
394 outofrange = (outofrange<<8);
396 value = (source&mask);
397 if (value&negative)
398 value = -1 * (outofrange - value);
399 return value;
402 void parse_io_feature(unsigned int bSize, int itemVal, int bTag, unsigned int *feature_index, struct feature *feature)
404 if (bSize <= 0)
406 return;
408 else
410 if ((itemVal & INPUT_DATA) == 0)
411 feature->isData = TRUE;
412 else
413 feature->isData = FALSE; /* Const */
414 if ((itemVal & INPUT_ARRAY) == 0)
415 feature->isArray= TRUE;
416 else
417 feature->isArray= TRUE; /* Var */
418 if ((itemVal & INPUT_ABS) == 0)
419 feature->IsAbsolute = TRUE;
420 else
421 feature->IsAbsolute = FALSE; /* Rel */
422 if ((itemVal & INPUT_WRAP) == 0)
423 feature->Wrap = FALSE;
424 else
425 feature->Wrap = TRUE;
426 if ((itemVal & INPUT_LINEAR) == 0)
427 feature->Linear = TRUE;
428 else
429 feature->Linear = FALSE;
430 if ((itemVal & INPUT_PREFSTATE) == 0)
431 feature->prefState = TRUE;
432 else
433 feature->prefState = FALSE;
434 if ((itemVal & INPUT_NULL) == 0)
435 feature->HasNull = FALSE;
436 else
437 feature->HasNull = TRUE;
439 if (bTag != TAG_MAIN_INPUT)
441 if ((itemVal & INPUT_VOLATILE) == 0)
442 feature->Volatile = FALSE;
443 else
444 feature->Volatile = TRUE;
446 if (bSize > 1)
448 if ((itemVal & INPUT_BITFIELD) == 0)
449 feature->BitField = TRUE;
450 else
451 feature->BitField = FALSE; /* Buffered Bytes */
453 feature->index = *feature_index;
454 *feature_index = *feature_index + 1;
458 void parse_collection(unsigned int bSize, int itemVal, struct collection *collection)
460 if (bSize <= 0)
461 return;
462 else
464 collection->type = itemVal;
466 if (itemVal >= 0x07 && itemVal <= 0x7F) {
467 ERR(" (Reserved 0x%x )\n", itemVal);
469 else if (itemVal >= 0x80 && itemVal <= 0xFF) {
470 ERR(" (Vendor Defined 0x%x )\n", itemVal);
475 static void new_caps(struct caps *caps)
477 caps->IsRange = 0;
478 caps->IsStringRange = 0;
479 caps->IsDesignatorRange = 0;
480 caps->usage_count = 0;
483 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)
485 unsigned int i;
486 for (i = index; i < length;)
488 BYTE b0 = descriptor[i++];
489 int bSize = b0 & 0x03;
490 int bType = (b0 >> 2) & 0x03;
491 int bTag = (b0 >> 4) & 0x0F;
493 bSize = (bSize == 3) ? 4 : bSize;
494 if (bType == TAG_TYPE_RESERVED && bTag == 0x0F && bSize == 2 &&
495 i + 2 < length)
497 /* Long data items: Should be unused */
498 ERR("Long Data Item, should be unused\n");
500 else
502 int bSizeActual = 0;
503 int itemVal = 0;
504 unsigned int j;
506 for (j = 0; j < bSize; j++)
508 if (i + j < length)
510 itemVal += descriptor[i + j] << (8 * j);
511 bSizeActual++;
514 TRACE(" 0x%x[%i], type %i , tag %i, size %i, val %i\n",b0,i-1,bType, bTag, bSize, itemVal );
516 if (bType == TAG_TYPE_MAIN)
518 struct feature *feature;
519 switch(bTag)
521 case TAG_MAIN_INPUT:
522 feature = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*feature));
523 list_add_tail(&collection->features, &feature->col_entry);
524 list_add_tail(features, &feature->entry);
525 feature->type = HidP_Input;
526 parse_io_feature(bSize, itemVal, bTag, feature_index, feature);
527 feature->caps = *caps;
528 feature->collection = collection;
529 new_caps(caps);
530 break;
531 case TAG_MAIN_OUTPUT:
532 feature = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*feature));
533 list_add_tail(&collection->features, &feature->col_entry);
534 list_add_tail(features, &feature->entry);
535 feature->type = HidP_Output;
536 parse_io_feature(bSize, itemVal, bTag, feature_index, feature);
537 feature->caps = *caps;
538 feature->collection = collection;
539 new_caps(caps);
540 break;
541 case TAG_MAIN_FEATURE:
542 feature = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*feature));
543 list_add_tail(&collection->features, &feature->col_entry);
544 list_add_tail(features, &feature->entry);
545 feature->type = HidP_Feature;
546 parse_io_feature(bSize, itemVal, bTag, feature_index, feature);
547 feature->caps = *caps;
548 feature->collection = collection;
549 new_caps(caps);
550 break;
551 case TAG_MAIN_COLLECTION:
553 struct collection *subcollection = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct collection));
554 list_add_tail(&collection->collections, &subcollection->entry);
555 subcollection->parent = collection;
556 /* Only set our collection once...
557 We do not properly handle composite devices yet. */
558 if (*collection_index == 0)
559 collection->caps = *caps;
560 subcollection->caps = *caps;
561 subcollection->index = *collection_index;
562 *collection_index = *collection_index + 1;
563 list_init(&subcollection->features);
564 list_init(&subcollection->collections);
565 new_caps(caps);
567 parse_collection(bSize, itemVal, subcollection);
569 i = parse_descriptor(descriptor, i+1, length, feature_index, collection_index, subcollection, caps, features);
570 continue;
572 case TAG_MAIN_END_COLLECTION:
573 return i;
574 default:
575 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType);
578 else if (bType == TAG_TYPE_GLOBAL)
580 switch(bTag)
582 case TAG_GLOBAL_USAGE_PAGE:
583 caps->UsagePage = getValue(bSize, itemVal);
584 break;
585 case TAG_GLOBAL_LOGICAL_MINIMUM:
586 caps->LogicalMin = getValue(bSize, itemVal);
587 break;
588 case TAG_GLOBAL_LOGICAL_MAXIMUM:
589 caps->LogicalMax = getValue(bSize, itemVal);
590 break;
591 case TAG_GLOBAL_PHYSICAL_MINIMUM:
592 caps->PhysicalMin = getValue(bSize, itemVal);
593 break;
594 case TAG_GLOBAL_PHYSICAL_MAXIMUM:
595 caps->PhysicalMax = getValue(bSize, itemVal);
596 break;
597 case TAG_GLOBAL_UNIT_EXPONENT:
598 caps->UnitsExp = getValue(bSize, itemVal);
599 break;
600 case TAG_GLOBAL_UNIT:
601 caps->Units = getValue(bSize, itemVal);
602 break;
603 case TAG_GLOBAL_REPORT_SIZE:
604 caps->BitSize = getValue(bSize, itemVal);
605 break;
606 case TAG_GLOBAL_REPORT_ID:
607 caps->ReportID = getValue(bSize, itemVal);
608 break;
609 case TAG_GLOBAL_REPORT_COUNT:
610 caps->ReportCount = getValue(bSize, itemVal);
611 break;
612 case TAG_GLOBAL_PUSH:
613 FIXME("Unhandled Push\n");
614 break;
615 case TAG_GLOBAL_POP:
616 FIXME("Unhandled Pop\n");
617 break;
618 default:
619 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType);
622 else if (bType == TAG_TYPE_LOCAL)
624 switch(bTag)
626 case TAG_LOCAL_USAGE:
627 if (caps->usage_count >= USAGE_MAX)
628 FIXME("More than %i individual usages defined\n",USAGE_MAX);
629 else
631 caps->u.NotRange.Usage[caps->usage_count++] = getValue(bSize, itemVal);
632 caps->IsRange = FALSE;
634 break;
635 case TAG_LOCAL_USAGE_MINIMUM:
636 caps->usage_count = 1;
637 caps->u.Range.UsageMin = getValue(bSize, itemVal);
638 caps->IsRange = TRUE;
639 break;
640 case TAG_LOCAL_USAGE_MAXIMUM:
641 caps->usage_count = 1;
642 caps->u.Range.UsageMax = getValue(bSize, itemVal);
643 caps->IsRange = TRUE;
644 break;
645 case TAG_LOCAL_DESIGNATOR_INDEX:
646 caps->u.NotRange.DesignatorIndex = getValue(bSize, itemVal);
647 caps->IsDesignatorRange = FALSE;
648 break;
649 case TAG_LOCAL_DESIGNATOR_MINIMUM:
650 caps->u.Range.DesignatorMin = getValue(bSize, itemVal);
651 caps->IsDesignatorRange = TRUE;
652 break;
653 case TAG_LOCAL_DESIGNATOR_MAXIMUM:
654 caps->u.Range.DesignatorMax = getValue(bSize, itemVal);
655 caps->IsDesignatorRange = TRUE;
656 break;
657 case TAG_LOCAL_STRING_INDEX:
658 caps->u.NotRange.StringIndex = getValue(bSize, itemVal);
659 caps->IsStringRange = FALSE;
660 break;
661 case TAG_LOCAL_STRING_MINIMUM:
662 caps->u.Range.StringMin = getValue(bSize, itemVal);
663 caps->IsStringRange = TRUE;
664 break;
665 case TAG_LOCAL_STRING_MAXIMUM:
666 caps->u.Range.StringMax = getValue(bSize, itemVal);
667 caps->IsStringRange = TRUE;
668 break;
669 case TAG_LOCAL_DELIMITER:
670 caps->Delim = getValue(bSize, itemVal);
671 break;
672 default:
673 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType);
676 else
677 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType);
679 i += bSize;
682 return i;
685 static inline void new_report(WINE_HID_REPORT *wine_report, struct feature* feature)
687 wine_report->reportID = feature->caps.ReportID;
688 wine_report->dwSize = sizeof(*wine_report) - sizeof(WINE_HID_ELEMENT);
689 wine_report->elementCount = 0;
692 static void build_elements(WINE_HID_REPORT *wine_report, struct feature* feature, DWORD *bitOffset)
694 unsigned int i;
696 if (!feature->isData)
698 *bitOffset = *bitOffset + (feature->caps.BitSize * feature->caps.ReportCount);
699 return;
702 for (i = 0; i < feature->caps.usage_count; i++)
704 WINE_HID_ELEMENT *wine_element = &wine_report->Elements[wine_report->elementCount];
706 wine_element->valueStartBit = *bitOffset;
707 if (feature->caps.UsagePage == HID_USAGE_PAGE_BUTTON)
709 wine_element->ElementType = ButtonElement;
710 wine_element->caps.button.UsagePage = feature->caps.UsagePage;
711 wine_element->caps.button.ReportID = feature->caps.ReportID;
712 wine_element->caps.button.BitField = feature->BitField;
713 wine_element->caps.button.IsRange = feature->caps.IsRange;
714 wine_element->caps.button.IsStringRange = feature->caps.IsStringRange;
715 wine_element->caps.button.IsDesignatorRange = feature->caps.IsDesignatorRange;
716 wine_element->caps.button.IsAbsolute = feature->IsAbsolute;
717 if (wine_element->caps.button.IsRange)
719 wine_element->bitCount = (feature->caps.u.Range.UsageMax - feature->caps.u.Range.UsageMin) + 1;
720 *bitOffset = *bitOffset + wine_element->bitCount;
721 wine_element->caps.button.u.Range.UsageMin = feature->caps.u.Range.UsageMin;
722 wine_element->caps.button.u.Range.UsageMax = feature->caps.u.Range.UsageMax;
723 wine_element->caps.button.u.Range.StringMin = feature->caps.u.Range.StringMin;
724 wine_element->caps.button.u.Range.StringMax = feature->caps.u.Range.StringMax;
725 wine_element->caps.button.u.Range.DesignatorMin = feature->caps.u.Range.DesignatorMin;
726 wine_element->caps.button.u.Range.DesignatorMax = feature->caps.u.Range.DesignatorMax;
728 else
730 *bitOffset = *bitOffset + 1;
731 wine_element->bitCount = 1;
732 wine_element->caps.button.u.NotRange.Usage = feature->caps.u.NotRange.Usage[i];
733 wine_element->caps.button.u.NotRange.StringIndex = feature->caps.u.NotRange.StringIndex;
734 wine_element->caps.button.u.NotRange.DesignatorIndex = feature->caps.u.NotRange.DesignatorIndex;
737 else
739 wine_element->ElementType = ValueElement;
740 wine_element->caps.value.UsagePage = feature->caps.UsagePage;
741 wine_element->caps.value.ReportID = feature->caps.ReportID;
742 wine_element->caps.value.BitField = feature->BitField;
743 wine_element->caps.value.IsRange = feature->caps.IsRange;
744 wine_element->caps.value.IsStringRange = feature->caps.IsStringRange;
745 wine_element->caps.value.IsDesignatorRange = feature->caps.IsDesignatorRange;
746 wine_element->caps.value.IsAbsolute = feature->IsAbsolute;
747 wine_element->caps.value.HasNull = feature->HasNull;
748 wine_element->caps.value.BitSize = feature->caps.BitSize;
749 if (feature->caps.usage_count > 1)
750 wine_element->caps.value.ReportCount = 1;
751 else
752 wine_element->caps.value.ReportCount = feature->caps.ReportCount;
753 wine_element->bitCount = (feature->caps.BitSize * wine_element->caps.value.ReportCount);
754 *bitOffset = *bitOffset + wine_element->bitCount;
755 wine_element->caps.value.UnitsExp = feature->caps.UnitsExp;
756 wine_element->caps.value.Units = feature->caps.Units;
757 wine_element->caps.value.LogicalMin = feature->caps.LogicalMin;
758 wine_element->caps.value.LogicalMax = feature->caps.LogicalMax;
759 wine_element->caps.value.PhysicalMin = feature->caps.PhysicalMin;
760 wine_element->caps.value.PhysicalMax = feature->caps.PhysicalMax;
761 if (wine_element->caps.value.IsRange)
763 wine_element->caps.value.u.Range.UsageMin = feature->caps.u.Range.UsageMin;
764 wine_element->caps.value.u.Range.UsageMax = feature->caps.u.Range.UsageMax;
765 wine_element->caps.value.u.Range.StringMin = feature->caps.u.Range.StringMin;
766 wine_element->caps.value.u.Range.StringMax = feature->caps.u.Range.StringMax;
767 wine_element->caps.value.u.Range.DesignatorMin = feature->caps.u.Range.DesignatorMin;
768 wine_element->caps.value.u.Range.DesignatorMax = feature->caps.u.Range.DesignatorMax;
770 else
772 wine_element->caps.value.u.NotRange.Usage = feature->caps.u.NotRange.Usage[i];
773 wine_element->caps.value.u.NotRange.StringIndex = feature->caps.u.NotRange.StringIndex;
774 wine_element->caps.value.u.NotRange.DesignatorIndex = feature->caps.u.NotRange.DesignatorIndex;
778 wine_report->elementCount++;
782 static void count_elements(struct feature* feature, USHORT *buttons, USHORT *values)
784 if (feature->caps.UsagePage == HID_USAGE_PAGE_BUTTON)
786 if (feature->caps.IsRange)
787 *buttons = *buttons + 1;
788 else
789 *buttons = *buttons + feature->caps.usage_count;
791 else
793 if (feature->caps.IsRange)
794 *values = *values + 1;
795 else
796 *values = *values + feature->caps.usage_count;
800 WINE_HIDP_PREPARSED_DATA* build_PreparseData(
801 struct feature **features, int feature_count,
802 struct feature **input_features, int i_count,
803 struct feature **output_features, int o_count,
804 struct feature **feature_features, int f_count,
805 struct collection *base_collection)
807 WINE_HIDP_PREPARSED_DATA *data;
808 WINE_HID_REPORT *wine_report = NULL;
809 DWORD bitOffset, bitLength;
810 unsigned int report_count = 1;
811 unsigned int i;
812 unsigned int element_count;
813 unsigned int size = 0;
815 if (features[0]->caps.ReportID != 0)
817 unsigned int *report_ids;
818 unsigned int cnt = max(i_count, o_count);
819 cnt = max(cnt, f_count);
820 report_ids = HeapAlloc(GetProcessHeap(), 0 , sizeof(*report_ids) * cnt);
822 if (i_count)
824 report_ids[0] = input_features[0]->caps.ReportID;
825 for (i = 1; i < i_count; i++)
827 unsigned int j;
828 unsigned int found = FALSE;
829 for (j = 0; !found && j < i_count; j++)
831 if (report_ids[j] == input_features[i]->caps.ReportID)
832 found = TRUE;
834 if (!found)
836 report_ids[report_count] = input_features[i]->caps.ReportID;
837 report_count++;
841 if (o_count)
843 report_count++;
844 report_ids[0] = output_features[0]->caps.ReportID;
845 for (i = 1; i < o_count; i++)
847 unsigned int j;
848 unsigned int found = FALSE;
849 for (j = 0; !found && j < o_count; j++)
851 if (report_ids[j] == output_features[i]->caps.ReportID)
852 found = TRUE;
854 if (!found)
856 report_ids[report_count] = output_features[i]->caps.ReportID;
857 report_count++;
861 if (f_count)
863 report_count++;
864 report_ids[0] = feature_features[0]->caps.ReportID;
865 for (i = 1; i < f_count; i++)
867 unsigned int j;
868 unsigned int found = FALSE;
869 for (j = 0; !found && j < f_count; j++)
871 if (report_ids[j] == feature_features[i]->caps.ReportID)
872 found = TRUE;
874 if (!found)
876 report_ids[report_count] = feature_features[i]->caps.ReportID;
877 report_count++;
881 HeapFree(GetProcessHeap(), 0, report_ids);
883 else
885 if (o_count) report_count++;
886 if (f_count) report_count++;
889 element_count = 0;
890 for (i = 0; i < feature_count; i++)
891 element_count += features[i]->caps.usage_count;
893 size = sizeof(WINE_HIDP_PREPARSED_DATA) +
894 (element_count * sizeof(WINE_HID_ELEMENT)) +
895 (report_count * sizeof(WINE_HID_REPORT));
897 TRACE("%i reports %i elements -> size %i\n",report_count, element_count, size);
899 data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
900 data->magic = HID_MAGIC;
901 data->dwSize = size;
902 data->caps.Usage = base_collection->caps.u.NotRange.Usage[0];
903 data->caps.UsagePage = base_collection->caps.UsagePage;
905 wine_report = data->InputReports;
906 if (i_count)
908 bitLength = 0;
909 new_report(wine_report, input_features[0]);
910 data->dwInputReportCount++;
912 if (input_features[0]->caps.ReportID != 0)
913 bitOffset = 8;
914 else
915 bitOffset = 0;
917 for (i = 0; i < i_count; i++)
919 if (input_features[i]->caps.ReportID != wine_report->reportID)
921 wine_report->dwSize += (sizeof(WINE_HID_ELEMENT) * wine_report->elementCount);
922 wine_report = (WINE_HID_REPORT*)(((BYTE*)wine_report)+wine_report->dwSize);
923 new_report(wine_report, input_features[i]);
924 data->dwInputReportCount++;
925 bitLength = max(bitOffset, bitLength);
926 if (input_features[i]->caps.ReportID != 0)
927 bitOffset = 8;
928 else
929 bitOffset = 0;
931 build_elements(wine_report, input_features[i], &bitOffset);
932 count_elements(input_features[i], &data->caps.NumberInputButtonCaps,
933 &data->caps.NumberInputValueCaps);
935 wine_report->dwSize += (sizeof(WINE_HID_ELEMENT) * wine_report->elementCount);
936 bitLength = max(bitOffset, bitLength);
937 data->caps.InputReportByteLength = ((bitLength + 7) & ~7)/8;
940 if (o_count)
942 bitLength = 0;
943 wine_report = (WINE_HID_REPORT*)(((BYTE*)wine_report)+wine_report->dwSize);
944 data->dwOutputReportOffset = (BYTE*)wine_report - (BYTE*)data->InputReports;
945 new_report(wine_report, output_features[0]);
946 data->dwOutputReportCount++;
947 if (output_features[0]->caps.ReportID != 0)
948 bitOffset = 8;
949 else
950 bitOffset = 0;
952 for (i = 0; i < o_count; i++)
954 if (output_features[i]->caps.ReportID != wine_report->reportID)
956 wine_report->dwSize += (sizeof(WINE_HID_ELEMENT) * wine_report->elementCount);
957 wine_report = (WINE_HID_REPORT*)(((BYTE*)wine_report)+wine_report->dwSize);
958 new_report(wine_report, output_features[i]);
959 data->dwOutputReportCount++;
960 bitLength = max(bitOffset, bitLength);
961 if (output_features[0]->caps.ReportID != 0)
962 bitOffset = 8;
963 else
964 bitOffset = 0;
966 build_elements(wine_report, output_features[i], &bitOffset);
967 count_elements(output_features[i], &data->caps.NumberOutputButtonCaps,
968 &data->caps.NumberOutputValueCaps);
970 wine_report->dwSize += (sizeof(WINE_HID_ELEMENT) * wine_report->elementCount);
971 bitLength = max(bitOffset, bitLength);
972 data->caps.OutputReportByteLength = ((bitLength + 7) & ~7)/8;
975 if (f_count)
977 bitLength = 0;
978 wine_report = (WINE_HID_REPORT*)(((BYTE*)wine_report)+wine_report->dwSize);
979 data->dwFeatureReportOffset = (BYTE*)wine_report - (BYTE*)data->InputReports;
980 new_report(wine_report, feature_features[0]);
981 data->dwFeatureReportCount++;
982 if (feature_features[0]->caps.ReportID != 0)
983 bitOffset = 8;
984 else
985 bitOffset = 0;
987 for (i = 0; i < f_count; i++)
989 if (feature_features[i]->caps.ReportID != wine_report->reportID)
991 wine_report->dwSize += (sizeof(WINE_HID_ELEMENT) * wine_report->elementCount);
992 wine_report = (WINE_HID_REPORT*)((BYTE*)wine_report)+wine_report->dwSize;
993 new_report(wine_report, feature_features[i]);
994 data->dwFeatureReportCount++;
995 bitLength = max(bitOffset, bitLength);
996 if (feature_features[0]->caps.ReportID != 0)
997 bitOffset = 8;
998 else
999 bitOffset = 0;
1001 build_elements(wine_report, feature_features[i], &bitOffset);
1002 count_elements(feature_features[i], &data->caps.NumberFeatureButtonCaps,
1003 &data->caps.NumberFeatureValueCaps);
1005 bitLength = max(bitOffset, bitLength);
1006 data->caps.FeatureReportByteLength = ((bitLength + 7) & ~7)/8;
1009 return data;
1012 static void free_collection(struct collection *collection)
1014 struct feature *fentry, *fnext;
1015 struct collection *centry, *cnext;
1016 LIST_FOR_EACH_ENTRY_SAFE(centry, cnext, &collection->collections, struct collection, entry)
1018 list_remove(&centry->entry);
1019 free_collection(centry);
1021 LIST_FOR_EACH_ENTRY_SAFE(fentry, fnext, &collection->features, struct feature, col_entry)
1023 list_remove(&fentry->col_entry);
1024 HeapFree(GetProcessHeap(), 0, fentry);
1026 HeapFree(GetProcessHeap(), 0, collection);
1029 static int compare_reports(const void *a, const void* b)
1031 struct feature *f1 = *(struct feature **)a;
1032 struct feature *f2 = *(struct feature **)b;
1033 int c = (f1->caps.ReportID - f2->caps.ReportID);
1034 if (c) return c;
1035 return (f1->index - f2->index);
1038 WINE_HIDP_PREPARSED_DATA* ParseDescriptor(BYTE *descriptor, unsigned int length)
1040 WINE_HIDP_PREPARSED_DATA *data = NULL;
1041 struct collection *base;
1042 struct caps caps;
1044 struct list features;
1046 unsigned int feature_count = 0;
1047 unsigned int cidx;
1049 if (TRACE_ON(hid))
1051 TRACE("Descriptor[%i]: ", length);
1052 for (cidx = 0; cidx < length; cidx++)
1053 TRACE("%x ",descriptor[cidx]);
1054 TRACE("\n");
1057 list_init(&features);
1059 base = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*base));
1060 base->index = 1;
1061 list_init(&base->features);
1062 list_init(&base->collections);
1063 memset(&caps, 0, sizeof(caps));
1065 cidx = 0;
1066 parse_descriptor(descriptor, 0, length, &feature_count, &cidx, base, &caps, &features);
1068 debug_collection(base);
1070 cidx = 2;
1071 if (feature_count)
1073 struct feature *entry;
1074 struct feature** sorted_features;
1075 struct feature** input_features;
1076 struct feature** output_features;
1077 struct feature** feature_features;
1078 unsigned int i_count, o_count, f_count;
1079 unsigned int i;
1081 i_count = o_count = f_count = 0;
1083 sorted_features = HeapAlloc(GetProcessHeap(), 0, sizeof(*sorted_features) * feature_count);
1084 input_features = HeapAlloc(GetProcessHeap(), 0, sizeof(*input_features) * feature_count);
1085 output_features = HeapAlloc(GetProcessHeap(), 0, sizeof(*output_features) * feature_count);
1086 feature_features = HeapAlloc(GetProcessHeap(), 0, sizeof(*feature_features) * feature_count);
1088 i = 0;
1089 LIST_FOR_EACH_ENTRY(entry, &features, struct feature, entry)
1090 sorted_features[i++] = entry;
1092 /* Sort features base on report if there are multiple reports */
1093 if (sorted_features[0]->caps.ReportID != 0)
1094 qsort(sorted_features, feature_count, sizeof(struct feature*), compare_reports);
1096 for (i = 0; i < feature_count; i++)
1098 switch (sorted_features[i]->type)
1100 case HidP_Input:
1101 input_features[i_count] = sorted_features[i];
1102 i_count++;
1103 break;
1104 case HidP_Output:
1105 output_features[o_count] = sorted_features[i];
1106 o_count++;
1107 break;
1108 case HidP_Feature:
1109 feature_features[f_count] = sorted_features[i];
1110 f_count++;
1111 break;
1112 default:
1113 ERR("Unknown type %i\n",sorted_features[i]->type);
1117 if (TRACE_ON(hid))
1119 TRACE("DUMP FEATURES:\n");
1120 TRACE("----INPUT----\n");
1121 for (cidx = 0; cidx < i_count; cidx++)
1122 debug_feature(input_features[cidx]);
1123 TRACE("----OUTPUT----\n");
1124 for (cidx = 0; cidx < o_count; cidx++)
1125 debug_feature(output_features[cidx]);
1126 TRACE("----FEATURE----\n");
1127 for (cidx = 0; cidx < f_count; cidx++)
1128 debug_feature(feature_features[cidx]);
1131 data = build_PreparseData(sorted_features, feature_count, input_features, i_count, output_features, o_count, feature_features, f_count, base);
1133 debug_print_preparsed(data);
1135 HeapFree(GetProcessHeap(), 0, sorted_features);
1136 HeapFree(GetProcessHeap(), 0, input_features);
1137 HeapFree(GetProcessHeap(), 0, output_features);
1138 HeapFree(GetProcessHeap(), 0, feature_features);
1141 free_collection(base);
1142 /* We do not have to free the list as free_collection does all the work */
1144 return data;