VirtualBox

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

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

pdmifs, Devices/Input, Main, FE/BFE: add support for absolute-only pointing devices

  • 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 26935 2010-03-02 10:32:28Z 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 = PDMDrvHlpPDMQueueCreate(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