Delete old legacy serial mouse driver, will be replaced by a PnP driver in next commit

svn path=/trunk/; revision=19099
This commit is contained in:
Hervé Poussineau 2005-11-09 11:54:53 +00:00
parent 9fcc9fe902
commit 9bfa51a8fc
4 changed files with 0 additions and 1050 deletions

View file

@ -1,953 +0,0 @@
/*
* Serial Mouse driver 0.0.9
* Written by Jason Filby (jasonfilby@yahoo.com)
* And heavily rewritten by Filip Navara (xnavara@volny.cz)
* For ReactOS (www.reactos.com)
*
* Technical information about mouse protocols can be found
* in the file sermouse.txt.
*/
/* INCLUDES *****************************************************************/
#include <stdio.h>
#include <ddk/ntddk.h>
#include <ddk/ntddmou.h>
#include <ddk/kbdmou.h>
#define NDEBUG
#include <debug.h>
/*
* Compile time options
*/
/* Support for the IOCTL_MOUSE_QUERY_ATTRIBUTES I/O control code */
#define SERMOUSE_QUERYATTRIBUTES_SUPPORT
/* Check for mouse on COM1? */
#define SERMOUSE_COM1_SUPPORT
/* Check for mouse on COM2? */
/* #define SERMOUSE_COM2_SUPPORT */
/*
* Definitions
*/
#define MOUSE_IRQ_COM1 4
#define MOUSE_IRQ_COM2 3
#define MOUSE_PORT_COM1 0x3f8
#define MOUSE_PORT_COM2 0x2f8
/* Maximum value plus one for \Device\PointerClass* device name */
#define POINTER_PORTS_MAXIMUM 8
/* Letter count for POINTER_PORTS_MAXIMUM variable * sizeof(WCHAR) */
#define SUFFIX_MAXIMUM_SIZE (1 * sizeof(WCHAR))
/* No Mouse */
#define MOUSE_TYPE_NONE 0
/* Microsoft Mouse with 2 buttons */
#define MOUSE_TYPE_MICROSOFT 1
/* Logitech Mouse with 3 buttons */
#define MOUSE_TYPE_LOGITECH 2
/* Microsoft Wheel Mouse (aka Z Mouse) */
#define MOUSE_TYPE_WHEELZ 3
/* Mouse Systems Mouse */
#define MOUSE_TYPE_MOUSESYSTEMS 4
/* Size for packet buffer used in interrupt routine */
#define PACKET_BUFFER_SIZE 4
/* Hardware byte mask for left button */
#define LEFT_BUTTON_MASK 0x20
/* Hardware to Microsoft specific code byte shift for left button */
#define LEFT_BUTTON_SHIFT 5
/* Hardware byte mask for right button */
#define RIGHT_BUTTON_MASK 0x10
/* Hardware to Microsoft specific code byte shift for right button */
#define RIGHT_BUTTON_SHIFT 3
/* Hardware byte mask for middle button */
#define MIDDLE_BUTTON_MASK 0x20
/* Hardware to Microsoft specific code byte shift for middle button */
#define MIDDLE_BUTTON_SHIFT 3
/* Microsoft byte mask for left button */
#define MOUSE_BUTTON_LEFT 0x01
/* Microsoft byte mask for right button */
#define MOUSE_BUTTON_RIGHT 0x02
/* Microsoft byte mask for middle button */
#define MOUSE_BUTTON_MIDDLE 0x04
#define MOUSE_BUFFER_SIZE 100
/*
* Structures
*/
typedef struct _DEVICE_EXTENSION
{
PDEVICE_OBJECT DeviceObject;
ULONG ActiveQueue;
ULONG InputDataCount[2];
MOUSE_INPUT_DATA MouseInputData[2][MOUSE_BUFFER_SIZE];
CONNECT_DATA ClassInformation;
PKINTERRUPT MouseInterrupt;
KDPC IsrDpc;
ULONG MousePort;
ULONG MouseType;
UCHAR PacketBuffer[PACKET_BUFFER_SIZE];
ULONG PacketBufferPosition;
ULONG PreviousButtons;
#ifdef SERMOUSE_QUERYATTRIBUTES_SUPPORT
MOUSE_ATTRIBUTES AttributesInformation;
#endif
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
/*
* Functions
*/
NTSTATUS STDCALL
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
/* Waits until the mouse calms down but also quits out after a while
* in case some destructive user wants to keep moving the mouse
* before we're done */
static VOID ClearMouse(ULONG Port)
{
ULONG Restarts = 0;
ULONG i;
UCHAR Temp;
for (i = 0; i < 60000; i++)
{
Temp = READ_PORT_UCHAR((PUCHAR)Port);
if (Temp != 0)
{
Restarts++;
if (Restarts < 300000)
i = 0;
else
i = 60000;
}
}
}
static BOOLEAN STDCALL
SerialMouseInterruptService(IN PKINTERRUPT Interrupt, PVOID ServiceContext)
{
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)ServiceContext;
PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
UCHAR *PacketBuffer = DeviceExtension->PacketBuffer;
ULONG MousePort = DeviceExtension->MousePort;
UCHAR InterruptId = READ_PORT_UCHAR((PUCHAR)MousePort + 2);
UCHAR RecievedByte;
ULONG Queue;
PMOUSE_INPUT_DATA Input;
ULONG ButtonsDifference;
/* Is the interrupt for us? */
if ((InterruptId & 0x01) == 0x01)
{
return FALSE;
}
/* Not a Receive Data Available interrupt? */
if ((InterruptId & 0x04) == 0)
{
return TRUE;
}
/* Read all available data and process */
while ((READ_PORT_UCHAR((PUCHAR)MousePort + 5) & 0x01) != 0)
{
RecievedByte = READ_PORT_UCHAR((PUCHAR)MousePort);
/* Synchronize */
if ((RecievedByte & 0x40) == 0x40)
DeviceExtension->PacketBufferPosition = 0;
PacketBuffer[DeviceExtension->PacketBufferPosition] =
(RecievedByte & 0x7f);
++DeviceExtension->PacketBufferPosition;
/* Process packet if complete */
if (DeviceExtension->PacketBufferPosition >= 3)
{
Queue = DeviceExtension->ActiveQueue % 2;
/* Prevent buffer overflow */
if (DeviceExtension->InputDataCount[Queue] == MOUSE_BUFFER_SIZE)
continue;
Input = &DeviceExtension->MouseInputData[Queue][DeviceExtension->InputDataCount[Queue]];
if (DeviceExtension->PacketBufferPosition == 3)
{
/* Retrieve change in x and y from packet */
Input->LastX = (signed char)(PacketBuffer[1] | ((PacketBuffer[0] & 0x03) << 6));
Input->LastY = (signed char)(PacketBuffer[2] | ((PacketBuffer[0] & 0x0c) << 4));
/* Determine the current state of the buttons */
Input->RawButtons = (DeviceExtension->PreviousButtons & MOUSE_BUTTON_MIDDLE) |
((UCHAR)(PacketBuffer[0] & LEFT_BUTTON_MASK) >> LEFT_BUTTON_SHIFT) |
((UCHAR)(PacketBuffer[0] & RIGHT_BUTTON_MASK) >> RIGHT_BUTTON_SHIFT);
}
else if (DeviceExtension->PacketBufferPosition == 4)
{
DeviceExtension->PacketBufferPosition = 0;
/* If middle button state changed than report event */
if (((UCHAR)(PacketBuffer[3] & MIDDLE_BUTTON_MASK) >> MIDDLE_BUTTON_SHIFT) ^
(DeviceExtension->PreviousButtons & MOUSE_BUTTON_MIDDLE))
{
Input->RawButtons ^= MOUSE_BUTTON_MIDDLE;
Input->LastX = 0;
Input->LastY = 0;
}
else
{
continue;
}
}
/* Determine ButtonFlags */
Input->ButtonFlags = 0;
ButtonsDifference = DeviceExtension->PreviousButtons ^ Input->RawButtons;
if (ButtonsDifference != 0)
{
if (ButtonsDifference & MOUSE_BUTTON_LEFT)
{
if (Input->RawButtons & MOUSE_BUTTON_LEFT)
Input->ButtonFlags |= MOUSE_LEFT_BUTTON_DOWN;
else
Input->ButtonFlags |= MOUSE_LEFT_BUTTON_UP;
}
if (ButtonsDifference & MOUSE_BUTTON_RIGHT)
{
if (Input->RawButtons & MOUSE_BUTTON_RIGHT)
Input->ButtonFlags |= MOUSE_RIGHT_BUTTON_DOWN;
else
Input->ButtonFlags |= MOUSE_RIGHT_BUTTON_UP;
}
if (ButtonsDifference & MOUSE_BUTTON_MIDDLE)
{
if (Input->RawButtons & MOUSE_BUTTON_MIDDLE)
Input->ButtonFlags |= MOUSE_MIDDLE_BUTTON_DOWN;
else
Input->ButtonFlags |= MOUSE_MIDDLE_BUTTON_UP;
}
}
/* Send the Input data to the Mouse Class driver */
DeviceExtension->InputDataCount[Queue]++;
KeInsertQueueDpc(&DeviceExtension->IsrDpc, DeviceObject->CurrentIrp, NULL);
/* Copy RawButtons to Previous Buttons for Input */
DeviceExtension->PreviousButtons = Input->RawButtons;
}
}
return TRUE;
}
static VOID
SerialMouseInitializeDataQueue(PVOID Context)
{
}
static BOOLEAN STDCALL
MouseSynchronizeRoutine(PVOID Context)
{
return TRUE;
}
static VOID STDCALL
SerialMouseStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
if (KeSynchronizeExecution(DeviceExtension->MouseInterrupt, MouseSynchronizeRoutine, Irp))
{
KIRQL oldIrql;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
oldIrql = KeGetCurrentIrql();
if (oldIrql < DISPATCH_LEVEL)
{
KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
IoStartNextPacket(DeviceObject, FALSE);
KeLowerIrql(oldIrql);
}
else
{
IoStartNextPacket (DeviceObject, FALSE);
}
}
}
static NTSTATUS STDCALL
SerialMouseInternalDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS Status;
switch (Stack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_INTERNAL_MOUSE_CONNECT:
DeviceExtension->ClassInformation =
*((PCONNECT_DATA)Stack->Parameters.DeviceIoControl.Type3InputBuffer);
/* Reinitialize the port input data queue synchronously */
KeSynchronizeExecution(DeviceExtension->MouseInterrupt,
(PKSYNCHRONIZE_ROUTINE)SerialMouseInitializeDataQueue,
DeviceExtension);
Status = STATUS_SUCCESS;
break;
#ifdef SERMOUSE_QUERYATTRIBUTES_SUPPORT
case IOCTL_MOUSE_QUERY_ATTRIBUTES:
if (Stack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(MOUSE_ATTRIBUTES))
{
*(PMOUSE_ATTRIBUTES)Irp->AssociatedIrp.SystemBuffer =
DeviceExtension->AttributesInformation;
Irp->IoStatus.Information = sizeof(MOUSE_ATTRIBUTES);
Status = STATUS_SUCCESS;
} else {
Status = STATUS_BUFFER_TOO_SMALL;
}
break;
#endif
default:
Status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
Irp->IoStatus.Status = Status;
if (Status == STATUS_PENDING)
{
IoMarkIrpPending(Irp);
IoStartPacket(DeviceObject, Irp, NULL, NULL);
}
else
{
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
return Status;
}
static NTSTATUS STDCALL
SerialMouseDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS Status;
switch (Stack->MajorFunction)
{
case IRP_MJ_CREATE:
case IRP_MJ_CLOSE:
Status = STATUS_SUCCESS;
break;
default:
DbgPrint("NOT IMPLEMENTED\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
}
if (Status == STATUS_PENDING)
{
IoMarkIrpPending(Irp);
}
else
{
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
return Status;
}
static VOID SerialMouseIsrDpc(PKDPC Dpc, PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
{
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
ULONG Queue;
Queue = DeviceExtension->ActiveQueue % 2;
InterlockedIncrement((PLONG)&DeviceExtension->ActiveQueue);
(*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassInformation.ClassService)(
DeviceExtension->ClassInformation.ClassDeviceObject,
DeviceExtension->MouseInputData[Queue],
NULL,
&DeviceExtension->InputDataCount[Queue]);
DeviceExtension->InputDataCount[Queue] = 0;
}
static VOID InitializeSerialPort(ULONG Port)
{
/* DLAB off */
WRITE_PORT_UCHAR((PUCHAR)Port + 3, 0);
WRITE_PORT_UCHAR((PUCHAR)Port + 2, 0); /* FCR: disable FIFO */
WRITE_PORT_UCHAR((PUCHAR)Port + 1, 0); /* IER: disable ints */
/* Set DLAB on */
WRITE_PORT_UCHAR((PUCHAR)Port + 3, 0x80);
/* Set serial port speed */
WRITE_PORT_UCHAR((PUCHAR)Port, 0x60);
WRITE_PORT_UCHAR((PUCHAR)Port + 1, 0);
/* Set DLAB off and set LCR */
WRITE_PORT_UCHAR((PUCHAR)Port + 3, 2);
}
static BOOLEAN UARTReadChar(ULONG Port, CHAR *Value, ULONG Timeout)
{
ULONG i, j;
for (i = 0; i < Timeout; i++)
{
for (j = 0; j < 1000; j++)
{
/* Is there a character ready? */
if (READ_PORT_UCHAR((PUCHAR)Port + 5) & 0x01)
{
/* Yes, read it and return */
*Value = READ_PORT_UCHAR((PUCHAR)Port);
return TRUE;
}
else
{
/* No, wait */
KeStallExecutionProcessor(1);
}
}
}
return FALSE;
}
static ULONG DetectMicrosoftMouse(ULONG Port)
{
CHAR Buffer[8];
ULONG Count, i;
UCHAR LCR, MCR;
/* Save original LCR/MCR */
LCR = READ_PORT_UCHAR((PUCHAR)Port + 3); /* LCR (line ctrl reg) */
MCR = READ_PORT_UCHAR((PUCHAR)Port + 4); /* MCR (modem ctrl reg) */
/* Reset UART */
WRITE_PORT_UCHAR((PUCHAR)Port + 4, 0); /* MCR: DTR/RTS/OUT2 off */
/* Set communications parameters */
InitializeSerialPort(Port);
/* Flush receive buffer */
(void) READ_PORT_UCHAR((PUCHAR)Port);
/* right? -> wait two ticks (approx 1/9 sec) */
KeStallExecutionProcessor(100000);
/* Enable DTR/RTS (OUT2 disabled) */
WRITE_PORT_UCHAR((PUCHAR)Port + 4, 3);
if (UARTReadChar(Port, &Buffer[0], 500))
{
Count = 1;
while (Count < 8)
{
if (UARTReadChar(Port, &Buffer[Count], 100))
Count++;
else
break;
}
}
else
return MOUSE_TYPE_NONE;
/* Restore LCR/MCR */
WRITE_PORT_UCHAR((PUCHAR)Port + 3, LCR); /* LCR (line ctrl reg) */
WRITE_PORT_UCHAR((PUCHAR)Port + 4, MCR); /* MCR (modem ctrl reg) */
for (i = 0; i < Count; ++i)
{
/* Sign for Microsoft Ballpoint */
if (Buffer[i] == 'B')
{
DbgPrint("Microsoft Ballpoint device detected");
DbgPrint("THIS DEVICE IS NOT SUPPORTED, YET");
return MOUSE_TYPE_NONE;
} else
/* Sign for Microsoft Mouse protocol followed by button specifier */
if (Buffer[i] == 'M')
{
if (i == 3)
{
/* Overflow Error */
return MOUSE_TYPE_NONE;
}
switch (Buffer[i + 1])
{
case '3':
DbgPrint("Microsoft Mouse with 3-buttons detected\n");
return MOUSE_TYPE_LOGITECH;
case 'Z':
DbgPrint("Microsoft Wheel Mouse detected\n");
return MOUSE_TYPE_WHEELZ;
/* case '2': */
default:
DbgPrint("Microsoft Mouse with 2-buttons detected\n");
return MOUSE_TYPE_MICROSOFT;
}
}
}
return MOUSE_TYPE_NONE;
}
static PDEVICE_OBJECT
AllocatePointerDevice(PDRIVER_OBJECT DriverObject)
{
PDEVICE_OBJECT DeviceObject;
UNICODE_STRING DeviceName;
UNICODE_STRING SuffixString;
PDEVICE_EXTENSION DeviceExtension;
ULONG Suffix;
NTSTATUS Status;
/* Allocate buffer for full device name */
RtlInitUnicodeString(&DeviceName, NULL);
DeviceName.MaximumLength = sizeof(DD_MOUSE_DEVICE_NAME_U) + SUFFIX_MAXIMUM_SIZE + sizeof(UNICODE_NULL);
DeviceName.Buffer = ExAllocatePool(PagedPool, DeviceName.MaximumLength);
RtlAppendUnicodeToString(&DeviceName, DD_MOUSE_DEVICE_NAME_U);
/* Allocate buffer for device name suffix */
RtlInitUnicodeString(&SuffixString, NULL);
SuffixString.MaximumLength = SUFFIX_MAXIMUM_SIZE + sizeof(UNICODE_NULL);
SuffixString.Buffer = ExAllocatePool(PagedPool, SuffixString.MaximumLength);
/* Generate full qualified name with suffix */
for (Suffix = 0; Suffix < POINTER_PORTS_MAXIMUM; ++Suffix)
{
RtlIntegerToUnicodeString(Suffix, 10, &SuffixString);
RtlAppendUnicodeToString(&DeviceName, SuffixString.Buffer);
Status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION),
&DeviceName, FILE_DEVICE_SERIAL_MOUSE_PORT, 0, TRUE, &DeviceObject);
/* Device successfully created, leave the cyclus */
if (NT_SUCCESS(Status))
break;
DeviceName.Length -= SuffixString.Length;
}
ExFreePool(DeviceName.Buffer);
ExFreePool(SuffixString.Buffer);
/* Couldn't create device */
if (!NT_SUCCESS(Status))
{
return NULL;
}
DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO;
DeviceExtension = DeviceObject->DeviceExtension;
KeInitializeDpc(&DeviceExtension->IsrDpc, (PKDEFERRED_ROUTINE)SerialMouseIsrDpc, DeviceObject);
return DeviceObject;
}
static BOOLEAN
InitializeMouse(ULONG Port, ULONG Irq, PDRIVER_OBJECT DriverObject)
{
PDEVICE_EXTENSION DeviceExtension;
PDEVICE_OBJECT DeviceObject;
ULONG MappedIrq;
KIRQL Dirql;
KAFFINITY Affinity;
ULONG MouseType;
/* Try to detect mouse on specified port */
MouseType = DetectMicrosoftMouse(Port);
/* No mouse, no need to continue */
if (MouseType == MOUSE_TYPE_NONE)
{
return FALSE;
}
/* Enable interrupts */
WRITE_PORT_UCHAR((PUCHAR)(Port) + 1, 1);
ClearMouse(Port);
/* Enable RTS, DTR and OUT2 */
WRITE_PORT_UCHAR((PUCHAR)Port + 4, 0x0b);
/* Allocate new device */
DeviceObject = AllocatePointerDevice(DriverObject);
if (!DeviceObject)
{
DbgPrint("Oops, couldn't creat device object.\n");
return FALSE;
}
DeviceExtension = DeviceObject->DeviceExtension;
/* Setup device extension structure */
DeviceExtension->ActiveQueue = 0;
DeviceExtension->MouseType = MouseType;
DeviceExtension->MousePort = Port;
DeviceExtension->PacketBufferPosition = 0;
DeviceExtension->PreviousButtons = 0;
#ifdef SERMOUSE_QUERYATTRIBUTES_SUPPORT
switch (MouseType)
{
case MOUSE_TYPE_MICROSOFT:
DeviceExtension->AttributesInformation.MouseIdentifier = MOUSE_SERIAL_HARDWARE;
DeviceExtension->AttributesInformation.NumberOfButtons = 2;
break;
case MOUSE_TYPE_LOGITECH:
DeviceExtension->AttributesInformation.MouseIdentifier = MOUSE_SERIAL_HARDWARE;
DeviceExtension->AttributesInformation.NumberOfButtons = 3;
break;
case MOUSE_TYPE_WHEELZ:
DeviceExtension->AttributesInformation.MouseIdentifier = WHEELMOUSE_SERIAL_HARDWARE;
DeviceExtension->AttributesInformation.NumberOfButtons = 3;
break;
};
DeviceExtension->AttributesInformation.SampleRate = 40;
DeviceExtension->AttributesInformation.InputDataQueueLength = MOUSE_BUFFER_SIZE;
#endif
MappedIrq = HalGetInterruptVector(Internal, 0, 0, Irq, &Dirql, &Affinity);
IoConnectInterrupt(
&DeviceExtension->MouseInterrupt, SerialMouseInterruptService,
DeviceObject, NULL, MappedIrq, Dirql, Dirql, 0, FALSE,
Affinity, FALSE);
return TRUE;
}
static VOID
GetMouseResourceData(PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor,
PULONG Port,
PULONG Interrupt)
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
ULONG i;
for (i = 0; i < FullDescriptor->PartialResourceList.Count; i++)
{
PartialDescriptor = &FullDescriptor->PartialResourceList.PartialDescriptors[i];
switch (PartialDescriptor->Type)
{
case CmResourceTypePort:
*Port = (ULONG)PartialDescriptor->u.Port.Start.u.LowPart;
break;
case CmResourceTypeInterrupt:
*Interrupt = (ULONG)PartialDescriptor->u.Interrupt.Level;
break;
}
}
}
static BOOLEAN
GetMouseResources(PULONG Port,
PULONG Interrupt)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
WCHAR Buffer[32];
HANDLE BusKey;
HANDLE BusInstanceKey;
HANDLE ControllerKey;
HANDLE ControllerInstanceKey;
HANDLE PeripheralKey;
HANDLE PeripheralInstanceKey;
ULONG BusInstance;
ULONG ControllerInstance;
ULONG PeripheralInstance;
ULONG BufferLength;
ULONG ReturnedLength;
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
NTSTATUS Status;
DPRINT("GetMouseResources() called\n");
/* Open the bus key */
RtlInitUnicodeString(&KeyName,
L"\\Registry\\Machine\\HARDWARE\\Description\\System\\MultifunctionAdapter");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ZwOpenKey(&BusKey,
KEY_ALL_ACCESS,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
DPRINT("NtOpenKey() failed (Status %lx)\n", Status);
return FALSE;
}
BusInstance = 0;
while (TRUE)
{
sprintf((PCHAR)Buffer, "%lu", (ULONG)0);
swprintf(Buffer, L"%lu", BusInstance);
RtlInitUnicodeString(&KeyName,
Buffer);
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
BusKey,
NULL);
Status = ZwOpenKey(&BusInstanceKey,
KEY_ALL_ACCESS,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
DPRINT("NtOpenKey() failed (Status %lx)\n", Status);
ZwClose(BusKey);
return FALSE;
}
/* Open the controller type key */
RtlInitUnicodeString(&KeyName,
L"SerialController");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
BusInstanceKey,
NULL);
Status = ZwOpenKey(&ControllerKey,
KEY_ALL_ACCESS,
&ObjectAttributes);
if (NT_SUCCESS(Status))
{
ControllerInstance = 0;
while (TRUE)
{
/* Open the pointer controller instance key */
swprintf(Buffer, L"%lu", ControllerInstance);
RtlInitUnicodeString(&KeyName,
Buffer);
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
ControllerKey,
NULL);
Status = ZwOpenKey(&ControllerInstanceKey,
KEY_ALL_ACCESS,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
DPRINT("NtOpenKey() failed (Status %lx)\n", Status);
ZwClose(ControllerKey);
ZwClose(BusInstanceKey);
ZwClose(BusKey);
return FALSE;
}
/* Open the 'PointerPeripheral' key */
RtlInitUnicodeString(&KeyName,
L"PointerPeripheral");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
ControllerInstanceKey,
NULL);
Status = ZwOpenKey(&PeripheralKey,
KEY_ALL_ACCESS,
&ObjectAttributes);
if (NT_SUCCESS(Status))
{
PeripheralInstance = 0;
while (TRUE)
{
/* Open the pointer peripheral instance key */
swprintf(Buffer, L"%lu", PeripheralInstance);
RtlInitUnicodeString(&KeyName,
Buffer);
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
PeripheralKey,
NULL);
Status = ZwOpenKey(&PeripheralInstanceKey,
KEY_ALL_ACCESS,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
DPRINT("ZwOpenKey() failed (Status %lx)\n", Status);
ZwClose(PeripheralKey);
ZwClose(ControllerInstanceKey);
ZwClose(ControllerKey);
ZwClose(BusInstanceKey);
ZwClose(BusKey);
return FALSE;
}
/* Get peripheral identifier */
RtlInitUnicodeString(&KeyName,
L"Configuration Data");
BufferLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION);
ReturnedLength = 0;
ValueInfo = ExAllocatePool(NonPagedPool,
BufferLength);
if (ValueInfo == NULL)
{
DPRINT("ExAllocatePool() failed\n");
ZwClose(PeripheralInstanceKey);
ZwClose(PeripheralKey);
ZwClose(ControllerInstanceKey);
ZwClose(ControllerKey);
ZwClose(BusInstanceKey);
ZwClose(BusKey);
return FALSE;
}
Status = ZwQueryValueKey(ControllerInstanceKey,
&KeyName,
KeyValuePartialInformation,
ValueInfo,
BufferLength,
&ReturnedLength);
DPRINT("ZwQueryValueKey() called (Status %lx)\n", Status);
DPRINT("ReturnedLength %ld\n", ReturnedLength);
ExFreePool(ValueInfo);
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL)
{
DPRINT("ZwQueryValueKey() failed (Status %lx)\n", Status);
ZwClose(PeripheralInstanceKey);
ZwClose(PeripheralKey);
ZwClose(ControllerInstanceKey);
ZwClose(ControllerKey);
ZwClose(BusInstanceKey);
ZwClose(BusKey);
return FALSE;
}
BufferLength = ReturnedLength;
ValueInfo = ExAllocatePool(NonPagedPool,
BufferLength);
if (ValueInfo == NULL)
{
DPRINT("ExAllocatePool() failed\n");
ZwClose(PeripheralInstanceKey);
ZwClose(PeripheralKey);
ZwClose(ControllerInstanceKey);
ZwClose(ControllerKey);
ZwClose(BusInstanceKey);
ZwClose(BusKey);
return FALSE;
}
Status = ZwQueryValueKey(ControllerInstanceKey,
&KeyName,
KeyValuePartialInformation,
ValueInfo,
BufferLength,
&ReturnedLength);
if (NT_SUCCESS(Status))
{
DPRINT("Done\n");
GetMouseResourceData((PCM_FULL_RESOURCE_DESCRIPTOR)(ValueInfo->Data),
Port,
Interrupt);
ExFreePool(ValueInfo);
ZwClose(PeripheralInstanceKey);
ZwClose(PeripheralKey);
ZwClose(ControllerInstanceKey);
ZwClose(ControllerKey);
ZwClose(BusInstanceKey);
ZwClose(BusKey);
return TRUE;
}
ExFreePool(ValueInfo);
ZwClose(PeripheralInstanceKey);
PeripheralInstance++;
}
ZwClose(PeripheralKey);
}
ZwClose(ControllerInstanceKey);
ControllerInstance++;
}
ZwClose(ControllerKey);
}
ZwClose(BusInstanceKey);
BusInstance++;
}
ZwClose(BusKey);
return FALSE;
}
NTSTATUS STDCALL
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
BOOLEAN MouseFound = FALSE;
ULONG BaseAddress = (ULONG)-1;
ULONG Interrupt = (ULONG)-1;
DPRINT1("Serial Mouse Driver 0.0.9\n");
if (GetMouseResources(&BaseAddress, &Interrupt))
{
if (BaseAddress != (ULONG)-1 && Interrupt != (ULONG)-1)
{
DPRINT1("Found mouse: Port %lx Interupt %lu\n", BaseAddress, Interrupt);
MouseFound |= InitializeMouse(BaseAddress, Interrupt, DriverObject);
}
}
else
{
#ifdef SERMOUSE_COM1_SUPPORT
DPRINT1("Trying to find mouse on COM1\n");
MouseFound |= InitializeMouse(MOUSE_PORT_COM1, MOUSE_IRQ_COM1, DriverObject);
#endif
#ifdef SERMOUSE_COM2_SUPPORT
DPRINT1("Trying to find mouse on COM2\n");
MouseFound |= InitializeMouse(MOUSE_PORT_COM2, MOUSE_IRQ_COM2, DriverObject);
#endif
}
if (!MouseFound)
{
DPRINT1("No serial mouse found.\n");
return STATUS_UNSUCCESSFUL;
}
DriverObject->MajorFunction[IRP_MJ_CREATE] = SerialMouseDispatch;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = SerialMouseDispatch;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = SerialMouseInternalDeviceControl;
DriverObject->DriverStartIo = SerialMouseStartIo;
return STATUS_SUCCESS;
}

