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 byte_index
= (startBit
+ valueSize
- 1) / 8;
58 ULONG remainingBits
= valueSize
;
63 if (remainingBits
>= 8)
65 data
|= report
[byte_index
];
69 else if (remainingBits
> 0)
71 BYTE mask
= ~(0xff << (8-remainingBits
));
72 data
|= report
[byte_index
] & mask
;
78 return HIDP_STATUS_SUCCESS
;
81 NTSTATUS WINAPI
HidP_GetButtonCaps(HIDP_REPORT_TYPE ReportType
, PHIDP_BUTTON_CAPS ButtonCaps
,
82 PUSHORT ButtonCapsLength
, PHIDP_PREPARSED_DATA PreparsedData
)
84 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
85 WINE_HID_REPORT
*report
= NULL
;
86 USHORT b_count
= 0, r_count
= 0;
89 TRACE("(%i, %p, %p, %p)\n",ReportType
, ButtonCaps
, ButtonCapsLength
, PreparsedData
);
91 if (data
->magic
!= HID_MAGIC
)
92 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
97 b_count
= data
->caps
.NumberInputButtonCaps
;
98 r_count
= data
->dwInputReportCount
;
99 report
= HID_INPUT_REPORTS(data
);
102 b_count
= data
->caps
.NumberOutputButtonCaps
;
103 r_count
= data
->dwOutputReportCount
;
104 report
= HID_OUTPUT_REPORTS(data
);
107 b_count
= data
->caps
.NumberFeatureButtonCaps
;
108 r_count
= data
->dwFeatureReportCount
;
109 report
= HID_FEATURE_REPORTS(data
);
112 return HIDP_STATUS_INVALID_REPORT_TYPE
;
115 if (!r_count
|| !b_count
|| !report
)
117 *ButtonCapsLength
= 0;
118 return HIDP_STATUS_SUCCESS
;
121 b_count
= min(b_count
, *ButtonCapsLength
);
124 for (j
= 0; j
< r_count
&& u
< b_count
; j
++)
126 for (i
= 0; i
< report
->elementCount
&& u
< b_count
; i
++)
128 if (report
->Elements
[i
].ElementType
== ButtonElement
)
129 ButtonCaps
[u
++] = report
->Elements
[i
].caps
.button
;
131 report
= HID_NEXT_REPORT(data
, report
);
134 *ButtonCapsLength
= b_count
;
135 return HIDP_STATUS_SUCCESS
;
139 NTSTATUS WINAPI
HidP_GetCaps(PHIDP_PREPARSED_DATA PreparsedData
,
140 PHIDP_CAPS Capabilities
)
142 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
144 TRACE("(%p, %p)\n",PreparsedData
, Capabilities
);
146 if (data
->magic
!= HID_MAGIC
)
147 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
149 *Capabilities
= data
->caps
;
151 return HIDP_STATUS_SUCCESS
;
154 static NTSTATUS
find_value(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
155 USAGE Usage
, PHIDP_PREPARSED_DATA PreparsedData
, PCHAR Report
,
156 WINE_HID_ELEMENT
**element
)
158 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
159 WINE_HID_REPORT
*report
= NULL
;
160 USHORT v_count
= 0, r_count
= 0;
163 TRACE("(%i, %x, %i, %i, %p, %p)\n", ReportType
, UsagePage
, LinkCollection
, Usage
,
164 PreparsedData
, Report
);
166 if (data
->magic
!= HID_MAGIC
)
167 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
171 v_count
= data
->caps
.NumberInputValueCaps
;
172 r_count
= data
->dwInputReportCount
;
173 report
= HID_INPUT_REPORTS(data
);
176 v_count
= data
->caps
.NumberOutputValueCaps
;
177 r_count
= data
->dwOutputReportCount
;
178 report
= HID_OUTPUT_REPORTS(data
);
181 v_count
= data
->caps
.NumberFeatureValueCaps
;
182 r_count
= data
->dwFeatureReportCount
;
183 report
= HID_FEATURE_REPORTS(data
);
186 return HIDP_STATUS_INVALID_REPORT_TYPE
;
189 if (!r_count
|| !v_count
|| !report
)
190 return HIDP_STATUS_USAGE_NOT_FOUND
;
192 for (i
= 0; i
< r_count
; i
++)
194 if (!report
->reportID
|| report
->reportID
== Report
[0])
196 report
= HID_NEXT_REPORT(data
, report
);
200 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
202 for (i
= 0; i
< report
->elementCount
; i
++)
204 if (report
->Elements
[i
].ElementType
== ValueElement
&&
205 report
->Elements
[i
].caps
.value
.UsagePage
== UsagePage
&&
206 report
->Elements
[i
].caps
.value
.u
.NotRange
.Usage
== Usage
)
208 *element
= &report
->Elements
[i
];
209 return HIDP_STATUS_SUCCESS
;
213 return HIDP_STATUS_USAGE_NOT_FOUND
;
216 NTSTATUS WINAPI
HidP_GetScaledUsageValue(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
,
217 USHORT LinkCollection
, USAGE Usage
, PLONG UsageValue
,
218 PHIDP_PREPARSED_DATA PreparsedData
, PCHAR Report
, ULONG ReportLength
)
221 WINE_HID_ELEMENT
*element
;
222 TRACE("(%i, %x, %i, %i, %p, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, Usage
, UsageValue
,
223 PreparsedData
, Report
, ReportLength
);
225 rc
= find_value(ReportType
, UsagePage
, LinkCollection
, Usage
, PreparsedData
, Report
, &element
);
227 if (rc
== HIDP_STATUS_SUCCESS
)
230 rc
= get_report_data((BYTE
*)Report
, ReportLength
,
231 element
->valueStartBit
, element
->bitCount
, &rawValue
);
232 if (rc
!= HIDP_STATUS_SUCCESS
)
234 if (element
->caps
.value
.BitSize
== 16)
235 rawValue
= (short)rawValue
;
236 *UsageValue
= rawValue
;
243 NTSTATUS WINAPI
HidP_GetUsageValue(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
244 USAGE Usage
, PULONG UsageValue
, PHIDP_PREPARSED_DATA PreparsedData
,
245 PCHAR Report
, ULONG ReportLength
)
247 WINE_HID_ELEMENT
*element
;
250 TRACE("(%i, %x, %i, %i, %p, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, Usage
, UsageValue
,
251 PreparsedData
, Report
, ReportLength
);
253 rc
= find_value(ReportType
, UsagePage
, LinkCollection
, Usage
, PreparsedData
, Report
, &element
);
255 if (rc
== HIDP_STATUS_SUCCESS
)
257 return get_report_data((BYTE
*)Report
, ReportLength
,
258 element
->valueStartBit
, element
->bitCount
, UsageValue
);
265 NTSTATUS WINAPI
HidP_GetUsages(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, USHORT LinkCollection
,
266 PUSAGE UsageList
, PULONG UsageLength
, PHIDP_PREPARSED_DATA PreparsedData
,
267 PCHAR Report
, ULONG ReportLength
)
269 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
270 WINE_HID_REPORT
*report
= NULL
;
272 USHORT b_count
= 0, r_count
= 0;
275 TRACE("(%i, %x, %i, %p, %p, %p, %p, %i)\n", ReportType
, UsagePage
, LinkCollection
, UsageList
,
276 UsageLength
, PreparsedData
, Report
, ReportLength
);
278 if (data
->magic
!= HID_MAGIC
)
279 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
284 b_count
= data
->caps
.NumberInputButtonCaps
;
285 r_count
= data
->dwInputReportCount
;
286 report
= HID_INPUT_REPORTS(data
);
289 b_count
= data
->caps
.NumberOutputButtonCaps
;
290 r_count
= data
->dwOutputReportCount
;
291 report
= HID_OUTPUT_REPORTS(data
);
294 b_count
= data
->caps
.NumberFeatureButtonCaps
;
295 r_count
= data
->dwFeatureReportCount
;
296 report
= HID_FEATURE_REPORTS(data
);
299 return HIDP_STATUS_INVALID_REPORT_TYPE
;
302 if (!r_count
|| !b_count
|| !report
)
303 return HIDP_STATUS_USAGE_NOT_FOUND
;
305 for (i
= 0; i
< r_count
; i
++)
307 if (!report
->reportID
|| report
->reportID
== Report
[0])
309 report
= HID_NEXT_REPORT(data
, report
);
313 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
316 for (i
= 0; i
< report
->elementCount
&& uCount
< *UsageLength
; i
++)
318 if (report
->Elements
[i
].ElementType
== ButtonElement
&&
319 report
->Elements
[i
].caps
.button
.UsagePage
== UsagePage
)
322 WINE_HID_ELEMENT
*element
= &report
->Elements
[i
];
323 for (k
=0; k
< element
->bitCount
; k
++)
326 NTSTATUS rc
= get_report_data((BYTE
*)Report
, ReportLength
,
327 element
->valueStartBit
+ k
, 1, &v
);
328 if (rc
!= HIDP_STATUS_SUCCESS
)
333 if (uCount
== *UsageLength
)
334 return HIDP_STATUS_BUFFER_TOO_SMALL
;
335 UsageList
[uCount
] = element
->caps
.button
.u
.Range
.UsageMin
+ k
;
343 return HIDP_STATUS_USAGE_NOT_FOUND
;
345 *UsageLength
= uCount
;
347 return HIDP_STATUS_SUCCESS
;
351 NTSTATUS WINAPI
HidP_GetValueCaps(HIDP_REPORT_TYPE ReportType
, PHIDP_VALUE_CAPS ValueCaps
,
352 PUSHORT ValueCapsLength
, PHIDP_PREPARSED_DATA PreparsedData
)
354 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
355 WINE_HID_REPORT
*report
= NULL
;
356 USHORT v_count
= 0, r_count
= 0;
359 TRACE("(%i, %p, %p, %p)\n", ReportType
, ValueCaps
, ValueCapsLength
, PreparsedData
);
361 if (data
->magic
!= HID_MAGIC
)
362 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
367 v_count
= data
->caps
.NumberInputValueCaps
;
368 r_count
= data
->dwInputReportCount
;
369 report
= HID_INPUT_REPORTS(data
);
372 v_count
= data
->caps
.NumberOutputValueCaps
;
373 r_count
= data
->dwOutputReportCount
;
374 report
= HID_OUTPUT_REPORTS(data
);
377 v_count
= data
->caps
.NumberFeatureValueCaps
;
378 r_count
= data
->dwFeatureReportCount
;
379 report
= HID_FEATURE_REPORTS(data
);
382 return HIDP_STATUS_INVALID_REPORT_TYPE
;
385 if (!r_count
|| !v_count
|| !report
)
387 *ValueCapsLength
= 0;
388 return HIDP_STATUS_SUCCESS
;
391 v_count
= min(v_count
, *ValueCapsLength
);
394 for (j
= 0; j
< r_count
&& u
< v_count
; j
++)
396 for (i
= 0; i
< report
->elementCount
&& u
< v_count
; i
++)
398 if (report
->Elements
[i
].ElementType
== ValueElement
)
399 ValueCaps
[u
++] = report
->Elements
[i
].caps
.value
;
401 report
= HID_NEXT_REPORT(data
, report
);
404 *ValueCapsLength
= v_count
;
405 return HIDP_STATUS_SUCCESS
;
408 NTSTATUS WINAPI
HidP_InitializeReportForID(HIDP_REPORT_TYPE ReportType
, UCHAR ReportID
,
409 PHIDP_PREPARSED_DATA PreparsedData
, PCHAR Report
,
413 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
414 WINE_HID_REPORT
*report
= NULL
;
419 TRACE("(%i, %i, %p, %p, %i)\n",ReportType
, ReportID
, PreparsedData
, Report
, ReportLength
);
421 if (data
->magic
!= HID_MAGIC
)
422 return HIDP_STATUS_INVALID_PREPARSED_DATA
;
427 size
= data
->caps
.InputReportByteLength
;
428 report
= HID_INPUT_REPORTS(data
);
429 r_count
= data
->dwInputReportCount
;
432 size
= data
->caps
.OutputReportByteLength
;
433 report
= HID_OUTPUT_REPORTS(data
);
434 r_count
= data
->dwOutputReportCount
;
437 size
= data
->caps
.FeatureReportByteLength
;
438 report
= HID_FEATURE_REPORTS(data
);
439 r_count
= data
->dwFeatureReportCount
;
442 return HIDP_STATUS_INVALID_REPORT_TYPE
;
445 if (!r_count
|| !size
|| !report
)
446 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
448 if (size
!= ReportLength
)
449 return HIDP_STATUS_INVALID_REPORT_LENGTH
;
451 ZeroMemory(Report
, size
);
453 for (i
= 0; i
< r_count
; i
++)
455 if (report
->reportID
== ReportID
)
458 if (report
->reportID
)
459 Report
[0] = ReportID
;
460 /* TODO: Handle null and default values */
462 report
= HID_NEXT_REPORT(data
, report
);
466 return HIDP_STATUS_REPORT_DOES_NOT_EXIST
;
468 return HIDP_STATUS_SUCCESS
;
471 ULONG WINAPI
HidP_MaxUsageListLength(HIDP_REPORT_TYPE ReportType
, USAGE UsagePage
, PHIDP_PREPARSED_DATA PreparsedData
)
473 PWINE_HIDP_PREPARSED_DATA data
= (PWINE_HIDP_PREPARSED_DATA
)PreparsedData
;
474 WINE_HID_REPORT
*report
= NULL
;
479 TRACE("(%i, %x, %p)\n", ReportType
, UsagePage
, PreparsedData
);
481 if (data
->magic
!= HID_MAGIC
)
487 report
= HID_INPUT_REPORTS(data
);
488 r_count
= data
->dwInputReportCount
;
491 report
= HID_OUTPUT_REPORTS(data
);
492 r_count
= data
->dwOutputReportCount
;
495 report
= HID_FEATURE_REPORTS(data
);
496 r_count
= data
->dwFeatureReportCount
;
499 return HIDP_STATUS_INVALID_REPORT_TYPE
;
502 if (!r_count
|| !report
)
505 for (i
= 0; i
< r_count
; i
++)
508 for (j
= 0; j
< report
->elementCount
; j
++)
510 if (report
->Elements
[j
].caps
.button
.UsagePage
== UsagePage
)
512 if (report
->Elements
[j
].caps
.button
.IsRange
)
513 count
+= (report
->Elements
[j
].caps
.button
.u
.Range
.UsageMax
-
514 report
->Elements
[j
].caps
.button
.u
.Range
.UsageMin
) + 1;
519 report
= HID_NEXT_REPORT(data
, report
);
524 NTSTATUS WINAPI
HidP_TranslateUsagesToI8042ScanCodes(USAGE
*ChangedUsageList
,
525 ULONG UsageListLength
, HIDP_KEYBOARD_DIRECTION KeyAction
,
526 HIDP_KEYBOARD_MODIFIER_STATE
*ModifierState
,
527 PHIDP_INSERT_SCANCODES InsertCodesProcedure
, VOID
*InsertCodesContext
)
529 FIXME("stub: %p, %i, %i, %p, %p, %p\n", ChangedUsageList
, UsageListLength
,
530 KeyAction
, ModifierState
, InsertCodesProcedure
, InsertCodesContext
);
532 return STATUS_NOT_IMPLEMENTED
;