Work in progress on GUI (firmware update)

This commit is contained in:
Raphael Assenat 2015-10-20 07:55:08 -04:00
parent bfa73890d4
commit a103350625
3 changed files with 206 additions and 55 deletions

View File

@ -8,7 +8,7 @@ PREFIX=/usr/local
PROG=gcn64ctl_gui
OBJS=main.o ../gcn64.o ../mempak.o ../gcn64lib.o ../hexdump.o
OBJS=main.o ../gcn64.o ../mempak.o ../gcn64lib.o ../hexdump.o ../ihex.o
.PHONY : clean install

View File

@ -579,7 +579,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="gtk_widget_show" object="hexfile_chooser" swapped="yes"/>
<signal name="clicked" handler="update_usbadapter_firmware" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
@ -655,35 +655,30 @@
</object>
</child>
</object>
<object class="GtkFileChooserDialog" id="hexfile_chooser">
<object class="GtkDialog" id="firmware_update_dialog">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Select firmware file...</property>
<property name="title" translatable="yes">Firmware update</property>
<property name="resizable">False</property>
<property name="modal">True</property>
<property name="type_hint">dialog</property>
<property name="attached_to">mainWindow</property>
<property name="filter">hexfilter</property>
<property name="local_only">False</property>
<property name="preview_widget_active">False</property>
<property name="use_preview_label">False</property>
<property name="transient_for">mainWindow</property>
<child internal-child="vbox">
<object class="GtkBox" id="filechooserdialog-vbox1">
<object class="GtkBox" id="dialog-vbox1">
<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="filechooserdialog-action_area1">
<object class="GtkButtonBox" id="update_dialog_btnBox">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="button5">
<object class="GtkButton" id="update_cancel_button">
<property name="label">gtk-cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="relief">none</property>
<property name="use_stock">True</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="gtk_widget_hide" object="hexfile_chooser" swapped="yes"/>
</object>
<packing>
<property name="expand">True</property>
@ -692,14 +687,13 @@
</packing>
</child>
<child>
<object class="GtkButton" id="button6">
<property name="label">gtk-open</property>
<object class="GtkButton" id="update_start_btn">
<property name="label" translatable="yes">Start update</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="yalign">0.46000000834465027</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="updatestart_btn_clicked_cb" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
@ -715,42 +709,51 @@
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
<object class="GtkMessageDialog" id="internalError">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Error</property>
<property name="modal">True</property>
<property name="icon_name">dialog-error</property>
<property name="type_hint">normal</property>
<property name="transient_for">mainWindow</property>
<property name="message_type">question</property>
<property name="text" translatable="yes">Internal error</property>
<child internal-child="vbox">
<object class="GtkBox" id="messagedialog-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="messagedialog-action_area">
<object class="GtkBox" id="box6">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="homogeneous">True</property>
<property name="layout_style">end</property>
<property name="valign">center</property>
<property name="orientation">vertical</property>
<child>
<placeholder/>
<object class="GtkBox" id="box7">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="label10">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Firmware file:</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_firmware_filename">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">filename.hex</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="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="internalErrorDialog">
<property name="label">gtk-close</property>
<object class="GtkProgressBar" id="updateProgress">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="yalign">0.47999998927116394</property>
<signal name="clicked" handler="gtk_main_quit" swapped="no"/>
<property name="can_focus">False</property>
<property name="show_text">True</property>
</object>
<packing>
<property name="expand">True</property>
@ -758,14 +761,29 @@
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="updateStatus">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Ready</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="1">update_cancel_button</action-widget>
</action-widgets>
</object>
</interface>

View File

