commit 4ffba69d998544b302751e576d5c89399c9a9960
parent 24170a13d19422dc453db11592192ad2c823b636
Author: Tellenbach Reto <tellr1@bfh.ch>
Date: Wed, 3 Jun 2026 16:32:21 +0200
[dbg] ConfigFile: draft show qrcode
Diffstat:
6 files changed, 786 insertions(+), 44 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -6,5 +6,6 @@ project(taler-digitizer LANGUAGES C )
set(CMAKE_C_STANDARD 17)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)
+add_executable(taler-digitizer src/taler-digitizer.c)
add_subdirectory(src)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
@@ -1,6 +1,4 @@
# Add files and libs
-add_executable(taler-digitizer taler-digitizer.c)
-
find_package(PkgConfig REQUIRED)
diff --git a/src/taler-digitizer.c b/src/taler-digitizer.c
@@ -33,7 +33,7 @@
* Time unit for PERSON_WITHDRAL_PERIOD config.
* Normaly in Days but, can be changed for testing
*/
-#define DIGITIZER_PERSON_WITHDRAWL_PERIOD_TIME_UNIT GNUNET_TIME_UNIT_DAYS
+#define DIGITIZER_PERSON_WITHDRAWAL_PERIOD_TIME_UNIT GNUNET_TIME_UNIT_DAYS
/**
* Global return value
@@ -56,19 +56,14 @@ static char *cfg_backend_base_url;
static char *cfg_currency;
/**
- * Minimum balance read from configuration file
- */
-static unsigned long long cfg_backend_min_balance;
-
-/**
* Per-person withdrawal limit read from configuration file
*/
-static unsigned long long cfg_user_withdrawllimit;
+static struct TALER_Amount cfg_user_withdrawallimit;
/**
* Per-person withdrawal period read from configuration file
*/
-static struct GNUNET_TIME_Relative cfg_user_withdrawl_period;
+static struct GNUNET_TIME_Relative cfg_user_withdrawal_period;
/**
* KYC functionality flag read from configuration file
@@ -76,6 +71,70 @@ static struct GNUNET_TIME_Relative cfg_user_withdrawl_period;
static enum GNUNET_GenericReturnValue cfg_kyc_functionality;
/**
+ * device path to display framebuffer.
+ * usualy in /dev/fbX.
+ */
+static char *cfg_framebuffer_device;
+
+/**
+ * device path to display backlight.
+ * usualy in /sys/class/backlight/<XX>/brightness
+ */
+static char *cfg_framebuffer_backlight;
+
+/**
+ * Coin Acceptor installed
+ */
+static enum GNUNET_GenericReturnValue cfg_ca_enable;
+
+/**
+ * device path to coin acceptor interface
+ */
+static char *cfg_ca_device;
+
+/**
+ * Pin to enable Accepting coins
+ */
+static unsigned long long cfg_ca_en_pin;
+
+/**
+ * Pin to recive inserted amount signal
+ */
+static unsigned long long cfg_ca_rx_pin;
+
+/**
+ * Biggest value of one coin insertion
+ */
+static struct TALER_Amount cfg_ca_max_denomination;
+
+/**
+ * Smallest value of one coin insertion
+ */
+static struct TALER_Amount cfg_ca_min_denomination;
+
+/**
+ * Bill Acceptor installed
+ */
+static enum GNUNET_GenericReturnValue cfg_ba_enable;
+
+/**
+ * device path to bill acceptor interface
+ */
+static char *cfg_ba_device;
+
+/**
+ * Biggest value of one bill insertion
+ */
+static struct TALER_Amount cfg_ba_max_denomination;
+
+/**
+ * Smallest value of one bill insertion
+ */
+static struct TALER_Amount cfg_ba_min_denomination;
+
+
+
+/**
* Handle to the context for interacting with the bank.
*/
static struct GNUNET_CURL_Context *curl_ctx;
@@ -91,13 +150,46 @@ static struct GNUNET_CURL_RescheduleContext *reschedule_ctx;
static struct TALER_BANK_GetConfigHandle *get_config_handle;
-static enum DIGITIZER_
+/**
+ * State-Machine state of Cash Digitizer
+ */
+typedef void (*DIGITIZER_State)(void);
-typedef void (*DIGITIZER_State)(enum)
+/**
+ * keeps the current state and is used to change states
+ */
+static DIGITIZER_State current_state;
+
+
+/**
+ * Joinn currency and V.F format value string to TALER amount".
+ *
+ * @param currency currency string
+ * @param value_fraction value string format "Value.Fraction"
+ * @param[out] amount amount to write the result to
+ * @return #GNUNET_OK if the string is a valid monetary amount specification,
+ * #GNUNET_SYSERR if it is invalid.
+ */
+enum GNUNET_GenericReturnValue
+TALER_join_strings_to_amount(const char *currency,
+ const char *value_fraction,
+ struct TALER_Amount *amount)
+{
+ enum GNUNET_GenericReturnValue ret;
+ char *str;
+ GNUNET_asprintf (&str,
+ "%s:%s",
+ currency,
+ value_fraction);
+ ret = TALER_string_to_amount(str,
+ amount);
+ GNUNET_free(str);
+ return ret;
+}
static void
-on_config_received (void *cls,
+on_get_config_done (void *cls,
const struct TALER_BANK_ConfigResponse *vr)
{
(void) cls;
@@ -185,47 +277,57 @@ run (void *cls,
global_ret = EXIT_FAILURE;
return;
}
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (cfg,
- "taler-digitizer",
- "BANK_MIN_BALANCE",
- &cfg_backend_min_balance))
+ if(GNUNET_OK != TALER_check_currency(cfg_currency))
{
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "taler-digitizer",
- "BANK_MIN_BALANCE");
+ GNUNET_log_config_invalid(GNUNET_ERROR_TYPE_ERROR,
+ "taler-digitizer",
+ "CURRENCY",
+ "malformed currency");
global_ret = EXIT_FAILURE;
- return;
+ return;
}
+ char *limit_value;
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (cfg,
- "taler-digitizer",
- "USER_WITHDRAWLLIMIT",
- &cfg_user_withdrawllimit))
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ "taler-digitizer",
+ "USER_WITHDRAWALLIMIT",
+ &limit_value))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "taler-digitizer",
- "USER_WITHDRAWLLIMIT");
+ "taler-digitizer",
+ "USER_WITHDRAWALLIMIT");
global_ret = EXIT_FAILURE;
return;
}
+ if (GNUNET_OK !=
+ TALER_join_strings_to_amount(cfg_currency,
+ limit_value,
+ &cfg_user_withdrawallimit))
+ {
+ GNUNET_log_config_invalid(GNUNET_ERROR_TYPE_ERROR,
+ "taler-digitizer",
+ "USER_WITHDRAWALLIMIT",
+ "malformed denomination");
+ global_ret = EXIT_FAILURE;
+ return;
+ }
- unsigned long long user_withdrawl_period_number;
+ unsigned long long user_withdrawal_period_number;
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_number (cfg,
"taler-digitizer",
- "USER_WITHDRAL_PERIOD",
- &user_withdrawl_period_number))
+ "USER_WITHDRAWAL_PERIOD",
+ &user_withdrawal_period_number))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"taler-digitizer",
- "USER_WITHDRAL_PERIOD");
+ "USER_WITHDRAWAL_PERIOD");
global_ret = EXIT_FAILURE;
return;
}
- cfg_user_withdrawl_period = GNUNET_TIME_relative_multiply (
- DIGITIZER_PERSON_WITHDRAWL_PERIOD_TIME_UNIT,
- user_withdrawl_period_number);
+ cfg_user_withdrawal_period = GNUNET_TIME_relative_multiply (
+ DIGITIZER_PERSON_WITHDRAWAL_PERIOD_TIME_UNIT,
+ user_withdrawal_period_number);
cfg_kyc_functionality = GNUNET_CONFIGURATION_get_value_yesno (cfg,
"taler-digitizer",
@@ -238,6 +340,205 @@ run (void *cls,
global_ret = EXIT_FAILURE;
return;
}
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (cfg,
+ "taler-digitizer",
+ "FRAMEBUFFER_DEVICE",
+ &cfg_framebuffer_device))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "taler-digitizer",
+ "FRAMEBUFFER_DEVICE");
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (cfg,
+ "taler-digitizer",
+ "FRAMEBUFFER_BACKLIGHT",
+ &cfg_framebuffer_backlight))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "taler-digitizer",
+ "FRAMEBUFFER_BACKLIGHT");
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ cfg_ca_enable = GNUNET_CONFIGURATION_get_value_yesno (cfg,
+ "coin-acceptor",
+ "ENABLE");
+ cfg_ba_enable = GNUNET_CONFIGURATION_get_value_yesno (cfg,
+ "bill-acceptor",
+ "ENABLE");
+ if(GNUNET_OK != cfg_ba_enable)
+ {
+ cfg_ba_enable = GNUNET_NO;
+ if(GNUNET_OK != cfg_ca_enable)
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "coin-acceptor or bill-acceptor",
+ "ENABLE");
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ }
+ else
+ {
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (cfg,
+ "bill-acceptor",
+ "DEVICE",
+ &cfg_ba_device))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "bill-acceptor",
+ "DEVICE");
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ char *denomination_value;
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ "bill-acceptor",
+ "MAX_DENOMINATION",
+ &denomination_value))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "bill-acceptor",
+ "MAX_DENOMINATION");
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ if (GNUNET_OK !=
+ TALER_join_strings_to_amount(cfg_currency,
+ denomination_value,
+ &cfg_ba_max_denomination))
+ {
+ GNUNET_log_config_invalid(GNUNET_ERROR_TYPE_ERROR,
+ "bill-acceptor",
+ "MAX_DENOMINATION",
+ "malformed denomination");
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ "bill-acceptor",
+ "MIN_DENOMINATION",
+ &denomination_value))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "bill-acceptor",
+ "MIN_DENOMINATION");
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ if (GNUNET_OK !=
+ TALER_join_strings_to_amount(cfg_currency,
+ denomination_value,
+ &cfg_ba_min_denomination))
+ {
+ GNUNET_log_config_invalid(GNUNET_ERROR_TYPE_ERROR,
+ "bill-acceptor",
+ "MIN_DENOMINATION",
+ "malformed denomination");
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ }
+ if(GNUNET_OK != cfg_ca_enable)
+ {
+ cfg_ca_enable = GNUNET_NO;
+ }
+ else
+ {
+ char *denomination_value;
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ "coin-acceptor",
+ "MAX_DENOMINATION",
+ &denomination_value))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "coin-acceptor",
+ "MAX_DENOMINATION");
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ if (GNUNET_OK !=
+ TALER_join_strings_to_amount(cfg_currency,
+ denomination_value,
+ &cfg_ca_max_denomination))
+ {
+ GNUNET_log_config_invalid(GNUNET_ERROR_TYPE_ERROR,
+ "coin-acceptor",
+ "MAX_DENOMINATION",
+ "malformed denomination");
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ "coin-acceptor",
+ "MIN_DENOMINATION",
+ &denomination_value))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "coin-acceptor",
+ "MIN_DENOMINATION");
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ if (GNUNET_OK !=
+ TALER_join_strings_to_amount(cfg_currency,
+ denomination_value,
+ &cfg_ca_min_denomination))
+ {
+ GNUNET_log_config_invalid(GNUNET_ERROR_TYPE_ERROR,
+ "coin-acceptor",
+ "MIN_DENOMINATION",
+ "malformed denomination");
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (cfg,
+ "coin-acceptor",
+ "DEVICE",
+ &cfg_ca_device))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "coin-acceptor",
+ "DEVICE");
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_number (cfg,
+ "coin-acceptor",
+ "ENABLE_PIN",
+ &cfg_ca_en_pin))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "coin-acceptor",
+ "ENABLE_PIN");
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_number (cfg,
+ "coin-acceptor",
+ "UART_RX_PIN",
+ &cfg_ca_rx_pin))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "coin-acceptor",
+ "UART_RX_PIN");
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ }
+
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Config URL: %s\n",
@@ -252,7 +553,7 @@ run (void *cls,
get_config_handle = TALER_BANK_get_config (curl_ctx,
cfg_backend_base_url,
- &on_config_received,
+ &on_get_config_done,
NULL);
diff --git a/taler-digitizer.conf b/taler-digitizer.conf
@@ -3,15 +3,14 @@ BACKEND_BASE_URL = https://bank.demo.taler.net/
CURRENCY = KUDOS
BANK_ACCOUNT = bank_acc_tellr
-BANK_TOKEN = 4NA4S6GKGCRBB65M99QKPKD29K2HTRBDZRJYTTVZ0K6QEYBQPHH0
+BANK_TOKEN = Bearer secret-token:HHPNC9XSV3X69RDENP4AHGWF5G681KVRVNJ7E5R6F3QB8J2Y8Y1G
# Withdrawl limitation per person, for a limited time period.
# This can only be enforced with KYC functionality
-USER_WITHDRAWLLIMIT = 200
-USER_WITHDRAL_PERIOD = 10
+USER_WITHDRAWALLIMIT = 200
+USER_WITHDRAWAL_PERIOD = 10
-#BACKEND_AUTHORIZATION = Bearer secret-token:sandbox
KYC_FUNCTIONALITY = NO
# Name of the framebuffer to use for the QR code.
@@ -20,15 +19,21 @@ FRAMEBUFFER_DEVICE = /dev/fb1
# Name of the backlight file for the framebuffer
FRAMEBUFFER_BACKLIGHT = /sys/class/backlight/soc:backlight/brightness
+
+# At least a coin or a bill acceptor need to be enabled
+# requiered config for each:
+# ENABLE, MAX_DENOMINATION, MIN_DENOMINATION
[coin-acceptor]
ENABLE = YES
-GPIO_CHIP = /dev/gpiochip0
-GPIO_PIN = 16
+DEVICE = /dev/gpiochip0
+ENABLE_PIN = 16
+UART_RX_PIN = 15
MAX_DENOMINATION = 5
MIN_DENOMINATION = 0.1
[bill-acceptor]
ENABLE = NO
+DEVICE = /dev/XXX
MAX_DENOMINATION = 100
MIN_DENOMINATION = 10
diff --git a/thinker/qr_code/taler-digitizer-qr-show.c b/thinker/qr_code/taler-digitizer-qr-show.c
@@ -0,0 +1,437 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2019 GNUnet e.V.
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER 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 General Public License for more
+details.
+
+ You should have received a copy of the GNU General Public License
+along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+* @file taler-mdb-qr-show.c
+* @brief shows a QR code on the display for a defined amount of time
+* @author Boss Marco
+* @author Christian Grothoff
+*/
+
+#include <errno.h>
+#include <qrencode.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <linux/fb.h>
+#include "taler_digitizer_util.h"
+
+
+/**
+ * Disable i18n support.
+ */
+#define _(s) (s)
+
+/**
+ * Handle for the Framebuffer device
+ */
+struct Display
+{
+ /**
+ * File descriptor for the screen
+ */
+ int devicefd;
+
+ /**
+ * File descriptor to set backlight information
+ */
+ int backlightfd;
+
+ /**
+ * The display memory to set the pixel information
+ */
+ uint16_t *memory;
+
+ /**
+ * Original screen information
+ */
+ struct fb_var_screeninfo orig_vinfo;
+
+ /**
+ * Variable screen information (color depth ...)
+ */
+ struct fb_var_screeninfo var_info;
+
+ /**
+ * Fixed screen informtaion
+ */
+ struct fb_fix_screeninfo fix_info;
+};
+
+
+/**
+ * Next program to launch.
+ */
+static char *const *arg_next;
+
+static struct GNUNET_TIME_Relative delay;
+
+/**
+ * Reference to the delay task
+ */
+static struct GNUNET_SCHEDULER_Task *delay_task;
+
+/**
+ * Name of the framebuffer device (i.e. /dev/fb1).
+ */
+static char *framebuffer_device_filename;
+
+/**
+ * Name of the backlight file of @e framebuffer_device_filename (i.e. /sys/class/backlight/soc:backlight/brightness).
+ */
+static char *framebuffer_backlight_filename;
+
+/**
+ * Global option '-i' to invert backlight on/off values
+ */
+static int backlight_invert;
+
+/**
+ * Standard backlight on value
+ */
+static char backlight_on = '1';
+
+/**
+ * Standard backlight off value
+ */
+static char backlight_off = '0';
+
+/**
+ * Handle for the framebuffer device
+ */
+static struct Display qrDisplay;
+
+
+/**
+ * @brief Create the QR code to pay and display it on screen
+ *
+ * @param uri what text to show in the QR code
+ */
+static void
+show_qrcode (const char *uri)
+{
+ QRinput *qri;
+ QRcode *qrc;
+ unsigned int size;
+ size_t xOff;
+ size_t yOff;
+ unsigned int nwidth;
+
+ if (0 > qrDisplay.devicefd)
+ return; /* no display, no dice */
+ qri = QRinput_new2 (0, QR_ECLEVEL_L);
+ if (NULL == qri)
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "QRinput_new2");
+ return;
+ }
+ /* first try encoding as uppercase-only alpha-numerical
+ QR code (much smaller encoding); if that fails, also
+ try using binary encoding (in case nick contains
+ special characters). */
+ if ( (0 !=
+ QRinput_append (qri,
+ QR_MODE_AN,
+ strlen (uri),
+ (unsigned char *) uri)) &&
+ (0 !=
+ QRinput_append (qri,
+ QR_MODE_8,
+ strlen (uri),
+ (unsigned char *) uri)))
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "QRinput_append");
+ return;
+ }
+ qrc = QRcode_encodeInput (qri);
+ if (NULL == qrc)
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "QRcode_encodeInput");
+ QRinput_free (qri);
+ return;
+ }
+
+ /* +8 for 4-pixels border */
+ size = GNUNET_MIN (qrDisplay.var_info.xres,
+ qrDisplay.var_info.yres);
+ nwidth = qrc->width + 8; /* 4 pixel border */
+ xOff = 4 * size / nwidth;
+ yOff = 4 * size / nwidth;
+ if (qrDisplay.var_info.xres < qrDisplay.var_info.yres)
+ yOff += (qrDisplay.var_info.yres - qrDisplay.var_info.xres) / 2;
+ else
+ xOff += (qrDisplay.var_info.xres - qrDisplay.var_info.yres) / 2;
+ for (unsigned int x = 0; x < qrDisplay.var_info.xres - 2 * xOff; x++)
+ for (unsigned int y = 0; y < qrDisplay.var_info.yres - 2 * yOff; y++)
+ {
+ unsigned int xoff = x * nwidth / size;
+ unsigned int yoff = y * nwidth / size;
+ unsigned int off = xoff + yoff * qrc->width;
+ if ( (xoff >= (unsigned) qrc->width) ||
+ (yoff >= (unsigned) qrc->width) )
+ continue;
+ qrDisplay.memory[(y + yOff) * qrDisplay.var_info.xres + (x + xOff)] =
+ (0 == (qrc->data[off] & 1)) ? 0xFFFF : 0x0000;
+ }
+
+ QRcode_free (qrc);
+ QRinput_free (qri);
+
+ if (0 < qrDisplay.backlightfd)
+ (void) ! write (qrDisplay.backlightfd,
+ &backlight_on,
+ 1);
+}
+
+
+static void
+stop_task (void *cls)
+{
+ (void) cls;
+ delay_task = NULL;
+ GNUNET_SCHEDULER_shutdown ();
+}
+
+
+static void
+shutdown_task (void *cls)
+{
+ (void) cls;
+ if (NULL != delay_task)
+ {
+ GNUNET_SCHEDULER_cancel (delay_task);
+ delay_task = NULL;
+ }
+ if (NULL != qrDisplay.memory)
+ memset (qrDisplay.memory,
+ 0xFF,
+ qrDisplay.var_info.xres
+ * qrDisplay.var_info.yres
+ * sizeof (uint16_t));
+ if (0 < qrDisplay.backlightfd)
+ (void) ! write (qrDisplay.backlightfd,
+ &backlight_off,
+ 1);
+ if (NULL != qrDisplay.memory)
+ {
+ /* free the display data */
+ munmap (qrDisplay.memory,
+ qrDisplay.fix_info.smem_len);
+ qrDisplay.memory = NULL;
+ /* reset original state */
+ if (0 > ioctl (qrDisplay.devicefd,
+ FBIOPUT_VSCREENINFO,
+ &qrDisplay.orig_vinfo))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "failed to reset original display state\n");
+ }
+ /* close device */
+ GNUNET_break (0 == close (qrDisplay.devicefd));
+ qrDisplay.devicefd = -1;
+ if (0 < qrDisplay.backlightfd)
+ GNUNET_break (0 == close (qrDisplay.backlightfd));
+ qrDisplay.backlightfd = -1;
+ }
+}
+
+
+/**
+ * @brief Start the application
+ *
+ * @param cls closure
+ * @param args arguments left
+ * @param cfgfile config file name
+ * @param cfg handle for the configuration file
+ */
+static void
+run (void *cls,
+ char *const *args,
+ const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ (void) cls;
+ (void) cfgfile;
+
+ if (NULL == args[0])
+ return;
+ arg_next = args + 1;
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (
+ cfg,
+ "taler-digitizer",
+ "FRAMEBUFFER_DEVICE",
+ &framebuffer_device_filename))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "taler-digitizer",
+ "FRAMEBUFFER_DEVICE");
+ framebuffer_device_filename = GNUNET_strdup ("/dev/fb1");
+ }
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (
+ cfg,
+ "taler-digitizer",
+ "FRAMEBUFFER_BACKLIGHT",
+ &framebuffer_backlight_filename))
+ {
+ GNUNET_log_config_missing (
+ GNUNET_ERROR_TYPE_ERROR,
+ "taler-digitizer",
+ "FRAMEBUFFER_BACKLIGHT");
+ framebuffer_backlight_filename = GNUNET_strdup (
+ "/sys/class/backlight/*/brightness");
+ }
+ /* open the framebuffer device */
+ qrDisplay.devicefd = open (framebuffer_device_filename,
+ O_RDWR);
+ if (0 < qrDisplay.devicefd)
+ {
+ /* read information about the screen */
+ ioctl (qrDisplay.devicefd,
+ FBIOGET_VSCREENINFO,
+ &qrDisplay.var_info);
+
+ /* store current screeninfo for reset */
+ qrDisplay.orig_vinfo = qrDisplay.var_info;
+
+ if (16 != qrDisplay.var_info.bits_per_pixel)
+ {
+ /* Change variable info to 16 bit per pixel */
+ qrDisplay.var_info.bits_per_pixel = 16;
+ if (0 > ioctl (qrDisplay.devicefd,
+ FBIOPUT_VSCREENINFO,
+ &qrDisplay.var_info))
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "ioctl(FBIOPUT_VSCREENINFO)");
+ return;
+ }
+ }
+
+ /* Get fixed screen information */
+ if (0 > ioctl (qrDisplay.devicefd,
+ FBIOGET_FSCREENINFO,
+ &qrDisplay.fix_info))
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "ioctl(FBIOGET_FSCREENINFO)");
+ return;
+ }
+
+ /* get pointer onto frame buffer */
+ qrDisplay.memory
+ = mmap (NULL,
+ qrDisplay.fix_info.smem_len,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ qrDisplay.devicefd,
+ 0);
+
+ /* open backlight file to turn display backlight on and off */
+ if (0 > qrDisplay.devicefd)
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "mmap");
+ return;
+ }
+
+ memset (qrDisplay.memory,
+ 0xFF,
+ qrDisplay.var_info.xres * qrDisplay.var_info.yres
+ * sizeof (uint16_t));
+
+ qrDisplay.backlightfd = open (
+ framebuffer_backlight_filename, O_WRONLY);
+ if (0 > qrDisplay.backlightfd)
+ {
+ GNUNET_log_strerror_file (
+ GNUNET_ERROR_TYPE_WARNING,
+ "open",
+ framebuffer_backlight_filename);
+ }
+ else
+ {
+ if (backlight_invert)
+ {
+ backlight_on = '0';
+ backlight_off = '1';
+ }
+ (void) ! write (qrDisplay.backlightfd,
+ &backlight_off,
+ 1);
+ }
+ }
+ else
+ {
+ GNUNET_log_strerror_file (
+ GNUNET_ERROR_TYPE_WARNING,
+ "open",
+ framebuffer_device_filename);
+ }
+ GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+ NULL);
+ show_qrcode (args[0]);
+ delay_task = GNUNET_SCHEDULER_add_delayed (delay,
+ &stop_task,
+ NULL);
+}
+
+
+int
+main (int argc,
+ char*const*argv)
+{
+ int ret;
+ /* the available command line options */
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_option_relative_time ('d',
+ "delay",
+ "DELAY",
+ "how long should we display the QR code before exiting",
+ &delay),
+ GNUNET_GETOPT_option_flag ('i',
+ "backlight-invert",
+ "invert the backlight on/off values (standard on = 1)",
+ &backlight_invert),
+ GNUNET_GETOPT_OPTION_END
+ };
+
+ ret = GNUNET_PROGRAM_run (TALER_DIGITIZER_project_data (),
+ argc,
+ argv,
+ "taler-digitizer-qr-show",
+ "This is an application to show a QR code for a defined period of time before starting another program.\n",
+ options,
+ &run,
+ NULL);
+ if (GNUNET_OK != ret)
+ return 1;
+ if ( (NULL == arg_next) ||
+ (NULL == arg_next[0]) )
+ return 0;
+ execvp (arg_next[0],
+ arg_next);
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
+ "execvp",
+ arg_next[0]);
+ return 1;
+}
diff --git a/thinker/taler_api/taler-digitizer.conf b/thinker/taler_api/taler-digitizer.conf
@@ -9,8 +9,8 @@ BANK_MIN_BALANCE = 1000
# Withdrawl limitation per person, for a limited time period.
# This can only be enforced with KYC functionality
-PERSON_WITHDRAWLLIMIT = 200
-PERSON_WITHDRAL_PERIOD = 10
+USER_WITHDRAWALLIMIT = 200
+USER_WITHDRAWAL_PERIOD = 10
#BACKEND_AUTHORIZATION = Bearer secret-token:sandbox