~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/Main/VMMDevInterface.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-01-30 23:27:25 UTC
  • mfrom: (0.3.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20110130232725-2ouajjd2ggdet0zd
Tags: 4.0.2-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Drop ubuntu-01-fix-build-gcc45.patch, fixed upstream.
* Drop ubuntu-02-as-needed.patch, added to the Debian package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: VMMDevInterface.cpp $ */
2
 
/** @file
3
 
 * VirtualBox Driver Interface to VMM device.
4
 
 */
5
 
 
6
 
/*
7
 
 * Copyright (C) 2006-2010 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 "VMMDev.h"
19
 
#include "ConsoleImpl.h"
20
 
#include "DisplayImpl.h"
21
 
#include "GuestImpl.h"
22
 
#include "MouseImpl.h"
23
 
 
24
 
#include "Logging.h"
25
 
 
26
 
#include <VBox/pdmdrv.h>
27
 
#include <VBox/VMMDev.h>
28
 
#include <VBox/shflsvc.h>
29
 
#include <iprt/asm.h>
30
 
 
31
 
#ifdef VBOX_WITH_HGCM
32
 
#include "hgcm/HGCM.h"
33
 
#include "hgcm/HGCMObjects.h"
34
 
# if defined(RT_OS_DARWIN) && defined(VBOX_WITH_CROGL)
35
 
#  include <VBox/HostServices/VBoxCrOpenGLSvc.h>
36
 
# endif
37
 
#endif
38
 
 
39
 
//
40
 
// defines
41
 
//
42
 
 
43
 
#ifdef RT_OS_OS2
44
 
# define VBOXSHAREDFOLDERS_DLL "VBoxSFld"
45
 
#else
46
 
# define VBOXSHAREDFOLDERS_DLL "VBoxSharedFolders"
47
 
#endif
48
 
 
49
 
//
50
 
// globals
51
 
//
52
 
 
53
 
 
54
 
/**
55
 
 * VMMDev driver instance data.
56
 
 */
57
 
typedef struct DRVMAINVMMDEV
58
 
{
59
 
    /** Pointer to the VMMDev object. */
60
 
    VMMDev                      *pVMMDev;
61
 
    /** Pointer to the driver instance structure. */
62
 
    PPDMDRVINS                  pDrvIns;
63
 
    /** Pointer to the VMMDev port interface of the driver/device above us. */
64
 
    PPDMIVMMDEVPORT             pUpPort;
65
 
    /** Our VMM device connector interface. */
66
 
    PDMIVMMDEVCONNECTOR         Connector;
67
 
 
68
 
#ifdef VBOX_WITH_HGCM
69
 
    /** Pointer to the HGCM port interface of the driver/device above us. */
70
 
    PPDMIHGCMPORT               pHGCMPort;
71
 
    /** Our HGCM connector interface. */
72
 
    PDMIHGCMCONNECTOR           HGCMConnector;
73
 
#endif
74
 
} DRVMAINVMMDEV, *PDRVMAINVMMDEV;
75
 
 
76
 
/** Converts PDMIVMMDEVCONNECTOR pointer to a DRVMAINVMMDEV pointer. */
77
 
#define PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface) ( (PDRVMAINVMMDEV) ((uintptr_t)pInterface - RT_OFFSETOF(DRVMAINVMMDEV, Connector)) )
78
 
 
79
 
#ifdef VBOX_WITH_HGCM
80
 
/** Converts PDMIHGCMCONNECTOR pointer to a DRVMAINVMMDEV pointer. */
81
 
#define PDMIHGCMCONNECTOR_2_MAINVMMDEV(pInterface) ( (PDRVMAINVMMDEV) ((uintptr_t)pInterface - RT_OFFSETOF(DRVMAINVMMDEV, HGCMConnector)) )
82
 
#endif
83
 
 
84
 
//
85
 
// constructor / destructor
86
 
//
87
 
VMMDev::VMMDev(Console *console)
88
 
    : mpDrv(NULL),
89
 
      mParent(console)
90
 
{
91
 
    int rc = RTSemEventCreate(&mCredentialsEvent);
92
 
    AssertRC(rc);
93
 
#ifdef VBOX_WITH_HGCM
94
 
    rc = HGCMHostInit ();
95
 
    AssertRC(rc);
96
 
    m_fHGCMActive = true;
97
 
#endif /* VBOX_WITH_HGCM */
98
 
    mu32CredentialsFlags = 0;
99
 
}
100
 
 
101
 
VMMDev::~VMMDev()
102
 
{
103
 
#ifdef VBOX_WITH_HGCM
104
 
    if (hgcmIsActive())
105
 
    {
106
 
        ASMAtomicWriteBool(&m_fHGCMActive, false);
107
 
        HGCMHostShutdown();
108
 
    }
109
 
#endif /* VBOX_WITH_HGCM */
110
 
    RTSemEventDestroy (mCredentialsEvent);
111
 
    if (mpDrv)
112
 
        mpDrv->pVMMDev = NULL;
113
 
    mpDrv = NULL;
114
 
}
115
 
 
116
 
PPDMIVMMDEVPORT VMMDev::getVMMDevPort()
117
 
{
118
 
    AssertReturn(mpDrv, NULL);
119
 
    return mpDrv->pUpPort;
120
 
}
121
 
 
122
 
 
123
 
 
124
 
//
125
 
// public methods
126
 
//
127
 
 
128
 
/**
129
 
 * Wait on event semaphore for guest credential judgement result.
130
 
 */
131
 
int VMMDev::WaitCredentialsJudgement(uint32_t u32Timeout, uint32_t *pu32CredentialsFlags)
132
 
{
133
 
    if (u32Timeout == 0)
134
 
    {
135
 
        u32Timeout = 5000;
136
 
    }
137
 
 
138
 
    int rc = RTSemEventWait (mCredentialsEvent, u32Timeout);
139
 
 
140
 
    if (RT_SUCCESS(rc))
141
 
    {
142
 
        *pu32CredentialsFlags = mu32CredentialsFlags;
143
 
    }
144
 
 
145
 
    return rc;
146
 
}
147
 
 
148
 
int VMMDev::SetCredentialsJudgementResult(uint32_t u32Flags)
149
 
{
150
 
    mu32CredentialsFlags = u32Flags;
151
 
 
152
 
    int rc = RTSemEventSignal (mCredentialsEvent);
153
 
    AssertRC(rc);
154
 
 
155
 
    return rc;
156
 
}
157
 
 
158
 
 
159
 
/**
160
 
 * Reports Guest Additions status.
161
 
 * Called whenever the Additions issue a guest status report request or the VM is reset.
162
 
 *
163
 
 * @param   pInterface          Pointer to this interface.
164
 
 * @param   guestInfo           Pointer to guest information structure
165
 
 * @thread  The emulation thread.
166
 
 */
167
 
DECLCALLBACK(void) vmmdevUpdateGuestStatus(PPDMIVMMDEVCONNECTOR pInterface, const VBoxGuestStatus *guestStatus)
168
 
{
169
 
    PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
170
 
 
171
 
    Assert(guestStatus);
172
 
    if (!guestStatus)
173
 
        return;
174
 
 
175
 
    Console *pConsole = pDrv->pVMMDev->getParent();
176
 
 
177
 
    /* Store that information in IGuest */
178
 
    Guest* guest = pConsole->getGuest();
179
 
    Assert(guest);
180
 
    if (!guest)
181
 
        return;
182
 
 
183
 
    guest->setAdditionsStatus((VBoxGuestStatusFacility)guestStatus->facility,
184
 
                              (VBoxGuestStatusCurrent)guestStatus->status,
185
 
                              guestStatus->flags);
186
 
    pConsole->onAdditionsStateChange();
187
 
}
188
 
 
189
 
 
190
 
/**
191
 
 * Reports Guest Additions API and OS version.
192
 
 * Called whenever the Additions issue a guest version report request or the VM is reset.
193
 
 *
194
 
 * @param   pInterface          Pointer to this interface.
195
 
 * @param   guestInfo           Pointer to guest information structure
196
 
 * @thread  The emulation thread.
197
 
 */
198
 
DECLCALLBACK(void) vmmdevUpdateGuestInfo(PPDMIVMMDEVCONNECTOR pInterface, const VBoxGuestInfo *guestInfo)
199
 
{
200
 
    PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
201
 
 
202
 
    Assert(guestInfo);
203
 
    if (!guestInfo)
204
 
        return;
205
 
 
206
 
    Console *pConsole = pDrv->pVMMDev->getParent();
207
 
 
208
 
    /* Store that information in IGuest */
209
 
    Guest* guest = pConsole->getGuest();
210
 
    Assert(guest);
211
 
    if (!guest)
212
 
        return;
213
 
 
214
 
    if (guestInfo->additionsVersion != 0)
215
 
    {
216
 
        char version[20];
217
 
        RTStrPrintf(version, sizeof(version), "%d", guestInfo->additionsVersion);
218
 
        guest->setAdditionsInfo(Bstr(version), guestInfo->osType);
219
 
 
220
 
        /*
221
 
         * Tell the console interface about the event
222
 
         * so that it can notify its consumers.
223
 
         */
224
 
        pConsole->onAdditionsStateChange();
225
 
 
226
 
        if (guestInfo->additionsVersion < VMMDEV_VERSION)
227
 
            pConsole->onAdditionsOutdated();
228
 
    }
229
 
    else
230
 
    {
231
 
        /*
232
 
         * The guest additions was disabled because of a reset
233
 
         * or driver unload.
234
 
         */
235
 
        guest->setAdditionsInfo(Bstr(), guestInfo->osType);
236
 
        guest->setAdditionsStatus(VBoxGuestStatusFacility_Unknown,
237
 
                                  VBoxGuestStatusCurrent_Disabled,
238
 
                                  0); /* Flags; not used. */
239
 
        pConsole->onAdditionsStateChange();
240
 
    }
241
 
}
242
 
 
243
 
/**
244
 
 * Update the guest additions capabilities.
245
 
 * This is called when the guest additions capabilities change. The new capabilities
246
 
 * are given and the connector should update its internal state.
247
 
 *
248
 
 * @param   pInterface          Pointer to this interface.
249
 
 * @param   newCapabilities     New capabilities.
250
 
 * @thread  The emulation thread.
251
 
 */
252
 
DECLCALLBACK(void) vmmdevUpdateGuestCapabilities(PPDMIVMMDEVCONNECTOR pInterface, uint32_t newCapabilities)
253
 
{
254
 
    PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
255
 
    Console *pConsole = pDrv->pVMMDev->getParent();
256
 
 
257
 
    /* store that information in IGuest */
258
 
    Guest* guest = pConsole->getGuest();
259
 
    Assert(guest);
260
 
    if (!guest)
261
 
        return;
262
 
 
263
 
    /*
264
 
     * Report our current capabilites (and assume none is active yet).
265
 
     */
266
 
    guest->setSupportedFeatures((ULONG64)newCapabilities, 0 /* Active capabilities, not used here. */);
267
 
 
268
 
    /*
269
 
     * Tell the console interface about the event
270
 
     * so that it can notify its consumers.
271
 
     */
272
 
    pConsole->onAdditionsStateChange();
273
 
 
274
 
}
275
 
 
276
 
/**
277
 
 * Update the mouse capabilities.
278
 
 * This is called when the mouse capabilities change. The new capabilities
279
 
 * are given and the connector should update its internal state.
280
 
 *
281
 
 * @param   pInterface          Pointer to this interface.
282
 
 * @param   newCapabilities     New capabilities.
283
 
 * @thread  The emulation thread.
284
 
 */
285
 
DECLCALLBACK(void) vmmdevUpdateMouseCapabilities(PPDMIVMMDEVCONNECTOR pInterface, uint32_t newCapabilities)
286
 
{
287
 
    PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
288
 
    Console *pConsole = pDrv->pVMMDev->getParent();
289
 
 
290
 
    /*
291
 
     * Tell the console interface about the event
292
 
     * so that it can notify its consumers.
293
 
     */
294
 
    Mouse *pMouse = pConsole->getMouse();
295
 
    if (pMouse)  /** @todo and if not?  Can that actually happen? */
296
 
    {
297
 
        pMouse->onVMMDevCanAbsChange(!!(newCapabilities & VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE));
298
 
        pMouse->onVMMDevNeedsHostChange(!!(newCapabilities & VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR));
299
 
    }
300
 
}
301
 
 
302
 
 
303
 
/**
304
 
 * Update the pointer shape or visibility.
305
 
 *
306
 
 * This is called when the mouse pointer shape changes or pointer is hidden/displaying.
307
 
 * The new shape is passed as a caller allocated buffer that will be freed after returning.
308
 
 *
309
 
 * @param   pInterface          Pointer to this interface.
310
 
 * @param   fVisible            Whether the pointer is visible or not.
311
 
 * @param   fAlpha              Alpha channel information is present.
312
 
 * @param   xHot                Horizontal coordinate of the pointer hot spot.
313
 
 * @param   yHot                Vertical coordinate of the pointer hot spot.
314
 
 * @param   width               Pointer width in pixels.
315
 
 * @param   height              Pointer height in pixels.
316
 
 * @param   pShape              The shape buffer. If NULL, then only pointer visibility is being changed.
317
 
 * @thread  The emulation thread.
318
 
 */
319
 
DECLCALLBACK(void) vmmdevUpdatePointerShape(PPDMIVMMDEVCONNECTOR pInterface, bool fVisible, bool fAlpha,
320
 
                                            uint32_t xHot, uint32_t yHot,
321
 
                                            uint32_t width, uint32_t height,
322
 
                                            void *pShape)
323
 
{
324
 
    PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
325
 
    Console *pConsole = pDrv->pVMMDev->getParent();
326
 
 
327
 
    /* tell the console about it */
328
 
    size_t cbShapeSize = 0;
329
 
 
330
 
    if (pShape)
331
 
    {
332
 
        cbShapeSize = (width + 7) / 8 * height; /* size of the AND mask */
333
 
        cbShapeSize = ((cbShapeSize + 3) & ~3) + width * 4 * height; /* + gap + size of the XOR mask */
334
 
    }
335
 
    com::SafeArray<BYTE> shapeData(cbShapeSize);
336
 
    if (pShape)
337
 
        ::memcpy(shapeData.raw(), pShape, cbShapeSize);
338
 
    pConsole->onMousePointerShapeChange(fVisible, fAlpha, xHot, yHot, width, height, ComSafeArrayAsInParam(shapeData));
339
 
}
340
 
 
341
 
DECLCALLBACK(int) iface_VideoAccelEnable(PPDMIVMMDEVCONNECTOR pInterface, bool fEnable, VBVAMEMORY *pVbvaMemory)
342
 
{
343
 
    PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
344
 
    Console *pConsole = pDrv->pVMMDev->getParent();
345
 
 
346
 
    Display *display = pConsole->getDisplay();
347
 
 
348
 
    if (display)
349
 
    {
350
 
        LogSunlover(("MAIN::VMMDevInterface::iface_VideoAccelEnable: %d, %p\n", fEnable, pVbvaMemory));
351
 
        return display->VideoAccelEnable(fEnable, pVbvaMemory);
352
 
    }
353
 
 
354
 
    return VERR_NOT_SUPPORTED;
355
 
}
356
 
DECLCALLBACK(void) iface_VideoAccelFlush(PPDMIVMMDEVCONNECTOR pInterface)
357
 
{
358
 
    PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
359
 
    Console *pConsole = pDrv->pVMMDev->getParent();
360
 
 
361
 
    Display *display = pConsole->getDisplay();
362
 
 
363
 
    if (display)
364
 
    {
365
 
        LogSunlover(("MAIN::VMMDevInterface::iface_VideoAccelFlush\n"));
366
 
        display->VideoAccelFlush ();
367
 
    }
368
 
}
369
 
 
370
 
DECLCALLBACK(int) vmmdevVideoModeSupported(PPDMIVMMDEVCONNECTOR pInterface, uint32_t display, uint32_t width, uint32_t height,
371
 
                                           uint32_t bpp, bool *fSupported)
372
 
{
373
 
    PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
374
 
    Console *pConsole = pDrv->pVMMDev->getParent();
375
 
 
376
 
    if (!fSupported)
377
 
        return VERR_INVALID_PARAMETER;
378
 
#ifdef DEBUG_sunlover
379
 
    Log(("vmmdevVideoModeSupported: [%d]: %dx%dx%d\n", display, width, height, bpp));
380
 
#endif
381
 
    IFramebuffer *framebuffer = NULL;
382
 
    LONG xOrigin = 0;
383
 
    LONG yOrigin = 0;
384
 
    HRESULT hrc = pConsole->getDisplay()->GetFramebuffer(display, &framebuffer, &xOrigin, &yOrigin);
385
 
    if (SUCCEEDED(hrc) && framebuffer)
386
 
    {
387
 
        framebuffer->VideoModeSupported(width, height, bpp, (BOOL*)fSupported);
388
 
        framebuffer->Release();
389
 
    }
390
 
    else
391
 
    {
392
 
#ifdef DEBUG_sunlover
393
 
        Log(("vmmdevVideoModeSupported: hrc %x, framebuffer %p!!!\n", hrc, framebuffer));
394
 
#endif
395
 
        *fSupported = true;
396
 
    }
397
 
    return VINF_SUCCESS;
398
 
}
399
 
 
400
 
DECLCALLBACK(int) vmmdevGetHeightReduction(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *heightReduction)
401
 
{
402
 
    PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
403
 
    Console *pConsole = pDrv->pVMMDev->getParent();
404
 
 
405
 
    if (!heightReduction)
406
 
        return VERR_INVALID_PARAMETER;
407
 
    IFramebuffer *framebuffer = pConsole->getDisplay()->getFramebuffer();
408
 
    if (framebuffer)
409
 
        framebuffer->COMGETTER(HeightReduction)((ULONG*)heightReduction);
410
 
    else
411
 
        *heightReduction = 0;
412
 
    return VINF_SUCCESS;
413
 
}
414
 
 
415
 
DECLCALLBACK(int) vmmdevSetCredentialsJudgementResult(PPDMIVMMDEVCONNECTOR pInterface, uint32_t u32Flags)
416
 
{
417
 
    PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
418
 
 
419
 
    if (pDrv->pVMMDev)
420
 
        return pDrv->pVMMDev->SetCredentialsJudgementResult (u32Flags);
421
 
 
422
 
    return VERR_GENERAL_FAILURE;
423
 
}
424
 
 
425
 
DECLCALLBACK(int) vmmdevSetVisibleRegion(PPDMIVMMDEVCONNECTOR pInterface, uint32_t cRect, PRTRECT pRect)
426
 
{
427
 
    PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
428
 
    Console *pConsole = pDrv->pVMMDev->getParent();
429
 
 
430
 
    if (!cRect)
431
 
        return VERR_INVALID_PARAMETER;
432
 
#ifdef MMSEAMLESS
433
 
    /* Forward to Display, which calls corresponding framebuffers. */
434
 
    pConsole->getDisplay()->handleSetVisibleRegion(cRect, pRect);
435
 
#else
436
 
    IFramebuffer *framebuffer = pConsole->getDisplay()->getFramebuffer();
437
 
    if (framebuffer)
438
 
    {
439
 
        framebuffer->SetVisibleRegion((BYTE *)pRect, cRect);
440
 
#if defined(RT_OS_DARWIN) && defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
441
 
        {
442
 
            BOOL is3denabled;
443
 
 
444
 
            pConsole->machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
445
 
 
446
 
            if (is3denabled)
447
 
            {
448
 
                VBOXHGCMSVCPARM parms[2];
449
 
 
450
 
                parms[0].type = VBOX_HGCM_SVC_PARM_PTR;
451
 
                parms[0].u.pointer.addr = pRect;
452
 
                parms[0].u.pointer.size = 0;  /* We don't actually care. */
453
 
                parms[1].type = VBOX_HGCM_SVC_PARM_32BIT;
454
 
                parms[1].u.uint32 = cRect;
455
 
 
456
 
                if (pDrv->pVMMDev)
457
 
                    return pDrv->pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SET_VISIBLE_REGION, 2, &parms[0]);
458
 
            }
459
 
        }
460
 
#endif
461
 
    }
462
 
#endif
463
 
 
464
 
    return VINF_SUCCESS;
465
 
}
466
 
 
467
 
