broadband-modem-qmi: fix listing images when 'Get Stored Image Info' is unsupported
This commit is contained in:
@@ -7053,14 +7053,18 @@ firmware_pair_free (FirmwarePair *pair)
|
|||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
QmiClientDms *client;
|
QmiClientDms *client;
|
||||||
GList *pairs;
|
GList *pairs;
|
||||||
GList *l;
|
FirmwarePair *current_pair;
|
||||||
|
MMFirmwareProperties *current_firmware;
|
||||||
|
gboolean skip_image_info;
|
||||||
} FirmwareListPreloadContext;
|
} FirmwareListPreloadContext;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
firmware_list_preload_context_free (FirmwareListPreloadContext *ctx)
|
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_list_free_full (ctx->pairs, (GDestroyNotify)firmware_pair_free);
|
||||||
g_object_unref (ctx->client);
|
g_object_unref (ctx->client);
|
||||||
g_slice_free (FirmwareListPreloadContext, ctx);
|
g_slice_free (FirmwareListPreloadContext, ctx);
|
||||||
@@ -7074,150 +7078,173 @@ firmware_list_preload_finish (MMBroadbandModemQmi *self,
|
|||||||
return g_task_propagate_boolean (G_TASK (res), error);
|
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_next_image_info (GTask *task);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
get_pri_image_info_ready (QmiClientDms *client,
|
get_pri_image_info_ready (QmiClientDms *client,
|
||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
GTask *task)
|
GTask *task)
|
||||||
{
|
{
|
||||||
MMBroadbandModemQmi *self;
|
MMBroadbandModemQmi *self;
|
||||||
FirmwareListPreloadContext *ctx;
|
FirmwareListPreloadContext *ctx;
|
||||||
QmiMessageDmsGetStoredImageInfoOutput *output;
|
QmiMessageDmsGetStoredImageInfoOutput *output;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
FirmwarePair *current;
|
|
||||||
|
|
||||||
self = g_task_get_source_object (task);
|
self = g_task_get_source_object (task);
|
||||||
ctx = g_task_get_task_data (task);
|
ctx = g_task_get_task_data (task);
|
||||||
current = (FirmwarePair *)ctx->l->data;
|
|
||||||
|
g_assert (ctx->current_pair);
|
||||||
|
g_assert (ctx->current_firmware);
|
||||||
|
|
||||||
output = qmi_client_dms_get_stored_image_info_finish (client, res, &error);
|
output = qmi_client_dms_get_stored_image_info_finish (client, res, &error);
|
||||||
if (!output ||
|
if (!output || !qmi_message_dms_get_stored_image_info_output_get_result (output, &error)) {
|
||||||
!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))
|
||||||
mm_warn ("Couldn't get detailed info for PRI image with build ID '%s': %s",
|
ctx->skip_image_info = TRUE;
|
||||||
current->build_id,
|
else
|
||||||
error->message);
|
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);
|
g_error_free (error);
|
||||||
} else {
|
goto out;
|
||||||
gchar *unique_id_str;
|
}
|
||||||
MMFirmwareProperties *firmware;
|
|
||||||
|
|
||||||
firmware = mm_firmware_properties_new (MM_FIRMWARE_IMAGE_TYPE_GOBI,
|
/* Boot version (optional) */
|
||||||
current->build_id);
|
{
|
||||||
|
guint16 boot_major_version;
|
||||||
|
guint16 boot_minor_version;
|
||||||
|
|
||||||
unique_id_str = mm_utils_bin2hexstr ((const guint8 *)current->pri_unique_id->data,
|
if (qmi_message_dms_get_stored_image_info_output_get_boot_version (
|
||||||
current->pri_unique_id->len);
|
output,
|
||||||
mm_firmware_properties_set_gobi_pri_unique_id (firmware, unique_id_str);
|
&boot_major_version,
|
||||||
g_free (unique_id_str);
|
&boot_minor_version,
|
||||||
|
NULL)) {
|
||||||
unique_id_str = mm_utils_bin2hexstr ((const guint8 *)current->modem_unique_id->data,
|
gchar *aux;
|
||||||
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;
|
|
||||||
|
|
||||||
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 (firmware, aux);
|
|
||||||
g_free (aux);
|
|
||||||
|
|
||||||
mm_firmware_properties_set_gobi_pri_info (firmware, pri_info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add firmware image to our internal list */
|
|
||||||
self->priv->firmware_list = g_list_append (self->priv->firmware_list,
|
|
||||||
firmware);
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output)
|
/* PRI version (optional) */
|
||||||
qmi_message_dms_get_stored_image_info_output_unref (output);
|
{
|
||||||
|
guint32 pri_version;
|
||||||
|
const gchar *pri_info;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 */
|
/* Go on to the next one */
|
||||||
ctx->l = g_list_next (ctx->l);
|
|
||||||
get_next_image_info (task);
|
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
|
static void
|
||||||
get_next_image_info (GTask *task)
|
get_next_image_info (GTask *task)
|
||||||
{
|
{
|
||||||
MMBroadbandModemQmi *self;
|
MMBroadbandModemQmi *self;
|
||||||
FirmwareListPreloadContext *ctx;
|
FirmwareListPreloadContext *ctx;
|
||||||
QmiMessageDmsGetStoredImageInfoInputImage image_id;
|
|
||||||
QmiMessageDmsGetStoredImageInfoInput *input;
|
|
||||||
FirmwarePair *current;
|
|
||||||
|
|
||||||
self = g_task_get_source_object (task);
|
self = g_task_get_source_object (task);
|
||||||
ctx = g_task_get_task_data (task);
|
ctx = g_task_get_task_data (task);
|
||||||
|
|
||||||
if (!ctx->l) {
|
if (!ctx->pairs) {
|
||||||
/* We're done */
|
g_task_return_boolean (task, TRUE);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
g_object_unref (task);
|
g_object_unref (task);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
current = (FirmwarePair *)ctx->l->data;
|
/* 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);
|
||||||
|
|
||||||
/* Query PRI image info */
|
/* Build firmware properties */
|
||||||
image_id.type = QMI_DMS_FIRMWARE_IMAGE_TYPE_PRI;
|
ctx->current_firmware = create_firmware_properties_from_pair (ctx->current_pair);
|
||||||
image_id.unique_id = current->pri_unique_id;
|
|
||||||
image_id.build_id = current->build_id;
|
/* Now, load additional optional information for the PRI image */
|
||||||
input = qmi_message_dms_get_stored_image_info_input_new ();
|
if (!ctx->skip_image_info) {
|
||||||
qmi_message_dms_get_stored_image_info_input_set_image (input, &image_id, NULL);
|
QmiMessageDmsGetStoredImageInfoInputImage image_id;
|
||||||
qmi_client_dms_get_stored_image_info (ctx->client,
|
QmiMessageDmsGetStoredImageInfoInput *input;
|
||||||
input,
|
|
||||||
10,
|
image_id.type = QMI_DMS_FIRMWARE_IMAGE_TYPE_PRI;
|
||||||
NULL,
|
image_id.unique_id = ctx->current_pair->pri_unique_id;
|
||||||
(GAsyncReadyCallback)get_pri_image_info_ready,
|
image_id.build_id = ctx->current_pair->build_id;
|
||||||
task);
|
input = qmi_message_dms_get_stored_image_info_input_new ();
|
||||||
qmi_message_dms_get_stored_image_info_input_unref (input);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
/* Go on to the next one */
|
||||||
|
get_next_image_info (task);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@@ -7387,7 +7414,6 @@ list_stored_images_ready (QmiClientDms *client,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Now keep on loading info for each image and cache it */
|
/* Now keep on loading info for each image and cache it */
|
||||||
ctx->l = ctx->pairs;
|
|
||||||
get_next_image_info (task);
|
get_next_image_info (task);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
Reference in New Issue
Block a user