1 #include <CoreFoundation/CoreFoundation.h>
2 #include <IOKit/hid/IOHIDLib.h>
3 #include <IOKit/IOKitLib.h>
7 const CFStringRef kPrefDomain
= CFSTR("com.apple.driver.AppleIRController");
8 const CFStringRef kPrefEnabled
= CFSTR("DeviceEnabled");
12 #define LOG(msg, ...) do { \
14 printf(msg " [%s:%d]\n", ##__VA_ARGS__, __FILE__, __LINE__); \
17 #define ERROR(msg, ...) fprintf(stderr, msg " [%s:%d]\n", ##__VA_ARGS__, __FILE__, __LINE__)
19 class ScopedIOHIDManager
{
22 : manager_(IOHIDManagerCreate(nullptr, kIOHIDManagerOptionNone
)) {}
24 ~ScopedIOHIDManager() {
25 IOHIDManagerClose(manager_
, kIOHIDManagerOptionNone
);
28 ScopedIOHIDManager(const ScopedIOHIDManager
&) = delete;
31 IOReturn ret
= IOHIDManagerOpen(manager_
, kIOHIDManagerOptionNone
);
32 if (ret
!= kIOReturnSuccess
) {
33 ERROR("Failed to IOHIDManagerOpen: 0x%x", ret
);
39 IOHIDManagerRef
get() { return manager_
; }
42 IOHIDManagerRef manager_
;
46 class ScopedCFTypeRef
{
48 ScopedCFTypeRef(T t
= nullptr) : t_(t
) {}
55 ScopedCFTypeRef(const ScopedCFTypeRef
<T
>&) = delete;
57 operator bool() { return t_
!= nullptr; }
59 T
get() { return t_
; }
61 T
* pointer_to() { return &t_
; }
67 bool IsIRAvailable() {
68 ScopedIOHIDManager manager
;
69 IOHIDManagerSetDeviceMatching(manager
.get(), nullptr);
70 if (!manager
.Open()) {
73 ScopedCFTypeRef
<CFSetRef
> devices(IOHIDManagerCopyDevices(manager
.get()));
75 ERROR("Failed to IOHIDManagerCopyDevices");
78 std
::vector
<void*> devices_array(CFSetGetCount(devices
.get()), nullptr);
79 CFSetGetValues(devices
.get(), const_cast<const void**>(devices_array
.data()));
80 for (const auto& device
: devices_array
) {
82 IOHIDDeviceGetProperty(reinterpret_cast<IOHIDDeviceRef
>(device
),
83 CFSTR("HIDRemoteControl"));
86 LOG("Located HIDRemoteControl:");
95 CFTypeRef
GetUserPropertyValue() {
96 return CFPreferencesCopyValue(kPrefEnabled
, kPrefDomain
,
97 kCFPreferencesAnyUser
, kCFPreferencesCurrentHost
);
101 CFTypeRef user_prop
= GetUserPropertyValue();
104 CFMutableDictionaryRef matching_dict
= IOServiceMatching("AppleIRController");
105 io_iterator_t iterator
;
106 kern_return_t kr
= IOServiceGetMatchingServices(kIOMasterPortDefault
, matching_dict
, &iterator
);
107 if (kr
!= KERN_SUCCESS
) {
108 ERROR("Failed to IOServiceGetMatchingServices: 0x%x", kr
);
113 bool did_find
= false;
114 while ((service
= IOIteratorNext(iterator
))) {
118 kern_return_t kr
= IORegistryEntryGetName(service
, name
);
119 if (kr
!= KERN_SUCCESS
) {
120 ERROR("Failed to IORegistryEntryGetName: 0x%x", kr
);
124 LOG("Found AppleIRController: %s", name
);
126 ScopedCFTypeRef
<CFTypeRef
> device_enabled(
127 IORegistryEntryCreateCFProperty(service
, kPrefEnabled
, nullptr, 0));
128 CFShow(device_enabled
.get());
131 ScopedCFTypeRef
<CFMutableDictionaryRef
> props
;
132 kr
= IORegistryEntryCreateCFProperties(service
, props
.pointer_to(), nullptr, 0);
133 if (kr
!= KERN_SUCCESS
) {
134 ERROR("Failed to IORegistryEntryCreateCFProperties(%s) = 0x%x", name
, kr
);
142 ERROR("Failed to match AppleIRController");
149 int HandleWrite(bool enable
) {
153 int main(int argc
, char* argv
[]) {
154 if (!IsIRAvailable()) {
155 ERROR("No HIDRemoteControl available");
161 } else if (argc
== 2) {
162 if (strcmp("on", argv
[1])) {
163 return HandleWrite(true);
164 } else if (strcmp("off", argv
[1])) {
165 return HandleWrite(false);
169 fprintf(stderr
, "Usage: %s [on|off]\n", argv
[0]);