VirtualBox

Ignore:
Timestamp:
Dec 13, 2022 1:06:03 PM (2 years ago)
Author:
vboxsync
Message:

VMMDev mouse: bugref:10285: Introduce extended host mouse pointer state.

Provide VMMDev mouse with buttons and H/V wheel movement state. Extended
state can be now fetched from host in scope of VMMDevReqMouseStatusEx request.
Currently only Linux Additions utilize this functionality.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-linux.c

    r96407 r97790  
    103103# define kgid_t gid_t
    104104# define kuid_t uid_t
     105#endif
     106
     107#ifdef VBOXGUEST_WITH_INPUT_DRIVER
     108/** The name of input pointing device for mouse integration. */
     109# define VBOX_INPUT_DEVICE_NAME  "VirtualBox mouse integration"
    105110#endif
    106111
     
    148153static struct fasync_struct    *g_pFAsyncQueue;
    149154#ifdef VBOXGUEST_WITH_INPUT_DRIVER
    150 /** Pre-allocated mouse status VMMDev request for use in the IRQ
    151  * handler. */
    152 static VMMDevReqMouseStatus    *g_pMouseStatusReq;
     155/** Pre-allocated mouse status VMMDev requests for use in the IRQ handler. */
     156static VMMDevReqMouseStatusEx  *g_pMouseStatusReqEx;
    153157#endif
    154158#if RTLNX_VER_MIN(2,6,0)
     
    421425
    422426#ifdef VBOXGUEST_WITH_INPUT_DRIVER
     427/**
     428 * Check if extended mouse pointer state request protocol is currently used by driver.
     429 *
     430 * @returns True if extended protocol is used, False otherwise.
     431 */
     432static bool vgdrvLinuxUsesMouseStatusEx(void)
     433{
     434    return g_pMouseStatusReqEx->Core.header.requestType == VMMDevReq_GetMouseStatusEx;
     435}
    423436
    424437/**
     
    450463static int vboxguestOpenInputDevice(struct input_dev *pDev)
    451464{
    452     int rc = vgdrvLinuxSetMouseStatus(VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE | VMMDEV_MOUSE_NEW_PROTOCOL);
     465    int rc = vgdrvLinuxSetMouseStatus(  VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE
     466                                      | VMMDEV_MOUSE_NEW_PROTOCOL
     467                                      | (vgdrvLinuxUsesMouseStatusEx() ? VMMDEV_MOUSE_GUEST_USES_FULL_STATE_PROTOCOL : 0));
    453468    if (RT_FAILURE(rc))
    454469        return ENODEV;
     
    471486
    472487/**
     488 * Free corresponding mouse status request structure.
     489 */
     490static void vgdrvLinuxFreeMouseStatusReq(void)
     491{
     492    VbglR0GRFree(&g_pMouseStatusReqEx->Core.header);
     493    g_pMouseStatusReqEx = NULL;
     494}
     495
     496/**
    473497 * Creates the kernel input device.
    474498 */
    475499static int __init vgdrvLinuxCreateInputDevice(void)
    476500{
    477     int rc = VbglR0GRAlloc((VMMDevRequestHeader **)&g_pMouseStatusReq, sizeof(*g_pMouseStatusReq), VMMDevReq_GetMouseStatus);
     501    /* Try to allocate legacy request data first, and check if host supports extended protocol. */
     502    int rc = VbglR0GRAlloc((VMMDevRequestHeader **)&g_pMouseStatusReqEx, sizeof(VMMDevReqMouseStatus), VMMDevReq_GetMouseStatus);
     503    if (RT_SUCCESS(rc))
     504    {
     505        /* Check if host supports extended mouse state reporting. */
     506        g_pMouseStatusReqEx->Core.mouseFeatures = 0;
     507        rc = VbglR0GRPerform(&g_pMouseStatusReqEx->Core.header);
     508        if (RT_SUCCESS(rc))
     509        {
     510            if (g_pMouseStatusReqEx->Core.mouseFeatures & VMMDEV_MOUSE_HOST_USES_FULL_STATE_PROTOCOL)
     511            {
     512                VMMDevReqMouseStatusEx *pReqEx = NULL;
     513                rc = VbglR0GRAlloc((VMMDevRequestHeader **)&pReqEx, sizeof(*pReqEx), VMMDevReq_GetMouseStatusEx);
     514                if (RT_SUCCESS(rc))
     515                {
     516                    /* De-allocate legacy request data, */
     517                    VbglR0GRFree(&g_pMouseStatusReqEx->Core.header);
     518                    /* ..and switch to extended requests. */
     519                    g_pMouseStatusReqEx = pReqEx;
     520                    LogRel(("Host supports full mouse state reporting, switching to extended mouse integration protocol\n"));
     521                }
     522                else
     523                    LogRel(("Host supports full mouse state reporting, but feature cannot be initialized, switching to legacy mouse integration protocol\n"));
     524            }
     525            else
     526                LogRel(("Host does not support full mouse state reporting, switching to legacy mouse integration protocol\n"));
     527        }
     528        else
     529            LogRel(("Unable to get host mouse capabilities, switching to legacy mouse integration protocol\n"));
     530    }
     531    else
     532        rc = -ENOMEM;
     533
    478534    if (RT_SUCCESS(rc))
    479535    {
     
    481537        if (g_pInputDevice)
    482538        {
     539            g_pInputDevice->name       = VBOX_INPUT_DEVICE_NAME;
    483540            g_pInputDevice->id.bustype = BUS_PCI;
    484541            g_pInputDevice->id.vendor  = VMMDEV_VENDORID;
     
    492549            g_pInputDevice->dev.parent = &g_pPciDev->dev;
    493550# endif
     551            /* Set up input device capabilities. */
     552            ASMBitSet(g_pInputDevice->evbit, EV_ABS);
     553# ifdef EV_SYN
     554            ASMBitSet(g_pInputDevice->evbit, EV_SYN);
     555# endif
     556            ASMBitSet(g_pInputDevice->absbit, ABS_X);
     557            ASMBitSet(g_pInputDevice->absbit, ABS_Y);
     558
     559            input_set_abs_params(g_pInputDevice, ABS_X, VMMDEV_MOUSE_RANGE_MIN, VMMDEV_MOUSE_RANGE_MAX, 0, 0);
     560            input_set_abs_params(g_pInputDevice, ABS_Y, VMMDEV_MOUSE_RANGE_MIN, VMMDEV_MOUSE_RANGE_MAX, 0, 0);
     561
     562            /* Report extra capabilities to input layer if extended mouse state protocol
     563             * will be used in communication with host. */
     564            if (vgdrvLinuxUsesMouseStatusEx())
     565            {
     566                ASMBitSet(g_pInputDevice->evbit, EV_REL);
     567                ASMBitSet(g_pInputDevice->evbit, EV_KEY);
     568
     569                ASMBitSet(g_pInputDevice->relbit, REL_WHEEL);
     570                ASMBitSet(g_pInputDevice->relbit, REL_HWHEEL);
     571
     572                ASMBitSet(g_pInputDevice->keybit, BTN_LEFT);
     573                ASMBitSet(g_pInputDevice->keybit, BTN_RIGHT);
     574                ASMBitSet(g_pInputDevice->keybit, BTN_MIDDLE);
     575                ASMBitSet(g_pInputDevice->keybit, BTN_SIDE);
     576                ASMBitSet(g_pInputDevice->keybit, BTN_EXTRA);
     577            }
     578
    494579            rc = input_register_device(g_pInputDevice);
    495580            if (rc == 0)
    496             {
    497                 /* Do what one of our competitors apparently does as that works. */
    498                 ASMBitSet(g_pInputDevice->evbit, EV_ABS);
    499                 ASMBitSet(g_pInputDevice->evbit, EV_KEY);
    500 # ifdef EV_SYN
    501                 ASMBitSet(g_pInputDevice->evbit, EV_SYN);
    502 # endif
    503                 input_set_abs_params(g_pInputDevice, ABS_X, VMMDEV_MOUSE_RANGE_MIN, VMMDEV_MOUSE_RANGE_MAX, 0, 0);
    504                 input_set_abs_params(g_pInputDevice, ABS_Y, VMMDEV_MOUSE_RANGE_MIN, VMMDEV_MOUSE_RANGE_MAX, 0, 0);
    505                 ASMBitSet(g_pInputDevice->keybit, BTN_MOUSE);
    506                 /** @todo this string should be in a header file somewhere. */
    507                 g_pInputDevice->name = "VirtualBox mouse integration";
    508581                return 0;
    509             }
    510582
    511583            input_free_device(g_pInputDevice);
     
    513585        else
    514586            rc = -ENOMEM;
    515         VbglR0GRFree(&g_pMouseStatusReq->header);
    516         g_pMouseStatusReq = NULL;
    517     }
    518     else
    519         rc = -ENOMEM;
     587
     588        vgdrvLinuxFreeMouseStatusReq();
     589    }
     590
    520591    return rc;
    521592}
     
    527598static void vgdrvLinuxTermInputDevice(void)
    528599{
    529     VbglR0GRFree(&g_pMouseStatusReq->header);
    530     g_pMouseStatusReq = NULL;
     600    /* Notify host that mouse integration is no longer available. */
     601    vgdrvLinuxSetMouseStatus(0);
     602
     603    vgdrvLinuxFreeMouseStatusReq();
    531604
    532605    /* See documentation of input_register_device(): input_free_device()
     
    11551228
    11561229
     1230#ifdef VBOXGUEST_WITH_INPUT_DRIVER
     1231/**
     1232 * Get host mouse state.
     1233 *
     1234 * @returns                 IPRT status code.
     1235 * @param pfMouseFeatures   Where to store host mouse capabilities.
     1236 * @param pX                Where to store X axis coordinate.
     1237 * @param pY                Where to store Y axis coordinate.
     1238 * @param pDz               Where to store vertical wheel movement offset (only set if in case of VMMDevReq_GetMouseStatusEx request).
     1239 * @param pDw               Where to store horizontal wheel movement offset (only set if in case of VMMDevReq_GetMouseStatusEx request).
     1240 * @param pfButtons         Where to store mouse buttons state (only set if in case of VMMDevReq_GetMouseStatusEx request).
     1241 */
     1242static int vgdrvLinuxGetHostMouseState(uint32_t *pfMouseFeatures, int32_t *pX, int32_t *pY, int32_t *pDz, int32_t *pDw, uint32_t *pfButtons)
     1243{
     1244    int rc = VERR_INVALID_PARAMETER;
     1245
     1246    Assert(pfMouseFeatures);
     1247    Assert(pX);
     1248    Assert(pY);
     1249    Assert(pDz);
     1250    Assert(pDw);
     1251    Assert(pfButtons);
     1252
     1253    /* Initialize legacy request data. */
     1254    g_pMouseStatusReqEx->Core.mouseFeatures = 0;
     1255    g_pMouseStatusReqEx->Core.pointerXPos = 0;
     1256    g_pMouseStatusReqEx->Core.pointerYPos = 0;
     1257
     1258    /* Initialize extended request data if VMMDevReq_GetMouseStatusEx is used. */
     1259    if (vgdrvLinuxUsesMouseStatusEx())
     1260    {
     1261        g_pMouseStatusReqEx->dz = 0;
     1262        g_pMouseStatusReqEx->dw = 0;
     1263        g_pMouseStatusReqEx->fButtons = 0;
     1264    }
     1265
     1266    /* Get host mouse state - either lagacy or extended version. */
     1267    rc = VbglR0GRPerform(&g_pMouseStatusReqEx->Core.header);
     1268    if (RT_SUCCESS(rc))
     1269    {
     1270        *pfMouseFeatures = g_pMouseStatusReqEx->Core.mouseFeatures;
     1271        *pX = g_pMouseStatusReqEx->Core.pointerXPos;
     1272        *pY = g_pMouseStatusReqEx->Core.pointerYPos;
     1273
     1274        /* Get extended mouse state data in case of VMMDevReq_GetMouseStatusEx. */
     1275        if (vgdrvLinuxUsesMouseStatusEx())
     1276        {
     1277            *pDz = g_pMouseStatusReqEx->dz;
     1278            *pDw = g_pMouseStatusReqEx->dw;
     1279            *pfButtons = g_pMouseStatusReqEx->fButtons;
     1280        }
     1281    }
     1282
     1283    return rc;
     1284}
     1285#endif /* VBOXGUEST_WITH_INPUT_DRIVER */
     1286
     1287
    11571288void VGDrvNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt)
    11581289{
    11591290#ifdef VBOXGUEST_WITH_INPUT_DRIVER
    11601291    int rc;
     1292    uint32_t fMouseFeatures = 0;
     1293    int32_t x = 0;
     1294    int32_t y = 0;
     1295    int32_t dz = 0;
     1296    int32_t dw = 0;
     1297    uint32_t fButtons = 0;
    11611298#endif
    11621299    NOREF(pDevExt);
     
    11711308    kill_fasync(&g_pFAsyncQueue, SIGIO, POLL_IN);
    11721309#ifdef VBOXGUEST_WITH_INPUT_DRIVER
    1173     /* Report events to the kernel input device */
    1174     g_pMouseStatusReq->mouseFeatures = 0;
    1175     g_pMouseStatusReq->pointerXPos = 0;
    1176     g_pMouseStatusReq->pointerYPos = 0;
    1177     rc = VbglR0GRPerform(&g_pMouseStatusReq->header);
     1310    rc = vgdrvLinuxGetHostMouseState(&fMouseFeatures, &x, &y, &dz, &dw, &fButtons);
    11781311    if (RT_SUCCESS(rc))
    11791312    {
    1180         input_report_abs(g_pInputDevice, ABS_X,
    1181                          g_pMouseStatusReq->pointerXPos);
    1182         input_report_abs(g_pInputDevice, ABS_Y,
    1183                          g_pMouseStatusReq->pointerYPos);
     1313        input_report_abs(g_pInputDevice, ABS_X, x);
     1314        input_report_abs(g_pInputDevice, ABS_Y, y);
     1315
     1316        if (   vgdrvLinuxUsesMouseStatusEx()
     1317            && fMouseFeatures & VMMDEV_MOUSE_HOST_USES_FULL_STATE_PROTOCOL
     1318            && fMouseFeatures & VMMDEV_MOUSE_GUEST_USES_FULL_STATE_PROTOCOL)
     1319        {
     1320            input_report_rel(g_pInputDevice, REL_WHEEL,  dz);
     1321            input_report_rel(g_pInputDevice, REL_HWHEEL, dw);
     1322
     1323            input_report_key(g_pInputDevice, BTN_LEFT,   RT_BOOL(fButtons & VMMDEV_MOUSE_BUTTON_LEFT));
     1324            input_report_key(g_pInputDevice, BTN_RIGHT,  RT_BOOL(fButtons & VMMDEV_MOUSE_BUTTON_RIGHT));
     1325            input_report_key(g_pInputDevice, BTN_MIDDLE, RT_BOOL(fButtons & VMMDEV_MOUSE_BUTTON_MIDDLE));
     1326            input_report_key(g_pInputDevice, BTN_SIDE,   RT_BOOL(fButtons & VMMDEV_MOUSE_BUTTON_X1));
     1327            input_report_key(g_pInputDevice, BTN_EXTRA,  RT_BOOL(fButtons & VMMDEV_MOUSE_BUTTON_X2));
     1328        }
     1329
    11841330# ifdef EV_SYN
    11851331        input_sync(g_pInputDevice);
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