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
AllocFunction(IN ULONG ItemSize)45 AllocFunction(
46 IN ULONG ItemSize)
47 {
48 return LocalAlloc(LHND, ItemSize);
49 }
50
51 VOID
52 NTAPI
FreeFunction(IN PVOID Item)53 FreeFunction(
54 IN PVOID Item)
55 {
56 LocalFree((HLOCAL)Item);
57 }
58
59 VOID
60 NTAPI
ZeroFunction(IN PVOID Item,IN ULONG ItemSize)61 ZeroFunction(
62 IN PVOID Item,
63 IN ULONG ItemSize)
64 {
65 memset(Item, 0, ItemSize);
66 }
67
68 VOID
69 NTAPI
CopyFunction(IN PVOID Target,IN PVOID Source,IN ULONG Length)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
DebugFunction(IN LPCSTR FormatStr,...)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
DllMain(HINSTANCE hinstDLL,DWORD dwReason,LPVOID lpvReserved)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
HidD_FlushQueue(IN HANDLE HidDeviceObject)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
HidD_FreePreparsedData(IN PHIDP_PREPARSED_DATA PreparsedData)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
HidD_GetAttributes(IN HANDLE HidDeviceObject,OUT PHIDD_ATTRIBUTES Attributes)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
HidD_GetFeature(IN HANDLE HidDeviceObject,OUT PVOID ReportBuffer,IN ULONG ReportBufferLength)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
HidD_GetHidGuid(OUT LPGUID HidGuid)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
HidD_GetInputReport(IN HANDLE HidDeviceObject,IN OUT PVOID ReportBuffer,IN ULONG ReportBufferLength)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
HidD_GetManufacturerString(IN HANDLE HidDeviceObject,OUT PVOID Buffer,IN ULONG BufferLength)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
HidD_GetNumInputBuffers(IN HANDLE HidDeviceObject,OUT PULONG NumberBuffers)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
HidD_GetPhysicalDescriptor(IN HANDLE HidDeviceObject,OUT PVOID Buffer,IN ULONG BufferLength)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
HidD_GetPreparsedData(IN HANDLE HidDeviceObject,OUT PHIDP_PREPARSED_DATA * PreparsedData)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
HidD_GetProductString(IN HANDLE HidDeviceObject,OUT PVOID Buffer,IN ULONG BufferLength)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
HidD_GetSerialNumberString(IN HANDLE HidDeviceObject,OUT PVOID Buffer,IN ULONG BufferLength)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
HidD_Hello(OUT PCHAR Buffer,IN ULONG BufferLength)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
HidD_SetFeature(IN HANDLE HidDeviceObject,IN PVOID ReportBuffer,IN ULONG ReportBufferLength)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
HidD_SetNumInputBuffers(IN HANDLE HidDeviceObject,IN ULONG NumberBuffers)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
HidD_SetOutputReport(IN HANDLE HidDeviceObject,IN PVOID ReportBuffer,IN ULONG ReportBufferLength)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
HidD_GetIndexedString(IN HANDLE HidDeviceObject,IN ULONG StringIndex,OUT PVOID Buffer,IN ULONG BufferLength)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
HidD_GetMsGenreDescriptor(IN HANDLE HidDeviceObject,OUT PVOID Buffer,IN ULONG BufferLength)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
HidD_GetConfiguration(IN HANDLE HidDeviceObject,OUT PHIDD_CONFIGURATION Configuration,IN ULONG ConfigurationLength)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
HidD_SetConfiguration(IN HANDLE HidDeviceObject,IN PHIDD_CONFIGURATION Configuration,IN ULONG ConfigurationLength)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