ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

readmouse.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.