#include "dbus.h" #ifdef FF_HAVE_DBUS #include "common/thread.h" #include "util/stringUtils.h" static bool loadLibSymbols(FFDBusLibrary* lib) { FF_LIBRARY_LOAD(dbus, &instance.config.library.libDBus, false, "libdbus-1" FF_LIBRARY_EXTENSION, 4); FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_bus_get, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_new_method_call, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_init, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_init_append, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_append_basic, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_get_arg_type, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_get_basic, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_recurse, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_has_next, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_next, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_unref, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_connection_send_with_reply_and_block, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_connection_flush, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_block, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_steal_reply, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_unref, false) dbus = NULL; // don't auto dlclose return true; } static const FFDBusLibrary* loadLib(void) { static FFDBusLibrary lib; static bool loaded = false; static bool loadSuccess = false; if(!loaded) { loaded = true; loadSuccess = loadLibSymbols(&lib); } return loadSuccess ? &lib : NULL; } const char* ffDBusLoadData(DBusBusType busType, FFDBusData* data) { data->lib = loadLib(); if(data->lib == NULL) return "Failed to load DBus library"; data->connection = data->lib->ffdbus_bus_get(busType, NULL); if(data->connection == NULL) return "Failed to connect to DBus"; return NULL; } bool ffDBusGetValue(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result) { int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter); if(argType == DBUS_TYPE_STRING) { const char* value = NULL; dbus->lib->ffdbus_message_iter_get_basic(iter, &value); if(!ffStrSet(value)) return false; ffStrbufAppendS(result, value); return true; } if(argType != DBUS_TYPE_VARIANT && argType != DBUS_TYPE_ARRAY) return false; DBusMessageIter subIter; dbus->lib->ffdbus_message_iter_recurse(iter, &subIter); if(argType == DBUS_TYPE_VARIANT) return ffDBusGetValue(dbus, &subIter, result); //At this point we have an array bool foundAValue = false; while(true) { if(ffDBusGetValue(dbus, &subIter, result)) { foundAValue = true; ffStrbufAppendS(result, ", "); } FF_DBUS_ITER_CONTINUE(dbus, &subIter); } if(foundAValue) ffStrbufSubstrBefore(result, result->length - 2); return foundAValue; } bool ffDBusGetBool(FFDBusData* dbus, DBusMessageIter* iter, bool* result) { int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter); if(argType == DBUS_TYPE_BOOLEAN) { dbus_bool_t value = 0; dbus->lib->ffdbus_message_iter_get_basic(iter, &value); *result = value != 0; return true; } if(argType != DBUS_TYPE_VARIANT) return false; DBusMessageIter subIter; dbus->lib->ffdbus_message_iter_recurse(iter, &subIter); return ffDBusGetBool(dbus, &subIter, result); } bool ffDBusGetByte(FFDBusData* dbus, DBusMessageIter* iter, uint8_t* result) { int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter); if(argType == DBUS_TYPE_BYTE) { dbus->lib->ffdbus_message_iter_get_basic(iter, result); return true; } if(argType != DBUS_TYPE_VARIANT) return false; DBusMessageIter subIter; dbus->lib->ffdbus_message_iter_recurse(iter, &subIter); return ffDBusGetByte(dbus, &subIter, result); } DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method) { DBusMessage* message = dbus->lib->ffdbus_message_new_method_call(busName, objectPath, interface, method); if(message == NULL) return NULL; DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, FF_DBUS_TIMEOUT_MILLISECONDS, NULL); dbus->lib->ffdbus_message_unref(message); return reply; } DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property) { DBusMessage* message = dbus->lib->ffdbus_message_new_method_call(busName, objectPath, "org.freedesktop.DBus.Properties", "Get"); if(message == NULL) return NULL; DBusMessageIter requestIterator; dbus->lib->ffdbus_message_iter_init_append(message, &requestIterator); if(!dbus->lib->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &interface)) { dbus->lib->ffdbus_message_unref(message); return NULL; } if(!dbus->lib->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &property)) { dbus->lib->ffdbus_message_unref(message); return NULL; } DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, FF_DBUS_TIMEOUT_MILLISECONDS, NULL); dbus->lib->ffdbus_message_unref(message); return reply; } void ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result) { DBusMessage* reply = ffDBusGetProperty(dbus, busName, objectPath, interface, property); if(reply == NULL) return; DBusMessageIter rootIterator; if(!dbus->lib->ffdbus_message_iter_init(reply, &rootIterator)) { dbus->lib->ffdbus_message_unref(reply); return; } ffDBusGetValue(dbus, &rootIterator, result); dbus->lib->ffdbus_message_unref(reply); } #endif //FF_HAVE_DBUS