From aa66904d79bb3ce13e32689b45dbd416d4a73fc7 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 22 Jul 2022 16:22:59 +0200 Subject: use tty directly for coin acceptor, build event loop --- src/Makefile.am | 2 +- src/taler-coin-acceptor.c | 333 ++++++++++++++++++++++++---------------------- src/taler-mdb.c | 2 +- 3 files changed, 176 insertions(+), 161 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 86ddd3b..cf53389 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,7 +15,7 @@ endif taler_coin_acceptor_SOURCES = \ taler-coin-acceptor.c taler_coin_acceptor_LDADD = \ - -lusb-1.0 + -lgnunetutil taler_mdb_SOURCES = \ taler-mdb.c diff --git a/src/taler-coin-acceptor.c b/src/taler-coin-acceptor.c index fde4a8a..3f0f1ef 100644 --- a/src/taler-coin-acceptor.c +++ b/src/taler-coin-acceptor.c @@ -27,196 +27,211 @@ along with #include #include #include -#include -#include +#include +#include +#include +#include +#include +#include -// FIXME: make this configurable later... -/* future technology devices international */ -#define VENDOR_ID 0x0403 -/* FT232 Serial UART IC */ -#define PRODUCT_ID 0x6001 - -#define USB_CTL_REQ_SET_LINE_CODING 0x20 - -#define LEO_ONE_STOP_BIT 0x00 -#define LEO_ONEHALF_STOP_BIT 0x01 -#define LEO_TWO_STOP_BIT 0x02 - -#define LEO_PARITY_NONE 0x00 -#define LEO_PARITY_ODD 0x01 -#define LEO_PARITY_EVEN 0x02 -#define LEO_PARITY_MARK 0x03 -#define LEO_PARITY_SPACE 0x04 +/** + * File descriptor of the coin acceptor. + */ +static int fd = -1; -#define ACM_CTRL_DTR 0x01 -#define ACM_CTRL_RTS 0x02 +/** + * Wrapper around #fd. + */ +static struct GNUNET_NETWORK_Handle *rf; /** - * Handle to USB device. + * Original terminal discipline. */ -static struct libusb_device_handle *device_handle; +static struct termios uart_opts_backup; -/* The Endpoint address are hard coded. You should use lsusb -v to find - * the values corresponding to your device. +/** + * Our main task. */ -static int ep_in_addr = 0x83; -static int ep_out_addr = 0x02; +static struct GNUNET_SCHEDULER_Task *tt; +/** + * Return value from #main(). + */ +static int global_ret; -static int -read_char (void) +/** + * Function run on shutdown. + * + * @param cls NULL + */ +static void +do_shutdown (void *cls) { - int actual_length; - unsigned char data; - int rc; - - rc = libusb_bulk_transfer (device_handle, - ep_in_addr, - &data, - sizeof (data), - &actual_length, - 1000 /* timeout? */); - if (rc == LIBUSB_ERROR_TIMEOUT) + (void) cls; + + if (-1 != fd) { - fprintf (stderr, - "TIMEOUT\n"); - return EOF; + if (0 != tcsetattr (fd, + TCSAFLUSH, + &uart_opts_backup)) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "tcsetattr"); + } + GNUNET_break (0 == close (fd)); + fd = -1; } - if (rc < 0) + if (NULL != tt) { - fprintf (stderr, - "Error %s while waiting for char\n", - libusb_error_name (rc)); - return EOF; + GNUNET_SCHEDULER_cancel (tt); + tt = NULL; } - return data; + GNUNET_free (rf); } -int -main (int argc, - char **argv) +/** + * Function run on coin insert. + * + * @param cls NULL + */ +static void +do_read (void *cls) { - int rc; + char c = '\0'; + int ret; - rc = libusb_init (NULL); - if (rc < 0) + (void) cls; + ret = read (fd, &c, 1); + if ( (0 != ret) && + (-1 != (int) c) ) { - fprintf (stderr, - "Error initializing usb: %s\n", - libusb_error_name (rc)); - return 1; + fprintf (stdout, + "%d\n", + (int) c); } + tt = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + rf, + &do_read, + NULL); +} - libusb_set_debug (NULL, - 3); - device_handle = libusb_open_device_with_vid_pid (NULL, - VENDOR_ID, - PRODUCT_ID); - if (NULL == device_handle) - { - fprintf (stderr, - "Error finding USB device\n"); - libusb_exit (NULL); - return 1; - } - /* Maybe there is someone else attached, detach other drivers from - all the USB interfaces. NOTE: not sure if there are *2*! */ - for (int if_num = 0; if_num < 2; if_num++) +/** + * Function run on startup. + * + * @param cls NULL + * @param args arguments left + * @param cfgfile config file name + * @param cfg handle for the configuration file + */ +static void +run (void *cls, + char *const *argv, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + struct termios uart_opts_raw; + + (void) cls; + /* reset current uart discipline */ + memset (&uart_opts_raw, + 0, + sizeof(uart_opts_raw)); + + /* set baudrate */ + cfsetispeed (&uart_opts_raw, B4800); + cfsetospeed (&uart_opts_raw, B4800); + + /* set options */ + uart_opts_raw.c_cflag &= ~PARENB; + uart_opts_raw.c_cflag &= ~CSTOPB; + uart_opts_raw.c_cflag &= ~CSIZE; + uart_opts_raw.c_cflag |= CS8; + + /* 19200 bps, 8 databits, ignore cd-signal, allow reading */ + uart_opts_raw.c_cflag |= (CLOCAL | CREAD); + uart_opts_raw.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + uart_opts_raw.c_iflag = IGNPAR; + uart_opts_raw.c_oflag &= ~OPOST; + uart_opts_raw.c_cc[VMIN] = 0; + uart_opts_raw.c_cc[VTIME] = 50; + + if (NULL == argv[0]) { - if (libusb_kernel_driver_active (device_handle, - if_num)) - { - libusb_detach_kernel_driver (device_handle, - if_num); - } - rc = libusb_claim_interface (device_handle, - if_num); - if (rc < 0) - { - fprintf (stderr, - "Error claiming interface: %s\n", - libusb_error_name (rc)); - libusb_close (device_handle); - libusb_exit (NULL); - return 1; - } + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "call with TTY filename argument\n"); + global_ret = 1; + return; } -#if 1 - rc = libusb_control_transfer (device_handle, - 0x21, - 0x22, - ACM_CTRL_DTR | ACM_CTRL_RTS, - 0, - NULL, - 0, - 0); - if (rc < 0) + fd = open (argv[0], + O_RDONLY); + if (-1 == fd) { - fprintf (stderr, - "Error during control transfer: %s\n", - libusb_error_name (rc)); - libusb_close (device_handle); - libusb_exit (NULL); - return 1; + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, + "open", + argv[0]); + global_ret = 1; + return; } -#endif - - /* - set line encoding: here 9600 8N1 - * 9600 = 0x2580 ~> 0x80, 0x25 in little endian - */ + if (0 != tcgetattr (fd, + &uart_opts_backup)) { - struct LineEncodingOptions - { - /** - * In *little* endian. - */ - uint32_t baud_rate; - uint8_t b_char_format; - uint8_t b_parity_type; - uint8_t b_data_bits; - } leo = { - .baud_rate = __builtin_bswap32 (htonl (4800)), - .b_char_format = LEO_ONE_STOP_BIT, - .b_parity_type = LEO_PARITY_ODD, - .b_data_bits = 0x08 - }; - - rc = libusb_control_transfer (device_handle, - 0x21, - USB_CTL_REQ_SET_LINE_CODING, - 0, - 0, - (unsigned char *) &leo, - sizeof(leo), - 0); - if (rc < 0) - { - fprintf (stderr, - "Error during control transfer: %s\n", - libusb_error_name (rc)); - libusb_close (device_handle); - libusb_exit (NULL); - return 1; - } + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "tcgetattr"); + GNUNET_break (0 == close (fd)); + fd = -1; + global_ret = 1; + return; } - - /* FIXME: proper event loop... */ - while (1) + GNUNET_SCHEDULER_add_shutdown (&do_shutdown, + NULL); + tcflush (fd, + TCIOFLUSH); + if (0 != tcsetattr (fd, + TCSAFLUSH, + &uart_opts_raw)) { - int in = read_char (); - - if (-1 != in) - fprintf (stdout, - "Received: %d\n", - in); + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "tcsetattr"); + GNUNET_SCHEDULER_shutdown (); + global_ret = 1; + return; } + rf = GNUNET_NETWORK_socket_box_native (fd); + tt = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + rf, + &do_read, + NULL); +} - libusb_release_interface (device_handle, - 0); - libusb_close (device_handle); - libusb_exit (NULL); - return 0; + +int +main (int argc, + char *const*argv) +{ + /* the available command line options */ + struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + enum GNUNET_GenericReturnValue ret; + + if (GNUNET_OK != + GNUNET_STRINGS_get_utf8_args (argc, argv, + &argc, &argv)) + return 4; + ret = GNUNET_PROGRAM_run (argc, + argv, + "taler-mdb", + "This is an application for snack machines to pay with GNU Taler via NFC.\n", + options, + &run, + NULL); + GNUNET_free_nz ((void *) argv); + if (GNUNET_NO == ret) + return 0; + if (GNUNET_OK != ret) + return 1; + return global_ret; } diff --git a/src/taler-mdb.c b/src/taler-mdb.c index f0b1529..0e2d6d8 100644 --- a/src/taler-mdb.c +++ b/src/taler-mdb.c @@ -3065,7 +3065,7 @@ mdb_init (void) * @param cls closure * @param args arguments left * @param cfgfile config file name - * @param cfg handle for the configuration file + * @param cfg handle for the configuration */ static void run (void *cls, -- cgit v1.2.3