Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenreadmouse.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Serial mouse driver 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: drivers/input/sermouse/fdo.c 00005 * PURPOSE: Read mouse moves and send them to mouclass 00006 * PROGRAMMERS: Copyright Jason Filby (jasonfilby@yahoo.com) 00007 Copyright Filip Navara (xnavara@volny.cz) 00008 Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org) 00009 */ 00010 00011 #include "sermouse.h" 00012 00013 static NTSTATUS 00014 SermouseDeviceIoControl( 00015 IN PDEVICE_OBJECT DeviceObject, 00016 IN ULONG CtlCode, 00017 IN PVOID InputBuffer OPTIONAL, 00018 IN ULONG InputBufferSize, 00019 IN OUT PVOID OutputBuffer OPTIONAL, 00020 IN OUT PULONG OutputBufferSize) 00021 { 00022 KEVENT Event; 00023 PIRP Irp; 00024 IO_STATUS_BLOCK IoStatus; 00025 NTSTATUS Status; 00026 00027 KeInitializeEvent(&Event, NotificationEvent, FALSE); 00028 00029 Irp = IoBuildDeviceIoControlRequest(CtlCode, 00030 DeviceObject, 00031 InputBuffer, 00032 InputBufferSize, 00033 OutputBuffer, 00034 (OutputBufferSize) ? *OutputBufferSize : 0, 00035 FALSE, 00036 &Event, 00037 &IoStatus); 00038 if (Irp == NULL) 00039 { 00040 WARN_(SERMOUSE, "IoBuildDeviceIoControlRequest() failed\n"); 00041 return STATUS_INSUFFICIENT_RESOURCES; 00042 } 00043 00044 Status = IoCallDriver(DeviceObject, Irp); 00045 00046 if (Status == STATUS_PENDING) 00047 { 00048 INFO_(SERMOUSE, "Operation pending\n"); 00049 KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); 00050 Status = IoStatus.Status; 00051 } 00052 00053 if (OutputBufferSize) 00054 { 00055 *OutputBufferSize = (ULONG)IoStatus.Information; 00056 } 00057 00058 return Status; 00059 } 00060 00061 VOID NTAPI 00062 SermouseDeviceWorker( 00063 PVOID Context) 00064 { 00065 PSERMOUSE_DEVICE_EXTENSION DeviceExtension; 00066 PDEVICE_OBJECT LowerDevice; 00067 UCHAR Buffer[PACKET_BUFFER_SIZE]; 00068 PIRP Irp; 00069 IO_STATUS_BLOCK ioStatus; 00070 KEVENT event; 00071 PUCHAR PacketBuffer; 00072 UCHAR ReceivedByte; 00073 ULONG Queue; 00074 PMOUSE_INPUT_DATA Input; 00075 ULONG ButtonsDifference; 00076 KIRQL OldIrql; 00077 ULONG i; 00078 ULONG Fcr; 00079 ULONG BaudRate; 00080 SERIAL_TIMEOUTS Timeouts; 00081 SERIAL_LINE_CONTROL LCR; 00082 LARGE_INTEGER Zero; 00083 NTSTATUS Status; 00084 00085 TRACE_(SERMOUSE, "SermouseDeviceWorker() called\n"); 00086 00087 DeviceExtension = (PSERMOUSE_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension; 00088 LowerDevice = DeviceExtension->LowerDevice; 00089 Zero.QuadPart = 0; 00090 PacketBuffer = DeviceExtension->PacketBuffer; 00091 00092 ASSERT(LowerDevice); 00093 00094 /* Initialize device extension */ 00095 DeviceExtension->ActiveQueue = 0; 00096 DeviceExtension->PacketBufferPosition = 0; 00097 DeviceExtension->PreviousButtons = 0; 00098 00099 /* Initialize serial port */ 00100 Fcr = 0; 00101 Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_FIFO_CONTROL, 00102 &Fcr, sizeof(Fcr), NULL, NULL); 00103 if (!NT_SUCCESS(Status)) PsTerminateSystemThread(Status); 00104 /* Set serial port speed */ 00105 BaudRate = DeviceExtension->AttributesInformation.SampleRate * 8; 00106 Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_BAUD_RATE, 00107 &BaudRate, sizeof(BaudRate), NULL, NULL); 00108 if (!NT_SUCCESS(Status)) PsTerminateSystemThread(Status); 00109 /* Set LCR */ 00110 LCR.WordLength = 7; 00111 LCR.Parity = NO_PARITY; 00112 LCR.StopBits = STOP_BIT_1; 00113 Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_LINE_CONTROL, 00114 &LCR, sizeof(LCR), NULL, NULL); 00115 if (!NT_SUCCESS(Status)) PsTerminateSystemThread(Status); 00116 00117 /* Set timeouts */ 00118 Timeouts.ReadTotalTimeoutConstant = Timeouts.ReadTotalTimeoutMultiplier = 0; 00119 Timeouts.ReadIntervalTimeout = 100; 00120 Timeouts.WriteTotalTimeoutMultiplier = Timeouts.WriteTotalTimeoutConstant = 0; 00121 Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_TIMEOUTS, 00122 &Timeouts, sizeof(Timeouts), NULL, NULL); 00123 if (!NT_SUCCESS(Status)) PsTerminateSystemThread(Status); 00124 00125 /* main read loop */ 00126 RtlZeroMemory(Buffer, PACKET_BUFFER_SIZE); 00127 while (TRUE) 00128 { 00129 Status = KeWaitForSingleObject( 00130 &DeviceExtension->StopWorkerThreadEvent, 00131 Executive, 00132 KernelMode, 00133 TRUE, 00134 &Zero); 00135 if (Status != STATUS_TIMEOUT) 00136 { 00137 /* we need to stop the worker thread */ 00138 KeResetEvent(&DeviceExtension->StopWorkerThreadEvent); 00139 break; 00140 } 00141 00142 KeInitializeEvent(&event, NotificationEvent, FALSE); 00143 Irp = IoBuildSynchronousFsdRequest( 00144 IRP_MJ_READ, 00145 LowerDevice, 00146 Buffer, PACKET_BUFFER_SIZE, 00147 &Zero, 00148 &event, 00149 &ioStatus); 00150 if (!Irp) 00151 { 00152 /* No memory actually, try later */ 00153 INFO_(SERMOUSE, "No memory actually, trying again\n"); 00154 KeStallExecutionProcessor(10); 00155 continue; 00156 } 00157 00158 Status = IoCallDriver(LowerDevice, Irp); 00159 if (Status == STATUS_PENDING) 00160 { 00161 KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL); 00162 Status = ioStatus.Status; 00163 } 00164 00165 if (!NT_SUCCESS(Status)) 00166 continue; 00167 00168 /* Read all available data and process */ 00169 for (i = 0; i < ioStatus.Information; i++) 00170 { 00171 ReceivedByte = Buffer[i]; 00172 INFO_(SERMOUSE, "ReceivedByte 0x%02x\n", ReceivedByte); 00173 00174 /* Synchronize */ 00175 if ((ReceivedByte & 0x40) == 0x40) 00176 DeviceExtension->PacketBufferPosition = 0; 00177 00178 PacketBuffer[DeviceExtension->PacketBufferPosition] = ReceivedByte & 0x7f; 00179 DeviceExtension->PacketBufferPosition++; 00180 00181 /* Process packet if complete */ 00182 if (DeviceExtension->PacketBufferPosition >= 3) 00183 { 00184 Queue = DeviceExtension->ActiveQueue % 2; 00185 00186 /* Prevent buffer overflow */ 00187 if (DeviceExtension->InputDataCount[Queue] == 1) 00188 continue; 00189 00190 Input = &DeviceExtension->MouseInputData[Queue]; 00191 00192 if (DeviceExtension->PacketBufferPosition == 3) 00193 { 00194 /* Retrieve change in x and y from packet */ 00195 Input->LastX = (signed char)(PacketBuffer[1] | ((PacketBuffer[0] & 0x03) << 6)); 00196 Input->LastY = (signed char)(PacketBuffer[2] | ((PacketBuffer[0] & 0x0c) << 4)); 00197 00198 /* Determine the current state of the buttons */ 00199 Input->RawButtons = (DeviceExtension->PreviousButtons & MOUSE_BUTTON_MIDDLE) | 00200 ((UCHAR)(PacketBuffer[0] & LEFT_BUTTON_MASK) >> LEFT_BUTTON_SHIFT) | 00201 ((UCHAR)(PacketBuffer[0] & RIGHT_BUTTON_MASK) >> RIGHT_BUTTON_SHIFT); 00202 } 00203 else if (DeviceExtension->PacketBufferPosition == 4) 00204 { 00205 DeviceExtension->PacketBufferPosition = 0; 00206 /* If middle button state changed than report event */ 00207 if (((UCHAR)(PacketBuffer[3] & MIDDLE_BUTTON_MASK) >> MIDDLE_BUTTON_SHIFT) ^ 00208 (DeviceExtension->PreviousButtons & MOUSE_BUTTON_MIDDLE)) 00209 { 00210 Input->RawButtons ^= MOUSE_BUTTON_MIDDLE; 00211 Input->LastX = 0; 00212 Input->LastY = 0; 00213 } 00214 else 00215 { 00216 continue; 00217 } 00218 } 00219 00220 /* Determine ButtonFlags */ 00221 Input->ButtonFlags = 0; 00222 ButtonsDifference = DeviceExtension->PreviousButtons ^ Input->RawButtons; 00223 00224 if (ButtonsDifference != 0) 00225 { 00226 if (ButtonsDifference & MOUSE_BUTTON_LEFT 00227 && DeviceExtension->AttributesInformation.NumberOfButtons >= 1) 00228 { 00229 if (Input->RawButtons & MOUSE_BUTTON_LEFT) 00230 Input->ButtonFlags |= MOUSE_LEFT_BUTTON_DOWN; 00231 else 00232 Input->ButtonFlags |= MOUSE_LEFT_BUTTON_UP; 00233 } 00234 00235 if (ButtonsDifference & MOUSE_BUTTON_RIGHT 00236 && DeviceExtension->AttributesInformation.NumberOfButtons >= 2) 00237 { 00238 if (Input->RawButtons & MOUSE_BUTTON_RIGHT) 00239 Input->ButtonFlags |= MOUSE_RIGHT_BUTTON_DOWN; 00240 else 00241 Input->ButtonFlags |= MOUSE_RIGHT_BUTTON_UP; 00242 } 00243 00244 if (ButtonsDifference & MOUSE_BUTTON_MIDDLE 00245 && DeviceExtension->AttributesInformation.NumberOfButtons >= 3) 00246 { 00247 if (Input->RawButtons & MOUSE_BUTTON_MIDDLE) 00248 Input->ButtonFlags |= MOUSE_MIDDLE_BUTTON_DOWN; 00249 else 00250 Input->ButtonFlags |= MOUSE_MIDDLE_BUTTON_UP; 00251 } 00252 } 00253 00254 /* Send the Input data to the Mouse Class driver */ 00255 DeviceExtension->InputDataCount[Queue]++; 00256 00257 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 00258 InterlockedIncrement((PLONG)&DeviceExtension->ActiveQueue); 00259 (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ConnectData.ClassService)( 00260 DeviceExtension->ConnectData.ClassDeviceObject, 00261 &DeviceExtension->MouseInputData[Queue], 00262 &DeviceExtension->MouseInputData[Queue] + 1, 00263 &DeviceExtension->InputDataCount[Queue]); 00264 KeLowerIrql(OldIrql); 00265 DeviceExtension->InputDataCount[Queue] = 0; 00266 00267 /* Copy RawButtons to Previous Buttons for Input */ 00268 DeviceExtension->PreviousButtons = Input->RawButtons; 00269 } 00270 } 00271 } 00272 00273 PsTerminateSystemThread(STATUS_SUCCESS); 00274 } Generated on Thu May 24 2012 04:28:20 for ReactOS by
1.7.6.1
|