xref: /reactos/dll/win32/hid/hid.c (revision 4561998a)
1 /*
2  * ReactOS Hid User Library
3  * Copyright (C) 2004-2005 ReactOS Team
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19 /*
20  * PROJECT:         ReactOS Hid User Library
21  * FILE:            lib/hid/hid.c
22  * PURPOSE:         ReactOS Hid User Library
23  * PROGRAMMER:      Thomas Weidenmueller <w3seek@reactos.com>
24  *
25  * UPDATE HISTORY:
26  *      07/12/2004  Created
27  */
28 
29 #include "precomp.h"
30 
31 #include <winbase.h>
32 
33 #define NDEBUG
34 #include <debug.h>
35 
36 HINSTANCE hDllInstance;
37 
38 /* device interface GUID for HIDClass devices */
39 const GUID HidClassGuid = {0x4D1E55B2, 0xF16F, 0x11CF, {0x88,0xCB,0x00,0x11,0x11,0x00,0x00,0x30}};
40 
41 BOOL WINAPI
42 DllMain(HINSTANCE hinstDLL,
43         DWORD dwReason,
44         LPVOID lpvReserved)
45 {
46   switch(dwReason)
47   {
48     case DLL_PROCESS_ATTACH:
49       hDllInstance = hinstDLL;
50       break;
51 
52     case DLL_THREAD_ATTACH:
53       break;
54 
55     case DLL_THREAD_DETACH:
56       break;
57 
58     case DLL_PROCESS_DETACH:
59       break;
60   }
61   return TRUE;
62 }
63 
64 
65 /*
66  * HidD_FlushQueue							EXPORTED
67  *
68  * @implemented
69  */
70 HIDAPI
71 BOOLEAN WINAPI
72 HidD_FlushQueue(IN HANDLE HidDeviceObject)
73 {
74   DWORD RetLen;
75   return DeviceIoControl(HidDeviceObject, IOCTL_HID_FLUSH_QUEUE,
76                          NULL, 0,
77                          NULL, 0,
78                          &RetLen, NULL) != 0;
79 }
80 
81 
82 /*
83  * HidD_FreePreparsedData						EXPORTED
84  *
85  * @implemented
86  */
87 HIDAPI
88 BOOLEAN WINAPI
89 HidD_FreePreparsedData(IN PHIDP_PREPARSED_DATA PreparsedData)
90 {
91   return (LocalFree((HLOCAL)PreparsedData) == NULL);
92 }
93 
94 
95 /*
96  * HidD_GetAttributes							EXPORTED
97  *
98  * @implemented
99  */
100 HIDAPI
101 BOOLEAN WINAPI
102 HidD_GetAttributes(IN HANDLE HidDeviceObject,
103                    OUT PHIDD_ATTRIBUTES Attributes)
104 {
105   HID_COLLECTION_INFORMATION hci;
106   DWORD RetLen;
107 
108   if(!DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_COLLECTION_INFORMATION,
109                                        NULL, 0,
110                                        &hci, sizeof(HID_COLLECTION_INFORMATION),
111                                        &RetLen, NULL))
112   {
113     return FALSE;
114   }
115 
116   /* copy the fields */
117   Attributes->Size = sizeof(HIDD_ATTRIBUTES);
118   Attributes->VendorID = hci.VendorID;
119   Attributes->ProductID = hci.ProductID;
120   Attributes->VersionNumber = hci.VersionNumber;
121 
122   return TRUE;
123 }
124 
125 
126 /*
127  * HidP_GetButtonCaps							EXPORTED
128  *
129  * @implemented
130  */
131 HIDAPI
132 NTSTATUS WINAPI
133 HidP_GetButtonCaps(IN HIDP_REPORT_TYPE ReportType,
134                    OUT PHIDP_BUTTON_CAPS ButtonCaps,
135                    IN OUT PUSHORT ButtonCapsLength,
136                    IN PHIDP_PREPARSED_DATA PreparsedData)
137 {
138   return HidP_GetSpecificButtonCaps(ReportType, 0, 0, 0, ButtonCaps,
139                                     ButtonCapsLength, PreparsedData);
140 }
141 
142 
143 /*
144  * HidD_GetFeature							EXPORTED
145  *
146  * @implemented
147  */
148 HIDAPI
149 BOOLEAN WINAPI
150 HidD_GetFeature(IN HANDLE HidDeviceObject,
151                 OUT PVOID ReportBuffer,
152                 IN ULONG ReportBufferLength)
153 {
154   DWORD RetLen;
155   return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_FEATURE,
156                          NULL, 0,
157                          ReportBuffer, ReportBufferLength,
158                          &RetLen, NULL) != 0;
159 }
160 
161 
162 /*
163  * HidD_GetHidGuid							EXPORTED
164  *
165  * @implemented
166  */
167 HIDAPI
168 VOID WINAPI
169 HidD_GetHidGuid(OUT LPGUID HidGuid)
170 {
171   *HidGuid = HidClassGuid;
172 }
173 
174 
175 /*
176  * HidD_GetInputReport							EXPORTED
177  *
178  * @implemented
179  */
180 HIDAPI
181 BOOLEAN WINAPI
182 HidD_GetInputReport(IN HANDLE HidDeviceObject,
183                     IN OUT PVOID ReportBuffer,
184                     IN ULONG ReportBufferLength)
185 {
186   DWORD RetLen;
187   return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_INPUT_REPORT,
188                          NULL, 0,
189                          ReportBuffer, ReportBufferLength,
190                          &RetLen, NULL) != 0;
191 }
192 
193 
194 /*
195  * HidD_GetManufacturerString						EXPORTED
196  *
197  * @implemented
198  */
199 HIDAPI
200 BOOLEAN WINAPI
201 HidD_GetManufacturerString(IN HANDLE HidDeviceObject,
202                            OUT PVOID Buffer,
203                            IN ULONG BufferLength)
204 {
205   DWORD RetLen;
206   return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_MANUFACTURER_STRING,
207                          NULL, 0,
208                          Buffer, BufferLength,
209                          &RetLen, NULL) != 0;
210 }
211 
212 
213 /*
214  * HidD_GetNumInputBuffers						EXPORTED
215  *
216  * @implemented
217  */
218 HIDAPI
219 BOOLEAN WINAPI
220 HidD_GetNumInputBuffers(IN HANDLE HidDeviceObject,
221                         OUT PULONG NumberBuffers)
222 {
223   DWORD RetLen;
224   return DeviceIoControl(HidDeviceObject, IOCTL_GET_NUM_DEVICE_INPUT_BUFFERS,
225                          NULL, 0,
226                          NumberBuffers, sizeof(ULONG),
227                          &RetLen, NULL) != 0;
228 }
229 
230 
231 /*
232  * HidD_GetPhysicalDescriptor						EXPORTED
233  *
234  * @implemented
235  */
236 HIDAPI
237 BOOLEAN WINAPI
238 HidD_GetPhysicalDescriptor(IN HANDLE HidDeviceObject,
239                            OUT PVOID Buffer,
240                            IN ULONG BufferLength)
241 {
242   DWORD RetLen;
243   return DeviceIoControl(HidDeviceObject, IOCTL_GET_PHYSICAL_DESCRIPTOR,
244                          NULL, 0,
245                          Buffer, BufferLength,
246                          &RetLen, NULL) != 0;
247 }
248 
249 
250 /*
251  * HidD_GetPreparsedData						EXPORTED
252  *
253  * @implemented
254  */
255 HIDAPI
256 BOOLEAN WINAPI
257 HidD_GetPreparsedData(IN HANDLE HidDeviceObject,
258                       OUT PHIDP_PREPARSED_DATA *PreparsedData)
259 {
260   HID_COLLECTION_INFORMATION hci;
261   DWORD RetLen;
262   BOOLEAN Ret;
263 
264   if(PreparsedData == NULL)
265   {
266     return FALSE;
267   }
268 
269   if(!DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_COLLECTION_INFORMATION,
270                                        NULL, 0,
271                                        &hci, sizeof(HID_COLLECTION_INFORMATION),
272                                        &RetLen, NULL))
273   {
274     return FALSE;
275   }
276 
277   *PreparsedData = LocalAlloc(LHND, hci.DescriptorSize);
278   if(*PreparsedData == NULL)
279   {
280     SetLastError(ERROR_NOT_ENOUGH_MEMORY);
281     return FALSE;
282   }
283 
284   Ret = DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_COLLECTION_DESCRIPTOR,
285                         NULL, 0,
286                         *PreparsedData, hci.DescriptorSize,
287                         &RetLen, NULL) != 0;
288 
289   if(!Ret)
290   {
291     /* FIXME - Free the buffer in case we failed to get the descriptor? */
292     LocalFree((HLOCAL)*PreparsedData);
293   }
294 #if 0
295   else
296   {
297     /* should we truncate the memory in case RetLen < hci.DescriptorSize? */
298   }
299 #endif
300 
301   return Ret;
302 }
303 
304 
305 /*
306  * HidD_GetProductString						EXPORTED
307  *
308  * @implemented
309  */
310 HIDAPI
311 BOOLEAN WINAPI
312 HidD_GetProductString(IN HANDLE HidDeviceObject,
313                       OUT PVOID Buffer,
314                       IN ULONG BufferLength)
315 {
316   DWORD RetLen;
317   return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_PRODUCT_STRING,
318                          NULL, 0,
319                          Buffer, BufferLength,
320                          &RetLen, NULL) != 0;
321 }
322 
323 
324 /*
325  * HidD_GetSerialNumberString						EXPORTED
326  *
327  * @implemented
328  */
329 HIDAPI
330 BOOLEAN WINAPI
331 HidD_GetSerialNumberString(IN HANDLE HidDeviceObject,
332                            OUT PVOID Buffer,
333                            IN ULONG BufferLength)
334 {
335   DWORD RetLen;
336   return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_SERIALNUMBER_STRING,
337                          NULL, 0,
338                          Buffer, BufferLength,
339                          &RetLen, NULL) != 0;
340 }
341 
342 
343 /*
344  * HidP_GetValueCaps							EXPORTED
345  *
346  * @implemented
347  */
348 HIDAPI
349 NTSTATUS WINAPI
350 HidP_GetValueCaps(IN HIDP_REPORT_TYPE ReportType,
351                   OUT PHIDP_VALUE_CAPS ValueCaps,
352                   IN OUT PUSHORT ValueCapsLength,
353                   IN PHIDP_PREPARSED_DATA PreparsedData)
354 {
355   return HidP_GetSpecificValueCaps(ReportType, 0, 0, 0, ValueCaps,
356                                    ValueCapsLength, PreparsedData);
357 }
358 
359 
360 /*
361  * HidD_Hello								EXPORTED
362  *
363  * Undocumented easter egg function. It fills the buffer with "Hello\n"
364  * and returns number of bytes filled in (lstrlen(Buffer) + 1 == 7)
365  *
366  * Bugs: - doesn't check Buffer for NULL
367  *       - always returns 7 even if BufferLength < 7 but doesn't produce a buffer overflow
368  *
369  * @implemented
370  */
371 HIDAPI
372 ULONG WINAPI
373 HidD_Hello(OUT PCHAR Buffer,
374            IN ULONG BufferLength)
375 {
376   const CHAR HelloString[] = "Hello\n";
377 
378   if(BufferLength > 0)
379   {
380     memcpy(Buffer, HelloString, min(sizeof(HelloString), BufferLength));
381   }
382 
383   return sizeof(HelloString);
384 }
385 
386 
387 /*
388  * HidD_SetFeature							EXPORTED
389  *
390  * @implemented
391  */
392 HIDAPI
393 BOOLEAN WINAPI
394 HidD_SetFeature(IN HANDLE HidDeviceObject,
395                 IN PVOID ReportBuffer,
396                 IN ULONG ReportBufferLength)
397 {
398   DWORD RetLen;
399   return DeviceIoControl(HidDeviceObject, IOCTL_HID_SET_FEATURE,
400                          ReportBuffer, ReportBufferLength,
401                          NULL, 0,
402                          &RetLen, NULL) != 0;
403 }
404 
405 
406 /*
407  * HidD_SetNumInputBuffers						EXPORTED
408  *
409  * @implemented
410  */
411 HIDAPI
412 BOOLEAN WINAPI
413 HidD_SetNumInputBuffers(IN HANDLE HidDeviceObject,
414                         IN ULONG NumberBuffers)
415 {
416   DWORD RetLen;
417   return DeviceIoControl(HidDeviceObject, IOCTL_SET_NUM_DEVICE_INPUT_BUFFERS,
418                          &NumberBuffers, sizeof(ULONG),
419                          NULL, 0,
420                          &RetLen, NULL) != 0;
421 }
422 
423 
424 /*
425  * HidD_SetOutputReport							EXPORTED
426  *
427  * @implemented
428  */
429 HIDAPI
430 BOOLEAN WINAPI
431 HidD_SetOutputReport(IN HANDLE HidDeviceObject,
432                      IN PVOID ReportBuffer,
433                      IN ULONG ReportBufferLength)
434 {
435   DWORD RetLen;
436   return DeviceIoControl(HidDeviceObject, IOCTL_HID_SET_OUTPUT_REPORT,
437                          ReportBuffer, ReportBufferLength,
438                          NULL, 0,
439                          &RetLen, NULL) != 0;
440 }
441 
442 /*
443  * HidD_GetIndexedString							EXPORTED
444  *
445  * @implemented
446  */
447 HIDAPI
448 BOOLEAN WINAPI
449 HidD_GetIndexedString(IN HANDLE HidDeviceObject,
450                       IN ULONG StringIndex,
451                       OUT PVOID Buffer,
452                       IN ULONG BufferLength)
453 {
454   DWORD RetLen;
455   return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_INDEXED_STRING,
456                          &StringIndex, sizeof(ULONG),
457                          Buffer, BufferLength,
458                          &RetLen, NULL) != 0;
459 }
460 
461 /*
462  * HidD_GetMsGenreDescriptor							EXPORTED
463  *
464  * @implemented
465  */
466 HIDAPI
467 BOOLEAN WINAPI
468 HidD_GetMsGenreDescriptor(IN HANDLE HidDeviceObject,
469                           OUT PVOID Buffer,
470                           IN ULONG BufferLength)
471 {
472   DWORD RetLen;
473   return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_MS_GENRE_DESCRIPTOR,
474                          0, 0,
475                          Buffer, BufferLength,
476                          &RetLen, NULL) != 0;
477 }
478 
479 /*
480  * HidD_GetConfiguration							EXPORTED
481  *
482  * @implemented
483  */
484 HIDAPI
485 BOOLEAN WINAPI
486 HidD_GetConfiguration(IN HANDLE HidDeviceObject,
487                       OUT PHIDD_CONFIGURATION Configuration,
488                       IN ULONG ConfigurationLength)
489 {
490 
491   // magic cookie
492   Configuration->cookie = (PVOID)HidD_GetConfiguration;
493 
494   return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_DRIVER_CONFIG,
495                          0, 0,
496                          &Configuration->size, ConfigurationLength - sizeof(ULONG),
497                          (PULONG)&Configuration->cookie, NULL) != 0;
498 }
499 
500 /*
501  * HidD_SetConfiguration							EXPORTED
502  *
503  * @implemented
504  */
505 HIDAPI
506 BOOLEAN WINAPI
507 HidD_SetConfiguration(IN HANDLE HidDeviceObject,
508                       IN PHIDD_CONFIGURATION Configuration,
509                       IN ULONG ConfigurationLength)
510 {
511     BOOLEAN Ret = FALSE;
512 
513     if (Configuration->cookie == (PVOID)HidD_GetConfiguration)
514     {
515         Ret = DeviceIoControl(HidDeviceObject, IOCTL_HID_SET_DRIVER_CONFIG,
516                               0, 0,
517                               (PVOID)&Configuration->size, ConfigurationLength - sizeof(ULONG),
518                               (PULONG)&Configuration->cookie, NULL) != 0;
519     }
520     else
521     {
522         SetLastError(ERROR_INVALID_PARAMETER);
523     }
524 
525     return Ret;
526 }
527 
528 /*
529  * HidP_GetUsagesEx							EXPORTED
530  *
531  * @implemented
532  */
533 HIDAPI
534 NTSTATUS WINAPI
535 HidP_GetUsagesEx(IN HIDP_REPORT_TYPE ReportType,
536                  IN USHORT LinkCollection,
537                  OUT PUSAGE_AND_PAGE ButtonList,
538                  IN OUT ULONG *UsageLength,
539                  IN PHIDP_PREPARSED_DATA PreparsedData,
540                  IN PCHAR Report,
541                  IN ULONG ReportLength)
542 {
543     return HidP_GetUsages(ReportType, ButtonList->UsagePage, LinkCollection, &ButtonList->Usage, UsageLength, PreparsedData, Report, ReportLength);
544 }
545 
546 
547 /* EOF */
548