Changeset 54593 in vbox for trunk/src/VBox
- Timestamp:
- Mar 2, 2015 8:44:44 PM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 98732
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp
r54522 r54593 62 62 63 63 /******************************************************************************* 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. */ 76 enum 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 /******************************************************************************* 64 87 * Internal Functions * 65 88 *******************************************************************************/ … … 70 93 uint32_t fNotMask, VBOXGUESTCAPSACQUIRE_FLAGS enmFlags); 71 94 static 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? */ 95 static int vboxGuestUpdateHostFlags(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, unsigned fFlags); 96 static uint32_t VBoxGuestCommonGetAndCleanPendingEventsLocked(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, uint32_t fReqEvents); 97 static uint32_t VBoxGuestCommonGetHandledEventsLocked(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession); 98 static bool VBoxGuestCommonGuestCapsModeSet(PVBOXGUESTDEVEXT pDevExt, uint32_t fCaps, bool fAcquire, uint32_t *pu32OtherVal); 99 100 313 101 /******************************************************************************* 314 102 * Global Variables * … … 1101 889 * by default. The guest specific graphics driver will re-enable 1102 890 * 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); 1106 892 if (RT_SUCCESS(rc)) 1107 893 { … … 2111 1897 2112 1898 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 2129 1899 /** 2130 1900 * Sets the mouse status features for this session and updates them … … 2635 2405 2636 2406 2407 /** @name Guest Capabilities, Mouse Status and Event Filter 2408 * @{ 2409 */ 2410 2637 2411 static bool VBoxGuestCommonGuestCapsValidateValues(uint32_t fCaps) 2638 2412 { 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 )) 2640 2416 return false; 2641 2642 2417 return true; 2643 2418 } … … 2647 2422 * the currently listening sessions. In addition, report any events in 2648 2423 * @a fGenFakeEvents. 2424 * 2649 2425 * @note This is called by GUEST_CAPS_ACQUIRE in case any pending events can now 2650 2426 * be dispatched to the session which acquired capabilities. The fake … … 2655 2431 * @todo Why does acquiring capabilities block and unblock events? Capabilities 2656 2432 * 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 */ 2658 2435 static void VBoxGuestCommonCheckEvents(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, uint32_t fGenFakeEvents) 2659 2436 { … … 2693 2470 } 2694 2471 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. */ 2476 static 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 2494 static 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. */ 2506 static 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 */ 2538 static 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 */ 2560 static 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 */ 2582 static 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 2596 static 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 */ 2643 static 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 2695 2692 /** Switch the capabilities in @a fOrMask to "acquire" mode if they are not 2696 2693 * already in "set" mode. If @a enmFlags is not set to … … 2809 2806 2810 2807 2811 static int VBoxGuestCommonIOCTL_GuestCapsAcquire(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, VBoxGuestCapsAquire *pAcquire) 2808 static int VBoxGuestCommonIOCTL_GuestCapsAcquire(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, 2809 VBoxGuestCapsAquire *pAcquire) 2812 2810 { 2813 2811 int rc = VBoxGuestCommonGuestCapsAcquire(pDevExt, pSession, pAcquire->u32OrMask, pAcquire->u32NotMask, pAcquire->enmFlags); … … 2817 2815 return VINF_SUCCESS; 2818 2816 } 2817 2818 2819 static 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 /** @} */ 2819 2835 2820 2836
Note:
See TracChangeset
for help on using the changeset viewer.