wineps: Handle EMR_INVERTRGN record in spool files.
[wine.git] / dlls / hidparse.sys / main.c
blobfeb5b3531a4ef1bd796569f5a3496a2fb4680b5c
1 /*
2 * HID parsing library
4 * Copyright 2021 RĂ©mi Bernon for CodeWeavers
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>
24 #include "ntstatus.h"
25 #define WIN32_NO_STATUS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winternl.h"
29 #include "winioctl.h"
31 #include <ddk/wdm.h>
32 #include <ddk/hidpddi.h>
34 #include "wine/hid.h"
35 #include "wine/list.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(hid);
40 /* Flags that are defined in the document
41 "Device Class Definition for Human Interface Devices" */
42 enum
44 INPUT_DATA_CONST = 0x01, /* Data (0) | Constant (1) */
45 INPUT_ARRAY_VAR = 0x02, /* Array (0) | Variable (1) */
46 INPUT_ABS_REL = 0x04, /* Absolute (0) | Relative (1) */
47 INPUT_WRAP = 0x08, /* No Wrap (0) | Wrap (1) */
48 INPUT_LINEAR = 0x10, /* Linear (0) | Non Linear (1) */
49 INPUT_PREFSTATE = 0x20, /* Preferred State (0) | No Preferred (1) */
50 INPUT_NULL = 0x40, /* No Null position (0) | Null state(1) */
51 INPUT_VOLATILE = 0x80, /* Non Volatile (0) | Volatile (1) */
52 INPUT_BITFIELD = 0x100 /* Bit Field (0) | Buffered Bytes (1) */
55 enum
57 TAG_TYPE_MAIN = 0x0,
58 TAG_TYPE_GLOBAL,
59 TAG_TYPE_LOCAL,
60 TAG_TYPE_RESERVED,
63 enum
65 TAG_MAIN_INPUT = 0x08,
66 TAG_MAIN_OUTPUT = 0x09,
67 TAG_MAIN_FEATURE = 0x0B,
68 TAG_MAIN_COLLECTION = 0x0A,
69 TAG_MAIN_END_COLLECTION = 0x0C
72 enum
74 TAG_GLOBAL_USAGE_PAGE = 0x0,
75 TAG_GLOBAL_LOGICAL_MINIMUM,
76 TAG_GLOBAL_LOGICAL_MAXIMUM,
77 TAG_GLOBAL_PHYSICAL_MINIMUM,
78 TAG_GLOBAL_PHYSICAL_MAXIMUM,
79 TAG_GLOBAL_UNIT_EXPONENT,
80 TAG_GLOBAL_UNIT,
81 TAG_GLOBAL_REPORT_SIZE,
82 TAG_GLOBAL_REPORT_ID,
83 TAG_GLOBAL_REPORT_COUNT,
84 TAG_GLOBAL_PUSH,
85 TAG_GLOBAL_POP
88 enum
90 TAG_LOCAL_USAGE = 0x0,
91 TAG_LOCAL_USAGE_MINIMUM,
92 TAG_LOCAL_USAGE_MAXIMUM,
93 TAG_LOCAL_DESIGNATOR_INDEX,
94 TAG_LOCAL_DESIGNATOR_MINIMUM,
95 TAG_LOCAL_DESIGNATOR_MAXIMUM,
96 TAG_LOCAL_STRING_INDEX = 0x7,
97 TAG_LOCAL_STRING_MINIMUM,
98 TAG_LOCAL_STRING_MAXIMUM,
99 TAG_LOCAL_DELIMITER
102 static inline const char *debugstr_hid_value_caps( struct hid_value_caps *caps )
104 if (!caps) return "(null)";
105 return wine_dbg_sprintf( "RId %d, Usg %02x:%02x-%02x Dat %02x-%02x, Str %d-%d, Des %d-%d, "
106 "Bits %02lx Flags %#lx, LCol %d LUsg %02x:%02x, BitSz %d, RCnt %d, Unit %lx E%+ld, Log %+ld-%+ld, Phy %+ld-%+ld",
107 caps->report_id, caps->usage_page, caps->usage_min, caps->usage_max, caps->data_index_min, caps->data_index_max,
108 caps->string_min, caps->string_max, caps->designator_min, caps->designator_max, caps->bit_field, caps->flags,
109 caps->link_collection, caps->link_usage_page, caps->link_usage, caps->bit_size, caps->report_count,
110 caps->units, caps->units_exp, caps->logical_min, caps->logical_max, caps->physical_min, caps->physical_max );
113 static inline const char *debugstr_hid_collection_node( struct hid_collection_node *node )
115 if (!node) return "(null)";
116 return wine_dbg_sprintf( "Usg %02x:%02x, Parent %u, Next %u, NbChild %u, Child %u, Type %02lx",
117 node->usage_page, node->usage, node->parent, node->next_sibling,
118 node->number_of_children, node->first_child, node->collection_type );
121 static void debug_print_preparsed( struct hid_preparsed_data *data )
123 unsigned int i, end;
125 if (TRACE_ON(hid))
127 TRACE( "usage %02x:%02x input %u-(%u)-%u, report len %u output %u-(%u)-%u, report len %u "
128 "feature %u-(%u)-%u, report len %u collections %u\n", data->usage_page, data->usage,
129 data->input_caps_start, data->input_caps_count, data->input_caps_end, data->input_report_byte_length,
130 data->output_caps_start, data->output_caps_count, data->output_caps_end, data->output_report_byte_length,
131 data->feature_caps_start, data->feature_caps_count, data->feature_caps_end, data->feature_report_byte_length,
132 data->number_link_collection_nodes );
133 end = data->input_caps_end - data->input_caps_start;
134 for (i = 0; i < end; i++) TRACE( "input %d: %s\n", i, debugstr_hid_value_caps( HID_INPUT_VALUE_CAPS( data ) + i ) );
135 end = data->output_caps_end - data->output_caps_start;
136 for (i = 0; i < end; i++) TRACE( "output %d: %s\n", i, debugstr_hid_value_caps( HID_OUTPUT_VALUE_CAPS( data ) + i ) );
137 end = data->feature_caps_end - data->feature_caps_start;
138 for (i = 0; i < end; i++) TRACE( "feature %d: %s\n", i, debugstr_hid_value_caps( HID_FEATURE_VALUE_CAPS( data ) + i ) );
139 end = data->number_link_collection_nodes;
140 for (i = 0; i < end; i++) TRACE( "collection %d: %s\n", i, debugstr_hid_collection_node( HID_COLLECTION_NODES( data ) + i ) );
144 struct hid_parser_state
146 USAGE usage;
147 USAGE usage_page;
148 USHORT input_report_byte_length;
149 USHORT output_report_byte_length;
150 USHORT feature_report_byte_length;
151 USHORT number_link_collection_nodes;
153 USAGE usages_page[256];
154 USAGE usages_min[256];
155 USAGE usages_max[256];
156 DWORD usages_size;
158 struct hid_value_caps items;
160 struct hid_value_caps *stack;
161 DWORD stack_size;
162 DWORD global_idx;
163 DWORD collection_idx;
165 struct hid_value_caps *collections;
166 DWORD collections_size;
168 struct hid_value_caps *values[3];
169 ULONG values_size[3];
171 ULONG bit_size[3][256];
172 USHORT byte_length[3];
173 USHORT caps_count[3];
174 USHORT empty_caps[3];
175 USHORT data_count[3];
178 static BOOL array_reserve( struct hid_value_caps **array, DWORD *array_size, DWORD index )
180 if (index < *array_size) return TRUE;
181 if ((*array_size = *array_size ? (*array_size * 3 / 2) : 32) <= index) return FALSE;
182 if (!(*array = realloc( *array, *array_size * sizeof(**array) ))) return FALSE;
183 return TRUE;
186 static void copy_global_items( struct hid_value_caps *dst, const struct hid_value_caps *src )
188 dst->usage_page = src->usage_page;
189 dst->logical_min = src->logical_min;
190 dst->logical_max = src->logical_max;
191 dst->physical_min = src->physical_min;
192 dst->physical_max = src->physical_max;
193 dst->units_exp = src->units_exp;
194 dst->units = src->units;
195 dst->bit_size = src->bit_size;
196 dst->report_id = src->report_id;
197 dst->report_count = src->report_count;
200 static void copy_collection_items( struct hid_value_caps *dst, const struct hid_value_caps *src )
202 dst->link_collection = src->link_collection;
203 dst->link_usage_page = src->link_usage_page;
204 dst->link_usage = src->link_usage;
207 static void reset_local_items( struct hid_parser_state *state )
209 struct hid_value_caps tmp;
210 copy_global_items( &tmp, &state->items );
211 copy_collection_items( &tmp, &state->items );
212 memset( &state->items, 0, sizeof(state->items) );
213 copy_global_items( &state->items, &tmp );
214 copy_collection_items( &state->items, &tmp );
215 memset( &state->usages_page, 0, sizeof(state->usages_page) );
216 memset( &state->usages_min, 0, sizeof(state->usages_min) );
217 memset( &state->usages_max, 0, sizeof(state->usages_max) );
218 state->usages_size = 0;
221 static BOOL parse_global_push( struct hid_parser_state *state )
223 if (!array_reserve( &state->stack, &state->stack_size, state->global_idx ))
225 ERR( "HID parser stack overflow!\n" );
226 return FALSE;
229 copy_global_items( state->stack + state->global_idx, &state->items );
230 state->global_idx++;
231 return TRUE;
234 static BOOL parse_global_pop( struct hid_parser_state *state )
236 if (!state->global_idx)
238 ERR( "HID parser global stack underflow!\n" );
239 return FALSE;
242 state->global_idx--;
243 copy_global_items( &state->items, state->stack + state->global_idx );
244 return TRUE;
247 static BOOL parse_local_usage( struct hid_parser_state *state, USAGE usage_page, USAGE usage )
249 if (!usage_page) usage_page = state->items.usage_page;
250 if (state->items.flags & HID_VALUE_CAPS_IS_RANGE) state->usages_size = 0;
251 state->usages_page[state->usages_size] = usage_page;
252 state->usages_min[state->usages_size] = usage;
253 state->usages_max[state->usages_size] = usage;
254 state->items.usage_min = usage;
255 state->items.usage_max = usage;
256 state->items.flags &= ~HID_VALUE_CAPS_IS_RANGE;
257 if (state->usages_size++ == 255) ERR( "HID parser usages stack overflow!\n" );
258 return state->usages_size <= 255;
261 static void parse_local_usage_min( struct hid_parser_state *state, USAGE usage_page, USAGE usage )
263 if (!usage_page) usage_page = state->items.usage_page;
264 if (!(state->items.flags & HID_VALUE_CAPS_IS_RANGE)) state->usages_max[0] = 0;
265 state->usages_page[0] = usage_page;
266 state->usages_min[0] = usage;
267 state->items.usage_min = usage;
268 state->items.flags |= HID_VALUE_CAPS_IS_RANGE;
269 state->usages_size = 1;
272 static void parse_local_usage_max( struct hid_parser_state *state, USAGE usage_page, USAGE usage )
274 if (!usage_page) usage_page = state->items.usage_page;
275 if (!(state->items.flags & HID_VALUE_CAPS_IS_RANGE)) state->usages_min[0] = 0;
276 state->usages_page[0] = usage_page;
277 state->usages_max[0] = usage;
278 state->items.usage_max = usage;
279 state->items.flags |= HID_VALUE_CAPS_IS_RANGE;
280 state->usages_size = 1;
283 static BOOL parse_new_collection( struct hid_parser_state *state )
285 if (!array_reserve( &state->stack, &state->stack_size, state->collection_idx ))
287 ERR( "HID parser stack overflow!\n" );
288 return FALSE;
291 if (!array_reserve( &state->collections, &state->collections_size, state->number_link_collection_nodes ))
293 ERR( "HID parser collections overflow!\n" );
294 return FALSE;
297 copy_collection_items( state->stack + state->collection_idx, &state->items );
298 state->collection_idx++;
300 state->items.usage_min = state->usages_min[0];
301 state->items.usage_max = state->usages_max[0];
303 state->collections[state->number_link_collection_nodes] = state->items;
304 state->items.link_collection = state->number_link_collection_nodes;
305 state->items.link_usage_page = state->items.usage_page;
306 state->items.link_usage = state->items.usage_min;
307 if (!state->number_link_collection_nodes)
309 state->usage_page = state->items.usage_page;
310 state->usage = state->items.usage_min;
312 state->number_link_collection_nodes++;
314 reset_local_items( state );
315 return TRUE;
318 static BOOL parse_end_collection( struct hid_parser_state *state )
320 if (!state->collection_idx)
322 ERR( "HID parser collection stack underflow!\n" );
323 return FALSE;
326 state->collection_idx--;
327 copy_collection_items( &state->items, state->stack + state->collection_idx );
328 reset_local_items( state );
329 return TRUE;
332 static void add_new_value_caps( struct hid_parser_state *state, struct hid_value_caps *values,
333 LONG i, ULONG start_bit )
335 DWORD count, usages_size = max( 1, state->usages_size );
337 state->items.start_byte = start_bit / 8;
338 state->items.start_bit = start_bit % 8;
339 state->items.total_bits = state->items.report_count * state->items.bit_size;
340 state->items.end_byte = (start_bit + state->items.total_bits + 7) / 8;
341 state->items.usage_page = state->usages_page[usages_size - 1 - i];
342 state->items.usage_min = state->usages_min[usages_size - 1 - i];
343 state->items.usage_max = state->usages_max[usages_size - 1 - i];
344 if (!state->items.usage_max && !state->items.usage_min) count = -1;
345 else count = state->items.usage_max - state->items.usage_min;
346 state->items.data_index_min = state->items.data_index_max + 1;
347 state->items.data_index_max = state->items.data_index_min + count;
348 values[i] = state->items;
350 if (values[i].flags & HID_VALUE_CAPS_IS_BUTTON)
352 if (!HID_VALUE_CAPS_IS_ARRAY( values + i )) values[i].logical_min = 0;
353 else values[i].logical_min = values[i].logical_max;
354 values[i].logical_max = 0;
355 values[i].physical_min = 0;
356 values[i].physical_max = 0;
360 static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TYPE type )
362 struct hid_value_caps *values;
363 USAGE usage_page = state->items.usage_page;
364 USHORT report_count = state->items.report_count;
365 DWORD i, usages_size = max( 1, state->usages_size );
366 USHORT *byte_length = &state->byte_length[type];
367 ULONG start_bit, *bit_size = &state->bit_size[type][state->items.report_id];
368 BOOL is_array;
370 if (!*bit_size) *bit_size = 8;
371 *bit_size += state->items.bit_size * state->items.report_count;
372 *byte_length = max( *byte_length, (*bit_size + 7) / 8 );
373 start_bit = *bit_size;
375 if (!state->items.report_count)
377 state->empty_caps[type] += usages_size;
378 reset_local_items( state );
379 return TRUE;
382 if (!array_reserve( &state->values[type], &state->values_size[type],
383 state->caps_count[type] + usages_size ))
385 ERR( "HID parser values overflow!\n" );
386 return FALSE;
388 values = state->values[type] + state->caps_count[type];
390 if (!(is_array = HID_VALUE_CAPS_IS_ARRAY( &state->items ))) state->items.report_count -= usages_size - 1;
391 else start_bit -= state->items.report_count * state->items.bit_size;
393 if (!(state->items.bit_field & INPUT_ABS_REL)) state->items.flags |= HID_VALUE_CAPS_IS_ABSOLUTE;
394 if (state->items.bit_field & INPUT_DATA_CONST) state->items.flags |= HID_VALUE_CAPS_IS_CONSTANT;
395 if (state->items.bit_size == 1 || is_array) state->items.flags |= HID_VALUE_CAPS_IS_BUTTON;
397 if (is_array) state->items.null_value = state->items.logical_min;
398 else if (!(state->items.bit_field & INPUT_NULL)) state->items.null_value = 0;
399 else state->items.null_value = 1;
401 state->items.data_index_max = state->data_count[type] - 1;
402 for (i = 0; i < usages_size; ++i)
404 if (!is_array) start_bit -= state->items.report_count * state->items.bit_size;
405 else if (i) state->items.flags |= HID_VALUE_CAPS_ARRAY_HAS_MORE;
406 else state->items.flags &= ~HID_VALUE_CAPS_ARRAY_HAS_MORE;
407 add_new_value_caps( state, values, is_array ? usages_size - i - 1 : i, start_bit );
408 if (!is_array) state->items.report_count = 1;
410 state->caps_count[type] += usages_size;
411 state->data_count[type] = state->items.data_index_max + 1;
413 state->items.usage_page = usage_page;
414 state->items.report_count = report_count;
415 reset_local_items( state );
416 return TRUE;
419 static void free_parser_state( struct hid_parser_state *state )
421 if (state->global_idx) ERR( "%lu unpopped device caps on the stack\n", state->global_idx );
422 if (state->collection_idx) ERR( "%lu unpopped device collection on the stack\n", state->collection_idx );
423 free( state->stack );
424 free( state->collections );
425 free( state->values[HidP_Input] );
426 free( state->values[HidP_Output] );
427 free( state->values[HidP_Feature] );
428 free( state );
431 static struct hid_preparsed_data *build_preparsed_data( struct hid_parser_state *state, POOL_TYPE pool_type )
433 struct hid_collection_node *nodes;
434 struct hid_preparsed_data *data;
435 struct hid_value_caps *caps;
436 DWORD i, size, caps_size;
438 caps_size = state->caps_count[HidP_Input] + state->caps_count[HidP_Output] +
439 state->caps_count[HidP_Feature];
440 caps_size += state->empty_caps[HidP_Input] + state->empty_caps[HidP_Output] +
441 state->empty_caps[HidP_Feature];
442 caps_size *= sizeof(struct hid_value_caps);
444 size = caps_size + FIELD_OFFSET(struct hid_preparsed_data, value_caps[0]) +
445 state->number_link_collection_nodes * sizeof(struct hid_collection_node);
446 if (!(data = ExAllocatePool( pool_type, size ))) return NULL;
447 memset( data, 0, size );
449 memcpy( data->magic, "HidP KDR", 8 );
450 data->usage = state->usage;
451 data->usage_page = state->usage_page;
452 data->input_caps_start = 0;
453 data->input_caps_count = state->caps_count[HidP_Input] + state->empty_caps[HidP_Input];
454 data->input_caps_end = data->input_caps_start + state->caps_count[HidP_Input];
455 data->input_report_byte_length = state->byte_length[HidP_Input];
456 data->output_caps_start = data->input_caps_end;
457 data->output_caps_count = state->caps_count[HidP_Output] + state->empty_caps[HidP_Output];
458 data->output_caps_end = data->output_caps_start + state->caps_count[HidP_Output];
459 data->output_report_byte_length = state->byte_length[HidP_Output];
460 data->feature_caps_start = data->output_caps_end;
461 data->feature_caps_count = state->caps_count[HidP_Feature] + state->empty_caps[HidP_Feature];
462 data->feature_caps_end = data->feature_caps_start + state->caps_count[HidP_Feature];
463 data->feature_report_byte_length = state->byte_length[HidP_Feature];
464 data->caps_size = caps_size;
465 data->number_link_collection_nodes = state->number_link_collection_nodes;
467 caps = HID_INPUT_VALUE_CAPS( data );
468 memcpy( caps, state->values[0], state->caps_count[HidP_Input] * sizeof(*caps) );
469 caps = HID_OUTPUT_VALUE_CAPS( data );
470 memcpy( caps, state->values[1], state->caps_count[HidP_Output] * sizeof(*caps) );
471 caps = HID_FEATURE_VALUE_CAPS( data );
472 memcpy( caps, state->values[2], state->caps_count[HidP_Feature] * sizeof(*caps) );
474 nodes = HID_COLLECTION_NODES( data );
475 for (i = 0; i < data->number_link_collection_nodes; ++i)
477 nodes[i].usage_page = state->collections[i].usage_page;
478 nodes[i].usage = state->collections[i].usage_min;
479 nodes[i].parent = state->collections[i].link_collection;
480 nodes[i].collection_type = state->collections[i].bit_field;
481 nodes[i].first_child = 0;
482 nodes[i].next_sibling = 0;
483 nodes[i].number_of_children = 0;
485 if (i > 0)
487 nodes[i].next_sibling = nodes[nodes[i].parent].first_child;
488 nodes[nodes[i].parent].first_child = i;
489 nodes[nodes[i].parent].number_of_children++;
493 return data;
496 struct hid_preparsed_data *parse_descriptor( BYTE *descriptor, unsigned int length, POOL_TYPE pool_type )
498 struct hid_preparsed_data *data = NULL;
499 struct hid_parser_state *state;
500 UINT32 size, value;
501 INT32 signed_value;
502 BYTE *ptr, *end;
503 int i;
505 if (TRACE_ON(hid))
507 TRACE( "descriptor %p, length %u:\n", descriptor, length );
508 for (i = 0; i < length;)
510 TRACE( "%08x ", i );
511 do { TRACE( " %02x", descriptor[i] ); } while (++i % 16 && i < length);
512 TRACE( "\n" );
516 if (!(state = calloc( 1, sizeof(*state) ))) return NULL;
518 for (ptr = descriptor, end = descriptor + length; ptr != end; ptr += size + 1)
520 size = (*ptr & 0x03);
521 if (size == 3) size = 4;
522 if (ptr + size > end)
524 ERR( "Need %d bytes to read item value\n", size );
525 goto done;
528 if (size == 0) signed_value = value = 0;
529 else if (size == 1) signed_value = (INT8)(value = *(UINT8 *)(ptr + 1));
530 else if (size == 2) signed_value = (INT16)(value = *(UINT16 *)(ptr + 1));
531 else if (size == 4) signed_value = (INT32)(value = *(UINT32 *)(ptr + 1));
532 else
534 ERR( "Unexpected item value size %d.\n", size );
535 goto done;
538 state->items.bit_field = value;
540 #define SHORT_ITEM( tag, type ) (((tag) << 4) | ((type) << 2))
541 switch (*ptr & SHORT_ITEM( 0xf, 0x3 ))
543 case SHORT_ITEM( TAG_MAIN_INPUT, TAG_TYPE_MAIN ):
544 if (!parse_new_value_caps( state, HidP_Input )) goto done;
545 break;
546 case SHORT_ITEM( TAG_MAIN_OUTPUT, TAG_TYPE_MAIN ):
547 if (!parse_new_value_caps( state, HidP_Output )) goto done;
548 break;
549 case SHORT_ITEM( TAG_MAIN_FEATURE, TAG_TYPE_MAIN ):
550 if (!parse_new_value_caps( state, HidP_Feature )) goto done;
551 break;
552 case SHORT_ITEM( TAG_MAIN_COLLECTION, TAG_TYPE_MAIN ):
553 if (!parse_new_collection( state )) goto done;
554 break;
555 case SHORT_ITEM( TAG_MAIN_END_COLLECTION, TAG_TYPE_MAIN ):
556 if (!parse_end_collection( state )) goto done;
557 break;
559 case SHORT_ITEM( TAG_GLOBAL_USAGE_PAGE, TAG_TYPE_GLOBAL ):
560 state->items.usage_page = value;
561 break;
562 case SHORT_ITEM( TAG_GLOBAL_LOGICAL_MINIMUM, TAG_TYPE_GLOBAL ):
563 state->items.logical_min = signed_value;
564 break;
565 case SHORT_ITEM( TAG_GLOBAL_LOGICAL_MAXIMUM, TAG_TYPE_GLOBAL ):
566 state->items.logical_max = signed_value;
567 break;
568 case SHORT_ITEM( TAG_GLOBAL_PHYSICAL_MINIMUM, TAG_TYPE_GLOBAL ):
569 state->items.physical_min = signed_value;
570 break;
571 case SHORT_ITEM( TAG_GLOBAL_PHYSICAL_MAXIMUM, TAG_TYPE_GLOBAL ):
572 state->items.physical_max = signed_value;
573 break;
574 case SHORT_ITEM( TAG_GLOBAL_UNIT_EXPONENT, TAG_TYPE_GLOBAL ):
575 state->items.units_exp = signed_value;
576 break;
577 case SHORT_ITEM( TAG_GLOBAL_UNIT, TAG_TYPE_GLOBAL ):
578 state->items.units = signed_value;
579 break;
580 case SHORT_ITEM( TAG_GLOBAL_REPORT_SIZE, TAG_TYPE_GLOBAL ):
581 state->items.bit_size = value;
582 break;
583 case SHORT_ITEM( TAG_GLOBAL_REPORT_ID, TAG_TYPE_GLOBAL ):
584 state->items.report_id = value;
585 break;
586 case SHORT_ITEM( TAG_GLOBAL_REPORT_COUNT, TAG_TYPE_GLOBAL ):
587 state->items.report_count = value;
588 break;
589 case SHORT_ITEM( TAG_GLOBAL_PUSH, TAG_TYPE_GLOBAL ):
590 if (!parse_global_push( state )) goto done;
591 break;
592 case SHORT_ITEM( TAG_GLOBAL_POP, TAG_TYPE_GLOBAL ):
593 if (!parse_global_pop( state )) goto done;
594 break;
596 case SHORT_ITEM( TAG_LOCAL_USAGE, TAG_TYPE_LOCAL ):
597 if (!parse_local_usage( state, value >> 16, value & 0xffff )) goto done;
598 break;
599 case SHORT_ITEM( TAG_LOCAL_USAGE_MINIMUM, TAG_TYPE_LOCAL ):
600 parse_local_usage_min( state, value >> 16, value & 0xffff );
601 break;
602 case SHORT_ITEM( TAG_LOCAL_USAGE_MAXIMUM, TAG_TYPE_LOCAL ):
603 parse_local_usage_max( state, value >> 16, value & 0xffff );
604 break;
605 case SHORT_ITEM( TAG_LOCAL_DESIGNATOR_INDEX, TAG_TYPE_LOCAL ):
606 state->items.designator_min = state->items.designator_max = value;
607 state->items.flags &= ~HID_VALUE_CAPS_IS_DESIGNATOR_RANGE;
608 break;
609 case SHORT_ITEM( TAG_LOCAL_DESIGNATOR_MINIMUM, TAG_TYPE_LOCAL ):
610 state->items.designator_min = value;
611 state->items.flags |= HID_VALUE_CAPS_IS_DESIGNATOR_RANGE;
612 break;
613 case SHORT_ITEM( TAG_LOCAL_DESIGNATOR_MAXIMUM, TAG_TYPE_LOCAL ):
614 state->items.designator_max = value;
615 state->items.flags |= HID_VALUE_CAPS_IS_DESIGNATOR_RANGE;
616 break;
617 case SHORT_ITEM( TAG_LOCAL_STRING_INDEX, TAG_TYPE_LOCAL ):
618 state->items.string_min = state->items.string_max = value;
619 state->items.flags &= ~HID_VALUE_CAPS_IS_STRING_RANGE;
620 break;
621 case SHORT_ITEM( TAG_LOCAL_STRING_MINIMUM, TAG_TYPE_LOCAL ):
622 state->items.string_min = value;
623 state->items.flags |= HID_VALUE_CAPS_IS_STRING_RANGE;
624 break;
625 case SHORT_ITEM( TAG_LOCAL_STRING_MAXIMUM, TAG_TYPE_LOCAL ):
626 state->items.string_max = value;
627 state->items.flags |= HID_VALUE_CAPS_IS_STRING_RANGE;
628 break;
629 case SHORT_ITEM( TAG_LOCAL_DELIMITER, TAG_TYPE_LOCAL ):
630 FIXME( "delimiter %d not implemented!\n", value );
631 goto done;
633 default:
634 FIXME( "item type %x not implemented!\n", *ptr );
635 break;
637 #undef SHORT_ITEM
640 if ((data = build_preparsed_data( state, pool_type ))) debug_print_preparsed( data );
642 done:
643 free_parser_state( state );
644 return data;
647 NTSTATUS WINAPI HidP_GetCollectionDescription( PHIDP_REPORT_DESCRIPTOR report_desc, ULONG report_desc_len,
648 POOL_TYPE pool_type, HIDP_DEVICE_DESC *device_desc )
650 ULONG i, len, report_count = 0, input_len[256] = {0}, output_len[256] = {0}, feature_len[256] = {0};
651 struct hid_value_caps *caps, *caps_end;
652 struct hid_preparsed_data *preparsed;
654 TRACE( "report_desc %p, report_desc_len %lu, pool_type %u, device_desc %p.\n",
655 report_desc, report_desc_len, pool_type, device_desc );
657 memset( device_desc, 0, sizeof(*device_desc) );
659 if (!(preparsed = parse_descriptor( report_desc, report_desc_len, pool_type )))
660 return HIDP_STATUS_INTERNAL_ERROR;
662 if (!(device_desc->CollectionDesc = ExAllocatePool( pool_type, sizeof(*device_desc->CollectionDesc) )))
664 free( preparsed );
665 return STATUS_NO_MEMORY;
668 len = preparsed->caps_size + FIELD_OFFSET(struct hid_preparsed_data, value_caps[0]) +
669 preparsed->number_link_collection_nodes * sizeof(struct hid_collection_node);
671 device_desc->CollectionDescLength = 1;
672 device_desc->CollectionDesc[0].UsagePage = preparsed->usage_page;
673 device_desc->CollectionDesc[0].Usage = preparsed->usage;
674 device_desc->CollectionDesc[0].CollectionNumber = 1;
675 device_desc->CollectionDesc[0].InputLength = preparsed->input_report_byte_length;
676 device_desc->CollectionDesc[0].OutputLength = preparsed->output_report_byte_length;
677 device_desc->CollectionDesc[0].FeatureLength = preparsed->feature_report_byte_length;
678 device_desc->CollectionDesc[0].PreparsedDataLength = len;
679 device_desc->CollectionDesc[0].PreparsedData = (PHIDP_PREPARSED_DATA)preparsed;
681 caps = HID_INPUT_VALUE_CAPS( preparsed );
682 caps_end = caps + preparsed->input_caps_end - preparsed->input_caps_start;
683 for (; caps != caps_end; ++caps)
685 len = caps->start_byte * 8 + caps->start_bit + caps->bit_size * caps->report_count;
686 if (!input_len[caps->report_id]) report_count++;
687 input_len[caps->report_id] = max(input_len[caps->report_id], len);
690 caps = HID_OUTPUT_VALUE_CAPS( preparsed );
691 caps_end = caps + preparsed->output_caps_end - preparsed->output_caps_start;
692 for (; caps != caps_end; ++caps)
694 len = caps->start_byte * 8 + caps->start_bit + caps->bit_size * caps->report_count;
695 if (!input_len[caps->report_id] && !output_len[caps->report_id]) report_count++;
696 output_len[caps->report_id] = max(output_len[caps->report_id], len);
699 caps = HID_FEATURE_VALUE_CAPS( preparsed );
700 caps_end = caps + preparsed->feature_caps_end - preparsed->feature_caps_start;
701 for (; caps != caps_end; ++caps)
703 len = caps->start_byte * 8 + caps->start_bit + caps->bit_size * caps->report_count;
704 if (!input_len[caps->report_id] && !output_len[caps->report_id] && !feature_len[caps->report_id]) report_count++;
705 feature_len[caps->report_id] = max(feature_len[caps->report_id], len);
708 if (!(device_desc->ReportIDs = ExAllocatePool( pool_type, sizeof(*device_desc->ReportIDs) * report_count )))
710 free( preparsed );
711 ExFreePool( device_desc->CollectionDesc );
712 return STATUS_NO_MEMORY;
715 for (i = 0, report_count = 0; i < 256; ++i)
717 if (!input_len[i] && !output_len[i] && !feature_len[i]) continue;
718 device_desc->ReportIDs[report_count].ReportID = i;
719 device_desc->ReportIDs[report_count].CollectionNumber = 1;
720 device_desc->ReportIDs[report_count].InputLength = (input_len[i] + 7) / 8;
721 device_desc->ReportIDs[report_count].OutputLength = (output_len[i] + 7) / 8;
722 device_desc->ReportIDs[report_count].FeatureLength = (feature_len[i] + 7) / 8;
723 report_count++;
725 device_desc->ReportIDsLength = report_count;
727 return HIDP_STATUS_SUCCESS;
730 void WINAPI HidP_FreeCollectionDescription( HIDP_DEVICE_DESC *device_desc )
732 TRACE( "device_desc %p.\n", device_desc );
734 ExFreePool( device_desc->CollectionDesc );
735 ExFreePool( device_desc->ReportIDs );