Reorganize stlink-gui and update README, add building gui with Travis CI on linux
authorJerry Jacobs <jerry.jacobs@xor-gate.org>
Wed, 11 May 2016 05:33:41 +0000 (07:33 +0200)
committerJerry Jacobs <jerry.jacobs@dualinventive.com>
Wed, 11 May 2016 10:03:56 +0000 (12:03 +0200)
13 files changed:
.travis.sh
CMakeLists.txt
Makefile.am
README
configure.ac
gui/Makefile.am [deleted file]
gui/stlink-gui.c [deleted file]
gui/stlink-gui.h [deleted file]
gui/stlink-gui.ui [deleted file]
src/tools/gui/Makefile.am [new file with mode: 0644]
src/tools/gui/stlink-gui.c [new file with mode: 0644]
src/tools/gui/stlink-gui.h [new file with mode: 0644]
src/tools/gui/stlink-gui.ui [new file with mode: 0644]

index 6b69c638ac94fc639c842137de4d59f1f2899e64..13d2c1dcdbc4e8ae08ec0c43496d55f8554d9052 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/bash
 if [ "$TRAVIS_OS_NAME" != "osx" ]; then
        sudo apt-get update -qq || true
-       sudo apt-get install -qq -y --no-install-recommends libusb-1.0.0-dev
+       sudo apt-get install -qq -y --no-install-recommends libusb-1.0.0-dev libgtk-3-dev
 else
        brew install libusb
 fi
@@ -13,6 +13,10 @@ if [ "$BUILD_SYSTEM" == "cmake" ]; then
        make
 else
        ./autogen.sh
-       ./configure
+       if [ "$TRAVIS_OS_NAME" == "osx" ]; then
+               ./configure
+       else
+               ./configure --with-gtk-gui
+       fi
        make
 fi
index f75ce611db9ac5aede84b3f3ddf200c9775f59a3..1c56ed49d4cb8c825c9bf2aae2414046a2938f2d 100644 (file)
@@ -97,8 +97,8 @@ endif()
 
 if(gtk_FOUND)
   include_directories(${gtk_INCLUDE_DIRS})
