0
+ * Manipulate keyboard LEDs (capslock and numlock) programmatically.
0
+ * gcc -Wall -o keyboard_leds keyboard_leds.c -framework IOKit
0
+ * -framework CoreFoundation
0
+ * Copyright (c) 2007,2008 Amit Singh. All Rights Reserved.
0
+ * Redistribution and use in source and binary forms, with or without
0
+ * modification, are permitted provided that the following conditions
0
+ * 1. Redistributions of source code must retain the above copyright
0
+ * notice, this list of conditions and the following disclaimer.
0
+ * 2. Redistributions in binary form must reproduce the above copyright
0
+ * notice, this list of conditions and the following disclaimer in the
0
+ * documentation and/or other materials provided with the distribution.
0
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
0
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
0
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0
+#include <mach/mach_error.h>
0
+#include <IOKit/IOCFPlugIn.h>
0
+#include <IOKit/hid/IOHIDLib.h>
0
+#include <IOKit/hid/IOHIDUsageTables.h>
0
+#include "keyboard_leds.h"
0
+static IOHIDElementCookie capslock_cookie = (IOHIDElementCookie)0;
0
+static IOHIDElementCookie numlock_cookie = (IOHIDElementCookie)0;
0
+inline void print_errmsg_if_io_err(int expr, char* msg);
0
+inline void print_errmsg_if_err(int expr, char* msg);
0
+print_errmsg_if_io_err(int expr, char* msg)
0
+ IOReturn err = (expr);
0
+ if (err != kIOReturnSuccess) {
0
+ fprintf(stderr, "*** %s - %s(%x, %d).\n", msg, mach_error_string(err),
0
+print_errmsg_if_err(int expr, char* msg)
0
+ fprintf(stderr, "*** %s.\n", msg);
0
+ io_service_t result = (io_service_t)0;
0
+ CFNumberRef usagePageRef = (CFNumberRef)0;
0
+ CFNumberRef usageRef = (CFNumberRef)0;
0
+ CFMutableDictionaryRef matchingDictRef = (CFMutableDictionaryRef)0;
0
+ if (!(matchingDictRef = IOServiceMatching(kIOHIDDeviceKey))) {
0
+ UInt32 usagePage = kHIDPage_GenericDesktop;
0
+ UInt32 usage = kHIDUsage_GD_Keyboard;
0
+ if (!(usagePageRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType,
0
+ if (!(usageRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType,
0
+ CFDictionarySetValue(matchingDictRef, CFSTR(kIOHIDPrimaryUsagePageKey),
0
+ CFDictionarySetValue(matchingDictRef, CFSTR(kIOHIDPrimaryUsageKey),
0
+ result = IOServiceGetMatchingService(kIOMasterPortDefault, matchingDictRef);
0
+ CFRelease(usagePageRef);
0
+find_led_cookies(IOHIDDeviceInterface122** handle)
0
+ IOHIDElementCookie cookie;
0
+ CFDictionaryRef element;
0
+ if (!handle || !(*handle)) {
0
+ result = (*handle)->copyMatchingElements(handle, NULL, &elements);
0
+ if (result != kIOReturnSuccess) {
0
+ fprintf(stderr, "Failed to copy cookies.\n");
0
+ for (i = 0; i < CFArrayGetCount(elements); i++) {
0
+ element = CFArrayGetValueAtIndex(elements, i);
0
+ object = (CFDictionaryGetValue(element, CFSTR(kIOHIDElementCookieKey)));
0
+ if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) {
0
+ if (!CFNumberGetValue((CFNumberRef) object, kCFNumberLongType,
0
+ cookie = (IOHIDElementCookie)number;
0
+ object = CFDictionaryGetValue(element, CFSTR(kIOHIDElementUsageKey));
0
+ if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) {
0
+ if (!CFNumberGetValue((CFNumberRef)object, kCFNumberLongType,
0
+ object = CFDictionaryGetValue(element,CFSTR(kIOHIDElementUsagePageKey));
0
+ if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) {
0
+ if (!CFNumberGetValue((CFNumberRef)object, kCFNumberLongType,
0
+ if (usagePage == kHIDPage_LEDs) {
0
+ case kHIDUsage_LED_NumLock:
0
+ numlock_cookie = cookie;
0
+ case kHIDUsage_LED_CapsLock:
0
+ capslock_cookie = cookie;
0
+create_hid_interface(io_object_t hidDevice, IOHIDDeviceInterface*** hdi)
0
+ IOCFPlugInInterface** plugInInterface = NULL;
0
+ HRESULT plugInResult = S_OK;
0
+ IOReturn ioReturnValue = kIOReturnSuccess;
0
+ ioReturnValue = IOObjectGetClass(hidDevice, className);
0
+ print_errmsg_if_io_err(ioReturnValue, "Failed to get class name.");
0
+ ioReturnValue = IOCreatePlugInInterfaceForService(
0
+ hidDevice, kIOHIDDeviceUserClientTypeID,
0
+ kIOCFPlugInInterfaceID, &plugInInterface, &score);
0
+ if (ioReturnValue != kIOReturnSuccess) {
0
+ plugInResult = (*plugInInterface)->QueryInterface(plugInInterface,
0
+ CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), (LPVOID)hdi);
0
+ print_errmsg_if_err(plugInResult != S_OK,
0
+ "Failed to create device interface.\n");
0
+ (*plugInInterface)->Release(plugInInterface);
0
+manipulate_led(UInt32 whichLED, UInt32 value)
0
+ io_service_t hidService = (io_service_t)0;
0
+ io_object_t hidDevice = (io_object_t)0;
0
+ IOHIDDeviceInterface **hidDeviceInterface = NULL;
0
+ IOReturn ioReturnValue = kIOReturnError;
0
+ IOHIDElementCookie theCookie = (IOHIDElementCookie)0;
0
+ IOHIDEventStruct theEvent;
0
+ if (!(hidService = find_a_keyboard())) {
0
+ fprintf(stderr, "No keyboard found.\n");
0
+ hidDevice = (io_object_t)hidService;
0
+ create_hid_interface(hidDevice, &hidDeviceInterface);
0
+ find_led_cookies((IOHIDDeviceInterface122 **)hidDeviceInterface);
0
+ ioReturnValue = IOObjectRelease(hidDevice);
0
+ if (ioReturnValue != kIOReturnSuccess) {
0
+ ioReturnValue = kIOReturnError;
0
+ if (hidDeviceInterface == NULL) {
0
+ fprintf(stderr, "Failed to create HID device interface.\n");
0
+ if (whichLED == kHIDUsage_LED_NumLock) {
0
+ theCookie = numlock_cookie;
0
+ } else if (whichLED == kHIDUsage_LED_CapsLock) {
0
+ theCookie = capslock_cookie;
0
+ fprintf(stderr, "Bad or missing LED cookie.\n");
0
+ ioReturnValue = (*hidDeviceInterface)->open(hidDeviceInterface, 0);
0
+ if (ioReturnValue != kIOReturnSuccess) {
0
+ fprintf(stderr, "Failed to open HID device interface.\n");
0
+ ioReturnValue = (*hidDeviceInterface)->getElementValue(hidDeviceInterface,
0
+ theCookie, &theEvent);
0
+ if (ioReturnValue != kIOReturnSuccess) {
0
+ (void)(*hidDeviceInterface)->close(hidDeviceInterface);
0
+ fprintf(stdout, "%s\n", (theEvent.value) ? "on" : "off");
0
+ if (theEvent.value != value) {
0
+ theEvent.value = value;
0
+ ioReturnValue = (*hidDeviceInterface)->setElementValue(
0
+ hidDeviceInterface, theCookie,
0
+ &theEvent, 0, 0, 0, 0);
0
+ if (ioReturnValue == kIOReturnSuccess) {
0
+ fprintf(stdout, "%s\n", (theEvent.value) ? "on" : "off");
0
+ ioReturnValue = (*hidDeviceInterface)->close(hidDeviceInterface);
0
+ (void)(*hidDeviceInterface)->Release(hidDeviceInterface);
Comments
No one has commented yet.