VirtualBox

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

Last change on this file since 46336 was 44528, checked in by vboxsync, 12 years ago

header (C) fixes

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