Changeset 49048 in vbox for trunk/src/VBox/Frontends
- Timestamp:
- Oct 11, 2013 7:45:09 AM (11 years ago)
- 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 22 22 *******************************************************************************/ 23 23 #define LOG_GROUP LOG_GROUP_GUI 24 24 25 #define VBOX_WITH_KBD_LEDS_SYNC 26 //#define VBOX_WITHOUT_KBD_LEDS_SYNC_FILTERING 25 27 26 28 #include "DarwinKeyboard.h" … … 32 34 #ifdef DEBUG_PRINTF 33 35 # include <iprt/stream.h> 36 #endif 37 38 #ifdef VBOX_WITH_KBD_LEDS_SYNC 39 # include <iprt/err.h> 40 # include <iprt/semaphore.h> 34 41 #endif 35 42 … … 291 298 292 299 #ifdef VBOX_WITH_KBD_LEDS_SYNC 300 301 #define VBOX_BOOL_TO_STR_STATE(x) (x) ? "ON" : "OFF" 293 302 /* HID LEDs synchronization data: LED states. */ 303 typedef 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. */ 294 310 typedef 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) */ 299 315 } VBoxKbdState_t; 300 316 301 317 /* HID LEDs synchronization data: IOKit specific data. */ 302 318 typedef 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 */ 307 324 CFMachPortRef pTapRef; 308 325 CFRunLoopSourceRef pLoopSourceRef; … … 311 328 /* A *sync* between IOKit and Carbon callbacks. */ 312 329 static VBoxKbdState_t *g_LastTouchedState; 313 #endif / / !VBOX_WITH_KBD_LEDS_SYNC330 #endif /* !VBOX_WITH_KBD_LEDS_SYNC */ 314 331 315 332 /******************************************************************************* … … 1159 1176 #ifdef VBOX_WITH_KBD_LEDS_SYNC 1160 1177 /** Prepare dictionary that will be used to match HID LED device(s) while discovering. */ 1161 static CFDictionaryRef darwin GetLedDeviceMatchingDictionary()1178 static CFDictionaryRef darwinQueryLedDeviceMatchingDictionary() 1162 1179 { 1163 1180 CFDictionaryRef deviceMatchingDictRef; … … 1204 1221 1205 1222 /** Prepare dictionary that will be used to match HID LED device element(s) while discovering. */ 1206 static CFDictionaryRef darwin GetLedElementMatchingDictionary()1223 static CFDictionaryRef darwinQueryLedElementMatchingDictionary() 1207 1224 { 1208 1225 CFDictionaryRef elementMatchingDictRef; … … 1380 1397 } 1381 1398 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. */ 1403 static 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. */ 1440 static void darwinHidInputCallback(void *pData, IOReturn unused, void *unused1, IOHIDValueRef pValueRef) 1383 1441 { 1384 1442 (void)unused; 1385 1443 (void)unused1; 1386 1444 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. */ 1419 1462 static CGEventRef darwinCarbonGlobalKeyPressCallback(CGEventTapProxy unused, CGEventType type, CGEventRef pEventRef, void *unused1) 1420 1463 { … … 1437 1480 if (g_LastTouchedState) 1438 1481 { 1439 g_LastTouchedState-> fCapsLockOn = fCaps;1440 g_LastTouchedState-> fNumLockOn = fNum;1482 g_LastTouchedState->LED.fCapsLockOn = fCaps; 1483 g_LastTouchedState->LED.fNumLockOn = fNum; 1441 1484 1442 1485 /* Forget device */ … … 1447 1490 return pEventRef; 1448 1491 } 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. */ 1494 static 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 */ 1510 static 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. */ 1526 static 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! */ 1592 static 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 } 1450 1605 1451 1606 /** Register Carbon key press callback. */ 1452 static int darwinAddCarbonGlobalKeyPressHandler(VBoxHidsState_t *p State)1607 static int darwinAddCarbonGlobalKeyPressHandler(VBoxHidsState_t *pHidState) 1453 1608 { 1454 1609 CFMachPortRef pTapRef; … … 1467 1622 CGEventTapEnable(pTapRef, true); 1468 1623 1469 p State->pTapRef = pTapRef;1470 p State->pLoopSourceRef = pLoopSourceRef;1624 pHidState->pTapRef = pTapRef; 1625 pHidState->pLoopSourceRef = pLoopSourceRef; 1471 1626 1472 1627 return 0; … … 1484 1639 1485 1640 /** Remove Carbon key press callback. */ 1486 static void darwinRemoveCarbonGlobalKeyPressHandler(VBoxHidsState_t *p State)1487 { 1488 AssertReturnVoid(p State);1489 AssertReturnVoid(p State->pTapRef);1490 AssertReturnVoid(p State->pLoopSourceRef);1641 static void darwinRemoveCarbonGlobalKeyPressHandler(VBoxHidsState_t *pHidState) 1642 { 1643 AssertReturnVoid(pHidState); 1644 AssertReturnVoid(pHidState->pTapRef); 1645 AssertReturnVoid(pHidState->pLoopSourceRef); 1491 1646 1492 1647 g_LastTouchedState = NULL; 1493 1648 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 */ 1540 1655 1541 1656 /** Save the states of leds for all HID devices attached to the system and return it. */ … … 1544 1659 #ifdef VBOX_WITH_KBD_LEDS_SYNC 1545 1660 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) 1556 1677 { 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) 1562 1680 { 1563 CFSetRef hidDevicesSetRef; 1564 1565 hidDevicesSetRef = IOHIDManagerCopyDevices(hidsState->hidManagerRef); 1566 if (hidDevicesSetRef) 1681 if (darwinAddCarbonGlobalKeyPressHandler(pHidState) == 0) 1567 1682 { 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) 1572 1686 { 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) 1575 1691 { 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); 1627 1697 } 1628 1698 1629 free(hidsState->hidDevicesCollection);1699 CFRelease(pDevicesSet); 1630 1700 } 1631 1701 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; 1633 1712 } 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"));1638 1713 } 1639 1714 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")); 1641 1718 } 1642 1719 1643 CFRelease(hidsState->hidManagerRef); 1644 } 1645 1646 free(hidsState); 1647 } 1720 CFRelease(deviceMatchingDictRef); 1721 } 1722 1723 CFRelease(pHidState->hidManagerRef); 1724 } 1725 1726 free(pHidState); 1648 1727 1649 1728 return NULL; 1650 #else / / !VBOX_WITH_KBD_LEDS_SYNC1729 #else /* !VBOX_WITH_KBD_LEDS_SYNC */ 1651 1730 return NULL; 1652 1731 #endif … … 1663 1742 { 1664 1743 #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) 1680 1763 { 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) 1685 1770 { 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; 1699 1773 } 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); 1700 1783 } 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); 1720 1804 1721 1805 return rc2; … … 1732 1816 * keyboard devices attached to the system. 1733 1817 * 1818 * @param pState Pointer to saved LEDs state 1734 1819 * @param fNumLockOn Turn on NumLock led if TRUE, turn off otherwise 1735 1820 * @param fCapsLockOn Turn on CapsLock led if TRUE, turn off otherwise 1736 1821 * @param fScrollLockOn Turn on ScrollLock led if TRUE, turn off otherwise 1737 1822 */ 1738 void DarwinHidDevicesBroadcastLeds( bool fNumLockOn, bool fCapsLockOn, bool fScrollLockOn)1823 void DarwinHidDevicesBroadcastLeds(void *pState, bool fNumLockOn, bool fCapsLockOn, bool fScrollLockOn) 1739 1824 { 1740 1825 /* Temporary disabled */ 1741 1826 #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) 1756 1846 { 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)); 1799 1854 } 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 1808 1867 #else /* !VBOX_WITH_KBD_LEDS_SYNC */ 1809 1868 (void)fNumLockOn; -
trunk/src/VBox/Frontends/VirtualBox/src/platform/darwin/DarwinKeyboard.h
r48517 r49048 49 49 void * DarwinHidDevicesKeepLedsState(void); 50 50 int DarwinHidDevicesApplyAndReleaseLedsState(void *pState); 51 void DarwinHidDevicesBroadcastLeds( bool fNumLockOn, bool fCapsLockOn, bool fScrollLockOn);51 void DarwinHidDevicesBroadcastLeds(void *pState, bool fNumLockOn, bool fCapsLockOn, bool fScrollLockOn); 52 52 53 53 RT_C_DECLS_END -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp
r49025 r49048 490 490 LogRelFlow(("UIMachineLogic::sltKeyboardLedsChanged: Updating host LED lock states (NOT IMPLEMENTED).\n")); 491 491 #ifdef Q_WS_MAC 492 DarwinHidDevicesBroadcastLeds( uisession()->isNumLock(), uisession()->isCapsLock(), uisession()->isScrollLock());492 DarwinHidDevicesBroadcastLeds(m_pHostLedsState, uisession()->isNumLock(), uisession()->isCapsLock(), uisession()->isScrollLock()); 493 493 #endif 494 494 } … … 2210 2210 if (m_pHostLedsState == NULL) 2211 2211 m_pHostLedsState = DarwinHidDevicesKeepLedsState(); 2212 DarwinHidDevicesBroadcastLeds( uisession()->isNumLock(), uisession()->isCapsLock(), uisession()->isScrollLock());2212 DarwinHidDevicesBroadcastLeds(m_pHostLedsState, uisession()->isNumLock(), uisession()->isCapsLock(), uisession()->isScrollLock()); 2213 2213 #endif /* Q_WS_MAC */ 2214 2214 }
Note:
See TracChangeset
for help on using the changeset viewer.