DrvKeyboardQueue.cpp revision da957c069c2a3c582fe265ff88170ce4c42b499d
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * VBox input devices:
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Keyboard queue driver
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Copyright (C) 2006-2007 innotek GmbH
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * available from http://www.virtualbox.org. This file is free software;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * you can redistribute it and/or modify it under the terms of the GNU
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * General Public License as published by the Free Software Foundation,
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * If you received this file as part of a commercial VirtualBox
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * distribution, then only the terms of your commercial VirtualBox
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * license agreement apply instead of the previous paragraph.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/*******************************************************************************
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync* Header Files *
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync*******************************************************************************/
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/*******************************************************************************
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync* Structures and Typedefs *
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync*******************************************************************************/
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Keyboard queue driver instance data.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsynctypedef struct DRVKBDQUEUE
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Pointer to the driver instance structure. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Pointer to the keyboard port interface of the driver/device above us. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Pointer to the keyboard port interface of the driver/device below us. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Our keyboard connector interface. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Our keyboard port interface. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** The queue handle. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** Discard input when this flag is set.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * We only accept input when the VM is running. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Keyboard queue item.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** The core part owned by the queue manager. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** The keycode. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/* -=-=-=-=- IBase -=-=-=-=- */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Queries an interface to the driver.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @returns Pointer to interface.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @returns NULL if the interface was not supported by the driver.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param pInterface Pointer to this interface structure.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param enmInterface The requested interface identification.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsyncstatic DECLCALLBACK(void *) drvKbdQueueQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync PDRVKBDQUEUE pDrv = PDMINS2DATA(pDrvIns, PDRVKBDQUEUE);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/* -=-=-=-=- IKeyboardPort -=-=-=-=- */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/** Converts a pointer to DRVKBDQUEUE::Port to a DRVKBDQUEUE pointer. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync#define IKEYBOARDPORT_2_DRVKBDQUEUE(pInterface) ( (PDRVKBDQUEUE)((char *)(pInterface) - RT_OFFSETOF(DRVKBDQUEUE, Port)) )
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Queues a keyboard event.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Because of the event queueing the EMT context requirement is lifted.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @returns VBox status code.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param pInterface Pointer to this interface structure.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param u8KeyCode The keycode to queue.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @thread Any thread.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsyncstatic DECLCALLBACK(int) drvKbdQueuePutEvent(PPDMIKEYBOARDPORT pInterface, uint8_t u8KeyCode)
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync PDRVKBDQUEUE pDrv = IKEYBOARDPORT_2_DRVKBDQUEUE(pInterface);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync PDRVKBDQUEUEITEM pItem = (PDRVKBDQUEUEITEM)PDMQueueAlloc(pDrv->pQueue);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync AssertMsgFailed(("drvKbdQueuePutEvent: Queue is full!!!!\n"));
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/* -=-=-=-=- Connector -=-=-=-=- */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync#define PPDMIKEYBOARDCONNECTOR_2_DRVKBDQUEUE(pInterface) ( (PDRVKBDQUEUE)((char *)(pInterface) - RT_OFFSETOF(DRVKBDQUEUE, Connector)) )
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Pass LED status changes from the guest thru to the frontent driver.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param pInterface Pointer to the keyboard connector interface structure.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param enmLeds The new LED mask.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsyncstatic DECLCALLBACK(void) drvKbdPassThruLedsChange(PPDMIKEYBOARDCONNECTOR pInterface, PDMKEYBLEDS enmLeds)
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync PDRVKBDQUEUE pDrv = PPDMIKEYBOARDCONNECTOR_2_DRVKBDQUEUE(pInterface);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync pDrv->pDownConnector->pfnLedStatusChange(pDrv->pDownConnector, enmLeds);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/* -=-=-=-=- queue -=-=-=-=- */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Queue callback for processing a queued item.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @returns Success indicator.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * If false the item will not be removed and the flushing will stop.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param pDrvIns The driver instance.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param pItemCore Pointer to the queue item to process.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsyncstatic DECLCALLBACK(bool) drvKbdQueueConsumer(PPDMDRVINS pDrvIns, PPDMQUEUEITEMCORE pItemCore)
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync PDRVKBDQUEUE pData = PDMINS2DATA(pDrvIns, PDRVKBDQUEUE);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync PDRVKBDQUEUEITEM pItem = (PDRVKBDQUEUEITEM)pItemCore;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync int rc = pData->pUpPort->pfnPutEvent(pData->pUpPort, pItem->u8KeyCode);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/* -=-=-=-=- driver interface -=-=-=-=- */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Power On notification.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @returns VBox status.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param pDrvIns The drive instance data.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsyncstatic DECLCALLBACK(void) drvKbdQueuePowerOn(PPDMDRVINS pDrvIns)
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync PDRVKBDQUEUE pData = PDMINS2DATA(pDrvIns, PDRVKBDQUEUE);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Reset notification.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @returns VBox status.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param pDrvIns The drive instance data.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsyncstatic DECLCALLBACK(void) drvKbdQueueReset(PPDMDRVINS pDrvIns)
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync //PDRVKBDQUEUE pData = PDMINS2DATA(pDrvIns, PDRVKBDQUEUE);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync /** @todo purge the queue on reset. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Suspend notification.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @returns VBox status.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param pDrvIns The drive instance data.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsyncstatic DECLCALLBACK(void) drvKbdQueueSuspend(PPDMDRVINS pDrvIns)
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync PDRVKBDQUEUE pData = PDMINS2DATA(pDrvIns, PDRVKBDQUEUE);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Resume notification.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @returns VBox status.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param pDrvIns The drive instance data.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsyncstatic DECLCALLBACK(void) drvKbdQueueResume(PPDMDRVINS pDrvIns)
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync PDRVKBDQUEUE pData = PDMINS2DATA(pDrvIns, PDRVKBDQUEUE);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Power Off notification.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * @param pDrvIns The drive instance data.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsyncstatic DECLCALLBACK(void) drvKbdQueuePowerOff(PPDMDRVINS pDrvIns)
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync PDRVKBDQUEUE pData = PDMINS2DATA(pDrvIns, PDRVKBDQUEUE);
pDrv->pUpPort = (PPDMIKEYBOARDPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_KEYBOARD_PORT);
return VERR_PDM_MISSING_INTERFACE_ABOVE;
return rc;
pDrv->pDownConnector = (PPDMIKEYBOARDCONNECTOR)pDownBase->pfnQueryInterface(pDownBase, PDMINTERFACE_KEYBOARD_CONNECTOR);
return VERR_PDM_MISSING_INTERFACE_BELOW;
cMilliesInterval = 0;
return rc;
return rc;
rc = pDrvIns->pDrvHlp->pfnPDMQueueCreate(pDrvIns, sizeof(DRVKBDQUEUEITEM), cItems, cMilliesInterval, drvKbdQueueConsumer, &pDrv->pQueue);
AssertMsgFailed(("Failed to create driver: cItems=%d cMilliesInterval=%d rc=%Vrc\n", cItems, cMilliesInterval, rc));
return rc;
return VINF_SUCCESS;
"Keyboard queue driver to plug in between the key source and the device to do queueing and inter-thread transport.",
sizeof(DRVKBDQUEUE),
NULL,
NULL,
NULL,