1d4d0b9cc698e99438217f5624bf23b962ede9ab
[reactos.git] / reactos / drivers / input / psaux / psaux.c
1 /*
2
3 ** PS/2 driver 0.0.1
4 ** Written by Jason Filby (jasonfilby@yahoo.com)
5 ** For ReactOS (www.reactos.com)
6
7 ** Handles the keyboard and mouse on the PS/2 ports
8
9 ** TODO: Fix detect_ps2_port(void) so that it works under BOCHs
10 Implement mouse button support
11
12 */
13
14 #include <ddk/ntddk.h>
15 #include "../include/mouse.h"
16 #include "mouse.h"
17 #include "psaux.h"
18
19 BOOLEAN MouseSynchronizeRoutine(PVOID Context)
20 {
21 PIRP Irp = (PIRP)Context;
22 PMOUSE_INPUT_DATA rec = (PMOUSE_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer;
23 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
24 ULONG NrToRead = stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA);
25 int i;
26
27 if ((stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA))==NrToRead)
28 {
29 return(TRUE);
30 }
31
32 MouseDataRequired=stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA);
33 MouseDataRead=NrToRead;
34 CurrentIrp=Irp;
35
36 return(FALSE);
37 }
38
39 VOID PS2MouseStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
40 {
41 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
42
43 if (KeSynchronizeExecution(DeviceExtension->MouseInterrupt, MouseSynchronizeRoutine, Irp))
44 {
45 Irp->IoStatus.Status = STATUS_SUCCESS;
46 Irp->IoStatus.Information = 0;
47 IoCompleteRequest(Irp, IO_NO_INCREMENT);
48 IoStartNextPacket(DeviceObject, FALSE);
49 }
50 }
51
52 NTSTATUS PS2MouseDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
53 {
54 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
55 NTSTATUS Status;
56
57 switch (stk->MajorFunction)
58 {
59 case IRP_MJ_CREATE:
60 if (AlreadyOpened == TRUE)
61 {
62 Status = STATUS_SUCCESS;
63 }
64 else
65 {
66 Status = STATUS_SUCCESS;
67 AlreadyOpened = TRUE;
68 }
69 break;
70
71 case IRP_MJ_CLOSE:
72 Status = STATUS_SUCCESS;
73 break;
74
75 default:
76 DbgPrint("NOT IMPLEMENTED\n");
77 Status = STATUS_NOT_IMPLEMENTED;
78 break;
79 }
80
81 if (Status==STATUS_PENDING)
82 {
83 IoMarkIrpPending(Irp);
84 }
85 else
86 {
87 Irp->IoStatus.Status = Status;
88 Irp->IoStatus.Information = 0;
89 IoCompleteRequest(Irp,IO_NO_INCREMENT);
90 }
91 return(Status);
92 }
93
94 VOID PS2MouseInitializeDataQueue(PVOID Context)
95 {
96 ;
97 /* PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceExtension;
98
99 DeviceExtension->InputDataCount = 0;
100 DeviceExtension->MouseInputData = ExAllocatePool(NonPagedPool, sizeof(MOUSE_INPUT_DATA) * MOUSE_BUFFER_SIZE); */
101 }
102
103 NTSTATUS PS2MouseInternalDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
104 {
105 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
106 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
107 NTSTATUS status;
108
109 switch(Stack->Parameters.DeviceIoControl.IoControlCode)
110 {
111 case IOCTL_INTERNAL_MOUSE_CONNECT:
112
113 DeviceExtension->ClassInformation =
114 *((PCLASS_INFORMATION)Stack->Parameters.DeviceIoControl.Type3InputBuffer);
115
116 // Reinitialize the port input data queue synchronously
117 KeSynchronizeExecution(DeviceExtension->MouseInterrupt,
118 (PKSYNCHRONIZE_ROUTINE)PS2MouseInitializeDataQueue, DeviceExtension);
119
120 status = STATUS_SUCCESS;
121 break;
122
123 default:
124 status = STATUS_INVALID_DEVICE_REQUEST;
125 break;
126 }
127
128 Irp->IoStatus.Status = status;
129 if (status == STATUS_PENDING) {
130 IoMarkIrpPending(Irp);
131 IoStartPacket(DeviceObject, Irp, NULL, NULL);
132 } else {
133 IoCompleteRequest(Irp, IO_NO_INCREMENT);
134 }
135
136 return status;
137 }
138
139 VOID PS2MouseIsrDpc(PKDPC Dpc, PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
140 {
141 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
142
143 (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassInformation.CallBack)(
144 DeviceExtension->ClassInformation.DeviceObject,
145 DeviceExtension->MouseInputData,
146 NULL,
147 &DeviceExtension->InputDataCount);
148
149 DeviceExtension->InputDataCount = 0;
150 }
151
152 NTSTATUS STDCALL
153 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
154 {
155 PDEVICE_OBJECT DeviceObject;
156 UNICODE_STRING DeviceName;
157 UNICODE_STRING SymlinkName;
158 PDEVICE_EXTENSION DeviceExtension;
159
160 DbgPrint("PS/2 Keyboard & Mouse Driver 0.0.2\n");
161
162 if(detect_ps2_port() == TRUE)
163 {
164 DbgPrint("PS/2 Mouse Detected\n");
165 } else
166 return STATUS_UNSUCCESSFUL;
167
168 DriverObject->MajorFunction[IRP_MJ_CREATE] = PS2MouseDispatch;
169 DriverObject->MajorFunction[IRP_MJ_CLOSE] = PS2MouseDispatch;
170 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = PS2MouseInternalDeviceControl;
171 DriverObject->DriverStartIo = PS2MouseStartIo;
172
173 RtlInitUnicodeString(&DeviceName, L"\\Device\\Mouse"); // FIXME: find correct device name
174 IoCreateDevice(DriverObject,
175 sizeof(DEVICE_EXTENSION),
176 &DeviceName,
177 FILE_DEVICE_SERIAL_MOUSE_PORT, // FIXME: this isn't really a serial mouse port driver
178 0,
179 TRUE,
180 &DeviceObject);
181 DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO;
182
183 RtlInitUnicodeString(&SymlinkName, L"\\??\\Mouse"); // FIXME: find correct device name
184 IoCreateSymbolicLink(&SymlinkName, &DeviceName);
185
186 DeviceExtension = DeviceObject->DeviceExtension;
187 KeInitializeDpc(&DeviceExtension->IsrDpc, (PKDEFERRED_ROUTINE)PS2MouseIsrDpc, DeviceObject);
188 KeInitializeDpc(&DeviceExtension->IsrDpcRetry, (PKDEFERRED_ROUTINE)PS2MouseIsrDpc, DeviceObject);
189
190 mouse_init(DeviceObject);
191
192 return(STATUS_SUCCESS);
193 }