+++ /dev/null
-/*
- * 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 NTSTATUS
-DeviceIoControl(
- 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 NTSTATUS
-ReadBytes(
- 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 NTSTATUS
-Wait(
- 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_TYPE
-SermouseDetectLegacyDevice(
- 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;
-}