OSX non riconosce il tasto Scroll Lock sulla mia tastiera USB esterna

2

Sto provando a condividere il mio monitor e tastiera / mouse tra il mio PC (Windows 7) e Macbook Pro (1,1 - 2006, Snow Leopard) utilizzando uno switch KVM di base (Trendnet TK207).

Colpendo Scroll Lock due volte gli switch KVM da un computer a un altro. Il problema è che funziona su Windows ma non su OS X. OS X non riconosce affatto il mio tasto Scroll Lock (anche la spia Scroll Lock non funziona).

Qualche idea su come eseguire il debug / correggere questo problema?

    
posta r1x 27.08.2011 - 16:36
fonte

1 risposta

4

Ho creato una piccola utility da riga di comando per risolvere questo problema con il mio Trendnet TK-204UK. Il trucco consiste nel commutare lo stato del LED Scroll Lock sulla tastiera perché sembra essere monitorato dallo switch. Normalmente il Mac non commuta il LED quando si preme il tasto Scroll Lock. Ho trovato un programma di esempio Apple (strumento di test LED HID) che esegue l'accesso a basso livello alla tastiera e lo ha modificato per far lampeggiare il LED Scroll Lock. L'ho chiamato kvm, l'ho messo nel mio / usr / local / bin e il bingo non ha bisogno di arrivare sotto la scrivania per fare quello che ho comprato per farlo. Ecco la funzione principale modificata del file main.c del progetto HID_LED_test_tool. Nota che probabilmente dovrai modificare un'impostazione del progetto Xcode per compilarlo con l'SDK 10.7 perché è configurato per usare 10.5.

--- update ---

Questa soluzione funziona (grazie mille) ma ti manca parte del codice. Devi andare al link e prendere la funzione dichiarata in alto.

Anche per chi non sa cosa fare con questo, è necessario creare una nuova applicazione OS X da riga di comando in Xcode e crearla. Quindi puoi eseguirlo per cambiare il tuo KVM. Dovrai anche aggiungere CoreFoundation.framework e IOKit.framework alla build.

--- end update ---

--- update 2 ---

Ci siamo solo resi conto che se invece di costruire una "applicazione OS X a riga di comando", crei una "Applicazione Cocoa" e poi elimini tutto eccetto per main.m e fai il dump del codice qui sotto, creerai un 'normale 'applicazione invece di un'applicazione' riga di comando 'e che si avvierà più velocemente (senza caricare il terminale) e può essere agganciata al dock, ecc. Se si utilizza la "Cocoa App", è necessario aggiornare alcuni dei costruisci le impostazioni per corrispondere ai file che elimini.

--- end update 2 ---

//
//  main.m
//

// ****************************************************
#pragma mark -
#pragma mark * complation directives *
// ----------------------------------------------------

#ifndef FALSE
#define FALSE 0
#define TRUE !FALSE
#endif

// ****************************************************
#pragma mark -
#pragma mark * includes & imports *
// ----------------------------------------------------

#include <CoreFoundation/CoreFoundation.h>
#include <Carbon/Carbon.h>
#include <IOKit/hid/IOHIDLib.h>

