web-dev-qa-db-ja.com

OSXでCAPSLOCK LEDを制御することは可能ですか?

OSXでCAPSLOCK機能を使用していないため、システム環境設定でキーを無効にしました。そのキーは私にはまったく役に立たない-わかりました、CMD/CTRL/ALTキーをそのキーにマップすることはできますが、そのためのキーはすでに取得しています…

だから私が考えているのは、キーのLEDを使用して(最近のAppleワイヤレスキーボード)を使用して、メールが待っている場合に通知することです...そのようなことです。 LEDを直接制御しますか?objective-c cocoaアプリを介して制御することは問題ありません。そのアプリは自分で作成しますが、これまではAppleのcocoaドキュメントから役立つものを見つけることができます。

8
DASKAjA

1つPython例: http://www.psychicorigami.com/2009/03/01/5k-morse-code-app-using-capslock-led/

可能です。古いiBook(10.4)のnumロックとcapslockのLEDを切り替えることができるアプリを何年も前に見つけようとしています。今日見ながらそれを見つけました。

それを見つけた。

ただし、コンパイルする必要があります。

ああ、そして HID LEDテストツール – Xcodeの例:D

6
cde

OSXでキーボードLEDを制御する別のツールは次のとおりです。 https://github.com/busyloop/maclight

MacLightを使用すると、MacのキーボードLED(capslock、numlock)を制御できます。

8
Isqy

これでMacのキーボードLEDを操作できます。

/*
 * keyboard_leds.c
 * Manipulate keyboard LEDs (capslock and numlock) programmatically.
 *
 * gcc -Wall -o keyboard_leds keyboard_leds.c -framework IOKit
 *     -framework CoreFoundation
 *
 * Copyright (c) 2007,2008 Amit Singh. All Rights Reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *     
 *  THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
 *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 *  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 *  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 *  SUCH DAMAGE.
 */

#define PROGNAME "keyboard_leds"
#define PROGVERS "0.1"

#include <stdio.h>
#include <getopt.h>
#include <stdlib.h>
#include <sysexits.h>
#include <mach/mach_error.h>

#include <IOKit/IOCFPlugIn.h>
#include <IOKit/hid/IOHIDLib.h>
#include <IOKit/hid/IOHIDUsageTables.h>

static IOHIDElementCookie capslock_cookie = (IOHIDElementCookie)0;
static IOHIDElementCookie numlock_cookie  = (IOHIDElementCookie)0;
static int capslock_value = -1;
static int numlock_value  = -1;

void         usage(void);
inline void  print_errmsg_if_io_err(int expr, char* msg);
inline void  print_errmsg_if_err(int expr, char* msg);

io_service_t find_a_keyboard(void);
void         find_led_cookies(IOHIDDeviceInterface122** handle);
void         create_hid_interface(io_object_t hidDevice,
                                  IOHIDDeviceInterface*** hdi);
int          manipulate_led(UInt32 whichLED, UInt32 value);

void
usage(void)
{
    fprintf(stderr, "%s (version %s)\n"
      "Copyright (c) 2007,2008 Amit Singh. All Rights Reserved.\n"
      "Manipulate keyboard LEDs\n\n"
      "Usage: %s [OPTIONS...], where OPTIONS is one of the following\n\n"
      "  -c[1|0], --capslock[=1|=0] get or set (on=1, off=0) caps lock LED\n"
      "  -h,      --help            print this help message and exit\n"
      "  -n[1|0], --numlock[=1|=0]  get or set (on=1, off=0) num lock LED\n",
    PROGNAME, PROGVERS, PROGNAME);
}

inline void
print_errmsg_if_io_err(int expr, char* msg)
{
    IOReturn err = (expr);

    if (err != kIOReturnSuccess) {
        fprintf(stderr, "*** %s - %s(%x, %d).\n", msg, mach_error_string(err),
                err, err & 0xffffff);
        fflush(stderr);
        exit(EX_OSERR);
    }
}

inline void
print_errmsg_if_err(int expr, char* msg)
{
    if (expr) {
        fprintf(stderr, "*** %s.\n", msg);
        fflush(stderr);
        exit(EX_OSERR);
    }
}

