aboutsummaryrefslogtreecommitdiff
path: root/src
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 /src
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.
Diffstat (limited to 'src')
-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;
}