diff options
-rw-r--r-- | src/mm-broadband-modem-qmi.c | 240 |
1 files changed, 133 insertions, 107 deletions
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c index bb8b20af..723be393 100644 --- a/src/mm-broadband-modem-qmi.c +++ b/src/mm-broadband-modem-qmi.c @@ -7053,14 +7053,18 @@ firmware_pair_free (FirmwarePair *pair) } typedef struct { - QmiClientDms *client; - GList *pairs; - GList *l; + QmiClientDms *client; + GList *pairs; + FirmwarePair *current_pair; + MMFirmwareProperties *current_firmware; + gboolean skip_image_info; } FirmwareListPreloadContext; static void firmware_list_preload_context_free (FirmwareListPreloadContext *ctx) { + g_clear_object (&ctx->current_firmware); + g_clear_pointer (&ctx->current_pair, (GDestroyNotify)firmware_pair_free); g_list_free_full (ctx->pairs, (GDestroyNotify)firmware_pair_free); g_object_unref (ctx->client); g_slice_free (FirmwareListPreloadContext, ctx); @@ -7074,150 +7078,173 @@ firmware_list_preload_finish (MMBroadbandModemQmi *self, return g_task_propagate_boolean (G_TASK (res), error); } +static void +store_preloaded_firmware_image_info (MMBroadbandModemQmi *self, + MMFirmwareProperties *firmware, + gboolean running) +{ + self->priv->firmware_list = g_list_append (self->priv->firmware_list, g_object_ref (firmware)); + + /* If this is is also the running image, keep an extra reference to it */ + if (running) { + if (self->priv->current_firmware) + mm_warn ("A running firmware is already set (%s), not setting '%s'", + mm_firmware_properties_get_unique_id (self->priv->current_firmware), + mm_firmware_properties_get_unique_id (firmware)); + else + self->priv->current_firmware = g_object_ref (firmware); + } +} + static void get_next_image_info (GTask *task); static void get_pri_image_info_ready (QmiClientDms *client, GAsyncResult *res, - GTask *task) + GTask *task) { - MMBroadbandModemQmi *self; - FirmwareListPreloadContext *ctx; + MMBroadbandModemQmi *self; + FirmwareListPreloadContext *ctx; QmiMessageDmsGetStoredImageInfoOutput *output; - GError *error = NULL; - FirmwarePair *current; + GError *error = NULL; self = g_task_get_source_object (task); - ctx = g_task_get_task_data (task); - current = (FirmwarePair *)ctx->l->data; + ctx = g_task_get_task_data (task); + + g_assert (ctx->current_pair); + g_assert (ctx->current_firmware); output = qmi_client_dms_get_stored_image_info_finish (client, res, &error); - if (!output || - !qmi_message_dms_get_stored_image_info_output_get_result (output, &error)) { - mm_warn ("Couldn't get detailed info for PRI image with build ID '%s': %s", - current->build_id, - error->message); + if (!output || !qmi_message_dms_get_stored_image_info_output_get_result (output, &error)) { + if (g_error_matches (error, QMI_PROTOCOL_ERROR, QMI_PROTOCOL_ERROR_INVALID_QMI_COMMAND)) + ctx->skip_image_info = TRUE; + else + mm_dbg ("couldn't get detailed info for PRI image with build ID '%s': %s", + ctx->current_pair->build_id, error->message); g_error_free (error); - } else { - gchar *unique_id_str; - MMFirmwareProperties *firmware; - - firmware = mm_firmware_properties_new (MM_FIRMWARE_IMAGE_TYPE_GOBI, - current->build_id); - - unique_id_str = mm_utils_bin2hexstr ((const guint8 *)current->pri_unique_id->data, - current->pri_unique_id->len); - mm_firmware_properties_set_gobi_pri_unique_id (firmware, unique_id_str); - g_free (unique_id_str); - - unique_id_str = mm_utils_bin2hexstr ((const guint8 *)current->modem_unique_id->data, - current->modem_unique_id->len); - mm_firmware_properties_set_gobi_modem_unique_id (firmware, unique_id_str); - g_free (unique_id_str); - - /* Boot version (optional) */ - { - guint16 boot_major_version; - guint16 boot_minor_version; - - if (qmi_message_dms_get_stored_image_info_output_get_boot_version ( - output, - &boot_major_version, - &boot_minor_version, - NULL)) { - gchar *aux; - - aux = g_strdup_printf ("%u.%u", boot_major_version, boot_minor_version); - mm_firmware_properties_set_gobi_boot_version (firmware, aux); - g_free (aux); - } - } - - /* PRI version (optional) */ - { - guint32 pri_version; - const gchar *pri_info; + goto out; + } - if (qmi_message_dms_get_stored_image_info_output_get_pri_version ( - output, - &pri_version, - &pri_info, - NULL)) { - gchar *aux; + /* Boot version (optional) */ + { + guint16 boot_major_version; + guint16 boot_minor_version; - aux = g_strdup_printf ("%u", pri_version); - mm_firmware_properties_set_gobi_pri_version (firmware, aux); - g_free (aux); + if (qmi_message_dms_get_stored_image_info_output_get_boot_version ( + output, + &boot_major_version, + &boot_minor_version, + NULL)) { + gchar *aux; - mm_firmware_properties_set_gobi_pri_info (firmware, pri_info); - } + aux = g_strdup_printf ("%u.%u", boot_major_version, boot_minor_version); + mm_firmware_properties_set_gobi_boot_version (ctx->current_firmware, aux); + g_free (aux); } + } - /* Add firmware image to our internal list */ - self->priv->firmware_list = g_list_append (self->priv->firmware_list, - firmware); + /* PRI version (optional) */ + { + guint32 pri_version; + const gchar *pri_info; - /* If this is is also the current image running, keep it */ - if (current->current) { - if (self->priv->current_firmware) - mm_warn ("A current firmware is already set (%s), not setting '%s' as current", - mm_firmware_properties_get_unique_id (self->priv->current_firmware), - current->build_id); - else - self->priv->current_firmware = g_object_ref (firmware); + if (qmi_message_dms_get_stored_image_info_output_get_pri_version ( + output, + &pri_version, + &pri_info, + NULL)) { + gchar *aux; + + aux = g_strdup_printf ("%u", pri_version); + mm_firmware_properties_set_gobi_pri_version (ctx->current_firmware, aux); + g_free (aux); + mm_firmware_properties_set_gobi_pri_info (ctx->current_firmware, pri_info); } } - if (output) - qmi_message_dms_get_stored_image_info_output_unref (output); +out: + + /* We're done with this image */ + store_preloaded_firmware_image_info (self, ctx->current_firmware, ctx->current_pair->current); + g_clear_object (&ctx->current_firmware); + g_clear_pointer (&ctx->current_pair, (GDestroyNotify)firmware_pair_free); /* Go on to the next one */ - ctx->l = g_list_next (ctx->l); get_next_image_info (task); + + if (output) + qmi_message_dms_get_stored_image_info_output_unref (output); +} + +static MMFirmwareProperties * +create_firmware_properties_from_pair (FirmwarePair *pair) +{ + gchar *unique_id_str; + MMFirmwareProperties *firmware; + + firmware = mm_firmware_properties_new (MM_FIRMWARE_IMAGE_TYPE_GOBI, pair->build_id); + + unique_id_str = mm_utils_bin2hexstr ((const guint8 *)pair->pri_unique_id->data, pair->pri_unique_id->len); + mm_firmware_properties_set_gobi_pri_unique_id (firmware, unique_id_str); + g_free (unique_id_str); + + unique_id_str = mm_utils_bin2hexstr ((const guint8 *)pair->modem_unique_id->data, pair->modem_unique_id->len); + mm_firmware_properties_set_gobi_modem_unique_id (firmware, unique_id_str); + g_free (unique_id_str); + + return firmware; } static void get_next_image_info (GTask *task) { - MMBroadbandModemQmi *self; + MMBroadbandModemQmi *self; FirmwareListPreloadContext *ctx; - QmiMessageDmsGetStoredImageInfoInputImage image_id; - QmiMessageDmsGetStoredImageInfoInput *input; - FirmwarePair *current; self = g_task_get_source_object (task); ctx = g_task_get_task_data (task); - if (!ctx->l) { - /* We're done */ + if (!ctx->pairs) { + g_task_return_boolean (task, TRUE); + g_object_unref (task); + return; + } - if (!self->priv->firmware_list) { - mm_warn ("No valid firmware images listed. " - "Assuming firmware unsupported."); - g_task_return_boolean (task, FALSE); - } else - g_task_return_boolean (task, TRUE); + /* Take next pair to process from list head */ + ctx->current_pair = (FirmwarePair *)ctx->pairs->data; + ctx->pairs = g_list_delete_link (ctx->pairs, ctx->pairs); - g_object_unref (task); + /* Build firmware properties */ + ctx->current_firmware = create_firmware_properties_from_pair (ctx->current_pair); + + /* Now, load additional optional information for the PRI image */ + if (!ctx->skip_image_info) { + QmiMessageDmsGetStoredImageInfoInputImage image_id; + QmiMessageDmsGetStoredImageInfoInput *input; + + image_id.type = QMI_DMS_FIRMWARE_IMAGE_TYPE_PRI; + image_id.unique_id = ctx->current_pair->pri_unique_id; + image_id.build_id = ctx->current_pair->build_id; + input = qmi_message_dms_get_stored_image_info_input_new (); + qmi_message_dms_get_stored_image_info_input_set_image (input, &image_id, NULL); + qmi_client_dms_get_stored_image_info (ctx->client, + input, + 10, + NULL, + (GAsyncReadyCallback)get_pri_image_info_ready, + task); + qmi_message_dms_get_stored_image_info_input_unref (input); return; } - current = (FirmwarePair *)ctx->l->data; + /* If we shouldn't be loading additional image info, we're done with this image */ + store_preloaded_firmware_image_info (self, ctx->current_firmware, ctx->current_pair->current); + g_clear_object (&ctx->current_firmware); + g_clear_pointer (&ctx->current_pair, (GDestroyNotify)firmware_pair_free); - /* Query PRI image info */ - image_id.type = QMI_DMS_FIRMWARE_IMAGE_TYPE_PRI; - image_id.unique_id = current->pri_unique_id; - image_id.build_id = current->build_id; - input = qmi_message_dms_get_stored_image_info_input_new (); - qmi_message_dms_get_stored_image_info_input_set_image (input, &image_id, NULL); - qmi_client_dms_get_stored_image_info (ctx->client, - input, - 10, - NULL, - (GAsyncReadyCallback)get_pri_image_info_ready, - task); - qmi_message_dms_get_stored_image_info_input_unref (input); + /* Go on to the next one */ + get_next_image_info (task); } static gboolean @@ -7387,7 +7414,6 @@ list_stored_images_ready (QmiClientDms *client, } /* Now keep on loading info for each image and cache it */ - ctx->l = ctx->pairs; get_next_image_info (task); out: |