io_service_t
find_a_keyboard(void)
{
    io_service_t result = (io_service_t)0;

    CFNumberRef usagePageRef = (CFNumberRef)0;
    CFNumberRef usageRef = (CFNumberRef)0;
    CFMutableDictionaryRef matchingDictRef = (CFMutableDictionaryRef)0;

    if (!(matchingDictRef = IOServiceMatching(kIOHIDDeviceKey))) {
        return result;
    }

    UInt32 usagePage = kHIDPage_GenericDesktop;
    UInt32 usage = kHIDUsage_Gd_Keyboard;

    if (!(usagePageRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType,
                                        &usagePage))) {
        goto out;
    }

    if (!(usageRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType,
                                    &usage))) {
        goto out;
    }

    CFDictionarySetValue(matchingDictRef, CFSTR(kIOHIDPrimaryUsagePageKey),
                         usagePageRef);
    CFDictionarySetValue(matchingDictRef, CFSTR(kIOHIDPrimaryUsageKey),
                         usageRef);

    result = IOServiceGetMatchingService(kIOMasterPortDefault, matchingDictRef);

out:
    if (usageRef) {
        CFRelease(usageRef);
    }
    if (usagePageRef) {
        CFRelease(usagePageRef);
    }

    return result;
}

void
find_led_cookies(IOHIDDeviceInterface122** handle)
{
    IOHIDElementCookie cookie;
    CFTypeRef          object;
    long               number;
    long               usage;
    long               usagePage;
    CFArrayRef         elements;
    CFDictionaryRef    element;
    IOReturn           result;

    if (!handle || !(*handle)) {
        return;
    }

    result = (*handle)->copyMatchingElements(handle, NULL, &elements);

    if (result != kIOReturnSuccess) {
        fprintf(stderr, "Failed to copy cookies.\n");
        exit(1);
    }

    CFIndex i;

    for (i = 0; i < CFArrayGetCount(elements); i++) {

        element = CFArrayGetValueAtIndex(elements, i);

        object = (CFDictionaryGetValue(element, CFSTR(kIOHIDElementCookieKey)));
        if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) {
            continue;
        }
        if (!CFNumberGetValue((CFNumberRef) object, kCFNumberLongType,
                              &number)) {
            continue;
        }
        cookie = (IOHIDElementCookie)number;

        object = CFDictionaryGetValue(element, CFSTR(kIOHIDElementUsageKey));
        if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) {
            continue;
        }
        if (!CFNumberGetValue((CFNumberRef)object, kCFNumberLongType,
                              &number)) {
            continue;
        }
        usage = number;

        object = CFDictionaryGetValue(element,CFSTR(kIOHIDElementUsagePageKey));
        if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) {
            continue;
        }
        if (!CFNumberGetValue((CFNumberRef)object, kCFNumberLongType,
                              &number)) {
            continue;
        }
        usagePage = number;

        if (usagePage == kHIDPage_LEDs) {
            switch (usage) {

            case kHIDUsage_LED_NumLock:
                numlock_cookie = cookie;
                break;

            case kHIDUsage_LED_CapsLock:
                capslock_cookie = cookie;
                break;

            default:
                break;
            }
        }
    }

    return;
}

void
create_hid_interface(io_object_t hidDevice, IOHIDDeviceInterface*** hdi)
{
    IOCFPlugInInterface** plugInInterface = NULL;

    io_name_t className;
    HRESULT   plugInResult = S_OK;
    SInt32    score = 0;
    IOReturn  ioReturnValue = kIOReturnSuccess;

    ioReturnValue = IOObjectGetClass(hidDevice, className);

    print_errmsg_if_io_err(ioReturnValue, "Failed to get class name.");

    ioReturnValue = IOCreatePlugInInterfaceForService(
                        hidDevice, kIOHIDDeviceUserClientTypeID,
                        kIOCFPlugInInterfaceID, &plugInInterface, &score);
    if (ioReturnValue != kIOReturnSuccess) {
        return;
    }

    plugInResult = (*plugInInterface)->QueryInterface(plugInInterface,
                     CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), (LPVOID)hdi);
    print_errmsg_if_err(plugInResult != S_OK,
                        "Failed to create device interface.\n");

    (*plugInInterface)->Release(plugInInterface);
}

