2011-08-25 15 views
7

Próbuję użyć IOHIDManagera, aby uzyskać zdarzenia z kluczem modyfikującym, ponieważ brakuje flag Cocoa flagsChanged (trudny do rozróżnienia między naciśnięciem/zwolnieniem, lewo/prawo, jeśli oba są wyłączone, itp.) Oto kod, w którym utworzę menedżera i zarejestruję wywołanie zwrotne.Używanie IOHIDManagera do pobierania kluczowych zdarzeń modyfikatora

IOHIDManagerRef hidManager = IOHIDManagerCreate(kCFAllocatorDefault, 
     kIOHIDOptionsTypeNone); 
if (CFGetTypeID(hidManager) != IOHIDManagerGetTypeID()) 
    return 1; 

CFMutableDictionaryRef capsLock = 
    myCreateDeviceMatchingDictionary(0x07, 0x39); 
CFMutableDictionaryRef lctrl = 
    myCreateDeviceMatchingDictionary(0x07, 0xE0); 
CFMutableDictionaryRef lshift = 
    myCreateDeviceMatchingDictionary(0x07, 0xE1); 
CFMutableDictionaryRef lalt = 
    myCreateDeviceMatchingDictionary(0x07, 0xE2); 
CFMutableDictionaryRef lsuper = 
    myCreateDeviceMatchingDictionary(0x07, 0xE3); 
CFMutableDictionaryRef rctrl = 
    myCreateDeviceMatchingDictionary(0x07, 0xE4); 
CFMutableDictionaryRef rshift = 
    myCreateDeviceMatchingDictionary(0x07, 0xE5); 
CFMutableDictionaryRef ralt = 
    myCreateDeviceMatchingDictionary(0x07, 0xE6); 
CFMutableDictionaryRef rsuper = 
    myCreateDeviceMatchingDictionary(0x07, 0xE7); 

CFMutableDictionaryRef matchesList[] = { 
    capsLock, 
    lctrl, 
    lshift, 
    lalt, 
    lsuper, 
    rctrl, 
    rshift, 
    ralt, 
    rsuper 
}; 
CFArrayRef matches = CFArrayCreate(kCFAllocatorDefault, 
     (const void **)matchesList, 9, NULL); 
IOHIDManagerSetDeviceMatchingMultiple(hidManager, matches); 

IOHIDManagerRegisterInputValueCallback(hidManager, 
     myHandleModifiersCallback, NULL); 

IOHIDManagerScheduleWithRunLoop(hidManager, CFRunLoopGetMain(), 
     kCFRunLoopDefaultMode); 

IOHIDManagerOpen(hidManager, kIOHIDOptionsTypeNone); 

Jednak wywołanie zwrotne nie jest nigdy uruchamiane. Czy brakuje mi czegoś?

Nie w pełni rozumiem strony użycia HID, więc nie wiedziałem, czy używać Generic Desktop Page (0x01) z ID użycia klawiatury (06), czy klawiatury/klawiatury (0x07) z użyciem Identyfikatory poszczególnych kluczy. Może to ma coś z tym wspólnego?

Odpowiedz

9

Wyjaśniałem to. Aby to zrobić, należy użyć klawiatury ogólnej (0x01) (06) (i klawiatury (07), aby uzyskać kompletność) do użycia z IOHIDManagerSetDeviceMatchingMultiple, a następnie wywołanie wartości wejściowej pobiera rzeczy z klawiatury/klawiatury (0x07).

Na przykład, aby skonfigurować HIDManager dla wszystkich Klawiatury/klawiatur, można zrobić coś takiego:

IOHIDManagerRef hidManager = IOHIDManagerCreate(kCFAllocatorDefault, 
     kIOHIDOptionsTypeNone); 

CFMutableDictionaryRef keyboard = 
    myCreateDeviceMatchingDictionary(0x01, 6); 
CFMutableDictionaryRef keypad = 
    myCreateDeviceMatchingDictionary(0x01, 7); 

CFMutableDictionaryRef matchesList[] = { 
    keyboard, 
    keypad, 
}; 
CFArrayRef matches = CFArrayCreate(kCFAllocatorDefault, 
     (const void **)matchesList, 2, NULL); 
IOHIDManagerSetDeviceMatchingMultiple(hidManager, matches); 

IOHIDManagerRegisterInputValueCallback(hidManager, 
     myHIDKeyboardCallback, NULL); 

IOHIDManagerScheduleWithRunLoop(hidManager, CFRunLoopGetMain(), 
     kCFRunLoopDefaultMode); 

