VirtualBox

Changeset 49463 in vbox for trunk/src/VBox/Frontends


Ignore:
Timestamp:
Nov 13, 2013 12:35:28 PM (11 years ago)
Author:
vboxsync
Message:

OS X host: HID LEDs sync: split IOKit callback into smaller parts; update log messages and comments.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/platform/darwin/DarwinKeyboard.cpp

    r49457 r49463  
    14721472}
    14731473
    1474 /** IOKit key press callback. Triggered before Carbon callback. We remember which keyboard produced a keypress here. */
    1475 static void darwinHidInputCallback(void *pData, IOReturn unused, void *unused1, IOHIDValueRef pValueRef)
    1476 {
    1477     (void)unused;
    1478     (void)unused1;
    1479 
    1480     AssertReturnVoid(pValueRef);
    1481 
    1482     IOHIDElementRef pElementRef = IOHIDValueGetElement(pValueRef);
    1483     AssertReturnVoid(pElementRef);
    1484 
    1485     uint32_t usage = IOHIDElementGetUsage(pElementRef);
    1486 
    1487     if (IOHIDElementGetUsagePage(pElementRef) == kHIDPage_KeyboardOrKeypad)    /* Keyboard or keypad event */
    1488         if (usage == kHIDUsage_KeyboardCapsLock ||                             /* CapsLock key has been pressed */
    1489             usage == kHIDUsage_KeypadNumLock)                                  /* ... or NumLock key has been pressed */
    1490         {
    1491             VBoxKbdState_t *pKbd = (VBoxKbdState_t *)pData;
    1492 
    1493             if (pKbd && pKbd->pParentContainer)
    1494             {
    1495                 bool fKeyDown = (IOHIDValueGetIntegerValue(pValueRef) == 1);
    1496 
    1497                 VBoxHidsState_t *pHidState = (VBoxHidsState_t *)pKbd->pParentContainer;
    1498                 VBoxKbdEvent_t  *pEvent = NULL;;
    1499                 CFIndex          iQueue = 0;
    1500 
    1501                 AssertReturnVoid(pHidState);
    1502 
    1503                 if (RT_FAILURE(RTSemMutexRequest(pHidState->fifoEventQueueLock, RT_INDEFINITE_WAIT)))
    1504                     return ;
    1505 
    1506                 /* Allocate new event data on Key-Down, find a cached one on Key-Up */
    1507                 if (fKeyDown)
    1508                     pEvent = (VBoxKbdEvent_t *)malloc(sizeof(VBoxKbdEvent_t));
    1509                 else
    1510                 {
    1511                     for (CFIndex i = 0; i < CFArrayGetCount(pHidState->pFifoEventQueue); i++)
    1512                     {
    1513                         VBoxKbdEvent_t *pCachedEvent = (VBoxKbdEvent_t *)CFArrayGetValueAtIndex(pHidState->pFifoEventQueue, i);
    1514                         if (pCachedEvent && pCachedEvent->pKbd == pKbd && pCachedEvent->iKeyCode == usage)
    1515                         {
    1516                             pEvent = pCachedEvent;
    1517                             iQueue = i;
    1518                             break;
    1519                         }
    1520                     }
    1521                 }
    1522 
    1523                 if (pEvent)
    1524                 {
    1525                     if (usage == kHIDUsage_KeyboardCapsLock && pKbd->cCapsLockTimeout)
    1526                     {
    1527                         if (fKeyDown)
    1528                             pEvent->tsKeyDown = RTTimeSystemMilliTS();
    1529                     }
    1530 
    1531                     if (fKeyDown)
    1532                     {
    1533                         LogRel2(("IOHID: KBD %d: Modifier Key-Down\n", (int)pKbd->idxPosition));
    1534 
    1535                         pEvent->pKbd = pKbd;
    1536                         pEvent->iKeyCode = usage;
    1537 
    1538                         /* Append FIFO event queue */
    1539                         CFArrayAppendValue(pHidState->pFifoEventQueue, (void *)pEvent);
    1540                     }
    1541                     else if (pEvent->iKeyCode == kHIDUsage_KeyboardCapsLock)
    1542                     {
    1543                         /* An Apple keyboard */
    1544                         if (pKbd->cCapsLockTimeout > 0)
    1545                         {
    1546                             if (pHidState->guestState.fCapsLockOn == false)
    1547                             {
    1548                                 uint64_t tsDiff = RTTimeSystemMilliTS() - pEvent->tsKeyDown;
    1549                                 if (tsDiff < pKbd->cCapsLockTimeout)
    1550                                 {
    1551                                     /* Such key-press should not trigger Carbon callback. Just remove an event from queue. */
    1552                                     free(pEvent);
    1553                                     CFArrayRemoveValueAtIndex(pHidState->pFifoEventQueue, iQueue);
    1554                                     LogRel2(("IOHID: KBD %d: Modifier Key-Up event on Apple keyboard. Key-Down event was triggered %llu ms "
    1555                                         "ago. Carbon event should not be triggered, removed from queue\n", (int)pKbd->idxPosition, tsDiff));
    1556                                 }
    1557                                 else
    1558                                     LogRel2(("IOHID: KBD %d: Modifier Key-Up event: Apple keyboard: possibly LEDs now out of sync. "
    1559                                         "Diff between Key-Down and Key-Up is too big (%llu ms) but Carbon callback did not care about "
    1560                                         "Key-Down event.\n", (int)pKbd->idxPosition, tsDiff));
    1561                             }
    1562                             else
    1563                                 LogRel2(("IOHID: KBD %d: Modifier Key-Up event on Apple keyboard occurred before Carbon callback. No worries.\n",
    1564                                     (int)pKbd->idxPosition));
    1565                         }
    1566                         /* Non-Apple keyboard */
    1567                         else
    1568                         {
    1569                             LogRel2(("IOHID: KBD %d: Modifier Key-Up event: Non-Apple keyboard: possibly LEDs now out of sync. "
    1570                                 "Carbon callback did not care about Key-Down event.\n", (int)pKbd->idxPosition));
    1571                         }
    1572                     }
    1573                 }
    1574                 else
    1575                 {
    1576                     if (fKeyDown)
    1577                         LogRel2(("IOHID: unable to find memory for KBD %d event\n", (int)pKbd->idxPosition));
    1578                     else
    1579                         LogRel2(("IOHID: KBD %d event was successfully handled by Carbon callback\n", (int)pKbd->idxPosition));
    1580                 }
    1581 
    1582                 RTSemMutexRelease(pHidState->fifoEventQueueLock);
    1583             }
    1584             else
    1585                 LogRel2(("IOHID: No KBD: A modifier key has been pressed\n"));
    1586         }
    1587 }
    1588 
    1589 /** Carbon key press callback helper: CapsLock timeout checker. */
     1474/** IOKit key press callback helper: take care about key-down event.
     1475 * This code should be executed within a critical section under pHidState->fifoEventQueueLock. */
     1476static void darwinHidInputCbKeyDown(VBoxKbdState_t *pKbd, uint32_t iKeyCode, VBoxHidsState_t *pHidState)
     1477{
     1478    VBoxKbdEvent_t *pEvent = (VBoxKbdEvent_t *)malloc(sizeof(VBoxKbdEvent_t));
     1479
     1480    if (pEvent)
     1481    {
     1482        /* Queue Key-Down event. */
     1483        pEvent->tsKeyDown = RTTimeSystemMilliTS();
     1484        pEvent->pKbd      = pKbd;
     1485        pEvent->iKeyCode  = iKeyCode;
     1486
     1487        CFArrayAppendValue(pHidState->pFifoEventQueue, (void *)pEvent);
     1488
     1489        LogRel2(("IOHID: KBD %d: Modifier Key-Down event\n", (int)pKbd->idxPosition));
     1490    }
     1491    else
     1492        LogRel2(("IOHID: Modifier Key-Up event. Unable to find memory for KBD %d event\n", (int)pKbd->idxPosition));
     1493}
     1494
     1495/** IOkit and Carbon key press callbacks helper: CapsLock timeout checker.
     1496 *
     1497 * Returns FALSE if CAPS LOCK timeout not occurred and its state still was not switched (Apple kbd).
     1498 * Returns TRUE if CAPS LOCK timeout occurred and its state was switched (Apple kbd).
     1499 * Returns TRUE for non-Apple kbd. */
    15901500static bool darwinKbdCapsEventMatches(VBoxKbdEvent_t *pEvent, bool fCapsLed)
    15911501{
     
    16081518
    16091519    return true;
     1520}
     1521
     1522/** IOKit key press callback helper: take care about key-up event.
     1523 * This code should be executed within a critical section under pHidState->fifoEventQueueLock. */
     1524static void darwinHidInputCbKeyUp(VBoxKbdState_t *pKbd, uint32_t iKeyCode, VBoxHidsState_t *pHidState)
     1525{
     1526    CFIndex         iQueue = 0;
     1527    VBoxKbdEvent_t *pEvent = NULL;
     1528
     1529    /* Key-up event assumes that key-down event occured previously. If so, an event
     1530     * data should be in event queue. Attempt to find it. */
     1531    for (CFIndex i = 0; i < CFArrayGetCount(pHidState->pFifoEventQueue); i++)
     1532    {
     1533        VBoxKbdEvent_t *pCachedEvent = (VBoxKbdEvent_t *)CFArrayGetValueAtIndex(pHidState->pFifoEventQueue, i);
     1534
     1535        if (pCachedEvent && pCachedEvent->pKbd == pKbd && pCachedEvent->iKeyCode == iKeyCode)
     1536        {
     1537            pEvent = pCachedEvent;
     1538            iQueue = i;
     1539            break;
     1540        }
     1541    }
     1542
     1543    /* Event found. */
     1544    if (pEvent)
     1545    {
     1546        /* NUM LOCK should not have timeout and its press should immidiately trigger Carbon callback.
     1547         * Therefore, if it is still in queue this is a problem because it was not handled by Carbon callback.
     1548         * This mean that NUM LOCK is most likely out of sync. */
     1549        if (iKeyCode == kHIDUsage_KeypadNumLock)
     1550        {
     1551            LogRel2(("IOHID: KBD %d: Modifier Key-Up event. Key-Down event was not habdled by Carbon callback. "
     1552                "NUM LOCK is most likely out of sync\n", (int)pKbd->idxPosition));
     1553        }
     1554        else if (iKeyCode == kHIDUsage_KeyboardCapsLock)
     1555        {
     1556            /* If CAPS LOCK key-press event still not match CAPS LOCK timeout criteria, Carbon callback
     1557             * should not be triggered for this event at all. Threfore, event should be removed from queue. */
     1558            if (!darwinKbdCapsEventMatches(pEvent, pHidState->guestState.fCapsLockOn))
     1559            {
     1560                free(pEvent);
     1561                CFArrayRemoveValueAtIndex(pHidState->pFifoEventQueue, iQueue);
     1562
     1563                LogRel2(("IOHID: KBD %d: Modifier Key-Up event on Apple keyboard. Key-Down event was triggered %llu ms "
     1564                    "ago. Carbon event should not be triggered, removed from queue\n", (int)pKbd->idxPosition,
     1565                    RTTimeSystemMilliTS() - pEvent->tsKeyDown));
     1566            }
     1567            else
     1568            {
     1569                /* CAPS LOCK key-press event matches to CAPS LOCK timeout criteria and still present in queue.
     1570                 * This might mean that Carbon callback was triggered for this event, but cached keyboard state was not updated.
     1571                 * It also might mean that Carbon callback still was not triggered, but it will be soon.
     1572                 * Threfore, CAPS LOCK might be out of sync. */
     1573                LogRel2(("IOHID: KBD %d: Modifier Key-Up event. Key-Down event was triggered %llu ms "
     1574                    "ago and still was not handled by Carbon callback. CAPS LOCK might out of sync if "
     1575                    "Carbon will not handle this\n", (int)pKbd->idxPosition, RTTimeSystemMilliTS() - pEvent->tsKeyDown));
     1576            }
     1577        }
     1578    }
     1579    else
     1580        LogRel2(("IOHID: KBD %d: Modifier Key-Up event. Modifier state change was "
     1581            "successfully handled by Carbon callback\n", (int)pKbd->idxPosition));
     1582}
     1583
     1584/** IOKit key press callback. Triggered before Carbon callback. We remember which keyboard produced a keypress here. */
     1585static void darwinHidInputCallback(void *pData, IOReturn unused, void *unused1, IOHIDValueRef pValueRef)
     1586{
     1587    (void)unused;
     1588    (void)unused1;
     1589
     1590    AssertReturnVoid(pValueRef);
     1591
     1592    IOHIDElementRef pElementRef = IOHIDValueGetElement(pValueRef);
     1593    AssertReturnVoid(pElementRef);
     1594
     1595    uint32_t usage = IOHIDElementGetUsage(pElementRef);
     1596
     1597    if (IOHIDElementGetUsagePage(pElementRef) == kHIDPage_KeyboardOrKeypad)    /* Keyboard or keypad event */
     1598        if (usage == kHIDUsage_KeyboardCapsLock ||                             /* CapsLock key has been pressed */
     1599            usage == kHIDUsage_KeypadNumLock)                                  /* ... or NumLock key has been pressed */
     1600        {
     1601            VBoxKbdState_t *pKbd = (VBoxKbdState_t *)pData;
     1602
     1603            if (pKbd && pKbd->pParentContainer)
     1604            {
     1605                bool             fKeyDown  = (IOHIDValueGetIntegerValue(pValueRef) == 1);
     1606                VBoxHidsState_t *pHidState = (VBoxHidsState_t *)pKbd->pParentContainer;
     1607
     1608                AssertReturnVoid(pHidState);
     1609
     1610                if (RT_FAILURE(RTSemMutexRequest(pHidState->fifoEventQueueLock, RT_INDEFINITE_WAIT)))
     1611                    return ;
     1612
     1613                /* Handle corresponding event. */
     1614                if (fKeyDown)
     1615                    darwinHidInputCbKeyDown(pKbd, usage, pHidState);
     1616                else
     1617                    darwinHidInputCbKeyUp(pKbd, usage, pHidState);
     1618
     1619                RTSemMutexRelease(pHidState->fifoEventQueueLock);
     1620            }
     1621            else
     1622                LogRel2(("IOHID: No KBD: A modifier key has been pressed\n"));
     1623        }
    16101624}
    16111625
     
    17961810                         (int)pKbd->idxPosition, pKbd, VBOX_BOOL_TO_STR_STATE(pKbd->LED.fNumLockOn), VBOX_BOOL_TO_STR_STATE(pKbd->LED.fCapsLockOn),
    17971811                         VBOX_BOOL_TO_STR_STATE(pKbd->LED.fScrollLockOn)));
     1812
    17981813                    if (fApplyLedState)
    17991814                    {
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