int
manipulate_led(UInt32 whichLED, UInt32 value)
{
    io_service_t           hidService = (io_service_t)0;
    io_object_t            hidDevice = (io_object_t)0;
    IOHIDDeviceInterface **hidDeviceInterface = NULL;
    IOReturn               ioReturnValue = kIOReturnError;
    IOHIDElementCookie     theCookie = (IOHIDElementCookie)0;
    IOHIDEventStruct       theEvent;

    if (!(hidService = find_a_keyboard())) {
        fprintf(stderr, "No keyboard found.\n");
        return ioReturnValue;
    }

    hidDevice = (io_object_t)hidService;

    create_hid_interface(hidDevice, &hidDeviceInterface);

    find_led_cookies((IOHIDDeviceInterface122 **)hidDeviceInterface);

    ioReturnValue = IOObjectRelease(hidDevice);
    if (ioReturnValue != kIOReturnSuccess) {
        goto out;
    }

    ioReturnValue = kIOReturnError;

    if (hidDeviceInterface == NULL) {
        fprintf(stderr, "Failed to create HID device interface.\n");
        return ioReturnValue;
    }

    if (whichLED == kHIDUsage_LED_NumLock) {
        theCookie = numlock_cookie;
    } else if (whichLED == kHIDUsage_LED_CapsLock) {
        theCookie = capslock_cookie;
    }

    if (theCookie == 0) {
        fprintf(stderr, "Bad or missing LED cookie.\n");
        goto out;
    }

    ioReturnValue = (*hidDeviceInterface)->open(hidDeviceInterface, 0);
    if (ioReturnValue != kIOReturnSuccess) {
        fprintf(stderr, "Failed to open HID device interface.\n");
        goto out;
    }

    ioReturnValue = (*hidDeviceInterface)->getElementValue(hidDeviceInterface,
                                               theCookie, &theEvent);
    if (ioReturnValue != kIOReturnSuccess) {
        (void)(*hidDeviceInterface)->close(hidDeviceInterface);
        goto out;
    }

    fprintf(stdout, "%s\n", (theEvent.value) ? "on" : "off");
    if (value != -1) {
        if (theEvent.value != value) {
            theEvent.value = value;
            ioReturnValue = (*hidDeviceInterface)->setElementValue(
                                hidDeviceInterface, theCookie,
                                &theEvent, 0, 0, 0, 0);
            if (ioReturnValue == kIOReturnSuccess) {
                fprintf(stdout, "%s\n", (theEvent.value) ? "on" : "off");
            }
        }
    }

    ioReturnValue = (*hidDeviceInterface)->close(hidDeviceInterface);

out:
    (void)(*hidDeviceInterface)->Release(hidDeviceInterface);

    return ioReturnValue;
}

static const char *options = "c::hn::";
static struct option
long_options[] = {
    { "capslock", optional_argument, 0, 'c' },
    { "help",     no_argument,       0, 'h' },
    { "numlock",  optional_argument, 0, 'n' },
    { 0, 0, 0, 0 },
};

int
main (int argc, char **argv)
{
    UInt32 whichLED = (UInt32)0;
    int c, ctr = 0;
    int target_value = -1;

    while ((c = getopt_long(argc, argv, options, long_options, NULL)) != -1) {

        switch (c) {

        case 0:
            break;

        case 'c':
            ctr++;
            whichLED = kHIDUsage_LED_CapsLock;
            if (optarg) {
                capslock_value = atoi(optarg);
                target_value = (capslock_value);
            }
            break;

        case 'h':
            usage();
            exit(0);
            break;

        case 'n':
            ctr++;
            whichLED = kHIDUsage_LED_NumLock;
            if (optarg) {
                numlock_value = atoi(optarg);
                target_value = (numlock_value);
            }
            break;

        default:
            usage();
            exit(1);
            break;
        }
    }

    if (ctr != 1) {
        fprintf(stderr, "Missing options or invalid combination of options. "
                        "Try -h for help.\n");
        exit(1);
    }

    return manipulate_led(whichLED, target_value);
}

このスクリプトをコンパイルして使用するには

gcc -Wall -o keyboard_leds keyboard_leds.c \
    -framework IOKit -framework CoreFoundation
./keyboard_leds -h
./keyboard_leds -c # query caps lock LED state
./keyboard_leds -c1 # turn caps lock LED on
./keyboard_leds -c0 # turn caps lock LED off
0
davidcondrey