@ -1,18 +1,150 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <gtk/gtk.h>
#include "../gcn64.h"
#include "../gcn64lib.h"
#include "../../requests.h"
#include "../ihex.h"
#define GET_ELEMENT(TYPE, ELEMENT) (TYPE *)gtk_builder_get_object(app->builder, #ELEMENT)
#define GET_UI_ELEMENT(TYPE, ELEMENT) TYPE *ELEMENT = GET_ELEMENT(TYPE, ELEMENT)
struct application {
GtkBuilder *builder;
GtkWindow *mainwindow;
gcn64_hdl_t current_adapter_handle;
};
G_MODULE_EXPORT void updatestart_btn_clicked_cb(GtkWidget *w, gpointer data)
{
struct application *app = data;
GET_UI_ELEMENT(GtkProgressBar, updateProgress);
GET_UI_ELEMENT(GtkDialog, firmware_update_dialog);
GET_UI_ELEMENT(GtkButtonBox, update_dialog_btnBox);
int i;
gtk_widget_set_sensitive(GTK_WIDGET(update_dialog_btnBox), FALSE);
for (i=0; i<100; i++) {
gtk_progress_bar_set_fraction(updateProgress, i/100.0);
usleep(50000);
gtk_main_iteration_do(FALSE);
}
gtk_dialog_response(firmware_update_dialog, GTK_RESPONSE_OK);
}
void infoPopop(struct application *app, const char *message)
{
GtkWidget *dialog;
dialog = gtk_message_dialog_new(app->mainwindow,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_CLOSE,
message);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
}
void errorPopop(struct application *app, const char *message)
{
GtkWidget *dialog;
dialog = gtk_message_dialog_new(app->mainwindow,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
message);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
}
#define IHEX_MAX_FILE_SIZE 0x20000
char check_ihex_for_signature(const char *filename, const char *signature)
{
unsigned char *buf;
int max_address;
buf = malloc(IHEX_MAX_FILE_SIZE);
if (!buf) {
perror("malloc");
return 0;
}
max_address= load_ihex(filename, buf, IHEX_MAX_FILE_SIZE);
if (max_address > 0) {
if (!memmem(buf, max_address + 1, signature, strlen(signature))) {
return 0;
}
return 1;
}
return 0;
}
G_MODULE_EXPORT void update_usbadapter_firmware(GtkWidget *w, gpointer data)
{
struct application *app = data;
gint res;
GtkWidget *dialog;
GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN;
GET_UI_ELEMENT(GtkFileFilter, hexfilter);
GET_UI_ELEMENT(GtkDialog, firmware_update_dialog);
GET_UI_ELEMENT(GtkLabel, lbl_firmware_filename);
GET_UI_ELEMENT(GtkButtonBox, update_dialog_btnBox);
dialog = gtk_file_chooser_dialog_new("Open .hex file",
app->mainwindow,
action,
"_Cancel",
GTK_RESPONSE_CANCEL,
"_Open",
GTK_RESPONSE_ACCEPT,
NULL);
gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), hexfilter);
res = gtk_dialog_run (GTK_DIALOG(dialog));
if (res == GTK_RESPONSE_ACCEPT) {
char *filename, *basename;
GtkFileChooser *chooser = GTK_FILE_CHOOSER(dialog);
filename = gtk_file_chooser_get_filename(chooser);
basename = g_path_get_basename(filename);
printf("File selected: %s\n", filename);
if (!check_ihex_for_signature(filename, "9c3ea8b8-753f-11e5-a0dc-001bfca3c593")) {
errorPopop(app, "Signature not found - This file is invalid or not meant for this adapter");
}
/* Prepare the update dialog widgets... */
gtk_label_set_text(lbl_firmware_filename, basename);
gtk_widget_set_sensitive(GTK_WIDGET(update_dialog_btnBox), TRUE);
/* Run the dialog */
res = gtk_dialog_run(firmware_update_dialog);
gtk_widget_hide( GTK_WIDGET(firmware_update_dialog));
if (res == GTK_RESPONSE_OK) {
infoPopop(app, "Update succeeded.");
}
g_free(filename);
g_free(basename);
}
gtk_widget_destroy(dialog);
}
static void updateGuiFromAdapter(struct application *app, struct gcn64_info *info)
{
unsigned char buf[32];
@ -197,7 +329,7 @@ int
main( int argc,
char **argv )
{
GtkWidget *window;
GtkWindow *window;
GError *error = NULL;
struct application app = { };
@ -216,7 +348,8 @@ main( int argc,
}
/* Get main window pointer from UI */
window = GTK_WIDGET( gtk_builder_get_object( app.builder, "mainWindow" ) );
window = GTK_WINDOW( gtk_builder_get_object( app.builder, "mainWindow" ) );
app.mainwindow = window;
/* Connect signals */
gtk_builder_connect_signals( app.builder, &app );
@ -225,7 +358,7 @@ main( int argc,
// g_object_unref( G_OBJECT( builder ) );
/* Show window. All other widgets are automatically shown by GtkBuilder */
gtk_widget_show( window );
gtk_widget_show( GTK_WIDGET(window) );
/* Start main loop */
gtk_main();