wined3d: Get rid of the "render_to_fbo" field from the wined3d_swapchain structure.
[wine.git] / dlls / hidparse.sys / main.c
blob3a57c338165125dbe5b006b6d35e11caebaf4c3c
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(hidp);
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,
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 (%d), Str %d-%d (%d), Des %d-%d (%d), "
106 "Bits %02x, LCol %d LUsg %02x:%02x, BitSz %d, RCnt %d, Unit %x E%+d, Log %+d-%+d, Phy %+d-%+d",
107 caps->report_id, caps->usage_page, caps->usage_min, caps->usage_max, caps->data_index_min, caps->data_index_max, caps->is_range,
108 caps->string_min, caps->string_max, caps->is_string_range, caps->designator_min, caps->designator_max, caps->is_designator_range,
109 caps->bit_field, 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 void debug_print_preparsed( struct hid_preparsed_data *data )
115 unsigned int i, end;
117 if (TRACE_ON( hidp ))
119 TRACE( "START PREPARSED Data <<< Usage: %i, UsagePage: %i, "
120 "InputReportByteLength: %i, tOutputReportByteLength: %i, "
121 "FeatureReportByteLength: %i, NumberLinkCollectionNodes: %i, "
122 "NumberInputButtonCaps: %i, NumberInputValueCaps: %i, "
123 "NumberInputDataIndices: %i, NumberOutputButtonCaps: %i, "
124 "NumberOutputValueCaps: %i, NumberOutputDataIndices: %i, "
125 "NumberFeatureButtonCaps: %i, NumberFeatureValueCaps: %i, "
126 "NumberFeatureDataIndices: %i\n",
127 data->caps.Usage, data->caps.UsagePage, data->caps.InputReportByteLength,
128 data->caps.OutputReportByteLength, data->caps.FeatureReportByteLength,
129 data->caps.NumberLinkCollectionNodes, data->caps.NumberInputButtonCaps,
130 data->caps.NumberInputValueCaps, data->caps.NumberInputDataIndices,
131 data->caps.NumberOutputButtonCaps, data->caps.NumberOutputValueCaps,
132 data->caps.NumberOutputDataIndices, data->caps.NumberFeatureButtonCaps,
133 data->caps.NumberFeatureValueCaps, data->caps.NumberFeatureDataIndices );
134 end = data->value_caps_count[HidP_Input];
135 for (i = 0; i < end; i++) TRACE( "INPUT: %s\n", debugstr_hid_value_caps( HID_INPUT_VALUE_CAPS( data ) + i ) );
136 end = data->value_caps_count[HidP_Output];
137 for (i = 0; i < end; i++) TRACE( "OUTPUT: %s\n", debugstr_hid_value_caps( HID_OUTPUT_VALUE_CAPS( data ) + i ) );
138 end = data->value_caps_count[HidP_Feature];
139 for (i = 0; i < end; i++) TRACE( "FEATURE: %s\n", debugstr_hid_value_caps( HID_FEATURE_VALUE_CAPS( data ) + i ) );
140 end = data->caps.NumberLinkCollectionNodes;
141 for (i = 0; i < end; i++) TRACE( "COLLECTION: %s\n", debugstr_hid_value_caps( HID_COLLECTION_VALUE_CAPS( data ) + i ) );
142 TRACE(">>> END Preparsed Data\n");
146 struct hid_parser_state
148 HIDP_CAPS caps;
150 USAGE usages_page[256];
151 USAGE usages_min[256];
152 USAGE usages_max[256];
153 DWORD usages_size;
155 struct hid_value_caps items;
157 struct hid_value_caps *stack;
158 DWORD stack_size;
159 DWORD global_idx;
160 DWORD collection_idx;
162 struct hid_value_caps *collections;
163 DWORD collections_size;
165 struct hid_value_caps *values[3];
166 ULONG values_size[3];
168 ULONG bit_size[3][256];
169 USHORT *byte_size[3]; /* pointers to caps */
170 USHORT *value_idx[3]; /* pointers to caps */
171 USHORT *data_idx[3]; /* pointers to caps */
174 static BOOL array_reserve( struct hid_value_caps **array, DWORD *array_size, DWORD index )
176 if (index < *array_size) return TRUE;
177 if ((*array_size = *array_size ? (*array_size * 3 / 2) : 32) <= index) return FALSE;
178 if (!(*array = realloc( *array, *array_size * sizeof(**array) ))) return FALSE;
179 return TRUE;
182 static void copy_global_items( struct hid_value_caps *dst, const struct hid_value_caps *src )
184 dst->usage_page = src->usage_page;
185 dst->logical_min = src->logical_min;
186 dst->logical_max = src->logical_max;
187 dst->physical_min = src->physical_min;
188 dst->physical_max = src->physical_max;
189 dst->units_exp = src->units_exp;
190 dst->units = src->units;
191 dst->bit_size = src->bit_size;
192 dst->report_id = src->report_id;
193 dst->report_count = src->report_count;
196 static void copy_collection_items( struct hid_value_caps *dst, const struct hid_value_caps *src )
198 dst->link_collection = src->link_collection;
199 dst->link_usage_page = src->link_usage_page;
200 dst->link_usage = src->link_usage;
203 static void reset_local_items( struct hid_parser_state *state )
205 struct hid_value_caps tmp;
206 copy_global_items( &tmp, &state->items );
207 copy_collection_items( &tmp, &state->items );
208 memset( &state->items, 0, sizeof(state->items) );
209 copy_global_items( &state->items, &tmp );
210 copy_collection_items( &state->items, &tmp );
211 memset( &state->usages_page, 0, sizeof(state->usages_page) );
212 memset( &state->usages_min, 0, sizeof(state->usages_min) );
213 memset( &state->usages_max, 0, sizeof(state->usages_max) );
214 state->usages_size = 0;
217 static BOOL parse_global_push( struct hid_parser_state *state )
219 if (!array_reserve( &state->stack, &state->stack_size, state->global_idx ))
221 ERR( "HID parser stack overflow!\n" );
222 return FALSE;
225 copy_global_items( state->stack + state->global_idx, &state->items );
226 state->global_idx++;
227 return TRUE;
230 static BOOL parse_global_pop( struct hid_parser_state *state )
232 if (!state->global_idx)
234 ERR( "HID parser global stack underflow!\n" );
235 return FALSE;
238 state->global_idx--;
239 copy_global_items( &state->items, state->stack + state->global_idx );
240 return TRUE;
243 static BOOL parse_local_usage( struct hid_parser_state *state, USAGE usage_page, USAGE usage )
245 if (!usage_page) usage_page = state->items.usage_page;
246 if (state->items.is_range) state->usages_size = 0;
247 state->usages_page[state->usages_size] = usage_page;
248 state->usages_min[state->usages_size] = usage;
249 state->usages_max[state->usages_size] = usage;
250 state->items.usage_min = usage;
251 state->items.usage_max = usage;
252 state->items.is_range = FALSE;
253 if (state->usages_size++ == 255) ERR( "HID parser usages stack overflow!\n" );
254 return state->usages_size <= 255;
257 static void parse_local_usage_min( struct hid_parser_state *state, USAGE usage_page, USAGE usage )
259 if (!usage_page) usage_page = state->items.usage_page;
260 if (!state->items.is_range) state->usages_max[0] = 0;
261 state->usages_page[0] = usage_page;
262 state->usages_min[0] = usage;
263 state->items.usage_min = usage;
264 state->items.is_range = TRUE;
265 state->usages_size = 1;
268 static void parse_local_usage_max( struct hid_parser_state *state, USAGE usage_page, USAGE usage )
270 if (!usage_page) usage_page = state->items.usage_page;
271 if (!state->items.is_range) state->usages_min[0] = 0;
272 state->usages_page[0] = usage_page;
273 state->usages_max[0] = usage;
274 state->items.usage_max = usage;
275 state->items.is_range = TRUE;
276 state->usages_size = 1;
279 static BOOL parse_new_collection( struct hid_parser_state *state )
281 if (!array_reserve( &state->stack, &state->stack_size, state->collection_idx ))
283 ERR( "HID parser stack overflow!\n" );
284 return FALSE;
287 if (!array_reserve( &state->collections, &state->collections_size, state->caps.NumberLinkCollectionNodes ))
289 ERR( "HID parser collections overflow!\n" );
290 return FALSE;
293 copy_collection_items( state->stack + state->collection_idx, &state->items );
294 state->collection_idx++;
296 state->items.usage_min = state->usages_min[0];
297 state->items.usage_max = state->usages_max[0];
299 state->collections[state->caps.NumberLinkCollectionNodes] = state->items;
300 state->items.link_collection = state->caps.NumberLinkCollectionNodes;
301 state->items.link_usage_page = state->items.usage_page;
302 state->items.link_usage = state->items.usage_min;
303 if (!state->caps.NumberLinkCollectionNodes)
305 state->caps.UsagePage = state->items.usage_page;
306 state->caps.Usage = state->items.usage_min;
308 state->caps.NumberLinkCollectionNodes++;
310 reset_local_items( state );
311 return TRUE;
314 static BOOL parse_end_collection( struct hid_parser_state *state )
316 if (!state->collection_idx)
318 ERR( "HID parser collection stack underflow!\n" );
319 return FALSE;
322 state->collection_idx--;
323 copy_collection_items( &state->items, state->stack + state->collection_idx );
324 reset_local_items( state );
325 return TRUE;
328 static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TYPE type )
330 struct hid_value_caps *value;
331 USAGE usage_page = state->items.usage_page;
332 DWORD usages_size = max( 1, state->usages_size );
333 USHORT *byte_size = state->byte_size[type];
334 USHORT *value_idx = state->value_idx[type];
335 USHORT *data_idx = state->data_idx[type];
336 ULONG *bit_size = &state->bit_size[type][state->items.report_id];
337 BOOL is_array;
339 if (!*bit_size) *bit_size = 8;
340 *bit_size += state->items.bit_size * state->items.report_count;
341 *byte_size = max( *byte_size, (*bit_size + 7) / 8 );
342 state->items.start_bit = *bit_size;
344 if (!state->items.report_count)
346 reset_local_items( state );
347 return TRUE;
350 if (!array_reserve( &state->values[type], &state->values_size[type], *value_idx + usages_size ))
352 ERR( "HID parser values overflow!\n" );
353 return FALSE;
355 value = state->values[type] + *value_idx;
357 state->items.start_index = usages_size;
358 if (!(is_array = HID_VALUE_CAPS_IS_ARRAY( &state->items ))) state->items.report_count -= usages_size - 1;
359 else state->items.start_bit -= state->items.report_count * state->items.bit_size;
361 while (usages_size--)
363 if (!is_array) state->items.start_bit -= state->items.report_count * state->items.bit_size;
364 state->items.usage_page = state->usages_page[usages_size];
365 state->items.usage_min = state->usages_min[usages_size];
366 state->items.usage_max = state->usages_max[usages_size];
367 state->items.data_index_min = *data_idx;
368 state->items.data_index_max = *data_idx + state->items.usage_max - state->items.usage_min;
369 if (state->items.usage_max || state->items.usage_min) *data_idx = state->items.data_index_max + 1;
370 *value++ = state->items;
371 *value_idx += 1;
372 if (!is_array) state->items.report_count = 1;
373 else state->items.start_index -= 1;
376 state->items.usage_page = usage_page;
377 reset_local_items( state );
378 return TRUE;
381 static void init_parser_state( struct hid_parser_state *state )
383 memset( state, 0, sizeof(*state) );
384 state->byte_size[HidP_Input] = &state->caps.InputReportByteLength;
385 state->byte_size[HidP_Output] = &state->caps.OutputReportByteLength;
386 state->byte_size[HidP_Feature] = &state->caps.FeatureReportByteLength;
388 state->value_idx[HidP_Input] = &state->caps.NumberInputValueCaps;
389 state->value_idx[HidP_Output] = &state->caps.NumberOutputValueCaps;
390 state->value_idx[HidP_Feature] = &state->caps.NumberFeatureValueCaps;
392 state->data_idx[HidP_Input] = &state->caps.NumberInputDataIndices;
393 state->data_idx[HidP_Output] = &state->caps.NumberOutputDataIndices;
394 state->data_idx[HidP_Feature] = &state->caps.NumberFeatureDataIndices;
397 static void free_parser_state( struct hid_parser_state *state )
399 if (state->global_idx) ERR( "%u unpopped device caps on the stack\n", state->global_idx );
400 if (state->collection_idx) ERR( "%u unpopped device collection on the stack\n", state->collection_idx );
401 free( state->stack );
402 free( state->collections );
403 free( state->values[HidP_Input] );
404 free( state->values[HidP_Output] );
405 free( state->values[HidP_Feature] );
406 free( state );
409 static struct hid_preparsed_data *build_preparsed_data( struct hid_parser_state *state, POOL_TYPE pool_type )
411 struct hid_preparsed_data *data;
412 struct hid_value_caps *caps;
413 DWORD i, button, filler, caps_len, size;
415 caps_len = state->caps.NumberInputValueCaps + state->caps.NumberOutputValueCaps +
416 state->caps.NumberFeatureValueCaps + state->caps.NumberLinkCollectionNodes;
417 size = FIELD_OFFSET( struct hid_preparsed_data, value_caps[caps_len] );
419 if (!(data = ExAllocatePool( pool_type, size ))) return NULL;
420 memset( data, 0, size );
421 data->magic = HID_MAGIC;
422 data->size = size;
423 data->caps = state->caps;
424 data->value_caps_count[HidP_Input] = state->caps.NumberInputValueCaps;
425 data->value_caps_count[HidP_Output] = state->caps.NumberOutputValueCaps;
426 data->value_caps_count[HidP_Feature] = state->caps.NumberFeatureValueCaps;
428 /* fixup value vs button vs filler counts */
430 caps = HID_INPUT_VALUE_CAPS( data );
431 memcpy( caps, state->values[0], data->caps.NumberInputValueCaps * sizeof(*caps) );
432 for (i = 0, button = 0, filler = 0; i < data->caps.NumberInputValueCaps; ++i)
434 if (!caps[i].usage_min && !caps[i].usage_max) filler++;
435 else if (HID_VALUE_CAPS_IS_BUTTON( caps + i )) button++;
437 data->caps.NumberInputButtonCaps = button;
438 data->caps.NumberInputValueCaps -= filler + button;
440 caps = HID_OUTPUT_VALUE_CAPS( data );
441 memcpy( caps, state->values[1], data->caps.NumberOutputValueCaps * sizeof(*caps) );
442 for (i = 0, button = 0, filler = 0; i < data->caps.NumberOutputValueCaps; ++i)
444 if (!caps[i].usage_min && !caps[i].usage_max) filler++;
445 else if (HID_VALUE_CAPS_IS_BUTTON( caps + i )) button++;
447 caps += data->caps.NumberOutputValueCaps;
448 data->caps.NumberOutputButtonCaps = button;
449 data->caps.NumberOutputValueCaps -= filler + button;
451 caps = HID_FEATURE_VALUE_CAPS( data );
452 memcpy( caps, state->values[2], data->caps.NumberFeatureValueCaps * sizeof(*caps) );
453 for (i = 0, button = 0, filler = 0; i < data->caps.NumberFeatureValueCaps; ++i)
455 if (!caps[i].usage_min && !caps[i].usage_max) filler++;
456 else if (HID_VALUE_CAPS_IS_BUTTON( caps + i )) button++;
458 caps += data->caps.NumberFeatureValueCaps;
459 data->caps.NumberFeatureButtonCaps = button;
460 data->caps.NumberFeatureValueCaps -= filler + button;
462 caps = HID_COLLECTION_VALUE_CAPS( data );
463 memcpy( caps, state->collections, data->caps.NumberLinkCollectionNodes * sizeof(*caps) );
465 return data;
468 struct hid_preparsed_data *parse_descriptor( BYTE *descriptor, unsigned int length, POOL_TYPE pool_type )
470 struct hid_preparsed_data *data = NULL;
471 struct hid_parser_state *state;
472 UINT32 size, value;
473 INT32 signed_value;
474 BYTE *ptr, *end;
475 int i;
477 if (TRACE_ON( hidp ))
479 TRACE( "descriptor %p, length %u:\n", descriptor, length );
480 for (i = 0; i < length;)
482 TRACE( "%08x ", i );
483 do { TRACE( " %02x", descriptor[i] ); } while (++i % 16 && i < length);
484 TRACE( "\n" );
488 if (!(state = malloc( sizeof(*state) ))) return NULL;
489 init_parser_state( state );
491 for (ptr = descriptor, end = descriptor + length; ptr != end; ptr += size + 1)
493 size = (*ptr & 0x03);
494 if (size == 3) size = 4;
495 if (ptr + size > end)
497 ERR( "Need %d bytes to read item value\n", size );
498 goto done;
501 if (size == 0) signed_value = value = 0;
502 else if (size == 1) signed_value = (INT8)(value = *(UINT8 *)(ptr + 1));
503 else if (size == 2) signed_value = (INT16)(value = *(UINT16 *)(ptr + 1));
504 else if (size == 4) signed_value = (INT32)(value = *(UINT32 *)(ptr + 1));
505 else
507 ERR( "Unexpected item value size %d.\n", size );
508 goto done;
511 state->items.bit_field = value;
513 #define SHORT_ITEM( tag, type ) (((tag) << 4) | ((type) << 2))
514 switch (*ptr & SHORT_ITEM( 0xf, 0x3 ))
516 case SHORT_ITEM( TAG_MAIN_INPUT, TAG_TYPE_MAIN ):
517 if (!parse_new_value_caps( state, HidP_Input )) goto done;
518 break;
519 case SHORT_ITEM( TAG_MAIN_OUTPUT, TAG_TYPE_MAIN ):
520 if (!parse_new_value_caps( state, HidP_Output )) goto done;
521 break;
522 case SHORT_ITEM( TAG_MAIN_FEATURE, TAG_TYPE_MAIN ):
523 if (!parse_new_value_caps( state, HidP_Feature )) goto done;
524 break;
525 case SHORT_ITEM( TAG_MAIN_COLLECTION, TAG_TYPE_MAIN ):
526 if (!parse_new_collection( state )) goto done;
527 break;
528 case SHORT_ITEM( TAG_MAIN_END_COLLECTION, TAG_TYPE_MAIN ):
529 if (!parse_end_collection( state )) goto done;
530 break;
532 case SHORT_ITEM( TAG_GLOBAL_USAGE_PAGE, TAG_TYPE_GLOBAL ):
533 state->items.usage_page = value;
534 break;
535 case SHORT_ITEM( TAG_GLOBAL_LOGICAL_MINIMUM, TAG_TYPE_GLOBAL ):
536 state->items.logical_min = signed_value;
537 break;
538 case SHORT_ITEM( TAG_GLOBAL_LOGICAL_MAXIMUM, TAG_TYPE_GLOBAL ):
539 state->items.logical_max = signed_value;
540 break;
541 case SHORT_ITEM( TAG_GLOBAL_PHYSICAL_MINIMUM, TAG_TYPE_GLOBAL ):
542 state->items.physical_min = signed_value;
543 break;
544 case SHORT_ITEM( TAG_GLOBAL_PHYSICAL_MAXIMUM, TAG_TYPE_GLOBAL ):
545 state->items.physical_max = signed_value;
546 break;
547 case SHORT_ITEM( TAG_GLOBAL_UNIT_EXPONENT, TAG_TYPE_GLOBAL ):
548 state->items.units_exp = signed_value;
549 break;
550 case SHORT_ITEM( TAG_GLOBAL_UNIT, TAG_TYPE_GLOBAL ):
551 state->items.units = signed_value;
552 break;
553 case SHORT_ITEM( TAG_GLOBAL_REPORT_SIZE, TAG_TYPE_GLOBAL ):
554 state->items.bit_size = value;
555 break;
556 case SHORT_ITEM( TAG_GLOBAL_REPORT_ID, TAG_TYPE_GLOBAL ):
557 state->items.report_id = value;
558 break;
559 case SHORT_ITEM( TAG_GLOBAL_REPORT_COUNT, TAG_TYPE_GLOBAL ):
560 state->items.report_count = value;
561 break;
562 case SHORT_ITEM( TAG_GLOBAL_PUSH, TAG_TYPE_GLOBAL ):
563 if (!parse_global_push( state )) goto done;
564 break;
565 case SHORT_ITEM( TAG_GLOBAL_POP, TAG_TYPE_GLOBAL ):
566 if (!parse_global_pop( state )) goto done;
567 break;
569 case SHORT_ITEM( TAG_LOCAL_USAGE, TAG_TYPE_LOCAL ):
570 if (!parse_local_usage( state, value >> 16, value & 0xffff )) goto done;
571 break;
572 case SHORT_ITEM( TAG_LOCAL_USAGE_MINIMUM, TAG_TYPE_LOCAL ):
573 parse_local_usage_min( state, value >> 16, value & 0xffff );
574 break;
575 case SHORT_ITEM( TAG_LOCAL_USAGE_MAXIMUM, TAG_TYPE_LOCAL ):
576 parse_local_usage_max( state, value >> 16, value & 0xffff );
577 break;
578 case SHORT_ITEM( TAG_LOCAL_DESIGNATOR_INDEX, TAG_TYPE_LOCAL ):
579 state->items.designator_min = state->items.designator_max = value;
580 state->items.is_designator_range = FALSE;
581 break;
582 case SHORT_ITEM( TAG_LOCAL_DESIGNATOR_MINIMUM, TAG_TYPE_LOCAL ):
583 state->items.designator_min = value;
584 state->items.is_designator_range = TRUE;
585 break;
586 case SHORT_ITEM( TAG_LOCAL_DESIGNATOR_MAXIMUM, TAG_TYPE_LOCAL ):
587 state->items.designator_max = value;
588 state->items.is_designator_range = TRUE;
589 break;
590 case SHORT_ITEM( TAG_LOCAL_STRING_INDEX, TAG_TYPE_LOCAL ):
591 state->items.string_min = state->items.string_max = value;
592 state->items.is_string_range = FALSE;
593 break;
594 case SHORT_ITEM( TAG_LOCAL_STRING_MINIMUM, TAG_TYPE_LOCAL ):
595 state->items.string_min = value;
596 state->items.is_string_range = TRUE;
597 break;
598 case SHORT_ITEM( TAG_LOCAL_STRING_MAXIMUM, TAG_TYPE_LOCAL ):
599 state->items.string_max = value;
600 state->items.is_string_range = TRUE;
601 break;
602 case SHORT_ITEM( TAG_LOCAL_DELIMITER, TAG_TYPE_LOCAL ):
603 FIXME( "delimiter %d not implemented!\n", value );
604 goto done;
606 default:
607 FIXME( "item type %x not implemented!\n", *ptr );
608 goto done;
610 #undef SHORT_ITEM
613 if ((data = build_preparsed_data( state, pool_type ))) debug_print_preparsed( data );
615 done:
616 free_parser_state( state );
617 return data;
620 NTSTATUS WINAPI HidP_GetCollectionDescription( PHIDP_REPORT_DESCRIPTOR report_desc, ULONG report_desc_len,
621 POOL_TYPE pool_type, HIDP_DEVICE_DESC *device_desc )
623 ULONG i, len, report_count = 0, input_len[256] = {0}, output_len[256] = {0}, feature_len[256] = {0};
624 struct hid_value_caps *caps, *caps_end;
625 struct hid_preparsed_data *preparsed;
627 TRACE( "report_desc %p, report_desc_len %u, pool_type %u, device_desc %p.\n",
628 report_desc, report_desc_len, pool_type, device_desc );
630 memset( device_desc, 0, sizeof(*device_desc) );
632 if (!(preparsed = parse_descriptor( report_desc, report_desc_len, pool_type )))
633 return HIDP_STATUS_INTERNAL_ERROR;
635 if (!(device_desc->CollectionDesc = ExAllocatePool( pool_type, sizeof(*device_desc->CollectionDesc) )))
637 free( preparsed );
638 return STATUS_NO_MEMORY;
641 device_desc->CollectionDescLength = 1;
642 device_desc->CollectionDesc[0].UsagePage = preparsed->caps.UsagePage;
643 device_desc->CollectionDesc[0].Usage = preparsed->caps.Usage;
644 device_desc->CollectionDesc[0].CollectionNumber = 1;
645 device_desc->CollectionDesc[0].InputLength = preparsed->caps.InputReportByteLength;
646 device_desc->CollectionDesc[0].OutputLength = preparsed->caps.OutputReportByteLength;
647 device_desc->CollectionDesc[0].FeatureLength = preparsed->caps.FeatureReportByteLength;
648 device_desc->CollectionDesc[0].PreparsedDataLength = preparsed->size;
649 device_desc->CollectionDesc[0].PreparsedData = (PHIDP_PREPARSED_DATA)preparsed;
651 caps = HID_INPUT_VALUE_CAPS( preparsed );
652 caps_end = caps + preparsed->value_caps_count[HidP_Input];
653 for (; caps != caps_end; ++caps)
655 len = caps->start_bit + caps->bit_size * caps->report_count;
656 if (!input_len[caps->report_id]) report_count++;
657 input_len[caps->report_id] = max(input_len[caps->report_id], len);
660 caps = HID_OUTPUT_VALUE_CAPS( preparsed );
661 caps_end = caps + preparsed->value_caps_count[HidP_Output];
662 for (; caps != caps_end; ++caps)
664 len = caps->start_bit + caps->bit_size * caps->report_count;
665 if (!input_len[caps->report_id] && !output_len[caps->report_id]) report_count++;
666 output_len[caps->report_id] = max(output_len[caps->report_id], len);
669 caps = HID_FEATURE_VALUE_CAPS( preparsed );
670 caps_end = caps + preparsed->value_caps_count[HidP_Feature];
671 for (; caps != caps_end; ++caps)
673 len = caps->start_bit + caps->bit_size * caps->report_count;
674 if (!input_len[caps->report_id] && !output_len[caps->report_id] && !feature_len[caps->report_id]) report_count++;
675 feature_len[caps->report_id] = max(feature_len[caps->report_id], len);
678 if (!(device_desc->ReportIDs = ExAllocatePool( pool_type, sizeof(*device_desc->ReportIDs) * report_count )))
680 free( preparsed );
681 ExFreePool( device_desc->CollectionDesc );
682 return STATUS_NO_MEMORY;
685 for (i = 0, report_count = 0; i < 256; ++i)
687 if (!input_len[i] && !output_len[i] && !feature_len[i]) continue;
688 device_desc->ReportIDs[report_count].ReportID = i;
689 device_desc->ReportIDs[report_count].CollectionNumber = 1;
690 device_desc->ReportIDs[report_count].InputLength = (input_len[i] + 7) / 8;
691 device_desc->ReportIDs[report_count].OutputLength = (output_len[i] + 7) / 8;
692 device_desc->ReportIDs[report_count].FeatureLength = (feature_len[i] + 7) / 8;
693 report_count++;
695 device_desc->ReportIDsLength = report_count;
697 return HIDP_STATUS_SUCCESS;
700 void WINAPI HidP_FreeCollectionDescription( HIDP_DEVICE_DESC *device_desc )
702 TRACE( "device_desc %p.\n", device_desc );
704 ExFreePool( device_desc->CollectionDesc );
705 ExFreePool( device_desc->ReportIDs );