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
;
120 static NTSTATUS
get_report_data_array(BYTE
*report
, UINT reportLength
, UINT startBit
, UINT elemSize
,
121 UINT numElements
, PCHAR values
, UINT valuesSize
)
123 BYTE byte
, *end
, *p
= report
+ startBit
/ 8;
124 ULONG size
= elemSize
* numElements
;
125 ULONG m
, bit_index
= startBit
% 8;
126 BYTE
*data
= (BYTE
*)values
;
128 if ((startBit
+ size
) / 8 > reportLength
)
129 return HIDP_STATUS_INVALID_REPORT_LENGTH
;
131 if (valuesSize
< (size
+ 7) / 8)
132 return HIDP_STATUS_BUFFER_TOO_SMALL
;
134 end
= report
+ (startBit
+ size
+ 7) / 8;
140 *(++data
) = byte
>> bit_index
;
142 *data
|= byte
<< (8 - bit_index
);
145 /* Handle the end and mask out bits beyond */
146 m
= (startBit
+ size
) % 8;
150 *(++data
) = (byte
>> bit_index
) & ((1 << (m
- bit_index
)) - 1);
152 *data
&= (1 << (m
+ 8 - bit_index
)) - 1;
154 if (++data
< (BYTE
*)values
+ valuesSize
)
155 memset(data
, 0, (BYTE
*)values
+ valuesSize
- data
);
157 return HIDP_STATUS_SUCCESS
;
161 NTSTATUS WINAPI
HidP_GetButtonCaps(HIDP_REPORT_TYPE ReportType
, PHIDP_BUTTON_CAPS ButtonCaps
,
162 PUSHORT ButtonCapsLength
, PHIDP_PREPARSED_DATA PreparsedData
)
164 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
165 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
166 WINE_HID_REPORT
*report
= NULL
;
167 USHORT b_count
= 0, r_count
= 0;
170 TRACE("(%i, %p, %p, %p)\n",ReportType
, ButtonCaps
, ButtonCapsLength
, PreparsedData
);
172 if (data
->magic
!= HID_MAGIC
)
173 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
178 b_count
= data
->caps
.NumberInputButtonCaps
;
179 report
= HID_INPUT_REPORTS(data
);
182 b_count
= data
->caps
.NumberOutputButtonCaps
;
183 report
= HID_OUTPUT_REPORTS(data
);
186 b_count
= data
->caps
.NumberFeatureButtonCaps
;
187 report
= HID_FEATURE_REPORTS(data
);
190 return HIDP_STATUS_INVALID_REPORT_TYPE
;
192 r_count
= data
->reportCount
[ReportType
];
194 if (!r_count
|| !b_count
)
196 *ButtonCapsLength
= 0;
197 return HIDP_STATUS_SUCCESS
;
200 b_count
= min(b_count
, *ButtonCapsLength
);
203 for (j
= 0; j
< r_count
&& u
< b_count
; j
++)
205 for (i
= 0; i
< report
[j
].elementCount
&& u
< b_count
; i
++)
207 if (elems
[report
[j
].elementIdx
+ i
].ElementType
== ButtonElement
)
208 ButtonCaps
[u
++] = elems
[report
[j
].elementIdx
+ i
].caps
.button
;
212 *ButtonCapsLength
= b_count
;
213 return HIDP_STATUS_SUCCESS
;
217 NTSTATUS WINAPI
HidP_GetCaps(PHIDP_PREPARSED_DATA PreparsedData
,
218 PHIDP_CAPS Capabilities
)
220 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
222 TRACE("(%p, %p)\n",PreparsedData
, Capabilities
);
224 if (data
->magic
!= HID_MAGIC
)
225 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
227 *Capabilities
= data
->caps
;
229 return HIDP_STATUS_SUCCESS
;
232 static NTSTATUS
find_usage(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
233 USAGE Usage
, PHIDP_PREPARSED_DATA PreparsedData
, PCHAR Report
,
234 WINE_ELEMENT_TYPE ElementType
, WINE_HID_ELEMENT
*element
)
236 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
237 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
238 WINE_HID_REPORT
*report
= NULL
;
239 USHORT v_count
= 0, r_count
= 0;
242 TRACE("(%i, %x, %i, %i, %p, %p)\n", ReportType
, UsagePage
, LinkCollection
, Usage
,
243 PreparsedData
, Report
);
245 if (data
->magic
!= HID_MAGIC
)
246 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
250 v_count
= data
->caps
.NumberInputValueCaps
;
253 v_count
= data
->caps
.NumberOutputValueCaps
;
256 v_count
= data
->caps
.NumberFeatureValueCaps
;
259 return HIDP_STATUS_INVALID_REPORT_TYPE
;
261 r_count
= data
->reportCount
[ReportType
];
262 report
= &data
->reports
[data
->reportIdx
[ReportType
][(BYTE
)Report
[0]]];
264 if (!r_count
|| !v_count
)
265 return HIDP_STATUS_USAGE_NOT_FOUND
;
267 if (report
->reportID
&& report
->reportID
!= Report
[0])
268 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
270 for (i
= 0; i
< report
->elementCount
; i
++)
272 HIDP_VALUE_CAPS
*value
= &elems
[report
->elementIdx
+ i
].caps
.value
;
274 if (elems
[report
->elementIdx
+ i
].ElementType
!= ElementType
||
275 value
->UsagePage
!= UsagePage
)
278 if (value
->IsRange
&& value
->u
.Range
.UsageMin
<= Usage
&& Usage
<= value
->u
.Range
.UsageMax
)
280 *element
= elems
[report
->elementIdx
+ i
];
281 element
->valueStartBit
+= value
->BitSize
* (Usage
- value
->u
.Range
.UsageMin
);
282 element
->bitCount
= elems
[report
->elementIdx
+ i
].ElementType
== ValueElement
? value
->BitSize
: 1;
283 return HIDP_STATUS_SUCCESS
;
285 else if (value
->u
.NotRange
.Usage
== Usage
)
287 *element
= elems
[report
->elementIdx
+ i
];
288 element
->bitCount
= elems
[report
->elementIdx
+ i
].ElementType
== ValueElement
? value
->BitSize
: 1;
289 return HIDP_STATUS_SUCCESS
;
293 return HIDP_STATUS_USAGE_NOT_FOUND
;
296 static LONG
sign_extend(ULONG value
, const WINE_HID_ELEMENT
*element
)
298 UINT bit_count
= element
->bitCount
;
300 if ((value
& (1 << (bit_count
- 1)))
301 && element
->ElementType
== ValueElement
302 && element
->caps
.value
.LogicalMin
< 0)
304 value
-= (1 << bit_count
);
309 static LONG
logical_to_physical(LONG value
, const WINE_HID_ELEMENT
*element
)
311 if (element
->caps
.value
.PhysicalMin
|| element
->caps
.value
.PhysicalMax
)
313 value
= (((ULONGLONG
)(value
- element
->caps
.value
.LogicalMin
)
314 * (element
->caps
.value
.PhysicalMax
- element
->caps
.value
.PhysicalMin
))
315 / (element
->caps
.value
.LogicalMax
- element
->caps
.value
.LogicalMin
))
316 + element
->caps
.value
.PhysicalMin
;
321 NTSTATUS WINAPI
HidP_GetScaledUsageValue(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
,
322 USHORT LinkCollection
, USAGE Usage
, PLONG UsageValue
,
323 PHIDP_PREPARSED_DATA PreparsedData
, PCHAR Report
, ULONG ReportLength
)
326 WINE_HID_ELEMENT element
;
327 TRACE("(%i, %x, %i, %i, %p, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, Usage
, UsageValue
,
328 PreparsedData
, Report
, ReportLength
);
330 rc
= find_usage(ReportType
, UsagePage
, LinkCollection
, Usage
, PreparsedData
, Report
, ValueElement
, &element
);
332 if (rc
== HIDP_STATUS_SUCCESS
)
335 rc
= get_report_data((BYTE
*)Report
, ReportLength
,
336 element
.valueStartBit
, element
.bitCount
, &rawValue
);
337 if (rc
!= HIDP_STATUS_SUCCESS
)
339 *UsageValue
= logical_to_physical(sign_extend(rawValue
, &element
), &element
);
346 NTSTATUS WINAPI
HidP_GetUsageValue(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
347 USAGE Usage
, PULONG UsageValue
, PHIDP_PREPARSED_DATA PreparsedData
,
348 PCHAR Report
, ULONG ReportLength
)
350 WINE_HID_ELEMENT element
;
353 TRACE("(%i, %x, %i, %i, %p, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, Usage
, UsageValue
,
354 PreparsedData
, Report
, ReportLength
);
356 rc
= find_usage(ReportType
, UsagePage
, LinkCollection
, Usage
, PreparsedData
, Report
, ValueElement
, &element
);
358 if (rc
== HIDP_STATUS_SUCCESS
)
360 return get_report_data((BYTE
*)Report
, ReportLength
,
361 element
.valueStartBit
, element
.bitCount
, UsageValue
);
368 NTSTATUS WINAPI
HidP_GetUsageValueArray(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
369 USAGE Usage
, PCHAR UsageValue
, USHORT UsageValueByteLength
,
370 PHIDP_PREPARSED_DATA PreparsedData
, PCHAR Report
, ULONG ReportLength
)
372 WINE_HID_ELEMENT element
;
375 TRACE("(%i, %x, %i, %i, %p, %u, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, Usage
, UsageValue
,
376 UsageValueByteLength
, PreparsedData
, Report
, ReportLength
);
378 rc
= find_usage(ReportType
, UsagePage
, LinkCollection
, Usage
, PreparsedData
, Report
, ValueElement
, &element
);
380 if (rc
== HIDP_STATUS_SUCCESS
)
382 if (element
.caps
.value
.IsRange
|| element
.caps
.value
.ReportCount
<= 1 || !element
.bitCount
)
383 return HIDP_STATUS_NOT_VALUE_ARRAY
;
385 return get_report_data_array((BYTE
*)Report
, ReportLength
, element
.valueStartBit
, element
.bitCount
,
386 element
.caps
.value
.ReportCount
, UsageValue
, UsageValueByteLength
);
393 NTSTATUS WINAPI
HidP_GetUsages(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
394 PUSAGE UsageList
, PULONG UsageLength
, PHIDP_PREPARSED_DATA PreparsedData
,
395 PCHAR Report
, ULONG ReportLength
)
397 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
398 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
399 WINE_HID_REPORT
*report
= NULL
;
401 USHORT b_count
= 0, r_count
= 0;
404 TRACE("(%i, %x, %i, %p, %p, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, UsageList
,
405 UsageLength
, PreparsedData
, Report
, ReportLength
);
407 if (data
->magic
!= HID_MAGIC
)
410 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
416 b_count
= data
->caps
.NumberInputButtonCaps
;
419 b_count
= data
->caps
.NumberOutputButtonCaps
;
422 b_count
= data
->caps
.NumberFeatureButtonCaps
;
425 return HIDP_STATUS_INVALID_REPORT_TYPE
;
427 r_count
= data
->reportCount
[ReportType
];
428 report
= &data
->reports
[data
->reportIdx
[ReportType
][(BYTE
)Report
[0]]];
430 if (!r_count
|| !b_count
)
431 return HIDP_STATUS_USAGE_NOT_FOUND
;
433 if (report
->reportID
&& report
->reportID
!= Report
[0])
434 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
437 for (i
= 0; i
< report
->elementCount
&& uCount
< *UsageLength
; i
++)
439 if (elems
[report
->elementIdx
+ i
].ElementType
== ButtonElement
&&
440 elems
[report
->elementIdx
+ i
].caps
.button
.UsagePage
== UsagePage
)
443 WINE_HID_ELEMENT
*element
= &elems
[report
->elementIdx
+ i
];
444 for (k
=0; k
< element
->bitCount
; k
++)
447 NTSTATUS rc
= get_report_data((BYTE
*)Report
, ReportLength
,
448 element
->valueStartBit
+ k
, 1, &v
);
449 if (rc
!= HIDP_STATUS_SUCCESS
)
454 if (uCount
== *UsageLength
)
455 return HIDP_STATUS_BUFFER_TOO_SMALL
;
456 UsageList
[uCount
] = element
->caps
.button
.u
.Range
.UsageMin
+ k
;
463 *UsageLength
= uCount
;
466 return HIDP_STATUS_USAGE_NOT_FOUND
;
468 return HIDP_STATUS_SUCCESS
;
472 NTSTATUS WINAPI
HidP_GetValueCaps(HIDP_REPORT_TYPE ReportType
, PHIDP_VALUE_CAPS ValueCaps
,
473 PUSHORT ValueCapsLength
, PHIDP_PREPARSED_DATA PreparsedData
)
475 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
476 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
477 WINE_HID_REPORT
*report
= NULL
;
478 USHORT v_count
= 0, r_count
= 0;
481 TRACE("(%i, %p, %p, %p)\n", ReportType
, ValueCaps
, ValueCapsLength
, PreparsedData
);
483 if (data
->magic
!= HID_MAGIC
)
484 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
489 v_count
= data
->caps
.NumberInputValueCaps
;
490 report
= HID_INPUT_REPORTS(data
);
493 v_count
= data
->caps
.NumberOutputValueCaps
;
494 report
= HID_OUTPUT_REPORTS(data
);
497 v_count
= data
->caps
.NumberFeatureValueCaps
;
498 report
= HID_FEATURE_REPORTS(data
);
501 return HIDP_STATUS_INVALID_REPORT_TYPE
;
503 r_count
= data
->reportCount
[ReportType
];
505 if (!r_count
|| !v_count
)
507 *ValueCapsLength
= 0;
508 return HIDP_STATUS_SUCCESS
;
511 v_count
= min(v_count
, *ValueCapsLength
);
514 for (j
= 0; j
< r_count
&& u
< v_count
; j
++)
516 for (i
= 0; i
< report
[j
].elementCount
&& u
< v_count
; i
++)
518 if (elems
[report
[j
].elementIdx
+ i
].ElementType
== ValueElement
)
519 ValueCaps
[u
++] = elems
[report
[j
].elementIdx
+ i
].caps
.value
;
523 *ValueCapsLength
= v_count
;
524 return HIDP_STATUS_SUCCESS
;
527 NTSTATUS WINAPI
HidP_InitializeReportForID(HIDP_REPORT_TYPE ReportType
, UCHAR ReportID
,
528 PHIDP_PREPARSED_DATA PreparsedData
, PCHAR Report
,
532 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
533 WINE_HID_REPORT
*report
= NULL
;
536 TRACE("(%i, %i, %p, %p, %i)\n",ReportType
, ReportID
, PreparsedData
, Report
, ReportLength
);
538 if (data
->magic
!= HID_MAGIC
)
539 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
544 size
= data
->caps
.InputReportByteLength
;
547 size
= data
->caps
.OutputReportByteLength
;
550 size
= data
->caps
.FeatureReportByteLength
;
553 return HIDP_STATUS_INVALID_REPORT_TYPE
;
555 r_count
= data
->reportCount
[ReportType
];
556 report
= &data
->reports
[data
->reportIdx
[ReportType
][(BYTE
)Report
[0]]];
558 if (!r_count
|| !size
)
559 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
561 if (size
!= ReportLength
)
562 return HIDP_STATUS_INVALID_REPORT_LENGTH
;
564 if (report
->reportID
&& report
->reportID
!= Report
[0])
565 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
567 ZeroMemory(Report
, size
);
568 Report
[0] = ReportID
;
569 return HIDP_STATUS_SUCCESS
;
572 ULONG WINAPI
HidP_MaxUsageListLength(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, PHIDP_PREPARSED_DATA PreparsedData
)
574 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
575 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
576 WINE_HID_REPORT
*report
= NULL
;
581 TRACE("(%i, %x, %p)\n", ReportType
, UsagePage
, PreparsedData
);
583 if (data
->magic
!= HID_MAGIC
)
589 report
= HID_INPUT_REPORTS(data
);
592 report
= HID_OUTPUT_REPORTS(data
);
595 report
= HID_FEATURE_REPORTS(data
);
598 return HIDP_STATUS_INVALID_REPORT_TYPE
;
600 r_count
= data
->reportCount
[ReportType
];
606 for (i
= 0; i
< r_count
; i
++)
609 for (j
= 0; j
< report
[i
].elementCount
; j
++)
611 if (elems
[report
[i
].elementIdx
+ j
].ElementType
== ButtonElement
&&
612 (UsagePage
== 0 || elems
[report
[i
].elementIdx
+ j
].caps
.button
.UsagePage
== UsagePage
))
614 if (elems
[report
[i
].elementIdx
+ j
].caps
.button
.IsRange
)
615 count
+= (elems
[report
[i
].elementIdx
+ j
].caps
.button
.u
.Range
.UsageMax
-
616 elems
[report
[i
].elementIdx
+ j
].caps
.button
.u
.Range
.UsageMin
) + 1;
625 NTSTATUS WINAPI
HidP_SetUsageValue(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
626 USAGE Usage
, ULONG UsageValue
, PHIDP_PREPARSED_DATA PreparsedData
,
627 CHAR
*Report
, ULONG ReportLength
)
629 WINE_HID_ELEMENT element
;
632 TRACE("(%i, %x, %i, %i, %i, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, Usage
, UsageValue
,
633 PreparsedData
, Report
, ReportLength
);
635 rc
= find_usage(ReportType
, UsagePage
, LinkCollection
, Usage
, PreparsedData
, Report
, ValueElement
, &element
);
637 if (rc
== HIDP_STATUS_SUCCESS
)
639 return set_report_data((BYTE
*)Report
, ReportLength
,
640 element
.valueStartBit
, element
.bitCount
, UsageValue
);
647 NTSTATUS WINAPI
HidP_SetUsages(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
648 PUSAGE UsageList
, PULONG UsageLength
, PHIDP_PREPARSED_DATA PreparsedData
,
649 PCHAR Report
, ULONG ReportLength
)
651 WINE_HID_ELEMENT element
;
655 TRACE("(%i, %x, %i, %p, %p, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, UsageList
,
656 UsageLength
, PreparsedData
, Report
, ReportLength
);
658 for (i
= 0; i
< *UsageLength
; i
++)
660 rc
= find_usage(ReportType
, UsagePage
, LinkCollection
,
661 UsageList
[i
], PreparsedData
, Report
, ButtonElement
, &element
);
662 if (rc
== HIDP_STATUS_SUCCESS
)
664 rc
= set_report_data((BYTE
*)Report
, ReportLength
,
665 element
.valueStartBit
, element
.bitCount
, -1);
668 if (rc
!= HIDP_STATUS_SUCCESS
)
675 return HIDP_STATUS_SUCCESS
;
679 NTSTATUS WINAPI
HidP_TranslateUsagesToI8042ScanCodes(USAGE
*ChangedUsageList
,
680 ULONG UsageListLength
, HIDP_KEYBOARD_DIRECTION KeyAction
,
681 HIDP_KEYBOARD_MODIFIER_STATE
*ModifierState
,
682 PHIDP_INSERT_SCANCODES InsertCodesProcedure
, VOID
*InsertCodesContext
)
684 FIXME("stub: %p, %i, %i, %p, %p, %p\n", ChangedUsageList
, UsageListLength
,
685 KeyAction
, ModifierState
, InsertCodesProcedure
, InsertCodesContext
);
687 return STATUS_NOT_IMPLEMENTED
;
690 NTSTATUS WINAPI
HidP_GetSpecificButtonCaps(HIDP_REPORT_TYPE ReportType
,
691 USAGE UsagePage
, USHORT LinkCollection
, USAGE Usage
,
692 HIDP_BUTTON_CAPS
*ButtonCaps
, USHORT
*ButtonCapsLength
, PHIDP_PREPARSED_DATA PreparsedData
)
694 WINE_HIDP_PREPARSED_DATA
*data
= (WINE_HIDP_PREPARSED_DATA
*)PreparsedData
;
695 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
696 WINE_HID_REPORT
*report
= NULL
;
697 USHORT b_count
= 0, r_count
= 0;
700 TRACE("(%i, 0x%x, %i, 0x%x, %p %p %p)\n", ReportType
, UsagePage
, LinkCollection
,
701 Usage
, ButtonCaps
, ButtonCapsLength
, PreparsedData
);
703 if (data
->magic
!= HID_MAGIC
)
704 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
709 b_count
= data
->caps
.NumberInputButtonCaps
;
710 report
= HID_INPUT_REPORTS(data
);
713 b_count
= data
->caps
.NumberOutputButtonCaps
;
714 report
= HID_OUTPUT_REPORTS(data
);
717 b_count
= data
->caps
.NumberFeatureButtonCaps
;
718 report
= HID_FEATURE_REPORTS(data
);
721 return HIDP_STATUS_INVALID_REPORT_TYPE
;
723 r_count
= data
->reportCount
[ReportType
];
725 if (!r_count
|| !b_count
)
727 *ButtonCapsLength
= 0;
728 return HIDP_STATUS_SUCCESS
;
731 b_count
= min(b_count
, *ButtonCapsLength
);
734 for (j
= 0; j
< r_count
&& u
< b_count
; j
++)
736 for (i
= 0; i
< report
[j
].elementCount
&& u
< b_count
; i
++)
738 if (elems
[report
[j
].elementIdx
+ i
].ElementType
== ButtonElement
&&
739 (UsagePage
== 0 || UsagePage
== elems
[report
[j
].elementIdx
+ i
].caps
.button
.UsagePage
) &&
740 (LinkCollection
== 0 || LinkCollection
== elems
[report
[j
].elementIdx
+ i
].caps
.button
.LinkCollection
) &&
742 (!elems
[report
[j
].elementIdx
+ i
].caps
.button
.IsRange
&&
743 Usage
== elems
[report
[j
].elementIdx
+ i
].caps
.button
.u
.NotRange
.Usage
)) ||
744 (elems
[report
[j
].elementIdx
+ i
].caps
.button
.IsRange
&&
745 Usage
>= elems
[report
[j
].elementIdx
+ i
].caps
.button
.u
.Range
.UsageMin
&&
746 Usage
<= elems
[report
[j
].elementIdx
+ i
].caps
.button
.u
.Range
.UsageMax
)))
748 ButtonCaps
[u
++] = elems
[report
[j
].elementIdx
+ i
].caps
.button
;
752 TRACE("Matched %i usages\n", u
);
754 *ButtonCapsLength
= u
;
756 return HIDP_STATUS_SUCCESS
;
760 NTSTATUS WINAPI
HidP_GetSpecificValueCaps(HIDP_REPORT_TYPE ReportType
,
761 USAGE UsagePage
, USHORT LinkCollection
, USAGE Usage
,
762 HIDP_VALUE_CAPS
*ValueCaps
, USHORT
*ValueCapsLength
, PHIDP_PREPARSED_DATA PreparsedData
)
764 WINE_HIDP_PREPARSED_DATA
*data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
765 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
766 WINE_HID_REPORT
*report
= NULL
;
767 USHORT v_count
= 0, r_count
= 0;
770 TRACE("(%i, 0x%x, %i, 0x%x, %p %p %p)\n", ReportType
, UsagePage
, LinkCollection
,
771 Usage
, ValueCaps
, ValueCapsLength
, PreparsedData
);
773 if (data
->magic
!= HID_MAGIC
)
774 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
779 v_count
= data
->caps
.NumberInputValueCaps
;
780 report
= HID_INPUT_REPORTS(data
);
783 v_count
= data
->caps
.NumberOutputValueCaps
;
784 report
= HID_OUTPUT_REPORTS(data
);
787 v_count
= data
->caps
.NumberFeatureValueCaps
;
788 report
= HID_FEATURE_REPORTS(data
);
791 return HIDP_STATUS_INVALID_REPORT_TYPE
;
793 r_count
= data
->reportCount
[ReportType
];
795 if (!r_count
|| !v_count
)
797 *ValueCapsLength
= 0;
798 return HIDP_STATUS_SUCCESS
;
801 v_count
= min(v_count
, *ValueCapsLength
);
804 for (j
= 0; j
< r_count
&& u
< v_count
; j
++)
806 for (i
= 0; i
< report
[j
].elementCount
&& u
< v_count
; i
++)
808 if (elems
[report
[j
].elementIdx
+ i
].ElementType
== ValueElement
&&
809 (UsagePage
== 0 || UsagePage
== elems
[report
[j
].elementIdx
+ i
].caps
.value
.UsagePage
) &&
810 (LinkCollection
== 0 || LinkCollection
== elems
[report
[j
].elementIdx
+ i
].caps
.value
.LinkCollection
) &&
811 (Usage
== 0 || Usage
== elems
[report
[j
].elementIdx
+ i
].caps
.value
.u
.NotRange
.Usage
))
813 ValueCaps
[u
++] = elems
[report
[j
].elementIdx
+ i
].caps
.value
;
817 TRACE("Matched %i usages\n", u
);
819 *ValueCapsLength
= u
;
821 return HIDP_STATUS_SUCCESS
;
824 NTSTATUS WINAPI
HidP_GetUsagesEx(HIDP_REPORT_TYPE ReportType
, USHORT LinkCollection
, USAGE_AND_PAGE
*ButtonList
,
825 ULONG
*UsageLength
, PHIDP_PREPARSED_DATA PreparsedData
, CHAR
*Report
, ULONG ReportLength
)
827 WINE_HIDP_PREPARSED_DATA
*data
= (WINE_HIDP_PREPARSED_DATA
*)PreparsedData
;
828 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
829 WINE_HID_REPORT
*report
= NULL
;
830 USHORT b_count
= 0, r_count
= 0;
834 TRACE("(%i, %i, %p, %p(%i), %p, %p, %i)\n", ReportType
, LinkCollection
, ButtonList
,
835 UsageLength
, *UsageLength
, PreparsedData
, Report
, ReportLength
);
837 if (data
->magic
!= HID_MAGIC
)
838 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
843 b_count
= data
->caps
.NumberInputButtonCaps
;
846 b_count
= data
->caps
.NumberOutputButtonCaps
;
849 b_count
= data
->caps
.NumberFeatureButtonCaps
;
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
|| !b_count
)
858 return HIDP_STATUS_USAGE_NOT_FOUND
;
860 if (report
->reportID
&& report
->reportID
!= Report
[0])
861 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
863 for (i
= 0; i
< report
->elementCount
; i
++)
865 if (elems
[report
->elementIdx
+ i
].ElementType
== ButtonElement
)
868 WINE_HID_ELEMENT
*element
= &elems
[report
->elementIdx
+ i
];
869 for (k
=0; k
< element
->bitCount
; k
++)
872 NTSTATUS rc
= get_report_data((BYTE
*)Report
, ReportLength
,
873 element
->valueStartBit
+ k
, 1, &v
);
874 if (rc
!= HIDP_STATUS_SUCCESS
)
878 if (uCount
< *UsageLength
)
880 ButtonList
[uCount
].Usage
= element
->caps
.button
.u
.Range
.UsageMin
+ k
;
881 ButtonList
[uCount
].UsagePage
= element
->caps
.button
.UsagePage
;
889 TRACE("Returning %i usages\n", uCount
);
891 if (*UsageLength
< uCount
)
892 rc
= HIDP_STATUS_BUFFER_TOO_SMALL
;
894 rc
= HIDP_STATUS_SUCCESS
;
896 *UsageLength
= uCount
;
901 ULONG WINAPI
HidP_MaxDataListLength(HIDP_REPORT_TYPE ReportType
, PHIDP_PREPARSED_DATA PreparsedData
)
903 WINE_HIDP_PREPARSED_DATA
*data
= (WINE_HIDP_PREPARSED_DATA
*)PreparsedData
;
904 TRACE("(%i, %p)\n", ReportType
, PreparsedData
);
905 if (data
->magic
!= HID_MAGIC
)
911 return data
->caps
.NumberInputDataIndices
;
913 return data
->caps
.NumberOutputDataIndices
;
915 return data
->caps
.NumberFeatureDataIndices
;
921 NTSTATUS WINAPI
HidP_GetData(HIDP_REPORT_TYPE ReportType
, HIDP_DATA
*DataList
, ULONG
*DataLength
,
922 PHIDP_PREPARSED_DATA PreparsedData
,CHAR
*Report
, ULONG ReportLength
)
924 WINE_HIDP_PREPARSED_DATA
*data
= (WINE_HIDP_PREPARSED_DATA
*)PreparsedData
;
925 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
926 WINE_HID_REPORT
*report
= NULL
;
931 TRACE("(%i, %p, %p(%i), %p, %p, %i)\n", ReportType
, DataList
, DataLength
,
932 DataLength
?*DataLength
:0, PreparsedData
, Report
, ReportLength
);
934 if (data
->magic
!= HID_MAGIC
)
937 if (ReportType
!= HidP_Input
&& ReportType
!= HidP_Output
&& ReportType
!= HidP_Feature
)
938 return HIDP_STATUS_INVALID_REPORT_TYPE
;
940 r_count
= data
->reportCount
[ReportType
];
941 report
= &data
->reports
[data
->reportIdx
[ReportType
][(BYTE
)Report
[0]]];
943 if (!r_count
|| (report
->reportID
&& report
->reportID
!= Report
[0]))
944 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
946 for (i
= 0; i
< report
->elementCount
; i
++)
948 WINE_HID_ELEMENT
*element
= &elems
[report
->elementIdx
+ i
];
949 if (element
->ElementType
== ButtonElement
)
952 for (k
=0; k
< element
->bitCount
; k
++)
955 NTSTATUS rc
= get_report_data((BYTE
*)Report
, ReportLength
,
956 element
->valueStartBit
+ k
, 1, &v
);
957 if (rc
!= HIDP_STATUS_SUCCESS
)
961 if (uCount
< *DataLength
)
963 DataList
[uCount
].DataIndex
= element
->caps
.button
.u
.Range
.DataIndexMin
+ k
;
964 DataList
[uCount
].u
.On
= v
;
972 if (uCount
< *DataLength
)
975 NTSTATUS rc
= get_report_data((BYTE
*)Report
, ReportLength
,
976 element
->valueStartBit
, element
->bitCount
, &v
);
977 if (rc
!= HIDP_STATUS_SUCCESS
)
979 DataList
[uCount
].DataIndex
= element
->caps
.value
.u
.NotRange
.DataIndex
;
980 DataList
[uCount
].u
.RawValue
= v
;
986 if (*DataLength
< uCount
)
987 rc
= HIDP_STATUS_BUFFER_TOO_SMALL
;
989 rc
= HIDP_STATUS_SUCCESS
;
991 *DataLength
= uCount
;
996 NTSTATUS WINAPI
HidP_GetLinkCollectionNodes(HIDP_LINK_COLLECTION_NODE
*LinkCollectionNode
,
997 ULONG
*LinkCollectionNodeLength
, PHIDP_PREPARSED_DATA PreparsedData
)
999 WINE_HIDP_PREPARSED_DATA
*data
= (WINE_HIDP_PREPARSED_DATA
*)PreparsedData
;
1000 WINE_HID_LINK_COLLECTION_NODE
*nodes
= HID_NODES(data
);
1003 TRACE("(%p, %p, %p)\n", LinkCollectionNode
, LinkCollectionNodeLength
, PreparsedData
);
1005 if (*LinkCollectionNodeLength
< data
->caps
.NumberLinkCollectionNodes
)
1006 return HIDP_STATUS_BUFFER_TOO_SMALL
;
1008 for (i
= 0; i
< data
->caps
.NumberLinkCollectionNodes
; ++i
)
1010 LinkCollectionNode
[i
].LinkUsage
= nodes
[i
].LinkUsage
;
1011 LinkCollectionNode
[i
].LinkUsagePage
= nodes
[i
].LinkUsagePage
;
1012 LinkCollectionNode
[i
].Parent
= nodes
[i
].Parent
;
1013 LinkCollectionNode
[i
].NumberOfChildren
= nodes
[i
].NumberOfChildren
;
1014 LinkCollectionNode
[i
].NextSibling
= nodes
[i
].NextSibling
;
1015 LinkCollectionNode
[i
].FirstChild
= nodes
[i
].FirstChild
;
1016 LinkCollectionNode
[i
].CollectionType
= nodes
[i
].CollectionType
;
1017 LinkCollectionNode
[i
].IsAlias
= nodes
[i
].IsAlias
;
1019 *LinkCollectionNodeLength
= data
->caps
.NumberLinkCollectionNodes
;
1021 return HIDP_STATUS_SUCCESS
;