mirror of
https://github.com/reactos/reactos.git
synced 2024-07-06 12:45:16 +00:00
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:
parent
9fcc9fe902
commit
9bfa51a8fc
|
@ -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;
|
||||
}
|
|
@ -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>
|
|
@ -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.
|
|
@ -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>
|
Loading…
Reference in a new issue