VirtualBox

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

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

PDMDrv,*: multi context drivers, part 2.

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