mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-04 23:02:28 +00:00
libdfu: Support download and upload to ST DfuSe devices
Also, simplify the general download and upload API now we can deal with element data in chunks.
This commit is contained in:
parent
0256f04338
commit
e7ba943cf5
@ -52,6 +52,7 @@ IGNORE_HFILES= \
|
||||
dfu-device-private.h \
|
||||
dfu-element-private.h \
|
||||
dfu-image-private.h \
|
||||
dfu-sector-private.h \
|
||||
dfu-target-private.h
|
||||
|
||||
# Images to copy into HTML directory.
|
||||
|
@ -80,6 +80,7 @@ if (!dfu_device_download (dfu_device, dfu_firmware,
|
||||
<xi:include href="xml/dfu-firmware.xml"/>
|
||||
<xi:include href="xml/dfu-image.xml"/>
|
||||
<xi:include href="xml/dfu-element.xml"/>
|
||||
<xi:include href="xml/dfu-sector.xml"/>
|
||||
<xi:include href="xml/dfu-target.xml"/>
|
||||
<xi:include href="xml/dfu-common.xml"/>
|
||||
<xi:include href="xml/dfu-error.xml"/>
|
||||
|
@ -34,6 +34,9 @@ libdfu_private_la_SOURCES = \
|
||||
dfu-image.c \
|
||||
dfu-image.h \
|
||||
dfu-image-private.h \
|
||||
dfu-sector.c \
|
||||
dfu-sector.h \
|
||||
dfu-sector-private.h \
|
||||
dfu-target.c \
|
||||
dfu-target.h \
|
||||
dfu-target-private.h
|
||||
|
@ -603,7 +603,6 @@ dfu_device_reset (DfuDevice *device, GError **error)
|
||||
/**
|
||||
* dfu_device_upload:
|
||||
* @device: a #DfuDevice
|
||||
* @expected_size: the expected size of the firmware, or 0 for unknown
|
||||
* @flags: flags to use, e.g. %DFU_TARGET_TRANSFER_FLAG_VERIFY
|
||||
* @cancellable: a #GCancellable, or %NULL
|
||||
* @progress_cb: a #GFileProgressCallback, or %NULL
|
||||
@ -618,7 +617,6 @@ dfu_device_reset (DfuDevice *device, GError **error)
|
||||
**/
|
||||
DfuFirmware *
|
||||
dfu_device_upload (DfuDevice *device,
|
||||
gsize expected_size,
|
||||
DfuTargetTransferFlags flags,
|
||||
GCancellable *cancellable,
|
||||
DfuProgressCallback progress_cb,
|
||||
@ -646,25 +644,30 @@ dfu_device_upload (DfuDevice *device,
|
||||
dfu_firmware_set_release (firmware, 0xffff);
|
||||
|
||||
/* APP -> DFU */
|
||||
if (flags & DFU_TARGET_TRANSFER_FLAG_DETACH) {
|
||||
target_default = dfu_device_get_target_default (device, error);
|
||||
if (target_default == NULL)
|
||||
return NULL;
|
||||
if (dfu_target_get_mode (target_default) == DFU_MODE_RUNTIME) {
|
||||
g_debug ("detaching");
|
||||
|
||||
/* inform UI there's going to be a detach:attach */
|
||||
if (progress_cb != NULL) {
|
||||
progress_cb (DFU_STATE_APP_DETACH, 0, 0,
|
||||
progress_cb_data);
|
||||
}
|
||||
|
||||
/* detach and USB reset */
|
||||
if (!dfu_target_detach (target_default, NULL, error))
|
||||
return NULL;
|
||||
if (!dfu_device_wait_for_replug (device, 5000, NULL, error))
|
||||
return NULL;
|
||||
target_default = dfu_device_get_target_default (device, error);
|
||||
if (target_default == NULL)
|
||||
return NULL;
|
||||
if (dfu_target_get_mode (target_default) == DFU_MODE_RUNTIME) {
|
||||
if ((flags & DFU_TARGET_TRANSFER_FLAG_DETACH) == 0) {
|
||||
g_set_error (error,
|
||||
DFU_ERROR,
|
||||
DFU_ERROR_NOT_SUPPORTED,
|
||||
"device is not in DFU mode");
|
||||
return FALSE;
|
||||
}
|
||||
g_debug ("detaching");
|
||||
|
||||
/* inform UI there's going to be a detach:attach */
|
||||
if (progress_cb != NULL) {
|
||||
progress_cb (DFU_STATE_APP_DETACH, 0, 0,
|
||||
progress_cb_data);
|
||||
}
|
||||
|
||||
/* detach and USB reset */
|
||||
if (!dfu_target_detach (target_default, NULL, error))
|
||||
return NULL;
|
||||
if (!dfu_device_wait_for_replug (device, 5000, NULL, error))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* upload from each target */
|
||||
@ -673,7 +676,12 @@ dfu_device_upload (DfuDevice *device,
|
||||
DfuTarget *target;
|
||||
g_autoptr(DfuImage) image = NULL;
|
||||
target = g_ptr_array_index (targets, i);
|
||||
image = dfu_target_upload (target, 0,
|
||||
if (!dfu_target_open (target,
|
||||
DFU_TARGET_OPEN_FLAG_NONE,
|
||||
cancellable,
|
||||
error))
|
||||
return NULL;
|
||||
image = dfu_target_upload (target,
|
||||
DFU_TARGET_TRANSFER_FLAG_NONE,
|
||||
cancellable,
|
||||
progress_cb,
|
||||
@ -811,7 +819,18 @@ dfu_device_download (DfuDevice *device,
|
||||
}
|
||||
|
||||
/* APP -> DFU */
|
||||
if (flags & DFU_TARGET_TRANSFER_FLAG_DETACH) {
|
||||
/* detach and USB reset */
|
||||
target_default = dfu_device_get_target_default (device, error);
|
||||
if (target_default == NULL)
|
||||
return FALSE;
|
||||
if (dfu_target_get_mode (target_default) == DFU_MODE_RUNTIME) {
|
||||
if ((flags & DFU_TARGET_TRANSFER_FLAG_DETACH) == 0) {
|
||||
g_set_error (error,
|
||||
DFU_ERROR,
|
||||
DFU_ERROR_NOT_SUPPORTED,
|
||||
"device is not in DFU mode");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* inform UI there's going to be a detach:attach */
|
||||
if (progress_cb != NULL) {
|
||||
@ -819,17 +838,11 @@ dfu_device_download (DfuDevice *device,
|
||||
progress_cb_data);
|
||||
}
|
||||
|
||||
/* detach and USB reset */
|
||||
target_default = dfu_device_get_target_default (device, error);
|
||||
if (target_default == NULL)
|
||||
g_debug ("detaching");
|
||||
if (!dfu_target_detach (target_default, NULL, error))
|
||||
return FALSE;
|
||||
if (!dfu_device_wait_for_replug (device, 5000, NULL, error))
|
||||
return FALSE;
|
||||
if (dfu_target_get_mode (target_default) == DFU_MODE_RUNTIME) {
|
||||
g_debug ("detaching");
|
||||
if (!dfu_target_detach (target_default, NULL, error))
|
||||
return FALSE;
|
||||
if (!dfu_device_wait_for_replug (device, 5000, NULL, error))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* download each target */
|
||||
|
@ -62,7 +62,6 @@ gboolean dfu_device_wait_for_replug (DfuDevice *device,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
DfuFirmware *dfu_device_upload (DfuDevice *device,
|
||||
gsize expected_size,
|
||||
DfuTargetTransferFlags flags,
|
||||
GCancellable *cancellable,
|
||||
DfuProgressCallback progress_cb,
|
||||
|
@ -928,7 +928,13 @@ dfu_firmware_write_data (DfuFirmware *firmware, GError **error)
|
||||
image = dfu_firmware_get_image_default (firmware);
|
||||
g_assert (image != NULL);
|
||||
element = dfu_image_get_element (image, 0);
|
||||
g_assert (element != NULL);
|
||||
if (element == NULL) {
|
||||
g_set_error (error,
|
||||
DFU_ERROR,
|
||||
DFU_ERROR_NOT_FOUND,
|
||||
"no firmware element data to write");
|
||||
return NULL;
|
||||
}
|
||||
contents = dfu_element_get_contents (element);
|
||||
return g_bytes_ref (contents);
|
||||
}
|
||||
@ -940,7 +946,13 @@ dfu_firmware_write_data (DfuFirmware *firmware, GError **error)
|
||||
image = dfu_firmware_get_image_default (firmware);
|
||||
g_assert (image != NULL);
|
||||
element = dfu_image_get_element (image, 0);
|
||||
g_assert (element != NULL);
|
||||
if (element == NULL) {
|
||||
g_set_error (error,
|
||||
DFU_ERROR,
|
||||
DFU_ERROR_NOT_FOUND,
|
||||
"no firmware element data to write");
|
||||
return NULL;
|
||||
}
|
||||
contents = dfu_element_get_contents (element);
|
||||
g_assert (contents != NULL);
|
||||
return dfu_firmware_add_footer (firmware, contents);
|
||||
|
38
libdfu/dfu-sector-private.h
Normal file
38
libdfu/dfu-sector-private.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
||||
*
|
||||
* Copyright (C) 2015 Richard Hughes <richard@hughsie.com>
|
||||
*
|
||||
* Licensed under the GNU Lesser General Public License Version 2.1
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __DFU_SECTOR_PRIVATE_H
|
||||
#define __DFU_SECTOR_PRIVATE_H
|
||||
|
||||
#include "dfu-sector.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
DfuSector *dfu_sector_new (guint32 address,
|
||||
guint32 size,
|
||||
guint32 size_left,
|
||||
guint16 zone,
|
||||
guint16 number,
|
||||
DfuSectorCap cap);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __DFU_SECTOR_PRIVATE_H */
|
229
libdfu/dfu-sector.c
Normal file
229
libdfu/dfu-sector.c
Normal file
@ -0,0 +1,229 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
||||
*
|
||||
* Copyright (C) 2015 Richard Hughes <richard@hughsie.com>
|
||||
*
|
||||
* Licensed under the GNU Lesser General Public License Version 2.1
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:dfu-sector
|
||||
* @short_description: Object representing a sector on a chip
|
||||
*
|
||||
* This object represents an sector of memory at a specific address on the
|
||||
* device itself.
|
||||
*
|
||||
* This allows relocatable data segments to be stored in different
|
||||
* locations on the device itself.
|
||||
*
|
||||
* You can think of these objects as flash segments on devices, where a
|
||||
* complete block can be erased and then written to.
|
||||
*
|
||||
* See also: #DfuElement
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "dfu-common.h"
|
||||
#include "dfu-sector-private.h"
|
||||
|
||||
/**
|
||||
* DfuSectorPrivate:
|
||||
*
|
||||
* Private #DfuSector data
|
||||
**/
|
||||
typedef struct {
|
||||
guint32 address;
|
||||
guint32 size;
|
||||
guint32 size_left;
|
||||
guint16 zone;
|
||||
guint16 number;
|
||||
DfuSectorCap cap;
|
||||
} DfuSectorPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (DfuSector, dfu_sector, G_TYPE_OBJECT)
|
||||
#define GET_PRIVATE(o) (dfu_sector_get_instance_private (o))
|
||||
|
||||
/**
|
||||
* dfu_sector_class_init:
|
||||
**/
|
||||
static void
|
||||
dfu_sector_class_init (DfuSectorClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* dfu_sector_init:
|
||||
**/
|
||||
static void
|
||||
dfu_sector_init (DfuSector *sector)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* dfu_sector_new: (skip)
|
||||
* address: the address for the sector
|
||||
* size: the size of this sector
|
||||
* size_left: the size of the rest of the sector
|
||||
* zone: the zone of memory the setor belongs
|
||||
* number: the sector number in the zone
|
||||
* cap: the #DfuSectorCap
|
||||
*
|
||||
* Creates a new DFU sector object.
|
||||
*
|
||||
* Return value: a new #DfuSector
|
||||
*
|
||||
* Since: 0.5.4
|
||||
**/
|
||||
DfuSector *
|
||||
dfu_sector_new (guint32 address, guint32 size, guint32 size_left,
|
||||
guint16 zone, guint16 number, DfuSectorCap cap)
|
||||
{
|
||||
DfuSectorPrivate *priv;
|
||||
DfuSector *sector;
|
||||
sector = g_object_new (DFU_TYPE_SECTOR, NULL);
|
||||
priv = GET_PRIVATE (sector);
|
||||
priv->address = address;
|
||||
priv->size = size;
|
||||
priv->size_left = size_left;
|
||||
priv->zone = zone;
|
||||
priv->number = number;
|
||||
priv->cap = cap;
|
||||
return sector;
|
||||
}
|
||||
|
||||
/**
|
||||
* dfu_sector_get_address:
|
||||
* @sector: a #DfuSector
|
||||
*
|
||||
* Gets the alternate setting.
|
||||
*
|
||||
* Return value: integer, or 0x00 for unset
|
||||
*
|
||||
* Since: 0.5.4
|
||||
**/
|
||||
guint32
|
||||
dfu_sector_get_address (DfuSector *sector)
|
||||
{
|
||||
DfuSectorPrivate *priv = GET_PRIVATE (sector);
|
||||
g_return_val_if_fail (DFU_IS_SECTOR (sector), 0x00);
|
||||
return priv->address;
|
||||
}
|
||||
|
||||
/**
|
||||
* dfu_sector_get_size:
|
||||
* @sector: a #DfuSector
|
||||
*
|
||||
* Gets the alternate setting.
|
||||
*
|
||||
* Return value: integer, or 0x00 for unset
|
||||
*
|
||||
* Since: 0.5.4
|
||||
**/
|
||||
guint32
|
||||
dfu_sector_get_size (DfuSector *sector)
|
||||
{
|
||||
DfuSectorPrivate *priv = GET_PRIVATE (sector);
|
||||
g_return_val_if_fail (DFU_IS_SECTOR (sector), 0x00);
|
||||
return priv->size;
|
||||
}
|
||||
|
||||
/**
|
||||
* dfu_sector_get_size_left:
|
||||
* @sector: a #DfuSector
|
||||
*
|
||||
* Gets the alternate setting.
|
||||
*
|
||||
* Return value: integer, or 0x00 for unset
|
||||
*
|
||||
* Since: 0.5.4
|
||||
**/
|
||||
guint32
|
||||
dfu_sector_get_size_left (DfuSector *sector)
|
||||
{
|
||||
DfuSectorPrivate *priv = GET_PRIVATE (sector);
|
||||
g_return_val_if_fail (DFU_IS_SECTOR (sector), 0x00);
|
||||
return priv->size_left;
|
||||
}
|
||||
|
||||
/**
|
||||
* dfu_sector_get_id:
|
||||
* @sector: a #DfuSector
|
||||
*
|
||||
* Gets the sector ID which is a combination of the zone and sector number.
|
||||
* You can use this number to check if the segment is the 'same' as the last
|
||||
* written or read sector.
|
||||
*
|
||||
* Return value: integer ID, or 0x00 for unset
|
||||
*
|
||||
* Since: 0.5.4
|
||||
**/
|
||||
guint32
|
||||
dfu_sector_get_id (DfuSector *sector)
|
||||
{
|
||||
DfuSectorPrivate *priv = GET_PRIVATE (sector);
|
||||
g_return_val_if_fail (DFU_IS_SECTOR (sector), 0x00);
|
||||
return (((guint32) priv->zone) << 16) | priv->number;
|
||||
}
|
||||
|
||||
/**
|
||||
* dfu_sector_has_cap:
|
||||
* @sector: a #DfuSector
|
||||
* @cap: a #DfuSectorCap, e.g. %DFU_SECTOR_CAP_ERASEABLE
|
||||
*
|
||||
* Finds out if the sector has the required capability.
|
||||
*
|
||||
* Return value: %TRUE if the sector has the capabilily
|
||||
*
|
||||
* Since: 0.5.4
|
||||
**/
|
||||
gboolean
|
||||
dfu_sector_has_cap (DfuSector *sector, DfuSectorCap cap)
|
||||
{
|
||||
DfuSectorPrivate *priv = GET_PRIVATE (sector);
|
||||
g_return_val_if_fail (DFU_IS_SECTOR (sector), FALSE);
|
||||
return priv->cap & cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* dfu_sector_to_string:
|
||||
* @sector: a #DfuSector
|
||||
*
|
||||
* Returns a string representaiton of the object.
|
||||
*
|
||||
* Return value: NULL terminated string, or %NULL for invalid
|
||||
*
|
||||
* Since: 0.5.4
|
||||
**/
|
||||
gchar *
|
||||
dfu_sector_to_string (DfuSector *sector)
|
||||
{
|
||||
DfuSectorPrivate *priv = GET_PRIVATE (sector);
|
||||
GString *str;
|
||||
|
||||
g_return_val_if_fail (DFU_IS_SECTOR (sector), NULL);
|
||||
|
||||
str = g_string_new ("");
|
||||
g_string_append_printf (str,
|
||||
"Zone:%i, Sec#:%i, Addr:0x%08x, "
|
||||
"Size:0x%04x, Caps:0x%01x",
|
||||
priv->zone, priv->number, priv->address,
|
||||
priv->size, priv->cap);
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
66
libdfu/dfu-sector.h
Normal file
66
libdfu/dfu-sector.h
Normal file
@ -0,0 +1,66 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
||||
*
|
||||
* Copyright (C) 2015 Richard Hughes <richard@hughsie.com>
|
||||
*
|
||||
* Licensed under the GNU Lesser General Public License Version 2.1
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __DFU_SECTOR_H
|
||||
#define __DFU_SECTOR_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define DFU_TYPE_SECTOR (dfu_sector_get_type ())
|
||||
G_DECLARE_DERIVABLE_TYPE (DfuSector, dfu_sector, DFU, SECTOR, GObject)
|
||||
|
||||
struct _DfuSectorClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
/**
|
||||
* DfuSectorCap:
|
||||
* @DFU_SECTOR_CAP_NONE: No operations possible
|
||||
* @DFU_SECTOR_CAP_READABLE: Sector can be read
|
||||
* @DFU_SECTOR_CAP_WRITEABLE: Sector can be written
|
||||
* @DFU_SECTOR_CAP_ERASEABLE: Sector can be erased
|
||||
*
|
||||
* The flags indicating what the sector can do.
|
||||
**/
|
||||
typedef enum {
|
||||
DFU_SECTOR_CAP_NONE = 0,
|
||||
DFU_SECTOR_CAP_READABLE = 1 << 0,
|
||||
DFU_SECTOR_CAP_WRITEABLE = 1 << 1,
|
||||
DFU_SECTOR_CAP_ERASEABLE = 1 << 2,
|
||||
/*< private >*/
|
||||
DFU_SECTOR_CAP_LAST
|
||||
} DfuSectorCap;
|
||||
|
||||
guint32 dfu_sector_get_id (DfuSector *sector);
|
||||
guint32 dfu_sector_get_address (DfuSector *sector);
|
||||
guint32 dfu_sector_get_size (DfuSector *sector);
|
||||
guint32 dfu_sector_get_size_left (DfuSector *sector);
|
||||
gboolean dfu_sector_has_cap (DfuSector *sector,
|
||||
DfuSectorCap cap);
|
||||
gchar *dfu_sector_to_string (DfuSector *sector);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __DFU_SECTOR_H */
|
@ -28,7 +28,8 @@
|
||||
#include "dfu-device.h"
|
||||
#include "dfu-error.h"
|
||||
#include "dfu-firmware.h"
|
||||
#include "dfu-target.h"
|
||||
#include "dfu-sector-private.h"
|
||||
#include "dfu-target-private.h"
|
||||
|
||||
/**
|
||||
* dfu_test_get_filename:
|
||||
@ -322,6 +323,7 @@ dfu_device_func (void)
|
||||
static void
|
||||
dfu_colorhug_plus_func (void)
|
||||
{
|
||||
GPtrArray *elements;
|
||||
gboolean ret;
|
||||
gboolean seen_app_idle = FALSE;
|
||||
g_autoptr(DfuDevice) device = NULL;
|
||||
@ -425,10 +427,13 @@ dfu_colorhug_plus_func (void)
|
||||
}
|
||||
|
||||
/* get a dump of the existing firmware */
|
||||
image = dfu_target_upload (target, 0, DFU_TARGET_TRANSFER_FLAG_NONE,
|
||||
image = dfu_target_upload (target, DFU_TARGET_TRANSFER_FLAG_NONE,
|
||||
NULL, NULL, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (DFU_IS_IMAGE (image));
|
||||
elements = dfu_image_get_elements (image);
|
||||
g_assert_nonnull (elements);
|
||||
g_assert_cmpint (elements->len, ==, 1);
|
||||
|
||||
/* download a new firmware */
|
||||
ret = dfu_target_download (target, image,
|
||||
@ -460,6 +465,102 @@ dfu_colorhug_plus_func (void)
|
||||
g_assert (ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* _dfu_target_sectors_to_string:
|
||||
**/
|
||||
static gchar *
|
||||
_dfu_target_sectors_to_string (DfuTarget *target)
|
||||
{
|
||||
DfuSector *sector;
|
||||
GPtrArray *sectors;
|
||||
GString *str;
|
||||
guint i;
|
||||
|
||||
str = g_string_new ("");
|
||||
sectors = dfu_target_get_sectors (target);
|
||||
for (i = 0; i < sectors->len; i++) {
|
||||
g_autofree gchar *tmp = NULL;
|
||||
sector = g_ptr_array_index (sectors, i);
|
||||
tmp = dfu_sector_to_string (sector);
|
||||
g_string_append_printf (str, "%s\n", tmp);
|
||||
}
|
||||
if (str->len > 0)
|
||||
g_string_truncate (str, str->len - 1);
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
dfu_target_dfuse_func (void)
|
||||
{
|
||||
gboolean ret;
|
||||
gchar *tmp;
|
||||
g_autoptr(DfuTarget) target = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
/* NULL */
|
||||
target = g_object_new (DFU_TYPE_TARGET, NULL);
|
||||
ret = dfu_target_parse_sectors (target, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (ret);
|
||||
tmp = _dfu_target_sectors_to_string (target);
|
||||
g_assert_cmpstr (tmp, ==, "");
|
||||
g_free (tmp);
|
||||
|
||||
/* no addresses */
|
||||
ret = dfu_target_parse_sectors (target, "@Flash3", &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (ret);
|
||||
tmp = _dfu_target_sectors_to_string (target);
|
||||
g_assert_cmpstr (tmp, ==, "");
|
||||
g_free (tmp);
|
||||
|
||||
/* one sector, no space */
|
||||
ret = dfu_target_parse_sectors (target, "@Internal Flash /0x08000000/2*001Ka", &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (ret);
|
||||
tmp = _dfu_target_sectors_to_string (target);
|
||||
g_assert_cmpstr (tmp, ==, "Zone:0, Sec#:0, Addr:0x08000000, Size:0x0400, Caps:0x1\n"
|
||||
"Zone:0, Sec#:0, Addr:0x08000400, Size:0x0400, Caps:0x1");
|
||||
g_free (tmp);
|
||||
|
||||
/* multiple sectors */
|
||||
ret = dfu_target_parse_sectors (target, "@Flash1 /0x08000000/2*001 Ka,4*001 Kg", &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (ret);
|
||||
tmp = _dfu_target_sectors_to_string (target);
|
||||
g_assert_cmpstr (tmp, ==, "Zone:0, Sec#:0, Addr:0x08000000, Size:0x0400, Caps:0x1\n"
|
||||
"Zone:0, Sec#:0, Addr:0x08000400, Size:0x0400, Caps:0x1\n"
|
||||
"Zone:0, Sec#:1, Addr:0x08000000, Size:0x0400, Caps:0x7\n"
|
||||
"Zone:0, Sec#:1, Addr:0x08000400, Size:0x0400, Caps:0x7\n"
|
||||
"Zone:0, Sec#:1, Addr:0x08000800, Size:0x0400, Caps:0x7\n"
|
||||
"Zone:0, Sec#:1, Addr:0x08000c00, Size:0x0400, Caps:0x7");
|
||||
g_free (tmp);
|
||||
|
||||
/* non-contiguous */
|
||||
ret = dfu_target_parse_sectors (target, "@Flash2 /0xF000/4*100Ba/0xE000/3*8Kg/0x80000/2*24Kg", &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (ret);
|
||||
tmp = _dfu_target_sectors_to_string (target);
|
||||
g_assert_cmpstr (tmp, ==, "Zone:0, Sec#:0, Addr:0x0000f000, Size:0x0064, Caps:0x1\n"
|
||||
"Zone:0, Sec#:0, Addr:0x0000f064, Size:0x0064, Caps:0x1\n"
|
||||
"Zone:0, Sec#:0, Addr:0x0000f0c8, Size:0x0064, Caps:0x1\n"
|
||||
"Zone:0, Sec#:0, Addr:0x0000f12c, Size:0x0064, Caps:0x1\n"
|
||||
"Zone:1, Sec#:0, Addr:0x0000e000, Size:0x2000, Caps:0x7\n"
|
||||
"Zone:1, Sec#:0, Addr:0x00010000, Size:0x2000, Caps:0x7\n"
|
||||
"Zone:1, Sec#:0, Addr:0x00012000, Size:0x2000, Caps:0x7\n"
|
||||
"Zone:2, Sec#:0, Addr:0x00080000, Size:0x6000, Caps:0x7\n"
|
||||
"Zone:2, Sec#:0, Addr:0x00086000, Size:0x6000, Caps:0x7");
|
||||
g_free (tmp);
|
||||
|
||||
/* invalid */
|
||||
ret = dfu_target_parse_sectors (target, "Flash", NULL);
|
||||
g_assert (ret);
|
||||
ret = dfu_target_parse_sectors (target, "@Internal Flash /0x08000000", NULL);
|
||||
g_assert (!ret);
|
||||
ret = dfu_target_parse_sectors (target, "@Internal Flash /0x08000000/12*001a", NULL);
|
||||
g_assert (!ret);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
@ -470,6 +571,7 @@ main (int argc, char **argv)
|
||||
|
||||
/* tests go here */
|
||||
g_test_add_func ("/libdfu/enums", dfu_enums_func);
|
||||
g_test_add_func ("/libdfu/target(DfuSe}", dfu_target_dfuse_func);
|
||||
g_test_add_func ("/libdfu/firmware{raw}", dfu_firmware_raw_func);
|
||||
g_test_add_func ("/libdfu/firmware{dfu}", dfu_firmware_dfu_func);
|
||||
g_test_add_func ("/libdfu/firmware{dfuse}", dfu_firmware_dfuse_func);
|
||||
|
@ -36,6 +36,11 @@ gboolean _dfu_target_update (DfuTarget *target,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
/* export this just for the self tests */
|
||||
gboolean dfu_target_parse_sectors (DfuTarget *target,
|
||||
const gchar *alt_name,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __DFU_TARGET_PRIVATE_H */
|
||||
|
1121
libdfu/dfu-target.c
1121
libdfu/dfu-target.c
File diff suppressed because it is too large
Load Diff
@ -90,6 +90,7 @@ gboolean dfu_target_close (DfuTarget *target,
|
||||
DfuMode dfu_target_get_mode (DfuTarget *target);
|
||||
DfuState dfu_target_get_state (DfuTarget *target);
|
||||
DfuStatus dfu_target_get_status (DfuTarget *target);
|
||||
GPtrArray *dfu_target_get_sectors (DfuTarget *target);
|
||||
gboolean dfu_target_can_upload (DfuTarget *target);
|
||||
gboolean dfu_target_can_download (DfuTarget *target);
|
||||
gboolean dfu_target_refresh (DfuTarget *target,
|
||||
@ -105,7 +106,6 @@ gboolean dfu_target_clear_status (DfuTarget *target,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
DfuImage *dfu_target_upload (DfuTarget *target,
|
||||
gsize expected_size,
|
||||
DfuTargetTransferFlags flags,
|
||||
GCancellable *cancellable,
|
||||
DfuProgressCallback progress_cb,
|
||||
|
@ -861,7 +861,7 @@ dfu_tool_upload_target (DfuToolPrivate *priv, gchar **values, GError **error)
|
||||
helper.last_state = DFU_STATE_DFU_ERROR;
|
||||
helper.marks_total = 30;
|
||||
helper.marks_shown = 0;
|
||||
image = dfu_target_upload (target, 0, flags, NULL,
|
||||
image = dfu_target_upload (target, flags, NULL,
|
||||
fu_tool_transfer_progress_cb, &helper,
|
||||
error);
|
||||
if (image == NULL)
|
||||
@ -928,7 +928,7 @@ dfu_tool_upload (DfuToolPrivate *priv, gchar **values, GError **error)
|
||||
helper.last_state = DFU_STATE_DFU_ERROR;
|
||||
helper.marks_total = 30;
|
||||
helper.marks_shown = 0;
|
||||
firmware = dfu_device_upload (device, 0, flags, NULL,
|
||||
firmware = dfu_device_upload (device, flags, NULL,
|
||||
fu_tool_transfer_progress_cb, &helper,
|
||||
error);
|
||||
if (firmware == NULL)
|
||||
@ -1181,6 +1181,7 @@ dfu_tool_list_target (DfuTarget *target)
|
||||
{
|
||||
const gchar *tmp;
|
||||
gboolean ret;
|
||||
guint i;
|
||||
g_autofree gchar *alt_id = NULL;
|
||||
g_autoptr(GError) error_local = NULL;
|
||||
|
||||
@ -1199,6 +1200,7 @@ dfu_tool_list_target (DfuTarget *target)
|
||||
DFU_TARGET_OPEN_FLAG_NONE,
|
||||
NULL, &error_local);
|
||||
if (ret) {
|
||||
GPtrArray *sectors;
|
||||
tmp = dfu_status_to_string (dfu_target_get_status (target));
|
||||
/* TRANSLATORS: device status, e.g. "OK" */
|
||||
dfu_tool_print_indent (_("Status"), tmp, 2);
|
||||
@ -1206,6 +1208,19 @@ dfu_tool_list_target (DfuTarget *target)
|
||||
tmp = dfu_state_to_string (dfu_target_get_state (target));
|
||||
/* TRANSLATORS: device state, i.e. appIDLE */
|
||||
dfu_tool_print_indent (_("State"), tmp, 2);
|
||||
|
||||
/* print sector information */
|
||||
sectors = dfu_target_get_sectors (target);
|
||||
for (i = 0; i < sectors->len; i++) {
|
||||
DfuSector *sector;
|
||||
g_autofree gchar *msg = NULL;
|
||||
g_autofree gchar *title = NULL;
|
||||
sector = g_ptr_array_index (sectors, i);
|
||||
msg = dfu_sector_to_string (sector);
|
||||
/* TRANSLATORS: these are areas of memory on the chip */
|
||||
title = g_strdup_printf ("%s 0x%02x", _("Region"), i);
|
||||
dfu_tool_print_indent (title, msg, 3);
|
||||
}
|
||||
} else {
|
||||
if (g_error_matches (error_local,
|
||||
DFU_ERROR,
|
||||
@ -1217,6 +1232,7 @@ dfu_tool_list_target (DfuTarget *target)
|
||||
dfu_tool_print_indent (_("Status"), error_local->message, 2);
|
||||
}
|
||||
}
|
||||
|
||||
dfu_target_close (target, NULL);
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <libdfu/dfu-error.h>
|
||||
#include <libdfu/dfu-firmware.h>
|
||||
#include <libdfu/dfu-image.h>
|
||||
#include <libdfu/dfu-sector.h>
|
||||
#include <libdfu/dfu-target.h>
|
||||
|
||||
#undef __DFU_H_INSIDE__
|
||||
|
@ -417,7 +417,6 @@ fu_provider_usb_verify (FuProvider *provider,
|
||||
|
||||
/* get data from hardware */
|
||||
dfu_firmware = dfu_device_upload (dfu_device,
|
||||
0,
|
||||
DFU_TARGET_TRANSFER_FLAG_DETACH |
|
||||
DFU_TARGET_TRANSFER_FLAG_BOOT_RUNTIME,
|
||||
NULL,
|
||||
|
Loading…
Reference in New Issue
Block a user