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