DECLCALLBACK(int) vmmdevQueryVisibleRegion(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pcRect, PRTRECT pRect)
468
 
{
469
 
    PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
470
 
    Console *pConsole = pDrv->pVMMDev->getParent();
471
 
 
472
 
#ifdef MMSEAMLESS
473
 
    /* Forward to Display, which calls corresponding framebuffers. */
474
 
    pConsole->getDisplay()->handleQueryVisibleRegion(pcRect, pRect);
475
 
#else
476
 
    IFramebuffer *framebuffer = pConsole->getDisplay()->getFramebuffer();
477
 
    if (framebuffer)
478
 
    {
479
 
        ULONG cRect = 0;
480
 
        framebuffer->GetVisibleRegion((BYTE *)pRect, cRect, &cRect);
481
 
 
482
 
        *pcRect = cRect;
483
 
    }
484
 
#endif
485
 
 
486
 
    return VINF_SUCCESS;
487
 
}
488
 
 
489
 
/**
490
 
 * Request the statistics interval
491
 
 *
492
 
 * @returns VBox status code.
493
 
 * @param   pInterface          Pointer to this interface.
494
 
 * @param   pulInterval         Pointer to interval in seconds
495
 
 * @thread  The emulation thread.
496
 
 */
497
 
DECLCALLBACK(int) vmmdevQueryStatisticsInterval(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pulInterval)
498
 