// ****************************************************
#pragma mark -
#pragma mark * typedef's, struct's, enums, defines, etc. *
// ----------------------------------------------------
// function to create a matching dictionary for usage page & usage
static CFMutableDictionaryRef hu_CreateMatchingDictionaryUsagePageUsage(Boolean isDeviceNotElement,
                                                                    UInt32 inUsagePage,
                                                                    UInt32 inUsage )
{
    // create a dictionary to add usage page / usages to
    CFMutableDictionaryRef result = CFDictionaryCreateMutable(kCFAllocatorDefault,
                                                          0,
                                                          &kCFTypeDictionaryKeyCallBacks,
                                                          &kCFTypeDictionaryValueCallBacks );

    if ( result ) {
        if ( inUsagePage ) {
            // Add key for device type to refine the matching dictionary.
            CFNumberRef pageCFNumberRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &inUsagePage );

            if ( pageCFNumberRef ) {
                if ( isDeviceNotElement ) {
                    CFDictionarySetValue( result, CFSTR( kIOHIDDeviceUsagePageKey ), pageCFNumberRef );
                } else {
                    CFDictionarySetValue( result, CFSTR( kIOHIDElementUsagePageKey ), pageCFNumberRef );
                }
                CFRelease( pageCFNumberRef );

                // note: the usage is only valid if the usage page is also defined
                if ( inUsage ) {
                    CFNumberRef usageCFNumberRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &inUsage );

                    if ( usageCFNumberRef ) {
                        if ( isDeviceNotElement ) {
                            CFDictionarySetValue( result, CFSTR( kIOHIDDeviceUsageKey ), usageCFNumberRef );
                        } else {
                            CFDictionarySetValue( result, CFSTR( kIOHIDElementUsageKey ), usageCFNumberRef );
                        }
                        CFRelease( usageCFNumberRef );
                    } else {
                        fprintf( stderr, "%s: CFNumberCreate( usage ) failed.", __PRETTY_FUNCTION__ );
                    }
                }
            } else {
                fprintf( stderr, "%s: CFNumberCreate( usage page ) failed.", __PRETTY_FUNCTION__ );
            }
        }
    } else {
        fprintf( stderr, "%s: CFDictionaryCreateMutable failed.", __PRETTY_FUNCTION__ );
    }
    return result;
}    // hu_CreateMatchingDictionaryUsagePageUsage



