aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/novatel/mm-broadband-modem-novatel.c286
1 files changed, 145 insertions, 141 deletions
diff --git a/plugins/novatel/mm-broadband-modem-novatel.c b/plugins/novatel/mm-broadband-modem-novatel.c
index 9fd14e2b..f752849d 100644
--- a/plugins/novatel/mm-broadband-modem-novatel.c
+++ b/plugins/novatel/mm-broadband-modem-novatel.c
@@ -397,107 +397,84 @@ set_current_modes (MMIfaceModem *self,
}
/*****************************************************************************/
-/* Load access technologies (Modem interface) */
-
-typedef struct {
- guint hdr_revision; /* QCDM_HDR_REV_x */
- MMModemAccessTechnology generic_act;
- guint mask;
-} SnapshotResult;
-
-typedef struct {
- MMBaseModem *self;
- MMPortSerialQcdm *port;
- GSimpleAsyncResult *simple;
- MMModemAccessTechnology generic_act;
- guint mask;
-} SnapshotContext;
static void
-snapshot_result_complete (GSimpleAsyncResult *simple,
- guint hdr_revision,
- MMModemAccessTechnology generic_act,
- guint mask)
+close_and_unref_port (MMPortSerialQcdm *port)
{
- SnapshotResult *r;
-
- r = g_new0 (SnapshotResult, 1);
- r->hdr_revision = hdr_revision;
- r->generic_act = generic_act;
- r->mask = mask;
-
- g_simple_async_result_set_op_res_gpointer (simple, r, g_free);
- g_simple_async_result_complete (simple);
+ mm_port_serial_close (MM_PORT_SERIAL (port));
+ g_object_unref (port);
}
-static void
-snapshot_result_complete_simple (GSimpleAsyncResult *simple,
- MMModemAccessTechnology generic_act,
- guint mask)
+static gboolean
+get_evdo_version_finish (MMBaseModem *self,
+ GAsyncResult *res,
+ guint *hdr_revision, /* QCDM_HDR_REV_* */
+ GError **error)
{
- snapshot_result_complete (simple, QCDM_HDR_REV_UNKNOWN, generic_act, mask);
-}
+ gssize result;
-static void
-snapshot_context_complete_and_free (SnapshotContext *ctx, guint hdr_revision)
-{
- snapshot_result_complete (ctx->simple,
- hdr_revision,
- ctx->generic_act,
- ctx->mask);
- g_object_unref (ctx->simple);
- g_object_unref (ctx->self);
- g_object_unref (ctx->port);
- g_free (ctx);
+ result = g_task_propagate_int (G_TASK (res), error);
+ if (result < 0)
+ return FALSE;
+
+ *hdr_revision = (guint8) result;
+ return TRUE;
}
static void
-nw_snapshot_old_cb (MMPortSerialQcdm *port,
- GAsyncResult *res,
- SnapshotContext *ctx)
+nw_snapshot_old_ready (MMPortSerialQcdm *port,
+ GAsyncResult *res,
+ GTask *task)
{
QcdmResult *result;
- guint8 hdr_revision = QCDM_HDR_REV_UNKNOWN;
GError *error = NULL;
GByteArray *response;
+ guint8 hdr_revision = QCDM_HDR_REV_UNKNOWN;
response = mm_port_serial_qcdm_command_finish (port, res, &error);
if (error) {
/* Just ignore the error and complete with the input info */
mm_dbg ("Couldn't run QCDM Novatel Modem MSM6500 snapshot: '%s'", error->message);
- g_error_free (error);
- snapshot_context_complete_and_free (ctx, QCDM_HDR_REV_UNKNOWN);
+ g_task_return_error (task, error);
+ g_object_unref (task);
return;
}
/* Parse the response */
result = qcdm_cmd_nw_subsys_modem_snapshot_cdma_result ((const gchar *) response->data, response->len, NULL);
g_byte_array_unref (response);
- if (result) {
- qcdm_result_get_u8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_HDR_REV, &hdr_revision);
+ if (!result) {
qcdm_result_unref (result);
- } else
- mm_dbg ("Failed to get QCDM Novatel Modem MSM6500 snapshot.");
+ mm_dbg ("Failed to get QCDM Novatel Modem MSM6500 snapshot: %s", error->message);
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ /* Success */
+ qcdm_result_get_u8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_HDR_REV, &hdr_revision);
+ qcdm_result_unref (result);
- snapshot_context_complete_and_free (ctx, hdr_revision);
+ g_task_return_int (task, (gint) hdr_revision);
+ g_object_unref (task);
}
static void
-nw_snapshot_new_cb (MMPortSerialQcdm *port,
- GAsyncResult *res,
- SnapshotContext *ctx)
+nw_snapshot_new_ready (MMPortSerialQcdm *port,
+ GAsyncResult *res,
+ GTask *task)
{
QcdmResult *result;
GByteArray *nwsnap;
- guint8 hdr_revision = QCDM_HDR_REV_UNKNOWN;
GError *error = NULL;
GByteArray *response;
+ guint8 hdr_revision = QCDM_HDR_REV_UNKNOWN;
response = mm_port_serial_qcdm_command_finish (port, res, &error);
if (error) {
mm_dbg ("Couldn't run QCDM Novatel Modem MSM6800 snapshot: '%s'", error->message);
- g_error_free (error);
- snapshot_context_complete_and_free (ctx, QCDM_HDR_REV_UNKNOWN);
+ g_task_return_error (task, error);
+ g_object_unref (task);
return;
}
@@ -505,9 +482,12 @@ nw_snapshot_new_cb (MMPortSerialQcdm *port,
result = qcdm_cmd_nw_subsys_modem_snapshot_cdma_result ((const gchar *) response->data, response->len, NULL);
g_byte_array_unref (response);
if (result) {
+ /* Success */
qcdm_result_get_u8 (result, QCDM_CMD_NW_SUBSYS_MODEM_SNAPSHOT_CDMA_ITEM_HDR_REV, &hdr_revision);
qcdm_result_unref (result);
- snapshot_context_complete_and_free (ctx, hdr_revision);
+
+ g_task_return_int (task, (gint) hdr_revision);
+ g_object_unref (task);
return;
}
@@ -521,32 +501,40 @@ nw_snapshot_new_cb (MMPortSerialQcdm *port,
nwsnap,
3,
NULL,
- (GAsyncReadyCallback)nw_snapshot_old_cb,
- ctx);
+ (GAsyncReadyCallback)nw_snapshot_old_ready,
+ task);
g_byte_array_unref (nwsnap);
}
-static gboolean
-get_nw_modem_snapshot (MMBaseModem *self,
- GSimpleAsyncResult *simple,
- MMModemAccessTechnology generic_act,
- guint mask)
+static void
+get_evdo_version (MMBaseModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- SnapshotContext *ctx;
+ GError *error = NULL;
GByteArray *nwsnap;
+ GTask *task;
MMPortSerialQcdm *port;
- port = mm_base_modem_peek_port_qcdm (self);
- if (!port)
- return FALSE;
+ task = g_task_new (self, NULL, callback, user_data);
- /* Setup context */
- ctx = g_new0 (SnapshotContext, 1);
- ctx->self = g_object_ref (self);
- ctx->port = g_object_ref (port);
- ctx->simple = simple;
- ctx->generic_act = generic_act;
- ctx->mask = mask;
+ port = mm_base_modem_get_port_qcdm (self);
+ if (!port) {
+ error = g_error_new (MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "No available QCDM port.");
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+ g_task_set_task_data (task, port, (GDestroyNotify) close_and_unref_port);
+
+ if (!mm_port_serial_open (MM_PORT_SERIAL (port), &error)) {
+ g_prefix_error (&error, "Couldn't open QCDM port: ");
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
/* Try MSM6800 first since newer cards use that */
nwsnap = g_byte_array_sized_new (25);
@@ -556,12 +544,20 @@ get_nw_modem_snapshot (MMBaseModem *self,
nwsnap,
3,
NULL,
- (GAsyncReadyCallback)nw_snapshot_new_cb,
- ctx);
+ (GAsyncReadyCallback)nw_snapshot_new_ready,
+ task);
g_byte_array_unref (nwsnap);
- return TRUE;
}
+/*****************************************************************************/
+/* Load access technologies (Modem interface) */
+
+typedef struct {
+ MMModemAccessTechnology act;
+ guint mask;
+ guint hdr_revision; /* QCDM_HDR_REV_* */
+} AccessTechContext;
+
static gboolean
modem_load_access_technologies_finish (MMIfaceModem *self,
GAsyncResult *res,
@@ -569,48 +565,45 @@ modem_load_access_technologies_finish (MMIfaceModem *self,
guint *mask,
GError **error)
{
- SnapshotResult *r;
- MMModemAccessTechnology act;
+ GTask *task = G_TASK (res);
+ AccessTechContext *ctx = g_task_get_task_data (task);
- if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+ if (!g_task_propagate_boolean (task, error))
return FALSE;
- r = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res));
-
- act = r->generic_act;
- if (act & MM_IFACE_MODEM_CDMA_ALL_EVDO_ACCESS_TECHNOLOGIES_MASK) {
- /* Update access technology with specific EVDO revision from QCDM */
- if (r->hdr_revision == QCDM_HDR_REV_0) {
+ /* Update access technology with specific EVDO revision from QCDM if we have them */
+ if (ctx->act & MM_IFACE_MODEM_CDMA_ALL_EVDO_ACCESS_TECHNOLOGIES_MASK) {
+ if (ctx->hdr_revision == QCDM_HDR_REV_0) {
mm_dbg ("Novatel Modem Snapshot EVDO revision: 0");
- act &= ~MM_IFACE_MODEM_CDMA_ALL_EVDO_ACCESS_TECHNOLOGIES_MASK;
- act |= MM_MODEM_ACCESS_TECHNOLOGY_EVDO0;
- } else if (r->hdr_revision == QCDM_HDR_REV_A) {
+ ctx->act &= ~MM_IFACE_MODEM_CDMA_ALL_EVDO_ACCESS_TECHNOLOGIES_MASK;
+ ctx->act |= MM_MODEM_ACCESS_TECHNOLOGY_EVDO0;
+ } else if (ctx->hdr_revision == QCDM_HDR_REV_A) {
mm_dbg ("Novatel Modem Snapshot EVDO revision: A");
- act &= ~MM_IFACE_MODEM_CDMA_ALL_EVDO_ACCESS_TECHNOLOGIES_MASK;
- act |= MM_MODEM_ACCESS_TECHNOLOGY_EVDOA;
+ ctx->act &= ~MM_IFACE_MODEM_CDMA_ALL_EVDO_ACCESS_TECHNOLOGIES_MASK;
+ ctx->act |= MM_MODEM_ACCESS_TECHNOLOGY_EVDOA;
} else
- mm_dbg ("Novatel Modem Snapshot EVDO revision: %d (unknown)", r->hdr_revision);
+ mm_dbg ("Novatel Modem Snapshot EVDO revision: %d (unknown)", ctx->hdr_revision);
}
- *access_technologies = act;
- *mask = r->mask;
+ *access_technologies = ctx->act;
+ *mask = ctx->mask;
return TRUE;
}
static void
cnti_set_ready (MMBaseModem *self,
GAsyncResult *res,
- GSimpleAsyncResult *simple)
+ GTask *task)
{
+ AccessTechContext *ctx = g_task_get_task_data (task);
GError *error = NULL;
const gchar *response;
const gchar *p;
response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
if (!response) {
- g_simple_async_result_take_error (simple, error);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
+ g_task_return_error (task, error);
+ g_object_unref (task);
return;
}
@@ -621,55 +614,64 @@ cnti_set_ready (MMBaseModem *self,
MM_CORE_ERROR_FAILED,
"Couldn't parse $CNTI result '%s'",
response);
- g_simple_async_result_take_error (simple, error);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
+ g_task_return_error (task, error);
+ g_object_unref (task);
return;
}
- snapshot_result_complete_simple (simple,
- mm_string_to_access_tech (p),
- MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK);
- g_object_unref (simple);
+ ctx->act = mm_string_to_access_tech (p);
+ ctx->mask = MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK;
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+}
+
+static void
+evdo_version_ready (MMBaseModem *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ GError *error = NULL;
+ AccessTechContext *ctx = g_task_get_task_data (task);
+
+ if (!get_evdo_version_finish (self, res, &ctx->hdr_revision, &error)) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
}
static void
parent_load_access_technologies_ready (MMIfaceModem *self,
GAsyncResult *res,
- GSimpleAsyncResult *simple)
+ GTask *task)
{
- MMModemAccessTechnology act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN;
- guint mask = 0;
GError *error = NULL;
+ AccessTechContext *ctx = g_task_get_task_data (task);
if (!iface_modem_parent->load_access_technologies_finish (self,
res,
- &act,
- &mask,
+ &ctx->act,
+ &ctx->mask,
&error)) {
- g_simple_async_result_take_error (simple, error);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
+ g_task_return_error (task, error);
+ g_object_unref (task);
return;
}
- /* No point in checking EVDO revision if EVDO isn't being used or if for
- * some reason we don't have a QCDM port.
- */
- if (!(act & MM_IFACE_MODEM_CDMA_ALL_EVDO_ACCESS_TECHNOLOGIES_MASK)) {
- snapshot_result_complete (simple, QCDM_HDR_REV_UNKNOWN, act, mask);
- g_object_unref (simple);
+ /* No point in checking EVDO revision if EVDO isn't being used */
+ if (!(ctx->act & MM_IFACE_MODEM_CDMA_ALL_EVDO_ACCESS_TECHNOLOGIES_MASK)) {
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
return;
}
- /* Pass along the access tech & mask that the parent determined so we
- * can specialize it based on the EVDO revision from QCDM.
- */
- if (!get_nw_modem_snapshot (MM_BASE_MODEM (self), simple, act, mask)) {
- /* If there's any error, use the access tech that the parent interface determined */
- snapshot_result_complete (simple, QCDM_HDR_REV_UNKNOWN, act, mask);
- g_object_unref (simple);
- }
+ /* Get the EVDO revision from QCDM */
+ get_evdo_version (MM_BASE_MODEM (self),
+ (GAsyncReadyCallback) evdo_version_ready,
+ task);
}
static void
@@ -677,12 +679,14 @@ modem_load_access_technologies (MMIfaceModem *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
- GSimpleAsyncResult *result;
+ AccessTechContext *ctx;
+ GTask *task;
- result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- modem_load_access_technologies);
+ /* Setup context */
+ task = g_task_new (self, NULL, callback, user_data);
+
+ ctx = g_new0 (AccessTechContext, 1);
+ g_task_set_task_data (task, ctx, g_free);
/* CDMA-only modems defer to parent for generic access technology
* checking, but can determine EVDOr0 vs. EVDOrA through proprietary
@@ -692,7 +696,7 @@ modem_load_access_technologies (MMIfaceModem *self,
iface_modem_parent->load_access_technologies (
self,
(GAsyncReadyCallback)parent_load_access_technologies_ready,
- result);
+ task);
return;
}
@@ -702,7 +706,7 @@ modem_load_access_technologies (MMIfaceModem *self,
3,
FALSE,
(GAsyncReadyCallback)cnti_set_ready,
- result);
+ task);
}
/*****************************************************************************/