{
499
 
    PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
500
 
    Console *pConsole = pDrv->pVMMDev->getParent();
501
 
    ULONG          val = 0;
502
 
 
503
 
    if (!pulInterval)
504
 
        return VERR_INVALID_POINTER;
505
 
 
506
 
    /* store that information in IGuest */
507
 
    Guest* guest = pConsole->getGuest();
508
 
    Assert(guest);
509
 
    if (!guest)
510
 
        return VERR_GENERAL_FAILURE;
511
 
 
512
 
    guest->COMGETTER(StatisticsUpdateInterval)(&val);
513
 
    *pulInterval = val;
514
 
    return VINF_SUCCESS;
515
 
}
516
 
 
517
 
/**
518
 
 * Query the current balloon size
519
 
 *
520
 
 * @returns VBox status code.
521
 
 * @param   pInterface          Pointer to this interface.
522
 
 * @param   pcbBalloon          Balloon size
523
 
 * @thread  The emulation thread.
524
 
 */
525
 
DECLCALLBACK(int) vmmdevQueryBalloonSize(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pcbBalloon)
526
 
{
527
 
    PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
528
 
    Console *pConsole = pDrv->pVMMDev->getParent();
529
 
    ULONG          val = 0;
530
 
 
531
 
    if (!pcbBalloon)
532
 
        return VERR_INVALID_POINTER;
533
 
 
534
 
    /* store that information in IGuest */
535
 
    Guest* guest = pConsole->getGuest();
536
 
    Assert(guest);
537
 
    if (!guest)
538
 
        return VERR_GENERAL_FAILURE;
539
 
 
540
 
    guest->COMGETTER(MemoryBalloonSize)(&val);
541
 
    *pcbBalloon = val;
542
 
    return VINF_SUCCESS;
543
 
}
544
 
 
545
 
