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

Definition at line 62 of file readmouse.c.

Referenced by SermouseStartDevice().

{
    PSERMOUSE_DEVICE_EXTENSION DeviceExtension;
    PDEVICE_OBJECT LowerDevice;
    UCHAR Buffer[PACKET_BUFFER_SIZE];
    PIRP Irp;
    IO_STATUS_BLOCK ioStatus;
    KEVENT event;
    PUCHAR PacketBuffer;
    UCHAR ReceivedByte;
    ULONG Queue;
    PMOUSE_INPUT_DATA Input;
    ULONG ButtonsDifference;
    KIRQL OldIrql;
    ULONG i;
    ULONG Fcr;
    ULONG BaudRate;
    SERIAL_TIMEOUTS Timeouts;
    SERIAL_LINE_CONTROL LCR;
    LARGE_INTEGER Zero;
    NTSTATUS Status;

    TRACE_(SERMOUSE, "SermouseDeviceWorker() called\n");

    DeviceExtension = (PSERMOUSE_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
    LowerDevice = DeviceExtension->LowerDevice;
    Zero.QuadPart = 0;
    PacketBuffer = DeviceExtension->PacketBuffer;

    ASSERT(LowerDevice);

    /* Initialize device extension */
    DeviceExtension->ActiveQueue = 0;
    DeviceExtension->PacketBufferPosition = 0;
    DeviceExtension->PreviousButtons = 0;

    /* Initialize serial port */
    Fcr = 0;
    Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_FIFO_CONTROL,
        &Fcr, sizeof(Fcr), NULL, NULL);
    if (!NT_SUCCESS(Status)) PsTerminateSystemThread(Status);
    /* Set serial port speed */
    BaudRate = DeviceExtension->AttributesInformation.SampleRate * 8;
    Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_BAUD_RATE,
        &BaudRate, sizeof(BaudRate), NULL, NULL);
    if (!NT_SUCCESS(Status)) PsTerminateSystemThread(Status);
    /* Set LCR */
    LCR.WordLength = 7;
    LCR.Parity = NO_PARITY;
    LCR.StopBits = STOP_BIT_1;
    Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_LINE_CONTROL,
        &LCR, sizeof(LCR), NULL, NULL);
    if (!NT_SUCCESS(Status)) PsTerminateSystemThread(Status);

    /* Set timeouts */
    Timeouts.ReadTotalTimeoutConstant = Timeouts.ReadTotalTimeoutMultiplier = 0;
    Timeouts.ReadIntervalTimeout = 100;
    Timeouts.WriteTotalTimeoutMultiplier = Timeouts.WriteTotalTimeoutConstant = 0;
    Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_TIMEOUTS,
        &Timeouts, sizeof(Timeouts), NULL, NULL);
    if (!NT_SUCCESS(Status)) PsTerminateSystemThread(Status);

    /* main read loop */
    RtlZeroMemory(Buffer, PACKET_BUFFER_SIZE);
    while (TRUE)
    {
        Status = KeWaitForSingleObject(
            &DeviceExtension->StopWorkerThreadEvent,
            Executive,
            KernelMode,
            TRUE,
            &Zero);
        if (Status != STATUS_TIMEOUT)
        {
            /* we need to stop the worker thread */
            KeResetEvent(&DeviceExtension->StopWorkerThreadEvent);
            break;
        }

        KeInitializeEvent(&event, NotificationEvent, FALSE);
        Irp = IoBuildSynchronousFsdRequest(
            IRP_MJ_READ,
            LowerDevice,
            Buffer, PACKET_BUFFER_SIZE,
            &Zero,
            &event,
            &ioStatus);
        if (!Irp)
        {
            /* No memory actually, try later */
            INFO_(SERMOUSE, "No memory actually, trying again\n");
            KeStallExecutionProcessor(10);
            continue;
        }

        Status = IoCallDriver(LowerDevice, Irp);
        if (Status == STATUS_PENDING)
        {
            KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
            Status = ioStatus.Status;
        }

        if (!NT_SUCCESS(Status))
            continue;

        /* Read all available data and process */
        for (i = 0; i < ioStatus.Information; i++)
        {
            ReceivedByte = Buffer[i];
            INFO_(SERMOUSE, "ReceivedByte 0x%02x\n", ReceivedByte);

            /* Synchronize */
            if ((ReceivedByte & 0x40) == 0x40)
                DeviceExtension->PacketBufferPosition = 0;

            PacketBuffer[DeviceExtension->PacketBufferPosition] = ReceivedByte & 0x7f;
            DeviceExtension->PacketBufferPosition++;

            /* Process packet if complete */
            if (DeviceExtension->PacketBufferPosition >= 3)
            {
                Queue = DeviceExtension->ActiveQueue % 2;

                /* Prevent buffer overflow */
                if (DeviceExtension->InputDataCount[Queue] == 1)
                    continue;

                Input = &DeviceExtension->MouseInputData[Queue];

                if (DeviceExtension->PacketBufferPosition == 3)
                {
                    /* Retrieve change in x and y from packet */
                    Input->LastX = (signed char)(PacketBuffer[1] | ((PacketBuffer[0] & 0x03) << 6));
                    Input->LastY = (signed char)(PacketBuffer[2] | ((PacketBuffer[0] & 0x0c) << 4));

                    /* Determine the current state of the buttons */
                    Input->RawButtons = (DeviceExtension->PreviousButtons & MOUSE_BUTTON_MIDDLE) |
                        ((UCHAR)(PacketBuffer[0] & LEFT_BUTTON_MASK) >> LEFT_BUTTON_SHIFT) |
                        ((UCHAR)(PacketBuffer[0] & RIGHT_BUTTON_MASK) >> RIGHT_BUTTON_SHIFT);
                }
                else if (DeviceExtension->PacketBufferPosition == 4)
                {
                    DeviceExtension->PacketBufferPosition = 0;
                    /* If middle button state changed than report event */
                    if (((UCHAR)(PacketBuffer[3] & MIDDLE_BUTTON_MASK) >> MIDDLE_BUTTON_SHIFT) ^
                        (DeviceExtension->PreviousButtons & MOUSE_BUTTON_MIDDLE))
                    {
                        Input->RawButtons ^= MOUSE_BUTTON_MIDDLE;
                        Input->LastX = 0;
                        Input->LastY = 0;
                    }
                    else
                    {
                        continue;
                    }
                }

                /* Determine ButtonFlags */
                Input->ButtonFlags = 0;
                ButtonsDifference = DeviceExtension->PreviousButtons ^ Input->RawButtons;

                if (ButtonsDifference != 0)
                {
                    if (ButtonsDifference & MOUSE_BUTTON_LEFT
                        && DeviceExtension->AttributesInformation.NumberOfButtons >= 1)
                    {
                        if (Input->RawButtons & MOUSE_BUTTON_LEFT)
                            Input->ButtonFlags |= MOUSE_LEFT_BUTTON_DOWN;
                        else
                            Input->ButtonFlags |= MOUSE_LEFT_BUTTON_UP;
                    }

                    if (ButtonsDifference & MOUSE_BUTTON_RIGHT
                        && DeviceExtension->AttributesInformation.NumberOfButtons >= 2)
                    {
                        if (Input->RawButtons & MOUSE_BUTTON_RIGHT)
                            Input->ButtonFlags |= MOUSE_RIGHT_BUTTON_DOWN;
                        else
                            Input->ButtonFlags |= MOUSE_RIGHT_BUTTON_UP;
                    }

                    if (ButtonsDifference & MOUSE_BUTTON_MIDDLE
                        && DeviceExtension->AttributesInformation.NumberOfButtons >= 3)
                    {
                        if (Input->RawButtons & MOUSE_BUTTON_MIDDLE)
                            Input->ButtonFlags |= MOUSE_MIDDLE_BUTTON_DOWN;
                        else
                            Input->ButtonFlags |= MOUSE_MIDDLE_BUTTON_UP;
                    }
                }

                /* Send the Input data to the Mouse Class driver */
                DeviceExtension->InputDataCount[Queue]++;

                KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
                InterlockedIncrement((PLONG)&DeviceExtension->ActiveQueue);
                (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ConnectData.ClassService)(
                    DeviceExtension->ConnectData.ClassDeviceObject,
                    &DeviceExtension->MouseInputData[Queue],
                    &DeviceExtension->MouseInputData[Queue] + 1,
                    &DeviceExtension->InputDataCount[Queue]);
                KeLowerIrql(OldIrql);
                DeviceExtension->InputDataCount[Queue] = 0;

                /* Copy RawButtons to Previous Buttons for Input */
                DeviceExtension->PreviousButtons = Input->RawButtons;
            }
        }
    }

    PsTerminateSystemThread(STATUS_SUCCESS);
}

Generated on Thu May 24 2012 05:24:07 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.