VirtualBox

source: vbox/trunk/src/VBox/Devices/Input/DrvKeyboardQueue.cpp@ 2685

Last change on this file since 2685 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.1 KB
Line 
1/** @file
2 *
3 * VBox input devices:
4 * Keyboard queue driver
5 */
6
7/*
8 * Copyright (C) 2006 InnoTek Systemberatung GmbH
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License as published by the Free Software Foundation,
14 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
15 * distribution. VirtualBox OSE is distributed in the hope that it will
16 * be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * If you received this file as part of a commercial VirtualBox
19 * distribution, then only the terms of your commercial VirtualBox
20 * license agreement apply instead of the previous paragraph.
21 */
22
23
24/*******************************************************************************
25* Header Files *
26*******************************************************************************/
27#define LOG_GROUP LOG_GROUP_DRV_KBD_QUEUE
28#include <VBox/pdm.h>
29#include <VBox/err.h>
30
31#include <VBox/log.h>
32#include <iprt/assert.h>
33
34#include "Builtins.h"
35
36
37
38/*******************************************************************************
39* Structures and Typedefs *
40*******************************************************************************/
41/**
42 * Keyboard queue driver instance data.
43 */
44typedef struct DRVKBDQUEUE
45{
46 /** Pointer to the driver instance structure. */
47 PPDMDRVINS pDrvIns;
48 /** Pointer to the keyboard port interface of the driver/device above us. */
49 PPDMIKEYBOARDPORT pUpPort;
50 /** Pointer to the keyboard port interface of the driver/device below us. */
51 PPDMIKEYBOARDCONNECTOR pDownConnector;
52 /** Our keyboard connector interface. */
53 PDMIKEYBOARDCONNECTOR Connector;
54 /** Our keyboard port interface. */
55 PDMIKEYBOARDPORT Port;
56 /** The queue handle. */
57 PPDMQUEUE pQueue;
58 /** Discard input when this flag is set.
59 * We only accept input when the VM is running. */
60 bool fInactive;
61} DRVKBDQUEUE, *PDRVKBDQUEUE;
62
63
64/**
65 * Keyboard queue item.
66 */
67typedef struct DRVKBDQUEUEITEM
68{
69 /** The core part owned by the queue manager. */
70 PDMQUEUEITEMCORE Core;
71 /** The keycode. */
72 uint8_t u8KeyCode;
73} DRVKBDQUEUEITEM, *PDRVKBDQUEUEITEM;
74
75
76
77/* -=-=-=-=- IBase -=-=-=-=- */
78
79/**
80 * Queries an interface to the driver.
81 *
82 * @returns Pointer to interface.
83 * @returns NULL if the interface was not supported by the driver.
84 * @param pInterface Pointer to this interface structure.
85 * @param enmInterface The requested interface identification.
86 */
87static DECLCALLBACK(void *) drvKbdQueueQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
88{
89 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
90 PDRVKBDQUEUE pDrv = PDMINS2DATA(pDrvIns, PDRVKBDQUEUE);
91 switch (enmInterface)
92 {
93 case PDMINTERFACE_BASE:
94 return &pDrvIns->IBase;
95 case PDMINTERFACE_KEYBOARD_PORT:
96 return &pDrv->Port;
97 case PDMINTERFACE_KEYBOARD_CONNECTOR:
98 return &pDrv->Connector;
99 default:
100 return NULL;
101 }
102}
103
104
105/* -=-=-=-=- IKeyboardPort -=-=-=-=- */
106
107/** Converts a pointer to DRVKBDQUEUE::Port to a DRVKBDQUEUE pointer. */
108#define IKEYBOARDPORT_2_DRVKBDQUEUE(pInterface) ( (PDRVKBDQUEUE)((char *)(pInterface) - RT_OFFSETOF(DRVKBDQUEUE, Port)) )
109
110
111/**
112 * Queues a keyboard event.
113 * Because of the event queueing the EMT context requirement is lifted.
114 *
115 * @returns VBox status code.
116 * @param pInterface Pointer to this interface structure.
117 * @param u8KeyCode The keycode to queue.
118 * @thread Any thread.
119 */
120static DECLCALLBACK(int) drvKbdQueuePutEvent(PPDMIKEYBOARDPORT pInterface, uint8_t u8KeyCode)
121{
122 PDRVKBDQUEUE pDrv = IKEYBOARDPORT_2_DRVKBDQUEUE(pInterface);
123 if (pDrv->fInactive)
124 return VINF_SUCCESS;
125
126 PDRVKBDQUEUEITEM pItem = (PDRVKBDQUEUEITEM)PDMQueueAlloc(pDrv->pQueue);
127 if (pItem)
128 {
129 pItem->u8KeyCode = u8KeyCode;
130 PDMQueueInsert(pDrv->pQueue, &pItem->Core);
131 return VINF_SUCCESS;
132 }
133 AssertMsgFailed(("drvKbdQueuePutEvent: Queue is full!!!!\n"));
134 return VERR_PDM_NO_QUEUE_ITEMS;
135}
136
137
138/* -=-=-=-=- Connector -=-=-=-=- */
139
140#define PPDMIKEYBOARDCONNECTOR_2_DRVKBDQUEUE(pInterface) ( (PDRVKBDQUEUE)((char *)(pInterface) - RT_OFFSETOF(DRVKBDQUEUE, Connector)) )
141
142
143/**
144 * Pass LED status changes from the guest thru to the frontent driver.
145 *
146 * @param pInterface Pointer to the keyboard connector interface structure.
147 * @param enmLeds The new LED mask.
148 */
149static DECLCALLBACK(void) drvKbdPassThruLedsChange(PPDMIKEYBOARDCONNECTOR pInterface, PDMKEYBLEDS enmLeds)
150{
151 PDRVKBDQUEUE pDrv = PPDMIKEYBOARDCONNECTOR_2_DRVKBDQUEUE(pInterface);
152 pDrv->pDownConnector->pfnLedStatusChange(pDrv->pDownConnector, enmLeds);
153}
154
155
156
157/* -=-=-=-=- queue -=-=-=-=- */
158
159/**
160 * Queue callback for processing a queued item.
161 *
162 * @returns Success indicator.
163 * If false the item will not be removed and the flushing will stop.
164 * @param pDrvIns The driver instance.
165 * @param pItemCore Pointer to the queue item to process.
166 */
167static DECLCALLBACK(bool) drvKbdQueueConsumer(PPDMDRVINS pDrvIns, PPDMQUEUEITEMCORE pItemCore)
168{
169 PDRVKBDQUEUE pData = PDMINS2DATA(pDrvIns, PDRVKBDQUEUE);
170 PDRVKBDQUEUEITEM pItem = (PDRVKBDQUEUEITEM)pItemCore;
171 int rc = pData->pUpPort->pfnPutEvent(pData->pUpPort, pItem->u8KeyCode);
172 return VBOX_SUCCESS(rc);
173}
174
175
176/* -=-=-=-=- driver interface -=-=-=-=- */
177
178/**
179 * Power On notification.
180 *
181 * @returns VBox status.
182 * @param pDrvIns The drive instance data.
183 */
184static DECLCALLBACK(void) drvKbdQueuePowerOn(PPDMDRVINS pDrvIns)
185{
186 PDRVKBDQUEUE pData = PDMINS2DATA(pDrvIns, PDRVKBDQUEUE);
187 pData->fInactive = false;
188}
189
190
191/**
192 * Reset notification.
193 *
194 * @returns VBox status.
195 * @param pDrvIns The drive instance data.
196 */
197static DECLCALLBACK(void) drvKbdQueueReset(PPDMDRVINS pDrvIns)
198{
199 //PDRVKBDQUEUE pData = PDMINS2DATA(pDrvIns, PDRVKBDQUEUE);
200 /** @todo purge the queue on reset. */
201}
202
203
204/**
205 * Suspend notification.
206 *
207 * @returns VBox status.
208 * @param pDrvIns The drive instance data.
209 */
210static DECLCALLBACK(void) drvKbdQueueSuspend(PPDMDRVINS pDrvIns)
211{
212 PDRVKBDQUEUE pData = PDMINS2DATA(pDrvIns, PDRVKBDQUEUE);
213 pData->fInactive = true;
214}
215
216
217/**
218 * Resume notification.
219 *
220 * @returns VBox status.
221 * @param pDrvIns The drive instance data.
222 */
223static DECLCALLBACK(void) drvKbdQueueResume(PPDMDRVINS pDrvIns)
224{
225 PDRVKBDQUEUE pData = PDMINS2DATA(pDrvIns, PDRVKBDQUEUE);
226 pData->fInactive = false;
227}
228
229
230/**
231 * Power Off notification.
232 *
233 * @param pDrvIns The drive instance data.
234 */
235static DECLCALLBACK(void) drvKbdQueuePowerOff(PPDMDRVINS pDrvIns)
236{
237 PDRVKBDQUEUE pData = PDMINS2DATA(pDrvIns, PDRVKBDQUEUE);
238 pData->fInactive = true;
239}
240
241
242/**
243 * Construct a keyboard driver instance.
244 *
245 * @returns VBox status.
246 * @param pDrvIns The driver instance data.
247 * If the registration structure is needed, pDrvIns->pDrvReg points to it.
248 * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
249 * of the driver instance. It's also found in pDrvIns->pCfgHandle, but like
250 * iInstance it's expected to be used a bit in this function.
251 */
252static DECLCALLBACK(int) drvKbdQueueConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
253{
254 PDRVKBDQUEUE pDrv = PDMINS2DATA(pDrvIns, PDRVKBDQUEUE);
255 LogFlow(("drvKbdQueueConstruct: iInstance=%d\n", pDrvIns->iInstance));
256
257 /*
258 * Validate configuration.
259 */
260 if (!CFGMR3AreValuesValid(pCfgHandle, "QueueSize\0Interval\0"))
261 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
262
263 /*
264 * Init basic data members and interfaces.
265 */
266 pDrv->fInactive = true;
267 /* IBase. */
268 pDrvIns->IBase.pfnQueryInterface = drvKbdQueueQueryInterface;
269 /* IKeyboardConnector. */
270 pDrv->Connector.pfnLedStatusChange = drvKbdPassThruLedsChange;
271 /* IKeyboardPort. */
272 pDrv->Port.pfnPutEvent = drvKbdQueuePutEvent;
273
274 /*
275 * Get the IKeyboardPort interface of the above driver/device.
276 */
277 pDrv->pUpPort = (PPDMIKEYBOARDPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_KEYBOARD_PORT);
278 if (!pDrv->pUpPort)
279 {
280 AssertMsgFailed(("Configuration error: No keyboard port interface above!\n"));
281 return VERR_PDM_MISSING_INTERFACE_ABOVE;
282 }
283
284 /*
285 * Attach driver below and query it's connector interface.
286 */
287 PPDMIBASE pDownBase;
288 int rc = pDrvIns->pDrvHlp->pfnAttach(pDrvIns, &pDownBase);
289 if (VBOX_FAILURE(rc))
290 {
291 AssertMsgFailed(("Failed to attach driver below us! rc=%Vra\n", rc));
292 return rc;
293 }
294 pDrv->pDownConnector = (PPDMIKEYBOARDCONNECTOR)pDownBase->pfnQueryInterface(pDownBase, PDMINTERFACE_KEYBOARD_CONNECTOR);
295 if (!pDrv->pDownConnector)
296 {
297 AssertMsgFailed(("Configuration error: No keyboard connector interface below!\n"));
298 return VERR_PDM_MISSING_INTERFACE_BELOW;
299 }
300
301 /*
302 * Create the queue.
303 */
304 uint32_t cMilliesInterval = 0;
305 rc = CFGMR3QueryU32(pCfgHandle, "Interval", &cMilliesInterval);
306 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
307 cMilliesInterval = 0;
308 else if (VBOX_FAILURE(rc))
309 {
310 AssertMsgFailed(("Configuration error: 32-bit \"Interval\" -> rc=%Vrc\n", rc));
311 return rc;
312 }
313
314 uint32_t cItems = 0;
315 rc = CFGMR3QueryU32(pCfgHandle, "QueueSize", &cItems);
316 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
317 cItems = 128;
318 else if (VBOX_FAILURE(rc))
319 {
320 AssertMsgFailed(("Configuration error: 32-bit \"QueueSize\" -> rc=%Vrc\n", rc));
321 return rc;
322 }
323
324 rc = pDrvIns->pDrvHlp->pfnPDMQueueCreate(pDrvIns, sizeof(DRVKBDQUEUEITEM), cItems, cMilliesInterval, drvKbdQueueConsumer, &pDrv->pQueue);
325 if (VBOX_FAILURE(rc))
326 {
327 AssertMsgFailed(("Failed to create driver: cItems=%d cMilliesInterval=%d rc=%Vrc\n", cItems, cMilliesInterval, rc));
328 return rc;
329 }
330
331 return VINF_SUCCESS;
332}
333
334
335/**
336 * Keyboard queue driver registration record.
337 */
338const PDMDRVREG g_DrvKeyboardQueue =
339{
340 /* u32Version */
341 PDM_DRVREG_VERSION,
342 /* szDriverName */
343 "KeyboardQueue",
344 /* pszDescription */
345 "Keyboard queue driver to plug in between the key source and the device to do queueing and inter-thread transport.",
346 /* fFlags */
347 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
348 /* fClass. */
349 PDM_DRVREG_CLASS_KEYBOARD,
350 /* cMaxInstances */
351 ~0,
352 /* cbInstance */
353 sizeof(DRVKBDQUEUE),
354 /* pfnConstruct */
355 drvKbdQueueConstruct,
356 /* pfnDestruct */
357 NULL,
358 /* pfnIOCtl */
359 NULL,
360 /* pfnPowerOn */
361 drvKbdQueuePowerOn,
362 /* pfnReset */
363 drvKbdQueueReset,
364 /* pfnSuspend */
365 drvKbdQueueSuspend,
366 /* pfnResume */
367 drvKbdQueueResume,
368 /* pfnDetach */
369 NULL,
370 /** pfnPowerOff */
371 drvKbdQueuePowerOff
372};
373
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette