taler-mdb

GNU Taler Extensions and Integrations
Log | Files | Refs | Submodules | README | LICENSE

commit b1fd9e82edbd8b1a04ea25388a6ce28f00742445
parent b18e9662d0bc300d143df8f14b1ed4e4fc609471
Author: Dominik Hofer <dominik.hofer@bfh.ch>
Date:   Fri, 29 Nov 2019 13:46:42 +0100

Added mdb communication module

Diffstat:
Asrc/mdb/mdb_uart.c | 344+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/mdb/mdb_uart.h | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 426 insertions(+), 0 deletions(-)

diff --git a/src/mdb/mdb_uart.c b/src/mdb/mdb_uart.c @@ -0,0 +1,344 @@ +/* + This file is part of TALER + Copyright (C) 2014 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 mdb_uart.c + * @brief Functions for communication via the mdb bus with the VMC + * @author Dominik Hofer <dominik.hofer@bfh.ch> + */ + +#include "mdb_uart.h" + +int +mdbUart_init(void) +{ + int uart0_filestream = -1; + struct termios options; + + //Open Uart + uart0_filestream = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY); + printf("File Descriptor: %d\n", uart0_filestream); + + if(uart0_filestream < 0){ + printf("Error - cannot open UART Device\n"); + } + else{ + fcntl(uart0_filestream, F_SETFL, 0); + if(tcgetattr(uart0_filestream, &options) != 0){ + printf("Error - Cannot get current UART configuration\n"); + return -1; + } + + memset(&options, 0, sizeof(options)); /* Structur loeschen, ggf. vorher sichern + und bei Programmende wieder restaurieren */ + /* Baudrate setzen */ + cfsetispeed(&options, B9600); + cfsetospeed(&options, B9600); + + /* setze Optionen */ + options.c_cflag &= ~PARENB; /* kein Paritybit */ + options.c_cflag &= ~CSTOPB; /* 1 Stoppbit */ + options.c_cflag &= ~CSIZE; /* 8 Datenbits */ + options.c_cflag |= CS8; + + /* 19200 bps, 8 Datenbits, CD-Signal ignorieren, Lesen erlauben */ + options.c_cflag |= (CLOCAL | CREAD); + + /* Kein Echo, keine Steuerzeichen, keine Interrupts */ + options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + options.c_iflag = IGNPAR; /* Parity-Fehler ignorieren */ + options.c_oflag &= ~OPOST; /* setze "raw" Input */ + options.c_cc[VMIN] = 14; /* warten auf min. 0 Zeichen */ + options.c_cc[VTIME] = 10; /* Timeout 1 Sekunde */ + tcflush(uart0_filestream,TCIOFLUSH); /* Puffer leeren */ + if(tcsetattr(uart0_filestream, TCSAFLUSH, &options) != 0){ + printf("Error - Cannot configurate UART device\n"); + return(-1); + } + } + + return uart0_filestream; +} + +int +uart_close(int filestream) +{ + + return close(filestream); +} + +int +mdb_init(int filestream) +{ + mdbCmd *readerConfigData; + + + readerConfigData = newMdbCmd("Reader Config", "0101", "19780A02FF0C"); + + while(1){ + sendMdbCmd(readerConfigData, filestream); + receivedMdbCmd = receiveMdbCmd(filestream); + if(receivedMdbCmd){ + if(strcmp("Reader Enable", receivedMdbCmd) == 0){ + break; + } + else{ + free(receivedMdbCmd); + } + } + } + + free(receivedMdbCmd); + + deleteMdbCmd(readerConfigData); + + return EXIT_SUCCESS; +} +int +uartSendBytes(int uart0_filestream, uint8_t* txBuffer, int nrOfBytes) +{ + int nrOfSentBytes = 0; + + nrOfSentBytes = write(uart0_filestream, txBuffer, nrOfBytes); + + printf("Number of Bytes sent: %d\n", nrOfSentBytes); + + return nrOfSentBytes; +} + +int +uartReceiveBytes(int uart0_filestream, uint8_t *rxBuffer, int nrOfBytes) +{ + int Bytes = 0; + + nrOfReceivedBytes = read(uart0_filestream, rxBuffer, nrOfBytes); + + // printf("Number of Bytes received: %d\n", nrOfReceivedBytes); + + return nrOfReceivedBytes; +} + +char * +receiveMdbCmd(int filestream) +{ + uint8_t rxBuffer[MAX_SIZE_RX_BUFFER]; + uint8_t cmd = 0xFF; + + size_t cmdStartIdx = 0; + int nrOfReceivedBytes = 0; + + nrOfReceivedBytes = read(filestream, rxBuffer, MAX_SIZE_RX_BUFFER); + + if(nrOfReceivedBytes < 4){ + return NULL; + } + + while(rxBuffer[cmdStartIdx] != 0x02){ + cmdStartIdx++; + if(cmdStartIdx == nrOfReceivedBytes){ + return NULL; + } + } + //printf("Received Bytes: %d\n", nrOfReceivedBytes); + char *retVal = malloc(30*sizeof(char) + sizeof(uint16_t)); + + if(!retVal){ + puts("Error: Cannot allocate memory"); + } + + cmd = ((convertChar2Hex(rxBuffer[cmdStartIdx+1]) << 4) | (convertChar2Hex(rxBuffer[cmdStartIdx+2]))); + printf("Received Command: %X\n", cmd); + + switch (cmd) { + case 0x13: + if(((convertChar2Hex(rxBuffer[cmdStartIdx+3]) << 4) | (convertChar2Hex(rxBuffer[cmdStartIdx+4]))) == 0x00){ + uint16_t productNmbr = 0x0000; + size_t idx; + size_t shiftIdx; + for (idx = cmdStartIdx + 9, shiftIdx = 12; idx <= cmdStartIdx + 12; idx++, shiftIdx -= 4) { + productNmbr |= ((uint16_t)((convertChar2Hex(rxBuffer[idx])) << shiftIdx)); + } + puts(""); + sprintf(retVal, "Vend Request for: %d", productNmbr); + } + else if (((convertChar2Hex(rxBuffer[cmdStartIdx+3]) << 4) | (convertChar2Hex(rxBuffer[cmdStartIdx+4]))) == 0x02) { + sprintf(retVal, "Vend Success"); + } + else if (((convertChar2Hex(rxBuffer[cmdStartIdx+3]) << 4) | (convertChar2Hex(rxBuffer[cmdStartIdx+4]))) == 0x03) { + sprintf(retVal, "Vend Failure"); + } + else if (((convertChar2Hex(rxBuffer[cmdStartIdx+3]) << 4) | (convertChar2Hex(rxBuffer[cmdStartIdx+4]))) == 0x04) { + sprintf(retVal, "Session Complete"); + } + else { + free(retVal); + retVal = NULL; + } + break; + case 0x11: + sprintf(retVal, "Config Data"); + break; + case 0x14: + if(((convertChar2Hex(rxBuffer[cmdStartIdx+3]) << 4) | (convertChar2Hex(rxBuffer[cmdStartIdx+4]))) == 0x01){ + sprintf(retVal, "Reader Enable"); + } + else { + free(retVal); + retVal = NULL; + } + break; + case 0x00: + sprintf(retVal, "Acknowledge"); + break; + case 0xD0: + sprintf(retVal, "Command out of Sequence"); + break; + case 0xAA: + sprintf(retVal, "Resend previous data"); + break; + default: + free(retVal); + retVal = NULL; + break; + } + return retVal; + +} +mdbCmd * +newMdbCmd(char *name, char *cmd, char *data) +{ + + mdbCmd* cmdNew = malloc(sizeof(mdbCmd)); + size_t idx = 0; + size_t strIdx = 0; + + if(name == NULL){ + cmdNew->name = malloc(sizeof(char) * strlen("No Cmd Name Set") + 1); + strncpy(cmdNew->name, "No Cmd Name Set", strlen("No Cmd Name Set") + 1); + } + else{ + cmdNew->name = malloc(sizeof(char) * strlen(name) + 1); + strncpy(cmdNew->name, name, strlen(name) + 1); + } + + if(cmd == NULL){ + cmdNew->cmdLength = 0; + cmdNew->cmd = NULL; + } + else{ + cmdNew->cmdLength = strlen(cmd) / 2; + cmdNew->cmd = malloc(sizeof(uint8_t) * cmdNew->cmdLength); + printf("New Command: "); + for(idx = 0, strIdx = 0; idx < cmdNew->cmdLength; idx++, strIdx += 2){ + cmdNew->cmd[idx] = (convertChar2Hex(cmd[strIdx]) << 4 | convertChar2Hex(cmd[strIdx + 1])); + printf("%X", cmdNew->cmd[idx]); + } + puts(""); + } + + if(data == NULL){ + cmdNew->dataLength = 0; + cmdNew->data = NULL; + } + else{ + cmdNew->dataLength = strlen(data) / 2; + cmdNew->data = malloc(sizeof(uint8_t) * cmdNew->dataLength); + + for(idx = 0, strIdx = 0; idx < cmdNew->dataLength; idx++, strIdx += 2){ + cmdNew->data[idx] = ((convertChar2Hex(data[strIdx])) << 4 | convertChar2Hex(data[strIdx + 1])); + } + } + + return cmdNew; +} + +void +deleteMdbCmd(mdbCmd *mdbCmdToDelete) +{ + free(mdbCmdToDelete->name); + free(mdbCmdToDelete->cmd); + free(mdbCmdToDelete->data); + free(mdbCmdToDelete); +} + +void +setMdbCmdData(mdbCmd *mdbCmdToSet, char *data) +{ + mdbCmdToSet->dataLength = strlen(data); + + if(mdbCmdToSet->dataLength == 0){ + free(mdbCmdToSet->data); + mdbCmdToSet->data = NULL; + } + else{ + mdbCmdToSet = realloc(mdbCmdToSet->data, sizeof(uint8_t) * mdbCmdToSet->dataLength); + size_t strIdx = 0; + for(size_t idx = 0; idx < mdbCmdToSet->dataLength; idx++){ + mdbCmdToSet->data[idx] = (convertChar2Hex(data[strIdx]) << 4) | (convertChar2Hex(data[strIdx + 1])); + strIdx = strIdx + 2; + } + } + +} + +int +sendMdbCmd(mdbCmd* cmdToSend, int filestream) +{ + + uint8_t* txBuffer; + uint32_t chkSum = 0x00000000; + int nrOfSentBytes = 0; + char *receivedMdbCmd = NULL; + + txBuffer = malloc(sizeof(uint8_t) * (cmdToSend->cmdLength + cmdToSend->dataLength + 1)); + + for(size_t idx = 0; idx < cmdToSend->cmdLength; idx++){ + txBuffer[idx] = cmdToSend->cmd[idx]; + //printf("%X", cmdToSend->cmd[idx]); + chkSum += cmdToSend->cmd[idx]; + } + + for(size_t idx = 0; idx < cmdToSend->dataLength; idx++){ + txBuffer[idx + cmdToSend->cmdLength] = cmdToSend->data[idx]; + chkSum += cmdToSend->data[idx]; + } + + txBuffer[cmdToSend->cmdLength + cmdToSend->dataLength] = (uint8_t)(chkSum & 0xFF); + + printf("Send command: %s\n", cmdToSend->name); + + + while(!receivedMdbCmd){ + nrOfSentBytes = uartSendBytes(filestream, txBuffer, cmdToSend->cmdLength + cmdToSend->dataLength + 1); + receivedMdbCmd = receiveMdbCmd(filestream); + + if(receivedMdbCmd){ + if(strcmp("Acknowledge", receivedMdbCmd) == 0){ + break; + } + else{ + free(receivedMdbCmd); + receivedMdbCmd = NULL; + } + } + } + free(receivedMdbCmd); + + return nrOfSentBytes; +} diff --git a/src/mdb/mdb_uart.h b/src/mdb/mdb_uart.h @@ -0,0 +1,82 @@ +/* + This file is part of TALER + Copyright (C) 2014 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 mdb_uart.h + * @brief Functions for communication via the mdb bus with the VMC + * @author Dominik Hofer <dominik.hofer@bfh.ch> + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <termios.h> + +/* Commands for communication via MDB/ICP */ +/* VMC commands */ +#define VMC_VEND 0x13 +#define VMC_VEND_REQUEST 0x00 +#define VMC_VEND_CANCEL 0x01 +#define VMC_VEND_SUCCESS 0x02 +#define VMC_VEND_FAILURE 0x03 +#define VMC_VEND_SESSION_COMPLETE 0x04 + +/* Reader commands */ +#define READER_CONFIG "01" +#define READER_DISPLAY_REQUEST "02" +#define READER_BEGIN_SESSION "03" +#define READER_SESSION_CANCEL_REQUEST "04" +#define READER_VEND_APPROVE "05" +#define READER_VEND_DENIED "06" +#define READER_END_SESSION "07" +#define READER_SESSION_CANCELLED "08" +#define READER_REVALUE_APPROVED "0D" +#define READER_REVALUE_DENIED "0E" + +/* Constants */ +#define MAX_SIZE_RX_BUFFER 256 + +/* Macro for char to hex conversion */ +#define convertChar2Hex(C) (((C) >= 'A' && (C) <= 'F') ? ((C) - 55) : ((C) - '0')) + +/* Datatype for mdb command */ +typedef struct mdbCmd_ +{ + char* name; + uint8_t* cmd; + size_t cmdLength; + uint8_t* data; + size_t dataLength; +}mdbCmd; + +/* Function Prototypes */ +int uart_init(void); +int uart_close(int filestream); +int mdb_init(int filestream); +int uartSendBytes(int uart0_filestream, uint8_t* txBuffer, int nrOfBytes); +int uartReceiveBytes(int uart0_filestream, uint8_t* rxBuffer, int nrOfBytes); +mdbCmd* newMdbCmd(char* name, char *cmd, char *data); +void deleteMdbCmd(mdbCmd *mdbCmdToDelete); +void setMdbCmdData(mdbCmd *mdbCmdToSet, char *data); +int sendMdbCmd(mdbCmd* cmdToSend, int filestream); +char *receiveMdbCmd(int filestream);