int main( int argc, const char * argv[] )
{
#pragma unused ( argc, argv )

    // create a IO HID Manager reference
    IOHIDManagerRef tIOHIDManagerRef = IOHIDManagerCreate( kCFAllocatorDefault, kIOHIDOptionsTypeNone );
    require( tIOHIDManagerRef, Oops );

    // Create a device matching dictionary
    CFDictionaryRef matchingCFDictRef = hu_CreateMatchingDictionaryUsagePageUsage( TRUE,
                                                                                  kHIDPage_GenericDesktop,
                                                                                  kHIDUsage_GD_Keyboard );
    require( matchingCFDictRef, Oops );

    // set the HID device matching dictionary
    IOHIDManagerSetDeviceMatching( tIOHIDManagerRef, matchingCFDictRef );

    if ( matchingCFDictRef ) {
        CFRelease( matchingCFDictRef );
    }

    // Now open the IO HID Manager reference
    IOReturn tIOReturn = IOHIDManagerOpen( tIOHIDManagerRef, kIOHIDOptionsTypeNone );
    require_noerr( tIOReturn, Oops );

    // and copy out its devices
    CFSetRef deviceCFSetRef = IOHIDManagerCopyDevices( tIOHIDManagerRef );
    require( deviceCFSetRef, Oops );

    // how many devices in the set?
    CFIndex deviceIndex, deviceCount = CFSetGetCount( deviceCFSetRef );

    // allocate a block of memory to extact the device ref's from the set into
    IOHIDDeviceRef * tIOHIDDeviceRefs = malloc( sizeof( IOHIDDeviceRef ) * deviceCount );
    require( tIOHIDDeviceRefs, Oops );

    // now extract the device ref's from the set
    CFSetGetValues( deviceCFSetRef, (const void **) tIOHIDDeviceRefs );

    // before we get into the device loop we'll setup our element matching dictionary
    matchingCFDictRef = hu_CreateMatchingDictionaryUsagePageUsage( FALSE, kHIDPage_LEDs, 0 );
    require( matchingCFDictRef, Oops );

    int pass;   // do 3 passes
    for ( pass = 0; pass < 3; pass++ ) {
        Boolean delayFlag = FALSE;  // if we find an LED element we'll set this to TRUE

        //printf( "pass = %d.\n", pass );
        for ( deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++ ) {

            // if this isn't a keyboard device...
            if ( !IOHIDDeviceConformsTo( tIOHIDDeviceRefs[deviceIndex], kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard ) ) {
                continue;   // ...skip it
            }

            //printf( "  device = %p.\n", tIOHIDDeviceRefs[deviceIndex] );

            // copy all the elements
            CFArrayRef elementCFArrayRef = IOHIDDeviceCopyMatchingElements( tIOHIDDeviceRefs[deviceIndex],
                                                                           matchingCFDictRef,
                                                                           kIOHIDOptionsTypeNone );
            require( elementCFArrayRef, next_device );

            // for each device on the system these values are divided by the value ranges of all LED elements found
            // for example, if the first four LED element have a range of 0-1 then the four least significant bits of 
            // this value will be sent to these first four LED elements, etc.
            int device_value = pass;

            // iterate over all the elements
            CFIndex elementIndex, elementCount = CFArrayGetCount( elementCFArrayRef );
            for ( elementIndex = 0; elementIndex < elementCount; elementIndex++ ) {
                IOHIDElementRef tIOHIDElementRef = ( IOHIDElementRef ) CFArrayGetValueAtIndex( elementCFArrayRef, elementIndex );
                require( tIOHIDElementRef, next_element );

                uint32_t usagePage = IOHIDElementGetUsagePage( tIOHIDElementRef );
                uint32_t usage = IOHIDElementGetUsage( tIOHIDElementRef );

                // if this isn't an LED element or the Scroll Lock key...
                if ( kHIDPage_LEDs != usagePage || 3 != usage ) {
                    continue;   // ...skip it
                }

                //IOHIDElementType tIOHIDElementType = IOHIDElementGetType( tIOHIDElementRef );

                //printf( "      element = %p (page: %d, usage: %d, type: %d ).\n",                    tIOHIDElementRef, usagePage, usage, tIOHIDElementType );

                // get the logical mix/max for this LED element
                CFIndex minCFIndex = IOHIDElementGetLogicalMin( tIOHIDElementRef );
                CFIndex maxCFIndex = IOHIDElementGetLogicalMax( tIOHIDElementRef );

                // calculate the range
                CFIndex modCFIndex = maxCFIndex - minCFIndex + 1;

                // compute the value for this LED element
                CFIndex tCFIndex = minCFIndex + ( device_value % modCFIndex );
                device_value /= modCFIndex;

                //printf( "          value = 0x%08lX.\n", tCFIndex );

                uint64_t timestamp = 0; // create the IO HID Value to be sent to this LED element
                IOHIDValueRef tIOHIDValueRef = IOHIDValueCreateWithIntegerValue( kCFAllocatorDefault, tIOHIDElementRef, timestamp, tCFIndex );
                if ( tIOHIDValueRef ) {
                    // now set it on the device
                    tIOReturn = IOHIDDeviceSetValue( tIOHIDDeviceRefs[deviceIndex], tIOHIDElementRef, tIOHIDValueRef );
                    CFRelease( tIOHIDValueRef );
                    require_noerr( tIOReturn, next_element );
                    delayFlag = TRUE;   // set this TRUE so we'll delay before changing our LED values again
                }
            next_element:   ;
                continue;
            }
        next_device: ;
            CFRelease( elementCFArrayRef );
            continue;
        }

        // if we found an LED we'll delay before continuing
        if ( delayFlag ) {
            usleep( 250000 ); // sleep 0.25 second
        }
    }                         // next pass

    if ( tIOHIDManagerRef ) {
        CFRelease( tIOHIDManagerRef );
    }

    if ( matchingCFDictRef ) {
        CFRelease( matchingCFDictRef );
    }
Oops:   ;
    return 0;
} /* main */
    
risposta data 31.10.2011 - 04:42
fonte

Leggi altre domande sui tag