4 ** Written by Jason Filby (jasonfilby@yahoo.com)
5 ** For ReactOS (www.sid-dis.com/reactos)
7 ** Note: The serial.o driver must be loaded before loading this driver
10 ** Only supports mice on COM port 1
14 #include <ddk/ntddk.h>
15 #include "../include/mouse.h"
19 #define MOUSE_IRQ_COM1 4
20 #define MOUSE_IRQ_COM2 3
22 #define COM1_PORT 0x3f8
23 #define COM2_PORT 0x2f8
25 #define max_screen_x 79
26 #define max_screen_y 24
28 //static unsigned int MOUSE_IRQ=MOUSE_IRQ_COM1;
29 static unsigned int MOUSE_COM=COM1_PORT;
31 static unsigned int bytepos=0, coordinate;
32 static unsigned char mpacket[3];
33 static signed int mouse_x=40, mouse_y=12;
34 static unsigned char mouse_button1, mouse_button2;
35 static signed int horiz_sensitivity, vert_sensitivity;
37 BOOLEAN microsoft_mouse_handler(PKINTERRUPT Interrupt, PVOID ServiceContext)
39 unsigned int mbyte=READ_PORT_UCHAR((PUCHAR)MOUSE_COM);
42 if((mbyte&64)==64) { bytepos=0; }
44 mpacket[bytepos]=mbyte;
49 // Retrieve change in x and y from packet
50 int change_x=((mpacket[0] & 3) << 6) + mpacket[1];
51 int change_y=((mpacket[0] & 12) << 4) + mpacket[2];
53 // Some mice need this
60 if(change_x>=128) { change_x=change_x-256; }
61 if(change_y>=128) { change_y=change_y-256; }
63 // Adjust mouse position according to sensitivity
64 mouse_x+=change_x/horiz_sensitivity;
65 mouse_y+=change_y/vert_sensitivity;
67 // Check that mouse is still in screen
68 if(mouse_x<0) { mouse_x=0; }
69 if(mouse_x>max_screen_x) { mouse_x=max_screen_x; }
70 if(mouse_y<0) { mouse_y=0; }
71 if(mouse_y>max_screen_y) { mouse_y=max_screen_y; }
73 // Retrieve mouse button status from packet
74 mouse_button1=mpacket[0] & 32;
75 mouse_button2=mpacket[0] & 16;
82 void InitializeMouseHardware(unsigned int mtype)
84 char clear_error_bits;
86 WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+3, 0x80); // set DLAB on
87 WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM, 0x60); // speed LO byte
88 WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+1, 0); // speed HI byte
89 WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+3, mtype); // 2=MS Mouse; 3=Mouse systems mouse
90 WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+1, 0); // set comm and DLAB to 0
91 WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+4, 1); // DR int enable
93 clear_error_bits=READ_PORT_UCHAR((PUCHAR)MOUSE_COM+5); // clear error bits
96 int DetMicrosoft(void)
99 int buttons=0, i, timeout=250;
101 WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+4, 0x0b);
102 tmp=READ_PORT_UCHAR((PUCHAR)MOUSE_COM);
104 // Check the first four bytes for signs that this is an MS mouse
106 while(((READ_PORT_UCHAR((PUCHAR)MOUSE_COM+5) & 1)==0) && (timeout>0))
108 KeDelayExecutionThread (KernelMode, FALSE, 1);
111 ind=READ_PORT_UCHAR((PUCHAR)MOUSE_COM);
112 if(ind==0x33) buttons=3;
113 if(ind==0x4d) buttons=2;
119 int CheckMouseType(unsigned int mtype)
121 unsigned int retval=0;
123 InitializeMouseHardware(mtype);
124 if(mtype==2) retval=DetMicrosoft();
126 WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+4, 11);
129 WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+1, 1);
134 void ClearMouse(void)
136 // Waits until the mouse calms down but also quits out after a while
137 // in case some destructive user wants to keep moving the mouse
140 unsigned int restarts=0, i;
141 for (i=0; i<60000; i++)
143 unsigned temp=READ_PORT_UCHAR((PUCHAR)MOUSE_COM);
146 if(restarts<300000) {
156 BOOLEAN InitializeMouse(PDEVICE_OBJECT DeviceObject)
158 int mbuttons=0, gotmouse=0;
159 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
167 // Check for Microsoft mouse (2 buttons)
168 if(CheckMouseType(2)!=0)
171 DbgPrint("Microsoft Mouse Detected\n");
176 // Check for Microsoft Systems mouse (3 buttons)
178 if(CheckMouseType(3)!=0)
181 DbgPrint("Microsoft Mouse Detected\n");
187 if(gotmouse==0) return FALSE;
189 DeviceExtension->InputDataCount = 0;
190 DeviceExtension->MouseInputData = ExAllocatePool(NonPagedPool, sizeof(MOUSE_INPUT_DATA) * MOUSE_BUFFER_SIZE);
192 MappedIrq = HalGetInterruptVector(Internal, 0, 0, MOUSE_IRQ,
195 IoConnectInterrupt(&DeviceExtension->MouseInterrupt, microsoft_mouse_handler, NULL,
196 NULL, MappedIrq, Dirql, Dirql, 0, FALSE,
202 VOID SerialMouseInitializeDataQueue(PVOID Context)
205 /* PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceExtension;
207 DeviceExtension->InputDataCount = 0;
208 DeviceExtension->MouseInputData = ExAllocatePool(NonPagedPool, sizeof(MOUSE_INPUT_DATA) * MOUSE_BUFFER_SIZE); */
211 BOOLEAN MouseSynchronizeRoutine(PVOID Context)
213 PIRP Irp = (PIRP)Context;
214 PMOUSE_INPUT_DATA rec = (PMOUSE_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer;
215 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
216 ULONG NrToRead = stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA);
219 if ((stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA))==NrToRead)
224 MouseDataRequired=stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA);
225 MouseDataRead=NrToRead;
231 VOID SerialMouseStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
233 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
235 if (KeSynchronizeExecution(DeviceExtension->MouseInterrupt, MouseSynchronizeRoutine, Irp))
237 Irp->IoStatus.Status = STATUS_SUCCESS;
238 Irp->IoStatus.Information = 0;
239 IoCompleteRequest(Irp, IO_NO_INCREMENT);
240 IoStartNextPacket(DeviceObject, FALSE);
244 NTSTATUS SerialMouseInternalDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
246 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
247 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
250 switch(Stack->Parameters.DeviceIoControl.IoControlCode)
252 case IOCTL_INTERNAL_MOUSE_CONNECT:
254 DeviceExtension->ClassInformation =
255 *((PCLASS_INFORMATION)Stack->Parameters.DeviceIoControl.Type3InputBuffer);
257 // Reinitialize the port input data queue synchronously
258 KeSynchronizeExecution(DeviceExtension->MouseInterrupt,
259 (PKSYNCHRONIZE_ROUTINE)SerialMouseInitializeDataQueue, DeviceExtension);
261 status = STATUS_SUCCESS;
265 status = STATUS_INVALID_DEVICE_REQUEST;
269 Irp->IoStatus.Status = status;
270 if (status == STATUS_PENDING) {
271 IoMarkIrpPending(Irp);
272 IoStartPacket(DeviceObject, Irp, NULL, NULL);
274 IoCompleteRequest(Irp, IO_NO_INCREMENT);
280 NTSTATUS SerialMouseDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
282 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
285 switch (stk->MajorFunction)
288 if (AlreadyOpened == TRUE)
290 Status = STATUS_SUCCESS;
294 Status = STATUS_SUCCESS;
295 AlreadyOpened = TRUE;
300 Status = STATUS_SUCCESS;
304 DbgPrint("NOT IMPLEMENTED\n");
305 Status = STATUS_NOT_IMPLEMENTED;
309 if (Status==STATUS_PENDING)
311 IoMarkIrpPending(Irp);
315 Irp->IoStatus.Status = Status;
316 Irp->IoStatus.Information = 0;
317 IoCompleteRequest(Irp,IO_NO_INCREMENT);
322 VOID SerialMouseIsrDpc(PKDPC Dpc, PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
324 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
326 (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassInformation.CallBack)(
327 DeviceExtension->ClassInformation.DeviceObject,
328 DeviceExtension->MouseInputData,
330 &DeviceExtension->InputDataCount);
332 DeviceExtension->InputDataCount = 0;
336 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
338 PDEVICE_OBJECT DeviceObject;
339 UNICODE_STRING DeviceName;
340 UNICODE_STRING SymlinkName;
341 PDEVICE_EXTENSION DeviceExtension;
343 DbgPrint("Serial Mouse Driver 0.0.4\n");
345 if(InitializeMouse(DeviceObject) == FALSE)
346 return STATUS_UNSUCCESSFUL;
348 DriverObject->MajorFunction[IRP_MJ_CREATE] = SerialMouseDispatch;
349 DriverObject->MajorFunction[IRP_MJ_CLOSE] = SerialMouseDispatch;
350 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = SerialMouseInternalDeviceControl;
351 DriverObject->DriverStartIo = SerialMouseStartIo;
353 RtlInitUnicodeStringFromLiteral(&DeviceName,
354 L"\\Device\\Mouse"); // FIXME: find correct device name
355 IoCreateDevice(DriverObject,
356 sizeof(DEVICE_EXTENSION),
358 FILE_DEVICE_SERIAL_MOUSE_PORT,
362 DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO;
364 RtlInitUnicodeStringFromLiteral(&SymlinkName,
365 L"\\??\\Mouse"); // FIXME: find correct device name
366 IoCreateSymbolicLink(&SymlinkName, &DeviceName);
368 DeviceExtension = DeviceObject->DeviceExtension;
369 KeInitializeDpc(&DeviceExtension->IsrDpc, (PKDEFERRED_ROUTINE)SerialMouseIsrDpc, DeviceObject);
370 KeInitializeDpc(&DeviceExtension->IsrDpcRetry, (PKDEFERRED_ROUTINE)SerialMouseIsrDpc, DeviceObject);
372 return(STATUS_SUCCESS);