reg/tests: Test import with non-standard registry file headers.
[wine.git] / dlls / hidclass.sys / descriptor.c
blobee1305562360fc11dac7b0e79b56f159436e9b4f
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 /* Flags that are defined in the document
37 "Device Class Definition for Human Interface Devices" */
38 enum {
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) */
50 enum {
51 TAG_TYPE_MAIN = 0x0,
52 TAG_TYPE_GLOBAL,
53 TAG_TYPE_LOCAL,
54 TAG_TYPE_RESERVED,
57 enum {
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
65 enum {
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,
72 TAG_GLOBAL_UNIT,
73 TAG_GLOBAL_REPORT_SIZE,
74 TAG_GLOBAL_REPORT_ID,
75 TAG_GLOBAL_REPORT_COUNT,
76 TAG_GLOBAL_PUSH,
77 TAG_GLOBAL_POP
80 enum {
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,
90 TAG_LOCAL_DELIMITER
94 static const char* const feature_string[] =
95 { "Input", "Output", "Feature" };
97 struct caps {
98 USAGE UsagePage;
99 LONG LogicalMin;
100 LONG LogicalMax;
101 LONG PhysicalMin;
102 LONG PhysicalMax;
103 ULONG UnitsExp;
104 ULONG Units;
105 USHORT BitSize;
106 UCHAR ReportID;
107 USHORT ReportCount;
109 BOOLEAN IsRange;
110 BOOLEAN IsStringRange;
111 BOOLEAN IsDesignatorRange;
112 unsigned int usage_count;
113 union {
114 struct {
115 USAGE UsageMin;
116 USAGE UsageMax;
117 USHORT StringMin;
118 USHORT StringMax;
119 USHORT DesignatorMin;
120 USHORT DesignatorMax;
121 } Range;
122 struct {
123 USAGE Usage[USAGE_MAX];
124 USAGE Reserved1;
125 USHORT StringIndex;
126 USHORT Reserved2;
127 USHORT DesignatorIndex;
128 USHORT Reserved3;
129 } NotRange;
130 } DUMMYUNIONNAME;
132 int Delim;
135 struct feature {
136 struct list entry;
137 struct list col_entry;
138 struct caps caps;
140 HIDP_REPORT_TYPE type;
141 BOOLEAN isData;
142 BOOLEAN isArray;
143 BOOLEAN IsAbsolute;
144 BOOLEAN Wrap;
145 BOOLEAN Linear;
146 BOOLEAN prefState;
147 BOOLEAN HasNull;
148 BOOLEAN Volatile;
149 BOOLEAN BitField;
151 unsigned int index;
152 struct collection *collection;
155 static const char* const collection_string[] = {
156 "Physical",
157 "Application",
158 "Logical",
159 "Report",
160 "Named Array",
161 "Usage Switch",
162 "Usage Modifier",
165 struct collection {
166 struct list entry;
167 struct caps caps;
168 unsigned int index;
169 unsigned int type;
170 struct collection *parent;
171 struct list features;
172 struct list collections;
175 struct caps_stack {
176 struct list entry;
177 struct caps caps;
180 static const char* debugstr_usages(struct caps *caps)
182 if (!caps->IsRange)
184 char out[12 * USAGE_MAX];
185 unsigned int i;
186 if (caps->usage_count == 0)
187 return "[ none ]";
188 out[0] = 0;
189 for (i = 0; i < caps->usage_count; i++)
190 sprintf(out + strlen(out), "0x%x ", caps->u.NotRange.Usage[i]);
191 return wine_dbg_sprintf("[ %s] ", out);
193 else
194 return wine_dbg_sprintf("[0x%x - 0x%x]", caps->u.Range.UsageMin, caps->u.Range.UsageMax);
197 static const char* debugstr_stringindex(struct caps *caps)
199 if (!caps->IsStringRange)
200 return wine_dbg_sprintf("%i", caps->u.NotRange.StringIndex);
201 else
202 return wine_dbg_sprintf("[%i - %i]", caps->u.Range.StringMin, caps->u.Range.StringMax);
205 static const char* debugstr_designatorindex(struct caps *caps)
207 if (!caps->IsDesignatorRange)
208 return wine_dbg_sprintf("%i", caps->u.NotRange.DesignatorIndex);
209 else
210 return wine_dbg_sprintf("[%i - %i]", caps->u.Range.DesignatorMin, caps->u.Range.DesignatorMax);
213 static void debugstr_caps(const char* type, struct caps *caps)
215 if (!caps)
216 return;
217 TRACE("(%s Caps: UsagePage 0x%x; LogicalMin %i; LogicalMax %i; PhysicalMin %i; PhysicalMax %i; UnitsExp %i; Units %i; BitSize %i; ReportID %i; ReportCount %i; Usage %s; StringIndex %s; DesignatorIndex %s; Delim %i;)\n",
218 type,
219 caps->UsagePage,
220 caps->LogicalMin,
221 caps->LogicalMax,
222 caps->PhysicalMin,
223 caps->PhysicalMax,
224 caps->UnitsExp,
225 caps->Units,
226 caps->BitSize,
227 caps->ReportID,
228 caps->ReportCount,
229 debugstr_usages(caps),
230 debugstr_stringindex(caps),
231 debugstr_designatorindex(caps),
232 caps->Delim);
235 static void debug_feature(struct feature *feature)
237 if (!feature)
238 return;
239 TRACE("[Feature type %s [%i]; %s; %s; %s; %s; %s; %s; %s; %s; %s]\n",
240 feature_string[feature->type],
241 feature->index,
242 (feature->isData)?"Data":"Const",
243 (feature->isArray)?"Array":"Var",
244 (feature->IsAbsolute)?"Abs":"Rel",
245 (feature->Wrap)?"Wrap":"NoWrap",
246 (feature->Linear)?"Linear":"NonLinear",
247 (feature->prefState)?"PrefStat":"NoPrefState",
248 (feature->HasNull)?"HasNull":"NoNull",
249 (feature->Volatile)?"Volatile":"NonVolatile",
250 (feature->BitField)?"BitField":"Buffered");
252 debugstr_caps("Feature", &feature->caps);
255 static void debug_collection(struct collection *collection)
257 struct feature *fentry;
258 struct collection *centry;
259 if (TRACE_ON(hid))
261 TRACE("START Collection %i <<< %s, parent: %p, %i features, %i collections\n", collection->index, collection_string[collection->type], collection->parent, list_count(&collection->features), list_count(&collection->collections));
262 debugstr_caps("Collection", &collection->caps);
263 LIST_FOR_EACH_ENTRY(fentry, &collection->features, struct feature, col_entry)
264 debug_feature(fentry);
265 LIST_FOR_EACH_ENTRY(centry, &collection->collections, struct collection, entry)
266 debug_collection(centry);
267 TRACE(">>> END Collection %i\n", collection->index);
271 static void debug_print_button_cap(const CHAR * type, WINE_HID_ELEMENT *wine_element)
273 if (!wine_element->caps.button.IsRange)
274 TRACE("%s Button: 0x%x/0x%04x: ReportId %i, startBit %i/1\n" , type,
275 wine_element->caps.button.UsagePage,
276 wine_element->caps.button.u.NotRange.Usage,
277 wine_element->caps.value.ReportID,
278 wine_element->valueStartBit);
279 else
280 TRACE("%s Button: 0x%x/[0x%04x-0x%04x]: ReportId %i, startBit %i/%i\n" ,type,
281 wine_element->caps.button.UsagePage,
282 wine_element->caps.button.u.Range.UsageMin,
283 wine_element->caps.button.u.Range.UsageMax,
284 wine_element->caps.value.ReportID,
285 wine_element->valueStartBit,
286 wine_element->bitCount);
289 static void debug_print_value_cap(const CHAR * type, WINE_HID_ELEMENT *wine_element)
291 TRACE("%s Value: 0x%x/0x%x: ReportId %i, IsAbsolute %i, HasNull %i, "
292 "Bit Size %i, ReportCount %i, UnitsExp %i, Units %i, "
293 "LogicalMin %i, Logical Max %i, PhysicalMin %i, "
294 "PhysicalMax %i -- StartBit %i/%i\n", type,
295 wine_element->caps.value.UsagePage,
296 wine_element->caps.value.u.NotRange.Usage,
297 wine_element->caps.value.ReportID,
298 wine_element->caps.value.IsAbsolute,
299 wine_element->caps.value.HasNull,
300 wine_element->caps.value.BitSize,
301 wine_element->caps.value.ReportCount,
302 wine_element->caps.value.UnitsExp,
303 wine_element->caps.value.Units,
304 wine_element->caps.value.LogicalMin,
305 wine_element->caps.value.LogicalMax,
306 wine_element->caps.value.PhysicalMin,
307 wine_element->caps.value.PhysicalMax,
308 wine_element->valueStartBit,
309 wine_element->bitCount);
312 static void debug_print_element(const CHAR* type, WINE_HID_ELEMENT *wine_element)
314 if (wine_element->ElementType == ButtonElement)
315 debug_print_button_cap(type, wine_element);
316 else if (wine_element->ElementType == ValueElement)
317 debug_print_value_cap(type, wine_element);
318 else
319 TRACE("%s: UNKNOWN\n", type);
322 static void debug_print_report(const char* type, WINE_HID_REPORT *report)
324 unsigned int i;
325 TRACE("START Report %i <<< %s report : dwSize: %i elementCount: %i\n",
326 report->reportID,
327 type,
328 report->dwSize,
329 report->elementCount);
330 for (i = 0; i < report->elementCount; i++)
331 debug_print_element(type, &report->Elements[i]);
332 TRACE(">>> END Report %i\n",report->reportID);
335 static void debug_print_preparsed(WINE_HIDP_PREPARSED_DATA *data)
337 unsigned int i;
338 WINE_HID_REPORT *r;
339 if (TRACE_ON(hid))
341 TRACE("START PREPARSED Data <<< dwSize: %i Usage: %i, UsagePage: %i, InputReportByteLength: %i, tOutputReportByteLength: %i, FeatureReportByteLength: %i, NumberLinkCollectionNodes: %i, NumberInputButtonCaps: %i, NumberInputValueCaps: %i,NumberInputDataIndices: %i, NumberOutputButtonCaps: %i, NumberOutputValueCaps: %i, NumberOutputDataIndices: %i, NumberFeatureButtonCaps: %i, NumberFeatureValueCaps: %i, NumberFeatureDataIndices: %i, dwInputReportCount: %i, dwOutputReportCount: %i, dwFeatureReportCount: %i, dwOutputReportOffset: %i, dwFeatureReportOffset: %i\n",
342 data->dwSize,
343 data->caps.Usage,
344 data->caps.UsagePage,
345 data->caps.InputReportByteLength,
346 data->caps.OutputReportByteLength,
347 data->caps.FeatureReportByteLength,
348 data->caps.NumberLinkCollectionNodes,
349 data->caps.NumberInputButtonCaps,
350 data->caps.NumberInputValueCaps,
351 data->caps.NumberInputDataIndices,
352 data->caps.NumberOutputButtonCaps,
353 data->caps.NumberOutputValueCaps,
354 data->caps.NumberOutputDataIndices,
355 data->caps.NumberFeatureButtonCaps,
356 data->caps.NumberFeatureValueCaps,
357 data->caps.NumberFeatureDataIndices,
358 data->dwInputReportCount,
359 data->dwOutputReportCount,
360 data->dwFeatureReportCount,
361 data->dwOutputReportOffset,
362 data->dwFeatureReportOffset);
364 r = HID_INPUT_REPORTS(data);
365 for (i = 0; i < data->dwInputReportCount; i++)
367 debug_print_report("INPUT", r);
368 r = HID_NEXT_REPORT(data, r);
370 r = HID_OUTPUT_REPORTS(data);
371 for (i = 0; i < data->dwOutputReportCount; i++)
373 debug_print_report("OUTPUT", r);
374 r = HID_NEXT_REPORT(data, r);
376 r = HID_FEATURE_REPORTS(data);
377 for (i = 0; i < data->dwFeatureReportCount; i++)
379 debug_print_report("FEATURE", r);
380 r = HID_NEXT_REPORT(data, r);
382 TRACE(">>> END Preparsed Data\n");
386 static int getValue(int bsize, int source, BOOL allow_negative)
388 int mask = 0xff;
389 int negative = 0x80;
390 int outofrange = 0x100;
391 int value;
392 unsigned int i;
394 if (bsize == 4)
395 return source;
397 for (i = 1; i < bsize; i++)
399 mask = (mask<<8) + 0xff;
400 negative = (negative<<8);
401 outofrange = (outofrange<<8);
403 value = (source&mask);
404 if (allow_negative && value&negative)
405 value = -1 * (outofrange - value);
406 return value;
409 static void parse_io_feature(unsigned int bSize, int itemVal, int bTag,
410 unsigned int *feature_index,
411 struct feature *feature)
413 if (bSize == 0)
415 return;
417 else
419 feature->isData = ((itemVal & INPUT_DATA_CONST) == 0);
420 feature->isArray = ((itemVal & INPUT_ARRAY_VAR) == 0);
421 feature->IsAbsolute = ((itemVal & INPUT_ABS_REL) == 0);
422 feature->Wrap = ((itemVal & INPUT_WRAP) != 0);
423 feature->Linear = ((itemVal & INPUT_LINEAR) == 0);
424 feature->prefState = ((itemVal & INPUT_PREFSTATE) == 0);
425 feature->HasNull = ((itemVal & INPUT_NULL) != 0);
427 if (bTag != TAG_MAIN_INPUT)
429 feature->Volatile = ((itemVal & INPUT_VOLATILE) != 0);
431 if (bSize > 1)
433 feature->BitField = ((itemVal & INPUT_BITFIELD) == 0);
435 feature->index = *feature_index;
436 *feature_index = *feature_index + 1;
440 static void parse_collection(unsigned int bSize, int itemVal,
441 struct collection *collection)
443 if (bSize <= 0)
444 return;
445 else
447 collection->type = itemVal;
449 if (itemVal >= 0x07 && itemVal <= 0x7F) {
450 ERR(" (Reserved 0x%x )\n", itemVal);
452 else if (itemVal >= 0x80 && itemVal <= 0xFF) {
453 ERR(" (Vendor Defined 0x%x )\n", itemVal);
458 static void new_caps(struct caps *caps)
460 caps->IsRange = 0;
461 caps->IsStringRange = 0;
462 caps->IsDesignatorRange = 0;
463 caps->usage_count = 0;
466 static int parse_descriptor(BYTE *descriptor, unsigned int index, unsigned int length,
467 unsigned int *feature_index, unsigned int *collection_index,
468 struct collection *collection, struct caps *caps,
469 struct list *features, struct list *stack)
471 unsigned int i;
472 for (i = index; i < length;)
474 BYTE b0 = descriptor[i++];
475 int bSize = b0 & 0x03;
476 int bType = (b0 >> 2) & 0x03;
477 int bTag = (b0 >> 4) & 0x0F;
479 bSize = (bSize == 3) ? 4 : bSize;
480 if (bType == TAG_TYPE_RESERVED && bTag == 0x0F && bSize == 2 &&
481 i + 2 < length)
483 /* Long data items: Should be unused */
484 ERR("Long Data Item, should be unused\n");
486 else
488 int bSizeActual = 0;
489 int itemVal = 0;
490 unsigned int j;
492 for (j = 0; j < bSize; j++)
494 if (i + j < length)
496 itemVal += descriptor[i + j] << (8 * j);
497 bSizeActual++;
500 TRACE(" 0x%x[%i], type %i , tag %i, size %i, val %i\n",b0,i-1,bType, bTag, bSize, itemVal );
502 if (bType == TAG_TYPE_MAIN)
504 struct feature *feature;
505 switch(bTag)
507 case TAG_MAIN_INPUT:
508 feature = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*feature));
509 list_add_tail(&collection->features, &feature->col_entry);
510 list_add_tail(features, &feature->entry);
511 feature->type = HidP_Input;
512 parse_io_feature(bSize, itemVal, bTag, feature_index, feature);
513 feature->caps = *caps;
514 feature->collection = collection;
515 new_caps(caps);
516 break;
517 case TAG_MAIN_OUTPUT:
518 feature = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*feature));
519 list_add_tail(&collection->features, &feature->col_entry);
520 list_add_tail(features, &feature->entry);
521 feature->type = HidP_Output;
522 parse_io_feature(bSize, itemVal, bTag, feature_index, feature);
523 feature->caps = *caps;
524 feature->collection = collection;
525 new_caps(caps);
526 break;
527 case TAG_MAIN_FEATURE:
528 feature = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*feature));
529 list_add_tail(&collection->features, &feature->col_entry);
530 list_add_tail(features, &feature->entry);
531 feature->type = HidP_Feature;
532 parse_io_feature(bSize, itemVal, bTag, feature_index, feature);
533 feature->caps = *caps;
534 feature->collection = collection;
535 new_caps(caps);
536 break;
537 case TAG_MAIN_COLLECTION:
539 struct collection *subcollection = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct collection));
540 list_add_tail(&collection->collections, &subcollection->entry);
541 subcollection->parent = collection;
542 /* Only set our collection once...
543 We do not properly handle composite devices yet. */
544 if (*collection_index == 0)
545 collection->caps = *caps;
546 subcollection->caps = *caps;
547 subcollection->index = *collection_index;
548 *collection_index = *collection_index + 1;
549 list_init(&subcollection->features);
550 list_init(&subcollection->collections);
551 new_caps(caps);
553 parse_collection(bSize, itemVal, subcollection);
555 i = parse_descriptor(descriptor, i+1, length, feature_index, collection_index, subcollection, caps, features, stack);
556 continue;
558 case TAG_MAIN_END_COLLECTION:
559 return i;
560 default:
561 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType);
564 else if (bType == TAG_TYPE_GLOBAL)
566 switch(bTag)
568 case TAG_GLOBAL_USAGE_PAGE:
569 caps->UsagePage = getValue(bSize, itemVal, FALSE);
570 break;
571 case TAG_GLOBAL_LOGICAL_MINIMUM:
572 caps->LogicalMin = getValue(bSize, itemVal, TRUE);
573 break;
574 case TAG_GLOBAL_LOGICAL_MAXIMUM:
575 caps->LogicalMax = getValue(bSize, itemVal, TRUE);
576 break;
577 case TAG_GLOBAL_PHYSICAL_MINIMUM:
578 caps->PhysicalMin = getValue(bSize, itemVal, TRUE);
579 break;
580 case TAG_GLOBAL_PHYSICAL_MAXIMUM:
581 caps->PhysicalMax = getValue(bSize, itemVal, TRUE);
582 break;
583 case TAG_GLOBAL_UNIT_EXPONENT:
584 caps->UnitsExp = getValue(bSize, itemVal, TRUE);
585 break;
586 case TAG_GLOBAL_UNIT:
587 caps->Units = getValue(bSize, itemVal, TRUE);
588 break;
589 case TAG_GLOBAL_REPORT_SIZE:
590 caps->BitSize = getValue(bSize, itemVal, FALSE);
591 break;
592 case TAG_GLOBAL_REPORT_ID:
593 caps->ReportID = getValue(bSize, itemVal, FALSE);
594 break;
595 case TAG_GLOBAL_REPORT_COUNT:
596 caps->ReportCount = getValue(bSize, itemVal, FALSE);
597 break;
598 case TAG_GLOBAL_PUSH:
600 struct caps_stack *saved = HeapAlloc(GetProcessHeap(), 0, sizeof(*saved));
601 saved->caps = *caps;
602 TRACE("Push\n");
603 list_add_tail(stack, &saved->entry);
604 break;
606 case TAG_GLOBAL_POP:
608 struct list *tail;
609 struct caps_stack *saved;
610 TRACE("Pop\n");
611 tail = list_tail(stack);
612 if (tail)
614 saved = LIST_ENTRY(tail, struct caps_stack, entry);
615 *caps = saved->caps;
616 list_remove(tail);
617 HeapFree(GetProcessHeap(), 0, saved);
619 else
620 ERR("Pop but no stack!\n");
621 break;
623 default:
624 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType);
627 else if (bType == TAG_TYPE_LOCAL)
629 switch(bTag)
631 case TAG_LOCAL_USAGE:
632 if (caps->usage_count >= USAGE_MAX)
633 FIXME("More than %i individual usages defined\n",USAGE_MAX);
634 else
636 caps->u.NotRange.Usage[caps->usage_count++] = getValue(bSize, itemVal, FALSE);
637 caps->IsRange = FALSE;
639 break;
640 case TAG_LOCAL_USAGE_MINIMUM:
641 caps->usage_count = 1;
642 caps->u.Range.UsageMin = getValue(bSize, itemVal, FALSE);
643 caps->IsRange = TRUE;
644 break;
645 case TAG_LOCAL_USAGE_MAXIMUM:
646 caps->usage_count = 1;
647 caps->u.Range.UsageMax = getValue(bSize, itemVal, FALSE);
648 caps->IsRange = TRUE;
649 break;
650 case TAG_LOCAL_DESIGNATOR_INDEX:
651 caps->u.NotRange.DesignatorIndex = getValue(bSize, itemVal, FALSE);
652 caps->IsDesignatorRange = FALSE;
653 break;
654 case TAG_LOCAL_DESIGNATOR_MINIMUM:
655 caps->u.Range.DesignatorMin = getValue(bSize, itemVal, FALSE);
656 caps->IsDesignatorRange = TRUE;
657 break;
658 case TAG_LOCAL_DESIGNATOR_MAXIMUM:
659 caps->u.Range.DesignatorMax = getValue(bSize, itemVal, FALSE);
660 caps->IsDesignatorRange = TRUE;
661 break;
662 case TAG_LOCAL_STRING_INDEX:
663 caps->u.NotRange.StringIndex = getValue(bSize, itemVal, FALSE);
664 caps->IsStringRange = FALSE;
665 break;
666 case TAG_LOCAL_STRING_MINIMUM:
667 caps->u.Range.StringMin = getValue(bSize, itemVal, FALSE);
668 caps->IsStringRange = TRUE;
669 break;
670 case TAG_LOCAL_STRING_MAXIMUM:
671 caps->u.Range.StringMax = getValue(bSize, itemVal, FALSE);
672 caps->IsStringRange = TRUE;
673 break;
674 case TAG_LOCAL_DELIMITER:
675 caps->Delim = getValue(bSize, itemVal, FALSE);
676 break;
677 default:
678 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType);
681 else
682 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType);
684 i += bSize;
687 return i;
690 static inline void new_report(WINE_HID_REPORT *wine_report, struct feature* feature)
692 wine_report->reportID = feature->caps.ReportID;
693 wine_report->dwSize = sizeof(*wine_report) - sizeof(WINE_HID_ELEMENT);
694 wine_report->elementCount = 0;
697 static void build_elements(WINE_HID_REPORT *wine_report, struct feature* feature, DWORD *bitOffset, unsigned int *data_index)
699 unsigned int i;
701 if (!feature->isData)
703 *bitOffset = *bitOffset + (feature->caps.BitSize * feature->caps.ReportCount);
704 return;
707 for (i = 0; i < feature->caps.usage_count; i++)
709 WINE_HID_ELEMENT *wine_element = &wine_report->Elements[wine_report->elementCount];
711 wine_element->valueStartBit = *bitOffset;
712 if (feature->caps.UsagePage == HID_USAGE_PAGE_BUTTON)
714 wine_element->ElementType = ButtonElement;
715 wine_element->caps.button.UsagePage = feature->caps.UsagePage;
716 wine_element->caps.button.ReportID = feature->caps.ReportID;
717 wine_element->caps.button.BitField = feature->BitField;
718 wine_element->caps.button.IsRange = feature->caps.IsRange;
719 wine_element->caps.button.IsStringRange = feature->caps.IsStringRange;
720 wine_element->caps.button.IsDesignatorRange = feature->caps.IsDesignatorRange;
721 wine_element->caps.button.IsAbsolute = feature->IsAbsolute;
722 if (wine_element->caps.button.IsRange)
724 wine_element->bitCount = (feature->caps.u.Range.UsageMax - feature->caps.u.Range.UsageMin) + 1;
725 *bitOffset = *bitOffset + wine_element->bitCount;
726 wine_element->caps.button.u.Range.UsageMin = feature->caps.u.Range.UsageMin;
727 wine_element->caps.button.u.Range.UsageMax = feature->caps.u.Range.UsageMax;
728 wine_element->caps.button.u.Range.StringMin = feature->caps.u.Range.StringMin;
729 wine_element->caps.button.u.Range.StringMax = feature->caps.u.Range.StringMax;
730 wine_element->caps.button.u.Range.DesignatorMin = feature->caps.u.Range.DesignatorMin;
731 wine_element->caps.button.u.Range.DesignatorMax = feature->caps.u.Range.DesignatorMax;
732 wine_element->caps.button.u.Range.DataIndexMin = *data_index;
733 wine_element->caps.button.u.Range.DataIndexMax = *data_index + wine_element->bitCount - 1;
734 *data_index = *data_index + wine_element->bitCount;
736 else
738 *bitOffset = *bitOffset + 1;
739 wine_element->bitCount = 1;
740 wine_element->caps.button.u.NotRange.Usage = feature->caps.u.NotRange.Usage[i];
741 wine_element->caps.button.u.NotRange.StringIndex = feature->caps.u.NotRange.StringIndex;
742 wine_element->caps.button.u.NotRange.DesignatorIndex = feature->caps.u.NotRange.DesignatorIndex;
743 wine_element->caps.button.u.NotRange.DataIndex = *data_index;
744 *data_index = *data_index + 1;
747 else
749 wine_element->ElementType = ValueElement;
750 wine_element->caps.value.UsagePage = feature->caps.UsagePage;
751 wine_element->caps.value.ReportID = feature->caps.ReportID;
752 wine_element->caps.value.BitField = feature->BitField;
753 wine_element->caps.value.IsRange = feature->caps.IsRange;
754 wine_element->caps.value.IsStringRange = feature->caps.IsStringRange;
755 wine_element->caps.value.IsDesignatorRange = feature->caps.IsDesignatorRange;
756 wine_element->caps.value.IsAbsolute = feature->IsAbsolute;
757 wine_element->caps.value.HasNull = feature->HasNull;
758 wine_element->caps.value.BitSize = feature->caps.BitSize;
759 if (feature->caps.usage_count > 1)
761 if (feature->caps.ReportCount > feature->caps.usage_count)
762 wine_element->caps.value.ReportCount = feature->caps.ReportCount / feature->caps.usage_count;
763 else
764 wine_element->caps.value.ReportCount = 1;
766 else
767 wine_element->caps.value.ReportCount = feature->caps.ReportCount;
768 wine_element->bitCount = (feature->caps.BitSize * wine_element->caps.value.ReportCount);
769 *bitOffset = *bitOffset + wine_element->bitCount;
770 wine_element->caps.value.UnitsExp = feature->caps.UnitsExp;
771 wine_element->caps.value.Units = feature->caps.Units;
772 wine_element->caps.value.LogicalMin = feature->caps.LogicalMin;
773 wine_element->caps.value.LogicalMax = feature->caps.LogicalMax;
774 wine_element->caps.value.PhysicalMin = feature->caps.PhysicalMin;
775 wine_element->caps.value.PhysicalMax = feature->caps.PhysicalMax;
776 if (wine_element->caps.value.IsRange)
778 wine_element->caps.value.u.Range.UsageMin = feature->caps.u.Range.UsageMin;
779 wine_element->caps.value.u.Range.UsageMax = feature->caps.u.Range.UsageMax;
780 wine_element->caps.value.u.Range.StringMin = feature->caps.u.Range.StringMin;
781 wine_element->caps.value.u.Range.StringMax = feature->caps.u.Range.StringMax;
782 wine_element->caps.value.u.Range.DesignatorMin = feature->caps.u.Range.DesignatorMin;
783 wine_element->caps.value.u.Range.DesignatorMax = feature->caps.u.Range.DesignatorMax;
784 wine_element->caps.value.u.Range.DataIndexMin = *data_index;
785 wine_element->caps.value.u.Range.DataIndexMax = *data_index +
786 (wine_element->caps.value.u.Range.UsageMax -
787 wine_element->caps.value.u.Range.UsageMin);
788 *data_index = *data_index +
789 (wine_element->caps.value.u.Range.UsageMax -
790 wine_element->caps.value.u.Range.UsageMin) + 1;
792 else
794 wine_element->caps.value.u.NotRange.Usage = feature->caps.u.NotRange.Usage[i];
795 wine_element->caps.value.u.NotRange.StringIndex = feature->caps.u.NotRange.StringIndex;
796 wine_element->caps.value.u.NotRange.DesignatorIndex = feature->caps.u.NotRange.DesignatorIndex;
797 wine_element->caps.value.u.NotRange.DataIndex = *data_index;
798 *data_index = *data_index + 1;
802 wine_report->elementCount++;
806 static void count_elements(struct feature* feature, USHORT *buttons, USHORT *values)
808 if (feature->caps.UsagePage == HID_USAGE_PAGE_BUTTON)
810 if (feature->caps.IsRange)
811 *buttons = *buttons + 1;
812 else
813 *buttons = *buttons + feature->caps.usage_count;
815 else
817 if (feature->caps.IsRange)
818 *values = *values + 1;
819 else
820 *values = *values + feature->caps.usage_count;
824 static WINE_HIDP_PREPARSED_DATA* build_PreparseData(
825 struct feature **features, int feature_count,
826 struct feature **input_features, int i_count,
827 struct feature **output_features, int o_count,
828 struct feature **feature_features, int f_count,
829 struct collection *base_collection)
831 WINE_HIDP_PREPARSED_DATA *data;
832 WINE_HID_REPORT *wine_report = NULL;
833 DWORD bitOffset, bitLength;
834 unsigned int report_count = 1;
835 unsigned int i;
836 unsigned int element_count;
837 unsigned int size = 0;
838 unsigned int data_index;
840 if (features[0]->caps.ReportID != 0)
842 unsigned int *report_ids;
843 unsigned int cnt = max(i_count, o_count);
844 cnt = max(cnt, f_count);
845 report_ids = HeapAlloc(GetProcessHeap(), 0 , sizeof(*report_ids) * cnt);
847 if (i_count)
849 report_ids[0] = input_features[0]->caps.ReportID;
850 for (i = 1; i < i_count; i++)
852 unsigned int j;
853 unsigned int found = FALSE;
854 for (j = 0; !found && j < i_count; j++)
856 if (report_ids[j] == input_features[i]->caps.ReportID)
857 found = TRUE;
859 if (!found)
861 report_ids[report_count] = input_features[i]->caps.ReportID;
862 report_count++;
866 if (o_count)
868 report_count++;
869 report_ids[0] = output_features[0]->caps.ReportID;
870 for (i = 1; i < o_count; i++)
872 unsigned int j;
873 unsigned int found = FALSE;
874 for (j = 0; !found && j < o_count; j++)
876 if (report_ids[j] == output_features[i]->caps.ReportID)
877 found = TRUE;
879 if (!found)
881 report_ids[report_count] = output_features[i]->caps.ReportID;
882 report_count++;
886 if (f_count)
888 report_count++;
889 report_ids[0] = feature_features[0]->caps.ReportID;
890 for (i = 1; i < f_count; i++)
892 unsigned int j;
893 unsigned int found = FALSE;
894 for (j = 0; !found && j < f_count; j++)
896 if (report_ids[j] == feature_features[i]->caps.ReportID)
897 found = TRUE;
899 if (!found)
901 report_ids[report_count] = feature_features[i]->caps.ReportID;
902 report_count++;
906 HeapFree(GetProcessHeap(), 0, report_ids);
908 else
910 if (o_count) report_count++;
911 if (f_count) report_count++;
914 element_count = 0;
915 for (i = 0; i < feature_count; i++)
916 element_count += features[i]->caps.usage_count;
918 size = sizeof(WINE_HIDP_PREPARSED_DATA) +
919 (element_count * sizeof(WINE_HID_ELEMENT)) +
920 (report_count * sizeof(WINE_HID_REPORT));
922 TRACE("%i reports %i elements -> size %i\n",report_count, element_count, size);
924 data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
925 data->magic = HID_MAGIC;
926 data->dwSize = size;
927 data->caps.Usage = base_collection->caps.u.NotRange.Usage[0];
928 data->caps.UsagePage = base_collection->caps.UsagePage;
930 wine_report = data->InputReports;
931 if (i_count)
933 data_index = 0;
934 bitLength = 0;
935 new_report(wine_report, input_features[0]);
936 data->dwInputReportCount++;
938 /* Room for the reportID */
939 bitOffset = 8;
941 for (i = 0; i < i_count; i++)
943 if (input_features[i]->caps.ReportID != wine_report->reportID)
945 wine_report->dwSize += (sizeof(WINE_HID_ELEMENT) * wine_report->elementCount);
946 wine_report = (WINE_HID_REPORT*)(((BYTE*)wine_report)+wine_report->dwSize);
947 new_report(wine_report, input_features[i]);
948 data->dwInputReportCount++;
949 bitLength = max(bitOffset, bitLength);
950 bitOffset = 8;
952 build_elements(wine_report, input_features[i], &bitOffset, &data_index);
953 count_elements(input_features[i], &data->caps.NumberInputButtonCaps,
954 &data->caps.NumberInputValueCaps);
956 wine_report->dwSize += (sizeof(WINE_HID_ELEMENT) * wine_report->elementCount);
957 bitLength = max(bitOffset, bitLength);
958 data->caps.InputReportByteLength = ((bitLength + 7) & ~7)/8;
959 data->caps.NumberInputDataIndices = data_index;
962 if (o_count)
964 data_index = 0;
965 bitLength = 0;
966 wine_report = (WINE_HID_REPORT*)(((BYTE*)wine_report)+wine_report->dwSize);
967 data->dwOutputReportOffset = (BYTE*)wine_report - (BYTE*)data->InputReports;
968 new_report(wine_report, output_features[0]);
969 data->dwOutputReportCount++;
970 bitOffset = 8;
972 for (i = 0; i < o_count; i++)
974 if (output_features[i]->caps.ReportID != wine_report->reportID)
976 wine_report->dwSize += (sizeof(WINE_HID_ELEMENT) * wine_report->elementCount);
977 wine_report = (WINE_HID_REPORT*)(((BYTE*)wine_report)+wine_report->dwSize);
978 new_report(wine_report, output_features[i]);
979 data->dwOutputReportCount++;
980 bitLength = max(bitOffset, bitLength);
981 bitOffset = 8;
983 build_elements(wine_report, output_features[i], &bitOffset, &data_index);
984 count_elements(output_features[i], &data->caps.NumberOutputButtonCaps,
985 &data->caps.NumberOutputValueCaps);
987 wine_report->dwSize += (sizeof(WINE_HID_ELEMENT) * wine_report->elementCount);
988 bitLength = max(bitOffset, bitLength);
989 data->caps.OutputReportByteLength = ((bitLength + 7) & ~7)/8;
990 data->caps.NumberOutputDataIndices = data_index;
993 if (f_count)
995 data_index = 0;
996 bitLength = 0;
997 wine_report = (WINE_HID_REPORT*)(((BYTE*)wine_report)+wine_report->dwSize);
998 data->dwFeatureReportOffset = (BYTE*)wine_report - (BYTE*)data->InputReports;
999 new_report(wine_report, feature_features[0]);
1000 data->dwFeatureReportCount++;
1001 bitOffset = 8;
1003 for (i = 0; i < f_count; i++)
1005 if (feature_features[i]->caps.ReportID != wine_report->reportID)
1007 wine_report->dwSize += (sizeof(WINE_HID_ELEMENT) * wine_report->elementCount);
1008 wine_report = (WINE_HID_REPORT*)((BYTE*)wine_report+wine_report->dwSize);
1009 new_report(wine_report, feature_features[i]);
1010 data->dwFeatureReportCount++;
1011 bitLength = max(bitOffset, bitLength);
1012 bitOffset = 8;
1014 build_elements(wine_report, feature_features[i], &bitOffset, &data_index);
1015 count_elements(feature_features[i], &data->caps.NumberFeatureButtonCaps,
1016 &data->caps.NumberFeatureValueCaps);
1018 bitLength = max(bitOffset, bitLength);
1019 data->caps.FeatureReportByteLength = ((bitLength + 7) & ~7)/8;
1020 data->caps.NumberFeatureDataIndices = data_index;
1023 return data;
1026 static void free_collection(struct collection *collection)
1028 struct feature *fentry, *fnext;
1029 struct collection *centry, *cnext;
1030 LIST_FOR_EACH_ENTRY_SAFE(centry, cnext, &collection->collections, struct collection, entry)
1032 list_remove(&centry->entry);
1033 free_collection(centry);
1035 LIST_FOR_EACH_ENTRY_SAFE(fentry, fnext, &collection->features, struct feature, col_entry)
1037 list_remove(&fentry->col_entry);
1038 HeapFree(GetProcessHeap(), 0, fentry);
1040 HeapFree(GetProcessHeap(), 0, collection);
1043 static int compare_reports(const void *a, const void* b)
1045 struct feature *f1 = *(struct feature **)a;
1046 struct feature *f2 = *(struct feature **)b;
1047 int c = (f1->caps.ReportID - f2->caps.ReportID);
1048 if (c) return c;
1049 return (f1->index - f2->index);
1052 WINE_HIDP_PREPARSED_DATA* ParseDescriptor(BYTE *descriptor, unsigned int length)
1054 WINE_HIDP_PREPARSED_DATA *data = NULL;
1055 struct collection *base;
1056 struct caps caps;
1058 struct list features;
1059 struct list caps_stack;
1061 unsigned int feature_count = 0;
1062 unsigned int cidx;
1064 if (TRACE_ON(hid))
1066 TRACE("Descriptor[%i]: ", length);
1067 for (cidx = 0; cidx < length; cidx++)
1069 TRACE("%x ",descriptor[cidx]);
1070 if ((cidx+1) % 80 == 0)
1071 TRACE("\n");
1073 TRACE("\n");
1076 list_init(&features);
1077 list_init(&caps_stack);
1079 base = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*base));
1080 base->index = 1;
1081 list_init(&base->features);
1082 list_init(&base->collections);
1083 memset(&caps, 0, sizeof(caps));
1085 cidx = 0;
1086 parse_descriptor(descriptor, 0, length, &feature_count, &cidx, base, &caps, &features, &caps_stack);
1088 debug_collection(base);
1090 if (!list_empty(&caps_stack))
1092 struct caps_stack *entry, *cursor;
1093 ERR("%i unpopped device caps on the stack\n", list_count(&caps_stack));
1094 LIST_FOR_EACH_ENTRY_SAFE(entry, cursor, &caps_stack, struct caps_stack, entry)
1096 list_remove(&entry->entry);
1097 HeapFree(GetProcessHeap(), 0, entry);
1101 cidx = 2;
1102 if (feature_count)
1104 struct feature *entry;
1105 struct feature** sorted_features;
1106 struct feature** input_features;
1107 struct feature** output_features;
1108 struct feature** feature_features;
1109 unsigned int i_count, o_count, f_count;
1110 unsigned int i;
1112 i_count = o_count = f_count = 0;
1114 sorted_features = HeapAlloc(GetProcessHeap(), 0, sizeof(*sorted_features) * feature_count);
1115 input_features = HeapAlloc(GetProcessHeap(), 0, sizeof(*input_features) * feature_count);
1116 output_features = HeapAlloc(GetProcessHeap(), 0, sizeof(*output_features) * feature_count);
1117 feature_features = HeapAlloc(GetProcessHeap(), 0, sizeof(*feature_features) * feature_count);
1119 i = 0;
1120 LIST_FOR_EACH_ENTRY(entry, &features, struct feature, entry)
1121 sorted_features[i++] = entry;
1123 /* Sort features base on report if there are multiple reports */
1124 if (sorted_features[0]->caps.ReportID != 0)
1125 qsort(sorted_features, feature_count, sizeof(struct feature*), compare_reports);
1127 for (i = 0; i < feature_count; i++)
1129 switch (sorted_features[i]->type)
1131 case HidP_Input:
1132 input_features[i_count] = sorted_features[i];
1133 i_count++;
1134 break;
1135 case HidP_Output:
1136 output_features[o_count] = sorted_features[i];
1137 o_count++;
1138 break;
1139 case HidP_Feature:
1140 feature_features[f_count] = sorted_features[i];
1141 f_count++;
1142 break;
1143 default:
1144 ERR("Unknown type %i\n",sorted_features[i]->type);
1148 if (TRACE_ON(hid))
1150 TRACE("DUMP FEATURES:\n");
1151 TRACE("----INPUT----\n");
1152 for (cidx = 0; cidx < i_count; cidx++)
1153 debug_feature(input_features[cidx]);
1154 TRACE("----OUTPUT----\n");
1155 for (cidx = 0; cidx < o_count; cidx++)
1156 debug_feature(output_features[cidx]);
1157 TRACE("----FEATURE----\n");
1158 for (cidx = 0; cidx < f_count; cidx++)
1159 debug_feature(feature_features[cidx]);
1162 data = build_PreparseData(sorted_features, feature_count, input_features, i_count, output_features, o_count, feature_features, f_count, base);
1164 debug_print_preparsed(data);
1166 HeapFree(GetProcessHeap(), 0, sorted_features);
1167 HeapFree(GetProcessHeap(), 0, input_features);
1168 HeapFree(GetProcessHeap(), 0, output_features);
1169 HeapFree(GetProcessHeap(), 0, feature_features);
1172 free_collection(base);
1173 /* We do not have to free the list as free_collection does all the work */
1175 return data;