VirtualBox

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

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

Main: don't assert in Mouse code all over the place. Now that we have absolute mouse coordinates, the GUI may send mouse events after having destroyed its session and console, and we shouldn't assert then

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