README: mention that the Prevention DS-2200PV uses the same protocol
[visomat-utils.git] / src / visomat-data-downloader.c
index a53f72c..1cbe6f5 100644 (file)
  */
 
 #include <stdio.h>
+#include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
 #include <unistd.h>
 #include <libusb.h>
 
+#ifdef DEBUG
+#define debug(...) fprintf(stderr, __VA_ARGS__)
+static void debug_dump_buffer(const char *filename, uint8_t *buffer, unsigned int len)
+{
+       FILE *dump_file;
+
+       dump_file = fopen(filename, "wb");
+       if (dump_file == NULL) {
+               fprintf(stderr, "Failed to open %s: %s\n", filename, strerror(errno));
+               return;
+       }
+
+       fwrite(buffer, 1, len, dump_file);
+       fclose(dump_file);
+}
+#else
+#define debug(...) do {} while(0)
+static void debug_dump_buffer(const char *filename, uint8_t *buffer, unsigned int len)
+{
+       (void)filename;
+       (void)buffer;
+       (void)len;
+}
+#endif
+
 #define VISOMAT_DEVICE_VID    0x1247
 #define VISOMAT_DEVICE_PID    0x00f8
 #define VISOMAT_CONFIGURATION 1
 #define VISOMAT_INTERFACE     1
 #define VISOMAT_EP_IN         0x82
 #define VISOMAT_EP_OUT        0x03
+#define VISOMAT_PACKET_SIZE   64
 
 #define STX 0x02
 #define ETX 0x03
 
+#define DATETIME_PACKET_SIZE 15
 #define BASE_YEAR 2000
 
 typedef enum {
@@ -206,18 +234,18 @@ static int decode_eeprom(uint8_t *buffer,
 static int decode_datetime(uint8_t *buffer, unsigned int len)
 {
        int ret;
-       uint8_t code[4] = { 0 };
+       uint8_t code[4] = { 0 }; /* the initial STX + 3 bytes command code */
        struct datetime d;
        uint8_t *pbuffer = buffer;
 
-       if (len != 15)
+       if (len != DATETIME_PACKET_SIZE)
                return -EINVAL;
 
        code[0] = buffer[1];
        code[1] = buffer[2];
        code[2] = buffer[3];
 
-       ret = extract_datetime(pbuffer + 4, &d);
+       ret = extract_datetime(pbuffer + sizeof(code), &d);
        if (ret < 0)
                return ret;
 
@@ -255,7 +283,7 @@ static int get_response(libusb_device_handle *dev,
 {
        int ret;
        int transferred;
-       uint8_t response[64] = { 0 };
+       uint8_t response[VISOMAT_PACKET_SIZE] = { 0 };
        unsigned int i;
 
        i = 0;
@@ -277,7 +305,7 @@ static int get_response(libusb_device_handle *dev,
 
        } while (buffer[i - 1] != ETX && i < len);
 
-       /* Check the buffer is a valid response packet */
+       /* Check if the buffer contains a valid response packet */
        if (buffer[0] != STX || buffer[i - 1] != ETX)
                return -EINVAL;
 
@@ -288,8 +316,8 @@ static int get_response(libusb_device_handle *dev,
 #define visomat_device libusb_device_handle
 static int visomat_dump_eeprom(visomat_device *dev, unsigned int user_mask)
 {
-       /* Assuming an EEPROM of 1 KiB  */
-       uint8_t buffer[1024] = { 0 };
+       /* Assuming an EEPROM of 4 KiB  */
+       uint8_t buffer[4096] = { 0 };
        int ret;
 
        ret = send_command(dev, VISOMAT_CMD_DUMP_EEPROM);
@@ -297,6 +325,8 @@ static int visomat_dump_eeprom(visomat_device *dev, unsigned int user_mask)
                return ret;
 
        ret = get_response(dev, buffer, sizeof(buffer));
+       debug("buffer size: %d\n", ret);
+       debug_dump_buffer("eeprom.bin", buffer, sizeof(buffer));
        if (ret < 0)
                return ret;
 
@@ -327,12 +357,38 @@ static int visomat_get_datetime(visomat_device *dev)
        return 0;
 }
 
-int main(void)
+static void usage(const char *name)
+{
+       printf("usage: %s [OPTIONS]\n\n", name);
+       printf("OPTIONS:\n");
+       printf("\t-D\t\tenable libusb debug output\n");
+       printf("\t-h\t\tthis help message\n");
+}
+
+int main(int argc, char *argv[])
 {
        int ret;
+       int opt;
+       bool enable_libusb_debug = false;
        libusb_device_handle *dev;
        int current_configuration;
 
+       while ((opt = getopt(argc, argv, "Dh")) != -1) {
+               switch (opt) {
+               case 'D':
+                       enable_libusb_debug = true;
+                       break;
+               case 'h':
+                       usage(argv[0]);
+                       ret = 0;
+                       goto out;
+               default: /* '?' */
+                       usage(argv[0]);
+                       ret = -EINVAL;
+                       goto out;
+               }
+       }
+
        ret = libusb_init(NULL);
        if (ret < 0) {
                fprintf(stderr, "libusb_init failed: %s\n",
@@ -340,7 +396,8 @@ int main(void)
                goto out;
        }
 
-       libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_INFO);
+       libusb_set_debug(NULL, enable_libusb_debug ?
+                        LIBUSB_LOG_LEVEL_DEBUG : LIBUSB_LOG_LEVEL_INFO);
 
        dev = libusb_open_device_with_vid_pid(NULL,
                                              VISOMAT_DEVICE_VID,