VirtualBox

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

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

PDM: s/szDriverName/szName/g - PDMDRVREG.

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