1 /* 2 * PROJECT: ReactOS HID Stack 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: drivers/hid/mouhid/mouhid.c 5 * PURPOSE: Mouse HID Driver 6 * PROGRAMMERS: 7 * Michael Martin (michael.martin@reactos.org) 8 * Johannes Anderwald (johannes.anderwald@reactos.org) 9 */ 10 11 #include "mouhid.h" 12 13 static USHORT MouHid_ButtonDownFlags[] = 14 { 15 MOUSE_LEFT_BUTTON_DOWN, 16 MOUSE_RIGHT_BUTTON_DOWN, 17 MOUSE_MIDDLE_BUTTON_DOWN, 18 MOUSE_BUTTON_4_DOWN, 19 MOUSE_BUTTON_5_DOWN 20 }; 21 22 static USHORT MouHid_ButtonUpFlags[] = 23 { 24 MOUSE_LEFT_BUTTON_UP, 25 MOUSE_RIGHT_BUTTON_UP, 26 MOUSE_MIDDLE_BUTTON_UP, 27 MOUSE_BUTTON_4_UP, 28 MOUSE_BUTTON_5_UP 29 }; 30 31 VOID 32 MouHid_GetButtonFlags( 33 IN PDEVICE_OBJECT DeviceObject, 34 OUT PUSHORT ButtonFlags) 35 { 36 PMOUHID_DEVICE_EXTENSION DeviceExtension; 37 NTSTATUS Status; 38 USAGE Usage; 39 ULONG Index; 40 PUSAGE TempList; 41 ULONG CurrentUsageListLength; 42 43 /* get device extension */ 44 DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 45 46 /* init flags */ 47 *ButtonFlags = 0; 48 49 /* get usages */ 50 CurrentUsageListLength = DeviceExtension->UsageListLength; 51 Status = HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, HIDP_LINK_COLLECTION_UNSPECIFIED, DeviceExtension->CurrentUsageList, &CurrentUsageListLength, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength); 52 if (Status != HIDP_STATUS_SUCCESS) 53 { 54 DPRINT1("MouHid_GetButtonFlags failed to get usages with %x\n", Status); 55 return; 56 } 57 58 /* extract usage list difference */ 59 Status = HidP_UsageListDifference(DeviceExtension->PreviousUsageList, DeviceExtension->CurrentUsageList, DeviceExtension->BreakUsageList, DeviceExtension->MakeUsageList, DeviceExtension->UsageListLength); 60 if (Status != HIDP_STATUS_SUCCESS) 61 { 62 DPRINT1("MouHid_GetButtonFlags failed to get usages with %x\n", Status); 63 return; 64 } 65 66 if (DeviceExtension->UsageListLength) 67 { 68 Index = 0; 69 do 70 { 71 /* get usage */ 72 Usage = DeviceExtension->BreakUsageList[Index]; 73 if (!Usage) 74 break; 75 76 if (Usage <= 5) 77 { 78 /* max 5 buttons supported */ 79 *ButtonFlags |= MouHid_ButtonDownFlags[Usage]; 80 } 81 82 /* move to next index*/ 83 Index++; 84 }while(Index < DeviceExtension->UsageListLength); 85 } 86 87 if (DeviceExtension->UsageListLength) 88 { 89 Index = 0; 90 do 91 { 92 /* get usage */ 93 Usage = DeviceExtension->MakeUsageList[Index]; 94 if (!Usage) 95 break; 96 97 if (Usage <= 5) 98 { 99 /* max 5 buttons supported */ 100 *ButtonFlags |= MouHid_ButtonUpFlags[Usage]; 101 } 102 103 /* move to next index*/ 104 Index++; 105 }while(Index < DeviceExtension->UsageListLength); 106 } 107 108 /* now switch the previous list with current list */ 109 TempList = DeviceExtension->CurrentUsageList; 110 DeviceExtension->CurrentUsageList = DeviceExtension->PreviousUsageList; 111 DeviceExtension->PreviousUsageList = TempList; 112 } 113 114 VOID 115 MouHid_DispatchInputData( 116 IN PDEVICE_OBJECT DeviceObject, 117 IN PMOUSE_INPUT_DATA InputData) 118 { 119 PMOUHID_DEVICE_EXTENSION DeviceExtension; 120 KIRQL OldIrql; 121 ULONG InputDataConsumed; 122 123 /* get device extension */ 124 DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 125 126 /* sanity check */ 127 ASSERT(DeviceExtension->ClassService); 128 ASSERT(DeviceExtension->ClassDeviceObject); 129 130 /* raise irql */ 131 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 132 133 /* dispatch input data */ 134 (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassService)(DeviceExtension->ClassDeviceObject, InputData, InputData + 1, &InputDataConsumed); 135 136 /* lower irql to previous level */ 137 KeLowerIrql(OldIrql); 138 } 139 140 141 142 NTSTATUS 143 NTAPI 144 MouHid_Create( 145 IN PDEVICE_OBJECT DeviceObject, 146 IN PIRP Irp) 147 { 148 UNIMPLEMENTED 149 ASSERT(FALSE); 150 return STATUS_NOT_IMPLEMENTED; 151 } 152 153 154 NTSTATUS 155 NTAPI 156 MouHid_Close( 157 IN PDEVICE_OBJECT DeviceObject, 158 IN PIRP Irp) 159 { 160 UNIMPLEMENTED 161 ASSERT(FALSE); 162 return STATUS_NOT_IMPLEMENTED; 163 } 164 165 NTSTATUS 166 NTAPI 167 MouHid_DeviceControl( 168 IN PDEVICE_OBJECT DeviceObject, 169 IN PIRP Irp) 170 { 171 PIO_STACK_LOCATION IoStack; 172 PMOUSE_ATTRIBUTES Attributes; 173 PMOUHID_DEVICE_EXTENSION DeviceExtension; 174 PCONNECT_DATA Data; 175 176 /* get current stack location */ 177 IoStack = IoGetCurrentIrpStackLocation(Irp); 178 179 /* get device extension */ 180 DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 181 182 /* handle requests */ 183 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_MOUSE_QUERY_ATTRIBUTES) 184 { 185 /* verify output buffer length */ 186 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUSE_ATTRIBUTES)) 187 { 188 /* invalid request */ 189 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; 190 IoCompleteRequest(Irp, IO_NO_INCREMENT); 191 return STATUS_BUFFER_TOO_SMALL; 192 } 193 194 /* get output buffer */ 195 Attributes = (PMOUSE_ATTRIBUTES)Irp->AssociatedIrp.SystemBuffer; 196 197 /* type of mouse */ 198 Attributes->MouseIdentifier = DeviceExtension->MouseIdentifier; 199 200 /* number of buttons */ 201 Attributes->NumberOfButtons = DeviceExtension->UsageListLength; 202 203 /* sample rate not used for usb */ 204 Attributes->SampleRate = 0; 205 206 /* queue length */ 207 Attributes->InputDataQueueLength = 2; 208 209 /* complete request */ 210 Irp->IoStatus.Information = sizeof(MOUSE_ATTRIBUTES); 211 Irp->IoStatus.Status = STATUS_SUCCESS; 212 IoCompleteRequest(Irp, IO_NO_INCREMENT); 213 return STATUS_SUCCESS; 214 } 215 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_MOUSE_CONNECT) 216 { 217 /* verify input buffer length */ 218 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA)) 219 { 220 /* invalid request */ 221 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 222 IoCompleteRequest(Irp, IO_NO_INCREMENT); 223 return STATUS_INVALID_PARAMETER; 224 } 225 226 /* is it already connected */ 227 if (DeviceExtension->ClassService) 228 { 229 /* already connected */ 230 Irp->IoStatus.Status = STATUS_SHARING_VIOLATION; 231 IoCompleteRequest(Irp, IO_NO_INCREMENT); 232 return STATUS_SHARING_VIOLATION; 233 } 234 235 /* get connect data */ 236 Data = (PCONNECT_DATA)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; 237 238 /* store connect details */ 239 DeviceExtension->ClassDeviceObject = Data->ClassDeviceObject; 240 DeviceExtension->ClassService = Data->ClassService; 241 242 /* completed successfully */ 243 Irp->IoStatus.Status = STATUS_SUCCESS; 244 IoCompleteRequest(Irp, IO_NO_INCREMENT); 245 return STATUS_SUCCESS; 246 } 247 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_MOUSE_DISCONNECT) 248 { 249 /* not supported */ 250 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; 251 IoCompleteRequest(Irp, IO_NO_INCREMENT); 252 return STATUS_NOT_IMPLEMENTED; 253 } 254 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_MOUSE_ENABLE) 255 { 256 /* not supported */ 257 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; 258 IoCompleteRequest(Irp, IO_NO_INCREMENT); 259 return STATUS_NOT_SUPPORTED; 260 } 261 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_MOUSE_DISABLE) 262 { 263 /* not supported */ 264 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; 265 IoCompleteRequest(Irp, IO_NO_INCREMENT); 266 return STATUS_INVALID_DEVICE_REQUEST; 267 } 268 269 /* unknown request not supported */ 270 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; 271 IoCompleteRequest(Irp, IO_NO_INCREMENT); 272 return STATUS_NOT_SUPPORTED; 273 } 274 275 NTSTATUS 276 NTAPI 277 MouHid_InternalDeviceControl( 278 IN PDEVICE_OBJECT DeviceObject, 279 IN PIRP Irp) 280 { 281 PMOUHID_DEVICE_EXTENSION DeviceExtension; 282 283 /* get device extension */ 284 DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 285 286 /* skip stack location */ 287 IoSkipCurrentIrpStackLocation(Irp); 288 289 /* pass and forget */ 290 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp); 291 } 292 293 NTSTATUS 294 NTAPI 295 MouHid_Power( 296 IN PDEVICE_OBJECT DeviceObject, 297 IN PIRP Irp) 298 { 299 UNIMPLEMENTED 300 ASSERT(FALSE); 301 return STATUS_NOT_IMPLEMENTED; 302 } 303 304 NTSTATUS 305 MouHid_SubmitRequest( 306 PDEVICE_OBJECT DeviceObject, 307 ULONG IoControlCode, 308 ULONG InputBufferSize, 309 PVOID InputBuffer, 310 ULONG OutputBufferSize, 311 PVOID OutputBuffer) 312 { 313 KEVENT Event; 314 PMOUHID_DEVICE_EXTENSION DeviceExtension; 315 PIRP Irp; 316 NTSTATUS Status; 317 IO_STATUS_BLOCK IoStatus; 318 319 /* get device extension */ 320 DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 321 322 /* init event */ 323 KeInitializeEvent(&Event, NotificationEvent, FALSE); 324 325 /* build request */ 326 Irp = IoBuildDeviceIoControlRequest(IoControlCode, DeviceExtension->NextDeviceObject, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize, FALSE, &Event, &IoStatus); 327 if (!Irp) 328 { 329 /* no memory */ 330 return STATUS_INSUFFICIENT_RESOURCES; 331 } 332 333 /* send request */ 334 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp); 335 if (Status == STATUS_PENDING) 336 { 337 /* wait for request to complete */ 338 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 339 Status = IoStatus.Status; 340 } 341 342 /* done */ 343 return Status; 344 } 345 346 NTSTATUS 347 NTAPI 348 MouHid_StartDevice( 349 IN PDEVICE_OBJECT DeviceObject) 350 { 351 NTSTATUS Status; 352 ULONG Buttons; 353 HID_COLLECTION_INFORMATION Information; 354 PVOID PreparsedData; 355 HIDP_CAPS Capabilities; 356 ULONG ValueCapsLength; 357 HIDP_VALUE_CAPS ValueCaps; 358 PMOUHID_DEVICE_EXTENSION DeviceExtension; 359 PUSHORT Buffer; 360 361 /* get device extension */ 362 DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 363 364 /* query collection information */ 365 Status = MouHid_SubmitRequest(DeviceObject, IOCTL_HID_GET_COLLECTION_INFORMATION, 0, NULL, sizeof(HID_COLLECTION_INFORMATION), &Information); 366 if (!NT_SUCCESS(Status)) 367 { 368 /* failed to query collection information */ 369 return Status; 370 } 371 372 /* lets allocate space for preparsed data */ 373 PreparsedData = ExAllocatePool(NonPagedPool, Information.DescriptorSize); 374 if (PreparsedData) 375 { 376 /* no memory */ 377 return STATUS_INSUFFICIENT_RESOURCES; 378 } 379 380 /* now obtain the preparsed data */ 381 Status = MouHid_SubmitRequest(DeviceObject, IOCTL_HID_GET_DRIVER_CONFIG, 0, NULL, Information.DescriptorSize, PreparsedData); 382 if (!NT_SUCCESS(Status)) 383 { 384 /* failed to get preparsed data */ 385 ExFreePool(PreparsedData); 386 return Status; 387 } 388 389 /* lets get the caps */ 390 Status = HidP_GetCaps(PreparsedData, &Capabilities); 391 if (!NT_SUCCESS(Status)) 392 { 393 /* failed to get capabilities */ 394 ExFreePool(PreparsedData); 395 return Status; 396 } 397 398 /* verify capabilities */ 399 if (Capabilities.Usage != HID_USAGE_GENERIC_POINTER && Capabilities.Usage != HID_USAGE_GENERIC_MOUSE || Capabilities.UsagePage != HID_USAGE_PAGE_GENERIC) 400 { 401 /* not supported */ 402 ExFreePool(PreparsedData); 403 return STATUS_UNSUCCESSFUL; 404 } 405 406 /* init input report*/ 407 DeviceExtension->ReportLength = Capabilities.InputReportByteLength; 408 ASSERT(DeviceExtension->ReportLength); 409 DeviceExtension->Report = (PUCHAR)ExAllocatePool(NonPagedPool, DeviceExtension->ReportLength); 410 ASSERT(DeviceExtension->Report); 411 RtlZeroMemory(DeviceExtension->Report, DeviceExtension->ReportLength); 412 DeviceExtension->ReportMDL = IoAllocateMdl(DeviceExtension->Report, DeviceExtension->ReportLength, FALSE, FALSE, NULL); 413 ASSERT(DeviceExtension->ReportMDL); 414 415 416 /* get max number of buttons */ 417 Buttons = HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_BUTTON, PreparsedData); 418 ASSERT(Buttons > 0); 419 420 /* now allocate an array for those buttons */ 421 Buffer = ExAllocatePool(NonPagedPool, sizeof(USAGE) * 4 * Buttons); 422 if (!Buffer) 423 { 424 /* no memory */ 425 ExFreePool(PreparsedData); 426 return STATUS_INSUFFICIENT_RESOURCES; 427 } 428 429 /* init usage lists */ 430 RtlZeroMemory(Buffer, sizeof(USAGE) * 4 * Buttons); 431 DeviceExtension->CurrentUsageList = Buffer; 432 Buffer += Buttons; 433 DeviceExtension->PreviousUsageList = Buffer; 434 Buffer += Buttons; 435 DeviceExtension->MakeUsageList = Buffer; 436 Buffer += Buttons; 437 DeviceExtension->BreakUsageList = Buffer; 438 439 /* store number of buttons */ 440 DeviceExtension->UsageListLength = (USHORT)Buttons; 441 442 /* store preparsed data */ 443 DeviceExtension->PreparsedData = PreparsedData; 444 445 ValueCapsLength = 1; 446 HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_X, &ValueCaps, &ValueCapsLength, PreparsedData); 447 448 ValueCapsLength = 1; 449 HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Y, &ValueCaps, &ValueCapsLength, PreparsedData); 450 451 /* now check for wheel mouse support */ 452 ValueCapsLength = 1; 453 Status = HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_WHEEL, &ValueCaps, &ValueCapsLength, PreparsedData); 454 if (Status == HIDP_STATUS_SUCCESS ) 455 { 456 /* mouse has wheel support */ 457 DeviceExtension->MouseIdentifier = WHEELMOUSE_HID_HARDWARE; 458 DeviceExtension->WheelUsagePage = ValueCaps.UsagePage; 459 } 460 else 461 { 462 /* check if the mouse has z-axis */ 463 ValueCapsLength = 1; 464 Status = HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Z, &ValueCaps, &ValueCapsLength, PreparsedData); 465 if (Status == HIDP_STATUS_SUCCESS && ValueCapsLength == 1) 466 { 467 /* wheel support */ 468 DeviceExtension->MouseIdentifier = WHEELMOUSE_HID_HARDWARE; 469 DeviceExtension->WheelUsagePage = ValueCaps.UsagePage; 470 } 471 } 472 473 /* completed successfully */ 474 return STATUS_SUCCESS; 475 } 476 477 NTSTATUS 478 NTAPI 479 MouHid_StartDeviceCompletion( 480 IN PDEVICE_OBJECT DeviceObject, 481 IN PIRP Irp, 482 IN PVOID Context) 483 { 484 KeSetEvent((PKEVENT)Context, 0, FALSE); 485 return STATUS_MORE_PROCESSING_REQUIRED; 486 } 487 488 NTSTATUS 489 NTAPI 490 MouHid_Pnp( 491 IN PDEVICE_OBJECT DeviceObject, 492 IN PIRP Irp) 493 { 494 PIO_STACK_LOCATION IoStack; 495 KEVENT Event; 496 NTSTATUS Status; 497 PMOUHID_DEVICE_EXTENSION DeviceExtension; 498 499 /* get device extension */ 500 DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 501 502 /* get current irp stack */ 503 IoStack = IoGetCurrentIrpStackLocation(Irp); 504 505 if (IoStack->MinorFunction == IRP_MN_STOP_DEVICE || IoStack->MinorFunction == IRP_MN_CANCEL_REMOVE_DEVICE || IoStack->MinorFunction == IRP_MN_QUERY_STOP_DEVICE || IoStack->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE) 506 { 507 /* indicate success */ 508 Irp->IoStatus.Status = STATUS_SUCCESS; 509 510 /* skip irp stack location */ 511 IoSkipCurrentIrpStackLocation(Irp); 512 513 /* dispatch to lower device */ 514 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp); 515 } 516 else if (IoStack->MinorFunction == IRP_MN_REMOVE_DEVICE) 517 { 518 /* FIXME synchronization */ 519 520 /* cancel irp */ 521 IoCancelIrp(DeviceExtension->Irp); 522 523 /* indicate success */ 524 Irp->IoStatus.Status = STATUS_SUCCESS; 525 526 /* skip irp stack location */ 527 IoSkipCurrentIrpStackLocation(Irp); 528 529 /* dispatch to lower device */ 530 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp); 531 532 IoFreeIrp(DeviceExtension->Irp); 533 IoDetachDevice(DeviceExtension->NextDeviceObject); 534 IoDeleteDevice(DeviceObject); 535 return Status; 536 } 537 else if (IoStack->MinorFunction == IRP_MN_START_DEVICE) 538 { 539 /* init event */ 540 KeInitializeEvent(&Event, NotificationEvent, FALSE); 541 542 /* copy stack location */ 543 IoCopyCurrentIrpStackLocationToNext (Irp); 544 545 /* set completion routine */ 546 IoSetCompletionRoutine(Irp, MouHid_StartDeviceCompletion, &Event, TRUE, TRUE, TRUE); 547 Irp->IoStatus.Status = 0; 548 549 /* pass request */ 550 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp); 551 if (Status == STATUS_PENDING) 552 { 553 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 554 Status = Irp->IoStatus.Status; 555 } 556 557 if (!NT_SUCCESS(Status)) 558 { 559 /* failed */ 560 Irp->IoStatus.Status = Status; 561 IoCompleteRequest(Irp, IO_NO_INCREMENT); 562 return Status; 563 } 564 565 /* lets start the device */ 566 Status = MouHid_StartDevice(DeviceObject); 567 DPRINT1("MouHid_StartDevice %x\n", Status); 568 569 /* complete request */ 570 Irp->IoStatus.Status = Status; 571 IoCompleteRequest(Irp, IO_NO_INCREMENT); 572 573 /* done */ 574 return Status; 575 } 576 else 577 { 578 /* skip irp stack location */ 579 IoSkipCurrentIrpStackLocation(Irp); 580 581 /* dispatch to lower device */ 582 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp); 583 } 584 } 585 586 NTSTATUS 587 NTAPI 588 MouHid_AddDevice( 589 IN PDRIVER_OBJECT DriverObject, 590 IN PDEVICE_OBJECT PhysicalDeviceObject) 591 { 592 NTSTATUS Status; 593 PDEVICE_OBJECT DeviceObject, NextDeviceObject; 594 PMOUHID_DEVICE_EXTENSION DeviceExtension; 595 POWER_STATE State; 596 597 /* create device object */ 598 Status = IoCreateDevice(DriverObject, sizeof(MOUHID_DEVICE_EXTENSION), NULL, FILE_DEVICE_MOUSE, 0, FALSE, &DeviceObject); 599 if (!NT_SUCCESS(Status)) 600 { 601 /* failed to create device object */ 602 return Status; 603 } 604 605 /* now attach it */ 606 NextDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject); 607 if (!NextDeviceObject) 608 { 609 /* failed to attach */ 610 IoDeleteDevice(DeviceObject); 611 return STATUS_DEVICE_NOT_CONNECTED; 612 } 613 614 /* get device extension */ 615 DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 616 617 /* zero extension */ 618 RtlZeroMemory(DeviceExtension, sizeof(MOUHID_DEVICE_EXTENSION)); 619 620 /* init device extension */ 621 DeviceExtension->MouseIdentifier = MOUSE_HID_HARDWARE; 622 DeviceExtension->WheelUsagePage = 0; 623 DeviceExtension->NextDeviceObject = NextDeviceObject; 624 KeInitializeEvent(&DeviceExtension->Event, NotificationEvent, FALSE); 625 DeviceExtension->Irp = IoAllocateIrp(NextDeviceObject->StackSize, FALSE); 626 627 /* FIXME handle allocation error */ 628 ASSERT(DeviceExtension->Irp); 629 630 /* FIXME query parameter 'FlipFlopWheel', 'WheelScalingFactor' */ 631 632 /* set power state to D0 */ 633 State.DeviceState = PowerDeviceD0; 634 PoSetPowerState(DeviceObject, DevicePowerState, State); 635 636 /* init device object */ 637 DeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE; 638 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 639 640 /* completed successfully */ 641 return STATUS_SUCCESS; 642 } 643 644 VOID 645 NTAPI 646 MouHid_Unload( 647 IN PDRIVER_OBJECT DriverObject) 648 { 649 UNIMPLEMENTED 650 ASSERT(FALSE); 651 } 652 653 654 NTSTATUS 655 NTAPI 656 DriverEntry( 657 IN PDRIVER_OBJECT DriverObject, 658 IN PUNICODE_STRING RegPath) 659 { 660 /* FIXME check for parameters 'UseOnlyMice', 'TreatAbsoluteAsRelative', 'TreatAbsolutePointerAsAbsolute' */ 661 662 /* initialize driver object */ 663 DriverObject->DriverUnload = MouHid_Unload; 664 DriverObject->DriverExtension->AddDevice = MouHid_AddDevice; 665 DriverObject->MajorFunction[IRP_MJ_CREATE] = MouHid_Create; 666 DriverObject->MajorFunction[IRP_MJ_CLOSE] = MouHid_Close; 667 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MouHid_DeviceControl; 668 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = MouHid_InternalDeviceControl; 669 DriverObject->MajorFunction[IRP_MJ_POWER] = MouHid_Power; 670 DriverObject->MajorFunction[IRP_MJ_PNP] = MouHid_Pnp; 671 DriverObject->DriverUnload = MouHid_Unload; 672 DriverObject->DriverExtension->AddDevice = MouHid_AddDevice; 673 674 /* done */ 675 return STATUS_SUCCESS; 676 } 677