VirtualBox

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

Last change on this file since 98410 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.3 KB
Line 
1/* $Id: DrvMouseQueue.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBox input devices: Mouse queue driver
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_DRV_MOUSE_QUEUE
33#include <VBox/vmm/pdmdrv.h>
34#include <iprt/assert.h>
35#include <iprt/uuid.h>
36
37#include "VBoxDD.h"
38
39
40
41/*********************************************************************************************************************************
42* Structures and Typedefs *
43*********************************************************************************************************************************/
44/**
45 * Mouse queue driver instance data.
46 *
47 * @implements PDMIMOUSECONNECTOR
48 * @implements PDMIMOUSEPORT
49 */
50typedef struct DRVMOUSEQUEUE
51{
52 /** Pointer to the driver instance structure. */
53 PPDMDRVINS pDrvIns;
54 /** Pointer to the mouse port interface of the driver/device above us. */
55 PPDMIMOUSEPORT pUpPort;
56 /** Pointer to the mouse port interface of the driver/device below us. */
57 PPDMIMOUSECONNECTOR pDownConnector;
58 /** Our mouse connector interface. */
59 PDMIMOUSECONNECTOR IConnector;
60 /** Our mouse port interface. */
61 PDMIMOUSEPORT IPort;
62 /** The queue handle. */
63 PDMQUEUEHANDLE hQueue;
64 /** Discard input when this flag is set.
65 * We only accept input when the VM is running. */
66 bool fInactive;
67} DRVMOUSEQUEUE, *PDRVMOUSEQUEUE;
68
69
70/**
71 * Event type for @a DRVMOUSEQUEUEITEM
72 */
73enum EVENTTYPE { RELATIVE, ABSOLUTE };
74
75/**
76 * Mouse queue item.
77 */
78typedef struct DRVMOUSEQUEUEITEM
79{
80 /** The core part owned by the queue manager. */
81 PDMQUEUEITEMCORE Core;
82 enum EVENTTYPE enmType;
83 union
84 {
85 uint32_t padding[5];
86 struct
87 {
88 uint32_t fButtons;
89 int32_t dx;
90 int32_t dy;
91 int32_t dz;
92 int32_t dw;
93 } Relative;
94 struct
95 {
96 uint32_t fButtons;
97 uint32_t x;
98 uint32_t y;
99 int32_t dz;
100 int32_t dw;
101 } Absolute;
102 } u;
103} DRVMOUSEQUEUEITEM, *PDRVMOUSEQUEUEITEM;
104
105
106
107/* -=-=-=-=- IBase -=-=-=-=- */
108
109/**
110 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
111 */
112static DECLCALLBACK(void *) drvMouseQueueQueryInterface(PPDMIBASE pInterface, const char *pszIID)
113{
114 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
115 PDRVMOUSEQUEUE pThis = PDMINS_2_DATA(pDrvIns, PDRVMOUSEQUEUE);
116 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
117 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUSEPORT, &pThis->IPort);
118 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUSECONNECTOR, &pThis->IConnector);
119 return NULL;
120}
121
122
123/* -=-=-=-=- IMousePort -=-=-=-=- */
124
125/** Converts a pointer to DRVMOUSEQUEUE::Port to a DRVMOUSEQUEUE pointer. */
126#define IMOUSEPORT_2_DRVMOUSEQUEUE(pInterface) ( (PDRVMOUSEQUEUE)((char *)(pInterface) - RT_UOFFSETOF(DRVMOUSEQUEUE, IPort)) )
127
128
129/**
130 * @interface_method_impl{PDMIMOUSEPORT,pfnPutEvent}
131 */
132static DECLCALLBACK(int) drvMouseQueuePutEvent(PPDMIMOUSEPORT pInterface,
133 int32_t dx, int32_t dy,
134 int32_t dz, int32_t dw,
135 uint32_t fButtons)
136{
137 PDRVMOUSEQUEUE pDrv = IMOUSEPORT_2_DRVMOUSEQUEUE(pInterface);
138 if (pDrv->fInactive)
139 return VINF_SUCCESS;
140
141 PDRVMOUSEQUEUEITEM pItem = (PDRVMOUSEQUEUEITEM)PDMDrvHlpQueueAlloc(pDrv->pDrvIns, pDrv->hQueue);
142 if (pItem)
143 {
144 RT_ZERO(pItem->u.padding);
145 pItem->enmType = RELATIVE;
146 pItem->u.Relative.dx = dx;
147 pItem->u.Relative.dy = dy;
148 pItem->u.Relative.dz = dz;
149 pItem->u.Relative.dw = dw;
150 pItem->u.Relative.fButtons = fButtons;
151 PDMDrvHlpQueueInsert(pDrv->pDrvIns, pDrv->hQueue, &pItem->Core);
152 return VINF_SUCCESS;
153 }
154 return VERR_PDM_NO_QUEUE_ITEMS;
155}
156
157/**
158 * @interface_method_impl{PDMIMOUSEPORT,pfnPutEventAbs}
159 */
160static DECLCALLBACK(int) drvMouseQueuePutEventAbs(PPDMIMOUSEPORT pInterface,
161 uint32_t x, uint32_t y,
162 int32_t dz, int32_t dw,
163 uint32_t fButtons)
164{
165 PDRVMOUSEQUEUE pDrv = IMOUSEPORT_2_DRVMOUSEQUEUE(pInterface);
166 if (pDrv->fInactive)
167 return VINF_SUCCESS;
168
169 PDRVMOUSEQUEUEITEM pItem = (PDRVMOUSEQUEUEITEM)PDMDrvHlpQueueAlloc(pDrv->pDrvIns, pDrv->hQueue);
170 if (pItem)
171 {
172 RT_ZERO(pItem->u.padding);
173 pItem->enmType = ABSOLUTE;
174 pItem->u.Absolute.x = x;
175 pItem->u.Absolute.y = y;
176 pItem->u.Absolute.dz = dz;
177 pItem->u.Absolute.dw = dw;
178 pItem->u.Absolute.fButtons = fButtons;
179 PDMDrvHlpQueueInsert(pDrv->pDrvIns, pDrv->hQueue, &pItem->Core);
180 return VINF_SUCCESS;
181 }
182 return VERR_PDM_NO_QUEUE_ITEMS;
183}
184
185
186static DECLCALLBACK(int) drvMouseQueuePutEventMTAbs(PPDMIMOUSEPORT pInterface,
187 uint8_t cContacts,
188 const uint64_t *pau64Contacts,
189 uint32_t u32ScanTime)
190{
191 PDRVMOUSEQUEUE pThis = IMOUSEPORT_2_DRVMOUSEQUEUE(pInterface);
192 return pThis->pUpPort->pfnPutEventTouchScreen(pThis->pUpPort, cContacts, pau64Contacts, u32ScanTime);
193}
194
195static DECLCALLBACK(int) drvMouseQueuePutEventMTRel(PPDMIMOUSEPORT pInterface,
196 uint8_t cContacts,
197 const uint64_t *pau64Contacts,
198 uint32_t u32ScanTime)
199{
200 PDRVMOUSEQUEUE pThis = IMOUSEPORT_2_DRVMOUSEQUEUE(pInterface);
201 return pThis->pUpPort->pfnPutEventTouchPad(pThis->pUpPort, cContacts, pau64Contacts, u32ScanTime);
202}
203
204/* -=-=-=-=- IConnector -=-=-=-=- */
205
206#define PPDMIMOUSECONNECTOR_2_DRVMOUSEQUEUE(pInterface) ( (PDRVMOUSEQUEUE)((char *)(pInterface) - RT_UOFFSETOF(DRVMOUSEQUEUE, IConnector)) )
207
208
209/**
210 * Pass absolute mode status changes from the guest through to the frontend
211 * driver.
212 *
213 * @param pInterface Pointer to the mouse connector interface structure.
214 * @param fRel Is relative reporting supported?
215 * @param fAbs Is absolute reporting supported?
216 * @param fMTAbs Is absolute multi-touch reporting supported?
217 * @param fMTRel Is relative multi-touch reporting supported?
218 */
219static DECLCALLBACK(void) drvMousePassThruReportModes(PPDMIMOUSECONNECTOR pInterface, bool fRel, bool fAbs, bool fMTAbs, bool fMTRel)
220{
221 PDRVMOUSEQUEUE pDrv = PPDMIMOUSECONNECTOR_2_DRVMOUSEQUEUE(pInterface);
222 pDrv->pDownConnector->pfnReportModes(pDrv->pDownConnector, fRel, fAbs, fMTAbs, fMTRel);
223}
224
225
226/**
227 * Flush the mouse queue if there are pending events.
228 *
229 * @param pInterface Pointer to the mouse connector interface structure.
230 */
231static DECLCALLBACK(void) drvMouseFlushQueue(PPDMIMOUSECONNECTOR pInterface)
232{
233 PDRVMOUSEQUEUE pDrv = PPDMIMOUSECONNECTOR_2_DRVMOUSEQUEUE(pInterface);
234
235 PDMDrvHlpQueueFlushIfNecessary(pDrv->pDrvIns, pDrv->hQueue);
236}
237
238
239
240/* -=-=-=-=- queue -=-=-=-=- */
241
242/**
243 * Queue callback for processing a queued item.
244 *
245 * @returns Success indicator.
246 * If false the item will not be removed and the flushing will stop.
247 * @param pDrvIns The driver instance.
248 * @param pItemCore Pointer to the queue item to process.
249 */
250static DECLCALLBACK(bool) drvMouseQueueConsumer(PPDMDRVINS pDrvIns, PPDMQUEUEITEMCORE pItemCore)
251{
252 PDRVMOUSEQUEUE pThis = PDMINS_2_DATA(pDrvIns, PDRVMOUSEQUEUE);
253 PDRVMOUSEQUEUEITEM pItem = (PDRVMOUSEQUEUEITEM)pItemCore;
254 int rc;
255 if (pItem->enmType == RELATIVE)
256 rc = pThis->pUpPort->pfnPutEvent(pThis->pUpPort,
257 pItem->u.Relative.dx,
258 pItem->u.Relative.dy,
259 pItem->u.Relative.dz,
260 pItem->u.Relative.dw,
261 pItem->u.Relative.fButtons);
262 else if (pItem->enmType == ABSOLUTE)
263 rc = pThis->pUpPort->pfnPutEventAbs(pThis->pUpPort,
264 pItem->u.Absolute.x,
265 pItem->u.Absolute.y,
266 pItem->u.Absolute.dz,
267 pItem->u.Absolute.dw,
268 pItem->u.Absolute.fButtons);
269 else
270 AssertMsgFailedReturn(("enmType=%d\n", pItem->enmType), true /* remove buggy data */);
271 return rc != VERR_TRY_AGAIN;
272}
273
274
275/* -=-=-=-=- driver interface -=-=-=-=- */
276
277/**
278 * Power On notification.
279 *
280 * @returns VBox status code.
281 * @param pDrvIns The drive instance data.
282 */
283static DECLCALLBACK(void) drvMouseQueuePowerOn(PPDMDRVINS pDrvIns)
284{
285 PDRVMOUSEQUEUE pThis = PDMINS_2_DATA(pDrvIns, PDRVMOUSEQUEUE);
286 pThis->fInactive = false;
287}
288
289
290/**
291 * Reset notification.
292 *
293 * @returns VBox status code.
294 * @param pDrvIns The drive instance data.
295 */
296static DECLCALLBACK(void) drvMouseQueueReset(PPDMDRVINS pDrvIns)
297{
298 //PDRVKBDQUEUE pThis = PDMINS_2_DATA(pDrvIns, PDRVKBDQUEUE);
299 /** @todo purge the queue on reset. */
300 RT_NOREF(pDrvIns);
301}
302
303
304/**
305 * Suspend notification.
306 *
307 * @returns VBox status code.
308 * @param pDrvIns The drive instance data.
309 */
310static DECLCALLBACK(void) drvMouseQueueSuspend(PPDMDRVINS pDrvIns)
311{
312 PDRVMOUSEQUEUE pThis = PDMINS_2_DATA(pDrvIns, PDRVMOUSEQUEUE);
313 pThis->fInactive = true;
314}
315
316
317/**
318 * Resume notification.
319 *
320 * @returns VBox status code.
321 * @param pDrvIns The drive instance data.
322 */
323static DECLCALLBACK(void) drvMouseQueueResume(PPDMDRVINS pDrvIns)
324{
325 PDRVMOUSEQUEUE pThis = PDMINS_2_DATA(pDrvIns, PDRVMOUSEQUEUE);
326 pThis->fInactive = false;
327}
328
329
330/**
331 * Power Off notification.
332 *
333 * @param pDrvIns The drive instance data.
334 */
335static DECLCALLBACK(void) drvMouseQueuePowerOff(PPDMDRVINS pDrvIns)
336{
337 PDRVMOUSEQUEUE pThis = PDMINS_2_DATA(pDrvIns, PDRVMOUSEQUEUE);
338 pThis->fInactive = true;
339}
340
341
342/**
343 * Construct a mouse driver instance.
344 *
345 * @copydoc FNPDMDRVCONSTRUCT
346 */
347static DECLCALLBACK(int) drvMouseQueueConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
348{
349 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
350 PDRVMOUSEQUEUE pDrv = PDMINS_2_DATA(pDrvIns, PDRVMOUSEQUEUE);
351 PCPDMDRVHLPR3 pHlp = pDrvIns->pHlpR3;
352
353 LogFlow(("drvMouseQueueConstruct: iInstance=%d\n", pDrvIns->iInstance));
354
355 /*
356 * Validate configuration.
357 */
358 PDMDRV_VALIDATE_CONFIG_RETURN(pDrvIns, "QueueSize|Interval", "");
359
360 /*
361 * Init basic data members and interfaces.
362 */
363 pDrv->pDrvIns = pDrvIns;
364 pDrv->fInactive = true;
365 /* IBase. */
366 pDrvIns->IBase.pfnQueryInterface = drvMouseQueueQueryInterface;
367 /* IMouseConnector. */
368 pDrv->IConnector.pfnReportModes = drvMousePassThruReportModes;
369 pDrv->IConnector.pfnFlushQueue = drvMouseFlushQueue;
370 /* IMousePort. */
371 pDrv->IPort.pfnPutEvent = drvMouseQueuePutEvent;
372 pDrv->IPort.pfnPutEventAbs = drvMouseQueuePutEventAbs;
373 pDrv->IPort.pfnPutEventTouchScreen = drvMouseQueuePutEventMTAbs;
374 pDrv->IPort.pfnPutEventTouchPad = drvMouseQueuePutEventMTRel;
375
376 /*
377 * Get the IMousePort interface of the above driver/device.
378 */
379 pDrv->pUpPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMOUSEPORT);
380 AssertMsgReturn(pDrv->pUpPort, ("Configuration error: No mouse port interface above!\n"), VERR_PDM_MISSING_INTERFACE_ABOVE);
381
382 /*
383 * Attach driver below and query it's connector interface.
384 */
385 PPDMIBASE pDownBase;
386 int rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pDownBase);
387 AssertMsgRCReturn(rc, ("Failed to attach driver below us! rc=%Rra\n", rc), rc);
388
389 pDrv->pDownConnector = PDMIBASE_QUERY_INTERFACE(pDownBase, PDMIMOUSECONNECTOR);
390 AssertMsgReturn(pDrv->pDownConnector, ("Configuration error: No mouse connector interface below!\n"),
391 VERR_PDM_MISSING_INTERFACE_BELOW);
392
393 /*
394 * Create the queue.
395 */
396 uint32_t cMilliesInterval = 0;
397 rc = pHlp->pfnCFGMQueryU32(pCfg, "Interval", &cMilliesInterval);
398 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
399 cMilliesInterval = 0;
400 else
401 AssertMsgRCReturn(rc, ("Configuration error: 32-bit \"Interval\" -> rc=%Rrc\n", rc), rc);
402
403 uint32_t cItems = 0;
404 rc = pHlp->pfnCFGMQueryU32(pCfg, "QueueSize", &cItems);
405 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
406 cItems = 128;
407 else
408 AssertMsgRCReturn(rc, ("Configuration error: 32-bit \"QueueSize\" -> rc=%Rrc\n", rc), rc);
409
410 rc = PDMDrvHlpQueueCreate(pDrvIns, sizeof(DRVMOUSEQUEUEITEM), cItems, cMilliesInterval,
411 drvMouseQueueConsumer, "Mouse", &pDrv->hQueue);
412 AssertMsgRCReturn(rc, ("Failed to create driver: cItems=%d cMilliesInterval=%d rc=%Rrc\n", cItems, cMilliesInterval, rc), rc);
413
414 return VINF_SUCCESS;
415}
416
417
418/**
419 * Mouse queue driver registration record.
420 */
421const PDMDRVREG g_DrvMouseQueue =
422{
423 /* u32Version */
424 PDM_DRVREG_VERSION,
425 /* szName */
426 "MouseQueue",
427 /* szRCMod */
428 "",
429 /* szR0Mod */
430 "",
431 /* pszDescription */
432 "Mouse queue driver to plug in between the key source and the device to do queueing and inter-thread transport.",
433 /* fFlags */
434 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
435 /* fClass. */
436 PDM_DRVREG_CLASS_MOUSE,
437 /* cMaxInstances */
438 ~0U,
439 /* cbInstance */
440 sizeof(DRVMOUSEQUEUE),
441 /* pfnConstruct */
442 drvMouseQueueConstruct,
443 /* pfnRelocate */
444 NULL,
445 /* pfnDestruct */
446 NULL,
447 /* pfnIOCtl */
448 NULL,
449 /* pfnPowerOn */
450 drvMouseQueuePowerOn,
451 /* pfnReset */
452 drvMouseQueueReset,
453 /* pfnSuspend */
454 drvMouseQueueSuspend,
455 /* pfnResume */
456 drvMouseQueueResume,
457 /* pfnAttach */
458 NULL,
459 /* pfnDetach */
460 NULL,
461 /* pfnPowerOff */
462 drvMouseQueuePowerOff,
463 /* pfnSoftReset */
464 NULL,
465 /* u32EndVersion */
466 PDM_DRVREG_VERSION
467};
468
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