1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * PROJECT: ReactOS Serial mouse driver
3*c2c66affSColin Finck * LICENSE: GPL - See COPYING in the top level directory
4*c2c66affSColin Finck * FILE: drivers/input/sermouse/detect.c
5*c2c66affSColin Finck * PURPOSE: Detect serial mouse type
6*c2c66affSColin Finck * PROGRAMMERS: Copyright Jason Filby (jasonfilby@yahoo.com)
7*c2c66affSColin Finck Copyright Filip Navara (xnavara@volny.cz)
8*c2c66affSColin Finck Copyright 2005-2006 Herv� Poussineau (hpoussin@reactos.org)
9*c2c66affSColin Finck */
10*c2c66affSColin Finck
11*c2c66affSColin Finck #include "sermouse.h"
12*c2c66affSColin Finck
13*c2c66affSColin Finck #include <ntifs.h>
14*c2c66affSColin Finck #include <debug.h>
15*c2c66affSColin Finck
16*c2c66affSColin Finck /* Most of this file is ripped from reactos/drivers/bus/serenum/detect.c */
17*c2c66affSColin Finck
18*c2c66affSColin Finck 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)19*c2c66affSColin Finck DeviceIoControl(
20*c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
21*c2c66affSColin Finck IN ULONG CtlCode,
22*c2c66affSColin Finck IN PVOID InputBuffer OPTIONAL,
23*c2c66affSColin Finck IN SIZE_T InputBufferSize,
24*c2c66affSColin Finck IN OUT PVOID OutputBuffer OPTIONAL,
25*c2c66affSColin Finck IN OUT PSIZE_T OutputBufferSize)
26*c2c66affSColin Finck {
27*c2c66affSColin Finck KEVENT Event;
28*c2c66affSColin Finck PIRP Irp;
29*c2c66affSColin Finck IO_STATUS_BLOCK IoStatus;
30*c2c66affSColin Finck NTSTATUS Status;
31*c2c66affSColin Finck
32*c2c66affSColin Finck KeInitializeEvent (&Event, NotificationEvent, FALSE);
33*c2c66affSColin Finck
34*c2c66affSColin Finck Irp = IoBuildDeviceIoControlRequest(CtlCode,
35*c2c66affSColin Finck DeviceObject,
36*c2c66affSColin Finck InputBuffer,
37*c2c66affSColin Finck (ULONG)InputBufferSize,
38*c2c66affSColin Finck OutputBuffer,
39*c2c66affSColin Finck (OutputBufferSize) ? (ULONG)*OutputBufferSize : 0,
40*c2c66affSColin Finck FALSE,
41*c2c66affSColin Finck &Event,
42*c2c66affSColin Finck &IoStatus);
43*c2c66affSColin Finck if (Irp == NULL)
44*c2c66affSColin Finck {
45*c2c66affSColin Finck WARN_(SERMOUSE, "IoBuildDeviceIoControlRequest() failed\n");
46*c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES;
47*c2c66affSColin Finck }
48*c2c66affSColin Finck
49*c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp);
50*c2c66affSColin Finck
51*c2c66affSColin Finck if (Status == STATUS_PENDING)
52*c2c66affSColin Finck {
53*c2c66affSColin Finck INFO_(SERMOUSE, "Operation pending\n");
54*c2c66affSColin Finck KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
55*c2c66affSColin Finck Status = IoStatus.Status;
56*c2c66affSColin Finck }
57*c2c66affSColin Finck
58*c2c66affSColin Finck if (OutputBufferSize)
59*c2c66affSColin Finck {
60*c2c66affSColin Finck *OutputBufferSize = (SIZE_T)IoStatus.Information;
61*c2c66affSColin Finck }
62*c2c66affSColin Finck
63*c2c66affSColin Finck return Status;
64*c2c66affSColin Finck }
65*c2c66affSColin Finck
66*c2c66affSColin Finck static NTSTATUS
ReadBytes(IN PDEVICE_OBJECT LowerDevice,OUT PUCHAR Buffer,IN ULONG BufferSize,OUT PULONG_PTR FilledBytes)67*c2c66affSColin Finck ReadBytes(
68*c2c66affSColin Finck IN PDEVICE_OBJECT LowerDevice,
69*c2c66affSColin Finck OUT PUCHAR Buffer,
70*c2c66affSColin Finck IN ULONG BufferSize,
71*c2c66affSColin Finck OUT PULONG_PTR FilledBytes)
72*c2c66affSColin Finck {
73*c2c66affSColin Finck PIRP Irp;
74*c2c66affSColin Finck IO_STATUS_BLOCK ioStatus;
75*c2c66affSColin Finck KEVENT event;
76*c2c66affSColin Finck LARGE_INTEGER zero;
77*c2c66affSColin Finck NTSTATUS Status;
78*c2c66affSColin Finck
79*c2c66affSColin Finck KeInitializeEvent(&event, NotificationEvent, FALSE);
80*c2c66affSColin Finck zero.QuadPart = 0;
81*c2c66affSColin Finck Irp = IoBuildSynchronousFsdRequest(
82*c2c66affSColin Finck IRP_MJ_READ,
83*c2c66affSColin Finck LowerDevice,
84*c2c66affSColin Finck Buffer, BufferSize,
85*c2c66affSColin Finck &zero,
86*c2c66affSColin Finck &event,
87*c2c66affSColin Finck &ioStatus);
88*c2c66affSColin Finck if (!Irp)
89*c2c66affSColin Finck return FALSE;
90*c2c66affSColin Finck
91*c2c66affSColin Finck Status = IoCallDriver(LowerDevice, Irp);
92*c2c66affSColin Finck if (Status == STATUS_PENDING)
93*c2c66affSColin Finck {
94*c2c66affSColin Finck KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
95*c2c66affSColin Finck Status = ioStatus.Status;
96*c2c66affSColin Finck }
97*c2c66affSColin Finck INFO_(SERMOUSE, "Bytes received: %lu/%lu\n",
98*c2c66affSColin Finck ioStatus.Information, BufferSize);
99*c2c66affSColin Finck *FilledBytes = ioStatus.Information;
100*c2c66affSColin Finck return Status;
101*c2c66affSColin Finck }
102*c2c66affSColin Finck
103*c2c66affSColin Finck static NTSTATUS
Wait(IN ULONG milliseconds)104*c2c66affSColin Finck Wait(
105*c2c66affSColin Finck IN ULONG milliseconds)
106*c2c66affSColin Finck {
107*c2c66affSColin Finck KTIMER Timer;
108*c2c66affSColin Finck LARGE_INTEGER DueTime;
109*c2c66affSColin Finck
110*c2c66affSColin Finck DueTime.QuadPart = milliseconds * -10;
111*c2c66affSColin Finck KeInitializeTimer(&Timer);
112*c2c66affSColin Finck KeSetTimer(&Timer, DueTime, NULL);
113*c2c66affSColin Finck return KeWaitForSingleObject(&Timer, Executive, KernelMode, FALSE, NULL);
114*c2c66affSColin Finck }
115*c2c66affSColin Finck
116*c2c66affSColin Finck SERMOUSE_MOUSE_TYPE
SermouseDetectLegacyDevice(IN PDEVICE_OBJECT LowerDevice)117*c2c66affSColin Finck SermouseDetectLegacyDevice(
118*c2c66affSColin Finck IN PDEVICE_OBJECT LowerDevice)
119*c2c66affSColin Finck {
120*c2c66affSColin Finck HANDLE Handle;
121*c2c66affSColin Finck ULONG Fcr, Mcr;
122*c2c66affSColin Finck ULONG BaudRate;
123*c2c66affSColin Finck ULONG Command;
124*c2c66affSColin Finck SERIAL_TIMEOUTS Timeouts;
125*c2c66affSColin Finck SERIAL_LINE_CONTROL LCR;
126*c2c66affSColin Finck ULONG_PTR i, Count = 0;
127*c2c66affSColin Finck UCHAR Buffer[16];
128*c2c66affSColin Finck SERMOUSE_MOUSE_TYPE MouseType = mtNone;
129*c2c66affSColin Finck NTSTATUS Status;
130*c2c66affSColin Finck
131*c2c66affSColin Finck TRACE_(SERMOUSE, "SermouseDetectLegacyDevice(LowerDevice %p)\n", LowerDevice);
132*c2c66affSColin Finck
133*c2c66affSColin Finck RtlZeroMemory(Buffer, sizeof(Buffer));
134*c2c66affSColin Finck
135*c2c66affSColin Finck /* Open port */
136*c2c66affSColin Finck Status = ObOpenObjectByPointer(
137*c2c66affSColin Finck LowerDevice,
138*c2c66affSColin Finck OBJ_KERNEL_HANDLE,
139*c2c66affSColin Finck NULL,
140*c2c66affSColin Finck 0,
141*c2c66affSColin Finck NULL,
142*c2c66affSColin Finck KernelMode,
143*c2c66affSColin Finck &Handle);
144*c2c66affSColin Finck if (!NT_SUCCESS(Status)) return mtNone;
145*c2c66affSColin Finck
146*c2c66affSColin Finck /* Reset UART */
147*c2c66affSColin Finck TRACE_(SERMOUSE, "Reset UART\n");
148*c2c66affSColin Finck Mcr = 0; /* MCR: DTR/RTS/OUT2 off */
149*c2c66affSColin Finck Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_MODEM_CONTROL,
150*c2c66affSColin Finck &Mcr, sizeof(Mcr), NULL, NULL);
151*c2c66affSColin Finck if (!NT_SUCCESS(Status)) goto ByeBye;
152*c2c66affSColin Finck
153*c2c66affSColin Finck /* Set communications parameters */
154*c2c66affSColin Finck TRACE_(SERMOUSE, "Set communications parameters\n");
155*c2c66affSColin Finck /* DLAB off */
156*c2c66affSColin Finck Fcr = 0;
157*c2c66affSColin Finck Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_FIFO_CONTROL,
158*c2c66affSColin Finck &Fcr, sizeof(Fcr), NULL, NULL);
159*c2c66affSColin Finck if (!NT_SUCCESS(Status)) goto ByeBye;
160*c2c66affSColin Finck /* Set serial port speed */
161*c2c66affSColin Finck BaudRate = 1200;
162*c2c66affSColin Finck Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_BAUD_RATE,
163*c2c66affSColin Finck &BaudRate, sizeof(BaudRate), NULL, NULL);
164*c2c66affSColin Finck if (!NT_SUCCESS(Status)) goto ByeBye;
165*c2c66affSColin Finck /* Set LCR */
166*c2c66affSColin Finck LCR.WordLength = 7;
167*c2c66affSColin Finck LCR.Parity = NO_PARITY;
168*c2c66affSColin Finck LCR.StopBits = STOP_BITS_2;
169*c2c66affSColin Finck Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_LINE_CONTROL,
170*c2c66affSColin Finck &LCR, sizeof(LCR), NULL, NULL);
171*c2c66affSColin Finck if (!NT_SUCCESS(Status)) goto ByeBye;
172*c2c66affSColin Finck
173*c2c66affSColin Finck /* Flush receive buffer */
174*c2c66affSColin Finck TRACE_(SERMOUSE, "Flush receive buffer\n");
175*c2c66affSColin Finck Command = SERIAL_PURGE_RXCLEAR;
176*c2c66affSColin Finck Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_MODEM_CONTROL,
177*c2c66affSColin Finck &Command, sizeof(Command), NULL, NULL);
178*c2c66affSColin Finck if (!NT_SUCCESS(Status)) goto ByeBye;
179*c2c66affSColin Finck /* Wait 100 ms */
180*c2c66affSColin Finck Wait(100);
181*c2c66affSColin Finck
182*c2c66affSColin Finck /* Enable DTR/RTS */
183*c2c66affSColin Finck TRACE_(SERMOUSE, "Enable DTR/RTS\n");
184*c2c66affSColin Finck Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_DTR,
185*c2c66affSColin Finck NULL, 0, NULL, NULL);
186*c2c66affSColin Finck if (!NT_SUCCESS(Status)) goto ByeBye;
187*c2c66affSColin Finck Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_RTS,
188*c2c66affSColin Finck NULL, 0, NULL, NULL);
189*c2c66affSColin Finck if (!NT_SUCCESS(Status)) goto ByeBye;
190*c2c66affSColin Finck
191*c2c66affSColin Finck /* Set timeout to 500 microseconds */
192*c2c66affSColin Finck TRACE_(SERMOUSE, "Set timeout to 500 microseconds\n");
193*c2c66affSColin Finck Timeouts.ReadIntervalTimeout = 100;
194*c2c66affSColin Finck Timeouts.ReadTotalTimeoutMultiplier = 0;
195*c2c66affSColin Finck Timeouts.ReadTotalTimeoutConstant = 500;
196*c2c66affSColin Finck Timeouts.WriteTotalTimeoutMultiplier = Timeouts.WriteTotalTimeoutConstant = 0;
197*c2c66affSColin Finck Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_TIMEOUTS,
198*c2c66affSColin Finck &Timeouts, sizeof(Timeouts), NULL, NULL);
199*c2c66affSColin Finck if (!NT_SUCCESS(Status)) goto ByeBye;
200*c2c66affSColin Finck
201*c2c66affSColin Finck /* Fill the read buffer */
202*c2c66affSColin Finck TRACE_(SERMOUSE, "Fill the read buffer\n");
203*c2c66affSColin Finck Status = ReadBytes(LowerDevice, Buffer, sizeof(Buffer)/sizeof(Buffer[0]), &Count);
204*c2c66affSColin Finck if (!NT_SUCCESS(Status)) goto ByeBye;
205*c2c66affSColin Finck
206*c2c66affSColin Finck for (i = 0; i < Count; i++)
207*c2c66affSColin Finck {
208*c2c66affSColin Finck if (Buffer[i] == 'B')
209*c2c66affSColin Finck {
210*c2c66affSColin Finck /* Sign for Microsoft Ballpoint */
211*c2c66affSColin Finck ERR_(SERMOUSE, "Microsoft Ballpoint device detected. THIS DEVICE IS NOT YET SUPPORTED");
212*c2c66affSColin Finck MouseType = mtNone;
213*c2c66affSColin Finck goto ByeBye;
214*c2c66affSColin Finck }
215*c2c66affSColin Finck else if (Buffer[i] == 'M')
216*c2c66affSColin Finck {
217*c2c66affSColin Finck /* Sign for Microsoft Mouse protocol followed by button specifier */
218*c2c66affSColin Finck if (i == sizeof(Buffer) - 1)
219*c2c66affSColin Finck {
220*c2c66affSColin Finck /* Overflow Error */
221*c2c66affSColin Finck goto ByeBye;
222*c2c66affSColin Finck }
223*c2c66affSColin Finck switch (Buffer[i + 1])
224*c2c66affSColin Finck {
225*c2c66affSColin Finck case '3':
226*c2c66affSColin Finck INFO_(SERMOUSE, "Microsoft Mouse with 3-buttons detected\n");
227*c2c66affSColin Finck MouseType = mtLogitech;
228*c2c66affSColin Finck break;
229*c2c66affSColin Finck case 'Z':
230*c2c66affSColin Finck INFO_(SERMOUSE, "Microsoft Wheel Mouse detected\n");
231*c2c66affSColin Finck MouseType = mtWheelZ;
232*c2c66affSColin Finck break;
233*c2c66affSColin Finck default:
234*c2c66affSColin Finck INFO_(SERMOUSE, "Microsoft Mouse with 2-buttons detected\n");
235*c2c66affSColin Finck MouseType = mtMicrosoft;
236*c2c66affSColin Finck break;
237*c2c66affSColin Finck }
238*c2c66affSColin Finck goto ByeBye;
239*c2c66affSColin Finck }
240*c2c66affSColin Finck }
241*c2c66affSColin Finck
242*c2c66affSColin Finck ByeBye:
243*c2c66affSColin Finck /* Close port */
244*c2c66affSColin Finck if (Handle)
245*c2c66affSColin Finck ZwClose(Handle);
246*c2c66affSColin Finck return MouseType;
247*c2c66affSColin Finck }
248