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(hidp
);
39 static NTSTATUS
get_value_caps_range( WINE_HIDP_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
->magic
!= HID_MAGIC
) return HIDP_STATUS_INVALID_PREPARSED_DATA
;
47 if (report_len
&& report_len
!= preparsed
->caps
.InputReportByteLength
)
48 return HIDP_STATUS_INVALID_REPORT_LENGTH
;
49 *caps
= HID_INPUT_VALUE_CAPS( preparsed
);
52 if (report_len
&& report_len
!= preparsed
->caps
.OutputReportByteLength
)
53 return HIDP_STATUS_INVALID_REPORT_LENGTH
;
54 *caps
= HID_OUTPUT_VALUE_CAPS( preparsed
);
57 if (report_len
&& report_len
!= preparsed
->caps
.FeatureReportByteLength
)
58 return HIDP_STATUS_INVALID_REPORT_LENGTH
;
59 *caps
= HID_FEATURE_VALUE_CAPS( preparsed
);
62 return HIDP_STATUS_INVALID_REPORT_TYPE
;
65 *caps_end
= *caps
+ preparsed
->value_caps_count
[report_type
];
66 return HIDP_STATUS_SUCCESS
;
78 static BOOL
match_value_caps( const struct hid_value_caps
*caps
, const struct caps_filter
*filter
)
80 if (!caps
->usage_min
&& !caps
->usage_max
) return FALSE
;
81 if (filter
->buttons
&& !HID_VALUE_CAPS_IS_BUTTON( caps
)) return FALSE
;
82 if (filter
->values
&& HID_VALUE_CAPS_IS_BUTTON( caps
)) return FALSE
;
83 if (filter
->usage_page
&& filter
->usage_page
!= caps
->usage_page
) return FALSE
;
84 if (filter
->collection
&& filter
->collection
!= caps
->link_collection
) return FALSE
;
85 if (!filter
->usage
) return TRUE
;
86 return caps
->usage_min
<= filter
->usage
&& caps
->usage_max
>= filter
->usage
;
89 typedef NTSTATUS (*enum_value_caps_callback
)( const struct hid_value_caps
*caps
, void *user
);
91 static NTSTATUS
enum_value_caps( WINE_HIDP_PREPARSED_DATA
*preparsed
, HIDP_REPORT_TYPE report_type
,
92 const struct caps_filter
*filter
, enum_value_caps_callback callback
,
93 void *user
, USHORT
*count
)
95 const struct hid_value_caps
*caps
, *caps_end
;
97 LONG remaining
= *count
;
99 for (status
= get_value_caps_range( preparsed
, report_type
, 0, &caps
, &caps_end
);
100 status
== HIDP_STATUS_SUCCESS
&& caps
!= caps_end
; caps
++)
102 if (!match_value_caps( caps
, filter
)) continue;
103 if (remaining
-- > 0) status
= callback( caps
, user
);
106 if (status
!= HIDP_STATUS_SUCCESS
) return status
;
109 if (*count
== 0) return HIDP_STATUS_USAGE_NOT_FOUND
;
110 if (remaining
< 0) return HIDP_STATUS_BUFFER_TOO_SMALL
;
111 return HIDP_STATUS_SUCCESS
;
114 static NTSTATUS
get_report_data(BYTE
*report
, INT reportLength
, INT startBit
, INT valueSize
, PULONG value
)
117 if ((startBit
+ valueSize
) / 8 > reportLength
)
118 return HIDP_STATUS_INVALID_REPORT_LENGTH
;
122 ULONG byte_index
= startBit
/ 8;
123 ULONG bit_index
= startBit
- (byte_index
* 8);
124 INT mask
= (1 << bit_index
);
125 *value
= !!(report
[byte_index
] & mask
);
129 ULONG remaining_bits
= valueSize
;
130 ULONG byte_index
= startBit
/ 8;
131 ULONG bit_index
= startBit
% 8;
134 while (remaining_bits
)
136 ULONG copy_bits
= 8 - bit_index
;
137 if (remaining_bits
< copy_bits
)
138 copy_bits
= remaining_bits
;
140 data
|= ((report
[byte_index
] >> bit_index
) & ((1 << copy_bits
) - 1)) << shift
;
145 remaining_bits
-= copy_bits
;
149 return HIDP_STATUS_SUCCESS
;
152 static NTSTATUS
set_report_data(BYTE
*report
, INT reportLength
, INT startBit
, INT valueSize
, ULONG value
)
154 if ((startBit
+ valueSize
) / 8 > reportLength
)
155 return HIDP_STATUS_INVALID_REPORT_LENGTH
;
159 ULONG byte_index
= startBit
/ 8;
160 ULONG bit_index
= startBit
- (byte_index
* 8);
162 report
[byte_index
] |= (1 << bit_index
);
164 report
[byte_index
] &= ~(1 << bit_index
);
168 ULONG byte_index
= (startBit
+ valueSize
- 1) / 8;
170 ULONG remainingBits
= valueSize
;
171 while (remainingBits
)
173 BYTE subvalue
= data
& 0xff;
177 if (remainingBits
>= 8)
179 report
[byte_index
] = subvalue
;
183 else if (remainingBits
> 0)
185 BYTE mask
= (0xff << (8-remainingBits
)) & subvalue
;
186 report
[byte_index
] |= mask
;
191 return HIDP_STATUS_SUCCESS
;
194 static NTSTATUS
get_report_data_array(BYTE
*report
, UINT reportLength
, UINT startBit
, UINT elemSize
,
195 UINT numElements
, PCHAR values
, UINT valuesSize
)
197 BYTE byte
, *end
, *p
= report
+ startBit
/ 8;
198 ULONG size
= elemSize
* numElements
;
199 ULONG m
, bit_index
= startBit
% 8;
200 BYTE
*data
= (BYTE
*)values
;
202 if ((startBit
+ size
) / 8 > reportLength
)
203 return HIDP_STATUS_INVALID_REPORT_LENGTH
;
205 if (valuesSize
< (size
+ 7) / 8)
206 return HIDP_STATUS_BUFFER_TOO_SMALL
;
208 end
= report
+ (startBit
+ size
+ 7) / 8;
214 *(++data
) = byte
>> bit_index
;
216 *data
|= byte
<< (8 - bit_index
);
219 /* Handle the end and mask out bits beyond */
220 m
= (startBit
+ size
) % 8;
224 *(++data
) = (byte
>> bit_index
) & ((1 << (m
- bit_index
)) - 1);
226 *data
&= (1 << (m
+ 8 - bit_index
)) - 1;
228 if (++data
< (BYTE
*)values
+ valuesSize
)
229 memset(data
, 0, (BYTE
*)values
+ valuesSize
- data
);
231 return HIDP_STATUS_SUCCESS
;
234 NTSTATUS WINAPI
HidP_GetButtonCaps( HIDP_REPORT_TYPE report_type
, HIDP_BUTTON_CAPS
*caps
, USHORT
*caps_count
,
235 PHIDP_PREPARSED_DATA preparsed_data
)
237 return HidP_GetSpecificButtonCaps( report_type
, 0, 0, 0, caps
, caps_count
, preparsed_data
);
240 NTSTATUS WINAPI
HidP_GetCaps( PHIDP_PREPARSED_DATA preparsed_data
, HIDP_CAPS
*caps
)
242 WINE_HIDP_PREPARSED_DATA
*preparsed
= (WINE_HIDP_PREPARSED_DATA
*)preparsed_data
;
244 TRACE( "preparsed_data %p, caps %p.\n", preparsed_data
, caps
);
246 if (preparsed
->magic
!= HID_MAGIC
) return HIDP_STATUS_INVALID_PREPARSED_DATA
;
248 *caps
= preparsed
->caps
;
249 caps
->NumberInputButtonCaps
= preparsed
->new_caps
.NumberInputButtonCaps
;
250 caps
->NumberOutputButtonCaps
= preparsed
->new_caps
.NumberOutputButtonCaps
;
251 caps
->NumberFeatureButtonCaps
= preparsed
->new_caps
.NumberFeatureButtonCaps
;
252 caps
->NumberInputValueCaps
= preparsed
->new_caps
.NumberInputValueCaps
;
253 caps
->NumberOutputValueCaps
= preparsed
->new_caps
.NumberOutputValueCaps
;
254 caps
->NumberFeatureValueCaps
= preparsed
->new_caps
.NumberFeatureValueCaps
;
256 return HIDP_STATUS_SUCCESS
;
259 static NTSTATUS
find_usage(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
260 USAGE Usage
, PHIDP_PREPARSED_DATA PreparsedData
, PCHAR Report
,
261 USHORT bit_size
, WINE_HID_ELEMENT
*element
)
263 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
264 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
265 WINE_HID_REPORT
*report
= NULL
;
266 USHORT v_count
= 0, r_count
= 0;
269 TRACE("(%i, %x, %i, %i, %p, %p)\n", ReportType
, UsagePage
, LinkCollection
, Usage
,
270 PreparsedData
, Report
);
272 if (data
->magic
!= HID_MAGIC
)
273 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
277 v_count
= data
->caps
.NumberInputValueCaps
;
280 v_count
= data
->caps
.NumberOutputValueCaps
;
283 v_count
= data
->caps
.NumberFeatureValueCaps
;
286 return HIDP_STATUS_INVALID_REPORT_TYPE
;
288 r_count
= data
->reportCount
[ReportType
];
289 report
= &data
->reports
[data
->reportIdx
[ReportType
][(BYTE
)Report
[0]]];
291 if (!r_count
|| !v_count
)
292 return HIDP_STATUS_USAGE_NOT_FOUND
;
294 if (report
->reportID
&& report
->reportID
!= Report
[0])
295 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
297 for (i
= 0; i
< report
->elementCount
; i
++)
299 HIDP_VALUE_CAPS
*value
= &elems
[report
->elementIdx
+ i
].caps
;
301 if ((elems
[report
->elementIdx
+ i
].caps
.BitSize
== 1) != (bit_size
== 1) ||
302 value
->UsagePage
!= UsagePage
)
305 if (value
->IsRange
&& value
->Range
.UsageMin
<= Usage
&& Usage
<= value
->Range
.UsageMax
)
307 *element
= elems
[report
->elementIdx
+ i
];
308 element
->valueStartBit
+= value
->BitSize
* (Usage
- value
->Range
.UsageMin
);
309 element
->bitCount
= elems
[report
->elementIdx
+ i
].caps
.BitSize
;
310 return HIDP_STATUS_SUCCESS
;
312 else if (value
->NotRange
.Usage
== Usage
)
314 *element
= elems
[report
->elementIdx
+ i
];
315 element
->bitCount
= elems
[report
->elementIdx
+ i
].caps
.BitSize
;
316 return HIDP_STATUS_SUCCESS
;
320 return HIDP_STATUS_USAGE_NOT_FOUND
;
323 static LONG
sign_extend(ULONG value
, const WINE_HID_ELEMENT
*element
)
325 UINT bit_count
= element
->bitCount
;
327 if ((value
& (1 << (bit_count
- 1)))
328 && element
->caps
.BitSize
!= 1
329 && element
->caps
.LogicalMin
< 0)
331 value
-= (1 << bit_count
);
336 static LONG
logical_to_physical(LONG value
, const WINE_HID_ELEMENT
*element
)
338 if (element
->caps
.PhysicalMin
|| element
->caps
.PhysicalMax
)
340 value
= (((ULONGLONG
)(value
- element
->caps
.LogicalMin
)
341 * (element
->caps
.PhysicalMax
- element
->caps
.PhysicalMin
))
342 / (element
->caps
.LogicalMax
- element
->caps
.LogicalMin
))
343 + element
->caps
.PhysicalMin
;
348 NTSTATUS WINAPI
HidP_GetScaledUsageValue(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
,
349 USHORT LinkCollection
, USAGE Usage
, PLONG UsageValue
,
350 PHIDP_PREPARSED_DATA PreparsedData
, PCHAR Report
, ULONG ReportLength
)
353 WINE_HID_ELEMENT element
;
354 TRACE("(%i, %x, %i, %i, %p, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, Usage
, UsageValue
,
355 PreparsedData
, Report
, ReportLength
);
357 rc
= find_usage(ReportType
, UsagePage
, LinkCollection
, Usage
, PreparsedData
, Report
, 0, &element
);
359 if (rc
== HIDP_STATUS_SUCCESS
)
362 rc
= get_report_data((BYTE
*)Report
, ReportLength
,
363 element
.valueStartBit
, element
.bitCount
, &rawValue
);
364 if (rc
!= HIDP_STATUS_SUCCESS
)
366 *UsageValue
= logical_to_physical(sign_extend(rawValue
, &element
), &element
);
373 NTSTATUS WINAPI
HidP_GetUsageValue(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
374 USAGE Usage
, PULONG UsageValue
, PHIDP_PREPARSED_DATA PreparsedData
,
375 PCHAR Report
, ULONG ReportLength
)
377 WINE_HID_ELEMENT element
;
380 TRACE("(%i, %x, %i, %i, %p, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, Usage
, UsageValue
,
381 PreparsedData
, Report
, ReportLength
);
383 rc
= find_usage(ReportType
, UsagePage
, LinkCollection
, Usage
, PreparsedData
, Report
, 0, &element
);
385 if (rc
== HIDP_STATUS_SUCCESS
)
387 return get_report_data((BYTE
*)Report
, ReportLength
,
388 element
.valueStartBit
, element
.bitCount
, UsageValue
);
395 NTSTATUS WINAPI
HidP_GetUsageValueArray(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
396 USAGE Usage
, PCHAR UsageValue
, USHORT UsageValueByteLength
,
397 PHIDP_PREPARSED_DATA PreparsedData
, PCHAR Report
, ULONG ReportLength
)
399 WINE_HID_ELEMENT element
;
402 TRACE("(%i, %x, %i, %i, %p, %u, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, Usage
, UsageValue
,
403 UsageValueByteLength
, PreparsedData
, Report
, ReportLength
);
405 rc
= find_usage(ReportType
, UsagePage
, LinkCollection
, Usage
, PreparsedData
, Report
, 0, &element
);
407 if (rc
== HIDP_STATUS_SUCCESS
)
409 if (element
.caps
.IsRange
|| element
.caps
.ReportCount
<= 1 || !element
.bitCount
)
410 return HIDP_STATUS_NOT_VALUE_ARRAY
;
412 return get_report_data_array((BYTE
*)Report
, ReportLength
, element
.valueStartBit
, element
.bitCount
,
413 element
.caps
.ReportCount
, UsageValue
, UsageValueByteLength
);
420 NTSTATUS WINAPI
HidP_GetUsages(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
421 PUSAGE UsageList
, PULONG UsageLength
, PHIDP_PREPARSED_DATA PreparsedData
,
422 PCHAR Report
, ULONG ReportLength
)
424 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
425 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
426 WINE_HID_REPORT
*report
= NULL
;
428 USHORT b_count
= 0, r_count
= 0;
431 TRACE("(%i, %x, %i, %p, %p, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, UsageList
,
432 UsageLength
, PreparsedData
, Report
, ReportLength
);
434 if (data
->magic
!= HID_MAGIC
)
437 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
443 b_count
= data
->caps
.NumberInputButtonCaps
;
446 b_count
= data
->caps
.NumberOutputButtonCaps
;
449 b_count
= data
->caps
.NumberFeatureButtonCaps
;
452 return HIDP_STATUS_INVALID_REPORT_TYPE
;
454 r_count
= data
->reportCount
[ReportType
];
455 report
= &data
->reports
[data
->reportIdx
[ReportType
][(BYTE
)Report
[0]]];
457 if (!r_count
|| !b_count
)
458 return HIDP_STATUS_USAGE_NOT_FOUND
;
460 if (report
->reportID
&& report
->reportID
!= Report
[0])
461 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
464 for (i
= 0; i
< report
->elementCount
&& uCount
< *UsageLength
; i
++)
466 if (elems
[report
->elementIdx
+ i
].caps
.BitSize
== 1 &&
467 elems
[report
->elementIdx
+ i
].caps
.UsagePage
== UsagePage
)
470 WINE_HID_ELEMENT
*element
= &elems
[report
->elementIdx
+ i
];
471 for (k
=0; k
< element
->bitCount
; k
++)
474 NTSTATUS rc
= get_report_data((BYTE
*)Report
, ReportLength
,
475 element
->valueStartBit
+ k
, 1, &v
);
476 if (rc
!= HIDP_STATUS_SUCCESS
)
481 if (uCount
== *UsageLength
)
482 return HIDP_STATUS_BUFFER_TOO_SMALL
;
483 UsageList
[uCount
] = element
->caps
.Range
.UsageMin
+ k
;
490 *UsageLength
= uCount
;
493 return HIDP_STATUS_USAGE_NOT_FOUND
;
495 return HIDP_STATUS_SUCCESS
;
498 NTSTATUS WINAPI
HidP_GetValueCaps( HIDP_REPORT_TYPE report_type
, HIDP_VALUE_CAPS
*caps
, USHORT
*caps_count
,
499 PHIDP_PREPARSED_DATA preparsed_data
)
501 return HidP_GetSpecificValueCaps( report_type
, 0, 0, 0, caps
, caps_count
, preparsed_data
);
504 NTSTATUS WINAPI
HidP_InitializeReportForID( HIDP_REPORT_TYPE report_type
, UCHAR report_id
,
505 PHIDP_PREPARSED_DATA preparsed_data
, char *report_buf
, ULONG report_len
)
507 WINE_HIDP_PREPARSED_DATA
*preparsed
= (WINE_HIDP_PREPARSED_DATA
*)preparsed_data
;
508 const struct hid_value_caps
*caps
, *end
;
511 TRACE( "report_type %d, report_id %x, preparsed_data %p, report_buf %p, report_len %u.\n", report_type
,
512 report_id
, preparsed_data
, report_buf
, report_len
);
514 if (!report_len
) return HIDP_STATUS_INVALID_REPORT_LENGTH
;
516 status
= get_value_caps_range( preparsed
, report_type
, report_len
, &caps
, &end
);
517 if (status
!= HIDP_STATUS_SUCCESS
) return status
;
519 while (caps
!= end
&& (caps
->report_id
!= report_id
|| (!caps
->usage_min
&& !caps
->usage_max
))) caps
++;
520 if (caps
== end
) return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
522 memset( report_buf
, 0, report_len
);
523 report_buf
[0] = report_id
;
524 return HIDP_STATUS_SUCCESS
;
527 static NTSTATUS
get_usage_list_length( const struct hid_value_caps
*caps
, void *data
)
529 *(ULONG
*)data
+= caps
->report_count
;
530 return HIDP_STATUS_SUCCESS
;
533 ULONG WINAPI
HidP_MaxUsageListLength( HIDP_REPORT_TYPE report_type
, USAGE usage_page
, PHIDP_PREPARSED_DATA preparsed_data
)
535 WINE_HIDP_PREPARSED_DATA
*preparsed
= (WINE_HIDP_PREPARSED_DATA
*)preparsed_data
;
536 struct caps_filter filter
= {.buttons
= TRUE
, .usage_page
= usage_page
};
540 TRACE( "report_type %d, usage_page %x, preparsed_data %p.\n", report_type
, usage_page
, preparsed_data
);
542 enum_value_caps( preparsed
, report_type
, &filter
, get_usage_list_length
, &count
, &limit
);
546 NTSTATUS WINAPI
HidP_SetUsageValue(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
547 USAGE Usage
, ULONG UsageValue
, PHIDP_PREPARSED_DATA PreparsedData
,
548 CHAR
*Report
, ULONG ReportLength
)
550 WINE_HID_ELEMENT element
;
553 TRACE("(%i, %x, %i, %i, %i, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, Usage
, UsageValue
,
554 PreparsedData
, Report
, ReportLength
);
556 rc
= find_usage(ReportType
, UsagePage
, LinkCollection
, Usage
, PreparsedData
, Report
, 0, &element
);
558 if (rc
== HIDP_STATUS_SUCCESS
)
560 return set_report_data((BYTE
*)Report
, ReportLength
,
561 element
.valueStartBit
, element
.bitCount
, UsageValue
);
567 NTSTATUS WINAPI
HidP_SetUsageValueArray( HIDP_REPORT_TYPE report_type
, USAGE usage_page
, USHORT collection
,
568 USAGE usage
, char *value_buf
, USHORT value_len
,
569 PHIDP_PREPARSED_DATA preparsed_data
, char *report_buf
, ULONG report_len
)
571 FIXME( "report_type %d, usage_page %x, collection %d, usage %x, value_buf %p, value_len %u, "
572 "preparsed_data %p, report_buf %p, report_len %u stub!\n",
573 report_type
, usage_page
, collection
, usage
, value_buf
, value_len
, preparsed_data
, report_buf
, report_len
);
575 return HIDP_STATUS_NOT_IMPLEMENTED
;
578 NTSTATUS WINAPI
HidP_SetUsages(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
579 PUSAGE UsageList
, PULONG UsageLength
, PHIDP_PREPARSED_DATA PreparsedData
,
580 PCHAR Report
, ULONG ReportLength
)
582 WINE_HID_ELEMENT element
;
586 TRACE("(%i, %x, %i, %p, %p, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, UsageList
,
587 UsageLength
, PreparsedData
, Report
, ReportLength
);
589 for (i
= 0; i
< *UsageLength
; i
++)
591 rc
= find_usage(ReportType
, UsagePage
, LinkCollection
,
592 UsageList
[i
], PreparsedData
, Report
, 1, &element
);
593 if (rc
== HIDP_STATUS_SUCCESS
)
595 rc
= set_report_data((BYTE
*)Report
, ReportLength
,
596 element
.valueStartBit
, element
.bitCount
, -1);
599 if (rc
!= HIDP_STATUS_SUCCESS
)
606 return HIDP_STATUS_SUCCESS
;
610 NTSTATUS WINAPI
HidP_TranslateUsagesToI8042ScanCodes(USAGE
*ChangedUsageList
,
611 ULONG UsageListLength
, HIDP_KEYBOARD_DIRECTION KeyAction
,
612 HIDP_KEYBOARD_MODIFIER_STATE
*ModifierState
,
613 PHIDP_INSERT_SCANCODES InsertCodesProcedure
, VOID
*InsertCodesContext
)
615 FIXME("stub: %p, %i, %i, %p, %p, %p\n", ChangedUsageList
, UsageListLength
,
616 KeyAction
, ModifierState
, InsertCodesProcedure
, InsertCodesContext
);
618 return STATUS_NOT_IMPLEMENTED
;
621 static NTSTATUS
get_button_caps( const struct hid_value_caps
*caps
, void *user
)
623 HIDP_BUTTON_CAPS
**iter
= user
, *dst
= *iter
;
624 dst
->UsagePage
= caps
->usage_page
;
625 dst
->ReportID
= caps
->report_id
;
626 dst
->LinkCollection
= caps
->link_collection
;
627 dst
->LinkUsagePage
= caps
->link_usage_page
;
628 dst
->LinkUsage
= caps
->link_usage
;
629 dst
->BitField
= caps
->bit_field
;
630 dst
->IsAlias
= FALSE
;
631 dst
->IsAbsolute
= HID_VALUE_CAPS_IS_ABSOLUTE( caps
);
632 if (!(dst
->IsRange
= caps
->is_range
))
634 dst
->NotRange
.Usage
= caps
->usage_min
;
635 dst
->NotRange
.DataIndex
= caps
->data_index_min
;
639 dst
->Range
.UsageMin
= caps
->usage_min
;
640 dst
->Range
.UsageMax
= caps
->usage_max
;
641 dst
->Range
.DataIndexMin
= caps
->data_index_min
;
642 dst
->Range
.DataIndexMax
= caps
->data_index_max
;
644 if (!(dst
->IsStringRange
= caps
->is_string_range
))
645 dst
->NotRange
.StringIndex
= caps
->string_min
;
648 dst
->Range
.StringMin
= caps
->string_min
;
649 dst
->Range
.StringMax
= caps
->string_max
;
651 if ((dst
->IsDesignatorRange
= caps
->is_designator_range
))
652 dst
->NotRange
.DesignatorIndex
= caps
->designator_min
;
655 dst
->Range
.DesignatorMin
= caps
->designator_min
;
656 dst
->Range
.DesignatorMax
= caps
->designator_max
;
659 return HIDP_STATUS_SUCCESS
;
662 NTSTATUS WINAPI
HidP_GetSpecificButtonCaps( HIDP_REPORT_TYPE report_type
, USAGE usage_page
, USHORT collection
,
663 USAGE usage
, HIDP_BUTTON_CAPS
*caps
, USHORT
*caps_count
,
664 PHIDP_PREPARSED_DATA preparsed_data
)
666 WINE_HIDP_PREPARSED_DATA
*preparsed
= (WINE_HIDP_PREPARSED_DATA
*)preparsed_data
;
667 const struct caps_filter filter
= {.buttons
= TRUE
, .usage_page
= usage_page
, .collection
= collection
, .usage
= usage
};
669 TRACE( "report_type %d, usage_page %x, collection %d, usage %x, caps %p, caps_count %p, preparsed_data %p.\n",
670 report_type
, usage_page
, collection
, usage
, caps
, caps_count
, preparsed_data
);
672 return enum_value_caps( preparsed
, report_type
, &filter
, get_button_caps
, &caps
, caps_count
);
675 static NTSTATUS
get_value_caps( const struct hid_value_caps
*caps
, void *user
)
677 HIDP_VALUE_CAPS
**iter
= user
, *dst
= *iter
;
678 dst
->UsagePage
= caps
->usage_page
;
679 dst
->ReportID
= caps
->report_id
;
680 dst
->LinkCollection
= caps
->link_collection
;
681 dst
->LinkUsagePage
= caps
->link_usage_page
;
682 dst
->LinkUsage
= caps
->link_usage
;
683 dst
->BitField
= caps
->bit_field
;
684 dst
->IsAlias
= FALSE
;
685 dst
->IsAbsolute
= HID_VALUE_CAPS_IS_ABSOLUTE( caps
);
686 dst
->HasNull
= HID_VALUE_CAPS_HAS_NULL( caps
);
687 dst
->BitSize
= caps
->bit_size
;
688 dst
->ReportCount
= caps
->is_range
? 1 : caps
->report_count
;
689 dst
->UnitsExp
= caps
->units_exp
;
690 dst
->Units
= caps
->units
;
691 dst
->LogicalMin
= caps
->logical_min
;
692 dst
->LogicalMax
= caps
->logical_max
;
693 dst
->PhysicalMin
= caps
->physical_min
;
694 dst
->PhysicalMax
= caps
->physical_max
;
695 if (!(dst
->IsRange
= caps
->is_range
))
697 dst
->NotRange
.Usage
= caps
->usage_min
;
698 dst
->NotRange
.DataIndex
= caps
->data_index_min
;
702 dst
->Range
.UsageMin
= caps
->usage_min
;
703 dst
->Range
.UsageMax
= caps
->usage_max
;
704 dst
->Range
.DataIndexMin
= caps
->data_index_min
;
705 dst
->Range
.DataIndexMax
= caps
->data_index_max
;
707 if (!(dst
->IsStringRange
= caps
->is_string_range
))
708 dst
->NotRange
.StringIndex
= caps
->string_min
;
711 dst
->Range
.StringMin
= caps
->string_min
;
712 dst
->Range
.StringMax
= caps
->string_max
;
714 if ((dst
->IsDesignatorRange
= caps
->is_designator_range
))
715 dst
->NotRange
.DesignatorIndex
= caps
->designator_min
;
718 dst
->Range
.DesignatorMin
= caps
->designator_min
;
719 dst
->Range
.DesignatorMax
= caps
->designator_max
;
722 return HIDP_STATUS_SUCCESS
;
725 NTSTATUS WINAPI
HidP_GetSpecificValueCaps( HIDP_REPORT_TYPE report_type
, USAGE usage_page
, USHORT collection
,
726 USAGE usage
, HIDP_VALUE_CAPS
*caps
, USHORT
*caps_count
,
727 PHIDP_PREPARSED_DATA preparsed_data
)
729 WINE_HIDP_PREPARSED_DATA
*preparsed
= (WINE_HIDP_PREPARSED_DATA
*)preparsed_data
;
730 const struct caps_filter filter
= {.values
= TRUE
, .usage_page
= usage_page
, .collection
= collection
, .usage
= usage
};
732 TRACE( "report_type %d, usage_page %x, collection %d, usage %x, caps %p, caps_count %p, preparsed_data %p.\n",
733 report_type
, usage_page
, collection
, usage
, caps
, caps_count
, preparsed_data
);
735 return enum_value_caps( preparsed
, report_type
, &filter
, get_value_caps
, &caps
, caps_count
);
738 NTSTATUS WINAPI
HidP_GetUsagesEx(HIDP_REPORT_TYPE ReportType
, USHORT LinkCollection
, USAGE_AND_PAGE
*ButtonList
,
739 ULONG
*UsageLength
, PHIDP_PREPARSED_DATA PreparsedData
, CHAR
*Report
, ULONG ReportLength
)
741 WINE_HIDP_PREPARSED_DATA
*data
= (WINE_HIDP_PREPARSED_DATA
*)PreparsedData
;
742 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
743 WINE_HID_REPORT
*report
= NULL
;
744 USHORT b_count
= 0, r_count
= 0;
748 TRACE("(%i, %i, %p, %p(%i), %p, %p, %i)\n", ReportType
, LinkCollection
, ButtonList
,
749 UsageLength
, *UsageLength
, PreparsedData
, Report
, ReportLength
);
751 if (data
->magic
!= HID_MAGIC
)
752 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
757 b_count
= data
->caps
.NumberInputButtonCaps
;
760 b_count
= data
->caps
.NumberOutputButtonCaps
;
763 b_count
= data
->caps
.NumberFeatureButtonCaps
;
766 return HIDP_STATUS_INVALID_REPORT_TYPE
;
768 r_count
= data
->reportCount
[ReportType
];
769 report
= &data
->reports
[data
->reportIdx
[ReportType
][(BYTE
)Report
[0]]];
771 if (!r_count
|| !b_count
)
772 return HIDP_STATUS_USAGE_NOT_FOUND
;
774 if (report
->reportID
&& report
->reportID
!= Report
[0])
775 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
777 for (i
= 0; i
< report
->elementCount
; i
++)
779 if (elems
[report
->elementIdx
+ i
].caps
.BitSize
== 1)
782 WINE_HID_ELEMENT
*element
= &elems
[report
->elementIdx
+ i
];
783 for (k
=0; k
< element
->bitCount
; k
++)
786 NTSTATUS rc
= get_report_data((BYTE
*)Report
, ReportLength
,
787 element
->valueStartBit
+ k
, 1, &v
);
788 if (rc
!= HIDP_STATUS_SUCCESS
)
792 if (uCount
< *UsageLength
)
794 ButtonList
[uCount
].Usage
= element
->caps
.Range
.UsageMin
+ k
;
795 ButtonList
[uCount
].UsagePage
= element
->caps
.UsagePage
;
803 TRACE("Returning %i usages\n", uCount
);
805 if (*UsageLength
< uCount
)
806 rc
= HIDP_STATUS_BUFFER_TOO_SMALL
;
808 rc
= HIDP_STATUS_SUCCESS
;
810 *UsageLength
= uCount
;
815 ULONG WINAPI
HidP_MaxDataListLength(HIDP_REPORT_TYPE ReportType
, PHIDP_PREPARSED_DATA PreparsedData
)
817 WINE_HIDP_PREPARSED_DATA
*data
= (WINE_HIDP_PREPARSED_DATA
*)PreparsedData
;
818 TRACE("(%i, %p)\n", ReportType
, PreparsedData
);
819 if (data
->magic
!= HID_MAGIC
)
825 return data
->caps
.NumberInputDataIndices
;
827 return data
->caps
.NumberOutputDataIndices
;
829 return data
->caps
.NumberFeatureDataIndices
;
835 NTSTATUS WINAPI
HidP_GetData(HIDP_REPORT_TYPE ReportType
, HIDP_DATA
*DataList
, ULONG
*DataLength
,
836 PHIDP_PREPARSED_DATA PreparsedData
,CHAR
*Report
, ULONG ReportLength
)
838 WINE_HIDP_PREPARSED_DATA
*data
= (WINE_HIDP_PREPARSED_DATA
*)PreparsedData
;
839 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
840 WINE_HID_REPORT
*report
= NULL
;
845 TRACE("(%i, %p, %p(%i), %p, %p, %i)\n", ReportType
, DataList
, DataLength
,
846 DataLength
?*DataLength
:0, PreparsedData
, Report
, ReportLength
);
848 if (data
->magic
!= HID_MAGIC
)
851 if (ReportType
!= HidP_Input
&& ReportType
!= HidP_Output
&& ReportType
!= HidP_Feature
)
852 return HIDP_STATUS_INVALID_REPORT_TYPE
;
854 r_count
= data
->reportCount
[ReportType
];
855 report
= &data
->reports
[data
->reportIdx
[ReportType
][(BYTE
)Report
[0]]];
857 if (!r_count
|| (report
->reportID
&& report
->reportID
!= Report
[0]))
858 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
860 for (i
= 0; i
< report
->elementCount
; i
++)
862 WINE_HID_ELEMENT
*element
= &elems
[report
->elementIdx
+ i
];
863 if (element
->caps
.BitSize
== 1)
866 for (k
=0; k
< element
->bitCount
; k
++)
869 NTSTATUS rc
= get_report_data((BYTE
*)Report
, ReportLength
,
870 element
->valueStartBit
+ k
, 1, &v
);
871 if (rc
!= HIDP_STATUS_SUCCESS
)
875 if (uCount
< *DataLength
)
877 DataList
[uCount
].DataIndex
= element
->caps
.Range
.DataIndexMin
+ k
;
878 DataList
[uCount
].On
= v
;
886 if (uCount
< *DataLength
)
889 NTSTATUS rc
= get_report_data((BYTE
*)Report
, ReportLength
,
890 element
->valueStartBit
, element
->bitCount
, &v
);
891 if (rc
!= HIDP_STATUS_SUCCESS
)
893 DataList
[uCount
].DataIndex
= element
->caps
.NotRange
.DataIndex
;
894 DataList
[uCount
].RawValue
= v
;
900 if (*DataLength
< uCount
)
901 rc
= HIDP_STATUS_BUFFER_TOO_SMALL
;
903 rc
= HIDP_STATUS_SUCCESS
;
905 *DataLength
= uCount
;
910 NTSTATUS WINAPI
HidP_GetLinkCollectionNodes(HIDP_LINK_COLLECTION_NODE
*LinkCollectionNode
,
911 ULONG
*LinkCollectionNodeLength
, PHIDP_PREPARSED_DATA PreparsedData
)
913 WINE_HIDP_PREPARSED_DATA
*data
= (WINE_HIDP_PREPARSED_DATA
*)PreparsedData
;
914 WINE_HID_LINK_COLLECTION_NODE
*nodes
= HID_NODES(data
);
917 TRACE("(%p, %p, %p)\n", LinkCollectionNode
, LinkCollectionNodeLength
, PreparsedData
);
919 if (data
->magic
!= HID_MAGIC
)
920 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
922 if (*LinkCollectionNodeLength
< data
->caps
.NumberLinkCollectionNodes
)
923 return HIDP_STATUS_BUFFER_TOO_SMALL
;
925 for (i
= 0; i
< data
->caps
.NumberLinkCollectionNodes
; ++i
)
927 LinkCollectionNode
[i
].LinkUsage
= nodes
[i
].LinkUsage
;
928 LinkCollectionNode
[i
].LinkUsagePage
= nodes
[i
].LinkUsagePage
;
929 LinkCollectionNode
[i
].Parent
= nodes
[i
].Parent
;
930 LinkCollectionNode
[i
].NumberOfChildren
= nodes
[i
].NumberOfChildren
;
931 LinkCollectionNode
[i
].NextSibling
= nodes
[i
].NextSibling
;
932 LinkCollectionNode
[i
].FirstChild
= nodes
[i
].FirstChild
;
933 LinkCollectionNode
[i
].CollectionType
= nodes
[i
].CollectionType
;
934 LinkCollectionNode
[i
].IsAlias
= nodes
[i
].IsAlias
;
936 *LinkCollectionNodeLength
= data
->caps
.NumberLinkCollectionNodes
;
938 return HIDP_STATUS_SUCCESS
;