diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2012-09-25 13:37:52 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2012-09-26 10:19:53 +0200 |
commit | f8dc62149e6d33ee8a30b2ebc01d31ff2d7c0cc8 (patch) | |
tree | d7d89e361488d7ef6b686e3fbd9b2ac5b3d65513 | |
parent | d2b7ea2eeade7b34654a0e44fde16f8bbb46a790 (diff) | |
download | external_libqmi-f8dc62149e6d33ee8a30b2ebc01d31ff2d7c0cc8.zip external_libqmi-f8dc62149e6d33ee8a30b2ebc01d31ff2d7c0cc8.tar.gz external_libqmi-f8dc62149e6d33ee8a30b2ebc01d31ff2d7c0cc8.tar.bz2 |
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.c | 228 | ||||
-rw-r--r-- | cli/qmicli-helpers.c | 46 | ||||
-rw-r--r-- | cli/qmicli-helpers.h | 5 |
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__ */ |