diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2012-07-13 12:19:19 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2012-08-29 17:26:39 +0200 |
commit | b2ea82ed3b85897094257ac63230048ab9605f1c (patch) | |
tree | d70c13c6768dac0ee604facd4b482190c01cfad6 /src | |
parent | 19da38a330ad0e5ef567c074932a79ae09e897f2 (diff) |
broadband-modem-qmi: keep the QMI port open for the whole lifetime of the modem
The QMI port is opened during the modem initialization, and kept open until the
modem gets destroyed.
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-broadband-modem-qmi.c | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c index 9f9efdb7..e81f98ca 100644 --- a/src/mm-broadband-modem-qmi.c +++ b/src/mm-broadband-modem-qmi.c @@ -30,6 +30,158 @@ G_DEFINE_TYPE (MMBroadbandModemQmi, mm_broadband_modem_qmi, MM_TYPE_BROADBAND_MODEM); /*****************************************************************************/ +/* First initialization step */ + +typedef struct { + MMBroadbandModem *self; + GSimpleAsyncResult *result; + MMQmiPort *qmi; + QmiService services[32]; + guint service_index; +} InitializationStartedContext; + +static void +initialization_started_context_complete_and_free (InitializationStartedContext *ctx) +{ + g_simple_async_result_complete_in_idle (ctx->result); + if (ctx->qmi) + g_object_unref (ctx->qmi); + g_object_unref (ctx->result); + g_object_unref (ctx->self); + g_free (ctx); +} + +static gpointer +initialization_started_finish (MMBroadbandModem *self, + GAsyncResult *res, + GError **error) +{ + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) + return NULL; + + /* Just parent's pointer passed here */ + return g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)); +} + +static void +parent_initialization_started_ready (MMBroadbandModem *self, + GAsyncResult *res, + InitializationStartedContext *ctx) +{ + gpointer parent_ctx; + GError *error = NULL; + + parent_ctx = MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_qmi_parent_class)->initialization_started_finish ( + self, + res, + &error); + if (error) { + g_prefix_error (&error, "Couldn't start parent initialization: "); + g_simple_async_result_take_error (ctx->result, error); + } else + g_simple_async_result_set_op_res_gpointer (ctx->result, parent_ctx, NULL); + + initialization_started_context_complete_and_free (ctx); +} + +static void +parent_initialization_started (InitializationStartedContext *ctx) +{ + MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_qmi_parent_class)->initialization_started ( + ctx->self, + (GAsyncReadyCallback)parent_initialization_started_ready, + ctx); +} + +static void allocate_next_client (InitializationStartedContext *ctx); + +static void +qmi_port_allocate_client_ready (MMQmiPort *qmi, + GAsyncResult *res, + InitializationStartedContext *ctx) +{ + GError *error = NULL; + + if (!mm_qmi_port_allocate_client_finish (qmi, res, &error)) { + mm_dbg ("Couldn't allocate client for service '%s': %s", + qmi_service_get_string (ctx->services[ctx->service_index]), + error->message); + g_error_free (error); + } + + ctx->service_index++; + allocate_next_client (ctx); +} + +static void +allocate_next_client (InitializationStartedContext *ctx) +{ + if (ctx->services[ctx->service_index] == QMI_SERVICE_UNKNOWN) { + /* Done we are, launch parent's callback */ + parent_initialization_started (ctx); + return; + } + + /* Otherwise, allocate next client */ + mm_qmi_port_allocate_client (ctx->qmi, + ctx->services[ctx->service_index], + NULL, + (GAsyncReadyCallback)qmi_port_allocate_client_ready, + ctx); +} + +static void +qmi_port_open_ready (MMQmiPort *qmi, + GAsyncResult *res, + InitializationStartedContext *ctx) +{ + GError *error = NULL; + + if (!mm_qmi_port_open_finish (qmi, res, &error)) { + g_simple_async_result_take_error (ctx->result, error); + initialization_started_context_complete_and_free (ctx); + return; + } + + allocate_next_client (ctx); +} + +static void +initialization_started (MMBroadbandModem *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + InitializationStartedContext *ctx; + + ctx = g_new0 (InitializationStartedContext, 1); + ctx->self = g_object_ref (self); + ctx->result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + initialization_started); + ctx->qmi = mm_base_modem_get_port_qmi (MM_BASE_MODEM (self)); + g_assert (ctx->qmi); + + if (mm_qmi_port_is_open (ctx->qmi)) { + /* Nothing to be done, just launch parent's callback */ + parent_initialization_started (ctx); + return; + } + + /* Setup services to open */ + ctx->services[0] = QMI_SERVICE_DMS; + ctx->services[1] = QMI_SERVICE_WDS; + ctx->services[2] = QMI_SERVICE_NAS; + ctx->services[3] = QMI_SERVICE_UNKNOWN; + + /* Now open our QMI port */ + mm_qmi_port_open (ctx->qmi, + NULL, + (GAsyncReadyCallback)qmi_port_open_ready, + ctx); +} + +/*****************************************************************************/ MMBroadbandModemQmi * mm_broadband_modem_qmi_new (const gchar *device, @@ -53,6 +205,29 @@ mm_broadband_modem_qmi_init (MMBroadbandModemQmi *self) } static void +finalize (GObject *object) +{ + MMQmiPort *qmi; + MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (object); + + qmi = mm_base_modem_peek_port_qmi (MM_BASE_MODEM (self)); + /* If we did open the QMI port during initialization, close it now */ + if (qmi && + mm_qmi_port_is_open (qmi)) { + mm_qmi_port_close (qmi); + } + + G_OBJECT_CLASS (mm_broadband_modem_qmi_parent_class)->finalize (object); +} + +static void mm_broadband_modem_qmi_class_init (MMBroadbandModemQmiClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS (klass); + MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass); + + object_class->finalize = finalize; + + broadband_modem_class->initialization_started = initialization_started; + broadband_modem_class->initialization_started_finish = initialization_started_finish; } |