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
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
13 static USHORT MouHid_ButtonDownFlags
[] =
15 MOUSE_LEFT_BUTTON_DOWN
,
16 MOUSE_RIGHT_BUTTON_DOWN
,
17 MOUSE_MIDDLE_BUTTON_DOWN
,
22 static USHORT MouHid_ButtonUpFlags
[] =
25 MOUSE_RIGHT_BUTTON_UP
,
26 MOUSE_MIDDLE_BUTTON_UP
,
32 MouHid_GetButtonFlags(
33 IN PDEVICE_OBJECT DeviceObject
,
34 OUT PUSHORT ButtonFlags
)
36 PMOUHID_DEVICE_EXTENSION DeviceExtension
;
41 ULONG CurrentUsageListLength
;
43 /* get device extension */
44 DeviceExtension
= (PMOUHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
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
)
54 DPRINT1("MouHid_GetButtonFlags failed to get usages with %x\n", Status
);
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
)
62 DPRINT1("MouHid_GetButtonFlags failed to get usages with %x\n", Status
);
66 if (DeviceExtension
->UsageListLength
)
72 Usage
= DeviceExtension
->BreakUsageList
[Index
];
78 /* max 5 buttons supported */
79 *ButtonFlags
|= MouHid_ButtonDownFlags
[Usage
];
82 /* move to next index*/
84 }while(Index
< DeviceExtension
->UsageListLength
);
87 if (DeviceExtension
->UsageListLength
)
93 Usage
= DeviceExtension
->MakeUsageList
[Index
];
99 /* max 5 buttons supported */
100 *ButtonFlags
|= MouHid_ButtonUpFlags
[Usage
];
103 /* move to next index*/
105 }while(Index
< DeviceExtension
->UsageListLength
);
108 /* now switch the previous list with current list */
109 TempList
= DeviceExtension
->CurrentUsageList
;
110 DeviceExtension
->CurrentUsageList
= DeviceExtension
->PreviousUsageList
;
111 DeviceExtension
->PreviousUsageList
= TempList
;
115 MouHid_DispatchInputData(
116 IN PDEVICE_OBJECT DeviceObject
,
117 IN PMOUSE_INPUT_DATA InputData
)
119 PMOUHID_DEVICE_EXTENSION DeviceExtension
;
121 ULONG InputDataConsumed
;
123 /* get device extension */
124 DeviceExtension
= (PMOUHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
127 ASSERT(DeviceExtension
->ClassService
);
128 ASSERT(DeviceExtension
->ClassDeviceObject
);
131 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
133 /* dispatch input data */
134 (*(PSERVICE_CALLBACK_ROUTINE
)DeviceExtension
->ClassService
)(DeviceExtension
->ClassDeviceObject
, InputData
, InputData
+ 1, &InputDataConsumed
);
136 /* lower irql to previous level */
137 KeLowerIrql(OldIrql
);
142 MouHid_ReadCompletion(
143 IN PDEVICE_OBJECT DeviceObject
,
147 PMOUHID_DEVICE_EXTENSION DeviceExtension
;
149 MOUSE_INPUT_DATA MouseInputData
;
151 /* get device extension */
152 DeviceExtension
= (PMOUHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
154 /* get mouse change flags */
155 MouHid_GetButtonFlags(DeviceObject
, &ButtonFlags
);
157 /* FIXME detect mouse move change */
158 /* FIXME detect mouse wheel change */
160 /* init input data */
161 RtlZeroMemory(&MouseInputData
, sizeof(MOUSE_INPUT_DATA
));
163 /* init input data */
164 MouseInputData
.ButtonFlags
= ButtonFlags
;
166 /* dispatch mouse action */
167 MouHid_DispatchInputData(DeviceObject
, &MouseInputData
);
170 MouHid_InitiateRead(DeviceObject
);
172 /* stop completion */
173 return STATUS_MORE_PROCESSING_REQUIRED
;
178 IN PDEVICE_OBJECT DeviceObject
)
180 PMOUHID_DEVICE_EXTENSION DeviceExtension
;
181 PIO_STACK_LOCATION IoStack
;
184 /* get device extension */
185 DeviceExtension
= (PMOUHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
188 IoReuseIrp(DeviceExtension
->Irp
, STATUS_SUCCESS
);
191 DeviceExtension
->Irp
->MdlAddress
= DeviceExtension
->ReportMDL
;
193 /* get next stack location */
194 IoStack
= IoGetNextIrpStackLocation(DeviceExtension
->Irp
);
196 /* init stack location */
197 IoStack
->Parameters
.Read
.Length
= DeviceExtension
->ReportLength
;
198 IoStack
->Parameters
.Read
.Key
= 0;
199 IoStack
->Parameters
.Read
.ByteOffset
.QuadPart
= 0LL;
200 IoStack
->MajorFunction
= IRP_MJ_READ
;
201 IoStack
->FileObject
= DeviceExtension
->FileObject
;
203 /* set completion routine */
204 IoSetCompletionRoutine(DeviceExtension
->Irp
, MouHid_ReadCompletion
, DeviceExtension
, TRUE
, TRUE
, TRUE
);
207 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, DeviceExtension
->Irp
);
215 MouHid_CreateCompletion(
216 IN PDEVICE_OBJECT DeviceObject
,
220 KeSetEvent((PKEVENT
)Context
, 0, FALSE
);
221 return STATUS_MORE_PROCESSING_REQUIRED
;
228 IN PDEVICE_OBJECT DeviceObject
,
231 PIO_STACK_LOCATION IoStack
;
234 PMOUHID_DEVICE_EXTENSION DeviceExtension
;
236 DPRINT1("MOUHID: IRP_MJ_CREATE\n");
238 /* get device extension */
239 DeviceExtension
= (PMOUHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
241 /* get stack location */
242 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
244 /* copy stack location to next */
245 IoCopyCurrentIrpStackLocationToNext(Irp
);
248 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
251 IoSetCompletionRoutine(Irp
, MouHid_CreateCompletion
, &Event
, TRUE
, TRUE
, TRUE
);
253 /* call lower driver */
254 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
255 if (Status
== STATUS_PENDING
)
257 /* request pending */
258 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
261 /* check for success */
262 if (!NT_SUCCESS(Status
))
265 Irp
->IoStatus
.Status
= Status
;
266 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
270 /* is the driver already in use */
271 if (DeviceExtension
->FileObject
== NULL
)
273 /* did the caller specify correct attributes */
274 if (IoStack
->Parameters
.Create
.FileAttributes
& FILE_ATTRIBUTE_READONLY
)
276 /* store file object */
277 DeviceExtension
->FileObject
= IoStack
->FileObject
;
279 /* initiating read */
280 Status
= MouHid_InitiateRead(DeviceObject
);
285 DPRINT1("MOUHID: wrong attributes: %x\n", IoStack
->Parameters
.Create
.FileAttributes
);
289 /* complete request */
290 Irp
->IoStatus
.Status
= Status
;
291 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
299 IN PDEVICE_OBJECT DeviceObject
,
302 PMOUHID_DEVICE_EXTENSION DeviceExtension
;
304 /* get device extension */
305 DeviceExtension
= (PMOUHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
307 /* FIXME: cancel irp */
309 /* remove file object */
310 DeviceExtension
->FileObject
= NULL
;
313 IoSkipCurrentIrpStackLocation(Irp
);
315 /* pass irp to down the stack */
316 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
321 MouHid_DeviceControl(
322 IN PDEVICE_OBJECT DeviceObject
,
325 PIO_STACK_LOCATION IoStack
;
326 PMOUSE_ATTRIBUTES Attributes
;
327 PMOUHID_DEVICE_EXTENSION DeviceExtension
;
330 /* get current stack location */
331 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
333 /* get device extension */
334 DeviceExtension
= (PMOUHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
336 /* handle requests */
337 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_MOUSE_QUERY_ATTRIBUTES
)
339 /* verify output buffer length */
340 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(MOUSE_ATTRIBUTES
))
342 /* invalid request */
343 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
344 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
345 return STATUS_BUFFER_TOO_SMALL
;
348 /* get output buffer */
349 Attributes
= (PMOUSE_ATTRIBUTES
)Irp
->AssociatedIrp
.SystemBuffer
;
352 Attributes
->MouseIdentifier
= DeviceExtension
->MouseIdentifier
;
354 /* number of buttons */
355 Attributes
->NumberOfButtons
= DeviceExtension
->UsageListLength
;
357 /* sample rate not used for usb */
358 Attributes
->SampleRate
= 0;
361 Attributes
->InputDataQueueLength
= 2;
363 /* complete request */
364 Irp
->IoStatus
.Information
= sizeof(MOUSE_ATTRIBUTES
);
365 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
366 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
367 return STATUS_SUCCESS
;
369 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_MOUSE_CONNECT
)
371 /* verify input buffer length */
372 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(CONNECT_DATA
))
374 /* invalid request */
375 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
376 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
377 return STATUS_INVALID_PARAMETER
;
380 /* is it already connected */
381 if (DeviceExtension
->ClassService
)
383 /* already connected */
384 Irp
->IoStatus
.Status
= STATUS_SHARING_VIOLATION
;
385 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
386 return STATUS_SHARING_VIOLATION
;
389 /* get connect data */
390 Data
= (PCONNECT_DATA
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
392 /* store connect details */
393 DeviceExtension
->ClassDeviceObject
= Data
->ClassDeviceObject
;
394 DeviceExtension
->ClassService
= Data
->ClassService
;
396 /* completed successfully */
397 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
398 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
399 return STATUS_SUCCESS
;
401 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_MOUSE_DISCONNECT
)
404 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
405 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
406 return STATUS_NOT_IMPLEMENTED
;
408 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_MOUSE_ENABLE
)
411 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
412 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
413 return STATUS_NOT_SUPPORTED
;
415 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_MOUSE_DISABLE
)
418 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
419 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
420 return STATUS_INVALID_DEVICE_REQUEST
;
423 /* unknown request not supported */
424 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
425 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
426 return STATUS_NOT_SUPPORTED
;
431 MouHid_InternalDeviceControl(
432 IN PDEVICE_OBJECT DeviceObject
,
435 PMOUHID_DEVICE_EXTENSION DeviceExtension
;
437 /* get device extension */
438 DeviceExtension
= (PMOUHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
440 /* skip stack location */
441 IoSkipCurrentIrpStackLocation(Irp
);
443 /* pass and forget */
444 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
450 IN PDEVICE_OBJECT DeviceObject
,
455 return STATUS_NOT_IMPLEMENTED
;
459 MouHid_SubmitRequest(
460 PDEVICE_OBJECT DeviceObject
,
462 ULONG InputBufferSize
,
464 ULONG OutputBufferSize
,
468 PMOUHID_DEVICE_EXTENSION DeviceExtension
;
471 IO_STATUS_BLOCK IoStatus
;
473 /* get device extension */
474 DeviceExtension
= (PMOUHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
477 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
480 Irp
= IoBuildDeviceIoControlRequest(IoControlCode
, DeviceExtension
->NextDeviceObject
, InputBuffer
, InputBufferSize
, OutputBuffer
, OutputBufferSize
, FALSE
, &Event
, &IoStatus
);
484 return STATUS_INSUFFICIENT_RESOURCES
;
488 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
489 if (Status
== STATUS_PENDING
)
491 /* wait for request to complete */
492 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
493 Status
= IoStatus
.Status
;
503 IN PDEVICE_OBJECT DeviceObject
)
507 HID_COLLECTION_INFORMATION Information
;
509 HIDP_CAPS Capabilities
;
510 ULONG ValueCapsLength
;
511 HIDP_VALUE_CAPS ValueCaps
;
512 PMOUHID_DEVICE_EXTENSION DeviceExtension
;
515 /* get device extension */
516 DeviceExtension
= (PMOUHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
518 /* query collection information */
519 Status
= MouHid_SubmitRequest(DeviceObject
, IOCTL_HID_GET_COLLECTION_INFORMATION
, 0, NULL
, sizeof(HID_COLLECTION_INFORMATION
), &Information
);
520 if (!NT_SUCCESS(Status
))
522 /* failed to query collection information */
526 /* lets allocate space for preparsed data */
527 PreparsedData
= ExAllocatePool(NonPagedPool
, Information
.DescriptorSize
);
531 return STATUS_INSUFFICIENT_RESOURCES
;
534 /* now obtain the preparsed data */
535 Status
= MouHid_SubmitRequest(DeviceObject
, IOCTL_HID_GET_DRIVER_CONFIG
, 0, NULL
, Information
.DescriptorSize
, PreparsedData
);
536 if (!NT_SUCCESS(Status
))
538 /* failed to get preparsed data */
539 ExFreePool(PreparsedData
);
543 /* lets get the caps */
544 Status
= HidP_GetCaps(PreparsedData
, &Capabilities
);
545 if (!NT_SUCCESS(Status
))
547 /* failed to get capabilities */
548 ExFreePool(PreparsedData
);
552 /* verify capabilities */
553 if (Capabilities
.Usage
!= HID_USAGE_GENERIC_POINTER
&& Capabilities
.Usage
!= HID_USAGE_GENERIC_MOUSE
|| Capabilities
.UsagePage
!= HID_USAGE_PAGE_GENERIC
)
556 ExFreePool(PreparsedData
);
557 return STATUS_UNSUCCESSFUL
;
560 /* init input report*/
561 DeviceExtension
->ReportLength
= Capabilities
.InputReportByteLength
;
562 ASSERT(DeviceExtension
->ReportLength
);
563 DeviceExtension
->Report
= (PUCHAR
)ExAllocatePool(NonPagedPool
, DeviceExtension
->ReportLength
);
564 ASSERT(DeviceExtension
->Report
);
565 RtlZeroMemory(DeviceExtension
->Report
, DeviceExtension
->ReportLength
);
566 DeviceExtension
->ReportMDL
= IoAllocateMdl(DeviceExtension
->Report
, DeviceExtension
->ReportLength
, FALSE
, FALSE
, NULL
);
567 ASSERT(DeviceExtension
->ReportMDL
);
570 /* get max number of buttons */
571 Buttons
= HidP_MaxUsageListLength(HidP_Input
, HID_USAGE_PAGE_BUTTON
, PreparsedData
);
574 /* now allocate an array for those buttons */
575 Buffer
= ExAllocatePool(NonPagedPool
, sizeof(USAGE
) * 4 * Buttons
);
579 ExFreePool(PreparsedData
);
580 return STATUS_INSUFFICIENT_RESOURCES
;
583 /* init usage lists */
584 RtlZeroMemory(Buffer
, sizeof(USAGE
) * 4 * Buttons
);
585 DeviceExtension
->CurrentUsageList
= Buffer
;
587 DeviceExtension
->PreviousUsageList
= Buffer
;
589 DeviceExtension
->MakeUsageList
= Buffer
;
591 DeviceExtension
->BreakUsageList
= Buffer
;
593 /* store number of buttons */
594 DeviceExtension
->UsageListLength
= (USHORT
)Buttons
;
596 /* store preparsed data */
597 DeviceExtension
->PreparsedData
= PreparsedData
;
600 HidP_GetSpecificValueCaps(HidP_Input
, HID_USAGE_PAGE_GENERIC
, HIDP_LINK_COLLECTION_UNSPECIFIED
, HID_USAGE_GENERIC_X
, &ValueCaps
, &ValueCapsLength
, PreparsedData
);
603 HidP_GetSpecificValueCaps(HidP_Input
, HID_USAGE_PAGE_GENERIC
, HIDP_LINK_COLLECTION_UNSPECIFIED
, HID_USAGE_GENERIC_Y
, &ValueCaps
, &ValueCapsLength
, PreparsedData
);
605 /* now check for wheel mouse support */
607 Status
= HidP_GetSpecificValueCaps(HidP_Input
, HID_USAGE_PAGE_GENERIC
, HIDP_LINK_COLLECTION_UNSPECIFIED
, HID_USAGE_GENERIC_WHEEL
, &ValueCaps
, &ValueCapsLength
, PreparsedData
);
608 if (Status
== HIDP_STATUS_SUCCESS
)
610 /* mouse has wheel support */
611 DeviceExtension
->MouseIdentifier
= WHEELMOUSE_HID_HARDWARE
;
612 DeviceExtension
->WheelUsagePage
= ValueCaps
.UsagePage
;
616 /* check if the mouse has z-axis */
618 Status
= HidP_GetSpecificValueCaps(HidP_Input
, HID_USAGE_PAGE_GENERIC
, HIDP_LINK_COLLECTION_UNSPECIFIED
, HID_USAGE_GENERIC_Z
, &ValueCaps
, &ValueCapsLength
, PreparsedData
);
619 if (Status
== HIDP_STATUS_SUCCESS
&& ValueCapsLength
== 1)
622 DeviceExtension
->MouseIdentifier
= WHEELMOUSE_HID_HARDWARE
;
623 DeviceExtension
->WheelUsagePage
= ValueCaps
.UsagePage
;
627 /* completed successfully */
628 return STATUS_SUCCESS
;
633 MouHid_StartDeviceCompletion(
634 IN PDEVICE_OBJECT DeviceObject
,
638 KeSetEvent((PKEVENT
)Context
, 0, FALSE
);
639 return STATUS_MORE_PROCESSING_REQUIRED
;
645 IN PDEVICE_OBJECT DeviceObject
,
648 PIO_STACK_LOCATION IoStack
;
651 PMOUHID_DEVICE_EXTENSION DeviceExtension
;
653 /* get device extension */
654 DeviceExtension
= (PMOUHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
656 /* get current irp stack */
657 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
659 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
)
661 /* indicate success */
662 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
664 /* skip irp stack location */
665 IoSkipCurrentIrpStackLocation(Irp
);
667 /* dispatch to lower device */
668 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
670 else if (IoStack
->MinorFunction
== IRP_MN_REMOVE_DEVICE
)
672 /* FIXME synchronization */
675 IoCancelIrp(DeviceExtension
->Irp
);
677 /* indicate success */
678 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
680 /* skip irp stack location */
681 IoSkipCurrentIrpStackLocation(Irp
);
683 /* dispatch to lower device */
684 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
686 IoFreeIrp(DeviceExtension
->Irp
);
687 IoDetachDevice(DeviceExtension
->NextDeviceObject
);
688 IoDeleteDevice(DeviceObject
);
691 else if (IoStack
->MinorFunction
== IRP_MN_START_DEVICE
)
694 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
696 /* copy stack location */
697 IoCopyCurrentIrpStackLocationToNext (Irp
);
699 /* set completion routine */
700 IoSetCompletionRoutine(Irp
, MouHid_StartDeviceCompletion
, &Event
, TRUE
, TRUE
, TRUE
);
701 Irp
->IoStatus
.Status
= 0;
704 Status
= IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
705 if (Status
== STATUS_PENDING
)
707 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
708 Status
= Irp
->IoStatus
.Status
;
711 if (!NT_SUCCESS(Status
))
714 Irp
->IoStatus
.Status
= Status
;
715 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
719 /* lets start the device */
720 Status
= MouHid_StartDevice(DeviceObject
);
721 DPRINT1("MouHid_StartDevice %x\n", Status
);
723 /* complete request */
724 Irp
->IoStatus
.Status
= Status
;
725 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
732 /* skip irp stack location */
733 IoSkipCurrentIrpStackLocation(Irp
);
735 /* dispatch to lower device */
736 return IoCallDriver(DeviceExtension
->NextDeviceObject
, Irp
);
743 IN PDRIVER_OBJECT DriverObject
,
744 IN PDEVICE_OBJECT PhysicalDeviceObject
)
747 PDEVICE_OBJECT DeviceObject
, NextDeviceObject
;
748 PMOUHID_DEVICE_EXTENSION DeviceExtension
;
751 /* create device object */
752 Status
= IoCreateDevice(DriverObject
, sizeof(MOUHID_DEVICE_EXTENSION
), NULL
, FILE_DEVICE_MOUSE
, 0, FALSE
, &DeviceObject
);
753 if (!NT_SUCCESS(Status
))
755 /* failed to create device object */
760 NextDeviceObject
= IoAttachDeviceToDeviceStack(DeviceObject
, PhysicalDeviceObject
);
761 if (!NextDeviceObject
)
763 /* failed to attach */
764 IoDeleteDevice(DeviceObject
);
765 return STATUS_DEVICE_NOT_CONNECTED
;
768 /* get device extension */
769 DeviceExtension
= (PMOUHID_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
772 RtlZeroMemory(DeviceExtension
, sizeof(MOUHID_DEVICE_EXTENSION
));
774 /* init device extension */
775 DeviceExtension
->MouseIdentifier
= MOUSE_HID_HARDWARE
;
776 DeviceExtension
->WheelUsagePage
= 0;
777 DeviceExtension
->NextDeviceObject
= NextDeviceObject
;
778 KeInitializeEvent(&DeviceExtension
->Event
, NotificationEvent
, FALSE
);
779 DeviceExtension
->Irp
= IoAllocateIrp(NextDeviceObject
->StackSize
, FALSE
);
781 /* FIXME handle allocation error */
782 ASSERT(DeviceExtension
->Irp
);
784 /* FIXME query parameter 'FlipFlopWheel', 'WheelScalingFactor' */
786 /* set power state to D0 */
787 State
.DeviceState
= PowerDeviceD0
;
788 PoSetPowerState(DeviceObject
, DevicePowerState
, State
);
790 /* init device object */
791 DeviceObject
->Flags
|= DO_BUFFERED_IO
| DO_POWER_PAGABLE
;
792 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
794 /* completed successfully */
795 return STATUS_SUCCESS
;
801 IN PDRIVER_OBJECT DriverObject
)
811 IN PDRIVER_OBJECT DriverObject
,
812 IN PUNICODE_STRING RegPath
)
814 /* FIXME check for parameters 'UseOnlyMice', 'TreatAbsoluteAsRelative', 'TreatAbsolutePointerAsAbsolute' */
816 /* initialize driver object */
817 DriverObject
->DriverUnload
= MouHid_Unload
;
818 DriverObject
->DriverExtension
->AddDevice
= MouHid_AddDevice
;
819 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = MouHid_Create
;
820 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = MouHid_Close
;
821 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = MouHid_DeviceControl
;
822 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = MouHid_InternalDeviceControl
;
823 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = MouHid_Power
;
824 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = MouHid_Pnp
;
825 DriverObject
->DriverUnload
= MouHid_Unload
;
826 DriverObject
->DriverExtension
->AddDevice
= MouHid_AddDevice
;
829 return STATUS_SUCCESS
;