aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2012-07-13 12:19:19 +0200
committerAleksander Morgado <aleksander@lanedo.com>2012-08-29 17:26:39 +0200
commitb2ea82ed3b85897094257ac63230048ab9605f1c (patch)
treed70c13c6768dac0ee604facd4b482190c01cfad6
parent19da38a330ad0e5ef567c074932a79ae09e897f2 (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.
-rw-r--r--src/mm-broadband-modem-qmi.c175
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;
}