VirtualBox

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

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

PDMQueue&users-thereof: Named the queues and added statistics.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.0 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 * @returns VBox status.
243 * @param pDrvIns The driver instance data.
244 * If the registration structure is needed, pDrvIns->pDrvReg points to it.
245 * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
246 * of the driver instance. It's also found in pDrvIns->pCfgHandle, but like
247 * iInstance it's expected to be used a bit in this function.
248 */
249static DECLCALLBACK(int) drvKbdQueueConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
250{
251 PDRVKBDQUEUE pDrv = PDMINS_2_DATA(pDrvIns, PDRVKBDQUEUE);
252 LogFlow(("drvKbdQueueConstruct: iInstance=%d\n", pDrvIns->iInstance));
253
254 /*
255 * Validate configuration.
256 */
257 if (!CFGMR3AreValuesValid(pCfgHandle, "QueueSize\0Interval\0"))
258 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
259
260 /*
261 * Init basic data members and interfaces.
262 */
263 pDrv->fInactive = true;
264 /* IBase. */
265 pDrvIns->IBase.pfnQueryInterface = drvKbdQueueQueryInterface;
266 /* IKeyboardConnector. */
267 pDrv->Connector.pfnLedStatusChange = drvKbdPassThruLedsChange;
268 /* IKeyboardPort. */
269 pDrv->Port.pfnPutEvent = drvKbdQueuePutEvent;
270
271 /*
272 * Get the IKeyboardPort interface of the above driver/device.
273 */
274 pDrv->pUpPort = (PPDMIKEYBOARDPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_KEYBOARD_PORT);
275 if (!pDrv->pUpPort)
276 {
277 AssertMsgFailed(("Configuration error: No keyboard port interface above!\n"));
278 return VERR_PDM_MISSING_INTERFACE_ABOVE;
279 }
280
281 /*
282 * Attach driver below and query it's connector interface.
283 */
284 PPDMIBASE pDownBase;
285 int rc = pDrvIns->pDrvHlp->pfnAttach(pDrvIns, &pDownBase);
286 if (RT_FAILURE(rc))
287 {
288 AssertMsgFailed(("Failed to attach driver below us! rc=%Rra\n", rc));
289 return rc;
290 }
291 pDrv->pDownConnector = (PPDMIKEYBOARDCONNECTOR)pDownBase->pfnQueryInterface(pDownBase, PDMINTERFACE_KEYBOARD_CONNECTOR);
292 if (!pDrv->pDownConnector)
293 {
294 AssertMsgFailed(("Configuration error: No keyboard connector interface below!\n"));
295 return VERR_PDM_MISSING_INTERFACE_BELOW;
296 }
297
298 /*
299 * Create the queue.
300 */
301 uint32_t cMilliesInterval = 0;
302 rc = CFGMR3QueryU32(pCfgHandle, "Interval", &cMilliesInterval);
303 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
304 cMilliesInterval = 0;
305 else if (RT_FAILURE(rc))
306 {
307 AssertMsgFailed(("Configuration error: 32-bit \"Interval\" -> rc=%Rrc\n", rc));
308 return rc;
309 }
310
311 uint32_t cItems = 0;
312 rc = CFGMR3QueryU32(pCfgHandle, "QueueSize", &cItems);
313 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
314 cItems = 128;
315 else if (RT_FAILURE(rc))
316 {
317 AssertMsgFailed(("Configuration error: 32-bit \"QueueSize\" -> rc=%Rrc\n", rc));
318 return rc;
319 }
320
321 rc = PDMDrvHlpPDMQueueCreate(pDrvIns, sizeof(DRVKBDQUEUEITEM), cItems, cMilliesInterval, drvKbdQueueConsumer, "Keyboard", &pDrv->pQueue);
322 if (RT_FAILURE(rc))
323 {
324 AssertMsgFailed(("Failed to create driver: cItems=%d cMilliesInterval=%d rc=%Rrc\n", cItems, cMilliesInterval, rc));
325 return rc;
326 }
327
328 return VINF_SUCCESS;
329}
330
331
332/**
333 * Keyboard queue driver registration record.
334 */
335const PDMDRVREG g_DrvKeyboardQueue =
336{
337 /* u32Version */
338 PDM_DRVREG_VERSION,
339 /* szDriverName */
340 "KeyboardQueue",
341 /* pszDescription */
342 "Keyboard queue driver to plug in between the key source and the device to do queueing and inter-thread transport.",
343 /* fFlags */
344 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
345 /* fClass. */
346 PDM_DRVREG_CLASS_KEYBOARD,
347 /* cMaxInstances */
348 ~0,
349 /* cbInstance */
350 sizeof(DRVKBDQUEUE),
351 /* pfnConstruct */
352 drvKbdQueueConstruct,
353 /* pfnDestruct */
354 NULL,
355 /* pfnIOCtl */
356 NULL,
357 /* pfnPowerOn */
358 drvKbdQueuePowerOn,
359 /* pfnReset */
360 drvKbdQueueReset,
361 /* pfnSuspend */
362 drvKbdQueueSuspend,
363 /* pfnResume */
364 drvKbdQueueResume,
365 /* pfnDetach */
366 NULL,
367 /** pfnPowerOff */
368 drvKbdQueuePowerOff
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