diff options
-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; } |