mirror of
https://github.com/raphnet/gc_n64_usb-v3
synced 2025-01-30 14:50:10 -05:00
Work in progress on GUI (firmware update)
This commit is contained in:
parent
bfa73890d4
commit
a103350625
@ -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
|
||||
|
||||
|
@ -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>
|
||||
|
139
tool/gtk/main.c
139
tool/gtk/main.c
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user