VirtualBox

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

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

Automated rebranding to Oracle copyright/license strings via filemuncher

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

© 2023 Oracle
ContactPrivacy policyTerms of Use