/**
546
 
 * Query the current page fusion setting
547
 
 *
548
 
 * @returns VBox status code.
549
 
 * @param   pInterface          Pointer to this interface.
550
 
 * @param   pfPageFusionEnabled Pointer to boolean
551
 
 * @thread  The emulation thread.
552
 
 */
553
 
DECLCALLBACK(int) vmmdevIsPageFusionEnabled(PPDMIVMMDEVCONNECTOR pInterface, bool *pfPageFusionEnabled)
554
 
{
555
 
    PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
556
 
    Console *pConsole = pDrv->pVMMDev->getParent();
557
 
    BOOL           val = 0;
558
 
 
559
 
    if (!pfPageFusionEnabled)
560
 
        return VERR_INVALID_POINTER;
561
 
 
562
 
    /* store that information in IGuest */
563
 
    Guest* guest = pConsole->getGuest();
564
 
    Assert(guest);
565
 
    if (!guest)
566
 
        return VERR_GENERAL_FAILURE;
567
 
 
568
 
    guest->COMGETTER(PageFusionEnabled)(&val);
569
 
    *pfPageFusionEnabled = !!val;
570
 
    return VINF_SUCCESS;
571
 
}
572
 
 
573
 
/**
574
 
 * Report new guest statistics
575
 
 *
576
 
 * @returns VBox status code.
577
 
 * @param   pInterface          Pointer to this interface.
578
 
 * @param   pGuestStats         Guest statistics
579
 
 * @thread  The emulation thread.
580
 
 */
