maclight 2.0.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 214cc2a1bc8b6597a2aba20b8ada99138e581540
4
- data.tar.gz: 6aaf23bcf522b680158eeaa49d285f1f3de846f7
3
+ metadata.gz: b24508bb26e8dd38759e7ac95fa0ff03f6526a08
4
+ data.tar.gz: f97b6d155204e429e3c869bd16ec2dc8ccc8cc76
5
5
  SHA512:
6
- metadata.gz: a94f4339ee62e3e2e314c10df89c1d49bcb347983499fda177de0ce3abcbbdabce885d2e1d2a013dc7462ca908c8416468fcf4fa49370a6a9983f1247d702557
7
- data.tar.gz: 593bbc2b9d2e17e9b147890db0cd4248f29d2b5ed39b9607c30182808e6c4e5f82b8de232fede599b6bf4e412b7d73c8e9eb30df0ca8388d49e9a9f75b609146
6
+ metadata.gz: 168125dcb91528fbeeaa03f4861e73a3e3a82265067cfc368a2e221d6fb6f083f2a9777b3d45a43e678bb64c62d3b268f357d46c5a7249758e2f20d1621f0137
7
+ data.tar.gz: ac5f80babb1f27b4addb159fb95b0ae31cefa2aecbf820d3870499eca7d69cb9ebb4cfbdbf0e10e2d78ee21cbc136aee09e6df0509238ed071cf4805696cb814
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # MacLight [![Dependency Status](https://gemnasium.com/busyloop/maclight.png)](https://gemnasium.com/busyloop/maclight)
2
2
 
3
- MacLight lets you control the keyboard-LEDs (capslock, numlock) on your Mac.
3
+ MacLight lets you control the keyboard LEDs on your Mac or Macbook.
4
4
 
5
5
  ## Screenshot
6
6
 
@@ -17,7 +17,7 @@ $ maclight --help
17
17
 
18
18
  Usage: maclight <command>
19
19
 
20
- MacLight v1.0.0 - LED control utility
20
+ MacLight v3.0.0 - LED control utility
21
21
 
22
22
  Options:
23
23
  --version: Print version and exit
@@ -35,17 +35,17 @@ Commands:
35
35
 
36
36
  require 'maclight'
37
37
 
38
- # Turn both LEDs on
39
- MacLight.capslock(true)
40
- MacLight.numlock(true)
38
+ # Turn LEDs on
39
+ MacLight.all_leds(true)
41
40
 
42
41
  sleep 2
43
42
 