View file

@ -1,7 +0,0 @@
/* $Id$ */
#define REACTOS_VERSION_DLL
#define REACTOS_STR_FILE_DESCRIPTION "Serial Mouse Device Driver\0"
#define REACTOS_STR_INTERNAL_NAME "sermouse\0"
#define REACTOS_STR_ORIGINAL_FILENAME "sermouse.sys\0"
#include <reactos/version.rc>

View file

@ -1,82 +0,0 @@
Following information obtained from Tomi Engdahl (then@delta.hut.fi),
http://www.hut.fi/~then/mytexts/mouse.html
Microsoft serial mouse
Serial data parameters:
1200bps, 7 databits, 1 stop-bit
Data packet format:
Data packet is 3 byte packet. It is send to the computer every time mouse
state changes (mouse moves or keys are pressed/released).
D7 D6 D5 D4 D3 D2 D1 D0
1. X 1 LB RB Y7 Y6 X7 X6
2. X 0 X5 X4 X3 X2 X1 X0
3. X 0 Y5 Y4 Y3 Y2 Y1 Y0
Note: The bit marked with X is 0 if the mouse received with 7 databits
and 2 stop bits format. It is also possible to use 8 databits and 1 stop
bit format for receiving. In this case X gets value 1. The safest thing
to get everything working is to use 7 databits and 1 stopbit when
receiving mouse information (and if you are making mouse then send out
7 databits and 2 stop bits).
The byte marked with 1. is send first, then the others. The bit D6 in
the first byte is used for syncronizing the software to mouse packets
if it goes out of sync.
LB is the state of the left button (1 means pressed down)
RB is the state of the right button (1 means pressed down)
X7-X0 movement in X direction since last packet (signed byte)
Y7-Y0 movement in Y direction since last packet (signed byte)
Mouse identification
When DTR line is toggled, mouse should send one data byte containing
letter 'M' (ascii 77).
Logitech serial mouse
Logitech uses the Microsoft serial mouse protocol in their mouses (for
example Logitech Pilot mouse and others). The origianal protocol supports
only two buttons, but logitech as added third button to some of their
mouse models. To make this possible logitech has made one extension to
the protocol.
I have not seen any documentation about the exact documents, but here is
what I have found out: The information of the third button state is sent
using one extra byte which is send after the normal packet when needed.
Value 32 (dec) is sent every time when the center button is pressed down.
It is also sent every time with the data packet when center button is kept
down and the mouse data packet is sent for other reasons. When center
button is released, the mouse sends the normal data packet followed by
data bythe which has value 0 (dec). As you can see the extra data byte
is sent only when you mess with the center button.
Mouse systems mouse
Serial data parameters:
1200bps, 8 databits, 1 stop-bit
Data packet format:
D7 D6 D5 D4 D3 D2 D1 D0
1. 1 0 0 0 0 LB CB RB
2. X7 X6 X5 X4 X3 X2 X1 X0
3. Y7 Y6 Y5 Y4 Y3 Y4 Y1 Y0
4. X7' X6' X5' X4' X3' X2' X1' X0'
5. Y7' Y6' Y5' Y4' Y3' Y4' Y1' Y0'
LB is left button state (0 = pressed, 1 = released)
CB is center button state (0 = pressed, 1 = released)
RB is right button state (0 = pressed, 1 = released)
X7-X0 movement in X direction since last packet in signed byte
format (-128..+127), positive direction right
Y7-Y0 movement in Y direction since last packet in signed byte
format (-128..+127), positive direction up
X7'-X0' movement in X direction since sending of X7-X0 packet in
signed byte format (-128..+127), positive direction right
Y7'-Y0' movement in Y direction since sending of Y7-Y0 packet in
signed byte format (-128..+127), positive direction up
The last two bytes in the packet (bytes 4 and 5) contains information
about movement data changes which have occured after data bytes 2 and 3
have been sent.

View file

@ -1,8 +0,0 @@
<module name="sermouse" type="kernelmodedriver" installbase="system32/drivers" installname="sermouse.sys">
<include base="sermouse">.</include>
<define name="__USE_W32API" />
<library>ntoskrnl</library>
<library>hal</library>
<file>sermouse.c</file>
<file>sermouse.rc</file>
</module>