Bodged p7os in.
This commit is contained in:
parent
24237160e4
commit
6545ef3546
|
@ -0,0 +1,3 @@
|
|||
[submodule "src/p7os/update.exe"]
|
||||
path = src/p7os/update.exe
|
||||
url = https://forge.touhey.fr/casio/update.exe
|
19
Makefile
19
Makefile
|
@ -84,13 +84,26 @@ reinstall: uninstall install
|
|||
$(BINARIES:%=$(OBJDIR)/%):
|
||||
$(call bcmd,mkdir,$@,$(MD) $@)
|
||||
|
||||
# Make an object out of a C source file.
|
||||
# Make an object out of a source file/directory.
|
||||
define make-binaryobj-rule
|
||||
$(OBJDIR)/$1/%.o: $(SRCDIR)/$1/%.c | $(OBJDIR)/$1
|
||||
ifeq ($(shell test -f $(SRCDIR)/$1/$2.c && echo y),y)
|
||||
# - Out of a C source file
|
||||
$(OBJDIR)/$1/$2.o: $(SRCDIR)/$1/$2.c | $(OBJDIR)/$1
|
||||
$(call bcmd,cc,$$@,$(CC) -c -o $$@ $$< $(CFLAGS))
|
||||
else
|
||||
# - Out of an update.exe project
|
||||
$(SRCDIR)/$1/$2.exe/$2.exe.bin:| $(SRCDIR)/$1/$2.exe
|
||||
$(call qcmd,cd $$| && ./configure)
|
||||
$(call bcmd,make,$2.exe,$(MAKE) $$| $2.exe.bin | sed -e 's/^/ /')
|
||||
|
||||
$(OBJDIR)/$1/$2.o: $(SRCDIR)/$1/$2.exe/$2.exe.bin | $(OBJDIR)/$1
|
||||
$(call bcmd,ld -r,$$@,cd $(SRCDIR)/$1/$2.exe && \
|
||||
$(LDR) -o ../../../$$@ -b binary $2.exe.bin)
|
||||
endif
|
||||
endef
|
||||
$(foreach bin,$(BINARIES),\
|
||||
$(eval $(call make-binaryobj-rule,$(bin))))
|
||||
$(foreach obj,$(SRC_$(bin)),\
|
||||
$(eval $(call make-binaryobj-rule,$(bin),$(obj)))))
|
||||
|
||||
# Make a binary
|
||||
define make-binary-rule
|
||||
|
|
|
@ -76,6 +76,11 @@
|
|||
LDFLAGS := $(shell $(PKGCONFIG) --libs $(LIBS) 2>/dev/null) \
|
||||
$(if $(FOR_WINDOWS),,$(LDFLAGS_Linux))
|
||||
|
||||
# Raw ELF object maker
|
||||
LDR := $(TARGET)ld -r
|
||||
|
||||
# Maker
|
||||
MAKE := make -C
|
||||
# Directory maker
|
||||
MD := mkdir -p
|
||||
# File remover
|
||||
|
@ -97,7 +102,9 @@
|
|||
# Look for their sources
|
||||
define get-binary-sources
|
||||
SRC_$1 := $(basename $(shell find $(SRCDIR)/$1 \
|
||||
-maxdepth 1 -mindepth 1 -type f -name "*.c" -printf "%P\n" | sort))
|
||||
-maxdepth 1 -mindepth 1 \
|
||||
\( -name "*.c" -or -name "*.exe" \) \
|
||||
-printf "%P\n" | sort))
|
||||
endef
|
||||
$(foreach bin,$(BINARIES), \
|
||||
$(eval $(call get-binary-sources,$(bin))))
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
P7OS(1)
|
||||
=======
|
||||
Thomas "Cakeisalie5" Touhey
|
||||
:Email: thomas@touhey.fr
|
||||
:man source: p7os
|
||||
:man manual: p7os manual
|
||||
|
||||
NAME
|
||||
----
|
||||
p7os - get and change CASIO calculator's OSes using protocol 7
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[source,bash]
|
||||
----
|
||||
p7os [-h|--help] [-v|--version] [<subcommand> [<args>]]
|
||||
----
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
p7os is a command-line utility to get and upload an OS on CASIO fx calculators,
|
||||
using its communication protocol 7.00 and OS update mode.
|
||||
|
||||
Available submenus are :
|
||||
|
||||
*prepare*::
|
||||
This subcommand must be run before *any* other subcommand. It will upload
|
||||
a P7 server that supports the commands required by them.
|
||||
*get [-o os.bin]*::
|
||||
Get OS image copy.
|
||||
|
||||
You have to *prepare* before doing any other action. Preparing means sending
|
||||
a P7 server on the calculator that will be able to execute commands required
|
||||
by other subcommands.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
Options start with one or two dashes. Some of the options require an additional
|
||||
value next to them.
|
||||
|
||||
*-h, --help*::
|
||||
Display command/subcommand help page and quit.
|
||||
*-v, --version*::
|
||||
Display version and quit.
|
||||
*--device /dev/mydevice0*::
|
||||
The device with which to interact.
|
||||
Mostly */dev/cfx0* for USB and */dev/ttyS0* for serial connections.
|
||||
*-o OUT, --output=OUT*::
|
||||
When getting something, where to store.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
*libp7*(3)
|
|
@ -0,0 +1,175 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* args.c |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project: p7os | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/09/28 06:00:10 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#include "main.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Help and version messages */
|
||||
/* ************************************************************************** */
|
||||
/* The version message - that's when the President comes in */
|
||||
const char version_message[] =
|
||||
"P7OS v" QUOTE(VERSION) " (licensed under " QUOTE(LICENSE) ")\n"
|
||||
"Made by " QUOTE(AUTHOR) " <" QUOTE(AUTHOR_MAIL) ">.\n"
|
||||
"\n"
|
||||
"This is free software; see the source for copying conditions.\n"
|
||||
"There is NO warranty; not even for MERCHANTABILITY or\n"
|
||||
"FITNESS FOR A PARTICULAR PURPOSE.";
|
||||
|
||||
/* Main help message */
|
||||
const char help_main[] =
|
||||
"Usage: p7os [--version|-v] [--help|-h] [--device /dev/omg0]\n"
|
||||
" <subcommand> [options...]\n"
|
||||
"\n"
|
||||
"Subcommands you can use are :\n"
|
||||
" prepare Prepare server on distant machine\n"
|
||||
" get Get the OS image\n"
|
||||
"\n"
|
||||
"All subcommands that aren't \"prepare\" require \"prepare\" to be run\n"
|
||||
"before them.\n"
|
||||
"\n"
|
||||
"General options:\n"
|
||||
" -h, --help Display the help page of the (sub)command and quit.\n"
|
||||
" -v, --version Display the version message and quit.\n"
|
||||
" --device dev The calculator device (usually /dev/ttyUSBx).\n"
|
||||
" By default, will use the first appropriate device found.\n"
|
||||
"\n"
|
||||
"Type \"p7os <subcommand> --help\" for some help about a subcommand.\n"
|
||||
"Report bugs to " QUOTE(AUTHOR) " <" QUOTE(AUTHOR_MAIL) ">.";
|
||||
|
||||
/* Help message for prepare subcommand */
|
||||
const char help_prepare[] =
|
||||
"Usage: p7os prepare\n"
|
||||
"Send the P7 server on the calculator for further operations.\n"
|
||||
"This must be used before any other p7os operation.\n"
|
||||
"\n"
|
||||
"Type \"p7os --help\" for other subcommands and general options.";
|
||||
|
||||
/* Help message for get subcommand */
|
||||
const char help_get[] =
|
||||
"Usage: p7os get [-o <os.bin>]\n"
|
||||
"Get the calculator OS image.\n"
|
||||
"You must have \"p7os prepare\"-ed before.\n"
|
||||
"\n"
|
||||
"Options are :\n"
|
||||
" -o <os.bin> Where to store the image (default is \"os.bin\")\n"
|
||||
"\n"
|
||||
"Type \"p7os --help\" for other subcommands and general options.";
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Main function */
|
||||
/* ************************************************************************** */
|
||||
/* Help macro */
|
||||
#define ragequit(ARGS, N) { \
|
||||
if (help || aac != (ARGS)) { \
|
||||
puts(help_##N); \
|
||||
return (1); \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* parse_args:
|
||||
* Args parsing main function.
|
||||
*
|
||||
* Based on my very first experiment with getopt.
|
||||
*
|
||||
* @arg ac the arguments count
|
||||
* @arg av the arguments values
|
||||
* @arg args the parsed args pointer
|
||||
* @return if has been parsed successfully
|
||||
*/
|
||||
|
||||
int parse_args(int ac, char **av, args_t *args)
|
||||
{
|
||||
/* initialize args */
|
||||
*args = (args_t){
|
||||
.device = NULL,
|
||||
.local = NULL, .localpath = NULL
|
||||
};
|
||||
|
||||
/* define options */
|
||||
const char short_options[] = "hvo:";
|
||||
const struct option long_options[] = {
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"version", no_argument, NULL, 'v'},
|
||||
{"device", required_argument, NULL, 'p'},
|
||||
{"output", required_argument, NULL, 'o'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
/* get all options */
|
||||
int c; opterr = 0;
|
||||
int help = 0, version = 0;
|
||||
const char *s_out = "os.bin";
|
||||
while ((c = getopt_long(ac, av, short_options, long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
/* help */
|
||||
case 'h': help = 1; break;
|
||||
/* version */
|
||||
case 'v': version = 1; break;
|
||||
/* device */
|
||||
case 'p': args->device = optarg; break;
|
||||
/* output */
|
||||
case 'o': s_out = optarg; break;
|
||||
|
||||
/* error */
|
||||
case '?':
|
||||
if (optopt == 'o')
|
||||
log("-o, --output: expected an argument\n");
|
||||
else if (optopt == 'p')
|
||||
log("--device: expected an argument\n");
|
||||
else
|
||||
break;
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
/* check for version */
|
||||
if (version) {
|
||||
puts(version_message);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* get non-option arguments (subcommand and parameters) */
|
||||
int aac = ac - optind;
|
||||
char **aav = &av[optind];
|
||||
char *sub = aac ? aav[0] : NULL;
|
||||
aac--; aav++;
|
||||
|
||||
/* subcommand. */
|
||||
char fpmode[2] = "r";
|
||||
if (!sub || !strcmp(sub, "help")) {
|
||||
puts(help_main);
|
||||
return (1);
|
||||
} else if (!strcmp(sub, "prepare")) {
|
||||
ragequit(0, prepare)
|
||||
} else if (!strcmp(sub, "get")) {
|
||||
ragequit(0, get)
|
||||
args->localpath = s_out;
|
||||
fpmode[0] = 'w';
|
||||
} else {
|
||||
log("Unknown subcommand '%s'.\n", aav[0]);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* open destination file */
|
||||
if (args->localpath) {
|
||||
args->local = fopen(args->localpath, fpmode);
|
||||
if (!args->local) {
|
||||
log("Could not open local file: '%s'\n", strerror(errno));
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
/* everything went well :) */
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* main.c |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project: p7os | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/09/28 06:00:10 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#include "main.h"
|
||||
#include <unistd.h>
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Error messages */
|
||||
/* ************************************************************************** */
|
||||
/* Couldn't initialize connexion to calculator. */
|
||||
const char error_noconnexion[] =
|
||||
"Could not connect to the calculator.\n"
|
||||
"- Is it plugged in and in Receive mode/OS Update?\n"
|
||||
"- Have you tried changing the cable ?\n";
|
||||
|
||||
/* Calculator was found but program wasn't allowed to communicate with it. */
|
||||
const char error_noaccess[] =
|
||||
"Could not get access to the calculator.\n"
|
||||
"Install the appropriate udev rule, or run as root.\n";
|
||||
|
||||
/* The calculator acted in a weird way. */
|
||||
const char error_unplanned[] =
|
||||
"The calculator didn't act as planned: %s.\n"
|
||||
"Stop receive mode on calculator and start it again before re-running p7os.\n";
|
||||
|
||||
/* Unsupported operation -> OS Update, not receive mode! */
|
||||
const char error_unsupported[] =
|
||||
"Required operation was unsupported.\n"
|
||||
"- If you were using anything else than the *prepare* subcommand, are you\n"
|
||||
" sure you've run *prepare* before?\n"
|
||||
"- Otherwise, I gotta be honest, I'd like to know how you've managed that.\n";
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Main function */
|
||||
/* ************************************************************************** */
|
||||
/**
|
||||
* main:
|
||||
* User entry point of the program.
|
||||
*
|
||||
* @arg ac arguments count
|
||||
* @arg av arguments values
|
||||
* @return return code (0 if OK)
|
||||
*/
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
/* parse args */
|
||||
args_t args;
|
||||
if (parse_args(ac, av, &args))
|
||||
return (0);
|
||||
|
||||
/* Initialize libp7 and communication */
|
||||
p7_handle_t *handle; int err;
|
||||
if (args.device) err = p7_cinit(&handle, 1, 1, args.device, 0);
|
||||
else err = p7_init(&handle, 1, 1);
|
||||
if (err) {
|
||||
/* displaying error */
|
||||
switch (err) {
|
||||
case p7_error_nocalc: log(error_noconnexion);
|
||||
case p7_error_noaccess: log(error_noaccess);
|
||||
case p7_error_unsupported: log(error_unsupported);
|
||||
default: log(error_unplanned, p7_strerror(err));
|
||||
}
|
||||
|
||||
/* closing, removing if necessary */
|
||||
if (args.localpath) {
|
||||
fclose(args.local);
|
||||
remove(args.localpath);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* check according to menu */
|
||||
FILE *update_exe;
|
||||
switch (args.menu) {
|
||||
/* prepare menu */
|
||||
case mn_prepare:;
|
||||
/* open memory stream for the update.exe */
|
||||
size_t uexe_size = (size_t)&update_exe_end - (size_t)&update_exe_str;
|
||||
update_exe = fmemopen(update_exe_str, uexe_size, "r");
|
||||
if (!update_exe) break;
|
||||
|
||||
/* send the update.exe */
|
||||
if ((err = p7_sendexe_stream(handle, update_exe, (p7uint_t)uexe_size,
|
||||
0x88030000, 0x88030000)))
|
||||
fprintf(stderr, "An error has occurred: %s\n", p7_strerror(err));
|
||||
break;
|
||||
|
||||
/* get menu */
|
||||
case mn_get:
|
||||
/* get the os */
|
||||
err = !get_os(handle, args.local);
|
||||
fclose(args.local);
|
||||
/* if there was an error, delete created file */
|
||||
if (err) unlink(args.localpath);
|
||||
break;
|
||||
}
|
||||
|
||||
/* exit libp7
|
||||
* due to the nature of command 0x56,
|
||||
* no need to terminate communication! */
|
||||
p7_exit(handle, 0);
|
||||
|
||||
/* then we're good */
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* main.h |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project: p7os | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/09/28 06:00:10 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#ifndef MAIN_H
|
||||
# define MAIN_H
|
||||
# include <stdio.h>
|
||||
# include <libp7.h>
|
||||
# define Q(x) #x
|
||||
# define QUOTE(x) Q(x)
|
||||
# define log(S, ...) fprintf(stderr, S, ##__VA_ARGS__)
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Embedded update.exe */
|
||||
/* ************************************************************************** */
|
||||
#define update_exe_str (_binary_update_exe_bin_start)
|
||||
#define update_exe_end (_binary_update_exe_bin_end)
|
||||
extern char _binary_update_exe_bin_start[];
|
||||
extern char _binary_update_exe_bin_end[];
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* CLI options */
|
||||
/* ************************************************************************** */
|
||||
/* Menu */
|
||||
typedef enum {
|
||||
mn_prepare,
|
||||
mn_get
|
||||
} menu_t;
|
||||
|
||||
/* Arguments */
|
||||
typedef struct {
|
||||
/* basic things */
|
||||
menu_t menu;
|
||||
|
||||
/* others */
|
||||
char *device;
|
||||
FILE *local; const char *localpath;
|
||||
} args_t;
|
||||
|
||||
/* Parsing function */
|
||||
int parse_args(int ac, char **av, args_t *args);
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Actual things */
|
||||
/* ************************************************************************** */
|
||||
/* Main functions */
|
||||
int get_os(p7_handle_t *handle, FILE *dest);
|
||||
|
||||
#endif /* MAIN_H */
|
|
@ -0,0 +1,30 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* stuff.c |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project: p7os | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/09/28 06:00:10 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#include "main.h"
|
||||
|
||||
/**
|
||||
* get_os:
|
||||
* Gather the OS.
|
||||
*
|
||||
* @arg handle the libp7 handle
|
||||
* @arg dest the destination file
|
||||
* @return if it worked
|
||||
*/
|
||||
|
||||
int get_os(p7_handle_t *handle, FILE *dest)
|
||||
{
|
||||
/* TODO */
|
||||
fprintf(stderr, "Unimplemented yet.\n");
|
||||
(void)handle;
|
||||
(void)dest;
|
||||
|
||||
/* then nothing */
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 787d8bb1083c7608bd62ff06a73b441e920c6105
|
Reference in New Issue