VirtualBox

Changeset 54593 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Mar 2, 2015 8:44:44 PM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
98732
Message:

VBoxGuest.cpp: Moved the code guest caps where it belongs.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp

    r54522 r54593  
    6262
    6363/*******************************************************************************
     64*   Defined Constants And Macros                                               *
     65*******************************************************************************/
     66#define VBOXGUEST_ACQUIRE_STYLE_EVENTS (VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST | VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST)
     67
     68
     69/*******************************************************************************
     70*   Structures and Typedefs                                                    *
     71*******************************************************************************/
     72/** Host flags to be updated by a given invocation of the
     73 * vboxGuestUpdateHostFlags() method. */
     74/** @todo r=bird: Use RT_BIT_32 for the bits, preferably replace enum with
     75 *        \#define. */
     76enum
     77{
     78    HostFlags_FilterMask   = 1,
     79    HostFlags_Capabilities = 2,
     80    HostFlags_MouseStatus  = 4,
     81    HostFlags_All          = 7,
     82    HostFlags_SizeHack = (unsigned)-1
     83};
     84
     85
     86/*******************************************************************************
    6487*   Internal Functions                                                         *
    6588*******************************************************************************/
     
    7093                                           uint32_t fNotMask, VBOXGUESTCAPSACQUIRE_FLAGS enmFlags);
    7194static int VBoxGuestCommonIOCtl_CancelAllWaitEvents(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession);
    72 
    73 #define VBOXGUEST_ACQUIRE_STYLE_EVENTS (VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST | VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST)
    74 
    75 /** Return the mask of VMM device events that this session is allowed to see,
    76  *  ergo, all events except those in "acquire" mode which have not been acquired
    77  *  by this session. */
    78 DECLINLINE(uint32_t) VBoxGuestCommonGetHandledEventsLocked(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession)
    79 {
    80     if (!pDevExt->u32AcquireModeGuestCaps)
    81         return VMMDEV_EVENT_VALID_EVENT_MASK;
    82 
    83     /** @note VMMDEV_EVENT_VALID_EVENT_MASK should actually be the mask of valid
    84      *        capabilities, but that doesn't affect this code. */
    85     uint32_t u32AllowedGuestCaps = pSession->u32AquiredGuestCaps | (VMMDEV_EVENT_VALID_EVENT_MASK & ~pDevExt->u32AcquireModeGuestCaps);
    86     uint32_t u32CleanupEvents = VBOXGUEST_ACQUIRE_STYLE_EVENTS;
    87     if (u32AllowedGuestCaps & VMMDEV_GUEST_SUPPORTS_GRAPHICS)
    88         u32CleanupEvents &= ~VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST;
    89     if (u32AllowedGuestCaps & VMMDEV_GUEST_SUPPORTS_SEAMLESS)
    90         u32CleanupEvents &= ~VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST;
    91 
    92     return VMMDEV_EVENT_VALID_EVENT_MASK & ~u32CleanupEvents;
    93 }
    94 
    95 DECLINLINE(uint32_t) VBoxGuestCommonGetAndCleanPendingEventsLocked(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, uint32_t fReqEvents)
    96 {
    97     uint32_t fMatches = pDevExt->f32PendingEvents & fReqEvents & VBoxGuestCommonGetHandledEventsLocked(pDevExt, pSession);
    98     if (fMatches)
    99         ASMAtomicAndU32(&pDevExt->f32PendingEvents, ~fMatches);
    100     return fMatches;
    101 }
    102 
    103 /** Puts a capability in "acquire" or "set" mode and returns the mask of
    104  * capabilities currently in the other mode.  Once a capability has been put in
    105  * one of the two modes it can no longer be removed from that mode. */
    106 DECLINLINE(bool) VBoxGuestCommonGuestCapsModeSet(PVBOXGUESTDEVEXT pDevExt, uint32_t fCaps, bool fAcquire, uint32_t *pu32OtherVal)
    107 {
    108     uint32_t *pVal = fAcquire ? &pDevExt->u32AcquireModeGuestCaps : &pDevExt->u32SetModeGuestCaps;
    109     const uint32_t fNotVal = !fAcquire ? pDevExt->u32AcquireModeGuestCaps : pDevExt->u32SetModeGuestCaps;
    110     bool fResult = true;
    111     RTSpinlockAcquire(pDevExt->EventSpinlock);
    112 
    113     if (!(fNotVal & fCaps))
    114         *pVal |= fCaps;
    115     else
    116     {
    117         AssertMsgFailed(("trying to change caps mode\n"));
    118         fResult = false;
    119     }
    120 
    121     RTSpinlockRelease(pDevExt->EventSpinlock);
    122 
    123     if (pu32OtherVal)
    124         *pu32OtherVal = fNotVal;
    125     return fResult;
    126 }
    127 
    128 
    129 /**
    130  * Sets the interrupt filter mask during initialization and termination.
    131  *
    132  * This will ASSUME that we're the ones in carge over the mask, so
    133  * we'll simply clear all bits we don't set.
    134  *
    135  * @returns VBox status code (ignored).
    136  * @param   fMask       The new mask.
    137  */
    138 static int vboxGuestSetFilterMask(VMMDevCtlGuestFilterMask *pReq, uint32_t fMask)
    139 {
    140     int rc;
    141 
    142     pReq->u32OrMask = fMask;
    143     pReq->u32NotMask = ~fMask;
    144     rc = VbglGRPerform(&pReq->header);
    145     if (RT_FAILURE(rc))
    146         LogRel(("vboxGuestSetFilterMask: failed with rc=%Rrc\n", rc));
    147     return rc;
    148 }
    149 
    150 
    151 /**
    152  * Sets the guest capabilities to the host.
    153  *
    154  * This will ASSUME that we're the ones in charge of the mask, so
    155  * we'll simply clear all bits we don't set.
    156  *
    157  * @returns VBox status code.
    158  * @param   fMask       The new mask.
    159  */
    160 static int vboxGuestSetCapabilities(VMMDevReqGuestCapabilities2 *pReq, uint32_t fMask)
    161 {
    162     int rc;
    163 
    164     pReq->u32OrMask = fMask;
    165     pReq->u32NotMask = ~fMask;
    166     rc = VbglGRPerform(&pReq->header);
    167     if (RT_FAILURE(rc))
    168         LogRelFunc(("failed with rc=%Rrc\n", rc));
    169     return rc;
    170 }
    171 
    172 
    173 /**
    174  * Sets the mouse status to the host.
    175  *
    176  * This will ASSUME that we're the ones in charge of the mask, so
    177  * we'll simply clear all bits we don't set.
    178  *
    179  * @returns VBox status code.
    180  * @param   fMask       The new mask.
    181  */
    182 static int vboxGuestSetMouseStatus(VMMDevReqMouseStatus *pReq, uint32_t fMask)
    183 {
    184     int rc;
    185 
    186     pReq->mouseFeatures = fMask;
    187     pReq->pointerXPos   = 0;
    188     pReq->pointerYPos   = 0;
    189     rc = VbglGRPerform(&pReq->header);
    190     if (RT_FAILURE(rc))
    191         LogRelFunc(("failed with rc=%Rrc\n", rc));
    192     return rc;
    193 }
    194 
    195 
    196 /** Host flags to be updated by a given invocation of the
    197  * vboxGuestUpdateHostFlags() method. */
    198 /** @todo r=bird: Use RT_BIT_32 for the bits, preferably replace enum with
    199  *        \#define. */
    200 enum
    201 {
    202     HostFlags_FilterMask   = 1,
    203     HostFlags_Capabilities = 2,
    204     HostFlags_MouseStatus  = 4,
    205     HostFlags_All          = 7,
    206     HostFlags_SizeHack = (unsigned)-1
    207 };
    208 
    209 
    210 static int vboxGuestGetHostFlagsFromSessions(PVBOXGUESTDEVEXT pDevExt,
    211                                              PVBOXGUESTSESSION pSession,
    212                                              uint32_t *pfFilterMask,
    213                                              uint32_t *pfCapabilities,
    214                                              uint32_t *pfMouseStatus)
    215 {
    216     PVBOXGUESTSESSION pIterator;
    217     uint32_t fFilterMask = 0, fCapabilities = 0, fMouseStatus = 0;
    218     unsigned cSessions = 0;
    219     int rc = VINF_SUCCESS;
    220 
    221 /** @todo r=bird: Please just do the global bit counting thing.  This code
    222  * gives me the [performances] creeps.  */
    223     RTListForEach(&pDevExt->SessionList, pIterator, VBOXGUESTSESSION, ListNode)
    224     {
    225         fFilterMask   |= pIterator->fFilterMask;
    226         fCapabilities |= pIterator->fCapabilities;
    227         fMouseStatus  |= pIterator->fMouseStatus;
    228         ++cSessions;
    229     }
    230     if (!cSessions)
    231         if (fFilterMask | fCapabilities | fMouseStatus)
    232             rc = VERR_INTERNAL_ERROR;
    233     if (cSessions == 1 && pSession)
    234         if (   fFilterMask   != pSession->fFilterMask
    235             || fCapabilities != pSession->fCapabilities
    236             || fMouseStatus  != pSession->fMouseStatus)
    237             rc = VERR_INTERNAL_ERROR;
    238     if (cSessions > 1 && pSession)
    239         if (   ~fFilterMask   & pSession->fFilterMask
    240             || ~fCapabilities & pSession->fCapabilities
    241             || ~fMouseStatus  & pSession->fMouseStatus)
    242             rc = VERR_INTERNAL_ERROR;
    243     *pfFilterMask = fFilterMask;
    244     *pfCapabilities = fCapabilities;
    245     *pfMouseStatus = fMouseStatus;
    246     return rc;
    247 }
    248 
    249 
    250 /**
    251  * Calls the host and set the filter mask, capabilities and/or mouse status.
    252  *
    253  * Check which host flags in a given category are being asserted by some guest
    254  * session and assert exactly those on the host which are being asserted by one
    255  * or more sessions.  pCallingSession is purely for sanity checking and can be
    256  * NULL.
    257  *
    258  * @note Takes the session spin-lock.
    259  */
    260 static int vboxGuestUpdateHostFlags(PVBOXGUESTDEVEXT pDevExt,
    261                                     PVBOXGUESTSESSION pSession,
    262                                     unsigned fFlags)
    263 {
    264     int rc;
    265     VMMDevCtlGuestFilterMask    *pFilterReq = NULL;
    266     VMMDevReqGuestCapabilities2 *pCapabilitiesReq = NULL;
    267     VMMDevReqMouseStatus        *pStatusReq = NULL;
    268     uint32_t                     fFilterMask = 0;
    269     uint32_t                     fCapabilities = 0;
    270     uint32_t                     fMouseStatus = 0;
    271 
    272     rc = VbglGRAlloc((VMMDevRequestHeader **)&pFilterReq, sizeof(*pFilterReq),
    273                      VMMDevReq_CtlGuestFilterMask);
    274     if (RT_SUCCESS(rc))
    275         rc = VbglGRAlloc((VMMDevRequestHeader **)&pCapabilitiesReq,
    276                          sizeof(*pCapabilitiesReq),
    277                          VMMDevReq_SetGuestCapabilities);
    278     if (RT_SUCCESS(rc))
    279         rc = VbglGRAlloc((VMMDevRequestHeader **)&pStatusReq,
    280                          sizeof(*pStatusReq), VMMDevReq_SetMouseStatus);
    281     if (RT_SUCCESS(rc))
    282     {
    283         RTSpinlockAcquire(pDevExt->SessionSpinlock);
    284         rc = vboxGuestGetHostFlagsFromSessions(pDevExt, pSession, &fFilterMask,
    285                                                &fCapabilities, &fMouseStatus);
    286         if (RT_SUCCESS(rc))
    287         {
    288             fFilterMask |= pDevExt->fFixedEvents;
    289             /* Since VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR is inverted in the session
    290              * capabilities we invert it again before sending it to the host. */
    291             fMouseStatus ^= VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR;
    292             if (fFlags & HostFlags_FilterMask)
    293                 vboxGuestSetFilterMask(pFilterReq, fFilterMask);
    294             fCapabilities |= pDevExt->u32GuestCaps;
    295             if (fFlags & HostFlags_Capabilities)
    296                 vboxGuestSetCapabilities(pCapabilitiesReq, fCapabilities);
    297             if (fFlags & HostFlags_MouseStatus)
    298                 vboxGuestSetMouseStatus(pStatusReq, fMouseStatus);
    299         }
    300         RTSpinlockRelease(pDevExt->SessionSpinlock);
    301     }
    302     if (pFilterReq)
    303         VbglGRFree(&pFilterReq->header);
    304     if (pCapabilitiesReq)
    305         VbglGRFree(&pCapabilitiesReq->header);
    306     if (pStatusReq)
    307         VbglGRFree(&pStatusReq->header);
    308     return rc;
    309 }
    310 
    311 
    312 /** @todo r=bird: WTF did someone add code before the globals? */
     95static int      vboxGuestUpdateHostFlags(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, unsigned fFlags);
     96static uint32_t VBoxGuestCommonGetAndCleanPendingEventsLocked(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, uint32_t fReqEvents);
     97static uint32_t VBoxGuestCommonGetHandledEventsLocked(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession);
     98static bool     VBoxGuestCommonGuestCapsModeSet(PVBOXGUESTDEVEXT pDevExt, uint32_t fCaps, bool fAcquire, uint32_t *pu32OtherVal);
     99
     100
    313101/*******************************************************************************
    314102*   Global Variables                                                           *
     
    1101889                 * by default. The guest specific graphics driver will re-enable
    1102890                 * the graphics capability if and when appropriate. */
    1103                 rc = vboxGuestUpdateHostFlags(pDevExt, NULL,
    1104                                                 HostFlags_FilterMask
    1105                                               | HostFlags_Capabilities);
     891                rc = vboxGuestUpdateHostFlags(pDevExt, NULL, HostFlags_FilterMask | HostFlags_Capabilities);
    1106892                if (RT_SUCCESS(rc))
    1107893                {
     
    21111897
    21121898
    2113 static int VBoxGuestCommonIOCtl_SetCapabilities(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
    2114                                                 VBoxGuestSetCapabilitiesInfo *pInfo)
    2115 {
    2116     int rc;
    2117 
    2118     if ((pInfo->u32OrMask | pInfo->u32NotMask) & ~VMMDEV_GUEST_CAPABILITIES_MASK)
    2119         return VERR_INVALID_PARAMETER;
    2120     RTSpinlockAcquire(pDevExt->SessionSpinlock);
    2121     pSession->fCapabilities |= pInfo->u32OrMask;
    2122     pSession->fCapabilities &= ~pInfo->u32NotMask;
    2123     RTSpinlockRelease(pDevExt->SessionSpinlock);
    2124     rc = vboxGuestUpdateHostFlags(pDevExt, pSession, HostFlags_Capabilities);
    2125     return rc;
    2126 }
    2127 
    2128 
    21291899/**
    21301900 * Sets the mouse status features for this session and updates them
     
    26352405
    26362406
     2407/** @name Guest Capabilities, Mouse Status and Event Filter
     2408 * @{
     2409 */
     2410
    26372411static bool VBoxGuestCommonGuestCapsValidateValues(uint32_t fCaps)
    26382412{
    2639     if (fCaps & (~(VMMDEV_GUEST_SUPPORTS_SEAMLESS | VMMDEV_GUEST_SUPPORTS_GUEST_HOST_WINDOW_MAPPING | VMMDEV_GUEST_SUPPORTS_GRAPHICS)))
     2413    if (fCaps & ~(  VMMDEV_GUEST_SUPPORTS_SEAMLESS
     2414                  | VMMDEV_GUEST_SUPPORTS_GUEST_HOST_WINDOW_MAPPING
     2415                  | VMMDEV_GUEST_SUPPORTS_GRAPHICS ))
    26402416        return false;
    2641 
    26422417    return true;
    26432418}
     
    26472422 * the currently listening sessions.  In addition, report any events in
    26482423 * @a fGenFakeEvents.
     2424 *
    26492425 * @note This is called by GUEST_CAPS_ACQUIRE in case any pending events can now
    26502426 *       be dispatched to the session which acquired capabilities.  The fake
     
    26552431 * @todo Why does acquiring capabilities block and unblock events?  Capabilities
    26562432 *       are supposed to control what is reported to the host, we already have
    2657  *       separate requests for blocking and unblocking events. */
     2433 *       separate requests for blocking and unblocking events.
     2434 */
    26582435static void VBoxGuestCommonCheckEvents(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, uint32_t fGenFakeEvents)
    26592436{
     
    26932470}
    26942471
     2472
     2473/** Return the mask of VMM device events that this session is allowed to see,
     2474 *  ergo, all events except those in "acquire" mode which have not been acquired
     2475 *  by this session. */
     2476static uint32_t VBoxGuestCommonGetHandledEventsLocked(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession)
     2477{
     2478    if (!pDevExt->u32AcquireModeGuestCaps)
     2479        return VMMDEV_EVENT_VALID_EVENT_MASK;
     2480
     2481    /** @note VMMDEV_EVENT_VALID_EVENT_MASK should actually be the mask of valid
     2482     *        capabilities, but that doesn't affect this code. */
     2483    uint32_t u32AllowedGuestCaps = pSession->u32AquiredGuestCaps | (VMMDEV_EVENT_VALID_EVENT_MASK & ~pDevExt->u32AcquireModeGuestCaps);
     2484    uint32_t u32CleanupEvents = VBOXGUEST_ACQUIRE_STYLE_EVENTS;
     2485    if (u32AllowedGuestCaps & VMMDEV_GUEST_SUPPORTS_GRAPHICS)
     2486        u32CleanupEvents &= ~VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST;
     2487    if (u32AllowedGuestCaps & VMMDEV_GUEST_SUPPORTS_SEAMLESS)
     2488        u32CleanupEvents &= ~VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST;
     2489
     2490    return VMMDEV_EVENT_VALID_EVENT_MASK & ~u32CleanupEvents;
     2491}
     2492
     2493
     2494static uint32_t VBoxGuestCommonGetAndCleanPendingEventsLocked(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, uint32_t fReqEvents)
     2495{
     2496    uint32_t fMatches = pDevExt->f32PendingEvents & fReqEvents & VBoxGuestCommonGetHandledEventsLocked(pDevExt, pSession);
     2497    if (fMatches)
     2498        ASMAtomicAndU32(&pDevExt->f32PendingEvents, ~fMatches);
     2499    return fMatches;
     2500}
     2501
     2502
     2503/** Puts a capability in "acquire" or "set" mode and returns the mask of
     2504 * capabilities currently in the other mode.  Once a capability has been put in
     2505 * one of the two modes it can no longer be removed from that mode. */
     2506static bool VBoxGuestCommonGuestCapsModeSet(PVBOXGUESTDEVEXT pDevExt, uint32_t fCaps, bool fAcquire, uint32_t *pu32OtherVal)
     2507{
     2508    uint32_t *pVal = fAcquire ? &pDevExt->u32AcquireModeGuestCaps : &pDevExt->u32SetModeGuestCaps;
     2509    const uint32_t fNotVal = !fAcquire ? pDevExt->u32AcquireModeGuestCaps : pDevExt->u32SetModeGuestCaps;
     2510    bool fResult = true;
     2511    RTSpinlockAcquire(pDevExt->EventSpinlock);
     2512
     2513    if (!(fNotVal & fCaps))
     2514        *pVal |= fCaps;
     2515    else
     2516    {
     2517        AssertMsgFailed(("trying to change caps mode\n"));
     2518        fResult = false;
     2519    }
     2520
     2521    RTSpinlockRelease(pDevExt->EventSpinlock);
     2522
     2523    if (pu32OtherVal)
     2524        *pu32OtherVal = fNotVal;
     2525    return fResult;
     2526}
     2527
     2528
     2529/**
     2530 * Sets the interrupt filter mask during initialization and termination.
     2531 *
     2532 * This will ASSUME that we're the ones in carge over the mask, so
     2533 * we'll simply clear all bits we don't set.
     2534 *
     2535 * @returns VBox status code (ignored).
     2536 * @param   fMask       The new mask.
     2537 */
     2538static int vboxGuestSetFilterMask(VMMDevCtlGuestFilterMask *pReq, uint32_t fMask)
     2539{
     2540    int rc;
     2541
     2542    pReq->u32OrMask = fMask;
     2543    pReq->u32NotMask = ~fMask;
     2544    rc = VbglGRPerform(&pReq->header);
     2545    if (RT_FAILURE(rc))
     2546        LogRel(("vboxGuestSetFilterMask: failed with rc=%Rrc\n", rc));
     2547    return rc;
     2548}
     2549
     2550
     2551/**
     2552 * Sets the guest capabilities to the host.
     2553 *
     2554 * This will ASSUME that we're the ones in charge of the mask, so
     2555 * we'll simply clear all bits we don't set.
     2556 *
     2557 * @returns VBox status code.
     2558 * @param   fMask       The new mask.
     2559 */
     2560static int vboxGuestSetCapabilities(VMMDevReqGuestCapabilities2 *pReq, uint32_t fMask)
     2561{
     2562    int rc;
     2563
     2564    pReq->u32OrMask = fMask;
     2565    pReq->u32NotMask = ~fMask;
     2566    rc = VbglGRPerform(&pReq->header);
     2567    if (RT_FAILURE(rc))
     2568        LogRelFunc(("failed with rc=%Rrc\n", rc));
     2569    return rc;
     2570}
     2571
     2572
     2573/**
     2574 * Sets the mouse status to the host.
     2575 *
     2576 * This will ASSUME that we're the ones in charge of the mask, so
     2577 * we'll simply clear all bits we don't set.
     2578 *
     2579 * @returns VBox status code.
     2580 * @param   fMask       The new mask.
     2581 */
     2582static int vboxGuestSetMouseStatus(VMMDevReqMouseStatus *pReq, uint32_t fMask)
     2583{
     2584    int rc;
     2585
     2586    pReq->mouseFeatures = fMask;
     2587    pReq->pointerXPos   = 0;
     2588    pReq->pointerYPos   = 0;
     2589    rc = VbglGRPerform(&pReq->header);
     2590    if (RT_FAILURE(rc))
     2591        LogRelFunc(("failed with rc=%Rrc\n", rc));
     2592    return rc;
     2593}
     2594
     2595
     2596static int vboxGuestGetHostFlagsFromSessions(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
     2597                                             uint32_t *pfFilterMask, uint32_t *pfCapabilities, uint32_t *pfMouseStatus)
     2598{
     2599    PVBOXGUESTSESSION pIterator;
     2600    uint32_t fFilterMask = 0, fCapabilities = 0, fMouseStatus = 0;
     2601    unsigned cSessions = 0;
     2602    int rc = VINF_SUCCESS;
     2603
     2604/** @todo r=bird: Please just do the global bit counting thing.  This code
     2605 * gives me the [performances] creeps.  */
     2606    RTListForEach(&pDevExt->SessionList, pIterator, VBOXGUESTSESSION, ListNode)
     2607    {
     2608        fFilterMask   |= pIterator->fFilterMask;
     2609        fCapabilities |= pIterator->fCapabilities;
     2610        fMouseStatus  |= pIterator->fMouseStatus;
     2611        ++cSessions;
     2612    }
     2613    if (!cSessions)
     2614        if (fFilterMask | fCapabilities | fMouseStatus)
     2615            rc = VERR_INTERNAL_ERROR;
     2616    if (cSessions == 1 && pSession)
     2617        if (   fFilterMask   != pSession->fFilterMask
     2618            || fCapabilities != pSession->fCapabilities
     2619            || fMouseStatus  != pSession->fMouseStatus)
     2620            rc = VERR_INTERNAL_ERROR;
     2621    if (cSessions > 1 && pSession)
     2622        if (   ~fFilterMask   & pSession->fFilterMask
     2623            || ~fCapabilities & pSession->fCapabilities
     2624            || ~fMouseStatus  & pSession->fMouseStatus)
     2625            rc = VERR_INTERNAL_ERROR;
     2626    *pfFilterMask = fFilterMask;
     2627    *pfCapabilities = fCapabilities;
     2628    *pfMouseStatus = fMouseStatus;
     2629    return rc;
     2630}
     2631
     2632
     2633/**
     2634 * Calls the host and set the filter mask, capabilities and/or mouse status.
     2635 *
     2636 * Check which host flags in a given category are being asserted by some guest
     2637 * session and assert exactly those on the host which are being asserted by one
     2638 * or more sessions.  pCallingSession is purely for sanity checking and can be
     2639 * NULL.
     2640 *
     2641 * @note Takes the session spin-lock.
     2642 */
     2643static int vboxGuestUpdateHostFlags(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, unsigned fFlags)
     2644{
     2645    int rc;
     2646    VMMDevCtlGuestFilterMask    *pFilterReq = NULL;
     2647    VMMDevReqGuestCapabilities2 *pCapabilitiesReq = NULL;
     2648    VMMDevReqMouseStatus        *pStatusReq = NULL;
     2649    uint32_t                     fFilterMask = 0;
     2650    uint32_t                     fCapabilities = 0;
     2651    uint32_t                     fMouseStatus = 0;
     2652
     2653    rc = VbglGRAlloc((VMMDevRequestHeader **)&pFilterReq, sizeof(*pFilterReq),
     2654                     VMMDevReq_CtlGuestFilterMask);
     2655    if (RT_SUCCESS(rc))
     2656        rc = VbglGRAlloc((VMMDevRequestHeader **)&pCapabilitiesReq,
     2657                         sizeof(*pCapabilitiesReq),
     2658                         VMMDevReq_SetGuestCapabilities);
     2659    if (RT_SUCCESS(rc))
     2660        rc = VbglGRAlloc((VMMDevRequestHeader **)&pStatusReq,
     2661                         sizeof(*pStatusReq), VMMDevReq_SetMouseStatus);
     2662    if (RT_SUCCESS(rc))
     2663    {
     2664        RTSpinlockAcquire(pDevExt->SessionSpinlock);
     2665        rc = vboxGuestGetHostFlagsFromSessions(pDevExt, pSession, &fFilterMask,
     2666                                               &fCapabilities, &fMouseStatus);
     2667        if (RT_SUCCESS(rc))
     2668        {
     2669            fFilterMask |= pDevExt->fFixedEvents;
     2670            /* Since VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR is inverted in the session
     2671             * capabilities we invert it again before sending it to the host. */
     2672            fMouseStatus ^= VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR;
     2673            if (fFlags & HostFlags_FilterMask)
     2674                vboxGuestSetFilterMask(pFilterReq, fFilterMask);
     2675            fCapabilities |= pDevExt->u32GuestCaps;
     2676            if (fFlags & HostFlags_Capabilities)
     2677                vboxGuestSetCapabilities(pCapabilitiesReq, fCapabilities);
     2678            if (fFlags & HostFlags_MouseStatus)
     2679                vboxGuestSetMouseStatus(pStatusReq, fMouseStatus);
     2680        }
     2681        RTSpinlockRelease(pDevExt->SessionSpinlock);
     2682    }
     2683    if (pFilterReq)
     2684        VbglGRFree(&pFilterReq->header);
     2685    if (pCapabilitiesReq)
     2686        VbglGRFree(&pCapabilitiesReq->header);
     2687    if (pStatusReq)
     2688        VbglGRFree(&pStatusReq->header);
     2689    return rc;
     2690}
     2691
    26952692/** Switch the capabilities in @a fOrMask to "acquire" mode if they are not
    26962693 * already in "set" mode.  If @a enmFlags is not set to
     
    28092806
    28102807
    2811 static int VBoxGuestCommonIOCTL_GuestCapsAcquire(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, VBoxGuestCapsAquire *pAcquire)
     2808static int VBoxGuestCommonIOCTL_GuestCapsAcquire(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
     2809                                                 VBoxGuestCapsAquire *pAcquire)
    28122810{
    28132811    int rc = VBoxGuestCommonGuestCapsAcquire(pDevExt, pSession, pAcquire->u32OrMask, pAcquire->u32NotMask, pAcquire->enmFlags);
     
    28172815    return VINF_SUCCESS;
    28182816}
     2817
     2818
     2819static int VBoxGuestCommonIOCtl_SetCapabilities(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession,
     2820                                                VBoxGuestSetCapabilitiesInfo *pInfo)
     2821{
     2822    int rc;
     2823
     2824    if ((pInfo->u32OrMask | pInfo->u32NotMask) & ~VMMDEV_GUEST_CAPABILITIES_MASK)
     2825        return VERR_INVALID_PARAMETER;
     2826    RTSpinlockAcquire(pDevExt->SessionSpinlock);
     2827    pSession->fCapabilities |= pInfo->u32OrMask;
     2828    pSession->fCapabilities &= ~pInfo->u32NotMask;
     2829    RTSpinlockRelease(pDevExt->SessionSpinlock);
     2830    rc = vboxGuestUpdateHostFlags(pDevExt, pSession, HostFlags_Capabilities);
     2831    return rc;
     2832}
     2833
     2834/** @} */
    28192835
    28202836
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette