--- /dev/null
+#include <CoreFoundation/CoreFoundation.h>
+#include <IOKit/hid/IOHIDLib.h>
+#include <IOKit/IOKitLib.h>
+#include <unistd.h>
+#include <vector>
+
+const CFStringRef kPrefDomain = CFSTR("com.apple.driver.AppleIRController");
+const CFStringRef kPrefEnabled = CFSTR("DeviceEnabled");
+
+bool VERBOSE = true;
+
+#define LOG(msg, ...) do { \
+ if (VERBOSE) { \
+ printf(msg " [%s:%d]\n", ##__VA_ARGS__, __FILE__, __LINE__); \
+ } \
+ } while(0)
+#define ERROR(msg, ...) fprintf(stderr, msg " [%s:%d]\n", ##__VA_ARGS__, __FILE__, __LINE__)
+
+class ScopedIOHIDManager {
+ public:
+ ScopedIOHIDManager()
+ : manager_(IOHIDManagerCreate(nullptr, kIOHIDManagerOptionNone)) {}
+
+ ~ScopedIOHIDManager() {
+ IOHIDManagerClose(manager_, kIOHIDManagerOptionNone);
+ }
+
+ ScopedIOHIDManager(const ScopedIOHIDManager&) = delete;
+
+ bool Open() {
+ IOReturn ret = IOHIDManagerOpen(manager_, kIOHIDManagerOptionNone);
+ if (ret != kIOReturnSuccess) {
+ ERROR("Failed to IOHIDManagerOpen: 0x%x", ret);
+ return false;
+ }
+ return true;
+ }
+
+ IOHIDManagerRef get() { return manager_; }
+
+ private:
+ IOHIDManagerRef manager_;
+};
+
+template <typename T>
+class ScopedCFTypeRef {
+ public:
+ ScopedCFTypeRef(T t = nullptr) : t_(t) {}
+ ~ScopedCFTypeRef() {
+ if (t_) {
+ CFRelease(t_);
+ }
+ }
+
+ ScopedCFTypeRef(const ScopedCFTypeRef<T>&) = delete;
+
+ operator bool() { return t_ != nullptr; }
+
+ T get() { return t_; }
+
+ T* pointer_to() { return &t_; }
+
+ private:
+ T t_;
+};
+
+bool IsIRAvailable() {
+ ScopedIOHIDManager manager;
+ IOHIDManagerSetDeviceMatching(manager.get(), nullptr);
+ if (!manager.Open()) {
+ //return false;
+ }
+ ScopedCFTypeRef<CFSetRef> devices(IOHIDManagerCopyDevices(manager.get()));
+ if (!devices) {
+ ERROR("Failed to IOHIDManagerCopyDevices");
+ return false;
+ }
+ std::vector<void*> devices_array(CFSetGetCount(devices.get()), nullptr);
+ CFSetGetValues(devices.get(), const_cast<const void**>(devices_array.data()));
+ for (const auto& device : devices_array) {
+ CFTypeRef prop =
+ IOHIDDeviceGetProperty(reinterpret_cast<IOHIDDeviceRef>(device),
+ CFSTR("HIDRemoteControl"));
+ if (prop) {
+ if (VERBOSE) {
+ LOG("Located HIDRemoteControl:");
+ CFShow(device);
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+CFTypeRef GetUserPropertyValue() {
+ return CFPreferencesCopyValue(kPrefEnabled, kPrefDomain,
+ kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
+}
+
+int HandleRead() {
+ CFTypeRef user_prop = GetUserPropertyValue();
+ CFShow(user_prop);
+
+ CFMutableDictionaryRef matching_dict = IOServiceMatching("AppleIRController");
+ io_iterator_t iterator;
+ kern_return_t kr = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dict, &iterator);
+ if (kr != KERN_SUCCESS) {
+ ERROR("Failed to IOServiceGetMatchingServices: 0x%x", kr);
+ return EXIT_FAILURE;
+ }
+
+ io_object_t service;
+ bool did_find = false;
+ while ((service = IOIteratorNext(iterator))) {
+ did_find = true;
+
+ io_name_t name;
+ kern_return_t kr = IORegistryEntryGetName(service, name);
+ if (kr != KERN_SUCCESS) {
+ ERROR("Failed to IORegistryEntryGetName: 0x%x", kr);
+ continue;
+ }
+
+ LOG("Found AppleIRController: %s", name);
+
+ ScopedCFTypeRef<CFTypeRef> device_enabled(
+ IORegistryEntryCreateCFProperty(service, kPrefEnabled, nullptr, 0));
+ CFShow(device_enabled.get());
+
+#if 0
+ ScopedCFTypeRef<CFMutableDictionaryRef> props;
+ kr = IORegistryEntryCreateCFProperties(service, props.pointer_to(), nullptr, 0);
+ if (kr != KERN_SUCCESS) {
+ ERROR("Failed to IORegistryEntryCreateCFProperties(%s) = 0x%x", name, kr);
+ continue;
+ }
+ CFShow(props.get());
+#endif
+ }
+
+ if (!did_find) {
+ ERROR("Failed to match AppleIRController");
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+int HandleWrite(bool enable) {
+ return EXIT_SUCCESS;
+}
+
+int main(int argc, char* argv[]) {
+ if (!IsIRAvailable()) {
+ ERROR("No HIDRemoteControl available");
+ return EXIT_FAILURE;
+ }
+
+ if (argc == 1) {
+ return HandleRead();
+ } else if (argc == 2) {
+ if (strcmp("on", argv[1])) {
+ return HandleWrite(true);
+ } else if (strcmp("off", argv[1])) {
+ return HandleWrite(false);
+ }
+ }
+
+ fprintf(stderr, "Usage: %s [on|off]\n", argv[0]);
+ return EXIT_FAILURE;
+}