#!/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
make
else
./autogen.sh
- ./configure
+ if [ "$TRAVIS_OS_NAME" == "osx" ]; then
+ ./configure
+ else
+ ./configure --with-gtk-gui
+ fi
make
fi
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
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()
# Makefile.am -- Process this file with automake to produce Makefile.in
-SUBDIRS = . $(MAYBE_GUI)
+SUBDIRS = . $(STLINK_HAS_GUI)
AUTOMAKE_OPTIONS = subdir-objects
* `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
```
$ ./autogen.sh
-$ ./configure
+$ ./configure --with-gtk-gui
$ make
```
# 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])
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
+++ /dev/null
-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
+++ /dev/null
-#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;
-}
+++ /dev/null
-
-#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
+++ /dev/null
-<?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"><b>Device</b></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>
--- /dev/null
+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
--- /dev/null
+#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;
+}
--- /dev/null
+
+#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
--- /dev/null
+<?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"><b>Device</b></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>