Led Retro Illuminated Keyboard on Mac.

Recentemente comprei um teclado com retro iluminação, semelhante ao da imagem, via ebay. Depois de 17 dias de espera, quando finalmente chegou, fui logo experimentaá-lo no meu mac mini. Para minha grande surpresa nada acendeu...nem um mísero LED! Calculei que se tivesse de pressionar alguma tecla, ou até mesmo algum botão, e começo a  experimentar tudo e mais alguma coisa. Nisto, lembro-me de procurar na caixa alguma instrução e lá estava ela. A indicação, precisa, da tecla que se deveria pressionar. Pressionei-a como um louco mas sem efeito. Já convicto de que me tinham "passado a perna" lembrei-me de o ligar na minha máquina XP (sim ainda tenho um PC com o windows XP), e para minha surpresa tudo funcionava e às mil maravilhas. 

Obviamente o problema tinha de estar no mac mini. Depois de alguma pesquisa, percebi que os mac tratam as teclas de funçōes de forma diferente. Independentemente de tudo isso, um teclado com retro iluminação, que não dá iluminação nenhuma, não me serve para nada. Assim depois de mais algumas horas de pesquisa, encontrei o seguinte código:

 

//
//  File:       main.c
//
//  Contains:   main source code to HID LED test tool
//
//  Copyright:  Copyright (c) 2007 Apple Inc., All Rights Reserved
//
//  Disclaimer: IMPORTANT:  This Apple software is supplied to you by
//              Apple Inc. ("Apple") in consideration of your agreement to the
//              following terms, and your use, installation, modification or
//              redistribution of this Apple software constitutes acceptance of these
//              terms.  If you do not agree with these terms, please do not use,
//              install, modify or redistribute this Apple software.
//
//              In consideration of your agreement to abide by the following terms, and
//              subject to these terms, Apple grants you a personal, non-exclusive
//              license, under Apple's copyrights in this original Apple software (the
//              "Apple Software"), to use, reproduce, modify and redistribute the Apple
//              Software, with or without modifications, in source and/or binary forms;
//              provided that if you redistribute the Apple Software in its entirety and
//              without modifications, you must retain this notice and the following
//              text and disclaimers in all such redistributions of the Apple Software.
//              Neither the name, trademarks, service marks or logos of Apple Inc.
//              may be used to endorse or promote products derived from the Apple
//              Software without specific prior written permission from Apple.  Except
//              as expressly stated in this notice, no other rights or licenses, express
//              or implied, are granted by Apple herein, including but not limited to
//              any patent rights that may be infringed by your derivative works or by
//              other works in which the Apple Software may be incorporated.
//
//              The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
//              MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
//              THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
//              FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
//              OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
//
//              IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
//              OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//              SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//              INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
//              MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
//              AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
//              STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
//              POSSIBILITY OF SUCH DAMAGE.
//
// ****************************************************
#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 256 passes
    for ( pass = 0; pass < 256; 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 );                 // if this isn't an LED element...
                if ( kHIDPage_LEDs != usagePage ) {
                    continue;   // ...skip it
                }                 uint32_t usage = IOHIDElementGetUsage( tIOHIDElementRef );
                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( 500000 ); // sleep one half second
        }
    }                         // next pass     if ( tIOHIDManagerRef ) {
        CFRelease( tIOHIDManagerRef );
    }     if ( matchingCFDictRef ) {
        CFRelease( matchingCFDictRef );
    }
Oops:   ;
    return 0;
} /* main */

 

Contudo, este código, faz com que o teclado percorra vários modos, acendendo e apagando consecutivamente as suas teclas, devendo o programa ser terminado (ctrl + c) quando estiver no modo pretendido. Tal, significava a execução trivial de um padrão de frequência previsível e repetitiva...muito tedioso de facto ter de passar por todo esse processo sempre que fazia login. Nesse sentido procurei alterar o funcionamento do programa supracitado. Infelizmente a minha experiência em programação C é reduzida e no caso específico de dispositivos Mac é ainda menor. No entanto, é sempre tempo de aprender e depois de alguns testes cheguei a uma situação intermédia, em que já não é necessária a minha intervenção para parar no modo pretendido, e por outro lado, apesar de ainda percorrer alguns dos diferentes modos, com as alterações que fiz, percorre-os de forma tão rápida que parece imediato. Obviamente, em termos de programação não será uma solução óptima, mas do ponto de vista da funcionalidade, é satisfatória. Os proveitos, do ponto de vista estritamente funcional, que obteria se continuasse a "perder tempo" com a procura de uma solução mais elegante, seriam diminutos, pelo que, pesados os pratos aceitei esta como a solução final. A obra está terminada quando o artista se cansa de nela trabalhar.