581
 
DECLCALLBACK(int) vmmdevReportStatistics(PPDMIVMMDEVCONNECTOR pInterface, VBoxGuestStatistics *pGuestStats)
582
 
{
583
 
    PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
584
 
    Console *pConsole = pDrv->pVMMDev->getParent();
585
 
 
586
 
    Assert(pGuestStats);
587
 
    if (!pGuestStats)
588
 
        return VERR_INVALID_POINTER;
589
 
 
590
 
    /* store that information in IGuest */
591
 
    Guest* guest = pConsole->getGuest();
592
 
    Assert(guest);
593
 
    if (!guest)
594
 
        return VERR_GENERAL_FAILURE;
595
 
 
596
 
    if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_CPU_LOAD_IDLE)
597
 
        guest->setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_CPUIDLE, pGuestStats->u32CpuLoad_Idle);
598
 
 
599
 
    if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_CPU_LOAD_KERNEL)
600
 
        guest->setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_CPUKERNEL, pGuestStats->u32CpuLoad_Kernel);
601
 
 
602
 
    if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_CPU_LOAD_USER)
603
 
        guest->setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_CPUUSER, pGuestStats->u32CpuLoad_User);
604
 
 
605
 
 
606
 
    /** @todo r=bird: Convert from 4KB to 1KB units?
607
 
     *        CollectorGuestHAL::getGuestMemLoad says it returns KB units to
608
 
     *        preCollect().  I might be wrong ofc, this is convoluted code... */
609
 
    if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_TOTAL)
610
 
        guest->setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_MEMTOTAL, pGuestStats->u32PhysMemTotal);
611
 
 
612
 
    if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_AVAIL)
613
 
        guest->setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_MEMFREE, pGuestStats->u32PhysMemAvail);
614
 
 
615
 
    if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_BALLOON)
616
 
        guest->setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_MEMBALLOON, pGuestStats->u32PhysMemBalloon);
