int main( int argc, const char * argv[] ) { Boolean initialized = FALSE; if (( argc != 4 ) && ( argc != 5 )) { printf ( "usage: Dream Cheeky Notifier R G B [A]\n\tRGB values should be 0-31. A is an optional parameter on whether to do the LED activation sequence. Anything larger than 0 is YES, default is 0 (activate).\n\n"); exit ( -1 ); } char r = (int)strtol ( argv[1], NULL, 10 ); char g = (int)strtol ( argv[2], NULL, 10 ); char b = (int)strtol ( argv[3], NULL, 10 ); if ( argc == 5 ) { initialized = TRUE; } if ((r < 0) || (r > 31) || (g < 0) || (g > 31) || (b < 0) || (b > 31)) { printf("RGB values must be within 0-31."); exit -1; } // create a IO HID Manager reference IOHIDManagerRef tIOHIDManagerRef = IOHIDManagerCreate( kCFAllocatorDefault, kIOHIDOptionsTypeNone ); // Create a device matching dictionary CFDictionaryRef matchingCFDictRef = hu_CreateMatchingDictionaryUsagePageUsage( TRUE, kHIDPage_GenericDesktop, 0x10 ); // 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 ); // and copy out its devices CFSetRef deviceCFSetRef = IOHIDManagerCopyDevices( tIOHIDManagerRef ); // 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 ); // 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 (Note: we don't do element matching anymore) matchingCFDictRef = hu_CreateMatchingDictionaryUsagePageUsage( FALSE, 0, 0 ); for ( deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++ ) { // if this isn't the notifier device... TODO: let's detect via vendor/product ids instead long vendor_id = 0; IOHIDDevice_GetLongProperty(tIOHIDDeviceRefs[deviceIndex], CFSTR(kIOHIDVendorIDKey), &vendor_id); long product_id = 0; IOHIDDevice_GetLongProperty(tIOHIDDeviceRefs[deviceIndex], CFSTR(kIOHIDProductIDKey), &product_id); if ((vendor_id != 0x1D34 ) || (product_id != 0x0004 )) { printf(" skipping device %p.\n", tIOHIDDeviceRefs[deviceIndex] ); continue; // ...skip it } printf( " device = %p.\n", tIOHIDDeviceRefs[deviceIndex] ); unsigned char report[8]; if (initialized == FALSE) { report[0] = 0x1F; // turn on LEDs report[1] = 0x02; report[2] = 0x00; report[3] = 0x5F; report[4] = 0x00; report[5] = 0x00; report[6] = 0x1A; report[7] = 0x03; // Note: We don't use the returned value here, so the compiler might throw a warning. IOReturn tIOReturn = IOHIDDeviceSetReport( tIOHIDDeviceRefs[deviceIndex], // IOHIDDeviceRef for the HID device kIOHIDReportTypeInput, // IOHIDReportType for the report (input, output, feature) 0, // CFIndex for the report ID report, // address of report buffer 8); // length of the report initialized = TRUE; } report[0] = r; // set brightness on LEDs to r, g, & b report[1] = g; report[2] = b; report[3] = 0x00; report[4] = 0x00; report[5] = 0x00; report[6] = 0x1A; report[7] = 0x05; tIOReturn = IOHIDDeviceSetReport( tIOHIDDeviceRefs[deviceIndex], // IOHIDDeviceRef for the HID device kIOHIDReportTypeInput, // IOHIDReportType for the report (input, output, feature) 0, // CFIndex for the report ID report, // address of report buffer 8); // length of the report next_device: ; continue; } if ( tIOHIDManagerRef ) { CFRelease( tIOHIDManagerRef ); } if ( matchingCFDictRef ) { CFRelease( matchingCFDictRef ); } Oops: ; return -1; } /* main */
//int main( int argc, const char * argv[] ) int manipulate_led( int which_led, int led_value ) { #pragma unused ( argc, argv ) IOHIDDeviceRef * tIOHIDDeviceRefs = nil; // 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 tIOHIDDeviceRefs = malloc( sizeof( IOHIDDeviceRef ) * deviceCount ); if (!tIOHIDDeviceRefs) { CFRelease(deviceCFSetRef); deviceCFSetRef = NULL; goto Oops; } // now extract the device ref's from the set CFSetGetValues( deviceCFSetRef, (const void **) tIOHIDDeviceRefs ); CFRelease(deviceCFSetRef); deviceCFSetRef = NULL; // 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 ); CFIndex tCFIndex = led_value; 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; } CFRelease( elementCFArrayRef ); next_device: ; continue; } // if we found an LED we'll delay before continuing //if ( delayFlag ) { // usleep( 500000 ); // sleep one half second //} // if the mouse is down… //if (GetCurrentButtonState()) { // break; // abort pass loop //} //} // next pass if ( matchingCFDictRef ) { CFRelease( matchingCFDictRef ); } Oops: ; if ( tIOHIDDeviceRefs ) { free(tIOHIDDeviceRefs); } if ( tIOHIDManagerRef ) { CFRelease( tIOHIDManagerRef ); } return 0; } /* main */