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
25 #define WIN32_NO_STATUS
33 #include "ddk/hidpi.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(hid
);
39 static NTSTATUS
get_value_caps_range( struct hid_preparsed_data
*preparsed
, HIDP_REPORT_TYPE report_type
, ULONG report_len
,
40 const struct hid_value_caps
**caps
, const struct hid_value_caps
**caps_end
)
42 if (!preparsed
|| memcmp( preparsed
->magic
, "HidP KDR", 8 )) return HIDP_STATUS_INVALID_PREPARSED_DATA
;
47 if (report_len
&& report_len
!= preparsed
->input_report_byte_length
)
48 return HIDP_STATUS_INVALID_REPORT_LENGTH
;
49 *caps
= HID_INPUT_VALUE_CAPS( preparsed
);
50 *caps_end
= *caps
+ preparsed
->input_caps_count
;
53 if (report_len
&& report_len
!= preparsed
->output_report_byte_length
)
54 return HIDP_STATUS_INVALID_REPORT_LENGTH
;
55 *caps
= HID_OUTPUT_VALUE_CAPS( preparsed
);
56 *caps_end
= *caps
+ preparsed
->output_caps_count
;
59 if (report_len
&& report_len
!= preparsed
->feature_report_byte_length
)
60 return HIDP_STATUS_INVALID_REPORT_LENGTH
;
61 *caps
= HID_FEATURE_VALUE_CAPS( preparsed
);
62 *caps_end
= *caps
+ preparsed
->feature_caps_count
;
65 return HIDP_STATUS_INVALID_REPORT_TYPE
;
68 return HIDP_STATUS_SUCCESS
;
71 #define USAGE_MASK 0xffff
72 #define USAGE_ANY 0x10000
85 static BOOL
match_value_caps( const struct hid_value_caps
*caps
, const struct caps_filter
*filter
)
87 if (!caps
->usage_min
&& !caps
->usage_max
) return FALSE
;
88 if (filter
->buttons
&& !(caps
->flags
& HID_VALUE_CAPS_IS_BUTTON
)) return FALSE
;
89 if (filter
->values
&& (caps
->flags
& HID_VALUE_CAPS_IS_BUTTON
)) return FALSE
;
90 if (filter
->usage_page
!= USAGE_ANY
&& (filter
->usage_page
& USAGE_MASK
) != caps
->usage_page
) return FALSE
;
91 if (filter
->collection
&& filter
->collection
!= caps
->link_collection
) return FALSE
;
92 if (filter
->usage
== USAGE_ANY
) return TRUE
;
93 return caps
->usage_min
<= (filter
->usage
& USAGE_MASK
) && caps
->usage_max
>= (filter
->usage
& USAGE_MASK
);
96 typedef NTSTATUS (*enum_value_caps_callback
)( const struct hid_value_caps
*caps
, void *user
);
98 static NTSTATUS
enum_value_caps( struct hid_preparsed_data
*preparsed
, HIDP_REPORT_TYPE report_type
,
99 ULONG report_len
, const struct caps_filter
*filter
,
100 enum_value_caps_callback callback
, void *user
, USHORT
*count
)
102 const struct hid_value_caps
*caps
, *caps_end
;
103 BOOL is_range
, incompatible
= FALSE
;
104 LONG remaining
= *count
;
107 for (status
= get_value_caps_range( preparsed
, report_type
, report_len
, &caps
, &caps_end
);
108 status
== HIDP_STATUS_SUCCESS
&& caps
!= caps_end
; caps
++)
110 is_range
= caps
->flags
& HID_VALUE_CAPS_IS_RANGE
;
111 if (!match_value_caps( caps
, filter
)) continue;
112 if (filter
->report_id
&& caps
->report_id
!= filter
->report_id
) incompatible
= TRUE
;
113 else if (filter
->array
&& (is_range
|| caps
->report_count
<= 1)) return HIDP_STATUS_NOT_VALUE_ARRAY
;
114 else if (remaining
-- > 0) status
= callback( caps
, user
);
117 if (status
== HIDP_STATUS_NULL
) status
= HIDP_STATUS_SUCCESS
;
118 if (status
!= HIDP_STATUS_SUCCESS
) return status
;
121 if (*count
== 0) return incompatible
? HIDP_STATUS_INCOMPATIBLE_REPORT_ID
: HIDP_STATUS_USAGE_NOT_FOUND
;
122 if (remaining
< 0) return HIDP_STATUS_BUFFER_TOO_SMALL
;
123 return HIDP_STATUS_SUCCESS
;
126 /* copy count bits from src, starting at (-shift) bit if < 0, to dst starting at (shift) bit if > 0 */
127 static void copy_bits( unsigned char *dst
, const unsigned char *src
, int count
, int shift
)
129 unsigned char bits
, mask
;
130 size_t src_shift
= shift
< 0 ? (-shift
& 7) : 0;
131 size_t dst_shift
= shift
> 0 ? (shift
& 7) : 0;
132 if (shift
< 0) src
+= -shift
/ 8;
133 if (shift
> 0) dst
+= shift
/ 8;
135 if (src_shift
== 0 && dst_shift
== 0)
137 memcpy( dst
, src
, count
/ 8 );
145 bits
= *dst
<< (8 - dst_shift
);
150 *dst
= bits
>> (8 - dst_shift
);
151 bits
= *(unsigned short *)src
++ >> src_shift
;
152 *dst
++ |= bits
<< dst_shift
;
156 bits
>>= (8 - dst_shift
);
157 if (count
<= 8 - src_shift
) bits
|= (*src
>> src_shift
) << dst_shift
;
158 else bits
|= (*(unsigned short *)src
>> src_shift
) << dst_shift
;
160 mask
= (1 << count
) - 1;
161 *dst
= (bits
& mask
) | (*dst
& ~mask
);
164 NTSTATUS WINAPI
HidP_GetButtonCaps( HIDP_REPORT_TYPE report_type
, HIDP_BUTTON_CAPS
*caps
, USHORT
*caps_count
,
165 PHIDP_PREPARSED_DATA preparsed_data
)
167 return HidP_GetSpecificButtonCaps( report_type
, 0, 0, 0, caps
, caps_count
, preparsed_data
);
170 NTSTATUS WINAPI
HidP_GetCaps( PHIDP_PREPARSED_DATA preparsed_data
, HIDP_CAPS
*caps
)
172 struct hid_preparsed_data
*preparsed
= (struct hid_preparsed_data
*)preparsed_data
;
173 struct hid_value_caps
*it
, *end
;
175 TRACE( "preparsed_data %p, caps %p.\n", preparsed_data
, caps
);
177 if (!preparsed
|| memcmp( preparsed
->magic
, "HidP KDR", 8 )) return HIDP_STATUS_INVALID_PREPARSED_DATA
;
179 caps
->Usage
= preparsed
->usage
;
180 caps
->UsagePage
= preparsed
->usage_page
;
181 caps
->InputReportByteLength
= preparsed
->input_report_byte_length
;
182 caps
->OutputReportByteLength
= preparsed
->output_report_byte_length
;
183 caps
->FeatureReportByteLength
= preparsed
->feature_report_byte_length
;
184 caps
->NumberLinkCollectionNodes
= preparsed
->number_link_collection_nodes
;
185 caps
->NumberInputButtonCaps
= 0;
186 caps
->NumberInputValueCaps
= 0;
187 caps
->NumberInputDataIndices
= 0;
188 caps
->NumberOutputButtonCaps
= 0;
189 caps
->NumberOutputValueCaps
= 0;
190 caps
->NumberOutputDataIndices
= 0;
191 caps
->NumberFeatureButtonCaps
= 0;
192 caps
->NumberFeatureValueCaps
= 0;
193 caps
->NumberFeatureDataIndices
= 0;
195 for (it
= HID_INPUT_VALUE_CAPS( preparsed
), end
= it
+ preparsed
->input_caps_count
;
198 if (!it
->usage_min
&& !it
->usage_max
) continue;
199 if (it
->flags
& HID_VALUE_CAPS_IS_BUTTON
) caps
->NumberInputButtonCaps
++;
200 else caps
->NumberInputValueCaps
++;
201 if (!(it
->flags
& HID_VALUE_CAPS_IS_RANGE
)) caps
->NumberInputDataIndices
++;
202 else caps
->NumberInputDataIndices
+= it
->data_index_max
- it
->data_index_min
+ 1;
205 for (it
= HID_OUTPUT_VALUE_CAPS( preparsed
), end
= it
+ preparsed
->output_caps_count
;
208 if (!it
->usage_min
&& !it
->usage_max
) continue;
209 if (it
->flags
& HID_VALUE_CAPS_IS_BUTTON
) caps
->NumberOutputButtonCaps
++;
210 else caps
->NumberOutputValueCaps
++;
211 if (!(it
->flags
& HID_VALUE_CAPS_IS_RANGE
)) caps
->NumberOutputDataIndices
++;
212 else caps
->NumberOutputDataIndices
+= it
->data_index_max
- it
->data_index_min
+ 1;
215 for (it
= HID_FEATURE_VALUE_CAPS( preparsed
), end
= it
+ preparsed
->feature_caps_count
;
218 if (!it
->usage_min
&& !it
->usage_max
) continue;
219 if (it
->flags
& HID_VALUE_CAPS_IS_BUTTON
) caps
->NumberFeatureButtonCaps
++;
220 else caps
->NumberFeatureValueCaps
++;
221 if (!(it
->flags
& HID_VALUE_CAPS_IS_RANGE
)) caps
->NumberFeatureDataIndices
++;
222 else caps
->NumberFeatureDataIndices
+= it
->data_index_max
- it
->data_index_min
+ 1;
225 return HIDP_STATUS_SUCCESS
;
228 struct usage_value_params
237 static LONG
sign_extend( ULONG value
, const struct hid_value_caps
*caps
)
239 UINT sign
= 1 << (caps
->bit_size
- 1);
240 if (sign
<= 1 || caps
->logical_min
>= 0) return value
;
241 return value
- ((value
& sign
) << 1);
244 static NTSTATUS
get_usage_value( const struct hid_value_caps
*caps
, void *user
)
246 unsigned char *report_buf
, start_bit
= caps
->start_bit
;
247 ULONG bit_count
= caps
->bit_size
, bit_offset
= 0;
248 struct usage_value_params
*params
= user
;
250 if (params
->array
) bit_count
*= caps
->report_count
;
251 else bit_offset
= (params
->usage
- caps
->usage_min
) * caps
->bit_size
;
253 if ((bit_count
+ 7) / 8 > params
->value_len
) return HIDP_STATUS_BUFFER_TOO_SMALL
;
254 memset( params
->value_buf
, 0, params
->value_len
);
256 report_buf
= (unsigned char *)params
->report_buf
+ caps
->start_byte
+ bit_offset
/ 8;
257 copy_bits( params
->value_buf
, report_buf
, bit_count
, -(start_bit
+ bit_offset
% 8) );
259 return HIDP_STATUS_NULL
;
262 static NTSTATUS
get_scaled_usage_value( const struct hid_value_caps
*caps
, void *user
)
264 struct usage_value_params
*params
= user
;
265 LONG signed_value
, *value
= params
->value_buf
;
266 ULONG unsigned_value
= 0;
269 params
->value_buf
= &unsigned_value
;
270 params
->value_len
= sizeof(unsigned_value
);
271 if ((status
= get_usage_value( caps
, params
)) != HIDP_STATUS_NULL
) return status
;
273 if (sizeof(LONG
) > params
->value_len
) return HIDP_STATUS_BUFFER_TOO_SMALL
;
274 signed_value
= sign_extend( unsigned_value
, caps
);
276 if (caps
->logical_min
> caps
->logical_max
|| caps
->physical_min
> caps
->physical_max
)
277 return HIDP_STATUS_BAD_LOG_PHY_VALUES
;
278 if (caps
->logical_min
> signed_value
|| caps
->logical_max
< signed_value
)
279 return HIDP_STATUS_VALUE_OUT_OF_RANGE
;
281 if (!caps
->physical_min
&& !caps
->physical_max
) *value
= signed_value
;
282 else *value
= caps
->physical_min
+ MulDiv( signed_value
- caps
->logical_min
, caps
->physical_max
- caps
->physical_min
,
283 caps
->logical_max
- caps
->logical_min
);
284 return HIDP_STATUS_NULL
;
287 NTSTATUS WINAPI
HidP_GetScaledUsageValue( HIDP_REPORT_TYPE report_type
, USAGE usage_page
, USHORT collection
,
288 USAGE usage
, LONG
*value
, PHIDP_PREPARSED_DATA preparsed_data
,
289 char *report_buf
, ULONG report_len
)
291 struct usage_value_params params
= {.usage
= usage
, .value_buf
= value
, .value_len
= sizeof(*value
), .report_buf
= report_buf
};
292 struct hid_preparsed_data
*preparsed
= (struct hid_preparsed_data
*)preparsed_data
;
293 struct caps_filter filter
= {.values
= TRUE
, .usage_page
= usage_page
, .collection
= collection
, .usage
= usage
};
296 TRACE( "report_type %d, usage_page %u, collection %u, usage %u, value %p, preparsed_data %p, report_buf %p, report_len %lu.\n",
297 report_type
, usage_page
, collection
, usage
, value
, preparsed_data
, report_buf
, report_len
);
300 if (!report_len
) return HIDP_STATUS_INVALID_REPORT_LENGTH
;
302 filter
.report_id
= report_buf
[0];
303 return enum_value_caps( preparsed
, report_type
, report_len
, &filter
, get_scaled_usage_value
, ¶ms
, &count
);
306 NTSTATUS WINAPI
HidP_GetUsageValue( HIDP_REPORT_TYPE report_type
, USAGE usage_page
, USHORT collection
, USAGE usage
,
307 ULONG
*value
, PHIDP_PREPARSED_DATA preparsed_data
, char *report_buf
, ULONG report_len
)
309 struct usage_value_params params
= {.usage
= usage
, .value_buf
= value
, .value_len
= sizeof(*value
), .report_buf
= report_buf
};
310 struct hid_preparsed_data
*preparsed
= (struct hid_preparsed_data
*)preparsed_data
;
311 struct caps_filter filter
= {.values
= TRUE
, .usage_page
= usage_page
, .collection
= collection
, .usage
= usage
};
314 TRACE( "report_type %d, usage_page %u, collection %u, usage %u, value %p, preparsed_data %p, report_buf %p, report_len %lu.\n",
315 report_type
, usage_page
, collection
, usage
, value
, preparsed_data
, report_buf
, report_len
);
317 if (!report_len
) return HIDP_STATUS_INVALID_REPORT_LENGTH
;
319 filter
.report_id
= report_buf
[0];
320 return enum_value_caps( preparsed
, report_type
, report_len
, &filter
, get_usage_value
, ¶ms
, &count
);
323 NTSTATUS WINAPI
HidP_GetUsageValueArray( HIDP_REPORT_TYPE report_type
, USAGE usage_page
, USHORT collection
,
324 USAGE usage
, char *value_buf
, USHORT value_len
,
325 PHIDP_PREPARSED_DATA preparsed_data
, char *report_buf
, ULONG report_len
)
327 struct usage_value_params params
= {.array
= TRUE
, .usage
= usage
, .value_buf
= value_buf
, .value_len
= value_len
, .report_buf
= report_buf
};
328 struct hid_preparsed_data
*preparsed
= (struct hid_preparsed_data
*)preparsed_data
;
329 struct caps_filter filter
= {.values
= TRUE
, .array
= TRUE
, .usage_page
= usage_page
, .collection
= collection
, .usage
= usage
};
332 TRACE( "report_type %d, usage_page %u, collection %u, usage %u, value_buf %p, value_len %u, "
333 "preparsed_data %p, report_buf %p, report_len %lu.\n",
334 report_type
, usage_page
, collection
, usage
, value_buf
, value_len
, preparsed_data
, report_buf
, report_len
);
336 if (!report_len
) return HIDP_STATUS_INVALID_REPORT_LENGTH
;
338 filter
.report_id
= report_buf
[0];
339 return enum_value_caps( preparsed
, report_type
, report_len
, &filter
, get_usage_value
, ¶ms
, &count
);
343 struct get_usage_params
350 static NTSTATUS
get_usage( const struct hid_value_caps
*caps
, void *user
)
352 const struct hid_value_caps
*end
= caps
;
353 ULONG index_min
, index_max
, bit
, last
;
354 struct get_usage_params
*params
= user
;
355 unsigned char *report_buf
;
358 report_buf
= (unsigned char *)params
->report_buf
+ caps
->start_byte
;
360 if (HID_VALUE_CAPS_IS_ARRAY( caps
))
362 while (end
->flags
& HID_VALUE_CAPS_ARRAY_HAS_MORE
) end
++;
363 index_min
= end
- caps
+ 1;
364 index_max
= index_min
+ caps
->usage_max
- caps
->usage_min
;
366 for (bit
= caps
->start_bit
, last
= bit
+ caps
->report_count
* caps
->bit_size
- 1; bit
<= last
; bit
+= 8)
368 if (!(index
= report_buf
[bit
/ 8]) || index
< index_min
|| index
> index_max
) continue;
369 if (params
->usages
< params
->usages_end
) *params
->usages
= caps
->usage_min
+ index
- index_min
;
372 return HIDP_STATUS_SUCCESS
;
375 for (bit
= caps
->start_bit
, last
= bit
+ caps
->usage_max
- caps
->usage_min
; bit
<= last
; ++bit
)
377 if (!(report_buf
[bit
/ 8] & (1 << (bit
% 8)))) continue;
378 if (params
->usages
< params
->usages_end
) *params
->usages
= caps
->usage_min
+ bit
- caps
->start_bit
;
382 return HIDP_STATUS_SUCCESS
;
385 NTSTATUS WINAPI
HidP_GetUsages( HIDP_REPORT_TYPE report_type
, USAGE usage_page
, USHORT collection
, USAGE
*usages
,
386 ULONG
*usages_len
, PHIDP_PREPARSED_DATA preparsed_data
, char *report_buf
, ULONG report_len
)
388 struct hid_preparsed_data
*preparsed
= (struct hid_preparsed_data
*)preparsed_data
;
389 struct get_usage_params params
= {.usages
= usages
, .usages_end
= usages
+ *usages_len
, .report_buf
= report_buf
};
390 struct caps_filter filter
= {.buttons
= TRUE
, .usage_page
= usage_page
, .collection
= collection
, .usage
= USAGE_ANY
};
394 TRACE( "report_type %d, usage_page %u, collection %u, usages %p, usages_len %p, preparsed_data %p, "
395 "report_buf %p, report_len %lu.\n",
396 report_type
, usage_page
, collection
, usages
, usages_len
, preparsed_data
, report_buf
, report_len
);
398 if (!report_len
) return HIDP_STATUS_INVALID_REPORT_LENGTH
;
400 filter
.report_id
= report_buf
[0];
401 status
= enum_value_caps( preparsed
, report_type
, report_len
, &filter
, get_usage
, ¶ms
, &limit
);
402 *usages_len
= params
.usages
- usages
;
403 if (status
!= HIDP_STATUS_SUCCESS
) return status
;
405 if (params
.usages
> params
.usages_end
) return HIDP_STATUS_BUFFER_TOO_SMALL
;
409 NTSTATUS WINAPI
HidP_GetValueCaps( HIDP_REPORT_TYPE report_type
, HIDP_VALUE_CAPS
*caps
, USHORT
*caps_count
,
410 PHIDP_PREPARSED_DATA preparsed_data
)
412 return HidP_GetSpecificValueCaps( report_type
, 0, 0, 0, caps
, caps_count
, preparsed_data
);
415 NTSTATUS WINAPI
HidP_InitializeReportForID( HIDP_REPORT_TYPE report_type
, UCHAR report_id
,
416 PHIDP_PREPARSED_DATA preparsed_data
, char *report_buf
, ULONG report_len
)
418 struct hid_preparsed_data
*preparsed
= (struct hid_preparsed_data
*)preparsed_data
;
419 const struct hid_value_caps
*caps
, *end
;
422 TRACE( "report_type %d, report_id %u, preparsed_data %p, report_buf %p, report_len %lu.\n", report_type
,
423 report_id
, preparsed_data
, report_buf
, report_len
);
425 if (!report_len
) return HIDP_STATUS_INVALID_REPORT_LENGTH
;
427 status
= get_value_caps_range( preparsed
, report_type
, report_len
, &caps
, &end
);
428 if (status
!= HIDP_STATUS_SUCCESS
) return status
;
430 while (caps
!= end
&& (caps
->report_id
!= report_id
|| (!caps
->usage_min
&& !caps
->usage_max
))) caps
++;
431 if (caps
== end
) return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
433 memset( report_buf
, 0, report_len
);
434 report_buf
[0] = report_id
;
435 return HIDP_STATUS_SUCCESS
;
438 static NTSTATUS
get_usage_list_length( const struct hid_value_caps
*caps
, void *data
)
440 *(ULONG
*)data
+= caps
->report_count
;
441 return HIDP_STATUS_SUCCESS
;
444 ULONG WINAPI
HidP_MaxUsageListLength( HIDP_REPORT_TYPE report_type
, USAGE usage_page
, PHIDP_PREPARSED_DATA preparsed_data
)
446 struct hid_preparsed_data
*preparsed
= (struct hid_preparsed_data
*)preparsed_data
;
447 struct caps_filter filter
= {.buttons
= TRUE
, .usage_page
= usage_page
| USAGE_ANY
, .usage
= USAGE_ANY
};
451 TRACE( "report_type %d, usage_page %u, preparsed_data %p.\n", report_type
, usage_page
, preparsed_data
);
453 enum_value_caps( preparsed
, report_type
, 0, &filter
, get_usage_list_length
, &count
, &limit
);
457 static NTSTATUS
set_usage_value( const struct hid_value_caps
*caps
, void *user
)
459 unsigned char *report_buf
, start_bit
= caps
->start_bit
;
460 ULONG bit_count
= caps
->bit_size
, bit_offset
= 0;
461 struct usage_value_params
*params
= user
;
463 if (params
->array
) bit_count
*= caps
->report_count
;
464 else bit_offset
= (params
->usage
- caps
->usage_min
) * caps
->bit_size
;
466 if ((bit_count
+ 7) / 8 > params
->value_len
) return HIDP_STATUS_BUFFER_TOO_SMALL
;
468 report_buf
= (unsigned char *)params
->report_buf
+ caps
->start_byte
+ bit_offset
/ 8;
469 copy_bits( report_buf
, params
->value_buf
, bit_count
, start_bit
+ bit_offset
% 8 );
471 return HIDP_STATUS_NULL
;
474 static NTSTATUS
set_scaled_usage_value( const struct hid_value_caps
*caps
, void *user
)
476 struct usage_value_params
*params
= user
;
477 LONG value
, log_range
, phy_range
;
479 if (caps
->logical_min
> caps
->logical_max
) return HIDP_STATUS_BAD_LOG_PHY_VALUES
;
480 if (caps
->physical_min
> caps
->physical_max
) return HIDP_STATUS_BAD_LOG_PHY_VALUES
;
482 if (sizeof(LONG
) > params
->value_len
) return HIDP_STATUS_BUFFER_TOO_SMALL
;
483 value
= *(LONG
*)params
->value_buf
;
485 if (caps
->physical_min
|| caps
->physical_max
)
487 /* testing shows that this is what the function does, including all
488 * the overflows and rounding errors... */
489 log_range
= (caps
->logical_max
- caps
->logical_min
+ 1) / 2;
490 phy_range
= (caps
->physical_max
- caps
->physical_min
+ 1) / 2;
491 value
= value
- caps
->physical_min
;
492 value
= (log_range
* value
) / phy_range
;
493 value
= caps
->logical_min
+ value
;
496 params
->value_buf
= &value
;
497 params
->value_len
= sizeof(value
);
498 return set_usage_value( caps
, params
);
501 NTSTATUS WINAPI
HidP_SetScaledUsageValue( HIDP_REPORT_TYPE report_type
, USAGE usage_page
, USHORT collection
,
502 USAGE usage
, LONG value
, PHIDP_PREPARSED_DATA preparsed_data
,
503 char *report_buf
, ULONG report_len
)
505 struct usage_value_params params
= {.usage
= usage
, .value_buf
= &value
, .value_len
= sizeof(value
), .report_buf
= report_buf
};
506 struct hid_preparsed_data
*preparsed
= (struct hid_preparsed_data
*)preparsed_data
;
507 struct caps_filter filter
= {.values
= TRUE
, .usage_page
= usage_page
, .collection
= collection
, .usage
= usage
};
510 TRACE( "report_type %d, usage_page %u, collection %u, usage %u, value %ld, preparsed_data %p, report_buf %p, report_len %lu.\n",
511 report_type
, usage_page
, collection
, usage
, value
, preparsed_data
, report_buf
, report_len
);
513 if (!report_len
) return HIDP_STATUS_INVALID_REPORT_LENGTH
;
515 filter
.report_id
= report_buf
[0];
516 return enum_value_caps( preparsed
, report_type
, report_len
, &filter
, set_scaled_usage_value
, ¶ms
, &count
);
519 NTSTATUS WINAPI
HidP_SetUsageValue( HIDP_REPORT_TYPE report_type
, USAGE usage_page
, USHORT collection
, USAGE usage
,
520 ULONG value
, PHIDP_PREPARSED_DATA preparsed_data
, char *report_buf
, ULONG report_len
)
522 struct usage_value_params params
= {.usage
= usage
, .value_buf
= &value
, .value_len
= sizeof(value
), .report_buf
= report_buf
};
523 struct hid_preparsed_data
*preparsed
= (struct hid_preparsed_data
*)preparsed_data
;
524 struct caps_filter filter
= {.values
= TRUE
, .usage_page
= usage_page
, .collection
= collection
, .usage
= usage
};
527 TRACE( "report_type %d, usage_page %u, collection %u, usage %u, value %lu, preparsed_data %p, report_buf %p, report_len %lu.\n",
528 report_type
, usage_page
, collection
, usage
, value
, preparsed_data
, report_buf
, report_len
);
530 if (!report_len
) return HIDP_STATUS_INVALID_REPORT_LENGTH
;
532 filter
.report_id
= report_buf
[0];
533 return enum_value_caps( preparsed
, report_type
, report_len
, &filter
, set_usage_value
, ¶ms
, &count
);
536 NTSTATUS WINAPI
HidP_SetUsageValueArray( HIDP_REPORT_TYPE report_type
, USAGE usage_page
, USHORT collection
,
537 USAGE usage
, char *value_buf
, USHORT value_len
,
538 PHIDP_PREPARSED_DATA preparsed_data
, char *report_buf
, ULONG report_len
)
540 struct usage_value_params params
= {.array
= TRUE
, .usage
= usage
, .value_buf
= value_buf
, .value_len
= value_len
, .report_buf
= report_buf
};
541 struct hid_preparsed_data
*preparsed
= (struct hid_preparsed_data
*)preparsed_data
;
542 struct caps_filter filter
= {.values
= TRUE
, .array
= TRUE
, .usage_page
= usage_page
, .collection
= collection
, .usage
= usage
};
545 TRACE( "report_type %d, usage_page %u, collection %u, usage %u, value_buf %p, value_len %u, "
546 "preparsed_data %p, report_buf %p, report_len %lu.\n",
547 report_type
, usage_page
, collection
, usage
, value_buf
, value_len
, preparsed_data
, report_buf
, report_len
);
549 if (!report_len
) return HIDP_STATUS_INVALID_REPORT_LENGTH
;
551 filter
.report_id
= report_buf
[0];
552 return enum_value_caps( preparsed
, report_type
, report_len
, &filter
, set_usage_value
, ¶ms
, &count
);
555 struct set_usage_params
561 static NTSTATUS
set_usage( const struct hid_value_caps
*caps
, void *user
)
563 const struct hid_value_caps
*end
= caps
;
564 struct set_usage_params
*params
= user
;
565 ULONG index_min
, bit
, last
;
566 unsigned char *report_buf
;
568 report_buf
= (unsigned char *)params
->report_buf
+ caps
->start_byte
;
570 if (HID_VALUE_CAPS_IS_ARRAY( caps
))
572 while (end
->flags
& HID_VALUE_CAPS_ARRAY_HAS_MORE
) end
++;
573 index_min
= end
- caps
+ 1;
575 for (bit
= caps
->start_bit
, last
= bit
+ caps
->report_count
* caps
->bit_size
- 1; bit
<= last
; bit
+= 8)
577 if (report_buf
[bit
/ 8]) continue;
578 report_buf
[bit
/ 8] = index_min
+ params
->usage
- caps
->usage_min
;
582 if (bit
> last
) return HIDP_STATUS_BUFFER_TOO_SMALL
;
583 return HIDP_STATUS_NULL
;
586 bit
= caps
->start_bit
+ params
->usage
- caps
->usage_min
;
587 report_buf
[bit
/ 8] |= (1 << (bit
% 8));
588 return HIDP_STATUS_NULL
;
591 NTSTATUS WINAPI
HidP_SetUsages( HIDP_REPORT_TYPE report_type
, USAGE usage_page
, USHORT collection
, USAGE
*usages
,
592 ULONG
*usage_count
, PHIDP_PREPARSED_DATA preparsed_data
, char *report_buf
, ULONG report_len
)
594 struct hid_preparsed_data
*preparsed
= (struct hid_preparsed_data
*)preparsed_data
;
595 struct set_usage_params params
= {.report_buf
= report_buf
};
596 struct caps_filter filter
= {.buttons
= TRUE
, .usage_page
= usage_page
, .collection
= collection
, .usage
= USAGE_ANY
};
599 ULONG i
, count
= *usage_count
;
601 TRACE( "report_type %d, usage_page %u, collection %u, usages %p, usage_count %p, preparsed_data %p, "
602 "report_buf %p, report_len %lu.\n",
603 report_type
, usage_page
, collection
, usages
, usage_count
, preparsed_data
, report_buf
, report_len
);
605 if (!report_len
) return HIDP_STATUS_INVALID_REPORT_LENGTH
;
607 filter
.report_id
= report_buf
[0];
608 for (i
= 0; i
< count
; ++i
)
610 params
.usage
= filter
.usage
= usages
[i
];
611 status
= enum_value_caps( preparsed
, report_type
, report_len
, &filter
, set_usage
, ¶ms
, &limit
);
612 if (status
!= HIDP_STATUS_SUCCESS
) return status
;
615 return HIDP_STATUS_SUCCESS
;
618 struct unset_usage_params
625 static NTSTATUS
unset_usage( const struct hid_value_caps
*caps
, void *user
)
627 ULONG index
, index_min
, index_max
, bit
, last
;
628 const struct hid_value_caps
*end
= caps
;
629 struct unset_usage_params
*params
= user
;
630 unsigned char *report_buf
;
632 report_buf
= (unsigned char *)params
->report_buf
+ caps
->start_byte
;
634 if (HID_VALUE_CAPS_IS_ARRAY( caps
))
636 while (end
->flags
& HID_VALUE_CAPS_ARRAY_HAS_MORE
) end
++;
637 index_min
= end
- caps
+ 1;
638 index_max
= index_min
+ caps
->usage_max
- caps
->usage_min
;
640 for (bit
= caps
->start_bit
, last
= bit
+ caps
->report_count
* caps
->bit_size
- 1; bit
<= last
; bit
+= 8)
642 if (!(index
= report_buf
[bit
/ 8]) || index
< index_min
|| index
> index_max
) continue;
643 report_buf
[bit
/ 8] = 0;
644 params
->found
= TRUE
;
648 return HIDP_STATUS_NULL
;
651 bit
= caps
->start_bit
+ params
->usage
- caps
->usage_min
;
652 if (report_buf
[bit
/ 8] & (1 << (bit
% 8))) params
->found
= TRUE
;
653 report_buf
[bit
/ 8] &= ~(1 << (bit
% 8));
654 return HIDP_STATUS_NULL
;
657 NTSTATUS WINAPI
HidP_UnsetUsages( HIDP_REPORT_TYPE report_type
, USAGE usage_page
, USHORT collection
, USAGE
*usages
,
658 ULONG
*usage_count
, PHIDP_PREPARSED_DATA preparsed_data
, char *report_buf
, ULONG report_len
)
660 struct hid_preparsed_data
*preparsed
= (struct hid_preparsed_data
*)preparsed_data
;
661 struct unset_usage_params params
= {.report_buf
= report_buf
, .found
= FALSE
};
662 struct caps_filter filter
= {.buttons
= TRUE
, .usage_page
= usage_page
, .collection
= collection
, .usage
= USAGE_ANY
};
665 ULONG i
, count
= *usage_count
;
667 TRACE( "report_type %d, usage_page %u, collection %u, usages %p, usage_count %p, preparsed_data %p, "
668 "report_buf %p, report_len %lu.\n",
669 report_type
, usage_page
, collection
, usages
, usage_count
, preparsed_data
, report_buf
, report_len
);
671 if (!report_len
) return HIDP_STATUS_INVALID_REPORT_LENGTH
;
673 filter
.report_id
= report_buf
[0];
674 for (i
= 0; i
< count
; ++i
)
676 params
.usage
= filter
.usage
= usages
[i
];
677 status
= enum_value_caps( preparsed
, report_type
, report_len
, &filter
, unset_usage
, ¶ms
, &limit
);
678 if (status
!= HIDP_STATUS_SUCCESS
) return status
;
681 if (!params
.found
) return HIDP_STATUS_BUTTON_NOT_PRESSED
;
682 return HIDP_STATUS_SUCCESS
;
685 NTSTATUS WINAPI
HidP_TranslateUsagesToI8042ScanCodes(USAGE
*ChangedUsageList
,
686 ULONG UsageListLength
, HIDP_KEYBOARD_DIRECTION KeyAction
,
687 HIDP_KEYBOARD_MODIFIER_STATE
*ModifierState
,
688 PHIDP_INSERT_SCANCODES InsertCodesProcedure
, VOID
*InsertCodesContext
)
690 FIXME( "ChangedUsageList %p, UsageListLength %lu, KeyAction %u, ModifierState %p, InsertCodesProcedure %p, InsertCodesContext %p stub!\n",
691 ChangedUsageList
, UsageListLength
, KeyAction
, ModifierState
, InsertCodesProcedure
, InsertCodesContext
);
693 return STATUS_NOT_IMPLEMENTED
;
696 static NTSTATUS
get_button_caps( const struct hid_value_caps
*caps
, void *user
)
698 HIDP_BUTTON_CAPS
**iter
= user
, *dst
= *iter
;
699 dst
->UsagePage
= caps
->usage_page
;
700 dst
->ReportID
= caps
->report_id
;
701 dst
->LinkCollection
= caps
->link_collection
;
702 dst
->LinkUsagePage
= caps
->link_usage_page
;
703 dst
->LinkUsage
= caps
->link_usage
;
704 dst
->BitField
= caps
->bit_field
;
705 dst
->IsAlias
= FALSE
;
706 dst
->IsAbsolute
= (caps
->flags
& HID_VALUE_CAPS_IS_ABSOLUTE
) ? 1 : 0;
707 dst
->IsRange
= (caps
->flags
& HID_VALUE_CAPS_IS_RANGE
) ? 1 : 0;
710 dst
->NotRange
.Usage
= caps
->usage_min
;
711 dst
->NotRange
.DataIndex
= caps
->data_index_min
;
715 dst
->Range
.UsageMin
= caps
->usage_min
;
716 dst
->Range
.UsageMax
= caps
->usage_max
;
717 dst
->Range
.DataIndexMin
= caps
->data_index_min
;
718 dst
->Range
.DataIndexMax
= caps
->data_index_max
;
720 dst
->IsStringRange
= (caps
->flags
& HID_VALUE_CAPS_IS_STRING_RANGE
) ? 1 : 0;
721 if (!dst
->IsStringRange
)
722 dst
->NotRange
.StringIndex
= caps
->string_min
;
725 dst
->Range
.StringMin
= caps
->string_min
;
726 dst
->Range
.StringMax
= caps
->string_max
;
728 dst
->IsDesignatorRange
= (caps
->flags
& HID_VALUE_CAPS_IS_DESIGNATOR_RANGE
) ? 1 : 0;
729 if (!dst
->IsDesignatorRange
)
730 dst
->NotRange
.DesignatorIndex
= caps
->designator_min
;
733 dst
->Range
.DesignatorMin
= caps
->designator_min
;
734 dst
->Range
.DesignatorMax
= caps
->designator_max
;
737 return HIDP_STATUS_SUCCESS
;
740 NTSTATUS WINAPI
HidP_GetSpecificButtonCaps( HIDP_REPORT_TYPE report_type
, USAGE usage_page
, USHORT collection
,
741 USAGE usage
, HIDP_BUTTON_CAPS
*caps
, USHORT
*caps_count
,
742 PHIDP_PREPARSED_DATA preparsed_data
)
744 struct hid_preparsed_data
*preparsed
= (struct hid_preparsed_data
*)preparsed_data
;
745 const struct caps_filter filter
= {.buttons
= TRUE
, .usage_page
= usage_page
| USAGE_ANY
, .collection
= collection
, .usage
= usage
| USAGE_ANY
};
747 TRACE( "report_type %d, usage_page %u, collection %u, usage %u, caps %p, caps_count %p, preparsed_data %p.\n",
748 report_type
, usage_page
, collection
, usage
, caps
, caps_count
, preparsed_data
);
750 return enum_value_caps( preparsed
, report_type
, 0, &filter
, get_button_caps
, &caps
, caps_count
);
753 static NTSTATUS
get_value_caps( const struct hid_value_caps
*caps
, void *user
)
755 HIDP_VALUE_CAPS
**iter
= user
, *dst
= *iter
;
756 dst
->UsagePage
= caps
->usage_page
;
757 dst
->ReportID
= caps
->report_id
;
758 dst
->LinkCollection
= caps
->link_collection
;
759 dst
->LinkUsagePage
= caps
->link_usage_page
;
760 dst
->LinkUsage
= caps
->link_usage
;
761 dst
->BitField
= caps
->bit_field
;
762 dst
->IsAlias
= FALSE
;
763 dst
->IsAbsolute
= (caps
->flags
& HID_VALUE_CAPS_IS_ABSOLUTE
) ? 1 : 0;
764 dst
->HasNull
= HID_VALUE_CAPS_HAS_NULL( caps
);
765 dst
->BitSize
= caps
->bit_size
;
766 dst
->UnitsExp
= caps
->units_exp
;
767 dst
->Units
= caps
->units
;
768 dst
->LogicalMin
= caps
->logical_min
;
769 dst
->LogicalMax
= caps
->logical_max
;
770 dst
->PhysicalMin
= caps
->physical_min
;
771 dst
->PhysicalMax
= caps
->physical_max
;
772 dst
->IsRange
= (caps
->flags
& HID_VALUE_CAPS_IS_RANGE
) ? 1 : 0;
775 dst
->ReportCount
= caps
->report_count
;
776 dst
->NotRange
.Usage
= caps
->usage_min
;
777 dst
->NotRange
.DataIndex
= caps
->data_index_min
;
781 dst
->ReportCount
= 1;
782 dst
->Range
.UsageMin
= caps
->usage_min
;
783 dst
->Range
.UsageMax
= caps
->usage_max
;
784 dst
->Range
.DataIndexMin
= caps
->data_index_min
;
785 dst
->Range
.DataIndexMax
= caps
->data_index_max
;
787 dst
->IsStringRange
= (caps
->flags
& HID_VALUE_CAPS_IS_STRING_RANGE
) ? 1 : 0;
788 if (!dst
->IsStringRange
)
789 dst
->NotRange
.StringIndex
= caps
->string_min
;
792 dst
->Range
.StringMin
= caps
->string_min
;
793 dst
->Range
.StringMax
= caps
->string_max
;
795 dst
->IsDesignatorRange
= (caps
->flags
& HID_VALUE_CAPS_IS_DESIGNATOR_RANGE
) ? 1 : 0;
796 if (!dst
->IsDesignatorRange
)
797 dst
->NotRange
.DesignatorIndex
= caps
->designator_min
;
800 dst
->Range
.DesignatorMin
= caps
->designator_min
;
801 dst
->Range
.DesignatorMax
= caps
->designator_max
;
804 return HIDP_STATUS_SUCCESS
;
807 NTSTATUS WINAPI
HidP_GetSpecificValueCaps( HIDP_REPORT_TYPE report_type
, USAGE usage_page
, USHORT collection
,
808 USAGE usage
, HIDP_VALUE_CAPS
*caps
, USHORT
*caps_count
,
809 PHIDP_PREPARSED_DATA preparsed_data
)
811 struct hid_preparsed_data
*preparsed
= (struct hid_preparsed_data
*)preparsed_data
;
812 const struct caps_filter filter
= {.values
= TRUE
, .usage_page
= usage_page
| USAGE_ANY
, .collection
= collection
, .usage
= usage
| USAGE_ANY
};
814 TRACE( "report_type %d, usage_page %u, collection %u, usage %u, caps %p, caps_count %p, preparsed_data %p.\n",
815 report_type
, usage_page
, collection
, usage
, caps
, caps_count
, preparsed_data
);
817 return enum_value_caps( preparsed
, report_type
, 0, &filter
, get_value_caps
, &caps
, caps_count
);
820 struct get_usage_and_page_params
822 USAGE_AND_PAGE
*usages
;
823 USAGE_AND_PAGE
*usages_end
;
827 static NTSTATUS
get_usage_and_page( const struct hid_value_caps
*caps
, void *user
)
829 struct get_usage_and_page_params
*params
= user
;
830 const struct hid_value_caps
*end
= caps
;
831 ULONG index_min
, index_max
, bit
, last
;
832 unsigned char *report_buf
;
835 report_buf
= (unsigned char *)params
->report_buf
+ caps
->start_byte
;
837 if (HID_VALUE_CAPS_IS_ARRAY( caps
))
839 while (end
->flags
& HID_VALUE_CAPS_ARRAY_HAS_MORE
) end
++;
840 index_min
= end
- caps
+ 1;
841 index_max
= index_min
+ caps
->usage_max
- caps
->usage_min
;
843 for (bit
= caps
->start_bit
, last
= bit
+ caps
->report_count
* caps
->bit_size
- 1; bit
<= last
; bit
+= 8)
845 if (!(index
= report_buf
[bit
/ 8]) || index
< index_min
|| index
> index_max
) continue;
846 if (params
->usages
< params
->usages_end
)
848 params
->usages
->UsagePage
= caps
->usage_page
;
849 params
->usages
->Usage
= caps
->usage_min
+ index
- index_min
;
853 return HIDP_STATUS_SUCCESS
;
856 for (bit
= caps
->start_bit
, last
= bit
+ caps
->usage_max
- caps
->usage_min
; bit
<= last
; bit
++)
858 if (!(report_buf
[bit
/ 8] & (1 << (bit
% 8)))) continue;
859 if (params
->usages
< params
->usages_end
)
861 params
->usages
->UsagePage
= caps
->usage_page
;
862 params
->usages
->Usage
= caps
->usage_min
+ bit
- caps
->start_bit
;
867 return HIDP_STATUS_SUCCESS
;
870 NTSTATUS WINAPI
HidP_GetUsagesEx( HIDP_REPORT_TYPE report_type
, USHORT collection
, USAGE_AND_PAGE
*usages
,
871 ULONG
*usages_len
, PHIDP_PREPARSED_DATA preparsed_data
, char *report_buf
, ULONG report_len
)
873 struct get_usage_and_page_params params
= {.usages
= usages
, .usages_end
= usages
+ *usages_len
, .report_buf
= report_buf
};
874 struct hid_preparsed_data
*preparsed
= (struct hid_preparsed_data
*)preparsed_data
;
875 struct caps_filter filter
= {.buttons
= TRUE
, .usage_page
= USAGE_ANY
, .collection
= collection
, .usage
= USAGE_ANY
};
879 TRACE( "report_type %d, collection %u, usages %p, usages_len %p, preparsed_data %p, report_buf %p, report_len %lu.\n",
880 report_type
, collection
, usages
, usages_len
, preparsed_data
, report_buf
, report_len
);
882 if (!report_len
) return HIDP_STATUS_INVALID_REPORT_LENGTH
;
884 filter
.report_id
= report_buf
[0];
885 status
= enum_value_caps( preparsed
, report_type
, report_len
, &filter
, get_usage_and_page
, ¶ms
, &limit
);
886 *usages_len
= params
.usages
- usages
;
887 if (status
!= HIDP_STATUS_SUCCESS
) return status
;
889 if (params
.usages
> params
.usages_end
) return HIDP_STATUS_BUFFER_TOO_SMALL
;
893 static NTSTATUS
count_data( const struct hid_value_caps
*caps
, void *user
)
895 BOOL is_button
= caps
->flags
& HID_VALUE_CAPS_IS_BUTTON
;
896 BOOL is_range
= caps
->flags
& HID_VALUE_CAPS_IS_RANGE
;
897 if (is_range
|| is_button
) *(ULONG
*)user
+= caps
->report_count
;
898 else *(ULONG
*)user
+= 1;
899 return HIDP_STATUS_SUCCESS
;
902 ULONG WINAPI
HidP_MaxDataListLength( HIDP_REPORT_TYPE report_type
, PHIDP_PREPARSED_DATA preparsed_data
)
904 struct hid_preparsed_data
*preparsed
= (struct hid_preparsed_data
*)preparsed_data
;
905 struct caps_filter filter
= {.usage_page
= USAGE_ANY
, .usage
= USAGE_ANY
};
909 TRACE( "report_type %d, preparsed_data %p.\n", report_type
, preparsed_data
);
911 enum_value_caps( preparsed
, report_type
, 0, &filter
, count_data
, &count
, &limit
);
915 struct find_all_data_params
922 static NTSTATUS
find_all_data( const struct hid_value_caps
*caps
, void *user
)
924 struct find_all_data_params
*params
= user
;
925 HIDP_DATA
*data
= params
->data
, *data_end
= params
->data_end
;
926 ULONG index_min
, index_max
, bit
, last
, bit_count
;
927 const struct hid_value_caps
*end
= caps
;
928 unsigned char *report_buf
;
931 if (!caps
->bit_size
) return HIDP_STATUS_SUCCESS
;
933 report_buf
= (unsigned char *)params
->report_buf
+ caps
->start_byte
;
935 if (HID_VALUE_CAPS_IS_ARRAY( caps
))
937 while (end
->flags
& HID_VALUE_CAPS_ARRAY_HAS_MORE
) end
++;
938 index_min
= end
- caps
+ 1;
939 index_max
= index_min
+ caps
->usage_max
- caps
->usage_min
;
941 for (bit
= caps
->start_bit
, last
= bit
+ caps
->report_count
* caps
->bit_size
- 1; bit
<= last
; bit
+= 8)
943 if (!(index
= report_buf
[bit
/ 8]) || index
< index_min
|| index
> index_max
) continue;
946 data
->DataIndex
= caps
->data_index_min
+ index
- index_min
;
952 else if (caps
->flags
& HID_VALUE_CAPS_IS_BUTTON
)
954 for (bit
= caps
->start_bit
, last
= bit
+ caps
->usage_max
- caps
->usage_min
; bit
<= last
; bit
++)
956 if (!(report_buf
[bit
/ 8] & (1 << (bit
% 8)))) continue;
959 data
->DataIndex
= caps
->data_index_min
+ bit
- caps
->start_bit
;
965 else if (caps
->report_count
== 1)
969 data
->DataIndex
= caps
->data_index_min
;
971 bit_count
= caps
->bit_size
* caps
->report_count
;
972 if ((bit_count
+ 7) / 8 > sizeof(data
->RawValue
)) return HIDP_STATUS_BUFFER_TOO_SMALL
;
973 copy_bits( (void *)&data
->RawValue
, report_buf
, bit_count
, -caps
->start_bit
);
979 return HIDP_STATUS_SUCCESS
;
982 NTSTATUS WINAPI
HidP_GetData( HIDP_REPORT_TYPE report_type
, HIDP_DATA
*data
, ULONG
*data_len
,
983 PHIDP_PREPARSED_DATA preparsed_data
, char *report_buf
, ULONG report_len
)
985 struct find_all_data_params params
= {.data
= data
, .data_end
= data
+ *data_len
, .report_buf
= report_buf
};
986 struct hid_preparsed_data
*preparsed
= (struct hid_preparsed_data
*)preparsed_data
;
987 struct caps_filter filter
= {.usage_page
= USAGE_ANY
, .usage
= USAGE_ANY
};
991 TRACE( "report_type %d, data %p, data_len %p, preparsed_data %p, report_buf %p, report_len %lu.\n",
992 report_type
, data
, data_len
, preparsed_data
, report_buf
, report_len
);
994 if (!report_len
) return HIDP_STATUS_INVALID_REPORT_LENGTH
;
996 filter
.report_id
= report_buf
[0];
997 status
= enum_value_caps( preparsed
, report_type
, report_len
, &filter
, find_all_data
, ¶ms
, &limit
);
998 *data_len
= params
.data
- data
;
999 if (status
!= HIDP_STATUS_SUCCESS
) return status
;
1001 if (params
.data
> params
.data_end
) return HIDP_STATUS_BUFFER_TOO_SMALL
;
1002 return HIDP_STATUS_SUCCESS
;
1005 NTSTATUS WINAPI
HidP_GetLinkCollectionNodes( HIDP_LINK_COLLECTION_NODE
*nodes
, ULONG
*nodes_len
, PHIDP_PREPARSED_DATA preparsed_data
)
1007 struct hid_preparsed_data
*preparsed
= (struct hid_preparsed_data
*)preparsed_data
;
1008 struct hid_collection_node
*collections
= HID_COLLECTION_NODES( preparsed
);
1009 ULONG i
, count
, capacity
= *nodes_len
;
1011 TRACE( "nodes %p, nodes_len %p, preparsed_data %p.\n", nodes
, nodes_len
, preparsed_data
);
1013 if (!preparsed
|| memcmp( preparsed
->magic
, "HidP KDR", 8 )) return HIDP_STATUS_INVALID_PREPARSED_DATA
;
1015 count
= *nodes_len
= preparsed
->number_link_collection_nodes
;
1016 if (capacity
< count
) return HIDP_STATUS_BUFFER_TOO_SMALL
;
1018 for (i
= 0; i
< count
; ++i
)
1020 nodes
[i
].LinkUsagePage
= collections
[i
].usage_page
;
1021 nodes
[i
].LinkUsage
= collections
[i
].usage
;
1022 nodes
[i
].Parent
= collections
[i
].parent
;
1023 nodes
[i
].CollectionType
= collections
[i
].collection_type
;
1024 nodes
[i
].FirstChild
= collections
[i
].first_child
;
1025 nodes
[i
].NextSibling
= collections
[i
].next_sibling
;
1026 nodes
[i
].NumberOfChildren
= collections
[i
].number_of_children
;
1027 nodes
[i
].IsAlias
= 0;
1030 return HIDP_STATUS_SUCCESS
;