Deixo aqui o código alterado:

//	File:		main.c
//
//	Contains:	main source code to HID LED test tool
//
//	Copyright:	Copyright (c) 2007 Apple Inc., All Rights Reserved
//
//	Disclaimer: IMPORTANT:	This Apple software is supplied to you by
//				Apple Inc. ("Apple") in consideration of your agreement to the
//				following terms, and your use, installation, modification or
//				redistribution of this Apple software constitutes acceptance of these
//				terms.	If you do not agree with these terms, please do not use,
//				install, modify or redistribute this Apple software.
//
//				In consideration of your agreement to abide by the following terms, and
//				subject to these terms, Apple grants you a personal, non-exclusive
//				license, under Apple's copyrights in this original Apple software (the
//				"Apple Software"), to use, reproduce, modify and redistribute the Apple
//				Software, with or without modifications, in source and/or binary forms;
//				provided that if you redistribute the Apple Software in its entirety and
//				without modifications, you must retain this notice and the following
//				text and disclaimers in all such redistributions of the Apple Software.
//				Neither the name, trademarks, service marks or logos of Apple Inc.
//				may be used to endorse or promote products derived from the Apple
//				Software without specific prior written permission from Apple.	Except
//				as expressly stated in this notice, no other rights or licenses, express
//				or implied, are granted by Apple herein, including but not limited to
//				any patent rights that may be infringed by your derivative works or by
//				other works in which the Apple Software may be incorporated.
//
//				The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
//				MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
//				THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
//				FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
//				OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
//
//				IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
//				OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//				SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//				INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
//				MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
//				AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
//				STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
//				POSSIBILITY OF SUCH DAMAGE.
//
// ****************************************************
#pragma mark -
#pragma mark * complation directives *
// ----------------------------------------------------

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

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

#include 
#include 
#include 

// ****************************************************
#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, char * argv[] )
{
#pragma unused ( argc, argv )
    int n =1;
    if(argc > 1)
    {
        n=2;
    }
    
	// 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 256 passes
	for ( pass = 0; pass < n; pass++ ) {
		
        
		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, 2 );
				require( tIOHIDElementRef, next_element );
                
				uint32_t usagePage = IOHIDElementGetUsagePage( tIOHIDElementRef );
                
				// if this isn't an LED element...
				if ( kHIDPage_LEDs != usagePage ) {
					continue;	// ...skip it
				}
                
				uint32_t usage = IOHIDElementGetUsage( tIOHIDElementRef );
				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;
                CFIndex tCFIndex = minCFIndex + ( device_value % modCFIndex );
                printf( "			 value = 0x%08lX.\n", tCFIndex );				// compute the value for this LED element
				//tCFIndex = 00000001;
                
				printf( "			 value2 = 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 );
					
				}
			next_element:	;
				continue;
			}
		next_device: ;
			CFRelease( elementCFArrayRef );
			continue;
		}
        
		// if we found an LED we'll delay before continuing
		
	}						  // next pass
    
	if ( tIOHIDManagerRef ) {
		CFRelease( tIOHIDManagerRef );
	}
    
	if ( matchingCFDictRef ) {
		CFRelease( matchingCFDictRef );
	}
Oops:	;
	return 0;
} /* main */

Contudo sempre que queria ligar as luzes do teclado, tinha de "correr" este código, o que não era nada prático. Por isso, para que o mesmo fosse executado no início de cada sessão, adicionei o seguinte ficheiro "com.akanerd.lights.plist" na pasta "/System/Library/LaunchAgents/":


	

<?xml version="1.0" encoding="UTF-8"?>


	

<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd >


	

<plist version="1.0">


	

<dict>


	

        <key>Label</key>

                <string>com.akanerd.light</string>

        <key>ProgramArguments</key>


	

                <array>


	

                        <string>/bin/./light.sh</string>


	

                </array>


	

        <key>RunAtLoad</key>


	

                <true/>


	

        <key>WorkingDirectory</key>


	

                <string>/bin</string>


	

<key>OnDemand</key>


	

        <true/>


	

<key>KeepAlive</key>


	

        <false/>


	

</dict>


	

</plist>


	

 

akanerd

O administrador!
Pessoa extremamente inteligente, possui o dom da ubiquidade.

3 comments

Login to post comments

Subscreva a Newsletter

maker.akanerd.com

    • Neste site, procura-se documentar alguns projectos do seu mentor, projectos esses, relacionados com áreas como a electrónica, a automação industrial, a informática, desenvolvimento web, sistemas operativos e redes de computadores, entre outros. Conta também com uma área educacional (akanerdemy), onde se apresentam video tutorias nas referidas áreas.