IOHIDManagerOpen(hidManager, kIOHIDOptionsTypeNone); 

Gdzie myCreateDeviceMatchingDictionary jest coś takiego:

CFMutableDictionaryRef myCreateDeviceMatchingDictionary(UInt32 usagePage, 
     UInt32 usage) { 
    CFMutableDictionaryRef ret = CFDictionaryCreateMutable(kCFAllocatorDefault, 
      0, &kCFTypeDictionaryKeyCallBacks, 
      &kCFTypeDictionaryValueCallBacks); 
    if (!ret) 
     return NULL; 

    CFNumberRef pageNumberRef = CFNumberCreate(kCFAllocatorDefault, 
      kCFNumberIntType, &usagePage); 
    if (!pageNumberRef) { 
     CFRelease(ret); 
     return NULL; 
    } 

    CFDictionarySetValue(ret, CFSTR(kIOHIDDeviceUsagePageKey), pageNumberRef); 
    CFRelease(pageNumberRef); 

    CFNumberRef usageNumberRef = CFNumberCreate(kCFAllocatorDefault, 
      kCFNumberIntType, &usage); 
    if (!usageNumberRef) { 
     CFRelease(ret); 
     return NULL; 
    } 

    CFDictionarySetValue(ret, CFSTR(kIOHIDDeviceUsageKey), usageNumberRef); 
    CFRelease(usageNumberRef); 

    return ret; 
} 

I myHIDKeyboardCallback jest coś takiego:

void myHIDKeyboardCallback(void *context, IOReturn result, void *sender, 
     IOHIDValueRef value) { 
    IOHIDElementRef elem = IOHIDValueGetElement(value); 
    if (IOHIDElementGetUsagePage(elem) != 0x07) 
     return; 
    uint32_t scancode = IOHIDElementGetUsage(elem); 
    if (scancode < 4 || scancode > 231) 
     return; 
    long pressed = IOHIDValueGetIntegerValue(value); 
    // ... Do something ... 
} 

Należy pamiętać, że wywołanie zwrotne wydaje się nazywać się wiele razy za naciśnięcie lub zwolnienie, ale z identyfikatorami użytkowania wykraczającymi poza normalny zakres, co oznacza "if (scancode < 4 || scancode> 231)”jest.

+0

Gdzie znalazłeś informacje o tym, jak przeanalizować "wartość" w twoim oddzwanianiu, aby uzyskać takie rzeczy jak scancode? Czy masz jakieś (czytelne) referencje na ten temat, czy jak to zrozumiałeś? – jalf

4

thx za dostarczenie odpowiedzi na swoje pytanie.

zamiast IF-oświadczenie w myHIDKeyboardCallback, który sprawdza scancode < 4 lub scancode> 231 można użyć IOHIDManagerSetInputValueMatching.

// before IOHIDManagerOpen 
int usageMin = 4; 
CFNumberRef minNumberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usageMin); 
CFDictionarySetValue(inputValueFilter, CFSTR(kIOHIDElementUsageMinKey), minNumberRef); 
CFRelease(minNumberRef); 

int usageMax = 231; 
CFNumberRef maxNumberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usageMax); 
CFDictionarySetValue(inputValueFilter, CFSTR(kIOHIDElementUsageMaxKey), maxNumberRef); 
CFRelease(maxNumberRef); 

IOHIDManagerSetInputValueMatching(hidManager, inputValueFilter); 

jest bardziej LOC następnie prosty if-oświadczenie, ale w końcu z czystszym zwrotnego.

+0

Dobrze wiedzieć. Wyobrażam sobie, że możesz również ograniczyć strony użycia elementu do 0x07 za pomocą kIOHIDElementUsagePageKey. Czy to konieczne? Czy urządzenia klawiatury/klawiatury kiedykolwiek generują elementy inne niż 0x07? Wyobrażam sobie, że jest to możliwe, jeśli, powiedzmy, masz zewnętrzną klawiaturę z wbudowanym gładzikiem lub joystickiem lub coś takiego. – dostende

+0

nie, nigdy nie miałem wersji innej niż 0x07 :) – Yevgeniy

+0

Nigdy nie używałem takiej klawiatury (to znaczy z joystickiem lub podobną kompilacją), ale oczekiwałbym, że drugie urządzenie i klawiatura będą oddzielone od siebie. ale nie mogę powiedzieć na pewno. – Yevgeniy

Powiązane problemy