617
 
 
618
 
    if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_MEM_SYSTEM_CACHE)
619
 
        guest->setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_MEMCACHE, pGuestStats->u32MemSystemCache);
620
 
 
621
 
    if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PAGE_FILE_SIZE)
622
 
        guest->setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_PAGETOTAL, pGuestStats->u32PageFileSize);
623
 
 
624
 
    return VINF_SUCCESS;
625
 
}
626
 
 
627
 
#ifdef VBOX_WITH_HGCM
628
 
 
629
 
/* HGCM connector interface */
630
 
 
631
 
static DECLCALLBACK(int) iface_hgcmConnect (PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, PHGCMSERVICELOCATION pServiceLocation, uint32_t *pu32ClientID)
632
 
{
633
 
    LogSunlover(("Enter\n"));
634
 
 
635
 
    PDRVMAINVMMDEV pDrv = PDMIHGCMCONNECTOR_2_MAINVMMDEV(pInterface);
636
 
 
637
 
    if (    !pServiceLocation
638
 
        || (   pServiceLocation->type != VMMDevHGCMLoc_LocalHost
639
 
            && pServiceLocation->type != VMMDevHGCMLoc_LocalHost_Existing))
640
 
    {
641
 
        return VERR_INVALID_PARAMETER;
642
 
    }
643
 
 
644
 
    if (!pDrv->pVMMDev || !pDrv->pVMMDev->hgcmIsActive())
645
 
        return VERR_INVALID_STATE;
646
 
 
647
 
    return HGCMGuestConnect(pDrv->pHGCMPort, pCmd, pServiceLocation->u.host.achName, pu32ClientID);
648
 
}
649
 
 
650
 
static DECLCALLBACK(int) iface_hgcmDisconnect (PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, uint32_t u32ClientID)
651
 
{
652
 
    LogSunlover(("Enter\n"));
653
 
 
654
 
    PDRVMAINVMMDEV pDrv = PDMIHGCMCONNECTOR_2_MAINVMMDEV(pInterface);
655
 
 
656
 
    if (!pDrv->pVMMDev || !pDrv->pVMMDev->hgcmIsActive())
657
 
        return VERR_INVALID_STATE;
658
 
 
659
 
    return HGCMGuestDisconnect(pDrv->pHGCMPort, pCmd, u32ClientID);
660
 
}
661
 
 
662
 
static DECLCALLBACK(int) iface_hgcmCall (PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, uint32_t u32ClientID, uint32_t u32Function,
663
 
                                         uint32_t cParms, PVBOXHGCMSVCPARM paParms)
664
 
{
665
 
    LogSunlover(("Enter\n"));
666
 
 
667
 
    PDRVMAINVMMDEV pDrv = PDMIHGCMCONNECTOR_2_MAINVMMDEV(pInterface);
668
 
 
669
 
    if (!pDrv->pVMMDev || !pDrv->pVMMDev->hgcmIsActive())
670
 
        return VERR_INVALID_STATE;
671
 
 
672
 
    return HGCMGuestCall(pDrv->pHGCMPort, pCmd, u32ClientID, u32Function, cParms, paParms);
673
 
}
674
 
 
675
 
/**
676
 
 * Execute state save operation.
677
 
 *
678
 
 * @returns VBox status code.
679
 
 * @param   pDrvIns         Driver instance of the driver which registered the data unit.
680
 
 * @param   pSSM            SSM operation handle.
681
 
 */
682
 
static DECLCALLBACK(int) iface_hgcmSave(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM)
683
 
{
684
 
    LogSunlover(("Enter\n"));
685
 
    return HGCMHostSaveState(pSSM);
686
 
}
687
 
 
688
 
 
689
 
/**
690
 
 * Execute state load operation.
691
 
 *
692
 
 * @returns VBox status code.
693
 
 * @param   pDrvIns         Driver instance of the driver which registered the data unit.
694
 
 * @param   pSSM            SSM operation handle.
695
 
 * @param   uVersion        Data layout version.
696
 
 * @param   uPass           The data pass.
697
 
 */
698
 
static DECLCALLBACK(int) iface_hgcmLoad(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
699
 
{
700
 
    LogFlowFunc(("Enter\n"));
701
 
 
702
 
    if (uVersion != HGCM_SSM_VERSION)
703
 
        return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
704
 
    Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
705
 
 
706
 
    return HGCMHostLoadState(pSSM);
707
 
}
708
 
 
709
 
int VMMDev::hgcmLoadService(const char *pszServiceLibrary, const char *pszServiceName)
710
 
{
711
 
    if (!hgcmIsActive())
712
 
        return VERR_INVALID_STATE;
713
 
 
714
 
    return HGCMHostLoad(pszServiceLibrary, pszServiceName);
715
 
}
716
 
 
717
 
int VMMDev::hgcmHostCall(const char *pszServiceName, uint32_t u32Function,
718
 
                         uint32_t cParms, PVBOXHGCMSVCPARM paParms)
719
 
{
720
 
    if (!hgcmIsActive())
721
 
        return VERR_INVALID_STATE;
722
 
    return HGCMHostCall (pszServiceName, u32Function, cParms, paParms);
723
 
}
724
 
 
725
 
void VMMDev::hgcmShutdown(void)
726
 
{
727
 
    ASMAtomicWriteBool(&m_fHGCMActive, false);
728
 
    HGCMHostShutdown();
729
 
}
730
 
 
731
 
#endif /* HGCM */
732
 
 
733
 
 
734
 
/**
735
 
 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
736
 
 */
737
 
DECLCALLBACK(void *) VMMDev::drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
738
 
{
739
 
    PPDMDRVINS      pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
740
 
    PDRVMAINVMMDEV  pDrv    = PDMINS_2_DATA(pDrvIns, PDRVMAINVMMDEV);
741
 
 
742
 
    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
743
 
    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIVMMDEVCONNECTOR, &pDrv->Connector);
744
 
#ifdef VBOX_WITH_HGCM
745
 
    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHGCMCONNECTOR, &pDrv->HGCMConnector);
