+//
+// apple-ir-control
+// Copyright (c) 2016, Robert Sesek <https://www.bluestatic.org>
+//
+// This program is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free Software
+// Foundation, either version 3 of the License, or any later version.
+//
+
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/hid/IOHIDLib.h>
#include <IOKit/IOKitLib.h>
const CFStringRef kPrefEnabled = CFSTR("DeviceEnabled");
#if NDEBUG
-bool VERBOSE = false;
+const bool VERBOSE = false;
#else
-bool VERBOSE = true;
+const bool VERBOSE = true;
#endif
+#define LOCATION_LINE(x) #x
+#define LOCATION(line) __FILE__ ":" LOCATION_LINE(line)
+
#define LOG(msg, ...) do { \
if (VERBOSE) { \
- printf(msg " [%s:%d]\n", ##__VA_ARGS__, __FILE__, __LINE__); \
+ printf("[" LOCATION(__LINE__) "] " msg "\n", ##__VA_ARGS__); \
} \
} while(0)
-#define ERROR(msg, ...) fprintf(stderr, msg " [%s:%d]\n", ##__VA_ARGS__, __FILE__, __LINE__)
+#define ERROR(msg, ...) fprintf(stderr, "[" LOCATION(__LINE__) "] " msg "\n", ##__VA_ARGS__)
class ScopedIOHIDManager {
public:
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) {
bool SynchronizePrefs() {
bool rv = CFPreferencesSynchronize(kPrefDomain, kCFPreferencesAnyUser,
- kCFPreferencesCurrentHost);
+ kCFPreferencesCurrentHost);
if (!rv) {
ERROR("Failed to CFPreferencesSynchronize");
}
return rv;
}
-CFTypeRef GetUserPropertyValue() {
- return CFPreferencesCopyValue(kPrefEnabled, kPrefDomain,
- kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
-}
-
-io_iterator_t CreateIOServiceIterator() {
+bool CreateIOServiceIterator(io_iterator_t* iterator) {
CFMutableDictionaryRef matching_dict = IOServiceMatching("AppleIRController");
- io_iterator_t iterator;
kern_return_t kr = IOServiceGetMatchingServices(
- kIOMasterPortDefault, matching_dict, &iterator);
+ kIOMasterPortDefault, matching_dict, iterator);
if (kr != KERN_SUCCESS) {
ERROR("Failed to IOServiceGetMatchingServices: 0x%x", kr);
- return 0;
+ return false;
}
- return iterator;
+ return true;;
}
int HandleRead() {
- if (!SynchronizePrefs())
- return EXIT_FAILURE;
-
- CFTypeRef user_prop = GetUserPropertyValue();
+ CFTypeRef user_prop = CFPreferencesCopyValue(kPrefEnabled, kPrefDomain,
+ kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
printf("Userspace property value: %s\n", GetBooleanDescription(user_prop));
- io_iterator_t iterator = CreateIOServiceIterator();
- if (!iterator)
+ io_iterator_t iterator;
+ if (!CreateIOServiceIterator(&iterator))
return EXIT_FAILURE;
io_object_t service;
IORegistryEntryCreateCFProperty(service, kPrefEnabled, nullptr, 0));
printf("Kernel property value %s: %s\n",
name, GetBooleanDescription(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");
+ ERROR("Failed to match any AppleIRController");
return EXIT_FAILURE;
}
}
int HandleWrite(bool enable) {
+ if (geteuid() != 0) {
+ ERROR("This operation must be performed as root");
+ return EXIT_FAILURE;
+ }
+
const CFBooleanRef enabled_value = enable ? kCFBooleanTrue : kCFBooleanFalse;
CFPreferencesSetValue(kPrefEnabled, enabled_value, kPrefDomain,
if (!SynchronizePrefs())
return EXIT_FAILURE;
- io_iterator_t iterator = CreateIOServiceIterator();
+ io_iterator_t iterator;
+ if (!CreateIOServiceIterator(&iterator))
+ return EXIT_FAILURE;
+
io_object_t service;
while ((service = IOIteratorNext(iterator))) {
io_name_t name;