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