VirtualBox

source: vbox/trunk/src/VBox/Main/MouseImpl.cpp@ 30760

Last change on this file since 30760 was 30760, checked in by vboxsync, 14 years ago

Main: separate internal machine data structs into MachineImplPrivate.h to significantly speed up compilation and for better interface separation; remove obsolete ConsoleEvents.h file

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.0 KB
Line 
1/* $Id: MouseImpl.cpp 30760 2010-07-09 13:12:04Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2008 Oracle Corporation
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
18#include <iprt/cpp/utils.h>
19
20#include "MouseImpl.h"
21#include "DisplayImpl.h"
22#include "VMMDev.h"
23#include "ConsoleImpl.h"
24
25#include "AutoCaller.h"
26#include "Logging.h"
27
28#include <VBox/pdmdrv.h>
29
30#include <iprt/asm.h>
31
32#include <VBox/VMMDev.h>
33
34/** @name Mouse device capabilities bitfield
35 * @{ */
36enum
37{
38 /** The mouse device can do relative reporting */
39 MOUSE_DEVCAP_RELATIVE = 1,
40 /** The mouse device can do absolute reporting */
41 MOUSE_DEVCAP_ABSOLUTE = 2
42};
43/** @} */
44
45/**
46 * Mouse driver instance data.
47 */
48struct DRVMAINMOUSE
49{
50 /** Pointer to the mouse object. */
51 Mouse *pMouse;
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 /** Our mouse connector interface. */
57 PDMIMOUSECONNECTOR IConnector;
58 /** The capabilities of this device. */
59 uint32_t u32DevCaps;
60};
61
62// constructor / destructor
63/////////////////////////////////////////////////////////////////////////////
64
65Mouse::Mouse()
66 : mParent(NULL)
67{
68}
69
70Mouse::~Mouse()
71{
72}
73
74
75HRESULT Mouse::FinalConstruct()
76{
77 RT_ZERO(mpDrv);
78 fVMMDevCanAbs = false;
79 fVMMDevNeedsHostCursor = false;
80 mLastAbsX = 0x8000;
81 mLastAbsY = 0x8000;
82 mLastButtons = 0;
83 return S_OK;
84}
85
86void Mouse::FinalRelease()
87{
88 uninit();
89}
90
91// public methods only for internal purposes
92/////////////////////////////////////////////////////////////////////////////
93
94/**
95 * Initializes the mouse object.
96 *
97 * @returns COM result indicator
98 * @param parent handle of our parent object
99 */
100HRESULT Mouse::init (Console *parent)
101{
102 LogFlowThisFunc(("\n"));
103
104 ComAssertRet(parent, E_INVALIDARG);
105
106 /* Enclose the state transition NotReady->InInit->Ready */
107 AutoInitSpan autoInitSpan(this);
108 AssertReturn(autoInitSpan.isOk(), E_FAIL);
109
110 unconst(mParent) = parent;
111
112#ifdef RT_OS_L4
113 /* L4 console has no own mouse cursor */
114 uHostCaps = VMMDEV_MOUSE_HOST_CANNOT_HWPOINTER;
115#else
116 uHostCaps = 0;
117#endif
118
119 /* Confirm a successful initialization */
120 autoInitSpan.setSucceeded();
121
122 return S_OK;
123}
124
125/**
126 * Uninitializes the instance and sets the ready flag to FALSE.
127 * Called either from FinalRelease() or by the parent when it gets destroyed.
128 */
129void Mouse::uninit()
130{
131 LogFlowThisFunc(("\n"));
132
133 /* Enclose the state transition Ready->InUninit->NotReady */
134 AutoUninitSpan autoUninitSpan(this);
135 if (autoUninitSpan.uninitDone())
136 return;
137
138 for (unsigned i = 0; i < MOUSE_MAX_DEVICES; ++i)
139 {
140 if (mpDrv[i])
141 mpDrv[i]->pMouse = NULL;
142 mpDrv[i] = NULL;
143 }
144
145#ifdef VBOXBFE_WITHOUT_COM
146 mParent = NULL;
147#else
148 unconst(mParent) = NULL;
149#endif
150}
151
152
153// IMouse properties
154/////////////////////////////////////////////////////////////////////////////
155
156HRESULT Mouse::getVMMDevMouseCaps(uint32_t *pfCaps)
157{
158 AssertPtrReturn(pfCaps, E_POINTER);
159 VMMDev *pVMMDev = mParent->getVMMDev();
160 ComAssertRet(pVMMDev, E_FAIL);
161 PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
162 ComAssertRet(pVMMDevPort, E_FAIL);
163
164 int rc = pVMMDevPort->pfnQueryMouseCapabilities(pVMMDevPort, pfCaps);
165 return RT_SUCCESS(rc) ? S_OK : E_FAIL;
166}
167
168HRESULT Mouse::setVMMDevMouseCaps(uint32_t fCaps)
169{
170 VMMDev *pVMMDev = mParent->getVMMDev();
171 ComAssertRet(pVMMDev, E_FAIL);
172 PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
173 ComAssertRet(pVMMDevPort, E_FAIL);
174
175 int rc = pVMMDevPort->pfnSetMouseCapabilities(pVMMDevPort, fCaps);
176 return RT_SUCCESS(rc) ? S_OK : E_FAIL;
177}
178
179/**
180 * Returns whether the current setup can accept absolute mouse
181 * events.
182 *
183 * @returns COM status code
184 * @param absoluteSupported address of result variable
185 */
186STDMETHODIMP Mouse::COMGETTER(AbsoluteSupported) (BOOL *absoluteSupported)
187{
188 if (!absoluteSupported)
189 return E_POINTER;
190
191 AutoCaller autoCaller(this);
192 if (FAILED(autoCaller.rc())) return autoCaller.rc();
193
194 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
195 bool fAbs = false;
196
197 if (fVMMDevCanAbs)
198 fAbs = TRUE;
199
200 for (unsigned i = 0; i < MOUSE_MAX_DEVICES; ++i)
201 if (mpDrv[i] && (mpDrv[i]->u32DevCaps & MOUSE_DEVCAP_ABSOLUTE))
202 fAbs = TRUE;
203
204 *absoluteSupported = fAbs;
205 return S_OK;
206}
207
208/**
209 * Returns whether the current setup can accept relative mouse
210 * events.
211 *
212 * @returns COM status code
213 * @param relativeSupported address of result variable
214 */
215STDMETHODIMP Mouse::COMGETTER(RelativeSupported) (BOOL *relativeSupported)
216{
217 if (!relativeSupported)
218 return E_POINTER;
219
220 AutoCaller autoCaller(this);
221 if (FAILED(autoCaller.rc())) return autoCaller.rc();
222
223 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
224 bool fRel = false;
225
226 for (unsigned i = 0; i < MOUSE_MAX_DEVICES; ++i)
227 if (mpDrv[i] && (mpDrv[i]->u32DevCaps & MOUSE_DEVCAP_RELATIVE))
228 fRel = TRUE;
229
230 *relativeSupported = fRel;
231 return S_OK;
232}
233
234/**
235 * Returns whether the guest can currently draw the mouse cursor itself.
236 *
237 * @returns COM status code
238 * @param pfNeedsHostCursor address of result variable
239 */
240STDMETHODIMP Mouse::COMGETTER(NeedsHostCursor) (BOOL *pfNeedsHostCursor)
241{
242 if (!pfNeedsHostCursor)
243 return E_POINTER;
244
245 AutoCaller autoCaller(this);
246 if (FAILED(autoCaller.rc())) return autoCaller.rc();
247
248 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
249
250 *pfNeedsHostCursor = fVMMDevNeedsHostCursor;
251 return S_OK;
252}
253
254// IMouse methods
255/////////////////////////////////////////////////////////////////////////////
256
257static uint32_t mouseButtonsToPDM(LONG buttonState)
258{
259 uint32_t fButtons = 0;
260 if (buttonState & MouseButtonState_LeftButton)
261 fButtons |= PDMIMOUSEPORT_BUTTON_LEFT;
262 if (buttonState & MouseButtonState_RightButton)
263 fButtons |= PDMIMOUSEPORT_BUTTON_RIGHT;
264 if (buttonState & MouseButtonState_MiddleButton)
265 fButtons |= PDMIMOUSEPORT_BUTTON_MIDDLE;
266 if (buttonState & MouseButtonState_XButton1)
267 fButtons |= PDMIMOUSEPORT_BUTTON_X1;
268 if (buttonState & MouseButtonState_XButton2)
269 fButtons |= PDMIMOUSEPORT_BUTTON_X2;
270 return fButtons;
271}
272
273
274/**
275 * Send a relative event to the mouse device.
276 *
277 * @returns COM status code
278 */
279HRESULT Mouse::reportRelEventToMouseDev(int32_t dx, int32_t dy, int32_t dz,
280 int32_t dw, uint32_t fButtons)
281{
282 if (dx || dy || dz || dw || fButtons != mLastButtons)
283 {
284 PPDMIMOUSEPORT pUpPort = NULL;
285 for (unsigned i = 0; !pUpPort && i < MOUSE_MAX_DEVICES; ++i)
286 {
287 if (mpDrv[i] && (mpDrv[i]->u32DevCaps & MOUSE_DEVCAP_RELATIVE))
288 pUpPort = mpDrv[i]->pUpPort;
289 }
290 if (!pUpPort)
291 return S_OK;
292
293 int vrc = pUpPort->pfnPutEvent(pUpPort, dx, dy, dz, dw, fButtons);
294
295 if (RT_FAILURE(vrc))
296 return setError(VBOX_E_IPRT_ERROR,
297 tr("Could not send the mouse event to the virtual mouse (%Rrc)"),
298 vrc);
299 }
300 return S_OK;
301}
302
303
304/**
305 * Send an absolute position event to the mouse device.
306 *
307 * @returns COM status code
308 */
309HRESULT Mouse::reportAbsEventToMouseDev(uint32_t mouseXAbs, uint32_t mouseYAbs,
310 int32_t dz, int32_t dw, uint32_t fButtons)
311{
312 if ( mouseXAbs != mLastAbsX || mouseYAbs != mLastAbsY
313 || dz || dw || fButtons != mLastButtons)
314 {
315 PPDMIMOUSEPORT pUpPort = NULL;
316 for (unsigned i = 0; !pUpPort && i < MOUSE_MAX_DEVICES; ++i)
317 {
318 if (mpDrv[i] && (mpDrv[i]->u32DevCaps & MOUSE_DEVCAP_ABSOLUTE))
319 pUpPort = mpDrv[i]->pUpPort;
320 }
321 if (!pUpPort)
322 return S_OK;
323
324 int vrc = pUpPort->pfnPutEventAbs(pUpPort, mouseXAbs, mouseYAbs, dz,
325 dw, fButtons);
326 if (RT_FAILURE(vrc))
327 return setError(VBOX_E_IPRT_ERROR,
328 tr("Could not send the mouse event to the virtual mouse (%Rrc)"),
329 vrc);
330 }
331 return S_OK;
332}
333
334
335/**
336 * Send an absolute position event to the VMM device.
337 *
338 * @returns COM status code
339 */
340HRESULT Mouse::reportAbsEventToVMMDev(uint32_t mouseXAbs, uint32_t mouseYAbs)
341{
342 VMMDev *pVMMDev = mParent->getVMMDev();
343 ComAssertRet(pVMMDev, E_FAIL);
344 PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
345 ComAssertRet(pVMMDevPort, E_FAIL);
346
347 if (mouseXAbs != mLastAbsX || mouseYAbs != mLastAbsY)
348 {
349 int vrc = pVMMDevPort->pfnSetAbsoluteMouse(pVMMDevPort,
350 mouseXAbs, mouseYAbs);
351 if (RT_FAILURE(vrc))
352 return setError(VBOX_E_IPRT_ERROR,
353 tr("Could not send the mouse event to the virtual mouse (%Rrc)"),
354 vrc);
355 }
356 return S_OK;
357}
358
359/**
360 * Send a mouse event.
361 *
362 * @returns COM status code
363 * @param dx X movement
364 * @param dy Y movement
365 * @param dz Z movement
366 * @param buttonState The mouse button state
367 */
368STDMETHODIMP Mouse::PutMouseEvent(LONG dx, LONG dy, LONG dz, LONG dw, LONG buttonState)
369{
370 HRESULT rc = S_OK;
371
372 AutoCaller autoCaller(this);
373 if (FAILED(autoCaller.rc())) return autoCaller.rc();
374
375 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
376
377 LogRel3(("%s: dx=%d, dy=%d, dz=%d, dw=%d\n", __PRETTY_FUNCTION__,
378 dx, dy, dz, dw));
379 /*
380 * This method being called implies that the host no
381 * longer wants to use absolute coordinates. If the VMM
382 * device isn't aware of that yet, tell it.
383 */
384 if (uHostCaps & VMMDEV_MOUSE_HOST_CAN_ABSOLUTE)
385 {
386 uHostCaps &= ~VMMDEV_MOUSE_HOST_CAN_ABSOLUTE;
387 setVMMDevMouseCaps(uHostCaps);
388 }
389
390 uint32_t fButtons = mouseButtonsToPDM(buttonState);
391 rc = reportRelEventToMouseDev(dx, dy, dz, dw, fButtons);
392 if (SUCCEEDED(rc))
393 mLastButtons = fButtons;
394
395 return rc;
396}
397
398/**
399 * Convert an X value in screen co-ordinates (starting from 1) to a value
400 * from 0 to 0xffff.
401 *
402 * @returns COM status value
403 */
404HRESULT Mouse::convertDisplayWidth(LONG x, uint32_t *pcX)
405{
406 AssertPtrReturn(pcX, E_POINTER);
407 Display *pDisplay = mParent->getDisplay();
408 ComAssertRet(pDisplay, E_FAIL);
409
410 ULONG displayWidth;
411 HRESULT rc = pDisplay->GetScreenResolution (0, &displayWidth, NULL, NULL);
412 if (FAILED(rc)) return rc;
413
414 *pcX = displayWidth ? ((x - 1) * 0xFFFF) / displayWidth: 0;
415 return S_OK;
416}
417
418/**
419 * Convert a Y value in screen co-ordinates (starting from 1) to a value
420 * from 0 to 0xffff.
421 *
422 * @returns COM status value
423 */
424HRESULT Mouse::convertDisplayHeight(LONG y, uint32_t *pcY)
425{
426 AssertPtrReturn(pcY, E_POINTER);
427 Display *pDisplay = mParent->getDisplay();
428 ComAssertRet(pDisplay, E_FAIL);
429
430 ULONG displayHeight;
431 HRESULT rc = pDisplay->GetScreenResolution (0, NULL, &displayHeight, NULL);
432 if (FAILED(rc)) return rc;
433
434 *pcY = displayHeight ? ((y - 1) * 0xFFFF) / displayHeight: 0;
435 return S_OK;
436}
437
438
439/**
440 * Send an absolute mouse event to the VM. This only works
441 * when the required guest support has been installed.
442 *
443 * @returns COM status code
444 * @param x X position (pixel), starting from 1
445 * @param y Y position (pixel), starting from 1
446 * @param dz Z movement
447 * @param buttonState The mouse button state
448 */
449STDMETHODIMP Mouse::PutMouseEventAbsolute(LONG x, LONG y, LONG dz, LONG dw,
450 LONG buttonState)
451{
452 AutoCaller autoCaller(this);
453 if (FAILED(autoCaller.rc())) return autoCaller.rc();
454
455 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
456
457 LogRel3(("%s: x=%d, y=%d, dz=%d, dw=%d, buttonState=0x%x\n",
458 __PRETTY_FUNCTION__, x, y, dz, dw, buttonState));
459
460 uint32_t mouseXAbs;
461 /** @todo the front end should do this conversion to avoid races */
462 HRESULT rc = convertDisplayWidth(x, &mouseXAbs);
463 if (FAILED(rc)) return rc;
464
465 /**
466 * @todo multi-monitor Windows guests expect this to be unbounded.
467 * Understand the issues involved and fix for the rest.
468 */
469 /* if (mouseXAbs > 0xffff)
470 mouseXAbs = mLastAbsX; */
471
472 uint32_t mouseYAbs;
473 rc = convertDisplayHeight(y, &mouseYAbs);
474 if (FAILED(rc)) return rc;
475 /* if (mouseYAbs > 0xffff)
476 mouseYAbs = mLastAbsY; */
477
478 uint32_t fButtons = mouseButtonsToPDM(buttonState);
479
480 uint32_t mouseCaps;
481 rc = getVMMDevMouseCaps(&mouseCaps);
482 if (FAILED(rc)) return rc;
483
484 /*
485 * This method being called implies that the host wants
486 * to use absolute coordinates. If the VMM device isn't
487 * aware of that yet, tell it.
488 */
489 if (!(mouseCaps & VMMDEV_MOUSE_HOST_CAN_ABSOLUTE))
490 {
491 uHostCaps |= VMMDEV_MOUSE_HOST_CAN_ABSOLUTE;
492 setVMMDevMouseCaps(uHostCaps);
493 }
494
495 if (fVMMDevCanAbs)
496 {
497 /*
498 * Send the absolute mouse position to the VMM device.
499 */
500 rc = reportAbsEventToVMMDev(mouseXAbs, mouseYAbs);
501 /* We may need to send an additional event for button information or
502 * to wake up older guests to the changed absolute co-ordinates. If
503 * the event is a pure wake up one, we make sure it contains some
504 * (possibly phony) event data to make sure it isn't just discarded
505 * on the way. */
506 bool fNeedsJiggle = !(mouseCaps & VMMDEV_MOUSE_GUEST_USES_VMMDEV);
507 if (fNeedsJiggle || fButtons != mLastButtons || dz || dw)
508 {
509 rc = reportRelEventToMouseDev(fNeedsJiggle ? 1 : 0, 0, dz, dw,
510 fButtons);
511 }
512 }
513 else
514 rc = reportAbsEventToMouseDev(mouseXAbs, mouseYAbs, dz, dw, fButtons);
515
516 if (FAILED(rc)) return rc;
517
518 mLastAbsX = mouseXAbs;
519 mLastAbsY = mouseYAbs;
520
521 mLastButtons = fButtons;
522 return rc;
523}
524
525// private methods
526/////////////////////////////////////////////////////////////////////////////
527
528
529void Mouse::sendMouseCapsNotifications(void)
530{
531 bool fAbsDev = false;
532 bool fRelDev = false;
533 uint32_t u32MouseCaps;
534 for (unsigned i = 0; i < MOUSE_MAX_DEVICES; ++i)
535 if (mpDrv[i])
536 {
537 if (mpDrv[i]->u32DevCaps & MOUSE_DEVCAP_ABSOLUTE)
538 fAbsDev = true;
539 if (mpDrv[i]->u32DevCaps & MOUSE_DEVCAP_RELATIVE)
540 fRelDev = true;
541 }
542 if (SUCCEEDED(getVMMDevMouseCaps(&u32MouseCaps)))
543 fVMMDevCanAbs = (u32MouseCaps & VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE)
544 && fRelDev;
545 else
546 fVMMDevCanAbs = false;
547 mParent->onMouseCapabilityChange(fAbsDev || fVMMDevCanAbs, fRelDev,
548 fVMMDevNeedsHostCursor);
549 /** @todo if this gets called during device initialisation we get an
550 * error due to VMMDev not being initialised yet. */
551 if (fAbsDev && !(uHostCaps & VMMDEV_MOUSE_HOST_HAS_ABS_DEV))
552 uHostCaps |= VMMDEV_MOUSE_HOST_HAS_ABS_DEV;
553 if (!fAbsDev && (uHostCaps & VMMDEV_MOUSE_HOST_HAS_ABS_DEV))
554 uHostCaps &= ~VMMDEV_MOUSE_HOST_HAS_ABS_DEV;
555 setVMMDevMouseCaps(uHostCaps);
556}
557
558
559/**
560 * @interface_method_impl{PDMIMOUSECONNECTOR,pfnReportModes}
561 */
562DECLCALLBACK(void) Mouse::mouseReportModes(PPDMIMOUSECONNECTOR pInterface, bool fRel, bool fAbs)
563{
564 PDRVMAINMOUSE pDrv = RT_FROM_MEMBER(pInterface, DRVMAINMOUSE, IConnector);
565 if (fRel)
566 pDrv->u32DevCaps |= MOUSE_DEVCAP_RELATIVE;
567 else
568 pDrv->u32DevCaps &= ~MOUSE_DEVCAP_RELATIVE;
569 if (fAbs)
570 pDrv->u32DevCaps |= MOUSE_DEVCAP_ABSOLUTE;
571 else
572 pDrv->u32DevCaps &= ~MOUSE_DEVCAP_ABSOLUTE;
573
574 pDrv->pMouse->sendMouseCapsNotifications();
575}
576
577
578/**
579 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
580 */
581DECLCALLBACK(void *) Mouse::drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
582{
583 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
584 PDRVMAINMOUSE pDrv = PDMINS_2_DATA(pDrvIns, PDRVMAINMOUSE);
585
586 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
587 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUSECONNECTOR, &pDrv->IConnector);
588 return NULL;
589}
590
591
592/**
593 * Destruct a mouse driver instance.
594 *
595 * @returns VBox status.
596 * @param pDrvIns The driver instance data.
597 */
598DECLCALLBACK(void) Mouse::drvDestruct(PPDMDRVINS pDrvIns)
599{
600 PDRVMAINMOUSE pData = PDMINS_2_DATA(pDrvIns, PDRVMAINMOUSE);
601 LogFlow(("Mouse::drvDestruct: iInstance=%d\n", pDrvIns->iInstance));
602 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
603
604 if (pData->pMouse)
605 {
606 AutoWriteLock mouseLock(pData->pMouse COMMA_LOCKVAL_SRC_POS);
607 for (unsigned cDev = 0; cDev < MOUSE_MAX_DEVICES; ++cDev)
608 if (pData->pMouse->mpDrv[cDev] == pData)
609 {
610 pData->pMouse->mpDrv[cDev] = NULL;
611 break;
612 }
613 }
614}
615
616
617/**
618 * Construct a mouse driver instance.
619 *
620 * @copydoc FNPDMDRVCONSTRUCT
621 */
622DECLCALLBACK(int) Mouse::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
623{
624 PDRVMAINMOUSE pData = PDMINS_2_DATA(pDrvIns, PDRVMAINMOUSE);
625 LogFlow(("drvMainMouse_Construct: iInstance=%d\n", pDrvIns->iInstance));
626 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
627
628 /*
629 * Validate configuration.
630 */
631 if (!CFGMR3AreValuesValid(pCfg, "Object\0"))
632 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
633 AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
634 ("Configuration error: Not possible to attach anything to this driver!\n"),
635 VERR_PDM_DRVINS_NO_ATTACH);
636
637 /*
638 * IBase.
639 */
640 pDrvIns->IBase.pfnQueryInterface = Mouse::drvQueryInterface;
641
642 pData->IConnector.pfnReportModes = Mouse::mouseReportModes;
643
644 /*
645 * Get the IMousePort interface of the above driver/device.
646 */
647 pData->pUpPort = (PPDMIMOUSEPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMIMOUSEPORT_IID);
648 if (!pData->pUpPort)
649 {
650 AssertMsgFailed(("Configuration error: No mouse port interface above!\n"));
651 return VERR_PDM_MISSING_INTERFACE_ABOVE;
652 }
653
654 /*
655 * Get the Mouse object pointer and update the mpDrv member.
656 */
657 void *pv;
658 int rc = CFGMR3QueryPtr(pCfg, "Object", &pv);
659 if (RT_FAILURE(rc))
660 {
661 AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
662 return rc;
663 }
664 pData->pMouse = (Mouse *)pv; /** @todo Check this cast! */
665 unsigned cDev;
666 for (cDev = 0; cDev < MOUSE_MAX_DEVICES; ++cDev)
667 if (!pData->pMouse->mpDrv[cDev])
668 {
669 pData->pMouse->mpDrv[cDev] = pData;
670 break;
671 }
672 if (cDev == MOUSE_MAX_DEVICES)
673 return VERR_NO_MORE_HANDLES;
674
675 return VINF_SUCCESS;
676}
677
678
679/**
680 * Main mouse driver registration record.
681 */
682const PDMDRVREG Mouse::DrvReg =
683{
684 /* u32Version */
685 PDM_DRVREG_VERSION,
686 /* szName */
687 "MainMouse",
688 /* szRCMod */
689 "",
690 /* szR0Mod */
691 "",
692 /* pszDescription */
693 "Main mouse driver (Main as in the API).",
694 /* fFlags */
695 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
696 /* fClass. */
697 PDM_DRVREG_CLASS_MOUSE,
698 /* cMaxInstances */
699 ~0,
700 /* cbInstance */
701 sizeof(DRVMAINMOUSE),
702 /* pfnConstruct */
703 Mouse::drvConstruct,
704 /* pfnDestruct */
705 Mouse::drvDestruct,
706 /* pfnRelocate */
707 NULL,
708 /* pfnIOCtl */
709 NULL,
710 /* pfnPowerOn */
711 NULL,
712 /* pfnReset */
713 NULL,
714 /* pfnSuspend */
715 NULL,
716 /* pfnResume */
717 NULL,
718 /* pfnAttach */
719 NULL,
720 /* pfnDetach */
721 NULL,
722 /* pfnPowerOff */
723 NULL,
724 /* pfnSoftReset */
725 NULL,
726 /* u32EndVersion */
727 PDM_DRVREG_VERSION
728};
729/* vi: set tabstop=4 shiftwidth=4 expandtab: */
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