Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248/* * PROJECT: ReactOS Serial mouse driver * LICENSE: GPL - See COPYING in the top level directory * FILE: drivers/input/sermouse/detect.c * PURPOSE: Detect serial mouse type * 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 <ntifs.h>#include <debug.h>
/* Most of this file is ripped from reactos/drivers/bus/serenum/detect.c */
static NTSTATUSDeviceIoControl( IN PDEVICE_OBJECT DeviceObject, IN ULONG CtlCode, IN PVOID InputBuffer OPTIONAL, IN SIZE_T InputBufferSize, IN OUT PVOID OutputBuffer OPTIONAL, IN OUT PSIZE_T OutputBufferSize){ KEVENT Event; PIRP Irp; IO_STATUS_BLOCK IoStatus; NTSTATUS Status;
KeInitializeEvent (&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(CtlCode, DeviceObject, InputBuffer, (ULONG)InputBufferSize, OutputBuffer, (OutputBufferSize) ? (ULONG)*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 = (SIZE_T)IoStatus.Information; }
return Status;}
static NTSTATUSReadBytes( IN PDEVICE_OBJECT LowerDevice, OUT PUCHAR Buffer, IN ULONG BufferSize, OUT PULONG_PTR FilledBytes){ PIRP Irp; IO_STATUS_BLOCK ioStatus; KEVENT event; LARGE_INTEGER zero; NTSTATUS Status;
KeInitializeEvent(&event, NotificationEvent, FALSE); zero.QuadPart = 0; Irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ, LowerDevice, Buffer, BufferSize, &zero, &event, &ioStatus); if (!Irp) return FALSE;
Status = IoCallDriver(LowerDevice, Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL); Status = ioStatus.Status; } INFO_(SERMOUSE, "Bytes received: %lu/%lu\n", ioStatus.Information, BufferSize); *FilledBytes = ioStatus.Information; return Status;}
static NTSTATUSWait( IN ULONG milliseconds){ KTIMER Timer; LARGE_INTEGER DueTime;
DueTime.QuadPart = milliseconds * -10; KeInitializeTimer(&Timer); KeSetTimer(&Timer, DueTime, NULL); return KeWaitForSingleObject(&Timer, Executive, KernelMode, FALSE, NULL);}
SERMOUSE_MOUSE_TYPESermouseDetectLegacyDevice( IN PDEVICE_OBJECT LowerDevice){ HANDLE Handle; ULONG Fcr, Mcr; ULONG BaudRate; ULONG Command; SERIAL_TIMEOUTS Timeouts; SERIAL_LINE_CONTROL LCR; ULONG_PTR i, Count = 0; UCHAR Buffer[16]; SERMOUSE_MOUSE_TYPE MouseType = mtNone; NTSTATUS Status;
TRACE_(SERMOUSE, "SermouseDetectLegacyDevice(LowerDevice %p)\n", LowerDevice);
RtlZeroMemory(Buffer, sizeof(Buffer));
/* Open port */ Status = ObOpenObjectByPointer( LowerDevice, OBJ_KERNEL_HANDLE, NULL, 0, NULL, KernelMode, &Handle); if (!NT_SUCCESS(Status)) return mtNone;
/* Reset UART */ TRACE_(SERMOUSE, "Reset UART\n"); Mcr = 0; /* MCR: DTR/RTS/OUT2 off */ Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_MODEM_CONTROL, &Mcr, sizeof(Mcr), NULL, NULL); if (!NT_SUCCESS(Status)) goto ByeBye;
/* Set communications parameters */ TRACE_(SERMOUSE, "Set communications parameters\n"); /* DLAB off */ Fcr = 0; Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_FIFO_CONTROL, &Fcr, sizeof(Fcr), NULL, NULL); if (!NT_SUCCESS(Status)) goto ByeBye; /* Set serial port speed */ BaudRate = 1200; Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_BAUD_RATE, &BaudRate, sizeof(BaudRate), NULL, NULL); if (!NT_SUCCESS(Status)) goto ByeBye; /* Set LCR */ LCR.WordLength = 7; LCR.Parity = NO_PARITY; LCR.StopBits = STOP_BITS_2; Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_LINE_CONTROL, &LCR, sizeof(LCR), NULL, NULL); if (!NT_SUCCESS(Status)) goto ByeBye;
/* Flush receive buffer */ TRACE_(SERMOUSE, "Flush receive buffer\n"); Command = SERIAL_PURGE_RXCLEAR; Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_MODEM_CONTROL, &Command, sizeof(Command), NULL, NULL); if (!NT_SUCCESS(Status)) goto ByeBye; /* Wait 100 ms */ Wait(100);
/* Enable DTR/RTS */ TRACE_(SERMOUSE, "Enable DTR/RTS\n"); Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_DTR, NULL, 0, NULL, NULL); if (!NT_SUCCESS(Status)) goto ByeBye; Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_RTS, NULL, 0, NULL, NULL); if (!NT_SUCCESS(Status)) goto ByeBye;
/* Set timeout to 500 microseconds */ TRACE_(SERMOUSE, "Set timeout to 500 microseconds\n"); Timeouts.ReadIntervalTimeout = 100; Timeouts.ReadTotalTimeoutMultiplier = 0; Timeouts.ReadTotalTimeoutConstant = 500; Timeouts.WriteTotalTimeoutMultiplier = Timeouts.WriteTotalTimeoutConstant = 0; Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_TIMEOUTS, &Timeouts, sizeof(Timeouts), NULL, NULL); if (!NT_SUCCESS(Status)) goto ByeBye;
/* Fill the read buffer */ TRACE_(SERMOUSE, "Fill the read buffer\n"); Status = ReadBytes(LowerDevice, Buffer, sizeof(Buffer)/sizeof(Buffer[0]), &Count); if (!NT_SUCCESS(Status)) goto ByeBye;
for (i = 0; i < Count; i++) { if (Buffer[i] == 'B') { /* Sign for Microsoft Ballpoint */ ERR_(SERMOUSE, "Microsoft Ballpoint device detected. THIS DEVICE IS NOT YET SUPPORTED"); MouseType = mtNone; goto ByeBye; } else if (Buffer[i] == 'M') { /* Sign for Microsoft Mouse protocol followed by button specifier */ if (i == sizeof(Buffer) - 1) { /* Overflow Error */ goto ByeBye; } switch (Buffer[i + 1]) { case '3': INFO_(SERMOUSE, "Microsoft Mouse with 3-buttons detected\n"); MouseType = mtLogitech; break; case 'Z': INFO_(SERMOUSE, "Microsoft Wheel Mouse detected\n"); MouseType = mtWheelZ; break; default: INFO_(SERMOUSE, "Microsoft Mouse with 2-buttons detected\n"); MouseType = mtMicrosoft; break; } goto ByeBye; } }
ByeBye: /* Close port */ if (Handle) ZwClose(Handle); return MouseType;}