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
25 #define WIN32_NO_STATUS
32 #include <ddk/hidpddi.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" */
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) */
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
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
,
81 TAG_GLOBAL_REPORT_SIZE
,
83 TAG_GLOBAL_REPORT_COUNT
,
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
,
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
)
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
150 USAGE usages_page
[256];
151 USAGE usages_min
[256];
152 USAGE usages_max
[256];
155 struct hid_value_caps items
;
157 struct hid_value_caps
*stack
;
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
;
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" );
225 copy_global_items( state
->stack
+ state
->global_idx
, &state
->items
);
230 static BOOL
parse_global_pop( struct hid_parser_state
*state
)
232 if (!state
->global_idx
)
234 ERR( "HID parser global stack underflow!\n" );
239 copy_global_items( &state
->items
, state
->stack
+ state
->global_idx
);
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" );
287 if (!array_reserve( &state
->collections
, &state
->collections_size
, state
->caps
.NumberLinkCollectionNodes
))
289 ERR( "HID parser collections overflow!\n" );
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
);
314 static BOOL
parse_end_collection( struct hid_parser_state
*state
)
316 if (!state
->collection_idx
)
318 ERR( "HID parser collection stack underflow!\n" );
322 state
->collection_idx
--;
323 copy_collection_items( &state
->items
, state
->stack
+ state
->collection_idx
);
324 reset_local_items( state
);
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
];
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
);
350 if (!array_reserve( &state
->values
[type
], &state
->values_size
[type
], *value_idx
+ usages_size
))
352 ERR( "HID parser values overflow!\n" );
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
;
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
);
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
] );
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
;
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
) );
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
;
477 if (TRACE_ON( hidp
))
479 TRACE( "descriptor %p, length %u:\n", descriptor
, length
);
480 for (i
= 0; i
< length
;)
483 do { TRACE( " %02x", descriptor
[i
] ); } while (++i
% 16 && i
< length
);
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
);
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));
507 ERR( "Unexpected item value size %d.\n", size
);
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
;
519 case SHORT_ITEM( TAG_MAIN_OUTPUT
, TAG_TYPE_MAIN
):
520 if (!parse_new_value_caps( state
, HidP_Output
)) goto done
;
522 case SHORT_ITEM( TAG_MAIN_FEATURE
, TAG_TYPE_MAIN
):
523 if (!parse_new_value_caps( state
, HidP_Feature
)) goto done
;
525 case SHORT_ITEM( TAG_MAIN_COLLECTION
, TAG_TYPE_MAIN
):
526 if (!parse_new_collection( state
)) goto done
;
528 case SHORT_ITEM( TAG_MAIN_END_COLLECTION
, TAG_TYPE_MAIN
):
529 if (!parse_end_collection( state
)) goto done
;
532 case SHORT_ITEM( TAG_GLOBAL_USAGE_PAGE
, TAG_TYPE_GLOBAL
):
533 state
->items
.usage_page
= value
;
535 case SHORT_ITEM( TAG_GLOBAL_LOGICAL_MINIMUM
, TAG_TYPE_GLOBAL
):
536 state
->items
.logical_min
= signed_value
;
538 case SHORT_ITEM( TAG_GLOBAL_LOGICAL_MAXIMUM
, TAG_TYPE_GLOBAL
):
539 state
->items
.logical_max
= signed_value
;
541 case SHORT_ITEM( TAG_GLOBAL_PHYSICAL_MINIMUM
, TAG_TYPE_GLOBAL
):
542 state
->items
.physical_min
= signed_value
;
544 case SHORT_ITEM( TAG_GLOBAL_PHYSICAL_MAXIMUM
, TAG_TYPE_GLOBAL
):
545 state
->items
.physical_max
= signed_value
;
547 case SHORT_ITEM( TAG_GLOBAL_UNIT_EXPONENT
, TAG_TYPE_GLOBAL
):
548 state
->items
.units_exp
= signed_value
;
550 case SHORT_ITEM( TAG_GLOBAL_UNIT
, TAG_TYPE_GLOBAL
):
551 state
->items
.units
= signed_value
;
553 case SHORT_ITEM( TAG_GLOBAL_REPORT_SIZE
, TAG_TYPE_GLOBAL
):
554 state
->items
.bit_size
= value
;
556 case SHORT_ITEM( TAG_GLOBAL_REPORT_ID
, TAG_TYPE_GLOBAL
):
557 state
->items
.report_id
= value
;
559 case SHORT_ITEM( TAG_GLOBAL_REPORT_COUNT
, TAG_TYPE_GLOBAL
):
560 state
->items
.report_count
= value
;
562 case SHORT_ITEM( TAG_GLOBAL_PUSH
, TAG_TYPE_GLOBAL
):
563 if (!parse_global_push( state
)) goto done
;
565 case SHORT_ITEM( TAG_GLOBAL_POP
, TAG_TYPE_GLOBAL
):
566 if (!parse_global_pop( state
)) goto done
;
569 case SHORT_ITEM( TAG_LOCAL_USAGE
, TAG_TYPE_LOCAL
):
570 if (!parse_local_usage( state
, value
>> 16, value
& 0xffff )) goto done
;
572 case SHORT_ITEM( TAG_LOCAL_USAGE_MINIMUM
, TAG_TYPE_LOCAL
):
573 parse_local_usage_min( state
, value
>> 16, value
& 0xffff );
575 case SHORT_ITEM( TAG_LOCAL_USAGE_MAXIMUM
, TAG_TYPE_LOCAL
):
576 parse_local_usage_max( state
, value
>> 16, value
& 0xffff );
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
;
582 case SHORT_ITEM( TAG_LOCAL_DESIGNATOR_MINIMUM
, TAG_TYPE_LOCAL
):
583 state
->items
.designator_min
= value
;
584 state
->items
.is_designator_range
= TRUE
;
586 case SHORT_ITEM( TAG_LOCAL_DESIGNATOR_MAXIMUM
, TAG_TYPE_LOCAL
):
587 state
->items
.designator_max
= value
;
588 state
->items
.is_designator_range
= TRUE
;
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
;
594 case SHORT_ITEM( TAG_LOCAL_STRING_MINIMUM
, TAG_TYPE_LOCAL
):
595 state
->items
.string_min
= value
;
596 state
->items
.is_string_range
= TRUE
;
598 case SHORT_ITEM( TAG_LOCAL_STRING_MAXIMUM
, TAG_TYPE_LOCAL
):
599 state
->items
.string_max
= value
;
600 state
->items
.is_string_range
= TRUE
;
602 case SHORT_ITEM( TAG_LOCAL_DELIMITER
, TAG_TYPE_LOCAL
):
603 FIXME( "delimiter %d not implemented!\n", value
);
607 FIXME( "item type %x not implemented!\n", *ptr
);
613 if ((data
= build_preparsed_data( state
, pool_type
))) debug_print_preparsed( data
);
616 free_parser_state( state
);
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
) )))
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
)))
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;
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
);