diff options
author | Ossama Othman <ossama.othman@intel.com> | 2013-10-03 13:35:02 -0700 |
---|---|---|
committer | Ossama Othman <ossama.othman@intel.com> | 2013-10-03 14:10:29 -0700 |
commit | 9481ce3c822a1c9734068f8902e79547afc0d38b (patch) | |
tree | 096aa0fc6eba1c8449281385476f795924d94802 /plugins | |
parent | 38bb9a71ff04daff8702f20fed901831b690e29b (diff) | |
download | settings-daemon-9481ce3c822a1c9734068f8902e79547afc0d38b.tar.gz settings-daemon-9481ce3c822a1c9734068f8902e79547afc0d38b.tar.bz2 settings-daemon-9481ce3c822a1c9734068f8902e79547afc0d38b.zip |
TIVI-1924: Initial commit of IVI settings daemon.submit/tizen_ivi_release/20131120.032742submit/tizen_ivi_milestone/20131113.054518submit/tizen_ivi_genivi/20140131.070647submit/tizen_ivi_generic/20140131.065503submit/tizen/20131003.211152ivi_oct_m2accepted/tizen_ivi_release/20131120.050012accepted/tizen/ivi/genivi/20140131.070902accepted/tizen/20131003.220350accepted/tizen/20131003.215933tizen_ivi_genivi
This daemon provides a native backend to the Settings app.
It fills functionality gaps in the Web API, such as WiFi and
date/time, required by the Settings app.
This version contains support for unsecured WiFi connections
and setting the date and time.
Change-Id: I2810d0910029c4ed146e9ff740c246d428767649
Signed-off-by: Ossama Othman <ossama.othman@intel.com>
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/Makefile.am | 18 | ||||
-rw-r--r-- | plugins/connman/Makefile.am | 64 | ||||
-rw-r--r-- | plugins/connman/bluetooth.cpp | 66 | ||||
-rw-r--r-- | plugins/connman/bluetooth.hpp | 96 | ||||
-rw-r--r-- | plugins/connman/clock.cpp | 336 | ||||
-rw-r--r-- | plugins/connman/clock.hpp | 136 | ||||
-rw-r--r-- | plugins/connman/connman.cpp | 197 | ||||
-rw-r--r-- | plugins/connman/connman.hpp | 198 | ||||
-rw-r--r-- | plugins/connman/connman_api.hpp | 66 | ||||
-rw-r--r-- | plugins/connman/connman_manager.cpp | 228 | ||||
-rw-r--r-- | plugins/connman/connman_manager.hpp | 175 | ||||
-rw-r--r-- | plugins/connman/ethernet.cpp | 66 | ||||
-rw-r--r-- | plugins/connman/ethernet.hpp | 96 | ||||
-rw-r--r-- | plugins/connman/registration.cpp | 65 | ||||
-rw-r--r-- | plugins/connman/service.cpp | 87 | ||||
-rw-r--r-- | plugins/connman/service.hpp | 97 | ||||
-rw-r--r-- | plugins/connman/technology.cpp | 357 | ||||
-rw-r--r-- | plugins/connman/technology.hpp | 139 | ||||
-rw-r--r-- | plugins/connman/wifi.cpp | 66 | ||||
-rw-r--r-- | plugins/connman/wifi.hpp | 98 |
20 files changed, 2651 insertions, 0 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am new file mode 100644 index 0000000..8e03c1c --- /dev/null +++ b/plugins/Makefile.am @@ -0,0 +1,18 @@ +## Copyright 2013 Intel Corporation All Rights Reserved. +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; +## version 2.1 of the License. +## +## This library 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 +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, +## Boston, MA 02110-1301 USA + +SUBDIRS = connman diff --git a/plugins/connman/Makefile.am b/plugins/connman/Makefile.am new file mode 100644 index 0000000..2f6b3b6 --- /dev/null +++ b/plugins/connman/Makefile.am @@ -0,0 +1,64 @@ +## Copyright 2013 Intel Corporation All Rights Reserved. +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; +## version 2.1 of the License. +## +## This library 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 +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, +## Boston, MA 02110-1301 USA + + +pkglib_LTLIBRARIES = connman.la + +if SETTINGS_USE_GCC_SYMBOL_VISIBILITY + IVI_SETTINGS_PLUGIN_CXXFLAGS = -fvisibility=hidden -fvisibility-inlines-hidden +else + IVI_SETTINGS_PLUGIN_CXXFLAGS = +endif + +IVI_SETTINGS_PLUGIN_CPPFLAGS = \ + -DIVI_SETTINGS_CONNMAN_BUILDING_DLL \ + -I$(top_srcdir)/include + +IVI_SETTINGS_PLUGIN_LIBRARY = $(top_builddir)/lib/libsettings.la + +connman_la_SOURCES = \ + connman.cpp \ + connman_manager.cpp \ + service.cpp \ + technology.cpp \ + bluetooth.cpp \ + clock.cpp \ + ethernet.cpp \ + wifi.cpp \ + registration.cpp +connman_la_CXXFLAGS = \ + $(IVI_SETTINGS_PLUGIN_CXXFLAGS) \ + $(GIO_CFLAGS) \ + $(JSON_GLIB_CFLAGS) +connman_la_CPPFLAGS = $(IVI_SETTINGS_PLUGIN_CPPFLAGS) +connman_la_LIBADD = $(IVI_SETTINGS_PLUGIN_LIBRARY) +connman_la_LDFLAGS = -no-undefined \ + -module \ + -avoid-version \ + $(GIO_LIBS) \ + $(JSON_GLIB_LIBS) + +noinst_HEADERS = \ + connman_api.hpp \ + connman.hpp \ + connman_manager.hpp \ + service.hpp \ + technology.hpp \ + bluetooth.hpp \ + clock.hpp \ + ethernet.hpp \ + wifi.hpp diff --git a/plugins/connman/bluetooth.cpp b/plugins/connman/bluetooth.cpp new file mode 100644 index 0000000..576eb4e --- /dev/null +++ b/plugins/connman/bluetooth.cpp @@ -0,0 +1,66 @@ +/** + * @file bluetooth.cpp + * + * @brief Connman-based bluetooth settings. + * + * @author Ossama Othman @<ossama.othman@@intel.com@> + * + * @copyright @par + * Copyright 2013 Intel Corporation All Rights Reserved. + * @par + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * @par + * This library 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 + * Lesser General Public License for more details. + * @par + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "bluetooth.hpp" +#include <settingsd/response_callback.hpp> + +// ---------------------------------------------------------------------- + +namespace +{ + std::string const technology_name("bluetooth"); +} + +// ---------------------------------------------------------------------- + +ivi::settings::bluetooth::bluetooth() + : technology_(technology_name) +{ +} + +ivi::settings::bluetooth::~bluetooth() +{ +} + +std::string const & +ivi::settings::bluetooth::id() const +{ + return technology_name; +} + +void +ivi::settings::bluetooth::handle_request(std::string request, + response_callback response) +{ + technology_.handle_request(request, response); +} + + +// Local Variables: +// mode:c++ +// c-basic-offset:2 +// indent-tabs-mode: nil +// End: diff --git a/plugins/connman/bluetooth.hpp b/plugins/connman/bluetooth.hpp new file mode 100644 index 0000000..31741c0 --- /dev/null +++ b/plugins/connman/bluetooth.hpp @@ -0,0 +1,96 @@ +/** + * @file bluetooth.hpp + * + * @brief Bluetooth settings plugin. + * + * Connman-based bluetooth settings plugin. + * + * @author Ossama Othman @<ossama.othman@@intel.com@> + * + * @copyright @par + * Copyright 2012, 2013 Intel Corporation All Rights Reserved. + * @par + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * @par + * This library 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 + * Lesser General Public License for more details. + * @par + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * @note This header is internal. Settings provider plugin implementors + * should write their own library/symbol export macros as + * needed. + */ + + +#ifndef IVI_SETTINGS_CONNMAN_BLUETOOTH_HPP +#define IVI_SETTINGS_CONNMAN_BLUETOOTH_HPP + +#include <settingsd/plugin.hpp> + +#include "technology.hpp" + + +namespace ivi +{ + namespace settings + { + /** + * @class bluetooth + * + * @brief Connman-based bluetooth settings. + * + * This class implements all connman-based bluetooth settings. + */ + class bluetooth : public plugin + { + public: + + /// Constructor. + bluetooth(); + + /// Destructor. + virtual ~bluetooth(); + + /** + * @name Settings Plugin API + * + * Interface defined by the @c ivi::settings::plugin abstract + * base class. + * + * @see settingsd/plugin.hpp + */ + //@{ + virtual std::string const & id() const; + virtual void handle_request(std::string request, + response_callback response); + //@} + + private: + + /// Underlying connman proxy. + technology technology_; + + }; + + } +} + + +#endif /* IVI_SETTINGS_CONNMAN_BLUETOOTH_HPP */ + + +// Local Variables: +// mode:c++ +// c-basic-offset:2 +// indent-tabs-mode: nil +// End: + diff --git a/plugins/connman/clock.cpp b/plugins/connman/clock.cpp new file mode 100644 index 0000000..9ff91ea --- /dev/null +++ b/plugins/connman/clock.cpp @@ -0,0 +1,336 @@ +/** + * @file clock.cpp + * + * @brief Connman-based clock settings. + * + * @author Ossama Othman @<ossama.othman@@intel.com@> + * + * @copyright @par + * Copyright 2013 Intel Corporation All Rights Reserved. + * @par + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * @par + * This library 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 + * Lesser General Public License for more details. + * @par + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "clock.hpp" + +#include <settingsd/response_callback.hpp> +#include <settingsd/glib_traits.hpp> +#include <settingsd/json_glib_traits.hpp> +#include <settingsd/smart_ptr.hpp> + +#include <cstring> +#include <boost/lexical_cast.hpp> + + +ivi::settings::clock::clock() + : connman_("net.connman.Clock", "/") +{ +} + +ivi::settings::clock::~clock() +{ +} + +std::string const & +ivi::settings::clock::id() const +{ + static std::string const the_id("clock"); + + return the_id; +} + +void +ivi::settings::clock::handle_request(std::string request, + response_callback response) +{ + smart_ptr<JsonParser> const parser(json_parser_new()); + json_parser_load_from_data(parser.get(), request.c_str(), -1, nullptr); + + JsonReader * const reader = + json_reader_new(json_parser_get_root(parser.get())); + + smart_ptr<JsonReader> safe_reader(reader); + + char const * name = nullptr; + if (json_reader_read_member(reader, "name")) { + name = json_reader_get_string_value(reader); + } + json_reader_end_member(reader); + + if (name != nullptr) { + GError * error = nullptr; + bool success = false; + + if (strcmp(name, "time") == 0) + success = set_time(reader, response, error); + else if (strcmp(name, "time_updates") == 0) + success = set_updates("TimeUpdates", reader, response, error); + else if (strcmp(name, "timezone") == 0) + success = set_timezone(reader, response, error); + else if (strcmp(name, "timezone_updates") == 0) + success = set_updates("TimezoneUpdates", reader, response, error); + else if (strcmp(name, "is_time_updates_auto") == 0) + is_updates_auto("TimeUpdates", reader, response, error); + else if (strcmp(name, "is_timezone_updates_auto") == 0) + is_updates_auto("TimezoneUpdates", reader, response, error); + else { + response.send_error( + "Unrecognized " + id() + " request name: " + name); + } + + smart_ptr<GError> safe_error(error); + + if (success) { + + // Nothing to add to successful response. + response.send_response( + [](JsonBuilder * /* builder */) {}); + + } else if (error != nullptr) { + response.send_error( + std::string("Unable to set ") + name + ": " + error->message); + } + + // If success is false and error == nullptr a succesful response + // was sent by one of the functions above, e.g. is_update_auto(). + + } else { + response.send_error( + "Malformed " + id() + " request: \"name\" is missing."); + } +} + +bool +ivi::settings::clock::set_time(JsonReader * reader, + response_callback response, + GError *& error) +{ + int64_t time; + if (json_reader_read_member(reader, "value")) { + /** + * @bug @c json_read_get_int_value() returns a signed 64 bit + * integer. However, the connman clock API expects an + * unsigned 64 bit integer. This means we cannot set time + * values before the Unix epoch (< 0) or greater than + * (2^63)-1, i.e the largest signed 64 bit integer. + */ + time = json_reader_get_int_value(reader); + } + + json_reader_end_member(reader); + + bool success = false; + + if (time >= 0) { + // Note that the connman clock API expects an unsigned 64 bit + // integer containing seconds since the Unix epoch. We cast the + // positive int64_t value to an uint64_t value. There is no + // chance of overflow in this case. + success = + set_property("Time", + g_variant_new_uint64(static_cast<uint64_t>(time)), + response, + error); + } else { + response.send_error("Time value is earlier than epoch (negative): " + + boost::lexical_cast<std::string>(time)); + } + + return success; +} + +bool +ivi::settings::clock::set_timezone(JsonReader * reader, + response_callback response, + GError *& error) +{ + bool success = false; + + if (json_reader_read_member(reader, "value")) { + char const * const timezone = json_reader_get_string_value(reader); + success = this->set_property("Timezone", + g_variant_new_string(timezone), + response, + error); + } + + json_reader_end_member(reader); + + return success; +} + +bool +ivi::settings::clock::set_updates(char const * name, + JsonReader * reader, + response_callback response, + GError *& error) +{ + bool success = false; + + char const * updates = nullptr; + if (json_reader_read_member(reader, "value")) { + updates = json_reader_get_string_value(reader); + } + json_reader_end_member(reader); + + if (updates == nullptr + || (strcmp(updates, "manual") != 0 + && strcmp(updates, "auto") != 0)) { + response.send_error(id() + + ": updates value not \"manual\" " + "or \"auto\": " + + (updates == nullptr + ? "<invalid_string>" + : updates)); + } else { + smart_ptr<GVariant> const current_value(get_property(name, error)); + + if (current_value != nullptr) { + char const * value = + g_variant_get_string(current_value.get(), nullptr); + + if (strcmp(value, updates) == 0) { + // Already set. Just return success, otherwise we'll timeout + // waiting for a PropertyChanged signal that'll never come. + return true; + } + } + + success = set_property(name, + g_variant_new_string(updates), + response, + error); + } + + return success; +} + +void +ivi::settings::clock::is_updates_auto(char const * name, + JsonReader * reader, + response_callback response, + GError *& error) +{ + bool null = false; + if (json_reader_read_member(reader, "value")) { + null = json_reader_get_null_value(reader); + } + json_reader_end_member(reader); + + if (!null) { + response.send_error(std::string(name) + " query parameter is not null."); + return; + } + + smart_ptr<GVariant> const current_value(get_property(name, error)); + + if (current_value != nullptr) { + char const * value = + g_variant_get_string(current_value.get(), nullptr); + + bool const is_auto = (strcmp(value, "auto") == 0); + + response.send_response( + [is_auto](JsonBuilder * builder) + { + json_builder_set_member_name(builder, "value"); + json_builder_add_boolean_value(builder, is_auto); + }); + } +} + +bool +ivi::settings::clock::set_property(char const * name, + GVariant * value, + response_callback response, + GError *& error) +{ + bool success = false; + + // Get notified when the clock property has changed. + auto property_promise = connman_.get_property_changed_promise(name); + auto property_future = property_promise->get_future(); + + smart_ptr<GVariant> const ret( + connman_.set_property(name, value, error)); + + if (ret != nullptr) { + static int const timeout = 5000; // milliseconds + + // Block until the clock property has changed.. + std::future_status const status = + property_future.wait_for(std::chrono::milliseconds(timeout)); + + if (status == std::future_status::ready) { + smart_ptr<GVariant> const value(property_future.get()); + success = true; + } else { + response.send_error( + std::string("Wait for clock property \"") + + name + "\" set failed: " + + (status == std::future_status::timeout + ? "timeout" + : "deferred")); + } + } + + return success; +} + +GVariant * +ivi::settings::clock::get_property(char const * property, + GError *& error) const +{ + constexpr gint const timeout = 5000; // milliseconds + + smart_ptr<GVariant> const dictionary( + g_dbus_proxy_call_sync(connman_.proxy(), + "GetProperties", + nullptr, // No parameters + G_DBUS_CALL_FLAGS_NONE, + timeout, + nullptr, // Not cancellable + &error)); + + smart_ptr<GVariant> value; + + if (dictionary != nullptr) { + GVariantIter * i = nullptr; + g_variant_get(dictionary.get(), "(a{sv})", &i); + smart_ptr<GVariantIter> const iter(i); + + gchar * pname = nullptr; + GVariant * pvalue = nullptr; + + while (g_variant_iter_next(i, "{sv}", &pname, &pvalue)) { + smart_ptr<gchar> const name(pname); + value.reset(pvalue); + + // Check if this is the property we want. + if (strcmp(name.get(), property) == 0) + break; + } + } + + return value.release(); +} + + +// Local Variables: +// mode:c++ +// c-basic-offset:2 +// indent-tabs-mode: nil +// End: diff --git a/plugins/connman/clock.hpp b/plugins/connman/clock.hpp new file mode 100644 index 0000000..e902af4 --- /dev/null +++ b/plugins/connman/clock.hpp @@ -0,0 +1,136 @@ +/** + * @file clock.hpp + * + * @brief Clock settings plugin. + * + * Connman-based clock settings plugin. + * + * @author Ossama Othman @<ossama.othman@@intel.com@> + * + * @copyright @par + * Copyright 2012, 2013 Intel Corporation All Rights Reserved. + * @par + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * @par + * This library 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 + * Lesser General Public License for more details. + * @par + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * @note This header is internal. Settings provider plugin implementors + * should write their own library/symbol export macros as + * needed. + */ + + +#ifndef IVI_SETTINGS_CONNMAN_CLOCK_HPP +#define IVI_SETTINGS_CONNMAN_CLOCK_HPP + +#include "connman.hpp" +#include <settingsd/plugin.hpp> + +#include <json-glib/json-glib.h> + + +namespace ivi +{ + namespace settings + { + class response_callback; + + /** + * @class clock + * + * @brief Connman-based clock settings. + * + * This class implements all connman-based clock settings. + */ + class clock : public plugin + { + public: + + /// Constructor. + clock(); + + /// Destructor. + virtual ~clock(); + + /** + * @name Settings Plugin API + * + * Interface defined by the @c ivi::settings::plugin abstract + * base class. + * + * @see settingsd/plugin.hpp + */ + //@{ + virtual std::string const & id() const; + virtual void handle_request(std::string request, + response_callback response); + //@} + + private: + + /// Set the time. + bool set_time(JsonReader * reader, + response_callback response, + GError *& error); + + /// Set the timezone. + bool set_timezone(JsonReader * reader, + response_callback response, + GError *& error); + + /// Set time or timezone updates to manual or auto. + bool set_updates(char const * name, + JsonReader * reader, + response_callback response, + GError *& error); + + /** + * Check if the TimeUpdates or TimezoneUpdate property is set + * to "auto". + */ + void is_updates_auto(char const * name, + JsonReader * reader, + response_callback response, + GError *& error); + + /// Set the clock property. + bool set_property(char const * name, + GVariant * value, + response_callback response, + GError *& error); + + /// Get the clock property. + GVariant * get_property(char const * name, + GError *& error) const; + + private: + + /// Underlying connman proxy. + connman connman_; + + }; + + } +} + + +#endif /* IVI_SETTINGS_CONNMAN_CLOCK_HPP */ + + +// Local Variables: +// mode:c++ +// c-basic-offset:2 +// indent-tabs-mode: nil +// End: + diff --git a/plugins/connman/connman.cpp b/plugins/connman/connman.cpp new file mode 100644 index 0000000..a3864c8 --- /dev/null +++ b/plugins/connman/connman.cpp @@ -0,0 +1,197 @@ +/** + * @file connman.cpp + * + * @brief Connman-based settings plugin. + * + * @author Ossama Othman @<ossama.othman@@intel.com@> + * + * @copyright @par + * Copyright 2013 Intel Corporation All Rights Reserved. + * @par + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * @par + * This library 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 + * Lesser General Public License for more details. + * @par + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "connman.hpp" + +#include <settingsd/reverse_lock.hpp> + +#include <cstring> +#include <string> +#include <stdexcept> + + +namespace +{ + void + on_property_changed(GDBusConnection * /* connection */, + char const * /* sender_name */, + char const * /* object_path */, + char const * /* interface_name */, + char const * /* signal_name */, + GVariant * parameters, + gpointer user_data) + { + // Notify callers about the scan results. + typedef ivi::settings::connman::user_data user_data_type; + + user_data_type * const data = static_cast<user_data_type *>(user_data); + + std::lock_guard<std::mutex> lock(data->mutex); + auto const end = data->promises.end(); + for (auto i = data->promises.begin(); i != end; ) { + gchar * pname = nullptr; + GVariant * pvalue = nullptr; + + g_variant_get(parameters, "(sv)", &pname, &pvalue); + + using namespace ivi::settings; + + smart_ptr<gchar> name(pname); + smart_ptr<GVariant> value(pvalue); + + auto & p = *i; + + // Set the value in the promise if the desired property name + // matches. + if (strcmp(p.first, pname) == 0) { + { + // Release the mutex during the promise::set_value() + // call/notification so that we don't unnecessarily block + // threads attempting to get a property_changed promise. + typedef ivi::settings::reverse_lock<std::mutex> reverse_lock; + reverse_lock reverse(data->mutex); + + std::lock_guard<reverse_lock> kcol(reverse); + + p.second->set_value(std::move(value)); + } + + // Done with the pointer to the promise. Remove it from the + // list now since we already have an iterator to it. + i = data->promises.erase(i); + } else { + // Nothing to erase. Advance to the next list element. + ++i; + } + } + } +} + +// --------------------------------------------------------------- + +ivi::settings::connman::connman(char const * interface, + char const * path) + : proxy_(nullptr) + , mutex_() + , promises_() + , data_(mutex_, promises_) + , subscription_id_(0) +{ + static char const name[] = "net.connman"; // Service + + GError * error = nullptr; + + proxy_ = + g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + nullptr, // GDBusInterfaceInfo + name, + path, + interface, + nullptr, // GCancellable + &error); + + smart_ptr<GError> safe_error(error); + + if (proxy_ == nullptr) { + g_printerr("Unable to create D-Bus proxy for (\"%s\", \"%s\"): %s\n", + interface, + path, + error->message); + + throw std::runtime_error(error->message); + } + + // Listen for changes to properties. + subscription_id_ = + g_dbus_connection_signal_subscribe( + g_dbus_proxy_get_connection(G_DBUS_PROXY(proxy_)), + nullptr, + interface, + "PropertyChanged", + path, + nullptr, + G_DBUS_SIGNAL_FLAGS_NONE, + on_property_changed, + &data_, + nullptr); +} + +ivi::settings::connman::~connman() +{ + if (proxy_ != nullptr) { + g_dbus_connection_signal_unsubscribe( + g_dbus_proxy_get_connection(G_DBUS_PROXY(proxy_)), + subscription_id_); + + g_object_unref(proxy_); + } +} + +GVariant * +ivi::settings::connman::set_property(char const * property, + GVariant * value, + GError *& error) +{ + static gint const timeout = 5000; // milliseconds + + return g_dbus_proxy_call_sync(proxy_, + "SetProperty", // Method name + g_variant_new("(sv)", + property, + value), + G_DBUS_CALL_FLAGS_NONE, + timeout, + nullptr, // Not cancellable + &error); +} + +ivi::settings::connman::shared_promise_type +ivi::settings::connman::get_property_changed_promise( + char const * property) +{ + // This promise must exist long enough for the value to retrieved + // from the future. Use a shared_ptr<> to make that possible. + shared_promise_type promise = std::make_shared<promise_type>(); + + { + std::lock_guard<std::mutex> lock(mutex_); + + // Add a new std::promise to the promises list. The promise will + // only be used once, and will be removed once its value has been + // set. + promises_.push_back(std::make_pair(property, promise)); + } + + return promise; +} + + +// Local Variables: +// mode:c++ +// c-basic-offset:2 +// indent-tabs-mode: nil +// End: diff --git a/plugins/connman/connman.hpp b/plugins/connman/connman.hpp new file mode 100644 index 0000000..fa51caa --- /dev/null +++ b/plugins/connman/connman.hpp @@ -0,0 +1,198 @@ +/** + * @file connman.hpp + * + * @brief Connman-based settings plugin header. + * + * @author Ossama Othman @<ossama.othman@@intel.com@> + * + * @copyright @par + * Copyright 2013 Intel Corporation All Rights Reserved. + * @par + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * @par + * This library 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 + * Lesser General Public License for more details. + * @par + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + + +#ifndef IVI_SETTINGS_CONNMAN_HPP +#define IVI_SETTINGS_CONNMAN_HPP + +#include <settingsd/glib_traits.hpp> +#include <settingsd/smart_ptr.hpp> + +#include <gio/gio.h> + +#include <future> +#include <utility> +#include <list> +#include <memory> + + +namespace ivi +{ + namespace settings + { + /** + * @class connman + * + * @brief Common connman-based settings functionality. + * + * This class implements functionality common to all connman-based + * settings, such as bluetooth, wifi, date/time, etc. + */ + class connman + { + public: + + /** + * Constructor. + * + * @param[in] interface Connman D-Bus interface. + * @param[in] path Connman D-Bus object path. + */ + connman(char const * interface, + char const * path); + + /// Destructor. + ~connman(); + + /// The type held by the @c future containing the async result. + typedef smart_ptr<GVariant> future_value_type; + + /// The @c future type returned by the @c promise. + typedef std::future<future_value_type> future_type; + + /// The @c promise that provides the async result. + typedef std::promise<future_value_type> promise_type; + + /** + * Smart pointer to the @c promise that provides the async + * result. + */ + typedef std::shared_ptr<promise_type> shared_promise_type; + + /** + * Property Name/value pair type held by the @c future + * containing the async result. Both values will be populated + * when retrieving the value from the @c PropertyChanged + * signal. + * + * @note The property name is meant for internal use. + */ + typedef std::pair<char const *, + shared_promise_type> promise_value_type; + + /// List type for promises to be updated with async result. + typedef std::list<promise_value_type> promise_list_type; + + /** + * Set @a property to given @a value on the underlying connman + * object. + * + * @param[in] property The name of the property to be set. + * @param[in] value The property value to be set. + * @param[inout] error The error object containing information + * on a failed connman @c SetProperty method + * call. + * + * @returns @c nullptr on a failed call to the connman + * @c SetProperty method. + */ + GVariant * set_property(char const * property, + GVariant * value, + GError *& error); + + /** + * Get a promise that will contain the changed connman property + * when it becomes available. The user must obtain the value + * from the corresponding future object. + */ + shared_promise_type get_property_changed_promise( + char const * property); + + /// Get pointer to underlying GDBusProxy. + GDBusProxy * proxy() const { return proxy_; } + + /// Convenience function to get D-Bus interface name. + char const * + interface_name() const + { + return g_dbus_proxy_get_interface_name(proxy_); + } + + /// Convenience function to get D-Bus object path. + char const * + object_path() const + { + return g_dbus_proxy_get_object_path(proxy_); + } + + /** + * @struct user_data + * + * @brief Struct passed to @c ServicesChanged signal handler. + */ + struct user_data + { + /// Constructor. + user_data(std::mutex & m, promise_list_type & p) + : mutex(m) + , promises(p) + { + } + + /** + * References to mutex used to synchronize access to the list + * of promises. + */ + std::mutex & mutex; + + /// List of promises to be updated with the changed services. + promise_list_type & promises; + }; + + private: + + /// The proxy used to access the Connman D-Bus API. + GDBusProxy * proxy_; + + /// Mutex used to synchronize access to the promises list. + std::mutex mutex_; + + /** + * List of promises that will be updated with the + * PropertyChanged signal results. + */ + promise_list_type promises_; + + /// User data passed to @c PropertyChanged signal handler. + user_data data_; + + /// PropertyChanged signal subscription ID. + guint subscription_id_; + + }; + + } +} + + +#endif /* IVI_SETTINGS_CONNMAN_HPP */ + + +// Local Variables: +// mode:c++ +// c-basic-offset:2 +// indent-tabs-mode: nil +// End: diff --git a/plugins/connman/connman_api.hpp b/plugins/connman/connman_api.hpp new file mode 100644 index 0000000..232fb56 --- /dev/null +++ b/plugins/connman/connman_api.hpp @@ -0,0 +1,66 @@ +/** + * @file connman_api.hpp + * + * @brief @c Connman-based settings plugin export macros. + * + * The IVI connman settings plugin uses these macros to + * export the settings plugin API from the plugin as needed. + * + * @author Ossama Othman @<ossama.othman@@intel.com@> + * + * @copyright @par + * Copyright 2013 Intel Corporation All Rights Reserved. + * @par + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * @par + * This library 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 + * Lesser General Public License for more details. + * @par + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + + +#ifndef IVI_SETTINGS_CONNMAN_API_HPP +#define IVI_SETTINGS_CONNMAN_API_HPP + +# if defined _WIN32 || defined __CYGWIN__ +# ifdef IVI_SETTINGS_CONNMAN_BUILDING_DLL +# ifdef __GNUC__ +# define IVI_SETTINGS_CONNMAN_API __attribute__ ((dllexport)) +# else +# define IVI_SETTINGS_CONNMAN_API __declspec(dllexport) +# endif +# else +# ifdef __GNUC__ +# define IVI_SETTINGS_CONNMAN_API __attribute__ ((dllimport)) +# else +# define IVI_SETTINGS_CONNMAN_API __declspec(dllimport) +# endif +# endif +# define IVI_SETTINGS_CONNMAN_LOCAL +# else +# if __GNUC__ >= 4 +# define IVI_SETTINGS_CONNMAN_API __attribute__ ((visibility ("default"))) +# define IVI_SETTINGS_CONNMAN_LOCAL __attribute__ ((visibility ("hidden"))) +# else +# define IVI_SETTINGS_CONNMAN_API +# define IVI_SETTINGS_CONNMAN_LOCAL +# endif +# endif + +#endif /* IVI_SETTINGS_CONNMAN_API_HPP */ + + +// Local Variables: +// mode:c++ +// c-basic-offset:2 +// indent-tabs-mode: nil +// End: diff --git a/plugins/connman/connman_manager.cpp b/plugins/connman/connman_manager.cpp new file mode 100644 index 0000000..0be40e8 --- /dev/null +++ b/plugins/connman/connman_manager.cpp @@ -0,0 +1,228 @@ +/** + * @file connman_manager.cpp + * + * @brief Connman_Manager-based settings plugin. + * + * @author Ossama Othman @<ossama.othman@@intel.com@> + * + * @copyright @par + * Copyright 2013 Intel Corporation All Rights Reserved. + * @par + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * @par + * This library 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 + * Lesser General Public License for more details. + * @par + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "connman_manager.hpp" + +#include <settingsd/json_glib_traits.hpp> +#include <settingsd/reverse_lock.hpp> + +#include <cstring> + + +namespace +{ + void + on_services_changed(GDBusConnection * /* connection */, + char const * /* sender_name */, + char const * /* object_path */, + char const * /* interface_name */, + char const * /* signal_name */, + GVariant * parameters, + gpointer user_data) + { + gsize const num_params = g_variant_n_children(parameters); + if (num_params != 2) { + // We should never get here! + g_printerr("Number of ServicesChanged signal parameters " + "is not 2: %" G_GSIZE_FORMAT "\n", + num_params); + + return; + } + + using namespace ivi::settings; + + // Changed services are found in the first ServicesChanged + // argument. + smart_ptr<GVariant> const changed_services( + g_variant_get_child_value(parameters, 0)); + + // Serialize the changed services into a JSON tree. This will be + // an array of [object, dict], where "object" is the D-Bus object + // path, and "dict" is a dictionary of object-specific + // properties. + smart_ptr<JsonNode> services( + json_gvariant_serialize(changed_services.get())); + + // Notify callers about the scan results. + typedef connman_manager::user_data user_data_type; + + user_data_type * const p = static_cast<user_data_type *>(user_data); + connman_manager::promise_list_type & promises = p->promises; + + // Synchronize access to the promises list. + std::lock_guard<std::mutex> lock(p->mutex); + + // Note that the end() iterator must be retrieved during each loop + // iteration in case another thread caused another promise to be + // added to the list when the lock was temporarily unlocked during + // the promise::set_value() call below. + for (auto i = promises.begin(); i != promises.end(); ) { + auto & promise = *i; + + { + // Release the mutex during the promise::set_value() + // call/notification so that we don't unnecessarily block + // threads attempting to get a services_changed promise. + typedef ivi::settings::reverse_lock<std::mutex> reverse_lock; + reverse_lock reverse(p->mutex); + + std::lock_guard<reverse_lock> kcol(reverse); + + // Thread that owns the corresponding future must transfer + // ownership of the JsonNode to something that will release + // the underlying JsonNode, e.g. a JsonBuilder via + // json_builder_add_value() or another smart_ptr<JsonNode>. + promise->set_value(std::move(services)); + } + + // Done with the pointer to the promise. Remove it from the + // list now since we already have an iterator to it. + i = promises.erase(i); + } + } + +} + +// --------------------------------------------------------------- + +ivi::settings::connman_manager::connman_manager() + : connman_("net.connman.Manager", // Interface + "/") // Object path + , mutex_() + , promises_() + , data_(mutex_, promises_) + , subscription_id_( + g_dbus_connection_signal_subscribe( + g_dbus_proxy_get_connection(G_DBUS_PROXY(connman_.proxy())), + nullptr, + connman_.interface_name(), + "ServicesChanged", + connman_.object_path(), + nullptr, + G_DBUS_SIGNAL_FLAGS_NONE, + on_services_changed, + &data_, + nullptr)) +{ +} + +ivi::settings::connman_manager::~connman_manager() +{ + g_dbus_connection_signal_unsubscribe( + g_dbus_proxy_get_connection(G_DBUS_PROXY(connman_.proxy())), + subscription_id_); +} + +GVariant * +ivi::settings::connman_manager::get_properties( + std::string const & technology, + GError *& error) const +{ + constexpr gint const timeout = 5000; // milliseconds + + smart_ptr<GVariant> const dictionary( + g_dbus_proxy_call_sync(connman_.proxy(), + "GetTechnologies", + nullptr, // No parameters + G_DBUS_CALL_FLAGS_NONE, + timeout, + nullptr, // Not cancellable + &error)); + + if (dictionary != nullptr) { + GVariantIter * i = nullptr; + g_variant_get(dictionary.get(), "(a(oa{sv}))", &i); + smart_ptr<GVariantIter> const safe_i(i); + + for (smart_ptr<GVariant> child(g_variant_iter_next_value(i)); + child != nullptr; + child.reset(g_variant_iter_next_value(i))) { + + // The object path is the first tuple element. + smart_ptr<GVariant> const tmp( + g_variant_get_child_value(child.get(), 0)); + + char const * object = + g_variant_get_string(tmp.get(), nullptr); + + // The technology is found at end the object path, + // e.g. "/net/connman/technology/wifi" for the wifi. + char const * tech = strrchr(object, '/'); + + if (tech != nullptr) { + ++tech; // Skip the found '/'. + + if (technology == tech) { + // The property dictionary is the second tuple element. + return g_variant_get_child_value(child.get(), 1); + } + } + } + } + + return nullptr; +} + +GVariant * +ivi::settings::connman_manager::get_services(GError *& error) const +{ + constexpr gint const timeout = 5000; // milliseconds + + return g_dbus_proxy_call_sync(connman_.proxy(), + "GetServices", + nullptr, // No parameters + G_DBUS_CALL_FLAGS_NONE, + timeout, + nullptr, // Not cancellable + &error); +} + +ivi::settings::connman_manager::shared_promise_type +ivi::settings::connman_manager::get_services_changed_promise() +{ + // This promise must exist long enough for the value to retrieved + // from the future. Use a shared_ptr<> to make that possible. + shared_promise_type p = std::make_shared<promise_type>(); + + { + std::lock_guard<std::mutex> lock(mutex_); + + // Add a new std::promise to the promises list. The promise will + // only be used once, and will be removed once its value has been + // set. + promises_.push_back(p); + } + + return p; +} + + +// Local Variables: +// mode:c++ +// c-basic-offset:2 +// indent-tabs-mode: nil +// End: diff --git a/plugins/connman/connman_manager.hpp b/plugins/connman/connman_manager.hpp new file mode 100644 index 0000000..352b9fe --- /dev/null +++ b/plugins/connman/connman_manager.hpp @@ -0,0 +1,175 @@ +/** + * @file connman_manager.hpp + * + * @brief Connman connman_manager-based settings plugin header. + * + * @author Ossama Othman @<ossama.othman@@intel.com@> + * + * @copyright @par + * Copyright 2013 Intel Corporation All Rights Reserved. + * @par + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * @par + * This library 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 + * Lesser General Public License for more details. + * @par + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef IVI_SETTINGS_CONNMAN_MANAGER_HPP +#define IVI_SETTINGS_CONNMAN_MANAGER_HPP + +#include "connman.hpp" + +#include <settingsd/glib_traits.hpp> +#include <settingsd/smart_ptr.hpp> + +#include <gio/gio.h> +#include <json-glib/json-glib.h> + +#include <future> +#include <list> +#include <memory> + + +namespace ivi +{ + namespace settings + { + /** + * @class connman_manager + * + * @brief Common connman-based settings functionality. + * + * This class implements functionality common to all connman-based + * settings, such as bluetooth, wifi, date/time, etc. + */ + class connman_manager + { + public: + + /// Constructor. + connman_manager(); + + /// Destructor. + ~connman_manager(); + + /** + * Get the properties for a specific technology. + * + * @param[in] technology Connman technology for which properties + * are being retrieved. + * @param[inout] error Glib error object that contains + * additional error information if + * non-null if the call completes. + * + * @return @c GVariant containing a dictionary of properties + * specific to @a technology. + */ + GVariant * get_properties(std::string const & technology, + GError *& error) const; + + /** + * Get connman services and their properties. + * + * @param[inout] error Glib error object that contains + * additional error information if + * non-null if the call completes. + * + * @return @c GVariant containing a dictionary services and + * corresponding properties. + */ + GVariant * get_services(GError *& error) const; + + /// The type held by the @c future containing the async result. + typedef smart_ptr<JsonNode> future_value_type; + + /// The @c future type returned by the @c promise. + typedef std::future<future_value_type> future_type; + + /// The @c promise that provides the async result. + typedef std::promise<future_value_type> promise_type; + + /** + * Smart pointer to the @c promise that provides the async + * result. + */ + typedef std::shared_ptr<promise_type> shared_promise_type; + + /// List type for promises to be updated with async result. + typedef std::list<shared_promise_type> promise_list_type; + + /** + * Get a promise that will contain changed connman services when + * they become available. The user must obtain the value from + * the corresponding future object and release the @c JsonNode* + * value contained within that future with @c json_node_free(). + */ + shared_promise_type get_services_changed_promise(); + + /** + * @struct user_data + * + * @brief Struct passed to @c ServicesChanged signal handler. + */ + struct user_data + { + /// Constructor. + user_data(std::mutex & m, promise_list_type & p) + : mutex(m) + , promises(p) + { + } + + /** + * References to mutex used to synchronize access to the list + * of promises. + */ + std::mutex & mutex; + + /// List of promises to be updated with the changed services. + promise_list_type & promises; + }; + + private: + + /// The proxy used to access the connman Manager D-Bus API. + connman connman_; + + /// Mutex used to synchronize access to the promises list. + std::mutex mutex_; + + /** + * List of promises that will be updated with the + * ServicesChanged signal results. + */ + promise_list_type promises_; + + /// User data passed to @c ServicesChanged signal handler. + user_data data_; + + /// ServicesChanged signal subscription ID. + guint const subscription_id_; + + }; + + } +} + + +#endif /* IVI_SETTINGS_CONNMAN_MANAGER_HPP */ + + +// Local Variables: +// mode:c++ +// c-basic-offset:2 +// indent-tabs-mode: nil +// End: diff --git a/plugins/connman/ethernet.cpp b/plugins/connman/ethernet.cpp new file mode 100644 index 0000000..3e8699c --- /dev/null +++ b/plugins/connman/ethernet.cpp @@ -0,0 +1,66 @@ +/** + * @file ethernet.cpp + * + * @brief Connman-based ethernet settings. + * + * @author Ossama Othman @<ossama.othman@@intel.com@> + * + * @copyright @par + * Copyright 2013 Intel Corporation All Rights Reserved. + * @par + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * @par + * This library 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 + * Lesser General Public License for more details. + * @par + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "ethernet.hpp" +#include <settingsd/response_callback.hpp> + +// ---------------------------------------------------------------------- + +namespace +{ + std::string const technology_name("ethernet"); +} + +// ---------------------------------------------------------------------- + +ivi::settings::ethernet::ethernet() + : technology_(technology_name) +{ +} + +ivi::settings::ethernet::~ethernet() +{ +} + +std::string const & +ivi::settings::ethernet::id() const +{ + return technology_name; +} + +void +ivi::settings::ethernet::handle_request(std::string request, + response_callback response) +{ + technology_.handle_request(request, response); +} + + +// Local Variables: +// mode:c++ +// c-basic-offset:2 +// indent-tabs-mode: nil +// End: diff --git a/plugins/connman/ethernet.hpp b/plugins/connman/ethernet.hpp new file mode 100644 index 0000000..65bf7fe --- /dev/null +++ b/plugins/connman/ethernet.hpp @@ -0,0 +1,96 @@ +/** + * @file ethernet.hpp + * + * @brief Ethernet settings plugin. + * + * Connman-based ethernet settings plugin. + * + * @author Ossama Othman @<ossama.othman@@intel.com@> + * + * @copyright @par + * Copyright 2012, 2013 Intel Corporation All Rights Reserved. + * @par + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * @par + * This library 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 + * Lesser General Public License for more details. + * @par + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * @note This header is internal. Settings provider plugin implementors + * should write their own library/symbol export macros as + * needed. + */ + + +#ifndef IVI_SETTINGS_CONNMAN_ETHERNET_HPP +#define IVI_SETTINGS_CONNMAN_ETHERNET_HPP + +#include <settingsd/plugin.hpp> + +#include "technology.hpp" + + +namespace ivi +{ + namespace settings + { + /** + * @class ethernet + * + * @brief Connman-based ethernet settings. + * + * This class implements all connman-based ethernet settings. + */ + class ethernet : public plugin + { + public: + + /// Constructor. + ethernet(); + + /// Destructor. + virtual ~ethernet(); + + /** + * @name Settings Plugin API + * + * Interface defined by the @c ivi::settings::plugin abstract + * base class. + * + * @see settingsd/plugin.hpp + */ + //@{ + virtual std::string const & id() const; + virtual void handle_request(std::string request, + response_callback response); + //@} + + private: + + /// Underlying connman proxy. + technology technology_; + + }; + + } +} + + +#endif /* IVI_SETTINGS_CONNMAN_ETHERNET_HPP */ + + +// Local Variables: +// mode:c++ +// c-basic-offset:2 +// indent-tabs-mode: nil +// End: + diff --git a/plugins/connman/registration.cpp b/plugins/connman/registration.cpp new file mode 100644 index 0000000..2719f3d --- /dev/null +++ b/plugins/connman/registration.cpp @@ -0,0 +1,65 @@ +/** + * @file registration.cpp + * + * @brief Connman-based settings plugin registration. + * + * @author Ossama Othman @<ossama.othman@@intel.com@> + * + * @copyright @par + * Copyright 2013 Intel Corporation All Rights Reserved. + * @par + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * @par + * This library 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 + * Lesser General Public License for more details. + * @par + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "connman_api.hpp" +#include "bluetooth.hpp" +#include "clock.hpp" +#include "ethernet.hpp" +#include "wifi.hpp" + +#include <settingsd/registrar.hpp> + +#include <memory> + + +/// Plugin factory/registration function. +extern "C" IVI_SETTINGS_CONNMAN_API bool +register_settings(ivi::settings::registrar & r) +{ + std::unique_ptr<ivi::settings::plugin> bt( + new ivi::settings::bluetooth); + + std::unique_ptr<ivi::settings::plugin> clk( + new ivi::settings::clock); + + std::unique_ptr<ivi::settings::plugin> eth( + new ivi::settings::ethernet); + + std::unique_ptr<ivi::settings::plugin> wifi( + new ivi::settings::wifi); + + return + r.register_setting(std::move(bt)) + && r.register_setting(std::move(clk)) + && r.register_setting(std::move(eth)) + && r.register_setting(std::move(wifi)); +} + +// Local Variables: +// mode:c++ +// c-basic-offset:2 +// indent-tabs-mode: nil +// End: diff --git a/plugins/connman/service.cpp b/plugins/connman/service.cpp new file mode 100644 index 0000000..ecf267d --- /dev/null +++ b/plugins/connman/service.cpp @@ -0,0 +1,87 @@ +/** + * @file service.cpp + * + * @brief Connman service request handling. + * + * @author Ossama Othman @<ossama.othman@@intel.com@> + * + * @copyright @par + * Copyright 2013 Intel Corporation All Rights Reserved. + * @par + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * @par + * This library 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 + * Lesser General Public License for more details. + * @par + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "service.hpp" + +#include <settingsd/glib_traits.hpp> +#include <settingsd/smart_ptr.hpp> +#include <settingsd/response_callback.hpp> + +#include <chrono> + + +ivi::settings::service::service(std::string service_path) + : connman_("net.connman.Service", // Interface + service_path.c_str()) // Object path +{ +} + +void +ivi::settings::service::connect(response_callback response) +{ + call_method("Connect", response); +} + +void +ivi::settings::service::disconnect(response_callback response) +{ + call_method("Disconnect", response); +} + +void +ivi::settings::service::call_method(char const * name, + response_callback response) +{ + constexpr gint const timeout = 10000; // milliseconds + GError * error = nullptr; + + smart_ptr<GVariant> const ret( + g_dbus_proxy_call_sync(connman_.proxy(), + name, // "Connect", "Disconect", ... + nullptr, // No parameters + G_DBUS_CALL_FLAGS_NONE, + timeout, + nullptr, // Not cancellable + &error)); + + smart_ptr<GError> safe_error; + + if (ret != nullptr) { + // Nothing to add to successful response. + response.send_response( + [](JsonBuilder * /* builder */) {}); + + } else if (error != nullptr) { + response.send_error(std::string(name) + " failed: " + error->message); + } +} + + +// Local Variables: +// mode:c++ +// c-basic-offset:2 +// indent-tabs-mode: nil +// End: diff --git a/plugins/connman/service.hpp b/plugins/connman/service.hpp new file mode 100644 index 0000000..a10268e --- /dev/null +++ b/plugins/connman/service.hpp @@ -0,0 +1,97 @@ +/** + * @file service.hpp + * + * @brief Connman service request handling. + * + * @author Ossama Othman @<ossama.othman@@intel.com@> + * + * @copyright @par + * Copyright 2013 Intel Corporation All Rights Reserved. + * @par + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * @par + * This library 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 + * Lesser General Public License for more details. + * @par + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef IVI_SETTINGS_CONNMAN_SERVICE_HPP +#define IVI_SETTINGS_CONNMAN_SERVICE_HPP + +#include "connman.hpp" +#include "connman_manager.hpp" + + +namespace ivi +{ + namespace settings + { + class response_callback; + + /** + * @class service + * + * @brief Connman Service object proxy. + * + * This class exposes functionality found in the connman + * @c Service interface to the caller. + */ + class service + { + public: + + /** + * Constructor. + * + * @param[in] service_path The D-Bus object path for connman + * service. + */ + service(std::string service_path); + + /// Connect to the service. + void connect(response_callback response); + + /// Disconnect from the service. + void disconnect(response_callback response); + + private: + + /** + * Call the method @a name on the connman Service object. + * + * @param[in] name The connman Service object method + * name. + * @param[inout] response Callback used to inform the caller of + * success or failure. + */ + void call_method(char const * name, + response_callback response); + + private: + + /// The proxy used to access the connman Service D-Bus API. + connman connman_; + + }; + + } +} + + +#endif /* IVI_SETTINGS_CONNMAN_SERVICE_HPP */ + + +// Local Variables: +// mode:c++ +// c-basic-offset:2 +// indent-tabs-mode: nil +// End: diff --git a/plugins/connman/technology.cpp b/plugins/connman/technology.cpp new file mode 100644 index 0000000..bda9a1e --- /dev/null +++ b/plugins/connman/technology.cpp @@ -0,0 +1,357 @@ +/** + * @file technology.cpp + * + * @brief Connman technology request handling. + * + * @author Ossama Othman @<ossama.othman@@intel.com@> + * + * @copyright @par + * Copyright 2013 Intel Corporation All Rights Reserved. + * @par + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * @par + * This library 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 + * Lesser General Public License for more details. + * @par + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "technology.hpp" +#include "service.hpp" +#include <settingsd/response_callback.hpp> +#include <settingsd/glib_traits.hpp> +#include <settingsd/json_glib_traits.hpp> +#include <settingsd/smart_ptr.hpp> + +#include <cstring> +#include <chrono> + + +ivi::settings::technology::technology(std::string tech) + : connman_("net.connman.Technology", // Interface + ("/net/connman/technology/" + + tech).c_str()) // Object path + , manager_() + , technology_(tech) +{ +} + +void +ivi::settings::technology::handle_request(std::string request, + response_callback response) +{ + smart_ptr<JsonParser> const parser(json_parser_new()); + json_parser_load_from_data(parser.get(), request.c_str(), -1, nullptr); + + smart_ptr<JsonReader> const safe_reader( + json_reader_new(json_parser_get_root(parser.get()))); + JsonReader * const reader = safe_reader.get(); + + char const * name = nullptr; + if (json_reader_read_member(reader, "name")) + name = json_reader_get_string_value(reader); + else + response.send_error( + "Malformed " + technology_ + " request: missing 'name' element"); + + json_reader_end_member(reader); + + if (name != nullptr) { + if (strcmp(name, "is_enabled") == 0) + get_powered(reader, response); + else if (strcmp(name, "enable") == 0) + set_powered(reader, response); + else if (strcmp(name, "scan") == 0) + scan(reader, response); + else if (strcmp(name, "connect") == 0) + connect(reader, response); + else if (strcmp(name, "disconnect") == 0) + disconnect(reader, response); + else { + response.send_error( + "Unrecognized " + technology_ + " request name: " + + name); + } + } else { + response.send_error( + "Operation name for " + technology_ + " request is not a string."); + } +} + +void +ivi::settings::technology::get_powered(JsonReader * reader, + response_callback response) +{ + bool null = false; + if (json_reader_read_member(reader, "value")) { + null = json_reader_get_null_value(reader); + } + json_reader_end_member(reader); + + if (!null) { + response.send_error( + technology_ + " is_enabled parameter is not null."); + return; + } + + smart_ptr<GVariant> const property( + get_property("Powered", G_VARIANT_TYPE_BOOLEAN, response)); + + if (property != nullptr) { + bool const powered = g_variant_get_boolean(property.get()); + + response.send_response( + [powered](JsonBuilder * builder) + { + json_builder_set_member_name(builder, "value"); + json_builder_add_boolean_value(builder, powered); + }); + } + + // Error responses handled in get_property() method. +} + +void +ivi::settings::technology::set_powered(JsonReader * reader, + response_callback response) +{ + bool enable = false; + if (json_reader_read_member(reader, "value")) { + enable = json_reader_get_boolean_value(reader); + } + + json_reader_end_member(reader); + + constexpr char const name[] = "Powered"; + + // Get notified when the technology property has changed. + auto property_promise = connman_.get_property_changed_promise(name); + auto property_future = property_promise->get_future(); + + GError * error = nullptr; + + smart_ptr<GVariant> ret( + connman_.set_property(name, + g_variant_new_boolean(enable), + error)); + + smart_ptr<GError> safe_error(error); + + if (ret != nullptr) { + constexpr int const timeout = 5000; // milliseconds + + // Block until the technology property has changed.. + std::future_status const status = + property_future.wait_for(std::chrono::milliseconds(timeout)); + + if (status == std::future_status::ready) { + + // Nothing to add to successful response. + response.send_response( + [](JsonBuilder * /* builder */) {}); + + } else { + + response.send_error( + std::string("Wait for enable status failed: ") + + (status == std::future_status::timeout + ? "timeout" + : "deferred")); + + } + } else if (error != nullptr) { + response.send_error( + "Unable to set " + technology_ + " powered state: " + + error->message); + } else { + response.send_error( + "Malformed " + technology_ + " enable request value."); + } +} + +void +ivi::settings::technology::scan(JsonReader * reader, + response_callback response) +{ + bool null = false; + if (json_reader_read_member(reader, "value")) { + null = json_reader_get_null_value(reader); + } + json_reader_end_member(reader); + + if (!null) { + response.send_error(technology_ + " scan parameter is not null."); + return; + } + + // Get notified when scan results are available. + auto services_promise = manager_.get_services_changed_promise(); + auto services_future = services_promise->get_future(); + + // The scan could take a while. + constexpr gint const timeout = 10000; // milliseconds + GError * error = nullptr; + + smart_ptr<GVariant> const ret( + g_dbus_proxy_call_sync(connman_.proxy(), + "Scan", + nullptr, // No parameters + G_DBUS_CALL_FLAGS_NONE, + timeout, + nullptr, // Not cancellable + &error)); + + smart_ptr<GError> safe_error(error); + + if (ret != nullptr) { + constexpr gint const future_timeout = 5000; // milliseconds + + // Block until the scan results are in. + std::future_status const status = + services_future.wait_for(std::chrono::milliseconds(future_timeout)); + + if (status != std::future_status::deferred) { + // Don't call get() if the future isn't ready. Otherwise this + // will be a blocking call. + if (status == std::future_status::ready) { + smart_ptr<JsonNode> const changed_services(services_future.get()); + } + + send_services(response, error); + + // A timeout is okay since some services may not have changed + // within the timeout period but log it just in case. + if (status == std::future_status::timeout) + g_debug("%s settings: Timed out waiting for changed services.\n", + technology_.c_str()); + } else { + // We only get here if the future status is + // std::future_status::deferred, meaning the result hasn't been + // determined yet. That should never happen in our case. + response.send_error("Wait for scan results failed: deferred"); + } + } else if (error != nullptr) { + response.send_error( + "Unable to scan " + technology_ + ": " + + error->message); + } else { + response.send_error( + "Malformed " + technology_ + " scan request value."); + } +} + +void +ivi::settings::technology::connect(JsonReader * reader, + response_callback response) +{ + char const * service_path = nullptr; + if (json_reader_read_member(reader, "value")) { + service_path = json_reader_get_string_value(reader); + } + json_reader_end_member(reader); + + /// @todo Refactor malformed JSON request handling code. + if (service_path != nullptr) { + service s(service_path); + s.connect(response); + } else { + response.send_error( + "Malformed " + technology_ + " connect request value."); + } +} + +void +ivi::settings::technology::disconnect(JsonReader * reader, + response_callback response) +{ + char const * service_path = nullptr; + if (json_reader_read_member(reader, "value")) { + service_path = json_reader_get_string_value(reader); + } + json_reader_end_member(reader); + + if (service_path != nullptr) { + service s(service_path); + s.disconnect(response); + } else { + response.send_error( + "Malformed " + technology_ + " disconnect request value."); + } +} + +void +ivi::settings::technology::send_services(response_callback response, + GError *& error) +{ + smart_ptr<GVariant> const services(manager_.get_services(error)); + + if (services != nullptr) { + response.send_response( + [&services](JsonBuilder * builder) + { + /** + * @todo Can @c json_gvariant_serialize() ever return a nullptr? + */ + JsonNode * const value = + json_gvariant_serialize(services.get()); + + json_builder_set_member_name(builder, "value"); + json_builder_add_value(builder, value); + + // No need to free the JsonNode. The builder will take + // ownership of it. + }); + } +} + +GVariant * +ivi::settings::technology::get_property(char const * name, + GVariantType const * type, + response_callback response) +{ + GError * error = nullptr; + + smart_ptr<GVariant> const properties( + manager_.get_properties(technology_, error)); + + smart_ptr<GError> safe_error(error); + + smart_ptr<GVariant> property; + if (properties != nullptr) { + property.reset( + g_variant_lookup_value(properties.get(), name, type)); + + if (property == nullptr) { + response.send_error( + "Internal " + technology_ + + "error: \"" + name + "\" property lookup failed."); + } + } else if (error != nullptr) { + response.send_error( + "Unable to get " + technology_ + "properties: " + + error->message); + } else { + // This scenario will occur if the technology doesn't exist on + // the platform. For example, attempting to retrieve the wifi + // "Powered" property on a platform without supported hardware + // will result in this error. + response.send_error(technology_ + " properties are not available."); + } + + return property.release(); +} + + +// Local Variables: +// mode:c++ +// c-basic-offset:2 +// indent-tabs-mode: nil +// End: diff --git a/plugins/connman/technology.hpp b/plugins/connman/technology.hpp new file mode 100644 index 0000000..44fdef6 --- /dev/null +++ b/plugins/connman/technology.hpp @@ -0,0 +1,139 @@ +/** + * @file technology.hpp + * + * @brief Connman technology request handling. + * + * @author Ossama Othman @<ossama.othman@@intel.com@> + * + * @copyright @par + * Copyright 2013 Intel Corporation All Rights Reserved. + * @par + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * @par + * This library 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 + * Lesser General Public License for more details. + * @par + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef IVI_SETTINGS_CONNMAN_TECHNOLOGY_HPP +#define IVI_SETTINGS_CONNMAN_TECHNOLOGY_HPP + +#include "connman.hpp" +#include "connman_manager.hpp" + +#include <json-glib/json-glib.h> + + +namespace ivi +{ + namespace settings + { + class response_callback; + + /** + * @class technology + * + * @brief Common technology-based settings functionality. + * + * This class implements functionality common to all technology-based + * settings, such as bluetooth, wifi, date/time, etc. + */ + class technology + { + public: + + /** + * Constructor. + * + * @param[in] tech The connman technology, e.g. "bluetooth". + */ + technology(std::string tech); + + /// Handle requests common to all connman technologies. + void handle_request(std::string request, + response_callback response); + + private: + + /// Get technology "Powered" state. + void get_powered(JsonReader * reader, + response_callback response); + + /// Set technology "Powered" state. + void set_powered(JsonReader * reader, + response_callback response); + + /** + * Scan for services that implement the technology, e.g. WiFi + * access points. + */ + void scan(JsonReader * reader, + response_callback response); + + /** + * Connect to service whose object path is found in the JSON + * request. + */ + void connect(JsonReader * reader, + response_callback response); + + /** + * Disconnect from service whose object path is found in the + * JSON request. + */ + void disconnect(JsonReader * reader, + response_callback response); + + /// Send list of services to caller. + void send_services(response_callback response, + GError *& error); + + /** + * Get property for this technology. + * + * @param[in] name Name of the connman technology property + * to retrieve. + * @param[in] type The type of property being retrieved. + * @param[in] response The response callback through errors will + * be sent to the caller. + * + * @returns A @c GVariant containing the retrieved property. + */ + GVariant * get_property(char const * name, + GVariantType const * type, + response_callback response); + + private: + + /// The proxy used to access the connman Technology D-Bus API. + connman connman_; + + /// The proxy used to access the connman Manager D-Bus API. + connman_manager manager_; + + /// Technology name, e.g. "bluetooth" or "wifi". + std::string const technology_; + + }; + + } +} + + +#endif /* IVI_SETTINGS_CONNMAN_TECHNOLOGY_HPP */ + + +// Local Variables: +// mode:c++ +// c-basic-offset:2 +// indent-tabs-mode: nil +// End: diff --git a/plugins/connman/wifi.cpp b/plugins/connman/wifi.cpp new file mode 100644 index 0000000..15bebe6 --- /dev/null +++ b/plugins/connman/wifi.cpp @@ -0,0 +1,66 @@ +/** + * @file wifi.cpp + * + * @brief Connman-based wifi settings. + * + * @author Ossama Othman @<ossama.othman@@intel.com@> + * + * @copyright @par + * Copyright 2013 Intel Corporation All Rights Reserved. + * @par + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * @par + * This library 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 + * Lesser General Public License for more details. + * @par + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "wifi.hpp" +#include <settingsd/response_callback.hpp> + +// ---------------------------------------------------------------------- + +namespace +{ + std::string const technology_name("wifi"); +} + +// ---------------------------------------------------------------------- + +ivi::settings::wifi::wifi() + : technology_(technology_name) +{ +} + +ivi::settings::wifi::~wifi() +{ +} + +std::string const & +ivi::settings::wifi::id() const +{ + return technology_name; +} + +void +ivi::settings::wifi::handle_request(std::string request, + response_callback response) +{ + technology_.handle_request(request, response); +} + + +// Local Variables: +// mode:c++ +// c-basic-offset:2 +// indent-tabs-mode: nil +// End: diff --git a/plugins/connman/wifi.hpp b/plugins/connman/wifi.hpp new file mode 100644 index 0000000..d82c82b --- /dev/null +++ b/plugins/connman/wifi.hpp @@ -0,0 +1,98 @@ +/** + * @file wifi.hpp + * + * @brief Wifi settings plugin. + * + * Connman-based wifi settings plugin. + * + * @author Ossama Othman @<ossama.othman@@intel.com@> + * + * @copyright @par + * Copyright 2012, 2013 Intel Corporation All Rights Reserved. + * @par + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * @par + * This library 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 + * Lesser General Public License for more details. + * @par + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * @note This header is internal. Settings provider plugin implementors + * should write their own library/symbol export macros as + * needed. + */ + + +#ifndef IVI_SETTINGS_CONNMAN_WIFI_HPP +#define IVI_SETTINGS_CONNMAN_WIFI_HPP + +#include <settingsd/plugin.hpp> + +#include "technology.hpp" + + +namespace ivi +{ + namespace settings + { + class response_callback; + + /** + * @class wifi + * + * @brief Connman-based wifi settings. + * + * This class implements all connman-based wifi settings. + */ + class wifi : public plugin + { + public: + + /// Constructor. + wifi(); + + /// Destructor. + virtual ~wifi(); + + /** + * @name Settings Plugin API + * + * Interface defined by the @c ivi::settings::plugin abstract + * base class. + * + * @see settingsd/plugin.hpp + */ + //@{ + virtual std::string const & id() const; + virtual void handle_request(std::string request, + response_callback response); + //@} + + private: + + /// Underlying connman proxy. + technology technology_; + + }; + + } +} + + +#endif /* IVI_SETTINGS_CONNMAN_WIFI_HPP */ + + +// Local Variables: +// mode:c++ +// c-basic-offset:2 +// indent-tabs-mode: nil +// End: + |