update for HEAD-2003050101
[reactos.git] / drivers / input / psaux / psaux.c
1 /*
2  ** PS/2 driver 0.0.2
3  ** Written by Jason Filby (jasonfilby@yahoo.com)
4  ** For ReactOS (www.reactos.com)
5
6  ** Handles the keyboard and mouse on the PS/2 ports
7
8  ** TODO: Fix detect_ps2_port(void) so that it works under BOCHs
9 */
10
11 #include <ddk/ntddk.h>
12 #include <ddk/ntddmou.h>
13 #include "mouse.h"
14 #include "psaux.h"
15
16 BOOLEAN STDCALL
17 MouseSynchronizeRoutine(PVOID Context)
18 {
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);
23    int i;
24
25    if ((stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA))==NrToRead)
26    {
27       return(TRUE);
28    }
29
30    MouseDataRequired=stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA);
31    MouseDataRead=NrToRead;
32    CurrentIrp=Irp;
33
34    return(FALSE);
35 }
36
37 VOID STDCALL
38 PS2MouseStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
39 {
40    PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
41
42    if (KeSynchronizeExecution(DeviceExtension->MouseInterrupt, MouseSynchronizeRoutine, Irp))
43      {
44         Irp->IoStatus.Status = STATUS_SUCCESS;
45         Irp->IoStatus.Information = 0;
46         IoCompleteRequest(Irp, IO_NO_INCREMENT);
47         IoStartNextPacket(DeviceObject, FALSE);
48      }
49 }
50
51 NTSTATUS STDCALL
52 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
98 NTSTATUS STDCALL
99 PS2MouseInternalDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
100 {
101    PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
102    PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
103    NTSTATUS status;
104
105    switch(Stack->Parameters.DeviceIoControl.IoControlCode)
106    {
107       case IOCTL_INTERNAL_MOUSE_CONNECT:
108
109          DeviceExtension->ClassInformation =
110             *((PCLASS_INFORMATION)Stack->Parameters.DeviceIoControl.Type3InputBuffer);
111
112          // Reinitialize the port input data queue synchronously
113          KeSynchronizeExecution(DeviceExtension->MouseInterrupt,
114             (PKSYNCHRONIZE_ROUTINE)PS2MouseInitializeDataQueue, DeviceExtension);
115
116          status = STATUS_SUCCESS;
117          break;
118
119       default:
120          status = STATUS_INVALID_DEVICE_REQUEST;
121          break;
122    }
123
124    Irp->IoStatus.Status = status;
125    if (status == STATUS_PENDING) {
126       IoMarkIrpPending(Irp);
127       IoStartPacket(DeviceObject, Irp, NULL, NULL);
128    } else {
129       IoCompleteRequest(Irp, IO_NO_INCREMENT);
130    }
131
132    return status;
133 }
134
135 VOID PS2MouseIsrDpc(PKDPC Dpc, PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
136 {
137    PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
138    ULONG Queue;
139
140    Queue = DeviceExtension->ActiveQueue % 2;
141    InterlockedIncrement(&DeviceExtension->ActiveQueue);
142    (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassInformation.CallBack)(
143                         DeviceExtension->ClassInformation.DeviceObject,
144                         DeviceExtension->MouseInputData[Queue],
145                         NULL,
146                         &DeviceExtension->InputDataCount[Queue]);
147    DeviceExtension->InputDataCount[Queue] = 0;
148 }
149
150 NTSTATUS STDCALL
151 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
152 {
153    PDEVICE_OBJECT DeviceObject;
154    UNICODE_STRING DeviceName;
155    UNICODE_STRING SymlinkName;
156    PDEVICE_EXTENSION DeviceExtension;
157
158    if (detect_ps2_port() == TRUE) {
159      DbgPrint("PS2 Port Driver version 0.0.2\n");
160    } else {
161      DbgPrint("PS2 port not found.\n");
162      return STATUS_UNSUCCESSFUL;
163    }
164
165    DriverObject->MajorFunction[IRP_MJ_CREATE] = PS2MouseDispatch;
166    DriverObject->MajorFunction[IRP_MJ_CLOSE]  = PS2MouseDispatch;
167    DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = PS2MouseInternalDeviceControl;
168    DriverObject->DriverStartIo                = PS2MouseStartIo;
169
170    RtlInitUnicodeStringFromLiteral(&DeviceName,
171                                    L"\\Device\\Mouse"); // FIXME: find correct device name
172    IoCreateDevice(DriverObject,
173                   sizeof(DEVICE_EXTENSION),
174                   &DeviceName,
175                   FILE_DEVICE_SERIAL_MOUSE_PORT, // FIXME: this isn't really a serial mouse port driver
176                   0,
177                   TRUE,
178                   &DeviceObject);
179    DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO;
180
181    RtlInitUnicodeStringFromLiteral(&SymlinkName,
182                                    L"\\??\\Mouse"); // FIXME: find correct device name
183    IoCreateSymbolicLink(&SymlinkName, &DeviceName);
184
185    DeviceExtension = DeviceObject->DeviceExtension;
186    KeInitializeDpc(&DeviceExtension->IsrDpc, (PKDEFERRED_ROUTINE)PS2MouseIsrDpc, DeviceObject);
187
188    mouse_init(DeviceObject);
189
190    return(STATUS_SUCCESS);
191 }