746
 
#endif
747
 
    return NULL;
748
 
}
749
 
 
750
 
/**
751
 
 * Destruct a VMMDev driver instance.
752
 
 *
753
 
 * @returns VBox status.
754
 
 * @param   pDrvIns     The driver instance data.
755
 
 */
756
 
DECLCALLBACK(void) VMMDev::drvDestruct(PPDMDRVINS pDrvIns)
757
 
{
758
 
    PDRVMAINVMMDEV pData = PDMINS_2_DATA(pDrvIns, PDRVMAINVMMDEV);
759
 
    LogFlow(("VMMDev::drvDestruct: iInstance=%d\n", pDrvIns->iInstance));
760
 
#ifdef VBOX_WITH_HGCM
761
 
    /* HGCM is shut down on the VMMDev destructor. */
762
 
#endif /* VBOX_WITH_HGCM */
763
 
    if (pData->pVMMDev)
764
 
        pData->pVMMDev->mpDrv = NULL;
765
 
}
766
 
 
767
 
/**
768
 
 * Reset notification.
769
 
 *
770
 
 * @returns VBox status.
771
 
 * @param   pDrvIns     The driver instance data.
772
 
 */
773
 
DECLCALLBACK(void) VMMDev::drvReset(PPDMDRVINS pDrvIns)
774
 
{
775
 
    LogFlow(("VMMDev::drvReset: iInstance=%d\n", pDrvIns->iInstance));
776
 
#ifdef VBOX_WITH_HGCM
777
 
    HGCMHostReset ();
778
 
#endif /* VBOX_WITH_HGCM */
779
 
}
780
 
 
781
 
/**
782
 
 * Construct a VMMDev driver instance.
783
 
 *
784
 
 * @copydoc FNPDMDRVCONSTRUCT
785
 
 */
786
 
DECLCALLBACK(int) VMMDev::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle, uint32_t fFlags)
787
 
{
788
 
    PDRVMAINVMMDEV pData = PDMINS_2_DATA(pDrvIns, PDRVMAINVMMDEV);
789
 
    LogFlow(("Keyboard::drvConstruct: iInstance=%d\n", pDrvIns->iInstance));
790
 
 
791
 
    /*
792
 
     * Validate configuration.
793
 
     */
794
 
    if (!CFGMR3AreValuesValid(pCfgHandle, "Object\0"))
795
 
        return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
796
 
    AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
797
 
                    ("Configuration error: Not possible to attach anything to this driver!\n"),
798
 
                    VERR_PDM_DRVINS_NO_ATTACH);
799
 
 
800
 
    /*
801
 
     * IBase.
802
 
     */
803
 
    pDrvIns->IBase.pfnQueryInterface                  = VMMDev::drvQueryInterface;
804
 
 
805
 
    pData->Connector.pfnUpdateGuestStatus             = vmmdevUpdateGuestStatus;
806
 
    pData->Connector.pfnUpdateGuestInfo               = vmmdevUpdateGuestInfo;
807
 
    pData->Connector.pfnUpdateGuestCapabilities       = vmmdevUpdateGuestCapabilities;
808
 
    pData->Connector.pfnUpdateMouseCapabilities       = vmmdevUpdateMouseCapabilities;
809
 
    pData->Connector.pfnUpdatePointerShape            = vmmdevUpdatePointerShape;
810
 
    pData->Connector.pfnVideoAccelEnable              = iface_VideoAccelEnable;
811
 
    pData->Connector.pfnVideoAccelFlush               = iface_VideoAccelFlush;
812
 
    pData->Connector.pfnVideoModeSupported            = vmmdevVideoModeSupported;
813
 
    pData->Connector.pfnGetHeightReduction            = vmmdevGetHeightReduction;
814
 
    pData->Connector.pfnSetCredentialsJudgementResult = vmmdevSetCredentialsJudgementResult;
815
 
    pData->Connector.pfnSetVisibleRegion              = vmmdevSetVisibleRegion;
816
 
    pData->Connector.pfnQueryVisibleRegion            = vmmdevQueryVisibleRegion;
817
 
    pData->Connector.pfnReportStatistics              = vmmdevReportStatistics;
818
 
    pData->Connector.pfnQueryStatisticsInterval       = vmmdevQueryStatisticsInterval;
819
 
    pData->Connector.pfnQueryBalloonSize              = vmmdevQueryBalloonSize;
820
 
    pData->Connector.pfnIsPageFusionEnabled           = vmmdevIsPageFusionEnabled;
821
 
 
822
 
#ifdef VBOX_WITH_HGCM
823
 
    pData->HGCMConnector.pfnConnect                   = iface_hgcmConnect;
824
 
    pData->HGCMConnector.pfnDisconnect                = iface_hgcmDisconnect;
825
 
    pData->HGCMConnector.pfnCall                      = iface_hgcmCall;
826
 
