VirtualBox

Changeset 38592 in vbox for trunk/src/VBox/Additions/common


Ignore:
Timestamp:
Aug 31, 2011 8:45:29 PM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
73787
Message:

Additions/common/VBoxGuest: mediate SET_MOUSE_STATUS in the kernel module

Location:
trunk/src/VBox/Additions/common
Files:
3 edited

Legend:

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

    r34406 r38592  
    5656#ifdef VBOX_WITH_HGCM
    5757static DECLCALLBACK(int) VBoxGuestHGCMAsyncWaitCallback(VMMDevHGCMRequestHeader *pHdrNonVolatile, void *pvUser, uint32_t u32User);
     58#endif
     59#ifdef DEBUG
     60static void testSetMouseStatus(void);
    5861#endif
    5962
     
    789792                        vboxGuestInitFixateGuestMappings(pDevExt);
    790793
     794#ifdef DEBUG
     795                        testSetMouseStatus();  /* Other tests? */
     796#endif
     797
    791798                        rc = VBoxGuestReportDriverStatus(true /* Driver is active */);
    792799                        if (RT_FAILURE(rc))
     
    20682075}
    20692076#endif /* VBOX_WITH_VRDP_SESSION_HANDLING */
     2077
     2078#ifdef DEBUG
     2079/** Unit test SetMouseStatus instead of really executing the request. */
     2080static bool     g_test_fSetMouseStatus = false;
     2081/** When unit testing SetMouseStatus, the fake RC for the GR to return. */
     2082static int      g_test_SetMouseStatusGRRC;
     2083/** When unit testing SetMouseStatus this will be set to the status passed to
     2084 * the GR. */
     2085static uint32_t g_test_statusSetMouseStatus;
     2086#endif
     2087
     2088static int vboxguestcommonSetMouseStatus(uint32_t fFeatures)
     2089{
     2090    VMMDevReqMouseStatus *pReq;
     2091    int rc;
     2092
     2093    LogRelFlowFunc(("fFeatures=%u\n", (int) fFeatures));
     2094    rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(*pReq), VMMDevReq_SetMouseStatus);
     2095    if (RT_SUCCESS(rc))
     2096    {
     2097        pReq->mouseFeatures = fFeatures;
     2098        pReq->pointerXPos = 0;
     2099        pReq->pointerYPos = 0;
     2100#ifdef DEBUG
     2101        if (g_test_fSetMouseStatus)
     2102        {
     2103            g_test_statusSetMouseStatus = pReq->mouseFeatures;
     2104            rc = g_test_SetMouseStatusGRRC;
     2105        }
     2106        else
     2107#endif
     2108            rc = VbglGRPerform(&pReq->header);
     2109        VbglGRFree(&pReq->header);
     2110    }
     2111    LogRelFlowFunc(("rc=%Rrc\n", rc));
     2112    return rc;
     2113}
     2114
     2115
     2116/**
     2117 * Sets the mouse status features for this session and updates them globally.
     2118 *
     2119 * @returns VBox status code.
     2120 *
     2121 * @param   pDevExt             The device extention.
     2122 * @param   pSession            The session.
     2123 * @param   fFeatures           New bitmap of enabled features.
     2124 */
     2125static int VBoxGuestCommonIOCtl_SetMouseStatus(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, uint32_t fFeatures)
     2126{
     2127    unsigned i;
     2128    RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
     2129    uint32_t fNewDevExtStatus = 0;
     2130    int rc;
     2131
     2132    RTSpinlockAcquireNoInts(pDevExt->SessionSpinlock, &Tmp);
     2133    for (i = 0; i < sizeof(fFeatures) * 8; ++i)
     2134    {
     2135        if (RT_BIT_32(i) & VMMDEV_MOUSE_GUEST_MASK)
     2136        {
     2137            if (   (RT_BIT_32(i) & fFeatures)
     2138                && !(RT_BIT_32(i) & pSession->fMouseStatus))
     2139                ++pDevExt->cMouseFeatureUsage[i];
     2140            else if (   !(RT_BIT_32(i) & fFeatures)
     2141                     && (RT_BIT_32(i) & pSession->fMouseStatus))
     2142                --pDevExt->cMouseFeatureUsage[i];
     2143        }
     2144        if (pDevExt->cMouseFeatureUsage[i] > 0)
     2145            fNewDevExtStatus |= RT_BIT_32(i);
     2146    }
     2147    pSession->fMouseStatus = fFeatures & VMMDEV_MOUSE_GUEST_MASK;
     2148    pDevExt->fMouseStatus = fNewDevExtStatus;
     2149    RTSpinlockReleaseNoInts(pDevExt->SessionSpinlock, &Tmp);
     2150    do
     2151    {
     2152        fNewDevExtStatus = pDevExt->fMouseStatus;
     2153        rc = vboxguestcommonSetMouseStatus(fNewDevExtStatus);
     2154    } while(RT_SUCCESS(rc) && fNewDevExtStatus != pDevExt->fMouseStatus);
     2155    return rc;
     2156}
     2157
     2158
     2159#ifdef DEBUG
     2160/** Unit test for the SET_MOUSE_STATUS IoCtl.  Since this is closely tied to
     2161 * the code in question it probably makes most sense to keep it next to the
     2162 * code. */
     2163static void testSetMouseStatus(void)
     2164{
     2165    int cFailures = 0;
     2166    uint32_t u32Data;
     2167    int rc;
     2168    RTSPINLOCK Spinlock;
     2169
     2170    g_test_fSetMouseStatus = true;
     2171    rc = RTSpinlockCreate(&Spinlock);
     2172    AssertRCReturnVoid(rc);
     2173    {
     2174        VBOXGUESTDEVEXT  DevExt  = { 0 };
     2175        VBOXGUESTSESSION Session = { 0 };
     2176
     2177        g_test_statusSetMouseStatus = ~0;
     2178        g_test_SetMouseStatusGRRC = VINF_SUCCESS;
     2179        DevExt.SessionSpinlock = Spinlock;
     2180        u32Data = VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE;
     2181        rc = VBoxGuestCommonIOCtl(VBOXGUEST_IOCTL_SET_MOUSE_STATUS, &DevExt,
     2182                                  &Session, &u32Data, sizeof(u32Data), NULL);
     2183        AssertRCSuccess(rc);
     2184        AssertMsg(   g_test_statusSetMouseStatus
     2185                  == VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE,
     2186                  ("Actual status: 0x%x\n", g_test_statusSetMouseStatus));
     2187        DevExt.cMouseFeatureUsage[ASMBitFirstSetU32(VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR) - 1] = 1;
     2188        rc = VBoxGuestCommonIOCtl(VBOXGUEST_IOCTL_SET_MOUSE_STATUS, &DevExt,
     2189                                  &Session, &u32Data, sizeof(u32Data), NULL);
     2190        AssertRCSuccess(rc);
     2191        AssertMsg(   g_test_statusSetMouseStatus
     2192                  == (  VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE
     2193                      | VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR),
     2194                  ("Actual status: 0x%x\n", g_test_statusSetMouseStatus));
     2195        u32Data = VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE;  /* Can't change this */
     2196        rc = VBoxGuestCommonIOCtl(VBOXGUEST_IOCTL_SET_MOUSE_STATUS, &DevExt,
     2197                                  &Session, &u32Data, sizeof(u32Data), NULL);
     2198        AssertRCSuccess(rc);
     2199        AssertMsg(   g_test_statusSetMouseStatus
     2200                  == VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR,
     2201                  ("Actual status: 0x%x\n", g_test_statusSetMouseStatus));
     2202        u32Data = VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR;
     2203        rc = VBoxGuestCommonIOCtl(VBOXGUEST_IOCTL_SET_MOUSE_STATUS, &DevExt,
     2204                                  &Session, &u32Data, sizeof(u32Data), NULL);
     2205        AssertRCSuccess(rc);
     2206        AssertMsg(   g_test_statusSetMouseStatus
     2207                  == VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR,
     2208                  ("Actual status: 0x%x\n", g_test_statusSetMouseStatus));
     2209        u32Data = 0;
     2210        rc = VBoxGuestCommonIOCtl(VBOXGUEST_IOCTL_SET_MOUSE_STATUS, &DevExt,
     2211                                  &Session, &u32Data, sizeof(u32Data), NULL);
     2212        AssertRCSuccess(rc);
     2213        AssertMsg(   g_test_statusSetMouseStatus
     2214                  == VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR,
     2215                  ("Actual status: 0x%x\n", g_test_statusSetMouseStatus));
     2216        AssertMsg(DevExt.cMouseFeatureUsage[ASMBitFirstSetU32(VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR) - 1] == 1,
     2217                  ("Actual value: %d\n", DevExt.cMouseFeatureUsage[ASMBitFirstSetU32(VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR)]));
     2218        g_test_SetMouseStatusGRRC = VERR_UNRESOLVED_ERROR;
     2219        rc = VBoxGuestCommonIOCtl(VBOXGUEST_IOCTL_SET_MOUSE_STATUS, &DevExt,
     2220                                  &Session, &u32Data, sizeof(u32Data), NULL);
     2221        AssertMsg(rc == VERR_UNRESOLVED_ERROR, ("rc == %Rrc\n", rc));
     2222        /* Untested paths: out of memory; race setting status to host */
     2223   }
     2224    RTSpinlockDestroy(Spinlock);
     2225    g_test_fSetMouseStatus = false;
     2226}
     2227#endif
    20702228
    20712229
     
    21442302        } \
    21452303    } while (0)
     2304#define CHECKRET_SIZE(mnemonic, cb) \
     2305    do { \
     2306        if (cbData != (cb)) \
     2307        { \
     2308            LogFunc((mnemonic ": cbData=%#zx (%zu) expected is %#zx (%zu)\n", \
     2309                 cbData, cbData, (size_t)(cb), (size_t)(cb))); \
     2310            return VERR_BUFFER_OVERFLOW; \
     2311        } \
     2312        if ((cb) != 0 && !VALID_PTR(pvData)) \
     2313        { \
     2314            LogFunc((mnemonic ": Invalid pointer %p\n", pvData)); \
     2315            return VERR_INVALID_POINTER; \
     2316        } \
     2317    } while (0)
    21462318
    21472319
     
    22752447                break;
    22762448#endif /* VBOX_WITH_VRDP_SESSION_HANDLING */
     2449            case VBOXGUEST_IOCTL_SET_MOUSE_STATUS:
     2450                CHECKRET_SIZE("SET_MOUSE_STATUS", sizeof(uint32_t));
     2451                rc = VBoxGuestCommonIOCtl_SetMouseStatus(pDevExt, pSession,
     2452                                                         *(uint32_t *)pvData);
     2453                break;
    22772454
    22782455            default:
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuestInternal.h

    r33750 r38592  
    154154    /** Memory balloon information for RTR0MemObjAllocPhysNC(). */
    155155    VBOXGUESTMEMBALLOON         MemBalloon;
     156    /** For each mouse status feature the number of sessions which have
     157     * enabled it.  A feature is enabled globally if at least one session has
     158     * requested it. */
     159    /** @todo can we programmatically determine the size of the array and
     160     * still get the following alignment right? */
     161    uint32_t volatile           cMouseFeatureUsage[32];
     162    /** The mouse feature status matching the counts above.  These are updated
     163     * together inside the session spinlock. */
     164    uint32_t volatile           fMouseStatus;
    156165    /** Align the next bit on a 64-byte boundary and make sure it starts at the same
    157166     *  offset in both 64-bit and 32-bit builds.
     
    162171     *          following it (to grow into and align the struct size).
    163172     */
    164     uint8_t abAlignment1[HC_ARCH_BITS == 32 ? 24 : 4];
     173    uint8_t abAlignment1[HC_ARCH_BITS == 32 ? 20 : 0];
    165174
    166175    /** Windows part. */
     
    177186typedef VBOXGUESTDEVEXT *PVBOXGUESTDEVEXT;
    178187
     188AssertCompileMemberSizeAlignment(VBOXGUESTDEVEXT, win, 64);
    179189
    180190/**
     
    213223     * Used to implement polling.  */
    214224    uint32_t volatile           u32MousePosChangedSeq;
     225    /** Mouse features supported.  A feature enabled in any guest session will
     226     * be enabled for the host. */
     227    uint32_t volatile           fMouseStatus;
    215228
    216229} VBOXGUESTSESSION;
  • trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibMouse.cpp

    r28800 r38592  
    7171VBGLR3DECL(int) VbglR3SetMouseStatus(uint32_t fFeatures)
    7272{
    73     VMMDevReqMouseStatus Req;
    74     vmmdevInitRequest(&Req.header, VMMDevReq_SetMouseStatus);
    75     Req.mouseFeatures = fFeatures;
    76     Req.pointerXPos = 0;
    77     Req.pointerYPos = 0;
    78     return vbglR3GRPerform(&Req.header);
     73    return vbglR3DoIOCtl(VBOXGUEST_IOCTL_SET_MOUSE_STATUS, &fFeatures,
     74                         sizeof(fFeatures));
    7975}
    8076
Note: See TracChangeset for help on using the changeset viewer.

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