Пример #1
0
static VOID MouseDispatchPacket(PMOUSE_PACKET Packet)
{
    PS2QueuePush(MousePS2Port, Packet->Flags);
    PS2QueuePush(MousePS2Port, Packet->HorzCounter);
    PS2QueuePush(MousePS2Port, Packet->VertCounter);
    if (MouseId >= 3) PS2QueuePush(MousePS2Port, Packet->Extra);
}
Пример #2
0
VOID KeyboardEventHandler(PKEY_EVENT_RECORD KeyEvent)
{
    WORD i;
    BYTE ScanCode = (BYTE)KeyEvent->wVirtualScanCode;

    /* Check if we're not reporting */
    if (!Reporting) return;

    /* If this is a key release, set the highest bit in the scan code */
    if (!KeyEvent->bKeyDown) ScanCode |= 0x80;

    /* Push the scan code into the PS/2 queue */
    for (i = 0; i < KeyEvent->wRepeatCount; i++)
    {
        if (KeyEvent->dwControlKeyState & ENHANCED_KEY) PS2QueuePush(PS2Port, 0xE0);
        PS2QueuePush(PS2Port, ScanCode);
    }

    DPRINT("Press 0x%X\n", ScanCode);
}
Пример #3
0
static VOID WINAPI PS2WritePort(ULONG Port, BYTE Data)
{
    if (Port == PS2_CONTROL_PORT)
    {
        switch (Data)
        {
        /* Read configuration byte */
        case 0x20:
        {
            OutputBuffer = ControllerConfig;
            StatusRegister |= (1 << 0); // There is something to read
            break;
        }

        /* Write configuration byte */
        case 0x60:
        /* Write controller output port */
        case 0xD1:
        /* Write to the first PS/2 port output buffer */
        case 0xD2:
        /* Write to the second PS/2 port output buffer */
        case 0xD3:
        /* Write to the second PS/2 port input buffer */
        case 0xD4:
        {
            /* These commands require a response */
            ControllerCommand = Data;
            StatusRegister |= (1 << 3); // This is a controller command
            break;
        }

        /* Disable second PS/2 port */
        case 0xA7:
        {
            Ports[1].IsEnabled = FALSE;
            break;
        }

        /* Enable second PS/2 port */
        case 0xA8:
        {
            Ports[1].IsEnabled = TRUE;
            break;
        }

        /* Test second PS/2 port */
        case 0xA9:
        {
            OutputBuffer = 0x00; // Success code
            StatusRegister |= (1 << 0); // There is something to read
            break;
        }

        /* Test PS/2 controller */
        case 0xAA:
        {
            OutputBuffer = 0x55; // Success code
            StatusRegister |= (1 << 0); // There is something to read
            break;
        }

        /* Test first PS/2 port */
        case 0xAB:
        {
            OutputBuffer = 0x00; // Success code
            StatusRegister |= (1 << 0); // There is something to read
            break;
        }

        /* Disable first PS/2 port */
        case 0xAD:
        {
            Ports[0].IsEnabled = FALSE;
            break;
        }

        /* Enable first PS/2 port */
        case 0xAE:
        {
            Ports[0].IsEnabled = TRUE;
            break;
        }

        /* Read controller output port */
        case 0xD0:
        {
            // TODO: Not implemented
            break;
        }

        /* CPU Reset */
        case 0xF0:
        case 0xF2:
        case 0xF4:
        case 0xF6:
        case 0xF8:
        case 0xFA:
        case 0xFC:
        case 0xFE:
        {
            /* Stop the VDM */
            EmulatorTerminate();
            break;
        }
        }
    }
    else if (Port == PS2_DATA_PORT)
    {
        /* Check if the controller is waiting for a response */
        if (StatusRegister & (1 << 3)) // If we have data for the controller
        {
            StatusRegister &= ~(1 << 3);

            /* Check which command it was */
            switch (ControllerCommand)
            {
            /* Write configuration byte */
            case 0x60:
            {
                ControllerConfig = Data;
                break;
            }

            /* Write controller output */
            case 0xD1:
            {
                /* Check if bit 0 is unset */
                if (!(Data & (1 << 0)))
                {
                    /* CPU disabled - Stop the VDM */
                    EmulatorTerminate();
                }

                /* Update the A20 line setting */
                EmulatorSetA20(Data & (1 << 1));

                break;
            }

            /* Push the data byte into the first PS/2 port queue */
            case 0xD2:
            {
                PS2QueuePush(0, Data);
                break;
            }

            /* Push the data byte into the second PS/2 port queue */
            case 0xD3:
            {
                PS2QueuePush(1, Data);
                break;
            }

            /*
             * Send a command to the second PS/2 port (by default
             * it is a command for the first PS/2 port)
             */
            case 0xD4:
            {
                PS2SendCommand(&Ports[1], Data);
                break;
            }
            }

            return;
        }

        /* By default, send a command to the first PS/2 port */
        PS2SendCommand(&Ports[0], Data);
    }
}
Пример #4
0
static VOID WINAPI KeyboardCommand(LPVOID Param, BYTE Command)
{
    /* Check if we were waiting for a data byte */
    if (DataByteWait)
    {
        PS2QueuePush(PS2Port, KEYBOARD_ACK);

        switch (DataByteWait)
        {
            /* Set/Reset Mode Indicators */
            case 0xED:
            {
                // Ignore setting the keyboard LEDs
                break;
            }

            /* PS/2 Select/Read Alternate Scan Code Sets */
            case 0xF0:
            /* Set Typematic Rate/Delay */
            case 0xF3:
            {
                // FIXME: UNIMPLEMENTED; just return ACKnowledge.
                // This unblocks some programs that want to initialize
                // the keyboard by sending keyboard commands and then
                // performing polling on the port until "valid" data
                // comes out.
                DPRINT1("KeyboardCommand(0x%02X) NOT IMPLEMENTED\n", DataByteWait);
                break;
            }

            default:
            {
                /* Shouldn't happen */
                ASSERT(FALSE);
            }
        }

        DataByteWait = 0;
        return;
    }

    switch (Command)
    {
        /* Set/Reset Mode Indicators */
        case 0xED:
        /* PS/2 Select/Read Alternate Scan Code Sets */
        case 0xF0:
        /* Set Typematic Rate/Delay */
        case 0xF3:
        {
            DataByteWait = Command;
            PS2QueuePush(PS2Port, KEYBOARD_ACK);
            break;
        }

        /* Echo test command */
        case 0xEE:
        {
            PS2QueuePush(PS2Port, 0xEE);
            break;
        }

        /* Get Keyboard ID */
        case 0xF2:
        {
            PS2QueuePush(PS2Port, KEYBOARD_ACK);
            PS2QueuePush(PS2Port, KeyboardId);
            break;
        }

        /* Enable Reporting */
        case 0xF4:
        {
            Reporting = TRUE;
            PS2QueuePush(PS2Port, KEYBOARD_ACK);
            break;
        }

        /* Disable Reporting */
        case 0xF5:
        {
            Reporting = FALSE;
            PS2QueuePush(PS2Port, KEYBOARD_ACK);
            break;
        }

        /* Set Defaults */
        case 0xF6:
        {
            // So far, nothing to reset
            PS2QueuePush(PS2Port, KEYBOARD_ACK);
            break;
        }

        /* PS/2 Typematic & Make/Break key modes */
        case 0xF7: case 0xF8: case 0xF9:
        case 0xFA: case 0xFB: case 0xFC: case 0xFD:
        {
            /*
             * Unsupported on PC-AT, they are just ignored
             * and acknowledged as discussed in:
             * http://stanislavs.org/helppc/keyboard_commands.html
             */
            PS2QueuePush(PS2Port, KEYBOARD_ACK);
        }

        /* Resend */
        case 0xFE:
        {
            PS2QueuePush(PS2Port, KEYBOARD_ACK);
            UNIMPLEMENTED;
            break;
        }

        /* Reset */
        case 0xFF:
        {
            /* Send ACKnowledge */
            PS2QueuePush(PS2Port, KEYBOARD_ACK);

            // So far, nothing to reset

            /* Send the Basic Assurance Test success code and the device ID */
            PS2QueuePush(PS2Port, KEYBOARD_BAT_SUCCESS);
            PS2QueuePush(PS2Port, KeyboardId);
            break;
        }

        /* Unknown command */
        default:
        {
            PS2QueuePush(PS2Port, KEYBOARD_ERROR);
        }
    }
}
Пример #5
0
static VOID WINAPI MouseCommand(LPVOID Param, BYTE Command)
{
    /* Check if we were waiting for a data byte */
    if (MouseDataByteWait)
    {
        PS2QueuePush(MousePS2Port, MOUSE_ACK);

        switch (MouseDataByteWait)
        {
            /* Set Resolution */
            case 0xE8:
            {
                Resolution = Command;
                break;
            }

            /* Set Sample Rate */
            case 0xF3:
            {
                /* Check for the scroll wheel enabling sequence */
                if (MouseId == 0)
                {
                    if (Command == ScrollMagic[ScrollMagicCounter])
                    {
                        ScrollMagicCounter++;
                        if (ScrollMagicCounter == 3) MouseId = 3;
                    }
                    else
                    {
                        ScrollMagicCounter = 0;
                    }
                }

                /* Check for the 5-button enabling sequence */
                if (MouseId == 3)
                {
                    if (Command == ExtraButtonMagic[ExtraButtonMagicCounter])
                    {
                        ExtraButtonMagicCounter++;
                        if (ExtraButtonMagicCounter == 3) MouseId = 4;
                    }
                    else
                    {
                        ExtraButtonMagicCounter = 0;
                    }
                }

                MouseCycles = 1000 / (UINT)Command;
                break;
            }

            default:
            {
                /* Shouldn't happen */
                ASSERT(FALSE);
            }
        }

        MouseDataByteWait = 0;
        return;
    }

    /* Check if we're in wrap mode */
    if (Mode == MOUSE_WRAP_MODE)
    {
        /*
         * In this mode, we just echo whatever byte we get,
         * except for the 0xEC and 0xFF commands.
         */
        if (Command != 0xEC && Command != 0xFF)
        {
            PS2QueuePush(MousePS2Port, Command);
            return;
        }
    }

    switch (Command)
    {
        /* Set 1:1 Scaling */
        case 0xE6:
        {
            Scaling = FALSE;
            PS2QueuePush(MousePS2Port, MOUSE_ACK);
            break;
        }

        /* Set 2:1 Scaling */
        case 0xE7:
        {
            Scaling = TRUE;
            PS2QueuePush(MousePS2Port, MOUSE_ACK);
            break;
        }

        /* Set Resolution */
        case 0xE8:
        /* Set Sample Rate */
        case 0xF3:
        {
            MouseDataByteWait = Command;
            PS2QueuePush(MousePS2Port, MOUSE_ACK);
            break;
        }

        /* Read Status */
        case 0xE9:
        {
            BYTE Status = ButtonState & 7;

            if (Scaling)   Status |= 1 << 4;
            if (MouseReporting) Status |= 1 << 5;
            if (Mode == MOUSE_REMOTE_MODE) Status |= 1 << 6;

            PS2QueuePush(MousePS2Port, MOUSE_ACK);
            PS2QueuePush(MousePS2Port, Status);
            PS2QueuePush(MousePS2Port, Resolution);
            PS2QueuePush(MousePS2Port, (BYTE)(1000 / MouseCycles));
            break;
        }

        /* Enter Streaming Mode */
        case 0xEA:
        {
            MouseResetCounters();
            Mode = MOUSE_STREAMING_MODE;

            PS2QueuePush(MousePS2Port, MOUSE_ACK);
            break;
        }

        /* Read Packet */
        case 0xEB:
        {
            PS2QueuePush(MousePS2Port, MOUSE_ACK);
            MouseGetPacket(&LastPacket);
            MouseDispatchPacket(&LastPacket);
            break;
        }

        /* Return from Wrap Mode */
        case 0xEC:
        {
            if (Mode == MOUSE_WRAP_MODE)
            {
                /* Restore the previous mode */
                MouseResetCounters();
                Mode = PreviousMode;
                PS2QueuePush(MousePS2Port, MOUSE_ACK);
            }
            else
            {
                PS2QueuePush(MousePS2Port, MOUSE_ERROR);
            }

            break;
        }

        /* Enter Wrap Mode */
        case 0xEE:
        {
            if (Mode != MOUSE_WRAP_MODE)
            {
                /* Save the previous mode */
                PreviousMode = Mode;
            }

            MouseResetCounters();
            Mode = MOUSE_WRAP_MODE;

            PS2QueuePush(MousePS2Port, MOUSE_ACK);
            break;
        }

        /* Enter Remote Mode */
        case 0xF0:
        {
            MouseResetCounters();
            Mode = MOUSE_REMOTE_MODE;

            PS2QueuePush(MousePS2Port, MOUSE_ACK);
            break;
        }

        /* Get Mouse ID */
        case 0xF2:
        {
            PS2QueuePush(MousePS2Port, MOUSE_ACK);
            PS2QueuePush(MousePS2Port, MouseId);
            break;
        }

        /* Enable Reporting */
        case 0xF4:
        {
            MouseReporting = TRUE;
            MouseResetCounters();
            PS2QueuePush(MousePS2Port, MOUSE_ACK);
            break;
        }

        /* Disable Reporting */
        case 0xF5:
        {
            MouseReporting = FALSE;
            MouseResetCounters();
            PS2QueuePush(MousePS2Port, MOUSE_ACK);
            break;
        }

        /* Set Defaults */
        case 0xF6:
        {
            /* Reset the configuration and counters */
            MouseResetConfig();
            MouseResetCounters();
            PS2QueuePush(MousePS2Port, MOUSE_ACK);
            break;
        }

        /* Resend */
        case 0xFE:
        {
            PS2QueuePush(MousePS2Port, MOUSE_ACK);
            MouseDispatchPacket(&LastPacket);
            break;
        }

        /* Reset */
        case 0xFF:
        {
            /* Send ACKnowledge */
            PS2QueuePush(MousePS2Port, MOUSE_ACK);

            MouseReset();

            /* Send the Basic Assurance Test success code and the device ID */
            PS2QueuePush(MousePS2Port, MOUSE_BAT_SUCCESS);
            PS2QueuePush(MousePS2Port, MouseId);
            break;
        }

        /* Unknown command */
        default:
        {
            PS2QueuePush(MousePS2Port, MOUSE_ERROR);
        }
    }
}