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