44
- # Turn both LEDs off
45
- MacLight.capslock(false)
46
- MacLight.numlock(false)
43
+ # Turn LEDs off
44
+ MacLight.all_leds(false)
47
45
  ```
48
46
 
49
- ## Credits
47
+ ## Notice
48
+
49
+ MacLight can currently only toggle all LEDs at once
50
+ and has only been tested on OSX 10.11.3 (El Capitan).
50
51
 
51
- MacLight is based on HID demonstration code by [Amit Singh](http://googlemac.blogspot.de/2008/04/manipulating-keyboard-leds-through.html).
@@ -1,328 +1,288 @@
1
- /*
2
- * keyboard_leds.c
3
- * Manipulate keyboard LEDs (capslock and numlock) programmatically.
4
- *
5
- * gcc -Wall -o keyboard_leds keyboard_leds.c -framework IOKit
6
- * -framework CoreFoundation
7
- *
8
- * Copyright (c) 2007,2008 Amit Singh. All Rights Reserved.
9
- *
10
- * Redistribution and use in source and binary forms, with or without
11
- * modification, are permitted provided that the following conditions
12
- * are met:
13
- * 1. Redistributions of source code must retain the above copyright
14
- * notice, this list of conditions and the following disclaimer.
15
- * 2. Redistributions in binary form must reproduce the above copyright
16
- * notice, this list of conditions and the following disclaimer in the
17
- * documentation and/or other materials provided with the distribution.
18
- *
19
- * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
- * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
23
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
- * SUCH DAMAGE.
30
- */
1
+ // File: main.c
2
+ // Abstract: source code for HID LED test tool
3
+ // Version: 1.3
4
+ //
5
+ // Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
6
+ // Inc. ("Apple") in consideration of your agreement to the following
7
+ // terms, and your use, installation, modification or redistribution of
8
+ // this Apple software constitutes acceptance of these terms. If you do
9
+ // not agree with these terms, please do not use, install, modify or
10
+ // redistribute this Apple software.
11
+ //
12
+ // In consideration of your agreement to abide by the following terms, and
13
+ // subject to these terms, Apple grants you a personal, non-exclusive
14
+ // license, under Apple's copyrights in this original Apple software (the
15
+ // "Apple Software"), to use, reproduce, modify and redistribute the Apple
16
+ // Software, with or without modifications, in source and/or binary forms;
17
+ // provided that if you redistribute the Apple Software in its entirety and
18
+ // without modifications, you must retain this notice and the following
19
+ // text and disclaimers in all such redistributions of the Apple Software.
20
+ // Neither the name, trademarks, service marks or logos of Apple Inc. may
21
+ // be used to endorse or promote products derived from the Apple Software
22
+ // without specific prior written permission from Apple. Except as
23
+ // expressly stated in this notice, no other rights or licenses, express or
24
+ // implied, are granted by Apple herein, including but not limited to any
25
+ // patent rights that may be infringed by your derivative works or by other
26
+ // works in which the Apple Software may be incorporated.
27
+ //
28
+ // The Apple Software is provided by Apple on an "AS IS" basis. APPLE
29
+ // MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
30
+ // THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
31
+ // FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
32
+ // OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
33
+ //
34
+ // IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
35
+ // OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
36
+ // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37
+ // INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
38
+ // MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
39
+ // AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
40
+ // STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
41
+ // POSSIBILITY OF SUCH DAMAGE.
42
+ //
43
+ // Copyright (C) 2015 Apple Inc. All Rights Reserved.
44
+ //
45
+ // ****************************************************
31
46
 
32
47
  /* rubyfied by moe@busyloop.net */
48
+ #pragma mark -
49
+ #pragma mark * complation directives *
50
+ // ----------------------------------------------------
51
+ /* rubyfied by moe@busyloop.net */
52
+
53
+ #ifndef FALSE
54
+ #define FALSE 0
55
+ #define TRUE !FALSE
56
+ #endif
33
57
 
34
- #include <stdio.h>
35
- #include <getopt.h>
36
- #include <stdlib.h>
37
- #include <sysexits.h>
38
- #include <mach/mach_error.h>
58
+ // ****************************************************
59
+ #pragma mark -
60
+ #pragma mark * includes & imports *
61
+ // ----------------------------------------------------
39
62
 
40
- #include <IOKit/IOCFPlugIn.h>
63
+ #include <CoreFoundation/CoreFoundation.h>
64
+ #include <Carbon/Carbon.h>
41
65
  #include <IOKit/hid/IOHIDLib.h>
42
- #include <IOKit/hid/IOHIDUsageTables.h>
43
66
 
44
67
  #include "ruby.h"
45
68
 
46
- static IOHIDElementCookie capslock_cookie = (IOHIDElementCookie)0;
47
- static IOHIDElementCookie numlock_cookie = (IOHIDElementCookie)0;
48
- static int capslock_value = -1;
49
- static int numlock_value = -1;
50
-
51
- void usage(void);
52
- inline void print_errmsg_if_io_err(int expr, char* msg);
53
- inline void print_errmsg_if_err(int expr, char* msg);
54
-
55
- io_service_t find_a_keyboard(void);
56
- void find_led_cookies(IOHIDDeviceInterface122** handle);
57
- void create_hid_interface(io_object_t hidDevice,
58
- IOHIDDeviceInterface*** hdi);
59
- int manipulate_led(UInt32 whichLED, SInt32 value);
60
-
61
- inline void
62
- print_errmsg_if_io_err(int expr, char* msg)
69
+ // ****************************************************
70
+ #pragma mark -
71
+ #pragma mark * typedef's, struct's, enums, defines, etc. *
72
+ // ----------------------------------------------------
73
+ // function to create a matching dictionary for usage page & usage
74
+ static CFMutableDictionaryRef hu_CreateMatchingDictionaryUsagePageUsage( Boolean isDeviceNotElement,
75
+ UInt32 inUsagePage,
76
+ UInt32 inUsage )
63
77
  {
64
- IOReturn err = (expr);
65
-
66
- if (err != kIOReturnSuccess) {
67
- fprintf(stderr, "*** %s - %s(%x, %d).\n", msg, mach_error_string(err),
68
- err, err & 0xffffff);
69
- fflush(stderr);
70
- exit(EX_OSERR);
71
- }
72
- }
73
-
74
- inline void
75
- print_errmsg_if_err(int expr, char* msg)
76
- {
77
- if (expr) {
78
- fprintf(stderr, "*** %s.\n", msg);
79
- fflush(stderr);
80
- exit(EX_OSERR);
81
- }
82
- }
83
-
84
- io_service_t
85
- find_a_keyboard(void)
78
+ // create a dictionary to add usage page / usages to
79
+ CFMutableDictionaryRef result = CFDictionaryCreateMutable( kCFAllocatorDefault,
80
+ 0,
81
+ &kCFTypeDictionaryKeyCallBacks,
82
+ &kCFTypeDictionaryValueCallBacks );
83
+
84
+ if ( result ) {
85
+ if ( inUsagePage ) {
86
+ // Add key for device type to refine the matching dictionary.
87
+ CFNumberRef pageCFNumberRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &inUsagePage );
88
+
89
+ if ( pageCFNumberRef ) {
90
+ if ( isDeviceNotElement ) {
91
+ CFDictionarySetValue( result, CFSTR( kIOHIDDeviceUsagePageKey ), pageCFNumberRef );
92
+ } else {
93
+ CFDictionarySetValue( result, CFSTR( kIOHIDElementUsagePageKey ), pageCFNumberRef );
94
+ }
95
+ CFRelease( pageCFNumberRef );
96
+
97
+ // note: the usage is only valid if the usage page is also defined
98
+ if ( inUsage ) {
99
+ CFNumberRef usageCFNumberRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &inUsage );
100
+
101
+ if ( usageCFNumberRef ) {
102
+ if ( isDeviceNotElement ) {
103
+ CFDictionarySetValue( result, CFSTR( kIOHIDDeviceUsageKey ), usageCFNumberRef );
104
+ } else {
105
+ CFDictionarySetValue( result, CFSTR( kIOHIDElementUsageKey ), usageCFNumberRef );
106
+ }
107
+ CFRelease( usageCFNumberRef );
108
+ } else {
109
+ fprintf( stderr, "%s: CFNumberCreate( usage ) failed.", __PRETTY_FUNCTION__ );
110
+ }
111
+ }
112
+ } else {
113
+ fprintf( stderr, "%s: CFNumberCreate( usage page ) failed.", __PRETTY_FUNCTION__ );
114
+ }
115
+ }
116
+ } else {
117
+ fprintf( stderr, "%s: CFDictionaryCreateMutable failed.", __PRETTY_FUNCTION__ );
118
+ }
119
+ return result;
120
+ } // hu_CreateMatchingDictionaryUsagePageUsage
121
+
122
+ //int main( int argc, const char * argv[] )
123
+ int manipulate_led( int which_led, int led_value )
86
124
  {
87
- io_service_t result = (io_service_t)0;
88
-
89
- CFNumberRef usagePageRef = (CFNumberRef)0;
90
- CFNumberRef usageRef = (CFNumberRef)0;
91
- CFMutableDictionaryRef matchingDictRef = (CFMutableDictionaryRef)0;
92
-
93
- if (!(matchingDictRef = IOServiceMatching(kIOHIDDeviceKey))) {
94
- return result;
95
- }
96
-
97
- UInt32 usagePage = kHIDPage_GenericDesktop;
98
- UInt32 usage = kHIDUsage_GD_Keyboard;
99
-
100
- if (!(usagePageRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType,
101
- &usagePage))) {
102
- goto out;
103
- }
125
+ #pragma unused ( argc, argv )
126
+ IOHIDDeviceRef * tIOHIDDeviceRefs = nil;
127
+
128
+ // create a IO HID Manager reference
129
+ IOHIDManagerRef tIOHIDManagerRef = IOHIDManagerCreate( kCFAllocatorDefault, kIOHIDOptionsTypeNone );
130
+ require( tIOHIDManagerRef, Oops );
104
131
 
105
- if (!(usageRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType,
106
- &usage))) {
107
- goto out;
108
- }
109
-
110
- CFDictionarySetValue(matchingDictRef, CFSTR(kIOHIDPrimaryUsagePageKey),
111
- usagePageRef);
112
- CFDictionarySetValue(matchingDictRef, CFSTR(kIOHIDPrimaryUsageKey),
113
- usageRef);
114
-
115
- result = IOServiceGetMatchingService(kIOMasterPortDefault, matchingDictRef);
116
-
117
- out:
118
- if (usageRef) {
119
- CFRelease(usageRef);
120
- }
121
- if (usagePageRef) {
122
- CFRelease(usagePageRef);
123
- }
124
-
125
- return result;
126
- }
127
-
128
- void
129
- find_led_cookies(IOHIDDeviceInterface122** handle)
130
- {
131
- IOHIDElementCookie cookie;
132
- CFTypeRef object;
133
- long number;
134
- long usage;
135
- long usagePage;
136
- CFArrayRef elements;
137
- CFDictionaryRef element;
138
- IOReturn result;
139
-
140
- if (!handle || !(*handle)) {
141
- return;
142
- }
143
-
144
- result = (*handle)->copyMatchingElements(handle, NULL, &elements);
145
-
146
- if (result != kIOReturnSuccess) {
147
- fprintf(stderr, "Failed to copy cookies.\n");
148
- exit(1);
149
- }
150
-
151
- CFIndex i;
152
-
153
- for (i = 0; i < CFArrayGetCount(elements); i++) {
154
-
155
- element = CFArrayGetValueAtIndex(elements, i);
156
-
157
- object = (CFDictionaryGetValue(element, CFSTR(kIOHIDElementCookieKey)));
158
- if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) {
159
- continue;
160
- }
161
- if (!CFNumberGetValue((CFNumberRef) object, kCFNumberLongType,
162
- &number)) {
163
- continue;
164
- }
165
- cookie = (IOHIDElementCookie)number;
166
-
167
- object = CFDictionaryGetValue(element, CFSTR(kIOHIDElementUsageKey));
168
- if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) {
169
- continue;
170
- }
171
- if (!CFNumberGetValue((CFNumberRef)object, kCFNumberLongType,
172
- &number)) {
173
- continue;
174
- }
175
- usage = number;
176
-
177
- object = CFDictionaryGetValue(element,CFSTR(kIOHIDElementUsagePageKey));
178
- if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) {
179
- continue;
180
- }
181
- if (!CFNumberGetValue((CFNumberRef)object, kCFNumberLongType,
182
- &number)) {
183
- continue;
184
- }
185
- usagePage = number;
186
-
187
- if (usagePage == kHIDPage_LEDs) {
188
- switch (usage) {
189
-
190
- case kHIDUsage_LED_NumLock:
191
- numlock_cookie = cookie;
192
- break;
193
-
194
- case kHIDUsage_LED_CapsLock:
195
- capslock_cookie = cookie;
196
- break;
197
-
198
- default:
199
- break;
200
- }
201
- }
202
- }
203
-
204
- return;
205
- }
206
-
207
- void
208
- create_hid_interface(io_object_t hidDevice, IOHIDDeviceInterface*** hdi)
209
- {
210
- IOCFPlugInInterface** plugInInterface = NULL;
211
-
212
- io_name_t className;
213
- HRESULT plugInResult = S_OK;
214
- SInt32 score = 0;
215
- IOReturn ioReturnValue = kIOReturnSuccess;
216
-
217
- ioReturnValue = IOObjectGetClass(hidDevice, className);
218
-
219
- //print_errmsg_if_io_err(ioReturnValue, "Failed to get class name.");
220
-
221
- ioReturnValue = IOCreatePlugInInterfaceForService(
222
- hidDevice, kIOHIDDeviceUserClientTypeID,
223
- kIOCFPlugInInterfaceID, &plugInInterface, &score);
224
- if (ioReturnValue != kIOReturnSuccess) {
225
- return;
226
- }
227
-
228
- plugInResult = (*plugInInterface)->QueryInterface(plugInInterface,
229
- CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), (LPVOID)hdi);
230
- //print_errmsg_if_err(plugInResult != S_OK,
231
- // "Failed to create device interface.\n");
232
-
233
- (*plugInInterface)->Release(plugInInterface);
234
- }
235
-
236
- int
237
- manipulate_led(UInt32 whichLED, SInt32 value)
238
- {
239
- io_service_t hidService = (io_service_t)0;
240
- io_object_t hidDevice = (io_object_t)0;
241
- IOHIDDeviceInterface **hidDeviceInterface = NULL;
242
- IOReturn ioReturnValue = kIOReturnError;
243
- IOHIDElementCookie theCookie = (IOHIDElementCookie)0;
244
- IOHIDEventStruct theEvent;
245
-
246
- if (!(hidService = find_a_keyboard())) {
247
- fprintf(stderr, "No keyboard found.\n");
248
- return ioReturnValue;
249
- }
250
-
251
- hidDevice = (io_object_t)hidService;
252
-
253
- create_hid_interface(hidDevice, &hidDeviceInterface);
254
-
255
- find_led_cookies((IOHIDDeviceInterface122 **)hidDeviceInterface);
256
-
257
- ioReturnValue = IOObjectRelease(hidDevice);
258
- if (ioReturnValue != kIOReturnSuccess) {
259
- goto out;
260
- }
261
-
262
- ioReturnValue = kIOReturnError;
263
-
264
- if (hidDeviceInterface == NULL) {
265
- fprintf(stderr, "Failed to create HID device interface.\n");
266
- return ioReturnValue;
267
- }
268
-
269
- if (whichLED == kHIDUsage_LED_NumLock) {
270
- theCookie = numlock_cookie;
271
- } else if (whichLED == kHIDUsage_LED_CapsLock) {
272
- theCookie = capslock_cookie;
273
- }
274
-
275
- if (theCookie == 0) {
276
- fprintf(stderr, "Bad or missing LED cookie.\n");
277
- goto out;
278
- }
279
-
280
- ioReturnValue = (*hidDeviceInterface)->open(hidDeviceInterface, 0);
281
- if (ioReturnValue != kIOReturnSuccess) {
282
- fprintf(stderr, "Failed to open HID device interface.\n");
283
- goto out;
284
- }
285
-
286
- ioReturnValue = (*hidDeviceInterface)->getElementValue(hidDeviceInterface,
287
- theCookie, &theEvent);
288
- if (ioReturnValue != kIOReturnSuccess) {
289
- (void)(*hidDeviceInterface)->close(hidDeviceInterface);
290
- goto out;
291
- }
292
-
293
- //fprintf(stdout, "%s\n", (theEvent.value) ? "on" : "off");
294
- if (value != -1) {
295
- if (theEvent.value != value) {
296
- theEvent.value = value;
297
- ioReturnValue = (*hidDeviceInterface)->setElementValue(
298
- hidDeviceInterface, theCookie,
299
- &theEvent, 0, 0, 0, 0);
300
- //if (ioReturnValue == kIOReturnSuccess) {
301
- // fprintf(stdout, "%s\n", (theEvent.value) ? "on" : "off");
302
- //}
303
- }
304
- }
305
-
306
- ioReturnValue = (*hidDeviceInterface)->close(hidDeviceInterface);
307
-
308
- out:
309
- (void)(*hidDeviceInterface)->Release(hidDeviceInterface);
310
-
311
- //return ioReturnValue;
312
- return theEvent.value;
313
- }
132
+ // Create a device matching dictionary
133
+ CFDictionaryRef matchingCFDictRef = hu_CreateMatchingDictionaryUsagePageUsage( TRUE,
134
+ kHIDPage_GenericDesktop,
135
+ kHIDUsage_GD_Keyboard );
136
+ require( matchingCFDictRef, Oops );
137
+
138
+ // set the HID device matching dictionary
139
+ IOHIDManagerSetDeviceMatching( tIOHIDManagerRef, matchingCFDictRef );
140
+
141
+ if ( matchingCFDictRef ) {
142
+ CFRelease( matchingCFDictRef );
143
+ }
144
+
145
+ // Now open the IO HID Manager reference
146
+ IOReturn tIOReturn = IOHIDManagerOpen( tIOHIDManagerRef, kIOHIDOptionsTypeNone );
147
+ require_noerr( tIOReturn, Oops );
148
+
149
+ // and copy out its devices
150
+ CFSetRef deviceCFSetRef = IOHIDManagerCopyDevices( tIOHIDManagerRef );
151
+ require( deviceCFSetRef, Oops );
152
+
153
+ // how many devices in the set?
154
+ CFIndex deviceIndex, deviceCount = CFSetGetCount( deviceCFSetRef );
155
+
156
+ // allocate a block of memory to extact the device ref's from the set into
157
+ tIOHIDDeviceRefs = malloc( sizeof( IOHIDDeviceRef ) * deviceCount );
158
+ if (!tIOHIDDeviceRefs) {
159
+ CFRelease(deviceCFSetRef);
160
+ deviceCFSetRef = NULL;
161
+ goto Oops;
162
+ }
163
+
164
+ // now extract the device ref's from the set
165
+ CFSetGetValues( deviceCFSetRef, (const void **) tIOHIDDeviceRefs );
166
+ CFRelease(deviceCFSetRef);
167
+ deviceCFSetRef = NULL;
168
+
169
+ // before we get into the device loop we'll setup our element matching dictionary
170
+ matchingCFDictRef = hu_CreateMatchingDictionaryUsagePageUsage( FALSE, kHIDPage_LEDs, 0 );
171
+ require( matchingCFDictRef, Oops );
172
+
173
+ int pass; // do 256 passes
174
+ //for ( pass = 0; pass < 256; pass++ ) {
175
+ Boolean delayFlag = FALSE; // if we find an LED element we'll set this to TRUE
176
+
177
+ //printf( "pass = %d.\n", pass );
178
+ for ( deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++ ) {
179
+
180
+ // if this isn't a keyboard device...
181
+ if ( !IOHIDDeviceConformsTo( tIOHIDDeviceRefs[deviceIndex], kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard ) ) {
182
+ continue; // ...skip it
183
+ }
184
+
185
+ //printf( " device = %p.\n", tIOHIDDeviceRefs[deviceIndex] );
186
+
187
+ // copy all the elements
188
+ CFArrayRef elementCFArrayRef = IOHIDDeviceCopyMatchingElements( tIOHIDDeviceRefs[deviceIndex],
189
+ matchingCFDictRef,
190
+ kIOHIDOptionsTypeNone );
191
+ require( elementCFArrayRef, next_device );
192
+
193
+ // for each device on the system these values are divided by the value ranges of all LED elements found
194
+ // for example, if the first four LED element have a range of 0-1 then the four least significant bits of
195
+ // this value will be sent to these first four LED elements, etc.
196
+ int device_value = pass;
197
+
198
+ // iterate over all the elements
199
+ CFIndex elementIndex, elementCount = CFArrayGetCount( elementCFArrayRef );
200
+ for ( elementIndex = 0; elementIndex < elementCount; elementIndex++ ) {
201
+ IOHIDElementRef tIOHIDElementRef = ( IOHIDElementRef ) CFArrayGetValueAtIndex( elementCFArrayRef, elementIndex );
202
+ require( tIOHIDElementRef, next_element );
203
+
204
+ uint32_t usagePage = IOHIDElementGetUsagePage( tIOHIDElementRef );
205
+
206
+ // if this isn't an LED element...
207
+ if ( kHIDPage_LEDs != usagePage ) {
208
+ continue; // ...skip it
209
+ }
210
+
211
+ uint32_t usage = IOHIDElementGetUsage( tIOHIDElementRef );
212
+ IOHIDElementType tIOHIDElementType = IOHIDElementGetType( tIOHIDElementRef );
213
+
214
+ //printf( " element = %p (page: %d, usage: %d, type: %d ).\n",
215
+ // tIOHIDElementRef, usagePage, usage, tIOHIDElementType );
216
+
217
+ // get the logical mix/max for this LED element
218
+ CFIndex minCFIndex = IOHIDElementGetLogicalMin( tIOHIDElementRef );
219
+ CFIndex maxCFIndex = IOHIDElementGetLogicalMax( tIOHIDElementRef );
220
+
221
+ // calculate the range
222
+ CFIndex modCFIndex = maxCFIndex - minCFIndex + 1;
223
+
224
+ // compute the value for this LED element
225
+ //CFIndex tCFIndex = minCFIndex + ( device_value % modCFIndex );
226
+ CFIndex tCFIndex = led_value;
227
+ device_value /= modCFIndex;
228
+
229
+ //printf( " value = 0x%08lX.\n", tCFIndex );
230
+
231
+ uint64_t timestamp = 0; // create the IO HID Value to be sent to this LED element
232
+ IOHIDValueRef tIOHIDValueRef = IOHIDValueCreateWithIntegerValue( kCFAllocatorDefault, tIOHIDElementRef, timestamp, tCFIndex );
233
+ if ( tIOHIDValueRef ) {
234
+ // now set it on the device
235
+ tIOReturn = IOHIDDeviceSetValue( tIOHIDDeviceRefs[deviceIndex], tIOHIDElementRef, tIOHIDValueRef );
236
+ CFRelease( tIOHIDValueRef );
237
+ require_noerr( tIOReturn, next_element );
238
+ delayFlag = TRUE; // set this TRUE so we'll delay before changing our LED values again
239
+ }
240
+ next_element: ;
241
+ continue;
242
+ }
243
+ CFRelease( elementCFArrayRef );
244
+ next_device: ;
245
+ continue;
246
+ }
247
+
248
+ // if we found an LED we'll delay before continuing
249
+ //if ( delayFlag ) {
250
+ // usleep( 500000 ); // sleep one half second
251
+ //}
252
+
253
+ // if the mouse is down…
254
+ //if (GetCurrentButtonState()) {
255
+ // break; // abort pass loop
256
+ //}
257
+ //} // next pass
258
+
259
+ if ( matchingCFDictRef ) {
260
+ CFRelease( matchingCFDictRef );
261
+ }
262
+ Oops: ;
263
+ if ( tIOHIDDeviceRefs ) {
264
+ free(tIOHIDDeviceRefs);
265
+ }
266
+
267
+ if ( tIOHIDManagerRef ) {
268
+ CFRelease( tIOHIDManagerRef );
269
+ }
270
+ return 0;
271
+ } /* main */
314
272
 
315
273
  VALUE MacLight = Qnil;
316
274
 
317
275
  void Init_maclight();
318
276
 
319
- VALUE method_capslock(int argc, VALUE *argv, VALUE self);
320
- VALUE method_numlock(int argc, VALUE *argv, VALUE self);
277
+ //VALUE method_capslock(int argc, VALUE *argv, VALUE self);
278
+ //VALUE method_numlock(int argc, VALUE *argv, VALUE self);
279
+ VALUE method_all_leds(int argc, VALUE *argv, VALUE self);
321
280
 
322
281
  void Init_maclight() {
323
282
  MacLight = rb_define_module("MacLight");
324
- rb_define_singleton_method(MacLight, "capslock", method_capslock, -1);
325
- rb_define_singleton_method(MacLight, "numlock", method_numlock, -1);
283
+ //rb_define_singleton_method(MacLight, "capslock", method_capslock, -1);
284
+ //rb_define_singleton_method(MacLight, "numlock", method_numlock, -1);
285
+ rb_define_singleton_method(MacLight, "all_leds", method_all_leds, -1);
326
286
  }
327
287
 
328
288
  VALUE kbd_led(UInt32 whichLED, int argc, VALUE *argv, VALUE klass) {
@@ -342,11 +302,15 @@ VALUE kbd_led(UInt32 whichLED, int argc, VALUE *argv, VALUE klass) {
342
302
  return manipulate_led(whichLED, set_to) ? Qtrue : Qfalse;
343
303
  }
344
304
 
345
- VALUE method_capslock(int argc, VALUE *argv, VALUE klass) {
346
- return kbd_led(kHIDUsage_LED_CapsLock, argc, argv, klass);
305
+ VALUE method_all_leds(int argc, VALUE *argv, VALUE klass) {
306
+ return kbd_led(-1, argc, argv, klass);
347
307
  }
348
308
 
349
- VALUE method_numlock(int argc, VALUE *argv, VALUE klass) {
350
- return kbd_led(kHIDUsage_LED_NumLock, argc, argv, klass);
351
- }
309
+ //VALUE method_capslock(int argc, VALUE *argv, VALUE klass) {
310
+ // return kbd_led(kHIDUsage_LED_CapsLock, argc, argv, klass);
311
+ //}
312
+ //
313
+ //VALUE method_numlock(int argc, VALUE *argv, VALUE klass) {
314
+ // return kbd_led(kHIDUsage_LED_NumLock, argc, argv, klass);
315
+ //}
352
316
 
@@ -14,66 +14,109 @@ module MacLight
14
14
  end
15
15
  end
16
16
 
17
- desc "Toggle keyboard LEDs"
18
- text "Toggle keyboard LEDs (capslock, numlock)"
19
- opt :capslock, "Toggle capslock LED", :default => false
20
- opt :numlock, "Toggle numlock LED", :default => false
21
- opt :verbose, "Print current state of capslock, numlock"
22
- parent "keyboard", "Control keyboard LEDs"
23
- def toggle(cmd, opts, argv)
24
- raise Optix::HelpNeeded unless opts.values_at(:capslock, :numlock, :verbose).any?
25
- MacLight.capslock(!MacLight.capslock) if opts[:capslock]
26
- MacLight.numlock(!MacLight.numlock) if opts[:numlock]
27
- puts "#{MacLight.capslock ? 1:0} #{MacLight.numlock ? 1:0}" if opts[:verbose]
28
- end
17
+ # Commenting out most functionality
18
+ # until we get around to restore it.
19
+
20
+ # For now MacLight can only toggle all
21
+ # LEDs at once on and off.
22
+
23
+ #desc "Toggle keyboard LEDs"
24
+ #text "Toggle keyboard LEDs (capslock, numlock)"
25
+ #opt :capslock, "Toggle capslock LED", :default => false
26
+ #opt :numlock, "Toggle numlock LED", :default => false
27
+ #opt :verbose, "Print current state of capslock, numlock"
28
+ #parent "keyboard", "Control keyboard LEDs"
29
+ #def toggle(cmd, opts, argv)
30
+ # raise Optix::HelpNeeded unless opts.values_at(:capslock, :numlock, :verbose).any?
31
+ # MacLight.capslock(!MacLight.capslock) if opts[:capslock]
32
+ # MacLight.numlock(!MacLight.numlock) if opts[:numlock]
33
+ # puts "#{MacLight.capslock ? 1:0} #{MacLight.numlock ? 1:0}" if opts[:verbose]
34
+ #end
29
35
 
30
36
  desc "Set keyboard LEDs state"
31
37
  text "Set keyboard LEDs (capslock, numlock) state (on, off)"
32
- opt :capslock, "Set capslock LED (0|1)", :type => Integer
33
- opt :numlock, "Set numlock LED (0|1)", :type => Integer
34
- opt :verbose, "Print current state of capslock, numlock"
38
+ opt :all, "Set all LEDs (0|1)", :type => Integer
39
+ #opt :capslock, "Set capslock LED (0|1)", :type => Integer
40
+ #opt :numlock, "Set numlock LED (0|1)", :type => Integer
41
+ #opt :verbose, "Print current state of capslock, numlock"
35
42
  parent "keyboard"
36
43
  def set(cmd, opts, argv)
37
- raise Optix::HelpNeeded unless opts.values_at(:capslock, :numlock, :verbose).any?
38
- MacLight.capslock(1 == opts[:capslock]) unless opts[:capslock].nil?
39
- MacLight.numlock(1 == opts[:numlock]) unless opts[:numlock].nil?
40
- puts "#{MacLight.capslock ? 1:0} #{MacLight.numlock ? 1:0}" if opts[:verbose]
44
+ raise Optix::HelpNeeded unless opts.values_at(:all).any?
45
+ MacLight.all_leds(1 == opts[:all])
46
+ #MacLight.capslock(1 == opts[:capslock]) unless opts[:capslock].nil?
47
+ #MacLight.numlock(1 == opts[:numlock]) unless opts[:numlock].nil?
48
+ #puts "#{MacLight.capslock ? 1:0} #{MacLight.numlock ? 1:0}" if opts[:verbose]
41
49
  end
42
50
 
43
51
  desc "Blink keyboard LEDs"
44
- text "Blink keyboard LEDs (capslock, numlock)"
52
+ text "Blink keyboard LEDs"
45
53
  text ''
46
54
  text "Examples:"
47
- text " #{File.basename($0)} keyboard blink -r 3 -f 00 10:0.3 01:0.3"
48
- text " #{File.basename($0)} keyboard blink -r 3 10:0.3 01:0.2 00:0.1 11:0.2 00:0.07 11:0.07 00:0.07"
55
+ text " #{File.basename($0)} keyboard blink -r 3 -f 0 1:0.3 0:0.3"
56
+ text " #{File.basename($0)} keyboard blink -r 3 1:0.3 0:0.2 0:0.1 1:0.2 0:0.07 1:0.07 0:0.07"
49
57
  text ''
50
58
  text 'Parameters:'
51
- text ' <sequence> - Space-delimited sequence; CN:T CN:T ..'
52
- text ' C = capslock value, N = numlock value, T = time in seconds'
59
+ text ' <sequence> - Space-delimited sequence; V:T V:T ..'
60
+ text ' V = led value, T = time in seconds'
53
61
  opt :repeat, "Repetitions", :default => 0
54
62
  opt :fin, "Set this state after sequence has finished (CN)", :type => String
55
- opt :verbose, "Print state of capslock, numlock"
56
63
  params "<sequence>"
57
64
  parent "keyboard"
58
65
  def blink(cmd, opts, argv)
59
66
  raise Optix::HelpNeeded if argv.empty?
60
- puts "#{MacLight.capslock ? 1:0} #{MacLight.numlock ? 1:0}" if opts[:verbose]
61
- seq = argv.map {|e| ['1'==e[0],'1'==e[1],e[3..-1].to_f] }
67
+ seq = argv.map {|e| ['1'==e[0],e[2..-1].to_f] }
62
68
  (0..opts[:repeat]).each do |i|
63
69
  seq.each_with_index do |mode, step|
64
- MacLight.capslock(mode[0])
65
- MacLight.numlock(mode[1])
66
- puts "#{MacLight.capslock ? 1:0} #{MacLight.numlock ? 1:0}" if opts[:verbose]
67
- sleep mode[2]
70
+ MacLight.all_leds(mode[0])
71
+ sleep mode[1]
68
72
  end
69
73
  end
70
74
  if opts[:fin]
71
- MacLight.capslock('1'==opts[:fin][0])
72
- MacLight.numlock('1'==opts[:fin][1])
73
- puts "#{MacLight.capslock ? 1:0} #{MacLight.numlock ? 1:0}" if opts[:verbose]
75
+ MacLight.all_leds('1'==opts[:fin][0])
74
76
  end
75
77
  end
76
78
 
79
+ desc "Play a short test sequence"
80
+ text "Play a short test sequence"
81
+ parent "keyboard"
82
+ def test(cmd, opts, argv)
83
+ blink(nil, { :repeat => 3 }, %w(1:0.3 0:0.2 0:0.1 1:0.2 0:0.07 1:0.07 0:0.07))
84
+ end
85
+
86
+ #desc "Blink keyboard LEDs"
87
+ #text "Blink keyboard LEDs (capslock, numlock)"
88
+ #text ''
89
+ #text "Examples:"
90
+ #text " #{File.basename($0)} keyboard blink -r 3 -f 00 10:0.3 01:0.3"
91
+ #text " #{File.basename($0)} keyboard blink -r 3 10:0.3 01:0.2 00:0.1 11:0.2 00:0.07 11:0.07 00:0.07"
92
+ #text ''
93
+ #text 'Parameters:'
94
+ #text ' <sequence> - Space-delimited sequence; CN:T CN:T ..'
95
+ #text ' C = capslock value, N = numlock value, T = time in seconds'
96
+ #opt :repeat, "Repetitions", :default => 0
97
+ #opt :fin, "Set this state after sequence has finished (CN)", :type => String
98
+ #opt :verbose, "Print state of capslock, numlock"
99
+ #params "<sequence>"
100
+ #parent "keyboard"
101
+ #def blink(cmd, opts, argv)
102
+ # raise Optix::HelpNeeded if argv.empty?
103
+ # puts "#{MacLight.capslock ? 1:0} #{MacLight.numlock ? 1:0}" if opts[:verbose]
104
+ # seq = argv.map {|e| ['1'==e[0],'1'==e[1],e[3..-1].to_f] }
105
+ # (0..opts[:repeat]).each do |i|
106
+ # seq.each_with_index do |mode, step|
107
+ # MacLight.capslock(mode[0])
108
+ # MacLight.numlock(mode[1])
109
+ # puts "#{MacLight.capslock ? 1:0} #{MacLight.numlock ? 1:0}" if opts[:verbose]
110
+ # sleep mode[2]
111
+ # end
112
+ # end
113
+ # if opts[:fin]
114
+ # MacLight.capslock('1'==opts[:fin][0])
115
+ # MacLight.numlock('1'==opts[:fin][1])
116
+ # puts "#{MacLight.capslock ? 1:0} #{MacLight.numlock ? 1:0}" if opts[:verbose]
117
+ # end
118
+ #end
119
+
77
120
  def self.start
78
121
  Optix.invoke!
79
122
  end
@@ -1,3 +1,3 @@
1
1
  module MacLight
2
- VERSION = "2.0.0"
2
+ VERSION = "3.0.0"
3
3
  end
metadata CHANGED
@@ -1,41 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: maclight
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Moe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-21 00:00:00.000000000 Z
11
+ date: 2016-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: optix
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: 1.2.2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.2.2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: 10.1.0
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 10.1.0
41
41
  description: Control your Mac keyboard LEDs (capslock, numlock)
@@ -47,7 +47,7 @@ extensions:
47
47
  - ext/maclight/extconf.rb
48
48
  extra_rdoc_files: []
49
49
  files:
50
- - .gitignore
50
+ - ".gitignore"
51
51
  - Gemfile
52
52
  - LICENSE.txt
53
53
  - README.md
@@ -69,17 +69,17 @@ require_paths:
69
69
  - lib
70
70
  required_ruby_version: !ruby/object:Gem::Requirement
71
71
  requirements:
72
- - - '>='
72
+ - - ">="
73
73
  - !ruby/object:Gem::Version
74
74
  version: '0'
75
75
  required_rubygems_version: !ruby/object:Gem::Requirement
76
76
  requirements:
77
- - - '>='
77
+ - - ">="
78
78
  - !ruby/object:Gem::Version
79
79
  version: '0'
80
80
  requirements: []
81
81
  rubyforge_project:
82
- rubygems_version: 2.0.14
82
+ rubygems_version: 2.5.1
83
83
  signing_key:
84
84
  specification_version: 4
85
85
  summary: Control your Mac keyboard LEDs (capslock, numlock)