[PATCH] cbs: Resolve a use-after-free that could occur with rapid location changes.
by John Ernberg
From: John Ernberg <john.ernberg(a)actia.se>
What happens is that the timeout leaks and then the cbs struct with
the callback is cleaned up, resulting in a SIGSEGV when the callback
occurs from the glib loop.
---
src/cbs.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/cbs.c b/src/cbs.c
index b5f0b72..fdc44a1 100644
--- a/src/cbs.c
+++ b/src/cbs.c
@@ -1029,11 +1029,14 @@ out:
/*
* In order to minimize signal transmissions we wait about X seconds
- * before reseting the base station id. The hope is that we receive
+ * before resetting the base station id. The hope is that we receive
* another cell broadcast with the new base station name within
* that time
*/
if (lac_changed || ci_changed) {
+ if(cbs->reset_source)
+ g_source_remove(cbs->reset_source);
+
cbs->reset_source =
g_timeout_add_seconds(3, reset_base_station_name, cbs);
}
--
1.9.1
6 years, 7 months
[PATCH] gprs: Make the ContextAdded return a variant.
by John Ernberg
From: John Ernberg <john.ernberg(a)actia.se>
I am not sure if this is the desired way to resolve this issue. This will
break compatibility with Connman and possibly other systems using oFono
through D-Bus.
I do have a patch for Connman that I can send to them if this patch is
accepted, but not for any other potential systems.
It is also possible to change the introspection and the documentation,
the proposed patch is however more in line with the rest of oFono's
D-Bus API.
Discussion regarding this is encouraged before any possible acception
of this patch.
John Ernberg (1):
gprs: Make the ContextAdded return a variant.
src/gprs.c | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
--
1.9.1
6 years, 7 months
[PATCH 1/2 v5] plugins: add upower battery monitor for bluetooth
by Tony Espy
---
plugins/upower.c | 370 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 370 insertions(+)
create mode 100644 plugins/upower.c
diff --git a/plugins/upower.c b/plugins/upower.c
new file mode 100644
index 0000000..f3c33b7
--- /dev/null
+++ b/plugins/upower.c
@@ -0,0 +1,370 @@
+/*
+ *
+ * oFono - Open Source Telephony
+ *
+ * Copyright (C) 2015 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <gdbus.h>
+#include <ofono.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/plugin.h>
+#include <ofono/modem.h>
+#include <ofono/log.h>
+#include <ofono/emulator.h>
+
+#define DBUS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
+#define UPOWER_SERVICE "org.freedesktop.UPower"
+#define UPOWER_PATH "/org/freedesktop/UPower"
+#define UPOWER_INTERFACE UPOWER_SERVICE
+#define UPOWER_DEVICE_INTERFACE UPOWER_SERVICE ".Device"
+
+static guint modem_watch;
+static guint upower_daemon_watch;
+static DBusConnection *connection;
+static int last_battery_level;
+static char *battery_device_path;
+
+static void emulator_battery_cb(struct ofono_atom *atom, void *data)
+{
+ struct ofono_emulator *em = __ofono_atom_get_data(atom);
+ int val = GPOINTER_TO_INT(data);
+
+ DBG("calling set_indicator: %d", val);
+ ofono_emulator_set_indicator(em, OFONO_EMULATOR_IND_BATTERY, val);
+}
+
+static void update_modem_battery_indicator(struct ofono_modem *modem,
+ void *data)
+{
+ __ofono_modem_foreach_registered_atom(modem,
+ OFONO_ATOM_TYPE_EMULATOR_HFP,
+ emulator_battery_cb,
+ data);
+}
+
+static void update_battery_level(double percentage_val)
+{
+ int battery_level;
+
+ if (percentage_val <= 1.00) {
+ battery_level = 0;
+ } else if (percentage_val > 1.00 && percentage_val <= 100.00) {
+ battery_level = ((int) percentage_val - 1) / 20 + 1;
+ } else {
+ ofono_error("%s: Invalid value for battery level: %f",
+ __func__,
+ percentage_val);
+ return;
+ }
+
+ DBG("last_battery_level: %d battery_level: %d (%f)", last_battery_level,
+ battery_level, percentage_val);
+
+ if (last_battery_level == battery_level)
+ return;
+
+ last_battery_level = battery_level;
+
+ __ofono_modem_foreach(update_modem_battery_indicator,
+ GINT_TO_POINTER(battery_level));
+}
+
+static gboolean battery_props_changed(DBusConnection *conn, DBusMessage *msg,
+ void *user_data)
+
+{
+ const char *iface;
+ DBusMessageIter iter, dict;
+ double percentage_val;
+ gboolean percentage_found = FALSE;
+ gboolean retval = FALSE;
+
+ DBG("");
+
+ dbus_message_iter_init(msg, &iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) {
+ ofono_error("%s: iface != TYPE_STRING!", __func__);
+ goto done;
+ }
+
+ dbus_message_iter_get_basic(&iter, &iface);
+
+ if (g_str_equal(iface, UPOWER_DEVICE_INTERFACE) != TRUE) {
+ ofono_error("%s: wrong iface: %s!", __func__, iface);
+ goto done;
+ }
+
+ if (!dbus_message_iter_next(&iter)) {
+ ofono_error("%s: advance iter failed!", __func__);
+ goto done;
+ }
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
+ ofono_error("%s: type != ARRAY!", __func__);
+ goto done;
+ }
+
+ dbus_message_iter_recurse(&iter, &dict);
+
+ while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+ DBusMessageIter entry, val;
+ const char *key;
+
+ dbus_message_iter_recurse(&dict, &entry);
+
+ if (dbus_message_iter_get_arg_type(&entry) !=
+ DBUS_TYPE_STRING) {
+ ofono_error("%s: key type != STRING!", __func__);
+ goto done;
+ }
+
+ dbus_message_iter_get_basic(&entry, &key);
+
+ if (g_str_equal(key, "Percentage") != TRUE) {
+ dbus_message_iter_next(&dict);
+ continue;
+ }
+
+ dbus_message_iter_next(&entry);
+ if (dbus_message_iter_get_arg_type(&entry) !=
+ DBUS_TYPE_VARIANT) {
+ ofono_error("%s: 'Percentage' val != VARIANT",
+ __func__);
+ goto done;
+ }
+
+ dbus_message_iter_recurse(&entry, &val);
+
+ if (dbus_message_iter_get_arg_type(&val) != DBUS_TYPE_DOUBLE) {
+ ofono_error("%s: 'Percentage' val != DOUBLE", __func__);
+ goto done;
+ }
+
+ dbus_message_iter_get_basic(&val, &percentage_val);
+ percentage_found = TRUE;
+ break;
+ }
+
+ /* No errors found during parsing, so don't trigger cb removal */
+ retval = TRUE;
+
+ if (percentage_found == FALSE)
+ goto done;
+
+ update_battery_level(percentage_val);
+
+done:
+ return retval;
+}
+
+static void emulator_hfp_watch(struct ofono_atom *atom,
+ enum ofono_atom_watch_condition cond,
+ void *data)
+{
+ if (cond == OFONO_ATOM_WATCH_CONDITION_REGISTERED) {
+ struct ofono_emulator *em = __ofono_atom_get_data(atom);
+
+ DBG("REGISTERED; calling set_indicator: %d", last_battery_level);
+
+ ofono_emulator_set_indicator(em, OFONO_EMULATOR_IND_BATTERY,
+ last_battery_level);
+ return;
+ }
+
+ DBG("UNREGISTERED");
+}
+
+static void modemwatch(struct ofono_modem *modem, gboolean added, void *user)
+{
+
+ const char *path = ofono_modem_get_path(modem);
+
+ DBG("modem: %s, added: %d", path, added);
+
+ if (added)
+ __ofono_modem_add_atom_watch(modem,
+ OFONO_ATOM_TYPE_EMULATOR_HFP,
+ emulator_hfp_watch, NULL, NULL);
+
+}
+
+static void call_modemwatch(struct ofono_modem *modem, void *user)
+{
+ modemwatch(modem, TRUE, user);
+}
+
+static gboolean parse_devices_reply(DBusMessage *reply)
+{
+ DBusMessageIter array, iter;
+ const char *path;
+
+ DBG("");
+
+ if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
+ ofono_error("%s: ERROR reply to EnumerateDevices", __func__);
+ return FALSE;
+ }
+
+ if (dbus_message_iter_init(reply, &array) == FALSE) {
+ ofono_error("%s: error initializing array iter", __func__);
+ return FALSE;
+ }
+
+ if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY) {
+ ofono_error("%s: type != ARRAY!", __func__);
+ return FALSE;
+ }
+
+ dbus_message_iter_recurse(&array, &iter);
+
+ while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_OBJECT_PATH) {
+
+ dbus_message_iter_get_basic(&iter, &path);
+
+ if (g_strrstr(path, "/battery_")) {
+ ofono_info("%s: found 1st battery device: %s", __func__,
+ path);
+ battery_device_path = g_strdup(path);
+ break;
+ }
+
+ if (!dbus_message_iter_next(&iter))
+ break;
+ }
+
+ return TRUE;
+}
+
+static void enum_devices_reply(DBusPendingCall *call, void *user_data)
+{
+ DBusMessage *reply;
+
+ DBG("");
+
+ reply = dbus_pending_call_steal_reply(call);
+ if (reply == NULL) {
+ ofono_error("%s: dbus_message_new_method failed", __func__);
+ goto done;
+ }
+
+ if (parse_devices_reply(reply) == FALSE)
+ goto done;
+
+ DBG("parse_devices_reply OK");
+
+ /* TODO: handle removable batteries */
+
+ if (battery_device_path == NULL) {
+ ofono_error("%s: no battery detected", __func__);
+ goto done;
+ }
+
+ /* Always listen to PropertiesChanged for battery */
+ g_dbus_add_signal_watch(connection, UPOWER_SERVICE, battery_device_path,
+ DBUS_INTERFACE_PROPERTIES,
+ "PropertiesChanged",
+ battery_props_changed,
+ NULL, NULL);
+
+ modem_watch = __ofono_modemwatch_add(modemwatch, NULL, NULL);
+ __ofono_modem_foreach(call_modemwatch, NULL);
+
+done:
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_pending_call_unref(call);
+}
+
+static void upower_connect(DBusConnection *conn, void *user_data)
+{
+ DBusPendingCall *call;
+ DBusMessage *msg;
+
+ DBG("upower connect");
+
+ msg = dbus_message_new_method_call(UPOWER_SERVICE,
+ UPOWER_PATH,
+ UPOWER_INTERFACE,
+ "EnumerateDevices");
+ if (msg == NULL) {
+ ofono_error("%s: dbus_message_new_method failed", __func__);
+ return;
+ }
+
+ if (!dbus_connection_send_with_reply(conn, msg, &call, -1)) {
+ ofono_error("%s: Sending EnumerateDevices failed", __func__);
+ goto done;
+ }
+
+ dbus_pending_call_set_notify(call, enum_devices_reply, NULL, NULL);
+done:
+ dbus_message_unref(msg);
+}
+
+static void upower_disconnect(DBusConnection *conn, void *user_data)
+{
+ DBG("upower disconnect");
+
+ if (modem_watch) {
+ __ofono_modemwatch_remove(modem_watch);
+ modem_watch = 0;
+ }
+
+ if (battery_device_path) {
+ g_free(battery_device_path);
+ battery_device_path = NULL;
+ }
+}
+
+static int upower_init(void)
+{
+ DBG("upower init");
+
+ connection = ofono_dbus_get_connection();
+ upower_daemon_watch = g_dbus_add_service_watch(connection,
+ UPOWER_SERVICE,
+ upower_connect,
+ upower_disconnect,
+ NULL, NULL);
+
+ return 0;
+}
+
+static void upower_exit(void)
+{
+ if (upower_daemon_watch)
+ g_dbus_remove_watch(connection, upower_daemon_watch);
+
+ if (modem_watch)
+ __ofono_modemwatch_remove(modem_watch);
+
+ if (battery_device_path)
+ g_free(battery_device_path);
+
+}
+
+OFONO_PLUGIN_DEFINE(upower, "upower battery monitor", VERSION,
+ OFONO_PLUGIN_PRIORITY_DEFAULT, upower_init, upower_exit)
--
2.1.4
6 years, 7 months
[PATCH v2] build: untangle ATMODEM and BLUETOOTH conditionals
by Tony Espy
---
Makefile.am | 30 +++++++++++++++++-------------
1 file changed, 17 insertions(+), 13 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index b22c04b..8bbe25c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -478,9 +478,6 @@ builtin_sources += plugins/ublox.c
if BLUETOOTH
if BLUEZ4
-builtin_modules += bluez4
-builtin_sources += plugins/bluez4.c plugins/bluez4.h
-
builtin_modules += telit
builtin_sources += plugins/telit.c plugins/bluez4.h
@@ -490,11 +487,25 @@ builtin_sources += plugins/sap.c plugins/bluez4.h
builtin_modules += hfp_bluez4
builtin_sources += plugins/hfp_hf_bluez4.c plugins/bluez4.h
-builtin_modules += hfp_ag_bluez4
-builtin_sources += plugins/hfp_ag_bluez4.c plugins/bluez4.h
-
builtin_modules += dun_gw_bluez4
builtin_sources += plugins/dun_gw_bluez4.c plugins/bluez4.h
+else
+builtin_modules += hfp_bluez5
+builtin_sources += plugins/hfp_hf_bluez5.c plugins/bluez5.h
+
+builtin_modules += dun_gw_bluez5
+builtin_sources += plugins/dun_gw_bluez5.c plugins/bluez5.h
+endif
+endif
+endif
+
+if BLUETOOTH
+if BLUEZ4
+builtin_modules += bluez4
+builtin_sources += plugins/bluez4.c plugins/bluez4.h
+
+builtin_modules += hfp_ag_bluez4
+builtin_sources += plugins/hfp_ag_bluez4.c plugins/bluez4.h
builtin_sources += $(btio_sources)
builtin_cflags += @BLUEZ_CFLAGS@
@@ -503,15 +514,8 @@ else
builtin_modules += bluez5
builtin_sources += plugins/bluez5.c plugins/bluez5.h
-builtin_modules += hfp_bluez5
-builtin_sources += plugins/hfp_hf_bluez5.c plugins/bluez5.h
-
builtin_modules += hfp_ag_bluez5
builtin_sources += plugins/hfp_ag_bluez5.c plugins/bluez5.h
-
-builtin_modules += dun_gw_bluez5
-builtin_sources += plugins/dun_gw_bluez5.c plugins/bluez5.h
-endif
endif
endif
--
2.1.4
6 years, 7 months
Add/Remove phonesim on the fly
by Xavier Claessens
Ubuntu's ofono has a useful DBus interface to add/remove modems. Would
make sense to upstream that patch.
Regards,
Xavier Claessens.
6 years, 7 months
[PATCH 1/2 v4] plugins: add upower battery monitor for bluetooth
by Tony Espy
---
plugins/upower.c | 388 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 388 insertions(+)
create mode 100644 plugins/upower.c
diff --git a/plugins/upower.c b/plugins/upower.c
new file mode 100644
index 0000000..5500f00
--- /dev/null
+++ b/plugins/upower.c
@@ -0,0 +1,388 @@
+/*
+ *
+ * oFono - Open Source Telephony
+ *
+ * Copyright (C) 2015 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <gdbus.h>
+#include <ofono.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/plugin.h>
+#include <ofono/modem.h>
+#include <ofono/log.h>
+#include <ofono/emulator.h>
+
+#define DBUS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
+#define UPOWER_SERVICE "org.freedesktop.UPower"
+#define UPOWER_PATH "/org/freedesktop/UPower"
+#define UPOWER_INTERFACE UPOWER_SERVICE
+#define UPOWER_DEVICE_INTERFACE UPOWER_SERVICE ".Device"
+
+static guint modem_watch;
+static guint upower_daemon_watch;
+static DBusConnection *connection;
+static GHashTable *modem_hfp_watches;
+static int last_battery_level;
+static char *battery_device_path;
+
+static void emulator_battery_cb(struct ofono_atom *atom, void *data)
+{
+ struct ofono_emulator *em = __ofono_atom_get_data(atom);
+ int val = GPOINTER_TO_INT(data);
+
+ DBG("calling set_indicator: %d", val);
+ ofono_emulator_set_indicator(em, OFONO_EMULATOR_IND_BATTERY, val);
+}
+
+static void update_modem_battery_indicator(struct ofono_modem *modem,
+ void *data)
+{
+ __ofono_modem_foreach_registered_atom(modem,
+ OFONO_ATOM_TYPE_EMULATOR_HFP,
+ emulator_battery_cb,
+ data);
+}
+
+static void update_battery_level(double percentage_val)
+{
+ int battery_level;
+
+ if (percentage_val <= 1.00) {
+ battery_level = 0;
+ } else if (percentage_val > 1.00 && percentage_val <= 100.00) {
+ battery_level = ((int) percentage_val - 1) / 20 + 1;
+ } else {
+ ofono_error("%s: Invalid value for battery level: %f",
+ __func__,
+ percentage_val);
+ return;
+ }
+
+ DBG("last_battery_level: %d battery_level: %d (%f)", last_battery_level,
+ battery_level, percentage_val);
+
+ if (last_battery_level == battery_level)
+ return;
+
+ last_battery_level = battery_level;
+
+ __ofono_modem_foreach(update_modem_battery_indicator,
+ GINT_TO_POINTER(battery_level));
+}
+
+static gboolean battery_props_changed(DBusConnection *conn, DBusMessage *msg,
+ void *user_data)
+
+{
+ const char *iface;
+ DBusMessageIter iter, dict;
+ double percentage_val;
+ gboolean percentage_found = FALSE;
+ gboolean retval = FALSE;
+
+ DBG("");
+
+ dbus_message_iter_init(msg, &iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) {
+ ofono_error("%s: iface != TYPE_STRING!", __func__);
+ goto done;
+ }
+
+ dbus_message_iter_get_basic(&iter, &iface);
+
+ if (g_str_equal(iface, UPOWER_DEVICE_INTERFACE) != TRUE) {
+ ofono_error("%s: wrong iface: %s!", __func__, iface);
+ goto done;
+ }
+
+ if (!dbus_message_iter_next(&iter)) {
+ ofono_error("%s: advance iter failed!", __func__);
+ goto done;
+ }
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
+ ofono_error("%s: type != ARRAY!", __func__);
+ goto done;
+ }
+
+ dbus_message_iter_recurse(&iter, &dict);
+
+ while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+ DBusMessageIter entry, val;
+ const char *key;
+
+ dbus_message_iter_recurse(&dict, &entry);
+
+ if (dbus_message_iter_get_arg_type(&entry) !=
+ DBUS_TYPE_STRING) {
+ ofono_error("%s: key type != STRING!", __func__);
+ goto done;
+ }
+
+ dbus_message_iter_get_basic(&entry, &key);
+
+ if (g_str_equal(key, "Percentage") != TRUE) {
+ dbus_message_iter_next(&dict);
+ continue;
+ }
+
+ dbus_message_iter_next(&entry);
+ if (dbus_message_iter_get_arg_type(&entry) !=
+ DBUS_TYPE_VARIANT) {
+ ofono_error("%s: 'Percentage' val != VARIANT",
+ __func__);
+ goto done;
+ }
+
+ dbus_message_iter_recurse(&entry, &val);
+
+ if (dbus_message_iter_get_arg_type(&val) != DBUS_TYPE_DOUBLE) {
+ ofono_error("%s: 'Percentage' val != DOUBLE", __func__);
+ goto done;
+ }
+
+ dbus_message_iter_get_basic(&val, &percentage_val);
+ percentage_found = TRUE;
+ break;
+ }
+
+ /* No errors found during parsing, so don't trigger cb removal */
+ retval = TRUE;
+
+ if (percentage_found == FALSE)
+ goto done;
+
+ update_battery_level(percentage_val);
+
+done:
+ return retval;
+}
+
+static void emulator_hfp_watch(struct ofono_atom *atom,
+ enum ofono_atom_watch_condition cond,
+ void *data)
+{
+ if (cond == OFONO_ATOM_WATCH_CONDITION_REGISTERED) {
+ struct ofono_emulator *em = __ofono_atom_get_data(atom);
+
+ DBG("REGISTERED; calling set_indicator: %d", last_battery_level);
+
+ ofono_emulator_set_indicator(em, OFONO_EMULATOR_IND_BATTERY,
+ last_battery_level);
+ return;
+ }
+
+ DBG("UNREGISTERED");
+}
+
+static void modemwatch(struct ofono_modem *modem, gboolean added, void *user)
+{
+
+ const char *path = ofono_modem_get_path(modem);
+
+ DBG("modem: %s, added: %d", path, added);
+
+ if (added) {
+ guint watch_id;
+
+ watch_id = __ofono_modem_add_atom_watch(modem,
+ OFONO_ATOM_TYPE_EMULATOR_HFP,
+ emulator_hfp_watch, NULL, NULL);
+
+ g_hash_table_insert(modem_hfp_watches, g_strdup(path),
+ GINT_TO_POINTER(watch_id));
+
+ } else {
+ guint *watch_id = g_hash_table_lookup(modem_hfp_watches, path);
+
+ if (watch_id != NULL) {
+ __ofono_modem_remove_atom_watch(modem, *watch_id);
+ g_hash_table_remove(modem_hfp_watches, path);
+ }
+ }
+}
+
+static void call_modemwatch(struct ofono_modem *modem, void *user)
+{
+ modemwatch(modem, TRUE, user);
+}
+
+static gboolean parse_devices_reply(DBusMessage *reply)
+{
+ DBusMessageIter array, iter;
+ const char *path;
+
+ DBG("");
+
+ if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
+ ofono_error("%s: ERROR reply to EnumerateDevices", __func__);
+ return FALSE;
+ }
+
+ if (dbus_message_iter_init(reply, &array) == FALSE) {
+ ofono_error("%s: error initializing array iter", __func__);
+ return FALSE;
+ }
+
+ if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY) {
+ ofono_error("%s: type != ARRAY!", __func__);
+ return FALSE;
+ }
+
+ dbus_message_iter_recurse(&array, &iter);
+
+ while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_OBJECT_PATH) {
+
+ dbus_message_iter_get_basic(&iter, &path);
+
+ if (g_strrstr(path, "/battery_")) {
+ ofono_info("%s: found 1st battery device: %s", __func__,
+ path);
+ battery_device_path = g_strdup(path);
+ break;
+ }
+
+ if (!dbus_message_iter_next(&iter))
+ break;
+ }
+
+ return TRUE;
+}
+
+static void enum_devices_reply(DBusPendingCall *call, void *user_data)
+{
+ DBusMessage *reply;
+
+ DBG("");
+
+ reply = dbus_pending_call_steal_reply(call);
+ if (reply == NULL) {
+ ofono_error("%s: dbus_message_new_method failed", __func__);
+ goto done;
+ }
+
+ if (parse_devices_reply(reply) == FALSE)
+ goto done;
+
+ DBG("parse_devices_reply OK");
+
+ /* TODO: handle removable batteries */
+
+ if (battery_device_path == NULL) {
+ ofono_error("%s: no battery detected", __func__);
+ goto done;
+ }
+
+ /* Always listen to PropertiesChanged for battery */
+ g_dbus_add_signal_watch(connection, UPOWER_SERVICE, battery_device_path,
+ DBUS_INTERFACE_PROPERTIES,
+ "PropertiesChanged",
+ battery_props_changed,
+ NULL, NULL);
+
+ modem_watch = __ofono_modemwatch_add(modemwatch, NULL, NULL);
+ __ofono_modem_foreach(call_modemwatch, NULL);
+
+done:
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_pending_call_unref(call);
+}
+
+static void upower_connect(DBusConnection *conn, void *user_data)
+{
+ DBusPendingCall *call;
+ DBusMessage *msg;
+
+ DBG("upower connect");
+
+ msg = dbus_message_new_method_call(UPOWER_SERVICE,
+ UPOWER_PATH,
+ UPOWER_INTERFACE,
+ "EnumerateDevices");
+ if (msg == NULL) {
+ ofono_error("%s: dbus_message_new_method failed", __func__);
+ return;
+ }
+
+ if (!dbus_connection_send_with_reply(conn, msg, &call, -1)) {
+ ofono_error("%s: Sending EnumerateDevices failed", __func__);
+ goto done;
+ }
+
+ dbus_pending_call_set_notify(call, enum_devices_reply, NULL, NULL);
+done:
+ dbus_message_unref(msg);
+}
+
+static void upower_disconnect(DBusConnection *conn, void *user_data)
+{
+ DBG("upower disconnect");
+
+ if (modem_watch) {
+ __ofono_modemwatch_remove(modem_watch);
+ modem_watch = 0;
+ }
+
+ if (battery_device_path) {
+ g_free(battery_device_path);
+ battery_device_path = NULL;
+ }
+}
+
+static int upower_init(void)
+{
+ DBG("upower init");
+
+ connection = ofono_dbus_get_connection();
+ upower_daemon_watch = g_dbus_add_service_watch(connection,
+ UPOWER_SERVICE,
+ upower_connect,
+ upower_disconnect,
+ NULL, NULL);
+
+ modem_hfp_watches = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, NULL);
+
+ return 0;
+}
+
+static void upower_exit(void)
+{
+ if (upower_daemon_watch)
+ g_dbus_remove_watch(connection, upower_daemon_watch);
+
+ if (modem_watch)
+ __ofono_modemwatch_remove(modem_watch);
+
+ if (battery_device_path)
+ g_free(battery_device_path);
+
+ g_hash_table_destroy(modem_hfp_watches);
+}
+
+OFONO_PLUGIN_DEFINE(upower, "upower battery monitor", VERSION,
+ OFONO_PLUGIN_PRIORITY_DEFAULT, upower_init, upower_exit)
--
2.1.4
6 years, 7 months
[PATCH] build: untangle ATMODEM and BLUETOOTH conditionals
by Tony Espy
---
Makefile.am | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index b22c04b..270590b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -477,6 +477,14 @@ builtin_modules += ublox
builtin_sources += plugins/ublox.c
if BLUETOOTH
+if !BLUEZ4
+builtin_modules += hfp_bluez5
+builtin_sources += plugins/hfp_hf_bluez5.c plugins/bluez5.h
+endif
+endif
+endif
+
+if BLUETOOTH
if BLUEZ4
builtin_modules += bluez4
builtin_sources += plugins/bluez4.c plugins/bluez4.h
@@ -503,9 +511,6 @@ else
builtin_modules += bluez5
builtin_sources += plugins/bluez5.c plugins/bluez5.h
-builtin_modules += hfp_bluez5
-builtin_sources += plugins/hfp_hf_bluez5.c plugins/bluez5.h
-
builtin_modules += hfp_ag_bluez5
builtin_sources += plugins/hfp_ag_bluez5.c plugins/bluez5.h
@@ -513,7 +518,6 @@ builtin_modules += dun_gw_bluez5
builtin_sources += plugins/dun_gw_bluez5.c plugins/bluez5.h
endif
endif
-endif
if PROVISION
builtin_sources += plugins/mbpi.h plugins/mbpi.c
--
2.1.4
6 years, 7 months
[PATCH 1/2 v3] plugins: add upower battery monitor for bluetooth
by Tony Espy
---
plugins/upower.c | 388 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 388 insertions(+)
create mode 100644 plugins/upower.c
diff --git a/plugins/upower.c b/plugins/upower.c
new file mode 100644
index 0000000..5500f00
--- /dev/null
+++ b/plugins/upower.c
@@ -0,0 +1,388 @@
+/*
+ *
+ * oFono - Open Source Telephony
+ *
+ * Copyright (C) 2015 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <gdbus.h>
+#include <ofono.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/plugin.h>
+#include <ofono/modem.h>
+#include <ofono/log.h>
+#include <ofono/emulator.h>
+
+#define DBUS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
+#define UPOWER_SERVICE "org.freedesktop.UPower"
+#define UPOWER_PATH "/org/freedesktop/UPower"
+#define UPOWER_INTERFACE UPOWER_SERVICE
+#define UPOWER_DEVICE_INTERFACE UPOWER_SERVICE ".Device"
+
+static guint modem_watch;
+static guint upower_daemon_watch;
+static DBusConnection *connection;
+static GHashTable *modem_hfp_watches;
+static int last_battery_level;
+static char *battery_device_path;
+
+static void emulator_battery_cb(struct ofono_atom *atom, void *data)
+{
+ struct ofono_emulator *em = __ofono_atom_get_data(atom);
+ int val = GPOINTER_TO_INT(data);
+
+ DBG("calling set_indicator: %d", val);
+ ofono_emulator_set_indicator(em, OFONO_EMULATOR_IND_BATTERY, val);
+}
+
+static void update_modem_battery_indicator(struct ofono_modem *modem,
+ void *data)
+{
+ __ofono_modem_foreach_registered_atom(modem,
+ OFONO_ATOM_TYPE_EMULATOR_HFP,
+ emulator_battery_cb,
+ data);
+}
+
+static void update_battery_level(double percentage_val)
+{
+ int battery_level;
+
+ if (percentage_val <= 1.00) {
+ battery_level = 0;
+ } else if (percentage_val > 1.00 && percentage_val <= 100.00) {
+ battery_level = ((int) percentage_val - 1) / 20 + 1;
+ } else {
+ ofono_error("%s: Invalid value for battery level: %f",
+ __func__,
+ percentage_val);
+ return;
+ }
+
+ DBG("last_battery_level: %d battery_level: %d (%f)", last_battery_level,
+ battery_level, percentage_val);
+
+ if (last_battery_level == battery_level)
+ return;
+
+ last_battery_level = battery_level;
+
+ __ofono_modem_foreach(update_modem_battery_indicator,
+ GINT_TO_POINTER(battery_level));
+}
+
+static gboolean battery_props_changed(DBusConnection *conn, DBusMessage *msg,
+ void *user_data)
+
+{
+ const char *iface;
+ DBusMessageIter iter, dict;
+ double percentage_val;
+ gboolean percentage_found = FALSE;
+ gboolean retval = FALSE;
+
+ DBG("");
+
+ dbus_message_iter_init(msg, &iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) {
+ ofono_error("%s: iface != TYPE_STRING!", __func__);
+ goto done;
+ }
+
+ dbus_message_iter_get_basic(&iter, &iface);
+
+ if (g_str_equal(iface, UPOWER_DEVICE_INTERFACE) != TRUE) {
+ ofono_error("%s: wrong iface: %s!", __func__, iface);
+ goto done;
+ }
+
+ if (!dbus_message_iter_next(&iter)) {
+ ofono_error("%s: advance iter failed!", __func__);
+ goto done;
+ }
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
+ ofono_error("%s: type != ARRAY!", __func__);
+ goto done;
+ }
+
+ dbus_message_iter_recurse(&iter, &dict);
+
+ while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+ DBusMessageIter entry, val;
+ const char *key;
+
+ dbus_message_iter_recurse(&dict, &entry);
+
+ if (dbus_message_iter_get_arg_type(&entry) !=
+ DBUS_TYPE_STRING) {
+ ofono_error("%s: key type != STRING!", __func__);
+ goto done;
+ }
+
+ dbus_message_iter_get_basic(&entry, &key);
+
+ if (g_str_equal(key, "Percentage") != TRUE) {
+ dbus_message_iter_next(&dict);
+ continue;
+ }
+
+ dbus_message_iter_next(&entry);
+ if (dbus_message_iter_get_arg_type(&entry) !=
+ DBUS_TYPE_VARIANT) {
+ ofono_error("%s: 'Percentage' val != VARIANT",
+ __func__);
+ goto done;
+ }
+
+ dbus_message_iter_recurse(&entry, &val);
+
+ if (dbus_message_iter_get_arg_type(&val) != DBUS_TYPE_DOUBLE) {
+ ofono_error("%s: 'Percentage' val != DOUBLE", __func__);
+ goto done;
+ }
+
+ dbus_message_iter_get_basic(&val, &percentage_val);
+ percentage_found = TRUE;
+ break;
+ }
+
+ /* No errors found during parsing, so don't trigger cb removal */
+ retval = TRUE;
+
+ if (percentage_found == FALSE)
+ goto done;
+
+ update_battery_level(percentage_val);
+
+done:
+ return retval;
+}
+
+static void emulator_hfp_watch(struct ofono_atom *atom,
+ enum ofono_atom_watch_condition cond,
+ void *data)
+{
+ if (cond == OFONO_ATOM_WATCH_CONDITION_REGISTERED) {
+ struct ofono_emulator *em = __ofono_atom_get_data(atom);
+
+ DBG("REGISTERED; calling set_indicator: %d", last_battery_level);
+
+ ofono_emulator_set_indicator(em, OFONO_EMULATOR_IND_BATTERY,
+ last_battery_level);
+ return;
+ }
+
+ DBG("UNREGISTERED");
+}
+
+static void modemwatch(struct ofono_modem *modem, gboolean added, void *user)
+{
+
+ const char *path = ofono_modem_get_path(modem);
+
+ DBG("modem: %s, added: %d", path, added);
+
+ if (added) {
+ guint watch_id;
+
+ watch_id = __ofono_modem_add_atom_watch(modem,
+ OFONO_ATOM_TYPE_EMULATOR_HFP,
+ emulator_hfp_watch, NULL, NULL);
+
+ g_hash_table_insert(modem_hfp_watches, g_strdup(path),
+ GINT_TO_POINTER(watch_id));
+
+ } else {
+ guint *watch_id = g_hash_table_lookup(modem_hfp_watches, path);
+
+ if (watch_id != NULL) {
+ __ofono_modem_remove_atom_watch(modem, *watch_id);
+ g_hash_table_remove(modem_hfp_watches, path);
+ }
+ }
+}
+
+static void call_modemwatch(struct ofono_modem *modem, void *user)
+{
+ modemwatch(modem, TRUE, user);
+}
+
+static gboolean parse_devices_reply(DBusMessage *reply)
+{
+ DBusMessageIter array, iter;
+ const char *path;
+
+ DBG("");
+
+ if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
+ ofono_error("%s: ERROR reply to EnumerateDevices", __func__);
+ return FALSE;
+ }
+
+ if (dbus_message_iter_init(reply, &array) == FALSE) {
+ ofono_error("%s: error initializing array iter", __func__);
+ return FALSE;
+ }
+
+ if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY) {
+ ofono_error("%s: type != ARRAY!", __func__);
+ return FALSE;
+ }
+
+ dbus_message_iter_recurse(&array, &iter);
+
+ while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_OBJECT_PATH) {
+
+ dbus_message_iter_get_basic(&iter, &path);
+
+ if (g_strrstr(path, "/battery_")) {
+ ofono_info("%s: found 1st battery device: %s", __func__,
+ path);
+ battery_device_path = g_strdup(path);
+ break;
+ }
+
+ if (!dbus_message_iter_next(&iter))
+ break;
+ }
+
+ return TRUE;
+}
+
+static void enum_devices_reply(DBusPendingCall *call, void *user_data)
+{
+ DBusMessage *reply;
+
+ DBG("");
+
+ reply = dbus_pending_call_steal_reply(call);
+ if (reply == NULL) {
+ ofono_error("%s: dbus_message_new_method failed", __func__);
+ goto done;
+ }
+
+ if (parse_devices_reply(reply) == FALSE)
+ goto done;
+
+ DBG("parse_devices_reply OK");
+
+ /* TODO: handle removable batteries */
+
+ if (battery_device_path == NULL) {
+ ofono_error("%s: no battery detected", __func__);
+ goto done;
+ }
+
+ /* Always listen to PropertiesChanged for battery */
+ g_dbus_add_signal_watch(connection, UPOWER_SERVICE, battery_device_path,
+ DBUS_INTERFACE_PROPERTIES,
+ "PropertiesChanged",
+ battery_props_changed,
+ NULL, NULL);
+
+ modem_watch = __ofono_modemwatch_add(modemwatch, NULL, NULL);
+ __ofono_modem_foreach(call_modemwatch, NULL);
+
+done:
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_pending_call_unref(call);
+}
+
+static void upower_connect(DBusConnection *conn, void *user_data)
+{
+ DBusPendingCall *call;
+ DBusMessage *msg;
+
+ DBG("upower connect");
+
+ msg = dbus_message_new_method_call(UPOWER_SERVICE,
+ UPOWER_PATH,
+ UPOWER_INTERFACE,
+ "EnumerateDevices");
+ if (msg == NULL) {
+ ofono_error("%s: dbus_message_new_method failed", __func__);
+ return;
+ }
+
+ if (!dbus_connection_send_with_reply(conn, msg, &call, -1)) {
+ ofono_error("%s: Sending EnumerateDevices failed", __func__);
+ goto done;
+ }
+
+ dbus_pending_call_set_notify(call, enum_devices_reply, NULL, NULL);
+done:
+ dbus_message_unref(msg);
+}
+
+static void upower_disconnect(DBusConnection *conn, void *user_data)
+{
+ DBG("upower disconnect");
+
+ if (modem_watch) {
+ __ofono_modemwatch_remove(modem_watch);
+ modem_watch = 0;
+ }
+
+ if (battery_device_path) {
+ g_free(battery_device_path);
+ battery_device_path = NULL;
+ }
+}
+
+static int upower_init(void)
+{
+ DBG("upower init");
+
+ connection = ofono_dbus_get_connection();
+ upower_daemon_watch = g_dbus_add_service_watch(connection,
+ UPOWER_SERVICE,
+ upower_connect,
+ upower_disconnect,
+ NULL, NULL);
+
+ modem_hfp_watches = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, NULL);
+
+ return 0;
+}
+
+static void upower_exit(void)
+{
+ if (upower_daemon_watch)
+ g_dbus_remove_watch(connection, upower_daemon_watch);
+
+ if (modem_watch)
+ __ofono_modemwatch_remove(modem_watch);
+
+ if (battery_device_path)
+ g_free(battery_device_path);
+
+ g_hash_table_destroy(modem_hfp_watches);
+}
+
+OFONO_PLUGIN_DEFINE(upower, "upower battery monitor", VERSION,
+ OFONO_PLUGIN_PRIORITY_DEFAULT, upower_init, upower_exit)
--
2.1.4
6 years, 7 months
[PATCH 1/2 v2] plugins: add upower battery monitor for bluetooth
by Tony Espy
---
plugins/upower.c | 388 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 388 insertions(+)
create mode 100644 plugins/upower.c
diff --git a/plugins/upower.c b/plugins/upower.c
new file mode 100644
index 0000000..5500f00
--- /dev/null
+++ b/plugins/upower.c
@@ -0,0 +1,388 @@
+/*
+ *
+ * oFono - Open Source Telephony
+ *
+ * Copyright (C) 2015 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <gdbus.h>
+#include <ofono.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/plugin.h>
+#include <ofono/modem.h>
+#include <ofono/log.h>
+#include <ofono/emulator.h>
+
+#define DBUS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
+#define UPOWER_SERVICE "org.freedesktop.UPower"
+#define UPOWER_PATH "/org/freedesktop/UPower"
+#define UPOWER_INTERFACE UPOWER_SERVICE
+#define UPOWER_DEVICE_INTERFACE UPOWER_SERVICE ".Device"
+
+static guint modem_watch;
+static guint upower_daemon_watch;
+static DBusConnection *connection;
+static GHashTable *modem_hfp_watches;
+static int last_battery_level;
+static char *battery_device_path;
+
+static void emulator_battery_cb(struct ofono_atom *atom, void *data)
+{
+ struct ofono_emulator *em = __ofono_atom_get_data(atom);
+ int val = GPOINTER_TO_INT(data);
+
+ DBG("calling set_indicator: %d", val);
+ ofono_emulator_set_indicator(em, OFONO_EMULATOR_IND_BATTERY, val);
+}
+
+static void update_modem_battery_indicator(struct ofono_modem *modem,
+ void *data)
+{
+ __ofono_modem_foreach_registered_atom(modem,
+ OFONO_ATOM_TYPE_EMULATOR_HFP,
+ emulator_battery_cb,
+ data);
+}
+
+static void update_battery_level(double percentage_val)
+{
+ int battery_level;
+
+ if (percentage_val <= 1.00) {
+ battery_level = 0;
+ } else if (percentage_val > 1.00 && percentage_val <= 100.00) {
+ battery_level = ((int) percentage_val - 1) / 20 + 1;
+ } else {
+ ofono_error("%s: Invalid value for battery level: %f",
+ __func__,
+ percentage_val);
+ return;
+ }
+
+ DBG("last_battery_level: %d battery_level: %d (%f)", last_battery_level,
+ battery_level, percentage_val);
+
+ if (last_battery_level == battery_level)
+ return;
+
+ last_battery_level = battery_level;
+
+ __ofono_modem_foreach(update_modem_battery_indicator,
+ GINT_TO_POINTER(battery_level));
+}
+
+static gboolean battery_props_changed(DBusConnection *conn, DBusMessage *msg,
+ void *user_data)
+
+{
+ const char *iface;
+ DBusMessageIter iter, dict;
+ double percentage_val;
+ gboolean percentage_found = FALSE;
+ gboolean retval = FALSE;
+
+ DBG("");
+
+ dbus_message_iter_init(msg, &iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) {
+ ofono_error("%s: iface != TYPE_STRING!", __func__);
+ goto done;
+ }
+
+ dbus_message_iter_get_basic(&iter, &iface);
+
+ if (g_str_equal(iface, UPOWER_DEVICE_INTERFACE) != TRUE) {
+ ofono_error("%s: wrong iface: %s!", __func__, iface);
+ goto done;
+ }
+
+ if (!dbus_message_iter_next(&iter)) {
+ ofono_error("%s: advance iter failed!", __func__);
+ goto done;
+ }
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
+ ofono_error("%s: type != ARRAY!", __func__);
+ goto done;
+ }
+
+ dbus_message_iter_recurse(&iter, &dict);
+
+ while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+ DBusMessageIter entry, val;
+ const char *key;
+
+ dbus_message_iter_recurse(&dict, &entry);
+
+ if (dbus_message_iter_get_arg_type(&entry) !=
+ DBUS_TYPE_STRING) {
+ ofono_error("%s: key type != STRING!", __func__);
+ goto done;
+ }
+
+ dbus_message_iter_get_basic(&entry, &key);
+
+ if (g_str_equal(key, "Percentage") != TRUE) {
+ dbus_message_iter_next(&dict);
+ continue;
+ }
+
+ dbus_message_iter_next(&entry);
+ if (dbus_message_iter_get_arg_type(&entry) !=
+ DBUS_TYPE_VARIANT) {
+ ofono_error("%s: 'Percentage' val != VARIANT",
+ __func__);
+ goto done;
+ }
+
+ dbus_message_iter_recurse(&entry, &val);
+
+ if (dbus_message_iter_get_arg_type(&val) != DBUS_TYPE_DOUBLE) {
+ ofono_error("%s: 'Percentage' val != DOUBLE", __func__);
+ goto done;
+ }
+
+ dbus_message_iter_get_basic(&val, &percentage_val);
+ percentage_found = TRUE;
+ break;
+ }
+
+ /* No errors found during parsing, so don't trigger cb removal */
+ retval = TRUE;
+
+ if (percentage_found == FALSE)
+ goto done;
+
+ update_battery_level(percentage_val);
+
+done:
+ return retval;
+}
+
+static void emulator_hfp_watch(struct ofono_atom *atom,
+ enum ofono_atom_watch_condition cond,
+ void *data)
+{
+ if (cond == OFONO_ATOM_WATCH_CONDITION_REGISTERED) {
+ struct ofono_emulator *em = __ofono_atom_get_data(atom);
+
+ DBG("REGISTERED; calling set_indicator: %d", last_battery_level);
+
+ ofono_emulator_set_indicator(em, OFONO_EMULATOR_IND_BATTERY,
+ last_battery_level);
+ return;
+ }
+
+ DBG("UNREGISTERED");
+}
+
+static void modemwatch(struct ofono_modem *modem, gboolean added, void *user)
+{
+
+ const char *path = ofono_modem_get_path(modem);
+
+ DBG("modem: %s, added: %d", path, added);
+
+ if (added) {
+ guint watch_id;
+
+ watch_id = __ofono_modem_add_atom_watch(modem,
+ OFONO_ATOM_TYPE_EMULATOR_HFP,
+ emulator_hfp_watch, NULL, NULL);
+
+ g_hash_table_insert(modem_hfp_watches, g_strdup(path),
+ GINT_TO_POINTER(watch_id));
+
+ } else {
+ guint *watch_id = g_hash_table_lookup(modem_hfp_watches, path);
+
+ if (watch_id != NULL) {
+ __ofono_modem_remove_atom_watch(modem, *watch_id);
+ g_hash_table_remove(modem_hfp_watches, path);
+ }
+ }
+}
+
+static void call_modemwatch(struct ofono_modem *modem, void *user)
+{
+ modemwatch(modem, TRUE, user);
+}
+
+static gboolean parse_devices_reply(DBusMessage *reply)
+{
+ DBusMessageIter array, iter;
+ const char *path;
+
+ DBG("");
+
+ if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
+ ofono_error("%s: ERROR reply to EnumerateDevices", __func__);
+ return FALSE;
+ }
+
+ if (dbus_message_iter_init(reply, &array) == FALSE) {
+ ofono_error("%s: error initializing array iter", __func__);
+ return FALSE;
+ }
+
+ if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY) {
+ ofono_error("%s: type != ARRAY!", __func__);
+ return FALSE;
+ }
+
+ dbus_message_iter_recurse(&array, &iter);
+
+ while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_OBJECT_PATH) {
+
+ dbus_message_iter_get_basic(&iter, &path);
+
+ if (g_strrstr(path, "/battery_")) {
+ ofono_info("%s: found 1st battery device: %s", __func__,
+ path);
+ battery_device_path = g_strdup(path);
+ break;
+ }
+
+ if (!dbus_message_iter_next(&iter))
+ break;
+ }
+
+ return TRUE;
+}
+
+static void enum_devices_reply(DBusPendingCall *call, void *user_data)
+{
+ DBusMessage *reply;
+
+ DBG("");
+
+ reply = dbus_pending_call_steal_reply(call);
+ if (reply == NULL) {
+ ofono_error("%s: dbus_message_new_method failed", __func__);
+ goto done;
+ }
+
+ if (parse_devices_reply(reply) == FALSE)
+ goto done;
+
+ DBG("parse_devices_reply OK");
+
+ /* TODO: handle removable batteries */
+
+ if (battery_device_path == NULL) {
+ ofono_error("%s: no battery detected", __func__);
+ goto done;
+ }
+
+ /* Always listen to PropertiesChanged for battery */
+ g_dbus_add_signal_watch(connection, UPOWER_SERVICE, battery_device_path,
+ DBUS_INTERFACE_PROPERTIES,
+ "PropertiesChanged",
+ battery_props_changed,
+ NULL, NULL);
+
+ modem_watch = __ofono_modemwatch_add(modemwatch, NULL, NULL);
+ __ofono_modem_foreach(call_modemwatch, NULL);
+
+done:
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_pending_call_unref(call);
+}
+
+static void upower_connect(DBusConnection *conn, void *user_data)
+{
+ DBusPendingCall *call;
+ DBusMessage *msg;
+
+ DBG("upower connect");
+
+ msg = dbus_message_new_method_call(UPOWER_SERVICE,
+ UPOWER_PATH,
+ UPOWER_INTERFACE,
+ "EnumerateDevices");
+ if (msg == NULL) {
+ ofono_error("%s: dbus_message_new_method failed", __func__);
+ return;
+ }
+
+ if (!dbus_connection_send_with_reply(conn, msg, &call, -1)) {
+ ofono_error("%s: Sending EnumerateDevices failed", __func__);
+ goto done;
+ }
+
+ dbus_pending_call_set_notify(call, enum_devices_reply, NULL, NULL);
+done:
+ dbus_message_unref(msg);
+}
+
+static void upower_disconnect(DBusConnection *conn, void *user_data)
+{
+ DBG("upower disconnect");
+
+ if (modem_watch) {
+ __ofono_modemwatch_remove(modem_watch);
+ modem_watch = 0;
+ }
+
+ if (battery_device_path) {
+ g_free(battery_device_path);
+ battery_device_path = NULL;
+ }
+}
+
+static int upower_init(void)
+{
+ DBG("upower init");
+
+ connection = ofono_dbus_get_connection();
+ upower_daemon_watch = g_dbus_add_service_watch(connection,
+ UPOWER_SERVICE,
+ upower_connect,
+ upower_disconnect,
+ NULL, NULL);
+
+ modem_hfp_watches = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, NULL);
+
+ return 0;
+}
+
+static void upower_exit(void)
+{
+ if (upower_daemon_watch)
+ g_dbus_remove_watch(connection, upower_daemon_watch);
+
+ if (modem_watch)
+ __ofono_modemwatch_remove(modem_watch);
+
+ if (battery_device_path)
+ g_free(battery_device_path);
+
+ g_hash_table_destroy(modem_hfp_watches);
+}
+
+OFONO_PLUGIN_DEFINE(upower, "upower battery monitor", VERSION,
+ OFONO_PLUGIN_PRIORITY_DEFAULT, upower_init, upower_exit)
--
2.1.4
6 years, 7 months
[PATCH 1/3] unit: add new test-rilmodem-cb
by Tony Espy
---
unit/test-rilmodem-cb.c | 598 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 598 insertions(+)
create mode 100644 unit/test-rilmodem-cb.c
diff --git a/unit/test-rilmodem-cb.c b/unit/test-rilmodem-cb.c
new file mode 100644
index 0000000..d5b1d07
--- /dev/null
+++ b/unit/test-rilmodem-cb.c
@@ -0,0 +1,598 @@
+/*
+ *
+ * oFono - Open Source Telephony
+ *
+ * Copyright (C) 2015 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <assert.h>
+#include <errno.h>
+#include <glib.h>
+#include <stdio.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <ofono/modem.h>
+#include <ofono/types.h>
+#include <ofono/call-barring.h>
+#include <gril.h>
+
+#include "common.h"
+#include "ril_constants.h"
+#include "rilmodem-test-server.h"
+
+static GMainLoop *mainloop;
+
+static const struct ofono_call_barring_driver *cbdriver;
+
+struct rilmodem_cb_data {
+ GRil *ril;
+ struct ofono_modem *modem;
+ gconstpointer test_data;
+ struct ofono_call_barring *cb;
+ struct server_data *serverd;
+};
+
+typedef gboolean (*StartFunc)(gpointer data);
+
+struct cb_data {
+ StartFunc start_func;
+
+ const char *lock;
+ int enable;
+ const char *passwd;
+ const char *new_passwd;
+ int cls;
+
+ struct rilmodem_test_data rtd;
+ enum ofono_error_type error_type;
+
+ int status;
+};
+
+static void query_callback(const struct ofono_error *error, int status,
+ gpointer data)
+{
+ struct rilmodem_cb_data *rsd = data;
+ const struct cb_data *cbd = rsd->test_data;
+
+ g_assert(error->type == cbd->error_type);
+
+ if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
+ g_assert(status == cbd->status);
+
+ g_main_loop_quit(mainloop);
+}
+
+static gboolean trigger_query(gpointer data)
+{
+ struct rilmodem_cb_data *rsd = data;
+ const struct cb_data *cbd = rsd->test_data;
+
+ g_assert(cbdriver->query != NULL);
+ cbdriver->query(rsd->cb, cbd->lock, cbd->cls, query_callback, rsd);
+
+ return FALSE;
+}
+
+static void set_callback(const struct ofono_error *error, gpointer data)
+{
+ struct rilmodem_cb_data *rsd = data;
+ const struct cb_data *cbd = rsd->test_data;
+
+ g_assert(error->type == cbd->error_type);
+
+ g_main_loop_quit(mainloop);
+}
+
+static gboolean trigger_set(gpointer data)
+{
+ struct rilmodem_cb_data *rsd = data;
+ const struct cb_data *cbd = rsd->test_data;
+
+ g_assert(cbdriver->set != NULL);
+ cbdriver->set(rsd->cb, cbd->lock, cbd->enable, cbd->passwd, cbd->cls,
+ set_callback, rsd);
+
+ return FALSE;
+}
+
+static void set_passwd_callback(const struct ofono_error *error, gpointer data)
+{
+ struct rilmodem_cb_data *rsd = data;
+ const struct cb_data *cbd = rsd->test_data;
+
+ g_assert(error->type == cbd->error_type);
+
+ g_main_loop_quit(mainloop);
+}
+
+static gboolean trigger_set_passwd(gpointer data)
+{
+ struct rilmodem_cb_data *rsd = data;
+ const struct cb_data *cbd = rsd->test_data;
+
+ g_assert(cbdriver->set_passwd != NULL);
+ cbdriver->set_passwd(rsd->cb, cbd->lock, cbd->passwd, cbd->new_passwd,
+ set_passwd_callback, rsd);
+
+ return FALSE;
+}
+
+/* RIL_REQUEST_GET_FACILITY_LOCK witht the following parameters:
+ *
+ * facility="OI" (outgoing international calls)
+ * service class=1 ( VOICE )
+ */
+static const guchar req_get_facility_lock_parcel_1[] = {
+ 0x00, 0x00, 0x00, 0x2c, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x49, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff
+};
+
+/*
+ * The following structure contains test data for a valid
+ * RIL_REQUEST_GET_FACILITY_LOCK reply with parameter {1}
+ * which indicates that call-barring is activated for the
+ * previously specified facility for the VOICE class.
+ */
+static const guchar reply_get_facility_lock_data_valid_1[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+};
+
+static const struct cb_data testdata_query_valid_1 = {
+ .start_func = trigger_query,
+ .lock = "OI",
+ .cls = BEARER_CLASS_VOICE,
+ .rtd = {
+ .req_data = req_get_facility_lock_parcel_1,
+ .req_size = sizeof(req_get_facility_lock_parcel_1),
+ .rsp_data = reply_get_facility_lock_data_valid_1,
+ .rsp_size = sizeof(reply_get_facility_lock_data_valid_1),
+ },
+ .status = BEARER_CLASS_VOICE,
+};
+
+/* GENERIC_FAILURE returned in RIL reply */
+static const struct cb_data testdata_query_invalid_1 = {
+ .start_func = trigger_query,
+ .lock = "OI",
+ .cls = BEARER_CLASS_VOICE,
+ .rtd = {
+ .req_data = req_get_facility_lock_parcel_1,
+ .req_size = sizeof(req_get_facility_lock_parcel_1),
+ .rsp_data = reply_get_facility_lock_data_valid_1,
+ .rsp_size = sizeof(reply_get_facility_lock_data_valid_1),
+ .rsp_error = RIL_E_GENERIC_FAILURE,
+ },
+ .error_type = OFONO_ERROR_TYPE_FAILURE,
+};
+
+/*
+ * The following structure contains test data for a valid
+ * RIL_REQUEST_GET_FACILITY_LOCK reply with invalid number
+ * of parameters {0} specified.
+ */
+static const guchar reply_get_facility_lock_data_invalid_2[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+};
+
+static const struct cb_data testdata_query_invalid_2 = {
+ .start_func = trigger_query,
+ .lock = "OI",
+ .cls = BEARER_CLASS_VOICE,
+ .rtd = {
+ .req_data = req_get_facility_lock_parcel_1,
+ .req_size = sizeof(req_get_facility_lock_parcel_1),
+ .rsp_data = reply_get_facility_lock_data_invalid_2,
+ .rsp_size = sizeof(reply_get_facility_lock_data_invalid_2),
+ },
+ .error_type = OFONO_ERROR_TYPE_FAILURE,
+};
+
+/*
+ * The following structure contains test data for an invalid
+ * RIL_REQUEST_GET_FACILITY_LOCK reply with an invalid class
+ * mask (-255).
+ */
+static const guchar reply_get_facility_lock_data_invalid_3[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff
+};
+
+static const struct cb_data testdata_query_invalid_3 = {
+ .start_func = trigger_query,
+ .lock = "OI",
+ .cls = BEARER_CLASS_VOICE,
+ .rtd = {
+ .req_data = req_get_facility_lock_parcel_1,
+ .req_size = sizeof(req_get_facility_lock_parcel_1),
+ .rsp_data = reply_get_facility_lock_data_invalid_3,
+ .rsp_size = sizeof(reply_get_facility_lock_data_invalid_3),
+ },
+ .error_type = OFONO_ERROR_TYPE_FAILURE,
+};
+
+/*
+ * The following structure contains test data for a
+ * RIL_REQUEST_GET_FACILITY_LOCK reply with an incomplete
+ * integer parameter, which will trigger a malformed parcel
+ * error.
+ */
+static const guchar reply_get_facility_lock_data_invalid_4[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00
+};
+
+static const struct cb_data testdata_query_invalid_4 = {
+ .start_func = trigger_query,
+ .lock = "OI",
+ .cls = BEARER_CLASS_VOICE,
+ .rtd = {
+ .req_data = req_get_facility_lock_parcel_1,
+ .req_size = sizeof(req_get_facility_lock_parcel_1),
+ .rsp_data = reply_get_facility_lock_data_invalid_4,
+ .rsp_size = sizeof(reply_get_facility_lock_data_invalid_4),
+ },
+ .error_type = OFONO_ERROR_TYPE_FAILURE,
+};
+
+/* RIL_REQUEST_SET_FACILITY_LOCK witht the following parameters:
+ *
+ * facility="OI" (outgoing international calls)
+ * unlock (0)
+ * passwd="0000"
+ * service class=1 ( VOICE )
+ */
+static const guchar req_set_facility_lock_parcel_1[] = {
+ 0x00, 0x00, 0x00, 0x3c, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x49, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff
+};
+
+/*
+ * This test doesn't specify any data for RIL_REQUEST_SET_FACILITY_LOCK reply
+ * to simulate a reply generated by mako.
+ */
+static const struct cb_data testdata_set_valid_1 = {
+ .start_func = trigger_set,
+ .lock = "OI",
+ .passwd = "0000",
+ .cls = BEARER_CLASS_VOICE,
+ .rtd = {
+ .req_data = req_set_facility_lock_parcel_1,
+ .req_size = sizeof(req_set_facility_lock_parcel_1),
+ },
+};
+
+/* RIL_REQUEST_SET_FACILITY_LOCK witht the following parameters:
+ *
+ * facility="OI" (outgoing international calls)
+ * unlock (1)
+ * passwd="0000"
+ * service class=0 ( NONE )
+ */
+static const guchar req_set_facility_lock_parcel_2[] = {
+ 0x00, 0x00, 0x00, 0x3c, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x49, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff
+};
+
+/*
+ * The following structure contains test data for a valid
+ * RIL_REQUEST_SET_FACILITY_LOCK reply with parameter {1}
+ */
+static const guchar reply_set_facility_lock_data_valid_2[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+};
+
+static const struct cb_data testdata_set_valid_2 = {
+ .start_func = trigger_set,
+ .lock = "OI",
+ .enable = 1,
+ .passwd = "0000",
+ .cls = BEARER_CLASS_DEFAULT, /* updated to NONE in outgoing parcel */
+ .rtd = {
+ .req_data = req_set_facility_lock_parcel_2,
+ .req_size = sizeof(req_set_facility_lock_parcel_2),
+ .rsp_data = reply_set_facility_lock_data_valid_2,
+ .rsp_size = sizeof(reply_set_facility_lock_data_valid_2),
+ },
+};
+
+/* GENERIC_FAILURE returned in RIL reply */
+static const struct cb_data testdata_set_invalid_1 = {
+ .start_func = trigger_set,
+ .lock = "OI",
+ .enable = 1,
+ .passwd = "0000",
+ .cls = BEARER_CLASS_DEFAULT,
+ .rtd = {
+ .req_data = req_set_facility_lock_parcel_2,
+ .req_size = sizeof(req_set_facility_lock_parcel_2),
+ .rsp_error = RIL_E_GENERIC_FAILURE,
+ },
+ .error_type = OFONO_ERROR_TYPE_FAILURE,
+};
+
+
+/*
+ * The following structure contains test data for a
+ * RIL_REQUEST_SET_FACILITY_LOCK reply with an invalid
+ * number of parameters {2}
+ */
+static const guchar reply_set_facility_lock_data_invalid_2[] = {
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+};
+
+static const struct cb_data testdata_set_invalid_2 = {
+ .start_func = trigger_set,
+ .lock = "OI",
+ .enable = 1,
+ .passwd = "0000",
+ .cls = BEARER_CLASS_DEFAULT,
+ .rtd = {
+ .req_data = req_set_facility_lock_parcel_2,
+ .req_size = sizeof(req_set_facility_lock_parcel_2),
+ .rsp_data = reply_set_facility_lock_data_invalid_2,
+ .rsp_size = sizeof(reply_set_facility_lock_data_invalid_2),
+ },
+ .error_type = OFONO_ERROR_TYPE_FAILURE,
+};
+
+/*
+ * The following structure contains test data for a
+ * RIL_REQUEST_SET_FACILITY_LOCK reply with an incomplete
+ * integer parameter, which will trigger a malformed parcel
+ * error.
+ */
+static const guchar reply_set_facility_lock_data_invalid_3[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00
+};
+
+static const struct cb_data testdata_set_invalid_3 = {
+ .start_func = trigger_set,
+ .lock = "OI",
+ .enable = 1,
+ .passwd = "0000",
+ .cls = BEARER_CLASS_DEFAULT,
+ .rtd = {
+ .req_data = req_set_facility_lock_parcel_2,
+ .req_size = sizeof(req_set_facility_lock_parcel_2),
+ .rsp_data = reply_set_facility_lock_data_invalid_3,
+ .rsp_size = sizeof(reply_set_facility_lock_data_invalid_3),
+ },
+ .error_type = OFONO_ERROR_TYPE_FAILURE,
+};
+
+/* RIL_REQUEST_CHANGE_BARRING_PASSWORD with the following parameters:
+ *
+ * facility="OI" (outgoing international calls)
+ * old passwd="1111"
+ * new_passwd="0000"
+ */
+static const guchar req_change_barring_passwd_parcel_1[] = {
+ 0x00, 0x00, 0x00, 0x38, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x49, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x31, 0x00, 0x31, 0x00,
+ 0x31, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/*
+ * This test doesn't specify any data for RIL_REQUEST_SET_FACILITY_LOCK reply
+ * to simulate a reply generated by mako.
+ */
+static const struct cb_data testdata_set_passwd_valid_1 = {
+ .start_func = trigger_set_passwd,
+ .lock = "OI",
+ .passwd = "1111",
+ .new_passwd = "0000",
+ .rtd = {
+ .req_data = req_change_barring_passwd_parcel_1,
+ .req_size = sizeof(req_change_barring_passwd_parcel_1),
+ },
+};
+
+/* GENERIC_FAILURE returned in RIL reply */
+static const struct cb_data testdata_set_passwd_invalid_1 = {
+ .start_func = trigger_set_passwd,
+ .lock = "OI",
+ .passwd = "1111",
+ .new_passwd = "0000",
+ .rtd = {
+ .req_data = req_change_barring_passwd_parcel_1,
+ .req_size = sizeof(req_change_barring_passwd_parcel_1),
+ .rsp_error = RIL_E_GENERIC_FAILURE,
+ },
+ .error_type = OFONO_ERROR_TYPE_FAILURE,
+};
+
+/* Declarations && Re-implementations of core functions. */
+void ril_call_barring_exit(void);
+void ril_call_barring_init(void);
+
+struct ofono_call_barring {
+ void *driver_data;
+ const struct cb_data *cbd;
+};
+
+struct ofono_call_barring *ofono_call_barring_create(struct ofono_modem *modem,
+ unsigned int vendor,
+ const char *driver,
+ void *data)
+{
+ struct rilmodem_cb_data *rsd = data;
+ struct ofono_call_barring *cb = g_new0(struct ofono_call_barring, 1);
+ int retval;
+
+ retval = cbdriver->probe(cb, OFONO_RIL_VENDOR_AOSP, rsd->ril);
+ g_assert(retval == 0);
+
+ return cb;
+}
+
+int ofono_call_barring_driver_register(const struct ofono_call_barring_driver *d)
+{
+ if (cbdriver == NULL)
+ cbdriver = d;
+
+ return 0;
+}
+
+void ofono_call_barring_set_data(struct ofono_call_barring *cb, void *data)
+{
+ cb->driver_data = data;
+}
+
+void *ofono_call_barring_get_data(struct ofono_call_barring *cb)
+{
+ return cb->driver_data;
+}
+
+void ofono_call_barring_register(struct ofono_call_barring *cb)
+{
+}
+
+void ofono_call_barring_driver_unregister(const struct ofono_call_barring_driver *d)
+{
+}
+
+static void server_connect_cb(gpointer data)
+{
+ struct rilmodem_cb_data *rsd = data;
+ const struct cb_data *cbd = rsd->test_data;
+
+ /* This causes local impl of _create() to call driver's probe func. */
+ rsd->cb = ofono_call_barring_create(NULL, OFONO_RIL_VENDOR_AOSP,
+ "rilmodem", rsd);
+ rsd->cb->cbd = cbd;
+
+ /* add_idle doesn't work, read blocks main loop!!! */
+
+ if (cbd->rtd.unsol_test)
+ g_idle_add(cbd->start_func, (void *) rsd);
+ else
+ g_assert(cbd->start_func(rsd) == FALSE);
+}
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+/*
+ * This unit test:
+ * - does some test data setup
+ * - configures a dummy server socket
+ * - creates a new gril client instance
+ * - triggers a connect to the dummy
+ * server socket
+ * - starts a mainloop
+ */
+static void test_call_barring_func(gconstpointer data)
+{
+ const struct cb_data *sd = data;
+ struct rilmodem_cb_data *rsd;
+
+ ril_call_barring_init();
+
+ rsd = g_new0(struct rilmodem_cb_data, 1);
+
+ rsd->test_data = sd;
+
+ rsd->serverd = rilmodem_test_server_create(&server_connect_cb,
+ &sd->rtd, rsd);
+
+ rsd->ril = g_ril_new(RIL_SERVER_SOCK_PATH, OFONO_RIL_VENDOR_AOSP);
+ g_assert(rsd->ril != NULL);
+
+ mainloop = g_main_loop_new(NULL, FALSE);
+
+ g_main_loop_run(mainloop);
+ g_main_loop_unref(mainloop);
+
+ cbdriver->remove(rsd->cb);
+ g_ril_unref(rsd->ril);
+ g_free(rsd);
+
+ rilmodem_test_server_close(rsd->serverd);
+
+ ril_call_barring_exit();
+}
+
+#endif
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+/*
+ * As all our architectures are little-endian except for
+ * PowerPC, and the Binder wire-format differs slightly
+ * depending on endian-ness, the following guards against test
+ * failures when run on PowerPC.
+ */
+#if BYTE_ORDER == LITTLE_ENDIAN
+ g_test_add_data_func("/testrilmodemcallbarring/query/valid/1",
+ &testdata_query_valid_1,
+ test_call_barring_func);
+ g_test_add_data_func("/testrilmodemcallbarring/query/invalid/1",
+ &testdata_query_invalid_1,
+ test_call_barring_func);
+ g_test_add_data_func("/testrilmodemcallbarring/query/invalid/2",
+ &testdata_query_invalid_2,
+ test_call_barring_func);
+ g_test_add_data_func("/testrilmodemcallbarring/query/invalid/3",
+ &testdata_query_invalid_3,
+ test_call_barring_func);
+ g_test_add_data_func("/testrilmodemcallbarring/query/invalid/4",
+ &testdata_query_invalid_3,
+ test_call_barring_func);
+ g_test_add_data_func("/testrilmodemcallbarring/set/valid/4",
+ &testdata_set_valid_1,
+ test_call_barring_func);
+ g_test_add_data_func("/testrilmodemcallbarring/set/valid/2",
+ &testdata_set_valid_2,
+ test_call_barring_func);
+ g_test_add_data_func("/testrilmodemcallbarring/set/invalid/1",
+ &testdata_set_invalid_1,
+ test_call_barring_func);
+ g_test_add_data_func("/testrilmodemcallbarring/set/invalid/2",
+ &testdata_set_invalid_2,
+ test_call_barring_func);
+ g_test_add_data_func("/testrilmodemcallbarring/set/invalid/3",
+ &testdata_set_invalid_3,
+ test_call_barring_func);
+ g_test_add_data_func("/testrilmodemcallbarring/set_passwd/valid/1",
+ &testdata_set_passwd_valid_1,
+ test_call_barring_func);
+ g_test_add_data_func("/testrilmodemcallbarring/set_passwd/invalid/1",
+ &testdata_set_passwd_invalid_1,
+ test_call_barring_func);
+#endif
+ return g_test_run();
+}
--
2.1.4
6 years, 7 months