cash2ecash

cash2ecash: cash acceptor that issues digital cash (experimental)
Log | Files | Refs | README | LICENSE

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:
MCMakeLists.txt | 1+
Msrc/CMakeLists.txt | 2--
Msrc/taler-digitizer.c | 369+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Mtaler-digitizer.conf | 17+++++++++++------
Athinker/qr_code/taler-digitizer-qr-show.c | 437+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mthinker/taler_api/taler-digitizer.conf | 4++--
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