-  set(GUI_SOURCES gui/stlink-gui.c
-                  gui/stlink-gui.h)
+  set(GUI_SOURCES src/tools/gui/stlink-gui.c
+                  src/tools/gui/stlink-gui.h)
 
   add_executable(stlink-gui-local ${GUI_SOURCES})
   set_target_properties(stlink-gui-local PROPERTIES
@@ -113,6 +113,6 @@ if(gtk_FOUND)
 
   install(TARGETS stlink-gui
           RUNTIME DESTINATION bin)
-  install(FILES gui/stlink-gui.ui
+  install(FILES src/tools/gui/stlink-gui.ui
           DESTINATION ${INSTALLED_UI_DIR})
 endif()
index fc95184bc738b636bf0e9285ae6d6c603bf7f83a..7494913aca2002e57d171fa06ce5ee78e0c6a3e5 100644 (file)
@@ -1,6 +1,6 @@
 # Makefile.am -- Process this file with automake to produce Makefile.in
 
-SUBDIRS = . $(MAYBE_GUI)
+SUBDIRS = . $(STLINK_HAS_GUI)
 
 AUTOMAKE_OPTIONS = subdir-objects
 
diff --git a/README b/README
index 90bc0849de74afb1c9f32add6c6a1c5e9b883afc..89bb188c9c378b2c69087eede977792ba6715f04 100644 (file)
--- a/README
+++ b/README
@@ -21,6 +21,7 @@ Two different transport layers are used:
 
 * `pkg-config`
 * `libusb-1.0` (plus development headers for building, on debian based distros `libusb-1.0.0-dev` package)
+* (optional) for `stlink-gui` we need libgtk-3-dev
 
 ## For STLINKv1
 
@@ -48,7 +49,7 @@ following steps will build the project for you.
 
 ```
 $ ./autogen.sh
-$ ./configure
+$ ./configure --with-gtk-gui
 $ make
 ```
 
index f374717401835065314c9445c2fde5ca6ac5b2cb..7a101d55dd6fba36b2c0141c731ad14472da607d 100644 (file)
@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.61)
-AC_INIT([stlink],[0.5.6],[davem@devkitpro.org])
+AC_INIT([stlink],[1.2.0],[davem@devkitpro.org])
 AC_CONFIG_SRCDIR([src/common.c])
 AC_CONFIG_LIBOBJ_DIR([src])
 AM_INIT_AUTOMAKE([1.10])
@@ -44,15 +44,15 @@ case "${host}" in
                AM_CONDITIONAL(MINGW, false)
 esac
 
-MAYBE_GUI=
-AC_ARG_WITH([gtk], AS_HELP_STRING([--with-gtk], [enable GTK+ gui]))
-if test "x$with_gtk" = "xyes"; then
-      PKG_CHECK_MODULES([GTK], [gtk+-3.0])
+STLINK_HAS_GUI=
+AC_ARG_WITH([gtk_gui], AS_HELP_STRING([--with-gtk-gui], [enable GTK3+ gui]))
+if test "x$with_gtk_gui" = "xyes"; then
+      PKG_CHECK_MODULES([GTK3], [gtk+-3.0])
       PKG_CHECK_MODULES([GLIB], [glib-2.0 > 2.32.0])
-      MAYBE_GUI=gui
-      AC_CONFIG_FILES([gui/Makefile])
+      STLINK_HAS_GUI=src/tools/gui
+      AC_CONFIG_FILES([src/tools/gui/Makefile])
 fi
-AC_SUBST([MAYBE_GUI])
+AC_SUBST([STLINK_HAS_GUI])
 
 AC_CONFIG_FILES([Makefile])
 AC_OUTPUT
diff --git a/gui/Makefile.am b/gui/Makefile.am
deleted file mode 100644 (file)
index 97b780e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-bin_PROGRAMS = stlink-gui
-
-stlink_gui_SOURCES = \
-       stlink-gui.c \
-       stlink-gui.h
-
-stlink_gui_CPPFLAGS = \
-       -I$(top_srcdir) \
-       $(AM_CPPFLAGS) \
-       -I$(top_srcdir)/src \
-       @GTK_CFLAGS@
-
-stlink_gui_CFLAGS = \
-       $(WARN_CFLAGS) \
-       $(AM_CFLAGS) \
-       -DSTLINK_UI_DIR="\"$(uidir)\""
-
-stlink_gui_LDFLAGS =  \
-       $(AM_LDFLAGS)
-
-stlink_gui_LDADD = \
-       $(INTLLIBS) \
-       $(top_builddir)/libstlink.a \
-       @GTK_LIBS@
-
-uidir = $(pkgdatadir)/ui
-ui_DATA = stlink-gui.ui
-EXTRA_DIST = $(ui_DATA)
-
--include $(top_srcdir)/git.mk
diff --git a/gui/stlink-gui.c b/gui/stlink-gui.c
deleted file mode 100644 (file)
index 93f92c4..0000000
+++ /dev/null
@@ -1,955 +0,0 @@
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <gtk/gtk.h>
-
-#include "stlink-common.h"
-#include "stlink-gui.h"
-
-#define MEM_READ_SIZE 1024
-
-#ifndef G_VALUE_INIT
-#define G_VALUE_INIT {0, {{0}}}
-#endif
-
-G_DEFINE_TYPE (STlinkGUI, stlink_gui, G_TYPE_OBJECT);
-
-static void
-stlink_gui_dispose (GObject *gobject)
-{
-    G_OBJECT_CLASS (stlink_gui_parent_class)->dispose (gobject);
-}
-
-static void
-stlink_gui_finalize (GObject *gobject)
-{
-    G_OBJECT_CLASS (stlink_gui_parent_class)->finalize (gobject);
-}
-
-static void
-stlink_gui_class_init (STlinkGUIClass *klass)
-{
-    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
-    gobject_class->dispose  = stlink_gui_dispose;
-    gobject_class->finalize = stlink_gui_finalize;
-}
-
-static void
-stlink_gui_init (STlinkGUI *self)
-{
-    self->sl       = NULL;
-    self->filename = NULL;
-
-    self->progress.activity_mode = FALSE;
-    self->progress.fraction      = 0;
-
-    self->flash_mem.memory = NULL;
-    self->flash_mem.size   = 0;
-    self->flash_mem.base   = 0;
-
-    self->file_mem.memory = NULL;
-    self->file_mem.size   = 0;
-    self->file_mem.base   = 0;
-}
-
-static gboolean
-set_info_error_message_idle (STlinkGUI *gui)
-{
-    if (gui->error_message != NULL) {
-        gchar *markup;
-
-        markup = g_markup_printf_escaped ("<b>%s</b>", gui->error_message);
-        gtk_label_set_markup (gui->infolabel, markup);
-        gtk_info_bar_set_message_type (gui->infobar, GTK_MESSAGE_ERROR);
-        gtk_widget_show (GTK_WIDGET (gui->infobar));
-
-        g_free (markup);
-        g_free (gui->error_message);
-        gui->error_message = NULL;
-    }
-    return FALSE;
-}
-
-static void
-stlink_gui_set_info_error_message (STlinkGUI *gui, const gchar *message)
-{
-    gui->error_message = g_strdup (message);
-    g_idle_add ((GSourceFunc) set_info_error_message_idle, gui);
-}
-
-static void
-stlink_gui_set_sensitivity (STlinkGUI *gui, gboolean sensitivity)
-{
-    gtk_widget_set_sensitive (GTK_WIDGET (gui->open_button), sensitivity);
-
-    if (sensitivity && gui->sl)
-        gtk_widget_set_sensitive (GTK_WIDGET (gui->disconnect_button), sensitivity);
-
-    if (sensitivity && !gui->sl)
-        gtk_widget_set_sensitive (GTK_WIDGET (gui->connect_button), sensitivity);
-
-    if (sensitivity && gui->sl && gui->filename)
-        gtk_widget_set_sensitive (GTK_WIDGET (gui->flash_button), sensitivity);
-}
-
-static void
-mem_view_init_headers (GtkTreeView *view)
-{
-    GtkCellRenderer *renderer;
-    gint             i;
-
-    g_return_if_fail (view != NULL);
-
-    renderer = gtk_cell_renderer_text_new ();
-    gtk_tree_view_insert_column_with_attributes (view,
-            -1,
-            "Address",
-            renderer,
-            "text",
-            0, /* column */
-            NULL);
-    for (i = 0; i < 4; i++) {
-        gchar *label;
-
-        label = g_strdup_printf ("%X", i * 4);
-        renderer = gtk_cell_renderer_text_new ();
-        gtk_tree_view_insert_column_with_attributes (view,
-                -1,
-                label,
-                renderer,
-                "text",
-                (i + 1), /* column */
-                NULL);
-        g_free (label);
-    }
-
-    for (i = 0; i < 5; i++) {
-        GtkTreeViewColumn *column = gtk_tree_view_get_column (view, i);
-        gtk_tree_view_column_set_expand (column, TRUE);
-    }
-}
-
-static void
-mem_view_add_as_hex (GtkListStore *store,
-                     GtkTreeIter  *iter,
-                     gint          column,
-                     guint32       value)
-{
-    gchar     *hex_str;
-
-    hex_str = g_strdup_printf ("0x%08X", value);
-    gtk_list_store_set (store, iter, column, hex_str, -1);
-    g_free (hex_str);
-}
-
-static void
-mem_view_add_buffer (GtkListStore *store,
-                     GtkTreeIter  *iter,
-                     guint32       address,
-                     guchar       *buffer,
-                     gint          len)
-{
-    guint32 *word;
-    gint     i, step;
-    gint     column = 0;
-
-    step = sizeof (*word);
-
-    for (i = 0; i < len; i += step) {
-        word = (guint *) &buffer[i];
-
-        if (column == 0) {
-            /* new row */
-            gtk_list_store_append (store, iter);
-
-            /* add address */
-            mem_view_add_as_hex (store, iter, column, (address + i));
-        }
-        mem_view_add_as_hex (store, iter, (column + 1), *word);
-        column = (column + 1) % step;
-    }
-}
-
-static guint32
-hexstr_to_guint32 (const gchar *str, GError **err)
-{
-    guint32  val;
-    gchar   *end_ptr;
-
-    val = strtoul (str, &end_ptr, 16);
-    if ((errno == ERANGE && val == LONG_MAX) || (errno != 0 && val == 0)) {
-        g_set_error (err,
-                g_quark_from_string ("hextou32"),
-                1,
-                "Invalid hexstring");
-        return LONG_MAX;
-    }
-    if (end_ptr == str) {
-        g_set_error (err,
-                g_quark_from_string ("hextou32"),
-                2,
-                "Invalid hexstring");
-        return LONG_MAX;
-    }
-    return val;
-}
-
-
-static void
-stlink_gui_update_mem_view (STlinkGUI *gui, struct mem_t *mem, GtkTreeView *view) {
-    GtkListStore *store;
-    GtkTreeIter   iter;
-
-    store = GTK_LIST_STORE (gtk_tree_view_get_model (view));
-
-    mem_view_add_buffer (store,
-            &iter,
-            mem->base,
-            mem->memory,
-            mem->size);
-
-    gtk_widget_hide (GTK_WIDGET (gui->progress.bar));
-    gtk_progress_bar_set_fraction (gui->progress.bar, 0);
-    stlink_gui_set_sensitivity (gui, TRUE);
-}
-
-static gboolean
-stlink_gui_update_devmem_view (STlinkGUI *gui)
-{
-    stlink_gui_update_mem_view (gui, &gui->flash_mem, gui->devmem_treeview);
-    return FALSE;
-}
-
-
-static void
-stlink_gui_populate_devmem_view (STlinkGUI *gui)
-{
-    guint            off;
-    stm32_addr_t     addr;
-
-    g_return_if_fail (gui != NULL);
-    g_return_if_fail (gui->sl != NULL);
-
-    addr = gui->sl->flash_base;
-
-    if (gui->flash_mem.memory) {
-        g_free (gui->flash_mem.memory);
-    }
-    gui->flash_mem.memory = g_malloc (gui->sl->flash_size);
-    gui->flash_mem.size   = gui->sl->flash_size;
-    gui->flash_mem.base   = gui->sl->flash_base;
-
-    for (off = 0; off < gui->sl->flash_size; off += MEM_READ_SIZE) {
-        guint   n_read = MEM_READ_SIZE;
-
-        if (off + MEM_READ_SIZE > gui->sl->flash_size) {
-            n_read = gui->sl->flash_size - off;
-
-            /* align if needed */
-            if (n_read & 3) {
-                n_read = (n_read + 4) & ~(3);
-            }
-        }
-        /* reads to sl->q_buf */
-        stlink_read_mem32(gui->sl, addr + off, n_read);
-        if (gui->sl->q_len < 0) {
-            stlink_gui_set_info_error_message (gui, "Failed to read memory");
-            g_free (gui->flash_mem.memory);
-            gui->flash_mem.memory = NULL;
-            return;
-        }
-        memcpy (gui->flash_mem.memory + off, gui->sl->q_buf, n_read);
-        gui->progress.fraction = (gdouble) (off + n_read) / gui->sl->flash_size;
-    }
-    g_idle_add ((GSourceFunc) stlink_gui_update_devmem_view, gui);
-}
-
-static gboolean
-stlink_gui_update_filemem_view (STlinkGUI *gui)
-{
-    gchar *basename;
-
-    basename = g_path_get_basename (gui->filename);
-    gtk_notebook_set_tab_label_text (gui->notebook,
-            GTK_WIDGET (gtk_notebook_get_nth_page (gui->notebook, 1)),
-            basename);
-    g_free (basename);
-
-    stlink_gui_update_mem_view (gui, &gui->file_mem, gui->filemem_treeview);
-
-    return FALSE;
-}
-
-static gpointer
-stlink_gui_populate_filemem_view (STlinkGUI *gui)
-{
-    guchar        buffer[MEM_READ_SIZE];
-    GFile        *file;
-    GFileInfo    *file_info;
-    GInputStream *input_stream;
-    gint          off;
-    GError       *err = NULL;
-
-    g_return_val_if_fail (gui != NULL, NULL);
-    g_return_val_if_fail (gui->filename != NULL, NULL);
-
-    file = g_file_new_for_path (gui->filename);
-    input_stream = G_INPUT_STREAM (g_file_read (file, NULL, &err));
-    if (err) {
-        stlink_gui_set_info_error_message (gui, err->message);
-        g_error_free (err);
-        goto out;
-    }
-
-    file_info = g_file_input_stream_query_info (G_FILE_INPUT_STREAM (input_stream),
-            G_FILE_ATTRIBUTE_STANDARD_SIZE, NULL, &err);
-    if (err) {
-        stlink_gui_set_info_error_message (gui, err->message);
-        g_error_free (err);
-        goto out_input;
-    }
-    if (gui->file_mem.memory) {
-        g_free (gui->file_mem.memory);
-    }
-    gui->file_mem.size   = g_file_info_get_size (file_info);
-    gui->file_mem.memory = g_malloc (gui->file_mem.size);
-
-    for (off = 0; off < gui->file_mem.size; off += MEM_READ_SIZE) {
-        guint   n_read = MEM_READ_SIZE;
-
-        if (off + MEM_READ_SIZE > gui->file_mem.size) {
-            n_read = gui->file_mem.size - off;
-        }
-
-        if (g_input_stream_read (G_INPUT_STREAM (input_stream),
-                    &buffer, n_read, NULL, &err) == -1) {
-            stlink_gui_set_info_error_message (gui, err->message);
-            g_error_free (err);
-            goto out_input;
-        }
-        memcpy (gui->file_mem.memory + off, buffer, n_read);
-        gui->progress.fraction = (gdouble) (off + n_read) / gui->file_mem.size;
-    }
-    g_idle_add ((GSourceFunc) stlink_gui_update_filemem_view, gui);
-
-out_input:
-    g_object_unref (input_stream);
-out:
-    g_object_unref (file);
-    return NULL;
-}
-
-static void mem_jmp (GtkTreeView *view,
-                     GtkEntry    *entry,
-                     guint32      base_addr,
-                     gsize        size,
-                     GError     **err)
-{
-    GtkTreeModel *model;
-    guint32       jmp_addr;
-    GtkTreeIter   iter;
-
-    jmp_addr = hexstr_to_guint32 (gtk_entry_get_text (entry), err);
-    if (err && *err) {
-        return;
-    }
-
-    if (jmp_addr < base_addr || jmp_addr > base_addr + size) {
-        g_set_error (err,
-                g_quark_from_string ("mem_jmp"),
-                1,
-                "Invalid address");
-        return;
-    }
-
-    model = gtk_tree_view_get_model (view);
-    if (!model) {
-        return;
-    }
-
-    if (gtk_tree_model_get_iter_first (model, &iter)) {
-        do {
-            guint32 addr;
-            GValue  value = G_VALUE_INIT;
-            GError *err   = NULL;
-
-            gtk_tree_model_get_value (model, &iter, 0, &value);
-            if (G_VALUE_HOLDS_STRING (&value)) {
-                addr = hexstr_to_guint32 (g_value_get_string (&value), &err);
-                if (!err) {
-                    if (addr == (jmp_addr & 0xFFFFFFF0)) {
-                        GtkTreeSelection *selection;
-                        GtkTreePath      *path;
-
-                        selection = gtk_tree_view_get_selection (view);
-                        path      = gtk_tree_model_get_path (model, &iter);
-
-                        gtk_tree_selection_select_iter (selection, &iter);
-                        gtk_tree_view_scroll_to_cell (view,
-                                path,
-                                NULL,
-                                TRUE,
-                                0.0,
-                                0.0);
-                        gtk_tree_path_free (path);
-                    }
-                }
-            }
-            g_value_unset (&value);
-        } while (gtk_tree_model_iter_next (model, &iter));
-    }
-}
-
-static void
-devmem_jmp_cb (GtkWidget *widget, gpointer data)
-{
-    STlinkGUI *gui;
-    GError    *err = NULL;
-
-    gui = STLINK_GUI (data);
-
-    mem_jmp (gui->devmem_treeview,
-            gui->devmem_jmp_entry,
-            gui->sl->flash_base,
-            gui->sl->flash_size,
-            &err);
-
-    if (err) {
-        stlink_gui_set_info_error_message (gui, err->message);
-        g_error_free (err);
-    }
-}
-
-static void
-filemem_jmp_cb (GtkWidget *widget, gpointer data)
-{
-    STlinkGUI *gui;
-    GError    *err = NULL;
-
-    gui = STLINK_GUI (data);
-
-    g_return_if_fail (gui->filename != NULL);
-
-    mem_jmp (gui->filemem_treeview,
-            gui->filemem_jmp_entry,
-            0,
-            gui->file_mem.size,
-            &err);
-
-    if (err) {
-        stlink_gui_set_info_error_message (gui, err->message);
-        g_error_free (err);
-    }
-}
-
-static gchar *
-dev_format_chip_id (guint32 chip_id)
-{
-    gint i;
-
-    for (i = 0; i < sizeof (devices) / sizeof (devices[0]); i++) {
-        if (chip_id == devices[i].chip_id) {
-            return g_strdup (devices[i].description);
-        }
-    }
-    return g_strdup_printf ("0x%x", chip_id);
-}
-
-static gchar *
-dev_format_mem_size (gsize flash_size)
-{
-    return g_strdup_printf ("%u kB", flash_size / 1024);
-}
-
-
-static void
-stlink_gui_set_connected (STlinkGUI *gui)
-{
-    gchar        *tmp_str;
-    GtkListStore *store;
-    GtkTreeIter   iter;
-
-    gtk_statusbar_push (gui->statusbar,
-            gtk_statusbar_get_context_id (gui->statusbar, "conn"),
-            "Connected");
-
-    gtk_widget_set_sensitive (GTK_WIDGET (gui->device_frame), TRUE);
-    gtk_widget_set_sensitive (GTK_WIDGET (gui->devmem_box), TRUE);
-    gtk_widget_set_sensitive (GTK_WIDGET (gui->connect_button), FALSE);
-
-    if (gui->filename) {
-        gtk_widget_set_sensitive (GTK_WIDGET (gui->flash_button), TRUE);
-    }
-
-    tmp_str = dev_format_chip_id (gui->sl->chip_id);
-    gtk_label_set_text (gui->chip_id_label, tmp_str);
-    g_free (tmp_str);
-
-    tmp_str = g_strdup_printf ("0x%x", gui->sl->core_id);
-    gtk_label_set_text (gui->core_id_label, tmp_str);
-    g_free (tmp_str);
-
-    tmp_str = dev_format_mem_size (gui->sl->flash_size);
-    gtk_label_set_text (gui->flash_size_label, tmp_str);
-    g_free (tmp_str);
-
-    tmp_str = dev_format_mem_size (gui->sl->sram_size);
-    gtk_label_set_text (gui->ram_size_label, tmp_str);
-    g_free (tmp_str);
-
-    tmp_str = g_strdup_printf ("0x%08X", gui->sl->flash_base);
-    gtk_entry_set_text (gui->devmem_jmp_entry, tmp_str);
-    gtk_editable_set_editable (GTK_EDITABLE (gui->devmem_jmp_entry), TRUE);
-    g_free (tmp_str);
-
-    store = GTK_LIST_STORE (gtk_tree_view_get_model (gui->devmem_treeview));
-    if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) {
-        gtk_list_store_clear (store);
-    }
-
-    stlink_gui_set_sensitivity (gui, FALSE);
-    gtk_notebook_set_current_page (gui->notebook, PAGE_DEVMEM);
-    gtk_widget_show (GTK_WIDGET (gui->progress.bar));
-    gtk_progress_bar_set_text (gui->progress.bar, "Reading memory");
-
-    g_thread_new ("devmem", (GThreadFunc) stlink_gui_populate_devmem_view, gui);
-}
-
-static void
-connect_button_cb (GtkWidget *widget, gpointer data)
-{
-    STlinkGUI *gui;
-    gint       i;
-
-    gui = STLINK_GUI (data);
-
-    if (gui->sl != NULL)
-        return;
-
-    /* try version 1 then version 2 */
-    gui->sl = stlink_v1_open(0, 1);
-    if (gui->sl == NULL) {
-           gui->sl = stlink_open_usb(0, 1, NULL);
-    }
-    if (gui->sl == NULL) {
-        stlink_gui_set_info_error_message (gui, "Failed to connect to STLink.");               return;
-    }
-
-    /* code below taken from flash/main.c, refactoring might be in order */
-    if (stlink_current_mode(gui->sl) == STLINK_DEV_DFU_MODE)
-        stlink_exit_dfu_mode(gui->sl);
-
-    if (stlink_current_mode(gui->sl) != STLINK_DEV_DEBUG_MODE)
-        stlink_enter_swd_mode(gui->sl);
-
-    /* Disable DMA - Set All DMA CCR Registers to zero. - AKS 1/7/2013 */
-    if (gui->sl->chip_id == STM32_CHIPID_F4) {
-        memset(gui->sl->q_buf, 0, 4);
-        for (i = 0; i < 8; i++) {
-            stlink_write_mem32(gui->sl, 0x40026000 + 0x10 + 0x18 * i, 4);
-            stlink_write_mem32(gui->sl, 0x40026400 + 0x10 + 0x18 * i, 4);
-            stlink_write_mem32(gui->sl, 0x40026000 + 0x24 + 0x18 * i, 4);
-            stlink_write_mem32(gui->sl, 0x40026400 + 0x24 + 0x18 * i, 4);
-        }
-    }
-    stlink_gui_set_connected (gui);
-}
-
-static void stlink_gui_set_disconnected (STlinkGUI *gui)
-{
-    gtk_statusbar_push (gui->statusbar,
-            gtk_statusbar_get_context_id (gui->statusbar, "conn"),
-            "Disconnected");
-
-    gtk_widget_set_sensitive (GTK_WIDGET (gui->device_frame), FALSE);
-    gtk_widget_set_sensitive (GTK_WIDGET (gui->flash_button), FALSE);
-    gtk_widget_set_sensitive (GTK_WIDGET (gui->disconnect_button), FALSE);
-    gtk_widget_set_sensitive (GTK_WIDGET (gui->connect_button), TRUE);
-}
-
-static void
-disconnect_button_cb (GtkWidget *widget, gpointer data)
-{
-    STlinkGUI *gui;
-
-    gui = STLINK_GUI (data);
-
-    if (gui->sl != NULL) {
-        stlink_exit_debug_mode(gui->sl);
-        stlink_close(gui->sl);
-        gui->sl = NULL;
-    }
-    stlink_gui_set_disconnected (gui);
-}
-
-
-static void
-stlink_gui_open_file (STlinkGUI *gui)
-{
-    GtkWidget    *dialog;
-    GtkListStore *store;
-    GtkTreeIter   iter;
-
-    dialog = gtk_file_chooser_dialog_new ("Open file",
-            gui->window,
-            GTK_FILE_CHOOSER_ACTION_OPEN,
-            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-            GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
-            NULL);
-
-    if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
-        gui->filename =
-            gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
-
-        store = GTK_LIST_STORE (gtk_tree_view_get_model (gui->filemem_treeview));
-        if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) {
-            gtk_list_store_clear (store);
-        }
-
-        stlink_gui_set_sensitivity (gui, FALSE);
-        gtk_notebook_set_current_page (gui->notebook, PAGE_FILEMEM);
-        gtk_widget_show (GTK_WIDGET (gui->progress.bar));
-        gtk_progress_bar_set_text (gui->progress.bar, "Reading file");
-        g_thread_new ("file", (GThreadFunc) stlink_gui_populate_filemem_view, gui);
-    }
-    gtk_widget_destroy (dialog);
-}
-
-static void
-open_button_cb (GtkWidget *widget, gpointer data)
-{
-    STlinkGUI    *gui;
-
-    gui = STLINK_GUI (data);
-
-    stlink_gui_open_file (gui);
-}
-
-static gboolean
-stlink_gui_write_flash_update (STlinkGUI *gui)
-{
-    stlink_gui_set_sensitivity (gui, TRUE);
-    gui->progress.activity_mode = FALSE;
-    gtk_widget_hide (GTK_WIDGET (gui->progress.bar));
-
-    return FALSE;
-}
-
-static void
-stlink_gui_write_flash (STlinkGUI *gui)
-{
-    g_return_if_fail (gui->sl != NULL);
-    g_return_if_fail (gui->filename != NULL);
-
-    if (stlink_fwrite_flash(gui->sl, gui->filename, gui->sl->flash_base) < 0) {
-        stlink_gui_set_info_error_message (gui, "Failed to write to flash");
-    }
-
-    g_idle_add ((GSourceFunc) stlink_gui_write_flash_update, gui);
-}
-
-static void
-flash_button_cb (GtkWidget *widget, gpointer data)
-{
-    STlinkGUI *gui;
-    gchar     *tmp_str;
-    guint32    address;
-    gint       result;
-    GError    *err = NULL;
-
-    gui = STLINK_GUI (data);
-    g_return_if_fail (gui->sl != NULL);
-
-    if (!g_strcmp0 (gtk_entry_get_text (gui->flash_dialog_entry), "")) {
-        tmp_str = g_strdup_printf ("0x%08X", gui->sl->flash_base);
-        gtk_entry_set_text (gui->flash_dialog_entry, tmp_str);
-        g_free (tmp_str);
-    }
-
-    result = gtk_dialog_run (gui->flash_dialog);
-    if (result == GTK_RESPONSE_OK) {
-        address = hexstr_to_guint32 (gtk_entry_get_text (gui->flash_dialog_entry),
-                &err);
-        if (err) {
-            stlink_gui_set_info_error_message (gui, err->message);
-        } else {
-            if (address > gui->sl->flash_base + gui->sl->flash_size ||
-                    address < gui->sl->flash_base) {
-                stlink_gui_set_info_error_message (gui, "Invalid address");
-            }
-            else if (address + gui->file_mem.size >
-                    gui->sl->flash_base + gui->sl->flash_size) {
-                stlink_gui_set_info_error_message (gui, "Binary overwrites flash");
-            } else {
-                stlink_gui_set_sensitivity (gui, FALSE);
-                gtk_progress_bar_set_text (gui->progress.bar,
-                        "Writing to flash");
-                gui->progress.activity_mode = TRUE;
-                gtk_widget_show (GTK_WIDGET (gui->progress.bar));
-                g_thread_new ("flash",
-                        (GThreadFunc) stlink_gui_write_flash, gui);
-            }
-        }
-    }
-}
-
-static gboolean
-progress_pulse_timeout (STlinkGUI *gui) {
-    if (gui->progress.activity_mode) {
-        gtk_progress_bar_pulse (gui->progress.bar);
-    } else {
-        gtk_progress_bar_set_fraction (gui->progress.bar, gui->progress.fraction);
-    }
-    return TRUE;
-}
-
-static void
-notebook_switch_page_cb (GtkNotebook *notebook,
-                         GtkWidget   *widget,
-                         guint        page_num,
-                         gpointer     data)
-{
-    STlinkGUI *gui;
-
-    gui = STLINK_GUI (data);
-
-    if (page_num == 1) {
-        if (gui->filename == NULL) {
-            stlink_gui_open_file (gui);
-        }
-    }
-}
-
-static void
-dnd_received_cb (GtkWidget *widget,
-                 GdkDragContext *context,
-                 gint x,
-                 gint y,
-                 GtkSelectionData *selection_data,
-                 guint target_type,
-                 guint time,
-                 gpointer data)
-{
-    GFile        *file_uri;
-    gchar       **file_list;
-    const guchar *file_data;
-    STlinkGUI    *gui = STLINK_GUI (data);
-    GtkListStore *store;
-    GtkTreeIter   iter;
-
-    if (selection_data != NULL &&
-            gtk_selection_data_get_length (selection_data) > 0) {
-        switch (target_type) {
-        case TARGET_FILENAME:
-
-            if (gui->filename) {
-                g_free (gui->filename);
-            }
-
-            file_data = gtk_selection_data_get_data (selection_data);
-            file_list = g_strsplit ((gchar *)file_data, "\r\n", 0);
-
-            file_uri = g_file_new_for_uri (file_list[0]);
-            gui->filename = g_file_get_path (file_uri);
-
-            g_strfreev (file_list);
-            g_object_unref (file_uri);
-
-
-            store = GTK_LIST_STORE (gtk_tree_view_get_model (gui->devmem_treeview));
-            if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) {
-                gtk_list_store_clear (store);
-            }
-
-            stlink_gui_set_sensitivity (gui, FALSE);
-            gtk_notebook_set_current_page (gui->notebook, PAGE_FILEMEM);
-            gtk_widget_show (GTK_WIDGET (gui->progress.bar));
-            gtk_progress_bar_set_text (gui->progress.bar, "Reading file");
-            g_thread_new ("file", (GThreadFunc) stlink_gui_populate_filemem_view, gui);
-            break;
-        }
-    }
-    gtk_drag_finish (context,
-                     TRUE,
-                     gdk_drag_context_get_suggested_action (context) == GDK_ACTION_MOVE,
-                     time);
-}
-
-void
-stlink_gui_init_dnd (STlinkGUI *gui)
-{
-    GtkTargetEntry target_list[] = {
-        { "text/uri-list", 0, TARGET_FILENAME },
-    };
-
-    gtk_drag_dest_set (GTK_WIDGET (gui->window),
-                       GTK_DEST_DEFAULT_ALL,
-                       target_list,
-                       G_N_ELEMENTS (target_list),
-                       GDK_ACTION_COPY);
-
-    g_signal_connect (gui->window, "drag-data-received",
-                      G_CALLBACK (dnd_received_cb), gui);
-}
-
-static void
-stlink_gui_build_ui (STlinkGUI *gui) {
-    GtkBuilder   *builder;
-    GtkListStore *devmem_store;
-    GtkListStore *filemem_store;
-    gchar *ui_file = STLINK_UI_DIR "/stlink-gui.ui";
-
-    if (!g_file_test (ui_file, G_FILE_TEST_EXISTS)) {
-        ui_file = "stlink-gui.ui";
-    }
-    builder = gtk_builder_new ();
-    if (!gtk_builder_add_from_file (builder, ui_file, NULL)) {
-        g_printerr ("Failed to load UI file: %s\n", ui_file);
-        exit (1);
-    }
-
-    gui->window = GTK_WINDOW (gtk_builder_get_object (builder, "window"));
-    g_signal_connect (G_OBJECT (gui->window), "destroy",
-            G_CALLBACK (gtk_main_quit), NULL);
-
-    /* set up toolutton clicked callbacks */
-    gui->open_button =
-        GTK_TOOL_BUTTON (gtk_builder_get_object (builder, "open_button"));
-    g_signal_connect (G_OBJECT (gui->open_button), "clicked",
-            G_CALLBACK (open_button_cb), gui);
-
-    gui->connect_button =
-        GTK_TOOL_BUTTON (gtk_builder_get_object (builder, "connect_button"));
-    g_signal_connect (G_OBJECT (gui->connect_button), "clicked",
-            G_CALLBACK (connect_button_cb), gui);
-
-    gui->disconnect_button =
-        GTK_TOOL_BUTTON (gtk_builder_get_object (builder, "disconnect_button"));
-    g_signal_connect (G_OBJECT (gui->disconnect_button), "clicked",
-            G_CALLBACK (disconnect_button_cb), gui);
-
-    gui->flash_button =
-        GTK_TOOL_BUTTON (gtk_builder_get_object (builder, "flash_button"));
-    g_signal_connect (G_OBJECT (gui->flash_button), "clicked",
-            G_CALLBACK (flash_button_cb), gui);
-
-    gui->devmem_treeview =
-        GTK_TREE_VIEW (gtk_builder_get_object (builder, "devmem_treeview"));
-    gtk_tree_view_set_rules_hint (gui->devmem_treeview, TRUE);
-    mem_view_init_headers (gui->devmem_treeview);
-    devmem_store = gtk_list_store_new (5,
-            G_TYPE_STRING,
-            G_TYPE_STRING,
-            G_TYPE_STRING,
-            G_TYPE_STRING,
-            G_TYPE_STRING);
-    gtk_tree_view_set_model (gui->devmem_treeview, GTK_TREE_MODEL (devmem_store));
-    g_object_unref (devmem_store);
-
-    gui->filemem_treeview =
-        GTK_TREE_VIEW (gtk_builder_get_object (builder, "filemem_treeview"));
-    gtk_tree_view_set_rules_hint (gui->filemem_treeview, TRUE);
-    mem_view_init_headers (gui->filemem_treeview);
-    filemem_store = gtk_list_store_new (5,
-            G_TYPE_STRING,
-            G_TYPE_STRING,
-            G_TYPE_STRING,
-            G_TYPE_STRING,
-            G_TYPE_STRING);
-    gtk_tree_view_set_model (gui->filemem_treeview, GTK_TREE_MODEL (filemem_store));
-    g_object_unref (filemem_store);
-
-    gui->core_id_label =
-        GTK_LABEL (gtk_builder_get_object (builder, "core_id_value"));
-
-    gui->chip_id_label =
-        GTK_LABEL (gtk_builder_get_object (builder, "chip_id_value"));
-
-    gui->flash_size_label =
-        GTK_LABEL (gtk_builder_get_object (builder, "flash_size_value"));
-
-    gui->ram_size_label =
-        GTK_LABEL (gtk_builder_get_object (builder, "ram_size_value"));
-
-    gui->device_frame =
-        GTK_FRAME (gtk_builder_get_object (builder, "device_frame"));
-
-    gui->notebook =
-        GTK_NOTEBOOK (gtk_builder_get_object (builder, "mem_notebook"));
-    g_signal_connect (gui->notebook, "switch-page",
-            G_CALLBACK (notebook_switch_page_cb), gui);
-
-    gui->devmem_box =
-        GTK_BOX (gtk_builder_get_object (builder, "devmem_box"));
-
-    gui->filemem_box =
-        GTK_BOX (gtk_builder_get_object (builder, "filemem_box"));
-
-    gui->devmem_jmp_entry =
-        GTK_ENTRY (gtk_builder_get_object (builder, "devmem_jmp_entry"));
-    g_signal_connect (gui->devmem_jmp_entry, "activate",
-            G_CALLBACK (devmem_jmp_cb), gui);
-
-    gui->filemem_jmp_entry =
-        GTK_ENTRY (gtk_builder_get_object (builder, "filemem_jmp_entry"));
-    g_signal_connect (gui->filemem_jmp_entry, "activate",
-            G_CALLBACK (filemem_jmp_cb), gui);
-    gtk_editable_set_editable (GTK_EDITABLE (gui->filemem_jmp_entry), TRUE);
-
-    gui->progress.bar =
-        GTK_PROGRESS_BAR (gtk_builder_get_object (builder, "progressbar"));
-    gtk_progress_bar_set_show_text (gui->progress.bar, TRUE);
-    gui->progress.timer = g_timeout_add (100,
-            (GSourceFunc) progress_pulse_timeout,
-            gui);
-
-    gui->statusbar =
-        GTK_STATUSBAR (gtk_builder_get_object (builder, "statusbar"));
-
-    gui->infobar =
-        GTK_INFO_BAR (gtk_builder_get_object (builder, "infobar"));
-    gtk_info_bar_add_button (gui->infobar, GTK_STOCK_OK, GTK_RESPONSE_OK);
-    gui->infolabel = GTK_LABEL (gtk_label_new (""));
-    gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (gui->infobar)),
-            GTK_WIDGET (gui->infolabel));
-    g_signal_connect (gui->infobar, "response", G_CALLBACK (gtk_widget_hide), NULL);
-
-    /* flash dialog */
-    gui->flash_dialog =
-        GTK_DIALOG (gtk_builder_get_object (builder, "flash_dialog"));
-    g_signal_connect_swapped (gui->flash_dialog, "response",
-            G_CALLBACK (gtk_widget_hide), gui->flash_dialog);
-
-    gui->flash_dialog_ok =
-        GTK_BUTTON (gtk_builder_get_object (builder, "flash_dialog_ok_button"));
-
-    gui->flash_dialog_cancel =
-        GTK_BUTTON (gtk_builder_get_object (builder, "flash_dialog_cancel_button"));
-
-    gui->flash_dialog_entry =
-        GTK_ENTRY (gtk_builder_get_object (builder, "flash_dialog_entry"));
-
-    /* make it so */
-    gtk_widget_show_all (GTK_WIDGET (gui->window));
-    gtk_widget_hide (GTK_WIDGET (gui->infobar));
-    gtk_widget_hide (GTK_WIDGET (gui->progress.bar));
-
-    stlink_gui_set_disconnected (gui);
-}
-
-int
-main (int argc, char **argv)
-{
-    STlinkGUI *gui;
-
-    gtk_init (&argc, &argv);
-
-    gui = g_object_new (STLINK_TYPE_GUI, NULL);
-    stlink_gui_build_ui (gui);
-    stlink_gui_init_dnd (gui);
-
-    gtk_main ();
-
-    return 0;
-}
diff --git a/gui/stlink-gui.h b/gui/stlink-gui.h
deleted file mode 100644 (file)
index 0c90648..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-
-#ifndef __STLINK_GUI_H__
-#define __STLINK_GUI_H__
-
-#include <glib-object.h>
-
-#define STLINK_TYPE_GUI             (stlink_gui_get_type ())
-#define STLINK_GUI(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), STLINK_TYPE_GUI, STlinkGUI))
-#define STLINK_IS_GUI(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), STLINK_TYPE_GUI))
-#define STLINK_GUI_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), STLINK_TYPE_GUI, STlinkGUIClass))
-#define STLINK_IS_GUI_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), STLINK_TYPE_GUI))
-#define STLINK_GUI_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), STLINK_TYPE_GUI, STlinkGUIlass))
-#define STLINK_GUI_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), STLINK_TYPE_GUI, STlinkGUIPrivate))
-
-typedef struct _STlinkGUI        STlinkGUI;
-typedef struct _STlinkGUIClass   STlinkGUIClass;
-typedef struct _STlinkGUIPrivate STlinkGUIPrivate;
-
-enum stlink_gui_pages_t {
-    PAGE_DEVMEM,
-    PAGE_FILEMEM
-};
-
-enum stlink_gui_dnd_targets_t {
-    TARGET_FILENAME,
-    TARGET_ROOTWIN
-};
-
-struct progress_t {
-    GtkProgressBar *bar;
-    guint           timer;
-    gboolean        activity_mode;
-    gdouble         fraction;
-};
-
-struct mem_t {
-    guchar *memory;
-    gsize   size;
-    guint32 base;
-};
-
-struct _STlinkGUI
-{
-    GObject parent_instance;
-
-    /*< private >*/
-    GtkWindow      *window;
-    GtkTreeView    *devmem_treeview;
-    GtkTreeView    *filemem_treeview;
-    GtkSpinner     *spinner;
-    GtkStatusbar   *statusbar;
-    GtkInfoBar     *infobar;
-    GtkLabel       *infolabel;
-    GtkNotebook    *notebook;
-    GtkFrame       *device_frame;
-    GtkLabel       *chip_id_label;
-    GtkLabel       *core_id_label;
-    GtkLabel       *flash_size_label;
-    GtkLabel       *ram_size_label;
-    GtkBox         *devmem_box;
-    GtkEntry       *devmem_jmp_entry;
-    GtkBox         *filemem_box;
-    GtkEntry       *filemem_jmp_entry;
-    GtkToolButton  *connect_button;
-    GtkToolButton  *disconnect_button;
-    GtkToolButton  *flash_button;
-    GtkToolButton  *open_button;
-
-    /* flash dialog */
-    GtkDialog  *flash_dialog;
-    GtkButton  *flash_dialog_ok;
-    GtkButton  *flash_dialog_cancel;
-    GtkEntry   *flash_dialog_entry;
-
-    struct progress_t  progress;
-    struct mem_t       flash_mem;
-    struct mem_t       file_mem;
-
-    gchar    *error_message;
-    gchar    *filename;
-    stlink_t *sl;
-};
-
-struct _STlinkGUIClass
-{
-    GObjectClass parent_class;
-
-    /* class members */
-};
-
-GType stlink_gui_get_type (void);
-
-#endif
diff --git a/gui/stlink-gui.ui b/gui/stlink-gui.ui
deleted file mode 100644 (file)
index 193925c..0000000
+++ /dev/null
@@ -1,666 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<interface>
-  <!-- interface-requires gtk+ 3.0 -->
-  <object class="GtkDialog" id="flash_dialog">
-    <property name="can_focus">False</property>
-    <property name="border_width">5</property>
-    <property name="title" translatable="yes">Flash device</property>
-    <property name="type_hint">dialog</property>
-    <child internal-child="vbox">
-      <object class="GtkBox" id="flash_dialog-vbox">
-        <property name="can_focus">False</property>
-        <property name="orientation">vertical</property>
-        <property name="spacing">2</property>
-        <child internal-child="action_area">
-          <object class="GtkButtonBox" id="dialog-action_area1">
-            <property name="can_focus">False</property>
-            <property name="layout_style">end</property>
-            <child>
-              <object class="GtkButton" id="flash_dialog_cancel_button">
-                <property name="label">gtk-cancel</property>
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="receives_default">True</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="flash_dialog_ok_button">
-                <property name="label">gtk-ok</property>
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="receives_default">True</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="pack_type">end</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkGrid" id="flash_dialog_grid">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="margin_left">5</property>
-            <property name="margin_right">5</property>
-            <property name="margin_top">5</property>
-            <property name="margin_bottom">5</property>
-            <property name="column_spacing">5</property>
-            <property name="column_homogeneous">True</property>
-            <child>
-              <object class="GtkLabel" id="flash_dialog_label">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes">Address to write at:</property>
-              </object>
-              <packing>
-                <property name="left_attach">0</property>
-                <property name="top_attach">0</property>
-                <property name="width">1</property>
-                <property name="height">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkEntry" id="flash_dialog_entry">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="invisible_char">•</property>
-                <property name="width_chars">12</property>
-              </object>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="top_attach">0</property>
-                <property name="width">1</property>
-                <property name="height">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">2</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-    <action-widgets>
-      <action-widget response="0">flash_dialog_cancel_button</action-widget>
-      <action-widget response="-5">flash_dialog_ok_button</action-widget>
-    </action-widgets>
-  </object>
-  <object class="GtkWindow" id="window">
-    <property name="can_focus">False</property>
-    <property name="title" translatable="yes">STlink GUI</property>
-    <property name="default_width">550</property>
-    <property name="default_height">480</property>
-    <child>
-      <object class="GtkGrid" id="maingrid">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="orientation">vertical</property>
-        <child>
-          <object class="GtkToolbar" id="toolbar">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="hexpand">True</property>
-            <child>
-              <object class="GtkToolButton" id="open_button">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="tooltip_text" translatable="yes">Open</property>
-                <property name="label" translatable="yes">Open</property>
-                <property name="use_underline">True</property>
-                <property name="stock_id">gtk-open</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="homogeneous">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkToolButton" id="connect_button">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="tooltip_text" translatable="yes">Connect</property>
-                <property name="label" translatable="yes">Connect</property>
-                <property name="use_underline">True</property>
-                <property name="stock_id">gtk-connect</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="homogeneous">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkToolButton" id="disconnect_button">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="tooltip_text" translatable="yes">Disconnect</property>
-                <property name="label" translatable="yes">Disconnect</property>
-                <property name="use_underline">True</property>
-                <property name="stock_id">gtk-disconnect</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="homogeneous">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkToolButton" id="flash_button">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="tooltip_text" translatable="yes">Flash</property>
-                <property name="label" translatable="yes">Flash</property>
-                <property name="use_underline">True</property>
-                <property name="stock_id">gtk-media-record</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="homogeneous">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkToolItem" id="toolProgressbar">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <child>
-                  <object class="GtkProgressBar" id="progressbar">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="halign">start</property>
-                    <property name="margin_top">5</property>
-                    <property name="margin_bottom">5</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="homogeneous">True</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="left_attach">0</property>
-            <property name="top_attach">0</property>
-            <property name="width">1</property>
-            <property name="height">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkGrid" id="device_grid">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="margin_left">5</property>
-            <property name="margin_top">5</property>
-            <property name="margin_bottom">5</property>
-            <child>
-              <object class="GtkFrame" id="device_frame">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="opacity">0.98999999999999999</property>
-                <property name="margin_left">4</property>
-                <property name="margin_right">4</property>
-                <property name="border_width">1</property>
-                <property name="label_xalign">0</property>
-                <child>
-                  <object class="GtkAlignment" id="alignment1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="left_padding">12</property>
-                    <property name="right_padding">12</property>
-                    <child>
-                      <object class="GtkGrid" id="devstatus_grid">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="row_spacing">2</property>
-                        <property name="column_spacing">6</property>
-                        <property name="row_homogeneous">True</property>
-                        <child>
-                          <object class="GtkLabel" id="chip_label">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="margin_right">1</property>
-                            <property name="margin_top">1</property>
-                            <property name="xalign">0</property>
-                            <property name="yalign">0</property>
-                            <property name="label" translatable="yes">Chip:</property>
-                          </object>
-                          <packing>
-                            <property name="left_attach">0</property>
-                            <property name="top_attach">0</property>
-                            <property name="width">1</property>
-                            <property name="height">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="core_label">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="xalign">0</property>
-                            <property name="yalign">0</property>
-                            <property name="label" translatable="yes">Core:</property>
-                          </object>
-                          <packing>
-                            <property name="left_attach">0</property>
-                            <property name="top_attach">1</property>
-                            <property name="width">1</property>
-                            <property name="height">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="flash_label">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="xalign">0</property>
-                            <property name="yalign">0</property>
-                            <property name="label" translatable="yes">Flash size:</property>
-                          </object>
-                          <packing>
-                            <property name="left_attach">0</property>
-                            <property name="top_attach">2</property>
-                            <property name="width">1</property>
-                            <property name="height">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="core_id_value">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="xalign">0</property>
-                            <property name="yalign">0</property>
-                            <property name="single_line_mode">True</property>
-                          </object>
-                          <packing>
-                            <property name="left_attach">1</property>
-                            <property name="top_attach">1</property>
-                            <property name="width">1</property>
-                            <property name="height">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="chip_id_value">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="xalign">0</property>
-                            <property name="yalign">0</property>
-                            <property name="width_chars">20</property>
-                          </object>
-                          <packing>
-                            <property name="left_attach">1</property>
-                            <property name="top_attach">0</property>
-                            <property name="width">1</property>
-                            <property name="height">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="flash_size_value">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="xalign">0</property>
-                            <property name="yalign">0</property>
-                          </object>
-                          <packing>
-                            <property name="left_attach">1</property>
-                            <property name="top_attach">2</property>
-                            <property name="width">1</property>
-                            <property name="height">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="ram_size_label">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="xalign">0</property>
-                            <property name="yalign">0</property>
-                            <property name="label" translatable="yes">Ram size:</property>
-                          </object>
-                          <packing>
-                            <property name="left_attach">0</property>
-                            <property name="top_attach">3</property>
-                            <property name="width">1</property>
-                            <property name="height">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="ram_size_value">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="xalign">0</property>
-                            <property name="yalign">0</property>
-                          </object>
-                          <packing>
-                            <property name="left_attach">1</property>
-                            <property name="top_attach">3</property>
-                            <property name="width">1</property>
-                            <property name="height">1</property>
-                          </packing>
-                        </child>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-                <child type="label">
-                  <object class="GtkLabel" id="device_frame_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="yalign">0.49000000953674316</property>
-                    <property name="xpad">2</property>
-                    <property name="label" translatable="yes">&lt;b&gt;Device&lt;/b&gt;</property>
-                    <property name="use_markup">True</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="left_attach">0</property>
-                <property name="top_attach">0</property>
-                <property name="width">1</property>
-                <property name="height">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="left_attach">0</property>
-            <property name="top_attach">2</property>
-            <property name="width">1</property>
-            <property name="height">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkStatusbar" id="statusbar">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="margin_left">5</property>
-            <property name="margin_right">5</property>
-            <property name="margin_bottom">5</property>
-            <property name="orientation">vertical</property>
-            <property name="spacing">2</property>
-          </object>
-          <packing>
-            <property name="left_attach">0</property>
-            <property name="top_attach">4</property>
-            <property name="width">1</property>
-            <property name="height">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkNotebook" id="mem_notebook">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="margin_left">5</property>
-            <property name="margin_right">5</property>
-            <property name="margin_top">5</property>
-            <property name="margin_bottom">5</property>
-            <child>
-              <object class="GtkBox" id="devmem_box">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="orientation">vertical</property>
-                <child>
-                  <object class="GtkGrid" id="devmem_jmp_grid">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <child>
-                      <object class="GtkLabel" id="devmem_jmp">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="halign">start</property>
-                        <property name="margin_left">5</property>
-                        <property name="margin_right">5</property>
-                        <property name="margin_top">5</property>
-                        <property name="margin_bottom">5</property>
-                        <property name="label" translatable="yes">Goto address:</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">0</property>
-                        <property name="width">1</property>
-                        <property name="height">1</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkEntry" id="devmem_jmp_entry">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="margin_left">5</property>
-                        <property name="margin_right">5</property>
-                        <property name="margin_top">5</property>
-                        <property name="margin_bottom">5</property>
-                        <property name="max_length">15</property>
-                        <property name="invisible_char">•</property>
-                        <property name="width_chars">12</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="top_attach">0</property>
-                        <property name="width">1</property>
-                        <property name="height">1</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkScrolledWindow" id="devmem_scrolledwindow">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="vexpand">True</property>
-                    <property name="shadow_type">in</property>
-                    <child>
-                      <object class="GtkTreeView" id="devmem_treeview">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="rules_hint">True</property>
-                        <property name="enable_grid_lines">both</property>
-                        <child internal-child="selection">
-                          <object class="GtkTreeSelection" id="treeview-selection1"/>
-                        </child>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="menu_label">Device memory</property>
-              </packing>
-            </child>
-            <child type="tab">
-              <object class="GtkLabel" id="devmem_label">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes">Device memory</property>
-              </object>
-              <packing>
-                <property name="tab_fill">False</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkBox" id="filemem_box">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="orientation">vertical</property>
-                <child>
-                  <object class="GtkGrid" id="filemem_jmp_grid">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <child>
-                      <object class="GtkLabel" id="filemem_jmp">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="margin_left">5</property>
-                        <property name="margin_right">5</property>
-                        <property name="margin_top">5</property>
-                        <property name="margin_bottom">5</property>
-                        <property name="label" translatable="yes">Goto address:</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">0</property>
-                        <property name="width">1</property>
-                        <property name="height">1</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkEntry" id="filemem_jmp_entry">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="margin_left">5</property>
-                        <property name="margin_right">5</property>
-                        <property name="margin_top">5</property>
-                        <property name="margin_bottom">5</property>
-                        <property name="max_length">15</property>
-                        <property name="invisible_char">•</property>
-                        <property name="width_chars">12</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="top_attach">0</property>
-                        <property name="width">1</property>
-                        <property name="height">1</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkScrolledWindow" id="filemem_scrolledwindow">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="vexpand">True</property>
-                    <property name="shadow_type">in</property>
-                    <child>
-                      <object class="GtkTreeView" id="filemem_treeview">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="rules_hint">True</property>
-                        <property name="enable_grid_lines">both</property>
-                        <child internal-child="selection">
-                          <object class="GtkTreeSelection" id="treeview-selection2"/>
-                        </child>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child type="tab">
-              <object class="GtkLabel" id="filemem_label">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes">No file</property>
-              </object>
-              <packing>
-                <property name="position">1</property>
-                <property name="tab_fill">False</property>
-              </packing>
-            </child>
-            <child>
-              <placeholder/>
-            </child>
-            <child type="tab">
-              <placeholder/>
-            </child>
-            <child>
-              <placeholder/>
-            </child>
-            <child type="tab">
-              <placeholder/>
-            </child>
-          </object>
-          <packing>
-            <property name="left_attach">0</property>
-            <property name="top_attach">3</property>
-            <property name="width">1</property>
-            <property name="height">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkInfoBar" id="infobar">
-            <property name="visible">True</property>
-            <property name="app_paintable">True</property>
-            <property name="can_focus">False</property>
-            <property name="message_type">error</property>
-            <child internal-child="content_area">
-              <object class="GtkBox" id="infobar-content_area1">
-                <property name="can_focus">False</property>
-                <property name="border_width">8</property>
-                <property name="spacing">5</property>
-                <child>
-                  <placeholder/>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child internal-child="action_area">
-              <object class="GtkButtonBox" id="infobar-action_area1">
-                <property name="can_focus">False</property>
-                <property name="border_width">5</property>
-                <property name="orientation">vertical</property>
-                <property name="spacing">6</property>
-                <property name="layout_style">end</property>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="left_attach">0</property>
-            <property name="top_attach">1</property>
-            <property name="width">1</property>
-            <property name="height">1</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-  </object>
-</interface>
diff --git a/src/tools/gui/Makefile.am b/src/tools/gui/Makefile.am
new file mode 100644 (file)
index 0000000..23e582f
--- /dev/null
@@ -0,0 +1,30 @@
+bin_PROGRAMS = stlink-gui
+
+stlink_gui_SOURCES = \
+       stlink-gui.c \
+       stlink-gui.h
+
+stlink_gui_CPPFLAGS = \
+       -I$(top_srcdir)/include \
+       $(AM_CPPFLAGS) \
+       -I$(top_srcdir)/src \
+       @GTK3_CFLAGS@
+
+stlink_gui_CFLAGS = \
+       $(WARN_CFLAGS) \
+       $(AM_CFLAGS) \
+       -DSTLINK_UI_DIR="\"$(uidir)\""
+
+stlink_gui_LDFLAGS =  \
+       $(AM_LDFLAGS)
+
+stlink_gui_LDADD = \
+       $(INTLLIBS) \
+       $(top_builddir)/libstlink.a \
+       @GTK3_LIBS@
+
+uidir = $(pkgdatadir)/ui
+ui_DATA = stlink-gui.ui
+EXTRA_DIST = $(ui_DATA)
+
+-include $(top_srcdir)/git.mk
diff --git a/src/tools/gui/stlink-gui.c b/src/tools/gui/stlink-gui.c
new file mode 100644 (file)
index 0000000..944ad13
--- /dev/null
@@ -0,0 +1,955 @@
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <gtk/gtk.h>
+
+#include <stlink.h>
+#include "stlink-gui.h"
+
+#define MEM_READ_SIZE 1024
+
+#ifndef G_VALUE_INIT
+#define G_VALUE_INIT {0, {{0}}}
+#endif
+
+G_DEFINE_TYPE (STlinkGUI, stlink_gui, G_TYPE_OBJECT);
+
+static void
+stlink_gui_dispose (GObject *gobject)
+{
+    G_OBJECT_CLASS (stlink_gui_parent_class)->dispose (gobject);
+}
+
+static void
+stlink_gui_finalize (GObject *gobject)
+{
+    G_OBJECT_CLASS (stlink_gui_parent_class)->finalize (gobject);
+}
+
+static void
+stlink_gui_class_init (STlinkGUIClass *klass)
+{
+    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+    gobject_class->dispose  = stlink_gui_dispose;
+    gobject_class->finalize = stlink_gui_finalize;
+}
+
+static void
+stlink_gui_init (STlinkGUI *self)
+{
+    self->sl       = NULL;
+    self->filename = NULL;
+
+    self->progress.activity_mode = FALSE;
+    self->progress.fraction      = 0;
+
+    self->flash_mem.memory = NULL;
+    self->flash_mem.size   = 0;
+    self->flash_mem.base   = 0;
+
+    self->file_mem.memory = NULL;
+    self->file_mem.size   = 0;
+    self->file_mem.base   = 0;
+}
+
+static gboolean
+set_info_error_message_idle (STlinkGUI *gui)
+{
+    if (gui->error_message != NULL) {
+        gchar *markup;
+
+        markup = g_markup_printf_escaped ("<b>%s</b>", gui->error_message);
+        gtk_label_set_markup (gui->infolabel, markup);
+        gtk_info_bar_set_message_type (gui->infobar, GTK_MESSAGE_ERROR);
+        gtk_widget_show (GTK_WIDGET (gui->infobar));
+
+        g_free (markup);
+        g_free (gui->error_message);
+        gui->error_message = NULL;
+    }
+    return FALSE;
+}
+
+static void
+stlink_gui_set_info_error_message (STlinkGUI *gui, const gchar *message)
+{
+    gui->error_message = g_strdup (message);
+    g_idle_add ((GSourceFunc) set_info_error_message_idle, gui);
+}
+
+static void
+stlink_gui_set_sensitivity (STlinkGUI *gui, gboolean sensitivity)
+{
+    gtk_widget_set_sensitive (GTK_WIDGET (gui->open_button), sensitivity);
+
+    if (sensitivity && gui->sl)
+        gtk_widget_set_sensitive (GTK_WIDGET (gui->disconnect_button), sensitivity);
+
+    if (sensitivity && !gui->sl)
+        gtk_widget_set_sensitive (GTK_WIDGET (gui->connect_button), sensitivity);
+
+    if (sensitivity && gui->sl && gui->filename)
+        gtk_widget_set_sensitive (GTK_WIDGET (gui->flash_button), sensitivity);
+}
+
+static void
+mem_view_init_headers (GtkTreeView *view)
+{
+    GtkCellRenderer *renderer;
+    gint             i;
+
+    g_return_if_fail (view != NULL);
+
+    renderer = gtk_cell_renderer_text_new ();
+    gtk_tree_view_insert_column_with_attributes (view,
+            -1,
+            "Address",
+            renderer,
+            "text",
+            0, /* column */
+            NULL);
+    for (i = 0; i < 4; i++) {
+        gchar *label;
+
+        label = g_strdup_printf ("%X", i * 4);
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_tree_view_insert_column_with_attributes (view,
+                -1,
+                label,
+                renderer,
+                "text",
+                (i + 1), /* column */
+                NULL);
+        g_free (label);
+    }
+
+    for (i = 0; i < 5; i++) {
+        GtkTreeViewColumn *column = gtk_tree_view_get_column (view, i);
+        gtk_tree_view_column_set_expand (column, TRUE);
+    }
+}
+
+static void
+mem_view_add_as_hex (GtkListStore *store,
+                     GtkTreeIter  *iter,
+                     gint          column,
+                     guint32       value)
+{
+    gchar     *hex_str;
+
+    hex_str = g_strdup_printf ("0x%08X", value);
+    gtk_list_store_set (store, iter, column, hex_str, -1);
+    g_free (hex_str);
+}
+
+static void
+mem_view_add_buffer (GtkListStore *store,
+                     GtkTreeIter  *iter,
+                     guint32       address,
+                     guchar       *buffer,
+                     gint          len)
+{
+    guint32 *word;
+    gint     i, step;
+    gint     column = 0;
+
+    step = sizeof (*word);
+
+    for (i = 0; i < len; i += step) {
+        word = (guint *) &buffer[i];
+
+        if (column == 0) {
+            /* new row */
+            gtk_list_store_append (store, iter);
+
+            /* add address */
+            mem_view_add_as_hex (store, iter, column, (address + i));
+        }
+        mem_view_add_as_hex (store, iter, (column + 1), *word);
+        column = (column + 1) % step;
+    }
+}
+
+static guint32
+hexstr_to_guint32 (const gchar *str, GError **err)
+{
+    guint32  val;
+    gchar   *end_ptr;
+
+    val = strtoul (str, &end_ptr, 16);
+    if ((errno == ERANGE && val == LONG_MAX) || (errno != 0 && val == 0)) {
+        g_set_error (err,
+                g_quark_from_string ("hextou32"),
+                1,
+                "Invalid hexstring");
+        return LONG_MAX;
+    }
+    if (end_ptr == str) {
+        g_set_error (err,
+                g_quark_from_string ("hextou32"),
+                2,
+                "Invalid hexstring");
+        return LONG_MAX;
+    }
+    return val;
+}
+
+
+static void
+stlink_gui_update_mem_view (STlinkGUI *gui, struct mem_t *mem, GtkTreeView *view) {
+    GtkListStore *store;
+    GtkTreeIter   iter;
+
+    store = GTK_LIST_STORE (gtk_tree_view_get_model (view));
+
+    mem_view_add_buffer (store,
+            &iter,
+            mem->base,
+            mem->memory,
+            mem->size);
+
+    gtk_widget_hide (GTK_WIDGET (gui->progress.bar));
+    gtk_progress_bar_set_fraction (gui->progress.bar, 0);
+    stlink_gui_set_sensitivity (gui, TRUE);
+}
+
+static gboolean
+stlink_gui_update_devmem_view (STlinkGUI *gui)
+{
+    stlink_gui_update_mem_view (gui, &gui->flash_mem, gui->devmem_treeview);
+    return FALSE;
+}
+
+
+static void
+stlink_gui_populate_devmem_view (STlinkGUI *gui)
+{
+    guint            off;
+    stm32_addr_t     addr;
+
+    g_return_if_fail (gui != NULL);
+    g_return_if_fail (gui->sl != NULL);
+
+    addr = gui->sl->flash_base;
+
+    if (gui->flash_mem.memory) {
+        g_free (gui->flash_mem.memory);
+    }
+    gui->flash_mem.memory = g_malloc (gui->sl->flash_size);
+    gui->flash_mem.size   = gui->sl->flash_size;
+    gui->flash_mem.base   = gui->sl->flash_base;
+
+    for (off = 0; off < gui->sl->flash_size; off += MEM_READ_SIZE) {
+        guint   n_read = MEM_READ_SIZE;
+
+        if (off + MEM_READ_SIZE > gui->sl->flash_size) {
+            n_read = gui->sl->flash_size - off;
+
+            /* align if needed */
+            if (n_read & 3) {
+                n_read = (n_read + 4) & ~(3);
+            }
+        }
+        /* reads to sl->q_buf */
+        stlink_read_mem32(gui->sl, addr + off, n_read);
+        if (gui->sl->q_len < 0) {
+            stlink_gui_set_info_error_message (gui, "Failed to read memory");
+            g_free (gui->flash_mem.memory);
+            gui->flash_mem.memory = NULL;
+            return;
+        }
+        memcpy (gui->flash_mem.memory + off, gui->sl->q_buf, n_read);
+        gui->progress.fraction = (gdouble) (off + n_read) / gui->sl->flash_size;
+    }
+    g_idle_add ((GSourceFunc) stlink_gui_update_devmem_view, gui);
+}
+
+static gboolean
+stlink_gui_update_filemem_view (STlinkGUI *gui)
+{
+    gchar *basename;
+
+    basename = g_path_get_basename (gui->filename);
+    gtk_notebook_set_tab_label_text (gui->notebook,
+            GTK_WIDGET (gtk_notebook_get_nth_page (gui->notebook, 1)),
+            basename);
+    g_free (basename);
+
+    stlink_gui_update_mem_view (gui, &gui->file_mem, gui->filemem_treeview);
+
+    return FALSE;
+}
+
+static gpointer
+stlink_gui_populate_filemem_view (STlinkGUI *gui)
+{
+    guchar        buffer[MEM_READ_SIZE];
+    GFile        *file;
+    GFileInfo    *file_info;
+    GInputStream *input_stream;
+    gint          off;
+    GError       *err = NULL;
+
+    g_return_val_if_fail (gui != NULL, NULL);
+    g_return_val_if_fail (gui->filename != NULL, NULL);
+
+    file = g_file_new_for_path (gui->filename);
+    input_stream = G_INPUT_STREAM (g_file_read (file, NULL, &err));
+    if (err) {
+        stlink_gui_set_info_error_message (gui, err->message);
+        g_error_free (err);
+        goto out;
+    }
+
+    file_info = g_file_input_stream_query_info (G_FILE_INPUT_STREAM (input_stream),
+            G_FILE_ATTRIBUTE_STANDARD_SIZE, NULL, &err);
+    if (err) {
+        stlink_gui_set_info_error_message (gui, err->message);
+        g_error_free (err);
+        goto out_input;
+    }
+    if (gui->file_mem.memory) {
+        g_free (gui->file_mem.memory);
+    }
+    gui->file_mem.size   = g_file_info_get_size (file_info);
+    gui->file_mem.memory = g_malloc (gui->file_mem.size);
+
+    for (off = 0; off < gui->file_mem.size; off += MEM_READ_SIZE) {
+        guint   n_read = MEM_READ_SIZE;
+
+        if (off + MEM_READ_SIZE > gui->file_mem.size) {
+            n_read = gui->file_mem.size - off;
+        }
+
+        if (g_input_stream_read (G_INPUT_STREAM (input_stream),
+                    &buffer, n_read, NULL, &err) == -1) {
+            stlink_gui_set_info_error_message (gui, err->message);
+            g_error_free (err);
+            goto out_input;
+        }
+        memcpy (gui->file_mem.memory + off, buffer, n_read);
+        gui->progress.fraction = (gdouble) (off + n_read) / gui->file_mem.size;
+    }
+    g_idle_add ((GSourceFunc) stlink_gui_update_filemem_view, gui);
+
+out_input:
+    g_object_unref (input_stream);
+out:
+    g_object_unref (file);
+    return NULL;
+}
+
+static void mem_jmp (GtkTreeView *view,
+                     GtkEntry    *entry,
+                     guint32      base_addr,
+                     gsize        size,
+                     GError     **err)
+{
+    GtkTreeModel *model;
+    guint32       jmp_addr;
+    GtkTreeIter   iter;
+
+    jmp_addr = hexstr_to_guint32 (gtk_entry_get_text (entry), err);
+    if (err && *err) {
+        return;
+    }
+
+    if (jmp_addr < base_addr || jmp_addr > base_addr + size) {
+        g_set_error (err,
+                g_quark_from_string ("mem_jmp"),
+                1,
+                "Invalid address");
+        return;
+    }
+
+    model = gtk_tree_view_get_model (view);
+    if (!model) {
+        return;
+    }
+
+    if (gtk_tree_model_get_iter_first (model, &iter)) {
+        do {
+            guint32 addr;
+            GValue  value = G_VALUE_INIT;
+            GError *err   = NULL;
+
+            gtk_tree_model_get_value (model, &iter, 0, &value);
+            if (G_VALUE_HOLDS_STRING (&value)) {
+                addr = hexstr_to_guint32 (g_value_get_string (&value), &err);
+                if (!err) {
+                    if (addr == (jmp_addr & 0xFFFFFFF0)) {
+                        GtkTreeSelection *selection;
+                        GtkTreePath      *path;
+
+                        selection = gtk_tree_view_get_selection (view);
+                        path      = gtk_tree_model_get_path (model, &iter);
+
+                        gtk_tree_selection_select_iter (selection, &iter);
+                        gtk_tree_view_scroll_to_cell (view,
+                                path,
+                                NULL,
+                                TRUE,
+                                0.0,
+                                0.0);
+                        gtk_tree_path_free (path);
+                    }
+                }
+            }
+            g_value_unset (&value);
+        } while (gtk_tree_model_iter_next (model, &iter));
+    }
+}
+
+static void
+devmem_jmp_cb (GtkWidget *widget, gpointer data)
+{
+    STlinkGUI *gui;
+    GError    *err = NULL;
+
+    gui = STLINK_GUI (data);
+
+    mem_jmp (gui->devmem_treeview,
+            gui->devmem_jmp_entry,
+            gui->sl->flash_base,
+            gui->sl->flash_size,
+            &err);
+
+    if (err) {
+        stlink_gui_set_info_error_message (gui, err->message);
+        g_error_free (err);
+    }
+}
+
+static void
+filemem_jmp_cb (GtkWidget *widget, gpointer data)
+{
+    STlinkGUI *gui;
+    GError    *err = NULL;
+
+    gui = STLINK_GUI (data);
+
+    g_return_if_fail (gui->filename != NULL);
+
+    mem_jmp (gui->filemem_treeview,
+            gui->filemem_jmp_entry,
+            0,
+            gui->file_mem.size,
+            &err);
+
+    if (err) {
+        stlink_gui_set_info_error_message (gui, err->message);
+        g_error_free (err);
+    }
+}
+
+static gchar *
+dev_format_chip_id (guint32 chip_id)
+{
+    gint i;
+
+    for (i = 0; i < sizeof (devices) / sizeof (devices[0]); i++) {
+        if (chip_id == devices[i].chip_id) {
+            return g_strdup (devices[i].description);
+        }
+    }
+    return g_strdup_printf ("0x%x", chip_id);
+}
+
+static gchar *
+dev_format_mem_size (gsize flash_size)
+{
+    return g_strdup_printf ("%u kB", flash_size / 1024);
+}
+
+
+static void
+stlink_gui_set_connected (STlinkGUI *gui)
+{
+    gchar        *tmp_str;
+    GtkListStore *store;
+    GtkTreeIter   iter;
+
+    gtk_statusbar_push (gui->statusbar,
+            gtk_statusbar_get_context_id (gui->statusbar, "conn"),
+            "Connected");
+
+    gtk_widget_set_sensitive (GTK_WIDGET (gui->device_frame), TRUE);
+    gtk_widget_set_sensitive (GTK_WIDGET (gui->devmem_box), TRUE);
+    gtk_widget_set_sensitive (GTK_WIDGET (gui->connect_button), FALSE);
+
+    if (gui->filename) {
+        gtk_widget_set_sensitive (GTK_WIDGET (gui->flash_button), TRUE);
+    }
+
+    tmp_str = dev_format_chip_id (gui->sl->chip_id);
+    gtk_label_set_text (gui->chip_id_label, tmp_str);
+    g_free (tmp_str);
+
+    tmp_str = g_strdup_printf ("0x%x", gui->sl->core_id);
+    gtk_label_set_text (gui->core_id_label, tmp_str);
+    g_free (tmp_str);
+
+    tmp_str = dev_format_mem_size (gui->sl->flash_size);
+    gtk_label_set_text (gui->flash_size_label, tmp_str);
+    g_free (tmp_str);
+
+    tmp_str = dev_format_mem_size (gui->sl->sram_size);
+    gtk_label_set_text (gui->ram_size_label, tmp_str);
+    g_free (tmp_str);
+
+    tmp_str = g_strdup_printf ("0x%08X", gui->sl->flash_base);
+    gtk_entry_set_text (gui->devmem_jmp_entry, tmp_str);
+    gtk_editable_set_editable (GTK_EDITABLE (gui->devmem_jmp_entry), TRUE);
+    g_free (tmp_str);
+
+    store = GTK_LIST_STORE (gtk_tree_view_get_model (gui->devmem_treeview));
+    if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) {
+        gtk_list_store_clear (store);
+    }
+
+    stlink_gui_set_sensitivity (gui, FALSE);
+    gtk_notebook_set_current_page (gui->notebook, PAGE_DEVMEM);
+    gtk_widget_show (GTK_WIDGET (gui->progress.bar));
+    gtk_progress_bar_set_text (gui->progress.bar, "Reading memory");
+
+    g_thread_new ("devmem", (GThreadFunc) stlink_gui_populate_devmem_view, gui);
+}
+
+static void
+connect_button_cb (GtkWidget *widget, gpointer data)
+{
+    STlinkGUI *gui;
+    gint       i;
+
+    gui = STLINK_GUI (data);
+
+    if (gui->sl != NULL)
+        return;
+
+    /* try version 1 then version 2 */
+    gui->sl = stlink_v1_open(0, 1);
+    if (gui->sl == NULL) {
+           gui->sl = stlink_open_usb(0, 1, NULL);
+    }
+    if (gui->sl == NULL) {
+        stlink_gui_set_info_error_message (gui, "Failed to connect to STLink.");               return;
+    }
+
+    /* code below taken from flash/main.c, refactoring might be in order */
+    if (stlink_current_mode(gui->sl) == STLINK_DEV_DFU_MODE)
+        stlink_exit_dfu_mode(gui->sl);
+
+    if (stlink_current_mode(gui->sl) != STLINK_DEV_DEBUG_MODE)
+        stlink_enter_swd_mode(gui->sl);
+
+    /* Disable DMA - Set All DMA CCR Registers to zero. - AKS 1/7/2013 */
+    if (gui->sl->chip_id == STM32_CHIPID_F4) {
+        memset(gui->sl->q_buf, 0, 4);
+        for (i = 0; i < 8; i++) {
+            stlink_write_mem32(gui->sl, 0x40026000 + 0x10 + 0x18 * i, 4);
+            stlink_write_mem32(gui->sl, 0x40026400 + 0x10 + 0x18 * i, 4);
+            stlink_write_mem32(gui->sl, 0x40026000 + 0x24 + 0x18 * i, 4);
+            stlink_write_mem32(gui->sl, 0x40026400 + 0x24 + 0x18 * i, 4);
+        }
+    }
+    stlink_gui_set_connected (gui);
+}
+
+static void stlink_gui_set_disconnected (STlinkGUI *gui)
+{
+    gtk_statusbar_push (gui->statusbar,
+            gtk_statusbar_get_context_id (gui->statusbar, "conn"),
+            "Disconnected");
+
+    gtk_widget_set_sensitive (GTK_WIDGET (gui->device_frame), FALSE);
+    gtk_widget_set_sensitive (GTK_WIDGET (gui->flash_button), FALSE);
+    gtk_widget_set_sensitive (GTK_WIDGET (gui->disconnect_button), FALSE);
+    gtk_widget_set_sensitive (GTK_WIDGET (gui->connect_button), TRUE);
+}
+
+static void
+disconnect_button_cb (GtkWidget *widget, gpointer data)
+{
+    STlinkGUI *gui;
+
+    gui = STLINK_GUI (data);
+
+    if (gui->sl != NULL) {
+        stlink_exit_debug_mode(gui->sl);
+        stlink_close(gui->sl);
+        gui->sl = NULL;
+    }
+    stlink_gui_set_disconnected (gui);
+}
+
+
+static void
+stlink_gui_open_file (STlinkGUI *gui)
+{
+    GtkWidget    *dialog;
+    GtkListStore *store;
+    GtkTreeIter   iter;
+
+    dialog = gtk_file_chooser_dialog_new ("Open file",
+            gui->window,
+            GTK_FILE_CHOOSER_ACTION_OPEN,
+            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+            GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+            NULL);
+
+    if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
+        gui->filename =
+            gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+
+        store = GTK_LIST_STORE (gtk_tree_view_get_model (gui->filemem_treeview));
+        if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) {
+            gtk_list_store_clear (store);
+        }
+
+        stlink_gui_set_sensitivity (gui, FALSE);
+        gtk_notebook_set_current_page (gui->notebook, PAGE_FILEMEM);
+        gtk_widget_show (GTK_WIDGET (gui->progress.bar));
+        gtk_progress_bar_set_text (gui->progress.bar, "Reading file");
+        g_thread_new ("file", (GThreadFunc) stlink_gui_populate_filemem_view, gui);
+    }
+    gtk_widget_destroy (dialog);
+}
+
+static void
+open_button_cb (GtkWidget *widget, gpointer data)
+{
+    STlinkGUI    *gui;
+
+    gui = STLINK_GUI (data);
+
+    stlink_gui_open_file (gui);
+}
+
+static gboolean
+stlink_gui_write_flash_update (STlinkGUI *gui)
+{
+    stlink_gui_set_sensitivity (gui, TRUE);
+    gui->progress.activity_mode = FALSE;
+    gtk_widget_hide (GTK_WIDGET (gui->progress.bar));
+
+    return FALSE;
+}
+
+static void
+stlink_gui_write_flash (STlinkGUI *gui)
+{
+    g_return_if_fail (gui->sl != NULL);
+    g_return_if_fail (gui->filename != NULL);
+
+    if (stlink_fwrite_flash(gui->sl, gui->filename, gui->sl->flash_base) < 0) {
+        stlink_gui_set_info_error_message (gui, "Failed to write to flash");
+    }
+
+    g_idle_add ((GSourceFunc) stlink_gui_write_flash_update, gui);
+}
+
+static void
+flash_button_cb (GtkWidget *widget, gpointer data)
+{
+    STlinkGUI *gui;
+    gchar     *tmp_str;
+    guint32    address;
+    gint       result;
+    GError    *err = NULL;
+
+    gui = STLINK_GUI (data);
+    g_return_if_fail (gui->sl != NULL);
+
+    if (!g_strcmp0 (gtk_entry_get_text (gui->flash_dialog_entry), "")) {
+        tmp_str = g_strdup_printf ("0x%08X", gui->sl->flash_base);
+        gtk_entry_set_text (gui->flash_dialog_entry, tmp_str);
+        g_free (tmp_str);
+    }
+
+    result = gtk_dialog_run (gui->flash_dialog);
+    if (result == GTK_RESPONSE_OK) {
+        address = hexstr_to_guint32 (gtk_entry_get_text (gui->flash_dialog_entry),
+                &err);
+        if (err) {
+            stlink_gui_set_info_error_message (gui, err->message);
+        } else {
+            if (address > gui->sl->flash_base + gui->sl->flash_size ||
+                    address < gui->sl->flash_base) {
+                stlink_gui_set_info_error_message (gui, "Invalid address");
+            }
+            else if (address + gui->file_mem.size >
+                    gui->sl->flash_base + gui->sl->flash_size) {
+                stlink_gui_set_info_error_message (gui, "Binary overwrites flash");
+            } else {
+                stlink_gui_set_sensitivity (gui, FALSE);
+                gtk_progress_bar_set_text (gui->progress.bar,
+                        "Writing to flash");
+                gui->progress.activity_mode = TRUE;
+                gtk_widget_show (GTK_WIDGET (gui->progress.bar));
+                g_thread_new ("flash",
+                        (GThreadFunc) stlink_gui_write_flash, gui);
+            }
+        }
+    }
+}
+
+static gboolean
+progress_pulse_timeout (STlinkGUI *gui) {
+    if (gui->progress.activity_mode) {
+        gtk_progress_bar_pulse (gui->progress.bar);
+    } else {
+        gtk_progress_bar_set_fraction (gui->progress.bar, gui->progress.fraction);
+    }
+    return TRUE;
+}
+
+static void
+notebook_switch_page_cb (GtkNotebook *notebook,
+                         GtkWidget   *widget,
+                         guint        page_num,
+                         gpointer     data)
+{
+    STlinkGUI *gui;
+
+    gui = STLINK_GUI (data);
+
+    if (page_num == 1) {
+        if (gui->filename == NULL) {
+            stlink_gui_open_file (gui);
+        }
+    }
+}
+
+static void
+dnd_received_cb (GtkWidget *widget,
+                 GdkDragContext *context,
+                 gint x,
+                 gint y,
+                 GtkSelectionData *selection_data,
+                 guint target_type,
+                 guint time,
+                 gpointer data)
+{
+    GFile        *file_uri;
+    gchar       **file_list;
+    const guchar *file_data;
+    STlinkGUI    *gui = STLINK_GUI (data);
+    GtkListStore *store;
+    GtkTreeIter   iter;
+
+    if (selection_data != NULL &&
+            gtk_selection_data_get_length (selection_data) > 0) {
+        switch (target_type) {
+        case TARGET_FILENAME:
+
+            if (gui->filename) {
+                g_free (gui->filename);
+            }
+
+            file_data = gtk_selection_data_get_data (selection_data);
+            file_list = g_strsplit ((gchar *)file_data, "\r\n", 0);
+
+            file_uri = g_file_new_for_uri (file_list[0]);
+            gui->filename = g_file_get_path (file_uri);
+
+            g_strfreev (file_list);
+            g_object_unref (file_uri);
+
+
+            store = GTK_LIST_STORE (gtk_tree_view_get_model (gui->devmem_treeview));
+            if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) {
+                gtk_list_store_clear (store);
+            }
+
+            stlink_gui_set_sensitivity (gui, FALSE);
+            gtk_notebook_set_current_page (gui->notebook, PAGE_FILEMEM);
+            gtk_widget_show (GTK_WIDGET (gui->progress.bar));
+            gtk_progress_bar_set_text (gui->progress.bar, "Reading file");
+            g_thread_new ("file", (GThreadFunc) stlink_gui_populate_filemem_view, gui);
+            break;
+        }
+    }
+    gtk_drag_finish (context,
+                     TRUE,
+                     gdk_drag_context_get_suggested_action (context) == GDK_ACTION_MOVE,
+                     time);
+}
+
+void
+stlink_gui_init_dnd (STlinkGUI *gui)
+{
+    GtkTargetEntry target_list[] = {
+        { "text/uri-list", 0, TARGET_FILENAME },
+    };
+
+    gtk_drag_dest_set (GTK_WIDGET (gui->window),
+                       GTK_DEST_DEFAULT_ALL,
+                       target_list,
+                       G_N_ELEMENTS (target_list),
+                       GDK_ACTION_COPY);
+
+    g_signal_connect (gui->window, "drag-data-received",
+                      G_CALLBACK (dnd_received_cb), gui);
+}
+
+static void
+stlink_gui_build_ui (STlinkGUI *gui) {
+    GtkBuilder   *builder;
+    GtkListStore *devmem_store;
+    GtkListStore *filemem_store;
+    gchar *ui_file = STLINK_UI_DIR "/stlink-gui.ui";
+
+    if (!g_file_test (ui_file, G_FILE_TEST_EXISTS)) {
+        ui_file = "stlink-gui.ui";
+    }
+    builder = gtk_builder_new ();
+    if (!gtk_builder_add_from_file (builder, ui_file, NULL)) {
+        g_printerr ("Failed to load UI file: %s\n", ui_file);
+        exit (1);
+    }
+
+    gui->window = GTK_WINDOW (gtk_builder_get_object (builder, "window"));
+    g_signal_connect (G_OBJECT (gui->window), "destroy",
+            G_CALLBACK (gtk_main_quit), NULL);
+
+    /* set up toolutton clicked callbacks */
+    gui->open_button =
+        GTK_TOOL_BUTTON (gtk_builder_get_object (builder, "open_button"));
+    g_signal_connect (G_OBJECT (gui->open_button), "clicked",
+            G_CALLBACK (open_button_cb), gui);
+
+    gui->connect_button =
+        GTK_TOOL_BUTTON (gtk_builder_get_object (builder, "connect_button"));
+    g_signal_connect (G_OBJECT (gui->connect_button), "clicked",
+            G_CALLBACK (connect_button_cb), gui);
+
+    gui->disconnect_button =
+        GTK_TOOL_BUTTON (gtk_builder_get_object (builder, "disconnect_button"));
+    g_signal_connect (G_OBJECT (gui->disconnect_button), "clicked",
+            G_CALLBACK (disconnect_button_cb), gui);
+
+    gui->flash_button =
+        GTK_TOOL_BUTTON (gtk_builder_get_object (builder, "flash_button"));
+    g_signal_connect (G_OBJECT (gui->flash_button), "clicked",
+            G_CALLBACK (flash_button_cb), gui);
+
+    gui->devmem_treeview =
+        GTK_TREE_VIEW (gtk_builder_get_object (builder, "devmem_treeview"));
+    gtk_tree_view_set_rules_hint (gui->devmem_treeview, TRUE);
+    mem_view_init_headers (gui->devmem_treeview);
+    devmem_store = gtk_list_store_new (5,
+            G_TYPE_STRING,
+            G_TYPE_STRING,
+            G_TYPE_STRING,
+            G_TYPE_STRING,
+            G_TYPE_STRING);
+    gtk_tree_view_set_model (gui->devmem_treeview, GTK_TREE_MODEL (devmem_store));
+    g_object_unref (devmem_store);
+
+    gui->filemem_treeview =
+        GTK_TREE_VIEW (gtk_builder_get_object (builder, "filemem_treeview"));
+    gtk_tree_view_set_rules_hint (gui->filemem_treeview, TRUE);
+    mem_view_init_headers (gui->filemem_treeview);
+    filemem_store = gtk_list_store_new (5,
+            G_TYPE_STRING,
+            G_TYPE_STRING,
+            G_TYPE_STRING,
+            G_TYPE_STRING,
+            G_TYPE_STRING);
+    gtk_tree_view_set_model (gui->filemem_treeview, GTK_TREE_MODEL (filemem_store));
+    g_object_unref (filemem_store);
+
+    gui->core_id_label =
+        GTK_LABEL (gtk_builder_get_object (builder, "core_id_value"));
+
+    gui->chip_id_label =
+        GTK_LABEL (gtk_builder_get_object (builder, "chip_id_value"));
+
+    gui->flash_size_label =
+        GTK_LABEL (gtk_builder_get_object (builder, "flash_size_value"));
+
+    gui->ram_size_label =
+        GTK_LABEL (gtk_builder_get_object (builder, "ram_size_value"));
+
+    gui->device_frame =
+        GTK_FRAME (gtk_builder_get_object (builder, "device_frame"));
+
+    gui->notebook =
+        GTK_NOTEBOOK (gtk_builder_get_object (builder, "mem_notebook"));
+    g_signal_connect (gui->notebook, "switch-page",
+            G_CALLBACK (notebook_switch_page_cb), gui);
+
+    gui->devmem_box =
+        GTK_BOX (gtk_builder_get_object (builder, "devmem_box"));
+
+    gui->filemem_box =
+        GTK_BOX (gtk_builder_get_object (builder, "filemem_box"));
+
+    gui->devmem_jmp_entry =
+        GTK_ENTRY (gtk_builder_get_object (builder, "devmem_jmp_entry"));
+    g_signal_connect (gui->devmem_jmp_entry, "activate",
+            G_CALLBACK (devmem_jmp_cb), gui);
+
+    gui->filemem_jmp_entry =
+        GTK_ENTRY (gtk_builder_get_object (builder, "filemem_jmp_entry"));
+    g_signal_connect (gui->filemem_jmp_entry, "activate",
+            G_CALLBACK (filemem_jmp_cb), gui);
+    gtk_editable_set_editable (GTK_EDITABLE (gui->filemem_jmp_entry), TRUE);
+
+    gui->progress.bar =
+        GTK_PROGRESS_BAR (gtk_builder_get_object (builder, "progressbar"));
+    gtk_progress_bar_set_show_text (gui->progress.bar, TRUE);
+    gui->progress.timer = g_timeout_add (100,
+            (GSourceFunc) progress_pulse_timeout,
+            gui);
+
+    gui->statusbar =
+        GTK_STATUSBAR (gtk_builder_get_object (builder, "statusbar"));
+
+    gui->infobar =
+        GTK_INFO_BAR (gtk_builder_get_object (builder, "infobar"));
+    gtk_info_bar_add_button (gui->infobar, GTK_STOCK_OK, GTK_RESPONSE_OK);
+    gui->infolabel = GTK_LABEL (gtk_label_new (""));
+    gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (gui->infobar)),
+            GTK_WIDGET (gui->infolabel));
+    g_signal_connect (gui->infobar, "response", G_CALLBACK (gtk_widget_hide), NULL);
+
+    /* flash dialog */
+    gui->flash_dialog =
+        GTK_DIALOG (gtk_builder_get_object (builder, "flash_dialog"));
+    g_signal_connect_swapped (gui->flash_dialog, "response",
+            G_CALLBACK (gtk_widget_hide), gui->flash_dialog);
+
+    gui->flash_dialog_ok =
+        GTK_BUTTON (gtk_builder_get_object (builder, "flash_dialog_ok_button"));
+
+    gui->flash_dialog_cancel =
+        GTK_BUTTON (gtk_builder_get_object (builder, "flash_dialog_cancel_button"));
+
+    gui->flash_dialog_entry =
+        GTK_ENTRY (gtk_builder_get_object (builder, "flash_dialog_entry"));
+
+    /* make it so */
+    gtk_widget_show_all (GTK_WIDGET (gui->window));
+    gtk_widget_hide (GTK_WIDGET (gui->infobar));
+    gtk_widget_hide (GTK_WIDGET (gui->progress.bar));
+
+    stlink_gui_set_disconnected (gui);
+}
+
+int
+main (int argc, char **argv)
+{
+    STlinkGUI *gui;
+
+    gtk_init (&argc, &argv);
+
+    gui = g_object_new (STLINK_TYPE_GUI, NULL);
+    stlink_gui_build_ui (gui);
+    stlink_gui_init_dnd (gui);
+
+    gtk_main ();
+
+    return 0;
+}
diff --git a/src/tools/gui/stlink-gui.h b/src/tools/gui/stlink-gui.h
new file mode 100644 (file)
index 0000000..0c90648
--- /dev/null
@@ -0,0 +1,93 @@
+
+#ifndef __STLINK_GUI_H__
+#define __STLINK_GUI_H__
+
+#include <glib-object.h>
+
+#define STLINK_TYPE_GUI             (stlink_gui_get_type ())
+#define STLINK_GUI(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), STLINK_TYPE_GUI, STlinkGUI))
+#define STLINK_IS_GUI(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), STLINK_TYPE_GUI))
+#define STLINK_GUI_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), STLINK_TYPE_GUI, STlinkGUIClass))
+#define STLINK_IS_GUI_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), STLINK_TYPE_GUI))
+#define STLINK_GUI_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), STLINK_TYPE_GUI, STlinkGUIlass))
+#define STLINK_GUI_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), STLINK_TYPE_GUI, STlinkGUIPrivate))
+
+typedef struct _STlinkGUI        STlinkGUI;
+typedef struct _STlinkGUIClass   STlinkGUIClass;
+typedef struct _STlinkGUIPrivate STlinkGUIPrivate;
+
+enum stlink_gui_pages_t {
+    PAGE_DEVMEM,
+    PAGE_FILEMEM
+};
+
+enum stlink_gui_dnd_targets_t {
+    TARGET_FILENAME,
+    TARGET_ROOTWIN
+};
+
+struct progress_t {
+    GtkProgressBar *bar;
+    guint           timer;
+    gboolean        activity_mode;
+    gdouble         fraction;
+};
+
+struct mem_t {
+    guchar *memory;
+    gsize   size;
+    guint32 base;
+};
+
+struct _STlinkGUI
+{
+    GObject parent_instance;
+
+    /*< private >*/
+    GtkWindow      *window;
+    GtkTreeView    *devmem_treeview;
+    GtkTreeView    *filemem_treeview;
+    GtkSpinner     *spinner;
+    GtkStatusbar   *statusbar;
+    GtkInfoBar     *infobar;
+    GtkLabel       *infolabel;
+    GtkNotebook    *notebook;
+    GtkFrame       *device_frame;
+    GtkLabel       *chip_id_label;
+    GtkLabel       *core_id_label;
+    GtkLabel       *flash_size_label;
+    GtkLabel       *ram_size_label;
+    GtkBox         *devmem_box;
+    GtkEntry       *devmem_jmp_entry;
+    GtkBox         *filemem_box;
+    GtkEntry       *filemem_jmp_entry;
+    GtkToolButton  *connect_button;
+    GtkToolButton  *disconnect_button;
+    GtkToolButton  *flash_button;
+    GtkToolButton  *open_button;
+
+    /* flash dialog */
+    GtkDialog  *flash_dialog;
+    GtkButton  *flash_dialog_ok;
+    GtkButton  *flash_dialog_cancel;
+    GtkEntry   *flash_dialog_entry;
+
+    struct progress_t  progress;
+    struct mem_t       flash_mem;
+    struct mem_t       file_mem;
+
+    gchar    *error_message;
+    gchar    *filename;
+    stlink_t *sl;
+};
+
+struct _STlinkGUIClass
+{
+    GObjectClass parent_class;
+
+    /* class members */
+};
+
+GType stlink_gui_get_type (void);
+
+#endif
diff --git a/src/tools/gui/stlink-gui.ui b/src/tools/gui/stlink-gui.ui
new file mode 100644 (file)
index 0000000..193925c
--- /dev/null
@@ -0,0 +1,666 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkDialog" id="flash_dialog">
+    <property name="can_focus">False</property>
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Flash device</property>
+    <property name="type_hint">dialog</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="flash_dialog-vbox">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area1">
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="flash_dialog_cancel_button">
+                <property name="label">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="flash_dialog_ok_button">
+                <property name="label">gtk-ok</property>
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkGrid" id="flash_dialog_grid">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_left">5</property>
+            <property name="margin_right">5</property>
+            <property name="margin_top">5</property>
+            <property name="margin_bottom">5</property>
+            <property name="column_spacing">5</property>
+            <property name="column_homogeneous">True</property>
+            <child>
+              <object class="GtkLabel" id="flash_dialog_label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">Address to write at:</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="flash_dialog_entry">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="invisible_char">•</property>
+                <property name="width_chars">12</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="0">flash_dialog_cancel_button</action-widget>
+      <action-widget response="-5">flash_dialog_ok_button</action-widget>
+    </action-widgets>
+  </object>
+  <object class="GtkWindow" id="window">
+    <property name="can_focus">False</property>
+    <property name="title" translatable="yes">STlink GUI</property>
+    <property name="default_width">550</property>
+    <property name="default_height">480</property>
+    <child>
+      <object class="GtkGrid" id="maingrid">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkToolbar" id="toolbar">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="hexpand">True</property>
+            <child>
+              <object class="GtkToolButton" id="open_button">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="tooltip_text" translatable="yes">Open</property>
+                <property name="label" translatable="yes">Open</property>
+                <property name="use_underline">True</property>
+                <property name="stock_id">gtk-open</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="homogeneous">True</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkToolButton" id="connect_button">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="tooltip_text" translatable="yes">Connect</property>
+                <property name="label" translatable="yes">Connect</property>
+                <property name="use_underline">True</property>
+                <property name="stock_id">gtk-connect</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="homogeneous">True</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkToolButton" id="disconnect_button">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="tooltip_text" translatable="yes">Disconnect</property>
+                <property name="label" translatable="yes">Disconnect</property>
+                <property name="use_underline">True</property>
+                <property name="stock_id">gtk-disconnect</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="homogeneous">True</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkToolButton" id="flash_button">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="tooltip_text" translatable="yes">Flash</property>
+                <property name="label" translatable="yes">Flash</property>
+                <property name="use_underline">True</property>
+                <property name="stock_id">gtk-media-record</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="homogeneous">True</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkToolItem" id="toolProgressbar">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkProgressBar" id="progressbar">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="halign">start</property>
+                    <property name="margin_top">5</property>
+                    <property name="margin_bottom">5</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="homogeneous">True</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">0</property>
+            <property name="width">1</property>
+            <property name="height">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkGrid" id="device_grid">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_left">5</property>
+            <property name="margin_top">5</property>
+            <property name="margin_bottom">5</property>
+            <child>
+              <object class="GtkFrame" id="device_frame">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="opacity">0.98999999999999999</property>
+                <property name="margin_left">4</property>
+                <property name="margin_right">4</property>
+                <property name="border_width">1</property>
+                <property name="label_xalign">0</property>
+                <child>
+                  <object class="GtkAlignment" id="alignment1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="left_padding">12</property>
+                    <property name="right_padding">12</property>
+                    <child>
+                      <object class="GtkGrid" id="devstatus_grid">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="row_spacing">2</property>
+                        <property name="column_spacing">6</property>
+                        <property name="row_homogeneous">True</property>
+                        <child>
+                          <object class="GtkLabel" id="chip_label">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="margin_right">1</property>
+                            <property name="margin_top">1</property>
+                            <property name="xalign">0</property>
+                            <property name="yalign">0</property>
+                            <property name="label" translatable="yes">Chip:</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">0</property>
+                            <property name="width">1</property>
+                            <property name="height">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="core_label">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="yalign">0</property>
+                            <property name="label" translatable="yes">Core:</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">1</property>
+                            <property name="width">1</property>
+                            <property name="height">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="flash_label">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="yalign">0</property>
+                            <property name="label" translatable="yes">Flash size:</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">2</property>
+                            <property name="width">1</property>
+                            <property name="height">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="core_id_value">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="yalign">0</property>
+                            <property name="single_line_mode">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">1</property>
+                            <property name="width">1</property>
+                            <property name="height">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="chip_id_value">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="yalign">0</property>
+                            <property name="width_chars">20</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">0</property>
+                            <property name="width">1</property>
+                            <property name="height">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="flash_size_value">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="yalign">0</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">2</property>
+                            <property name="width">1</property>
+                            <property name="height">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="ram_size_label">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="yalign">0</property>
+                            <property name="label" translatable="yes">Ram size:</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">3</property>
+                            <property name="width">1</property>
+                            <property name="height">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="ram_size_value">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="yalign">0</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">3</property>
+                            <property name="width">1</property>
+                            <property name="height">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel" id="device_frame_label">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="yalign">0.49000000953674316</property>
+                    <property name="xpad">2</property>
+                    <property name="label" translatable="yes">&lt;b&gt;Device&lt;/b&gt;</property>
+                    <property name="use_markup">True</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">2</property>
+            <property name="width">1</property>
+            <property name="height">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkStatusbar" id="statusbar">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_left">5</property>
+            <property name="margin_right">5</property>
+            <property name="margin_bottom">5</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">2</property>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">4</property>
+            <property name="width">1</property>
+            <property name="height">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkNotebook" id="mem_notebook">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_left">5</property>
+            <property name="margin_right">5</property>
+            <property name="margin_top">5</property>
+            <property name="margin_bottom">5</property>
+            <child>
+              <object class="GtkBox" id="devmem_box">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="orientation">vertical</property>
+                <child>
+                  <object class="GtkGrid" id="devmem_jmp_grid">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkLabel" id="devmem_jmp">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="halign">start</property>
+                        <property name="margin_left">5</property>
+                        <property name="margin_right">5</property>
+                        <property name="margin_top">5</property>
+                        <property name="margin_bottom">5</property>
+                        <property name="label" translatable="yes">Goto address:</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">0</property>
+                        <property name="width">1</property>
+                        <property name="height">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkEntry" id="devmem_jmp_entry">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="margin_left">5</property>
+                        <property name="margin_right">5</property>
+                        <property name="margin_top">5</property>
+                        <property name="margin_bottom">5</property>
+                        <property name="max_length">15</property>
+                        <property name="invisible_char">•</property>
+                        <property name="width_chars">12</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="top_attach">0</property>
+                        <property name="width">1</property>
+                        <property name="height">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkScrolledWindow" id="devmem_scrolledwindow">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="vexpand">True</property>
+                    <property name="shadow_type">in</property>
+                    <child>
+                      <object class="GtkTreeView" id="devmem_treeview">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="rules_hint">True</property>
+                        <property name="enable_grid_lines">both</property>
+                        <child internal-child="selection">
+                          <object class="GtkTreeSelection" id="treeview-selection1"/>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="menu_label">Device memory</property>
+              </packing>
+            </child>
+            <child type="tab">
+              <object class="GtkLabel" id="devmem_label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">Device memory</property>
+              </object>
+              <packing>
+                <property name="tab_fill">False</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkBox" id="filemem_box">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="orientation">vertical</property>
+                <child>
+                  <object class="GtkGrid" id="filemem_jmp_grid">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkLabel" id="filemem_jmp">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_left">5</property>
+                        <property name="margin_right">5</property>
+                        <property name="margin_top">5</property>
+                        <property name="margin_bottom">5</property>
+                        <property name="label" translatable="yes">Goto address:</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">0</property>
+                        <property name="width">1</property>
+                        <property name="height">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkEntry" id="filemem_jmp_entry">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="margin_left">5</property>
+                        <property name="margin_right">5</property>
+                        <property name="margin_top">5</property>
+                        <property name="margin_bottom">5</property>
+                        <property name="max_length">15</property>
+                        <property name="invisible_char">•</property>
+                        <property name="width_chars">12</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="top_attach">0</property>
+                        <property name="width">1</property>
+                        <property name="height">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkScrolledWindow" id="filemem_scrolledwindow">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="vexpand">True</property>
+                    <property name="shadow_type">in</property>
+                    <child>
+                      <object class="GtkTreeView" id="filemem_treeview">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="rules_hint">True</property>
+                        <property name="enable_grid_lines">both</property>
+                        <child internal-child="selection">
+                          <object class="GtkTreeSelection" id="treeview-selection2"/>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child type="tab">
+              <object class="GtkLabel" id="filemem_label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">No file</property>
+              </object>
+              <packing>
+                <property name="position">1</property>
+                <property name="tab_fill">False</property>
+              </packing>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child type="tab">
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child type="tab">
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">3</property>
+            <property name="width">1</property>
+            <property name="height">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkInfoBar" id="infobar">
+            <property name="visible">True</property>
+            <property name="app_paintable">True</property>
+            <property name="can_focus">False</property>
+            <property name="message_type">error</property>
+            <child internal-child="content_area">
+              <object class="GtkBox" id="infobar-content_area1">
+                <property name="can_focus">False</property>
+                <property name="border_width">8</property>
+                <property name="spacing">5</property>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child internal-child="action_area">
+              <object class="GtkButtonBox" id="infobar-action_area1">
+                <property name="can_focus">False</property>
+                <property name="border_width">5</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">6</property>
+                <property name="layout_style">end</property>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">1</property>
+            <property name="width">1</property>
+            <property name="height">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>