2 * Serial Mouse driver 0.0.9
3 * Written by Jason Filby (jasonfilby@yahoo.com)
4 * And heavily rewritten by Filip Navara (xnavara@volny.cz)
5 * For ReactOS (www.reactos.com)
7 * Technical information about mouse protocols can be found
8 * in the file sermouse.txt.
11 /* INCLUDES *****************************************************************/
13 #include <ddk/ntddk.h>
14 #include <ddk/ntddmou.h>
20 * Compile time options
23 /* Support for the IOCTL_MOUSE_QUERY_ATTRIBUTES I/O control code */
24 #define SERMOUSE_QUERYATTRIBUTES_SUPPORT
25 /* Check for mouse on COM1? */
26 #define SERMOUSE_COM1_SUPPORT
27 /* Check for mouse on COM2? */
28 /* #define SERMOUSE_COM2_SUPPORT */
34 #define MOUSE_IRQ_COM1 4
35 #define MOUSE_IRQ_COM2 3
36 #define MOUSE_PORT_COM1 0x3f8
37 #define MOUSE_PORT_COM2 0x2f8
39 /* Maximum value plus one for \Device\PointerClass* device name */
40 #define POINTER_PORTS_MAXIMUM 8
41 /* Letter count for POINTER_PORTS_MAXIMUM variable * sizeof(WCHAR) */
42 #define SUFFIX_MAXIMUM_SIZE (1 * sizeof(WCHAR))
45 #define MOUSE_TYPE_NONE 0
46 /* Microsoft Mouse with 2 buttons */
47 #define MOUSE_TYPE_MICROSOFT 1
48 /* Logitech Mouse with 3 buttons */
49 #define MOUSE_TYPE_LOGITECH 2
50 /* Microsoft Wheel Mouse (aka Z Mouse) */
51 #define MOUSE_TYPE_WHEELZ 3
52 /* Mouse Systems Mouse */
53 #define MOUSE_TYPE_MOUSESYSTEMS 4
55 /* Size for packet buffer used in interrupt routine */
56 #define PACKET_BUFFER_SIZE 4
58 /* Hardware byte mask for left button */
59 #define LEFT_BUTTON_MASK 0x20
60 /* Hardware to Microsoft specific code byte shift for left button */
61 #define LEFT_BUTTON_SHIFT 5
62 /* Hardware byte mask for right button */
63 #define RIGHT_BUTTON_MASK 0x10
64 /* Hardware to Microsoft specific code byte shift for right button */
65 #define RIGHT_BUTTON_SHIFT 3
66 /* Hardware byte mask for middle button */
67 #define MIDDLE_BUTTON_MASK 0x20
68 /* Hardware to Microsoft specific code byte shift for middle button */
69 #define MIDDLE_BUTTON_SHIFT 3
71 /* Microsoft byte mask for left button */
72 #define MOUSE_BUTTON_LEFT 0x01
73 /* Microsoft byte mask for right button */
74 #define MOUSE_BUTTON_RIGHT 0x02
75 /* Microsoft byte mask for middle button */
76 #define MOUSE_BUTTON_MIDDLE 0x04
82 typedef struct _DEVICE_EXTENSION
84 PDEVICE_OBJECT DeviceObject
;
86 ULONG InputDataCount
[2];
87 MOUSE_INPUT_DATA MouseInputData
[2][MOUSE_BUFFER_SIZE
];
88 CLASS_INFORMATION ClassInformation
;
89 PKINTERRUPT MouseInterrupt
;
93 UCHAR PacketBuffer
[PACKET_BUFFER_SIZE
];
94 ULONG PacketBufferPosition
;
95 ULONG PreviousButtons
;
96 #ifdef SERMOUSE_QUERYATTRIBUTES_SUPPORT
97 MOUSE_ATTRIBUTES AttributesInformation
;
99 } DEVICE_EXTENSION
, *PDEVICE_EXTENSION
;
105 /* Waits until the mouse calms down but also quits out after a while
106 * in case some destructive user wants to keep moving the mouse
107 * before we're done */
108 VOID
ClearMouse(ULONG Port
)
114 for (i
= 0; i
< 60000; i
++)
116 Temp
= READ_PORT_UCHAR((PUCHAR
)Port
);
120 if (Restarts
< 300000)
129 SerialMouseInterruptService(IN PKINTERRUPT Interrupt
, PVOID ServiceContext
)
131 PDEVICE_OBJECT DeviceObject
= (PDEVICE_OBJECT
)ServiceContext
;
132 PDEVICE_EXTENSION DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
133 UCHAR
*PacketBuffer
= DeviceExtension
->PacketBuffer
;
134 ULONG MousePort
= DeviceExtension
->MousePort
;
135 UCHAR InterruptId
= READ_PORT_UCHAR((PUCHAR
)MousePort
+ 2);
138 PMOUSE_INPUT_DATA Input
;
139 ULONG ButtonsDifference
;
141 /* Is the interrupt for us? */
142 if ((InterruptId
& 0x01) == 0x01)
147 /* Not a Receive Data Available interrupt? */
148 if ((InterruptId
& 0x04) == 0)
153 /* Read all available data and process */
154 while ((READ_PORT_UCHAR((PUCHAR
)MousePort
+ 5) & 0x01) != 0)
156 RecievedByte
= READ_PORT_UCHAR((PUCHAR
)MousePort
);
159 if ((RecievedByte
& 0x40) == 0x40)
160 DeviceExtension
->PacketBufferPosition
= 0;
162 PacketBuffer
[DeviceExtension
->PacketBufferPosition
] =
163 (RecievedByte
& 0x7f);
164 ++DeviceExtension
->PacketBufferPosition
;
166 /* Process packet if complete */
167 if (DeviceExtension
->PacketBufferPosition
>= 3)
169 Queue
= DeviceExtension
->ActiveQueue
% 2;
171 /* Prevent buffer overflow */
172 if (DeviceExtension
->InputDataCount
[Queue
] == MOUSE_BUFFER_SIZE
)
175 Input
= &DeviceExtension
->MouseInputData
[Queue
][DeviceExtension
->InputDataCount
[Queue
]];
177 if (DeviceExtension
->PacketBufferPosition
== 3)
179 /* Retrieve change in x and y from packet */
180 Input
->LastX
= (signed char)(PacketBuffer
[1] | ((PacketBuffer
[0] & 0x03) << 6));
181 Input
->LastY
= (signed char)(PacketBuffer
[2] | ((PacketBuffer
[0] & 0x0c) << 4));
183 /* Determine the current state of the buttons */
184 Input
->RawButtons
= (DeviceExtension
->PreviousButtons
& MOUSE_BUTTON_MIDDLE
) |
185 ((UCHAR
)(PacketBuffer
[0] & LEFT_BUTTON_MASK
) >> LEFT_BUTTON_SHIFT
) |
186 ((UCHAR
)(PacketBuffer
[0] & RIGHT_BUTTON_MASK
) >> RIGHT_BUTTON_SHIFT
);
188 else if (DeviceExtension
->PacketBufferPosition
== 4)
190 DeviceExtension
->PacketBufferPosition
= 0;
191 /* If middle button state changed than report event */
192 if (((UCHAR
)(PacketBuffer
[3] & MIDDLE_BUTTON_MASK
) >> MIDDLE_BUTTON_SHIFT
) ^
193 (DeviceExtension
->PreviousButtons
& MOUSE_BUTTON_MIDDLE
))
195 Input
->RawButtons
^= MOUSE_BUTTON_MIDDLE
;
205 /* Determine ButtonFlags */
206 Input
->ButtonFlags
= 0;
207 ButtonsDifference
= DeviceExtension
->PreviousButtons
^ Input
->RawButtons
;
209 if (ButtonsDifference
!= 0)
211 if (ButtonsDifference
& MOUSE_BUTTON_LEFT
)
213 if (Input
->RawButtons
& MOUSE_BUTTON_LEFT
)
214 Input
->ButtonFlags
|= MOUSE_LEFT_BUTTON_DOWN
;
216 Input
->ButtonFlags
|= MOUSE_LEFT_BUTTON_UP
;
219 if (ButtonsDifference
& MOUSE_BUTTON_RIGHT
)
221 if (Input
->RawButtons
& MOUSE_BUTTON_RIGHT
)
222 Input
->ButtonFlags
|= MOUSE_RIGHT_BUTTON_DOWN
;
224 Input
->ButtonFlags
|= MOUSE_RIGHT_BUTTON_UP
;
227 if (ButtonsDifference
& MOUSE_BUTTON_MIDDLE
)
229 if (Input
->RawButtons
& MOUSE_BUTTON_MIDDLE
)
230 Input
->ButtonFlags
|= MOUSE_MIDDLE_BUTTON_DOWN
;
232 Input
->ButtonFlags
|= MOUSE_MIDDLE_BUTTON_UP
;
236 /* Send the Input data to the Mouse Class driver */
237 DeviceExtension
->InputDataCount
[Queue
]++;
238 KeInsertQueueDpc(&DeviceExtension
->IsrDpc
, DeviceObject
->CurrentIrp
, NULL
);
240 /* Copy RawButtons to Previous Buttons for Input */
241 DeviceExtension
->PreviousButtons
= Input
->RawButtons
;
249 SerialMouseInitializeDataQueue(PVOID Context
)
254 MouseSynchronizeRoutine(PVOID Context
)
260 SerialMouseStartIo(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
262 PDEVICE_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
264 if (KeSynchronizeExecution(DeviceExtension
->MouseInterrupt
, MouseSynchronizeRoutine
, Irp
))
267 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
268 Irp
->IoStatus
.Information
= 0;
269 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
270 oldIrql
= KeGetCurrentIrql();
271 if (oldIrql
< DISPATCH_LEVEL
)
273 KeRaiseIrql(DISPATCH_LEVEL
, &oldIrql
);
274 IoStartNextPacket(DeviceObject
, FALSE
);
275 KeLowerIrql(oldIrql
);
279 IoStartNextPacket (DeviceObject
, FALSE
);
285 SerialMouseInternalDeviceControl(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
287 PDEVICE_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
288 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
291 switch (Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
293 case IOCTL_INTERNAL_MOUSE_CONNECT
:
294 DeviceExtension
->ClassInformation
=
295 *((PCLASS_INFORMATION
)Stack
->Parameters
.DeviceIoControl
.Type3InputBuffer
);
297 /* Reinitialize the port input data queue synchronously */
298 KeSynchronizeExecution(DeviceExtension
->MouseInterrupt
,
299 (PKSYNCHRONIZE_ROUTINE
)SerialMouseInitializeDataQueue
,
302 Status
= STATUS_SUCCESS
;
305 #ifdef SERMOUSE_QUERYATTRIBUTES_SUPPORT
306 case IOCTL_MOUSE_QUERY_ATTRIBUTES
:
307 if (Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
>= sizeof(MOUSE_ATTRIBUTES
))
309 *(PMOUSE_ATTRIBUTES
)Irp
->AssociatedIrp
.SystemBuffer
=
310 DeviceExtension
->AttributesInformation
;
311 Irp
->IoStatus
.Information
= sizeof(MOUSE_ATTRIBUTES
);
312 Status
= STATUS_SUCCESS
;
314 Status
= STATUS_BUFFER_TOO_SMALL
;
320 Status
= STATUS_INVALID_DEVICE_REQUEST
;
324 Irp
->IoStatus
.Status
= Status
;
325 if (Status
== STATUS_PENDING
)
327 IoMarkIrpPending(Irp
);
328 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
332 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
339 SerialMouseDispatch(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
341 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
344 switch (Stack
->MajorFunction
)
348 Status
= STATUS_SUCCESS
;
352 DbgPrint("NOT IMPLEMENTED\n");
353 Status
= STATUS_NOT_IMPLEMENTED
;
357 if (Status
== STATUS_PENDING
)
359 IoMarkIrpPending(Irp
);
363 Irp
->IoStatus
.Status
= Status
;
364 Irp
->IoStatus
.Information
= 0;
365 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
371 VOID
SerialMouseIsrDpc(PKDPC Dpc
, PDEVICE_OBJECT DeviceObject
, PIRP Irp
, PVOID Context
)
373 PDEVICE_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
376 Queue
= DeviceExtension
->ActiveQueue
% 2;
377 InterlockedIncrement((PLONG
)&DeviceExtension
->ActiveQueue
);
378 (*(PSERVICE_CALLBACK_ROUTINE
)DeviceExtension
->ClassInformation
.CallBack
)(
379 DeviceExtension
->ClassInformation
.DeviceObject
,
380 DeviceExtension
->MouseInputData
[Queue
],
382 &DeviceExtension
->InputDataCount
[Queue
]);
384 DeviceExtension
->InputDataCount
[Queue
] = 0;
387 VOID
InitializeSerialPort(ULONG Port
)
390 WRITE_PORT_UCHAR((PUCHAR
)Port
+ 3, 0);
391 WRITE_PORT_UCHAR((PUCHAR
)Port
+ 2, 0); /* FCR: disable FIFO */
392 WRITE_PORT_UCHAR((PUCHAR
)Port
+ 1, 0); /* IER: disable ints */
394 WRITE_PORT_UCHAR((PUCHAR
)Port
+ 3, 0x80);
395 /* Set serial port speed */
396 WRITE_PORT_UCHAR((PUCHAR
)Port
, 0x60);
397 WRITE_PORT_UCHAR((PUCHAR
)Port
+ 1, 0);
398 /* Set DLAB off and set LCR */
399 WRITE_PORT_UCHAR((PUCHAR
)Port
+ 3, 2);
402 BOOLEAN
UARTReadChar(ULONG Port
, CHAR
*Value
, ULONG Timeout
)
406 for (i
= 0; i
< Timeout
; i
++)
408 for (j
= 0; j
< 1000; j
++)
410 /* Is there a character ready? */
411 if (READ_PORT_UCHAR((PUCHAR
)Port
+ 5) & 0x01)
413 /* Yes, read it and return */
414 *Value
= READ_PORT_UCHAR((PUCHAR
)Port
);
420 KeStallExecutionProcessor(1);
428 ULONG
DetectMicrosoftMouse(ULONG Port
)
434 /* Save original LCR/MCR */
435 LCR
= READ_PORT_UCHAR((PUCHAR
)Port
+ 3); /* LCR (line ctrl reg) */
436 MCR
= READ_PORT_UCHAR((PUCHAR
)Port
+ 4); /* MCR (modem ctrl reg) */
439 WRITE_PORT_UCHAR((PUCHAR
)Port
+ 4, 0); /* MCR: DTR/RTS/OUT2 off */
441 /* Set communications parameters */
442 InitializeSerialPort(Port
);
444 /* Flush receive buffer */
445 (void) READ_PORT_UCHAR((PUCHAR
)Port
);
446 /* right? -> wait two ticks (approx 1/9 sec) */
447 KeStallExecutionProcessor(100000);
449 /* Enable DTR/RTS (OUT2 disabled) */
450 WRITE_PORT_UCHAR((PUCHAR
)Port
+ 4, 3);
452 if (UARTReadChar(Port
, &Buffer
[0], 500))
457 if (UARTReadChar(Port
, &Buffer
[Count
], 100))
464 return MOUSE_TYPE_NONE
;
466 /* Restore LCR/MCR */
467 WRITE_PORT_UCHAR((PUCHAR
)Port
+ 3, LCR
); /* LCR (line ctrl reg) */
468 WRITE_PORT_UCHAR((PUCHAR
)Port
+ 4, MCR
); /* MCR (modem ctrl reg) */
470 for (i
= 0; i
< Count
; ++i
)
472 /* Sign for Microsoft Ballpoint */
473 if (Buffer
[i
] == 'B')
475 DbgPrint("Microsoft Ballpoint device detected");
476 DbgPrint("THIS DEVICE IS NOT SUPPORTED, YET");
477 return MOUSE_TYPE_NONE
;
479 /* Sign for Microsoft Mouse protocol followed by button specifier */
480 if (Buffer
[i
] == 'M')
485 return MOUSE_TYPE_NONE
;
487 switch (Buffer
[i
+ 1])
490 DbgPrint("Microsoft Mouse with 3-buttons detected\n");
491 return MOUSE_TYPE_LOGITECH
;
493 DbgPrint("Microsoft Wheel Mouse detected\n");
494 return MOUSE_TYPE_WHEELZ
;
497 DbgPrint("Microsoft Mouse with 2-buttons detected\n");
498 return MOUSE_TYPE_MICROSOFT
;
503 return MOUSE_TYPE_NONE
;
507 AllocatePointerDevice(PDRIVER_OBJECT DriverObject
)
509 PDEVICE_OBJECT DeviceObject
;
510 UNICODE_STRING DeviceName
;
511 UNICODE_STRING SuffixString
;
512 PDEVICE_EXTENSION DeviceExtension
;
516 /* Allocate buffer for full device name */
517 RtlInitUnicodeString(&DeviceName
, NULL
);
518 DeviceName
.MaximumLength
= sizeof(DD_MOUSE_DEVICE_NAME_U
) + SUFFIX_MAXIMUM_SIZE
+ sizeof(UNICODE_NULL
);
519 DeviceName
.Buffer
= ExAllocatePool(PagedPool
, DeviceName
.MaximumLength
);
520 RtlAppendUnicodeToString(&DeviceName
, DD_MOUSE_DEVICE_NAME_U
);
522 /* Allocate buffer for device name suffix */
523 RtlInitUnicodeString(&SuffixString
, NULL
);
524 SuffixString
.MaximumLength
= SUFFIX_MAXIMUM_SIZE
+ sizeof(UNICODE_NULL
);
525 SuffixString
.Buffer
= ExAllocatePool(PagedPool
, SuffixString
.MaximumLength
);
527 /* Generate full qualified name with suffix */
528 for (Suffix
= 0; Suffix
< POINTER_PORTS_MAXIMUM
; ++Suffix
)
530 RtlIntegerToUnicodeString(Suffix
, 10, &SuffixString
);
531 RtlAppendUnicodeToString(&DeviceName
, SuffixString
.Buffer
);
532 Status
= IoCreateDevice(DriverObject
, sizeof(DEVICE_EXTENSION
),
533 &DeviceName
, FILE_DEVICE_SERIAL_MOUSE_PORT
, 0, TRUE
, &DeviceObject
);
534 /* Device successfully created, leave the cyclus */
535 if (NT_SUCCESS(Status
))
537 DeviceName
.Length
-= SuffixString
.Length
;
540 ExFreePool(DeviceName
.Buffer
);
541 ExFreePool(SuffixString
.Buffer
);
543 /* Couldn't create device */
544 if (!NT_SUCCESS(Status
))
549 DeviceObject
->Flags
= DeviceObject
->Flags
| DO_BUFFERED_IO
;
551 DeviceExtension
= DeviceObject
->DeviceExtension
;
552 KeInitializeDpc(&DeviceExtension
->IsrDpc
, (PKDEFERRED_ROUTINE
)SerialMouseIsrDpc
, DeviceObject
);
558 InitializeMouse(ULONG Port
, ULONG Irq
, PDRIVER_OBJECT DriverObject
)
560 PDEVICE_EXTENSION DeviceExtension
;
561 PDEVICE_OBJECT DeviceObject
;
567 /* Try to detect mouse on specified port */
568 MouseType
= DetectMicrosoftMouse(Port
);
570 /* No mouse, no need to continue */
571 if (MouseType
== MOUSE_TYPE_NONE
)
576 /* Enable interrupts */
577 WRITE_PORT_UCHAR((PUCHAR
)(Port
) + 1, 1);
581 /* Enable RTS, DTR and OUT2 */
582 WRITE_PORT_UCHAR((PUCHAR
)Port
+ 4, 0x0b);
584 /* Allocate new device */
585 DeviceObject
= AllocatePointerDevice(DriverObject
);
588 DbgPrint("Oops, couldn't creat device object.\n");
592 DeviceExtension
= DeviceObject
->DeviceExtension
;
594 /* Setup device extension structure */
595 DeviceExtension
->ActiveQueue
= 0;
596 DeviceExtension
->MouseType
= MouseType
;
597 DeviceExtension
->MousePort
= Port
;
598 DeviceExtension
->PacketBufferPosition
= 0;
599 DeviceExtension
->PreviousButtons
= 0;
600 #ifdef SERMOUSE_QUERYATTRIBUTES_SUPPORT
603 case MOUSE_TYPE_MICROSOFT
:
604 DeviceExtension
->AttributesInformation
.MouseIdentifier
= MOUSE_SERIAL_HARDWARE
;
605 DeviceExtension
->AttributesInformation
.NumberOfButtons
= 2;
607 case MOUSE_TYPE_LOGITECH
:
608 DeviceExtension
->AttributesInformation
.MouseIdentifier
= MOUSE_SERIAL_HARDWARE
;
609 DeviceExtension
->AttributesInformation
.NumberOfButtons
= 3;
611 case MOUSE_TYPE_WHEELZ
:
612 DeviceExtension
->AttributesInformation
.MouseIdentifier
= WHEELMOUSE_SERIAL_HARDWARE
;
613 DeviceExtension
->AttributesInformation
.NumberOfButtons
= 3;
616 DeviceExtension
->AttributesInformation
.SampleRate
= 40;
617 DeviceExtension
->AttributesInformation
.InputDataQueueLength
= MOUSE_BUFFER_SIZE
;
620 MappedIrq
= HalGetInterruptVector(Internal
, 0, 0, Irq
, &Dirql
, &Affinity
);
623 &DeviceExtension
->MouseInterrupt
, SerialMouseInterruptService
,
624 DeviceObject
, NULL
, MappedIrq
, Dirql
, Dirql
, 0, FALSE
,
632 GetMouseResourceData(PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor
,
636 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
639 for (i
= 0; i
< FullDescriptor
->PartialResourceList
.Count
; i
++)
641 PartialDescriptor
= &FullDescriptor
->PartialResourceList
.PartialDescriptors
[i
];
643 switch (PartialDescriptor
->Type
)
645 case CmResourceTypePort
:
646 *Port
= (ULONG
)PartialDescriptor
->u
.Port
.Start
.u
.LowPart
;
649 case CmResourceTypeInterrupt
:
650 *Interrupt
= (ULONG
)PartialDescriptor
->u
.Interrupt
.Level
;
658 GetMouseResources(PULONG Port
,
661 OBJECT_ATTRIBUTES ObjectAttributes
;
662 UNICODE_STRING KeyName
;
665 HANDLE BusInstanceKey
;
666 HANDLE ControllerKey
;
667 HANDLE ControllerInstanceKey
;
668 HANDLE PeripheralKey
;
669 HANDLE PeripheralInstanceKey
;
671 ULONG ControllerInstance
;
672 ULONG PeripheralInstance
;
674 ULONG ReturnedLength
;
675 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
678 DPRINT("GetMouseResources() called\n");
680 /* Open the bus key */
681 RtlInitUnicodeString(&KeyName
,
682 L
"\\Registry\\Machine\\HARDWARE\\Description\\System\\MultifunctionAdapter");
683 InitializeObjectAttributes(&ObjectAttributes
,
685 OBJ_CASE_INSENSITIVE
,
688 Status
= ZwOpenKey(&BusKey
,
691 if (!NT_SUCCESS(Status
))
693 DPRINT("NtOpenKey() failed (Status %lx)\n", Status
);
700 sprintf((PCHAR
)Buffer
, "%lu", (ULONG
)0);
701 swprintf(Buffer
, L
"%lu", BusInstance
);
702 RtlInitUnicodeString(&KeyName
,
704 InitializeObjectAttributes(&ObjectAttributes
,
706 OBJ_CASE_INSENSITIVE
,
709 Status
= ZwOpenKey(&BusInstanceKey
,
712 if (!NT_SUCCESS(Status
))
714 DPRINT("NtOpenKey() failed (Status %lx)\n", Status
);
719 /* Open the controller type key */
720 RtlInitUnicodeString(&KeyName
,
721 L
"SerialController");
722 InitializeObjectAttributes(&ObjectAttributes
,
724 OBJ_CASE_INSENSITIVE
,
727 Status
= ZwOpenKey(&ControllerKey
,
730 if (NT_SUCCESS(Status
))
732 ControllerInstance
= 0;
735 /* Open the pointer controller instance key */
736 swprintf(Buffer
, L
"%lu", ControllerInstance
);
737 RtlInitUnicodeString(&KeyName
,
739 InitializeObjectAttributes(&ObjectAttributes
,
741 OBJ_CASE_INSENSITIVE
,
744 Status
= ZwOpenKey(&ControllerInstanceKey
,
747 if (!NT_SUCCESS(Status
))
749 DPRINT("NtOpenKey() failed (Status %lx)\n", Status
);
750 ZwClose(ControllerKey
);
751 ZwClose(BusInstanceKey
);
756 /* Open the 'PointerPeripheral' key */
757 RtlInitUnicodeString(&KeyName
,
758 L
"PointerPeripheral");
759 InitializeObjectAttributes(&ObjectAttributes
,
761 OBJ_CASE_INSENSITIVE
,
762 ControllerInstanceKey
,
764 Status
= ZwOpenKey(&PeripheralKey
,
767 if (NT_SUCCESS(Status
))
769 PeripheralInstance
= 0;
772 /* Open the pointer peripheral instance key */
773 swprintf(Buffer
, L
"%lu", PeripheralInstance
);
774 RtlInitUnicodeString(&KeyName
,
776 InitializeObjectAttributes(&ObjectAttributes
,
778 OBJ_CASE_INSENSITIVE
,
781 Status
= ZwOpenKey(&PeripheralInstanceKey
,
784 if (!NT_SUCCESS(Status
))
786 DPRINT("ZwOpenKey() failed (Status %lx)\n", Status
);
787 ZwClose(PeripheralKey
);
788 ZwClose(ControllerInstanceKey
);
789 ZwClose(ControllerKey
);
790 ZwClose(BusInstanceKey
);
795 /* Get peripheral identifier */
796 RtlInitUnicodeString(&KeyName
,
797 L
"Configuration Data");
799 BufferLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
);
801 ValueInfo
= ExAllocatePool(NonPagedPool
,
803 if (ValueInfo
== NULL
)
805 DPRINT("ExAllocatePool() failed\n");
806 ZwClose(PeripheralInstanceKey
);
807 ZwClose(PeripheralKey
);
808 ZwClose(ControllerInstanceKey
);
809 ZwClose(ControllerKey
);
810 ZwClose(BusInstanceKey
);
815 Status
= ZwQueryValueKey(ControllerInstanceKey
,
817 KeyValuePartialInformation
,
821 DPRINT("ZwQueryValueKey() called (Status %lx)\n", Status
);
822 DPRINT("ReturnedLength %ld\n", ReturnedLength
);
824 ExFreePool(ValueInfo
);
825 if (!NT_SUCCESS(Status
) && Status
!= STATUS_BUFFER_TOO_SMALL
)
827 DPRINT("ZwQueryValueKey() failed (Status %lx)\n", Status
);
828 ZwClose(PeripheralInstanceKey
);
829 ZwClose(PeripheralKey
);
830 ZwClose(ControllerInstanceKey
);
831 ZwClose(ControllerKey
);
832 ZwClose(BusInstanceKey
);
837 BufferLength
= ReturnedLength
;
838 ValueInfo
= ExAllocatePool(NonPagedPool
,
840 if (ValueInfo
== NULL
)
842 DPRINT("ExAllocatePool() failed\n");
843 ZwClose(PeripheralInstanceKey
);
844 ZwClose(PeripheralKey
);
845 ZwClose(ControllerInstanceKey
);
846 ZwClose(ControllerKey
);
847 ZwClose(BusInstanceKey
);
852 Status
= ZwQueryValueKey(ControllerInstanceKey
,
854 KeyValuePartialInformation
,
858 if (NT_SUCCESS(Status
))
861 GetMouseResourceData((PCM_FULL_RESOURCE_DESCRIPTOR
)(ValueInfo
->Data
),
865 ExFreePool(ValueInfo
);
866 ZwClose(PeripheralInstanceKey
);
867 ZwClose(PeripheralKey
);
868 ZwClose(ControllerInstanceKey
);
869 ZwClose(ControllerKey
);
870 ZwClose(BusInstanceKey
);
875 ExFreePool(ValueInfo
);
877 ZwClose(PeripheralInstanceKey
);
879 PeripheralInstance
++;
882 ZwClose(PeripheralKey
);
885 ZwClose(ControllerInstanceKey
);
887 ControllerInstance
++;
890 ZwClose(ControllerKey
);
893 ZwClose(BusInstanceKey
);
906 DriverEntry(PDRIVER_OBJECT DriverObject
, PUNICODE_STRING RegistryPath
)
908 BOOLEAN MouseFound
= FALSE
;
909 ULONG BaseAddress
= (ULONG
)-1;
910 ULONG Interrupt
= (ULONG
)-1;
912 DPRINT1("Serial Mouse Driver 0.0.9\n");
914 if (GetMouseResources(&BaseAddress
, &Interrupt
))
916 if (BaseAddress
!= (ULONG
)-1 && Interrupt
!= (ULONG
)-1)
918 DPRINT1("Found mouse: Port %lx Interupt %lu\n", BaseAddress
, Interrupt
);
919 MouseFound
|= InitializeMouse(BaseAddress
, Interrupt
, DriverObject
);
924 #ifdef SERMOUSE_COM1_SUPPORT
925 DPRINT1("Trying to find mouse on COM1\n");
926 MouseFound
|= InitializeMouse(MOUSE_PORT_COM1
, MOUSE_IRQ_COM1
, DriverObject
);
928 #ifdef SERMOUSE_COM2_SUPPORT
929 DPRINT1("Trying to find mouse on COM2\n");
930 MouseFound
|= InitializeMouse(MOUSE_PORT_COM2
, MOUSE_IRQ_COM2
, DriverObject
);
936 DPRINT1("No serial mouse found.\n");
937 return STATUS_UNSUCCESSFUL
;
940 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = SerialMouseDispatch
;
941 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = SerialMouseDispatch
;
942 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = SerialMouseInternalDeviceControl
;
943 DriverObject
->DriverStartIo
= SerialMouseStartIo
;
945 return STATUS_SUCCESS
;