3 ** Written by Jason Filby (jasonfilby@yahoo.com)
4 ** For ReactOS (www.reactos.com)
6 ** Handles the keyboard and mouse on the PS/2 ports
8 ** TODO: Fix detect_ps2_port(void) so that it works under BOCHs
11 #include <ddk/ntddk.h>
12 #include <ddk/ntddmou.h>
17 MouseSynchronizeRoutine(PVOID Context)
19 PIRP Irp = (PIRP)Context;
20 PMOUSE_INPUT_DATA rec = (PMOUSE_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer;
21 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
22 ULONG NrToRead = stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA);
25 if ((stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA))==NrToRead)
30 MouseDataRequired=stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA);
31 MouseDataRead=NrToRead;
38 PS2MouseStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
40 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
42 if (KeSynchronizeExecution(DeviceExtension->MouseInterrupt, MouseSynchronizeRoutine, Irp))
44 Irp->IoStatus.Status = STATUS_SUCCESS;
45 Irp->IoStatus.Information = 0;
46 IoCompleteRequest(Irp, IO_NO_INCREMENT);
47 IoStartNextPacket(DeviceObject, FALSE);
52 PS2MouseDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
54 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
57 switch (stk->MajorFunction)
60 if (AlreadyOpened == TRUE)
62 Status = STATUS_SUCCESS;
66 Status = STATUS_SUCCESS;
72 Status = STATUS_SUCCESS;
76 DbgPrint("NOT IMPLEMENTED\n");
77 Status = STATUS_NOT_IMPLEMENTED;
81 if (Status==STATUS_PENDING)
83 IoMarkIrpPending(Irp);
87 Irp->IoStatus.Status = Status;
88 Irp->IoStatus.Information = 0;
89 IoCompleteRequest(Irp,IO_NO_INCREMENT);
94 VOID PS2MouseInitializeDataQueue(PVOID Context)
99 PS2MouseInternalDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
101 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
102 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
105 switch(Stack->Parameters.DeviceIoControl.IoControlCode)
107 case IOCTL_INTERNAL_MOUSE_CONNECT:
109 DeviceExtension->ClassInformation =
110 *((PCLASS_INFORMATION)Stack->Parameters.DeviceIoControl.Type3InputBuffer);
112 // Reinitialize the port input data queue synchronously
113 KeSynchronizeExecution(DeviceExtension->MouseInterrupt,
114 (PKSYNCHRONIZE_ROUTINE)PS2MouseInitializeDataQueue, DeviceExtension);
116 status = STATUS_SUCCESS;
120 status = STATUS_INVALID_DEVICE_REQUEST;
124 Irp->IoStatus.Status = status;
125 if (status == STATUS_PENDING) {
126 IoMarkIrpPending(Irp);
127 IoStartPacket(DeviceObject, Irp, NULL, NULL);
129 IoCompleteRequest(Irp, IO_NO_INCREMENT);
135 VOID PS2MouseIsrDpc(PKDPC Dpc, PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
137 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
140 Queue = DeviceExtension->ActiveQueue % 2;
141 InterlockedIncrement(&DeviceExtension->ActiveQueue);
142 (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassInformation.CallBack)(
143 DeviceExtension->ClassInformation.DeviceObject,
144 DeviceExtension->MouseInputData[Queue],
146 &DeviceExtension->InputDataCount[Queue]);
147 DeviceExtension->InputDataCount[Queue] = 0;
150 /* Maximum value plus one for \Device\PointerClass* device name */
151 #define POINTER_PORTS_MAXIMUM 8
152 /* Letter count for POINTER_PORTS_MAXIMUM variable * sizeof(WCHAR) */
153 #define SUFFIX_MAXIMUM_SIZE (1 * sizeof(WCHAR))
155 /* This is almost the same routine as in sermouse.c. */
156 STATIC PDEVICE_OBJECT
157 AllocatePointerDevice(PDRIVER_OBJECT DriverObject)
159 PDEVICE_OBJECT DeviceObject;
160 UNICODE_STRING DeviceName;
161 UNICODE_STRING SuffixString;
162 UNICODE_STRING SymlinkName;
163 PDEVICE_EXTENSION DeviceExtension;
167 /* Allocate buffer for full device name */
168 RtlInitUnicodeString(&DeviceName, NULL);
169 DeviceName.MaximumLength = sizeof(DD_MOUSE_DEVICE_NAME_U) + SUFFIX_MAXIMUM_SIZE + sizeof(UNICODE_NULL);
170 DeviceName.Buffer = ExAllocatePool(PagedPool, DeviceName.MaximumLength);
171 RtlAppendUnicodeToString(&DeviceName, DD_MOUSE_DEVICE_NAME_U);
173 /* Allocate buffer for device name suffix */
174 RtlInitUnicodeString(&SuffixString, NULL);
175 SuffixString.MaximumLength = SUFFIX_MAXIMUM_SIZE + sizeof(UNICODE_NULL);
176 SuffixString.Buffer = ExAllocatePool(PagedPool, SuffixString.MaximumLength);
178 /* Generate full qualified name with suffix */
179 for (Suffix = 0; Suffix < POINTER_PORTS_MAXIMUM; ++Suffix)
181 ANSI_STRING DebugString;
183 RtlIntegerToUnicodeString(Suffix, 10, &SuffixString);
184 RtlAppendUnicodeToString(&DeviceName, SuffixString.Buffer);
185 // FIXME: this isn't really a serial mouse port driver
186 Status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION),
187 &DeviceName, FILE_DEVICE_SERIAL_MOUSE_PORT, 0, TRUE, &DeviceObject);
188 RtlUnicodeStringToAnsiString(&DebugString, &DeviceName, TRUE);
189 DbgPrint(DebugString.Buffer);
191 RtlFreeAnsiString(&DebugString);
192 /* Device successfully created, leave the cyclus */
193 if (NT_SUCCESS(Status))
195 DeviceName.Length -= SuffixString.Length;
198 ExFreePool(DeviceName.Buffer);
200 /* Couldn't create device */
201 if (!NT_SUCCESS(Status))
203 ExFreePool(SuffixString.Buffer);
207 DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO;
210 RtlInitUnicodeString(&SymlinkName, NULL);
211 SymlinkName.MaximumLength = sizeof(L"\\??\\Mouse") + SUFFIX_MAXIMUM_SIZE + sizeof(UNICODE_NULL);
212 SymlinkName.Buffer = ExAllocatePool(PagedPool, SymlinkName.MaximumLength);
213 RtlAppendUnicodeToString(&SymlinkName, L"\\??\\Mouse");
214 RtlAppendUnicodeToString(&DeviceName, SuffixString.Buffer);
215 IoCreateSymbolicLink(&SymlinkName, &DeviceName);
216 ExFreePool(SuffixString.Buffer);
218 DeviceExtension = DeviceObject->DeviceExtension;
219 KeInitializeDpc(&DeviceExtension->IsrDpc, (PKDEFERRED_ROUTINE)PS2MouseIsrDpc, DeviceObject);
225 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
227 PDEVICE_OBJECT DeviceObject;
228 UNICODE_STRING DeviceName;
229 UNICODE_STRING SymlinkName;
230 PDEVICE_EXTENSION DeviceExtension;
232 if (detect_ps2_port() == TRUE) {
233 DbgPrint("PS2 Port Driver version 0.0.2\n");
235 DbgPrint("PS2 port not found.\n");
236 return STATUS_UNSUCCESSFUL;
239 DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)PS2MouseDispatch;
240 DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)PS2MouseDispatch;
241 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = (PDRIVER_DISPATCH)PS2MouseInternalDeviceControl;
242 DriverObject->DriverStartIo = PS2MouseStartIo;
244 DeviceObject = AllocatePointerDevice(DriverObject);
246 mouse_init(DeviceObject);
248 return(STATUS_SUCCESS);