#endif
827
 
 
828
 
    /*
829
 
     * Get the IVMMDevPort interface of the above driver/device.
830
 
     */
831
 
    pData->pUpPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIVMMDEVPORT);
832
 
    AssertMsgReturn(pData->pUpPort, ("Configuration error: No VMMDev port interface above!\n"), VERR_PDM_MISSING_INTERFACE_ABOVE);
833
 
 
834
 
#ifdef VBOX_WITH_HGCM
835
 
    pData->pHGCMPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIHGCMPORT);
836
 
    AssertMsgReturn(pData->pHGCMPort, ("Configuration error: No HGCM port interface above!\n"), VERR_PDM_MISSING_INTERFACE_ABOVE);
837
 
#endif
838
 
 
839
 
    /*
840
 
     * Get the Console object pointer and update the mpDrv member.
841
 
     */
842
 
    void *pv;
843
 
    int rc = CFGMR3QueryPtr(pCfgHandle, "Object", &pv);
844
 
    if (RT_FAILURE(rc))
845
 
    {
846
 
        AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
847
 
        return rc;
848
 
    }
849
 
 
850
 
    pData->pVMMDev = (VMMDev*)pv;        /** @todo Check this cast! */
851
 
    pData->pVMMDev->mpDrv = pData;
852
 
 
853
 
#ifdef VBOX_WITH_HGCM
854
 
    rc = pData->pVMMDev->hgcmLoadService(VBOXSHAREDFOLDERS_DLL,
855
 
                                         "VBoxSharedFolders");
856
 
    pData->pVMMDev->fSharedFolderActive = RT_SUCCESS(rc);
857
 
    if (RT_SUCCESS(rc))
858
 
    {
859
 
        PPDMLED       pLed;
860
 
        PPDMILEDPORTS pLedPort;
861
 
 
862
 
        LogRel(("Shared Folders service loaded.\n"));
863
 
        pLedPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMILEDPORTS);
864
 
        AssertMsgReturn(pLedPort, ("Configuration error: No LED port interface above!\n"), VERR_PDM_MISSING_INTERFACE_ABOVE);
865
 
        rc = pLedPort->pfnQueryStatusLed(pLedPort, 0, &pLed);
866
 
        if (RT_SUCCESS(rc) && pLed)
867
 
        {
868
 
            VBOXHGCMSVCPARM  parm;
869
 
 
870
 
            parm.type = VBOX_HGCM_SVC_PARM_PTR;
871
 
            parm.u.pointer.addr = pLed;
872
 
            parm.u.pointer.size = sizeof(*pLed);
873
 
 
874
 
            rc = HGCMHostCall("VBoxSharedFolders", SHFL_FN_SET_STATUS_LED, 1, &parm);
875
 
        }
876
 
        else
877
 
            AssertMsgFailed(("pfnQueryStatusLed failed with %Rrc (pLed=%x)\n", rc, pLed));
878
 
    }
879
 
    else
880
 
        LogRel(("Failed to load Shared Folders service %Rrc\n", rc));
881
 
 
882
 
    rc = PDMDrvHlpSSMRegisterEx(pDrvIns, HGCM_SSM_VERSION, 4096 /* bad guess */,
883
 
                                NULL, NULL, NULL,
884
 
                                NULL, iface_hgcmSave, NULL,
885
 
                                NULL, iface_hgcmLoad, NULL);
886
 
    if (RT_FAILURE(rc))
887
 
        return rc;
888
 
 
889
 
#endif /* VBOX_WITH_HGCM */
890
 
 
891
 
    return VINF_SUCCESS;
892
 
}
893
 
 
894
 
 
895
 
/**
896
 
 * VMMDevice driver registration record.
897
 
 */
898
 
const PDMDRVREG VMMDev::DrvReg =
899
 
{
900
 
    /* u32Version */
901
 
    PDM_DRVREG_VERSION,
902
 
    /* szName */
903
 
    "HGCM",
904
 
    /* szRCMod */
905
 
    "",
906
 
    /* szR0Mod */
907
 
    "",
908
 
    /* pszDescription */
909
 
    "Main VMMDev driver (Main as in the API).",
910
 
    /* fFlags */
911
 
    PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
912
 
    /* fClass. */
913
 
    PDM_DRVREG_CLASS_VMMDEV,
914
 
    /* cMaxInstances */
915
 
    ~0,
916
 
    /* cbInstance */
917
 
    sizeof(DRVMAINVMMDEV),
918
 
    /* pfnConstruct */
919
 
    VMMDev::drvConstruct,
920
 
    /* pfnDestruct */
921
 
    VMMDev::drvDestruct,
922
 
    /* pfnRelocate */
923
 
    NULL,
924
 
    /* pfnIOCtl */
925
 
    NULL,
926
 
    /* pfnPowerOn */
927
 
    NULL,
928
 
    /* pfnReset */
929
 
    VMMDev::drvReset,
930
 
    /* pfnSuspend */
931
 
    NULL,
932
 
    /* pfnResume */
933
 
    NULL,
934
 
    /* pfnAttach */
935
 
    NULL,
936
 
    /* pfnDetach */
937
 
    NULL,
938
 
    /* pfnPowerOff */
939
 
    NULL,
940
 
    /* pfnSoftReset */
941
 
    NULL,
942
 
    /* u32EndVersion */
943
 
    PDM_DRVREG_VERSION
944
 
};
945
 
/* vi: set tabstop=4 shiftwidth=4 expandtab: */