ReactOS  0.4.13-dev-92-gf251225
readmouse.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Serial mouse driver
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: drivers/input/sermouse/fdo.c
5  * PURPOSE: Read mouse moves and send them to mouclass
6  * PROGRAMMERS: Copyright Jason Filby (jasonfilby@yahoo.com)
7  Copyright Filip Navara (xnavara@volny.cz)
8  Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
9  */
10 
11 #include "sermouse.h"
12 
13 #include <debug.h>
14 
15 static NTSTATUS
18  IN ULONG CtlCode,
20  IN ULONG InputBufferSize,
22  IN OUT PULONG OutputBufferSize)
23 {
24  KEVENT Event;
25  PIRP Irp;
28 
30 
34  InputBufferSize,
36  (OutputBufferSize) ? *OutputBufferSize : 0,
37  FALSE,
38  &Event,
39  &IoStatus);
40  if (Irp == NULL)
41  {
42  WARN_(SERMOUSE, "IoBuildDeviceIoControlRequest() failed\n");
44  }
45 
47 
48  if (Status == STATUS_PENDING)
49  {
50  INFO_(SERMOUSE, "Operation pending\n");
52  Status = IoStatus.Status;
53  }
54 
55  if (OutputBufferSize)
56  {
57  *OutputBufferSize = (ULONG)IoStatus.Information;
58  }
59 
60  return Status;
61 }
62 
63 VOID NTAPI
65  PVOID Context)
66 {
67  PSERMOUSE_DEVICE_EXTENSION DeviceExtension;
68  PDEVICE_OBJECT LowerDevice;
70  PIRP Irp;
71  IO_STATUS_BLOCK ioStatus;
72  KEVENT event;
73  PUCHAR PacketBuffer;
74  UCHAR ReceivedByte;
75  ULONG Queue;
77  ULONG ButtonsDifference;
78  KIRQL OldIrql;
79  ULONG i;
80  ULONG Fcr;
81  ULONG BaudRate;
82  SERIAL_TIMEOUTS Timeouts;
86 
87  TRACE_(SERMOUSE, "SermouseDeviceWorker() called\n");
88 
89  DeviceExtension = (PSERMOUSE_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
90  LowerDevice = DeviceExtension->LowerDevice;
91  Zero.QuadPart = 0;
92  PacketBuffer = DeviceExtension->PacketBuffer;
93 
94  ASSERT(LowerDevice);
95 
96  /* Initialize device extension */
97  DeviceExtension->ActiveQueue = 0;
98  DeviceExtension->PacketBufferPosition = 0;
99  DeviceExtension->PreviousButtons = 0;
100 
101  /* Initialize serial port */
102  Fcr = 0;
104  &Fcr, sizeof(Fcr), NULL, NULL);
106  /* Set serial port speed */
107  BaudRate = DeviceExtension->AttributesInformation.SampleRate * 8;
109  &BaudRate, sizeof(BaudRate), NULL, NULL);
111  /* Set LCR */
112  LCR.WordLength = 7;
113  LCR.Parity = NO_PARITY;
114  LCR.StopBits = STOP_BIT_1;
116  &LCR, sizeof(LCR), NULL, NULL);
118 
119  /* Set timeouts */
121  Timeouts.ReadIntervalTimeout = 100;
124  &Timeouts, sizeof(Timeouts), NULL, NULL);
126 
127  /* main read loop */
129  while (TRUE)
130  {
132  &DeviceExtension->StopWorkerThreadEvent,
133  Executive,
134  KernelMode,
135  TRUE,
136  &Zero);
137  if (Status != STATUS_TIMEOUT)
138  {
139  /* we need to stop the worker thread */
140  KeClearEvent(&DeviceExtension->StopWorkerThreadEvent);
141  break;
142  }
143 
146  IRP_MJ_READ,
147  LowerDevice,
149  &Zero,
150  &event,
151  &ioStatus);
152  if (!Irp)
153  {
154  /* No memory actually, try later */
155  INFO_(SERMOUSE, "No memory actually, trying again\n");
157  continue;
158  }
159 
160  Status = IoCallDriver(LowerDevice, Irp);
161  if (Status == STATUS_PENDING)
162  {
164  Status = ioStatus.Status;
165  }
166 
167  if (!NT_SUCCESS(Status))
168  continue;
169 
170  /* Read all available data and process */
171  for (i = 0; i < ioStatus.Information; i++)
172  {
173  ReceivedByte = Buffer[i];
174  INFO_(SERMOUSE, "ReceivedByte 0x%02x\n", ReceivedByte);
175 
176  /* Synchronize */
177  if ((ReceivedByte & 0x40) == 0x40)
178  DeviceExtension->PacketBufferPosition = 0;
179 
180  PacketBuffer[DeviceExtension->PacketBufferPosition] = ReceivedByte & 0x7f;
181  DeviceExtension->PacketBufferPosition++;
182 
183  /* Process packet if complete */
184  if (DeviceExtension->PacketBufferPosition >= 3)
185  {
186  Queue = DeviceExtension->ActiveQueue % 2;
187 
188  /* Prevent buffer overflow */
189  if (DeviceExtension->InputDataCount[Queue] == 1)
190  continue;
191 
192  Input = &DeviceExtension->MouseInputData[Queue];
193 
194  if (DeviceExtension->PacketBufferPosition == 3)
195  {
196  /* Retrieve change in x and y from packet */
197  Input->LastX = (signed char)(PacketBuffer[1] | ((PacketBuffer[0] & 0x03) << 6));
198  Input->LastY = (signed char)(PacketBuffer[2] | ((PacketBuffer[0] & 0x0c) << 4));
199 
200  /* Determine the current state of the buttons */
201  Input->RawButtons = (DeviceExtension->PreviousButtons & MOUSE_BUTTON_MIDDLE) |
202  ((UCHAR)(PacketBuffer[0] & LEFT_BUTTON_MASK) >> LEFT_BUTTON_SHIFT) |
203  ((UCHAR)(PacketBuffer[0] & RIGHT_BUTTON_MASK) >> RIGHT_BUTTON_SHIFT);
204  }
205  else if (DeviceExtension->PacketBufferPosition == 4)
206  {
207  DeviceExtension->PacketBufferPosition = 0;
208  /* If middle button state changed than report event */
209  if (((UCHAR)(PacketBuffer[3] & MIDDLE_BUTTON_MASK) >> MIDDLE_BUTTON_SHIFT) ^
210  (DeviceExtension->PreviousButtons & MOUSE_BUTTON_MIDDLE))
211  {
212  Input->RawButtons ^= MOUSE_BUTTON_MIDDLE;
213  Input->LastX = 0;
214  Input->LastY = 0;
215  }
216  else
217  {
218  continue;
219  }
220  }
221 
222  /* Determine ButtonFlags */
223  Input->ButtonFlags = 0;
224  ButtonsDifference = DeviceExtension->PreviousButtons ^ Input->RawButtons;
225 
226  if (ButtonsDifference != 0)
227  {
228  if (ButtonsDifference & MOUSE_BUTTON_LEFT
229  && DeviceExtension->AttributesInformation.NumberOfButtons >= 1)
230  {
231  if (Input->RawButtons & MOUSE_BUTTON_LEFT)
232  Input->ButtonFlags |= MOUSE_LEFT_BUTTON_DOWN;
233  else
234  Input->ButtonFlags |= MOUSE_LEFT_BUTTON_UP;
235  }
236 
237  if (ButtonsDifference & MOUSE_BUTTON_RIGHT
238  && DeviceExtension->AttributesInformation.NumberOfButtons >= 2)
239  {
240  if (Input->RawButtons & MOUSE_BUTTON_RIGHT)
241  Input->ButtonFlags |= MOUSE_RIGHT_BUTTON_DOWN;
242  else
243  Input->ButtonFlags |= MOUSE_RIGHT_BUTTON_UP;
244  }
245 
246  if (ButtonsDifference & MOUSE_BUTTON_MIDDLE
247  && DeviceExtension->AttributesInformation.NumberOfButtons >= 3)
248  {
249  if (Input->RawButtons & MOUSE_BUTTON_MIDDLE)
250  Input->ButtonFlags |= MOUSE_MIDDLE_BUTTON_DOWN;
251  else
252  Input->ButtonFlags |= MOUSE_MIDDLE_BUTTON_UP;
253  }
254  }
255 
256  /* Send the Input data to the Mouse Class driver */
257  DeviceExtension->InputDataCount[Queue]++;
258 
260  InterlockedIncrement((PLONG)&DeviceExtension->ActiveQueue);
262  DeviceExtension->ConnectData.ClassDeviceObject,
263  &DeviceExtension->MouseInputData[Queue],
264  &DeviceExtension->MouseInputData[Queue] + 1,
265  &DeviceExtension->InputDataCount[Queue]);
267  DeviceExtension->InputDataCount[Queue] = 0;
268 
269  /* Copy RawButtons to Previous Buttons for Input */
270  DeviceExtension->PreviousButtons = Input->RawButtons;
271  }
272  }
273  }
274 
276 }
#define IN
Definition: typedefs.h:38
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define TRUE
Definition: types.h:120
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define RIGHT_BUTTON_MASK
Definition: sermouse.h:35
#define MOUSE_MIDDLE_BUTTON_DOWN
Definition: ntddmou.h:50
#define MOUSE_LEFT_BUTTON_DOWN
Definition: ntddmou.h:46
#define STOP_BIT_1
Definition: ntddser.h:215
#define INFO_(ch,...)
Definition: debug.h:159
#define MIDDLE_BUTTON_SHIFT
Definition: sermouse.h:41
IN PLARGE_INTEGER IN ULONG IN BOOLEAN IN ULONG IN BOOLEAN OUT PIO_STATUS_BLOCK IoStatus
Definition: fatprocs.h:2650
PIRP NTAPI IoBuildSynchronousFsdRequest(IN ULONG MajorFunction, IN PDEVICE_OBJECT DeviceObject, IN PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER StartingOffset, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:1069
#define IOCTL_SERIAL_SET_BAUD_RATE
Definition: ntddser.h:82
ULONG WriteTotalTimeoutConstant
Definition: ntddser.h:307
_In_ PIRP Irp
Definition: csq.h:116
#define IOCTL_SERIAL_SET_FIFO_CONTROL
Definition: ntddser.h:92
PDEVICE_OBJECT LowerDevice
Definition: sermouse.h:57
unsigned char * PUCHAR
Definition: retypes.h:3
ULONG ReadTotalTimeoutConstant
Definition: ntddser.h:305
LONG NTSTATUS
Definition: precomp.h:26
Definition: arc.h:84
struct _SERMOUSE_DEVICE_EXTENSION * PSERMOUSE_DEVICE_EXTENSION
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
CHAR InputBuffer[80]
Definition: conmgr.c:33
#define IOCTL_SERIAL_SET_LINE_CONTROL
Definition: ntddser.h:96
#define LEFT_BUTTON_SHIFT
Definition: sermouse.h:33
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
UCHAR KIRQL
Definition: env_spec_w32.h:591
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
VOID NTAPI SermouseDeviceWorker(PVOID Context)
Definition: readmouse.c:64
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:434
USHORT SampleRate
Definition: ntddmou.h:111
ULONG ReadTotalTimeoutMultiplier
Definition: ntddser.h:304
smooth NULL
Definition: ftsmooth.c:416
unsigned char
Definition: typeof.h:29
Definition: bufpool.h:45
_Must_inspect_result_ __drv_aliasesMem _In_ PDEVICE_OBJECT _In_opt_ PVOID _In_ ULONG _Out_opt_ PVOID OutputBuffer
Definition: iofuncs.h:713
static NTSTATUS SermouseDeviceIoControl(IN PDEVICE_OBJECT DeviceObject, IN ULONG CtlCode, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferSize, IN OUT PVOID OutputBuffer OPTIONAL, IN OUT PULONG OutputBufferSize)
Definition: readmouse.c:16
#define TRACE_(x)
Definition: compat.h:66
ULONG WriteTotalTimeoutMultiplier
Definition: ntddser.h:306
#define RIGHT_BUTTON_SHIFT
Definition: sermouse.h:37
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
ULONG ReadIntervalTimeout
Definition: ntddser.h:303
MOUSE_ATTRIBUTES AttributesInformation
Definition: sermouse.h:72
#define MOUSE_LEFT_BUTTON_UP
Definition: ntddmou.h:47
#define MOUSE_MIDDLE_BUTTON_UP
Definition: ntddmou.h:51
#define LCR
Definition: serial_port.h:65
#define MOUSE_RIGHT_BUTTON_DOWN
Definition: ntddmou.h:48
#define PACKET_BUFFER_SIZE
Definition: sermouse.h:28
PVOID ClassService
Definition: kbdmou.h:82
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
unsigned char UCHAR
Definition: xmlstorage.h:181
VOID(STDAPICALLTYPE * PSERVICE_CALLBACK_ROUTINE)(IN PVOID NormalContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2, IN OUT PVOID SystemArgument3)
Definition: kbdmou.h:86
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
struct _cl_event * event
Definition: glext.h:7739
UCHAR PacketBuffer[PACKET_BUFFER_SIZE]
Definition: sermouse.h:69
Status
Definition: gdiplustypes.h:24
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
#define NO_PARITY
Definition: serial.c:89
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define InterlockedIncrement
Definition: armddk.h:53
NTSTATUS NTAPI PsTerminateSystemThread(IN NTSTATUS ExitStatus)
Definition: kill.c:1144
unsigned int * PULONG
Definition: retypes.h:1
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
IN PVCB IN VBO IN ULONG OUT PBCB OUT PVOID IN BOOLEAN IN BOOLEAN Zero
Definition: fatprocs.h:402
PIRP NTAPI IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:881
#define IRP_MJ_READ
Definition: rdpdr.c:46
MOUSE_INPUT_DATA MouseInputData[2]
Definition: sermouse.h:68
#define OUT
Definition: typedefs.h:39
#define MIDDLE_BUTTON_MASK
Definition: sermouse.h:39
struct tagContext Context
Definition: acpixf.h:1012
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define MOUSE_RIGHT_BUTTON_UP
Definition: ntddmou.h:49
#define LEFT_BUTTON_MASK
Definition: sermouse.h:31
CONNECT_DATA ConnectData
Definition: sermouse.h:67
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
return STATUS_SUCCESS
Definition: btrfs.c:2725
signed int * PLONG
Definition: retypes.h:5
USHORT NumberOfButtons
Definition: ntddmou.h:110
#define WARN_(ch,...)
Definition: debug.h:157
VOID NTAPI KeStallExecutionProcessor(IN ULONG MicroSeconds)
Definition: ntoskrnl.c:99
#define IOCTL_SERIAL_SET_TIMEOUTS
Definition: ntddser.h:104
PDEVICE_OBJECT ClassDeviceObject
Definition: kbdmou.h:81
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68