VirtualBox

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

Last change on this file since 25966 was 25966, checked in by vboxsync, 15 years ago

PDMIBASE refactoring; use UUID as interface IDs.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.7 KB
Line 
1/* $Id: DrvKeyboardQueue.cpp 25966 2010-01-22 11:15:43Z vboxsync $ */
2/** @file
3 * VBox input devices: Keyboard queue driver
4 */
5
6/*
7 * Copyright (C) 2006-2010 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP LOG_GROUP_DRV_KBD_QUEUE
27#include <VBox/pdmdrv.h>
28#include <iprt/assert.h>
29#include <iprt/uuid.h>
30
31#include "Builtins.h"
32
33
34
35/*******************************************************************************
36* Structures and Typedefs *
37*******************************************************************************/
38/**
39 * Keyboard queue driver instance data.
40 *
41 * @implements PDMIKEYBOARDCONNECTOR
42 * @implements PDMIKEYBOARDPORT
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 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
81 */
82static DECLCALLBACK(void *) drvKbdQueueQueryInterface(PPDMIBASE pInterface, const char *pszIID)
83{
84 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
85 PDRVKBDQUEUE pThis = PDMINS_2_DATA(pDrvIns, PDRVKBDQUEUE);
86
87 if (RTUuidCompare2Strs(pszIID, PDMIBASE_IID) == 0)
88 return &pDrvIns->IBase;
89 if (RTUuidCompare2Strs(pszIID, PDMINTERFACE_KEYBOARD_CONNECTOR) == 0)
90 return &pThis->Connector;
91 if (RTUuidCompare2Strs(pszIID, PDMINTERFACE_KEYBOARD_PORT) == 0)
92 return &pThis->Port;
93 return NULL;
94}
95
96
97/* -=-=-=-=- IKeyboardPort -=-=-=-=- */
98
99/** Converts a pointer to DRVKBDQUEUE::Port to a DRVKBDQUEUE pointer. */
100#define IKEYBOARDPORT_2_DRVKBDQUEUE(pInterface) ( (PDRVKBDQUEUE)((char *)(pInterface) - RT_OFFSETOF(DRVKBDQUEUE, Port)) )
101
102
103/**
104 * Queues a keyboard event.
105 * Because of the event queueing the EMT context requirement is lifted.
106 *
107 * @returns VBox status code.
108 * @param pInterface Pointer to this interface structure.
109 * @param u8KeyCode The keycode to queue.
110 * @thread Any thread.
111 */
112static DECLCALLBACK(int) drvKbdQueuePutEvent(PPDMIKEYBOARDPORT pInterface, uint8_t u8KeyCode)
113{
114 PDRVKBDQUEUE pDrv = IKEYBOARDPORT_2_DRVKBDQUEUE(pInterface);
115 if (pDrv->fInactive)
116 return VINF_SUCCESS;
117
118 PDRVKBDQUEUEITEM pItem = (PDRVKBDQUEUEITEM)PDMQueueAlloc(pDrv->pQueue);
119 if (pItem)
120 {
121 pItem->u8KeyCode = u8KeyCode;
122 PDMQueueInsert(pDrv->pQueue, &pItem->Core);
123 return VINF_SUCCESS;
124 }
125 AssertMsgFailed(("drvKbdQueuePutEvent: Queue is full!!!!\n"));
126 return VERR_PDM_NO_QUEUE_ITEMS;
127}
128
129
130/* -=-=-=-=- Connector -=-=-=-=- */
131
132#define PPDMIKEYBOARDCONNECTOR_2_DRVKBDQUEUE(pInterface) ( (PDRVKBDQUEUE)((char *)(pInterface) - RT_OFFSETOF(DRVKBDQUEUE, Connector)) )
133
134
135/**
136 * Pass LED status changes from the guest thru to the frontent driver.
137 *
138 * @param pInterface Pointer to the keyboard connector interface structure.
139 * @param enmLeds The new LED mask.
140 */
141static DECLCALLBACK(void) drvKbdPassThruLedsChange(PPDMIKEYBOARDCONNECTOR pInterface, PDMKEYBLEDS enmLeds)
142{
143 PDRVKBDQUEUE pDrv = PPDMIKEYBOARDCONNECTOR_2_DRVKBDQUEUE(pInterface);
144 pDrv->pDownConnector->pfnLedStatusChange(pDrv->pDownConnector, enmLeds);
145}
146
147
148
149/* -=-=-=-=- queue -=-=-=-=- */
150
151/**
152 * Queue callback for processing a queued item.
153 *
154 * @returns Success indicator.
155 * If false the item will not be removed and the flushing will stop.
156 * @param pDrvIns The driver instance.
157 * @param pItemCore Pointer to the queue item to process.
158 */
159static DECLCALLBACK(bool) drvKbdQueueConsumer(PPDMDRVINS pDrvIns, PPDMQUEUEITEMCORE pItemCore)
160{
161 PDRVKBDQUEUE pThis = PDMINS_2_DATA(pDrvIns, PDRVKBDQUEUE);
162 PDRVKBDQUEUEITEM pItem = (PDRVKBDQUEUEITEM)pItemCore;
163 int rc = pThis->pUpPort->pfnPutEvent(pThis->pUpPort, pItem->u8KeyCode);
164 return RT_SUCCESS(rc);
165}
166
167
168/* -=-=-=-=- driver interface -=-=-=-=- */
169
170/**
171 * Power On notification.
172 *
173 * @returns VBox status.
174 * @param pDrvIns The drive instance data.
175 */
176static DECLCALLBACK(void) drvKbdQueuePowerOn(PPDMDRVINS pDrvIns)
177{
178 PDRVKBDQUEUE pThis = PDMINS_2_DATA(pDrvIns, PDRVKBDQUEUE);
179 pThis->fInactive = false;
180}
181
182
183/**
184 * Reset notification.
185 *
186 * @returns VBox status.
187 * @param pDrvIns The drive instance data.
188 */
189static DECLCALLBACK(void) drvKbdQueueReset(PPDMDRVINS pDrvIns)
190{
191 //PDRVKBDQUEUE pThis = PDMINS_2_DATA(pDrvIns, PDRVKBDQUEUE);
192 /** @todo purge the queue on reset. */
193}
194
195
196/**
197 * Suspend notification.
198 *
199 * @returns VBox status.
200 * @param pDrvIns The drive instance data.
201 */
202static DECLCALLBACK(void) drvKbdQueueSuspend(PPDMDRVINS pDrvIns)
203{
204 PDRVKBDQUEUE pThis = PDMINS_2_DATA(pDrvIns, PDRVKBDQUEUE);
205 pThis->fInactive = true;
206}
207
208
209/**
210 * Resume notification.
211 *
212 * @returns VBox status.
213 * @param pDrvIns The drive instance data.
214 */
215static DECLCALLBACK(void) drvKbdQueueResume(PPDMDRVINS pDrvIns)
216{
217 PDRVKBDQUEUE pThis = PDMINS_2_DATA(pDrvIns, PDRVKBDQUEUE);
218 pThis->fInactive = false;
219}
220
221
222/**
223 * Power Off notification.
224 *
225 * @param pDrvIns The drive instance data.
226 */
227static DECLCALLBACK(void) drvKbdQueuePowerOff(PPDMDRVINS pDrvIns)
228{
229 PDRVKBDQUEUE pThis = PDMINS_2_DATA(pDrvIns, PDRVKBDQUEUE);
230 pThis->fInactive = true;
231}
232
233
234/**
235 * Construct a keyboard driver instance.
236 *
237 * @copydoc FNPDMDRVCONSTRUCT
238 */
239static DECLCALLBACK(int) drvKbdQueueConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle, uint32_t fFlags)
240{
241 PDRVKBDQUEUE pDrv = PDMINS_2_DATA(pDrvIns, PDRVKBDQUEUE);
242 LogFlow(("drvKbdQueueConstruct: iInstance=%d\n", pDrvIns->iInstance));
243
244 /*
245 * Validate configuration.
246 */
247 if (!CFGMR3AreValuesValid(pCfgHandle, "QueueSize\0Interval\0"))
248 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
249
250 /*
251 * Init basic data members and interfaces.
252 */
253 pDrv->fInactive = true;
254 /* IBase. */
255 pDrvIns->IBase.pfnQueryInterface = drvKbdQueueQueryInterface;
256 /* IKeyboardConnector. */
257 pDrv->Connector.pfnLedStatusChange = drvKbdPassThruLedsChange;
258 /* IKeyboardPort. */
259 pDrv->Port.pfnPutEvent = drvKbdQueuePutEvent;
260
261 /*
262 * Get the IKeyboardPort interface of the above driver/device.
263 */
264 pDrv->pUpPort = (PPDMIKEYBOARDPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_KEYBOARD_PORT);
265 if (!pDrv->pUpPort)
266 {
267 AssertMsgFailed(("Configuration error: No keyboard port interface above!\n"));
268 return VERR_PDM_MISSING_INTERFACE_ABOVE;
269 }
270
271 /*
272 * Attach driver below and query it's connector interface.
273 */
274 PPDMIBASE pDownBase;
275 int rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pDownBase);
276 if (RT_FAILURE(rc))
277 {
278 AssertMsgFailed(("Failed to attach driver below us! rc=%Rra\n", rc));
279 return rc;
280 }
281 pDrv->pDownConnector = (PPDMIKEYBOARDCONNECTOR)pDownBase->pfnQueryInterface(pDownBase, PDMINTERFACE_KEYBOARD_CONNECTOR);
282 if (!pDrv->pDownConnector)
283 {
284 AssertMsgFailed(("Configuration error: No keyboard connector interface below!\n"));
285 return VERR_PDM_MISSING_INTERFACE_BELOW;
286 }
287
288 /*
289 * Create the queue.
290 */
291 uint32_t cMilliesInterval = 0;
292 rc = CFGMR3QueryU32(pCfgHandle, "Interval", &cMilliesInterval);
293 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
294 cMilliesInterval = 0;
295 else if (RT_FAILURE(rc))
296 {
297 AssertMsgFailed(("Configuration error: 32-bit \"Interval\" -> rc=%Rrc\n", rc));
298 return rc;
299 }
300
301 uint32_t cItems = 0;
302 rc = CFGMR3QueryU32(pCfgHandle, "QueueSize", &cItems);
303 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
304 cItems = 128;
305 else if (RT_FAILURE(rc))
306 {
307 AssertMsgFailed(("Configuration error: 32-bit \"QueueSize\" -> rc=%Rrc\n", rc));
308 return rc;
309 }
310
311 rc = PDMDrvHlpPDMQueueCreate(pDrvIns, sizeof(DRVKBDQUEUEITEM), cItems, cMilliesInterval, drvKbdQueueConsumer, "Keyboard", &pDrv->pQueue);
312 if (RT_FAILURE(rc))
313 {
314 AssertMsgFailed(("Failed to create driver: cItems=%d cMilliesInterval=%d rc=%Rrc\n", cItems, cMilliesInterval, rc));
315 return rc;
316 }
317
318 return VINF_SUCCESS;
319}
320
321
322/**
323 * Keyboard queue driver registration record.
324 */
325const PDMDRVREG g_DrvKeyboardQueue =
326{
327 /* u32Version */
328 PDM_DRVREG_VERSION,
329 /* szDriverName */
330 "KeyboardQueue",
331 /* szRCMod */
332 "",
333 /* szR0Mod */
334 "",
335 /* pszDescription */
336 "Keyboard queue driver to plug in between the key source and the device to do queueing and inter-thread transport.",
337 /* fFlags */
338 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
339 /* fClass. */
340 PDM_DRVREG_CLASS_KEYBOARD,
341 /* cMaxInstances */
342 ~0,
343 /* cbInstance */
344 sizeof(DRVKBDQUEUE),
345 /* pfnConstruct */
346 drvKbdQueueConstruct,
347 /* pfnRelocate */
348 NULL,
349 /* pfnDestruct */
350 NULL,
351 /* pfnIOCtl */
352 NULL,
353 /* pfnPowerOn */
354 drvKbdQueuePowerOn,
355 /* pfnReset */
356 drvKbdQueueReset,
357 /* pfnSuspend */
358 drvKbdQueueSuspend,
359 /* pfnResume */
360 drvKbdQueueResume,
361 /* pfnAttach */
362 NULL,
363 /* pfnDetach */
364 NULL,
365 /* pfnPowerOff */
366 drvKbdQueuePowerOff,
367 /* pfnSoftReset */
368 NULL,
369 /* u32EndVersion */
370 PDM_DRVREG_VERSION
371};
372
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