VirtualBox

Changeset 72352 in vbox for trunk/src/VBox/Devices/VMMDev


Ignore:
Timestamp:
May 26, 2018 12:37:50 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
122809
Message:

Main, VMMDev: implemented IDisplay::SetScreenLayout, VMMDev multimonitor resize request and VBoxManage controlvm setscreenlayout. bugref:8393

Location:
trunk/src/VBox/Devices/VMMDev
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/VMMDev/VMMDev.cpp

    r71891 r72352  
    8383/* Enable dev_vmm Log3 statements to get IRQ-related logging. */
    8484#define LOG_GROUP LOG_GROUP_DEV_VMM
    85 #include <VBoxVideo.h>  /* For VBVA definitions. */
     85#include <VBox/AssertGuest.h>
    8686#include <VBox/VMMDev.h>
    8787#include <VBox/vmm/mm.h>
     
    13111311    }
    13121312
    1313     if (pThis->displayChangeData.fGuestSentChangeEventAck)
    1314     {
    1315         pReq->xres = pDispRequest->lastReadDisplayChangeRequest.xres;
    1316         pReq->yres = pDispRequest->lastReadDisplayChangeRequest.yres;
    1317         pReq->bpp  = pDispRequest->lastReadDisplayChangeRequest.bpp;
    1318     }
    1319     else
    1320     {
    1321         /* This is not a response to a VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST, just
    1322          * read the last valid video mode hint. This happens when the guest X server
    1323          * determines the initial mode. */
    1324         pReq->xres = pDispRequest->displayChangeRequest.xres;
    1325         pReq->yres = pDispRequest->displayChangeRequest.yres;
    1326         pReq->bpp  = pDispRequest->displayChangeRequest.bpp;
    1327     }
     1313    /* If not a response to a VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST, just
     1314     * read the last valid video mode hint. This happens when the guest X server
     1315     * determines the initial mode. */
     1316    VMMDevDisplayDef const *pDisplayDef = pThis->displayChangeData.fGuestSentChangeEventAck ?
     1317                                              &pDispRequest->lastReadDisplayChangeRequest :
     1318                                              &pDispRequest->displayChangeRequest;
     1319    pReq->xres = RT_BOOL(pDisplayDef->fDisplayFlags & VMMDEV_DISPLAY_CX)  ? pDisplayDef->cx : 0;
     1320    pReq->yres = RT_BOOL(pDisplayDef->fDisplayFlags & VMMDEV_DISPLAY_CY)  ? pDisplayDef->cy : 0;
     1321    pReq->bpp  = RT_BOOL(pDisplayDef->fDisplayFlags & VMMDEV_DISPLAY_BPP) ? pDisplayDef->cBitsPerPixel : 0;
     1322
    13281323    Log(("VMMDev: returning display change request xres = %d, yres = %d, bpp = %d\n", pReq->xres, pReq->yres, pReq->bpp));
    13291324
     
    13961391    }
    13971392
    1398     if (pThis->displayChangeData.fGuestSentChangeEventAck)
    1399     {
    1400         pReq->xres    = pDispRequest->lastReadDisplayChangeRequest.xres;
    1401         pReq->yres    = pDispRequest->lastReadDisplayChangeRequest.yres;
    1402         pReq->bpp     = pDispRequest->lastReadDisplayChangeRequest.bpp;
    1403         pReq->display = pDispRequest->lastReadDisplayChangeRequest.display;
    1404     }
    1405     else
    1406     {
    1407         /* This is not a response to a VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST, just
    1408          * read the last valid video mode hint. This happens when the guest X server
    1409          * determines the initial video mode. */
    1410         pReq->xres    = pDispRequest->displayChangeRequest.xres;
    1411         pReq->yres    = pDispRequest->displayChangeRequest.yres;
    1412         pReq->bpp     = pDispRequest->displayChangeRequest.bpp;
    1413         pReq->display = pDispRequest->displayChangeRequest.display;
    1414     }
     1393    /* If not a response to a VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST, just
     1394     * read the last valid video mode hint. This happens when the guest X server
     1395     * determines the initial mode. */
     1396    VMMDevDisplayDef const *pDisplayDef = pThis->displayChangeData.fGuestSentChangeEventAck ?
     1397                                              &pDispRequest->lastReadDisplayChangeRequest :
     1398                                              &pDispRequest->displayChangeRequest;
     1399    pReq->xres    = RT_BOOL(pDisplayDef->fDisplayFlags & VMMDEV_DISPLAY_CX)  ? pDisplayDef->cx : 0;
     1400    pReq->yres    = RT_BOOL(pDisplayDef->fDisplayFlags & VMMDEV_DISPLAY_CY)  ? pDisplayDef->cy : 0;
     1401    pReq->bpp     = RT_BOOL(pDisplayDef->fDisplayFlags & VMMDEV_DISPLAY_BPP) ? pDisplayDef->cBitsPerPixel : 0;
     1402    pReq->display = pDisplayDef->idDisplay;
     1403
    14151404    Log(("VMMDev: returning display change request xres = %d, yres = %d, bpp = %d at %d\n",
    14161405         pReq->xres, pReq->yres, pReq->bpp, pReq->display));
     
    14871476    }
    14881477
    1489     if (pThis->displayChangeData.fGuestSentChangeEventAck)
    1490     {
    1491         pReq->xres          = pDispRequest->lastReadDisplayChangeRequest.xres;
    1492         pReq->yres          = pDispRequest->lastReadDisplayChangeRequest.yres;
    1493         pReq->bpp           = pDispRequest->lastReadDisplayChangeRequest.bpp;
    1494         pReq->display       = pDispRequest->lastReadDisplayChangeRequest.display;
    1495         pReq->cxOrigin      = pDispRequest->lastReadDisplayChangeRequest.xOrigin;
    1496         pReq->cyOrigin      = pDispRequest->lastReadDisplayChangeRequest.yOrigin;
    1497         pReq->fEnabled      = pDispRequest->lastReadDisplayChangeRequest.fEnabled;
    1498         pReq->fChangeOrigin = pDispRequest->lastReadDisplayChangeRequest.fChangeOrigin;
    1499     }
    1500     else
    1501     {
    1502         /* This is not a response to a VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST, just
    1503          * read the last valid video mode hint. This happens when the guest X server
    1504          * determines the initial video mode. */
    1505         pReq->xres          = pDispRequest->displayChangeRequest.xres;
    1506         pReq->yres          = pDispRequest->displayChangeRequest.yres;
    1507         pReq->bpp           = pDispRequest->displayChangeRequest.bpp;
    1508         pReq->display       = pDispRequest->displayChangeRequest.display;
    1509         pReq->cxOrigin      = pDispRequest->displayChangeRequest.xOrigin;
    1510         pReq->cyOrigin      = pDispRequest->displayChangeRequest.yOrigin;
    1511         pReq->fEnabled      = pDispRequest->displayChangeRequest.fEnabled;
    1512         pReq->fChangeOrigin = pDispRequest->displayChangeRequest.fChangeOrigin;
    1513 
    1514     }
     1478    /* If not a response to a VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST, just
     1479     * read the last valid video mode hint. This happens when the guest X server
     1480     * determines the initial mode. */
     1481    VMMDevDisplayDef const *pDisplayDef = pThis->displayChangeData.fGuestSentChangeEventAck ?
     1482                                              &pDispRequest->lastReadDisplayChangeRequest :
     1483                                              &pDispRequest->displayChangeRequest;
     1484    pReq->xres          = RT_BOOL(pDisplayDef->fDisplayFlags & VMMDEV_DISPLAY_CX)  ? pDisplayDef->cx : 0;
     1485    pReq->yres          = RT_BOOL(pDisplayDef->fDisplayFlags & VMMDEV_DISPLAY_CY)  ? pDisplayDef->cy : 0;
     1486    pReq->bpp           = RT_BOOL(pDisplayDef->fDisplayFlags & VMMDEV_DISPLAY_BPP) ? pDisplayDef->cBitsPerPixel : 0;
     1487    pReq->display       = pDisplayDef->idDisplay;
     1488    pReq->cxOrigin      = pDisplayDef->xOrigin;
     1489    pReq->cyOrigin      = pDisplayDef->yOrigin;
     1490    pReq->fEnabled      = !RT_BOOL(pDisplayDef->fDisplayFlags & VMMDEV_DISPLAY_DISABLED);
     1491    pReq->fChangeOrigin = RT_BOOL(pDisplayDef->fDisplayFlags & VMMDEV_DISPLAY_ORIGIN);
     1492
    15151493    Log(("VMMDevEx: returning display change request xres = %d, yres = %d, bpp = %d id %d xPos = %d, yPos = %d & Enabled=%d\n",
    15161494         pReq->xres, pReq->yres, pReq->bpp, pReq->display, pReq->cxOrigin, pReq->cyOrigin, pReq->fEnabled));
     1495
     1496    return VINF_SUCCESS;
     1497}
     1498
     1499
     1500/**
     1501 * Handles VMMDevReq_GetDisplayChangeRequestMulti.
     1502 *
     1503 * @returns VBox status code that the guest should see.
     1504 * @param   pThis           The VMMDev instance data.
     1505 * @param   pReqHdr         The header of the request to handle.
     1506 */
     1507static int vmmdevReqHandler_GetDisplayChangeRequestMulti(PVMMDEV pThis, VMMDevRequestHeader *pReqHdr)
     1508{
     1509    VMMDevDisplayChangeRequestMulti *pReq = (VMMDevDisplayChangeRequestMulti *)pReqHdr;
     1510    unsigned i;
     1511
     1512    ASSERT_GUEST_MSG_RETURN(pReq->header.size >= sizeof(*pReq),
     1513                            ("%u\n", pReq->header.size), VERR_INVALID_PARAMETER);
     1514    RT_UNTRUSTED_VALIDATED_FENCE();
     1515
     1516    uint32_t const cDisplays = pReq->cDisplays;
     1517    ASSERT_GUEST_MSG_RETURN(cDisplays > 0 && cDisplays <= RT_ELEMENTS(pThis->displayChangeData.aRequests),
     1518                            ("cDisplays %u\n", cDisplays), VERR_INVALID_PARAMETER);
     1519    RT_UNTRUSTED_VALIDATED_FENCE();
     1520
     1521    ASSERT_GUEST_MSG_RETURN(pReq->header.size >= sizeof(*pReq) + (cDisplays - 1) * sizeof(VMMDevDisplayDef),
     1522                            ("%u\n", pReq->header.size), VERR_INVALID_PARAMETER);
     1523    RT_UNTRUSTED_VALIDATED_FENCE();
     1524
     1525    if (pReq->eventAck == VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST)
     1526    {
     1527        /* Remember which resolution the client has queried, subsequent reads
     1528         * will return the same values. */
     1529        for (i = 0; i < RT_ELEMENTS(pThis->displayChangeData.aRequests); ++i)
     1530        {
     1531            DISPLAYCHANGEREQUEST *pDCR = &pThis->displayChangeData.aRequests[i];
     1532
     1533            pDCR->lastReadDisplayChangeRequest = pDCR->displayChangeRequest;
     1534            pDCR->fPending = false;
     1535        }
     1536    }
     1537
     1538    /* Fill the guest request with monitor layout data. */
     1539    for (i = 0; i < cDisplays; ++i)
     1540    {
     1541        /* If not a response to a VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST, just
     1542         * read the last valid video mode hint. This happens when the guest X server
     1543         * determines the initial mode. */
     1544        DISPLAYCHANGEREQUEST const *pDCR = &pThis->displayChangeData.aRequests[i];
     1545        VMMDevDisplayDef const *pDisplayDef = pThis->displayChangeData.fGuestSentChangeEventAck ?
     1546                                                  &pDCR->lastReadDisplayChangeRequest :
     1547                                                  &pDCR->displayChangeRequest;
     1548        pReq->aDisplays[i] = *pDisplayDef;
     1549    }
     1550
     1551    Log(("VMMDev: returning multimonitor display change request cDisplays %d\n", cDisplays));
    15171552
    15181553    return VINF_SUCCESS;
     
    25702605        case VMMDevReq_GetDisplayChangeRequestEx:
    25712606            pReqHdr->rc = vmmdevReqHandler_GetDisplayChangeRequestEx(pThis, pReqHdr);
     2607            break;
     2608
     2609        case VMMDevReq_GetDisplayChangeRequestMulti:
     2610            pReqHdr->rc = vmmdevReqHandler_GetDisplayChangeRequestMulti(pThis, pReqHdr);
    25722611            break;
    25732612
     
    31823221}
    31833222
     3223static bool vmmdevIsMonitorDefEqual(VMMDevDisplayDef const *pNew, VMMDevDisplayDef const *pOld)
     3224{
     3225    bool     fEqual = pNew->idDisplay == pOld->idDisplay;
     3226
     3227    fEqual = fEqual && (   !RT_BOOL(pNew->fDisplayFlags & VMMDEV_DISPLAY_ORIGIN)    /* No change. */
     3228                        || (   RT_BOOL(pOld->fDisplayFlags & VMMDEV_DISPLAY_ORIGIN) /* Old value exists and */
     3229                            && pNew->xOrigin == pOld->xOrigin                       /* the old is equal to the new. */
     3230                            && pNew->yOrigin == pOld->yOrigin));
     3231
     3232    fEqual = fEqual && (   !RT_BOOL(pNew->fDisplayFlags & VMMDEV_DISPLAY_CX)
     3233                        || (   RT_BOOL(pOld->fDisplayFlags & VMMDEV_DISPLAY_CX)
     3234                            && pNew->cx == pOld->cx));
     3235
     3236    fEqual = fEqual && (   !RT_BOOL(pNew->fDisplayFlags & VMMDEV_DISPLAY_CY)
     3237                        || (   RT_BOOL(pOld->fDisplayFlags & VMMDEV_DISPLAY_CY)
     3238                            && pNew->cy == pOld->cy));
     3239
     3240    fEqual = fEqual && (   !RT_BOOL(pNew->fDisplayFlags & VMMDEV_DISPLAY_BPP)
     3241                        || (   RT_BOOL(pOld->fDisplayFlags & VMMDEV_DISPLAY_BPP)
     3242                            && pNew->cBitsPerPixel == pOld->cBitsPerPixel));
     3243
     3244    fEqual = fEqual && (   RT_BOOL(pNew->fDisplayFlags & VMMDEV_DISPLAY_DISABLED)
     3245                        == RT_BOOL(pOld->fDisplayFlags & VMMDEV_DISPLAY_DISABLED));
     3246
     3247    fEqual = fEqual && (   RT_BOOL(pNew->fDisplayFlags & VMMDEV_DISPLAY_PRIMARY)
     3248                        == RT_BOOL(pOld->fDisplayFlags & VMMDEV_DISPLAY_PRIMARY));
     3249
     3250    return fEqual;
     3251}
     3252
    31843253/**
    31853254 * @interface_method_impl{PDMIVMMDEVPORT,pfnRequestDisplayChange}
    31863255 */
    31873256static DECLCALLBACK(int)
    3188 vmmdevIPort_RequestDisplayChange(PPDMIVMMDEVPORT pInterface, uint32_t cx, uint32_t cy, uint32_t cBits, uint32_t idxDisplay,
    3189                                  int32_t xOrigin, int32_t yOrigin, bool fEnabled, bool fChangeOrigin)
    3190 {
     3257vmmdevIPort_RequestDisplayChange(PPDMIVMMDEVPORT pInterface, uint32_t cDisplays, VMMDevDisplayDef const *paDisplays, bool fForce)
     3258{
     3259    int rc = VINF_SUCCESS;
     3260
    31913261    PVMMDEV pThis = RT_FROM_MEMBER(pInterface, VMMDEV, IPort);
    3192 
    3193     if (idxDisplay >= RT_ELEMENTS(pThis->displayChangeData.aRequests))
    3194         return VERR_INVALID_PARAMETER;
     3262    bool fNotifyGuest = false;
    31953263
    31963264    PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);
    31973265
    3198     DISPLAYCHANGEREQUEST *pRequest = &pThis->displayChangeData.aRequests[idxDisplay];
    3199 
    3200     /* Verify that the new resolution is different and that guest does not yet know about it. */
    3201     bool fSameResolution = (!cx    || pRequest->lastReadDisplayChangeRequest.xres == cx)
    3202                         && (!cy    || pRequest->lastReadDisplayChangeRequest.yres == cy)
    3203                         && (!cBits || pRequest->lastReadDisplayChangeRequest.bpp  == cBits)
    3204                         && pRequest->lastReadDisplayChangeRequest.xOrigin  == xOrigin
    3205                         && pRequest->lastReadDisplayChangeRequest.yOrigin  == yOrigin
    3206                         && pRequest->lastReadDisplayChangeRequest.fEnabled == fEnabled
    3207                         && pRequest->lastReadDisplayChangeRequest.display  == idxDisplay;
    3208 
    3209     if (!cx && !cy && !cBits)
    3210     {
    3211         /* Special case of reset video mode. */
    3212         fSameResolution = false;
    3213     }
    3214 
    3215     Log3(("vmmdevIPort_RequestDisplayChange: same=%d. new: cx=%d, cy=%d, cBits=%d, idxDisplay=%d.\
    3216           old: cx=%d, cy=%d, cBits=%d, idxDisplay=%d. \n \
    3217           ,OriginX = %d , OriginY=%d, Enabled=%d, ChangeOrigin=%d\n",
    3218           fSameResolution, cx, cy, cBits, idxDisplay, pRequest->lastReadDisplayChangeRequest.xres,
    3219           pRequest->lastReadDisplayChangeRequest.yres, pRequest->lastReadDisplayChangeRequest.bpp,
    3220           pRequest->lastReadDisplayChangeRequest.display,
    3221           xOrigin, yOrigin, fEnabled, fChangeOrigin));
    3222 
    3223     /* we could validate the information here but hey, the guest can do that as well! */
    3224     pRequest->displayChangeRequest.xres          = cx;
    3225     pRequest->displayChangeRequest.yres          = cy;
    3226     pRequest->displayChangeRequest.bpp           = cBits;
    3227     pRequest->displayChangeRequest.display       = idxDisplay;
    3228     pRequest->displayChangeRequest.xOrigin       = xOrigin;
    3229     pRequest->displayChangeRequest.yOrigin       = yOrigin;
    3230     pRequest->displayChangeRequest.fEnabled      = fEnabled;
    3231     pRequest->displayChangeRequest.fChangeOrigin = fChangeOrigin;
    3232 
    3233     pRequest->fPending = !fSameResolution;
    3234 
    3235     if (!fSameResolution)
    3236     {
    3237         LogRel(("VMMDev: SetVideoModeHint: Got a video mode hint (%dx%dx%d)@(%dx%d),(%d;%d) at %d\n",
    3238                 cx, cy, cBits, xOrigin, yOrigin, fEnabled, fChangeOrigin, idxDisplay));
    3239 
    3240         /* IRQ so the guest knows what's going on */
    3241         VMMDevNotifyGuest(pThis, VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST);
     3266    uint32_t i;
     3267    for (i = 0; i < cDisplays; ++i)
     3268    {
     3269        VMMDevDisplayDef const *p = &paDisplays[i];
     3270
     3271        /* Either one display definition is provided or the display id must be equal to the array index. */
     3272        AssertBreakStmt(cDisplays == 1 || p->idDisplay == i, rc = VERR_INVALID_PARAMETER);
     3273        AssertBreakStmt(p->idDisplay < RT_ELEMENTS(pThis->displayChangeData.aRequests), rc = VERR_INVALID_PARAMETER);
     3274
     3275        DISPLAYCHANGEREQUEST *pRequest = &pThis->displayChangeData.aRequests[p->idDisplay];
     3276
     3277        VMMDevDisplayDef const *pLastRead = &pRequest->lastReadDisplayChangeRequest;
     3278
     3279        /* Verify that the new resolution is different and that guest does not yet know about it. */
     3280        bool const fDifferentResolution = fForce || !vmmdevIsMonitorDefEqual(p, pLastRead);
     3281
     3282        LogFunc(("same=%d. New: %dx%d, cBits=%d, id=%d. Old: %dx%d, cBits=%d, id=%d. @%d,%d, Enabled=%d, ChangeOrigin=%d\n",
     3283                 !fDifferentResolution, p->cx, p->cy, p->cBitsPerPixel, p->idDisplay,
     3284                 pLastRead->cx, pLastRead->cy, pLastRead->cBitsPerPixel, pLastRead->idDisplay,
     3285                 p->xOrigin, p->yOrigin,
     3286                 !RT_BOOL(p->fDisplayFlags & VMMDEV_DISPLAY_DISABLED),
     3287                 RT_BOOL(p->fDisplayFlags & VMMDEV_DISPLAY_ORIGIN)));
     3288
     3289        /* We could validate the information here but hey, the guest can do that as well! */
     3290        pRequest->displayChangeRequest = *p;
     3291        pRequest->fPending = fDifferentResolution;
     3292
     3293        fNotifyGuest = fNotifyGuest || fDifferentResolution;
     3294    }
     3295
     3296    if (RT_SUCCESS(rc))
     3297    {
     3298        if (fNotifyGuest)
     3299        {
     3300            for (i = 0; i < RT_ELEMENTS(pThis->displayChangeData.aRequests); ++i)
     3301            {
     3302                DISPLAYCHANGEREQUEST *pRequest = &pThis->displayChangeData.aRequests[i];
     3303                if (pRequest->fPending)
     3304                {
     3305                    VMMDevDisplayDef const *p = &pRequest->displayChangeRequest;
     3306                    LogRel(("VMMDev: SetVideoModeHint: Got a video mode hint (%dx%dx%d)@(%dx%d),(%d;%d) at %d\n",
     3307                            p->cx, p->cy, p->cBitsPerPixel, p->xOrigin, p->yOrigin,
     3308                            !RT_BOOL(p->fDisplayFlags & VMMDEV_DISPLAY_DISABLED),
     3309                            RT_BOOL(p->fDisplayFlags & VMMDEV_DISPLAY_ORIGIN), i));
     3310                }
     3311            }
     3312
     3313            /* IRQ so the guest knows what's going on */
     3314            VMMDevNotifyGuest(pThis, VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST);
     3315        }
    32423316    }
    32433317
    32443318    PDMCritSectLeave(&pThis->CritSect);
    3245     return VINF_SUCCESS;
     3319    return rc;
    32463320}
    32473321
  • trunk/src/VBox/Devices/VMMDev/VMMDevState.h

    r71891 r72352  
    1919#define ___VMMDev_VMMDevState_h
    2020
     21#include <VBoxVideo.h>  /* For VBVA definitions. */
    2122#include <VBox/VMMDev.h>
    2223#include <VBox/vmm/pdmdev.h>
     
    3132#define VMMDEV_WITH_ALT_TIMESYNC
    3233
    33 typedef struct DISPLAYCHANGEINFO
    34 {
    35     uint32_t xres;
    36     uint32_t yres;
    37     uint32_t bpp;
    38     uint32_t display;
    39     int32_t xOrigin;
    40     int32_t yOrigin;
    41     bool fEnabled;
    42     bool fChangeOrigin;
    43 } DISPLAYCHANGEINFO;
    44 
    4534typedef struct DISPLAYCHANGEREQUEST
    4635{
    4736    bool fPending;
    4837    bool afAlignment[3];
    49     DISPLAYCHANGEINFO displayChangeRequest;
    50     DISPLAYCHANGEINFO lastReadDisplayChangeRequest;
     38    VMMDevDisplayDef displayChangeRequest;
     39    VMMDevDisplayDef lastReadDisplayChangeRequest;
    5140} DISPLAYCHANGEREQUEST;
    5241
     
    6049    bool afAlignment[3];
    6150
    62     DISPLAYCHANGEREQUEST aRequests[64]; /// @todo maxMonitors
     51    DISPLAYCHANGEREQUEST aRequests[VBOX_VIDEO_MAX_SCREENS];
    6352} DISPLAYCHANGEDATA;
    6453
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