KeyboardImpl.cpp revision c2590a722c15520a45551ed7dc02d4831fb1a48e
77b1a2d8b5dbe2c0b5200794914239fee3c8ee5dvboxsync/* $Id$ */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @file
77b1a2d8b5dbe2c0b5200794914239fee3c8ee5dvboxsync * VirtualBox COM class implementation
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2006-2012 Oracle Corporation
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * available from http://www.virtualbox.org. This file is free software;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync */
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync#include "KeyboardImpl.h"
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync#include "ConsoleImpl.h"
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include "AutoCaller.h"
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include "Logging.h"
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <VBox/com/array.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <VBox/vmm/pdmdrv.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/asm.h>
da957c069c2a3c582fe265ff88170ce4c42b499dvboxsync#include <iprt/cpp/utils.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync// defines
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync////////////////////////////////////////////////////////////////////////////////
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync// globals
9496f2d398b49813176939d7a339ae513d5175efvboxsync////////////////////////////////////////////////////////////////////////////////
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** @name Keyboard device capabilities bitfield
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync * @{ */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncenum
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /** The keyboard device does not wish to receive keystrokes. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync KEYBOARD_DEVCAP_DISABLED = 0,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /** The keyboard device does wishes to receive keystrokes. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync KEYBOARD_DEVCAP_ENABLED = 1
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync};
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/**
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Keyboard driver instance data.
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsynctypedef struct DRVMAINKEYBOARD
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync /** Pointer to the keyboard object. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync Keyboard *pKeyboard;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Pointer to the driver instance structure. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PPDMDRVINS pDrvIns;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Pointer to the keyboard port interface of the driver/device above us. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PPDMIKEYBOARDPORT pUpPort;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Our keyboard connector interface. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PDMIKEYBOARDCONNECTOR IConnector;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** The capabilities of this device. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync uint32_t u32DevCaps;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync} DRVMAINKEYBOARD, *PDRVMAINKEYBOARD;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** Converts PDMIVMMDEVCONNECTOR pointer to a DRVMAINVMMDEV pointer. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#define PPDMIKEYBOARDCONNECTOR_2_MAINKEYBOARD(pInterface) ( (PDRVMAINKEYBOARD) ((uintptr_t)pInterface - RT_OFFSETOF(DRVMAINKEYBOARD, IConnector)) )
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync// constructor / destructor
0abd77741a608f6c41c8dfcd4781b8b84adf1044vboxsync////////////////////////////////////////////////////////////////////////////////
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsyncKeyboard::Keyboard()
9496f2d398b49813176939d7a339ae513d5175efvboxsync : mParent(NULL)
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsyncKeyboard::~Keyboard()
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsyncHRESULT Keyboard::FinalConstruct()
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync RT_ZERO(mpDrv);
9496f2d398b49813176939d7a339ae513d5175efvboxsync mpVMMDev = NULL;
9496f2d398b49813176939d7a339ae513d5175efvboxsync mfVMMDevInited = false;
9496f2d398b49813176939d7a339ae513d5175efvboxsync return BaseFinalConstruct();
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsyncvoid Keyboard::FinalRelease()
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync uninit();
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync BaseFinalRelease();
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync}
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync// public methods
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync////////////////////////////////////////////////////////////////////////////////
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync/**
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * Initializes the keyboard object.
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync *
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * @returns COM result indicator
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * @param parent handle of our parent object
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncHRESULT Keyboard::init(Console *aParent)
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync{
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync LogFlowThisFunc(("aParent=%p\n", aParent));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ComAssertRet(aParent, E_INVALIDARG);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Enclose the state transition NotReady->InInit->Ready */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AutoInitSpan autoInitSpan(this);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertReturn(autoInitSpan.isOk(), E_FAIL);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync unconst(mParent) = aParent;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync unconst(mEventSource).createObject();
9496f2d398b49813176939d7a339ae513d5175efvboxsync HRESULT rc = mEventSource->init();
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertComRCReturnRC(rc);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /* Confirm a successful initialization */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync autoInitSpan.setSucceeded();
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync return S_OK;
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/**
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * Uninitializes the instance and sets the ready flag to FALSE.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * Called either from FinalRelease() or by the parent when it gets destroyed.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync */
9496f2d398b49813176939d7a339ae513d5175efvboxsyncvoid Keyboard::uninit()
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync LogFlowThisFunc(("\n"));
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync /* Enclose the state transition Ready->InUninit->NotReady */
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync AutoUninitSpan autoUninitSpan(this);
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (autoUninitSpan.uninitDone())
9496f2d398b49813176939d7a339ae513d5175efvboxsync return;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync for (unsigned i = 0; i < KEYBOARD_MAX_DEVICES; ++i)
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (mpDrv[i])
9496f2d398b49813176939d7a339ae513d5175efvboxsync mpDrv[i]->pKeyboard = NULL;
9496f2d398b49813176939d7a339ae513d5175efvboxsync mpDrv[i] = NULL;
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync mpVMMDev = NULL;
9496f2d398b49813176939d7a339ae513d5175efvboxsync mfVMMDevInited = true;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync unconst(mParent) = NULL;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync unconst(mEventSource).setNull();
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/**
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Sends a scancode to the keyboard.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * @returns COM status code
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * @param scancode The scancode to send
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncSTDMETHODIMP Keyboard::PutScancode(LONG scancode)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync com::SafeArray<LONG> scancodes(1);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync scancodes[0] = scancode;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync return PutScancodes(ComSafeArrayAsInParam(scancodes), NULL);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync}
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync/**
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * Sends a list of scancodes to the keyboard.
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync *
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * @returns COM status code
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * @param scancodes Pointer to the first scancode
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * @param count Number of scancodes
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * @param codesStored Address of variable to store the number
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * of scancodes that were sent to the keyboard.
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync This value can be NULL.
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncSTDMETHODIMP Keyboard::PutScancodes(ComSafeArrayIn(LONG, scancodes),
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync ULONG *codesStored)
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync{
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync if (ComSafeArrayInIsNull(scancodes))
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync return E_INVALIDARG;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync AutoCaller autoCaller(this);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync com::SafeArray<LONG> keys(ComSafeArrayInArg(scancodes));
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync CHECK_CONSOLE_DRV(mpDrv[0]);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync /* Send input to the last enabled device. Relies on the fact that
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * the USB keyboard is always initialized after the PS/2 keyboard.
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync PPDMIKEYBOARDPORT pUpPort = NULL;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync for (int i = KEYBOARD_MAX_DEVICES - 1; i >= 0 ; --i)
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (mpDrv[i] && (mpDrv[i]->u32DevCaps & KEYBOARD_DEVCAP_ENABLED))
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync pUpPort = mpDrv[i]->pUpPort;
9496f2d398b49813176939d7a339ae513d5175efvboxsync break;
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync /* No enabled keyboard - throw the input away. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (!pUpPort)
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (codesStored)
9496f2d398b49813176939d7a339ae513d5175efvboxsync *codesStored = (uint32_t)keys.size();
9496f2d398b49813176939d7a339ae513d5175efvboxsync return S_OK;
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync int vrc = VINF_SUCCESS;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync uint32_t sent;
9496f2d398b49813176939d7a339ae513d5175efvboxsync for (sent = 0; (sent < keys.size()) && RT_SUCCESS(vrc); sent++)
9496f2d398b49813176939d7a339ae513d5175efvboxsync vrc = pUpPort->pfnPutEvent(pUpPort, (uint8_t)keys[sent]);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync if (codesStored)
9496f2d398b49813176939d7a339ae513d5175efvboxsync *codesStored = sent;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync /* Only signal the keys in the event which have been actually sent. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync com::SafeArray<LONG> keysSent(sent);
9496f2d398b49813176939d7a339ae513d5175efvboxsync memcpy(keysSent.raw(), keys.raw(), sent*sizeof(LONG));
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync VBoxEventDesc evDesc;
9496f2d398b49813176939d7a339ae513d5175efvboxsync evDesc.init(mEventSource, VBoxEventType_OnGuestKeyboard, ComSafeArrayAsInParam(keys));
9496f2d398b49813176939d7a339ae513d5175efvboxsync evDesc.fire(0);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (RT_FAILURE(vrc))
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync return setError(VBOX_E_IPRT_ERROR,
9496f2d398b49813176939d7a339ae513d5175efvboxsync tr("Could not send all scan codes to the virtual keyboard (%Rrc)"),
9496f2d398b49813176939d7a339ae513d5175efvboxsync vrc);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync return S_OK;
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync/**
9496f2d398b49813176939d7a339ae513d5175efvboxsync * Sends Control-Alt-Delete to the keyboard. This could be done otherwise
9496f2d398b49813176939d7a339ae513d5175efvboxsync * but it's so common that we'll be nice and supply a convenience API.
9496f2d398b49813176939d7a339ae513d5175efvboxsync *
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @returns COM status code
9496f2d398b49813176939d7a339ae513d5175efvboxsync *
9496f2d398b49813176939d7a339ae513d5175efvboxsync */
9496f2d398b49813176939d7a339ae513d5175efvboxsyncSTDMETHODIMP Keyboard::PutCAD()
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync static com::SafeArray<LONG> cadSequence(8);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync cadSequence[0] = 0x1d; // Ctrl down
9496f2d398b49813176939d7a339ae513d5175efvboxsync cadSequence[1] = 0x38; // Alt down
9496f2d398b49813176939d7a339ae513d5175efvboxsync cadSequence[2] = 0xe0; // Del down 1
9496f2d398b49813176939d7a339ae513d5175efvboxsync cadSequence[3] = 0x53; // Del down 2
9496f2d398b49813176939d7a339ae513d5175efvboxsync cadSequence[4] = 0xe0; // Del up 1
9496f2d398b49813176939d7a339ae513d5175efvboxsync cadSequence[5] = 0xd3; // Del up 2
9496f2d398b49813176939d7a339ae513d5175efvboxsync cadSequence[6] = 0xb8; // Alt up
9496f2d398b49813176939d7a339ae513d5175efvboxsync cadSequence[7] = 0x9d; // Ctrl up
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync return PutScancodes(ComSafeArrayAsInParam(cadSequence), NULL);
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync/**
9496f2d398b49813176939d7a339ae513d5175efvboxsync * Releases all currently held keys in the virtual keyboard.
9496f2d398b49813176939d7a339ae513d5175efvboxsync *
9496f2d398b49813176939d7a339ae513d5175efvboxsync * @returns COM status code
9496f2d398b49813176939d7a339ae513d5175efvboxsync *
9496f2d398b49813176939d7a339ae513d5175efvboxsync */
9496f2d398b49813176939d7a339ae513d5175efvboxsyncSTDMETHODIMP Keyboard::ReleaseKeys()
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync com::SafeArray<LONG> scancodes(1);
9496f2d398b49813176939d7a339ae513d5175efvboxsync scancodes[0] = 0xFC; /* Magic scancode, see PS/2 and USB keyboard devices. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync return PutScancodes(ComSafeArrayAsInParam(scancodes), NULL);
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsyncSTDMETHODIMP Keyboard::COMGETTER(EventSource)(IEventSource ** aEventSource)
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync CheckComArgOutPointerValid(aEventSource);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync AutoCaller autoCaller(this);
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync // no need to lock - lifetime constant
9496f2d398b49813176939d7a339ae513d5175efvboxsync mEventSource.queryInterfaceTo(aEventSource);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync return S_OK;
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync//
9496f2d398b49813176939d7a339ae513d5175efvboxsync// private methods
9496f2d398b49813176939d7a339ae513d5175efvboxsync//
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsyncDECLCALLBACK(void) Keyboard::keyboardLedStatusChange(PPDMIKEYBOARDCONNECTOR pInterface, PDMKEYBLEDS enmLeds)
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync{
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync PDRVMAINKEYBOARD pDrv = PPDMIKEYBOARDCONNECTOR_2_MAINKEYBOARD(pInterface);
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync pDrv->pKeyboard->getParent()->onKeyboardLedsChange(RT_BOOL(enmLeds & PDMKEYBLEDS_NUMLOCK),
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync RT_BOOL(enmLeds & PDMKEYBLEDS_CAPSLOCK),
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync RT_BOOL(enmLeds & PDMKEYBLEDS_SCROLLLOCK));
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync}
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync/**
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync * @interface_method_impl{PDMIKEYBOARDCONNECTOR,pfnSetActive}
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync */
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsyncDECLCALLBACK(void) Keyboard::keyboardSetActive(PPDMIKEYBOARDCONNECTOR pInterface, bool fActive)
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync{
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync PDRVMAINKEYBOARD pDrv = PPDMIKEYBOARDCONNECTOR_2_MAINKEYBOARD(pInterface);
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync if (fActive)
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync pDrv->u32DevCaps |= KEYBOARD_DEVCAP_ENABLED;
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync else
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync pDrv->u32DevCaps &= ~KEYBOARD_DEVCAP_ENABLED;
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync}
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/**
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @interface_method_impl{PDMIBASE,pfnQueryInterface}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncDECLCALLBACK(void *) Keyboard::drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PDRVMAINKEYBOARD pDrv = PDMINS_2_DATA(pDrvIns, PDRVMAINKEYBOARD);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIKEYBOARDCONNECTOR, &pDrv->IConnector);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return NULL;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/**
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * Destruct a keyboard driver instance.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @returns VBox status.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @param pDrvIns The driver instance data.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncDECLCALLBACK(void) Keyboard::drvDestruct(PPDMDRVINS pDrvIns)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PDRVMAINKEYBOARD pThis = PDMINS_2_DATA(pDrvIns, PDRVMAINKEYBOARD);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("Keyboard::drvDestruct: iInstance=%d\n", pDrvIns->iInstance));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (pThis->pKeyboard)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AutoWriteLock kbdLock(pThis->pKeyboard COMMA_LOCKVAL_SRC_POS);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync for (unsigned cDev = 0; cDev < KEYBOARD_MAX_DEVICES; ++cDev)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (pThis->pKeyboard->mpDrv[cDev] == pThis)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pThis->pKeyboard->mpDrv[cDev] = NULL;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync break;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pThis->pKeyboard->mpVMMDev = NULL;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/**
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * Construct a keyboard driver instance.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @copydoc FNPDMDRVCONSTRUCT
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncDECLCALLBACK(int) Keyboard::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PDRVMAINKEYBOARD pThis = PDMINS_2_DATA(pDrvIns, PDRVMAINKEYBOARD);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync LogFlow(("Keyboard::drvConstruct: iInstance=%d\n", pDrvIns->iInstance));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /*
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * Validate configuration.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (!CFGMR3AreValuesValid(pCfg, "Object\0"))
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync ("Configuration error: Not possible to attach anything to this driver!\n"),
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync VERR_PDM_DRVINS_NO_ATTACH);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /*
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * IBase.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pDrvIns->IBase.pfnQueryInterface = Keyboard::drvQueryInterface;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pThis->IConnector.pfnLedStatusChange = keyboardLedStatusChange;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pThis->IConnector.pfnSetActive = Keyboard::keyboardSetActive;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /*
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * Get the IKeyboardPort interface of the above driver/device.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pThis->pUpPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIKEYBOARDPORT);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (!pThis->pUpPort)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AssertMsgFailed(("Configuration error: No keyboard port interface above!\n"));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return VERR_PDM_MISSING_INTERFACE_ABOVE;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /*
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * Get the Keyboard object pointer and update the mpDrv member.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync void *pv;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync int rc = CFGMR3QueryPtr(pCfg, "Object", &pv);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (RT_FAILURE(rc))
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return rc;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pThis->pKeyboard = (Keyboard *)pv; /** @todo Check this cast! */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync unsigned cDev;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync for (cDev = 0; cDev < KEYBOARD_MAX_DEVICES; ++cDev)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (!pThis->pKeyboard->mpDrv[cDev])
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync pThis->pKeyboard->mpDrv[cDev] = pThis;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync break;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (cDev == KEYBOARD_MAX_DEVICES)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return VERR_NO_MORE_HANDLES;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return VINF_SUCCESS;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/**
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * Keyboard driver registration record.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncconst PDMDRVREG Keyboard::DrvReg =
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* u32Version */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PDM_DRVREG_VERSION,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* szName */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync "MainKeyboard",
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* szRCMod */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync "",
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* szR0Mod */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync "",
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* pszDescription */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync "Main keyboard driver (Main as in the API).",
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* fFlags */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* fClass. */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PDM_DRVREG_CLASS_KEYBOARD,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* cMaxInstances */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync ~0U,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* cbInstance */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync sizeof(DRVMAINKEYBOARD),
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* pfnConstruct */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync Keyboard::drvConstruct,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* pfnDestruct */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync Keyboard::drvDestruct,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* pfnRelocate */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync NULL,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* pfnIOCtl */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync NULL,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* pfnPowerOn */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync NULL,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* pfnReset */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync NULL,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* pfnSuspend */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync NULL,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* pfnResume */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync NULL,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* pfnAttach */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync NULL,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* pfnDetach */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync NULL,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* pfnPowerOff */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync NULL,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* pfnSoftReset */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync NULL,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* u32EndVersion */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync PDM_DRVREG_VERSION
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync};
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/* vi: set tabstop=4 shiftwidth=4 expandtab: */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync