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 +4 -4
- data/README.md +10 -10
- data/ext/maclight/maclight.c +275 -311
- data/lib/maclight/cli.rb +77 -34
- data/lib/maclight/version.rb +1 -1
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b24508bb26e8dd38759e7ac95fa0ff03f6526a08
|
4
|
+
data.tar.gz: f97b6d155204e429e3c869bd16ec2dc8ccc8cc76
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
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
|
39
|
-
MacLight.
|
40
|
-
MacLight.numlock(true)
|
38
|
+
# Turn LEDs on
|
39
|
+
MacLight.all_leds(true)
|
41
40
|
|
42
41
|
sleep 2
|
43
42
|
|
44
|
-
# Turn
|
45
|
-
MacLight.
|
46
|
-
MacLight.numlock(false)
|
43
|
+
# Turn LEDs off
|
44
|
+
MacLight.all_leds(false)
|
47
45
|
```
|
48
46
|
|
49
|
-
##
|
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).
|
data/ext/maclight/maclight.c
CHANGED
@@ -1,328 +1,288 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
-
|
35
|
-
#
|
36
|
-
#
|
37
|
-
|
38
|
-
#include <mach/mach_error.h>
|
58
|
+
// ****************************************************
|
59
|
+
#pragma mark -
|
60
|
+
#pragma mark * includes & imports *
|
61
|
+
// ----------------------------------------------------
|
39
62
|
|
40
|
-
#include <
|
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
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
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
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
{
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
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
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
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
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
}
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
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
|
346
|
-
return kbd_led(
|
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
|
350
|
-
return kbd_led(
|
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
|
|
data/lib/maclight/cli.rb
CHANGED
@@ -14,66 +14,109 @@ module MacLight
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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 :
|
33
|
-
opt :
|
34
|
-
opt :
|
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(:
|
38
|
-
MacLight.
|
39
|
-
MacLight.
|
40
|
-
|
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
|
52
|
+
text "Blink keyboard LEDs"
|
45
53
|
text ''
|
46
54
|
text "Examples:"
|
47
|
-
text " #{File.basename($0)} keyboard blink -r 3 -f
|
48
|
-
text " #{File.basename($0)} keyboard blink -r 3
|
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;
|
52
|
-
text '
|
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
|
-
|
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.
|
65
|
-
|
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.
|
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
|
data/lib/maclight/version.rb
CHANGED
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:
|
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:
|
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.
|
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)
|