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
24 #define NONAMELESSUNION
26 #define WIN32_NO_STATUS
34 #include "ddk/hidpi.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(hidp
);
40 static NTSTATUS
get_report_data(BYTE
*report
, INT reportLength
, INT startBit
, INT valueSize
, PULONG value
)
43 if ((startBit
+ valueSize
) / 8 > reportLength
)
44 return HIDP_STATUS_INVALID_REPORT_LENGTH
;
48 ULONG byte_index
= startBit
/ 8;
49 ULONG bit_index
= startBit
- (byte_index
* 8);
50 INT mask
= (1 << bit_index
);
51 *value
= !!(report
[byte_index
] & mask
);
55 ULONG remaining_bits
= valueSize
;
56 ULONG byte_index
= startBit
/ 8;
57 ULONG bit_index
= startBit
% 8;
60 while (remaining_bits
)
62 ULONG copy_bits
= 8 - bit_index
;
63 if (remaining_bits
< copy_bits
)
64 copy_bits
= remaining_bits
;
66 data
|= ((report
[byte_index
] >> bit_index
) & ((1 << copy_bits
) - 1)) << shift
;
71 remaining_bits
-= copy_bits
;
75 return HIDP_STATUS_SUCCESS
;
78 static NTSTATUS
set_report_data(BYTE
*report
, INT reportLength
, INT startBit
, INT valueSize
, ULONG value
)
80 if ((startBit
+ valueSize
) / 8 > reportLength
)
81 return HIDP_STATUS_INVALID_REPORT_LENGTH
;
85 ULONG byte_index
= startBit
/ 8;
86 ULONG bit_index
= startBit
- (byte_index
* 8);
88 report
[byte_index
] |= (1 << bit_index
);
90 report
[byte_index
] &= ~(1 << bit_index
);
94 ULONG byte_index
= (startBit
+ valueSize
- 1) / 8;
96 ULONG remainingBits
= valueSize
;
99 BYTE subvalue
= data
& 0xff;
103 if (remainingBits
>= 8)
105 report
[byte_index
] = subvalue
;
109 else if (remainingBits
> 0)
111 BYTE mask
= (0xff << (8-remainingBits
)) & subvalue
;
112 report
[byte_index
] |= mask
;
117 return HIDP_STATUS_SUCCESS
;
121 NTSTATUS WINAPI
HidP_GetButtonCaps(HIDP_REPORT_TYPE ReportType
, PHIDP_BUTTON_CAPS ButtonCaps
,
122 PUSHORT ButtonCapsLength
, PHIDP_PREPARSED_DATA PreparsedData
)
124 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
125 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
126 WINE_HID_REPORT
*report
= NULL
;
127 USHORT b_count
= 0, r_count
= 0;
130 TRACE("(%i, %p, %p, %p)\n",ReportType
, ButtonCaps
, ButtonCapsLength
, PreparsedData
);
132 if (data
->magic
!= HID_MAGIC
)
133 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
138 b_count
= data
->caps
.NumberInputButtonCaps
;
139 report
= HID_INPUT_REPORTS(data
);
142 b_count
= data
->caps
.NumberOutputButtonCaps
;
143 report
= HID_OUTPUT_REPORTS(data
);
146 b_count
= data
->caps
.NumberFeatureButtonCaps
;
147 report
= HID_FEATURE_REPORTS(data
);
150 return HIDP_STATUS_INVALID_REPORT_TYPE
;
152 r_count
= data
->reportCount
[ReportType
];
154 if (!r_count
|| !b_count
)
156 *ButtonCapsLength
= 0;
157 return HIDP_STATUS_SUCCESS
;
160 b_count
= min(b_count
, *ButtonCapsLength
);
163 for (j
= 0; j
< r_count
&& u
< b_count
; j
++)
165 for (i
= 0; i
< report
[j
].elementCount
&& u
< b_count
; i
++)
167 if (elems
[report
[j
].elementIdx
+ i
].ElementType
== ButtonElement
)
168 ButtonCaps
[u
++] = elems
[report
[j
].elementIdx
+ i
].caps
.button
;
172 *ButtonCapsLength
= b_count
;
173 return HIDP_STATUS_SUCCESS
;
177 NTSTATUS WINAPI
HidP_GetCaps(PHIDP_PREPARSED_DATA PreparsedData
,
178 PHIDP_CAPS Capabilities
)
180 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
182 TRACE("(%p, %p)\n",PreparsedData
, Capabilities
);
184 if (data
->magic
!= HID_MAGIC
)
185 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
187 *Capabilities
= data
->caps
;
189 return HIDP_STATUS_SUCCESS
;
192 static NTSTATUS
find_usage(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
193 USAGE Usage
, PHIDP_PREPARSED_DATA PreparsedData
, PCHAR Report
,
194 WINE_ELEMENT_TYPE ElementType
, WINE_HID_ELEMENT
*element
)
196 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
197 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
198 WINE_HID_REPORT
*report
= NULL
;
199 USHORT v_count
= 0, r_count
= 0;
202 TRACE("(%i, %x, %i, %i, %p, %p)\n", ReportType
, UsagePage
, LinkCollection
, Usage
,
203 PreparsedData
, Report
);
205 if (data
->magic
!= HID_MAGIC
)
206 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
210 v_count
= data
->caps
.NumberInputValueCaps
;
213 v_count
= data
->caps
.NumberOutputValueCaps
;
216 v_count
= data
->caps
.NumberFeatureValueCaps
;
219 return HIDP_STATUS_INVALID_REPORT_TYPE
;
221 r_count
= data
->reportCount
[ReportType
];
222 report
= &data
->reports
[data
->reportIdx
[ReportType
][(BYTE
)Report
[0]]];
224 if (!r_count
|| !v_count
)
225 return HIDP_STATUS_USAGE_NOT_FOUND
;
227 if (report
->reportID
&& report
->reportID
!= Report
[0])
228 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
230 for (i
= 0; i
< report
->elementCount
; i
++)
232 HIDP_VALUE_CAPS
*value
= &elems
[report
->elementIdx
+ i
].caps
.value
;
234 if (elems
[report
->elementIdx
+ i
].ElementType
!= ElementType
||
235 value
->UsagePage
!= UsagePage
)
238 if (value
->IsRange
&& value
->u
.Range
.UsageMin
<= Usage
&& Usage
<= value
->u
.Range
.UsageMax
)
240 *element
= elems
[report
->elementIdx
+ i
];
241 element
->valueStartBit
+= value
->BitSize
* (Usage
- value
->u
.Range
.UsageMin
);
242 element
->bitCount
= elems
[report
->elementIdx
+ i
].ElementType
== ValueElement
? value
->BitSize
: 1;
243 return HIDP_STATUS_SUCCESS
;
245 else if (value
->u
.NotRange
.Usage
== Usage
)
247 *element
= elems
[report
->elementIdx
+ i
];
248 element
->bitCount
= elems
[report
->elementIdx
+ i
].ElementType
== ValueElement
? value
->BitSize
: 1;
249 return HIDP_STATUS_SUCCESS
;
253 return HIDP_STATUS_USAGE_NOT_FOUND
;
256 static LONG
sign_extend(ULONG value
, const WINE_HID_ELEMENT
*element
)
258 UINT bit_count
= element
->bitCount
;
260 if ((value
& (1 << (bit_count
- 1)))
261 && element
->ElementType
== ValueElement
262 && element
->caps
.value
.LogicalMin
< 0)
264 value
-= (1 << bit_count
);
269 static LONG
logical_to_physical(LONG value
, const WINE_HID_ELEMENT
*element
)
271 if (element
->caps
.value
.PhysicalMin
|| element
->caps
.value
.PhysicalMax
)
273 value
= (((ULONGLONG
)(value
- element
->caps
.value
.LogicalMin
)
274 * (element
->caps
.value
.PhysicalMax
- element
->caps
.value
.PhysicalMin
))
275 / (element
->caps
.value
.LogicalMax
- element
->caps
.value
.LogicalMin
))
276 + element
->caps
.value
.PhysicalMin
;
281 NTSTATUS WINAPI
HidP_GetScaledUsageValue(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
,
282 USHORT LinkCollection
, USAGE Usage
, PLONG UsageValue
,
283 PHIDP_PREPARSED_DATA PreparsedData
, PCHAR Report
, ULONG ReportLength
)
286 WINE_HID_ELEMENT element
;
287 TRACE("(%i, %x, %i, %i, %p, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, Usage
, UsageValue
,
288 PreparsedData
, Report
, ReportLength
);
290 rc
= find_usage(ReportType
, UsagePage
, LinkCollection
, Usage
, PreparsedData
, Report
, ValueElement
, &element
);
292 if (rc
== HIDP_STATUS_SUCCESS
)
295 rc
= get_report_data((BYTE
*)Report
, ReportLength
,
296 element
.valueStartBit
, element
.bitCount
, &rawValue
);
297 if (rc
!= HIDP_STATUS_SUCCESS
)
299 *UsageValue
= logical_to_physical(sign_extend(rawValue
, &element
), &element
);
306 NTSTATUS WINAPI
HidP_GetUsageValue(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
307 USAGE Usage
, PULONG UsageValue
, PHIDP_PREPARSED_DATA PreparsedData
,
308 PCHAR Report
, ULONG ReportLength
)
310 WINE_HID_ELEMENT element
;
313 TRACE("(%i, %x, %i, %i, %p, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, Usage
, UsageValue
,
314 PreparsedData
, Report
, ReportLength
);
316 rc
= find_usage(ReportType
, UsagePage
, LinkCollection
, Usage
, PreparsedData
, Report
, ValueElement
, &element
);
318 if (rc
== HIDP_STATUS_SUCCESS
)
320 return get_report_data((BYTE
*)Report
, ReportLength
,
321 element
.valueStartBit
, element
.bitCount
, UsageValue
);
328 NTSTATUS WINAPI
HidP_GetUsages(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
329 PUSAGE UsageList
, PULONG UsageLength
, PHIDP_PREPARSED_DATA PreparsedData
,
330 PCHAR Report
, ULONG ReportLength
)
332 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
333 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
334 WINE_HID_REPORT
*report
= NULL
;
336 USHORT b_count
= 0, r_count
= 0;
339 TRACE("(%i, %x, %i, %p, %p, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, UsageList
,
340 UsageLength
, PreparsedData
, Report
, ReportLength
);
342 if (data
->magic
!= HID_MAGIC
)
345 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
351 b_count
= data
->caps
.NumberInputButtonCaps
;
354 b_count
= data
->caps
.NumberOutputButtonCaps
;
357 b_count
= data
->caps
.NumberFeatureButtonCaps
;
360 return HIDP_STATUS_INVALID_REPORT_TYPE
;
362 r_count
= data
->reportCount
[ReportType
];
363 report
= &data
->reports
[data
->reportIdx
[ReportType
][(BYTE
)Report
[0]]];
365 if (!r_count
|| !b_count
)
366 return HIDP_STATUS_USAGE_NOT_FOUND
;
368 if (report
->reportID
&& report
->reportID
!= Report
[0])
369 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
372 for (i
= 0; i
< report
->elementCount
&& uCount
< *UsageLength
; i
++)
374 if (elems
[report
->elementIdx
+ i
].ElementType
== ButtonElement
&&
375 elems
[report
->elementIdx
+ i
].caps
.button
.UsagePage
== UsagePage
)
378 WINE_HID_ELEMENT
*element
= &elems
[report
->elementIdx
+ i
];
379 for (k
=0; k
< element
->bitCount
; k
++)
382 NTSTATUS rc
= get_report_data((BYTE
*)Report
, ReportLength
,
383 element
->valueStartBit
+ k
, 1, &v
);
384 if (rc
!= HIDP_STATUS_SUCCESS
)
389 if (uCount
== *UsageLength
)
390 return HIDP_STATUS_BUFFER_TOO_SMALL
;
391 UsageList
[uCount
] = element
->caps
.button
.u
.Range
.UsageMin
+ k
;
398 *UsageLength
= uCount
;
401 return HIDP_STATUS_USAGE_NOT_FOUND
;
403 return HIDP_STATUS_SUCCESS
;
407 NTSTATUS WINAPI
HidP_GetValueCaps(HIDP_REPORT_TYPE ReportType
, PHIDP_VALUE_CAPS ValueCaps
,
408 PUSHORT ValueCapsLength
, PHIDP_PREPARSED_DATA PreparsedData
)
410 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
411 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
412 WINE_HID_REPORT
*report
= NULL
;
413 USHORT v_count
= 0, r_count
= 0;
416 TRACE("(%i, %p, %p, %p)\n", ReportType
, ValueCaps
, ValueCapsLength
, PreparsedData
);
418 if (data
->magic
!= HID_MAGIC
)
419 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
424 v_count
= data
->caps
.NumberInputValueCaps
;
425 report
= HID_INPUT_REPORTS(data
);
428 v_count
= data
->caps
.NumberOutputValueCaps
;
429 report
= HID_OUTPUT_REPORTS(data
);
432 v_count
= data
->caps
.NumberFeatureValueCaps
;
433 report
= HID_FEATURE_REPORTS(data
);
436 return HIDP_STATUS_INVALID_REPORT_TYPE
;
438 r_count
= data
->reportCount
[ReportType
];
440 if (!r_count
|| !v_count
)
442 *ValueCapsLength
= 0;
443 return HIDP_STATUS_SUCCESS
;
446 v_count
= min(v_count
, *ValueCapsLength
);
449 for (j
= 0; j
< r_count
&& u
< v_count
; j
++)
451 for (i
= 0; i
< report
[j
].elementCount
&& u
< v_count
; i
++)
453 if (elems
[report
[j
].elementIdx
+ i
].ElementType
== ValueElement
)
454 ValueCaps
[u
++] = elems
[report
[j
].elementIdx
+ i
].caps
.value
;
458 *ValueCapsLength
= v_count
;
459 return HIDP_STATUS_SUCCESS
;
462 NTSTATUS WINAPI
HidP_InitializeReportForID(HIDP_REPORT_TYPE ReportType
, UCHAR ReportID
,
463 PHIDP_PREPARSED_DATA PreparsedData
, PCHAR Report
,
467 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
468 WINE_HID_REPORT
*report
= NULL
;
471 TRACE("(%i, %i, %p, %p, %i)\n",ReportType
, ReportID
, PreparsedData
, Report
, ReportLength
);
473 if (data
->magic
!= HID_MAGIC
)
474 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
479 size
= data
->caps
.InputReportByteLength
;
482 size
= data
->caps
.OutputReportByteLength
;
485 size
= data
->caps
.FeatureReportByteLength
;
488 return HIDP_STATUS_INVALID_REPORT_TYPE
;
490 r_count
= data
->reportCount
[ReportType
];
491 report
= &data
->reports
[data
->reportIdx
[ReportType
][(BYTE
)Report
[0]]];
493 if (!r_count
|| !size
)
494 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
496 if (size
!= ReportLength
)
497 return HIDP_STATUS_INVALID_REPORT_LENGTH
;
499 if (report
->reportID
&& report
->reportID
!= Report
[0])
500 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
502 ZeroMemory(Report
, size
);
503 Report
[0] = ReportID
;
504 return HIDP_STATUS_SUCCESS
;
507 ULONG WINAPI
HidP_MaxUsageListLength(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, PHIDP_PREPARSED_DATA PreparsedData
)
509 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
510 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
511 WINE_HID_REPORT
*report
= NULL
;
516 TRACE("(%i, %x, %p)\n", ReportType
, UsagePage
, PreparsedData
);
518 if (data
->magic
!= HID_MAGIC
)
524 report
= HID_INPUT_REPORTS(data
);
527 report
= HID_OUTPUT_REPORTS(data
);
530 report
= HID_FEATURE_REPORTS(data
);
533 return HIDP_STATUS_INVALID_REPORT_TYPE
;
535 r_count
= data
->reportCount
[ReportType
];
541 for (i
= 0; i
< r_count
; i
++)
544 for (j
= 0; j
< report
[i
].elementCount
; j
++)
546 if (elems
[report
[i
].elementIdx
+ j
].ElementType
== ButtonElement
&&
547 (UsagePage
== 0 || elems
[report
[i
].elementIdx
+ j
].caps
.button
.UsagePage
== UsagePage
))
549 if (elems
[report
[i
].elementIdx
+ j
].caps
.button
.IsRange
)
550 count
+= (elems
[report
[i
].elementIdx
+ j
].caps
.button
.u
.Range
.UsageMax
-
551 elems
[report
[i
].elementIdx
+ j
].caps
.button
.u
.Range
.UsageMin
) + 1;
560 NTSTATUS WINAPI
HidP_SetUsageValue(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
561 USAGE Usage
, ULONG UsageValue
, PHIDP_PREPARSED_DATA PreparsedData
,
562 CHAR
*Report
, ULONG ReportLength
)
564 WINE_HID_ELEMENT element
;
567 TRACE("(%i, %x, %i, %i, %i, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, Usage
, UsageValue
,
568 PreparsedData
, Report
, ReportLength
);
570 rc
= find_usage(ReportType
, UsagePage
, LinkCollection
, Usage
, PreparsedData
, Report
, ValueElement
, &element
);
572 if (rc
== HIDP_STATUS_SUCCESS
)
574 return set_report_data((BYTE
*)Report
, ReportLength
,
575 element
.valueStartBit
, element
.bitCount
, UsageValue
);
582 NTSTATUS WINAPI
HidP_SetUsages(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
583 PUSAGE UsageList
, PULONG UsageLength
, PHIDP_PREPARSED_DATA PreparsedData
,
584 PCHAR Report
, ULONG ReportLength
)
586 WINE_HID_ELEMENT element
;
590 TRACE("(%i, %x, %i, %p, %p, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, UsageList
,
591 UsageLength
, PreparsedData
, Report
, ReportLength
);
593 for (i
= 0; i
< *UsageLength
; i
++)
595 rc
= find_usage(ReportType
, UsagePage
, LinkCollection
,
596 UsageList
[i
], PreparsedData
, Report
, ButtonElement
, &element
);
597 if (rc
== HIDP_STATUS_SUCCESS
)
599 rc
= set_report_data((BYTE
*)Report
, ReportLength
,
600 element
.valueStartBit
, element
.bitCount
, -1);
603 if (rc
!= HIDP_STATUS_SUCCESS
)
610 return HIDP_STATUS_SUCCESS
;
614 NTSTATUS WINAPI
HidP_TranslateUsagesToI8042ScanCodes(USAGE
*ChangedUsageList
,
615 ULONG UsageListLength
, HIDP_KEYBOARD_DIRECTION KeyAction
,
616 HIDP_KEYBOARD_MODIFIER_STATE
*ModifierState
,
617 PHIDP_INSERT_SCANCODES InsertCodesProcedure
, VOID
*InsertCodesContext
)
619 FIXME("stub: %p, %i, %i, %p, %p, %p\n", ChangedUsageList
, UsageListLength
,
620 KeyAction
, ModifierState
, InsertCodesProcedure
, InsertCodesContext
);
622 return STATUS_NOT_IMPLEMENTED
;
625 NTSTATUS WINAPI
HidP_GetSpecificButtonCaps(HIDP_REPORT_TYPE ReportType
,
626 USAGE UsagePage
, USHORT LinkCollection
, USAGE Usage
,
627 HIDP_BUTTON_CAPS
*ButtonCaps
, USHORT
*ButtonCapsLength
, PHIDP_PREPARSED_DATA PreparsedData
)
629 WINE_HIDP_PREPARSED_DATA
*data
= (WINE_HIDP_PREPARSED_DATA
*)PreparsedData
;
630 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
631 WINE_HID_REPORT
*report
= NULL
;
632 USHORT b_count
= 0, r_count
= 0;
635 TRACE("(%i, 0x%x, %i, 0x%x, %p %p %p)\n", ReportType
, UsagePage
, LinkCollection
,
636 Usage
, ButtonCaps
, ButtonCapsLength
, PreparsedData
);
638 if (data
->magic
!= HID_MAGIC
)
639 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
644 b_count
= data
->caps
.NumberInputButtonCaps
;
645 report
= HID_INPUT_REPORTS(data
);
648 b_count
= data
->caps
.NumberOutputButtonCaps
;
649 report
= HID_OUTPUT_REPORTS(data
);
652 b_count
= data
->caps
.NumberFeatureButtonCaps
;
653 report
= HID_FEATURE_REPORTS(data
);
656 return HIDP_STATUS_INVALID_REPORT_TYPE
;
658 r_count
= data
->reportCount
[ReportType
];
660 if (!r_count
|| !b_count
)
662 *ButtonCapsLength
= 0;
663 return HIDP_STATUS_SUCCESS
;
666 b_count
= min(b_count
, *ButtonCapsLength
);
669 for (j
= 0; j
< r_count
&& u
< b_count
; j
++)
671 for (i
= 0; i
< report
[j
].elementCount
&& u
< b_count
; i
++)
673 if (elems
[report
[j
].elementIdx
+ i
].ElementType
== ButtonElement
&&
674 (UsagePage
== 0 || UsagePage
== elems
[report
[j
].elementIdx
+ i
].caps
.button
.UsagePage
) &&
675 (LinkCollection
== 0 || LinkCollection
== elems
[report
[j
].elementIdx
+ i
].caps
.button
.LinkCollection
) &&
677 (!elems
[report
[j
].elementIdx
+ i
].caps
.button
.IsRange
&&
678 Usage
== elems
[report
[j
].elementIdx
+ i
].caps
.button
.u
.NotRange
.Usage
)) ||
679 (elems
[report
[j
].elementIdx
+ i
].caps
.button
.IsRange
&&
680 Usage
>= elems
[report
[j
].elementIdx
+ i
].caps
.button
.u
.Range
.UsageMin
&&
681 Usage
<= elems
[report
[j
].elementIdx
+ i
].caps
.button
.u
.Range
.UsageMax
)))
683 ButtonCaps
[u
++] = elems
[report
[j
].elementIdx
+ i
].caps
.button
;
687 TRACE("Matched %i usages\n", u
);
689 *ButtonCapsLength
= u
;
691 return HIDP_STATUS_SUCCESS
;
695 NTSTATUS WINAPI
HidP_GetSpecificValueCaps(HIDP_REPORT_TYPE ReportType
,
696 USAGE UsagePage
, USHORT LinkCollection
, USAGE Usage
,
697 HIDP_VALUE_CAPS
*ValueCaps
, USHORT
*ValueCapsLength
, PHIDP_PREPARSED_DATA PreparsedData
)
699 WINE_HIDP_PREPARSED_DATA
*data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
700 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
701 WINE_HID_REPORT
*report
= NULL
;
702 USHORT v_count
= 0, r_count
= 0;
705 TRACE("(%i, 0x%x, %i, 0x%x, %p %p %p)\n", ReportType
, UsagePage
, LinkCollection
,
706 Usage
, ValueCaps
, ValueCapsLength
, PreparsedData
);
708 if (data
->magic
!= HID_MAGIC
)
709 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
714 v_count
= data
->caps
.NumberInputValueCaps
;
715 report
= HID_INPUT_REPORTS(data
);
718 v_count
= data
->caps
.NumberOutputValueCaps
;
719 report
= HID_OUTPUT_REPORTS(data
);
722 v_count
= data
->caps
.NumberFeatureValueCaps
;
723 report
= HID_FEATURE_REPORTS(data
);
726 return HIDP_STATUS_INVALID_REPORT_TYPE
;
728 r_count
= data
->reportCount
[ReportType
];
730 if (!r_count
|| !v_count
)
732 *ValueCapsLength
= 0;
733 return HIDP_STATUS_SUCCESS
;
736 v_count
= min(v_count
, *ValueCapsLength
);
739 for (j
= 0; j
< r_count
&& u
< v_count
; j
++)
741 for (i
= 0; i
< report
[j
].elementCount
&& u
< v_count
; i
++)
743 if (elems
[report
[j
].elementIdx
+ i
].ElementType
== ValueElement
&&
744 (UsagePage
== 0 || UsagePage
== elems
[report
[j
].elementIdx
+ i
].caps
.value
.UsagePage
) &&
745 (LinkCollection
== 0 || LinkCollection
== elems
[report
[j
].elementIdx
+ i
].caps
.value
.LinkCollection
) &&
746 (Usage
== 0 || Usage
== elems
[report
[j
].elementIdx
+ i
].caps
.value
.u
.NotRange
.Usage
))
748 ValueCaps
[u
++] = elems
[report
[j
].elementIdx
+ i
].caps
.value
;
752 TRACE("Matched %i usages\n", u
);
754 *ValueCapsLength
= u
;
756 return HIDP_STATUS_SUCCESS
;
759 NTSTATUS WINAPI
HidP_GetUsagesEx(HIDP_REPORT_TYPE ReportType
, USHORT LinkCollection
, USAGE_AND_PAGE
*ButtonList
,
760 ULONG
*UsageLength
, PHIDP_PREPARSED_DATA PreparsedData
, CHAR
*Report
, ULONG ReportLength
)
762 WINE_HIDP_PREPARSED_DATA
*data
= (WINE_HIDP_PREPARSED_DATA
*)PreparsedData
;
763 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
764 WINE_HID_REPORT
*report
= NULL
;
765 USHORT b_count
= 0, r_count
= 0;
769 TRACE("(%i, %i, %p, %p(%i), %p, %p, %i)\n", ReportType
, LinkCollection
, ButtonList
,
770 UsageLength
, *UsageLength
, PreparsedData
, Report
, ReportLength
);
772 if (data
->magic
!= HID_MAGIC
)
773 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
778 b_count
= data
->caps
.NumberInputButtonCaps
;
781 b_count
= data
->caps
.NumberOutputButtonCaps
;
784 b_count
= data
->caps
.NumberFeatureButtonCaps
;
787 return HIDP_STATUS_INVALID_REPORT_TYPE
;
789 r_count
= data
->reportCount
[ReportType
];
790 report
= &data
->reports
[data
->reportIdx
[ReportType
][(BYTE
)Report
[0]]];
792 if (!r_count
|| !b_count
)
793 return HIDP_STATUS_USAGE_NOT_FOUND
;
795 if (report
->reportID
&& report
->reportID
!= Report
[0])
796 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
798 for (i
= 0; i
< report
->elementCount
; i
++)
800 if (elems
[report
->elementIdx
+ i
].ElementType
== ButtonElement
)
803 WINE_HID_ELEMENT
*element
= &elems
[report
->elementIdx
+ i
];
804 for (k
=0; k
< element
->bitCount
; k
++)
807 NTSTATUS rc
= get_report_data((BYTE
*)Report
, ReportLength
,
808 element
->valueStartBit
+ k
, 1, &v
);
809 if (rc
!= HIDP_STATUS_SUCCESS
)
813 if (uCount
< *UsageLength
)
815 ButtonList
[uCount
].Usage
= element
->caps
.button
.u
.Range
.UsageMin
+ k
;
816 ButtonList
[uCount
].UsagePage
= element
->caps
.button
.UsagePage
;
824 TRACE("Returning %i usages\n", uCount
);
826 if (*UsageLength
< uCount
)
827 rc
= HIDP_STATUS_BUFFER_TOO_SMALL
;
829 rc
= HIDP_STATUS_SUCCESS
;
831 *UsageLength
= uCount
;
836 ULONG WINAPI
HidP_MaxDataListLength(HIDP_REPORT_TYPE ReportType
, PHIDP_PREPARSED_DATA PreparsedData
)
838 WINE_HIDP_PREPARSED_DATA
*data
= (WINE_HIDP_PREPARSED_DATA
*)PreparsedData
;
839 TRACE("(%i, %p)\n", ReportType
, PreparsedData
);
840 if (data
->magic
!= HID_MAGIC
)
846 return data
->caps
.NumberInputDataIndices
;
848 return data
->caps
.NumberOutputDataIndices
;
850 return data
->caps
.NumberFeatureDataIndices
;
856 NTSTATUS WINAPI
HidP_GetData(HIDP_REPORT_TYPE ReportType
, HIDP_DATA
*DataList
, ULONG
*DataLength
,
857 PHIDP_PREPARSED_DATA PreparsedData
,CHAR
*Report
, ULONG ReportLength
)
859 WINE_HIDP_PREPARSED_DATA
*data
= (WINE_HIDP_PREPARSED_DATA
*)PreparsedData
;
860 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
861 WINE_HID_REPORT
*report
= NULL
;
866 TRACE("(%i, %p, %p(%i), %p, %p, %i)\n", ReportType
, DataList
, DataLength
,
867 DataLength
?*DataLength
:0, PreparsedData
, Report
, ReportLength
);
869 if (data
->magic
!= HID_MAGIC
)
872 if (ReportType
!= HidP_Input
&& ReportType
!= HidP_Output
&& ReportType
!= HidP_Feature
)
873 return HIDP_STATUS_INVALID_REPORT_TYPE
;
875 r_count
= data
->reportCount
[ReportType
];
876 report
= &data
->reports
[data
->reportIdx
[ReportType
][(BYTE
)Report
[0]]];
878 if (!r_count
|| (report
->reportID
&& report
->reportID
!= Report
[0]))
879 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
881 for (i
= 0; i
< report
->elementCount
; i
++)
883 WINE_HID_ELEMENT
*element
= &elems
[report
->elementIdx
+ i
];
884 if (element
->ElementType
== ButtonElement
)
887 for (k
=0; k
< element
->bitCount
; k
++)
890 NTSTATUS rc
= get_report_data((BYTE
*)Report
, ReportLength
,
891 element
->valueStartBit
+ k
, 1, &v
);
892 if (rc
!= HIDP_STATUS_SUCCESS
)
896 if (uCount
< *DataLength
)
898 DataList
[uCount
].DataIndex
= element
->caps
.button
.u
.Range
.DataIndexMin
+ k
;
899 DataList
[uCount
].u
.On
= v
;
907 if (uCount
< *DataLength
)
910 NTSTATUS rc
= get_report_data((BYTE
*)Report
, ReportLength
,
911 element
->valueStartBit
, element
->bitCount
, &v
);
912 if (rc
!= HIDP_STATUS_SUCCESS
)
914 DataList
[uCount
].DataIndex
= element
->caps
.value
.u
.NotRange
.DataIndex
;
915 DataList
[uCount
].u
.RawValue
= v
;
921 if (*DataLength
< uCount
)
922 rc
= HIDP_STATUS_BUFFER_TOO_SMALL
;
924 rc
= HIDP_STATUS_SUCCESS
;
926 *DataLength
= uCount
;