VirtualBox

source: vbox/trunk/src/VBox/Main/VMMDevInterface.cpp@ 7954

Last change on this file since 7954 was 7409, checked in by vboxsync, 17 years ago

VMMDev: added VMMDEV_GUEST_SUPPORTS_GRAPHICS capability, enabled by default, to distinguish cases where the guest additions are loaded but graphics are not supported

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 27.0 KB
Line 
1/** @file
2 *
3 * VirtualBox Driver Interface to VMM device
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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
23#include "Logging.h"
24
25#include <VBox/pdmdrv.h>
26#include <VBox/VBoxDev.h>
27#include <VBox/VBoxGuest.h>
28#include <VBox/shflsvc.h>
29#include <iprt/asm.h>
30
31#ifdef VBOX_HGCM
32#include "hgcm/HGCM.h"
33#include "hgcm/HGCMObjects.h"
34#endif
35
36//
37// defines
38//
39
40#ifdef RT_OS_OS2
41# define VBOXSHAREDFOLDERS_DLL "VBoxSFld"
42#else
43# define VBOXSHAREDFOLDERS_DLL "VBoxSharedFolders"
44#endif
45
46//
47// globals
48//
49
50
51/**
52 * VMMDev driver instance data.
53 */
54typedef struct DRVMAINVMMDEV
55{
56 /** Pointer to the VMMDev object. */
57 VMMDev *pVMMDev;
58 /** Pointer to the driver instance structure. */
59 PPDMDRVINS pDrvIns;
60 /** Pointer to the VMMDev port interface of the driver/device above us. */
61 PPDMIVMMDEVPORT pUpPort;
62 /** Our VMM device connector interface. */
63 PDMIVMMDEVCONNECTOR Connector;
64
65#ifdef VBOX_HGCM
66 /** Pointer to the HGCM port interface of the driver/device above us. */
67 PPDMIHGCMPORT pHGCMPort;
68 /** Our HGCM connector interface. */
69 PDMIHGCMCONNECTOR HGCMConnector;
70#endif
71} DRVMAINVMMDEV, *PDRVMAINVMMDEV;
72
73/** Converts PDMIVMMDEVCONNECTOR pointer to a DRVMAINVMMDEV pointer. */
74#define PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface) ( (PDRVMAINVMMDEV) ((uintptr_t)pInterface - RT_OFFSETOF(DRVMAINVMMDEV, Connector)) )
75
76#ifdef VBOX_HGCM
77/** Converts PDMIHGCMCONNECTOR pointer to a DRVMAINVMMDEV pointer. */
78#define PDMIHGCMCONNECTOR_2_MAINVMMDEV(pInterface) ( (PDRVMAINVMMDEV) ((uintptr_t)pInterface - RT_OFFSETOF(DRVMAINVMMDEV, HGCMConnector)) )
79#endif
80
81//
82// constructor / destructor
83//
84VMMDev::VMMDev(Console *console) : mpDrv(NULL)
85{
86 mParent = console;
87 int rc = RTSemEventCreate(&mCredentialsEvent);
88 AssertRC(rc);
89#ifdef VBOX_HGCM
90 rc = HGCMHostInit ();
91 AssertRC(rc);
92#endif /* VBOX_HGCM */
93 mu32CredentialsFlags = 0;
94}
95
96VMMDev::~VMMDev()
97{
98 RTSemEventDestroy (mCredentialsEvent);
99 if (mpDrv)
100 mpDrv->pVMMDev = NULL;
101 mpDrv = NULL;
102}
103
104PPDMIVMMDEVPORT VMMDev::getVMMDevPort()
105{
106 Assert(mpDrv);
107 return mpDrv->pUpPort;
108}
109
110
111
112//
113// public methods
114//
115
116/**
117 * Wait on event semaphore for guest credential judgement result.
118 */
119int VMMDev::WaitCredentialsJudgement (uint32_t u32Timeout, uint32_t *pu32CredentialsFlags)
120{
121 if (u32Timeout == 0)
122 {
123 u32Timeout = 5000;
124 }
125
126 int rc = RTSemEventWait (mCredentialsEvent, u32Timeout);
127
128 if (VBOX_SUCCESS (rc))
129 {
130 *pu32CredentialsFlags = mu32CredentialsFlags;
131 }
132
133 return rc;
134}
135
136int VMMDev::SetCredentialsJudgementResult (uint32_t u32Flags)
137{
138 mu32CredentialsFlags = u32Flags;
139
140 int rc = RTSemEventSignal (mCredentialsEvent);
141 AssertRC(rc);
142
143 return rc;
144}
145
146
147/**
148 * Report guest OS version.
149 * Called whenever the Additions issue a guest version report request.
150 *
151 * @param pInterface Pointer to this interface.
152 * @param guestInfo Pointer to guest information structure
153 * @thread The emulation thread.
154 */
155DECLCALLBACK(void) vmmdevUpdateGuestVersion(PPDMIVMMDEVCONNECTOR pInterface, VBoxGuestInfo *guestInfo)
156{
157 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
158
159 Assert(guestInfo);
160 if (!guestInfo)
161 return;
162
163 /* store that information in IGuest */
164 Guest* guest = pDrv->pVMMDev->getParent()->getGuest();
165 Assert(guest);
166 if (!guest)
167 return;
168
169 char version[20];
170 RTStrPrintf(version, sizeof(version), "%d", guestInfo->additionsVersion);
171 guest->setAdditionsVersion(Bstr(version));
172
173 /*
174 * Tell the console interface about the event
175 * so that it can notify its consumers.
176 */
177 pDrv->pVMMDev->getParent()->onAdditionsStateChange();
178
179 if (guestInfo->additionsVersion < VMMDEV_VERSION)
180 {
181 pDrv->pVMMDev->getParent()->onAdditionsOutdated();
182 }
183}
184
185/**
186 * Update the guest additions capabilities.
187 * This is called when the guest additions capabilities change. The new capabilities
188 * are given and the connector should update its internal state.
189 *
190 * @param pInterface Pointer to this interface.
191 * @param newCapabilities New capabilities.
192 * @thread The emulation thread.
193 */
194DECLCALLBACK(void) vmmdevUpdateGuestCapabilities(PPDMIVMMDEVCONNECTOR pInterface, uint32_t newCapabilities)
195{
196 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
197
198 /* store that information in IGuest */
199 Guest* guest = pDrv->pVMMDev->getParent()->getGuest();
200 Assert(guest);
201 if (!guest)
202 return;
203
204 guest->setSupportsSeamless(BOOL (newCapabilities & VMMDEV_GUEST_SUPPORTS_SEAMLESS));
205 guest->setSupportsGraphics(BOOL (newCapabilities & VMMDEV_GUEST_SUPPORTS_GRAPHICS));
206
207 /*
208 * Tell the console interface about the event
209 * so that it can notify its consumers.
210 */
211 pDrv->pVMMDev->getParent()->onAdditionsStateChange();
212
213}
214
215/**
216 * Update the mouse capabilities.
217 * This is called when the mouse capabilities change. The new capabilities
218 * are given and the connector should update its internal state.
219 *
220 * @param pInterface Pointer to this interface.
221 * @param newCapabilities New capabilities.
222 * @thread The emulation thread.
223 */
224DECLCALLBACK(void) vmmdevUpdateMouseCapabilities(PPDMIVMMDEVCONNECTOR pInterface, uint32_t newCapabilities)
225{
226 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
227 /*
228 * Tell the console interface about the event
229 * so that it can notify its consumers.
230 */
231 pDrv->pVMMDev->getParent()->onMouseCapabilityChange(BOOL (newCapabilities & VMMDEV_MOUSEGUESTWANTSABS),
232 BOOL (newCapabilities & VMMDEV_MOUSEGUESTNEEDSHOSTCUR));
233}
234
235
236/**
237 * Update the pointer shape or visibility.
238 *
239 * This is called when the mouse pointer shape changes or pointer is hidden/displaying.
240 * The new shape is passed as a caller allocated buffer that will be freed after returning.
241 *
242 * @param pInterface Pointer to this interface.
243 * @param fVisible Whether the pointer is visible or not.
244 * @param fAlpha Alpha channel information is present.
245 * @param xHot Horizontal coordinate of the pointer hot spot.
246 * @param yHot Vertical coordinate of the pointer hot spot.
247 * @param width Pointer width in pixels.
248 * @param height Pointer height in pixels.
249 * @param pShape The shape buffer. If NULL, then only pointer visibility is being changed.
250 * @thread The emulation thread.
251 */
252DECLCALLBACK(void) vmmdevUpdatePointerShape(PPDMIVMMDEVCONNECTOR pInterface, bool fVisible, bool fAlpha,
253 uint32_t xHot, uint32_t yHot,
254 uint32_t width, uint32_t height,
255 void *pShape)
256{
257 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
258
259 /* tell the console about it */
260 pDrv->pVMMDev->getParent()->onMousePointerShapeChange(fVisible, fAlpha,
261 xHot, yHot, width, height, pShape);
262}
263
264DECLCALLBACK(int) iface_VideoAccelEnable(PPDMIVMMDEVCONNECTOR pInterface, bool fEnable, VBVAMEMORY *pVbvaMemory)
265{
266 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
267
268 Display *display = pDrv->pVMMDev->getParent()->getDisplay();
269
270 if (display)
271 {
272 LogSunlover(("MAIN::VMMDevInterface::iface_VideoAccelEnable: %d, %p\n", fEnable, pVbvaMemory));
273 return display->VideoAccelEnable (fEnable, pVbvaMemory);
274 }
275
276 return VERR_NOT_SUPPORTED;
277}
278DECLCALLBACK(void) iface_VideoAccelFlush(PPDMIVMMDEVCONNECTOR pInterface)
279{
280 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
281
282 Display *display = pDrv->pVMMDev->getParent()->getDisplay();
283
284 if (display)
285 {
286 LogSunlover(("MAIN::VMMDevInterface::iface_VideoAccelFlush\n"));
287 display->VideoAccelFlush ();
288 }
289}
290
291DECLCALLBACK(int) vmmdevVideoModeSupported(PPDMIVMMDEVCONNECTOR pInterface, uint32_t width, uint32_t height,
292 uint32_t bpp, bool *fSupported)
293{
294 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
295
296 if (!fSupported)
297 return VERR_INVALID_PARAMETER;
298 IFramebuffer *framebuffer = pDrv->pVMMDev->getParent()->getDisplay()->getFramebuffer();
299 if (framebuffer)
300 framebuffer->VideoModeSupported(width, height, bpp, (BOOL*)fSupported);
301 else
302 *fSupported = true;
303 return VINF_SUCCESS;
304}
305
306DECLCALLBACK(int) vmmdevGetHeightReduction(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *heightReduction)
307{
308 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
309
310 if (!heightReduction)
311 return VERR_INVALID_PARAMETER;
312 IFramebuffer *framebuffer = pDrv->pVMMDev->getParent()->getDisplay()->getFramebuffer();
313 if (framebuffer)
314 framebuffer->COMGETTER(HeightReduction)((ULONG*)heightReduction);
315 else
316 *heightReduction = 0;
317 return VINF_SUCCESS;
318}
319
320DECLCALLBACK(int) vmmdevSetCredentialsJudgementResult(PPDMIVMMDEVCONNECTOR pInterface, uint32_t u32Flags)
321{
322 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
323
324 int rc = pDrv->pVMMDev->SetCredentialsJudgementResult (u32Flags);
325
326 return rc;
327}
328
329DECLCALLBACK(int) vmmdevSetVisibleRegion(PPDMIVMMDEVCONNECTOR pInterface, uint32_t cRect, PRTRECT pRect)
330{
331 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
332
333 if (!cRect)
334 return VERR_INVALID_PARAMETER;
335 IFramebuffer *framebuffer = pDrv->pVMMDev->getParent()->getDisplay()->getFramebuffer();
336 if (framebuffer)
337 framebuffer->SetVisibleRegion((BYTE *)pRect, cRect);
338
339 return VINF_SUCCESS;
340}
341
342DECLCALLBACK(int) vmmdevQueryVisibleRegion(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pcRect, PRTRECT pRect)
343{
344 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
345
346 IFramebuffer *framebuffer = pDrv->pVMMDev->getParent()->getDisplay()->getFramebuffer();
347 if (framebuffer)
348 {
349 ULONG cRect = 0;
350 framebuffer->GetVisibleRegion((BYTE *)pRect, cRect, &cRect);
351
352 *pcRect = cRect;
353 }
354
355 return VINF_SUCCESS;
356}
357
358/**
359 * Request the statistics interval
360 *
361 * @returns VBox status code.
362 * @param pInterface Pointer to this interface.
363 * @param pulInterval Pointer to interval in seconds
364 * @thread The emulation thread.
365 */
366DECLCALLBACK(int) vmmdevQueryStatisticsInterval(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pulInterval)
367{
368 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
369 ULONG val = 0;
370
371 if (!pulInterval)
372 return VERR_INVALID_POINTER;
373
374 /* store that information in IGuest */
375 Guest* guest = pDrv->pVMMDev->getParent()->getGuest();
376 Assert(guest);
377 if (!guest)
378 return VERR_INVALID_PARAMETER; /** @todo wrong error */
379
380 guest->COMGETTER(StatisticsUpdateInterval)(&val);
381 *pulInterval = val;
382 return VINF_SUCCESS;
383}
384
385/**
386 * Report new guest statistics
387 *
388 * @returns VBox status code.
389 * @param pInterface Pointer to this interface.
390 * @param pGuestStats Guest statistics
391 * @thread The emulation thread.
392 */
393DECLCALLBACK(int) vmmdevReportStatistics(PPDMIVMMDEVCONNECTOR pInterface, VBoxGuestStatistics *pGuestStats)
394{
395 PDRVMAINVMMDEV pDrv = PDMIVMMDEVCONNECTOR_2_MAINVMMDEV(pInterface);
396
397 Assert(pGuestStats);
398 if (!pGuestStats)
399 return VERR_INVALID_POINTER;
400
401 /* store that information in IGuest */
402 Guest* guest = pDrv->pVMMDev->getParent()->getGuest();
403 Assert(guest);
404 if (!guest)
405 return VERR_INVALID_PARAMETER; /** @todo wrong error */
406
407 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_CPU_LOAD_IDLE)
408 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_CPULoad_Idle, pGuestStats->u32CpuLoad_Idle);
409
410 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_CPU_LOAD_KERNEL)
411 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_CPULoad_Kernel, pGuestStats->u32CpuLoad_Kernel);
412
413 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_CPU_LOAD_USER)
414 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_CPULoad_User, pGuestStats->u32CpuLoad_User);
415
416 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_THREADS)
417 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_Threads, pGuestStats->u32Threads);
418
419 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PROCESSES)
420 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_Processes, pGuestStats->u32Processes);
421
422 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_HANDLES)
423 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_Handles, pGuestStats->u32Handles);
424
425 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_MEMORY_LOAD)
426 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_MemoryLoad, pGuestStats->u32MemoryLoad);
427
428 /* Note that reported values are in pages; upper layers expect them in megabytes */
429 Assert(pGuestStats->u32PageSize == 4096);
430 if (pGuestStats->u32PageSize != 4096)
431 pGuestStats->u32PageSize = 4096;
432
433 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_TOTAL)
434 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_PhysMemTotal, (pGuestStats->u32PhysMemTotal + (_1M/pGuestStats->u32PageSize)-1) / (_1M/pGuestStats->u32PageSize));
435
436 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_AVAIL)
437 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_PhysMemAvailable, pGuestStats->u32PhysMemAvail / (_1M/pGuestStats->u32PageSize));
438
439 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_BALLOON)
440 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_PhysMemBalloon, pGuestStats->u32PhysMemBalloon / (_1M/pGuestStats->u32PageSize));
441
442 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_MEM_COMMIT_TOTAL)
443 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_MemCommitTotal, pGuestStats->u32MemCommitTotal / (_1M/pGuestStats->u32PageSize));
444
445 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_MEM_KERNEL_TOTAL)
446 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_MemKernelTotal, pGuestStats->u32MemKernelTotal / (_1M/pGuestStats->u32PageSize));
447
448 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_MEM_KERNEL_PAGED)
449 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_MemKernelPaged, pGuestStats->u32MemKernelPaged / (_1M/pGuestStats->u32PageSize));
450
451 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_MEM_KERNEL_NONPAGED)
452 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_MemKernelNonpaged, pGuestStats->u32MemKernelNonPaged / (_1M/pGuestStats->u32PageSize));
453
454 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_MEM_SYSTEM_CACHE)
455 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_MemSystemCache, pGuestStats->u32MemSystemCache / (_1M/pGuestStats->u32PageSize));
456
457 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PAGE_FILE_SIZE)
458 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_PageFileSize, pGuestStats->u32PageFileSize / (_1M/pGuestStats->u32PageSize));
459
460 /* increase sample number */
461 ULONG sample;
462
463 int rc = guest->GetStatistic(0, GuestStatisticType_SampleNumber, &sample);
464 if (SUCCEEDED(rc))
465 guest->SetStatistic(pGuestStats->u32CpuId, GuestStatisticType_SampleNumber, sample+1);
466
467 return VINF_SUCCESS;
468}
469
470/**
471 * Inflate or deflate the memory balloon
472 *
473 * @returns VBox status code.
474 * @param pInterface Pointer to this interface.
475 * @param fInflate Inflate or deflate
476 * @param cPages Number of physical pages (must be 256 as we allocate in 1 MB chunks)
477 * @param aPhysPage Array of physical page addresses
478 * @thread The emulation thread.
479 */
480DECLCALLBACK(int) vmmdevChangeMemoryBalloon(PPDMIVMMDEVCONNECTOR pInterface, bool fInflate, uint32_t cPages, RTGCPHYS *aPhysPage)
481{
482 if ( cPages != VMMDEV_MEMORY_BALLOON_CHUNK_PAGES
483 || !aPhysPage)
484 return VERR_INVALID_PARAMETER;
485
486 Log(("vmmdevChangeMemoryBalloon @todo\n"));
487 return VINF_SUCCESS;
488}
489
490#ifdef VBOX_HGCM
491
492/* HGCM connector interface */
493
494static DECLCALLBACK(int) iface_hgcmConnect (PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, PHGCMSERVICELOCATION pServiceLocation, uint32_t *pu32ClientID)
495{
496 LogSunlover(("Enter\n"));
497
498 PDRVMAINVMMDEV pDrv = PDMIHGCMCONNECTOR_2_MAINVMMDEV(pInterface);
499
500 if ( !pServiceLocation
501 || ( pServiceLocation->type != VMMDevHGCMLoc_LocalHost
502 && pServiceLocation->type != VMMDevHGCMLoc_LocalHost_Existing))
503 {
504 return VERR_INVALID_PARAMETER;
505 }
506
507 return HGCMGuestConnect (pDrv->pHGCMPort, pCmd, pServiceLocation->u.host.achName, pu32ClientID);
508}
509
510static DECLCALLBACK(int) iface_hgcmDisconnect (PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, uint32_t u32ClientID)
511{
512 LogSunlover(("Enter\n"));
513
514 PDRVMAINVMMDEV pDrv = PDMIHGCMCONNECTOR_2_MAINVMMDEV(pInterface);
515
516 return HGCMGuestDisconnect (pDrv->pHGCMPort, pCmd, u32ClientID);
517}
518
519static DECLCALLBACK(int) iface_hgcmCall (PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, uint32_t u32ClientID, uint32_t u32Function,
520 uint32_t cParms, PVBOXHGCMSVCPARM paParms)
521{
522 LogSunlover(("Enter\n"));
523
524 PDRVMAINVMMDEV pDrv = PDMIHGCMCONNECTOR_2_MAINVMMDEV(pInterface);
525
526 return HGCMGuestCall (pDrv->pHGCMPort, pCmd, u32ClientID, u32Function, cParms, paParms);
527}
528
529/**
530 * Execute state save operation.
531 *
532 * @returns VBox status code.
533 * @param pDrvIns Driver instance of the driver which registered the data unit.
534 * @param pSSM SSM operation handle.
535 */
536static DECLCALLBACK(int) iface_hgcmSave(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM)
537{
538 LogSunlover(("Enter\n"));
539 return HGCMHostSaveState (pSSM);
540}
541
542
543/**
544 * Execute state load operation.
545 *
546 * @returns VBox status code.
547 * @param pDrvIns Driver instance of the driver which registered the data unit.
548 * @param pSSM SSM operation handle.
549 * @param u32Version Data layout version.
550 */
551static DECLCALLBACK(int) iface_hgcmLoad(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM, uint32_t u32Version)
552{
553 LogFlowFunc(("Enter\n"));
554
555 if (u32Version != HGCM_SSM_VERSION)
556 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
557
558 return HGCMHostLoadState (pSSM);
559}
560
561int VMMDev::hgcmLoadService (const char *pszServiceLibrary, const char *pszServiceName)
562{
563 return HGCMHostLoad (pszServiceLibrary, pszServiceName);
564}
565
566int VMMDev::hgcmHostCall (const char *pszServiceName, uint32_t u32Function,
567 uint32_t cParms, PVBOXHGCMSVCPARM paParms)
568{
569 return HGCMHostCall (pszServiceName, u32Function, cParms, paParms);
570}
571
572void VMMDev::hgcmShutdown (void)
573{
574 HGCMHostShutdown ();
575}
576
577#endif /* HGCM */
578
579
580/**
581 * Queries an interface to the driver.
582 *
583 * @returns Pointer to interface.
584 * @returns NULL if the interface was not supported by the driver.
585 * @param pInterface Pointer to this interface structure.
586 * @param enmInterface The requested interface identification.
587 */
588DECLCALLBACK(void *) VMMDev::drvQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
589{
590 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
591 PDRVMAINVMMDEV pDrv = PDMINS2DATA(pDrvIns, PDRVMAINVMMDEV);
592 switch (enmInterface)
593 {
594 case PDMINTERFACE_BASE:
595 return &pDrvIns->IBase;
596 case PDMINTERFACE_VMMDEV_CONNECTOR:
597 return &pDrv->Connector;
598#ifdef VBOX_HGCM
599 case PDMINTERFACE_HGCM_CONNECTOR:
600 return &pDrv->HGCMConnector;
601#endif
602 default:
603 return NULL;
604 }
605}
606
607/**
608 * Destruct a VMMDev driver instance.
609 *
610 * @returns VBox status.
611 * @param pDrvIns The driver instance data.
612 */
613DECLCALLBACK(void) VMMDev::drvDestruct(PPDMDRVINS pDrvIns)
614{
615 PDRVMAINVMMDEV pData = PDMINS2DATA(pDrvIns, PDRVMAINVMMDEV);
616 LogFlow(("VMMDev::drvDestruct: iInstance=%d\n", pDrvIns->iInstance));
617#ifdef VBOX_HGCM
618 /* HGCM is shut down on the VMMDev destructor. */
619#endif /* VBOX_HGCM */
620 if (pData->pVMMDev)
621 {
622 pData->pVMMDev->mpDrv = NULL;
623 }
624}
625
626/**
627 * Reset notification.
628 *
629 * @returns VBox status.
630 * @param pDrvIns The driver instance data.
631 */
632DECLCALLBACK(void) VMMDev::drvReset(PPDMDRVINS pDrvIns)
633{
634 LogFlow(("VMMDev::drvReset: iInstance=%d\n", pDrvIns->iInstance));
635#ifdef VBOX_HGCM
636 HGCMHostReset ();
637#endif /* VBOX_HGCM */
638}
639
640/**
641 * Construct a VMMDev driver instance.
642 *
643 * @returns VBox status.
644 * @param pDrvIns The driver instance data.
645 * If the registration structure is needed, pDrvIns->pDrvReg points to it.
646 * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
647 * of the driver instance. It's also found in pDrvIns->pCfgHandle, but like
648 * iInstance it's expected to be used a bit in this function.
649 */
650DECLCALLBACK(int) VMMDev::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
651{
652 PDRVMAINVMMDEV pData = PDMINS2DATA(pDrvIns, PDRVMAINVMMDEV);
653 LogFlow(("Keyboard::drvConstruct: iInstance=%d\n", pDrvIns->iInstance));
654
655 /*
656 * Validate configuration.
657 */
658 if (!CFGMR3AreValuesValid(pCfgHandle, "Object\0OpenGLEnabled\0"))
659 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
660 PPDMIBASE pBaseIgnore;
661 int rc = pDrvIns->pDrvHlp->pfnAttach(pDrvIns, &pBaseIgnore);
662 if (rc != VERR_PDM_NO_ATTACHED_DRIVER)
663 {
664 AssertMsgFailed(("Configuration error: Not possible to attach anything to this driver!\n"));
665 return VERR_PDM_DRVINS_NO_ATTACH;
666 }
667
668 /*
669 * IBase.
670 */
671 pDrvIns->IBase.pfnQueryInterface = VMMDev::drvQueryInterface;
672
673 pData->Connector.pfnUpdateGuestVersion = vmmdevUpdateGuestVersion;
674 pData->Connector.pfnUpdateGuestCapabilities = vmmdevUpdateGuestCapabilities;
675 pData->Connector.pfnUpdateMouseCapabilities = vmmdevUpdateMouseCapabilities;
676 pData->Connector.pfnUpdatePointerShape = vmmdevUpdatePointerShape;
677 pData->Connector.pfnVideoAccelEnable = iface_VideoAccelEnable;
678 pData->Connector.pfnVideoAccelFlush = iface_VideoAccelFlush;
679 pData->Connector.pfnVideoModeSupported = vmmdevVideoModeSupported;
680 pData->Connector.pfnGetHeightReduction = vmmdevGetHeightReduction;
681 pData->Connector.pfnSetCredentialsJudgementResult = vmmdevSetCredentialsJudgementResult;
682 pData->Connector.pfnSetVisibleRegion = vmmdevSetVisibleRegion;
683 pData->Connector.pfnQueryVisibleRegion = vmmdevQueryVisibleRegion;
684 pData->Connector.pfnReportStatistics = vmmdevReportStatistics;
685 pData->Connector.pfnQueryStatisticsInterval = vmmdevQueryStatisticsInterval;
686 pData->Connector.pfnChangeMemoryBalloon = vmmdevChangeMemoryBalloon;
687
688#ifdef VBOX_HGCM
689 pData->HGCMConnector.pfnConnect = iface_hgcmConnect;
690 pData->HGCMConnector.pfnDisconnect = iface_hgcmDisconnect;
691 pData->HGCMConnector.pfnCall = iface_hgcmCall;
692#endif
693
694 /*
695 * Get the IVMMDevPort interface of the above driver/device.
696 */
697 pData->pUpPort = (PPDMIVMMDEVPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_VMMDEV_PORT);
698 if (!pData->pUpPort)
699 {
700 AssertMsgFailed(("Configuration error: No VMMDev port interface above!\n"));
701 return VERR_PDM_MISSING_INTERFACE_ABOVE;
702 }
703
704#ifdef VBOX_HGCM
705 pData->pHGCMPort = (PPDMIHGCMPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_HGCM_PORT);
706 if (!pData->pHGCMPort)
707 {
708 AssertMsgFailed(("Configuration error: No HGCM port interface above!\n"));
709 return VERR_PDM_MISSING_INTERFACE_ABOVE;
710 }
711#endif
712
713 /*
714 * Get the Console object pointer and update the mpDrv member.
715 */
716 void *pv;
717 rc = CFGMR3QueryPtr(pCfgHandle, "Object", &pv);
718 if (VBOX_FAILURE(rc))
719 {
720 AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Vrc\n", rc));
721 return rc;
722 }
723
724 pData->pVMMDev = (VMMDev*)pv; /** @todo Check this cast! */
725 pData->pVMMDev->mpDrv = pData;
726
727#ifdef VBOX_HGCM
728 rc = pData->pVMMDev->hgcmLoadService (VBOXSHAREDFOLDERS_DLL,
729 "VBoxSharedFolders");
730 pData->pVMMDev->fSharedFolderActive = VBOX_SUCCESS(rc);
731 if (VBOX_SUCCESS(rc))
732 {
733 PPDMLED pLed;
734 PPDMILEDPORTS pLedPort;
735
736 LogRel(("Shared Folders service loaded.\n"));
737 pLedPort = (PPDMILEDPORTS)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_LED_PORTS);
738 if (!pLedPort)
739 {
740 AssertMsgFailed(("Configuration error: No LED port interface above!\n"));
741 return VERR_PDM_MISSING_INTERFACE_ABOVE;
742 }
743 rc = pLedPort->pfnQueryStatusLed(pLedPort, 0, &pLed);
744 if (VBOX_SUCCESS(rc) && pLed)
745 {
746 VBOXHGCMSVCPARM parm;
747
748 parm.type = VBOX_HGCM_SVC_PARM_PTR;
749 parm.u.pointer.addr = pLed;
750 parm.u.pointer.size = sizeof(*pLed);
751
752 rc = HGCMHostCall("VBoxSharedFolders", SHFL_FN_SET_STATUS_LED, 1, &parm);
753 }
754 else
755 AssertMsgFailed(("pfnQueryStatusLed failed with %Vrc (pLed=%x)\n", rc, pLed));
756 }
757 else
758 {
759 LogRel(("Failed to load Shared Folders service %Vrc\n", rc));
760 }
761
762 bool fEnabled;
763
764 /* Check CFGM option. */
765 rc = CFGMR3QueryBool(pCfgHandle, "OpenGLEnabled", &fEnabled);
766 if ( VBOX_SUCCESS(rc)
767 && fEnabled)
768 {
769 rc = pData->pVMMDev->hgcmLoadService ("VBoxSharedOpenGL", "VBoxSharedOpenGL");
770 if (VBOX_SUCCESS(rc))
771 {
772 LogRel(("Shared OpenGL service loaded.\n"));
773 }
774 else
775 {
776 LogRel(("Failed to load Shared OpenGL service %Vrc\n", rc));
777 }
778 }
779
780 pDrvIns->pDrvHlp->pfnSSMRegister(pDrvIns, "HGCM", 0, HGCM_SSM_VERSION, 4096/* bad guess */, NULL, iface_hgcmSave, NULL, NULL, iface_hgcmLoad, NULL);
781#endif /* VBOX_HGCM */
782
783 return VINF_SUCCESS;
784}
785
786
787/**
788 * VMMDevice driver registration record.
789 */
790const PDMDRVREG VMMDev::DrvReg =
791{
792 /* u32Version */
793 PDM_DRVREG_VERSION,
794 /* szDriverName */
795 "MainVMMDev",
796 /* pszDescription */
797 "Main VMMDev driver (Main as in the API).",
798 /* fFlags */
799 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
800 /* fClass. */
801 PDM_DRVREG_CLASS_VMMDEV,
802 /* cMaxInstances */
803 ~0,
804 /* cbInstance */
805 sizeof(DRVMAINVMMDEV),
806 /* pfnConstruct */
807 VMMDev::drvConstruct,
808 /* pfnDestruct */
809 VMMDev::drvDestruct,
810 /* pfnIOCtl */
811 NULL,
812 /* pfnPowerOn */
813 NULL,
814 /* pfnReset */
815 VMMDev::drvReset,
816 /* pfnSuspend */
817 NULL,
818 /* pfnResume */
819 NULL,
820 /* pfnDetach */
821 NULL
822};
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