VirtualBox

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

Last change on this file since 27279 was 27208, checked in by vboxsync, 15 years ago

Main/MouseImpl: some fixes and a todo

  • 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 27208 2010-03-09 12:31:03Z 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 - 1) * 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 - 1) * 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 /** @todo the front end should do this conversion to avoid races */
452 HRESULT rc = convertDisplayWidth(x, &mouseXAbs);
453 if (FAILED(rc)) return rc;
454
455 /**
456 * @todo multi-monitor Windows guests expect this to be unbounded.
457 * Understand the issues involved and fix for the rest.
458 */
459 /* if (mouseXAbs > 0xffff)
460 mouseXAbs = mLastAbsX; */
461
462 uint32_t mouseYAbs;
463 rc = convertDisplayHeight(y, &mouseYAbs);
464 if (FAILED(rc)) return rc;
465 /* if (mouseYAbs > 0xffff)
466 mouseYAbs = mLastAbsY; */
467
468 uint32_t fButtons = mouseButtonsToPDM(buttonState);
469
470 uint32_t mouseCaps;
471 rc = getVMMDevMouseCaps(&mouseCaps);
472 if (FAILED(rc)) return rc;
473
474 /*
475 * This method being called implies that the host wants
476 * to use absolute coordinates. If the VMM device isn't
477 * aware of that yet, tell it.
478 */
479 if (!(mouseCaps & VMMDEV_MOUSE_HOST_CAN_ABSOLUTE))
480 {
481 uHostCaps |= VMMDEV_MOUSE_HOST_CAN_ABSOLUTE;
482 setVMMDevMouseCaps(uHostCaps);
483 }
484
485 if (fVMMDevCanAbs)
486 {
487 /*
488 * Send the absolute mouse position to the VMM device.
489 */
490 rc = reportAbsEventToVMMDev(mouseXAbs, mouseYAbs);
491 /* We may need to send an additional event for button information or
492 * to wake up older guests to the changed absolute co-ordinates. If
493 * the event is a pure wake up one, we make sure it contains some
494 * (possibly phony) event data to make sure it isn't just discarded
495 * on the way. */
496 bool fNeedsJiggle = !(mouseCaps & VMMDEV_MOUSE_GUEST_USES_VMMDEV);
497 if (fNeedsJiggle || fButtons != mLastButtons || dz || dw)
498 {
499 rc = reportRelEventToMouseDev(fNeedsJiggle ? 1 : 0, 0, dz, dw,
500 fButtons);
501 }
502 }
503 else
504 rc = reportAbsEventToMouseDev(mouseXAbs, mouseYAbs, dz, dw, fButtons);
505
506 if (FAILED(rc)) return rc;
507
508 mLastAbsX = mouseXAbs;
509 mLastAbsY = mouseYAbs;
510
511 mLastButtons = fButtons;
512 return rc;
513}
514
515// private methods
516/////////////////////////////////////////////////////////////////////////////
517
518
519void Mouse::sendMouseCapsNotifications(void)
520{
521 bool fAbsDev = false;
522 bool fRelDev = false;
523 uint32_t u32MouseCaps;
524 for (unsigned i = 0; i < MOUSE_MAX_DEVICES; ++i)
525 if (mpDrv[i])
526 {
527 if (mpDrv[i]->u32DevCaps & MOUSE_DEVCAP_ABSOLUTE)
528 fAbsDev = true;
529 if (mpDrv[i]->u32DevCaps & MOUSE_DEVCAP_RELATIVE)
530 fRelDev = true;
531 }
532 if (SUCCEEDED(getVMMDevMouseCaps(&u32MouseCaps)))
533 fVMMDevCanAbs = (u32MouseCaps & VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE)
534 && fRelDev;
535 else
536 fVMMDevCanAbs = false;
537 mParent->onMouseCapabilityChange(fAbsDev || fVMMDevCanAbs, fRelDev,
538 fVMMDevNeedsHostCursor);
539 /** @todo if this gets called during device initialisation we get an
540 * error due to VMMDev not being initialised yet. */
541 if (fAbsDev && !(uHostCaps & VMMDEV_MOUSE_HOST_HAS_ABS_DEV))
542 uHostCaps |= VMMDEV_MOUSE_HOST_HAS_ABS_DEV;
543 if (!fAbsDev && (uHostCaps & VMMDEV_MOUSE_HOST_HAS_ABS_DEV))
544 uHostCaps &= ~VMMDEV_MOUSE_HOST_HAS_ABS_DEV;
545 setVMMDevMouseCaps(uHostCaps);
546}
547
548
549/**
550 * @interface_method_impl{PDMIMOUSECONNECTOR,pfnReportModes}
551 */
552DECLCALLBACK(void) Mouse::mouseReportModes(PPDMIMOUSECONNECTOR pInterface, bool fRel, bool fAbs)
553{
554 PDRVMAINMOUSE pDrv = RT_FROM_MEMBER(pInterface, DRVMAINMOUSE, IConnector);
555 if (fRel)
556 pDrv->u32DevCaps |= MOUSE_DEVCAP_RELATIVE;
557 else
558 pDrv->u32DevCaps &= ~MOUSE_DEVCAP_RELATIVE;
559 if (fAbs)
560 pDrv->u32DevCaps |= MOUSE_DEVCAP_ABSOLUTE;
561 else
562 pDrv->u32DevCaps &= ~MOUSE_DEVCAP_ABSOLUTE;
563
564 pDrv->pMouse->sendMouseCapsNotifications();
565}
566
567
568/**
569 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
570 */
571DECLCALLBACK(void *) Mouse::drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
572{
573 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
574 PDRVMAINMOUSE pDrv = PDMINS_2_DATA(pDrvIns, PDRVMAINMOUSE);
575
576 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
577 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUSECONNECTOR, &pDrv->IConnector);
578 return NULL;
579}
580
581
582/**
583 * Destruct a mouse driver instance.
584 *
585 * @returns VBox status.
586 * @param pDrvIns The driver instance data.
587 */
588DECLCALLBACK(void) Mouse::drvDestruct(PPDMDRVINS pDrvIns)
589{
590 PDRVMAINMOUSE pData = PDMINS_2_DATA(pDrvIns, PDRVMAINMOUSE);
591 LogFlow(("Mouse::drvDestruct: iInstance=%d\n", pDrvIns->iInstance));
592 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
593
594 if (pData->pMouse)
595 {
596 AutoWriteLock mouseLock(pData->pMouse COMMA_LOCKVAL_SRC_POS);
597 for (unsigned cDev = 0; cDev < MOUSE_MAX_DEVICES; ++cDev)
598 if (pData->pMouse->mpDrv[cDev] == pData)
599 {
600 pData->pMouse->mpDrv[cDev] = NULL;
601 break;
602 }
603 }
604}
605
606
607/**
608 * Construct a mouse driver instance.
609 *
610 * @copydoc FNPDMDRVCONSTRUCT
611 */
612DECLCALLBACK(int) Mouse::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
613{
614 PDRVMAINMOUSE pData = PDMINS_2_DATA(pDrvIns, PDRVMAINMOUSE);
615 LogFlow(("drvMainMouse_Construct: iInstance=%d\n", pDrvIns->iInstance));
616 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
617
618 /*
619 * Validate configuration.
620 */
621 if (!CFGMR3AreValuesValid(pCfg, "Object\0"))
622 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
623 AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
624 ("Configuration error: Not possible to attach anything to this driver!\n"),
625 VERR_PDM_DRVINS_NO_ATTACH);
626
627 /*
628 * IBase.
629 */
630 pDrvIns->IBase.pfnQueryInterface = Mouse::drvQueryInterface;
631
632 pData->IConnector.pfnReportModes = Mouse::mouseReportModes;
633
634 /*
635 * Get the IMousePort interface of the above driver/device.
636 */
637 pData->pUpPort = (PPDMIMOUSEPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMIMOUSEPORT_IID);
638 if (!pData->pUpPort)
639 {
640 AssertMsgFailed(("Configuration error: No mouse port interface above!\n"));
641 return VERR_PDM_MISSING_INTERFACE_ABOVE;
642 }
643
644 /*
645 * Get the Mouse object pointer and update the mpDrv member.
646 */
647 void *pv;
648 int rc = CFGMR3QueryPtr(pCfg, "Object", &pv);
649 if (RT_FAILURE(rc))
650 {
651 AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
652 return rc;
653 }
654 pData->pMouse = (Mouse *)pv; /** @todo Check this cast! */
655 unsigned cDev;
656 for (cDev = 0; cDev < MOUSE_MAX_DEVICES; ++cDev)
657 if (!pData->pMouse->mpDrv[cDev])
658 {
659 pData->pMouse->mpDrv[cDev] = pData;
660 break;
661 }
662 if (cDev == MOUSE_MAX_DEVICES)
663 return VERR_NO_MORE_HANDLES;
664
665 return VINF_SUCCESS;
666}
667
668
669/**
670 * Main mouse driver registration record.
671 */
672const PDMDRVREG Mouse::DrvReg =
673{
674 /* u32Version */
675 PDM_DRVREG_VERSION,
676 /* szName */
677 "MainMouse",
678 /* szRCMod */
679 "",
680 /* szR0Mod */
681 "",
682 /* pszDescription */
683 "Main mouse driver (Main as in the API).",
684 /* fFlags */
685 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
686 /* fClass. */
687 PDM_DRVREG_CLASS_MOUSE,
688 /* cMaxInstances */
689 ~0,
690 /* cbInstance */
691 sizeof(DRVMAINMOUSE),
692 /* pfnConstruct */
693 Mouse::drvConstruct,
694 /* pfnDestruct */
695 Mouse::drvDestruct,
696 /* pfnRelocate */
697 NULL,
698 /* pfnIOCtl */
699 NULL,
700 /* pfnPowerOn */
701 NULL,
702 /* pfnReset */
703 NULL,
704 /* pfnSuspend */
705 NULL,
706 /* pfnResume */
707 NULL,
708 /* pfnAttach */
709 NULL,
710 /* pfnDetach */
711 NULL,
712 /* pfnPowerOff */
713 NULL,
714 /* pfnSoftReset */
715 NULL,
716 /* u32EndVersion */
717 PDM_DRVREG_VERSION
718};
719/* 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