VirtualBox

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


Ignore:
Timestamp:
Oct 11, 2013 7:45:09 AM (11 years ago)
Author:
vboxsync
Message:

OS X host: leds sync: code reworked in order to support dynamic kbd attach/detach, updated coding style.

Location:
trunk/src/VBox/Frontends/VirtualBox/src
Files:
3 edited

Legend:

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

    r49012 r49048  
    2222*******************************************************************************/
    2323#define LOG_GROUP LOG_GROUP_GUI
     24
    2425#define VBOX_WITH_KBD_LEDS_SYNC
     26//#define VBOX_WITHOUT_KBD_LEDS_SYNC_FILTERING
    2527
    2628#include "DarwinKeyboard.h"
     
    3234#ifdef DEBUG_PRINTF
    3335# include <iprt/stream.h>
     36#endif
     37
     38#ifdef VBOX_WITH_KBD_LEDS_SYNC
     39# include <iprt/err.h>
     40# include <iprt/semaphore.h>
    3441#endif
    3542
     
    291298
    292299#ifdef VBOX_WITH_KBD_LEDS_SYNC
     300
     301#define VBOX_BOOL_TO_STR_STATE(x) (x) ? "ON" : "OFF"
    293302/* HID LEDs synchronization data: LED states. */
     303typedef struct VBoxLedState_t {
     304    bool fNumLockOn;                        /** A state of NUM LOCK */
     305    bool fCapsLockOn;                       /** A state of CAPS LOCK */
     306    bool fScrollLockOn;                     /** A state of SCROLL LOCK */
     307} VBoxLedState_t;
     308
     309/* HID LEDs synchronization data: keyboard states. */
    294310typedef struct VBoxKbdState_t {
    295     bool             fNumLockOn;
    296     bool             fCapsLockOn;
    297     bool             fScrollLockOn;
    298     bool             fAttached;
     311    IOHIDDeviceRef    pDevice;              /** A reference to IOKit HID device */
     312    VBoxLedState_t    LED;                  /** LED states */
     313    CFMutableArrayRef pStorageArray;        /** A reference to array where VBoxKbdState_t instance is stored */
     314    CFIndex           idxPosition;          /** Position in global storage (used to simplify CFArray navigation when removing detached device) */
    299315} VBoxKbdState_t;
    300316
    301317/* HID LEDs synchronization data: IOKit specific data. */
    302318typedef struct VBoxHidsState_t {
    303     IOHIDManagerRef     hidManagerRef;
    304     IOHIDDeviceRef     *hidDevicesCollection;
    305     VBoxKbdState_t      *hidLedsCollection;
    306     CFIndex             cDevices;
     319    IOHIDManagerRef     hidManagerRef;      /** IOKit HID manager reference */
     320    CFMutableArrayRef   pDeviceCollection;  /** This array consists of VBoxKbdState_t elements */
     321    VBoxLedState_t      guestState;         /** LED states that were stored during last broadcast and reflect a guest LED states */
     322
     323    /* Carbon events data */
    307324    CFMachPortRef       pTapRef;
    308325    CFRunLoopSourceRef  pLoopSourceRef;
     
    311328/* A *sync* between IOKit and Carbon callbacks. */
    312329static VBoxKbdState_t *g_LastTouchedState;
    313 #endif // !VBOX_WITH_KBD_LEDS_SYNC
     330#endif /* !VBOX_WITH_KBD_LEDS_SYNC */
    314331
    315332/*******************************************************************************
     
    11591176#ifdef VBOX_WITH_KBD_LEDS_SYNC
    11601177/** Prepare dictionary that will be used to match HID LED device(s) while discovering. */
    1161 static CFDictionaryRef darwinGetLedDeviceMatchingDictionary()
     1178static CFDictionaryRef darwinQueryLedDeviceMatchingDictionary()
    11621179{
    11631180    CFDictionaryRef deviceMatchingDictRef;
     
    12041221
    12051222/** Prepare dictionary that will be used to match HID LED device element(s) while discovering. */
    1206 static CFDictionaryRef darwinGetLedElementMatchingDictionary()
     1223static CFDictionaryRef darwinQueryLedElementMatchingDictionary()
    12071224{
    12081225    CFDictionaryRef elementMatchingDictRef;
     
    13801397}
    13811398
    1382 static void darwinHidRemovalCallback(void *pData, IOReturn unused, void *unused1)
     1399/** Some keyboard devices might freeze after LEDs manipulation. We filter out such devices here.
     1400 * In the list below, devices which verified to be stable against LEDs manipulation.
     1401 * If you want to add new device, then add it here. Currently, we only filter devices by Vendor ID.
     1402 * In future it might make sense to take Product ID into account as well. */
     1403static bool darwinHidDeviceSupported(IOHIDDeviceRef pHidDeviceRef)
     1404{
     1405#ifndef VBOX_WITHOUT_KBD_LEDS_SYNC_FILTERING
     1406    bool      fSupported = false;
     1407    CFTypeRef pNumberRef;
     1408    uint32_t  vendorId = 0;
     1409
     1410    AssertReturn(pHidDeviceRef, false);
     1411
     1412    pNumberRef = IOHIDDeviceGetProperty(pHidDeviceRef, CFSTR(kIOHIDVendorIDKey));
     1413    if (pNumberRef)
     1414    {
     1415        if (CFGetTypeID(pNumberRef) == CFNumberGetTypeID())
     1416        {
     1417            if (CFNumberGetValue((CFNumberRef)pNumberRef, kCFNumberSInt32Type, &vendorId))
     1418            {
     1419                switch (vendorId)
     1420                {
     1421                    case kIOUSBVendorIDAppleComputer:   /** Apple devices always in the list */
     1422                    case 0x03F0:                        /** Hewlett-Packard (verified with model KU-0316) */
     1423                    case 0x0430:                        /** Sun keyboards */
     1424                        fSupported = true;
     1425                        break;
     1426                }
     1427
     1428                Log2(("HID device Vendor ID 0x%X %s in the list of supported devices.\n", vendorId, (fSupported ? "is" : "is not")));
     1429            }
     1430        }
     1431    }
     1432
     1433    return fSupported;
     1434#else /* !VBOX_WITH_KBD_LEDS_SYNC_FILTERING */
     1435    return true;
     1436#endif
     1437}
     1438
     1439/** IOKit key press callback. Triggered before Carbon callback. We remember which keyboard produced a keypress here. */
     1440static void darwinHidInputCallback(void *pData, IOReturn unused, void *unused1, IOHIDValueRef pValueRef)
    13831441{
    13841442    (void)unused;
    13851443    (void)unused1;
    13861444
    1387     VBoxKbdState_t *pState = (VBoxKbdState_t *)pData;
    1388 
    1389     if (pState)
    1390     {
    1391         pState->fAttached = false;
    1392     }
    1393 }
    1394 
    1395 /** IOKit key press callback. Triggered before Carbon callback. */
    1396 static void darwinHidInputCallback(void *pData, IOReturn unused, void *unused1, IOHIDValueRef valueRef)
    1397 {
    1398     (void)unused;
    1399     (void)unused1;
    1400 
    1401     IOHIDElementRef pElementRef = IOHIDValueGetElement(valueRef);
    1402 
    1403     if (pElementRef)
    1404     {
    1405         if (IOHIDElementGetUsagePage(pElementRef) == kHIDPage_KeyboardOrKeypad)        /* Keyboard or keypad event */
    1406             if (IOHIDValueGetIntegerValue(valueRef) == 1)                              /* key has been pressed down */
    1407                 if (IOHIDElementGetUsage(pElementRef) == kHIDUsage_KeyboardCapsLock || /* CapsLock key has been pressed */
    1408                     IOHIDElementGetUsage(pElementRef) == kHIDUsage_KeypadNumLock)      /* ... or NumLock key has been pressed */
    1409                 {
    1410                     Log2(("A modifier key has been pressed\n"));
    1411                     g_LastTouchedState = (VBoxKbdState_t *)pData;
    1412                 }
    1413 
    1414     }
    1415 }
    1416 
    1417 /** Carbon key press callback. Triggered after IOKit callback. */
    1418 #define VBOX_BOOL_TO_STR_STATE(x) (x) ? "ON" : "OFF"
     1445    AssertReturnVoid(pValueRef);
     1446
     1447    IOHIDElementRef pElementRef = IOHIDValueGetElement(pValueRef);
     1448    AssertReturnVoid(pElementRef);
     1449
     1450    if (IOHIDElementGetUsagePage(pElementRef) == kHIDPage_KeyboardOrKeypad)        /* Keyboard or keypad event */
     1451        if (IOHIDValueGetIntegerValue(pValueRef) == 1)                             /* key has been pressed down */
     1452            if (IOHIDElementGetUsage(pElementRef) == kHIDUsage_KeyboardCapsLock || /* CapsLock key has been pressed */
     1453                IOHIDElementGetUsage(pElementRef) == kHIDUsage_KeypadNumLock)      /* ... or NumLock key has been pressed */
     1454            {
     1455                Log2(("A modifier key has been pressed\n"));
     1456                g_LastTouchedState = (VBoxKbdState_t *)pData;
     1457            }
     1458
     1459}
     1460
     1461/** Carbon key press callback. Triggered after IOKit callback. We update keyboard (catched in darwinHidInputCallback()) internal state here. */
    14191462static CGEventRef darwinCarbonGlobalKeyPressCallback(CGEventTapProxy unused, CGEventType type, CGEventRef pEventRef, void *unused1)
    14201463{
     
    14371480        if (g_LastTouchedState)
    14381481        {
    1439             g_LastTouchedState->fCapsLockOn = fCaps;
    1440             g_LastTouchedState->fNumLockOn  = fNum;
     1482            g_LastTouchedState->LED.fCapsLockOn = fCaps;
     1483            g_LastTouchedState->LED.fNumLockOn  = fNum;
    14411484
    14421485            /* Forget device */
     
    14471490    return pEventRef;
    14481491}
    1449 #undef VBOX_BOOL_TO_STR_STATE
     1492
     1493/** This callback is called when user physically removes HID device. We remove device from cache here. */
     1494static void darwinHidRemovalCallback(void *pData, IOReturn unused, void *unused1)
     1495{
     1496    (void)unused;
     1497    (void)unused1;
     1498
     1499    VBoxKbdState_t *pKbd = (VBoxKbdState_t *)pData;
     1500
     1501    AssertReturnVoid(pKbd);
     1502    AssertReturnVoid(pKbd->pStorageArray);
     1503
     1504    Log2(("Forget KBD %d\n", (int)pKbd->idxPosition));
     1505    CFArrayRemoveValueAtIndex(pKbd->pStorageArray, pKbd->idxPosition);
     1506    free(pKbd);
     1507}
     1508
     1509/* Check if we already cached given device */
     1510static bool darwinIsDeviceInCache(VBoxHidsState_t *pState, IOHIDDeviceRef pDevice)
     1511{
     1512    AssertReturn(pState, false);
     1513    AssertReturn(pState->pDeviceCollection, false);
     1514
     1515    for (CFIndex i = 0; i < CFArrayGetCount(pState->pDeviceCollection); i++)
     1516    {
     1517        VBoxKbdState_t *pKbd = (VBoxKbdState_t *)CFArrayGetValueAtIndex(pState->pDeviceCollection, i);
     1518        if (pKbd && pKbd->pDevice == pDevice)
     1519            return true;
     1520    }
     1521
     1522    return false;
     1523}
     1524
     1525/** Add device to cache. */
     1526static void darwinHidAddDevice(VBoxHidsState_t *pHidState, IOHIDDeviceRef pDevice, bool fApplyLedState)
     1527{
     1528    int rc;
     1529
     1530    if (!darwinIsDeviceInCache(pHidState, pDevice))
     1531    {
     1532        if (IOHIDDeviceConformsTo(pDevice, kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard)
     1533         && darwinHidDeviceSupported(pDevice))
     1534        {
     1535            VBoxKbdState_t *pKbd = (VBoxKbdState_t *)malloc(sizeof(VBoxKbdState_t));
     1536            if (pKbd)
     1537            {
     1538                pKbd->pDevice = pDevice;
     1539                pKbd->pStorageArray = pHidState->pDeviceCollection;
     1540                pKbd->idxPosition = CFArrayGetCount(pHidState->pDeviceCollection);
     1541
     1542                CFDictionaryRef elementMatchingDict = darwinQueryLedElementMatchingDictionary();
     1543                if (elementMatchingDict)
     1544                {
     1545                    rc = darwinGetDeviceLedsState(pKbd->pDevice,
     1546                                                  elementMatchingDict,
     1547                                                  &pKbd->LED.fNumLockOn,
     1548                                                  &pKbd->LED.fCapsLockOn,
     1549                                                  &pKbd->LED.fScrollLockOn);
     1550
     1551                    /* This should never happen, but if happened -- mark all the leds of current
     1552                     * device as turned OFF. */
     1553                    if (rc != 0)
     1554                    {
     1555                        Log2(("Unable to get leds state for device %d. Mark leds as turned off\n", (int)(pKbd->idxPosition)));
     1556                        pKbd->LED.fNumLockOn    =
     1557                        pKbd->LED.fCapsLockOn   =
     1558                        pKbd->LED.fScrollLockOn = false;
     1559                    }
     1560
     1561                    /* Register per-device removal callback */
     1562                    IOHIDDeviceRegisterRemovalCallback(pKbd->pDevice, darwinHidRemovalCallback, (void *)pKbd);
     1563
     1564                    /* Register per-device input callback */
     1565                    IOHIDDeviceRegisterInputValueCallback(pKbd->pDevice, darwinHidInputCallback, (void *)pKbd);
     1566                    IOHIDDeviceScheduleWithRunLoop(pKbd->pDevice, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
     1567
     1568                    CFArrayAppendValue(pHidState->pDeviceCollection, (void *)pKbd);
     1569
     1570                    Log2(("Saved LEDs for KBD %d (%p): fNumLockOn=%s, fCapsLockOn=%s, fScrollLockOn=%s\n",
     1571                         (int)pKbd->idxPosition, pKbd, VBOX_BOOL_TO_STR_STATE(pKbd->LED.fNumLockOn), VBOX_BOOL_TO_STR_STATE(pKbd->LED.fCapsLockOn),
     1572                         VBOX_BOOL_TO_STR_STATE(pKbd->LED.fScrollLockOn)));
     1573                    if (fApplyLedState)
     1574                    {
     1575                        rc = darwinSetDeviceLedsState(pKbd->pDevice, elementMatchingDict, pHidState->guestState.fNumLockOn,
     1576                                                      pHidState->guestState.fCapsLockOn, pHidState->guestState.fScrollLockOn);
     1577                        if (rc != 0)
     1578                            Log2(("Unable to apply guest state to newly attached device\n"));
     1579                    }
     1580
     1581                    CFRelease(elementMatchingDict);
     1582                    return;
     1583                }
     1584
     1585                free(pKbd);
     1586            }
     1587        }
     1588    }
     1589}
     1590
     1591/** This callback is called when new HID device discovered by IOHIDManager. We add devices to cache here and only here! */
     1592static void darwinHidMatchingCallback(void *pData, IOReturn unused, void *unused1, IOHIDDeviceRef pDevice)
     1593{
     1594    (void)unused;
     1595    (void)unused1;
     1596
     1597    VBoxHidsState_t *pHidState = (VBoxHidsState_t *)pData;
     1598
     1599    AssertReturnVoid(pHidState);
     1600    AssertReturnVoid(pHidState->pDeviceCollection);
     1601    AssertReturnVoid(pDevice);
     1602
     1603    darwinHidAddDevice(pHidState, pDevice, true);
     1604}
    14501605
    14511606/** Register Carbon key press callback. */
    1452 static int darwinAddCarbonGlobalKeyPressHandler(VBoxHidsState_t *pState)
     1607static int darwinAddCarbonGlobalKeyPressHandler(VBoxHidsState_t *pHidState)
    14531608{
    14541609    CFMachPortRef pTapRef;
     
    14671622            CGEventTapEnable(pTapRef, true);
    14681623
    1469             pState->pTapRef = pTapRef;
    1470             pState->pLoopSourceRef = pLoopSourceRef;
     1624            pHidState->pTapRef = pTapRef;
     1625            pHidState->pLoopSourceRef = pLoopSourceRef;
    14711626
    14721627            return 0;
     
    14841639
    14851640/** Remove Carbon key press callback. */
    1486 static void darwinRemoveCarbonGlobalKeyPressHandler(VBoxHidsState_t *pState)
    1487 {
    1488     AssertReturnVoid(pState);
    1489     AssertReturnVoid(pState->pTapRef);
    1490     AssertReturnVoid(pState->pLoopSourceRef);
     1641static void darwinRemoveCarbonGlobalKeyPressHandler(VBoxHidsState_t *pHidState)
     1642{
     1643    AssertReturnVoid(pHidState);
     1644    AssertReturnVoid(pHidState->pTapRef);
     1645    AssertReturnVoid(pHidState->pLoopSourceRef);
    14911646
    14921647    g_LastTouchedState = NULL;
    14931648
    1494     CGEventTapEnable(pState->pTapRef, false);
    1495     CFRunLoopRemoveSource(CFRunLoopGetCurrent(), pState->pLoopSourceRef, kCFRunLoopDefaultMode);
    1496     CFRelease(pState->pLoopSourceRef);
    1497     CFRelease(pState->pTapRef);
    1498 }
    1499 
    1500 /** Some keyboard devices might freeze after LEDs manipulation. We filter out such devices here.
    1501  * In the list below, devices which verified to be stable against LEDs manipulation.
    1502  * If you want to add new device, add it here. Currently, we only filter devices by Vendor ID.
    1503  * In future it might make sense to take Product ID into account as well. */
    1504 static bool darwinHidDeviceSupported(IOHIDDeviceRef pHidDeviceRef)
    1505 {
    1506     bool      fSupported = false;
    1507     CFTypeRef pNumberRef;
    1508     uint32_t  vendorId = 0;
    1509 
    1510     if (pHidDeviceRef)
    1511     {
    1512         pNumberRef = IOHIDDeviceGetProperty(pHidDeviceRef, CFSTR(kIOHIDVendorIDKey));
    1513         if (pNumberRef)
    1514         {
    1515             if (CFGetTypeID(pNumberRef) == CFNumberGetTypeID())
    1516             {
    1517                 if (CFNumberGetValue((CFNumberRef)pNumberRef, kCFNumberSInt32Type, &vendorId))
    1518                 {
    1519                     switch (vendorId)
    1520                     {
    1521                         case kIOUSBVendorIDAppleComputer:   /** Apple devices always in the list */
    1522                         case 0x03F0:                        /** Hewlett-Packard (verified with model KU-0316) */
    1523                         case 0x0430:                        /** Sun keyboards */
    1524                             fSupported = true;
    1525                             break;
    1526                     }
    1527 
    1528                     Log2(("HID device Vendor ID 0x%X %s in the list of supported devices.\n", vendorId, (fSupported ? "is" : "is not")));
    1529                 }
    1530             }
    1531 
    1532             //CFRelease(pNumberRef);
    1533         }
    1534     }
    1535 
    1536     return fSupported;
    1537 }
    1538 
    1539 #endif // !VBOX_WITH_KBD_LEDS_SYNC
     1649    CGEventTapEnable(pHidState->pTapRef, false);
     1650    CFRunLoopRemoveSource(CFRunLoopGetCurrent(), pHidState->pLoopSourceRef, kCFRunLoopDefaultMode);
     1651    CFRelease(pHidState->pLoopSourceRef);
     1652    CFRelease(pHidState->pTapRef);
     1653}
     1654#endif /* !VBOX_WITH_KBD_LEDS_SYNC */
    15401655
    15411656/** Save the states of leds for all HID devices attached to the system and return it. */
     
    15441659#ifdef VBOX_WITH_KBD_LEDS_SYNC
    15451660    IOReturn         rc;
    1546     VBoxHidsState_t *hidsState;
    1547 
    1548     hidsState = (VBoxHidsState_t *)malloc(sizeof(VBoxHidsState_t));
    1549     if (hidsState)
    1550     {
    1551         hidsState->hidManagerRef = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
    1552         if (hidsState->hidManagerRef)
    1553         {
    1554             CFDictionaryRef deviceMatchingDictRef = darwinGetLedDeviceMatchingDictionary();
    1555             if (deviceMatchingDictRef)
     1661    VBoxHidsState_t *pHidState;
     1662
     1663    pHidState = (VBoxHidsState_t *)malloc(sizeof(VBoxHidsState_t));
     1664    AssertReturn(pHidState, NULL);
     1665
     1666    pHidState->hidManagerRef = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
     1667    if (pHidState->hidManagerRef)
     1668    {
     1669        CFDictionaryRef deviceMatchingDictRef = darwinQueryLedDeviceMatchingDictionary();
     1670        if (deviceMatchingDictRef)
     1671        {
     1672            IOHIDManagerScheduleWithRunLoop(pHidState->hidManagerRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
     1673            IOHIDManagerSetDeviceMatching(pHidState->hidManagerRef, deviceMatchingDictRef);
     1674
     1675            rc = IOHIDManagerOpen(pHidState->hidManagerRef, kIOHIDOptionsTypeNone);
     1676            if (rc == kIOReturnSuccess)
    15561677            {
    1557                 IOHIDManagerScheduleWithRunLoop(hidsState->hidManagerRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    1558                 IOHIDManagerSetDeviceMatching(hidsState->hidManagerRef, deviceMatchingDictRef);
    1559 
    1560                 rc = IOHIDManagerOpen(hidsState->hidManagerRef, kIOHIDOptionsTypeNone);
    1561                 if (rc == kIOReturnSuccess)
     1678                pHidState->pDeviceCollection = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
     1679                if (pHidState->pDeviceCollection)
    15621680                {
    1563                     CFSetRef hidDevicesSetRef;
    1564 
    1565                     hidDevicesSetRef = IOHIDManagerCopyDevices(hidsState->hidManagerRef);
    1566                     if (hidDevicesSetRef)
     1681                    if (darwinAddCarbonGlobalKeyPressHandler(pHidState) == 0)
    15671682                    {
    1568                         /* Get all the available devices and cycle through them. */
    1569                         hidsState->cDevices = CFSetGetCount(hidDevicesSetRef);
    1570                         hidsState->hidDevicesCollection = (IOHIDDeviceRef *)malloc((size_t)hidsState->cDevices * sizeof(IOHIDDeviceRef));
    1571                         if (hidsState->hidDevicesCollection)
     1683                        /* Populate cache with HID devices */
     1684                        CFSetRef pDevicesSet = IOHIDManagerCopyDevices(pHidState->hidManagerRef);
     1685                        if (pDevicesSet)
    15721686                        {
    1573                             hidsState->hidLedsCollection = (VBoxKbdState_t *)malloc((size_t)hidsState->cDevices * sizeof(VBoxKbdState_t));
    1574                             if (hidsState->hidLedsCollection)
     1687                            CFIndex cDevices = CFSetGetCount(pDevicesSet);
     1688
     1689                            IOHIDDeviceRef *ppDevices = (IOHIDDeviceRef *)malloc((size_t)cDevices * sizeof(IOHIDDeviceRef));
     1690                            if (ppDevices)
    15751691                            {
    1576                                 CFSetGetValues(hidDevicesSetRef, (const void **)hidsState->hidDevicesCollection);
    1577 
    1578                                 CFDictionaryRef elementMatchingDict = darwinGetLedElementMatchingDictionary();
    1579                                 if (elementMatchingDict)
    1580                                 {
    1581                                     for (CFIndex i = 0; i < hidsState->cDevices; i++)
    1582                                     {
    1583                                         if (IOHIDDeviceConformsTo(hidsState->hidDevicesCollection[i], kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard)
    1584                                          && darwinHidDeviceSupported(hidsState->hidDevicesCollection[i]))
    1585                                         {
    1586                                             rc = darwinGetDeviceLedsState(hidsState->hidDevicesCollection[i],
    1587                                                                           elementMatchingDict,
    1588                                                                           &hidsState->hidLedsCollection[i].fNumLockOn,
    1589                                                                           &hidsState->hidLedsCollection[i].fCapsLockOn,
    1590                                                                           &hidsState->hidLedsCollection[i].fScrollLockOn);
    1591                                             /* This should never happen, but if happened -- mark all the leds of current
    1592                                              * device as turned OFF. */
    1593                                             if (rc != 0)
    1594                                             {
    1595                                                 Log2(("Unable to get leds state for device %d. Mark leds as turned off\n", (int)i));
    1596                                                 hidsState->hidLedsCollection[i].fNumLockOn    =
    1597                                                 hidsState->hidLedsCollection[i].fCapsLockOn   =
    1598                                                 hidsState->hidLedsCollection[i].fScrollLockOn = false;
    1599                                             }
    1600 
    1601                                             /* Mark a device as currently attached. If device will be removed (physically)
    1602                                              * before current state is applied (by DarwinHidDevicesApplyAndReleaseLedsState()), we mark
    1603                                              * it as detached one in a removal callback. We cannot access device which was detached
    1604                                              * because IOKit released the resources and this will trigger a SEGFAULT. */
    1605                                             hidsState->hidLedsCollection[i].fAttached = true;
    1606 
    1607                                             /* Register per-device removal callback */
    1608                                             IOHIDDeviceRegisterRemovalCallback(hidsState->hidDevicesCollection[i], darwinHidRemovalCallback, (void *)&hidsState->hidLedsCollection[i]);
    1609 
    1610                                             /* Register per-device input callback */
    1611                                             IOHIDDeviceRegisterInputValueCallback(hidsState->hidDevicesCollection[i], darwinHidInputCallback, (void *)&hidsState->hidLedsCollection[i]);
    1612                                             IOHIDDeviceScheduleWithRunLoop(hidsState->hidDevicesCollection[i], CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    1613                                         }
    1614                                     }
    1615 
    1616                                     CFRelease(elementMatchingDict);
    1617 
    1618                                     if (darwinAddCarbonGlobalKeyPressHandler(hidsState) == 0)
    1619                                     {
    1620                                         CFRelease(hidDevicesSetRef);
    1621                                         CFRelease(deviceMatchingDictRef);
    1622                                         return hidsState;
    1623                                     }
    1624                                 }
    1625 
    1626                                 free(hidsState->hidLedsCollection);
     1692                                CFSetGetValues(pDevicesSet, (const void **)ppDevices);
     1693                                for (CFIndex i= 0; i < cDevices; i++)
     1694                                    darwinHidAddDevice(pHidState, (IOHIDDeviceRef)ppDevices[i], false);
     1695
     1696                                free(ppDevices);
    16271697                            }
    16281698
    1629                             free(hidsState->hidDevicesCollection);
     1699                            CFRelease(pDevicesSet);
    16301700                        }
    16311701
    1632                         CFRelease(hidDevicesSetRef);
     1702                        IOHIDManagerRegisterDeviceMatchingCallback(pHidState->hidManagerRef, darwinHidMatchingCallback, (void *)pHidState);
     1703
     1704                        CFRelease(deviceMatchingDictRef);
     1705
     1706                        /* This states should be set on broadcast */
     1707                        pHidState->guestState.fNumLockOn =
     1708                        pHidState->guestState.fCapsLockOn =
     1709                        pHidState->guestState.fScrollLockOn = false;
     1710
     1711                        return pHidState;
    16331712                    }
    1634 
    1635                     rc = IOHIDManagerClose(hidsState->hidManagerRef, 0);
    1636                     if (rc != kIOReturnSuccess)
    1637                         Log2(("Warning! Something went wrong in attempt to close HID device manager!\n"));
    16381713                }
    16391714
    1640                 CFRelease(deviceMatchingDictRef);
     1715                rc = IOHIDManagerClose(pHidState->hidManagerRef, 0);
     1716                if (rc != kIOReturnSuccess)
     1717                    Log2(("Warning! Something went wrong in attempt to close HID device manager!\n"));
    16411718            }
    16421719
    1643             CFRelease(hidsState->hidManagerRef);
    1644         }
    1645 
    1646         free(hidsState);
    1647     }
     1720            CFRelease(deviceMatchingDictRef);
     1721        }
     1722
     1723        CFRelease(pHidState->hidManagerRef);
     1724    }
     1725
     1726    free(pHidState);
    16481727
    16491728    return NULL;
    1650 #else // !VBOX_WITH_KBD_LEDS_SYNC
     1729#else /* !VBOX_WITH_KBD_LEDS_SYNC */
    16511730    return NULL;
    16521731#endif
     
    16631742{
    16641743#ifdef VBOX_WITH_KBD_LEDS_SYNC
    1665     VBoxHidsState_t *hidsState = (VBoxHidsState_t *)pState;
    1666 
    1667     CFIndex     i;
    1668     IOReturn    rc, rc2 = 0;
    1669 
    1670     if (hidsState)
    1671     {
    1672         /* Need to unregister Carbon stuff first */
    1673         darwinRemoveCarbonGlobalKeyPressHandler(hidsState);
    1674 
    1675         CFDictionaryRef elementMatchingDict = darwinGetLedElementMatchingDictionary();
    1676         if (elementMatchingDict)
    1677         {
    1678             /* Restore LEDs */
    1679             for (i = 0; i < hidsState->cDevices; i++)
     1744    VBoxHidsState_t *pHidState = (VBoxHidsState_t *)pState;
     1745    IOReturn         rc, rc2 = 0;
     1746
     1747    AssertReturn(pHidState, kIOReturnError);
     1748
     1749    /* Need to unregister Carbon stuff first */
     1750    darwinRemoveCarbonGlobalKeyPressHandler(pHidState);
     1751
     1752    CFDictionaryRef elementMatchingDict = darwinQueryLedElementMatchingDictionary();
     1753    if (elementMatchingDict)
     1754    {
     1755        /* Restore LEDs */
     1756        for (CFIndex i = 0; i < CFArrayGetCount(pHidState->pDeviceCollection); i++)
     1757        {
     1758            /* Cycle through supported devices only. */
     1759            VBoxKbdState_t *pKbd;
     1760            pKbd = (VBoxKbdState_t *)CFArrayGetValueAtIndex(pHidState->pDeviceCollection, i);
     1761
     1762            if (pKbd)
    16801763            {
    1681                 /* Cycle through supported devices only. */
    1682                 if (hidsState->hidLedsCollection[i].fAttached
    1683                  && IOHIDDeviceConformsTo(hidsState->hidDevicesCollection[i], kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard)
    1684                  && darwinHidDeviceSupported(hidsState->hidDevicesCollection[i]))
     1764                rc = darwinSetDeviceLedsState(pKbd->pDevice,
     1765                                              elementMatchingDict,
     1766                                              pKbd->LED.fNumLockOn,
     1767                                              pKbd->LED.fCapsLockOn,
     1768                                              pKbd->LED.fScrollLockOn);
     1769                if (rc != 0)
    16851770                {
    1686                     rc = darwinSetDeviceLedsState(hidsState->hidDevicesCollection[i],
    1687                                                   elementMatchingDict,
    1688                                                   hidsState->hidLedsCollection[i].fNumLockOn,
    1689                                                   hidsState->hidLedsCollection[i].fCapsLockOn,
    1690                                                   hidsState->hidLedsCollection[i].fScrollLockOn);
    1691                     if (rc != 0)
    1692                     {
    1693                         Log2(("Unable to restore led states for device (%d)!\n", (int)i));
    1694                         rc2 = kIOReturnError;
    1695                     }
    1696 
    1697                     IOHIDDeviceUnscheduleFromRunLoop(hidsState->hidDevicesCollection[i], CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    1698                     IOHIDDeviceRegisterInputValueCallback(hidsState->hidDevicesCollection[i], NULL, NULL);
     1771                    Log2(("Unable to restore led states for device (%d)!\n", (int)i));
     1772                    rc2 = kIOReturnError;
    16991773                }
     1774
     1775                IOHIDDeviceUnscheduleFromRunLoop(pKbd->pDevice, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
     1776                IOHIDDeviceRegisterInputValueCallback(pKbd->pDevice, NULL, NULL);
     1777
     1778                Log2(("Restored LEDs for KBD %d (%p): fNumLockOn=%s, fCapsLockOn=%s, fScrollLockOn=%s\n",
     1779                     (int)i, pKbd, VBOX_BOOL_TO_STR_STATE(pKbd->LED.fNumLockOn), VBOX_BOOL_TO_STR_STATE(pKbd->LED.fCapsLockOn),
     1780                     VBOX_BOOL_TO_STR_STATE(pKbd->LED.fScrollLockOn)));
     1781
     1782                free(pKbd);
    17001783            }
    1701 
    1702             CFRelease(elementMatchingDict);
    1703         }
    1704 
    1705         /* Free resources */
    1706 
    1707         free(hidsState->hidLedsCollection);
    1708         free(hidsState->hidDevicesCollection);
    1709 
    1710         rc = IOHIDManagerClose(hidsState->hidManagerRef, 0);
    1711         if (rc != kIOReturnSuccess)
    1712             Log2(("Warning! Something went wrong in attempt to close HID device manager!\n"));
    1713 
    1714         IOHIDManagerUnscheduleFromRunLoop(hidsState->hidManagerRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    1715 
    1716         CFRelease(hidsState->hidManagerRef);
    1717 
    1718         free(hidsState);
    1719     }
     1784        }
     1785
     1786        CFRelease(elementMatchingDict);
     1787    }
     1788
     1789    /* Free resources */
     1790    CFRelease(pHidState->pDeviceCollection);
     1791
     1792    rc = IOHIDManagerClose(pHidState->hidManagerRef, 0);
     1793    if (rc != kIOReturnSuccess)
     1794    {
     1795        Log2(("Warning! Something went wrong in attempt to close HID device manager!\n"));
     1796        rc2 = kIOReturnError;
     1797    }
     1798
     1799    IOHIDManagerUnscheduleFromRunLoop(pHidState->hidManagerRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
     1800
     1801    CFRelease(pHidState->hidManagerRef);
     1802
     1803    free(pHidState);
    17201804
    17211805    return rc2;
     
    17321816 * keyboard devices attached to the system.
    17331817 *
     1818 * @param pState            Pointer to saved LEDs state
    17341819 * @param fNumLockOn        Turn on NumLock led if TRUE, turn off otherwise
    17351820 * @param fCapsLockOn       Turn on CapsLock led if TRUE, turn off otherwise
    17361821 * @param fScrollLockOn     Turn on ScrollLock led if TRUE, turn off otherwise
    17371822 */
    1738 void DarwinHidDevicesBroadcastLeds(bool fNumLockOn, bool fCapsLockOn, bool fScrollLockOn)
     1823void DarwinHidDevicesBroadcastLeds(void *pState, bool fNumLockOn, bool fCapsLockOn, bool fScrollLockOn)
    17391824{
    17401825/* Temporary disabled */
    17411826#ifdef VBOX_WITH_KBD_LEDS_SYNC
    1742     IOReturn        rc;
    1743     IOHIDManagerRef hidManagerRef;
    1744 
    1745     hidManagerRef = IOHIDManagerCreate(kCFAllocatorDefault, 0);
    1746     if (hidManagerRef)
    1747     {
    1748         CFDictionaryRef deviceMatchingDictRef = darwinGetLedDeviceMatchingDictionary();
    1749         if (deviceMatchingDictRef)
    1750         {
    1751             IOHIDManagerScheduleWithRunLoop(hidManagerRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    1752             IOHIDManagerSetDeviceMatching(hidManagerRef, deviceMatchingDictRef);
    1753 
    1754             rc = IOHIDManagerOpen(hidManagerRef, kIOHIDOptionsTypeNone);
    1755             if (rc == kIOReturnSuccess)
     1827    VBoxHidsState_t *pHidState = (VBoxHidsState_t *)pState;
     1828    IOReturn         rc;
     1829
     1830    AssertReturnVoid(pHidState);
     1831    AssertReturnVoid(pHidState->pDeviceCollection);
     1832
     1833    CFDictionaryRef elementMatchingDict = darwinQueryLedElementMatchingDictionary();
     1834    if (elementMatchingDict)
     1835    {
     1836        Log2(("Start LEDs broadcast: fNumLockOn=%s, fCapsLockOn=%s, fScrollLockOn=%s\n",
     1837            VBOX_BOOL_TO_STR_STATE(fNumLockOn), VBOX_BOOL_TO_STR_STATE(fCapsLockOn), VBOX_BOOL_TO_STR_STATE(fScrollLockOn)));
     1838
     1839        for (CFIndex i = 0; i < CFArrayGetCount(pHidState->pDeviceCollection); i++)
     1840        {
     1841            /* Cycle through supported devices only. */
     1842            VBoxKbdState_t *pKbd;
     1843            pKbd = (VBoxKbdState_t *)CFArrayGetValueAtIndex(pHidState->pDeviceCollection, i);
     1844
     1845            if (pKbd)
    17561846            {
    1757                 CFSetRef hidDevicesSetRef;
    1758 
    1759                 hidDevicesSetRef = IOHIDManagerCopyDevices(hidManagerRef);
    1760                 if (hidDevicesSetRef)
    1761                 {
    1762                     /* Get all the available devices and cycle through them. */
    1763                     CFIndex cDevices = CFSetGetCount(hidDevicesSetRef);
    1764                     IOHIDDeviceRef *hidDevicesCollection = (IOHIDDeviceRef *)malloc((size_t)cDevices * sizeof(IOHIDDeviceRef));
    1765                     if (hidDevicesCollection)
    1766                     {
    1767                         CFSetGetValues(hidDevicesSetRef, (const void **)hidDevicesCollection);
    1768 
    1769                         CFDictionaryRef elementMatchingDict = darwinGetLedElementMatchingDictionary();
    1770                         if (elementMatchingDict)
    1771                         {
    1772                             Log2(("Start LEDs broadcast\n"));
    1773 
    1774                             for (CFIndex i = 0; i < cDevices; i++)
    1775                             {
    1776                                 if (IOHIDDeviceConformsTo(hidDevicesCollection[i], kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard)
    1777                                  && darwinHidDeviceSupported(hidDevicesCollection[i]))
    1778                                 {
    1779                                     rc = darwinSetDeviceLedsState(hidDevicesCollection[i], elementMatchingDict,
    1780                                                                   fNumLockOn, fCapsLockOn, fScrollLockOn);
    1781                                     if (rc != 0)
    1782                                         Log2(("Unable to broadcast LEDs state to device (%d)\n", (int)i));
    1783                                 }
    1784                             }
    1785 
    1786                             Log2(("LEDs broadcast completed\n"));
    1787                             CFRelease(elementMatchingDict);
    1788                         }
    1789 
    1790                         free(hidDevicesCollection);
    1791                     }
    1792 
    1793                     CFRelease(hidDevicesSetRef);
    1794                 }
    1795 
    1796                 rc = IOHIDManagerClose(hidManagerRef, 0);
    1797                 if (rc != kIOReturnSuccess)
    1798                     Log2(("Warning! Something went wrong in attempt to close HID device manager!\n"));
     1847                rc = darwinSetDeviceLedsState(pKbd->pDevice,
     1848                                              elementMatchingDict,
     1849                                              fNumLockOn,
     1850                                              fCapsLockOn,
     1851                                              fScrollLockOn);
     1852                if (rc != 0)
     1853                    Log2(("Unable to restore led states for device (%d)!\n", (int)i));
    17991854            }
    1800 
    1801             IOHIDManagerUnscheduleFromRunLoop(hidManagerRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    1802 
    1803             CFRelease(deviceMatchingDictRef);
    1804         }
    1805 
    1806         CFRelease(hidManagerRef);
    1807     }
     1855        }
     1856
     1857        Log2(("LEDs broadcast completed\n"));
     1858
     1859        CFRelease(elementMatchingDict);
     1860    }
     1861
     1862    /* Dynamically attached device will use these states */
     1863    pHidState->guestState.fNumLockOn    = fNumLockOn;
     1864    pHidState->guestState.fCapsLockOn   = fCapsLockOn;
     1865    pHidState->guestState.fScrollLockOn = fScrollLockOn;
     1866
    18081867#else /* !VBOX_WITH_KBD_LEDS_SYNC */
    18091868    (void)fNumLockOn;
  • trunk/src/VBox/Frontends/VirtualBox/src/platform/darwin/DarwinKeyboard.h

    r48517 r49048  
    4949void   * DarwinHidDevicesKeepLedsState(void);
    5050int      DarwinHidDevicesApplyAndReleaseLedsState(void *pState);
    51 void     DarwinHidDevicesBroadcastLeds(bool fNumLockOn, bool fCapsLockOn, bool fScrollLockOn);
     51void     DarwinHidDevicesBroadcastLeds(void *pState, bool fNumLockOn, bool fCapsLockOn, bool fScrollLockOn);
    5252
    5353RT_C_DECLS_END
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp

    r49025 r49048  
    490490    LogRelFlow(("UIMachineLogic::sltKeyboardLedsChanged: Updating host LED lock states (NOT IMPLEMENTED).\n"));
    491491#ifdef Q_WS_MAC
    492     DarwinHidDevicesBroadcastLeds(uisession()->isNumLock(), uisession()->isCapsLock(), uisession()->isScrollLock());
     492    DarwinHidDevicesBroadcastLeds(m_pHostLedsState, uisession()->isNumLock(), uisession()->isCapsLock(), uisession()->isScrollLock());
    493493#endif
    494494}
     
    22102210    if (m_pHostLedsState == NULL)
    22112211        m_pHostLedsState = DarwinHidDevicesKeepLedsState();
    2212     DarwinHidDevicesBroadcastLeds(uisession()->isNumLock(), uisession()->isCapsLock(), uisession()->isScrollLock());
     2212    DarwinHidDevicesBroadcastLeds(m_pHostLedsState, uisession()->isNumLock(), uisession()->isCapsLock(), uisession()->isScrollLock());
    22132213#endif /* Q_WS_MAC */
    22142214}
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