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