VirtualBox

source: vbox/trunk/src/VBox/Devices/Input/DrvMouseQueue.cpp@ 28587

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

PDM critsects for drivers. Fixed critsect cleanup in failure path. Started on new transmit locking scheme (required for intnet buffer serialization).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.9 KB
Line 
1/* $Id: DrvMouseQueue.cpp 28258 2010-04-13 14:51:16Z vboxsync $ */
2/** @file
3 * VBox input devices: Mouse 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_MOUSE_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 * Mouse queue driver instance data.
40 *
41 * @implements PDMIMOUSECONNECTOR
42 * @implements PDMIMOUSEPORT
43 */
44typedef struct DRVMOUSEQUEUE
45{
46 /** Pointer to the driver instance structure. */
47 PPDMDRVINS pDrvIns;
48 /** Pointer to the mouse port interface of the driver/device above us. */
49 PPDMIMOUSEPORT pUpPort;
50 /** Pointer to the mouse port interface of the driver/device below us. */
51 PPDMIMOUSECONNECTOR pDownConnector;
52 /** Our mouse connector interface. */
53 PDMIMOUSECONNECTOR IConnector;
54 /** Our mouse port interface. */
55 PDMIMOUSEPORT 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} DRVMOUSEQUEUE, *PDRVMOUSEQUEUE;
62
63
64/**
65 * Mouse queue item.
66 */
67typedef struct DRVMOUSEQUEUEITEM
68{
69 /** The core part owned by the queue manager. */
70 PDMQUEUEITEMCORE Core;
71 uint32_t fAbs;
72 int32_t iDeltaX;
73 int32_t iDeltaY;
74 int32_t iDeltaZ;
75 int32_t iDeltaW;
76 uint32_t fButtonStates;
77 uint32_t uX;
78 uint32_t uY;
79} DRVMOUSEQUEUEITEM, *PDRVMOUSEQUEUEITEM;
80
81
82
83/* -=-=-=-=- IBase -=-=-=-=- */
84
85/**
86 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
87 */
88static DECLCALLBACK(void *) drvMouseQueueQueryInterface(PPDMIBASE pInterface, const char *pszIID)
89{
90 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
91 PDRVMOUSEQUEUE pThis = PDMINS_2_DATA(pDrvIns, PDRVMOUSEQUEUE);
92 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
93 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUSEPORT, &pThis->IPort);
94 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUSECONNECTOR, &pThis->IConnector);
95 return NULL;
96}
97
98
99/* -=-=-=-=- IMousePort -=-=-=-=- */
100
101/** Converts a pointer to DRVMOUSEQUEUE::Port to a DRVMOUSEQUEUE pointer. */
102#define IMOUSEPORT_2_DRVMOUSEQUEUE(pInterface) ( (PDRVMOUSEQUEUE)((char *)(pInterface) - RT_OFFSETOF(DRVMOUSEQUEUE, IPort)) )
103
104
105/**
106 * @interface_method_impl{PDMIMOUSEPORT,pfnPutEvent}
107 */
108static DECLCALLBACK(int) drvMouseQueuePutEvent(PPDMIMOUSEPORT pInterface, int32_t iDeltaX, int32_t iDeltaY, int32_t iDeltaZ, int32_t iDeltaW, uint32_t fButtonStates)
109{
110 PDRVMOUSEQUEUE pDrv = IMOUSEPORT_2_DRVMOUSEQUEUE(pInterface);
111 if (pDrv->fInactive)
112 return VINF_SUCCESS;
113
114 PDRVMOUSEQUEUEITEM pItem = (PDRVMOUSEQUEUEITEM)PDMQueueAlloc(pDrv->pQueue);
115 if (pItem)
116 {
117 pItem->fAbs = 0;
118 pItem->iDeltaX = iDeltaX;
119 pItem->iDeltaY = iDeltaY;
120 pItem->iDeltaZ = iDeltaZ;
121 pItem->iDeltaW = iDeltaW;
122 pItem->fButtonStates = fButtonStates;
123 pItem->uX = 0;
124 pItem->uY = 0;
125 PDMQueueInsert(pDrv->pQueue, &pItem->Core);
126 return VINF_SUCCESS;
127 }
128 return VERR_PDM_NO_QUEUE_ITEMS;
129}
130
131/**
132 * @interface_method_impl{PDMIMOUSEPORT,pfnPutEventAbs}
133 */
134static DECLCALLBACK(int) drvMouseQueuePutEventAbs(PPDMIMOUSEPORT pInterface, uint32_t uX, uint32_t uY, int32_t iDeltaZ, int32_t iDeltaW, uint32_t fButtonStates)
135{
136 PDRVMOUSEQUEUE pDrv = IMOUSEPORT_2_DRVMOUSEQUEUE(pInterface);
137 if (pDrv->fInactive)
138 return VINF_SUCCESS;
139
140 PDRVMOUSEQUEUEITEM pItem = (PDRVMOUSEQUEUEITEM)PDMQueueAlloc(pDrv->pQueue);
141 if (pItem)
142 {
143 pItem->fAbs = 1;
144 pItem->iDeltaX = 0;
145 pItem->iDeltaY = 0;
146 pItem->iDeltaZ = iDeltaZ;
147 pItem->iDeltaW = iDeltaW;
148 pItem->fButtonStates = fButtonStates;
149 pItem->uX = uX;
150 pItem->uY = uY;
151 PDMQueueInsert(pDrv->pQueue, &pItem->Core);
152 return VINF_SUCCESS;
153 }
154 return VERR_PDM_NO_QUEUE_ITEMS;
155}
156
157
158/* -=-=-=-=- IConnector -=-=-=-=- */
159
160#define PPDMIMOUSECONNECTOR_2_DRVMOUSEQUEUE(pInterface) ( (PDRVMOUSEQUEUE)((char *)(pInterface) - RT_OFFSETOF(DRVMOUSEQUEUE, IConnector)) )
161
162
163/**
164 * Pass absolute mode status changes from the guest through to the frontend
165 * driver.
166 *
167 * @param pInterface Pointer to the mouse connector interface structure.
168 * @param fAbs The new absolute mode state.
169 */
170static DECLCALLBACK(void) drvMousePassThruReportModes(PPDMIMOUSECONNECTOR pInterface, bool fRel, bool fAbs)
171{
172 PDRVMOUSEQUEUE pDrv = PPDMIMOUSECONNECTOR_2_DRVMOUSEQUEUE(pInterface);
173 pDrv->pDownConnector->pfnReportModes(pDrv->pDownConnector, fRel, fAbs);
174}
175
176
177
178/* -=-=-=-=- queue -=-=-=-=- */
179
180/**
181 * Queue callback for processing a queued item.
182 *
183 * @returns Success indicator.
184 * If false the item will not be removed and the flushing will stop.
185 * @param pDrvIns The driver instance.
186 * @param pItemCore Pointer to the queue item to process.
187 */
188static DECLCALLBACK(bool) drvMouseQueueConsumer(PPDMDRVINS pDrvIns, PPDMQUEUEITEMCORE pItemCore)
189{
190 PDRVMOUSEQUEUE pThis = PDMINS_2_DATA(pDrvIns, PDRVMOUSEQUEUE);
191 PDRVMOUSEQUEUEITEM pItem = (PDRVMOUSEQUEUEITEM)pItemCore;
192 int rc;
193 if (!pItem->fAbs)
194 rc = pThis->pUpPort->pfnPutEvent(pThis->pUpPort, pItem->iDeltaX, pItem->iDeltaY, pItem->iDeltaZ, pItem->iDeltaW, pItem->fButtonStates);
195 else
196 rc = pThis->pUpPort->pfnPutEventAbs(pThis->pUpPort, pItem->uX, pItem->uY, pItem->iDeltaZ, pItem->iDeltaW, pItem->fButtonStates);
197 return RT_SUCCESS(rc);
198}
199
200
201/* -=-=-=-=- driver interface -=-=-=-=- */
202
203/**
204 * Power On notification.
205 *
206 * @returns VBox status.
207 * @param pDrvIns The drive instance data.
208 */
209static DECLCALLBACK(void) drvMouseQueuePowerOn(PPDMDRVINS pDrvIns)
210{
211 PDRVMOUSEQUEUE pThis = PDMINS_2_DATA(pDrvIns, PDRVMOUSEQUEUE);
212 pThis->fInactive = false;
213}
214
215
216/**
217 * Reset notification.
218 *
219 * @returns VBox status.
220 * @param pDrvIns The drive instance data.
221 */
222static DECLCALLBACK(void) drvMouseQueueReset(PPDMDRVINS pDrvIns)
223{
224 //PDRVKBDQUEUE pThis = PDMINS_2_DATA(pDrvIns, PDRVKBDQUEUE);
225 /** @todo purge the queue on reset. */
226}
227
228
229/**
230 * Suspend notification.
231 *
232 * @returns VBox status.
233 * @param pDrvIns The drive instance data.
234 */
235static DECLCALLBACK(void) drvMouseQueueSuspend(PPDMDRVINS pDrvIns)
236{
237 PDRVMOUSEQUEUE pThis = PDMINS_2_DATA(pDrvIns, PDRVMOUSEQUEUE);
238 pThis->fInactive = true;
239}
240
241
242/**
243 * Resume notification.
244 *
245 * @returns VBox status.
246 * @param pDrvIns The drive instance data.
247 */
248static DECLCALLBACK(void) drvMouseQueueResume(PPDMDRVINS pDrvIns)
249{
250 PDRVMOUSEQUEUE pThis = PDMINS_2_DATA(pDrvIns, PDRVMOUSEQUEUE);
251 pThis->fInactive = false;
252}
253
254
255/**
256 * Power Off notification.
257 *
258 * @param pDrvIns The drive instance data.
259 */
260static DECLCALLBACK(void) drvMouseQueuePowerOff(PPDMDRVINS pDrvIns)
261{
262 PDRVMOUSEQUEUE pThis = PDMINS_2_DATA(pDrvIns, PDRVMOUSEQUEUE);
263 pThis->fInactive = true;
264}
265
266
267/**
268 * Construct a mouse driver instance.
269 *
270 * @copydoc FNPDMDRVCONSTRUCT
271 */
272static DECLCALLBACK(int) drvMouseQueueConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
273{
274 PDRVMOUSEQUEUE pDrv = PDMINS_2_DATA(pDrvIns, PDRVMOUSEQUEUE);
275 LogFlow(("drvMouseQueueConstruct: iInstance=%d\n", pDrvIns->iInstance));
276 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
277
278 /*
279 * Validate configuration.
280 */
281 if (!CFGMR3AreValuesValid(pCfg, "QueueSize\0Interval\0"))
282 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
283
284 /*
285 * Init basic data members and interfaces.
286 */
287 pDrv->fInactive = true;
288 /* IBase. */
289 pDrvIns->IBase.pfnQueryInterface = drvMouseQueueQueryInterface;
290 /* IMouseConnector. */
291 pDrv->IConnector.pfnReportModes = drvMousePassThruReportModes;
292 /* IMousePort. */
293 pDrv->IPort.pfnPutEvent = drvMouseQueuePutEvent;
294 pDrv->IPort.pfnPutEventAbs = drvMouseQueuePutEventAbs;
295
296 /*
297 * Get the IMousePort interface of the above driver/device.
298 */
299 pDrv->pUpPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMOUSEPORT);
300 if (!pDrv->pUpPort)
301 {
302 AssertMsgFailed(("Configuration error: No mouse port interface above!\n"));
303 return VERR_PDM_MISSING_INTERFACE_ABOVE;
304 }
305
306 /*
307 * Attach driver below and query it's connector interface.
308 */
309 PPDMIBASE pDownBase;
310 int rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pDownBase);
311 if (RT_FAILURE(rc))
312 {
313 AssertMsgFailed(("Failed to attach driver below us! rc=%Rra\n", rc));
314 return rc;
315 }
316 pDrv->pDownConnector = PDMIBASE_QUERY_INTERFACE(pDownBase, PDMIMOUSECONNECTOR);
317 if (!pDrv->pDownConnector)
318 {
319 AssertMsgFailed(("Configuration error: No mouse connector interface below!\n"));
320 return VERR_PDM_MISSING_INTERFACE_BELOW;
321 }
322
323 /*
324 * Create the queue.
325 */
326 uint32_t cMilliesInterval = 0;
327 rc = CFGMR3QueryU32(pCfg, "Interval", &cMilliesInterval);
328 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
329 cMilliesInterval = 0;
330 else if (RT_FAILURE(rc))
331 {
332 AssertMsgFailed(("Configuration error: 32-bit \"Interval\" -> rc=%Rrc\n", rc));
333 return rc;
334 }
335
336 uint32_t cItems = 0;
337 rc = CFGMR3QueryU32(pCfg, "QueueSize", &cItems);
338 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
339 cItems = 128;
340 else if (RT_FAILURE(rc))
341 {
342 AssertMsgFailed(("Configuration error: 32-bit \"QueueSize\" -> rc=%Rrc\n", rc));
343 return rc;
344 }
345
346 rc = PDMDrvHlpQueueCreate(pDrvIns, sizeof(DRVMOUSEQUEUEITEM), cItems, cMilliesInterval, drvMouseQueueConsumer, "Mouse", &pDrv->pQueue);
347 if (RT_FAILURE(rc))
348 {
349 AssertMsgFailed(("Failed to create driver: cItems=%d cMilliesInterval=%d rc=%Rrc\n", cItems, cMilliesInterval, rc));
350 return rc;
351 }
352
353 return VINF_SUCCESS;
354}
355
356
357/**
358 * Mouse queue driver registration record.
359 */
360const PDMDRVREG g_DrvMouseQueue =
361{
362 /* u32Version */
363 PDM_DRVREG_VERSION,
364 /* szName */
365 "MouseQueue",
366 /* szRCMod */
367 "",
368 /* szR0Mod */
369 "",
370 /* pszDescription */
371 "Mouse queue driver to plug in between the key source and the device to do queueing and inter-thread transport.",
372 /* fFlags */
373 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
374 /* fClass. */
375 PDM_DRVREG_CLASS_MOUSE,
376 /* cMaxInstances */
377 ~0,
378 /* cbInstance */
379 sizeof(DRVMOUSEQUEUE),
380 /* pfnConstruct */
381 drvMouseQueueConstruct,
382 /* pfnRelocate */
383 NULL,
384 /* pfnDestruct */
385 NULL,
386 /* pfnIOCtl */
387 NULL,
388 /* pfnPowerOn */
389 drvMouseQueuePowerOn,
390 /* pfnReset */
391 drvMouseQueueReset,
392 /* pfnSuspend */
393 drvMouseQueueSuspend,
394 /* pfnResume */
395 drvMouseQueueResume,
396 /* pfnAttach */
397 NULL,
398 /* pfnDetach */
399 NULL,
400 /* pfnPowerOff */
401 drvMouseQueuePowerOff,
402 /* pfnSoftReset */
403 NULL,
404 /* u32EndVersion */
405 PDM_DRVREG_VERSION
406};
407
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