maclight 2.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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)