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 NONAMELESSUNION
27 #define WIN32_NO_STATUS
35 #include "ddk/hidpi.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(hidp
);
41 static NTSTATUS
get_report_data(BYTE
*report
, INT reportLength
, INT startBit
, INT valueSize
, PULONG value
)
44 if ((startBit
+ valueSize
) / 8 > reportLength
)
45 return HIDP_STATUS_INVALID_REPORT_LENGTH
;
49 ULONG byte_index
= startBit
/ 8;
50 ULONG bit_index
= startBit
- (byte_index
* 8);
51 INT mask
= (1 << bit_index
);
52 *value
= !!(report
[byte_index
] & mask
);
56 ULONG remaining_bits
= valueSize
;
57 ULONG byte_index
= startBit
/ 8;
58 ULONG bit_index
= startBit
% 8;
61 while (remaining_bits
)
63 ULONG copy_bits
= 8 - bit_index
;
64 if (remaining_bits
< copy_bits
)
65 copy_bits
= remaining_bits
;
67 data
|= ((report
[byte_index
] >> bit_index
) & ((2 << copy_bits
) - 1)) << shift
;
72 remaining_bits
-= copy_bits
;
76 return HIDP_STATUS_SUCCESS
;
79 static NTSTATUS
set_report_data(BYTE
*report
, INT reportLength
, INT startBit
, INT valueSize
, ULONG value
)
81 if ((startBit
+ valueSize
) / 8 > reportLength
)
82 return HIDP_STATUS_INVALID_REPORT_LENGTH
;
86 ULONG byte_index
= startBit
/ 8;
87 ULONG bit_index
= startBit
- (byte_index
* 8);
89 report
[byte_index
] |= (1 << bit_index
);
91 report
[byte_index
] &= ~(1 << bit_index
);
95 ULONG byte_index
= (startBit
+ valueSize
- 1) / 8;
97 ULONG remainingBits
= valueSize
;
100 BYTE subvalue
= data
& 0xff;
104 if (remainingBits
>= 8)
106 report
[byte_index
] = subvalue
;
110 else if (remainingBits
> 0)
112 BYTE mask
= (0xff << (8-remainingBits
)) & subvalue
;
113 report
[byte_index
] |= mask
;
118 return HIDP_STATUS_SUCCESS
;
122 NTSTATUS WINAPI
HidP_GetButtonCaps(HIDP_REPORT_TYPE ReportType
, PHIDP_BUTTON_CAPS ButtonCaps
,
123 PUSHORT ButtonCapsLength
, PHIDP_PREPARSED_DATA PreparsedData
)
125 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
126 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
127 WINE_HID_REPORT
*report
= NULL
;
128 USHORT b_count
= 0, r_count
= 0;
131 TRACE("(%i, %p, %p, %p)\n",ReportType
, ButtonCaps
, ButtonCapsLength
, PreparsedData
);
133 if (data
->magic
!= HID_MAGIC
)
134 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
139 b_count
= data
->caps
.NumberInputButtonCaps
;
140 report
= HID_INPUT_REPORTS(data
);
143 b_count
= data
->caps
.NumberOutputButtonCaps
;
144 report
= HID_OUTPUT_REPORTS(data
);
147 b_count
= data
->caps
.NumberFeatureButtonCaps
;
148 report
= HID_FEATURE_REPORTS(data
);
151 return HIDP_STATUS_INVALID_REPORT_TYPE
;
153 r_count
= data
->reportCount
[ReportType
];
155 if (!r_count
|| !b_count
)
157 *ButtonCapsLength
= 0;
158 return HIDP_STATUS_SUCCESS
;
161 b_count
= min(b_count
, *ButtonCapsLength
);
164 for (j
= 0; j
< r_count
&& u
< b_count
; j
++)
166 for (i
= 0; i
< report
[j
].elementCount
&& u
< b_count
; i
++)
168 if (elems
[report
[j
].elementIdx
+ i
].ElementType
== ButtonElement
)
169 ButtonCaps
[u
++] = elems
[report
[j
].elementIdx
+ i
].caps
.button
;
173 *ButtonCapsLength
= b_count
;
174 return HIDP_STATUS_SUCCESS
;
178 NTSTATUS WINAPI
HidP_GetCaps(PHIDP_PREPARSED_DATA PreparsedData
,
179 PHIDP_CAPS Capabilities
)
181 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
183 TRACE("(%p, %p)\n",PreparsedData
, Capabilities
);
185 if (data
->magic
!= HID_MAGIC
)
186 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
188 *Capabilities
= data
->caps
;
190 return HIDP_STATUS_SUCCESS
;
193 static NTSTATUS
find_usage(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
194 USAGE Usage
, PHIDP_PREPARSED_DATA PreparsedData
, PCHAR Report
,
195 WINE_ELEMENT_TYPE ElementType
, WINE_HID_ELEMENT
*element
)
197 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
198 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
199 WINE_HID_REPORT
*report
= NULL
;
200 USHORT v_count
= 0, r_count
= 0;
203 TRACE("(%i, %x, %i, %i, %p, %p)\n", ReportType
, UsagePage
, LinkCollection
, Usage
,
204 PreparsedData
, Report
);
206 if (data
->magic
!= HID_MAGIC
)
207 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
211 v_count
= data
->caps
.NumberInputValueCaps
;
214 v_count
= data
->caps
.NumberOutputValueCaps
;
217 v_count
= data
->caps
.NumberFeatureValueCaps
;
220 return HIDP_STATUS_INVALID_REPORT_TYPE
;
222 r_count
= data
->reportCount
[ReportType
];
223 report
= &data
->reports
[data
->reportIdx
[ReportType
][(BYTE
)Report
[0]]];
225 if (!r_count
|| !v_count
)
226 return HIDP_STATUS_USAGE_NOT_FOUND
;
228 if (report
->reportID
&& report
->reportID
!= Report
[0])
229 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
231 for (i
= 0; i
< report
->elementCount
; i
++)
233 HIDP_VALUE_CAPS
*value
= &elems
[report
->elementIdx
+ i
].caps
.value
;
235 if (elems
[report
->elementIdx
+ i
].ElementType
!= ElementType
||
236 value
->UsagePage
!= UsagePage
)
239 if (value
->IsRange
&& value
->u
.Range
.UsageMin
<= Usage
&& Usage
<= value
->u
.Range
.UsageMax
)
241 *element
= elems
[report
->elementIdx
+ i
];
242 element
->valueStartBit
+= value
->BitSize
* (Usage
- value
->u
.Range
.UsageMin
);
243 element
->bitCount
= elems
[report
->elementIdx
+ i
].ElementType
== ValueElement
? value
->BitSize
: 1;
244 return HIDP_STATUS_SUCCESS
;
246 else if (value
->u
.NotRange
.Usage
== Usage
)
248 *element
= elems
[report
->elementIdx
+ i
];
249 element
->bitCount
= elems
[report
->elementIdx
+ i
].ElementType
== ValueElement
? value
->BitSize
: 1;
250 return HIDP_STATUS_SUCCESS
;
254 return HIDP_STATUS_USAGE_NOT_FOUND
;
257 static LONG
sign_extend(ULONG value
, const WINE_HID_ELEMENT
*element
)
259 UINT bit_count
= element
->bitCount
;
261 if ((value
& (1 << (bit_count
- 1)))
262 && element
->ElementType
== ValueElement
263 && element
->caps
.value
.LogicalMin
< 0)
265 value
-= (1 << bit_count
);
270 static LONG
logical_to_physical(LONG value
, const WINE_HID_ELEMENT
*element
)
272 if (element
->caps
.value
.PhysicalMin
|| element
->caps
.value
.PhysicalMax
)
274 value
= (((ULONGLONG
)(value
- element
->caps
.value
.LogicalMin
)
275 * (element
->caps
.value
.PhysicalMax
- element
->caps
.value
.PhysicalMin
))
276 / (element
->caps
.value
.LogicalMax
- element
->caps
.value
.LogicalMin
))
277 + element
->caps
.value
.PhysicalMin
;
282 NTSTATUS WINAPI
HidP_GetScaledUsageValue(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
,
283 USHORT LinkCollection
, USAGE Usage
, PLONG UsageValue
,
284 PHIDP_PREPARSED_DATA PreparsedData
, PCHAR Report
, ULONG ReportLength
)
287 WINE_HID_ELEMENT element
;
288 TRACE("(%i, %x, %i, %i, %p, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, Usage
, UsageValue
,
289 PreparsedData
, Report
, ReportLength
);
291 rc
= find_usage(ReportType
, UsagePage
, LinkCollection
, Usage
, PreparsedData
, Report
, ValueElement
, &element
);
293 if (rc
== HIDP_STATUS_SUCCESS
)
296 rc
= get_report_data((BYTE
*)Report
, ReportLength
,
297 element
.valueStartBit
, element
.bitCount
, &rawValue
);
298 if (rc
!= HIDP_STATUS_SUCCESS
)
300 *UsageValue
= logical_to_physical(sign_extend(rawValue
, &element
), &element
);
307 NTSTATUS WINAPI
HidP_GetUsageValue(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
308 USAGE Usage
, PULONG UsageValue
, PHIDP_PREPARSED_DATA PreparsedData
,
309 PCHAR Report
, ULONG ReportLength
)
311 WINE_HID_ELEMENT element
;
314 TRACE("(%i, %x, %i, %i, %p, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, Usage
, UsageValue
,
315 PreparsedData
, Report
, ReportLength
);
317 rc
= find_usage(ReportType
, UsagePage
, LinkCollection
, Usage
, PreparsedData
, Report
, ValueElement
, &element
);
319 if (rc
== HIDP_STATUS_SUCCESS
)
321 return get_report_data((BYTE
*)Report
, ReportLength
,
322 element
.valueStartBit
, element
.bitCount
, UsageValue
);
329 NTSTATUS WINAPI
HidP_GetUsages(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
330 PUSAGE UsageList
, PULONG UsageLength
, PHIDP_PREPARSED_DATA PreparsedData
,
331 PCHAR Report
, ULONG ReportLength
)
333 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
334 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
335 WINE_HID_REPORT
*report
= NULL
;
337 USHORT b_count
= 0, r_count
= 0;
340 TRACE("(%i, %x, %i, %p, %p, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, UsageList
,
341 UsageLength
, PreparsedData
, Report
, ReportLength
);
343 if (data
->magic
!= HID_MAGIC
)
346 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
352 b_count
= data
->caps
.NumberInputButtonCaps
;
355 b_count
= data
->caps
.NumberOutputButtonCaps
;
358 b_count
= data
->caps
.NumberFeatureButtonCaps
;
361 return HIDP_STATUS_INVALID_REPORT_TYPE
;
363 r_count
= data
->reportCount
[ReportType
];
364 report
= &data
->reports
[data
->reportIdx
[ReportType
][(BYTE
)Report
[0]]];
366 if (!r_count
|| !b_count
)
367 return HIDP_STATUS_USAGE_NOT_FOUND
;
369 if (report
->reportID
&& report
->reportID
!= Report
[0])
370 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
373 for (i
= 0; i
< report
->elementCount
&& uCount
< *UsageLength
; i
++)
375 if (elems
[report
->elementIdx
+ i
].ElementType
== ButtonElement
&&
376 elems
[report
->elementIdx
+ i
].caps
.button
.UsagePage
== UsagePage
)
379 WINE_HID_ELEMENT
*element
= &elems
[report
->elementIdx
+ i
];
380 for (k
=0; k
< element
->bitCount
; k
++)
383 NTSTATUS rc
= get_report_data((BYTE
*)Report
, ReportLength
,
384 element
->valueStartBit
+ k
, 1, &v
);
385 if (rc
!= HIDP_STATUS_SUCCESS
)
390 if (uCount
== *UsageLength
)
391 return HIDP_STATUS_BUFFER_TOO_SMALL
;
392 UsageList
[uCount
] = element
->caps
.button
.u
.Range
.UsageMin
+ k
;
399 *UsageLength
= uCount
;
402 return HIDP_STATUS_USAGE_NOT_FOUND
;
404 return HIDP_STATUS_SUCCESS
;
408 NTSTATUS WINAPI
HidP_GetValueCaps(HIDP_REPORT_TYPE ReportType
, PHIDP_VALUE_CAPS ValueCaps
,
409 PUSHORT ValueCapsLength
, PHIDP_PREPARSED_DATA PreparsedData
)
411 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
412 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
413 WINE_HID_REPORT
*report
= NULL
;
414 USHORT v_count
= 0, r_count
= 0;
417 TRACE("(%i, %p, %p, %p)\n", ReportType
, ValueCaps
, ValueCapsLength
, PreparsedData
);
419 if (data
->magic
!= HID_MAGIC
)
420 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
425 v_count
= data
->caps
.NumberInputValueCaps
;
426 report
= HID_INPUT_REPORTS(data
);
429 v_count
= data
->caps
.NumberOutputValueCaps
;
430 report
= HID_OUTPUT_REPORTS(data
);
433 v_count
= data
->caps
.NumberFeatureValueCaps
;
434 report
= HID_FEATURE_REPORTS(data
);
437 return HIDP_STATUS_INVALID_REPORT_TYPE
;
439 r_count
= data
->reportCount
[ReportType
];
441 if (!r_count
|| !v_count
)
443 *ValueCapsLength
= 0;
444 return HIDP_STATUS_SUCCESS
;
447 v_count
= min(v_count
, *ValueCapsLength
);
450 for (j
= 0; j
< r_count
&& u
< v_count
; j
++)
452 for (i
= 0; i
< report
[j
].elementCount
&& u
< v_count
; i
++)
454 if (elems
[report
->elementIdx
+ i
].ElementType
== ValueElement
)
455 ValueCaps
[u
++] = elems
[report
->elementIdx
+ i
].caps
.value
;
459 *ValueCapsLength
= v_count
;
460 return HIDP_STATUS_SUCCESS
;
463 NTSTATUS WINAPI
HidP_InitializeReportForID(HIDP_REPORT_TYPE ReportType
, UCHAR ReportID
,
464 PHIDP_PREPARSED_DATA PreparsedData
, PCHAR Report
,
468 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
469 WINE_HID_REPORT
*report
= NULL
;
472 TRACE("(%i, %i, %p, %p, %i)\n",ReportType
, ReportID
, PreparsedData
, Report
, ReportLength
);
474 if (data
->magic
!= HID_MAGIC
)
475 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
480 size
= data
->caps
.InputReportByteLength
;
483 size
= data
->caps
.OutputReportByteLength
;
486 size
= data
->caps
.FeatureReportByteLength
;
489 return HIDP_STATUS_INVALID_REPORT_TYPE
;
491 r_count
= data
->reportCount
[ReportType
];
492 report
= &data
->reports
[data
->reportIdx
[ReportType
][(BYTE
)Report
[0]]];
494 if (!r_count
|| !size
)
495 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
497 if (size
!= ReportLength
)
498 return HIDP_STATUS_INVALID_REPORT_LENGTH
;
500 if (report
->reportID
&& report
->reportID
!= Report
[0])
501 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
503 ZeroMemory(Report
, size
);
504 Report
[0] = ReportID
;
505 return HIDP_STATUS_SUCCESS
;
508 ULONG WINAPI
HidP_MaxUsageListLength(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, PHIDP_PREPARSED_DATA PreparsedData
)
510 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
511 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
512 WINE_HID_REPORT
*report
= NULL
;
517 TRACE("(%i, %x, %p)\n", ReportType
, UsagePage
, PreparsedData
);
519 if (data
->magic
!= HID_MAGIC
)
525 report
= HID_INPUT_REPORTS(data
);
528 report
= HID_OUTPUT_REPORTS(data
);
531 report
= HID_FEATURE_REPORTS(data
);
534 return HIDP_STATUS_INVALID_REPORT_TYPE
;
536 r_count
= data
->reportCount
[ReportType
];
542 for (i
= 0; i
< r_count
; i
++)
545 for (j
= 0; j
< report
[i
].elementCount
; j
++)
547 if (elems
[report
[i
].elementIdx
+ j
].ElementType
== ButtonElement
&&
548 (UsagePage
== 0 || elems
[report
[i
].elementIdx
+ j
].caps
.button
.UsagePage
== UsagePage
))
550 if (elems
[report
[i
].elementIdx
+ j
].caps
.button
.IsRange
)
551 count
+= (elems
[report
[i
].elementIdx
+ j
].caps
.button
.u
.Range
.UsageMax
-
552 elems
[report
[i
].elementIdx
+ j
].caps
.button
.u
.Range
.UsageMin
) + 1;
561 NTSTATUS WINAPI
HidP_SetUsageValue(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
562 USAGE Usage
, ULONG UsageValue
, PHIDP_PREPARSED_DATA PreparsedData
,
563 CHAR
*Report
, ULONG ReportLength
)
565 WINE_HID_ELEMENT element
;
568 TRACE("(%i, %x, %i, %i, %i, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, Usage
, UsageValue
,
569 PreparsedData
, Report
, ReportLength
);
571 rc
= find_usage(ReportType
, UsagePage
, LinkCollection
, Usage
, PreparsedData
, Report
, ValueElement
, &element
);
573 if (rc
== HIDP_STATUS_SUCCESS
)
575 return set_report_data((BYTE
*)Report
, ReportLength
,
576 element
.valueStartBit
, element
.bitCount
, UsageValue
);
583 NTSTATUS WINAPI
HidP_SetUsages(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
584 PUSAGE UsageList
, PULONG UsageLength
, PHIDP_PREPARSED_DATA PreparsedData
,
585 PCHAR Report
, ULONG ReportLength
)
587 WINE_HID_ELEMENT element
;
591 TRACE("(%i, %x, %i, %p, %p, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, UsageList
,
592 UsageLength
, PreparsedData
, Report
, ReportLength
);
594 for (i
= 0; i
< *UsageLength
; i
++)
596 rc
= find_usage(ReportType
, UsagePage
, LinkCollection
,
597 UsageList
[i
], PreparsedData
, Report
, ButtonElement
, &element
);
598 if (rc
== HIDP_STATUS_SUCCESS
)
600 rc
= set_report_data((BYTE
*)Report
, ReportLength
,
601 element
.valueStartBit
, element
.bitCount
, -1);
604 if (rc
!= HIDP_STATUS_SUCCESS
)
611 return HIDP_STATUS_SUCCESS
;
615 NTSTATUS WINAPI
HidP_TranslateUsagesToI8042ScanCodes(USAGE
*ChangedUsageList
,
616 ULONG UsageListLength
, HIDP_KEYBOARD_DIRECTION KeyAction
,
617 HIDP_KEYBOARD_MODIFIER_STATE
*ModifierState
,
618 PHIDP_INSERT_SCANCODES InsertCodesProcedure
, VOID
*InsertCodesContext
)
620 FIXME("stub: %p, %i, %i, %p, %p, %p\n", ChangedUsageList
, UsageListLength
,
621 KeyAction
, ModifierState
, InsertCodesProcedure
, InsertCodesContext
);
623 return STATUS_NOT_IMPLEMENTED
;
626 NTSTATUS WINAPI
HidP_GetSpecificButtonCaps(HIDP_REPORT_TYPE ReportType
,
627 USAGE UsagePage
, USHORT LinkCollection
, USAGE Usage
,
628 HIDP_BUTTON_CAPS
*ButtonCaps
, USHORT
*ButtonCapsLength
, PHIDP_PREPARSED_DATA PreparsedData
)
630 WINE_HIDP_PREPARSED_DATA
*data
= (WINE_HIDP_PREPARSED_DATA
*)PreparsedData
;
631 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
632 WINE_HID_REPORT
*report
= NULL
;
633 USHORT b_count
= 0, r_count
= 0;
636 TRACE("(%i, 0x%x, %i, 0x%x, %p %p %p)\n", ReportType
, UsagePage
, LinkCollection
,
637 Usage
, ButtonCaps
, ButtonCapsLength
, PreparsedData
);
639 if (data
->magic
!= HID_MAGIC
)
640 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
645 b_count
= data
->caps
.NumberInputButtonCaps
;
646 report
= HID_INPUT_REPORTS(data
);
649 b_count
= data
->caps
.NumberOutputButtonCaps
;
650 report
= HID_OUTPUT_REPORTS(data
);
653 b_count
= data
->caps
.NumberFeatureButtonCaps
;
654 report
= HID_FEATURE_REPORTS(data
);
657 return HIDP_STATUS_INVALID_REPORT_TYPE
;
659 r_count
= data
->reportCount
[ReportType
];
661 if (!r_count
|| !b_count
)
663 *ButtonCapsLength
= 0;
664 return HIDP_STATUS_SUCCESS
;
667 b_count
= min(b_count
, *ButtonCapsLength
);
670 for (j
= 0; j
< r_count
&& u
< b_count
; j
++)
672 for (i
= 0; i
< report
[j
].elementCount
&& u
< b_count
; i
++)
674 if (elems
[report
[j
].elementIdx
+ i
].ElementType
== ButtonElement
&&
675 (UsagePage
== 0 || UsagePage
== elems
[report
[j
].elementIdx
+ i
].caps
.button
.UsagePage
) &&
676 (LinkCollection
== 0 || LinkCollection
== elems
[report
[j
].elementIdx
+ i
].caps
.button
.LinkCollection
) &&
678 (!elems
[report
[j
].elementIdx
+ i
].caps
.button
.IsRange
&&
679 Usage
== elems
[report
[j
].elementIdx
+ i
].caps
.button
.u
.NotRange
.Usage
)) ||
680 (elems
[report
[j
].elementIdx
+ i
].caps
.button
.IsRange
&&
681 Usage
>= elems
[report
[j
].elementIdx
+ i
].caps
.button
.u
.Range
.UsageMin
&&
682 Usage
<= elems
[report
[j
].elementIdx
+ i
].caps
.button
.u
.Range
.UsageMax
)))
684 ButtonCaps
[u
++] = elems
[report
[j
].elementIdx
+ i
].caps
.button
;
688 TRACE("Matched %i usages\n", u
);
690 *ButtonCapsLength
= u
;
692 return HIDP_STATUS_SUCCESS
;
696 NTSTATUS WINAPI
HidP_GetSpecificValueCaps(HIDP_REPORT_TYPE ReportType
,
697 USAGE UsagePage
, USHORT LinkCollection
, USAGE Usage
,
698 HIDP_VALUE_CAPS
*ValueCaps
, USHORT
*ValueCapsLength
, PHIDP_PREPARSED_DATA PreparsedData
)
700 WINE_HIDP_PREPARSED_DATA
*data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
701 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
702 WINE_HID_REPORT
*report
= NULL
;
703 USHORT v_count
= 0, r_count
= 0;
706 TRACE("(%i, 0x%x, %i, 0x%x, %p %p %p)\n", ReportType
, UsagePage
, LinkCollection
,
707 Usage
, ValueCaps
, ValueCapsLength
, PreparsedData
);
709 if (data
->magic
!= HID_MAGIC
)
710 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
715 v_count
= data
->caps
.NumberInputValueCaps
;
716 report
= HID_INPUT_REPORTS(data
);
719 v_count
= data
->caps
.NumberOutputValueCaps
;
720 report
= HID_OUTPUT_REPORTS(data
);
723 v_count
= data
->caps
.NumberFeatureValueCaps
;
724 report
= HID_FEATURE_REPORTS(data
);
727 return HIDP_STATUS_INVALID_REPORT_TYPE
;
729 r_count
= data
->reportCount
[ReportType
];
731 if (!r_count
|| !v_count
)
733 *ValueCapsLength
= 0;
734 return HIDP_STATUS_SUCCESS
;
737 v_count
= min(v_count
, *ValueCapsLength
);
740 for (j
= 0; j
< r_count
&& u
< v_count
; j
++)
742 for (i
= 0; i
< report
[j
].elementCount
&& u
< v_count
; i
++)
744 if (elems
[report
[j
].elementIdx
+ i
].ElementType
== ValueElement
&&
745 (UsagePage
== 0 || UsagePage
== elems
[report
[j
].elementIdx
+ i
].caps
.value
.UsagePage
) &&
746 (LinkCollection
== 0 || LinkCollection
== elems
[report
[j
].elementIdx
+ i
].caps
.value
.LinkCollection
) &&
747 (Usage
== 0 || Usage
== elems
[report
[j
].elementIdx
+ i
].caps
.value
.u
.NotRange
.Usage
))
749 ValueCaps
[u
++] = elems
[report
[j
].elementIdx
+ i
].caps
.value
;
753 TRACE("Matched %i usages\n", u
);
755 *ValueCapsLength
= u
;
757 return HIDP_STATUS_SUCCESS
;
760 NTSTATUS WINAPI
HidP_GetUsagesEx(HIDP_REPORT_TYPE ReportType
, USHORT LinkCollection
, USAGE_AND_PAGE
*ButtonList
,
761 ULONG
*UsageLength
, PHIDP_PREPARSED_DATA PreparsedData
, CHAR
*Report
, ULONG ReportLength
)
763 WINE_HIDP_PREPARSED_DATA
*data
= (WINE_HIDP_PREPARSED_DATA
*)PreparsedData
;
764 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
765 WINE_HID_REPORT
*report
= NULL
;
766 USHORT b_count
= 0, r_count
= 0;
770 TRACE("(%i, %i, %p, %p(%i), %p, %p, %i)\n", ReportType
, LinkCollection
, ButtonList
,
771 UsageLength
, *UsageLength
, PreparsedData
, Report
, ReportLength
);
773 if (data
->magic
!= HID_MAGIC
)
774 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
779 b_count
= data
->caps
.NumberInputButtonCaps
;
782 b_count
= data
->caps
.NumberOutputButtonCaps
;
785 b_count
= data
->caps
.NumberFeatureButtonCaps
;
788 return HIDP_STATUS_INVALID_REPORT_TYPE
;
790 r_count
= data
->reportCount
[ReportType
];
791 report
= &data
->reports
[data
->reportIdx
[ReportType
][(BYTE
)Report
[0]]];
793 if (!r_count
|| !b_count
)
794 return HIDP_STATUS_USAGE_NOT_FOUND
;
796 if (report
->reportID
&& report
->reportID
!= Report
[0])
797 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
799 for (i
= 0; i
< report
->elementCount
; i
++)
801 if (elems
[report
->elementIdx
+ i
].ElementType
== ButtonElement
)
804 WINE_HID_ELEMENT
*element
= &elems
[report
->elementIdx
+ i
];
805 for (k
=0; k
< element
->bitCount
; k
++)
808 NTSTATUS rc
= get_report_data((BYTE
*)Report
, ReportLength
,
809 element
->valueStartBit
+ k
, 1, &v
);
810 if (rc
!= HIDP_STATUS_SUCCESS
)
814 if (uCount
< *UsageLength
)
816 ButtonList
[uCount
].Usage
= element
->caps
.button
.u
.Range
.UsageMin
+ k
;
817 ButtonList
[uCount
].UsagePage
= element
->caps
.button
.UsagePage
;
825 TRACE("Returning %i usages\n", uCount
);
827 if (*UsageLength
< uCount
)
828 rc
= HIDP_STATUS_BUFFER_TOO_SMALL
;
830 rc
= HIDP_STATUS_SUCCESS
;
832 *UsageLength
= uCount
;
837 ULONG WINAPI
HidP_MaxDataListLength(HIDP_REPORT_TYPE ReportType
, PHIDP_PREPARSED_DATA PreparsedData
)
839 WINE_HIDP_PREPARSED_DATA
*data
= (WINE_HIDP_PREPARSED_DATA
*)PreparsedData
;
840 TRACE("(%i, %p)\n", ReportType
, PreparsedData
);
841 if (data
->magic
!= HID_MAGIC
)
847 return data
->caps
.NumberInputDataIndices
;
849 return data
->caps
.NumberOutputDataIndices
;
851 return data
->caps
.NumberFeatureDataIndices
;
857 NTSTATUS WINAPI
HidP_GetData(HIDP_REPORT_TYPE ReportType
, HIDP_DATA
*DataList
, ULONG
*DataLength
,
858 PHIDP_PREPARSED_DATA PreparsedData
,CHAR
*Report
, ULONG ReportLength
)
860 WINE_HIDP_PREPARSED_DATA
*data
= (WINE_HIDP_PREPARSED_DATA
*)PreparsedData
;
861 WINE_HID_ELEMENT
*elems
= HID_ELEMS(data
);
862 WINE_HID_REPORT
*report
= NULL
;
867 TRACE("(%i, %p, %p(%i), %p, %p, %i)\n", ReportType
, DataList
, DataLength
,
868 DataLength
?*DataLength
:0, PreparsedData
, Report
, ReportLength
);
870 if (data
->magic
!= HID_MAGIC
)
873 if (ReportType
!= HidP_Input
&& ReportType
!= HidP_Output
&& ReportType
!= HidP_Feature
)
874 return HIDP_STATUS_INVALID_REPORT_TYPE
;
876 r_count
= data
->reportCount
[ReportType
];
877 report
= &data
->reports
[data
->reportIdx
[ReportType
][(BYTE
)Report
[0]]];
879 if (!r_count
|| (report
->reportID
&& report
->reportID
!= Report
[0]))
880 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
882 for (i
= 0; i
< report
->elementCount
; i
++)
884 WINE_HID_ELEMENT
*element
= &elems
[report
->elementIdx
+ i
];
885 if (element
->ElementType
== ButtonElement
)
888 for (k
=0; k
< element
->bitCount
; k
++)
891 NTSTATUS rc
= get_report_data((BYTE
*)Report
, ReportLength
,
892 element
->valueStartBit
+ k
, 1, &v
);
893 if (rc
!= HIDP_STATUS_SUCCESS
)
897 if (uCount
< *DataLength
)
899 DataList
[uCount
].DataIndex
= element
->caps
.button
.u
.Range
.DataIndexMin
+ k
;
900 DataList
[uCount
].u
.On
= v
;
908 if (uCount
< *DataLength
)
911 NTSTATUS rc
= get_report_data((BYTE
*)Report
, ReportLength
,
912 element
->valueStartBit
, element
->bitCount
, &v
);
913 if (rc
!= HIDP_STATUS_SUCCESS
)
915 DataList
[uCount
].DataIndex
= element
->caps
.value
.u
.NotRange
.DataIndex
;
916 DataList
[uCount
].u
.RawValue
= v
;
922 if (*DataLength
< uCount
)
923 rc
= HIDP_STATUS_BUFFER_TOO_SMALL
;
925 rc
= HIDP_STATUS_SUCCESS
;
927 *DataLength
= uCount
;