VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxBFE/MouseImpl.cpp@ 26935

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