mstask: Implement ITask::DeleteTrigger().
[wine.git] / dlls / hidclass.sys / descriptor.c
blob6b8499716347a9fdc1eb596a986a45ca711e0bc8
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)
445 collection->type = itemVal;
447 if (itemVal >= 0x07 && itemVal <= 0x7F) {
448 ERR(" (Reserved 0x%x )\n", itemVal);
450 else if (itemVal >= 0x80 && itemVal <= 0xFF) {
451 ERR(" (Vendor Defined 0x%x )\n", itemVal);
456 static void new_caps(struct caps *caps)
458 caps->IsRange = 0;
459 caps->IsStringRange = 0;
460 caps->IsDesignatorRange = 0;
461 caps->usage_count = 0;
464 static int parse_descriptor(BYTE *descriptor, unsigned int index, unsigned int length,
465 unsigned int *feature_index, unsigned int *collection_index,
466 struct collection *collection, struct caps *caps,
467 struct list *features, struct list *stack)
469 unsigned int i;
470 for (i = index; i < length;)
472 BYTE b0 = descriptor[i++];
473 int bSize = b0 & 0x03;
474 int bType = (b0 >> 2) & 0x03;
475 int bTag = (b0 >> 4) & 0x0F;
477 bSize = (bSize == 3) ? 4 : bSize;
478 if (bType == TAG_TYPE_RESERVED && bTag == 0x0F && bSize == 2 &&
479 i + 2 < length)
481 /* Long data items: Should be unused */
482 ERR("Long Data Item, should be unused\n");
484 else
486 int bSizeActual = 0;
487 int itemVal = 0;
488 unsigned int j;
490 for (j = 0; j < bSize; j++)
492 if (i + j < length)
494 itemVal += descriptor[i + j] << (8 * j);
495 bSizeActual++;
498 TRACE(" 0x%x[%i], type %i , tag %i, size %i, val %i\n",b0,i-1,bType, bTag, bSize, itemVal );
500 if (bType == TAG_TYPE_MAIN)
502 struct feature *feature;
503 switch(bTag)
505 case TAG_MAIN_INPUT:
506 feature = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*feature));
507 list_add_tail(&collection->features, &feature->col_entry);
508 list_add_tail(features, &feature->entry);
509 feature->type = HidP_Input;
510 parse_io_feature(bSize, itemVal, bTag, feature_index, feature);
511 feature->caps = *caps;
512 feature->collection = collection;
513 new_caps(caps);
514 break;
515 case TAG_MAIN_OUTPUT:
516 feature = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*feature));
517 list_add_tail(&collection->features, &feature->col_entry);
518 list_add_tail(features, &feature->entry);
519 feature->type = HidP_Output;
520 parse_io_feature(bSize, itemVal, bTag, feature_index, feature);
521 feature->caps = *caps;
522 feature->collection = collection;
523 new_caps(caps);
524 break;
525 case TAG_MAIN_FEATURE:
526 feature = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*feature));
527 list_add_tail(&collection->features, &feature->col_entry);
528 list_add_tail(features, &feature->entry);
529 feature->type = HidP_Feature;
530 parse_io_feature(bSize, itemVal, bTag, feature_index, feature);
531 feature->caps = *caps;
532 feature->collection = collection;
533 new_caps(caps);
534 break;
535 case TAG_MAIN_COLLECTION:
537 struct collection *subcollection = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct collection));
538 list_add_tail(&collection->collections, &subcollection->entry);
539 subcollection->parent = collection;
540 /* Only set our collection once...
541 We do not properly handle composite devices yet. */
542 if (*collection_index == 0)
543 collection->caps = *caps;
544 subcollection->caps = *caps;
545 subcollection->index = *collection_index;
546 *collection_index = *collection_index + 1;
547 list_init(&subcollection->features);
548 list_init(&subcollection->collections);
549 new_caps(caps);
551 parse_collection(bSize, itemVal, subcollection);
553 i = parse_descriptor(descriptor, i+1, length, feature_index, collection_index, subcollection, caps, features, stack);
554 continue;
556 case TAG_MAIN_END_COLLECTION:
557 return i;
558 default:
559 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType);
562 else if (bType == TAG_TYPE_GLOBAL)
564 switch(bTag)
566 case TAG_GLOBAL_USAGE_PAGE:
567 caps->UsagePage = getValue(bSize, itemVal, FALSE);
568 break;
569 case TAG_GLOBAL_LOGICAL_MINIMUM:
570 caps->LogicalMin = getValue(bSize, itemVal, TRUE);
571 break;
572 case TAG_GLOBAL_LOGICAL_MAXIMUM:
573 caps->LogicalMax = getValue(bSize, itemVal, TRUE);
574 break;
575 case TAG_GLOBAL_PHYSICAL_MINIMUM:
576 caps->PhysicalMin = getValue(bSize, itemVal, TRUE);
577 break;
578 case TAG_GLOBAL_PHYSICAL_MAXIMUM:
579 caps->PhysicalMax = getValue(bSize, itemVal, TRUE);
580 break;
581 case TAG_GLOBAL_UNIT_EXPONENT:
582 caps->UnitsExp = getValue(bSize, itemVal, TRUE);
583 break;
584 case TAG_GLOBAL_UNIT:
585 caps->Units = getValue(bSize, itemVal, TRUE);
586 break;
587 case TAG_GLOBAL_REPORT_SIZE:
588 caps->BitSize = getValue(bSize, itemVal, FALSE);
589 break;
590 case TAG_GLOBAL_REPORT_ID:
591 caps->ReportID = getValue(bSize, itemVal, FALSE);
592 break;
593 case TAG_GLOBAL_REPORT_COUNT:
594 caps->ReportCount = getValue(bSize, itemVal, FALSE);
595 break;
596 case TAG_GLOBAL_PUSH:
598 struct caps_stack *saved = HeapAlloc(GetProcessHeap(), 0, sizeof(*saved));
599 saved->caps = *caps;
600 TRACE("Push\n");
601 list_add_tail(stack, &saved->entry);
602 break;
604 case TAG_GLOBAL_POP:
606 struct list *tail;
607 struct caps_stack *saved;
608 TRACE("Pop\n");
609 tail = list_tail(stack);
610 if (tail)
612 saved = LIST_ENTRY(tail, struct caps_stack, entry);
613 *caps = saved->caps;
614 list_remove(tail);
615 HeapFree(GetProcessHeap(), 0, saved);
617 else
618 ERR("Pop but no stack!\n");
619 break;
621 default:
622 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType);
625 else if (bType == TAG_TYPE_LOCAL)
627 switch(bTag)
629 case TAG_LOCAL_USAGE:
630 if (caps->usage_count >= USAGE_MAX)
631 FIXME("More than %i individual usages defined\n",USAGE_MAX);
632 else
634 caps->u.NotRange.Usage[caps->usage_count++] = getValue(bSize, itemVal, FALSE);
635 caps->IsRange = FALSE;
637 break;
638 case TAG_LOCAL_USAGE_MINIMUM:
639 caps->usage_count = 1;
640 caps->u.Range.UsageMin = getValue(bSize, itemVal, FALSE);
641 caps->IsRange = TRUE;
642 break;
643 case TAG_LOCAL_USAGE_MAXIMUM:
644 caps->usage_count = 1;
645 caps->u.Range.UsageMax = getValue(bSize, itemVal, FALSE);
646 caps->IsRange = TRUE;
647 break;
648 case TAG_LOCAL_DESIGNATOR_INDEX:
649 caps->u.NotRange.DesignatorIndex = getValue(bSize, itemVal, FALSE);
650 caps->IsDesignatorRange = FALSE;
651 break;
652 case TAG_LOCAL_DESIGNATOR_MINIMUM:
653 caps->u.Range.DesignatorMin = getValue(bSize, itemVal, FALSE);
654 caps->IsDesignatorRange = TRUE;
655 break;
656 case TAG_LOCAL_DESIGNATOR_MAXIMUM:
657 caps->u.Range.DesignatorMax = getValue(bSize, itemVal, FALSE);
658 caps->IsDesignatorRange = TRUE;
659 break;
660 case TAG_LOCAL_STRING_INDEX:
661 caps->u.NotRange.StringIndex = getValue(bSize, itemVal, FALSE);
662 caps->IsStringRange = FALSE;
663 break;
664 case TAG_LOCAL_STRING_MINIMUM:
665 caps->u.Range.StringMin = getValue(bSize, itemVal, FALSE);
666 caps->IsStringRange = TRUE;
667 break;
668 case TAG_LOCAL_STRING_MAXIMUM:
669 caps->u.Range.StringMax = getValue(bSize, itemVal, FALSE);
670 caps->IsStringRange = TRUE;
671 break;
672 case TAG_LOCAL_DELIMITER:
673 caps->Delim = getValue(bSize, itemVal, FALSE);
674 break;
675 default:
676 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType);
679 else
680 ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType);
682 i += bSize;
685 return i;
688 static inline void new_report(WINE_HID_REPORT *wine_report, struct feature* feature)
690 wine_report->reportID = feature->caps.ReportID;
691 wine_report->dwSize = sizeof(*wine_report) - sizeof(WINE_HID_ELEMENT);
692 wine_report->elementCount = 0;
695 static void build_elements(WINE_HID_REPORT *wine_report, struct feature* feature, DWORD *bitOffset, unsigned int *data_index)
697 unsigned int i;
699 if (!feature->isData)
701 *bitOffset = *bitOffset + (feature->caps.BitSize * feature->caps.ReportCount);
702 return;
705 for (i = 0; i < feature->caps.usage_count; i++)
707 WINE_HID_ELEMENT *wine_element = &wine_report->Elements[wine_report->elementCount];
709 wine_element->valueStartBit = *bitOffset;
710 if (feature->caps.UsagePage == HID_USAGE_PAGE_BUTTON)
712 wine_element->ElementType = ButtonElement;
713 wine_element->caps.button.UsagePage = feature->caps.UsagePage;
714 wine_element->caps.button.ReportID = feature->caps.ReportID;
715 wine_element->caps.button.BitField = feature->BitField;
716 wine_element->caps.button.IsRange = feature->caps.IsRange;
717 wine_element->caps.button.IsStringRange = feature->caps.IsStringRange;
718 wine_element->caps.button.IsDesignatorRange = feature->caps.IsDesignatorRange;
719 wine_element->caps.button.IsAbsolute = feature->IsAbsolute;
720 if (wine_element->caps.button.IsRange)
722 wine_element->bitCount = (feature->caps.u.Range.UsageMax - feature->caps.u.Range.UsageMin) + 1;
723 *bitOffset = *bitOffset + wine_element->bitCount;
724 wine_element->caps.button.u.Range.UsageMin = feature->caps.u.Range.UsageMin;
725 wine_element->caps.button.u.Range.UsageMax = feature->caps.u.Range.UsageMax;
726 wine_element->caps.button.u.Range.StringMin = feature->caps.u.Range.StringMin;
727 wine_element->caps.button.u.Range.StringMax = feature->caps.u.Range.StringMax;
728 wine_element->caps.button.u.Range.DesignatorMin = feature->caps.u.Range.DesignatorMin;
729 wine_element->caps.button.u.Range.DesignatorMax = feature->caps.u.Range.DesignatorMax;
730 wine_element->caps.button.u.Range.DataIndexMin = *data_index;
731 wine_element->caps.button.u.Range.DataIndexMax = *data_index + wine_element->bitCount - 1;
732 *data_index = *data_index + wine_element->bitCount;
734 else
736 *bitOffset = *bitOffset + 1;
737 wine_element->bitCount = 1;
738 wine_element->caps.button.u.NotRange.Usage = feature->caps.u.NotRange.Usage[i];
739 wine_element->caps.button.u.NotRange.StringIndex = feature->caps.u.NotRange.StringIndex;
740 wine_element->caps.button.u.NotRange.DesignatorIndex = feature->caps.u.NotRange.DesignatorIndex;
741 wine_element->caps.button.u.NotRange.DataIndex = *data_index;
742 *data_index = *data_index + 1;
745 else
747 wine_element->ElementType = ValueElement;
748 wine_element->caps.value.UsagePage = feature->caps.UsagePage;
749 wine_element->caps.value.ReportID = feature->caps.ReportID;
750 wine_element->caps.value.BitField = feature->BitField;
751 wine_element->caps.value.IsRange = feature->caps.IsRange;
752 wine_element->caps.value.IsStringRange = feature->caps.IsStringRange;
753 wine_element->caps.value.IsDesignatorRange = feature->caps.IsDesignatorRange;
754 wine_element->caps.value.IsAbsolute = feature->IsAbsolute;
755 wine_element->caps.value.HasNull = feature->HasNull;
756 wine_element->caps.value.BitSize = feature->caps.BitSize;
757 if (feature->caps.usage_count > 1)
759 if (feature->caps.ReportCount > feature->caps.usage_count)
760 wine_element->caps.value.ReportCount = feature->caps.ReportCount / feature->caps.usage_count;
761 else
762 wine_element->caps.value.ReportCount = 1;
764 else
765 wine_element->caps.value.ReportCount = feature->caps.ReportCount;
766 wine_element->bitCount = (feature->caps.BitSize * wine_element->caps.value.ReportCount);
767 *bitOffset = *bitOffset + wine_element->bitCount;
768 wine_element->caps.value.UnitsExp = feature->caps.UnitsExp;
769 wine_element->caps.value.Units = feature->caps.Units;
770 wine_element->caps.value.LogicalMin = feature->caps.LogicalMin;
771 wine_element->caps.value.LogicalMax = feature->caps.LogicalMax;
772 wine_element->caps.value.PhysicalMin = feature->caps.PhysicalMin;
773 wine_element->caps.value.PhysicalMax = feature->caps.PhysicalMax;
774 if (wine_element->caps.value.IsRange)
776 wine_element->caps.value.u.Range.UsageMin = feature->caps.u.Range.UsageMin;
777 wine_element->caps.value.u.Range.UsageMax = feature->caps.u.Range.UsageMax;
778 wine_element->caps.value.u.Range.StringMin = feature->caps.u.Range.StringMin;
779 wine_element->caps.value.u.Range.StringMax = feature->caps.u.Range.StringMax;
780 wine_element->caps.value.u.Range.DesignatorMin = feature->caps.u.Range.DesignatorMin;
781 wine_element->caps.value.u.Range.DesignatorMax = feature->caps.u.Range.DesignatorMax;
782 wine_element->caps.value.u.Range.DataIndexMin = *data_index;
783 wine_element->caps.value.u.Range.DataIndexMax = *data_index +
784 (wine_element->caps.value.u.Range.UsageMax -
785 wine_element->caps.value.u.Range.UsageMin);
786 *data_index = *data_index +
787 (wine_element->caps.value.u.Range.UsageMax -
788 wine_element->caps.value.u.Range.UsageMin) + 1;
790 else
792 wine_element->caps.value.u.NotRange.Usage = feature->caps.u.NotRange.Usage[i];
793 wine_element->caps.value.u.NotRange.StringIndex = feature->caps.u.NotRange.StringIndex;
794 wine_element->caps.value.u.NotRange.DesignatorIndex = feature->caps.u.NotRange.DesignatorIndex;
795 wine_element->caps.value.u.NotRange.DataIndex = *data_index;
796 *data_index = *data_index + 1;
800 wine_report->elementCount++;
804 static void count_elements(struct feature* feature, USHORT *buttons, USHORT *values)
806 if (feature->caps.UsagePage == HID_USAGE_PAGE_BUTTON)
808 if (feature->caps.IsRange)
809 *buttons = *buttons + 1;
810 else
811 *buttons = *buttons + feature->caps.usage_count;
813 else
815 if (feature->caps.IsRange)
816 *values = *values + 1;
817 else
818 *values = *values + feature->caps.usage_count;
822 static WINE_HIDP_PREPARSED_DATA* build_PreparseData(
823 struct feature **features, int feature_count,
824 struct feature **input_features, int i_count,
825 struct feature **output_features, int o_count,
826 struct feature **feature_features, int f_count,
827 struct collection *base_collection)
829 WINE_HIDP_PREPARSED_DATA *data;
830 WINE_HID_REPORT *wine_report = NULL;
831 DWORD bitOffset, bitLength;
832 unsigned int report_count = 1;
833 unsigned int i;
834 unsigned int element_count;
835 unsigned int size = 0;
836 unsigned int data_index;
838 if (features[0]->caps.ReportID != 0)
840 unsigned int *report_ids;
841 unsigned int cnt = max(i_count, o_count);
842 cnt = max(cnt, f_count);
843 report_ids = HeapAlloc(GetProcessHeap(), 0 , sizeof(*report_ids) * cnt);
845 if (i_count)
847 report_ids[0] = input_features[0]->caps.ReportID;
848 for (i = 1; i < i_count; i++)
850 unsigned int j;
851 unsigned int found = FALSE;
852 for (j = 0; !found && j < i_count; j++)
854 if (report_ids[j] == input_features[i]->caps.ReportID)
855 found = TRUE;
857 if (!found)
859 report_ids[report_count] = input_features[i]->caps.ReportID;
860 report_count++;
864 if (o_count)
866 report_count++;
867 report_ids[0] = output_features[0]->caps.ReportID;
868 for (i = 1; i < o_count; i++)
870 unsigned int j;
871 unsigned int found = FALSE;
872 for (j = 0; !found && j < o_count; j++)
874 if (report_ids[j] == output_features[i]->caps.ReportID)
875 found = TRUE;
877 if (!found)
879 report_ids[report_count] = output_features[i]->caps.ReportID;
880 report_count++;
884 if (f_count)
886 report_count++;
887 report_ids[0] = feature_features[0]->caps.ReportID;
888 for (i = 1; i < f_count; i++)
890 unsigned int j;
891 unsigned int found = FALSE;
892 for (j = 0; !found && j < f_count; j++)
894 if (report_ids[j] == feature_features[i]->caps.ReportID)
895 found = TRUE;
897 if (!found)
899 report_ids[report_count] = feature_features[i]->caps.ReportID;
900 report_count++;
904 HeapFree(GetProcessHeap(), 0, report_ids);
906 else
908 if (o_count) report_count++;
909 if (f_count) report_count++;
912 element_count = 0;
913 for (i = 0; i < feature_count; i++)
914 element_count += features[i]->caps.usage_count;
916 size = sizeof(WINE_HIDP_PREPARSED_DATA) +
917 (element_count * sizeof(WINE_HID_ELEMENT)) +
918 (report_count * sizeof(WINE_HID_REPORT));
920 TRACE("%i reports %i elements -> size %i\n",report_count, element_count, size);
922 data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
923 data->magic = HID_MAGIC;
924 data->dwSize = size;
925 data->caps.Usage = base_collection->caps.u.NotRange.Usage[0];
926 data->caps.UsagePage = base_collection->caps.UsagePage;
928 wine_report = data->InputReports;
929 if (i_count)
931 data_index = 0;
932 bitLength = 0;
933 new_report(wine_report, input_features[0]);
934 data->dwInputReportCount++;
936 /* Room for the reportID */
937 bitOffset = 8;
939 for (i = 0; i < i_count; i++)
941 if (input_features[i]->caps.ReportID != wine_report->reportID)
943 wine_report->dwSize += (sizeof(WINE_HID_ELEMENT) * wine_report->elementCount);
944 wine_report = (WINE_HID_REPORT*)(((BYTE*)wine_report)+wine_report->dwSize);
945 new_report(wine_report, input_features[i]);
946 data->dwInputReportCount++;
947 bitLength = max(bitOffset, bitLength);
948 bitOffset = 8;
950 build_elements(wine_report, input_features[i], &bitOffset, &data_index);
951 count_elements(input_features[i], &data->caps.NumberInputButtonCaps,
952 &data->caps.NumberInputValueCaps);
954 wine_report->dwSize += (sizeof(WINE_HID_ELEMENT) * wine_report->elementCount);
955 bitLength = max(bitOffset, bitLength);
956 data->caps.InputReportByteLength = ((bitLength + 7) & ~7)/8;
957 data->caps.NumberInputDataIndices = data_index;
960 if (o_count)
962 data_index = 0;
963 bitLength = 0;
964 wine_report = (WINE_HID_REPORT*)(((BYTE*)wine_report)+wine_report->dwSize);
965 data->dwOutputReportOffset = (BYTE*)wine_report - (BYTE*)data->InputReports;
966 new_report(wine_report, output_features[0]);
967 data->dwOutputReportCount++;
968 bitOffset = 8;
970 for (i = 0; i < o_count; i++)
972 if (output_features[i]->caps.ReportID != wine_report->reportID)
974 wine_report->dwSize += (sizeof(WINE_HID_ELEMENT) * wine_report->elementCount);
975 wine_report = (WINE_HID_REPORT*)(((BYTE*)wine_report)+wine_report->dwSize);
976 new_report(wine_report, output_features[i]);
977 data->dwOutputReportCount++;
978 bitLength = max(bitOffset, bitLength);
979 bitOffset = 8;
981 build_elements(wine_report, output_features[i], &bitOffset, &data_index);
982 count_elements(output_features[i], &data->caps.NumberOutputButtonCaps,
983 &data->caps.NumberOutputValueCaps);
985 wine_report->dwSize += (sizeof(WINE_HID_ELEMENT) * wine_report->elementCount);
986 bitLength = max(bitOffset, bitLength);
987 data->caps.OutputReportByteLength = ((bitLength + 7) & ~7)/8;
988 data->caps.NumberOutputDataIndices = data_index;
991 if (f_count)
993 data_index = 0;
994 bitLength = 0;
995 wine_report = (WINE_HID_REPORT*)(((BYTE*)wine_report)+wine_report->dwSize);
996 data->dwFeatureReportOffset = (BYTE*)wine_report - (BYTE*)data->InputReports;
997 new_report(wine_report, feature_features[0]);
998 data->dwFeatureReportCount++;
999 bitOffset = 8;
1001 for (i = 0; i < f_count; i++)
1003 if (feature_features[i]->caps.ReportID != wine_report->reportID)
1005 wine_report->dwSize += (sizeof(WINE_HID_ELEMENT) * wine_report->elementCount);
1006 wine_report = (WINE_HID_REPORT*)((BYTE*)wine_report+wine_report->dwSize);
1007 new_report(wine_report, feature_features[i]);
1008 data->dwFeatureReportCount++;
1009 bitLength = max(bitOffset, bitLength);
1010 bitOffset = 8;
1012 build_elements(wine_report, feature_features[i], &bitOffset, &data_index);
1013 count_elements(feature_features[i], &data->caps.NumberFeatureButtonCaps,
1014 &data->caps.NumberFeatureValueCaps);
1016 bitLength = max(bitOffset, bitLength);
1017 data->caps.FeatureReportByteLength = ((bitLength + 7) & ~7)/8;
1018 data->caps.NumberFeatureDataIndices = data_index;
1021 return data;
1024 static void free_collection(struct collection *collection)
1026 struct feature *fentry, *fnext;
1027 struct collection *centry, *cnext;
1028 LIST_FOR_EACH_ENTRY_SAFE(centry, cnext, &collection->collections, struct collection, entry)
1030 list_remove(&centry->entry);
1031 free_collection(centry);
1033 LIST_FOR_EACH_ENTRY_SAFE(fentry, fnext, &collection->features, struct feature, col_entry)
1035 list_remove(&fentry->col_entry);
1036 HeapFree(GetProcessHeap(), 0, fentry);
1038 HeapFree(GetProcessHeap(), 0, collection);
1041 static int compare_reports(const void *a, const void* b)
1043 struct feature *f1 = *(struct feature **)a;
1044 struct feature *f2 = *(struct feature **)b;
1045 int c = (f1->caps.ReportID - f2->caps.ReportID);
1046 if (c) return c;
1047 return (f1->index - f2->index);
1050 WINE_HIDP_PREPARSED_DATA* ParseDescriptor(BYTE *descriptor, unsigned int length)
1052 WINE_HIDP_PREPARSED_DATA *data = NULL;
1053 struct collection *base;
1054 struct caps caps;
1056 struct list features;
1057 struct list caps_stack;
1059 unsigned int feature_count = 0;
1060 unsigned int cidx;
1062 if (TRACE_ON(hid))
1064 TRACE("Descriptor[%i]: ", length);
1065 for (cidx = 0; cidx < length; cidx++)
1067 TRACE("%x ",descriptor[cidx]);
1068 if ((cidx+1) % 80 == 0)
1069 TRACE("\n");
1071 TRACE("\n");
1074 list_init(&features);
1075 list_init(&caps_stack);
1077 base = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*base));
1078 base->index = 1;
1079 list_init(&base->features);
1080 list_init(&base->collections);
1081 memset(&caps, 0, sizeof(caps));
1083 cidx = 0;
1084 parse_descriptor(descriptor, 0, length, &feature_count, &cidx, base, &caps, &features, &caps_stack);
1086 debug_collection(base);
1088 if (!list_empty(&caps_stack))
1090 struct caps_stack *entry, *cursor;
1091 ERR("%i unpopped device caps on the stack\n", list_count(&caps_stack));
1092 LIST_FOR_EACH_ENTRY_SAFE(entry, cursor, &caps_stack, struct caps_stack, entry)
1094 list_remove(&entry->entry);
1095 HeapFree(GetProcessHeap(), 0, entry);
1099 cidx = 2;
1100 if (feature_count)
1102 struct feature *entry;
1103 struct feature** sorted_features;
1104 struct feature** input_features;
1105 struct feature** output_features;
1106 struct feature** feature_features;
1107 unsigned int i_count, o_count, f_count;
1108 unsigned int i;
1110 i_count = o_count = f_count = 0;
1112 sorted_features = HeapAlloc(GetProcessHeap(), 0, sizeof(*sorted_features) * feature_count);
1113 input_features = HeapAlloc(GetProcessHeap(), 0, sizeof(*input_features) * feature_count);
1114 output_features = HeapAlloc(GetProcessHeap(), 0, sizeof(*output_features) * feature_count);
1115 feature_features = HeapAlloc(GetProcessHeap(), 0, sizeof(*feature_features) * feature_count);
1117 i = 0;
1118 LIST_FOR_EACH_ENTRY(entry, &features, struct feature, entry)
1119 sorted_features[i++] = entry;
1121 /* Sort features base on report if there are multiple reports */
1122 if (sorted_features[0]->caps.ReportID != 0)
1123 qsort(sorted_features, feature_count, sizeof(struct feature*), compare_reports);
1125 for (i = 0; i < feature_count; i++)
1127 switch (sorted_features[i]->type)
1129 case HidP_Input:
1130 input_features[i_count] = sorted_features[i];
1131 i_count++;
1132 break;
1133 case HidP_Output:
1134 output_features[o_count] = sorted_features[i];
1135 o_count++;
1136 break;
1137 case HidP_Feature:
1138 feature_features[f_count] = sorted_features[i];
1139 f_count++;
1140 break;
1141 default:
1142 ERR("Unknown type %i\n",sorted_features[i]->type);
1146 if (TRACE_ON(hid))
1148 TRACE("DUMP FEATURES:\n");
1149 TRACE("----INPUT----\n");
1150 for (cidx = 0; cidx < i_count; cidx++)
1151 debug_feature(input_features[cidx]);
1152 TRACE("----OUTPUT----\n");
1153 for (cidx = 0; cidx < o_count; cidx++)
1154 debug_feature(output_features[cidx]);
1155 TRACE("----FEATURE----\n");
1156 for (cidx = 0; cidx < f_count; cidx++)
1157 debug_feature(feature_features[cidx]);
1160 data = build_PreparseData(sorted_features, feature_count, input_features, i_count, output_features, o_count, feature_features, f_count, base);
1162 debug_print_preparsed(data);
1164 HeapFree(GetProcessHeap(), 0, sorted_features);
1165 HeapFree(GetProcessHeap(), 0, input_features);
1166 HeapFree(GetProcessHeap(), 0, output_features);
1167 HeapFree(GetProcessHeap(), 0, feature_features);
1170 free_collection(base);
1171 /* We do not have to free the list as free_collection does all the work */
1173 return data;