summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/qmicli-dms.c228
-rw-r--r--cli/qmicli-helpers.c46
-rw-r--r--cli/qmicli-helpers.h5
3 files changed, 279 insertions, 0 deletions
diff --git a/cli/qmicli-dms.c b/cli/qmicli-dms.c
index d5b21ce..b469c92 100644
--- a/cli/qmicli-dms.c
+++ b/cli/qmicli-dms.c
@@ -78,6 +78,7 @@ static gchar *validate_service_programming_code_str;
static gboolean get_band_capabilities_flag;
static gboolean get_factory_sku_flag;
static gboolean list_stored_images_flag;
+static gchar *delete_stored_image_str;
static gboolean reset_flag;
static gboolean noop_flag;
@@ -226,6 +227,10 @@ static GOptionEntry entries[] = {
"List stored images",
NULL
},
+ { "dms-delete-stored-image", 0, 0, G_OPTION_ARG_STRING, &delete_stored_image_str,
+ "Delete stored image",
+ "[modem#|pri#] where # is the index"
+ },
{ "dms-reset", 0, 0, G_OPTION_ARG_NONE, &reset_flag,
"Reset the service state",
NULL
@@ -297,6 +302,7 @@ qmicli_dms_options_enabled (void)
get_band_capabilities_flag +
get_factory_sku_flag +
list_stored_images_flag +
+ !!delete_stored_image_str +
reset_flag +
noop_flag);
@@ -2467,6 +2473,218 @@ list_stored_images_ready (QmiClientDms *client,
get_image_info (operation_ctx);
}
+typedef struct {
+ QmiClientDms *client;
+ GSimpleAsyncResult *result;
+ QmiDmsFirmwareImageType type;
+ guint index;
+} GetStoredImageContext;
+
+typedef struct {
+ QmiDmsFirmwareImageType type;
+ GArray *unique_id;
+ gchar *build_id;
+} GetStoredImageResult;
+
+static void
+get_stored_image_context_complete_and_free (GetStoredImageContext *operation_ctx)
+{
+ g_simple_async_result_complete (operation_ctx->result);
+ g_object_unref (operation_ctx->result);
+ g_object_unref (operation_ctx->client);
+ g_slice_free (GetStoredImageContext, operation_ctx);
+}
+
+static void
+get_stored_image_finish (QmiClientDms *client,
+ GAsyncResult *res,
+ QmiDmsFirmwareImageType *type,
+ GArray **unique_id,
+ gchar **build_id)
+{
+ GetStoredImageResult *result;
+
+ result = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res));
+
+ *type = result->type;
+ *unique_id = g_array_ref (result->unique_id);
+ *build_id = g_strdup (result->build_id);
+}
+
+static void
+get_stored_image_list_stored_images_ready (QmiClientDms *client,
+ GAsyncResult *res,
+ GetStoredImageContext *operation_ctx)
+{
+ GArray *array;
+ QmiMessageDmsListStoredImagesOutput *output;
+ GError *error = NULL;
+ guint i;
+
+ output = qmi_client_dms_list_stored_images_finish (client, res, &error);
+ if (!output) {
+ g_printerr ("error: operation failed: %s\n", error->message);
+ g_error_free (error);
+ shutdown (FALSE);
+ return;
+ }
+
+ if (!qmi_message_dms_list_stored_images_output_get_result (output, &error)) {
+ g_printerr ("error: couldn't list stored images: %s\n", error->message);
+ g_error_free (error);
+ qmi_message_dms_list_stored_images_output_unref (output);
+ shutdown (FALSE);
+ return;
+ }
+
+ qmi_message_dms_list_stored_images_output_get_list (
+ output,
+ &array,
+ NULL);
+
+ for (i = 0; i < array->len; i++) {
+ QmiMessageDmsListStoredImagesOutputListImageSublistSublistElement *subimage;
+ QmiMessageDmsListStoredImagesOutputListImage *image;
+ GetStoredImageResult result;
+ gchar *unique_id_str;
+
+ image = &g_array_index (array,
+ QmiMessageDmsListStoredImagesOutputListImage,
+ i);
+
+ if (image->type != operation_ctx->type)
+ continue;
+
+ if (operation_ctx->index >= image->sublist->len) {
+ g_printerr ("error: couldn't find '%s' image at index '%u'",
+ qmi_dms_firmware_image_type_get_string (image->type),
+ operation_ctx->index);
+ qmi_message_dms_list_stored_images_output_unref (output);
+ shutdown (FALSE);
+ return;
+ }
+
+ subimage = &g_array_index (image->sublist,
+ QmiMessageDmsListStoredImagesOutputListImageSublistSublistElement,
+ operation_ctx->index);
+
+ unique_id_str = qmicli_get_raw_data_printable (subimage->unique_id, 80, "");
+ unique_id_str[strlen(unique_id_str) - 1] = '\0';
+ g_debug ("Found [%s,%u]: Unique ID: '%s', Build ID: '%s'",
+ qmi_dms_firmware_image_type_get_string (operation_ctx->type),
+ operation_ctx->index,
+ unique_id_str,
+ subimage->build_id);
+ g_free (unique_id_str);
+
+ /* Build result and complete */
+ result.type = operation_ctx->type;
+ result.unique_id = subimage->unique_id;
+ result.build_id = subimage->build_id;
+ g_simple_async_result_set_op_res_gpointer (operation_ctx->result, &result, NULL);
+ get_stored_image_context_complete_and_free (operation_ctx);
+ qmi_message_dms_list_stored_images_output_unref (output);
+ return;
+ }
+
+ g_printerr ("error: couldn't find any image of type '%s'",
+ qmi_dms_firmware_image_type_get_string (operation_ctx->type));
+ qmi_message_dms_list_stored_images_output_unref (output);
+ shutdown (FALSE);
+}
+
+static void
+get_stored_image (QmiClientDms *client,
+ const gchar *str,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GetStoredImageContext *operation_ctx;
+ QmiDmsFirmwareImageType type;
+ guint index;
+
+ if (!qmicli_read_firmware_id_from_string (str, &type, &index)) {
+ g_printerr ("Couldn't parse input string as firmware index info: '%s'\n", str);
+ shutdown (FALSE);
+ return;
+ }
+
+ operation_ctx = g_slice_new (GetStoredImageContext);
+ operation_ctx->client = g_object_ref (client);
+ operation_ctx->result = g_simple_async_result_new (G_OBJECT (client),
+ callback,
+ user_data,
+ get_stored_image);
+ operation_ctx->type = type;
+ operation_ctx->index = index;
+
+ qmi_client_dms_list_stored_images (
+ ctx->client,
+ NULL,
+ 10,
+ ctx->cancellable,
+ (GAsyncReadyCallback)get_stored_image_list_stored_images_ready,
+ operation_ctx);
+}
+
+static void
+delete_stored_image_ready (QmiClientDms *client,
+ GAsyncResult *res)
+{
+ QmiMessageDmsDeleteStoredImageOutput *output;
+ GError *error = NULL;
+
+ output = qmi_client_dms_delete_stored_image_finish (client, res, &error);
+ if (!output) {
+ g_printerr ("error: operation failed: %s\n", error->message);
+ g_error_free (error);
+ shutdown (FALSE);
+ return;
+ }
+
+ if (!qmi_message_dms_delete_stored_image_output_get_result (output, &error)) {
+ g_printerr ("error: couldn't delete stored image: %s\n", error->message);
+ g_error_free (error);
+ qmi_message_dms_delete_stored_image_output_unref (output);
+ shutdown (FALSE);
+ return;
+ }
+
+ g_print ("[%s] Stored image successfully deleted\n",
+ qmi_device_get_path_display (ctx->device));
+ qmi_message_dms_delete_stored_image_output_unref (output);
+ shutdown (TRUE);
+}
+
+static void
+get_stored_image_delete_ready (QmiClientDms *client,
+ GAsyncResult *res)
+{
+ QmiMessageDmsDeleteStoredImageInput *input;
+ QmiMessageDmsDeleteStoredImageInputImage image_id;
+
+ get_stored_image_finish (client,
+ res,
+ &image_id.type,
+ &image_id.unique_id,
+ &image_id.build_id);
+
+ input = qmi_message_dms_delete_stored_image_input_new ();
+ qmi_message_dms_delete_stored_image_input_set_image (input, &image_id, NULL);
+
+ qmi_client_dms_delete_stored_image (
+ client,
+ input,
+ 10,
+ NULL,
+ (GAsyncReadyCallback)delete_stored_image_ready,
+ NULL);
+ qmi_message_dms_delete_stored_image_input_unref (input);
+
+ g_free (image_id.build_id);
+ g_array_unref (image_id.unique_id);
+}
+
static void
reset_ready (QmiClientDms *client,
GAsyncResult *res)
@@ -3060,6 +3278,16 @@ qmicli_dms_run (QmiDevice *device,
return;
}
+ /* Request to delete stored image? */
+ if (delete_stored_image_str) {
+ g_debug ("Asynchronously deleting stored image...");
+ get_stored_image (ctx->client,
+ delete_stored_image_str,
+ (GAsyncReadyCallback)get_stored_image_delete_ready,
+ NULL);
+ return;
+ }
+
/* Request to reset DMS service? */
if (reset_flag) {
g_debug ("Asynchronously resetting DMS service...");
diff --git a/cli/qmicli-helpers.c b/cli/qmicli-helpers.c
index fb58631..f041126 100644
--- a/cli/qmicli-helpers.c
+++ b/cli/qmicli-helpers.c
@@ -19,7 +19,9 @@
*/
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <errno.h>
#include "qmicli-helpers.h"
@@ -202,3 +204,47 @@ qmicli_read_non_empty_string (const gchar *str,
*out = (gchar *)str;
return TRUE;
}
+
+gboolean
+qmicli_read_firmware_id_from_string (const gchar *str,
+ QmiDmsFirmwareImageType *out_type,
+ guint *out_index)
+{
+ const gchar *index_str;
+
+ if (g_str_has_prefix (str, "modem")) {
+ *out_type = QMI_DMS_FIRMWARE_IMAGE_TYPE_MODEM;
+ index_str = &str[5];
+ } else if (g_str_has_prefix (str, "pri")) {
+ *out_type = QMI_DMS_FIRMWARE_IMAGE_TYPE_PRI;
+ index_str = &str[3];
+ } else {
+ g_printerr ("error: invalid firmware image type value given: '%s'\n", str);
+ return FALSE;
+ }
+
+ return qmicli_read_uint_from_string (index_str, out_index);
+}
+
+gboolean
+qmicli_read_uint_from_string (const gchar *str,
+ guint *out)
+{
+ gulong num;
+
+ if (!str || !str[0])
+ return FALSE;
+
+ for (num = 0; str[num]; num++) {
+ if (!g_ascii_isdigit (str[num]))
+ return FALSE;
+ }
+
+ errno = 0;
+ num = strtoul (str, NULL, 10);
+ if (!errno && num <= G_MAXUINT) {
+ *out = (guint)num;
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/cli/qmicli-helpers.h b/cli/qmicli-helpers.h
index 6f9be9b..30a089a 100644
--- a/cli/qmicli-helpers.h
+++ b/cli/qmicli-helpers.h
@@ -37,8 +37,13 @@ gboolean qmicli_read_facility_from_string (const gchar *str,
QmiDmsUimFacility *out);
gboolean qmicli_read_enable_disable_from_string (const gchar *str,
gboolean *out);
+gboolean qmicli_read_firmware_id_from_string (const gchar *str,
+ QmiDmsFirmwareImageType *out_type,
+ guint *out_index);
gboolean qmicli_read_non_empty_string (const gchar *str,
const gchar *description,
gchar **out);
+gboolean qmicli_read_uint_from_string (const gchar *str,
+ guint *out);
#endif /* __QMICLI_H__ */