/************************************************************************** * Copyright (C) 2006-2007 by Danny Kukawka * * , * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of version 2 of the GNU General Public License * * as published by the Free Software Foundation. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ /*! * \file dbusHAL.cpp * \brief In this file can be found the functionality to connect to * the HAL daemon via D-Bus, to handle D-Bus calls/events and to * provide wrapper to HAL lib and functions * \author Danny Kukawka, , * \date 2006-2007 */ // KDE Header #include // DBUS - Header #include "dbusHAL.h" // system headers #include static void* myInstance = 0; /*! The default constructor of the class dbusHAL. */ dbusHAL::dbusHAL(){ kdDebugFuncIn(trace); dbus_is_connected = false; hal_is_connected = false; acquiredPolicyPower = false; hal_ctx = NULL; // add pointer to this for filter_function() myInstance=this; // init connection to dbus if(!initDBUS()) { kdError() << "Can't connect to D-Bus" << endl; m_dBusQtConnection = NULL; } if(!initHAL()) kdError() << "Can't connect to HAL" << endl; kdDebugFuncOut(trace); } /*! This is the default destructor of class dbusPowersaveConnection. */ dbusHAL::~dbusHAL(){ kdDebugFuncIn(trace); close(); myInstance = NULL; kdDebugFuncOut(trace); } /*! * This function return information about connection status to the DBUS daemon. * \return boolean with the state of the connection to D-Bus * \retval true if connected * \retval false if disconnected */ bool dbusHAL::isConnectedToDBUS() { return dbus_is_connected; } /*! * This function return information about connection status to the HAL daemon. * \return boolean with the state of the connection to HAL * \retval true if connected * \retval false if disconnected */ bool dbusHAL::isConnectedToHAL() { return hal_is_connected; } /*! * This function return information if the org.freedesktop.Policy.Power * interface was claimed. * \return boolean with the status of claim the interface * \retval true if acquired * \retval false if not */ bool dbusHAL::acquiredPolicyPowerInterface() { return acquiredPolicyPower; } /*! * This function try a reconnect to D-Bus and HAL daemon. * \return boolean with the result of the operation * \retval true if successful reconnected to D-Bus and HAL * \retval false if unsuccessful */ bool dbusHAL::reconnect() { // free HAL context freeHAL(); // close D-Bus connection close(); // init D-Bus conntection and HAL context return (initDBUS() && initHAL()); } /*! * This function close the connection to powersave over the D-Bus daemon. * \return boolean with the result of the operation * \retval true if successful closed the connection * \retval false if any problems */ bool dbusHAL::close() { if ( m_dBusQtConnection != NULL ) { releasePolicyPowerIface(); m_dBusQtConnection->close(); m_dBusQtConnection = NULL; } dbus_is_connected = false; return true; } /* ----> D-Bus section :: START <---- */ /*! * This function initialise the connection to the D-Bus daemon. * \return boolean with the result of the operation * \retval true if successful initialised D-Bus connection * \retval false if unsuccessful */ bool dbusHAL::initDBUS(){ kdDebugFuncIn(trace); dbus_is_connected = false; DBusError error; dbus_error_init(&error); dbus_connection = dbus_bus_get( DBUS_BUS_SYSTEM, &error ); if (dbus_connection == NULL){ kdError() << "Failed to open connection to system message bus: " << error.message << endl; dbus_error_free (&error); return false; } if ( dbus_error_is_set( &error ) ) { kdError() << "Failed to register connection with system message bus: " << error.message << endl; return false; } acquirePolicyPowerIface(); dbus_connection_set_exit_on_disconnect( dbus_connection, false ); /* add the filter function which should be executed on events on the bus */ if ( ! dbus_connection_add_filter( dbus_connection, filterFunction, this, NULL) ) { kdFatal() << "Error: Not enough memory to add filter to dbus connection" << endl; exit(EXIT_FAILURE); } /* add a match rule to catch all signals going through the bus with D-Bus interface */ dbus_bus_add_match( dbus_connection, "type='signal'," "interface='org.freedesktop.DBus'," "member='NameOwnerChanged'", NULL); /* add a match rule to catch all signals going through the bus with HAL interface */ dbus_bus_add_match( dbus_connection, "type='signal'," "interface='org.freedesktop.Hal.Manager'," "member='DeviceAdded'", NULL); dbus_bus_add_match( dbus_connection, "type='signal'," "interface='org.freedesktop.Hal.Manager'," "member='DeviceRemoved'", NULL); dbus_bus_add_match( dbus_connection, "type='signal'," "interface='org.freedesktop.Hal.Device'," "member='PropertyModified'", NULL); dbus_bus_add_match( dbus_connection, "type='signal'," "interface='org.freedesktop.Hal.Device'," "member='Condition'", NULL); /* add a match rule to catch all signals going through the bus with ConsoleKit Interface */ dbus_bus_add_match( dbus_connection, "type='signal'," "interface='org.freedesktop.ConsoleKit.Session'," "member='ActiveChanged'", NULL); m_dBusQtConnection = new DBusQt::Connection(this); m_dBusQtConnection->dbus_connection_setup_with_qt_main(dbus_connection); dbus_is_connected = true; kdDebugFuncOut(trace); return true; } /*! * This function acquire the org.freedesktop.Policy.Power interface * \return boolean with the result of the operation * \retval true if successful acquired the interface * \retval false if unsuccessful */ bool dbusHAL::acquirePolicyPowerIface(){ kdDebugFuncIn(trace); if (dbus_connection == NULL) { kdDebugFuncOut(trace); return false; } DBusError err; dbus_error_init(&err); int ret = dbus_bus_request_name(dbus_connection, "org.freedesktop.Policy.Power", DBUS_NAME_FLAG_REPLACE_EXISTING, &err); if (dbus_error_is_set(&err)) { kdWarning() << "Acquire org.freedesktop.Policy.Power interface failed with error: " << err.message << endl; dbus_error_free(&err); } switch (ret) { case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER: kdDebug() << "Acquired org.freedesktop.Policy.Power interface" << endl; acquiredPolicyPower = true; break; case DBUS_REQUEST_NAME_REPLY_IN_QUEUE: kdWarning() << "Queued to acquire org.freedesktop.Policy.Power interface" << endl; acquiredPolicyPower = false; break; default: acquiredPolicyPower = false; break; } kdDebugFuncOut(trace); return acquiredPolicyPower; } /*! * This function release the org.freedesktop.Policy.Power interface * \return boolean with the result of the operation * \retval true if successful acquired the interface * \retval false if unsuccessful */ bool dbusHAL::releasePolicyPowerIface(){ kdDebugFuncIn(trace); int result; bool retval = false; DBusError error; if (dbus_connection == NULL) { kdDebugFuncOut(trace); return false; } dbus_error_init(&error); result = dbus_bus_release_name(dbus_connection, "org.freedesktop.Policy.Power", &error); if ( dbus_error_is_set( &error ) ) { kdError() << "Failed to release org.freedesktop.Policy.Power: " << error.message << endl; dbus_error_free(&error); } else { switch (result) { case DBUS_RELEASE_NAME_REPLY_RELEASED: kdDebug() << "Released org.freedesktop.Policy.Power interface" << endl; retval = true; acquiredPolicyPower = false; break; case DBUS_RELEASE_NAME_REPLY_NOT_OWNER: kdWarning() << "Couldn't release org.freedesktop.Policy.Power, not the owner" << endl; break; case DBUS_RELEASE_NAME_REPLY_NON_EXISTENT: kdWarning() << "Couldn't release org.freedesktop.Policy.Power, Iface not existing" << endl; break; default: kdWarning() << "Couldn't release org.freedesktop.Policy.Power, unknown error" << endl; break; } } return retval; kdDebugFuncOut(trace); } /*! * This function check if the org.freedesktop.Policy.Power * interface is owned by someone * \return boolean with the result of the operation * \retval true if the interface is owned by someone * \retval false if else */ bool dbusHAL::isPolicyPowerIfaceOwned(){ kdDebugFuncIn(trace); bool retval = false; DBusError error; if (dbus_connection == NULL) { kdDebugFuncOut(trace); return false; } dbus_error_init(&error); retval = dbus_bus_name_has_owner(dbus_connection, "org.freedesktop.Policy.Power", &error); if ( dbus_error_is_set( &error ) ) { kdError() << "Failed to check if org.freedesktop.Policy.Power has an owner: " << error.message << endl; dbus_error_free(&error); } kdDebugFuncOut(trace); return retval; } /* ----> DBUS section :: END <---- */ /* ----> HAL section :: START <---- */ /*! * This function initialise the connection to HAL over the D-Bus daemon. * \return boolean with the result of the operation * \retval true if successful initialised HAL connection and context * \retval false if unsuccessful */ bool dbusHAL::initHAL(){ kdDebugFuncIn(trace); if ( !dbus_is_connected ) { freeHAL(); return false; } else if ( hal_is_connected && (hal_ctx != NULL)) { return true; } // could not connect to HAL, reset all and try again freeHAL(); DBusError error; dbus_error_init(&error); dbus_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); if (dbus_connection == NULL || dbus_error_is_set(&error)) { kdError() << "could not open connection to system bus: " << error.message << endl; dbus_error_free(&error); return false; } bool hal_is_ready = dbus_bus_name_has_owner(dbus_connection, "org.freedesktop.Hal", &error); if (!hal_is_ready) { kdWarning() << "HAL is not ready. We will try later... " << endl; if ( dbus_error_is_set( &error ) ) { kdError() << "Error checking if hal service exists: " << error.message << endl; dbus_error_free( &error ); } freeHAL(); return false; } if((hal_ctx = libhal_ctx_new()) == NULL) { kdError() << "Could not init HAL context" << endl; return false; } /* setup dbus connection for hal */ if (!libhal_ctx_set_dbus_connection(hal_ctx, dbus_connection)) { kdError() << "Could not set up connection to dbus for hal" << endl; freeHAL(); return false; } /* init the hal library */ if (!libhal_ctx_init(hal_ctx, &error)) { kdError() << "Could not init hal library: " << error.message << endl; freeHAL(); return false; } hal_is_connected = true; kdDebugFuncOut(trace); return hal_is_connected; } /*! * This function free the hal connection/context. */ void dbusHAL::freeHAL(){ if ( hal_ctx != NULL ) { libhal_ctx_free( hal_ctx ); hal_ctx = NULL; } hal_is_connected = false; } /*! * This function try a reconnect to the HAL daemon only. * \return boolean with the result of the operation * \retval true if successful reconnected to HAL * \retval false if unsuccessful */ bool dbusHAL::reconnectHAL() { // free HAL context freeHAL(); // init HAL context return (initHAL()); } /*! * This function query a integer property from HAL for a given device * \param udi TQString with the UDI of the device * \param property TQString with the property * \param returnval pointer to the return value * \return If the query was successful or not */ bool dbusHAL::halGetPropertyInt(TQString udi, TQString property, int *returnval){ kdDebugFuncIn(trace); bool ret = false; if (!initHAL() || udi.isEmpty() || property.isEmpty()) goto out; DBusError error; dbus_error_init(&error); if (!libhal_device_property_exists(hal_ctx, udi.ascii(), property.ascii(), &error)) { kdWarning() << "Property: " << property << " for: " << udi << " doesn't exist." << endl; goto out; } *returnval = libhal_device_get_property_int(hal_ctx, udi.ascii(), property.ascii(), &error); if (dbus_error_is_set(&error)) { kdError() << "Fetching property: " << property << " for: " << udi << " failed with: " << error.message << endl; dbus_error_free(&error); goto out; } else { ret = true; } out: kdDebugFuncOut(trace); return true; } /*! * This function query a boolean property from HAL for a given device * \param udi TQString with the UDI of the device * \param property TQString with the property * \param returnval pointer to the return value * \return If the query was successful or not */ bool dbusHAL::halGetPropertyBool(TQString udi, TQString property, bool *returnval){ kdDebugFuncIn(trace); bool ret = false; if (!initHAL() || udi.isEmpty() || property.isEmpty()) goto out; DBusError error; dbus_error_init(&error); if (!libhal_device_property_exists(hal_ctx, udi.ascii(), property.ascii(), &error)) { kdWarning() << "Property: " << property << " for: " << udi << " doesn't exist." << endl; goto out; } *returnval = libhal_device_get_property_bool(hal_ctx, udi.ascii(), property.ascii(), &error); if (dbus_error_is_set(&error)) { kdError() << "Fetching property: " << property << " for: " << udi << " failed with: " << error.message << endl; dbus_error_free(&error); goto out; } else { ret = true; } out: kdDebugFuncOut(trace); return ret; } /*! * This function query a Sting property from HAL for a given device * \param udi TQString with the UDI of the device * \param property TQString with the property * \param returnval pointer to the return value * \return If the query was successful or not */ bool dbusHAL::halGetPropertyString(TQString udi, TQString property, TQString *returnval){ kdDebugFuncIn(trace); bool ret = false; if (!initHAL() || udi.isEmpty() || property.isEmpty()) goto out; DBusError error; dbus_error_init(&error); if (!libhal_device_property_exists(hal_ctx, udi.ascii(), property.ascii(), &error)) { kdWarning() << "Property: " << property << " for: " << udi << " doesn't exist." << endl; goto out; } *returnval = libhal_device_get_property_string(hal_ctx, udi.ascii(), property.ascii(), &error); if (dbus_error_is_set(&error)) { kdError() << "Fetching property: " << property << " for: " << udi << " failed with: " << error.message << endl; dbus_error_free(&error); goto out; } else { ret = true; } out: kdDebugFuncOut(trace); return ret; } /*! * This function query a String List property from HAL for a given device * \param udi TQString with the udi of the device * \param property TQString with the property to query * \param devices TQStringList to return the values * \return If the query was successful or not */ bool dbusHAL::halGetPropertyStringList (TQString udi, TQString property, TQStringList *devices) { kdDebugFuncIn(trace); bool ret = false; if (!initHAL() || udi.isEmpty() || property.isEmpty()) goto out; DBusError error; char ** found; dbus_error_init(&error); if (!libhal_device_property_exists(hal_ctx, udi.ascii(), property.ascii(), &error)) { kdWarning() << "Property: " << property << " for: " << udi << " doesn't exist." << endl; goto out; } found = libhal_device_get_property_strlist (hal_ctx, udi.ascii(), property.ascii(), &error); if (dbus_error_is_set(&error)) { kdWarning() << "Error while query existing strlist Property: " << property << " for: " << udi << " error: " << error.message << endl; dbus_error_free(&error); libhal_free_string_array(found); goto out; } else { for (int i = 0; found[i] != NULL ; ++i) { TQString _to_add = found[i]; if (!_to_add.isEmpty()) *devices += _to_add; } libhal_free_string_array(found); ret = true; } out: kdDebugFuncOut(trace); return ret; } /*! * This function query a capability from HAL for a given device * \param udi TQString with the UDI of the device * \param capability TQString with the capability to query * \param returnval pointer to the return value as boolean * \return If the query was successful or not */ bool dbusHAL::halQueryCapability(TQString udi, TQString capability, bool *returnval) { kdDebugFuncIn(trace); bool ret = false; if (!initHAL() || udi.isEmpty() || capability.isEmpty()) goto out; DBusError error; dbus_error_init(&error); *returnval = libhal_device_query_capability(hal_ctx, udi.ascii(), capability.ascii(), &error); if (dbus_error_is_set(&error)) { kdError() << "Fetching capability: " << capability << " for: " << udi << " failed with: " << error.message << endl; dbus_error_free(&error); goto out; } else { ret = true; } out: kdDebugFuncOut(trace); return ret; } /*! * Use this function to check if a device has a specia property/key. * \param udi TQString with the UDI of the device * \param property TQString with the property * \return If the query was successful or not */ bool dbusHAL::halDevicePropertyExist(TQString udi, TQString property ) { kdDebugFuncIn(trace); bool ret = false; if (!initHAL() || udi.isEmpty() || property.isEmpty()) goto out; DBusError error; dbus_error_init(&error); if (! libhal_device_property_exists (hal_ctx, udi.ascii(), property.ascii(), &error)) { if (dbus_error_is_set(&error)) { kdError() << "Fetching existing property: " << property << " for: " << udi << " failed with: " << error.message << endl; dbus_error_free(&error); } goto out; } else { ret = true; } out: kdDebugFuncOut(trace); return ret; } /*! * Use this function to search find devices with a give capability * \param capability TQString with the capability to query * \param devices TQStringList to return the found devices * \return If the query was successful or not */ bool dbusHAL::halFindDeviceByCapability (TQString capability, TQStringList *devices) { kdDebugFuncIn(trace); DBusError error; char ** found; int num = 0; bool ret = false; if (!initHAL() || capability.isEmpty()) goto out; dbus_error_init(&error); found = libhal_find_device_by_capability (hal_ctx, capability.ascii(), &num, &error); if (dbus_error_is_set(&error)) { kdError() << "Could not get list of devices with capability: " << capability << " error: " << error.message << endl; dbus_error_free(&error); libhal_free_string_array(found); goto out; } else { for (int i = 0; i < num; ++i) { TQString _to_add = found[i]; if (!_to_add.isEmpty()) *devices += _to_add; } libhal_free_string_array(found); ret = true; } out: kdDebugFuncOut(trace); return ret; } /*! * Use this function to search find devices with a special string property * \param property TQString with the name of the property * \param keyval TQString with value of the string property * \param devices TQStringList to return the found devices * \return If the query was successful or not */ bool dbusHAL::halFindDeviceByString (TQString property, TQString keyval, TQStringList *devices) { kdDebugFuncIn(trace); DBusError error; char ** found; int num = 0; bool ret = false; if (!initHAL() || property.isEmpty() || keyval.isEmpty()) goto out; dbus_error_init(&error); found = libhal_manager_find_device_string_match (hal_ctx, property.ascii(), keyval.ascii(), &num, &error); if (dbus_error_is_set(&error)) { kdError() << "Could not get list of devices with key: " << property << "and string value: " << keyval << " error: " << error.message << endl; dbus_error_free(&error); libhal_free_string_array(found); goto out; } else { for (int i = 0; i < num; ++i) { TQString _to_add = found[i]; if (!_to_add.isEmpty()) *devices += _to_add; } libhal_free_string_array(found); ret = true; } out: kdDebugFuncOut(trace); return ret; } /* ----> HAL section :: END <---- */ /* ----> D-Bus methode calls functions :: START <---- */ /*! * This function call a D-Bus method * \param interface TQString with te dbus interface * \param path TQString with the object path * \param object TQString with the object name * \param method TQString with the name of the methode * \param first_arg_type integer with the dbus type of the first argument * \param ... more arguments * \return If the query was successful or not */ bool dbusHAL::dbusSystemMethodCall( TQString interface, TQString path, TQString object, TQString method, int first_arg_type, ... ) { kdDebugFuncIn(trace); bool _ret = false; va_list var_args; va_start(var_args, first_arg_type); _ret = dbusMethodCall( interface, path, object, method, DBUS_BUS_SYSTEM, NULL, -1, first_arg_type, var_args); va_end(var_args); kdDebugFuncOut(trace); return _ret; } /*! * This overloaded function call a D-Bus method on the D-Bus system bus with a return value * \param interface TQString with the dbus interface * \param path TQString with the object path * \param object TQString with the object name * \param method TQString with the name of the method * \param retvalue void pointer to arguments, if NULL we make a simple call * \param retval_type Integer with the dbus type of the return value, set to -1 if retvalue is NULL * \param first_arg_type Integer with the dbus type of the first argument followed by the value * \return If the query was successful or not */ bool dbusHAL::dbusSystemMethodCall( TQString interface, TQString path, TQString object, TQString method, void *retvalue, int retval_type, int first_arg_type, ... ) { kdDebugFuncIn(trace); bool _ret = false; va_list var_args; va_start(var_args, first_arg_type); _ret = dbusMethodCall( interface, path, object, method, DBUS_BUS_SYSTEM, retvalue, retval_type, first_arg_type, var_args); va_end(var_args); kdDebugFuncOut(trace); return _ret; } /*! * This function call a D-Bus method with a return value * \param interface TQString with the dbus interface * \param path TQString with the object path * \param object TQString with the object name * \param method TQString with the name of the method * \param dbus_type DBusBusType with the D-Bus BUS Type * \param retvalue void pointer to arguments, if NULL we make a simple call * \param retval_type Integer with the dbus type of the return value, set to -1 if retvalue is NULL * \param first_arg_type Integer with the dbus type of the first argument followed by the value * \param var_args va_list with more arguments * \return If the query was successful or not */ bool dbusHAL::dbusMethodCall( TQString interface, TQString path, TQString object, TQString method, DBusBusType dbus_type, void *retvalue, int retval_type, int first_arg_type, va_list var_args ) { kdDebugFuncIn(trace); DBusMessage *message; DBusMessage *reply; DBusError error; bool ret = false; dbus_error_init(&error); dbus_connection = dbus_bus_get(dbus_type, &error); if (dbus_error_is_set(&error)) { kdError() << "Could not get dbus connection: " << error.message << endl; dbus_error_free(&error); goto out; } message = dbus_message_new_method_call( interface.ascii(), path.ascii(), object.ascii(), method.ascii() ); dbus_message_append_args_valist(message, first_arg_type, var_args); if (retvalue == NULL) { if (!dbus_connection_send(dbus_connection, message, NULL)) { kdError() << "Could not send method call." << endl; dbus_message_unref( message ); goto out; } } else { reply = dbus_connection_send_with_reply_and_block(dbus_connection, message, -1, &error); if (dbus_error_is_set(&error)) { kdError() << "Could not send dbus message: " << error.message << endl; dbus_message_unref(message); dbus_error_free(&error); goto out; } int type = dbus_message_get_type(reply); if (type == DBUS_MESSAGE_TYPE_METHOD_RETURN) { if (!dbus_message_get_args(reply, &error, retval_type, retvalue, DBUS_TYPE_INVALID)){ if (dbus_error_is_set(&error)) { kdError() << "Could not get argument from reply: " << error.message << endl; dbus_error_free(&error); } dbus_message_unref(reply); dbus_message_unref(message); goto out; } } else { kdError() << "Revieved invalid DBUS_MESSAGE_TYPE: " << type << "expected: " << DBUS_MESSAGE_TYPE_METHOD_RETURN << endl; dbus_message_unref(reply); dbus_message_unref(message); goto out; } } ret = true; // if we are here, everything should be okay dbus_message_unref(message); dbus_connection_flush(dbus_connection); out: kdDebugFuncOut(trace); return ret; } /*! * Function to call a suspend and call if resumed \ref callBackSuspend() * to emit a resume signal. * \param suspend a char pointer with the name of the suspend interface * \return If the query was successful or not */ bool dbusHAL::dbusMethodCallSuspend ( const char *suspend ) { kdDebugFuncIn(trace); DBusMessage *message; DBusError error; DBusPendingCall* pcall = NULL; bool ret = false; dbus_error_init(&error); dbus_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); if (dbus_error_is_set(&error)) { kdError() << "Could not get dbus connection: " << error.message << endl; dbus_error_free(&error); goto out; } message = dbus_message_new_method_call( HAL_SERVICE, HAL_COMPUTER_UDI, HAL_PM_IFACE, suspend); if (strcmp( suspend, "Suspend") == 0) { int wake_up = 0; dbus_message_append_args (message, DBUS_TYPE_INT32, &wake_up, DBUS_TYPE_INVALID); } if (message) { // need to set INT_MAX as default and not -1 dbus_connection_send_with_reply (dbus_connection, message, &pcall, INT_MAX); if (pcall) { dbus_pending_call_ref (pcall); // really needed? dbus_pending_call_set_notify (pcall, dbusHAL::callBackSuspend, NULL, NULL); } dbus_message_unref (message); ret = true; } out: kdDebugFuncOut(trace); return ret; } /*! * Slot called by D-Bus as set in \ref dbusMethodCallSuspend() * Here we emit the resume signal. */ void dbusHAL::callBackSuspend (DBusPendingCall* pcall, void* /*data*/) { kdDebugFuncIn(trace); DBusMessage* reply = NULL; DBusError error; int result; bool failed = false; if (!pcall) { kdError() << "dbusHAL::callBackSuspend - DBusPendingCall not set, return" << endl; kdDebugFuncOut(trace); return; } reply = dbus_pending_call_steal_reply (pcall); if (reply == NULL) { kdError() << "dbusHAL::callBackSuspend - Got no reply, return" << endl; goto out; } dbus_error_init(&error); if (!dbus_message_get_args (reply, &error, DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID)) { if (dbus_error_is_set(&error)) { kdError() << "Could not get argument from reply: " << error.message << endl; dbus_error_free(&error); } kdWarning() << "dbusHAL::callBackSuspend dbus_message_get_args failed, maybe timouted" << endl; failed = true; } dbus_message_unref (reply); out: dbus_pending_call_unref (pcall); if (failed) emit ((dbusHAL*) myInstance)->backFromSuspend( -1 ); else emit ((dbusHAL*) myInstance)->backFromSuspend( result ); kdDebugFuncOut(trace); return; } /* ----> D-Bus methode calls functions :: END <---- */ /* ---> PolicyKit method call section :: START <--- */ /*! * Check if the user is privileged to a special privilege * \param privilege TQString with the name of the requested privilege * \param udi TQString with the UDI. * \param ressource TQString with the name of the ressource * \param user TQString with the name of the user. If empty the current user is used. * \return int with info if the user is allowed or not. * \retval 0 if not allowed * \retval 1 if allowed * \retval -1 if a error occurs or we could not query the interface */ int dbusHAL::isUserPrivileged(TQString privilege, TQString udi, TQString ressource, TQString user) { kdDebugFuncIn(trace); const char *_unique_name; const char *_user; const char *_privilege; int retval = -1; if (user.isEmpty() || user.isNull()) _user = getenv("USER"); else _user = user.latin1(); if (_user == NULL || privilege.isEmpty()) goto out; _unique_name = dbus_bus_get_unique_name(dbus_connection); _privilege = privilege.latin1(); #ifdef USE_LIBHAL_POLICYCHECK DBusError error; char *result; if (udi.isEmpty()) { kdError() << "No UDI given ... could not lookup privileges" << endl; goto out; } if (!hal_is_connected) { kdError() << "HAL not running, could not call libhal for lookup privileges" << endl; goto out; } dbus_error_init(&error); result = libhal_device_is_caller_privileged ( hal_ctx, udi.latin1(), _privilege, _unique_name, &error); if ( dbus_error_is_set( &error ) ) { kdWarning() << "Error while lookup privileges: " << error.message << endl; dbus_error_free( &error ); retval = -1; } else { if (!strcmp(result, "yes")) { retval = 1; } else if (!strcmp(result, "no")) { retval = 0; } else { retval = -1; } } libhal_free_string(result); #else // not sure if we need this, but to avoid problems dbus_bool_t _retval; const char *_ressource; _ressource = ressource.latin1(); if (!dbusSystemMethodCall( "org.freedesktop.PolicyKit", "/org/freedesktop/PolicyKit/Manager", "org.freedesktop.PolicyKit.Manager", "IsUserPrivileged", &_retval, DBUS_TYPE_BOOLEAN, DBUS_TYPE_STRING, &_unique_name, DBUS_TYPE_STRING, &_user, DBUS_TYPE_STRING, &_privilege, DBUS_TYPE_STRING, &_ressource, DBUS_TYPE_INVALID)) { retval = -1; // only to be sure we have no changes trough the call } else { retval = (int) _retval; } #endif out: kdDebugFuncOut(trace); return retval; } /* ---> PolicyKit method call section :: END <--- */ /*! * Use this TQT_SLOT to emit a reviced messages to the kpowersave. * NOTE: Because of the filter function this need to be a public function. * Don't use this function in any other place than this class. * \param type enum with the type of the message * \param message String with the message * \param string String with additional info */ void dbusHAL::emitMsgReceived( msg_type type, TQString message, TQString string ) { if (message.startsWith("dbus.terminate")) dbus_is_connected = false; if (type == POLICY_POWER_OWNER_CHANGED) { if (message.startsWith("NOW_OWNER")) acquiredPolicyPower = true; else acquiredPolicyPower = false; } emit msgReceived_withStringString( type, message, string ); } #include "dbusHAL.moc" // --> functions which are not member of the class ... /*! * This function is needed filter function for the D-Bus connection to filter * all needed messages from the bus which are needful for KPowersave. * \param connection existing connection to the D-Bus daemon * \param message the recieved message from the D-Bus daemon * \param data void pointer (see dbus bindings for more information) * \return DBusHandlerResult */ DBusHandlerResult filterFunction (DBusConnection *connection, DBusMessage *message, void */*data*/) { kdDebugFuncIn(trace); bool reply_wanted; char *value; TQString ifaceType; DBusError error; dbus_error_init( &error ); if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected")){ ((dbusHAL*) myInstance)->emitMsgReceived( DBUS_EVENT, "dbus.terminate", 0 ); dbus_connection_unref(connection); kdDebugFuncOut(trace); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } if ( dbus_message_get_type( message ) != DBUS_MESSAGE_TYPE_SIGNAL ) { if (trace) kdDebug() << "recieved message, but wasn't from type DBUS_MESSAGE_TYPE_SIGNAL" << endl; kdDebugFuncOut(trace); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } ifaceType = dbus_message_get_interface( message ); if (ifaceType == NULL) { kdDebug() << "Received message from invalid interface" << endl; kdDebugFuncOut(trace); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } reply_wanted = !dbus_message_get_no_reply( message ); if (ifaceType.startsWith(DBUS_INTERFACE_DBUS)) { if(trace) kdDebug() << "Received from DBUS_INTERFACE_DBUS" << endl; /* get the name of the signal */ const char *signal = dbus_message_get_member( message ); /* get the first argument. This must be a string at the moment */ dbus_message_get_args( message, &error, DBUS_TYPE_STRING, &value, DBUS_TYPE_INVALID ); if ( dbus_error_is_set( &error ) ) { kdWarning() << "Received signal " << error.message << " but no string argument" << endl; dbus_error_free( &error ); kdDebugFuncOut(trace); return DBUS_HANDLER_RESULT_HANDLED; } if (trace) kdDebug() << "filter_function::SIGNAL=" << signal << " VALUE=" << value << endl; /* our name is... */ if ( ! strcmp( signal, "NameAcquired" ) ) { kdDebugFuncOut(trace); return DBUS_HANDLER_RESULT_HANDLED; } else if ( ! strcmp( signal, "NameOwnerChanged" )) { char *service; char *old_owner; char *new_owner; if (dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &service, DBUS_TYPE_STRING, &old_owner, DBUS_TYPE_STRING, &new_owner, DBUS_TYPE_INVALID)) { if (!strcmp(service, "org.freedesktop.Hal")) { if (!strcmp(new_owner, "") && strcmp(old_owner, "")) { // Hal service stopped. kdDebug() << "=== org.freedesktop.Hal terminated ===" << endl; ((dbusHAL*) myInstance)->emitMsgReceived( DBUS_EVENT, "hal.terminate", NULL ); } else if (!strcmp(old_owner, "") && strcmp(new_owner, "")) { // Hal service started. kdDebug() << "=== org.freedesktop.Hal started ===" << endl; ((dbusHAL*) myInstance)->emitMsgReceived( DBUS_EVENT, "hal.started", NULL ); } } else if (!strcmp(service, "org.freedesktop.Policy.Power")) { const char *own_name; own_name = dbus_bus_get_unique_name(((dbusHAL*) myInstance)->get_DBUS_connection()); if (!strcmp(new_owner, own_name)) { kdDebug() << "=== now owner of org.freedesktop.Policy.Power ===" << endl; // we have now again the ower of the name! ((dbusHAL*) myInstance)->emitMsgReceived( POLICY_POWER_OWNER_CHANGED, "NOW_OWNER", NULL ); } else { // some other has now the interface kdDebug() << "=== someone owner of org.freedesktop.Policy.Power ===" << endl; ((dbusHAL*) myInstance)->emitMsgReceived( POLICY_POWER_OWNER_CHANGED, "OTHER_OWNER", NULL ); } } } } kdDebugFuncOut(trace); return DBUS_HANDLER_RESULT_HANDLED; } else if (ifaceType.startsWith("org.freedesktop.Hal.Manager")) { kdDebug() << "Received from org.freedesktop.Hal.Manager" << endl; char *udi; const char *signal = dbus_message_get_member( message ); /* get the first argument. This must be a string at the moment */ dbus_message_get_args( message, &error, DBUS_TYPE_STRING, &value, DBUS_TYPE_INVALID ); if ( dbus_error_is_set( &error ) ) { kdWarning() << "Received signal, but no string argument: " << error.message << endl; dbus_error_free( &error ); kdDebugFuncOut(trace); return DBUS_HANDLER_RESULT_HANDLED; } if (dbus_message_get_args( message, &error, DBUS_TYPE_STRING, &udi, DBUS_TYPE_INVALID )) { if (! strcmp(signal, "DeviceRemoved") || ! strcmp(signal, "DeviceAdded")) { ((dbusHAL*) myInstance)->emitMsgReceived( HAL_DEVICE, signal, udi ); kdDebug() << "org.freedesktop.Hal.Manager: uid: " << udi << " signal: " << signal << endl; } else { kdWarning() << "Received unknown signal from org.freedesktop.Hal.Manager: " << signal << endl; } } kdDebugFuncOut(trace); return DBUS_HANDLER_RESULT_HANDLED; } else if (ifaceType.startsWith("org.freedesktop.Hal.Device")) { const char *udi = dbus_message_get_path (message); const char *signal = dbus_message_get_member( message ); /* Code taken from libhal */ if (! strcmp(signal, "PropertyModified")) { if (trace) kdDebug() << "-------- PropertyModified ------" << endl; int i, num_modifications; DBusMessageIter iter; DBusMessageIter iter_array; dbus_message_iter_init (message, &iter); dbus_message_iter_get_basic (&iter, &num_modifications); dbus_message_iter_next (&iter); dbus_message_iter_recurse (&iter, &iter_array); for (i = 0; i < num_modifications; i++) { dbus_bool_t removed, added; char *key; DBusMessageIter iter_struct; dbus_message_iter_recurse (&iter_array, &iter_struct); dbus_message_iter_get_basic (&iter_struct, &key); dbus_message_iter_next (&iter_struct); dbus_message_iter_get_basic (&iter_struct, &removed); dbus_message_iter_next (&iter_struct); dbus_message_iter_get_basic (&iter_struct, &added); /* don't check if we really need this device, check this in an other class */ ((dbusHAL*) myInstance)->emitMsgReceived( HAL_PROPERTY_CHANGED, udi, key); kdDebug() << "PropertyModified: uid: " << udi << " key: " << key << endl; dbus_message_iter_next (&iter_array); } } else if (! strcmp(signal, "Condition")) { if (trace) kdDebug() << "-------- Condition ------" << endl; char *name, *detail; dbus_message_get_args( message, &error, DBUS_TYPE_STRING, &value, DBUS_TYPE_INVALID ); if (dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &detail, DBUS_TYPE_INVALID)) { ((dbusHAL*) myInstance)->emitMsgReceived( HAL_CONDITION, name, detail ); } else { if (dbus_error_is_set( &error )) dbus_error_free( &error ); } } else { kdDebug() << "Received unknown signal from org.freedesktop.Hal.Device: " << signal << endl; } kdDebugFuncOut(trace); return DBUS_HANDLER_RESULT_HANDLED; } else if (ifaceType.startsWith("org.freedesktop.ConsoleKit.Session")) { kdDebug() << "Received from org.freedesktop.ConsoleKit.Session" << endl; const char *session = dbus_message_get_path (message); const char *signal = dbus_message_get_member( message ); if (! strcmp(signal, "ActiveChanged")) { dbus_bool_t active; if (dbus_message_get_args( message, &error, DBUS_TYPE_BOOLEAN, &active, DBUS_TYPE_INVALID )) { ((dbusHAL*) myInstance)->emitMsgReceived( CONSOLEKIT_SESSION_ACTIVE, session, TQString("%1").arg((int)active)); } else { if (dbus_error_is_set( &error )) dbus_error_free( &error ); } } else { kdDebug() << "Received unknown signal from org.freedesktop.ConsoleKit.Session: " << signal << endl; kdDebugFuncOut(trace); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } kdDebugFuncOut(trace); return DBUS_HANDLER_RESULT_HANDLED; } else { kdDebugFuncOut(trace); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } } // --> some functions to get private members //! to get the current connection to D-Bus DBusConnection * dbusHAL::get_DBUS_connection() { return dbus_connection; }