mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
*** empty log message ***
svn path=/trunk/; revision=1408
This commit is contained in:
parent
bb44d63a00
commit
77d9f6fb99
20 changed files with 1595 additions and 5 deletions
|
@ -1,4 +0,0 @@
|
|||
base.tmp
|
||||
junk.tmp
|
||||
temp.exp
|
||||
keyboard.coff
|
39
reactos/drivers/input/include/mouse.h
Normal file
39
reactos/drivers/input/include/mouse.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
// Mouse definitions common to both mouse class and port drivers
|
||||
|
||||
#define IO_MOUSE_INCREMENT 6
|
||||
#define MOUSE_BUFFER_SIZE 32
|
||||
|
||||
#define IOCTL_INTERNAL_MOUSE_CONNECT CTL_CODE(FILE_DEVICE_MOUSE, 0x0080, METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||
#define IOCTL_INTERNAL_MOUSE_DISCONNECT CTL_CODE(FILE_DEVICE_MOUSE, 0x0100, METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||
#define IOCTL_INTERNAL_MOUSE_ENABLE CTL_CODE(FILE_DEVICE_MOUSE, 0x0200, METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||
#define IOCTL_INTERNAL_MOUSE_DISABLE CTL_CODE(FILE_DEVICE_MOUSE, 0x0400, METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||
|
||||
typedef struct _MOUSE_INPUT_DATA {
|
||||
USHORT UnitId;
|
||||
USHORT Flags;
|
||||
union {
|
||||
ULONG Buttons;
|
||||
struct {
|
||||
USHORT ButtonFlags;
|
||||
USHORT ButtonData;
|
||||
};
|
||||
};
|
||||
ULONG RawButtons;
|
||||
LONG LastX;
|
||||
LONG LastY;
|
||||
ULONG ExtraInformation;
|
||||
} MOUSE_INPUT_DATA, *PMOUSE_INPUT_DATA;
|
||||
|
||||
typedef struct _CLASS_INFORMATION {
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PVOID CallBack;
|
||||
} CLASS_INFORMATION, *PCLASS_INFORMATION;
|
||||
|
||||
typedef
|
||||
VOID
|
||||
(*PSERVICE_CALLBACK_ROUTINE) (
|
||||
IN PVOID NormalContext,
|
||||
IN PVOID SystemArgument1,
|
||||
IN PVOID SystemArgument2,
|
||||
IN OUT PVOID SystemArgument3
|
||||
);
|
|
@ -1,4 +1,4 @@
|
|||
# $Id: makefile,v 1.14 2000/10/07 13:41:55 dwelch Exp $
|
||||
# $Id: makefile,v 1.1 2000/10/18 09:09:14 jfilby Exp $
|
||||
#
|
||||
#
|
||||
PATH_TO_TOP = ../../..
|
71
reactos/drivers/input/mouclass/makefile
Normal file
71
reactos/drivers/input/mouclass/makefile
Normal file
|
@ -0,0 +1,71 @@
|
|||
# $Id: makefile,v 1.1 2000/10/18 09:09:14 jfilby Exp $
|
||||
#
|
||||
#
|
||||
TARGET = mouclass
|
||||
|
||||
BASE_CFLAGS = -I../../../include
|
||||
|
||||
OBJECTS = $(TARGET).o $(TARGET).coff ../../../ntoskrnl/ntoskrnl.a
|
||||
|
||||
all: $(TARGET).sys
|
||||
|
||||
.phony: all
|
||||
|
||||
clean:
|
||||
- $(RM) $(TARGET).o
|
||||
- $(RM) $(TARGET).coff
|
||||
- $(RM) junk.tmp
|
||||
- $(RM) base.tmp
|
||||
- $(RM) temp.exp
|
||||
- $(RM) mouclass.sys
|
||||
|
||||
.phony: clean
|
||||
|
||||
install: $(FLOPPY_DIR)/drivers/$(TARGET).sys
|
||||
|
||||
$(FLOPPY_DIR)/drivers/$(TARGET).sys: $(TARGET).sys
|
||||
ifeq ($(DOSCLI),yes)
|
||||
$(CP) $(TARGET).sys $(FLOPPY_DIR)\drivers\$(TARGET).sys
|
||||
else
|
||||
$(CP) $(TARGET).sys $(FLOPPY_DIR)/drivers/$(TARGET).sys
|
||||
endif
|
||||
|
||||
dist: ../../../$(DIST_DIR)/drivers/$(TARGET).sys
|
||||
|
||||
../../../$(DIST_DIR)/drivers/$(TARGET).sys: $(TARGET).sys
|
||||
ifeq ($(DOSCLI),yes)
|
||||
$(CP) $(TARGET).sys ..\..\..\$(DIST_DIR)\drivers\$(TARGET).sys
|
||||
else
|
||||
$(CP) $(TARGET).sys ../../../$(DIST_DIR)/drivers/$(TARGET).sys
|
||||
endif
|
||||
|
||||
$(TARGET).sys: $(OBJECTS)
|
||||
$(CC) \
|
||||
-specs=../../svc_specs \
|
||||
-mdll \
|
||||
-o junk.tmp \
|
||||
-Wl,--defsym,_end=end \
|
||||
-Wl,--defsym,_edata=__data_end__ \
|
||||
-Wl,--defsym,_etext=etext \
|
||||
-Wl,--base-file,base.tmp \
|
||||
$(OBJECTS)
|
||||
- $(RM) junk.tmp
|
||||
$(DLLTOOL) \
|
||||
--dllname $(TARGET).sys \
|
||||
--base-file base.tmp \
|
||||
--output-exp temp.exp \
|
||||
--kill-at
|
||||
- $(RM) base.tmp
|
||||
$(CC) \
|
||||
--verbose \
|
||||
-Wl,--image-base,0x10000 \
|
||||
-Wl,-e,_DriverEntry@8 \
|
||||
-Wl,temp.exp \
|
||||
-specs=../../svc_specs \
|
||||
-mdll \
|
||||
-o $(TARGET).sys \
|
||||
$(OBJECTS)
|
||||
- $(RM) temp.exp
|
||||
|
||||
|
||||
include ../../../rules.mak
|
228
reactos/drivers/input/mouclass/mouclass.c
Normal file
228
reactos/drivers/input/mouclass/mouclass.c
Normal file
|
@ -0,0 +1,228 @@
|
|||
/*
|
||||
|
||||
** Mouse class driver 0.0.1
|
||||
** Written by Jason Filby (jasonfilby@yahoo.com)
|
||||
** For ReactOS (www.reactos.com)
|
||||
|
||||
** The class driver between win32k and the various mouse port drivers
|
||||
|
||||
** TODO: Change interface to win32k to a callback instead of ReadFile IO
|
||||
Add support for multiple port devices
|
||||
|
||||
*/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include "..\include\mouse.h"
|
||||
#include "mouclass.h"
|
||||
|
||||
BOOLEAN AlreadyOpened = FALSE;
|
||||
|
||||
VOID MouseClassCallBack(PDEVICE_OBJECT ClassDeviceObject, PMOUSE_INPUT_DATA MouseDataStart,
|
||||
PMOUSE_INPUT_DATA MouseDataEnd, PULONG InputCount)
|
||||
{
|
||||
PDEVICE_EXTENSION ClassDeviceExtension = ClassDeviceObject->DeviceExtension;
|
||||
PIRP Irp;
|
||||
ULONG ReadSize;
|
||||
PIO_STACK_LOCATION Stack;
|
||||
|
||||
if(ClassDeviceExtension->ReadIsPending == TRUE)
|
||||
{
|
||||
Irp = ClassDeviceObject->CurrentIrp;
|
||||
ClassDeviceObject->CurrentIrp = NULL;
|
||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
ReadSize = sizeof(MOUSE_INPUT_DATA) * (*InputCount);
|
||||
|
||||
// A read request is waiting for input, so go straight to it
|
||||
RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, (PCHAR)MouseDataStart, ReadSize);
|
||||
|
||||
// Go to next packet and complete this request with STATUS_SUCCESS
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = ReadSize;
|
||||
Stack->Parameters.Read.Length = ReadSize;
|
||||
|
||||
IoStartNextPacket(ClassDeviceObject, FALSE);
|
||||
IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
|
||||
ClassDeviceExtension->ReadIsPending = FALSE;
|
||||
}
|
||||
if(InputCount>0)
|
||||
{
|
||||
// FIXME: If we exceed the buffer, mouse data gets thrown away.. better solution?
|
||||
|
||||
if(ClassDeviceExtension->InputCount + *InputCount > MOUSE_BUFFER_SIZE)
|
||||
{
|
||||
ReadSize = MOUSE_BUFFER_SIZE - ClassDeviceExtension->InputCount;
|
||||
} else {
|
||||
ReadSize = *InputCount;
|
||||
}
|
||||
|
||||
// Move the mouse input data from the port data queue to our class data queue
|
||||
RtlMoveMemory(ClassDeviceExtension->PortData, (PCHAR)MouseDataStart,
|
||||
sizeof(MOUSE_INPUT_DATA) * ReadSize);
|
||||
|
||||
// Move the pointer and counter up
|
||||
ClassDeviceExtension->PortData += ReadSize;
|
||||
ClassDeviceExtension->InputCount += ReadSize;
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS ConnectMousePortDriver(PDEVICE_OBJECT ClassDeviceObject)
|
||||
{
|
||||
PDEVICE_OBJECT PortDeviceObject = NULL;
|
||||
PFILE_OBJECT FileObject = NULL;
|
||||
NTSTATUS status;
|
||||
UNICODE_STRING PortName;
|
||||
IO_STATUS_BLOCK ioStatus;
|
||||
KEVENT event;
|
||||
PIRP irp;
|
||||
CLASS_INFORMATION ClassInformation;
|
||||
PDEVICE_EXTENSION DeviceExtension = ClassDeviceObject->DeviceExtension;
|
||||
|
||||
// Get the port driver's DeviceObject
|
||||
// FIXME: The name might change.. find a way to be more dynamic?
|
||||
|
||||
RtlInitUnicodeString(&PortName, L"\\Device\\Mouse");
|
||||
status = IoGetDeviceObjectPointer(&PortName, FILE_READ_ATTRIBUTES, &FileObject, &PortDeviceObject);
|
||||
|
||||
if(status != STATUS_SUCCESS)
|
||||
{
|
||||
DbgPrint("MOUCLASS: Could not connect to mouse port driver\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
DeviceExtension->PortDeviceObject = PortDeviceObject;
|
||||
DeviceExtension->PortData = ExAllocatePool(NonPagedPool, MOUSE_BUFFER_SIZE * sizeof(MOUSE_INPUT_DATA));
|
||||
DeviceExtension->InputCount = 0;
|
||||
DeviceExtension->ReadIsPending = FALSE;
|
||||
|
||||
// Connect our callback to the port driver
|
||||
|
||||
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
||||
|
||||
ClassInformation.DeviceObject = ClassDeviceObject;
|
||||
ClassInformation.CallBack = MouseClassCallBack;
|
||||
|
||||
irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT,
|
||||
PortDeviceObject, &ClassInformation, sizeof(CLASS_INFORMATION), NULL, 0, TRUE, &event, &ioStatus);
|
||||
|
||||
status = IoCallDriver(DeviceExtension->PortDeviceObject, irp);
|
||||
|
||||
if (status == STATUS_PENDING) {
|
||||
KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
|
||||
} else {
|
||||
ioStatus.Status = status;
|
||||
}
|
||||
|
||||
return ioStatus.Status;
|
||||
}
|
||||
|
||||
NTSTATUS MouseClassDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
NTSTATUS Status;
|
||||
|
||||
switch (Stack->MajorFunction)
|
||||
{
|
||||
case IRP_MJ_CREATE:
|
||||
if (AlreadyOpened == TRUE)
|
||||
{
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_SUCCESS;
|
||||
AlreadyOpened = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case IRP_MJ_CLOSE:
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
case IRP_MJ_READ:
|
||||
|
||||
if (Stack->Parameters.Read.Length == 0) {
|
||||
Status = STATUS_SUCCESS;
|
||||
} else {
|
||||
Status = STATUS_PENDING;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DbgPrint("NOT IMPLEMENTED\n");
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = 0;
|
||||
if (Status==STATUS_PENDING)
|
||||
{
|
||||
IoMarkIrpPending(Irp);
|
||||
IoStartPacket(DeviceObject, Irp, NULL, NULL);
|
||||
} else {
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
return(Status);
|
||||
}
|
||||
|
||||
VOID MouseClassStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
ULONG ReadSize;
|
||||
|
||||
if(DeviceExtension->InputCount>0)
|
||||
{
|
||||
// FIXME: We should not send to much input data.. depends on the max buffer size of the win32k
|
||||
ReadSize = DeviceExtension->InputCount * sizeof(MOUSE_INPUT_DATA);
|
||||
|
||||
// Bring the PortData back to base so that it can be copied
|
||||
DeviceExtension->PortData -= DeviceExtension->InputCount;
|
||||
DeviceExtension->InputCount = 0;
|
||||
DeviceExtension->ReadIsPending = FALSE;
|
||||
|
||||
RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, (PCHAR)DeviceExtension->PortData, ReadSize);
|
||||
|
||||
// Go to next packet and complete this request with STATUS_SUCCESS
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
|
||||
Irp->IoStatus.Information = ReadSize;
|
||||
Stack->Parameters.Read.Length = ReadSize;
|
||||
|
||||
IoStartNextPacket(DeviceObject, FALSE);
|
||||
IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
|
||||
} else {
|
||||
DeviceExtension->ReadIsPending = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
UNICODE_STRING DeviceName;
|
||||
UNICODE_STRING SymlinkName;
|
||||
|
||||
DbgPrint("Mouse Class Driver 0.0.1\n");
|
||||
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = MouseClassDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = MouseClassDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_READ] = MouseClassDispatch;
|
||||
DriverObject->DriverStartIo = MouseClassStartIo;
|
||||
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\MouseClass");
|
||||
IoCreateDevice(DriverObject,
|
||||
sizeof(DEVICE_EXTENSION),
|
||||
&DeviceName,
|
||||
FILE_DEVICE_MOUSE,
|
||||
0,
|
||||
TRUE,
|
||||
&DeviceObject);
|
||||
DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO;
|
||||
|
||||
RtlInitUnicodeString(&SymlinkName, L"\\??\\MouseClass");
|
||||
IoCreateSymbolicLink(&SymlinkName, &DeviceName);
|
||||
|
||||
return ConnectMousePortDriver(DeviceObject);
|
||||
}
|
6
reactos/drivers/input/mouclass/mouclass.h
Normal file
6
reactos/drivers/input/mouclass/mouclass.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
typedef struct _DEVICE_EXTENSION {
|
||||
BOOLEAN ReadIsPending;
|
||||
ULONG InputCount;
|
||||
PMOUSE_INPUT_DATA PortData;
|
||||
PDEVICE_OBJECT PortDeviceObject; // FIXME: Expand this to handle multiple port drivers (make *PortDeviceObject)
|
||||
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
|
39
reactos/drivers/input/mouclass/mouclass.rc
Normal file
39
reactos/drivers/input/mouclass/mouclass.rc
Normal file
|
@ -0,0 +1,39 @@
|
|||
|
||||
#include <defines.h>
|
||||
#include <reactos/resource.h>
|
||||
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
|
||||
PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", RES_STR_COMPANY_NAME
|
||||
VALUE "FileDescription", "Mouse Class Device Driver\0"
|
||||
VALUE "FileVersion", "0.0.1\0"
|
||||
VALUE "InternalName", "mouclass\0"
|
||||
VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
|
||||
VALUE "OriginalFilename", "mouclass.sys\0"
|
||||
VALUE "ProductName", RES_STR_PRODUCT_NAME
|
||||
VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
150
reactos/drivers/input/psaux/controller.c
Normal file
150
reactos/drivers/input/psaux/controller.c
Normal file
|
@ -0,0 +1,150 @@
|
|||
// All or parts of this file are from CHAOS (http://www.se.chaosdev.org/).
|
||||
// CHAOS is also under the GNU General Public License.
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
|
||||
#include "controller.h"
|
||||
#include "keyboard.h"
|
||||
#include "mouse.h"
|
||||
|
||||
/* This reads the controller status port, and does the appropriate
|
||||
action. It requires that we hold the keyboard controller spinlock. */
|
||||
|
||||
unsigned handle_event(void)
|
||||
{
|
||||
unsigned status = controller_read_status();
|
||||
unsigned int work;
|
||||
|
||||
for(work = 0; (work < 10000) && ((status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0); work++)
|
||||
{
|
||||
unsigned scancode;
|
||||
|
||||
scancode = controller_read_input();
|
||||
|
||||
#if 0
|
||||
/* Ignore error bytes. */
|
||||
|
||||
if((status &(CONTROLLER_STATUS_GENERAL_TIMEOUT |
|
||||
CONTROLLER_STATUS_PARITY_ERROR)) == 0)
|
||||
#endif
|
||||
{
|
||||
if((status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) != 0)
|
||||
{
|
||||
// mouse_handle_event(scancode); we just use the mouse handler directly..
|
||||
}
|
||||
else
|
||||
{
|
||||
// keyboard_handle_event(scancode);
|
||||
}
|
||||
}
|
||||
|
||||
status = controller_read_status();
|
||||
|
||||
}
|
||||
|
||||
if(work == 10000)
|
||||
{
|
||||
DbgPrint("PSAUX: Keyboard controller jammed\n");
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Wait for keyboard controller input buffer to drain.
|
||||
Quote from PS/2 System Reference Manual:
|
||||
"Address hex 0060 and address hex 0064 should be written only
|
||||
when the input-buffer-full bit and output-buffer-full bit in the
|
||||
Controller Status register are set 0." */
|
||||
|
||||
void controller_wait(void)
|
||||
{
|
||||
unsigned long timeout;
|
||||
|
||||
for(timeout = 0; timeout < CONTROLLER_TIMEOUT; timeout++)
|
||||
{
|
||||
// "handle_keyboard_event()" will handle any incoming events
|
||||
// while we wait -- keypresses or mouse movement
|
||||
|
||||
unsigned char status = handle_event();
|
||||
|
||||
if((status & CONTROLLER_STATUS_INPUT_BUFFER_FULL) == 0) return;
|
||||
|
||||
// Sleep for one millisecond
|
||||
KeDelayExecutionThread (KernelMode, FALSE, 1);
|
||||
}
|
||||
|
||||
DbgPrint("PSAUX: Keyboard timed out\n");
|
||||
}
|
||||
|
||||
/* Wait for input from the keyboard controller. */
|
||||
|
||||
int controller_wait_for_input(void)
|
||||
{
|
||||
int timeout;
|
||||
|
||||
for(timeout = KEYBOARD_INIT_TIMEOUT; timeout > 0; timeout--)
|
||||
{
|
||||
int return_value = controller_read_data();
|
||||
|
||||
if(return_value >= 0) return return_value;
|
||||
|
||||
// Sleep for one millisecond
|
||||
KeDelayExecutionThread (KernelMode, FALSE, 1);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Write a command word to the keyboard controller. */
|
||||
|
||||
void controller_write_command_word(unsigned data)
|
||||
{
|
||||
controller_wait();
|
||||
controller_write_command(data);
|
||||
}
|
||||
|
||||
/* Write an output word to the keyboard controller. */
|
||||
|
||||
void controller_write_output_word(unsigned data)
|
||||
{
|
||||
controller_wait();
|
||||
controller_write_output(data);
|
||||
}
|
||||
|
||||
|
||||
/* Empty the keyboard input buffer. */
|
||||
|
||||
void keyboard_clear_input(void)
|
||||
{
|
||||
int max_read;
|
||||
|
||||
for(max_read = 0; max_read < 100; max_read++)
|
||||
{
|
||||
if(controller_read_data() == KEYBOARD_NO_DATA)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Read data from the keyboard controller. */
|
||||
|
||||
int controller_read_data(void)
|
||||
{
|
||||
int return_value = KEYBOARD_NO_DATA;
|
||||
unsigned status;
|
||||
|
||||
status = controller_read_status();
|
||||
if(status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL)
|
||||
{
|
||||
unsigned data = controller_read_input();
|
||||
|
||||
return_value = data;
|
||||
if(status &(CONTROLLER_STATUS_GENERAL_TIMEOUT |
|
||||
CONTROLLER_STATUS_PARITY_ERROR))
|
||||
{
|
||||
return_value = KEYBOARD_BAD_DATA;
|
||||
}
|
||||
}
|
||||
return return_value;
|
||||
}
|
139
reactos/drivers/input/psaux/controller.h
Normal file
139
reactos/drivers/input/psaux/controller.h
Normal file
|
@ -0,0 +1,139 @@
|
|||
// All or parts of this file are from CHAOS (http://www.se.chaosdev.org/).
|
||||
// CHAOS is also under the GNU General Public License.
|
||||
|
||||
/* Keyboard controller registers. */
|
||||
|
||||
#define CONTROLLER_REGISTER_STATUS 0x64
|
||||
#define CONTROLLER_REGISTER_CONTROL 0x64
|
||||
#define CONTROLLER_REGISTER_DATA 0x60
|
||||
|
||||
/* Keyboard controller commands. */
|
||||
/* Read mode bits. */
|
||||
|
||||
#define CONTROLLER_COMMAND_READ_MODE 0x20
|
||||
|
||||
/* Write mode bits. */
|
||||
|
||||
#define CONTROLLER_COMMAND_WRITE_MODE 0x60
|
||||
|
||||
/* Get controller version. */
|
||||
|
||||
#define CONTROLLER_COMMAND_GET_VERSION 0xA1
|
||||
|
||||
/* Disable mouse interface. */
|
||||
|
||||
#define CONTROLLER_COMMAND_MOUSE_DISABLE 0xA7
|
||||
|
||||
/* Enable mouse interface. */
|
||||
|
||||
#define CONTROLLER_COMMAND_MOUSE_ENABLE 0xA8
|
||||
|
||||
/* Mouse interface test. */
|
||||
|
||||
#define CONTROLLER_COMMAND_TEST_MOUSE 0xA9
|
||||
|
||||
/* Controller self test. */
|
||||
|
||||
#define CONTROLLER_COMMAND_SELF_TEST 0xAA
|
||||
|
||||
/* Keyboard interface test. */
|
||||
|
||||
#define CONTROLLER_COMMAND_KEYBOARD_TEST 0xAB
|
||||
|
||||
/* Keyboard interface disable. */
|
||||
|
||||
#define CONTROLLER_COMMAND_KEYBOARD_DISABLE 0xAD
|
||||
|
||||
/* Keyboard interface enable. */
|
||||
|
||||
#define CONTROLLER_COMMAND_KEYBOARD_ENABLE 0xAE
|
||||
|
||||
/* Write to output buffer as if initiated by the auxiliary device. */
|
||||
|
||||
#define CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER 0xD3
|
||||
|
||||
/* Write the following byte to the mouse. */
|
||||
|
||||
#define CONTROLLER_COMMAND_WRITE_MOUSE 0xD4
|
||||
|
||||
/* Status Register Bits. */
|
||||
/* Keyboard output buffer full. */
|
||||
|
||||
#define CONTROLLER_STATUS_OUTPUT_BUFFER_FULL 0x01
|
||||
|
||||
/* Keyboard input buffer full. */
|
||||
|
||||
#define CONTROLLER_STATUS_INPUT_BUFFER_FULL 0x02
|
||||
|
||||
/* Self test successful. */
|
||||
|
||||
#define CONTROLLER_STATUS_SELF_TEST 0x04
|
||||
|
||||
/* Last write was a command write. (0 = data) */
|
||||
|
||||
#define CONTROLLER_STATUS_COMMAND 0x08
|
||||
|
||||
/* Zero if keyboard locked. */
|
||||
|
||||
#define CONTROLLER_STATUS_UNLOCKED 0x10
|
||||
|
||||
/* Mouse output buffer full. */
|
||||
|
||||
#define CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL 0x20
|
||||
|
||||
/* General receive/xmit timeout. */
|
||||
|
||||
#define CONTROLLER_STATUS_GENERAL_TIMEOUT 0x40
|
||||
|
||||
/* Parity error. */
|
||||
|
||||
#define CONTROLLER_STATUS_PARITY_ERROR 0x80
|
||||
|
||||
#define AUX_STATUS_OUTPUT_BUFFER_FULL (CONTROLLER_STATUS_OUTPUT_BUFFER_FULL | \
|
||||
CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL)
|
||||
|
||||
/* Controller mode register bits. */
|
||||
/* Keyboard data generate IRQ1. */
|
||||
|
||||
#define CONTROLLER_MODE_KEYBOARD_INTERRUPT 0x01
|
||||
|
||||
/* Mouse data generate IRQ12. */
|
||||
|
||||
#define CONTROLLER_MODE_MOUSE_INTERRUPT 0x02
|
||||
|
||||
/* The system flag. (?) */
|
||||
|
||||
#define CONTROLLER_MODE_SYS 0x04
|
||||
|
||||
/* The keylock doesn't affect the keyboard if set. */
|
||||
|
||||
#define CONTROLLER_MODE_NO_KEYLOCK 0x08
|
||||
|
||||
/* Disable keyboard interface. */
|
||||
|
||||
#define CONTROLLER_MODE_DISABLE_KEYBOARD 0x10
|
||||
|
||||
/* Disable mouse interface. */
|
||||
|
||||
#define CONTROLLER_MODE_DISABLE_MOUSE 0x20
|
||||
|
||||
/* Scan code conversion to PC format. */
|
||||
|
||||
#define CONTROLLER_MODE_KCC 0x40
|
||||
#define CONTROLLER_MODE_RFU 0x80
|
||||
|
||||
/* Timeout in ms for sending to keyboard controller. */
|
||||
|
||||
#define CONTROLLER_TIMEOUT 250
|
||||
|
||||
/* Hardware defines. */
|
||||
|
||||
#define CONTROLLER_PORT_BASE 0x60
|
||||
#define CONTROLLER_PORTS 0x10
|
||||
|
||||
/* Macros for accessing the keyboard controller on this platform. */
|
||||
|
||||
#define controller_read_input() READ_PORT_UCHAR ((PUCHAR)CONTROLLER_REGISTER_DATA)
|
||||
#define controller_read_status() READ_PORT_UCHAR ((PUCHAR)CONTROLLER_REGISTER_STATUS)
|
||||
#define controller_write_output(value) WRITE_PORT_UCHAR ((PUCHAR)CONTROLLER_REGISTER_DATA, value)
|
||||
#define controller_write_command(value) WRITE_PORT_UCHAR ((PUCHAR)CONTROLLER_REGISTER_CONTROL, value)
|
51
reactos/drivers/input/psaux/keyboard.h
Normal file
51
reactos/drivers/input/psaux/keyboard.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
// All or parts of this file are from CHAOS (http://www.se.chaosdev.org/).
|
||||
// CHAOS is also under the GNU General Public License.
|
||||
|
||||
/* Timeout in ms for keyboard command acknowledge. */
|
||||
|
||||
#define KEYBOARD_TIMEOUT 1000
|
||||
|
||||
/* Timeout in ms for initializing the keyboard. */
|
||||
|
||||
#define KEYBOARD_INIT_TIMEOUT 1000
|
||||
|
||||
/* Keyboard commands. */
|
||||
|
||||
#define KEYBOARD_COMMAND_SET_LEDS 0xED
|
||||
#define KEYBOARD_COMMAND_SET_RATE 0xF3
|
||||
#define KEYBOARD_COMMAND_ENABLE 0xF4
|
||||
#define KEYBOARD_COMMAND_DISABLE 0xF5
|
||||
#define KEYBOARD_COMMAND_RESET 0xFF
|
||||
|
||||
/* Keyboard replies. */
|
||||
/* Power on reset. */
|
||||
|
||||
#define KEYBOARD_REPLY_POWER_ON_RESET 0xAA
|
||||
|
||||
/* Acknowledgement of previous command. */
|
||||
|
||||
#define KEYBOARD_REPLY_ACK 0xFA
|
||||
|
||||
/* Command NACK, send the command again. */
|
||||
|
||||
#define KEYBOARD_REPLY_RESEND 0xFE
|
||||
|
||||
/* Hardware defines. */
|
||||
|
||||
#define KEYBOARD_IRQ 1
|
||||
|
||||
/* Return values from keyboard_read_data (). */
|
||||
/* No data. */
|
||||
|
||||
#define KEYBOARD_NO_DATA (-1)
|
||||
|
||||
/* Parity or other error. */
|
||||
|
||||
#define KEYBOARD_BAD_DATA (-2)
|
||||
|
||||
/* Common variables. */
|
||||
|
||||
int mouse_replies_expected;
|
||||
BOOLEAN has_mouse;
|
||||
// mailbox_id_type keyboard_target_mailbox_id;
|
||||
unsigned keyboard_pressed_keys[16];
|
226
reactos/drivers/input/psaux/mouse.c
Normal file
226
reactos/drivers/input/psaux/mouse.c
Normal file
|
@ -0,0 +1,226 @@
|
|||
// All or parts of this file are from CHAOS (http://www.se.chaosdev.org/).
|
||||
// CHAOS is also under the GNU General Public License.
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
|
||||
#include "controller.h"
|
||||
#include "mouse.h"
|
||||
#include "psaux.h"
|
||||
|
||||
// Have we got a PS/2 mouse port?
|
||||
BOOLEAN has_mouse = FALSE;
|
||||
|
||||
// This buffer holds the mouse scan codes. The PS/2 protocol sends three characters for each event.
|
||||
unsigned mouse_buffer[3];
|
||||
int mouse_buffer_position = 0;
|
||||
|
||||
// The number of mouse replies expected
|
||||
int mouse_replies_expected = 0;
|
||||
|
||||
// Handle a mouse event
|
||||
|
||||
BOOLEAN ps2_mouse_handler(PKINTERRUPT Interrupt, PVOID ServiceContext)
|
||||
{
|
||||
// char tmpstr[100];
|
||||
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)ServiceContext;
|
||||
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
|
||||
int state_dx, state_dy, state_buttons;
|
||||
unsigned scancode;
|
||||
unsigned status = controller_read_status();
|
||||
scancode = controller_read_input();
|
||||
|
||||
if((status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) != 0)
|
||||
{
|
||||
// mouse_handle_event(scancode); proceed to handle it
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE; // keyboard_handle_event(scancode);
|
||||
}
|
||||
|
||||
if (mouse_replies_expected > 0)
|
||||
{
|
||||
if (scancode == MOUSE_ACK)
|
||||
{
|
||||
mouse_replies_expected--;
|
||||
return;
|
||||
}
|
||||
|
||||
mouse_replies_expected = 0;
|
||||
}
|
||||
|
||||
/* Add this scancode to the mouse event queue. */
|
||||
|
||||
mouse_buffer[mouse_buffer_position] = scancode;
|
||||
mouse_buffer_position++;
|
||||
|
||||
// If the buffer is full, parse this event
|
||||
if (mouse_buffer_position == 3)
|
||||
{
|
||||
mouse_buffer_position = 0;
|
||||
// system_call_debug_print_simple ("We got a mouse event");
|
||||
|
||||
state_buttons = (mouse_buffer[0] & 1) * GPM_B_LEFT +
|
||||
(mouse_buffer[0] & 2) * GPM_B_RIGHT +
|
||||
(mouse_buffer[0] & 4) * GPM_B_MIDDLE;
|
||||
|
||||
/* Some PS/2 mice send reports with negative bit set in data[0] and zero for movement. I think this is a
|
||||
bug in the mouse, but working around it only causes artifacts when the actual report is -256; they'll
|
||||
be treated as zero. This should be rare if the mouse sampling rate is set to a reasonable value; the
|
||||
default of 100 Hz is plenty. (Stephen Tell) */
|
||||
|
||||
if (mouse_buffer[1] == 0)
|
||||
{
|
||||
state_dx = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
state_dx = (mouse_buffer[0] & 0x10) ?
|
||||
mouse_buffer[1] - 256 :
|
||||
mouse_buffer[1];
|
||||
}
|
||||
|
||||
if (mouse_buffer[2] == 0)
|
||||
{
|
||||
state_dy = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
state_dy = -((mouse_buffer[0] & 0x20) ?
|
||||
mouse_buffer[2] - 256 :
|
||||
mouse_buffer[2]);
|
||||
}
|
||||
|
||||
if (((state_dx!=0) || (state_dy!=0) /* || (state_buttons!=0) */ ))
|
||||
{
|
||||
// FIXME: Implement button state, see /include/ntddmous.h
|
||||
|
||||
DeviceObject = (PDEVICE_OBJECT)ServiceContext;
|
||||
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
if (DeviceExtension->InputDataCount == MOUSE_BUFFER_SIZE)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DeviceExtension->MouseInputData[DeviceExtension->InputDataCount].LastX = state_dx;
|
||||
DeviceExtension->MouseInputData[DeviceExtension->InputDataCount].LastY = state_dy;
|
||||
DeviceExtension->InputDataCount++;
|
||||
|
||||
KeInsertQueueDpc(&DeviceExtension->IsrDpc, DeviceObject->CurrentIrp, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Write a PS/2 mouse command. */
|
||||
|
||||
static void mouse_write_command (int command)
|
||||
{
|
||||
controller_wait ();
|
||||
controller_write_command (CONTROLLER_COMMAND_WRITE_MODE);
|
||||
controller_wait ();
|
||||
controller_write_output (command);
|
||||
}
|
||||
|
||||
/* Send a byte to the PS/2 mouse & handle returned ACK. */
|
||||
|
||||
static void mouse_write_ack (int value)
|
||||
{
|
||||
controller_wait ();
|
||||
controller_write_command (CONTROLLER_COMMAND_WRITE_MOUSE);
|
||||
controller_wait ();
|
||||
controller_write_output (value);
|
||||
|
||||
/* We expect an ACK in response. */
|
||||
|
||||
mouse_replies_expected++;
|
||||
controller_wait ();
|
||||
}
|
||||
|
||||
/* Check if this is a dual port controller. */
|
||||
|
||||
BOOLEAN detect_ps2_port(void)
|
||||
{
|
||||
int loops;
|
||||
BOOLEAN return_value = FALSE;
|
||||
|
||||
return TRUE; // The rest of this code fails under BOCHs
|
||||
|
||||
/* Put the value 0x5A in the output buffer using the "WriteAuxiliary Device Output Buffer" command (0xD3).
|
||||
Poll the Status Register for a while to see if the value really turns up in the Data Register. If the
|
||||
KEYBOARD_STATUS_MOUSE_OBF bit is also set to 1 in the Status Register, we assume this controller has an
|
||||
Auxiliary Port (a.k.a. Mouse Port). */
|
||||
|
||||
controller_wait ();
|
||||
controller_write_command (CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER);
|
||||
controller_wait ();
|
||||
|
||||
// 0x5A is a random dummy value
|
||||
controller_write_output (0x5A);
|
||||
|
||||
for (loops = 0; loops < 10; loops++)
|
||||
{
|
||||
unsigned char status = controller_read_status();
|
||||
|
||||
if((status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0)
|
||||
{
|
||||
controller_read_input();
|
||||
if ((status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) != 0)
|
||||
{
|
||||
return_value = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
KeDelayExecutionThread (KernelMode, FALSE, 1);
|
||||
}
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
// Initialize the PS/2 mouse support
|
||||
|
||||
BOOLEAN mouse_init (PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
ULONG MappedIrq;
|
||||
KIRQL Dirql;
|
||||
KAFFINITY Affinity;
|
||||
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
|
||||
DeviceExtension->InputDataCount = 0;
|
||||
DeviceExtension->MouseInputData = ExAllocatePool(NonPagedPool, sizeof(MOUSE_INPUT_DATA) * MOUSE_BUFFER_SIZE);
|
||||
|
||||
if (!detect_ps2_port ()) return FALSE;
|
||||
has_mouse = TRUE;
|
||||
|
||||
// Enable the PS/2 mouse port
|
||||
controller_write_command_word (CONTROLLER_COMMAND_MOUSE_ENABLE);
|
||||
|
||||
// 200 samples/sec
|
||||
mouse_write_ack (MOUSE_SET_SAMPLE_RATE);
|
||||
mouse_write_ack (200);
|
||||
|
||||
// 8 counts per mm
|
||||
mouse_write_ack (MOUSE_SET_RESOLUTION);
|
||||
mouse_write_ack (3);
|
||||
|
||||
// 2:1 scaling
|
||||
mouse_write_ack (MOUSE_SET_SCALE21);
|
||||
|
||||
// Enable the PS/2 device
|
||||
mouse_write_ack (MOUSE_ENABLE_DEVICE);
|
||||
|
||||
// Enable controller interrupts
|
||||
mouse_write_command (MOUSE_INTERRUPTS_ON);
|
||||
|
||||
// Connect the interrupt for the mouse irq
|
||||
MappedIrq = HalGetInterruptVector(Internal, 0, 0, MOUSE_IRQ, &Dirql, &Affinity);
|
||||
|
||||
IoConnectInterrupt(&DeviceExtension->MouseInterrupt, ps2_mouse_handler, DeviceObject, NULL, MappedIrq,
|
||||
Dirql, Dirql, 0, FALSE, Affinity, FALSE);
|
||||
|
||||
return TRUE;
|
||||
}
|
80
reactos/drivers/input/psaux/mouse.h
Normal file
80
reactos/drivers/input/psaux/mouse.h
Normal file
|
@ -0,0 +1,80 @@
|
|||
// All or parts of this file are from CHAOS (http://www.se.chaosdev.org/).
|
||||
// CHAOS is also under the GNU General Public License.
|
||||
|
||||
/* Mouse commands. */
|
||||
/* Set resolution. */
|
||||
|
||||
#define MOUSE_SET_RESOLUTION 0xE8
|
||||
|
||||
/* Set 1:1 scaling. */
|
||||
|
||||
#define MOUSE_SET_SCALE11 0xE6
|
||||
|
||||
/* Set 2:1 scaling. */
|
||||
|
||||
#define MOUSE_SET_SCALE21 0xE7
|
||||
|
||||
/* Get scaling factor. */
|
||||
|
||||
#define MOUSE_GET_SCALE 0xE9
|
||||
|
||||
/* Set stream mode. */
|
||||
|
||||
#define MOUSE_SET_STREAM 0xEA
|
||||
|
||||
/* Set sample rate (number of times the controller will poll the port
|
||||
per second). */
|
||||
|
||||
#define MOUSE_SET_SAMPLE_RATE 0xF3
|
||||
|
||||
/* Enable mouse device. */
|
||||
|
||||
#define MOUSE_ENABLE_DEVICE 0xF4
|
||||
|
||||
/* Disable mouse device. */
|
||||
|
||||
#define MOUSE_DISABLE_DEVICE 0xF5
|
||||
|
||||
/* Reset aux device. */
|
||||
|
||||
#define MOUSE_RESET 0xFF
|
||||
|
||||
/* Command byte ACK. */
|
||||
|
||||
#define MOUSE_ACK 0xFA
|
||||
|
||||
#define MOUSE_INTERRUPTS_OFF (CONTROLLER_MODE_KCC | \
|
||||
CONTROLLER_MODE_DISABLE_MOUSE | \
|
||||
CONTROLLER_MODE_SYS | \
|
||||
CONTROLLER_MODE_KEYBOARD_INTERRUPT)
|
||||
|
||||
#define MOUSE_INTERRUPTS_ON (CONTROLLER_MODE_KCC | \
|
||||
CONTROLLER_MODE_SYS | \
|
||||
CONTROLLER_MODE_MOUSE_INTERRUPT | \
|
||||
CONTROLLER_MODE_KEYBOARD_INTERRUPT)
|
||||
|
||||
/* Used with mouse buttons */
|
||||
|
||||
#define GPM_B_LEFT 4
|
||||
#define GPM_B_MIDDLE 2
|
||||
#define GPM_B_RIGHT 1
|
||||
|
||||
/* Some aux operations take long time. */
|
||||
|
||||
#define MAX_RETRIES 60
|
||||
|
||||
/* Hardware defines. */
|
||||
|
||||
#define MOUSE_IRQ 12
|
||||
#define MOUSE_WRAP_MASK 0x1F
|
||||
|
||||
static PIRP CurrentIrp;
|
||||
static ULONG MouseDataRead;
|
||||
static ULONG MouseDataRequired;
|
||||
static BOOLEAN AlreadyOpened = FALSE;
|
||||
static KDPC MouseDpc;
|
||||
|
||||
static VOID MouseDpcRoutine(PKDPC Dpc,
|
||||
PVOID DeferredContext,
|
||||
PVOID SystemArgument1,
|
||||
PVOID SystemArgument2);
|
192
reactos/drivers/input/psaux/psaux.c
Normal file
192
reactos/drivers/input/psaux/psaux.c
Normal file
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
|
||||
** PS/2 driver 0.0.1
|
||||
** Written by Jason Filby (jasonfilby@yahoo.com)
|
||||
** For ReactOS (www.reactos.com)
|
||||
|
||||
** Handles the keyboard and mouse on the PS/2 ports
|
||||
|
||||
** TODO: Fix detect_ps2_port(void) so that it works under BOCHs
|
||||
Implement mouse button support
|
||||
|
||||
*/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include "../include/mouse.h"
|
||||
#include "mouse.h"
|
||||
#include "psaux.h"
|
||||
|
||||
BOOLEAN MouseSynchronizeRoutine(PVOID Context)
|
||||
{
|
||||
PIRP Irp = (PIRP)Context;
|
||||
PMOUSE_INPUT_DATA rec = (PMOUSE_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer;
|
||||
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
|
||||
ULONG NrToRead = stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA);
|
||||
int i;
|
||||
|
||||
if ((stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA))==NrToRead)
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
MouseDataRequired=stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA);
|
||||
MouseDataRead=NrToRead;
|
||||
CurrentIrp=Irp;
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
VOID PS2MouseStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
|
||||
if (KeSynchronizeExecution(DeviceExtension->MouseInterrupt, MouseSynchronizeRoutine, Irp))
|
||||
{
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
IoStartNextPacket(DeviceObject, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS PS2MouseDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
|
||||
NTSTATUS Status;
|
||||
|
||||
switch (stk->MajorFunction)
|
||||
{
|
||||
case IRP_MJ_CREATE:
|
||||
if (AlreadyOpened == TRUE)
|
||||
{
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_SUCCESS;
|
||||
AlreadyOpened = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
VOID PS2MouseInitializeDataQueue(PVOID Context)
|
||||
{
|
||||
/* PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)((PGET_DATA_POINTER_CONTEXT)Context)->DeviceExtension;
|
||||
|
||||
((PGET_DATA_POINTER_CONTEXT)Context)->DataIn = DeviceExtension->DataIn;
|
||||
((PGET_DATA_POINTER_CONTEXT)Context)->DataOut = DeviceExtension->DataOut;
|
||||
((PGET_DATA_POINTER_CONTEXT)Context)->InputCount = DeviceExtension->InputCount; */
|
||||
|
||||
DbgPrint("PS2MouseInitializeDataQueue UNIMPLEMENTED\n");
|
||||
}
|
||||
|
||||
NTSTATUS PS2MouseInternalDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
||||
{
|
||||
// Refer to \readableMouseDriver\port\sermcmn.c line 54
|
||||
|
||||
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 =
|
||||
*((PCLASS_INFORMATION)Stack->Parameters.DeviceIoControl.Type3InputBuffer);
|
||||
|
||||
// Reinitialize the port input data queue synchronously
|
||||
KeSynchronizeExecution(DeviceExtension->MouseInterrupt,
|
||||
(PKSYNCHRONIZE_ROUTINE)PS2MouseInitializeDataQueue, DeviceExtension);
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
VOID PS2MouseIsrDpc(PKDPC Dpc, PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
|
||||
{
|
||||
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
|
||||
(*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassInformation.CallBack)(
|
||||
DeviceExtension->ClassInformation.DeviceObject,
|
||||
DeviceExtension->MouseInputData,
|
||||
NULL,
|
||||
&DeviceExtension->InputDataCount);
|
||||
|
||||
DeviceExtension->InputDataCount = 0;
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
UNICODE_STRING DeviceName;
|
||||
UNICODE_STRING SymlinkName;
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
DbgPrint("PS/2 Keyboard & Mouse Driver 0.0.1\n");
|
||||
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = PS2MouseDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = PS2MouseDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = PS2MouseInternalDeviceControl;
|
||||
|
||||
DriverObject->DriverStartIo = PS2MouseStartIo;
|
||||
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\Mouse"); // FIXME: find correct device name
|
||||
IoCreateDevice(DriverObject,
|
||||
sizeof(DEVICE_EXTENSION),
|
||||
&DeviceName,
|
||||
FILE_DEVICE_SERIAL_MOUSE_PORT, // FIXME: this isn't really a serial mouse port driver
|
||||
0,
|
||||
TRUE,
|
||||
&DeviceObject);
|
||||
DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO;
|
||||
|
||||
RtlInitUnicodeString(&SymlinkName, L"\\??\\Mouse"); // FIXME: find correct device name
|
||||
IoCreateSymbolicLink(&SymlinkName, &DeviceName);
|
||||
|
||||
DeviceExtension = DeviceObject->DeviceExtension;
|
||||
KeInitializeDpc(&DeviceExtension->IsrDpc, (PKDEFERRED_ROUTINE)PS2MouseIsrDpc, DeviceObject);
|
||||
KeInitializeDpc(&DeviceExtension->IsrDpcRetry, (PKDEFERRED_ROUTINE)PS2MouseIsrDpc, DeviceObject);
|
||||
|
||||
mouse_init(DeviceObject);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
12
reactos/drivers/input/psaux/psaux.h
Normal file
12
reactos/drivers/input/psaux/psaux.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
typedef struct _DEVICE_EXTENSION {
|
||||
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
ULONG InputDataCount;
|
||||
PMOUSE_INPUT_DATA MouseInputData;
|
||||
CLASS_INFORMATION ClassInformation;
|
||||
|
||||
PKINTERRUPT MouseInterrupt;
|
||||
KDPC IsrDpc;
|
||||
KDPC IsrDpcRetry;
|
||||
|
||||
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
|
39
reactos/drivers/input/psaux/psaux.rc
Normal file
39
reactos/drivers/input/psaux/psaux.rc
Normal file
|
@ -0,0 +1,39 @@
|
|||
|
||||
#include <defines.h>
|
||||
#include <reactos/resource.h>
|
||||
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
|
||||
PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", RES_STR_COMPANY_NAME
|
||||
VALUE "FileDescription", "PS Auxiliary Device Driver\0"
|
||||
VALUE "FileVersion", "0.0.1\0"
|
||||
VALUE "InternalName", "psaux\0"
|
||||
VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
|
||||
VALUE "OriginalFilename", "psaux.sys\0"
|
||||
VALUE "ProductName", RES_STR_PRODUCT_NAME
|
||||
VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
52
reactos/drivers/input/sermouse/makefile
Normal file
52
reactos/drivers/input/sermouse/makefile
Normal file
|
@ -0,0 +1,52 @@
|
|||
#
|
||||
#
|
||||
#
|
||||
PATH_TO_TOP = ../../..
|
||||
|
||||
TARGET=mouse
|
||||
OBJECTS= mouse.o ../../../ntoskrnl/ntoskrnl.a
|
||||
|
||||
all: mouse.o
|
||||
|
||||
.phony: all
|
||||
|
||||
clean:
|
||||
- $(RM) mouse.o
|
||||
- $(RM) junk.tmp
|
||||
- $(RM) base.tmp
|
||||
- $(RM) temp.exp
|
||||
- $(RM) mouse.sys
|
||||
|
||||
.phony: clean
|
||||
|
||||
install: $(FLOPPY_DIR)/drivers/$(TARGET).sys
|
||||
|
||||
$(FLOPPY_DIR)/drivers/$(TARGET).sys: $(TARGET).sys
|
||||
ifeq ($(DOSCLI),yes)
|
||||
$(CP) $(TARGET).sys $(FLOPPY_DIR)\drivers\$(TARGET).sys
|
||||
else
|
||||
$(CP) $(TARGET).sys $(FLOPPY_DIR)/drivers/$(TARGET).sys
|
||||
endif
|
||||
|
||||
dist: ../../../$(DIST_DIR)/drivers/$(TARGET).sys
|
||||
|
||||
../../../$(DIST_DIR)/drivers/$(TARGET).sys: $(TARGET).sys
|
||||
ifeq ($(DOSCLI),yes)
|
||||
$(CP) $(TARGET).sys ..\..\..\$(DIST_DIR)\drivers\$(TARGET).sys
|
||||
else
|
||||
$(CP) $(TARGET).sys ../../../$(DIST_DIR)/drivers/$(TARGET).sys
|
||||
endif
|
||||
|
||||
mouse.sys: $(OBJECTS)
|
||||
$(CC) -specs=../../svc_specs -mdll -o junk.tmp -Wl,--defsym,_end=end \
|
||||
-Wl,--defsym,_edata=__data_end__ -Wl,--defsym,_etext=etext \
|
||||
-Wl,--base-file,base.tmp $(OBJECTS)
|
||||
- $(RM) junk.tmp
|
||||
$(DLLTOOL) --dllname mouse.sys --base-file base.tmp \
|
||||
--output-exp temp.exp
|
||||
- $(RM) base.tmp
|
||||
$(CC) --verbose -Wl,--image-base,0x10000 -Wl,-e,_DriverEntry@8 \
|
||||
-specs=../../svc_specs -mdll -o mouse.sys $(OBJECTS) -Wl,temp.exp
|
||||
- $(RM) temp.exp
|
||||
|
||||
|
270
reactos/drivers/input/sermouse/mouse.c
Normal file
270
reactos/drivers/input/sermouse/mouse.c
Normal file
|
@ -0,0 +1,270 @@
|
|||
/*
|
||||
|
||||
** Mouse driver 0.0.3
|
||||
** Written by Jason Filby (jasonfilby@yahoo.com)
|
||||
** For ReactOS (www.sid-dis.com/reactos)
|
||||
|
||||
** Note: The serial.o driver must be loaded before loading this driver
|
||||
|
||||
** Known Limitations:
|
||||
** Only supports mice on COM port 1
|
||||
|
||||
*/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <internal/mmhal.h>
|
||||
#include <internal/halio.h>
|
||||
/* #include <internal/hal/ddk.h> */
|
||||
#include <funcs.h>
|
||||
|
||||
#define MOUSE_IRQ_COM1 4
|
||||
#define MOUSE_IRQ_COM2 3
|
||||
|
||||
#define COM1_PORT 0x3f8
|
||||
#define COM2_PORT 0x2f8
|
||||
|
||||
#define max_screen_x 79
|
||||
#define max_screen_y 24
|
||||
|
||||
static unsigned int MOUSE_IRQ=MOUSE_IRQ_COM1;
|
||||
static unsigned int MOUSE_COM=COM1_PORT;
|
||||
|
||||
static unsigned int bytepos=0, coordinate;
|
||||
static unsigned char mpacket[3];
|
||||
static signed int mouse_x=40, mouse_y=12;
|
||||
static unsigned char mouse_button1, mouse_button2;
|
||||
static signed int horiz_sensitivity, vert_sensitivity;
|
||||
|
||||
BOOLEAN microsoft_mouse_handler(PKINTERRUPT Interrupt, PVOID ServiceContext)
|
||||
{
|
||||
unsigned int mbyte=inb(MOUSE_COM);
|
||||
|
||||
// Synchronize
|
||||
if((mbyte&64)==64) { bytepos=0; };
|
||||
|
||||
mpacket[bytepos]=mbyte;
|
||||
bytepos++;
|
||||
|
||||
// Process packet
|
||||
if(bytepos==3) {
|
||||
// Retrieve change in x and y from packet
|
||||
int change_x=((mpacket[0] & 3) << 6) + mpacket[1];
|
||||
int change_y=((mpacket[0] & 12) << 4) + mpacket[2];
|
||||
|
||||
// Some mice need this
|
||||
if(coordinate==1) {
|
||||
change_x-=128;
|
||||
change_y-=128;
|
||||
};
|
||||
|
||||
// Change to signed
|
||||
if(change_x>=128) { change_x=change_x-256; };
|
||||
if(change_y>=128) { change_y=change_y-256; };
|
||||
|
||||
// Adjust mouse position according to sensitivity
|
||||
mouse_x+=change_x/horiz_sensitivity;
|
||||
mouse_y+=change_y/vert_sensitivity;
|
||||
|
||||
// Check that mouse is still in screen
|
||||
if(mouse_x<0) { mouse_x=0; };
|
||||
if(mouse_x>max_screen_x) { mouse_x=max_screen_x; };
|
||||
if(mouse_y<0) { mouse_y=0; };
|
||||
if(mouse_y>max_screen_y) { mouse_y=max_screen_y; };
|
||||
|
||||
// Retrieve mouse button status from packet
|
||||
mouse_button1=mpacket[0] & 32;
|
||||
mouse_button2=mpacket[0] & 16;
|
||||
|
||||
bytepos=0;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
void InitializeMouseHardware(unsigned int mtype)
|
||||
{
|
||||
char clear_error_bits;
|
||||
|
||||
outb_p(MOUSE_COM+3, 0x80); // set DLAB on
|
||||
outb_p(MOUSE_COM, 0x60); // speed LO byte
|
||||
outb_p(MOUSE_COM+1, 0); // speed HI byte
|
||||
outb_p(MOUSE_COM+3, mtype); // 2=MS Mouse; 3=Mouse systems mouse
|
||||
outb_p(MOUSE_COM+1, 0); // set comm and DLAB to 0
|
||||
outb_p(MOUSE_COM+4, 1); // DR int enable
|
||||
|
||||
clear_error_bits=inb_p(MOUSE_COM+5); // clear error bits
|
||||
};
|
||||
|
||||
int DetMicrosoft(void)
|
||||
{
|
||||
char tmp, ind;
|
||||
int buttons=0, i;
|
||||
|
||||
outb_p(MOUSE_COM+4, 0x0b);
|
||||
tmp=inb_p(MOUSE_COM);
|
||||
|
||||
// Check the first for bytes for signs that this is an MS mouse
|
||||
for(i=0; i<4; i++) {
|
||||
while((inb_p(MOUSE_COM+5) & 1)==0) ;
|
||||
ind=inb_p(MOUSE_COM);
|
||||
if(ind==0x33) buttons=3;
|
||||
if(ind==0x4d) buttons=2;
|
||||
};
|
||||
|
||||
return buttons;
|
||||
};
|
||||
|
||||
int CheckMouseType(unsigned int mtype)
|
||||
{
|
||||
unsigned int retval=0;
|
||||
|
||||
InitializeMouseHardware(mtype);
|
||||
if(mtype==2) retval=DetMicrosoft();
|
||||
if(mtype==3) {
|
||||
outb_p(MOUSE_COM+4, 11);
|
||||
retval=3;
|
||||
};
|
||||
outb_p(MOUSE_COM+1, 1);
|
||||
|
||||
return retval;
|
||||
};
|
||||
|
||||
void ClearMouse(void)
|
||||
{
|
||||
// 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
|
||||
|
||||
unsigned int restarts=0, i;
|
||||
for (i=0; i<60000; i++)
|
||||
{
|
||||
unsigned temp=inb(MOUSE_COM);
|
||||
if(temp!=0) {
|
||||
restarts++;
|
||||
if(restarts<300000) {
|
||||
i=0;
|
||||
} else
|
||||
{
|
||||
i=60000;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
void InitializeMouse(void)
|
||||
{
|
||||
int mbuttons=0, gotmouse=0;
|
||||
ULONG MappedIrq;
|
||||
KIRQL Dirql;
|
||||
KAFFINITY Affinity;
|
||||
PKINTERRUPT IrqObject;
|
||||
|
||||
horiz_sensitivity=2;
|
||||
vert_sensitivity=3;
|
||||
|
||||
// Check for Microsoft mouse (2 buttons)
|
||||
if(CheckMouseType(2)!=0)
|
||||
{
|
||||
gotmouse=1;
|
||||
DbgPrint("Microsoft Mouse Detected\n");
|
||||
ClearMouse();
|
||||
coordinate=0;
|
||||
};
|
||||
|
||||
// Check for Microsoft Systems mouse (3 buttons)
|
||||
if(gotmouse==0) {
|
||||
if(CheckMouseType(3)!=0)
|
||||
{
|
||||
gotmouse=1;
|
||||
DbgPrint("Microsoft Mouse Detected\n");
|
||||
ClearMouse();
|
||||
coordinate=1;
|
||||
};
|
||||
};
|
||||
|
||||
if(gotmouse==0) {
|
||||
DbgPrint("No Mouse Detected!\n");
|
||||
} else {
|
||||
MappedIrq = HalGetInterruptVector(Internal, 0, 0, MOUSE_IRQ,
|
||||
&Dirql, &Affinity);
|
||||
|
||||
IoConnectInterrupt(&IrqObject, microsoft_mouse_handler, NULL,
|
||||
NULL, MappedIrq, Dirql, Dirql, 0, FALSE,
|
||||
Affinity, FALSE);
|
||||
};
|
||||
};
|
||||
|
||||
// For test purposes only
|
||||
unsigned char get_text_char(int x, int y)
|
||||
{
|
||||
unsigned char getchar;
|
||||
char *vidmem=(char*)physical_to_linear((0xb8000+(y*160)+(x*2)));
|
||||
getchar=*vidmem;
|
||||
return getchar;
|
||||
};
|
||||
|
||||
// For test purposes only
|
||||
unsigned char get_text_color(int x, int y)
|
||||
{
|
||||
unsigned char getcolor;
|
||||
char *vidmem=(char*)physical_to_linear((0xb8000+(y*160)+(x*2)));
|
||||
vidmem++;
|
||||
getcolor=*vidmem;
|
||||
return getcolor;
|
||||
};
|
||||
|
||||
// For test purposes only
|
||||
void put_text_char(int x, int y, unsigned char putchar[2])
|
||||
{
|
||||
char *vidmem=(char*)physical_to_linear((0xb8000+(y*160)+(x*2)));
|
||||
*vidmem=putchar[0];
|
||||
vidmem++;
|
||||
*vidmem=putchar[1];
|
||||
};
|
||||
|
||||
// For test purposes only
|
||||
void test_mouse(void)
|
||||
{
|
||||
static int i=0, forcechange=0;
|
||||
static int old_x=40, old_y=12;
|
||||
static unsigned char old_cursor[2], new_cursor[2];
|
||||
|
||||
DbgPrint("Testing mouse...");
|
||||
|
||||
old_cursor[0]=' ';
|
||||
old_cursor[1]=7;
|
||||
new_cursor[0]='Û';
|
||||
new_cursor[1]=15;
|
||||
|
||||
old_cursor[0]=get_text_char(mouse_x, mouse_y);
|
||||
old_cursor[1]=get_text_color(mouse_x, mouse_y);
|
||||
put_text_char(mouse_x, mouse_y, new_cursor);
|
||||
|
||||
while(i!=1)
|
||||
{
|
||||
if(mouse_button1!=0) { new_cursor[1]=10; mouse_button1=0; forcechange=1; };
|
||||
if(mouse_button2!=0) { new_cursor[1]=12; mouse_button2=0; forcechange=1; };
|
||||
|
||||
if((mouse_x!=old_x) || (mouse_y!=old_y) || (forcechange==1)) {
|
||||
forcechange=0;
|
||||
|
||||
put_text_char(old_x, old_y, old_cursor);
|
||||
old_cursor[0]=get_text_char(mouse_x, mouse_y);
|
||||
old_cursor[1]=get_text_color(mouse_x, mouse_y);
|
||||
put_text_char(mouse_x, mouse_y, new_cursor);
|
||||
|
||||
old_x=mouse_x;
|
||||
old_y=mouse_y;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
NTSTATUS STDCALL
|
||||
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
DbgPrint("Mouse Driver 0.0.3\n");
|
||||
InitializeMouse();
|
||||
test_mouse();
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
};
|
||||
|
Loading…
Reference in a new issue