VirtualBox

Changeset 49850 in vbox for trunk/src


Ignore:
Timestamp:
Dec 9, 2013 5:24:01 PM (11 years ago)
Author:
vboxsync
Message:

OS X host: HID LEDs sync: resync kbd device when it awake from auto-sleep.

File:
1 edited

Legend:

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

    r49811 r49850  
    4040# include <iprt/semaphore.h>
    4141# include <VBox/sup.h>
     42# include <IOKit/IOMessage.h>
    4243#endif
    4344
     
    315316    CFIndex           idxPosition;          /** Position in global storage (used to simplify CFArray navigation when removing detached device) */
    316317    uint64_t          cCapsLockTimeout;     /** KBD CAPS LOCK key hold timeout (some Apple keyboards only) */
     318
     319    io_object_t           notification;         /** General interest notification stuff: notification reference */
     320    IONotificationPortRef notificationPortRef;  /** General interest notification stuff: notification port reference */
     321
    317322} VBoxKbdState_t;
    318323
     
    17181723}
    17191724
     1725/** IOHID Device general interest notification callback. We are interested in kIOMessageDeviceHasPoweredOn message.
     1726 * When we receive it, we do silently resync kbd which was just resumed. The rest of messages are for debugging
     1727 * purpose. */
     1728static void darwinHidNotificationCb(void *pData, io_service_t unused1, natural_t msg, void *unused2)
     1729{
     1730    NOREF(unused1);
     1731    NOREF(unused2);
     1732
     1733    AssertReturnVoid(pData);
     1734    VBoxKbdState_t *pKbd = (VBoxKbdState_t *)pData;
     1735
     1736    switch (msg)
     1737    {
     1738        case kIOMessageDeviceHasPoweredOn:
     1739            {
     1740                LogRel2(("HID general interest notification kIOMessageDeviceHasPoweredOn for KBD %d\n", (int)(pKbd->idxPosition)));
     1741
     1742                VBoxHidsState_t *pHidState = (VBoxHidsState_t *)pKbd->pParentContainer;
     1743                CFDictionaryRef  elementMatchingDict = darwinQueryLedElementMatchingDictionary();
     1744                if (elementMatchingDict)
     1745                {
     1746                    (void)darwinSetDeviceLedsState(pKbd->pDevice, elementMatchingDict,
     1747                        pHidState->guestState.fNumLockOn, pHidState->guestState.fCapsLockOn, pHidState->guestState.fScrollLockOn);
     1748                    CFRelease(elementMatchingDict);
     1749                }
     1750                break;
     1751            }
     1752
     1753        case kIOMessageDeviceWillPowerOff:
     1754            {
     1755                LogRel2(("HID general interest notification kIOMessageDeviceWillPowerOff for KBD %d\n", (int)(pKbd->idxPosition)));
     1756                break;
     1757            }
     1758
     1759        case kIOMessageCanDevicePowerOff:
     1760            {
     1761                LogRel2(("HID general interest notification kIOMessageCanDevicePowerOff for KBD %d\n", (int)(pKbd->idxPosition)));
     1762                break;
     1763            }
     1764
     1765        default:
     1766            LogRel2(("HID general interest notification 0x%X for KBD %d\n", (int)msg, (int)(pKbd->idxPosition)));
     1767    }
     1768}
     1769
     1770/** Battle against automatic power management for KBD devices. Register general interest notification
     1771 * callback in order to recync KBD device when its driver report that it has been resumed from auto-sleep. */
     1772static int darwinHidSubscribeInterestNotification(VBoxKbdState_t *pKbd)
     1773{
     1774    AssertReturn(pKbd, kIOReturnError);
     1775    AssertReturn(pKbd->pDevice, kIOReturnError);
     1776
     1777    io_service_t  service;
     1778    kern_return_t rc = kIOReturnError;
     1779
     1780    service = IOHIDDeviceGetService(pKbd->pDevice);
     1781    if (service)
     1782    {
     1783        pKbd->notificationPortRef = IONotificationPortCreate(kIOMasterPortDefault);
     1784        if (pKbd->notificationPortRef)
     1785        {
     1786            rc = IOServiceAddInterestNotification(pKbd->notificationPortRef, service, kIOGeneralInterest, darwinHidNotificationCb, pKbd, &(pKbd->notification));
     1787            if (rc == kIOReturnSuccess)
     1788            {
     1789                LogRel2(("Interest notification has been registeted for KBD %d\n", (int)(pKbd->idxPosition)));
     1790                CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(pKbd->notificationPortRef), kCFRunLoopDefaultMode);
     1791                return 0;
     1792            }
     1793        }
     1794    }
     1795
     1796    return rc;
     1797}
     1798
     1799/** Remove general interest notification subscription. */
     1800static void darwinHidUnsubscribeInterestNotification(VBoxKbdState_t *pKbd)
     1801{
     1802    AssertReturnVoid(pKbd);
     1803    AssertReturnVoid(pKbd->notificationPortRef);
     1804
     1805    CFRunLoopRemoveSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(pKbd->notificationPortRef), kCFRunLoopDefaultMode);
     1806    IONotificationPortDestroy(pKbd->notificationPortRef);
     1807    pKbd->notificationPortRef = 0;
     1808
     1809    LogRel2(("Interest notification has been removed for KBD %d\n", (int)(pKbd->idxPosition)));
     1810}
     1811
    17201812/** This callback is called when user physically removes HID device. We remove device from cache here. */
    17211813static void darwinHidRemovalCallback(void *pData, IOReturn unused, void *unused1)
     
    17331825    //if (RT_FAILURE(RTSemMutexRequest(pHidState->fifoEventQueueLock, RT_INDEFINITE_WAIT)))
    17341826    //    return ;
     1827
     1828    darwinHidUnsubscribeInterestNotification(pKbd);
    17351829
    17361830    CFArrayRemoveValueAtIndex(pHidState->pDeviceCollection, pKbd->idxPosition);
     
    17971891                    }
    17981892
    1799                     /* Register per-device removal callback */
    1800                     IOHIDDeviceRegisterRemovalCallback(pKbd->pDevice, darwinHidRemovalCallback, (void *)pKbd);
    1801 
    1802                     /* Register per-device input callback */
    1803                     IOHIDDeviceRegisterInputValueCallback(pKbd->pDevice, darwinHidInputCallback, (void *)pKbd);
    1804                     IOHIDDeviceScheduleWithRunLoop(pKbd->pDevice, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    1805 
    1806                     CFArrayAppendValue(pHidState->pDeviceCollection, (void *)pKbd);
    1807 
    1808                     LogRel2(("Saved LEDs for KBD %d (%p): fNumLockOn=%s, fCapsLockOn=%s, fScrollLockOn=%s\n",
    1809                          (int)pKbd->idxPosition, pKbd, VBOX_BOOL_TO_STR_STATE(pKbd->LED.fNumLockOn), VBOX_BOOL_TO_STR_STATE(pKbd->LED.fCapsLockOn),
    1810                          VBOX_BOOL_TO_STR_STATE(pKbd->LED.fScrollLockOn)));
    1811 
    1812                     if (fApplyLedState)
     1893                    rc = darwinHidSubscribeInterestNotification(pKbd);
     1894                    if (rc == 0)
    18131895                    {
    1814                         rc = darwinSetDeviceLedsState(pKbd->pDevice, elementMatchingDict, pHidState->guestState.fNumLockOn,
    1815                                                       pHidState->guestState.fCapsLockOn, pHidState->guestState.fScrollLockOn);
    1816                         if (rc != 0)
    1817                             LogRel2(("Unable to apply guest state to newly attached device\n"));
     1896                        /* Register per-device removal callback */
     1897                        IOHIDDeviceRegisterRemovalCallback(pKbd->pDevice, darwinHidRemovalCallback, (void *)pKbd);
     1898
     1899                        /* Register per-device input callback */
     1900                        IOHIDDeviceRegisterInputValueCallback(pKbd->pDevice, darwinHidInputCallback, (void *)pKbd);
     1901                        IOHIDDeviceScheduleWithRunLoop(pKbd->pDevice, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
     1902
     1903                        CFArrayAppendValue(pHidState->pDeviceCollection, (void *)pKbd);
     1904
     1905                        LogRel2(("Saved LEDs for KBD %d (%p): fNumLockOn=%s, fCapsLockOn=%s, fScrollLockOn=%s\n",
     1906                            (int)pKbd->idxPosition, pKbd, VBOX_BOOL_TO_STR_STATE(pKbd->LED.fNumLockOn), VBOX_BOOL_TO_STR_STATE(pKbd->LED.fCapsLockOn),
     1907                            VBOX_BOOL_TO_STR_STATE(pKbd->LED.fScrollLockOn)));
     1908
     1909                        if (fApplyLedState)
     1910                        {
     1911                            rc = darwinSetDeviceLedsState(pKbd->pDevice, elementMatchingDict, pHidState->guestState.fNumLockOn,
     1912                                                          pHidState->guestState.fCapsLockOn, pHidState->guestState.fScrollLockOn);
     1913                            if (rc != 0)
     1914                                LogRel2(("Unable to apply guest state to newly attached device\n"));
     1915                        }
     1916
     1917                        CFRelease(elementMatchingDict);
     1918                        return;
    18181919                    }
    1819 
    1820                     CFRelease(elementMatchingDict);
    1821                     return;
     1920                    else
     1921                        LogRel2(("Unable to subscribe to IOService interest notification for KBD %d. Disable sync for this keyboard.\n", (int)(pKbd->idxPosition)));
    18221922                }
    18231923
     
    20372137                     VBOX_BOOL_TO_STR_STATE(pKbd->LED.fScrollLockOn)));
    20382138
     2139                darwinHidUnsubscribeInterestNotification(pKbd);
     2140
    20392141                free(pKbd);
    20402142            }
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