Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277/* * PROJECT: ReactOS Serial mouse driver * LICENSE: GPL - See COPYING in the top level directory * FILE: drivers/input/sermouse/fdo.c * PURPOSE: Read mouse moves and send them to mouclass * PROGRAMMERS: Copyright Jason Filby (jasonfilby@yahoo.com) Copyright Filip Navara (xnavara@volny.cz) Copyright 2005-2006 Herv� Poussineau (hpoussin@reactos.org) */
#include "sermouse.h"
#include <debug.h>
static NTSTATUSSermouseDeviceIoControl( IN PDEVICE_OBJECT DeviceObject, IN ULONG CtlCode, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferSize, IN OUT PVOID OutputBuffer OPTIONAL, IN OUT PULONG OutputBufferSize){ KEVENT Event; PIRP Irp; IO_STATUS_BLOCK IoStatus; NTSTATUS Status;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(CtlCode, DeviceObject, InputBuffer, InputBufferSize, OutputBuffer, (OutputBufferSize) ? *OutputBufferSize : 0, FALSE, &Event, &IoStatus); if (Irp == NULL) { WARN_(SERMOUSE, "IoBuildDeviceIoControlRequest() failed\n"); return STATUS_INSUFFICIENT_RESOURCES; }
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING) { INFO_(SERMOUSE, "Operation pending\n"); KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); Status = IoStatus.Status; }
if (OutputBufferSize) { *OutputBufferSize = (ULONG)IoStatus.Information; }
return Status;}
VOID NTAPISermouseDeviceWorker( PVOID Context){ PSERMOUSE_DEVICE_EXTENSION DeviceExtension; PDEVICE_OBJECT LowerDevice; UCHAR Buffer[PACKET_BUFFER_SIZE]; PIRP Irp; IO_STATUS_BLOCK ioStatus; KEVENT event; PUCHAR PacketBuffer; UCHAR ReceivedByte; ULONG Queue; PMOUSE_INPUT_DATA Input; ULONG ButtonsDifference; KIRQL OldIrql; ULONG i; ULONG Fcr; ULONG BaudRate; SERIAL_TIMEOUTS Timeouts; SERIAL_LINE_CONTROL LCR; LARGE_INTEGER Zero; NTSTATUS Status;
TRACE_(SERMOUSE, "SermouseDeviceWorker() called\n");
DeviceExtension = (PSERMOUSE_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension; LowerDevice = DeviceExtension->LowerDevice; Zero.QuadPart = 0; PacketBuffer = DeviceExtension->PacketBuffer;
ASSERT(LowerDevice);
/* Initialize device extension */ DeviceExtension->ActiveQueue = 0; DeviceExtension->PacketBufferPosition = 0; DeviceExtension->PreviousButtons = 0;
/* Initialize serial port */ Fcr = 0; Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_FIFO_CONTROL, &Fcr, sizeof(Fcr), NULL, NULL); if (!NT_SUCCESS(Status)) PsTerminateSystemThread(Status); /* Set serial port speed */ BaudRate = DeviceExtension->AttributesInformation.SampleRate * 8; Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_BAUD_RATE, &BaudRate, sizeof(BaudRate), NULL, NULL); if (!NT_SUCCESS(Status)) PsTerminateSystemThread(Status); /* Set LCR */ LCR.WordLength = 7; LCR.Parity = NO_PARITY; LCR.StopBits = STOP_BIT_1; Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_LINE_CONTROL, &LCR, sizeof(LCR), NULL, NULL); if (!NT_SUCCESS(Status)) PsTerminateSystemThread(Status);
/* Set timeouts */ Timeouts.ReadTotalTimeoutConstant = Timeouts.ReadTotalTimeoutMultiplier = 0; Timeouts.ReadIntervalTimeout = 100; Timeouts.WriteTotalTimeoutMultiplier = Timeouts.WriteTotalTimeoutConstant = 0; Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_TIMEOUTS, &Timeouts, sizeof(Timeouts), NULL, NULL); if (!NT_SUCCESS(Status)) PsTerminateSystemThread(Status);
/* main read loop */ RtlZeroMemory(Buffer, PACKET_BUFFER_SIZE); while (TRUE) { Status = KeWaitForSingleObject( &DeviceExtension->StopWorkerThreadEvent, Executive, KernelMode, TRUE, &Zero); if (Status != STATUS_TIMEOUT) { /* we need to stop the worker thread */ KeClearEvent(&DeviceExtension->StopWorkerThreadEvent); break; }
KeInitializeEvent(&event, NotificationEvent, FALSE); Irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ, LowerDevice, Buffer, PACKET_BUFFER_SIZE, &Zero, &event, &ioStatus); if (!Irp) { /* No memory actually, try later */ INFO_(SERMOUSE, "No memory actually, trying again\n"); KeStallExecutionProcessor(10); continue; }
Status = IoCallDriver(LowerDevice, Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL); Status = ioStatus.Status; }
if (!NT_SUCCESS(Status)) continue;
/* Read all available data and process */ for (i = 0; i < ioStatus.Information; i++) { ReceivedByte = Buffer[i]; INFO_(SERMOUSE, "ReceivedByte 0x%02x\n", ReceivedByte);
/* Synchronize */ if ((ReceivedByte & 0x40) == 0x40) DeviceExtension->PacketBufferPosition = 0;
PacketBuffer[DeviceExtension->PacketBufferPosition] = ReceivedByte & 0x7f; DeviceExtension->PacketBufferPosition++;
/* Process packet if complete */ if (DeviceExtension->PacketBufferPosition >= 3) { Queue = DeviceExtension->ActiveQueue % 2;
/* Prevent buffer overflow */ if (DeviceExtension->InputDataCount[Queue] == 1) continue;
Input = &DeviceExtension->MouseInputData[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 && DeviceExtension->AttributesInformation.NumberOfButtons >= 1) { if (Input->RawButtons & MOUSE_BUTTON_LEFT) Input->ButtonFlags |= MOUSE_LEFT_BUTTON_DOWN; else Input->ButtonFlags |= MOUSE_LEFT_BUTTON_UP; }
if (ButtonsDifference & MOUSE_BUTTON_RIGHT && DeviceExtension->AttributesInformation.NumberOfButtons >= 2) { if (Input->RawButtons & MOUSE_BUTTON_RIGHT) Input->ButtonFlags |= MOUSE_RIGHT_BUTTON_DOWN; else Input->ButtonFlags |= MOUSE_RIGHT_BUTTON_UP; }
if (ButtonsDifference & MOUSE_BUTTON_MIDDLE && DeviceExtension->AttributesInformation.NumberOfButtons >= 3) { 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]++;
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); InterlockedIncrement((PLONG)&DeviceExtension->ActiveQueue); (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ConnectData.ClassService)( DeviceExtension->ConnectData.ClassDeviceObject, &DeviceExtension->MouseInputData[Queue], &DeviceExtension->MouseInputData[Queue] + 1, &DeviceExtension->InputDataCount[Queue]); KeLowerIrql(OldIrql); DeviceExtension->InputDataCount[Queue] = 0;
/* Copy RawButtons to Previous Buttons for Input */ DeviceExtension->PreviousButtons = Input->RawButtons; } } }
PsTerminateSystemThread(STATUS_SUCCESS);}