d3d11: Make extracting input signature more robust.
[wine.git] / dlls / hid / hidp.c
blobd6d143e899e3d8f585e3c70cfab6dd627d61dad9
1 /*
2 * Human Input Devices
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
21 #include "config.h"
23 #include <stdarg.h>
25 #define NONAMELESSUNION
26 #include "ntstatus.h"
27 #define WIN32_NO_STATUS
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winternl.h"
31 #include "winioctl.h"
32 #include "ddk/wdm.h"
34 #include "hidusage.h"
35 #include "ddk/hidpi.h"
36 #include "parse.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;
47 if (valueSize == 1)
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);
54 else
56 ULONG byte_index = startBit / 8;
57 ULONG data = 0;
58 ULONG remainingBits = valueSize;
59 ULONG shift = 0;
60 ULONG begin_offset = startBit % 8;
61 while (remainingBits)
63 if (remainingBits >= 8)
65 BYTE mask = 0xff << begin_offset;
66 data |= (report[byte_index] & mask) << shift;
67 byte_index ++;
68 remainingBits -= (8-begin_offset);
69 shift += (8-begin_offset);
70 begin_offset = 0;
72 else if (remainingBits > 0)
74 BYTE mask = (0xff >> (8-remainingBits)) << begin_offset;
75 data |= (report[byte_index] & mask) << shift;
76 remainingBits = 0;
79 *value = data;
81 return HIDP_STATUS_SUCCESS;
84 NTSTATUS WINAPI HidP_GetButtonCaps(HIDP_REPORT_TYPE ReportType, PHIDP_BUTTON_CAPS ButtonCaps,
85 PUSHORT ButtonCapsLength, PHIDP_PREPARSED_DATA PreparsedData)
87 PWINE_HIDP_PREPARSED_DATA data = (PWINE_HIDP_PREPARSED_DATA)PreparsedData;
88 WINE_HID_REPORT *report = NULL;
89 USHORT b_count = 0, r_count = 0;
90 int i,j,u;
92 TRACE("(%i, %p, %p, %p)\n",ReportType, ButtonCaps, ButtonCapsLength, PreparsedData);
94 if (data->magic != HID_MAGIC)
95 return HIDP_STATUS_INVALID_PREPARSED_DATA;
97 switch(ReportType)
99 case HidP_Input:
100 b_count = data->caps.NumberInputButtonCaps;
101 r_count = data->dwInputReportCount;
102 report = HID_INPUT_REPORTS(data);
103 break;
104 case HidP_Output:
105 b_count = data->caps.NumberOutputButtonCaps;
106 r_count = data->dwOutputReportCount;
107 report = HID_OUTPUT_REPORTS(data);
108 break;
109 case HidP_Feature:
110 b_count = data->caps.NumberFeatureButtonCaps;
111 r_count = data->dwFeatureReportCount;
112 report = HID_FEATURE_REPORTS(data);
113 break;
114 default:
115 return HIDP_STATUS_INVALID_REPORT_TYPE;
118 if (!r_count || !b_count || !report)
120 *ButtonCapsLength = 0;
121 return HIDP_STATUS_SUCCESS;
124 b_count = min(b_count, *ButtonCapsLength);
126 u = 0;
127 for (j = 0; j < r_count && u < b_count; j++)
129 for (i = 0; i < report->elementCount && u < b_count; i++)
131 if (report->Elements[i].ElementType == ButtonElement)
132 ButtonCaps[u++] = report->Elements[i].caps.button;
134 report = HID_NEXT_REPORT(data, report);
137 *ButtonCapsLength = b_count;
138 return HIDP_STATUS_SUCCESS;
142 NTSTATUS WINAPI HidP_GetCaps(PHIDP_PREPARSED_DATA PreparsedData,
143 PHIDP_CAPS Capabilities)
145 PWINE_HIDP_PREPARSED_DATA data = (PWINE_HIDP_PREPARSED_DATA)PreparsedData;
147 TRACE("(%p, %p)\n",PreparsedData, Capabilities);
149 if (data->magic != HID_MAGIC)
150 return HIDP_STATUS_INVALID_PREPARSED_DATA;
152 *Capabilities = data->caps;
154 return HIDP_STATUS_SUCCESS;
157 static NTSTATUS find_value(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection,
158 USAGE Usage, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report,
159 WINE_HID_ELEMENT **element)
161 PWINE_HIDP_PREPARSED_DATA data = (PWINE_HIDP_PREPARSED_DATA)PreparsedData;
162 WINE_HID_REPORT *report = NULL;
163 USHORT v_count = 0, r_count = 0;
164 int i;
166 TRACE("(%i, %x, %i, %i, %p, %p)\n", ReportType, UsagePage, LinkCollection, Usage,
167 PreparsedData, Report);
169 if (data->magic != HID_MAGIC)
170 return HIDP_STATUS_INVALID_PREPARSED_DATA;
171 switch(ReportType)
173 case HidP_Input:
174 v_count = data->caps.NumberInputValueCaps;
175 r_count = data->dwInputReportCount;
176 report = HID_INPUT_REPORTS(data);
177 break;
178 case HidP_Output:
179 v_count = data->caps.NumberOutputValueCaps;
180 r_count = data->dwOutputReportCount;
181 report = HID_OUTPUT_REPORTS(data);
182 break;
183 case HidP_Feature:
184 v_count = data->caps.NumberFeatureValueCaps;
185 r_count = data->dwFeatureReportCount;
186 report = HID_FEATURE_REPORTS(data);
187 break;
188 default:
189 return HIDP_STATUS_INVALID_REPORT_TYPE;
192 if (!r_count || !v_count || !report)
193 return HIDP_STATUS_USAGE_NOT_FOUND;
195 for (i = 0; i < r_count; i++)
197 if (!report->reportID || report->reportID == Report[0])
198 break;
199 report = HID_NEXT_REPORT(data, report);
202 if (i == r_count)
203 return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
205 for (i = 0; i < report->elementCount; i++)
207 if (report->Elements[i].ElementType == ValueElement &&
208 report->Elements[i].caps.value.UsagePage == UsagePage &&
209 report->Elements[i].caps.value.u.NotRange.Usage == Usage)
211 *element = &report->Elements[i];
212 return HIDP_STATUS_SUCCESS;
216 return HIDP_STATUS_USAGE_NOT_FOUND;
219 NTSTATUS WINAPI HidP_GetScaledUsageValue(HIDP_REPORT_TYPE ReportType, USAGE UsagePage,
220 USHORT LinkCollection, USAGE Usage, PLONG UsageValue,
221 PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength)
223 NTSTATUS rc;
224 WINE_HID_ELEMENT *element;
225 TRACE("(%i, %x, %i, %i, %p, %p, %p, %i)\n", ReportType, UsagePage, LinkCollection, Usage, UsageValue,
226 PreparsedData, Report, ReportLength);
228 rc = find_value(ReportType, UsagePage, LinkCollection, Usage, PreparsedData, Report, &element);
230 if (rc == HIDP_STATUS_SUCCESS)
232 ULONG rawValue;
233 rc = get_report_data((BYTE*)Report, ReportLength,
234 element->valueStartBit, element->bitCount, &rawValue);
235 if (rc != HIDP_STATUS_SUCCESS)
236 return rc;
237 if (element->caps.value.BitSize == 16)
238 rawValue = (short)rawValue;
239 *UsageValue = rawValue;
242 return rc;
246 NTSTATUS WINAPI HidP_GetUsageValue(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection,
247 USAGE Usage, PULONG UsageValue, PHIDP_PREPARSED_DATA PreparsedData,
248 PCHAR Report, ULONG ReportLength)
250 WINE_HID_ELEMENT *element;
251 NTSTATUS rc;
253 TRACE("(%i, %x, %i, %i, %p, %p, %p, %i)\n", ReportType, UsagePage, LinkCollection, Usage, UsageValue,
254 PreparsedData, Report, ReportLength);
256 rc = find_value(ReportType, UsagePage, LinkCollection, Usage, PreparsedData, Report, &element);
258 if (rc == HIDP_STATUS_SUCCESS)
260 return get_report_data((BYTE*)Report, ReportLength,
261 element->valueStartBit, element->bitCount, UsageValue);
264 return rc;
268 NTSTATUS WINAPI HidP_GetUsages(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection,
269 PUSAGE UsageList, PULONG UsageLength, PHIDP_PREPARSED_DATA PreparsedData,
270 PCHAR Report, ULONG ReportLength)
272 PWINE_HIDP_PREPARSED_DATA data = (PWINE_HIDP_PREPARSED_DATA)PreparsedData;
273 WINE_HID_REPORT *report = NULL;
274 BOOL found = FALSE;
275 USHORT b_count = 0, r_count = 0;
276 int i,uCount;
278 TRACE("(%i, %x, %i, %p, %p, %p, %p, %i)\n", ReportType, UsagePage, LinkCollection, UsageList,
279 UsageLength, PreparsedData, Report, ReportLength);
281 if (data->magic != HID_MAGIC)
283 *UsageLength = 0;
284 return HIDP_STATUS_INVALID_PREPARSED_DATA;
287 switch(ReportType)
289 case HidP_Input:
290 b_count = data->caps.NumberInputButtonCaps;
291 r_count = data->dwInputReportCount;
292 report = HID_INPUT_REPORTS(data);
293 break;
294 case HidP_Output:
295 b_count = data->caps.NumberOutputButtonCaps;
296 r_count = data->dwOutputReportCount;
297 report = HID_OUTPUT_REPORTS(data);
298 break;
299 case HidP_Feature:
300 b_count = data->caps.NumberFeatureButtonCaps;
301 r_count = data->dwFeatureReportCount;
302 report = HID_FEATURE_REPORTS(data);
303 break;
304 default:
305 return HIDP_STATUS_INVALID_REPORT_TYPE;
308 if (!r_count || !b_count || !report)
309 return HIDP_STATUS_USAGE_NOT_FOUND;
311 for (i = 0; i < r_count; i++)
313 if (!report->reportID || report->reportID == Report[0])
314 break;
315 report = HID_NEXT_REPORT(data, report);
318 if (i == r_count)
319 return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
321 uCount = 0;
322 for (i = 0; i < report->elementCount && uCount < *UsageLength; i++)
324 if (report->Elements[i].ElementType == ButtonElement &&
325 report->Elements[i].caps.button.UsagePage == UsagePage)
327 int k;
328 WINE_HID_ELEMENT *element = &report->Elements[i];
329 for (k=0; k < element->bitCount; k++)
331 UINT v = 0;
332 NTSTATUS rc = get_report_data((BYTE*)Report, ReportLength,
333 element->valueStartBit + k, 1, &v);
334 if (rc != HIDP_STATUS_SUCCESS)
335 return rc;
336 found = TRUE;
337 if (v)
339 if (uCount == *UsageLength)
340 return HIDP_STATUS_BUFFER_TOO_SMALL;
341 UsageList[uCount] = element->caps.button.u.Range.UsageMin + k;
342 uCount++;
348 *UsageLength = uCount;
350 if (!found)
351 return HIDP_STATUS_USAGE_NOT_FOUND;
353 return HIDP_STATUS_SUCCESS;
357 NTSTATUS WINAPI HidP_GetValueCaps(HIDP_REPORT_TYPE ReportType, PHIDP_VALUE_CAPS ValueCaps,
358 PUSHORT ValueCapsLength, PHIDP_PREPARSED_DATA PreparsedData)
360 PWINE_HIDP_PREPARSED_DATA data = (PWINE_HIDP_PREPARSED_DATA)PreparsedData;
361 WINE_HID_REPORT *report = NULL;
362 USHORT v_count = 0, r_count = 0;
363 int i,j,u;
365 TRACE("(%i, %p, %p, %p)\n", ReportType, ValueCaps, ValueCapsLength, PreparsedData);
367 if (data->magic != HID_MAGIC)
368 return HIDP_STATUS_INVALID_PREPARSED_DATA;
370 switch(ReportType)
372 case HidP_Input:
373 v_count = data->caps.NumberInputValueCaps;
374 r_count = data->dwInputReportCount;
375 report = HID_INPUT_REPORTS(data);
376 break;
377 case HidP_Output:
378 v_count = data->caps.NumberOutputValueCaps;
379 r_count = data->dwOutputReportCount;
380 report = HID_OUTPUT_REPORTS(data);
381 break;
382 case HidP_Feature:
383 v_count = data->caps.NumberFeatureValueCaps;
384 r_count = data->dwFeatureReportCount;
385 report = HID_FEATURE_REPORTS(data);
386 break;
387 default:
388 return HIDP_STATUS_INVALID_REPORT_TYPE;
391 if (!r_count || !v_count || !report)
393 *ValueCapsLength = 0;
394 return HIDP_STATUS_SUCCESS;
397 v_count = min(v_count, *ValueCapsLength);
399 u = 0;
400 for (j = 0; j < r_count && u < v_count; j++)
402 for (i = 0; i < report->elementCount && u < v_count; i++)
404 if (report->Elements[i].ElementType == ValueElement)
405 ValueCaps[u++] = report->Elements[i].caps.value;
407 report = HID_NEXT_REPORT(data, report);
410 *ValueCapsLength = v_count;
411 return HIDP_STATUS_SUCCESS;
414 NTSTATUS WINAPI HidP_InitializeReportForID(HIDP_REPORT_TYPE ReportType, UCHAR ReportID,
415 PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report,
416 ULONG ReportLength)
418 int size;
419 PWINE_HIDP_PREPARSED_DATA data = (PWINE_HIDP_PREPARSED_DATA)PreparsedData;
420 WINE_HID_REPORT *report = NULL;
421 BOOL found=FALSE;
422 int r_count;
423 int i;
425 TRACE("(%i, %i, %p, %p, %i)\n",ReportType, ReportID, PreparsedData, Report, ReportLength);
427 if (data->magic != HID_MAGIC)
428 return HIDP_STATUS_INVALID_PREPARSED_DATA;
430 switch(ReportType)
432 case HidP_Input:
433 size = data->caps.InputReportByteLength;
434 report = HID_INPUT_REPORTS(data);
435 r_count = data->dwInputReportCount;
436 break;
437 case HidP_Output:
438 size = data->caps.OutputReportByteLength;
439 report = HID_OUTPUT_REPORTS(data);
440 r_count = data->dwOutputReportCount;
441 break;
442 case HidP_Feature:
443 size = data->caps.FeatureReportByteLength;
444 report = HID_FEATURE_REPORTS(data);
445 r_count = data->dwFeatureReportCount;
446 break;
447 default:
448 return HIDP_STATUS_INVALID_REPORT_TYPE;
451 if (!r_count || !size || !report)
452 return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
454 if (size != ReportLength)
455 return HIDP_STATUS_INVALID_REPORT_LENGTH;
457 ZeroMemory(Report, size);
459 for (i = 0; i < r_count; i++)
461 if (report->reportID == ReportID)
463 found = TRUE;
464 if (report->reportID)
465 Report[0] = ReportID;
466 /* TODO: Handle null and default values */
468 report = HID_NEXT_REPORT(data, report);
471 if (!found)
472 return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
474 return HIDP_STATUS_SUCCESS;
477 ULONG WINAPI HidP_MaxUsageListLength(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, PHIDP_PREPARSED_DATA PreparsedData)
479 PWINE_HIDP_PREPARSED_DATA data = (PWINE_HIDP_PREPARSED_DATA)PreparsedData;
480 WINE_HID_REPORT *report = NULL;
481 int r_count;
482 int i;
483 int count = 0;
485 TRACE("(%i, %x, %p)\n", ReportType, UsagePage, PreparsedData);
487 if (data->magic != HID_MAGIC)
488 return 0;
490 switch(ReportType)
492 case HidP_Input:
493 report = HID_INPUT_REPORTS(data);
494 r_count = data->dwInputReportCount;
495 break;
496 case HidP_Output:
497 report = HID_OUTPUT_REPORTS(data);
498 r_count = data->dwOutputReportCount;
499 break;
500 case HidP_Feature:
501 report = HID_FEATURE_REPORTS(data);
502 r_count = data->dwFeatureReportCount;
503 break;
504 default:
505 return HIDP_STATUS_INVALID_REPORT_TYPE;
508 if (!r_count || !report)
509 return 0;
511 for (i = 0; i < r_count; i++)
513 int j;
514 for (j = 0; j < report->elementCount; j++)
516 if (report->Elements[j].ElementType == ButtonElement &&
517 (UsagePage == 0 || report->Elements[j].caps.button.UsagePage == UsagePage))
519 if (report->Elements[j].caps.button.IsRange)
520 count += (report->Elements[j].caps.button.u.Range.UsageMax -
521 report->Elements[j].caps.button.u.Range.UsageMin) + 1;
522 else
523 count++;
526 report = HID_NEXT_REPORT(data, report);
528 return count;
531 NTSTATUS WINAPI HidP_TranslateUsagesToI8042ScanCodes(USAGE *ChangedUsageList,
532 ULONG UsageListLength, HIDP_KEYBOARD_DIRECTION KeyAction,
533 HIDP_KEYBOARD_MODIFIER_STATE *ModifierState,
534 PHIDP_INSERT_SCANCODES InsertCodesProcedure, VOID *InsertCodesContext)
536 FIXME("stub: %p, %i, %i, %p, %p, %p\n", ChangedUsageList, UsageListLength,
537 KeyAction, ModifierState, InsertCodesProcedure, InsertCodesContext);
539 return STATUS_NOT_IMPLEMENTED;
542 NTSTATUS WINAPI HidP_GetSpecificButtonCaps(HIDP_REPORT_TYPE ReportType,
543 USAGE UsagePage, USHORT LinkCollection, USAGE Usage,
544 HIDP_BUTTON_CAPS *ButtonCaps, USHORT *ButtonCapsLength, PHIDP_PREPARSED_DATA PreparsedData)
546 WINE_HIDP_PREPARSED_DATA *data = (WINE_HIDP_PREPARSED_DATA*)PreparsedData;
547 WINE_HID_REPORT *report = NULL;
548 USHORT b_count = 0, r_count = 0;
549 int i,j,u;
551 TRACE("(%i, 0x%x, %i, 0x%x, %p %p %p)\n", ReportType, UsagePage, LinkCollection,
552 Usage, ButtonCaps, ButtonCapsLength, PreparsedData);
554 if (data->magic != HID_MAGIC)
555 return HIDP_STATUS_INVALID_PREPARSED_DATA;
557 switch(ReportType)
559 case HidP_Input:
560 b_count = data->caps.NumberInputButtonCaps;
561 r_count = data->dwInputReportCount;
562 report = HID_INPUT_REPORTS(data);
563 break;
564 case HidP_Output:
565 b_count = data->caps.NumberOutputButtonCaps;
566 r_count = data->dwOutputReportCount;
567 report = HID_OUTPUT_REPORTS(data);
568 break;
569 case HidP_Feature:
570 b_count = data->caps.NumberFeatureButtonCaps;
571 r_count = data->dwFeatureReportCount;
572 report = HID_FEATURE_REPORTS(data);
573 break;
574 default:
575 return HIDP_STATUS_INVALID_REPORT_TYPE;
578 if (!r_count || !b_count || !report)
580 *ButtonCapsLength = 0;
581 return HIDP_STATUS_SUCCESS;
584 b_count = min(b_count, *ButtonCapsLength);
586 u = 0;
587 for (j = 0; j < r_count && u < b_count; j++)
589 for (i = 0; i < report->elementCount && u < b_count; i++)
591 if (report->Elements[i].ElementType == ButtonElement &&
592 (UsagePage == 0 || UsagePage == report->Elements[i].caps.button.UsagePage) &&
593 (LinkCollection == 0 || LinkCollection == report->Elements[i].caps.button.LinkCollection) &&
594 (Usage == 0 || (
595 (!report->Elements[i].caps.button.IsRange &&
596 Usage == report->Elements[i].caps.button.u.NotRange.Usage)) ||
597 (report->Elements[i].caps.button.IsRange &&
598 Usage >=report->Elements[i].caps.button.u.Range.UsageMin &&
599 Usage <= report->Elements[i].caps.button.u.Range.UsageMax)))
601 ButtonCaps[u++] = report->Elements[i].caps.button;
604 report = HID_NEXT_REPORT(data, report);
606 TRACE("Matched %i usages\n", u);
608 *ButtonCapsLength = u;
610 return HIDP_STATUS_SUCCESS;
614 NTSTATUS WINAPI HidP_GetSpecificValueCaps(HIDP_REPORT_TYPE ReportType,
615 USAGE UsagePage, USHORT LinkCollection, USAGE Usage,
616 HIDP_VALUE_CAPS *ValueCaps, USHORT *ValueCapsLength, PHIDP_PREPARSED_DATA PreparsedData)
618 WINE_HIDP_PREPARSED_DATA *data = (PWINE_HIDP_PREPARSED_DATA)PreparsedData;
619 WINE_HID_REPORT *report = NULL;
620 USHORT v_count = 0, r_count = 0;
621 int i,j,u;
623 TRACE("(%i, 0x%x, %i, 0x%x, %p %p %p)\n", ReportType, UsagePage, LinkCollection,
624 Usage, ValueCaps, ValueCapsLength, PreparsedData);
626 if (data->magic != HID_MAGIC)
627 return HIDP_STATUS_INVALID_PREPARSED_DATA;
629 switch(ReportType)
631 case HidP_Input:
632 v_count = data->caps.NumberInputValueCaps;
633 r_count = data->dwInputReportCount;
634 report = HID_INPUT_REPORTS(data);
635 break;
636 case HidP_Output:
637 v_count = data->caps.NumberOutputValueCaps;
638 r_count = data->dwOutputReportCount;
639 report = HID_OUTPUT_REPORTS(data);
640 break;
641 case HidP_Feature:
642 v_count = data->caps.NumberFeatureValueCaps;
643 r_count = data->dwFeatureReportCount;
644 report = HID_FEATURE_REPORTS(data);
645 break;
646 default:
647 return HIDP_STATUS_INVALID_REPORT_TYPE;
650 if (!r_count || !v_count || !report)
652 *ValueCapsLength = 0;
653 return HIDP_STATUS_SUCCESS;
656 v_count = min(v_count, *ValueCapsLength);
658 u = 0;
659 for (j = 0; j < r_count && u < v_count; j++)
661 for (i = 0; i < report->elementCount && u < v_count; i++)
663 if (report->Elements[i].ElementType == ValueElement &&
664 (UsagePage == 0 || UsagePage == report->Elements[i].caps.value.UsagePage) &&
665 (LinkCollection == 0 || LinkCollection == report->Elements[i].caps.value.LinkCollection) &&
666 (Usage == 0 || Usage == report->Elements[i].caps.value.u.NotRange.Usage))
668 ValueCaps[u++] = report->Elements[i].caps.value;
671 report = HID_NEXT_REPORT(data, report);
673 TRACE("Matched %i usages\n", u);
675 *ValueCapsLength = u;
677 return HIDP_STATUS_SUCCESS;
680 NTSTATUS WINAPI HidP_GetUsagesEx(HIDP_REPORT_TYPE ReportType, USHORT LinkCollection, USAGE_AND_PAGE *ButtonList,
681 ULONG *UsageLength, PHIDP_PREPARSED_DATA PreparsedData, CHAR *Report, ULONG ReportLength)
683 WINE_HIDP_PREPARSED_DATA *data = (WINE_HIDP_PREPARSED_DATA*)PreparsedData;
684 WINE_HID_REPORT *report = NULL;
685 USHORT b_count = 0, r_count = 0;
686 int i,uCount = 0;
687 NTSTATUS rc;
689 TRACE("(%i, %i, %p, %p(%i), %p, %p, %i)\n", ReportType, LinkCollection, ButtonList,
690 UsageLength, *UsageLength, PreparsedData, Report, ReportLength);
692 if (data->magic != HID_MAGIC)
693 return HIDP_STATUS_INVALID_PREPARSED_DATA;
695 switch(ReportType)
697 case HidP_Input:
698 b_count = data->caps.NumberInputButtonCaps;
699 r_count = data->dwInputReportCount;
700 report = HID_INPUT_REPORTS(data);
701 break;
702 case HidP_Output:
703 b_count = data->caps.NumberOutputButtonCaps;
704 r_count = data->dwOutputReportCount;
705 report = HID_OUTPUT_REPORTS(data);
706 break;
707 case HidP_Feature:
708 b_count = data->caps.NumberFeatureButtonCaps;
709 r_count = data->dwFeatureReportCount;
710 report = HID_FEATURE_REPORTS(data);
711 break;
712 default:
713 return HIDP_STATUS_INVALID_REPORT_TYPE;
716 if (!r_count || !b_count || !report)
717 return HIDP_STATUS_USAGE_NOT_FOUND;
719 for (i = 0; i < r_count; i++)
721 if (!report->reportID || report->reportID == Report[0])
722 break;
723 report = HID_NEXT_REPORT(data, report);
726 if (i == r_count)
727 return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
729 for (i = 0; i < report->elementCount; i++)
731 if (report->Elements[i].ElementType == ButtonElement)
733 int k;
734 WINE_HID_ELEMENT *element = &report->Elements[i];
735 for (k=0; k < element->bitCount; k++)
737 UINT v = 0;
738 NTSTATUS rc = get_report_data((BYTE*)Report, ReportLength,
739 element->valueStartBit + k, 1, &v);
740 if (rc != HIDP_STATUS_SUCCESS)
741 return rc;
742 if (v)
744 if (uCount < *UsageLength)
746 ButtonList[uCount].Usage = element->caps.button.u.Range.UsageMin + k;
747 ButtonList[uCount].UsagePage = element->caps.button.UsagePage;
749 uCount++;
755 TRACE("Returning %i usages\n", uCount);
757 if (*UsageLength < uCount)
758 rc = HIDP_STATUS_BUFFER_TOO_SMALL;
759 else
760 rc = HIDP_STATUS_SUCCESS;
762 *UsageLength = uCount;
764 return rc;
767 ULONG WINAPI HidP_MaxDataListLength(HIDP_REPORT_TYPE ReportType, PHIDP_PREPARSED_DATA PreparsedData)
769 WINE_HIDP_PREPARSED_DATA *data = (WINE_HIDP_PREPARSED_DATA *)PreparsedData;
770 TRACE("(%i, %p)\n", ReportType, PreparsedData);
771 if (data->magic != HID_MAGIC)
772 return 0;
774 switch(ReportType)
776 case HidP_Input:
777 return data->caps.NumberInputDataIndices;
778 case HidP_Output:
779 return data->caps.NumberOutputDataIndices;
780 case HidP_Feature:
781 return data->caps.NumberFeatureDataIndices;
782 default:
783 return 0;
787 NTSTATUS WINAPI HidP_GetData(HIDP_REPORT_TYPE ReportType, HIDP_DATA *DataList, ULONG *DataLength,
788 PHIDP_PREPARSED_DATA PreparsedData,CHAR *Report, ULONG ReportLength)
790 WINE_HIDP_PREPARSED_DATA *data = (WINE_HIDP_PREPARSED_DATA*)PreparsedData;
791 WINE_HID_REPORT *report = NULL;
792 USHORT r_count = 0;
793 int i,uCount = 0;
794 NTSTATUS rc;
796 TRACE("(%i, %p, %p(%i), %p, %p, %i)\n", ReportType, DataList, DataLength,
797 DataLength?*DataLength:0, PreparsedData, Report, ReportLength);
799 if (data->magic != HID_MAGIC)
800 return 0;
802 switch(ReportType)
804 case HidP_Input:
805 r_count = data->dwInputReportCount;
806 report = HID_INPUT_REPORTS(data);
807 break;
808 case HidP_Output:
809 r_count = data->dwOutputReportCount;
810 report = HID_OUTPUT_REPORTS(data);
811 break;
812 case HidP_Feature:
813 r_count = data->dwFeatureReportCount;
814 report = HID_FEATURE_REPORTS(data);
815 break;
816 default:
817 return HIDP_STATUS_INVALID_REPORT_TYPE;
820 for (i = 0; i < r_count; i++)
822 if (!report->reportID || report->reportID == Report[0])
823 break;
824 report = HID_NEXT_REPORT(data, report);
827 if (i == r_count)
828 return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
830 for (i = 0; i < report->elementCount; i++)
832 WINE_HID_ELEMENT *element = &report->Elements[i];
833 if (element->ElementType == ButtonElement)
835 int k;
836 for (k=0; k < element->bitCount; k++)
838 UINT v = 0;
839 NTSTATUS rc = get_report_data((BYTE*)Report, ReportLength,
840 element->valueStartBit + k, 1, &v);
841 if (rc != HIDP_STATUS_SUCCESS)
842 return rc;
843 if (v)
845 if (uCount < *DataLength)
847 DataList[uCount].DataIndex = element->caps.button.u.Range.DataIndexMin + k;
848 DataList[uCount].u.On = v;
850 uCount++;
854 else
856 if (uCount < *DataLength)
858 UINT v;
859 NTSTATUS rc = get_report_data((BYTE*)Report, ReportLength,
860 element->valueStartBit, element->bitCount, &v);
861 if (rc != HIDP_STATUS_SUCCESS)
862 return rc;
863 if (element->caps.value.BitSize == 16)
864 v = (short)v;
865 DataList[uCount].DataIndex = element->caps.value.u.NotRange.DataIndex;
866 DataList[uCount].u.RawValue = v;
868 uCount++;
872 if (*DataLength < uCount)
873 rc = HIDP_STATUS_BUFFER_TOO_SMALL;
874 else
875 rc = HIDP_STATUS_SUCCESS;
877 *DataLength = uCount;
879 return rc;