forked from supermari0/WizardKeys
/
KBLKeyboardBacklightService.c
159 lines (141 loc) · 5.01 KB
/
KBLKeyboardBacklightService.c
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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
/* MacKeyLEDAPI.c
* This implements a few functions for accessing and modifying the keyboard
* lights on Mac laptops in OS X 10.6 and above.
*
* By Mario Villaplana http://www.stanford.edu/~mariojv
*
* Inspired by/some code taken from Amit Singh's site below the header
* inclusions.
*
* I also looked at some posts on these mailing lists and forums to figure out
* how to handle some deprecated functions from Amit's site:
* http://forums.macrumors.com/archive/index.php/t-1133446.html
* http://lists.apple.com/archives/darwin-drivers/2008/mar/msg00022.html
* http://lists.apple.com/archives/darwin-drivers/2008/Jan/msg00070.html
*
*
* UPDATE
*/
#include "KBLKeyboardBacklightService.h"
#include <mach/mach.h>
#include <IOKit/IOKitLib.h>
/* This enum defines the different functions available for hardware
* manipulation by the IOConnectCallMethod. Taken directly from Amit Singh's
* OSX Internals website at http://osxbook.com/book/bonus/chapter10/light/. */
enum {
kGetSensorReadingID = 0, // getSensorReading(int *, int *)
kGetLEDBrightnessID = 1, // getLEDBrightness(int, int *)
kSetLEDBrightnessID = 2, // setLEDBrightness(int, int, int *)
kSetLEDFadeID = 3, // setLEDFade(int, int, int, int *)
// other firmware-related functions
// verifyFirmwareID = 4, // verifyFirmware(int *)
// getFirmwareVersionID = 5, // getFirmwareVersion(int *)
// other flashing-related functions
// ...
};
/* This defines the connection used by the IOConnectCall methods. Must be set
* by the startLightService function before being used.
*
* UPDATE
* Renamed by Flávio Caetano in 2015-06-24
*/
static io_connect_t conn = 0;
/* This function performs initialization work to ensure that the connection to
* the service performing keyboard LED modifications is open. It modifies the
* io_connect_t connect used throughout the implementation.
*
* UPDATE
* Renamed by Flávio Caetano in 2015-06-24
*/
void KBLStartLightService() {
if (conn != 0) return;
kern_return_t kr;
io_service_t serviceObject;
// Find a service object for the controller.
serviceObject = IOServiceGetMatchingService(kIOMasterPortDefault,
IOServiceMatching("AppleLMUController"));
// Check a matching service object was found
if (!serviceObject) {
fprintf(stderr, "Failed to find service matching \"AppleLMUController\".\
Ending program.");
exit(1);
}
// Open the matching service. The static variable connect is used to allow
// communication with the IOConnect APIs.
kr = IOServiceOpen(serviceObject, mach_task_self(), 0, &conn);
// Release the service object and clean up, checking for errors.
IOObjectRelease(serviceObject);
if(kr != KERN_SUCCESS) {
mach_error("IOServiceOpen: ", kr);
exit(kr);
}
}
/* Returns a value between 0 and 0xfff indicating the brightness of the
* keyboard LED light.
*
* UPDATE
* Renamed by Flávio Caetano in 2015-06-24
*/
uint64_t KBLGetKeyboardLEDValue() {
kern_return_t kr;
IOItemCount inputCount = 1;
IOItemCount outputCount = 1;
uint64_t outValue = 5;
const uint64_t fakeInput = 0; // Function requires fake input.
kr = IOConnectCallMethod(conn, kGetLEDBrightnessID, &fakeInput, inputCount, nil,
0, &outValue, &outputCount, nil, 0);
if (kr != KERN_SUCCESS) {
mach_error("IOConnectCallMethod: ", kr);
}
return outValue;
}
/* Sets the keyboard LED brightness to a value between 0 and 0xfff.
*
* UPDATE
* Renamed by Flávio Caetano in 2015-06-24
*/
void KBLSetKeyboardLEDValue(uint64_t ledValue) {
if (ledValue > 0xfff) {
fprintf(stderr, "ledValue is higher than the maximum value, 0xfff. Ending\
program to avoid hardware funkiness.");
exit(1);
}
kern_return_t kr;
IOItemCount inputCount = 2; // 2 inputs are needed because of fake input var.
IOItemCount outputCount = 1; // Fake output is needed.
uint64_t fakeOutput = 0;
uint64_t inValues[2];
inValues[0] = 0;
inValues[1] = ledValue;
kr = IOConnectCallMethod(conn, kSetLEDBrightnessID, inValues, inputCount,
nil, 0, &fakeOutput, &outputCount, nil, 0);
if (kr != KERN_SUCCESS) {
mach_error("IOConnectCallMethod: ", kr);
}
}
/* Set keyboard LED brightness to a value between 0 and 0xfff, fading the
change in brightness over time_ms milliseconds.
*
* UPDATE
* Renamed by Flávio Caetano in 2015-06-24
*/
void KBLSetKeyboardLEDValueFade(uint64_t ledValue, uint64_t time_ms) {
if (ledValue > 0xfff) {
fprintf(stderr, "ledValue is higher than the maximum value, 0xfff. Ending\
program to avoid hardware funkiness.");
exit(1);
}
kern_return_t kr;
IOItemCount inputCount = 3; // 3 inputs are needed because of fake input var.
IOItemCount outputCount = 1; // Fake output is needed.
uint64_t fakeOutput = 0;
uint64_t inValues[3];
inValues[0] = 0;
inValues[1] = ledValue;
inValues[2] = time_ms;
kr = IOConnectCallMethod(conn, kSetLEDFadeID, inValues, inputCount,
nil, 0, &fakeOutput, &outputCount, nil, 0);
if (kr != KERN_SUCCESS) {
mach_error("IOConnectCallMethod: ", kr);
}
}