From ce472ffa19fcdd5fbbe6f86170e4d54b518fade2 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Mon, 28 Dec 2015 19:46:48 +0100 Subject: [PATCH] Add the read and write commands. --- examples/Makefile.am | 2 + examples/dctool.c | 2 + examples/dctool.h | 2 + examples/dctool_read.c | 197 +++++++++++++++++++++++++++++++++++++++ examples/dctool_write.c | 200 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 403 insertions(+) create mode 100644 examples/dctool_read.c create mode 100644 examples/dctool_write.c diff --git a/examples/Makefile.am b/examples/Makefile.am index 35f41bc..a0674ca 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -14,5 +14,7 @@ dctool_SOURCES = \ dctool_list.c \ dctool_download.c \ dctool_dump.c \ + dctool_read.c \ + dctool_write.c \ utils.h \ utils.c diff --git a/examples/dctool.c b/examples/dctool.c index faba3a5..d174372 100644 --- a/examples/dctool.c +++ b/examples/dctool.c @@ -53,6 +53,8 @@ static const dctool_command_t *g_commands[] = { &dctool_list, &dctool_download, &dctool_dump, + &dctool_read, + &dctool_write, NULL }; diff --git a/examples/dctool.h b/examples/dctool.h index d4a17be..a818aee 100644 --- a/examples/dctool.h +++ b/examples/dctool.h @@ -47,6 +47,8 @@ extern const dctool_command_t dctool_version; extern const dctool_command_t dctool_list; extern const dctool_command_t dctool_download; extern const dctool_command_t dctool_dump; +extern const dctool_command_t dctool_read; +extern const dctool_command_t dctool_write; const dctool_command_t * dctool_command_find (const char *name); diff --git a/examples/dctool_read.c b/examples/dctool_read.c new file mode 100644 index 0000000..85bd9de --- /dev/null +++ b/examples/dctool_read.c @@ -0,0 +1,197 @@ +/* + * libdivecomputer + * + * Copyright (C) 2015 Jef Driesen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#ifdef HAVE_GETOPT_H +#include +#endif + +#include +#include +#include + +#include "dctool.h" +#include "common.h" +#include "utils.h" + +static dc_status_t +doread (dc_context_t *context, dc_descriptor_t *descriptor, const char *devname, unsigned int address, dc_buffer_t *buffer) +{ + dc_status_t rc = DC_STATUS_SUCCESS; + dc_device_t *device = NULL; + + // Open the device. + message ("Opening the device (%s %s, %s).\n", + dc_descriptor_get_vendor (descriptor), + dc_descriptor_get_product (descriptor), + devname ? devname : "null"); + rc = dc_device_open (&device, context, descriptor, devname); + if (rc != DC_STATUS_SUCCESS) { + ERROR ("Error opening the device."); + goto cleanup; + } + + // Register the event handler. + message ("Registering the event handler.\n"); + int events = DC_EVENT_WAITING | DC_EVENT_PROGRESS | DC_EVENT_DEVINFO | DC_EVENT_CLOCK | DC_EVENT_VENDOR; + rc = dc_device_set_events (device, events, dctool_event_cb, NULL); + if (rc != DC_STATUS_SUCCESS) { + ERROR ("Error registering the event handler."); + goto cleanup; + } + + // Register the cancellation handler. + message ("Registering the cancellation handler.\n"); + rc = dc_device_set_cancel (device, dctool_cancel_cb, NULL); + if (rc != DC_STATUS_SUCCESS) { + ERROR ("Error registering the cancellation handler."); + goto cleanup; + } + + // Read data from the internal memory. + message ("Reading data from the internal memory.\n"); + rc = dc_device_read (device, address, dc_buffer_get_data (buffer), dc_buffer_get_size (buffer)); + if (rc != DC_STATUS_SUCCESS) { + ERROR ("Error reading from the internal memory."); + goto cleanup; + } + +cleanup: + dc_device_close (device); + return rc; +} + +static int +dctool_read_run (int argc, char *argv[], dc_context_t *context, dc_descriptor_t *descriptor) +{ + int exitcode = EXIT_SUCCESS; + dc_status_t status = DC_STATUS_SUCCESS; + dc_buffer_t *buffer = NULL; + + // Default option values. + unsigned int help = 0; + const char *filename = NULL; + unsigned int address = 0, have_address = 0; + unsigned int count = 0, have_count = 0; + + // Parse the command-line options. + int opt = 0; + const char *optstring = "ha:c:o:"; +#ifdef HAVE_GETOPT_LONG + struct option options[] = { + {"help", no_argument, 0, 'h'}, + {"address", required_argument, 0, 'a'}, + {"count", required_argument, 0, 'c'}, + {"output", required_argument, 0, 'o'}, + {0, 0, 0, 0 } + }; + while ((opt = getopt_long (argc, argv, optstring, options, NULL)) != -1) { +#else + while ((opt = getopt (argc, argv, optstring)) != -1) { +#endif + switch (opt) { + case 'h': + help = 1; + break; + case 'a': + address = strtoul (optarg, NULL, 0); + have_address = 1; + break; + case 'c': + count = strtoul (optarg, NULL, 0); + have_count = 1; + break; + case 'o': + filename = optarg; + break; + default: + return EXIT_FAILURE; + } + } + + argc -= optind; + argv += optind; + + // Show help message. + if (help) { + dctool_command_showhelp (&dctool_read); + return EXIT_SUCCESS; + } + + // Check mandatory arguments. + if (!have_address || !have_count) { + message ("No memory address or byte count specified.\n"); + exitcode = EXIT_FAILURE; + goto cleanup; + } + + // Allocate a memory buffer. + buffer = dc_buffer_new (count); + dc_buffer_resize (buffer, count); + if (buffer == NULL) { + message ("Failed to allocate a memory buffer.\n"); + exitcode = EXIT_FAILURE; + goto cleanup; + } + + // Read data from the internal memory. + status = doread (context, descriptor, argv[0], address, buffer); + if (status != DC_STATUS_SUCCESS) { + message ("ERROR: %s\n", dctool_errmsg (status)); + exitcode = EXIT_FAILURE; + goto cleanup; + } + + // Write the buffer to file. + dctool_file_write (filename, buffer); + +cleanup: + dc_buffer_free (buffer); + return exitcode; +} + +const dctool_command_t dctool_read = { + dctool_read_run, + DCTOOL_CONFIG_DESCRIPTOR, + "read", + "Read data from the internal memory", + "Usage:\n" + " dctool read [options] \n" + "\n" + "Options:\n" +#ifdef HAVE_GETOPT_LONG + " -h, --help Show help message\n" + " -a, --address
Memory address\n" + " -c, --count Number of bytes\n" + " -o, --output Output filename\n" +#else + " -h Show help message\n" + " -a
Memory address\n" + " -c Number of bytes\n" + " -o Output filename\n" +#endif +}; diff --git a/examples/dctool_write.c b/examples/dctool_write.c new file mode 100644 index 0000000..4bf193b --- /dev/null +++ b/examples/dctool_write.c @@ -0,0 +1,200 @@ +/* + * libdivecomputer + * + * Copyright (C) 2015 Jef Driesen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#ifdef HAVE_GETOPT_H +#include +#endif + +#include +#include +#include + +#include "dctool.h" +#include "common.h" +#include "utils.h" + +static dc_status_t +dowrite (dc_context_t *context, dc_descriptor_t *descriptor, const char *devname, unsigned int address, dc_buffer_t *buffer) +{ + dc_status_t rc = DC_STATUS_SUCCESS; + dc_device_t *device = NULL; + + // Open the device. + message ("Opening the device (%s %s, %s).\n", + dc_descriptor_get_vendor (descriptor), + dc_descriptor_get_product (descriptor), + devname ? devname : "null"); + rc = dc_device_open (&device, context, descriptor, devname); + if (rc != DC_STATUS_SUCCESS) { + ERROR ("Error opening the device."); + goto cleanup; + } + + // Register the event handler. + message ("Registering the event handler.\n"); + int events = DC_EVENT_WAITING | DC_EVENT_PROGRESS | DC_EVENT_DEVINFO | DC_EVENT_CLOCK | DC_EVENT_VENDOR; + rc = dc_device_set_events (device, events, dctool_event_cb, NULL); + if (rc != DC_STATUS_SUCCESS) { + ERROR ("Error registering the event handler."); + goto cleanup; + } + + // Register the cancellation handler. + message ("Registering the cancellation handler.\n"); + rc = dc_device_set_cancel (device, dctool_cancel_cb, NULL); + if (rc != DC_STATUS_SUCCESS) { + ERROR ("Error registering the cancellation handler."); + goto cleanup; + } + + // Write data to the internal memory. + message ("Writing data to the internal memory.\n"); + rc = dc_device_write (device, address, dc_buffer_get_data (buffer), dc_buffer_get_size (buffer)); + if (rc != DC_STATUS_SUCCESS) { + ERROR ("Error writing to the internal memory."); + goto cleanup; + } + +cleanup: + dc_device_close (device); + return rc; +} + +static int +dctool_write_run (int argc, char *argv[], dc_context_t *context, dc_descriptor_t *descriptor) +{ + int exitcode = EXIT_SUCCESS; + dc_status_t status = DC_STATUS_SUCCESS; + dc_buffer_t *buffer = NULL; + + // Default option values. + unsigned int help = 0; + const char *filename = NULL; + unsigned int address = 0, have_address = 0; + unsigned int count = 0, have_count = 0; + + // Parse the command-line options. + int opt = 0; + const char *optstring = "ha:c:i:"; +#ifdef HAVE_GETOPT_LONG + struct option options[] = { + {"help", no_argument, 0, 'h'}, + {"address", required_argument, 0, 'a'}, + {"count", required_argument, 0, 'c'}, + {"input", required_argument, 0, 'i'}, + {0, 0, 0, 0 } + }; + while ((opt = getopt_long (argc, argv, optstring, options, NULL)) != -1) { +#else + while ((opt = getopt (argc, argv, optstring)) != -1) { +#endif + switch (opt) { + case 'h': + help = 1; + break; + case 'a': + address = strtoul (optarg, NULL, 0); + have_address = 1; + break; + case 'c': + count = strtoul (optarg, NULL, 0); + have_count = 1; + break; + case 'i': + filename = optarg; + break; + default: + return EXIT_FAILURE; + } + } + + argc -= optind; + argv += optind; + + // Show help message. + if (help) { + dctool_command_showhelp (&dctool_write); + return EXIT_SUCCESS; + } + + // Check mandatory arguments. + if (!have_address) { + message ("No memory address specified.\n"); + exitcode = EXIT_FAILURE; + goto cleanup; + } + + // Read the buffer from file. + buffer = dctool_file_read (filename); + if (buffer == NULL) { + message ("Failed to read the input file.\n"); + exitcode = EXIT_FAILURE; + goto cleanup; + } + + // Check the number of bytes (if provided) + if (have_count && count != dc_buffer_get_size (buffer)) { + message ("Number of bytes doesn't match file length.\n"); + exitcode = EXIT_FAILURE; + goto cleanup; + } + + // Write data to the internal memory. + status = dowrite (context, descriptor, argv[0], address, buffer); + if (status != DC_STATUS_SUCCESS) { + message ("ERROR: %s\n", dctool_errmsg (status)); + exitcode = EXIT_FAILURE; + goto cleanup; + } + +cleanup: + dc_buffer_free (buffer); + return exitcode; +} + +const dctool_command_t dctool_write = { + dctool_write_run, + DCTOOL_CONFIG_DESCRIPTOR, + "write", + "Write data to the internal memory", + "Usage:\n" + " dctool write [options] \n" + "\n" + "Options:\n" +#ifdef HAVE_GETOPT_LONG + " -h, --help Show help message\n" + " -a, --address
Memory address\n" + " -c, --count Number of bytes\n" + " -i, --input Input filename\n" +#else + " -h Show help message\n" + " -a
Memory address\n" + " -c Number of bytes\n" + " -i Input filename\n" +#endif +};