hidclass.sys: Split feature parsing to separate helper.
[wine.git] / dlls / hidclass.sys / descriptor.c
blob930dcd527156a45d702e9bcefaadb9b9ec3c199d
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 <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include "hid.h"
26 #include "wine/debug.h"
27 #include "wine/list.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(hid);
31 /* Flags that are defined in the document
32 "Device Class Definition for Human Interface Devices" */
33 enum {
34 INPUT_DATA_CONST = 0x01, /* Data (0) | Constant (1) */
35 INPUT_ARRAY_VAR = 0x02, /* Array (0) | Variable (1) */
36 INPUT_ABS_REL = 0x04, /* Absolute (0) | Relative (1) */
37 INPUT_WRAP = 0x08, /* No Wrap (0) | Wrap (1) */
38 INPUT_LINEAR = 0x10, /* Linear (0) | Non Linear (1) */
39 INPUT_PREFSTATE = 0x20, /* Preferred State (0) | No Preferred (1) */
40 INPUT_NULL = 0x40, /* No Null position (0) | Null state(1) */
41 INPUT_VOLATILE = 0x80, /* Non Volatile (0) | Volatile (1) */
42 INPUT_BITFIELD = 0x100 /* Bit Field (0) | Buffered Bytes (1) */
45 enum {
46 TAG_TYPE_MAIN = 0x0,
47 TAG_TYPE_GLOBAL,
48 TAG_TYPE_LOCAL,
49 TAG_TYPE_RESERVED,
52 enum {
53 TAG_MAIN_INPUT = 0x08,
54 TAG_MAIN_OUTPUT = 0x09,
55 TAG_MAIN_FEATURE = 0x0B,
56 TAG_MAIN_COLLECTION = 0x0A,
57 TAG_MAIN_END_COLLECTION = 0x0C
60 enum {
61 TAG_GLOBAL_USAGE_PAGE = 0x0,
62 TAG_GLOBAL_LOGICAL_MINIMUM,
63 TAG_GLOBAL_LOGICAL_MAXIMUM,
64 TAG_GLOBAL_PHYSICAL_MINIMUM,
65 TAG_GLOBAL_PHYSICAL_MAXIMUM,
66 TAG_GLOBAL_UNIT_EXPONENT,
67 TAG_GLOBAL_UNIT,
68 TAG_GLOBAL_REPORT_SIZE,
69 TAG_GLOBAL_REPORT_ID,
70 TAG_GLOBAL_REPORT_COUNT,
71 TAG_GLOBAL_PUSH,
72 TAG_GLOBAL_POP
75 enum {
76 TAG_LOCAL_USAGE = 0x0,
77 TAG_LOCAL_USAGE_MINIMUM,
78 TAG_LOCAL_USAGE_MAXIMUM,
79 TAG_LOCAL_DESIGNATOR_INDEX,
80 TAG_LOCAL_DESIGNATOR_MINIMUM,
81 TAG_LOCAL_DESIGNATOR_MAXIMUM,
82 TAG_LOCAL_STRING_INDEX,
83 TAG_LOCAL_STRING_MINIMUM,
84 TAG_LOCAL_STRING_MAXIMUM,
85 TAG_LOCAL_DELIMITER
89 static const char* const feature_string[] =
90 { "Input", "Output", "Feature" };
92 struct feature {
93 struct list entry;
94 HIDP_VALUE_CAPS caps;
96 HIDP_REPORT_TYPE type;
97 BOOLEAN isData;
100 static const char* const collection_string[] = {
101 "Physical",
102 "Application",
103 "Logical",
104 "Report",
105 "Named Array",
106 "Usage Switch",
107 "Usage Modifier",
110 struct collection {
111 struct list entry;
112 unsigned int type;
113 struct collection *parent;
114 struct list features;
115 struct list collections;
118 static inline const char *debugstr_hidp_value_caps( HIDP_VALUE_CAPS *caps )
120 if (!caps) return "(null)";
121 return wine_dbg_sprintf( "RId %d, Usg %02x:%02x-%02x Dat %02x-%02x (%d), Str %d-%d (%d), Des %d-%d (%d), "
122 "Bits %02x, Als %d, Abs %d, Nul %d, LCol %d LUsg %02x:%02x, BitSz %d, RCnt %d, "
123 "Unit %x E%+d, Log %+d-%+d, Phy %+d-%+d",
124 caps->ReportID, caps->UsagePage, caps->Range.UsageMin, caps->Range.UsageMax, caps->Range.DataIndexMin, caps->Range.DataIndexMax, caps->IsRange,
125 caps->Range.StringMin, caps->Range.StringMax, caps->IsStringRange, caps->Range.DesignatorMin, caps->Range.DesignatorMax, caps->IsDesignatorRange,
126 caps->BitField, caps->IsAlias, caps->IsAbsolute, caps->HasNull, caps->LinkCollection, caps->LinkUsagePage, caps->LinkUsage, caps->BitSize, caps->ReportCount,
127 caps->Units, caps->UnitsExp, caps->LogicalMin, caps->LogicalMax, caps->PhysicalMin, caps->PhysicalMax );
130 static void copy_hidp_value_caps( HIDP_VALUE_CAPS *out, const struct hid_value_caps *in )
132 out->UsagePage = in->usage_page;
133 out->ReportID = in->report_id;
134 out->LinkCollection = in->link_collection;
135 out->LinkUsagePage = in->link_usage_page;
136 out->LinkUsage = in->link_usage;
137 out->BitField = in->bit_field;
138 out->IsAlias = FALSE;
139 out->IsAbsolute = HID_VALUE_CAPS_IS_ABSOLUTE( in );
140 out->HasNull = HID_VALUE_CAPS_HAS_NULL( in );
141 out->BitSize = in->bit_size;
142 out->ReportCount = in->report_count;
143 out->UnitsExp = in->units_exp;
144 out->Units = in->units;
145 out->LogicalMin = in->logical_min;
146 out->LogicalMax = in->logical_max;
147 out->PhysicalMin = in->physical_min;
148 out->PhysicalMax = in->physical_max;
149 if (!(out->IsRange = in->is_range))
150 out->NotRange.Usage = in->usage_min;
151 else
153 out->Range.UsageMin = in->usage_min;
154 out->Range.UsageMax = in->usage_max;
156 if (!(out->IsStringRange = in->is_string_range))
157 out->NotRange.StringIndex = in->string_min;
158 else
160 out->Range.StringMin = in->string_min;
161 out->Range.StringMax = in->string_max;
163 if ((out->IsDesignatorRange = in->is_designator_range))
164 out->NotRange.DesignatorIndex = in->designator_min;
165 else
167 out->Range.DesignatorMin = in->designator_min;
168 out->Range.DesignatorMax = in->designator_max;
172 static void debug_feature(struct feature *feature)
174 if (!feature)
175 return;
176 TRACE( "[Feature type %s %s]\n", feature_string[feature->type], (feature->isData) ? "Data" : "Const" );
178 TRACE("Feature %s\n", debugstr_hidp_value_caps(&feature->caps));
181 static void debug_collection(struct collection *collection)
183 struct feature *fentry;
184 struct collection *centry;
185 if (TRACE_ON(hid))
187 TRACE( "START Collection <<< %s, parent: %p, %i features, %i collections\n",
188 collection_string[collection->type], collection->parent,
189 list_count( &collection->features ), list_count( &collection->collections ) );
190 LIST_FOR_EACH_ENTRY(fentry, &collection->features, struct feature, entry)
191 debug_feature(fentry);
192 LIST_FOR_EACH_ENTRY(centry, &collection->collections, struct collection, entry)
193 debug_collection(centry);
194 TRACE( ">>> END Collection\n" );
198 static void debug_print_report(const char* type, WINE_HIDP_PREPARSED_DATA *data,
199 WINE_HID_REPORT *report)
201 WINE_HID_ELEMENT *elems = HID_ELEMS(data);
202 unsigned int i;
203 TRACE("START Report %i <<< %s report : bitSize: %i elementCount: %i\n",
204 report->reportID,
205 type,
206 report->bitSize,
207 report->elementCount);
208 for (i = 0; i < report->elementCount; i++)
210 WINE_HID_ELEMENT *elem = elems + report->elementIdx + i;
211 TRACE("%s: %s, StartBit %d, BitCount %d\n", type, debugstr_hidp_value_caps(&elem->caps), elem->valueStartBit, elem->bitCount);
213 TRACE(">>> END Report %i\n",report->reportID);
216 static void debug_print_preparsed(WINE_HIDP_PREPARSED_DATA *data)
218 unsigned int i, end;
219 if (TRACE_ON(hid))
221 TRACE("START PREPARSED Data <<< dwSize: %i Usage: %i, UsagePage: %i, "
222 "InputReportByteLength: %i, tOutputReportByteLength: %i, "
223 "FeatureReportByteLength: %i, NumberLinkCollectionNodes: %i, "
224 "NumberInputButtonCaps: %i, NumberInputValueCaps: %i, "
225 "NumberInputDataIndices: %i, NumberOutputButtonCaps: %i, "
226 "NumberOutputValueCaps: %i, NumberOutputDataIndices: %i, "
227 "NumberFeatureButtonCaps: %i, NumberFeatureValueCaps: %i, "
228 "NumberFeatureDataIndices: %i, reportCount[HidP_Input]: %i, "
229 "reportCount[HidP_Output]: %i, reportCount[HidP_Feature]: %i, "
230 "elementOffset: %i\n",
231 data->dwSize,
232 data->caps.Usage,
233 data->caps.UsagePage,
234 data->caps.InputReportByteLength,
235 data->caps.OutputReportByteLength,
236 data->caps.FeatureReportByteLength,
237 data->caps.NumberLinkCollectionNodes,
238 data->caps.NumberInputButtonCaps,
239 data->caps.NumberInputValueCaps,
240 data->caps.NumberInputDataIndices,
241 data->caps.NumberOutputButtonCaps,
242 data->caps.NumberOutputValueCaps,
243 data->caps.NumberOutputDataIndices,
244 data->caps.NumberFeatureButtonCaps,
245 data->caps.NumberFeatureValueCaps,
246 data->caps.NumberFeatureDataIndices,
247 data->reportCount[HidP_Input],
248 data->reportCount[HidP_Output],
249 data->reportCount[HidP_Feature],
250 data->elementOffset);
252 end = data->reportCount[HidP_Input];
253 for (i = 0; i < end; i++)
255 debug_print_report("INPUT", data, &data->reports[i]);
257 end += data->reportCount[HidP_Output];
258 for (; i < end; i++)
260 debug_print_report("OUTPUT", data, &data->reports[i]);
262 end += data->reportCount[HidP_Feature];
263 for (; i < end; i++)
265 debug_print_report("FEATURE", data, &data->reports[i]);
267 TRACE(">>> END Preparsed Data\n");
271 struct hid_parser_state
273 HIDP_CAPS caps;
275 USAGE usages[256];
276 DWORD usages_size;
278 struct hid_value_caps items;
280 struct hid_value_caps *stack;
281 DWORD stack_size;
282 DWORD global_idx;
283 DWORD collection_idx;
285 struct hid_value_caps *collections;
286 DWORD collections_size;
289 static BOOL array_reserve( struct hid_value_caps **array, DWORD *array_size, DWORD index )
291 if (index < *array_size) return TRUE;
292 if ((*array_size = *array_size ? (*array_size * 3 / 2) : 32) <= index) return FALSE;
293 if (!(*array = realloc( *array, *array_size * sizeof(**array) ))) return FALSE;
294 return TRUE;
297 static void copy_global_items( struct hid_value_caps *dst, const struct hid_value_caps *src )
299 dst->usage_page = src->usage_page;
300 dst->logical_min = src->logical_min;
301 dst->logical_max = src->logical_max;
302 dst->physical_min = src->physical_min;
303 dst->physical_max = src->physical_max;
304 dst->units_exp = src->units_exp;
305 dst->units = src->units;
306 dst->bit_size = src->bit_size;
307 dst->report_id = src->report_id;
308 dst->report_count = src->report_count;
311 static void copy_collection_items( struct hid_value_caps *dst, const struct hid_value_caps *src )
313 dst->link_collection = src->link_collection;
314 dst->link_usage_page = src->link_usage_page;
315 dst->link_usage = src->link_usage;
318 static void reset_local_items( struct hid_parser_state *state )
320 struct hid_value_caps tmp;
321 copy_global_items( &tmp, &state->items );
322 copy_collection_items( &tmp, &state->items );
323 memset( &state->items, 0, sizeof(state->items) );
324 copy_global_items( &state->items, &tmp );
325 copy_collection_items( &state->items, &tmp );
326 state->usages_size = 0;
329 static BOOL parse_global_push( struct hid_parser_state *state )
331 if (!array_reserve( &state->stack, &state->stack_size, state->global_idx ))
333 ERR( "HID parser stack overflow!\n" );
334 return FALSE;
337 copy_global_items( state->stack + state->global_idx, &state->items );
338 state->global_idx++;
339 return TRUE;
342 static BOOL parse_global_pop( struct hid_parser_state *state )
344 if (!state->global_idx)
346 ERR( "HID parser global stack underflow!\n" );
347 return FALSE;
350 state->global_idx--;
351 copy_global_items( &state->items, state->stack + state->global_idx );
352 return TRUE;
355 static BOOL parse_local_usage( struct hid_parser_state *state, USAGE usage )
357 state->usages[state->usages_size] = usage;
358 state->items.is_range = FALSE;
359 if (state->usages_size++ == 255) ERR( "HID parser usages stack overflow!\n" );
360 return state->usages_size <= 255;
363 static BOOL parse_new_collection( struct hid_parser_state *state )
365 if (!array_reserve( &state->stack, &state->stack_size, state->collection_idx ))
367 ERR( "HID parser stack overflow!\n" );
368 return FALSE;
371 if (!array_reserve( &state->collections, &state->collections_size, state->caps.NumberLinkCollectionNodes ))
373 ERR( "HID parser collections overflow!\n" );
374 return FALSE;
377 copy_collection_items( state->stack + state->collection_idx, &state->items );
378 state->collection_idx++;
380 state->collections[state->caps.NumberLinkCollectionNodes] = state->items;
381 state->items.link_collection = state->caps.NumberLinkCollectionNodes;
382 state->items.link_usage_page = state->items.usage_page;
383 state->items.link_usage = state->items.usage_min;
384 if (!state->caps.NumberLinkCollectionNodes)
386 state->caps.UsagePage = state->items.usage_page;
387 state->caps.Usage = state->items.usage_min;
389 state->caps.NumberLinkCollectionNodes++;
391 reset_local_items( state );
392 return TRUE;
395 static BOOL parse_end_collection( struct hid_parser_state *state )
397 if (!state->collection_idx)
399 ERR( "HID parser collection stack underflow!\n" );
400 return FALSE;
403 state->collection_idx--;
404 copy_collection_items( &state->items, state->stack + state->collection_idx );
405 reset_local_items( state );
406 return TRUE;
409 static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TYPE type, struct collection *collection )
411 struct feature *feature;
412 int j;
414 for (j = 0; j < state->items.report_count; j++)
416 if (!(feature = calloc( 1, sizeof(*feature) ))) return -1;
417 list_add_tail( &collection->features, &feature->entry );
418 feature->type = type;
419 feature->isData = ((state->items.bit_field & INPUT_DATA_CONST) == 0);
420 if (j < state->usages_size) state->items.usage_min = state->usages[j];
421 copy_hidp_value_caps( &feature->caps, &state->items );
422 feature->caps.ReportCount = 1;
423 if (j + 1 >= state->usages_size)
425 feature->caps.ReportCount += state->items.report_count - (j + 1);
426 break;
430 reset_local_items( state );
431 return TRUE;
434 static void free_parser_state( struct hid_parser_state *state )
436 if (state->global_idx) ERR( "%u unpopped device caps on the stack\n", state->global_idx );
437 if (state->collection_idx) ERR( "%u unpopped device collection on the stack\n", state->collection_idx );
438 free( state->stack );
439 free( state->collections );
440 free( state );
443 static void parse_collection(unsigned int bSize, int itemVal,
444 struct collection *collection)
446 if (bSize)
448 collection->type = itemVal;
450 if (itemVal >= 0x07 && itemVal <= 0x7F) {
451 ERR(" (Reserved 0x%x )\n", itemVal);
453 else if (itemVal >= 0x80 && itemVal <= 0xFF) {
454 ERR(" (Vendor Defined 0x%x )\n", itemVal);
459 static int parse_descriptor( BYTE *descriptor, unsigned int index, unsigned int length,
460 struct collection *collection, struct hid_parser_state *state )
462 int i;
463 UINT32 value;
464 INT32 signed_value;
466 for (i = index; i < length;)
468 BYTE item = descriptor[i++];
469 int size = item & 0x03;
471 if (size == 3) size = 4;
472 if (length - i < size)
474 ERR("Need %d bytes to read item value\n", size);
475 return -1;
478 if (size == 0) signed_value = value = 0;
479 else if (size == 1) signed_value = (INT8)(value = *(UINT8 *)(descriptor + i));
480 else if (size == 2) signed_value = (INT16)(value = *(UINT16 *)(descriptor + i));
481 else if (size == 4) signed_value = (INT32)(value = *(UINT32 *)(descriptor + i));
482 else
484 ERR("Unexpected item value size %d.\n", size);
485 return -1;
487 i += size;
489 state->items.bit_field = value;
491 #define SHORT_ITEM(tag,type) (((tag)<<4)|((type)<<2))
492 switch (item & SHORT_ITEM(0xf,0x3))
494 case SHORT_ITEM(TAG_MAIN_INPUT, TAG_TYPE_MAIN):
495 if (!parse_new_value_caps( state, HidP_Input, collection )) return -1;
496 break;
497 case SHORT_ITEM(TAG_MAIN_OUTPUT, TAG_TYPE_MAIN):
498 if (!parse_new_value_caps( state, HidP_Output, collection )) return -1;
499 break;
500 case SHORT_ITEM(TAG_MAIN_FEATURE, TAG_TYPE_MAIN):
501 if (!parse_new_value_caps( state, HidP_Feature, collection )) return -1;
502 break;
503 case SHORT_ITEM(TAG_MAIN_COLLECTION, TAG_TYPE_MAIN):
505 struct collection *subcollection;
506 if (!(subcollection = calloc(1, sizeof(struct collection)))) return -1;
507 list_add_tail(&collection->collections, &subcollection->entry);
508 subcollection->parent = collection;
509 /* Only set our collection once...
510 We do not properly handle composite devices yet. */
511 if (state->usages_size) state->items.usage_min = state->usages[state->usages_size - 1];
512 list_init(&subcollection->features);
513 list_init(&subcollection->collections);
514 parse_collection(size, value, subcollection);
515 if (!parse_new_collection( state )) return -1;
517 if ((i = parse_descriptor( descriptor, i, length, subcollection, state )) < 0) return i;
518 continue;
520 case SHORT_ITEM(TAG_MAIN_END_COLLECTION, TAG_TYPE_MAIN):
521 if (!parse_end_collection( state )) return -1;
522 return i;
524 case SHORT_ITEM(TAG_GLOBAL_USAGE_PAGE, TAG_TYPE_GLOBAL):
525 state->items.usage_page = value;
526 break;
527 case SHORT_ITEM(TAG_GLOBAL_LOGICAL_MINIMUM, TAG_TYPE_GLOBAL):
528 state->items.logical_min = signed_value;
529 break;
530 case SHORT_ITEM(TAG_GLOBAL_LOGICAL_MAXIMUM, TAG_TYPE_GLOBAL):
531 state->items.logical_max = signed_value;
532 break;
533 case SHORT_ITEM(TAG_GLOBAL_PHYSICAL_MINIMUM, TAG_TYPE_GLOBAL):
534 state->items.physical_min = signed_value;
535 break;
536 case SHORT_ITEM(TAG_GLOBAL_PHYSICAL_MAXIMUM, TAG_TYPE_GLOBAL):
537 state->items.physical_max = signed_value;
538 break;
539 case SHORT_ITEM(TAG_GLOBAL_UNIT_EXPONENT, TAG_TYPE_GLOBAL):
540 state->items.units_exp = signed_value;
541 break;
542 case SHORT_ITEM(TAG_GLOBAL_UNIT, TAG_TYPE_GLOBAL):
543 state->items.units = signed_value;
544 break;
545 case SHORT_ITEM(TAG_GLOBAL_REPORT_SIZE, TAG_TYPE_GLOBAL):
546 state->items.bit_size = value;
547 break;
548 case SHORT_ITEM(TAG_GLOBAL_REPORT_ID, TAG_TYPE_GLOBAL):
549 state->items.report_id = value;
550 break;
551 case SHORT_ITEM(TAG_GLOBAL_REPORT_COUNT, TAG_TYPE_GLOBAL):
552 state->items.report_count = value;
553 break;
554 case SHORT_ITEM(TAG_GLOBAL_PUSH, TAG_TYPE_GLOBAL):
555 if (!parse_global_push( state )) return -1;
556 break;
557 case SHORT_ITEM(TAG_GLOBAL_POP, TAG_TYPE_GLOBAL):
558 if (!parse_global_pop( state )) return -1;
559 break;
561 case SHORT_ITEM(TAG_LOCAL_USAGE, TAG_TYPE_LOCAL):
562 if (!parse_local_usage( state, value )) return -1;
563 break;
564 case SHORT_ITEM(TAG_LOCAL_USAGE_MINIMUM, TAG_TYPE_LOCAL):
565 state->items.usage_min = value;
566 state->items.is_range = TRUE;
567 break;
568 case SHORT_ITEM(TAG_LOCAL_USAGE_MAXIMUM, TAG_TYPE_LOCAL):
569 state->items.usage_max = value;
570 state->items.is_range = TRUE;
571 break;
572 case SHORT_ITEM(TAG_LOCAL_DESIGNATOR_INDEX, TAG_TYPE_LOCAL):
573 state->items.designator_min = state->items.designator_max = value;
574 state->items.is_designator_range = FALSE;
575 break;
576 case SHORT_ITEM(TAG_LOCAL_DESIGNATOR_MINIMUM, TAG_TYPE_LOCAL):
577 state->items.designator_min = value;
578 state->items.is_designator_range = TRUE;
579 break;
580 case SHORT_ITEM(TAG_LOCAL_DESIGNATOR_MAXIMUM, TAG_TYPE_LOCAL):
581 state->items.designator_max = value;
582 state->items.is_designator_range = TRUE;
583 break;
584 case SHORT_ITEM(TAG_LOCAL_STRING_INDEX, TAG_TYPE_LOCAL):
585 state->items.string_min = state->items.string_max = value;
586 state->items.is_string_range = FALSE;
587 break;
588 case SHORT_ITEM(TAG_LOCAL_STRING_MINIMUM, TAG_TYPE_LOCAL):
589 state->items.string_min = value;
590 state->items.is_string_range = TRUE;
591 break;
592 case SHORT_ITEM(TAG_LOCAL_STRING_MAXIMUM, TAG_TYPE_LOCAL):
593 state->items.string_max = value;
594 state->items.is_string_range = TRUE;
595 break;
596 case SHORT_ITEM(TAG_LOCAL_DELIMITER, TAG_TYPE_LOCAL):
597 FIXME("delimiter %d not implemented!\n", value);
598 return -1;
600 default:
601 FIXME("item type %x not implemented!\n", item);
602 return -1;
604 #undef SHORT_ITEM
606 return i;
609 static void build_elements(WINE_HID_REPORT *wine_report, WINE_HID_ELEMENT *elems,
610 struct feature* feature, USHORT *data_index)
612 WINE_HID_ELEMENT *wine_element = elems + wine_report->elementIdx + wine_report->elementCount;
613 ULONG index_count;
615 if (!feature->isData)
617 wine_report->bitSize += feature->caps.BitSize * feature->caps.ReportCount;
618 return;
621 wine_element->valueStartBit = wine_report->bitSize;
623 wine_element->bitCount = (feature->caps.BitSize * feature->caps.ReportCount);
624 wine_report->bitSize += wine_element->bitCount;
626 wine_element->caps = feature->caps;
628 if (wine_element->caps.IsRange)
630 if (wine_element->caps.BitSize == 1) index_count = wine_element->bitCount - 1;
631 else index_count = wine_element->caps.Range.UsageMax - wine_element->caps.Range.UsageMin;
632 wine_element->caps.Range.DataIndexMin = *data_index;
633 wine_element->caps.Range.DataIndexMax = *data_index + index_count;
634 *data_index = *data_index + index_count + 1;
636 else
638 wine_element->caps.NotRange.DataIndex = *data_index;
639 wine_element->caps.NotRange.Reserved4 = *data_index;
640 *data_index = *data_index + 1;
643 wine_report->elementCount++;
646 static void count_elements(struct feature* feature, USHORT *buttons, USHORT *values)
648 if (!feature->isData)
649 return;
651 if (feature->caps.BitSize == 1)
652 (*buttons)++;
653 else
654 (*values)++;
657 struct preparse_ctx
659 int report_count[3];
660 int elem_count;
661 int report_elem_count[3][256];
663 int elem_alloc;
664 BOOL report_created[3][256];
667 static void create_preparse_ctx(const struct collection *base, struct preparse_ctx *ctx)
669 struct feature *f;
670 struct collection *c;
672 LIST_FOR_EACH_ENTRY(f, &base->features, struct feature, entry)
674 ctx->elem_count++;
675 ctx->report_elem_count[f->type][f->caps.ReportID]++;
676 if (ctx->report_elem_count[f->type][f->caps.ReportID] != 1)
677 continue;
678 ctx->report_count[f->type]++;
681 LIST_FOR_EACH_ENTRY(c, &base->collections, struct collection, entry)
682 create_preparse_ctx(c, ctx);
685 static void preparse_collection(const struct collection *root, const struct collection *base,
686 WINE_HIDP_PREPARSED_DATA *data, struct preparse_ctx *ctx)
688 WINE_HID_ELEMENT *elem = HID_ELEMS(data);
689 struct feature *f;
690 struct collection *c;
692 LIST_FOR_EACH_ENTRY(f, &base->features, struct feature, entry)
694 WINE_HID_REPORT *report;
696 if (!ctx->report_created[f->type][f->caps.ReportID])
698 ctx->report_created[f->type][f->caps.ReportID] = TRUE;
699 data->reportIdx[f->type][f->caps.ReportID] = data->reportCount[f->type]++;
700 if (f->type > 0) data->reportIdx[f->type][f->caps.ReportID] += ctx->report_count[0];
701 if (f->type > 1) data->reportIdx[f->type][f->caps.ReportID] += ctx->report_count[1];
703 report = &data->reports[data->reportIdx[f->type][f->caps.ReportID]];
704 report->reportID = f->caps.ReportID;
705 /* Room for the reportID */
706 report->bitSize = 8;
707 report->elementIdx = ctx->elem_alloc;
708 ctx->elem_alloc += ctx->report_elem_count[f->type][f->caps.ReportID];
711 report = &data->reports[data->reportIdx[f->type][f->caps.ReportID]];
712 switch (f->type)
714 case HidP_Input:
715 build_elements(report, elem, f, &data->caps.NumberInputDataIndices);
716 count_elements(f, &data->caps.NumberInputButtonCaps, &data->caps.NumberInputValueCaps);
717 data->caps.InputReportByteLength =
718 max(data->caps.InputReportByteLength, (report->bitSize + 7) / 8);
719 break;
720 case HidP_Output:
721 build_elements(report, elem, f, &data->caps.NumberOutputDataIndices);
722 count_elements(f, &data->caps.NumberOutputButtonCaps, &data->caps.NumberOutputValueCaps);
723 data->caps.OutputReportByteLength =
724 max(data->caps.OutputReportByteLength, (report->bitSize + 7) / 8);
725 break;
726 case HidP_Feature:
727 build_elements(report, elem, f, &data->caps.NumberFeatureDataIndices);
728 count_elements(f, &data->caps.NumberFeatureButtonCaps, &data->caps.NumberFeatureValueCaps);
729 data->caps.FeatureReportByteLength =
730 max(data->caps.FeatureReportByteLength, (report->bitSize + 7) / 8);
731 break;
735 LIST_FOR_EACH_ENTRY(c, &base->collections, struct collection, entry)
736 preparse_collection(root, c, data, ctx);
739 static WINE_HIDP_PREPARSED_DATA *build_preparsed_data( struct collection *base_collection,
740 struct hid_parser_state *state )
742 WINE_HID_LINK_COLLECTION_NODE *nodes;
743 WINE_HIDP_PREPARSED_DATA *data;
744 unsigned int report_count;
745 unsigned int size;
746 DWORD i;
748 struct preparse_ctx ctx;
749 unsigned int element_off;
750 unsigned int nodes_offset;
752 memset(&ctx, 0, sizeof(ctx));
753 create_preparse_ctx(base_collection, &ctx);
755 report_count = ctx.report_count[HidP_Input] + ctx.report_count[HidP_Output]
756 + ctx.report_count[HidP_Feature];
757 element_off = FIELD_OFFSET(WINE_HIDP_PREPARSED_DATA, reports[report_count]);
758 size = element_off + (ctx.elem_count * sizeof(WINE_HID_ELEMENT));
760 nodes_offset = size;
761 size += state->caps.NumberLinkCollectionNodes * sizeof(WINE_HID_LINK_COLLECTION_NODE);
763 if (!(data = calloc(1, size))) return NULL;
764 data->magic = HID_MAGIC;
765 data->dwSize = size;
766 data->caps = state->caps;
767 data->elementOffset = element_off;
768 data->nodesOffset = nodes_offset;
770 preparse_collection(base_collection, base_collection, data, &ctx);
772 nodes = HID_NODES( data );
773 for (i = 0; i < data->caps.NumberLinkCollectionNodes; ++i)
775 nodes[i].LinkUsagePage = state->collections[i].usage_page;
776 nodes[i].LinkUsage = state->collections[i].usage_min;
777 nodes[i].Parent = state->collections[i].link_collection;
778 nodes[i].CollectionType = state->collections[i].bit_field;
779 nodes[i].IsAlias = 0;
781 if (i > 0)
783 nodes[i].NextSibling = nodes[nodes[i].Parent].FirstChild;
784 nodes[nodes[i].Parent].FirstChild = i;
785 nodes[nodes[i].Parent].NumberOfChildren++;
789 return data;
792 static void free_collection(struct collection *collection)
794 struct feature *fentry, *fnext;
795 struct collection *centry, *cnext;
796 LIST_FOR_EACH_ENTRY_SAFE(centry, cnext, &collection->collections, struct collection, entry)
798 list_remove(&centry->entry);
799 free_collection(centry);
801 LIST_FOR_EACH_ENTRY_SAFE(fentry, fnext, &collection->features, struct feature, entry)
803 list_remove(&fentry->entry);
804 free(fentry);
806 free(collection);
809 WINE_HIDP_PREPARSED_DATA* ParseDescriptor(BYTE *descriptor, unsigned int length)
811 WINE_HIDP_PREPARSED_DATA *data = NULL;
812 struct hid_parser_state *state;
813 struct collection *base;
814 int i;
816 if (TRACE_ON(hid))
818 TRACE("descriptor %p, length %u:\n", descriptor, length);
819 for (i = 0; i < length;)
821 TRACE("%08x ", i);
822 do { TRACE(" %02x", descriptor[i]); } while (++i % 16 && i < length);
823 TRACE("\n");
827 if (!(state = calloc( 1, sizeof(*state) ))) return NULL;
828 if (!(base = calloc( 1, sizeof(*base) )))
830 free( state );
831 return NULL;
833 list_init(&base->features);
834 list_init(&base->collections);
836 if (parse_descriptor( descriptor, 0, length, base, state ) < 0)
838 free_collection(base);
839 free_parser_state( state );
840 return NULL;
843 debug_collection(base);
845 if ((data = build_preparsed_data( base, state )))
846 debug_print_preparsed(data);
847 free_collection(base);
849 free_parser_state( state );
850 return data;