mirror of
https://git.planet-casio.com/Lephenixnoir/fxsdk.git
synced 2024-12-29 13:03:37 +01:00
Add push mode
This commit is contained in:
parent
7b2294d8c0
commit
6849c1624e
4 changed files with 147 additions and 4 deletions
|
@ -43,7 +43,7 @@ add_custom_target(fxsdk ALL DEPENDS "${BIN}/fxsdk.sh")
|
||||||
|
|
||||||
# fxlink
|
# fxlink
|
||||||
configure_file(fxlink/config.h.in "${BIN}/include/fxlink/config.h")
|
configure_file(fxlink/config.h.in "${BIN}/include/fxlink/config.h")
|
||||||
add_executable(fxlink fxlink/usb.c fxlink/filter.c fxlink/interactive.c
|
add_executable(fxlink fxlink/usb.c fxlink/filter.c fxlink/interactive.c fxlink/push.c
|
||||||
fxlink/main.c fxlink/png.c fxlink/properties.c fxlink/ud2.c fxlink/util.c
|
fxlink/main.c fxlink/png.c fxlink/properties.c fxlink/ud2.c fxlink/util.c
|
||||||
fxlink/protocol.c fxlink/sdl2.c)
|
fxlink/protocol.c fxlink/sdl2.c)
|
||||||
target_link_libraries(fxlink PkgConfig::libpng PkgConfig::libusb)
|
target_link_libraries(fxlink PkgConfig::libpng PkgConfig::libusb)
|
||||||
|
|
|
@ -28,6 +28,9 @@ int main_blocks(filter_t *filter, delay_t *delay);
|
||||||
int main_send(filter_t *filter, delay_t *delay, char **files);
|
int main_send(filter_t *filter, delay_t *delay, char **files);
|
||||||
|
|
||||||
/* Main function for -i */
|
/* Main function for -i */
|
||||||
int main_interactive(filter_t *filter,delay_t *delay,libusb_context *context);
|
int main_interactive(filter_t *filter, delay_t *delay, libusb_context *context);
|
||||||
|
|
||||||
|
/* Main function for -p */
|
||||||
|
int main_push(filter_t *filter, delay_t *delay, libusb_context *context, char **files);
|
||||||
|
|
||||||
#endif /* FXLINK_FXLINK_H */
|
#endif /* FXLINK_FXLINK_H */
|
||||||
|
|
|
@ -30,6 +30,7 @@ static const char *help_string =
|
||||||
" -b, --blocks List detected Mass Storage filesystems (udisks2)\n"
|
" -b, --blocks List detected Mass Storage filesystems (udisks2)\n"
|
||||||
" -s, --send Send a file to a Mass Storage calculator (udisks2)\n"
|
" -s, --send Send a file to a Mass Storage calculator (udisks2)\n"
|
||||||
" -i, --interactive Interactive messaging with a gint add-in (libusb)\n"
|
" -i, --interactive Interactive messaging with a gint add-in (libusb)\n"
|
||||||
|
" -p, --push Push a .bin file to the Add-In Push app (libusb)\n"
|
||||||
"\n"
|
"\n"
|
||||||
"General options:\n"
|
"General options:\n"
|
||||||
" -w DELAY Wait up to this many seconds for a calculator to\n"
|
" -w DELAY Wait up to this many seconds for a calculator to\n"
|
||||||
|
@ -87,6 +88,7 @@ int main(int argc, char **argv)
|
||||||
{ "blocks", no_argument, NULL, 'b' },
|
{ "blocks", no_argument, NULL, 'b' },
|
||||||
{ "send", no_argument, NULL, 's' },
|
{ "send", no_argument, NULL, 's' },
|
||||||
{ "interactive", no_argument, NULL, 'i' },
|
{ "interactive", no_argument, NULL, 'i' },
|
||||||
|
{ "push", no_argument, NULL, 'p' },
|
||||||
{ "libusb-log", required_argument, NULL, LIBUSB_LOG },
|
{ "libusb-log", required_argument, NULL, LIBUSB_LOG },
|
||||||
{ "quiet", no_argument, NULL, 'q' },
|
{ "quiet", no_argument, NULL, 'q' },
|
||||||
{ "fxlink-log", optional_argument, NULL, LOG_TO_FILE },
|
{ "fxlink-log", optional_argument, NULL, LOG_TO_FILE },
|
||||||
|
@ -95,7 +97,7 @@ int main(int argc, char **argv)
|
||||||
};
|
};
|
||||||
|
|
||||||
while(option >= 0 && option != '?')
|
while(option >= 0 && option != '?')
|
||||||
switch((option = getopt_long(argc, argv, "hlbsiquf:w::r", longs, NULL)))
|
switch((option = getopt_long(argc, argv, "hlbsipquf:w::r", longs, NULL)))
|
||||||
{
|
{
|
||||||
case 'h':
|
case 'h':
|
||||||
fprintf(stderr, help_string, argv[0]);
|
fprintf(stderr, help_string, argv[0]);
|
||||||
|
@ -104,6 +106,7 @@ int main(int argc, char **argv)
|
||||||
case 'b':
|
case 'b':
|
||||||
case 's':
|
case 's':
|
||||||
case 'i':
|
case 'i':
|
||||||
|
case 'p':
|
||||||
mode = option;
|
mode = option;
|
||||||
break;
|
break;
|
||||||
case LIBUSB_LOG:
|
case LIBUSB_LOG:
|
||||||
|
@ -163,6 +166,11 @@ int main(int argc, char **argv)
|
||||||
if(mode == 's' && optind == argc)
|
if(mode == 's' && optind == argc)
|
||||||
error = err("send mode requires additional arguments (file names)");
|
error = err("send mode requires additional arguments (file names)");
|
||||||
|
|
||||||
|
if(mode == 'p' && optind == argc)
|
||||||
|
error = err("push mode requires a file name");
|
||||||
|
if(mode == 'p' && optind < argc-1)
|
||||||
|
error = err("push mode only accepts one file name");
|
||||||
|
|
||||||
/* No arguments or bad arguments */
|
/* No arguments or bad arguments */
|
||||||
if(error)
|
if(error)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -178,7 +186,7 @@ int main(int argc, char **argv)
|
||||||
libusb_context *context = NULL;
|
libusb_context *context = NULL;
|
||||||
|
|
||||||
/* Initialize libusb for corresponding modes */
|
/* Initialize libusb for corresponding modes */
|
||||||
if(mode == 'l' || mode == 'i') {
|
if(mode == 'l' || mode == 'i' || mode == 'p') {
|
||||||
if((rc = libusb_init(&context)))
|
if((rc = libusb_init(&context)))
|
||||||
return libusb_err(rc, "error initializing libusb");
|
return libusb_err(rc, "error initializing libusb");
|
||||||
libusb_set_option(context, LIBUSB_OPTION_LOG_LEVEL, loglevel);
|
libusb_set_option(context, LIBUSB_OPTION_LOG_LEVEL, loglevel);
|
||||||
|
@ -211,6 +219,9 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
while(repeat);
|
while(repeat);
|
||||||
}
|
}
|
||||||
|
else if(mode == 'p') {
|
||||||
|
rc = main_push(filter, &delay, context, argv + optind);
|
||||||
|
}
|
||||||
|
|
||||||
if(context)
|
if(context)
|
||||||
libusb_exit(context);
|
libusb_exit(context);
|
||||||
|
|
129
fxlink/push.c
Normal file
129
fxlink/push.c
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
#include "config.h"
|
||||||
|
#include "fxlink.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "properties.h"
|
||||||
|
#include "filter.h"
|
||||||
|
#include "usb.h"
|
||||||
|
|
||||||
|
#include <libusb.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main_push(filter_t *filter, delay_t *delay, libusb_context *context, char** files)
|
||||||
|
{
|
||||||
|
int rc = 1;
|
||||||
|
libusb_device *dev = NULL;
|
||||||
|
libusb_device_handle *dh = NULL;
|
||||||
|
|
||||||
|
FILE *fp = fopen(files[0], "rb");
|
||||||
|
if (!fp) {
|
||||||
|
printf("error: Unable to open file %s\n", files[0]);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
long fsize = ftell(fp);
|
||||||
|
// If more than 6MB, abort
|
||||||
|
if (fsize > 6 * 1024 * 1024) {
|
||||||
|
printf("error: File is too large (max 6MB)\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
fseek(fp, 0, SEEK_SET);
|
||||||
|
uint8_t *filebuf = malloc(fsize);
|
||||||
|
fread(filebuf, fsize, 1, fp);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
/* Wait for a device to be connected */
|
||||||
|
filter_clean_libusb(filter);
|
||||||
|
rc = usb_unique_wait(filter, delay, context, &dev);
|
||||||
|
|
||||||
|
if(rc == FILTER_NONE) {
|
||||||
|
printf("No device found.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if(rc == FILTER_MULTIPLE) {
|
||||||
|
printf("Multiple devices found, ambiguous!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((rc = libusb_open(dev, &dh))) {
|
||||||
|
rc = libusb_err(rc, "cannot open device %s", usb_id(dev));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't detach kernel drivers to avoid breaking the Mass Storage
|
||||||
|
communications if fxlink is ever started while the native LINK
|
||||||
|
application is running! */
|
||||||
|
libusb_set_auto_detach_kernel_driver(dh, false);
|
||||||
|
|
||||||
|
if((rc = libusb_claim_interface(dh, 0))) {
|
||||||
|
rc = libusb_err(rc, "cannot claim interface on %s", usb_id(dev));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Connected to %s\n", usb_id(dev));
|
||||||
|
|
||||||
|
// Wait to receive "USB loader ready" over USB bulk transfer
|
||||||
|
uint8_t buf[18];
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
int actual_length;
|
||||||
|
rc = libusb_bulk_transfer(dh, 0x82, buf, sizeof(buf) - 1, &actual_length, 0);
|
||||||
|
buf[sizeof(buf) - 1] = 0;
|
||||||
|
// if (rc == LIBUSB_ERROR_TIMEOUT) continue;
|
||||||
|
if (rc) {
|
||||||
|
rc = libusb_err(rc, "cannot receive data: %s", usb_id(dev));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (actual_length == 0) continue;
|
||||||
|
if (actual_length != 17) {
|
||||||
|
printf("error: Received %d bytes, expected 17\n", actual_length);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
// See if it's the "USB loader ready" message with strcmp
|
||||||
|
if (strcmp((char*) buf, "USB loader ready") == 0) {
|
||||||
|
printf("Ready to send!\n");
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
printf("error: Unknown message received: %s\n", buf);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the contents of the passed file over USB bulk transfer
|
||||||
|
|
||||||
|
// First send the size of the file
|
||||||
|
uint8_t sizebuf[4];
|
||||||
|
sizebuf[0] = (fsize >> 24) & 0xFF;
|
||||||
|
sizebuf[1] = (fsize >> 16) & 0xFF;
|
||||||
|
sizebuf[2] = (fsize >> 8) & 0xFF;
|
||||||
|
sizebuf[3] = fsize & 0xFF;
|
||||||
|
rc = libusb_bulk_transfer(dh, 0x01, sizebuf, sizeof(sizebuf), NULL, 0);
|
||||||
|
if (rc) {
|
||||||
|
rc = libusb_err(rc, "cannot send size: %s", usb_id(dev));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then send the file contents
|
||||||
|
printf("Sending %ld bytes\n", fsize);
|
||||||
|
int sent = 0;
|
||||||
|
while (sent < fsize) {
|
||||||
|
int actual_length;
|
||||||
|
rc = libusb_bulk_transfer(dh, 0x01, filebuf + sent, fsize - sent, &actual_length, 0);
|
||||||
|
if (rc) {
|
||||||
|
rc = libusb_err(rc, "cannot send data: %s", usb_id(dev));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
sent += actual_length;
|
||||||
|
}
|
||||||
|
printf("Sent %d bytes\n", sent);
|
||||||
|
|
||||||
|
end:
|
||||||
|
if(dh) {
|
||||||
|
libusb_release_interface(dh, 0);
|
||||||
|
libusb_close(dh);
|
||||||
|
}
|
||||||
|
if(dev) libusb_unref_device(dev);
|
||||||
|
return rc;
|
||||||
|
}
|
Loading…
Reference in a new issue