diff --git a/mms-connman-nemo/Makefile b/mms-connman-nemo/Makefile new file mode 100644 index 0000000..d53361f --- /dev/null +++ b/mms-connman-nemo/Makefile @@ -0,0 +1,112 @@ +# -*- Mode: makefile-gmake -*- + +.PHONY: clean all debug release + +# Required packages +PKGS = libgofono libgofonoext libglibutil glib-2.0 gio-2.0 gio-unix-2.0 + +# +# Default target +# + +all: debug release + +# +# Sources +# + +SRC = \ + mms_connection_nemo.c \ + mms_connman_nemo.c + +# +# Directories +# + +SRC_DIR = src +INCLUDE_DIR = include +BUILD_DIR = build +SPEC_DIR = spec +MMS_LIB_INCLUDE = ../mms-lib/include +DEBUG_BUILD_DIR = $(BUILD_DIR)/debug +RELEASE_BUILD_DIR = $(BUILD_DIR)/release + +# +# Tools and flags +# + +CC = $(CROSS_COMPILE)gcc +LD = $(CC) +ARFLAGS = rc +DEBUG_FLAGS = -g +RELEASE_FLAGS = -O2 +DEBUG_DEFS = -DDEBUG +RELEASE_DEFS = +WARNINGS = -Wall +INCLUDES = -I$(SRC_DIR) -I$(INCLUDE_DIR) -I$(MMS_LIB_INCLUDE) -I. +CFLAGS += $(WARNINGS) $(INCLUDES) $(shell pkg-config --cflags $(PKGS)) \ + -fPIC -MMD + +ifndef KEEP_SYMBOLS +KEEP_SYMBOLS = 0 +endif + +ifneq ($(KEEP_SYMBOLS),0) +RELEASE_FLAGS += -g +endif + +DEBUG_CFLAGS = $(DEBUG_FLAGS) $(DEBUG_DEFS) $(CFLAGS) +RELEASE_CFLAGS = $(RELEASE_FLAGS) $(RELEASE_DEFS) $(CFLAGS) + +# +# Files +# + +DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o) +RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o) + +# +# Dependencies +# + +DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d) +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(strip $(DEPS)),) +-include $(DEPS) +endif +endif + +$(DEBUG_OBJS): | $(DEBUG_BUILD_DIR) +$(RELEASE_OBJS): | $(RELEASE_BUILD_DIR) + +# +# Rules +# +LIB = libmms-connman-nemo.a +DEBUG_LIB = $(DEBUG_BUILD_DIR)/$(LIB) +RELEASE_LIB = $(RELEASE_BUILD_DIR)/$(LIB) + +debug: $(DEBUG_LIB) + +release: $(RELEASE_LIB) + +clean: + rm -fr $(BUILD_DIR) *~ $(SRC_DIR)/*~ $(INCLUDE_DIR)/*~ + +$(DEBUG_BUILD_DIR): + mkdir -p $@ + +$(RELEASE_BUILD_DIR): + mkdir -p $@ + +$(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c + $(CC) -c $(WARN) $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ + +$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c + $(CC) -c $(WARN) $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ + +$(DEBUG_LIB): $(DEBUG_OBJS) + $(AR) $(ARFLAGS) $@ $^ + +$(RELEASE_LIB): $(RELEASE_OBJS) + $(AR) $(ARFLAGS) $@ $^ diff --git a/mms-connman-nemo/include/mms_connman_nemo.h b/mms-connman-nemo/include/mms_connman_nemo.h new file mode 100644 index 0000000..b6c4cfa --- /dev/null +++ b/mms-connman-nemo/include/mms_connman_nemo.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2013-2016 Jolla Ltd. + * Contact: Slava Monich + * + * 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. + * + */ + +#ifndef JOLLA_MMS_CONNMAN_NEMO_H +#define JOLLA_MMS_CONNMAN_NEMO_H + +#include "mms_connman.h" + +MMSConnMan* +mms_connman_nemo_new(void); + +#endif /* JOLLA_MMS_CONNMAN_NEMO_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-connman-nemo/include/mms_connman_nemo_log.h b/mms-connman-nemo/include/mms_connman_nemo_log.h new file mode 100644 index 0000000..e7f656c --- /dev/null +++ b/mms-connman-nemo/include/mms_connman_nemo_log.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Jolla Ltd. + * Contact: Slava Monich + * + * 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. + * + */ + +#ifndef JOLLA_MMS_CONNMAN_NEMO_LOG_H +#define JOLLA_MMS_CONNMAN_NEMO_LOG_H + +#include "mms_log.h" + +#define MMS_CONNMAN_LOG_MODULES(log) \ + log(gofonoext_log) \ + log(gofono_log) + +MMS_CONNMAN_LOG_MODULES(GLOG_MODULE_DECL) + +#endif /* JOLLA_MMS_CONNMAN_NEMO_LOG_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-connman-nemo/mms-connman-nemo.pro b/mms-connman-nemo/mms-connman-nemo.pro new file mode 100644 index 0000000..b38dfbb --- /dev/null +++ b/mms-connman-nemo/mms-connman-nemo.pro @@ -0,0 +1,27 @@ +TEMPLATE = lib +CONFIG += staticlib +CONFIG -= qt +CONFIG += link_pkgconfig +PKGCONFIG += libgofono libgofonoext libglibutil glib-2.0 gio-2.0 gio-unix-2.0 +DBUS_SPEC_DIR = $$_PRO_FILE_PWD_/spec +INCLUDEPATH += include +INCLUDEPATH += ../mms-lib/include +QMAKE_CFLAGS += -Wno-unused-parameter + +CONFIG(debug, debug|release) { + DEFINES += DEBUG + DESTDIR = $$_PRO_FILE_PWD_/build/debug +} else { + DESTDIR = $$_PRO_FILE_PWD_/build/release +} + +SOURCES += \ + src/mms_connection_nemo.c \ + src/mms_connman_nemo.c + +HEADERS += \ + src/mms_connection_nemo.h + +HEADERS += \ + include/mms_connman_nemo.h \ + include/mms_connman_nemo_log.h diff --git a/mms-connman-nemo/src/mms_connection_nemo.c b/mms-connman-nemo/src/mms_connection_nemo.c new file mode 100644 index 0000000..70e25a4 --- /dev/null +++ b/mms-connman-nemo/src/mms_connection_nemo.c @@ -0,0 +1,632 @@ +/* + * Copyright (C) 2016 Jolla Ltd. + * Contact: Slava Monich + * + * 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. + * + */ + +#include "mms_connection_nemo.h" +#include "mms_connman.h" + +#include +#include + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_connection_log +#include "mms_connman_nemo_log.h" +MMS_LOG_MODULE_DEFINE("mms-connection-nemo"); + +enum mm_handler_id { + MM_HANDLER_VALID, + MM_HANDLER_MMS_IMSI, + MM_HANDLER_COUNT +}; + +enum connmgr_handler_id { + CONNMGR_HANDLER_VALID, + CONNMGR_HANDLER_ATTACHED, + CONNMGR_HANDLER_COUNT +}; + +enum context_handler_id { + CONTEXT_HANDLER_VALID, + CONTEXT_HANDLER_ACTIVE, + CONTEXT_HANDLER_INTERFACE, + CONTEXT_HANDLER_MMS_PROXY, + CONTEXT_HANDLER_MMS_CENTER, + CONTEXT_HANDLER_ACTIVATE_FAILED, + CONTEXT_HANDLER_COUNT +}; + +typedef struct mms_connection_nemo { + MMSConnection connection; + MMSConnMan* cm; + OfonoExtModemManager* mm; + OfonoConnCtx* context; + OfonoConnMgr* connmgr; + gulong mm_handler_id[MM_HANDLER_COUNT]; + gulong context_handler_id[CONTEXT_HANDLER_COUNT]; + gulong connmgr_handler_id[CONNMGR_HANDLER_COUNT]; + char* imsi; + char* path; +} MMSConnectionNemo; + +typedef MMSConnectionClass MMSConnectionNemoClass; +G_DEFINE_TYPE(MMSConnectionNemo, mms_connection_nemo, MMS_TYPE_CONNECTION) +#define MMS_TYPE_CONNECTION_NEMO (mms_connection_nemo_get_type()) +#define MMS_CONNECTION_NEMO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + MMS_TYPE_CONNECTION_NEMO, MMSConnectionNemo)) + +static +void +mms_connection_nemo_disconnect( + MMSConnectionNemo* self) +{ + ofonoext_mm_remove_handlers(self->mm, self->mm_handler_id, + G_N_ELEMENTS(self->mm_handler_id)); + ofono_connmgr_remove_handlers(self->connmgr, self->connmgr_handler_id, + G_N_ELEMENTS(self->connmgr_handler_id)); + ofono_connctx_remove_handlers(self->context, self->context_handler_id, + G_N_ELEMENTS(self->context_handler_id)); +} + +static +void +mms_connection_nemo_disconnect_connmgr( + MMSConnectionNemo* self, + enum connmgr_handler_id id) +{ + if (self->connmgr_handler_id[id]) { + ofono_connmgr_remove_handler(self->connmgr, + self->connmgr_handler_id[id]); + self->connmgr_handler_id[id] = 0; + } +} + +static +void +mms_connection_nemo_disconnect_context( + MMSConnectionNemo* self, + enum context_handler_id id) +{ + if (self->context_handler_id[id]) { + ofono_connctx_remove_handler(self->context, + self->context_handler_id[id]); + self->context_handler_id[id] = 0; + } +} + +static +void +mms_connection_nemo_reset_mms_imsi_done( + OfonoExtModemManager* mm, + const char* path, + const GError* error, + void* arg) +{ + MMSConnectionNemo* self = MMS_CONNECTION_NEMO(arg); + MMS_DEBUG("Released %s", self->path); + mms_connman_busy_dec(self->cm); + mms_connection_unref(&self->connection); +} + +static +gboolean +mms_connection_nemo_set_state( + MMSConnectionNemo* self, + MMS_CONNECTION_STATE state) +{ + if (self->connection.state != state) { + if (self->connection.state == MMS_CONNECTION_STATE_FAILED || + self->connection.state == MMS_CONNECTION_STATE_CLOSED) { + /* These are terminal states, can't change those */ + return FALSE; + } else if (self->connection.state > state) { + /* Can't move back to a previous state */ + return FALSE; + } + if (state == MMS_CONNECTION_STATE_FAILED || + state == MMS_CONNECTION_STATE_CLOSED) { + + if (self->path) { + /* Tell ofono that this SIM is no longer reserved for MMS. + * Bump the reference while this D-Bus call is pending */ + mms_connection_ref(&self->connection); + mms_connman_busy_inc(self->cm); + ofonoext_mm_set_mms_imsi_full(self->mm, "", + mms_connection_nemo_reset_mms_imsi_done, self); + } + + /* Stop listening for property changes */ + mms_connection_nemo_disconnect(self); + } + self->connection.state = state; + mms_connection_signal_state_change(&self->connection); + } + return TRUE; +} + +static +void +mms_connection_nemo_cancel( + MMSConnectionNemo* self) +{ + if ((self->connection.state <= MMS_CONNECTION_STATE_OPENING && + mms_connection_nemo_set_state(self, MMS_CONNECTION_STATE_FAILED)) || + mms_connection_nemo_set_state(self, MMS_CONNECTION_STATE_CLOSED)) { + MMS_DEBUG("Cancelled %s", self->connection.imsi); + } +} + +static +void +mms_connection_nemo_cancel_if_invalid( + OfonoObject* obj, + void* arg) +{ + if (!obj->valid) { + MMS_VERBOSE_("oops!"); + mms_connection_nemo_cancel(MMS_CONNECTION_NEMO(arg)); + } +} + +static +void +mms_connection_nemo_active_changed( + OfonoConnCtx* context, + void* arg) +{ + MMSConnectionNemo* self = MMS_CONNECTION_NEMO(arg); + MMS_ASSERT(self->context == context); + if (context->active) { + MMS_DEBUG("Connection %s opened", self->connection.imsi); + mms_connection_nemo_set_state(self, MMS_CONNECTION_STATE_OPEN); + } else { + mms_connection_nemo_disconnect_context(self, CONTEXT_HANDLER_ACTIVE); + mms_connection_nemo_set_state(self, MMS_CONNECTION_STATE_CLOSED); + } +} + +static +void +mms_connection_nemo_interface_changed( + OfonoConnCtx* context, + void* arg) +{ + MMSConnectionNemo* self = MMS_CONNECTION_NEMO(arg); + MMS_ASSERT(self->context == context); + if (context->ifname) { + self->connection.netif = context->ifname; + MMS_DEBUG("Interface: %s", self->connection.netif); + } else { + self->connection.netif = NULL; + } +} + +static +void +mms_connection_nemo_mms_proxy_changed( + OfonoConnCtx* context, + void* arg) +{ + MMSConnectionNemo* self = MMS_CONNECTION_NEMO(arg); + MMS_ASSERT(self->context == context); + if (context->mms_proxy) { + self->connection.mmsproxy = context->mms_proxy; + MMS_DEBUG("MessageProxy: %s", self->connection.mmsproxy); + } else { + self->connection.mmsproxy = NULL; + } +} + +static +void +mms_connection_nemo_mms_center_changed( + OfonoConnCtx* context, + void* arg) +{ + MMSConnectionNemo* self = MMS_CONNECTION_NEMO(arg); + MMS_ASSERT(self->context == context); + if (context->mms_center) { + self->connection.mmsc = context->mms_center; + MMS_DEBUG("MessageCenter: %s", self->connection.mmsc); + } else { + self->connection.mmsc = NULL; + } +} + +static +void +mms_connection_nemo_activate_failed( + OfonoConnCtx* context, + const GError* error, + void* arg) +{ + MMSConnectionNemo* self = MMS_CONNECTION_NEMO(arg); + MMS_ASSERT(self->context == context); + mms_connection_nemo_cancel(self); +} + +static +void +mms_connection_nemo_check_context( + MMSConnectionNemo* self) +{ + if (self->connection.state == MMS_CONNECTION_STATE_OPENING) { + OfonoConnCtx* context = self->context; + if (ofono_connctx_valid(context) && context->active) { + /* Already connected */ + mms_connection_nemo_set_state(self, MMS_CONNECTION_STATE_OPEN); + } else { + OfonoConnMgr* connmgr = self->connmgr; + if (ofono_connmgr_valid(connmgr) && connmgr->attached) { + self->context_handler_id[CONTEXT_HANDLER_ACTIVATE_FAILED] = + ofono_connctx_add_activate_failed_handler(context, + mms_connection_nemo_activate_failed, self); + MMS_DEBUG("Activate %s", ofono_connctx_path(context)); + ofono_connctx_activate(context); + } + } + } +} + +static +void +mms_connection_nemo_connmgr_attached_changed( + OfonoConnMgr* connmgr, + void* arg) +{ + MMSConnectionNemo* self = MMS_CONNECTION_NEMO(arg); + MMS_DEBUG("Data registration %s for %s", connmgr->attached ? "on" : "off", + ofono_connmgr_path(connmgr)); + mms_connection_nemo_check_context(self); +} + +static +void +mms_connection_nemo_setup_context( + MMSConnectionNemo* self) +{ + MMSConnection* conn = &self->connection; + OfonoConnCtx* context = self->context; + + /* From this point on, cancel the connection if OfonoConnMgr becomes + * invalid (which would probably mean SIM removal or ofono crash) */ + mms_connection_nemo_disconnect_context(self, CONTEXT_HANDLER_VALID); + self->context_handler_id[CONTEXT_HANDLER_VALID] = + ofono_object_add_valid_changed_handler( + ofono_connctx_object(self->context), + mms_connection_nemo_cancel_if_invalid, self); + + /* Capture the current context state */ + if (context->mms_proxy && context->mms_proxy[0]) { + conn->mmsproxy = context->mms_proxy; + MMS_DEBUG("MessageProxy: %s", conn->mmsproxy); + } + if (context->mms_center && context->mms_center[0]) { + conn->mmsc = context->mms_center; + MMS_DEBUG("MessageCenter: %s", conn->mmsc); + } + if (context->ifname && context->ifname[0]) { + conn->netif = context->ifname; + MMS_DEBUG("Interface: %s", conn->netif); + } + + /* Track context property changes */ + self->context_handler_id[CONTEXT_HANDLER_ACTIVE] = + ofono_connctx_add_active_changed_handler(context, + mms_connection_nemo_active_changed, self); + self->context_handler_id[CONTEXT_HANDLER_INTERFACE] = + ofono_connctx_add_interface_changed_handler(context, + mms_connection_nemo_interface_changed, self); + self->context_handler_id[CONTEXT_HANDLER_MMS_PROXY] = + ofono_connctx_add_mms_proxy_changed_handler(context, + mms_connection_nemo_mms_proxy_changed, self); + self->context_handler_id[CONTEXT_HANDLER_MMS_CENTER] = + ofono_connctx_add_mms_center_changed_handler(context, + mms_connection_nemo_mms_center_changed, self); + + /* And start tracking the data registration state */ + self->connmgr_handler_id[CONNMGR_HANDLER_ATTACHED] = + ofono_connmgr_add_attached_changed_handler(self->connmgr, + mms_connection_nemo_connmgr_attached_changed, self); + + /* Check if we can actually connect */ + mms_connection_nemo_check_context(self); +} + +static +void +mms_connection_nemo_context_valid_changed( + OfonoConnCtx* context, + void* arg) +{ + MMSConnectionNemo* self = MMS_CONNECTION_NEMO(arg); + GASSERT(self->connection.state == MMS_CONNECTION_STATE_OPENING); + if (ofono_connctx_valid(context)) { + mms_connection_nemo_setup_context(self); + } +} + +static +void +mms_connection_nemo_init_context( + MMSConnectionNemo* self) +{ + MMS_ASSERT(ofono_connmgr_valid(self->connmgr)); + MMS_ASSERT(!self->context); + + /* From this point on, cancel the connection if OfonoConnMgr becomes + * invalid (which would probably mean SIM removal or ofono crash) */ + mms_connection_nemo_disconnect_connmgr(self, CONNMGR_HANDLER_VALID); + self->connmgr_handler_id[CONNMGR_HANDLER_VALID] = + ofono_object_add_valid_changed_handler( + ofono_connmgr_object(self->connmgr), + mms_connection_nemo_cancel_if_invalid, self); + + /* ofono_connctx_ref has no problem with a NULL pointer */ + self->context = ofono_connctx_ref(ofono_connmgr_get_context_for_type( + self->connmgr, OFONO_CONNCTX_TYPE_MMS)); + if (self->context) { + MMS_DEBUG("MMS context %s", ofono_connctx_path(self->context)); + if (ofono_connctx_valid(self->context)) { + mms_connection_nemo_setup_context(self); + } else { + self->context_handler_id[CONTEXT_HANDLER_VALID] = + ofono_connctx_add_valid_changed_handler(self->context, + mms_connection_nemo_context_valid_changed, self); + } + } else { + MMS_WARN("No MMS context"); + mms_connection_nemo_cancel(self); + } +} + +static +void +mms_connection_nemo_connmgr_valid_changed( + OfonoConnMgr* connmgr, + void* arg) +{ + MMSConnectionNemo* self = MMS_CONNECTION_NEMO(arg); + GASSERT(self->connection.state == MMS_CONNECTION_STATE_OPENING); + if (ofono_connmgr_valid(connmgr)) { + mms_connection_nemo_init_context(self); + } +} + +static +void +mms_connection_nemo_mms_imsi_changed( + OfonoExtModemManager* mm, + void* arg) +{ + MMSConnectionNemo* self = MMS_CONNECTION_NEMO(arg); + if (mm->valid && g_strcmp0(mm->mms_imsi, self->connection.imsi)) { + MMS_VERBOSE_("%s", mm->mms_imsi); + mms_connection_nemo_cancel(self); + } +} + +static +void +mms_connection_nemo_set_mms_imsi_done( + OfonoExtModemManager* mm, + const char* path, + const GError* error, + void* arg) +{ + MMSConnectionNemo* self = MMS_CONNECTION_NEMO(arg); + if (error) { + mms_connection_nemo_cancel(self); + } else { + MMS_DEBUG("MMS modem path %s", path); + MMS_ASSERT(!self->path); + MMS_ASSERT(!self->connmgr); + self->path = g_strdup(path); + + if (self->connection.state == MMS_CONNECTION_STATE_OPENING) { + self->connmgr = ofono_connmgr_new(path); + + /* Cancel connection if MMS SIM changes */ + self->mm_handler_id[MM_HANDLER_MMS_IMSI] = + ofonoext_mm_add_mms_imsi_changed_handler(mm, + mms_connection_nemo_mms_imsi_changed, self); + + if (ofono_connmgr_valid(self->connmgr)) { + mms_connection_nemo_init_context(self); + } else { + /* Wait for OfonoConnMgr to become valid */ + self->connmgr_handler_id[CONNMGR_HANDLER_VALID] = + ofono_connmgr_add_valid_changed_handler(self->connmgr, + mms_connection_nemo_connmgr_valid_changed, self); + } + } else { + /* Connection has been cancelled, release the slot */ + MMS_DEBUG("Canceled, releasing %s", path); + mms_connection_ref(&self->connection); + mms_connman_busy_inc(self->cm); + ofonoext_mm_set_mms_imsi_full(self->mm, "", + mms_connection_nemo_reset_mms_imsi_done, self); + } + } + /* Release the reference */ + mms_connman_busy_dec(self->cm); + mms_connection_unref(&self->connection); +} + +static +void +mms_connection_nemo_cancel_if_mm_invalid( + OfonoExtModemManager* mm, + void* arg) +{ + if (!mm->valid) { + MMS_VERBOSE_("oops!"); + mms_connection_nemo_cancel(MMS_CONNECTION_NEMO(arg)); + } +} + +static +void +mms_connection_nemo_request_sim( + MMSConnectionNemo* self) +{ + /* Cancel the connection if OfonoExtModemManager becomes invalid */ + GASSERT(self->mm->valid); + ofonoext_mm_remove_handler(self->mm, + self->mm_handler_id[MM_HANDLER_VALID]); + self->mm_handler_id[MM_HANDLER_VALID] = + ofonoext_mm_add_valid_changed_handler(self->mm, + mms_connection_nemo_cancel_if_mm_invalid, self); + + /* Bump the reference while this D-Bus call is pending */ + mms_connection_ref(&self->connection); + mms_connman_busy_inc(self->cm); + ofonoext_mm_set_mms_imsi_full(self->mm, self->imsi, + mms_connection_nemo_set_mms_imsi_done, self); +} + +static +void +mms_connection_nemo_mm_valid_changed( + OfonoExtModemManager* mm, + void* arg) +{ + MMSConnectionNemo* self = MMS_CONNECTION_NEMO(arg); + MMS_VERBOSE_("%p %d", self, mm->valid); + if (mm->valid) { + mms_connection_nemo_request_sim(arg); + } +} + +MMSConnection* +mms_connection_nemo_new( + MMSConnMan* cm, + const char* imsi, + gboolean user_request) +{ + MMSConnectionNemo* self = g_object_new(MMS_TYPE_CONNECTION_NEMO, NULL); + MMSConnection* conn = &self->connection; + + MMS_VERBOSE_("%p %s", self, imsi); + conn->user_connection = user_request; + conn->imsi = self->imsi = g_strdup(imsi); + conn->state = MMS_CONNECTION_STATE_OPENING; + self->mm = ofonoext_mm_new(); + self->cm = mms_connman_ref(cm); + + if (self->mm->valid) { + mms_connection_nemo_request_sim(self); + } else { + self->mm_handler_id[MM_HANDLER_VALID] = + ofonoext_mm_add_valid_changed_handler(self->mm, + mms_connection_nemo_mm_valid_changed, self); + } + + return &self->connection; +} + +static +void +mms_connection_nemo_close( + MMSConnection* connection) +{ + MMSConnectionNemo* self = MMS_CONNECTION_NEMO(connection); + OfonoConnCtx* context = self->context; + if (ofono_connctx_valid(context) && context->active) { + MMS_DEBUG("Deactivate %s", ofono_connctx_path(context)); + ofono_connctx_deactivate(context); + } else { + if (self->connection.state != MMS_CONNECTION_STATE_FAILED && + self->connection.state != MMS_CONNECTION_STATE_CLOSED) { + MMS_DEBUG("Cancelling %s", self->connection.imsi); + mms_connection_nemo_cancel(self); + } + } +} + +/** + * First stage of deinitialization (release all references). + * May be called more than once in the lifetime of the object. + */ +static +void +mms_connection_nemo_dispose( + GObject* object) +{ + MMSConnectionNemo* self = MMS_CONNECTION_NEMO(object); + MMS_VERBOSE_("%p %s", self, self->imsi); + MMS_ASSERT(!mms_connection_is_active(&self->connection)); + mms_connection_nemo_disconnect(self); + if (self->context) { + if (mms_connection_is_active(&self->connection) && + self->context->active) { + ofono_connctx_deactivate(self->context); + } + ofono_connctx_unref(self->context); + self->context = NULL; + } + self->connection.netif = NULL; + G_OBJECT_CLASS(mms_connection_nemo_parent_class)->dispose(object); +} + +/** + * Final stage of deinitialization + */ +static +void +mms_connection_nemo_finalize( + GObject* object) +{ + MMSConnectionNemo* self = MMS_CONNECTION_NEMO(object); + MMS_VERBOSE_("%p %s", self, self->imsi); + ofono_connmgr_unref(self->connmgr); + ofono_connctx_unref(self->context); + ofonoext_mm_unref(self->mm); + mms_connman_unref(self->cm); + g_free(self->imsi); + g_free(self->path); + G_OBJECT_CLASS(mms_connection_nemo_parent_class)->finalize(object); +} + +/** + * Per class initializer + */ +static +void +mms_connection_nemo_class_init( + MMSConnectionNemoClass* klass) +{ + GObjectClass* object_class = G_OBJECT_CLASS(klass); + klass->fn_close = mms_connection_nemo_close; + object_class->dispose = mms_connection_nemo_dispose; + object_class->finalize = mms_connection_nemo_finalize; +} + +/** + * Per instance initializer + */ +static +void +mms_connection_nemo_init( + MMSConnectionNemo* self) +{ + MMS_VERBOSE_("%p", self); +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-connman-nemo/src/mms_connection_nemo.h b/mms-connman-nemo/src/mms_connection_nemo.h new file mode 100644 index 0000000..08f888b --- /dev/null +++ b/mms-connman-nemo/src/mms_connection_nemo.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013-2016 Jolla Ltd. + * Contact: Slava Monich + * + * 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. + * + */ + +#ifndef JOLLA_MMS_CONNECTION_NEMO_H +#define JOLLA_MMS_CONNECTION_NEMO_H + +#include "mms_connection.h" + +#include + +MMSConnection* +mms_connection_nemo_new( + MMSConnMan* cm, + const char* imsi, + gboolean user_request); + +#endif /* JOLLA_MMS_CONNECTION_NEMO_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-connman-nemo/src/mms_connman_nemo.c b/mms-connman-nemo/src/mms_connman_nemo.c new file mode 100644 index 0000000..465d8eb --- /dev/null +++ b/mms-connman-nemo/src/mms_connman_nemo.c @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2016 Jolla Ltd. + * Contact: Slava Monich + * + * 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. + * + */ + +#include "mms_connman_nemo.h" +#include "mms_connection_nemo.h" + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_connman_log +#include "mms_connman_nemo_log.h" +MMS_LOG_MODULE_DEFINE("mms-connman-nemo"); + +typedef MMSConnManClass MMSConnManNemoClass; +typedef struct mms_connman_nemo { + MMSConnMan cm; + OfonoExtModemManager* mm; + MMSConnection* conn; + gulong voice_sim_changed_id; +} MMSConnManNemo; + +G_DEFINE_TYPE(MMSConnManNemo, mms_connman_nemo, MMS_TYPE_CONNMAN) +#define MMS_TYPE_CONNMAN_NEMO (mms_connman_nemo_get_type()) +#define MMS_CONNMAN_NEMO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + MMS_TYPE_CONNMAN_NEMO, MMSConnManNemo)) + +#define MMS_INIT_TIMEOUT_SEC (30) + +static +gboolean +mms_connman_nemo_wait_timeout( + gpointer data) +{ + g_main_loop_quit(data); + return G_SOURCE_REMOVE; +} + +static +void +mms_connman_nemo_wait_valid_changed( + OfonoExtModemManager* mm, + void* data) +{ + if (mm->valid) { + g_main_loop_quit(data); + } +} + +/** + * Checks if OfonoExtModemManager is initialized and waits up to + * MMS_INIT_TIMEOUT_SEC if necessary. + */ +static +gboolean +mms_connman_nemo_mm_valid( + MMSConnManNemo* self) +{ + if (self->mm->valid) { + return TRUE; + } else { + /* That shouldn't take long */ + GMainLoop* loop = g_main_loop_new(NULL, TRUE); + guint timeout_id = g_timeout_add(MMS_INIT_TIMEOUT_SEC*1000, + mms_connman_nemo_wait_timeout, loop); + gulong valid_id = ofonoext_mm_add_valid_changed_handler(self->mm, + mms_connman_nemo_wait_valid_changed, loop); + g_main_loop_run(loop); + g_main_loop_unref(loop); + g_source_remove(timeout_id); + ofonoext_mm_remove_handler(self->mm, valid_id); + return self->mm->valid; + } +} + +/** + * Returns IMSI of the default (voice) SIM + */ +static +char* +mms_connman_nemo_default_imsi( + MMSConnMan* cm) +{ + MMSConnManNemo* self = MMS_CONNMAN_NEMO(cm); + if (mms_connman_nemo_mm_valid(self)) { + return g_strdup(self->mm->voice_imsi); + } + return NULL; +} + +/** + * MMSConnection destroy notification. + */ +static +void +mms_connman_nemo_connection_weak_ref_notify( + gpointer arg, + GObject* connection) +{ + MMSConnManNemo* self = MMS_CONNMAN_NEMO(arg); + MMS_ASSERT(MMS_CONNECTION(connection) == self->conn); + self->conn = NULL; +} + +/** + * Creates a new connection or returns the reference to an aready active one. + * The caller must release the reference. Returns NULL if the modem is offline + * and the network task should fail immediately. + */ +static +MMSConnection* +mms_connman_nemo_open_connection( + MMSConnMan* cm, + const char* imsi, + gboolean user_request) +{ + MMSConnManNemo* self = MMS_CONNMAN_NEMO(cm); + if (self->conn) { + if (!g_strcmp0(self->conn->imsi, imsi)) { + return mms_connection_ref(self->conn); + } else { + g_object_weak_unref(G_OBJECT(self->conn), + mms_connman_nemo_connection_weak_ref_notify, self); + self->conn = NULL; + } + } + self->conn = mms_connection_nemo_new(cm, imsi, user_request); + g_object_weak_ref(G_OBJECT(self->conn), + mms_connman_nemo_connection_weak_ref_notify, self); + return self->conn; +} + +/** + * Creates connection manager + */ +MMSConnMan* +mms_connman_nemo_new() +{ + MMSConnManNemo* self = g_object_new(MMS_TYPE_CONNMAN_NEMO, NULL); + self->mm = ofonoext_mm_new(); + return &self->cm; +} + +/** + * Final stage of deinitialization + */ +static +void +mms_connman_nemo_finalize( + GObject* object) +{ + MMSConnManNemo* self = MMS_CONNMAN_NEMO(object); + MMS_VERBOSE_(""); + ofonoext_mm_unref(self->mm); + G_OBJECT_CLASS(mms_connman_nemo_parent_class)->finalize(object); +} + +/** + * Per class initializer + */ +static +void +mms_connman_nemo_class_init( + MMSConnManNemoClass* klass) +{ + GObjectClass* object_class = G_OBJECT_CLASS(klass); + klass->fn_default_imsi = mms_connman_nemo_default_imsi; + klass->fn_open_connection = mms_connman_nemo_open_connection; + object_class->finalize = mms_connman_nemo_finalize; +} + +/** + * Per instance initializer + */ +static +void +mms_connman_nemo_init( + MMSConnManNemo* self) +{ +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-engine/Makefile b/mms-engine/Makefile index 131f819..e0f60e9 100644 --- a/mms-engine/Makefile +++ b/mms-engine/Makefile @@ -18,6 +18,11 @@ include ../mms-lib/Config.mak PKGS = gio-unix-2.0 gio-2.0 libglibutil LIB_PKGS = libwspcodec gmime-2.6 libgofono libsoup-2.4 dconf + +ifdef MMS_CONNMAN_NEMO +LIB_PKGS += libgofonoext +endif + LIB_PKGS += $(RESIZE_PKG) $(PKGS) # @@ -58,8 +63,13 @@ MMS_LIB_RELEASE_LIB = $(MMS_LIB_BUILD_DIR)/release/$(MMS_LIB_LIB) # mms-connman # -MMS_CONNMAN_LIB = libmms-connman-ofono.a -MMS_CONNMAN_DIR = ../mms-connman-ofono +ifdef MMS_CONNMAN_NEMO +MMS_CONNMAN = nemo +else +MMS_CONNMAN = ofono +endif +MMS_CONNMAN_LIB = libmms-connman-$(MMS_CONNMAN).a +MMS_CONNMAN_DIR = ../mms-connman-$(MMS_CONNMAN) MMS_CONNMAN_BUILD_DIR = $(MMS_CONNMAN_DIR)/build MMS_CONNMAN_DEBUG_LIB = $(MMS_CONNMAN_BUILD_DIR)/debug/$(MMS_CONNMAN_LIB) MMS_CONNMAN_RELEASE_LIB = $(MMS_CONNMAN_BUILD_DIR)/release/$(MMS_CONNMAN_LIB) @@ -112,6 +122,10 @@ ifdef MMS_ENGINE_VERSION CFLAGS += -DMMS_ENGINE_VERSION="$(MMS_ENGINE_VERSION)" endif +ifdef MMS_CONNMAN_NEMO +CFLAGS += -DMMS_CONNMAN_NEMO +endif + DEBUG_CFLAGS = $(DEBUG_FLAGS) $(DEBUG_DEFS) $(CFLAGS) RELEASE_CFLAGS = $(RELEASE_FLAGS) $(RELEASE_DEFS) $(CFLAGS) diff --git a/mms-engine/main.c b/mms-engine/main.c index 375ebd9..017c321 100644 --- a/mms-engine/main.c +++ b/mms-engine/main.c @@ -17,11 +17,16 @@ #include #include "mms_engine.h" -#include "mms_connman_ofono_log.h" #include "mms_lib_log.h" #include "mms_lib_util.h" #include "mms_settings.h" +#ifdef MMS_CONNMAN_NEMO +# include "mms_connman_nemo_log.h" +#else +# include "mms_connman_ofono_log.h" +#endif + #define RET_OK (0) #define RET_ERR (1) diff --git a/mms-engine/mms-engine.pro b/mms-engine/mms-engine.pro index 566255a..6213809 100644 --- a/mms-engine/mms-engine.pro +++ b/mms-engine/mms-engine.pro @@ -2,16 +2,6 @@ TEMPLATE = app CONFIG += link_pkgconfig PKGCONFIG += gmime-2.6 gio-unix-2.0 gio-2.0 glib-2.0 libsoup-2.4 dconf PKGCONFIG += libwspcodec libgofono libglibutil -DBUS_INTERFACE_DIR = $$_PRO_FILE_PWD_ -MMS_LIB_DIR = $$_PRO_FILE_PWD_/../mms-lib -MMS_CONNMAN = mms-connman-ofono -MMS_CONNMAN_DIR = $$_PRO_FILE_PWD_/../$$MMS_CONNMAN -MMS_HANDLER_DIR = $$_PRO_FILE_PWD_/../mms-handler-dbus -MMS_SETTINGS_DIR = $$_PRO_FILE_PWD_/../mms-settings-dconf -INCLUDEPATH += $$MMS_CONNMAN_DIR/include -INCLUDEPATH += $$MMS_LIB_DIR/include -INCLUDEPATH += $$MMS_HANDLER_DIR/include -INCLUDEPATH += $$MMS_SETTINGS_DIR/include QMAKE_CFLAGS += -Wno-unused-parameter include(../mms-lib/mms-lib-config.pri) @@ -21,6 +11,25 @@ ResizeImageMagick { PKGCONFIG += ImageMagick } +ConnManNemo { + PKGCONFIG += libgofonoext + DEFINES += MMS_CONNMAN_NEMO + MMS_CONNMAN = mms-connman-nemo +} else { + MMS_CONNMAN = mms-connman-ofono +} + +DBUS_INTERFACE_DIR = $$_PRO_FILE_PWD_ +MMS_LIB_DIR = $$_PRO_FILE_PWD_/../mms-lib +MMS_HANDLER_DIR = $$_PRO_FILE_PWD_/../mms-handler-dbus +MMS_SETTINGS_DIR = $$_PRO_FILE_PWD_/../mms-settings-dconf +MMS_CONNMAN_DIR = $$_PRO_FILE_PWD_/../$$MMS_CONNMAN + +INCLUDEPATH += $$MMS_LIB_DIR/include +INCLUDEPATH += $$MMS_HANDLER_DIR/include +INCLUDEPATH += $$MMS_SETTINGS_DIR/include +INCLUDEPATH += $$MMS_CONNMAN_DIR/include + SOURCES += \ main.c \ mms_engine.c diff --git a/mms-engine/mms_engine.c b/mms-engine/mms_engine.c index e9dc005..bfc49fe 100644 --- a/mms-engine/mms_engine.c +++ b/mms-engine/mms_engine.c @@ -17,11 +17,18 @@ #include "mms_dispatcher.h" #include "mms_settings.h" #include "mms_lib_util.h" -#include "mms_connman_ofono.h" #include "mms_handler_dbus.h" #include "mms_settings_dconf.h" #include "mms_log.h" +#ifdef MMS_CONNMAN_NEMO +# include "mms_connman_nemo.h" +# define mms_connman_new() mms_connman_nemo_new() +#else +# include "mms_connman_ofono.h" +# define mms_connman_new() mms_connman_ofono_new() +#endif + /* Generated code */ #include "org.nemomobile.MmsEngine.h" @@ -452,7 +459,7 @@ mms_engine_new( MMSLogModule* log_modules[], int log_count) { - MMSConnMan* cm = mms_connman_ofono_new(); + MMSConnMan* cm = mms_connman_new(); if (cm) { MMSEngine* mms = g_object_new(MMS_TYPE_ENGINE, NULL); MMSHandler* handler = mms_handler_dbus_new(); diff --git a/mms-lib/include/mms_connman.h b/mms-lib/include/mms_connman.h index ac90cf7..6177f7b 100644 --- a/mms-lib/include/mms_connman.h +++ b/mms-lib/include/mms_connman.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2014 Jolla Ltd. + * Copyright (C) 2013-2016 Jolla 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 @@ -20,6 +20,7 @@ /* Instance */ struct mms_connman { GObject object; + int busy; }; /* Class */ @@ -33,6 +34,12 @@ typedef struct mms_connman_class { GType mms_connman_get_type(void); #define MMS_TYPE_CONNMAN (mms_connman_get_type()) +/* Connman event callback */ +typedef void +(*mms_connman_event_fn)( + MMSConnMan* cm, + void* param); + /* Reference counting */ MMSConnMan* mms_connman_ref( @@ -60,6 +67,29 @@ mms_connman_open_connection( const char* imsi, gboolean user_request); +/** + * While busy flags is on, mms-engine shouldn't exit + */ +void +mms_connman_busy_update( + MMSConnMan* cm, + int change); + +gulong +mms_connman_add_done_callback( + MMSConnMan* cm, + mms_connman_event_fn fn, + void* param); + +void +mms_connman_remove_callback( + MMSConnMan* cm, + gulong handler_id); + +#define mms_connman_busy(cm) ((cm) && ((cm)->busy > 0)) +#define mms_connman_busy_inc(cm) mms_connman_busy_update(cm,1) +#define mms_connman_busy_dec(cm) mms_connman_busy_update(cm,-1) + #endif /* JOLLA_MMS_CONNMAN_H */ /* diff --git a/mms-lib/mms-lib-config.pri b/mms-lib/mms-lib-config.pri index 18f4195..066e176 100644 --- a/mms-lib/mms-lib-config.pri +++ b/mms-lib/mms-lib-config.pri @@ -1,2 +1,4 @@ #CONFIG += ResizeImageMagick CONFIG += ResizeQt + +#CONFIG += ConnManNemo diff --git a/mms-lib/src/mms_connman.c b/mms-lib/src/mms_connman.c index 257e09e..006f47e 100644 --- a/mms-lib/src/mms_connman.c +++ b/mms-lib/src/mms_connman.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2014 Jolla Ltd. + * Copyright (C) 2013-2016 Jolla 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 @@ -14,12 +14,25 @@ #include "mms_connman.h" +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_connman_log +#include "mms_lib_log.h" + G_DEFINE_TYPE(MMSConnMan, mms_connman, G_TYPE_OBJECT); #define MMS_CONNMAN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ MMS_TYPE_CONNMAN, MMSConnMan)) #define MMS_CONNMAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \ MMS_TYPE_CONNMAN, MMSConnManClass)) +enum { + MMS_CONNMAN_SIGNAL_DONE, + MMS_CONNMAN_SIGNAL_COUNT +}; + +#define MMS_CONNMAN_SIGNAL_DONE_NAME "connman-done" + +static guint mms_connman_sig[MMS_CONNMAN_SIGNAL_COUNT] = { 0 }; + MMSConnMan* mms_connman_ref( MMSConnMan* cm) @@ -35,6 +48,36 @@ mms_connman_unref( if (cm) g_object_unref(MMS_CONNMAN(cm)); } +gulong +mms_connman_add_done_callback( + MMSConnMan* cm, + mms_connman_event_fn fn, + void* param) +{ + if (cm && fn) { + return g_signal_connect_data(cm, MMS_CONNMAN_SIGNAL_DONE_NAME, + G_CALLBACK(fn), param, NULL, 0); + } + return 0; +} + +void +mms_connman_remove_callback( + MMSConnMan* cm, + gulong handler_id) +{ + if (cm && handler_id) g_signal_handler_disconnect(cm, handler_id); +} + +static +void +mms_connman_finalize( + GObject* object) +{ + MMS_ASSERT(!MMS_CONNMAN(object)->busy); + G_OBJECT_CLASS(mms_connman_parent_class)->finalize(object); +} + /** * Per class initializer */ @@ -43,6 +86,11 @@ void mms_connman_class_init( MMSConnManClass* klass) { + G_OBJECT_CLASS(klass)->finalize = mms_connman_finalize; + mms_connman_sig[MMS_CONNMAN_SIGNAL_DONE] = + g_signal_new(MMS_CONNMAN_SIGNAL_DONE_NAME, + G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, G_TYPE_NONE, 0); } /** @@ -91,6 +139,22 @@ mms_connman_open_connection( return NULL; } +void +mms_connman_busy_update( + MMSConnMan* cm, + int change) +{ + MMS_ASSERT(change); + if (cm && change) { + cm->busy += change; + MMS_VERBOSE("busy count %d", cm->busy); + MMS_ASSERT(cm->busy >= 0); + if (cm->busy < 1) { + g_signal_emit(cm, mms_connman_sig[MMS_CONNMAN_SIGNAL_DONE], 0); + } + } +} + /* * Local Variables: * mode: C diff --git a/mms-lib/src/mms_dispatcher.c b/mms-lib/src/mms_dispatcher.c index 0222e7d..e137c80 100644 --- a/mms-lib/src/mms_dispatcher.c +++ b/mms-lib/src/mms_dispatcher.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2015 Jolla Ltd. + * Copyright (C) 2013-2016 Jolla Ltd. * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify @@ -44,6 +44,7 @@ struct mms_dispatcher { guint next_run_id; guint network_idle_id; gulong handler_done_id; + gulong connman_done_id; gulong connection_changed_id; gboolean started; }; @@ -302,8 +303,8 @@ mms_dispatcher_is_active( MMSDispatcher* disp) { return disp && (mms_connection_is_active(disp->connection) || - mms_handler_busy(disp->handler) || disp->active_task || - !g_queue_is_empty(disp->tasks)); + mms_handler_busy(disp->handler) || mms_connman_busy(disp->cm) || + disp->active_task || !g_queue_is_empty(disp->tasks)); } /** @@ -360,18 +361,24 @@ mms_dispatcher_pick_next_task( MMSTask* task = entry->data; if ((task->state == MMS_TASK_STATE_NEED_CONNECTION || task->state == MMS_TASK_STATE_NEED_USER_CONNECTION)) { + /* Closing the connection may take some time. If connection + * is still around, we will have to wait. */ mms_dispatcher_close_connection(disp); - disp->connection = mms_connman_open_connection( - disp->cm, task->imsi, FALSE); - if (disp->connection) { - MMS_ASSERT(!disp->connection_changed_id); - disp->connection_changed_id = - mms_connection_add_state_change_handler(disp->connection, - mms_dispatcher_connection_state_changed, disp); - g_queue_delete_link(disp->tasks, entry); - return task; - } else { - mms_task_network_unavailable(task, FALSE); + if (!disp->connection) { + disp->connection = mms_connman_open_connection(disp->cm, + task->imsi, FALSE); + if (disp->connection) { + MMS_ASSERT(!disp->connection_changed_id); + disp->connection_changed_id = + mms_connection_add_state_change_handler( + disp->connection, + mms_dispatcher_connection_state_changed, + disp); + g_queue_delete_link(disp->tasks, entry); + return task; + } else { + mms_task_network_unavailable(task, FALSE); + } } } } @@ -668,7 +675,21 @@ mms_dispatcher_handler_done( } /** - * Creates the dispatcher object. Caller must clal mms_dispatcher_unref + * Connman state callback + */ +static +void +mms_dispatcher_connman_done( + MMSConnMan* cm, + void* param) +{ + MMSDispatcher* disp = param; + MMS_VERBOSE("Connman is inactive"); + mms_dispatcher_check_if_done(disp); +} + +/** + * Creates the dispatcher object. Caller must call mms_dispatcher_unref * when it no longer needs it. */ MMSDispatcher* @@ -689,6 +710,8 @@ mms_dispatcher_new( mms_dispatcher_delegate_task_state_changed; disp->handler_done_id = mms_handler_add_done_callback(handler, mms_dispatcher_handler_done, disp); + disp->connman_done_id = mms_connman_add_done_callback(cm, + mms_dispatcher_connman_done, disp); return disp; } @@ -705,6 +728,7 @@ mms_dispatcher_finalize( char* msg_dir = g_strconcat(root_dir, "/" MMS_MESSAGE_DIR "/", NULL); MMS_VERBOSE_(""); mms_handler_remove_callback(disp->handler, disp->handler_done_id); + mms_connman_remove_callback(disp->cm, disp->connman_done_id); mms_dispatcher_drop_connection(disp); while ((task = g_queue_pop_head(disp->tasks)) != NULL) { task->delegate = NULL; diff --git a/mms.pro b/mms.pro index a607659..ee52a60 100644 --- a/mms.pro +++ b/mms.pro @@ -2,6 +2,7 @@ TEMPLATE = subdirs CONFIG += ordered SUBDIRS += \ mms-lib \ + mms-connman-nemo \ mms-connman-ofono \ mms-handler-dbus \ mms-settings-dconf \ diff --git a/rpm/mms-engine.spec b/rpm/mms-engine.spec index 2f5d229..ff3665e 100644 --- a/rpm/mms-engine.spec +++ b/rpm/mms-engine.spec @@ -21,9 +21,12 @@ BuildRequires: pkgconfig(glib-2.0) >= 2.32 BuildRequires: pkgconfig(libsoup-2.4) >= 2.38 BuildRequires: pkgconfig(libwspcodec) >= 2.2 BuildRequires: pkgconfig(libgofono) >= 1.0.5 +BuildRequires: pkgconfig(libgofonoext) >= 1.0.4 BuildRequires: pkgconfig(libglibutil) #BuildRequires: pkgconfig(ImageMagick) BuildRequires: pkgconfig(Qt5Gui) +Requires: libgofono >= 1.0.5 +Requires: libgofonoext >= 1.0.4 %define src mms-engine %define exe mms-engine @@ -52,7 +55,7 @@ MMS command line utilities %setup -q -n %{name}-%{version} %build -make -C %{src} KEEP_SYMBOLS=1 MMS_ENGINE_VERSION="%{version}" release +make -C %{src} KEEP_SYMBOLS=1 MMS_CONNMAN_NEMO=1 MMS_ENGINE_VERSION="%{version}" release make -C mms-dump KEEP_SYMBOLS=1 release make -C mms-send KEEP_SYMBOLS=1 release