PS2M.cpp revision ed4a2bd5f3f74bb638e09a9ef937e69d130263d6
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * PS2M - PS/2 auxiliary device (mouse) emulation.
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * Copyright (C) 2007-2013 Oracle Corporation
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * available from http://www.virtualbox.org. This file is free software;
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * you can redistribute it and/or modify it under the terms of the GNU
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * General Public License (GPL) as published by the Free Software
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * References:
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * The Undocumented PC (2nd Ed.), Frank van Gilluwe, Addison-Wesley, 1996.
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * IBM TrackPoint System Version 4.0 Engineering Specification, 1999.
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * ELAN Microelectronics eKM8025 USB & PS/2 Mouse Controller, 2006.
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * - The auxiliary device commands are very similar to keyboard commands.
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * Most keyboard commands which do not specifically deal with the keyboard
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * (enable, disable, reset) have identical counterparts.
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * - The code refers to 'auxiliary device' and 'mouse'; these terms are not
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * quite interchangeable. 'Auxiliary device' is used when referring to the
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * generic PS/2 auxiliary device interface and 'mouse' when referring to
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * a mouse attached to the auxiliary port.
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * - The basic modes of operation are reset, stream, and remote. Those are
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * mutually exclusive. Stream and remote modes can additionally have wrap
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * mode enabled.
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * - The auxiliary device sends unsolicited data to the host only when it is
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * both in stream mode and enabled. Otherwise it only responds to commands.
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * There are three report packet formats supported by the emulated device. The
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * standard three-byte PS/2 format (with middle button support), IntelliMouse
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * four-byte format with added scroll wheel, and IntelliMouse Explorer four-byte
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * format with reduced scroll wheel range but two additional buttons. Note that
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * the first three bytes of the report are always the same.
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * Upon reset, the mouse is always in the standard PS/2 mode. A special 'knock'
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * sequence can be used to switch to ImPS/2 or ImEx mode. Three consecutive
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * Set Sampling Rate (0F3h) commands with arguments 200, 100, 80 switch to ImPS/2
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * mode. While in ImPS/2 or PS/2 mode, three consecutive Set Sampling Rate
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * commands with arguments 200, 200, 80 switch to ImEx mode. The Read ID (0F2h)
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * command will report the currently selected protocol.
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * Standard PS/2 pointing device three-byte report packet format:
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * +--------+--------+--------+--------+--------+--------+--------+--------+--------+
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * |Bit/byte| bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 |
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * +--------+--------+--------+--------+--------+--------+--------+--------+--------+
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * | Byte 1 | Y ovfl | X ovfl | Y sign | X sign | Sync | M btn | R btn | L btn |
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * +--------+--------+--------+--------+--------+--------+--------+--------+--------+
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * | Byte 2 | X movement delta (two's complement) |
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * +--------+--------+--------+--------+--------+--------+--------+--------+--------+
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * | Byte 3 | Y movement delta (two's complement) |
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * +--------+--------+--------+--------+--------+--------+--------+--------+--------+
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * - The sync bit is always set. It allows software to synchronize data packets
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * as the X/Y position data typically does not have bit 4 set.
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * - The overflow bits are set if motion exceeds accumulator range. We use the
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * maximum range (effectively 9 bits) and do not set the overflow bits.
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * - Movement in the up/right direction is defined as having positive sign.
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * IntelliMouse PS/2 (ImPS/2) fourth report packet byte:
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * +--------+--------+--------+--------+--------+--------+--------+--------+--------+
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * |Bit/byte| bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 |
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * +--------+--------+--------+--------+--------+--------+--------+--------+--------+
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * | Byte 4 | Z movement delta (two's complement) |
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * +--------+--------+--------+--------+--------+--------+--------+--------+--------+
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * - The valid range for Z delta values is only -8/+7, i.e. 4 bits.
8b75d89699548c4501b141a9470997dfd6db2f16vboxsync * IntelliMouse Explorer (ImEx) fourth report packet byte:
#include "VBoxDD.h"
#define IN_PS2M
#include "PS2Dev.h"
} name
} PS2M_MODE;
} PS2M_STATE;
} PS2M_PROTO;
typedef struct PS2M
bool fThrottleActive;
bool fDelayReset;
unsigned uThrottleDelay;
} Mouse;
#ifndef VBOX_DEVICE_STRUCT_TESTCASE
#ifdef IN_RING3
int rc;
return rc;
if (pDrv)
return rc;
LogFlowFunc(("Sampling rate %u, throttle delay %u ms\n", pThis->u8SampleRate, pThis->uThrottleDelay));
case PS2M_KNOCK_INITIAL:
case PS2M_KNOCK_1ST:
case PS2M_KNOCK_IMPS2_2ND:
case PS2M_KNOCK_IMEX_2ND:
if (dX < 0)
if (dY < 0)
if (fAccumBtns)
bool fHandled = true;
return VINF_SUCCESS;
return VINF_SUCCESS;
#ifndef IN_RING3
return VINF_IOM_R3_IOPORT_WRITE;
switch (cmd)
case ACMD_SET_SCALE_11:
case ACMD_SET_SCALE_21:
case ACMD_REQ_STATUS:
case ACMD_SET_STREAM:
case ACMD_READ_REMOTE:
case ACMD_RESET_WRAP:
case ACMD_SET_WRAP:
case ACMD_SET_REMOTE:
case ACMD_READ_ID:
case ACMD_ENABLE:
#ifdef IN_RING3
case ACMD_DISABLE:
case ACMD_SET_DEFAULT:
case ACMD_RESEND:
case ACMD_RESET:
#ifdef IN_RING3
case ACMD_SET_RES:
case ACMD_SET_SAMP_RATE:
case ACMD_SET_RES:
case ACMD_SET_SAMP_RATE:
fHandled = false;
if (fHandled)
case ACMD_INVALID_1:
case ACMD_INVALID_2:
case ACMD_INVALID_3:
case ACMD_INVALID_4:
case ACMD_INVALID_5:
case ACMD_INVALID_6:
case ACMD_INVALID_7:
case ACMD_INVALID_8:
case ACMD_INVALID_9:
case ACMD_INVALID_10:
return VINF_SUCCESS;
int rc;
return rc;
#ifdef IN_RING3
if (uHaveEvents)
///@todo Might want a PS2MCompleteCommand() to push last response, clear command, and kick the KBC...
static DECLCALLBACK(void) ps2mInfoState(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
return NULL;
if (dx < 0)
if (dy < 0)
return rc;
return VINF_SUCCESS;
int rc;
rc = PDMDevHlpDriverAttach(pDevIns, iLUN, &pThis->Mouse.IBase, &pThis->Mouse.pDrvBase, "Mouse Port");
Log(("%s/%d: warning: no driver attached to LUN #1!\n", pDevIns->pReg->szName, pDevIns->iInstance));
return rc;
int rc;
return rc;
int rc;
return rc;
return rc;
return rc;