3 ** Mouse class driver 0.0.1
4 ** Written by Jason Filby (jasonfilby@yahoo.com)
5 ** For ReactOS (www.reactos.com)
7 ** The class driver between win32k and the various mouse port drivers
9 ** TODO: Change interface to win32k to a callback instead of ReadFile IO
10 Add support for multiple port devices
14 #include <ddk/ntddk.h>
15 #include "..\include\mouse.h"
18 BOOLEAN AlreadyOpened
= FALSE
;
20 VOID
MouseClassCallBack(PDEVICE_OBJECT ClassDeviceObject
, PMOUSE_INPUT_DATA MouseDataStart
,
21 PMOUSE_INPUT_DATA MouseDataEnd
, PULONG InputCount
)
23 PDEVICE_EXTENSION ClassDeviceExtension
= ClassDeviceObject
->DeviceExtension
;
26 PIO_STACK_LOCATION Stack
;
28 if(ClassDeviceExtension
->ReadIsPending
== TRUE
)
30 Irp
= ClassDeviceObject
->CurrentIrp
;
31 ClassDeviceObject
->CurrentIrp
= NULL
;
32 Stack
= IoGetCurrentIrpStackLocation(Irp
);
34 ReadSize
= sizeof(MOUSE_INPUT_DATA
) * (*InputCount
);
36 // A read request is waiting for input, so go straight to it
37 RtlMoveMemory(Irp
->AssociatedIrp
.SystemBuffer
, (PCHAR
)MouseDataStart
, ReadSize
);
39 // Go to next packet and complete this request with STATUS_SUCCESS
40 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
41 Irp
->IoStatus
.Information
= ReadSize
;
42 Stack
->Parameters
.Read
.Length
= ReadSize
;
44 IoStartNextPacket(ClassDeviceObject
, FALSE
);
45 IoCompleteRequest(Irp
, IO_MOUSE_INCREMENT
);
46 ClassDeviceExtension
->ReadIsPending
= FALSE
;
50 // FIXME: If we exceed the buffer, mouse data gets thrown away.. better solution?
52 if(ClassDeviceExtension
->InputCount
+ *InputCount
> MOUSE_BUFFER_SIZE
)
54 ReadSize
= MOUSE_BUFFER_SIZE
- ClassDeviceExtension
->InputCount
;
56 ReadSize
= *InputCount
;
59 // Move the mouse input data from the port data queue to our class data queue
60 RtlMoveMemory(ClassDeviceExtension
->PortData
, (PCHAR
)MouseDataStart
,
61 sizeof(MOUSE_INPUT_DATA
) * ReadSize
);
63 // Move the pointer and counter up
64 ClassDeviceExtension
->PortData
+= ReadSize
;
65 ClassDeviceExtension
->InputCount
+= ReadSize
;
69 NTSTATUS
ConnectMousePortDriver(PDEVICE_OBJECT ClassDeviceObject
)
71 PDEVICE_OBJECT PortDeviceObject
= NULL
;
72 PFILE_OBJECT FileObject
= NULL
;
74 UNICODE_STRING PortName
;
75 IO_STATUS_BLOCK ioStatus
;
78 CLASS_INFORMATION ClassInformation
;
79 PDEVICE_EXTENSION DeviceExtension
= ClassDeviceObject
->DeviceExtension
;
81 // Get the port driver's DeviceObject
82 // FIXME: The name might change.. find a way to be more dynamic?
84 RtlInitUnicodeString(&PortName
, L
"\\Device\\Mouse");
85 status
= IoGetDeviceObjectPointer(&PortName
, FILE_READ_ATTRIBUTES
, &FileObject
, &PortDeviceObject
);
87 if(status
!= STATUS_SUCCESS
)
89 DbgPrint("MOUCLASS: Could not connect to mouse port driver\n");
93 DeviceExtension
->PortDeviceObject
= PortDeviceObject
;
94 DeviceExtension
->PortData
= ExAllocatePool(NonPagedPool
, MOUSE_BUFFER_SIZE
* sizeof(MOUSE_INPUT_DATA
));
95 DeviceExtension
->InputCount
= 0;
96 DeviceExtension
->ReadIsPending
= FALSE
;
98 // Connect our callback to the port driver
100 KeInitializeEvent(&event
, NotificationEvent
, FALSE
);
102 ClassInformation
.DeviceObject
= ClassDeviceObject
;
103 ClassInformation
.CallBack
= MouseClassCallBack
;
105 irp
= IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT
,
106 PortDeviceObject
, &ClassInformation
, sizeof(CLASS_INFORMATION
), NULL
, 0, TRUE
, &event
, &ioStatus
);
108 status
= IoCallDriver(DeviceExtension
->PortDeviceObject
, irp
);
110 if (status
== STATUS_PENDING
) {
111 KeWaitForSingleObject(&event
, Suspended
, KernelMode
, FALSE
, NULL
);
113 ioStatus
.Status
= status
;
116 return ioStatus
.Status
;
119 NTSTATUS
MouseClassDispatch(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
121 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
124 switch (Stack
->MajorFunction
)
127 if (AlreadyOpened
== TRUE
)
129 Status
= STATUS_SUCCESS
;
133 Status
= STATUS_SUCCESS
;
134 AlreadyOpened
= TRUE
;
139 Status
= STATUS_SUCCESS
;
144 if (Stack
->Parameters
.Read
.Length
== 0) {
145 Status
= STATUS_SUCCESS
;
147 Status
= STATUS_PENDING
;
152 DbgPrint("NOT IMPLEMENTED\n");
153 Status
= STATUS_NOT_IMPLEMENTED
;
157 Irp
->IoStatus
.Status
= Status
;
158 Irp
->IoStatus
.Information
= 0;
159 if (Status
==STATUS_PENDING
)
161 IoMarkIrpPending(Irp
);
162 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
164 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
169 VOID
MouseClassStartIo(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
171 PDEVICE_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
172 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
175 if(DeviceExtension
->InputCount
>0)
177 // FIXME: We should not send to much input data.. depends on the max buffer size of the win32k
178 ReadSize
= DeviceExtension
->InputCount
* sizeof(MOUSE_INPUT_DATA
);
180 // Bring the PortData back to base so that it can be copied
181 DeviceExtension
->PortData
-= DeviceExtension
->InputCount
;
182 DeviceExtension
->InputCount
= 0;
183 DeviceExtension
->ReadIsPending
= FALSE
;
185 RtlMoveMemory(Irp
->AssociatedIrp
.SystemBuffer
, (PCHAR
)DeviceExtension
->PortData
, ReadSize
);
187 // Go to next packet and complete this request with STATUS_SUCCESS
188 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
190 Irp
->IoStatus
.Information
= ReadSize
;
191 Stack
->Parameters
.Read
.Length
= ReadSize
;
193 IoStartNextPacket(DeviceObject
, FALSE
);
194 IoCompleteRequest(Irp
, IO_MOUSE_INCREMENT
);
196 DeviceExtension
->ReadIsPending
= TRUE
;
201 DriverEntry(PDRIVER_OBJECT DriverObject
, PUNICODE_STRING RegistryPath
)
203 PDEVICE_OBJECT DeviceObject
;
204 UNICODE_STRING DeviceName
;
205 UNICODE_STRING SymlinkName
;
207 DbgPrint("Mouse Class Driver 0.0.1\n");
209 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = MouseClassDispatch
;
210 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = MouseClassDispatch
;
211 DriverObject
->MajorFunction
[IRP_MJ_READ
] = MouseClassDispatch
;
212 DriverObject
->DriverStartIo
= MouseClassStartIo
;
214 RtlInitUnicodeString(&DeviceName
, L
"\\Device\\MouseClass");
215 IoCreateDevice(DriverObject
,
216 sizeof(DEVICE_EXTENSION
),
222 DeviceObject
->Flags
= DeviceObject
->Flags
| DO_BUFFERED_IO
;
224 RtlInitUnicodeString(&SymlinkName
, L
"\\??\\MouseClass");
225 IoCreateSymbolicLink(&SymlinkName
, &DeviceName
);
227 return ConnectMousePortDriver(DeviceObject
);