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