libdfu: Handle cancellation with ctrl+c in dfu-tool

This commit is contained in:
Richard Hughes 2015-11-26 12:25:16 +00:00
parent ef617dbbc8
commit 60b7eeeca9
2 changed files with 196 additions and 57 deletions

View File

@ -223,6 +223,7 @@ dfu_device_finalize (GObject *object)
DfuDevicePrivate *priv = GET_PRIVATE (device); DfuDevicePrivate *priv = GET_PRIVATE (device);
/* don't rely on this */ /* don't rely on this */
if (priv->dev != NULL)
g_usb_device_close (priv->dev, NULL); g_usb_device_close (priv->dev, NULL);
g_free (priv->display_name); g_free (priv->display_name);

View File

@ -26,12 +26,14 @@
#include <locale.h> #include <locale.h>
#include <stdlib.h> #include <stdlib.h>
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include <glib-unix.h>
#include <appstream-glib.h> #include <appstream-glib.h>
#include "dfu-device-private.h" #include "dfu-device-private.h"
typedef struct { typedef struct {
DfuContext *dfu_context; DfuContext *dfu_context;
GCancellable *cancellable;
GPtrArray *cmd_array; GPtrArray *cmd_array;
gboolean force; gboolean force;
gboolean reset; gboolean reset;
@ -66,6 +68,7 @@ dfu_tool_private_free (DfuToolPrivate *priv)
if (priv->dfu_context != NULL) if (priv->dfu_context != NULL)
g_object_unref (priv->dfu_context); g_object_unref (priv->dfu_context);
g_free (priv->device_vid_pid); g_free (priv->device_vid_pid);
g_object_unref (priv->cancellable);
if (priv->cmd_array != NULL) if (priv->cmd_array != NULL)
g_ptr_array_unref (priv->cmd_array); g_ptr_array_unref (priv->cmd_array);
g_free (priv); g_free (priv);
@ -190,7 +193,10 @@ dfu_tool_get_descriptions (GPtrArray *array)
* dfu_tool_run: * dfu_tool_run:
**/ **/
static gboolean static gboolean
dfu_tool_run (DfuToolPrivate *priv, const gchar *command, gchar **values, GError **error) dfu_tool_run (DfuToolPrivate *priv,
const gchar *command,
gchar **values,
GError **error)
{ {
guint i; guint i;
FuUtilItem *item; FuUtilItem *item;
@ -283,7 +289,8 @@ dfu_tool_set_vendor (DfuToolPrivate *priv, gchar **values, GError **error)
firmware = dfu_firmware_new (); firmware = dfu_firmware_new ();
if (!dfu_firmware_parse_file (firmware, file, if (!dfu_firmware_parse_file (firmware, file,
DFU_FIRMWARE_PARSE_FLAG_NONE, DFU_FIRMWARE_PARSE_FLAG_NONE,
NULL, error)) { priv->cancellable,
error)) {
return FALSE; return FALSE;
} }
@ -293,13 +300,17 @@ dfu_tool_set_vendor (DfuToolPrivate *priv, gchar **values, GError **error)
g_set_error (error, g_set_error (error,
DFU_ERROR, DFU_ERROR,
DFU_ERROR_INTERNAL, DFU_ERROR_INTERNAL,
"Failed to parse VID '%s'", values[1]); "Failed to parse VID '%s'",
values[1]);
return FALSE; return FALSE;
} }
dfu_firmware_set_vid (firmware, tmp); dfu_firmware_set_vid (firmware, tmp);
/* write out new file */ /* write out new file */
return dfu_firmware_write_file (firmware, file, NULL, error); return dfu_firmware_write_file (firmware,
file,
priv->cancellable,
error);
} }
/** /**
@ -327,7 +338,8 @@ dfu_tool_set_product (DfuToolPrivate *priv, gchar **values, GError **error)
firmware = dfu_firmware_new (); firmware = dfu_firmware_new ();
if (!dfu_firmware_parse_file (firmware, file, if (!dfu_firmware_parse_file (firmware, file,
DFU_FIRMWARE_PARSE_FLAG_NONE, DFU_FIRMWARE_PARSE_FLAG_NONE,
NULL, error)) { priv->cancellable,
error)) {
return FALSE; return FALSE;
} }
@ -343,7 +355,10 @@ dfu_tool_set_product (DfuToolPrivate *priv, gchar **values, GError **error)
dfu_firmware_set_pid (firmware, tmp); dfu_firmware_set_pid (firmware, tmp);
/* write out new file */ /* write out new file */
return dfu_firmware_write_file (firmware, file, NULL, error); return dfu_firmware_write_file (firmware,
file,
priv->cancellable,
error);
} }
/** /**
@ -371,7 +386,8 @@ dfu_tool_set_release (DfuToolPrivate *priv, gchar **values, GError **error)
firmware = dfu_firmware_new (); firmware = dfu_firmware_new ();
if (!dfu_firmware_parse_file (firmware, file, if (!dfu_firmware_parse_file (firmware, file,
DFU_FIRMWARE_PARSE_FLAG_NONE, DFU_FIRMWARE_PARSE_FLAG_NONE,
NULL, error)) { priv->cancellable,
error)) {
return FALSE; return FALSE;
} }
@ -387,7 +403,10 @@ dfu_tool_set_release (DfuToolPrivate *priv, gchar **values, GError **error)
dfu_firmware_set_release (firmware, tmp); dfu_firmware_set_release (firmware, tmp);
/* write out new file */ /* write out new file */
return dfu_firmware_write_file (firmware, file, NULL, error); return dfu_firmware_write_file (firmware,
file,
priv->cancellable,
error);
} }
/** /**
@ -416,7 +435,8 @@ dfu_tool_set_alt_setting (DfuToolPrivate *priv, gchar **values, GError **error)
firmware = dfu_firmware_new (); firmware = dfu_firmware_new ();
if (!dfu_firmware_parse_file (firmware, file, if (!dfu_firmware_parse_file (firmware, file,
DFU_FIRMWARE_PARSE_FLAG_NONE, DFU_FIRMWARE_PARSE_FLAG_NONE,
NULL, error)) { priv->cancellable,
error)) {
return FALSE; return FALSE;
} }
@ -435,7 +455,8 @@ dfu_tool_set_alt_setting (DfuToolPrivate *priv, gchar **values, GError **error)
g_set_error (error, g_set_error (error,
DFU_ERROR, DFU_ERROR,
DFU_ERROR_INTERNAL, DFU_ERROR_INTERNAL,
"Failed to parse alternative setting '%s'", values[1]); "Failed to parse alternative setting '%s'",
values[1]);
return FALSE; return FALSE;
} }
image = dfu_firmware_get_image_default (firmware); image = dfu_firmware_get_image_default (firmware);
@ -449,7 +470,10 @@ dfu_tool_set_alt_setting (DfuToolPrivate *priv, gchar **values, GError **error)
dfu_image_set_alt_setting (image, tmp); dfu_image_set_alt_setting (image, tmp);
/* write out new file */ /* write out new file */
return dfu_firmware_write_file (firmware, file, NULL, error); return dfu_firmware_write_file (firmware,
file,
priv->cancellable,
error);
} }
/** /**
@ -477,7 +501,8 @@ dfu_tool_set_alt_setting_name (DfuToolPrivate *priv, gchar **values, GError **er
firmware = dfu_firmware_new (); firmware = dfu_firmware_new ();
if (!dfu_firmware_parse_file (firmware, file, if (!dfu_firmware_parse_file (firmware, file,
DFU_FIRMWARE_PARSE_FLAG_NONE, DFU_FIRMWARE_PARSE_FLAG_NONE,
NULL, error)) { priv->cancellable,
error)) {
return FALSE; return FALSE;
} }
@ -502,7 +527,10 @@ dfu_tool_set_alt_setting_name (DfuToolPrivate *priv, gchar **values, GError **er
dfu_image_set_name (image, values[1]); dfu_image_set_name (image, values[1]);
/* write out new file */ /* write out new file */
return dfu_firmware_write_file (firmware, file, NULL, error); return dfu_firmware_write_file (firmware,
file,
priv->cancellable,
error);
} }
/** /**
@ -544,7 +572,8 @@ dfu_tool_merge (DfuToolPrivate *priv, gchar **values, GError **error)
firmware_tmp = dfu_firmware_new (); firmware_tmp = dfu_firmware_new ();
if (!dfu_firmware_parse_file (firmware_tmp, file_tmp, if (!dfu_firmware_parse_file (firmware_tmp, file_tmp,
DFU_FIRMWARE_PARSE_FLAG_NONE, DFU_FIRMWARE_PARSE_FLAG_NONE,
NULL, error)) { priv->cancellable,
error)) {
return FALSE; return FALSE;
} }
@ -625,7 +654,10 @@ dfu_tool_merge (DfuToolPrivate *priv, gchar **values, GError **error)
/* write out new file */ /* write out new file */
file = g_file_new_for_path (values[0]); file = g_file_new_for_path (values[0]);
return dfu_firmware_write_file (firmware, file, NULL, error); return dfu_firmware_write_file (firmware,
file,
priv->cancellable,
error);
} }
/** /**
@ -658,7 +690,8 @@ dfu_tool_convert (DfuToolPrivate *priv, gchar **values, GError **error)
firmware = dfu_firmware_new (); firmware = dfu_firmware_new ();
if (!dfu_firmware_parse_file (firmware, file_in, if (!dfu_firmware_parse_file (firmware, file_in,
DFU_FIRMWARE_PARSE_FLAG_NONE, DFU_FIRMWARE_PARSE_FLAG_NONE,
NULL, error)) { priv->cancellable,
error)) {
return FALSE; return FALSE;
} }
@ -687,7 +720,8 @@ dfu_tool_convert (DfuToolPrivate *priv, gchar **values, GError **error)
g_set_error (error, g_set_error (error,
DFU_ERROR, DFU_ERROR,
DFU_ERROR_INTERNAL, DFU_ERROR_INTERNAL,
"Failed to parse target size '%s'", values[3]); "Failed to parse target size '%s'",
values[3]);
return FALSE; return FALSE;
} }
@ -714,7 +748,10 @@ dfu_tool_convert (DfuToolPrivate *priv, gchar **values, GError **error)
g_debug ("DFU: %s", str_debug); g_debug ("DFU: %s", str_debug);
/* write out new file */ /* write out new file */
return dfu_firmware_write_file (firmware, file_out, NULL, error); return dfu_firmware_write_file (firmware,
file_out,
priv->cancellable,
error);
} }
/** /**
@ -730,7 +767,8 @@ dfu_tool_reset (DfuToolPrivate *priv, gchar **values, GError **error)
return FALSE; return FALSE;
if (!dfu_device_open (device, if (!dfu_device_open (device,
DFU_DEVICE_OPEN_FLAG_NO_AUTO_REFRESH, DFU_DEVICE_OPEN_FLAG_NO_AUTO_REFRESH,
NULL, error)) priv->cancellable,
error))
return FALSE; return FALSE;
if (!dfu_device_reset (device, error)) if (!dfu_device_reset (device, error))
return FALSE; return FALSE;
@ -844,20 +882,27 @@ dfu_tool_upload_target (DfuToolPrivate *priv, gchar **values, GError **error)
return FALSE; return FALSE;
if (priv->transfer_size > 0) if (priv->transfer_size > 0)
dfu_device_set_transfer_size (device, priv->transfer_size); dfu_device_set_transfer_size (device, priv->transfer_size);
if (!dfu_device_open (device, DFU_DEVICE_OPEN_FLAG_NONE, NULL, error)) if (!dfu_device_open (device,
return FALSE; DFU_DEVICE_OPEN_FLAG_NONE,
priv->cancellable,
error))
/* APP -> DFU */ /* APP -> DFU */
if (dfu_device_get_mode (device) == DFU_MODE_RUNTIME) { if (dfu_device_get_mode (device) == DFU_MODE_RUNTIME) {
g_debug ("detaching"); g_debug ("detaching");
if (!dfu_device_detach (device, NULL, error)) if (!dfu_device_detach (device, priv->cancellable, error))
return FALSE; return FALSE;
if (!dfu_device_wait_for_replug (device, 5000, NULL, error)) if (!dfu_device_wait_for_replug (device,
DFU_DEVICE_REPLUG_TIMEOUT,
priv->cancellable,
error))
return FALSE; return FALSE;
} }
/* transfer */ /* transfer */
target = dfu_device_get_target_by_alt_setting (device, priv->alt_setting, error); target = dfu_device_get_target_by_alt_setting (device,
priv->alt_setting,
error);
if (target == NULL) if (target == NULL)
return FALSE; return FALSE;
helper.last_state = DFU_STATE_DFU_ERROR; helper.last_state = DFU_STATE_DFU_ERROR;
@ -867,7 +912,7 @@ dfu_tool_upload_target (DfuToolPrivate *priv, gchar **values, GError **error)
G_CALLBACK (fu_tool_state_changed_cb), &helper); G_CALLBACK (fu_tool_state_changed_cb), &helper);
g_signal_connect (device, "percentage-changed", g_signal_connect (device, "percentage-changed",
G_CALLBACK (fu_tool_percentage_changed_cb), &helper); G_CALLBACK (fu_tool_percentage_changed_cb), &helper);
image = dfu_target_upload (target, flags, NULL, error); image = dfu_target_upload (target, flags, priv->cancellable, error);
if (image == NULL) if (image == NULL)
return FALSE; return FALSE;
@ -880,7 +925,10 @@ dfu_tool_upload_target (DfuToolPrivate *priv, gchar **values, GError **error)
/* save file */ /* save file */
file = g_file_new_for_path (values[0]); file = g_file_new_for_path (values[0]);
if (!dfu_firmware_write_file (firmware, file, NULL, error)) if (!dfu_firmware_write_file (firmware,
file,
priv->cancellable,
error))
return FALSE; return FALSE;
/* print the new object */ /* print the new object */
@ -920,7 +968,10 @@ dfu_tool_upload (DfuToolPrivate *priv, gchar **values, GError **error)
device = dfu_tool_get_defalt_device (priv, error); device = dfu_tool_get_defalt_device (priv, error);
if (device == NULL) if (device == NULL)
return FALSE; return FALSE;
if (!dfu_device_open (device, DFU_DEVICE_OPEN_FLAG_NONE, NULL, error)) if (!dfu_device_open (device,
DFU_DEVICE_OPEN_FLAG_NONE,
priv->cancellable,
error))
return FALSE; return FALSE;
/* optional reset */ /* optional reset */
@ -938,13 +989,19 @@ dfu_tool_upload (DfuToolPrivate *priv, gchar **values, GError **error)
G_CALLBACK (fu_tool_state_changed_cb), &helper); G_CALLBACK (fu_tool_state_changed_cb), &helper);
g_signal_connect (device, "percentage-changed", g_signal_connect (device, "percentage-changed",
G_CALLBACK (fu_tool_percentage_changed_cb), &helper); G_CALLBACK (fu_tool_percentage_changed_cb), &helper);
firmware = dfu_device_upload (device, flags, NULL, error); firmware = dfu_device_upload (device,
flags,
priv->cancellable,
error);
if (firmware == NULL) if (firmware == NULL)
return FALSE; return FALSE;
/* save file */ /* save file */
file = g_file_new_for_path (values[0]); file = g_file_new_for_path (values[0]);
if (!dfu_firmware_write_file (firmware, file, NULL, error)) if (!dfu_firmware_write_file (firmware,
file,
priv->cancellable,
error))
return FALSE; return FALSE;
/* print the new object */ /* print the new object */
@ -961,7 +1018,7 @@ dfu_tool_upload (DfuToolPrivate *priv, gchar **values, GError **error)
* dfu_tool_get_device_string: * dfu_tool_get_device_string:
**/ **/
static gchar * static gchar *
dfu_tool_get_device_string (DfuDevice *device) dfu_tool_get_device_string (DfuToolPrivate *priv, DfuDevice *device)
{ {
gchar *dstr; gchar *dstr;
GUsbDevice *dev; GUsbDevice *dev;
@ -969,7 +1026,16 @@ dfu_tool_get_device_string (DfuDevice *device)
/* open, and get status */ /* open, and get status */
dev = dfu_device_get_usb_dev (device); dev = dfu_device_get_usb_dev (device);
if (!dfu_device_open (device, DFU_DEVICE_OPEN_FLAG_NONE, NULL, &error)) { if (dev == NULL) {
return g_strdup_printf ("%04x:%04x [%s]",
dfu_device_get_runtime_vid (device),
dfu_device_get_runtime_pid (device),
"removed");
}
if (!dfu_device_open (device,
DFU_DEVICE_OPEN_FLAG_NONE,
priv->cancellable,
&error)) {
return g_strdup_printf ("%04x:%04x [%s]", return g_strdup_printf ("%04x:%04x [%s]",
g_usb_device_get_vid (dev), g_usb_device_get_vid (dev),
g_usb_device_get_pid (dev), g_usb_device_get_pid (dev),
@ -988,10 +1054,13 @@ dfu_tool_get_device_string (DfuDevice *device)
* dfu_tool_device_added_cb: * dfu_tool_device_added_cb:
**/ **/
static void static void
dfu_tool_device_added_cb (DfuContext *context, DfuDevice *device, gpointer user_data) dfu_tool_device_added_cb (DfuContext *context,
DfuDevice *device,
gpointer user_data)
{ {
DfuToolPrivate *priv = (DfuToolPrivate *) user_data;
g_autofree gchar *tmp; g_autofree gchar *tmp;
tmp = dfu_tool_get_device_string (device); tmp = dfu_tool_get_device_string (priv, device);
/* TRANSLATORS: this is when a device is hotplugged */ /* TRANSLATORS: this is when a device is hotplugged */
dfu_tool_print_indent (_("Added"), tmp, 0); dfu_tool_print_indent (_("Added"), tmp, 0);
} }
@ -1000,10 +1069,13 @@ dfu_tool_device_added_cb (DfuContext *context, DfuDevice *device, gpointer user_
* dfu_tool_device_removed_cb: * dfu_tool_device_removed_cb:
**/ **/
static void static void
dfu_tool_device_removed_cb (DfuContext *context, DfuDevice *device, gpointer user_data) dfu_tool_device_removed_cb (DfuContext *context,
DfuDevice *device,
gpointer user_data)
{ {
DfuToolPrivate *priv = (DfuToolPrivate *) user_data;
g_autofree gchar *tmp; g_autofree gchar *tmp;
tmp = dfu_tool_get_device_string (device); tmp = dfu_tool_get_device_string (priv, device);
/* TRANSLATORS: this is when a device is hotplugged */ /* TRANSLATORS: this is when a device is hotplugged */
dfu_tool_print_indent (_("Removed"), tmp, 0); dfu_tool_print_indent (_("Removed"), tmp, 0);
} }
@ -1014,26 +1086,53 @@ dfu_tool_device_removed_cb (DfuContext *context, DfuDevice *device, gpointer use
static void static void
dfu_tool_device_changed_cb (DfuContext *context, DfuDevice *device, gpointer user_data) dfu_tool_device_changed_cb (DfuContext *context, DfuDevice *device, gpointer user_data)
{ {
DfuToolPrivate *priv = (DfuToolPrivate *) user_data;
g_autofree gchar *tmp; g_autofree gchar *tmp;
tmp = dfu_tool_get_device_string (device); tmp = dfu_tool_get_device_string (priv, device);
/* TRANSLATORS: this is when a device is hotplugged */ /* TRANSLATORS: this is when a device is hotplugged */
dfu_tool_print_indent (_("Changed"), tmp, 0); dfu_tool_print_indent (_("Changed"), tmp, 0);
} }
/**
* dfu_tool_watch_cancelled_cb:
**/
static void
dfu_tool_watch_cancelled_cb (GCancellable *cancellable, gpointer user_data)
{
GMainLoop *loop = (GMainLoop *) user_data;
/* TRANSLATORS: this is when a device ctrl+c's a watch */
g_print ("%s\n", _("Cancelled"));
g_main_loop_quit (loop);
}
/** /**
* dfu_tool_watch: * dfu_tool_watch:
**/ **/
static gboolean static gboolean
dfu_tool_watch (DfuToolPrivate *priv, gchar **values, GError **error) dfu_tool_watch (DfuToolPrivate *priv, gchar **values, GError **error)
{ {
guint i;
DfuDevice *device;
g_autoptr(GMainLoop) loop = NULL; g_autoptr(GMainLoop) loop = NULL;
g_signal_connect (priv->dfu_context, "device-added", g_autoptr(GPtrArray) devices = NULL;
G_CALLBACK (dfu_tool_device_added_cb), NULL);
g_signal_connect (priv->dfu_context, "device-removed", /* print what's already attached */
G_CALLBACK (dfu_tool_device_removed_cb), NULL); devices = dfu_context_get_devices (priv->dfu_context);
g_signal_connect (priv->dfu_context, "device-changed", for (i = 0; i < devices->len; i++) {
G_CALLBACK (dfu_tool_device_changed_cb), NULL); device = g_ptr_array_index (devices, i);
dfu_tool_device_added_cb (priv->dfu_context, device, NULL);
}
/* watch for any hotplugged device */
loop = g_main_loop_new (NULL, FALSE); loop = g_main_loop_new (NULL, FALSE);
g_signal_connect (priv->dfu_context, "device-added",
G_CALLBACK (dfu_tool_device_added_cb), priv);
g_signal_connect (priv->dfu_context, "device-removed",
G_CALLBACK (dfu_tool_device_removed_cb), priv);
g_signal_connect (priv->dfu_context, "device-changed",
G_CALLBACK (dfu_tool_device_changed_cb), priv);
g_signal_connect (priv->cancellable, "cancelled",
G_CALLBACK (dfu_tool_watch_cancelled_cb), loop);
g_main_loop_run (loop); g_main_loop_run (loop);
return TRUE; return TRUE;
} }
@ -1061,7 +1160,7 @@ dfu_tool_dump (DfuToolPrivate *priv, gchar **values, GError **error)
file = g_file_new_for_path (values[0]); file = g_file_new_for_path (values[0]);
if (!dfu_firmware_parse_file (firmware, file, if (!dfu_firmware_parse_file (firmware, file,
DFU_FIRMWARE_PARSE_FLAG_NONE, DFU_FIRMWARE_PARSE_FLAG_NONE,
NULL, error)) priv->cancellable, error))
return FALSE; return FALSE;
/* dump to screen */ /* dump to screen */
@ -1099,7 +1198,7 @@ dfu_tool_download_target (DfuToolPrivate *priv, gchar **values, GError **error)
file = g_file_new_for_path (values[0]); file = g_file_new_for_path (values[0]);
if (!dfu_firmware_parse_file (firmware, file, if (!dfu_firmware_parse_file (firmware, file,
DFU_FIRMWARE_PARSE_FLAG_NONE, DFU_FIRMWARE_PARSE_FLAG_NONE,
NULL, error)) priv->cancellable, error))
return FALSE; return FALSE;
/* open correct device */ /* open correct device */
@ -1108,15 +1207,18 @@ dfu_tool_download_target (DfuToolPrivate *priv, gchar **values, GError **error)
return FALSE; return FALSE;
if (priv->transfer_size > 0) if (priv->transfer_size > 0)
dfu_device_set_transfer_size (device, priv->transfer_size); dfu_device_set_transfer_size (device, priv->transfer_size);
if (!dfu_device_open (device, DFU_DEVICE_OPEN_FLAG_NONE, NULL, error)) if (!dfu_device_open (device,
DFU_DEVICE_OPEN_FLAG_NONE,
priv->cancellable,
error))
return FALSE; return FALSE;
/* APP -> DFU */ /* APP -> DFU */
if (dfu_device_get_mode (device) == DFU_MODE_RUNTIME) { if (dfu_device_get_mode (device) == DFU_MODE_RUNTIME) {
g_debug ("detaching"); g_debug ("detaching");
if (!dfu_device_detach (device, NULL, error)) if (!dfu_device_detach (device, priv->cancellable, error))
return FALSE; return FALSE;
if (!dfu_device_wait_for_replug (device, 5000, NULL, error)) if (!dfu_device_wait_for_replug (device, 5000, priv->cancellable, error))
return FALSE; return FALSE;
} }
@ -1137,7 +1239,8 @@ dfu_tool_download_target (DfuToolPrivate *priv, gchar **values, GError **error)
g_set_error (error, g_set_error (error,
DFU_ERROR, DFU_ERROR,
DFU_ERROR_INTERNAL, DFU_ERROR_INTERNAL,
"Failed to parse alt-setting '%s'", values[1]); "Failed to parse alt-setting '%s'",
values[1]);
return FALSE; return FALSE;
} }
image = dfu_firmware_get_image (firmware, tmp); image = dfu_firmware_get_image (firmware, tmp);
@ -1162,7 +1265,9 @@ dfu_tool_download_target (DfuToolPrivate *priv, gchar **values, GError **error)
} }
/* transfer */ /* transfer */
target = dfu_device_get_target_by_alt_setting (device, priv->alt_setting, error); target = dfu_device_get_target_by_alt_setting (device,
priv->alt_setting,
error);
if (target == NULL) if (target == NULL)
return FALSE; return FALSE;
helper.last_state = DFU_STATE_DFU_ERROR; helper.last_state = DFU_STATE_DFU_ERROR;
@ -1172,7 +1277,11 @@ dfu_tool_download_target (DfuToolPrivate *priv, gchar **values, GError **error)
G_CALLBACK (fu_tool_state_changed_cb), &helper); G_CALLBACK (fu_tool_state_changed_cb), &helper);
g_signal_connect (device, "percentage-changed", g_signal_connect (device, "percentage-changed",
G_CALLBACK (fu_tool_percentage_changed_cb), &helper); G_CALLBACK (fu_tool_percentage_changed_cb), &helper);
if (!dfu_target_download (target, image, flags, NULL, error)) if (!dfu_target_download (target,
image,
flags,
priv->cancellable,
error))
return FALSE; return FALSE;
/* success */ /* success */
@ -1208,14 +1317,17 @@ dfu_tool_download (DfuToolPrivate *priv, gchar **values, GError **error)
file = g_file_new_for_path (values[0]); file = g_file_new_for_path (values[0]);
if (!dfu_firmware_parse_file (firmware, file, if (!dfu_firmware_parse_file (firmware, file,
DFU_FIRMWARE_PARSE_FLAG_NONE, DFU_FIRMWARE_PARSE_FLAG_NONE,
NULL, error)) priv->cancellable, error))
return FALSE; return FALSE;
/* open correct device */ /* open correct device */
device = dfu_tool_get_defalt_device (priv, error); device = dfu_tool_get_defalt_device (priv, error);
if (device == NULL) if (device == NULL)
return FALSE; return FALSE;
if (!dfu_device_open (device, DFU_DEVICE_OPEN_FLAG_NONE, NULL, error)) if (!dfu_device_open (device,
DFU_DEVICE_OPEN_FLAG_NONE,
priv->cancellable,
error))
return FALSE; return FALSE;
/* print the new object */ /* print the new object */
@ -1243,7 +1355,11 @@ dfu_tool_download (DfuToolPrivate *priv, gchar **values, GError **error)
G_CALLBACK (fu_tool_state_changed_cb), &helper); G_CALLBACK (fu_tool_state_changed_cb), &helper);
g_signal_connect (device, "percentage-changed", g_signal_connect (device, "percentage-changed",
G_CALLBACK (fu_tool_percentage_changed_cb), &helper); G_CALLBACK (fu_tool_percentage_changed_cb), &helper);
if (!dfu_device_download (device, firmware, flags, NULL, error)) if (!dfu_device_download (device,
firmware,
flags,
priv->cancellable,
error))
return FALSE; return FALSE;
/* success */ /* success */
@ -1325,7 +1441,8 @@ dfu_tool_list (DfuToolPrivate *priv, gchar **values, GError **error)
/* open */ /* open */
if (!dfu_device_open (device, if (!dfu_device_open (device,
DFU_DEVICE_OPEN_FLAG_NONE, DFU_DEVICE_OPEN_FLAG_NONE,
NULL, &error_local)) { priv->cancellable,
&error_local)) {
if (g_error_matches (error_local, if (g_error_matches (error_local,
DFU_ERROR, DFU_ERROR,
DFU_ERROR_PERMISSION_DENIED)) { DFU_ERROR_PERMISSION_DENIED)) {
@ -1376,13 +1493,26 @@ dfu_tool_detach (DfuToolPrivate *priv, gchar **values, GError **error)
dfu_device_set_transfer_size (device, priv->transfer_size); dfu_device_set_transfer_size (device, priv->transfer_size);
/* detatch */ /* detatch */
if (!dfu_device_open (device, DFU_DEVICE_OPEN_FLAG_NONE, NULL, error)) if (!dfu_device_open (device, DFU_DEVICE_OPEN_FLAG_NONE,
priv->cancellable, error))
return FALSE; return FALSE;
if (!dfu_device_detach (device, NULL, error)) if (!dfu_device_detach (device, priv->cancellable, error))
return FALSE; return FALSE;
return TRUE; return TRUE;
} }
/**
* dfu_tool_sigint_cb:
**/
static gboolean
dfu_tool_sigint_cb (gpointer user_data)
{
DfuToolPrivate *priv = (DfuToolPrivate *) user_data;
g_debug ("Handling SIGINT");
g_cancellable_cancel (priv->cancellable);
return FALSE;
}
/** /**
* main: * main:
**/ **/
@ -1519,6 +1649,14 @@ main (int argc, char *argv[])
_("Watch DFU devices being hotplugged"), _("Watch DFU devices being hotplugged"),
dfu_tool_watch); dfu_tool_watch);
/* do stuff on ctrl+c */
priv->cancellable = g_cancellable_new ();
g_unix_signal_add_full (G_PRIORITY_DEFAULT,
SIGINT,
dfu_tool_sigint_cb,
priv,
NULL);
/* sort by command name */ /* sort by command name */
g_ptr_array_sort (priv->cmd_array, g_ptr_array_sort (priv->cmd_array,
(GCompareFunc) dfu_tool_sort_command_name_cb); (GCompareFunc) dfu_tool_sort_command_name_cb);