summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2012-09-25 13:37:52 +0200
committerAleksander Morgado <aleksander@lanedo.com>2012-09-26 10:19:53 +0200
commitf8dc62149e6d33ee8a30b2ebc01d31ff2d7c0cc8 (patch)
treed7d89e361488d7ef6b686e3fbd9b2ac5b3d65513
parentd2b7ea2eeade7b34654a0e44fde16f8bbb46a790 (diff)
cli: new `--dms-delete-stored-image' action
Can be run e.g. like: $> sudo qmicli -d /dev/cdc-wdm0 --dms-delete-stored-image="pri2" The passed index is the one given by a previous `--dms-list-stored-images' action. Please note that if you delete a given image, the listed indexes will change, so if you want to delete multiple images you'll need to first list stored images and grab the index and then use that bew index to delete the new image. Also, don't try this command many times or you'll run out of images to delete!
-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__ */