From 4e783ee6fd960bd34a7bd81e43d4f6f20f6cee92 Mon Sep 17 00:00:00 2001 From: Gerhard Hoffmann Date: Thu, 13 Jun 2024 17:23:47 +0200 Subject: [PATCH] just save --- main/MessageHelper.cpp | 353 ++++++ main/MessageHelper.h | 54 + main/aes128.cpp | 625 +++++++++++ main/aes128.h | 8 + main/cc_iuc_asynchpos.cpp | 2131 +++++++++++++++++++++++++++++++++++++ main/cc_iuc_asynchpos.h | 113 ++ main/main.cpp | 629 ++++++++++- main/main.pro | 12 +- main/terminal_utils.cpp | 124 +++ main/terminal_utils.h | 30 + 10 files changed, 4060 insertions(+), 19 deletions(-) create mode 100644 main/MessageHelper.cpp create mode 100644 main/MessageHelper.h create mode 100755 main/aes128.cpp create mode 100755 main/aes128.h create mode 100755 main/cc_iuc_asynchpos.cpp create mode 100755 main/cc_iuc_asynchpos.h create mode 100644 main/terminal_utils.cpp create mode 100644 main/terminal_utils.h diff --git a/main/MessageHelper.cpp b/main/MessageHelper.cpp new file mode 100644 index 0000000..03c6916 --- /dev/null +++ b/main/MessageHelper.cpp @@ -0,0 +1,353 @@ +#include "MessageHelper.h" +#include "terminal_utils.h" + +#include +#include +#include + +#define IUC_ASYNCHPOS_COINCOIDE_H 0x09 +#define IUC_ASYNCHPOS_COINCOIDE_L 0x78 +#define IUC_ASYNCHPOS_MAX_ARRAY_SIZE 1024 +#define IUC_ASYNCHPOS_MAX_TX_PACKET_SIZE 300 +#define IUC_ASYNCHPOS_MAX_RX_PACKET_SIZE 10000 // 17000 +#define IUC_ASYNCHPOS_MIN_PACKET_SIZE 16 +#define IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE 32 +#define IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE 16 +#define IUC_ASYNCHPOS_POLYNOME 0xedb88320 // 0x04C11DB7 +#define IUC_ASYNCHPOS_POLYNOME_INITIAL 0 // 0xFFFFFFFF +#define IUC_ASYNCHPOS_PRINTTIMOUT 1000 + +#define PACKET_ID_SIZE 8 +#define MAX_POSID_LENGTH 255 + +#define STX ((char)0x01) +#define ETX1 ((char)0x02) +#define ETX2 ((char)0x03) +#define EOT ((char)0x04) +#define ENQ ((char)0x05) +#define ACK1 ((char)0x06) +#define ACK2 ((char)0x07) +#define DLE ((char)0x10) +#define NAK ((char)0x15) + + +#define DBG_HEADER "(" << __func__ << ":" << __LINE__ << ")" + +static bool DEBUG_MESSAGE_HELPER=true; + +struct MessageHeader { + uint8_t packetType; + uint8_t packetID[PACKET_ID_SIZE]; + uint8_t POSIDLength; + uint8_t POSID[MAX_POSID_LENGTH]; +}; + +MessageHelper::MessageHelper(QString const &posID, QString const &apak) + : m_posID(posID.toUtf8().constData()) + , m_apak(apak) + , m_posIDLength(m_posID.size()) + , m_messageHeaderPrefix(1 + PACKET_ID_SIZE + 1, 0x00) + , m_rawPacket(IUC_ASYNCHPOS_MAX_TX_PACKET_SIZE, 0x00) { + m_messageHeaderPrefix[9] = (uint8_t)m_posID.size(); + + if (DEBUG_MESSAGE_HELPER) { + qCritical() << DBG_HEADER << m_posID.toHex(':'); + qCritical() << DBG_HEADER << m_messageHeaderPrefix.toHex(':'); + } +} + +MessageHelper::MessageHelper(QByteArray const &posID, QString const &apak) + : m_posID(posID) + , m_apak(apak) + , m_posIDLength(m_posID.size()) + , m_messageHeaderPrefix(1 + PACKET_ID_SIZE + 1, 0x00) + , m_rawPacket(IUC_ASYNCHPOS_MAX_TX_PACKET_SIZE, 0x00) { + m_messageHeaderPrefix[9] = (uint8_t)m_posID.size(); + + if (DEBUG_MESSAGE_HELPER) { + qCritical() << DBG_HEADER << m_posID.toHex(':'); + qCritical() << DBG_HEADER << m_messageHeaderPrefix.toHex(':'); + } +} + +MessageHelper::~MessageHelper() { + +} + +void MessageHelper::createRawPacket(PacketType packetType, + QByteArray const &encryptedPacketID, + QByteArray const &message) { + if (createMessageHeaderPrefix(packetType, encryptedPacketID)) { + QByteArray ba(m_messageHeaderPrefix); + ba = ba.append(m_posID); + ba = ba.append(message); + + uint16_t const size = ba.size(); + + ba.push_front((char)size); + ba.push_front((char)(size >> 8)); + + m_rawPacket = ba; + } +} + +bool MessageHelper::setMessageHeaderPacketType(PacketType packetType) { + + switch (packetType) { + case PacketType::POS_ECR: + case PacketType::MESSAGE_RECEIVED_POSITIVE_ACK: + case PacketType::MESSAGE_RECEIVED_NEGATIVE_ACK: + m_messageHeaderPrefix[0] = (uint8_t)packetType; + break; + default: + return false; + } + return true; +} + +bool MessageHelper::createMessageHeaderPrefix(PacketType packetType, QByteArray const &encryptedPacketID) { + if (encryptedPacketID.size() == PACKET_ID_SIZE) { + if (setMessageHeaderPacketType(packetType)) { + for (int i = 1; i <= 8; ++i) { + m_messageHeaderPrefix[i] = (uint8_t)encryptedPacketID[i-1]; + } + if (DEBUG_MESSAGE_HELPER) { + qCritical() << DBG_HEADER << m_messageHeaderPrefix.toHex(':'); + } + return true; + } + } + return false; +} + +void MessageHelper::createLoginMessage() { + m_loginMessage.clear(); + + m_loginMessage.push_back((char)0x85); // 5 in 0x85 is the size + m_loginMessage = m_loginMessage.append(QByteArray("Login")); + + m_loginMessage.push_back((char)0x04); + m_loginMessage = m_loginMessage.append(QByteArray("Time")); + m_loginMessage.push_back((char)0x00); + m_loginMessage.push_back((char)0x13); + + QDateTime current = QDateTime::currentDateTime(); + // TODO: wieder entfernen + current.setTime(QTime(12, 0, 0)); + + QByteArray time(current.toString(Qt::ISODate).toStdString().c_str()); + time[10] = ' '; + m_loginMessage = m_loginMessage.append(time); + + m_loginMessage.push_back((char)0x05); + m_loginMessage = m_loginMessage.append(QByteArray("Flags")); + m_loginMessage.push_back((char)0x00); + m_loginMessage.push_back((char)0x06); + m_loginMessage = m_loginMessage.append(QByteArray("AP3|LR")); + + m_loginMessage.push_back((char)0x00); + + if (DEBUG_MESSAGE_HELPER) { + qCritical() << DBG_HEADER << m_loginMessage.toHex(':'); + } +} + +uint32_t iuc_asynchpos_sub_updateCRC_2(uint32_t crc, char* pData, size_t len) { + // berechne CRC32 nach Polynom x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 + + QByteArray a(pData, len); + qCritical() << "updateCRC" << a.toHex(' '); + qCritical() << "updateCRC" << len << hex << crc; + + int i = 0; + int j = 0; + unsigned char ucCarry = 0x00; + + crc = ~crc; + while (len > 0) { + crc ^= (uint32_t) pData[i]; + ++i; + + for (j = 0; j < 8; ++j) { + ucCarry = crc & 1; + crc >>= 1; + + if (ucCarry) { + crc ^= IUC_ASYNCHPOS_POLYNOME; + } + } + --len; + } + + return ~crc; + +} + + +QByteArrayList const &MessageHelper::createLoginMessageChunksToSend(char etx) { + QByteArray encryptedPacketID(QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08")); + + m_messageChunkList.clear(); + createLoginMessage(); + createRawPacket(PacketType::POS_ECR, encryptedPacketID, m_loginMessage); + + if (DEBUG_MESSAGE_HELPER) { + qCritical() << DBG_HEADER << m_rawPacket.toHex(':'); + } + + QByteArray const &ba = m_rawPacket.mid(11); + if (DEBUG_MESSAGE_HELPER) { + qCritical() << DBG_HEADER << ba.toHex(':'); + } + + //uint32_t crc = TU::crc32(m_rawPacket.mid(11)); + uint32_t crc = 0; + + unsigned char posID = 16; + unsigned char uctemp = posID; + + fprintf(stderr, "POSID=%0X\n", uctemp); + + uint32_t chksum = IUC_ASYNCHPOS_POLYNOME_INITIAL; + chksum = iuc_asynchpos_sub_updateCRC_2(chksum,(char *)&uctemp,1); + fprintf(stderr, "%d CRC32=%04X\n", __LINE__, chksum); + chksum = iuc_asynchpos_sub_updateCRC_2(chksum, (char *)m_posID.data() ,posID); + fprintf(stderr, "%d CRC32=%04X\n", __LINE__, chksum); + //for (uitmp = 0; uitmp < length_; ++uitmp) { + chksum = iuc_asynchpos_sub_updateCRC_2(chksum, (char *)m_loginMessage.data(), m_loginMessage.size()); + fprintf(stderr, "%d CRC32=%04X\n", __LINE__, chksum); + //} + + crc = iuc_asynchpos_sub_updateCRC_2(crc, (char *)ba.toStdString().c_str(), ba.size()); + + if (DEBUG_MESSAGE_HELPER) { + qCritical() << DBG_HEADER << "crc" << hex << crc; + } + + crc = 0; + crc = TU::crc32(ba); + + if (DEBUG_MESSAGE_HELPER) { + qCritical() << DBG_HEADER << "crc" << hex << crc; + } + + // aes aufrufen + //unsigned char key[] = "8AC304380E0E476BA2558B75DB9E2516"; + //unsigned char output[256]; + //memset(output, 0, sizeof(output)); + + //aes_encrypt((unsigned char*)ba.data(), output, key); + + if (insertEncryptedPacketID(encryptedPacketID)) { + + if (DEBUG_MESSAGE_HELPER) { + qCritical() << DBG_HEADER << m_rawPacket.toHex(':'); + } + int const chunks = m_rawPacket.size() / IUC_ASYNCHPOS_MIN_PACKET_SIZE; + + if (DEBUG_MESSAGE_HELPER) { + qCritical() << DBG_HEADER << "nr of chunks" << chunks; + } + + for (int i = 0; i < chunks; ++i) { + QByteArray messageChunk = m_rawPacket.mid(IUC_ASYNCHPOS_MIN_PACKET_SIZE*i, + IUC_ASYNCHPOS_MIN_PACKET_SIZE); + if (DEBUG_MESSAGE_HELPER) { + qCritical() << DBG_HEADER << i << messageChunk.toHex(':'); + } + + messageChunk = MessageHelper::mask(messageChunk); + + if (DEBUG_MESSAGE_HELPER) { + qCritical() << DBG_HEADER << i << messageChunk.toHex(':'); + } + + char const lrc = TU::lrc(messageChunk); + + messageChunk.push_front(STX); + messageChunk.push_back(etx == ACK1 ? ETX2 : ETX1); // etx must be ACK1 or ACK2 + messageChunk.push_back(lrc); + + if (DEBUG_MESSAGE_HELPER) { + qCritical() << DBG_HEADER << i << messageChunk.toHex(':'); + } + + m_messageChunkList += messageChunk; + } + + int const rest = m_rawPacket.size() % IUC_ASYNCHPOS_MIN_PACKET_SIZE; + if (rest) { + QByteArray messageChunk = m_rawPacket.mid(IUC_ASYNCHPOS_MIN_PACKET_SIZE*chunks, rest); + char const lrc = TU::lrc(messageChunk); + + messageChunk.push_front(STX); + + messageChunk.push_back(etx == ACK1 ? ETX2 : ETX1); // etx must be ACK1 or ACK2 + messageChunk.push_back(lrc); + + messageChunk = mask(messageChunk); + + m_messageChunkList += messageChunk; + } + } + + return m_messageChunkList; +} + +bool MessageHelper::insertEncryptedPacketID(QByteArray const &encryptedPacketID) { + if (encryptedPacketID.size() == PACKET_ID_SIZE) { + for (int i = 0; i < PACKET_ID_SIZE; ++i) { + m_messageHeaderPrefix[i+1] = encryptedPacketID[i]; + } + if (DEBUG_MESSAGE_HELPER) { + qCritical() << DBG_HEADER << m_messageHeaderPrefix.toHex(':'); + } + return true; + } + return false; +} + +QByteArray const &MessageHelper::mask(QByteArray &messageChunk) { + QByteArray ba; + for (int i = 0; i < messageChunk.size(); ++i) { + char const c = messageChunk[i]; + switch(c) { + case STX: __attribute__((fallthrough)); + case ETX1: __attribute__((fallthrough)); + case ETX2: __attribute__((fallthrough)); + case EOT: __attribute__((fallthrough)); + case ENQ: __attribute__((fallthrough)); + case ACK1: __attribute__((fallthrough)); + case ACK2: __attribute__((fallthrough)); + case DLE: __attribute__((fallthrough)); + case NAK: + ba.push_back(char(DLE)); + ba.push_back(c + 0x30); + break; + default: + ba.push_back(c); + } + } + + if (DEBUG_MESSAGE_HELPER) { + qCritical() << DBG_HEADER << ba.toHex(':'); + } + + messageChunk = ba; + return messageChunk; +} + +QByteArray const &MessageHelper::unMask(QByteArray &messageChunk) { + QByteArray ba; + for (int i = 0; i < messageChunk.size(); ++i) { + char c = messageChunk[i]; + if (c == (char)0x10) /* DEL */ { + if ((i+1) < messageChunk.size()) { + c = messageChunk[i+1] - (char)0x30; + } + } + ba.push_back(c); + } + messageChunk = ba; + return messageChunk; +} diff --git a/main/MessageHelper.h b/main/MessageHelper.h new file mode 100644 index 0000000..c620caa --- /dev/null +++ b/main/MessageHelper.h @@ -0,0 +1,54 @@ +#ifndef MESSAGE_HELPER_H_INCLUDED +#define MESSAGE_HELPER_H_INCLUDED + +#include +#include +#include +#include + + +class MessageHelper { +public: + enum PacketType : std::uint8_t { + POS_ECR = 0, + // POS_EXT = 1, + MESSAGE_RECEIVED_POSITIVE_ACK = 0x0A, + MESSAGE_RECEIVED_NEGATIVE_ACK = 0x0F + // POS_HOST_FORMAT_1_ENCRYPTED = 0x11, + // POS_HOST_FORMAT_1_UNENCRYPTED = 0x21 + }; + + explicit MessageHelper(QString const &posID = "T-TPS-SELF2002in", + QString const &apak = "8AC304380E0E476BA2558B75DB9E2516"); + explicit MessageHelper(QByteArray const &posID, QString const &apak); + ~MessageHelper(); + + + void createRawPacket(PacketType PacketType, + QByteArray const &encryptedPacketId, + QByteArray const &message); + + bool insertEncryptedPacketID(QByteArray const &encryptedPacketID); + + QByteArrayList const &getMessageChunksToSend(); + QByteArrayList const &createLoginMessageChunksToSend(char ext); + +// private: + + QByteArray m_posID; + QString m_apak; + uint8_t m_posIDLength; + QByteArray m_messageHeaderPrefix; + QByteArray m_rawPacket; // without leading STX and trailing [ETX(1/2), LRC] + QByteArray m_loginMessage; + QByteArrayList m_messageChunkList; + + bool setMessageHeaderPacketType(PacketType packetType); + bool createMessageHeaderPrefix(PacketType packetType, QByteArray const &encryptedPacketID); + void createLoginMessage(); + + static QByteArray const &mask(QByteArray &messageChunk); + static QByteArray const &unMask(QByteArray &messageChunk); +}; + +#endif // MESSAGE_HELPER_H_INCLUDED diff --git a/main/aes128.cpp b/main/aes128.cpp new file mode 100755 index 0000000..555aede --- /dev/null +++ b/main/aes128.cpp @@ -0,0 +1,625 @@ +/* + * aes128.c + * + * Created: 27.11.2017 13:33:29 + * Author: Matthias + */ + +#include + +/* the expanded keySize */ +#define EXPANDED_KEY_SIZE 176 +//int expandedKeySize; + +/* the expanded key */ +//unsigned char expandedKey[EXPANDED_KEY_SIZE]; + +/* the cipher key */ +//unsigned char key[16]; + +/* the cipher key size */ + +enum keySize{ + SIZE_16 = 16, + SIZE_24 = 24, + SIZE_32 = 32 +}; + +//enum keySize size; + +unsigned char sbox[256] = { + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, //0 + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, //1 + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, //2 + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, //3 + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, //4 + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, //5 + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, //6 + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, //7 + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, //8 + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, //9 + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, //A + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, //B + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, //C + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, //D + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, //E +0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; //F + +unsigned char rsbox[256] = +{ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb + , 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb + , 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e + , 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 + , 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 + , 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 + , 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 + , 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b + , 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 + , 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e + , 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b + , 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 + , 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f + , 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef + , 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 +, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; + +unsigned char Rcon[256] = { + + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, + 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, + 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, + 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, + 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, + 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, + 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, + 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, + 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, + 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, + 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, + 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, + 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, + 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, + 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, + 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, + 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, + 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, +0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d}; + +void aes_init() { + //UINT uitemp = 0; + /* the expanded keySize */ + //expandedKeySize = EXPANDED_KEY_SIZE; + + /* the cipher key */ + //for (uitemp = 0; uitemp < 16; ++uitemp) + //key[uitemp] = 0x00; + + /* the cipher key size */ + //size = SIZE_16; +} + +unsigned char getSBoxValue(unsigned char num) +{ + return sbox[num]; +} + +unsigned char getSBoxInvert(unsigned char num) +{ + return rsbox[num]; +} + +//Key generation + +/* Rijndael's key schedule rotate operation + * rotate the word eight bits to the left + * + * rotate(1d2c3a4f) = 2c3a4f1d + * + * word is an char array of size 4 (32 bit) + */ +void rotate(unsigned char *word) +{ + unsigned char c; + int i; + + c = word[0]; + for (i = 0; i < 3; i++) + word[i] = word[i+1]; + word[3] = c; +} + +unsigned char getRconValue(unsigned char num) +{ + return Rcon[num]; +} + +void core(unsigned char *word, int iteration) +{ + int i; + + /* rotate the 32-bit word 8 bits to the left */ + rotate(word); + + /* apply S-Box substitution on all 4 parts of the 32-bit word */ + for (i = 0; i < 4; ++i) + { + word[i] = getSBoxValue(word[i]); + } + + /* XOR the output of the rcon operation with i to the first part (leftmost) only */ + word[0] = word[0]^getRconValue(((unsigned char) iteration)); +} + +/* Rijndael's key expansion + * expands an 128,192,256 key into an 176,208,240 bytes key + * + * expandedKey is a pointer to an char array of large enough size + * key is a pointer to a non-expanded key + */ + +void expandKey(unsigned char *expandedKey, + unsigned char *key, + enum keySize size, + /*size_t*/ unsigned int expandedKeySize) +{ + /* current expanded keySize, in bytes */ + int currentSize = 0; + int rconIteration = 1; + int i; + unsigned char t[4] = {0,0,0,0}; // temporary 4-byte variable + + /* set the 16,24,32 bytes of the expanded key to the input key */ + for (i = 0; i < size; i++) + expandedKey[i] = key[i]; + currentSize += size; + + while (currentSize < expandedKeySize) + { + /* assign the previous 4 bytes to the temporary value t */ + for (i = 0; i < 4; i++) + { + t[i] = expandedKey[(currentSize - 4) + i]; + } + + /* every 16,24,32 bytes we apply the core schedule to t + * and increment rconIteration afterwards + */ + if(currentSize % size == 0) + { + core(t, rconIteration++); + } + + /* For 256-bit keys, we add an extra sbox to the calculation */ + if(size == SIZE_32 && ((currentSize % size) == 16)) { + for(i = 0; i < 4; i++) + t[i] = getSBoxValue(t[i]); + } + + /* We XOR t with the four-byte block 16,24,32 bytes before the new expanded key. + * This becomes the next four bytes in the expanded key. + */ + for(i = 0; i < 4; i++) { + expandedKey[currentSize] = expandedKey[currentSize - size] ^ t[i]; + currentSize++; + } + } +} + +//Encrypt + +void subBytes(unsigned char *state) +{ + int i; + /* substitute all the values from the state with the value in the SBox + * using the state value as index for the SBox + */ + for (i = 0; i < 16; i++) + state[i] = getSBoxValue(state[i]); +} + +void shiftRow(unsigned char *state, unsigned char nbr) +{ + int i, j; + unsigned char tmp; + /* each iteration shifts the row to the left by 1 */ + for (i = 0; i < nbr; i++) + { + tmp = state[0]; + for (j = 0; j < 3; j++) + state[j] = state[j+1]; + state[3] = tmp; + } +} + +void shiftRows(unsigned char *state) +{ + int i; + /* iterate over the 4 rows and call shiftRow() with that row */ + for (i = 0; i < 4; i++) + shiftRow(state+i*4, i); +} + +void addRoundKey(unsigned char *state, unsigned char *roundKey) +{ + int i; + for (i = 0; i < 16; i++) + state[i] = state[i] ^ roundKey[i] ; +} + +unsigned char galois_multiplication(unsigned char a, unsigned char b) +{ + unsigned char p = 0; + unsigned char counter; + unsigned char hi_bit_set; + for(counter = 0; counter < 8; counter++) { + if((b & 1) == 1) + p ^= a; + hi_bit_set = (a & 0x80); + a <<= 1; + if(hi_bit_set == 0x80) + a ^= 0x1b; + b >>= 1; + } + return p; +} + +void mixColumn(unsigned char *column) +{ + unsigned char cpy[4]; + int i; + for(i = 0; i < 4; i++) + { + cpy[i] = column[i]; + } + column[0] = galois_multiplication(cpy[0],2) ^ + galois_multiplication(cpy[3],1) ^ + galois_multiplication(cpy[2],1) ^ + galois_multiplication(cpy[1],3); + + column[1] = galois_multiplication(cpy[1],2) ^ + galois_multiplication(cpy[0],1) ^ + galois_multiplication(cpy[3],1) ^ + galois_multiplication(cpy[2],3); + + column[2] = galois_multiplication(cpy[2],2) ^ + galois_multiplication(cpy[1],1) ^ + galois_multiplication(cpy[0],1) ^ + galois_multiplication(cpy[3],3); + + column[3] = galois_multiplication(cpy[3],2) ^ + galois_multiplication(cpy[2],1) ^ + galois_multiplication(cpy[1],1) ^ + galois_multiplication(cpy[0],3); +} + +void mixColumns(unsigned char *state) +{ + int i, j; + unsigned char column[4]; + + /* iterate over the 4 columns */ + for (i = 0; i < 4; i++) + { + /* construct one column by iterating over the 4 rows */ + for (j = 0; j < 4; j++) + { + column[j] = state[(j*4)+i]; + } + + /* apply the mixColumn on one column */ + mixColumn(column); + + /* put the values back into the state */ + for (j = 0; j < 4; j++) + { + state[(j*4)+i] = column[j]; + } + } +} + +void aes_round(unsigned char *state, unsigned char *roundKey) +{ + subBytes(state); + shiftRows(state); + mixColumns(state); + addRoundKey(state, roundKey); +} + +void createRoundKey(unsigned char *expandedKey, unsigned char *roundKey) +{ + int i,j; + /* iterate over the columns */ + for (i = 0; i < 4; i++) + { + /* iterate over the rows */ + for (j = 0; j < 4; j++) + roundKey[(i+(j*4))] = expandedKey[(i*4)+j]; + } +} + +void aes_main(unsigned char *state, unsigned char *expandedKey, int nbrRounds) +{ + int i = 0; + + unsigned char roundKey[16]; + + createRoundKey(expandedKey, roundKey); + addRoundKey(state, roundKey); + + for (i = 1; i < nbrRounds; i++) { + createRoundKey(expandedKey + 16*i, roundKey); + aes_round(state, roundKey); + } + + createRoundKey(expandedKey + 16*nbrRounds, roundKey); + subBytes(state); + shiftRows(state); + addRoundKey(state, roundKey); +} + +char aes_encrypt(unsigned char *input, + unsigned char *output, + unsigned char *key + /*, enum keySize size*/) +{ + enum keySize size = SIZE_16; + /* the expanded keySize */ + int expandedKeySize; + + /* the number of rounds */ + int nbrRounds = 10; //NOTE: modded + + /* the expanded key */ + //NOTE: modded: unsigned char *expandedKey = 0x00; + //unsigned char expandedKey[(16*(nbrRounds+1))]; + unsigned char expandedKey[176]; + + /* the 128 bit block to encode */ + unsigned char block[16]; + + int i,j; + + /* set the number of rounds */ + /*switch (size) + { + case SIZE_16: + nbrRounds = 10; + break; + case SIZE_24: + nbrRounds = 12; + break; + case SIZE_32: + nbrRounds = 14; + break; + default: + return 1; //UNKNOWN_KEYSIZE; + break; + }*/ //NOTE: modded + + expandedKeySize = (16*(nbrRounds+1)); + /*if ((expandedKey = malloc(expandedKeySize * sizeof(char))) == NULL) + { + return MEMORY_ALLOCATION_PROBLEM; + }*/ + + /* Set the block values, for the block: + * a0,0 a0,1 a0,2 a0,3 + * a1,0 a1,1 a1,2 a1,3 + * a2,0 a2,1 a2,2 a2,3 + * a3,0 a3,1 a3,2 a3,3 + * the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3 + */ + + /* iterate over the columns */ + for (i = 0; i < 4; i++) + { + /* iterate over the rows */ + for (j = 0; j < 4; j++) + block[(i+(j*4))] = input[(i*4)+j]; + } + + /* expand the key into an 176, 208, 240 bytes key */ + expandKey(expandedKey, key, size, expandedKeySize); + + /* encrypt the block using the expandedKey */ + aes_main(block, expandedKey, nbrRounds); + + /* unmap the block again into the output */ + for (i = 0; i < 4; i++) + { + /* iterate over the rows */ + for (j = 0; j < 4; j++) + output[(i*4)+j] = block[(i+(j*4))]; + } + return 0; +} + +//Decrypt +void invSubBytes(unsigned char *state) +{ + int i; + /* substitute all the values from the state with the value in the SBox + * using the state value as index for the SBox + */ + for (i = 0; i < 16; i++) + state[i] = getSBoxInvert(state[i]); +} + +void invShiftRow(unsigned char *state, unsigned char nbr) +{ + int i, j; + unsigned char tmp; + /* each iteration shifts the row to the right by 1 */ + for (i = 0; i < nbr; i++) + { + tmp = state[3]; + for (j = 3; j > 0; j--) + state[j] = state[j-1]; + state[0] = tmp; + } +} + +void invShiftRows(unsigned char *state) +{ + int i; + /* iterate over the 4 rows and call invShiftRow() with that row */ + for (i = 0; i < 4; i++) + invShiftRow(state+i*4, i); +} + +void invMixColumn(unsigned char *column) +{ + unsigned char cpy[4]; + int i; + for(i = 0; i < 4; i++) + { + cpy[i] = column[i]; + } + column[0] = galois_multiplication(cpy[0],14) ^ + galois_multiplication(cpy[3],9) ^ + galois_multiplication(cpy[2],13) ^ + galois_multiplication(cpy[1],11); + column[1] = galois_multiplication(cpy[1],14) ^ + galois_multiplication(cpy[0],9) ^ + galois_multiplication(cpy[3],13) ^ + galois_multiplication(cpy[2],11); + column[2] = galois_multiplication(cpy[2],14) ^ + galois_multiplication(cpy[1],9) ^ + galois_multiplication(cpy[0],13) ^ + galois_multiplication(cpy[3],11); + column[3] = galois_multiplication(cpy[3],14) ^ + galois_multiplication(cpy[2],9) ^ + galois_multiplication(cpy[1],13) ^ + galois_multiplication(cpy[0],11); +} + +void invMixColumns(unsigned char *state) +{ + int i, j; + unsigned char column[4]; + + /* iterate over the 4 columns */ + for (i = 0; i < 4; i++) + { + /* construct one column by iterating over the 4 rows */ + for (j = 0; j < 4; j++) + { + column[j] = state[(j*4)+i]; + } + + /* apply the invMixColumn on one column */ + invMixColumn(column); + + /* put the values back into the state */ + for (j = 0; j < 4; j++) + { + state[(j*4)+i] = column[j]; + } + } +} + +void aes_invRound(unsigned char *state, unsigned char *roundKey) +{ + + invShiftRows(state); + invSubBytes(state); + addRoundKey(state, roundKey); + invMixColumns(state); +} + +void aes_invMain(unsigned char *state, unsigned char *expandedKey, int nbrRounds) +{ + int i = 0; + + unsigned char roundKey[16]; + + createRoundKey(expandedKey + 16*nbrRounds, roundKey); + addRoundKey(state, roundKey); + + for (i = nbrRounds-1; i > 0; i--) { + createRoundKey(expandedKey + 16*i, roundKey); + aes_invRound(state, roundKey); + } + + createRoundKey(expandedKey, roundKey); + invShiftRows(state); + invSubBytes(state); + addRoundKey(state, roundKey); +} + +char aes_decrypt(unsigned char *input, + unsigned char *output, + unsigned char *key + /*´, enum keySize size*/) +{ + enum keySize size = SIZE_16; + /* the expanded keySize */ + int expandedKeySize; + + /* the number of rounds */ + int nbrRounds; + + /* the expanded key */ + unsigned char *expandedKey = 0x00; + + /* the 128 bit block to decode */ + unsigned char block[16]; + + int i,j; + + /* set the number of rounds */ + switch (size) + { + case SIZE_16: + nbrRounds = 10; + break; + case SIZE_24: + nbrRounds = 12; + break; + case SIZE_32: + nbrRounds = 14; + break; + default: + return 1; //UNKNOWN_KEYSIZE; + break; + } + + expandedKeySize = (16*(nbrRounds+1)); + /*if ((expandedKey = malloc(expandedKeySize * sizeof(char))) == NULL) + { + return MEMORY_ALLOCATION_PROBLEM; + }*/ + + /* Set the block values, for the block: + * a0,0 a0,1 a0,2 a0,3 + * a1,0 a1,1 a1,2 a1,3 + * a2,0 a2,1 a2,2 a2,3 + * a3,0 a3,1 a3,2 a3,3 + * the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3 + */ + + /* iterate over the columns */ + for (i = 0; i < 4; i++) + { + /* iterate over the rows */ + for (j = 0; j < 4; j++) + block[(i+(j*4))] = input[(i*4)+j]; + } + + /* expand the key into an 176, 208, 240 bytes key */ + expandKey(expandedKey, key, size, expandedKeySize); + + /* decrypt the block using the expandedKey */ + aes_invMain(block, expandedKey, nbrRounds); + + /* unmap the block again into the output */ + for (i = 0; i < 4; i++) + { + /* iterate over the rows */ + for (j = 0; j < 4; j++) + output[(i*4)+j] = block[(i+(j*4))]; + } + return 0; +} diff --git a/main/aes128.h b/main/aes128.h new file mode 100755 index 0000000..ddbe524 --- /dev/null +++ b/main/aes128.h @@ -0,0 +1,8 @@ +#ifndef AES128_H +#define AES128_H + +void aes_init(); +char aes_encrypt(unsigned char *input,unsigned char *output,unsigned char *key); +char aes_decrypt(unsigned char *input,unsigned char *output,unsigned char *key); + +#endif \ No newline at end of file diff --git a/main/cc_iuc_asynchpos.cpp b/main/cc_iuc_asynchpos.cpp new file mode 100755 index 0000000..a6686d6 --- /dev/null +++ b/main/cc_iuc_asynchpos.cpp @@ -0,0 +1,2131 @@ +/* + * cc_iuc_asynchpos.c + * + * Created: 21.11.2017 16:36:28 + * Author: Matthias + */ + +#include "cc_iuc_asynchpos.h" +#include "aes128.h" + +#include +#include + +//#include + +uint32_t iuc_asynchpos_sub_updateCRC(uint32_t crc, char* pData, size_t len) { + // berechne CRC32 nach Polynom x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 + + QByteArray a(pData, len); + qCritical() << "updateCRC" << a.toHex(' '); + qCritical() << "updateCRC" << len; + + int i = 0; + int j = 0; +// unsigned long rem; +// unsigned char octet; +// UCHAR *p, *q; + unsigned char ucCarry = 0x00; + + crc = ~crc; + while (len > 0) { + crc ^= (uint32_t) pData[i]; + ++i; + + for (j = 0; j < 8; ++j) { + ucCarry = crc & 1; + crc >>= 1; + + if (ucCarry) { + crc ^= IUC_ASYNCHPOS_POLYNOME; + } + } + --len; + } + + return ~crc; + +} + +#if 0 + +#include + +extern struct T_CONF eeprom Conf; +extern struct T_dynamicData GWglobTime; +extern struct T_vend Vend; +static struct billAsynchData asynchBill; +extern struct T_GWstate GWstate; +//extern UCHAR GWstate.VendRequest; + +unsigned static char messageData[IUC_ASYNCHPOS_MAX_RX_MESSAGE_SIZE]; + +ULONG com_totalSecSince1jan2017(void) +{ + // eine Zahl erzeugen die sich jede sec ändert und nicht 2x vorkommen darf + // Zeit und Datum in Sekunden umrechnen. Beginne bei 1.1.2017 um 0:00Uhr + // die nächsten Schaltjahre: 2020, 2024, 2028... + // Der Wert wird sich in den nächsten 130 Jahren nicht gleichen/wiederholen + + UINT uitmp; + ULONG ultmp; + + //uitmp=com_totalDaysSince1Jan2017(GlobTime.Year, GlobTime.Month, GlobTime.Day); + uitmp= ((UINT)GWglobTime.dayOfMon) + ((UINT)GWglobTime.month) * 30; + ultmp=(ULONG)uitmp; + ultmp*=1440L; // Tage--->min + ultmp+=(ULONG) (GWglobTime.MinOfDay);//GlobTime.MinOfDay; // min von heute drauf + ultmp*=60L; + return ultmp; +} + +void generate_UniqueTransNr(UCHAR *buf) +{ + // buf>=20 bytes! + UCHAR tmp12[12]; + ULONG ultmp = 0; + ULONG transID = com_totalSecSince1jan2017(); + + // a) Transaction ID, max 19 chars + // ab April 2017: TID muss über alle Automaten und über alle Zeiten eindeutig sein, + // sonst gibt SessionBase keine Antwort. + //uitmp=VKdata.TransID; sub_BufferNummEntry(ultmp); // einfache Version bis März 2017 + biox_ClearMem(buf, '0', 19); + biox_ClearMem(tmp12, 0, 12); + //VdKdata.TransID = com_totalSecSince1jan2017(); + //biox_ultoa(VKdata.TransID, tmp12); + biox_ultoa(transID, tmp12); + biox_MemCpPos(tmp12, buf, 1); + + // Automaten-nr auch rein, sonst können versch. Automaten die gleiche Nummer haben! + biox_ClearMem(tmp12, 0, 12); + ultmp=(ULONG) Conf.MachNr; //.MachineID; + biox_ultoa(ultmp, tmp12); + biox_MemCpPos(tmp12, buf, 11); + + biox_ClearMem(tmp12, 0, 12); + ultmp=(ULONG)Conf.CustomNr; //.CustID; + biox_ultoa(ultmp, tmp12); + biox_MemCpPos(tmp12, buf, 16); + buf[19]=0; +} + +void iuc_asynchpos_sub_initArray(unsigned char* pArray, int length) { + unsigned int uitemp = 0; + + for (uitemp = 0; uitemp < length; ++uitemp) + pArray[uitemp] = 0x00; +} + +void iuc_asynchpos_setTerminalID(unsigned char *pID, unsigned int length) { + unsigned int uctemp = 0; + + if (!biox_StrComp(pID,terminalID,length)) { + for (uctemp = 0; uctemp < length; ++uctemp) { + terminalID[uctemp] = pID[uctemp]; + } + } +} + +void iuc_asynchpos_setTerminalAPAK(unsigned char *pAPAK, unsigned int length) { + unsigned char uctemp = 0; + + if (!biox_StrComp(pAPAK,terminalAPAK,length)) { + for (uctemp = 0; uctemp < length; ++uctemp) { + terminalAPAK[uctemp] = pAPAK[uctemp]; + Conf.APAK_backup[uctemp] = pAPAK[uctemp]; + } + } +} + +ULONG iuc_asynchpos_sub_updateCRC(ULONG crc, UCHAR* pData, UINT len) //TODO +{ + // berechne CRC32 nach Polynom x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 + + int i = 0; + int j = 0; +// unsigned long rem; +// unsigned char octet; +// UCHAR *p, *q; + unsigned char ucCarry = 0x00; + + crc = ~crc; + while (len > 0) { + crc ^= (ULONG) pData[i]; + ++i; + + for (j = 0; j < 8; ++j) { + ucCarry = crc & 1; + crc >>= 1; + + if (ucCarry) { + crc ^= IUC_ASYNCHPOS_POLYNOME; + } + } + --len; + } + + return ~crc; +} + +unsigned char iuc_asynchpos_rts() { + unsigned char timeOut = 0x00; + unsigned char uctmp = 0x00; + + brd_switch_RS3(RS3SW2IUC); + biox_Usart3Ini(USART_Mode_Int, USART_Baud19200, USART_data8, USART_stop1, USART_parity_none); + uctmp = EOT; + biox_Usart3_ClearRecBuffer(); + biox_Usart3_SendBlock(&uctmp,1); + + while (timeOut < 0x06 && uctmp != ENQ) { + biox_delay_ms(400); + if (biox_Usart3_NewTelegram()) { + brd_SendDiagStr("->IUC ASYNCHPOS 0x05 (ENQ) received. RTS.",1); + biox_Usart3_GetRecBuffer(&uctmp,1); + biox_Usart3_ClearRecBuffer(); + iucAsynchpoxDataContext = 0x00; + } else { + brd_SendDiagStr("->IUC ASYNCHPOS waiting for 0x05 (ENQ).",1); + biox_Usart3_ClearRecBuffer(); + biox_Usart3_SendBlock(&uctmp,1); + } + ++timeOut; + } + + if (uctmp == ENQ) + return 0; + + return 1; +} + +unsigned char iuc_asynchpos_cts() { + unsigned int recLength; + unsigned char uctmp = ENQ; + + recLength = biox_Usart3BuffSize(); + + if (recLength > 0) { + biox_Usart3_GetRecBuffer(&uctmp,1); + + if (uctmp == EOT) { //The terminal is trying to send us data + uctmp = ENQ; + biox_Usart3_ClearRecBuffer(); + biox_Usart3_SendBlock(&uctmp,1); + biox_delay_ms(10); + return 1; + } + } + + return 0; +} + +unsigned char iuc_asynchpos_waitforACK() { + //unsigned char timeOut = 0x00; + unsigned char retVal = 0x00; + unsigned char rxData_[IUC_ASYNCHPOS_MAX_ARRAY_SIZE]; + unsigned int uitmp = 0; + + uitmp = biox_Usart3BuffSize(); + + if (uitmp > 1) { + //iuc_asynchpos_sub_initArray(rxData_,IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + biox_Usart3_GetRecBuffer(rxData_,uitmp); + if (GWstate.DebugLevel & 0x10) + { + brd_SendDiagStr("->IUC ASYNCHPOS (ACK/NACK) rx data: ",0); + brd_SendDiagBlock(rxData_,1,uitmp); + } + + retVal = rxData_[0]; + + for (;uitmp > 0;--uitmp) { + if (rxData_[uitmp] == 0x0A) { + retVal |= 0xA0; + } + + if (rxData_[uitmp] == 0x0F) { + retVal |= 0xF0; + } + } + } else { + + //if (uitmp == 1) + biox_Usart3_GetRecBuffer(&retVal,1); + } + + biox_Usart3_ClearRecBuffer(); + return retVal; +} + +unsigned char iuc_asynchpos_send_serial(unsigned char* pData, unsigned int length, unsigned char needRTS, unsigned char overrideACK) { + unsigned int uitmp = 0; + unsigned int uitmp2 = 0; + unsigned int uitmp3 = 0; + unsigned int txCounter = 0; + unsigned int dxCounter = 0; + unsigned char uctmp = 0x00; +// unsigned char uctmp2 =0x00; + unsigned char chksum = 0x00; + //unsigned char dataContext = 0x00; + unsigned int retryCount = 0; + unsigned long lastRetry = 0; + unsigned int dxLength; +// unsigned int dx = biox_StrLen(pData) + 1; + unsigned char rxBuf[8]; + //unsigned char pData_[IUC_ASYNCHPOS_MAX_ARRAY_SIZE]; +// unsigned int loopCount = 1000; +// unsigned char retVal = 0x01; + + //preparing to send + if (needRTS) { + brd_SendDiagStr("->IUC ASYNCHPOS sending 0x04 (EOT).",1); + uctmp = iuc_asynchpos_rts(); + } + + //sending data + if (!uctmp) { + brd_SendDiagStr("----->IUC ASYNCHPOS",1); + iuc_asynchpos_sub_initArray(txAsynchData, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + //iuc_asynchpos_sub_initArray(pData_, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + + //biox_CopyBlock(pData,0,pData_,0,IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + + /*dxCounter = 0; + for (uitmp = 0; uitmp < dx + dxCounter; ++uitmp) { + if ((pData[uitmp] >= STX && pData[uitmp] <= ACK2) + || (pData[uitmp] == DLE) || (pData[uitmp] == NAK)) { + + pData[uitmp] = (pData[uitmp] + 0x30); + + for (uitmp2 = uitmp; uitmp2 < dx + dxCounter; ++uitmp2) { + pData[uitmp2 + 1] = pData[uitmp2]; + } + + pData[uitmp] = DLE; + ++dxCounter; + } + } + + dxCounter = 0;*/ + + for (uitmp = 0; uitmp < length; uitmp += IUC_ASYNCHPOS_MIN_PACKET_SIZE) { + + //if (dxCounter > 0) + //uitmp -= dxCounter; + + uctmp = 0x00; + dxCounter = 0; + chksum = 0x00; + dxLength = IUC_ASYNCHPOS_MIN_PACKET_SIZE; + + if (length - uitmp <= IUC_ASYNCHPOS_MIN_PACKET_SIZE) + dxLength = 2 + length - uitmp; + + iuc_asynchpos_sub_initArray(txAsynchData, 3 + IUC_ASYNCHPOS_MIN_PACKET_SIZE); + + //Packet structure is STX ETX1|ETX2 {LRC} + txAsynchData[0] = STX; + + for (txCounter = 0; (txCounter/* + dxCounter*/) < dxLength; ++txCounter) { + //for (txCounter = 0; txCounter < dxLength; ++txCounter) { + + /*if ((pData[uitmp + txCounter] >= STX && pData[uitmp + txCounter] <= ACK2) + || (pData[uitmp + txCounter] == DLE) || (pData[uitmp + txCounter] == NAK)) { + txAsynchData[1 + txCounter + dxCounter] = DLE; + uctmp = (pData[uitmp + txCounter] + 0x30); + ++dxCounter; + txAsynchData[1 + txCounter + dxCounter] = uctmp; //(pData[uitmp + txCounter] + 0x30); + } else {*/ + txAsynchData[1 + txCounter/* + dxCounter*/] = pData[uitmp + txCounter]; + + if ((pData[uitmp + txCounter] >= STX && pData[uitmp + txCounter] <= ACK2) + || (pData[uitmp + txCounter] == DLE) || (pData[uitmp + txCounter] == NAK)) { + ++dxCounter; + } + } + + for (uitmp2 = 1; uitmp2 < dxLength + dxCounter; ++uitmp2) { + if ((txAsynchData[uitmp2] >= STX && txAsynchData[uitmp2] <= ACK2) + || (txAsynchData[uitmp2] == DLE) || (txAsynchData[uitmp2] == NAK)) { + for (uitmp3 = dxLength + dxCounter; uitmp3 > uitmp2; --uitmp3) { + txAsynchData[uitmp3] = txAsynchData[uitmp3 - 1]; + } + txAsynchData[uitmp2 + 1] = (txAsynchData[uitmp2 + 1] + 0x30); + txAsynchData[uitmp2] = DLE; + } + } + + /*if (dxLength < IUC_ASYNCHPOS_MIN_PACKET_SIZE && txAsynchData[txCounter + dxCounter] != 0x00) { + ++dxCounter; + }*/ + + for (uitmp2 = 1; uitmp2 <= (txCounter + dxCounter); ++uitmp2) { + chksum ^= txAsynchData[uitmp2]; + } + + if (!iucAsynchpoxDataContext) { + txAsynchData[1 + txCounter + dxCounter] = ETX1; + chksum ^= ETX1; + } else { + txAsynchData[1 + txCounter + dxCounter] = ETX2; + chksum ^= ETX2; + } + + txAsynchData[2 + txCounter + dxCounter] = chksum; + + //Check if the terminal has decided, that our gateway is gone and is frantically sending us EOTs all the time + //iuc_asynchpos_cts(); + + //send packet + biox_Usart3_ClearRecBuffer(); + biox_Usart3_SendBlock(txAsynchData,3 + txCounter + dxCounter); + biox_delay_ms(1); + + iuc_asynchpos_sub_initArray(rxBuf,8); + biox_itoa(3 + txCounter + dxCounter,rxBuf); + + if (GWstate.DebugLevel & 0x10) + { + brd_SendDiagStr("->IUC ASYNCHPOS Packetlength: ",0); + brd_SendDiagBlock(rxBuf,1,8); + brd_SendDiagStr("->IUC ASYNCHPOS send package: ",0); + brd_SendDiagBlock(txAsynchData,1,3 + txCounter + dxCounter); + } + //brd_SendDiagStr("->IUC ASYNCHPOS Send: ",0); + //brd_SendDiagBlock(txAsynchData,1,3 + txCounter + dxCounter); + + //wait for ACK + uctmp = 0x00; + lastRetry = 0; + retryCount = 0; + + brd_SendDiagStr("->IUC ASYNCHPOS waiting for answer (serial)",1); + do { + uctmp = iuc_asynchpos_waitforACK(); + //uctmp2 = uctmp; + uctmp &= 0x0F; + //if (!(lastRetry % 10)) { + //} + + if ((uctmp == NAK) || ((lastRetry >= 100) && (uctmp == 0x00))) { + brd_SendDiagStr("->IUC ASYNCHPOS waiting for answer (serial)",1); + if (uctmp == NAK) + brd_SendDiagStr("->IUC ASYNCHPOS NACK (serial)",1); + biox_Usart3_SendBlock(txAsynchData,3 + txCounter + dxCounter); + biox_delay_ms(1); + ++retryCount; + uctmp = 0x00; + lastRetry = 0; + } else { + ++lastRetry; + biox_delay_ms(1); + } + } while (retryCount < 25 && uctmp == 0x00); //Entweder Timeout, keine neuen Versuche oder ein ACK1/ACK2 holen uns hier raus + + /*while (retryCount < 5 && (uctmp == 0x00 || uctmp == NAK)) { + uctmp = iuc_asynchpos_waitforACK(); + ++lastRetry; + +// if (uitmp == 0) +// biox_delay_ms(100); + + if ((uctmp == NAK) || (uctmp == 0x00 && (lastRetry % 10 == 0x00))) { + biox_Usart2_ClearRecBuffer(); + brd_SendDiagStr("->IUC ASYNCHPOS NACK (serial)",1); + biox_Usart2_SendBlock(txAsynchData,3 + txCounter + dxCounter); + biox_delay_ms(10); + brd_SendDiagStr("->IUC ASYNCHPOS resend: ",0); + brd_SendDiagBlock(txAsynchData,1,3 + txCounter + dxCounter); + ++retryCount; + } else if (uctmp == ETX1 || uctmp == ETX2) { + biox_Usart2_ClearRecBuffer(); + uctmp = NAK; + biox_Usart2_SendBlock(&uctmp,1); + } + }*/ + + if (!uctmp) { + brd_SendDiagStr("->IUC ASYNCHPOS Terminal did not reply.",1); + return 1; //sending failed + } + + //iuc_asynchpos_sub_initArray(txAsynchData, 3 + txCounter + dxCounter); + + if (uctmp == ACK1) { + brd_SendDiagStr("->IUC ASYNCHPOS ACK 1 (serial)",1); + //dataContext = 0x01; + iucAsynchpoxDataContext = 0x01; + } + + if (uctmp == ACK2) { + brd_SendDiagStr("->IUC ASYNCHPOS ACK 2 (serial)",1); + //dataContext = 0x00; + iucAsynchpoxDataContext = 0x00; + } + + if (retryCount >= 5) { + brd_SendDiagStr("->IUC ASYNCHPOS Too much NACKs, giving up.",1); + return 2; //too much NACKs, giving up + } + } + + /*uctmp2 &= 0xF0; + + if (uctmp2 == 0xA0) { + retVal = 1; + } + + if (uctmp2 == 0xF0) { + retVal = 0; + }*/ + + /*if (!overrideACK) { + brd_SendDiagStr("->IUC ASYNCHPOS Retrieving.",1); + retVal = 0x01; + uitmp = 0x01; + while(uitmp > 0 && loopCount > 0) { + uitmp = iuc_asynchpos_recieve_serial(0x01); + biox_delay_ms(1); + --loopCount; + biox_Usart2_ClearRecBuffer(); + } + + if (loopCount == 0) { + brd_SendDiagStr("->IUC ASYNCHPOS Retrieving timeout!",1); + retVal = 0x00; + } + brd_SendDiagStr("->IUC ASYNCHPOS Retrieving ended.",1); + }*/ + + return 1;//retVal;//(UCHAR) uitmp; + } else { + brd_SendDiagStr("->IUC ASYNCHPOS Not ready to send to POS, giving up.",1); + } + + return 2; +} + +unsigned int iuc_asynchpos_send(unsigned char packetType, unsigned char* pData, unsigned int length, unsigned char needRTS) { + unsigned char txData_[IUC_ASYNCHPOS_MAX_ARRAY_SIZE]; + unsigned char tempID [IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE]; + unsigned char tempID_ [IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE]; + unsigned char tempAPAK [IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE]; + unsigned long uitmp = 0; + unsigned int posID = 0; + unsigned long chksum = 0; + unsigned int messageLength = length + 1; + unsigned int length_ = length + 1; + unsigned char pData_[IUC_ASYNCHPOS_MAX_ARRAY_SIZE]; + unsigned char uctemp = 0; +// unsigned char retries = 4; + unsigned char rxBuf[8]; + + iuc_asynchpos_crc_old = 0; + iuc_asynchpos_sub_initArray(rxBuf, 8); + iuc_asynchpos_sub_initArray(pData_, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + biox_CopyBlock(pData,0,pData_,0,length_); + + iuc_asynchpos_sub_initArray(txData_, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + iuc_asynchpos_sub_initArray(tempID, IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE); + iuc_asynchpos_sub_initArray(tempID_, IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE); + iuc_asynchpos_sub_initArray(tempAPAK, IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE); + + //header + /* + The header of the message is composed of: + ? 1 byte packet Type, which indicates the type of the packet; + ? 8 bytes Packet ID, a unique ID to achieve maximum security (for information on forming + Packet ID see chapter 3.4 Communication security); + ? 1 byte P.O.S. ID length; + ? ASCII encoded P.O.S. ID (up to 255 bytes); ((gemeint ist Terminal ID) + */ + + txData_[2] = packetType; + + //1 byte P.O.S. ID length + /*for (uitmp = 0; uitmp < 32 && terminalID[uitmp] != 0x00; ++uitmp) { + ++posID; // -= uitmp; + }*/ + + posID = biox_StrLen(terminalID)/* + 1*/; + + //++posID; + txData_[11] = (UCHAR) posID; + + messageLength += (10 + posID); //Added header + txData_[0] = (messageLength) & 0xFF00; //high byte + txData_[1] = (messageLength) & 0x00FF; //low byte + + //8 byte Packet ID + /* + Apak: 9D547268976ADE1BBB39DE90F3A449E5 + Terminal id: T-LT-OPT-01 + */ + + //calculate CRC32 + uctemp = (UCHAR) posID; + chksum = IUC_ASYNCHPOS_POLYNOME_INITIAL; + chksum = iuc_asynchpos_sub_updateCRC(chksum,&uctemp,1); + chksum = iuc_asynchpos_sub_updateCRC(chksum,terminalID,posID); + //for (uitmp = 0; uitmp < length_; ++uitmp) { + chksum = iuc_asynchpos_sub_updateCRC(chksum,pData_/*[uitmp]*/,length_); + //} + + //XOR crc value with APAK + //chksum = 2502456899; //HACK FOR TESTING, REMOVE LATER! + for(uitmp = 0; uitmp < IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE; ++uitmp) { + tempAPAK[uitmp] |= biox_ah2ui_char(terminalAPAK[uitmp * 2]) << 4; + tempAPAK[uitmp] |= biox_ah2ui_char(terminalAPAK[(uitmp * 2) + 1]); + //tempAPAK[uitmp] = (terminalAPAK[uitmp * 2] << 8) | (terminalAPAK[(uitmp * 2) + 1]); + } + + tempID[0] = (chksum >> 24) & 0xFF; + tempID[1] = (chksum >> 16) & 0xFF; + tempID[2] = (chksum >> 8) & 0xFF; + tempID[3] = chksum & 0xFF; + + for (uitmp = 0; uitmp < 4; ++uitmp) { + tempID[uitmp] ^= tempAPAK[uitmp]; //terminalAPAK[uitmp]; + } + + for (uitmp = 4; uitmp < IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE; ++uitmp) { + tempID[uitmp] = tempAPAK[uitmp]; //terminalAPAK[uitmp]; + } + + //Eyncrypt result with APAK, according to AES128 + aes_encrypt(tempID,tempID_,tempAPAK); + + //get the leftmost 8 byte of that value and set then as Packet ID + for (uitmp = 0; uitmp < 8; ++uitmp) + txData_[3 + uitmp] = tempID_[uitmp]; + + //P.O.S.ID + for (uitmp = 0; uitmp < posID; ++uitmp) { + txData_[12 + uitmp] = terminalID[uitmp]; + } + + //Message + //1 byte - marker + //0 . 7F bytes - tag name + //2 + N bytes - data + for (uitmp = 0; uitmp < length_; ++uitmp) { + txData_[12 + posID + uitmp] = pData_[uitmp]; + } + + brd_SendDiagStr("->IUC ASYNCHPOS send message: ",0); + brd_SendDiagBlock(txData_,1,messageLength); + + //Message compiled, now send it via serial + uitmp = 1; + //while (retries > 0 && uitmp > 0) { + //uitmp = iuc_asynchpos_send_serial(txData_, (messageLength + 1)); + //--retries; + if (iuc_asynchpos_send_serial(txData_, (messageLength/* + 1*/),needRTS,0x00)) { + //brd_SendDiagStr("->IUC ASYNCHPOS Message failed!",1); + //TODO Message sending failed -> Error handling here + //return 1; + uitmp = 0x00; + brd_SendDiagStr("->IUC ASYNCHPOS Message NOT send",1); + } else { + brd_SendDiagStr("->IUC ASYNCHPOS Message send",1); + } /*else { + --retries; + } + }*/ + + //if (!uitmp) + //return 1; + + /*if (retries == 0) { + brd_SendDiagStr("->IUC ASYNCHPOS Message failed!",1); + rxBuf[0] = 0x45; + rxBuf[1] = 0x00; + rxBuf[2] = 0xFF; + vmc_SendWithBuffer(rxBuf,20,0x69,0); + return 1; + } + + rxBuf[0] = 0x45; + rxBuf[1] = 0x00; + rxBuf[2] = 0x00; + vmc_SendWithBuffer(rxBuf,20,0x69,0);*/ + + //brd_SendDiagStr("->IUC ASYNCHPOS Message send",1); + //while(iuc_asynchpos_recieve_serial()); + + return 0; +} + +/* +Let us assume that a client wants to purchase items and he wants to pay for these items with his +bank card. When the client is ready to authorize the transaction, the ECR needs to send [Authorize] +request for the operations to start. Within the request, the ECR must include: +? An [Amount] sub tag with the tender amount in minor currency; +? A [Currency] sub tag with a three digit currency code; +? A [DocNr] sub tag with the number referencing the current receipt; +? [Time] – the time of the transaction; +? A [Lang] sub tag specifying a language code; +As a result, the P.O.S. will reply by an [AuthorizationResult] device event with an [ID], [DocNr], +[Result] sub tags. When ECR closes/finalizes its receipt, ECR must send [DocClosed] event to +finalize bank operation of in this receipt. A successful authorization Id from [AuthorizationResult] +must be included in [DocClosed] message. Only Id of successful authorization has to be included, +other Ids has to be omitted from message. +Depending on the configuration, and requirements, the ECR may receive a [PrintReceipt] event +(though some models of P.O.S. could as well print the receipt itself), with an [ID], [DocNr], and the +[ReceiptText], to be printed out. The [PrintReceipt] event may occur at any time of the operation, +whenever the P.O.S. needs to print something, and it should be printed as soon as possible. ECR +may be occupied during the event, so it may start printing when no more operations are waiting to +be processed. After the receipt has been printed, the ECR has to send a [PrintResult] to P.O.S. to +confirm the successful action. P.O.S. may send [GetMessageBoxInput] message to ECR if signature +of Client needed. ECR must send [InputResult] message to POS. This message informs about sign +status. +During bank card authorization [PrintReceipt] messages usually are sent before +[AuthorizationResult] event. +POS could send additional [DisplayText] message(s) to ECR to inform about process steps. +*/ + +void iuc_asynchpos_sub_initZero(unsigned char* pArray, int length) { + unsigned int uitemp = 0; + + for (uitemp = 0; uitemp < (length - 1); ++uitemp) + pArray[uitemp] = 0x30; + + pArray[length - 1] = 0x00; +} + +void iuc_asynchpos_sub_clear_message(unsigned char fillwithZero) { + if (fillwithZero) { + iuc_asynchpos_sub_initZero(asynchBill.id,37); + iuc_asynchpos_sub_initZero(asynchBill.docNr,33); + /*iuc_asynchpos_sub_initZero(asynchBill.token,25); + iuc_asynchpos_sub_initZero(asynchBill.result,8); + iuc_asynchpos_sub_initZero(asynchBill.amount,10); + iuc_asynchpos_sub_initZero(asynchBill.authCode,7); + iuc_asynchpos_sub_initZero(asynchBill.rrn,13); + iuc_asynchpos_sub_initZero(asynchBill.stan,7); + iuc_asynchpos_sub_initZero(asynchBill.cardtype,33);*/ + //iuc_asynchpos_sub_initZero(asynchBill.errCode,17); + } else { + iuc_asynchpos_sub_initArray(asynchBill.id,37); + iuc_asynchpos_sub_initArray(asynchBill.docNr,33); + /*iuc_asynchpos_sub_initArray(asynchBill.token,25); + iuc_asynchpos_sub_initArray(asynchBill.result,8); + iuc_asynchpos_sub_initArray(asynchBill.amount,10); + iuc_asynchpos_sub_initArray(asynchBill.authCode,7); + iuc_asynchpos_sub_initArray(asynchBill.rrn,13); + iuc_asynchpos_sub_initArray(asynchBill.stan,7); + iuc_asynchpos_sub_initArray(asynchBill.cardtype,33);*/ + //iuc_asynchpos_sub_initArray(asynchBill.errCode,17); + } +} + +void iuc_asynchpos_sub_sendACK(unsigned char switchPrint) { + unsigned char messageReturnData[100]; + unsigned int uitemp = 0; + unsigned int uitemp2 = 0; + unsigned int uitemp3 = 0; + unsigned char uctmp = 0; + unsigned int lastRetry = 0; + unsigned int retryCount = 0; + + iuc_asynchpos_sub_initArray(messageReturnData, 100); //iuc_asynchpos_sub_initArray(messageData, messageLength + 1);//iuc_asynchpos_sub_initArray(messageReturnData, IUC_ASYNCHPOS_MAX_MESSAGE_SIZE); + switch (switchPrint) { + case 1: + for (uitemp = 0; uitemp < 8; ++uitemp) { + messageReturnData[uitemp + 3] = terminalSignature[uitemp]; + } + messageReturnData[uitemp + 3] = (UCHAR) biox_StrLen(terminalID); + + for (uitemp = 0; uitemp < biox_StrLen(terminalID); ++uitemp) { + messageReturnData[uitemp + 12] = terminalID[uitemp]; + } + uitemp += 10; + break; + case 2: + for (uitemp = 0; uitemp < 8; ++uitemp) { + messageReturnData[uitemp + 3] = terminalSignature[uitemp + 8]; + } + messageReturnData[uitemp + 3] = biox_StrLen(terminalID); + + for (uitemp = 0; uitemp < biox_StrLen(terminalID); ++uitemp) { + messageReturnData[uitemp + 12] = terminalID[uitemp]; + } + uitemp += 10; + break; + case 0: + default: + for (uitemp = 0; uitemp < rxAsynchData[11] + 9; ++uitemp) { + messageReturnData[uitemp + 3] = rxAsynchData[uitemp + 3]; + } + ++uitemp; + break; + } + + messageReturnData[0] = uitemp & (0xFF00); + messageReturnData[1] = uitemp & (0x00FF); + messageReturnData[2] = 0x0A; + //iuc_asynchpos_send_serial(messageReturnData,uitemp/* + 1*/,0x00,0x01); + + for (uitemp2 = uitemp + 2; uitemp2 > 0; --uitemp2) { + messageReturnData[uitemp2] = messageReturnData[uitemp2 - 1]; + } + uitemp += 2; + + messageReturnData[0] = 0x01; + + //convert characters + for (uitemp2 = 1; uitemp2 < uitemp + 2; ++uitemp2) { + if ((messageReturnData[uitemp2] >= STX && messageReturnData[uitemp2] <= ACK2) + || (messageReturnData[uitemp2] == DLE) || (messageReturnData[uitemp2] == NAK)) { + ++uitemp; + for (uitemp3 = uitemp + 1; uitemp3 > uitemp2; --uitemp3) { + messageReturnData[uitemp3] = messageReturnData[uitemp3 - 1]; + } + messageReturnData[uitemp2 + 1] = messageReturnData[uitemp2 + 1] + 0x30; + messageReturnData[uitemp2] = DLE; + } + } + + messageReturnData[uitemp + 1] = ETX1; + + //calculate chksum + for (uitemp2 = 1; uitemp2 < uitemp + 2; ++uitemp2) { + messageReturnData[uitemp + 2] ^= messageReturnData[uitemp2]; + } + + biox_Usart3_SendBlock(messageReturnData,uitemp2+1); + + //wait for ACK + uctmp = 0x00; + lastRetry = 1; + retryCount = 0; + + brd_SendDiagStr("->IUC ASYNCHPOS waiting for answer (serial)",1); + do { + uctmp = iuc_asynchpos_waitforACK(); + //if (!(lastRetry % 10)) { + //} + + if (uctmp == NAK || ((lastRetry % 500 == 0) && (uctmp == 0x00))) { + brd_SendDiagStr("->IUC ASYNCHPOS waiting for answer (serial)",1); + if (uctmp == NAK) + brd_SendDiagStr("->IUC ASYNCHPOS NACK (serial)",1); + biox_Usart3_SendBlock(messageReturnData,uitemp2+1); + biox_delay_ms(1); + ++retryCount; + uctmp = 0x00; + lastRetry = 1; + } else { + ++lastRetry; + biox_delay_ms(1); + } + } while (retryCount < 5 && uctmp == 0x00); //Entweder Timeout, keine neuen Versuche oder ein ACK1/ACK2 holen uns hier raus + + if (!uctmp) { + brd_SendDiagStr("->IUC ASYNCHPOS Terminal did not reply.",1); + //return 1; //sending failed + } + + if (uctmp == ACK1) { + brd_SendDiagStr("->IUC ASYNCHPOS ACK 1 (ACK serial)",1); + //dataContext = 0x01; + iucAsynchpoxDataContext = 0x01; + } + + if (uctmp == ACK2) { + brd_SendDiagStr("->IUC ASYNCHPOS ACK 2 (ACK serial)",1); + //dataContext = 0x00; + iucAsynchpoxDataContext = 0x00; + } + + if (retryCount >= 5) { + brd_SendDiagStr("->IUC ASYNCHPOS (ACK serial) Too much NACKs, giving up.",1); + //return 2; //too much NACKs, giving up + } +} + +void iuc_asynchpos_resetBuffers(unsigned char sendENQ) { + unsigned char uctmp = ENQ; + unsigned char rxBuf[8]; + + if (sendENQ != 0x02) { + rxCounter = 0; + messageLength = 0; + iuc_asynchpos_sub_initArray(rxAsynchData, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + iuc_asynchpos_sub_initArray(txAsynchData, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + } + + if (sendENQ) { + iucAsynchpoxDataContext = 0x00; + ENQrecieved = 1; + brd_SendDiagStr("->IUC ASYNCHPOS 0x04 (EOT) received.",1); + brd_switch_RS3(RS3SW2IUC); + biox_Usart3Ini(USART_Mode_Int, USART_Baud19200, USART_data8, USART_stop1, USART_parity_none); + biox_delay_ms(1); + biox_Usart3_ClearRecBuffer(); + brd_SendDiagStr("->IUC ASYNCHPOS send 0x05 (ENQ). CTS",1); + biox_Usart3_SendBlock(&uctmp,1); + + if (asynchState <= 0x03) + { + brd_SendDiagStr("->IUC ASYNCHPOS sending an error to the VMC",1); + iuc_asynchpos_sub_initArray(rxBuf,8); + rxBuf[0] = 0x45; + rxBuf[1] = 0x00; + rxBuf[2] = 0xFF; + vmc_SendWithBuffer(rxBuf,8,0x69,0); + } + } +} + +//46 +void iuc_asynchpos_command_print_Result(unsigned char status) { //Finalize sale + UCHAR message[IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE]; + UCHAR packetType = 0x00; + UINT uitemp = 0; + UCHAR command[] = "PrintResult"; + UCHAR tagName[] = "DocNr"; + UCHAR tag2Name[] = "Result"; + UCHAR tag3Name[] = "ID"; + UCHAR tag2ValueO[] = "OK"; + UCHAR tag2ValueE[] = "ERROR"; + unsigned char uctmp = status; + + //Constructing the message + iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + + uitemp = biox_StrLen(command); + message[0] = (UCHAR) uitemp + 0x80; //constructed element, tag name length + biox_CopyBlock(command,0,message,1,uitemp); //tag name + ++uitemp; + + //ID + message[uitemp] = (UCHAR) biox_StrLen(tag3Name); + ++uitemp; + biox_CopyBlock(tag3Name,0,message,uitemp, biox_StrLen(tag3Name)); + uitemp += (1 + biox_StrLen(tag3Name)); + + message[uitemp] = (UCHAR) biox_StrLen(asynchBill.printId);//value length + ++uitemp; + biox_CopyBlock(asynchBill.printId,0,message,uitemp, biox_StrLen(asynchBill.printId));//value + uitemp += biox_StrLen(asynchBill.printId); + + //DocNr + message[uitemp] = (UCHAR) biox_StrLen(tagName);//data element, tag name length + ++uitemp; + biox_CopyBlock(tagName,0,message,uitemp, biox_StrLen(tagName));// tag name + uitemp += (1 + biox_StrLen(tagName)); + + message[uitemp] = (UCHAR) biox_StrLen(asynchBill.docNr);//value length + ++uitemp; + biox_CopyBlock(asynchBill.docNr,0,message,uitemp, biox_StrLen(asynchBill.docNr));//value + uitemp += biox_StrLen(asynchBill.docNr); + + //Result + message[uitemp] = (UCHAR) biox_StrLen(tag2Name);//data element, tag name length + ++uitemp; + biox_CopyBlock(tag2Name,0,message,uitemp, biox_StrLen(tag2Name));// tag name + uitemp += (1 + biox_StrLen(tag2Name)); + + if (!uctmp) { + message[uitemp] = (UCHAR) biox_StrLen(tag2ValueE);//value length + ++uitemp; + biox_CopyBlock(tag2ValueE,0,message,uitemp, biox_StrLen(tag2ValueE));//value + uitemp += biox_StrLen(tag2ValueE)/* + 1*/; + } else { + message[uitemp] = (UCHAR) biox_StrLen(tag2ValueO);//value length + ++uitemp; + biox_CopyBlock(tag2ValueO,0,message,uitemp, biox_StrLen(tag2ValueO));//value + uitemp += biox_StrLen(tag2ValueO)/* + 1*/; + } + + iuc_asynchpos_send(packetType,message,uitemp,0x00); +} + +void iuc_asynchpos_handleMessage(unsigned char* pData) { + //unsigned char marker = pData[0]; +// unsigned int tagNameLength = pData[1]; + unsigned char tagName[IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE]; +// unsigned int curElementLength = 0; + //unsigned char curElement[IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE]; + //unsigned char receiptData[IUC_ASYNCHPOS_MAX_ARRAY_SIZE + 1]; + unsigned char rxBuf[20]; +// unsigned char flags[129]; +// unsigned char docNr[32]; + //unsigned char messageType = pData[1]; + + unsigned int uitmp = 0; + unsigned int uitmp2 = 0; + + iuc_asynchpos_sub_initArray(tagName, IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE); + //iuc_asynchpos_sub_initArray(curElement, IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE); + + uitmp = biox_FindStrInBufferInt("LoginResult",pData) | biox_FindStrInBuffer("LOGINRESULT",pData); + if (uitmp) { + asynchState = 0x02; //eingeloggt + /*rxBuf[0] = 0x45; + rxBuf[1] = 0x00; + rxBuf[2] = 0x00; + vmc_SendWithBuffer(rxBuf,40,0x69,0);*/ + } + + uitmp = biox_FindStrInBufferInt("AuthorizationStarted",pData) | biox_FindStrInBuffer("AUTHORIZATIONSTARTED",pData); + if (uitmp) { + iuc_asynchpos_sub_initArray(rxBuf,5); + rxBuf[0] = 0x53; + rxBuf[1] = 0x00; + rxBuf[2] = 0x00; + vmc_SendWithBuffer(rxBuf,5,0x69,0); + } + + uitmp = biox_FindStrInBufferInt("AuthorizationResult",pData) | biox_FindStrInBuffer("AUTHORIZATIONRESULT",pData); + if (uitmp) { + asynchState = 0x03; //successfully authorized + iuc_asynchpos_sub_clear_message(0x00); + uitmp = biox_FindStrInBufferInt("ID",pData); + biox_CopyBlock(pData, uitmp + 2, asynchBill.id, 0, pData[uitmp + 1]); + uitmp = biox_FindStrInBufferInt("DocNr",pData) | biox_FindStrInBuffer("DOCNR",pData); + biox_CopyBlock(pData, uitmp + 2, asynchBill.docNr, 0, pData[uitmp + 1]); + //uitmp = biox_FindStrInBuffer("Result",pData) | biox_FindStrInBuffer("RESULT",pData); + //biox_CopyBlock(pData, uitmp + 2, asynchBill.result, 0, pData[uitmp + 1]); + + brd_SendDiagStr("->IUC ASYNCHPOS message ID: ",0); + brd_SendDiagBlock(asynchBill.id,1,36); + + /*if (iuc_asynch_PrintControl) { + brd_SendDiagStr("->IUC ASYNCHPOS print data send AUTH: ",1); + vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0); + iuc_asynch_PrintControl = 0x00; + //biox_delay_ms(750); + } else { + brd_SendDiagStr("->IUC ASYNCHPOS sending authorization: ",1); + iuc_asynch_PrintControl = 0x01; + }*/ + + uitmp = biox_FindStrInBufferInt("ERROR",pData); + if (!uitmp/*biox_FindStrInBuffer("OK",pData) | biox_FindStrInBuffer("Approved",pData) | biox_FindStrInBuffer("APPROVED",asynchBill.result)*/) { + iuc_asynch_PrintControl |= 0xF0; + /*uitmp = biox_FindStrInBufferInt("Amount",pData) | biox_FindStrInBufferInt("AMOUNT",pData); + //if (pData[uitmp + 1] <= 10) { + biox_CopyBlock(pData, uitmp + 2, asynchBill.amount, 0, pData[uitmp + 1]); + //} else { + //biox_CopyBlock(pData, uitmp + 2, asynchBill.amount, 0, 10); + //}*/ + + //uitmp = biox_FindStrInBuffer("Token",pData); + //biox_CopyBlock(pData, uitmp + 2, asynchBill.token, 0, pData[uitmp + 1]); + /*uitmp = biox_FindStrInBufferInt("Authcode",pData) | biox_FindStrInBufferInt("AUTHCODE",pData); + biox_CopyBlock(pData, uitmp + 2, asynchBill.authCode, 0, pData[uitmp + 1]); + uitmp = biox_FindStrInBufferInt("RRN",pData); + biox_CopyBlock(pData, uitmp + 2, asynchBill.rrn, 0, pData[uitmp + 1]); + uitmp = biox_FindStrInBufferInt("STAN",pData); + biox_CopyBlock(pData, uitmp + 2, asynchBill.stan, 0, pData[uitmp + 1]); + uitmp = biox_FindStrInBufferInt("CardType",pData) | biox_FindStrInBufferInt("CARDTYPE",pData); + biox_CopyBlock(pData, uitmp + 2, asynchBill.cardtype, 0, pData[uitmp + 1]);*/ + asynchState = 0x04; + + brd_SendDiagStr("->IUC ASYNCHPOS authorization confirmed.",1); + + /*iuc_asynchpos_sub_initArray(rxBuf,20); + rxBuf[0] = 0x45; + rxBuf[1] = 0x00; + rxBuf[2] = 0x00; + vmc_SendWithBuffer(rxBuf,20,0x69,0);*/ + + //iuc_asynchpos_resetBuffers(0x01); + //iuc_asynchpos_command_close_Document(); + } else { + iuc_asynch_PrintControl |= 0xF0; + //uitmp = biox_FindStrInBufferInt("ErrCode",pData) | biox_FindStrInBufferInt("ERRCODE",pData); + //biox_CopyBlock(pData, uitmp + 2, asynchBill.errCode, 0, pData[uitmp + 1]); + + brd_SendDiagStr("->IUC ASYNCHPOS authorization failed.",1); + + /*iuc_asynchpos_sub_initArray(rxBuf,20); + rxBuf[0] = 0x45; + rxBuf[1] = 0xFF; + biox_CopyBlock(pData, uitmp + 2, rxBuf, 2, pData[uitmp + 1]); + vmc_SendWithBuffer(rxBuf,20,0x69,0);*/ + iuc_asynch_keepAlive = 0x00; + //VendRequest=0; + } + } + + uitmp = biox_FindStrInBufferInt("PrintReceipt",pData) | biox_FindStrInBufferInt("PRINTRECEIPT",pData); + if (uitmp) { + asynchState = 0x03; //Customer receipt recieved + //iuc_asynchpos_sub_initArray(flags,129); + //uitmp = biox_FindStrInBufferInt("Flag",pData) | biox_FindStrInBufferInt("FLAG",pData) | biox_FindStrInBufferInt("Flags",pData) | biox_FindStrInBufferInt("FLAGS",pData); + /*if (uitmp) { + biox_CopyBlock(pData, uitmp + 2, flags, 0, pData[uitmp + 1]); + uitmp = biox_FindStrInBufferInt("CD",flags) | biox_FindStrInBufferInt("LR",flags); + }*/ + + /*iuc_asynchpos_sub_clear_message(0x00); + uitmp = biox_FindStrInBufferInt("ID",pData); + biox_CopyBlock(pData, uitmp + 2, asynchBill.id, 0, pData[uitmp + 1]); + uitmp = biox_FindStrInBufferInt("DocNr",pData) | biox_FindStrInBuffer("DOCNR",pData); + biox_CopyBlock(pData, uitmp + 2, asynchBill.docNr, 0, pData[uitmp + 1]);*/ + iuc_asynchpos_sub_initArray(asynchBill.printId,129); + uitmp = biox_FindStrInBufferInt("ID",pData); + biox_CopyBlock(pData, uitmp + 2, asynchBill.printId, 0, pData[uitmp + 1]); + + //if(asynchState == 0x02/* && uitmp biox_FindStrInBufferInt("CD",flags) || biox_FindStrInBufferInt("LR",flags)*/) { + if((!iuc_asynch_PRNrecieved) && (biox_FindStrInBufferInt("CD",pData) || biox_FindStrInBufferInt("LR",pData)) ) { + iuc_asynch_PRNrecieved = 0x01; + iuc_asynchpos_sub_initArray(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE + 1); + uitmp = /*biox_FindStrInBuffer("ReceiptText",pData) | */biox_FindStrInBufferInt("RECEIPTTEXT",pData); + uitmp2 = (pData[uitmp] * 256) + pData[uitmp + 1]; + + //if (uitmp2 <= IUC_ASYNCHPOS_MAX_ARRAY_SIZE) { + if (uitmp2 > IUC_ASYNCHPOS_MAX_ARRAY_SIZE) { + uitmp2 = IUC_ASYNCHPOS_MAX_ARRAY_SIZE; + brd_SendDiagStr("->IUC ASYNCHPOS receipt: ERROR. Receipt too large! Cutting off.",1); + /*receiptData[0] = 0x50; + biox_CopyBlock(pData, uitmp + 2, receiptData, 1, uitmp2/*IUC_ASYNCHPOS_MAX_ARRAY_SIZE*); + //uitmp += IUC_ASYNCHPOS_MAX_ARRAY_SIZE; + //uitmp2 -= IUC_ASYNCHPOS_MAX_ARRAY_SIZE; + + brd_SendDiagStr("->IUC ASYNCHPOS receipt: ",0); + brd_SendDiagBlock(receiptData,1,IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + iuc_asynch_PrintControl |= 0x0F;*/ + + /*if (iuc_asynch_PrintControl) { + brd_SendDiagStr("->IUC ASYNCHPOS print data send: ",1); + vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0); + iuc_asynch_PrintControl = 0x00; + } else { + brd_SendDiagStr("->IUC ASYNCHPOS print data stored: ",1); + iuc_asynch_PrintControl = 0x01; + }*/ + //biox_delay_ms(750); + + //iuc_asynchpos_resetBuffers(0x01); + //iuc_asynchpos_command_close_Document(); + + //iuc_asynchpos_resetBuffers(0x02); + //iuc_asynchpos_command_print_Result(0x01); + } + + receiptData[0] = 0x50; + biox_CopyBlock(pData, uitmp + 2, receiptData, 1, uitmp2/*IUC_ASYNCHPOS_MAX_ARRAY_SIZE*/); + + brd_SendDiagStr("->IUC ASYNCHPOS receipt: ",0); + brd_SendDiagBlock(receiptData,1,IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + iuc_asynch_PrintControl |= 0x0F; + + /* else { + //receiptData[0] = 0x50; + //iuc_asynchpos_sub_initZero(receiptData,1); + brd_SendDiagStr("->IUC ASYNCHPOS receipt: ERROR. Receipt too large!",1); + iuc_asynch_PrintControl |= 0x0E; + } */ + /* else { + //iuc_asynchpos_resetBuffers(0x02); + iuc_asynchpos_command_print_Result(0x00); + }*/ + } + + //++iuc_print_counter; + + //if(asynchState == 0x04 && iuc_asynch_PrintControl == 0) { + //iuc_asynchpos_resetBuffers(0x01); + //iuc_asynchpos_resetBuffers(0x00); + //iuc_asynchpos_command_print_Result(0x01); + /*} /else { + //iuc_asynchpos_resetBuffers(0x02); + iuc_asynchpos_command_print_Result(0x01); + }*/ + //iuc_asynchpos_command_print_Result(0x01); + + /*while (uitmp2 > IUC_ASYNCHPOS_MAX_ARRAY_SIZE) { + biox_CopyBlock(pData, uitmp + 2, receiptData, 0, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + uitmp += IUC_ASYNCHPOS_MAX_ARRAY_SIZE; + uitmp2 -= IUC_ASYNCHPOS_MAX_ARRAY_SIZE; + vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0); + } + + //Rest des Packets + biox_CopyBlock(pData, uitmp + 2, receiptData, 0, uitmp2); + vmc_SendWithBuffer(receiptData,uitmp2,0x69,0); + + //iuc_asynchpos_resetBuffers(0x02); + iuc_asynchpos_command_print_Result(0x01);*/ + } + + uitmp = biox_FindStrInBufferInt("VoidResult",pData) | biox_FindStrInBufferInt("VOIDRESULT",pData); + if (uitmp) { + asynchState = 0x01; //There was a cancel. Relogin and try again. + uitmp = biox_FindStrInBufferInt("ERROR",pData); + if (uitmp) { + rxBuf[0] = 0x45; + rxBuf[1] = 0x56; + rxBuf[2] = 0x45; + vmc_SendWithBuffer(rxBuf,3,0x69,0); + } + + uitmp = biox_FindStrInBufferInt("REFUND",pData); + if (uitmp) { + rxBuf[0] = 0x45; + rxBuf[1] = 0x56; + rxBuf[2] = 0x52; + vmc_SendWithBuffer(rxBuf,3,0x69,0); + //TODO refund bill here. Should not trigger, but it might. + } + } + + uitmp = biox_FindStrInBufferInt("DocClosed",pData); + if (uitmp) { + asynchState = 0x01; //Transaction successful + + //if (VendRequest) + GWstate.VendRequest=0; + } + + + /*while (pData[uitmp] != 0x00) { //0x00 is the end marker + if (tagNameLength > 0x7F) { + //tagNameLength -= 0x80; + + for (uitmp2 = 0; uitmp2 < (tagNameLength - 0x80); ++uitmp2) { + tagName[uitmp2] = pData[uitmp + 1 + uitmp2]; + } + + //TODO Do something with the name here + + uitmp = uitmp2 + 1; + tagNameLength = pData[uitmp]; + + } else { + for (uitmp2 = 0; uitmp2 < tagNameLength; ++uitmp2) { + tagName[uitmp2] = pData[uitmp + 1 + uitmp2]; + } + + //TODO Do something with the name here + + uitmp = uitmp2 + 1; + + curElementLength = ((UINT) pData[uitmp] << 8) | pData[uitmp]; + + for (uitmp2 = 0; uitmp2 < curElementLength; ++uitmp2) { + curElement[uitmp2] = pData[uitmp + 1 + uitmp2]; + } + + //TODO Do something with the data here + + uitmp = uitmp2 + 1; + tagNameLength = pData[uitmp]; + } + }*/ + +} + +void iuc_asynchpos_startCommunication() { + unsigned char uctmp = EOT; + + biox_Usart3_ClearRecBuffer(); + biox_Usart3_SendBlock(&uctmp,1); +} + +void iuc_asynchpos_init() { + //TODO: CHANGE THIS LATER ON! TEST ONLY! + #ifdef IUC_ASYCHNPOS_TESTMODE + unsigned char APAK[] = "9D547268976ADE1BBB39DE90F3A449E5"; //9D547268976ADE1BBB39DE90F3A449E5 + unsigned char TID[] = "T-LT-OPT-01"; + #endif + unsigned char timeStart[] = "2018-01-01 00:00:00"; + unsigned int uitmp = 0; + + iuc_asynchpos_sub_initArray(asynchBill.time,20); + biox_CopyBlock(timeStart,0,asynchBill.time,0,biox_StrLen(timeStart)); + //iuc_asynchpos_sub_initArray(asynchBill.id,20); + //iuc_asynchpos_sub_initArray(asynchBill.docNr,32); + iuc_asynchpos_sub_clear_message(0x01); + asynchState = 0; + iuc_asynch_keepAlive = 0x00; + iuc_asynch_PrintControl = 0x00; + + tableCreated = 0x00; + + #ifdef IUC_ASYCHNPOS_TESTMODE + iuc_asynchpos_setTerminalAPAK(APAK, biox_StrLen(APAK)); + iuc_asynchpos_setTerminalID(TID, biox_StrLen(TID)); + #endif + + ENQrecieved = 0x00; + timeInitalized = GWglobTime.SecOfDay; + asynchSessionClosed = 0x00; + iuc_asynch_PRNrecieved = 0x00; + iuc_asynchpos_crc_old = 0; + iucAsynchpoxDataContext = 0x00; + iuc_asynch_printTimeout = IUC_ASYNCHPOS_PRINTTIMOUT; + + brd_switch_RS3(RS3SW2IUC); + biox_Usart3_ClearRecBuffer(); + biox_Usart3Ini(USART_Mode_Int, USART_Baud19200, USART_data8, USART_stop1, USART_parity_none); + biox_delay_ms(1); + + /* + Apak: 9D547268976ADE1BBB39DE90F3A449E5 + Terminal id: T-LT-OPT-01 + */ + + for (uitmp = 0; uitmp < IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE; ++uitmp) + terminalAPAK[uitmp] = Conf.APAK_backup[uitmp]; + + //biox_CopyBlock(Conf.APAK_backup,0,terminalAPAK,0,IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE); + + iuc_asynchpos_resetBuffers(0x00); + iuc_asynchpos_startCommunication(); +} + +unsigned char iuc_asynchpos_recieve_serial(unsigned char waitforACK) { + unsigned int rxLength = 0; + unsigned int uitemp = 0; + unsigned int uitemp2 = 0; + unsigned char rxData_[IUC_ASYNCHPOS_MAX_ARRAY_SIZE]; +// unsigned char messageReturnData[100]; + unsigned char messageLength_[8]; + unsigned char messageCounter_[8]; + unsigned char chksum = 0x00; + unsigned char uctmp = 0x00; + unsigned char resetBuffers = 0x00; + //unsigned int rxCounter = messageLength; + unsigned char fullPackage = 0x00; + unsigned char rxBuf[8]; + + //if (biox_Usart2_NewTelegram()) { + //brd_SendDiagStr("<----- IUC ASYNCHPOS",1); + //get datastream from buffer + //iuc_asynchpos_sub_initArray(rxData_, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + rxLength = biox_Usart3BuffSize(); + + rxData_[0] = 0xFF; + + if (rxLength > 0) { + brd_SendDiagStr("<----- IUC ASYNCHPOS",1); + + if (rxLength >= IUC_ASYNCHPOS_MAX_ARRAY_SIZE) { + brd_SendDiagStr("->IUC ASYNCHPOS rx buffer overflow!",1); + biox_Usart3_ClearRecBuffer(); + return 8; + } + + brd_SendDiagStr("->IUC ASYNCHPOS Data recieved, ISMAS locked!",1); + ism_lock(); + timeHoldISMAS = GWglobTime.SecOfDay; + + //iuc_asynchpos_sub_initArray(rxData_, rxLength); + biox_Usart3_GetRecBuffer(rxData_,rxLength); + + if (GWstate.DebugLevel & 0x10) + { + biox_itoa(rxLength,messageLength_); + brd_SendDiagStr("->IUC ASYNCHPOS recieved: ",0); + brd_SendDiagBlock(messageLength_,1,8); + brd_SendDiagStr("->IUC ASYNCHPOS rx data: ",0); + brd_SendDiagBlock(rxData_,1,rxLength); + + if (rxLength <= 1) + brd_SendDiagStr("->IUC ASYNCHPOS Single Byte recieved.",1); + } + + for (uitemp = 0; uitemp < rxLength/* && resetBuffers == 0x00*/; ++uitemp) { + if (rxData_[uitemp] == EOT || (!ENQrecieved && rxData_[uitemp] == ENQ)) {//Either we did not initialize everysthing yet OR the PT wants to send something. + if (uitemp == 0 || (uitemp > 0 && (rxData_[uitemp-1] != ETX1 || rxData_[uitemp-1] != ETX2))) { + if (rxData_[uitemp] != ENQ) { + resetBuffers = 0x01; + } else { + resetBuffers = 0x02; + + brd_SendDiagStr("->IUC ASYNCHPOS ENQ recieved, ISMAS unlocked!",1); + ism_unlock(); + } + } + } + + if (rxData_[uitemp] == ETX1 || (rxData_[uitemp] == ETX2)) + fullPackage = 0x01; + } + + if (resetBuffers) { //Does the terminal want to send? / Did we receive an EOT? + /*ENQrecieved = 0x01; + rxCounter = 0; + messageLength = 0; + iuc_asynchpos_sub_initArray(rxData, IUC_ASYNCHPOS_MAX_ARRAY_SIZE);*/ + /*if (ENQrecieved == 0) { + brd_SendDiagStr("-> IUC ANSNYCHPOS initialized",1); + } else { + brd_SendDiagStr("->IUC ASYNCHPOS listening to terminal",1); + }*/ + + if (resetBuffers >= 0x01) { + iuc_asynchpos_resetBuffers(0x01); + } else { + iuc_asynchpos_resetBuffers(0x00); + } + + if (rxLength > 1) { + //biox_Usart2_ClearRecBuffer(); + uctmp = NAK; + biox_Usart3_SendBlock(&uctmp,1); + } + + //iuc_asynchpos_sub_initArray(messageData, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + return 2; //Yes, it does. / Yes, we did. + } else + + if (ENQrecieved && fullPackage/* && biox_Usart2_NewTelegram()*/) { + + brd_SendDiagStr("->IUC ASYNCHPOS Full packet recieved, ISMAS unlocked!",1); + ism_unlock(); + + //brd_SendDiagStr("->IUC ASYNCHPOS Data recieved.",1); + //calculate chksum + for (uitemp = 1; uitemp < (rxLength - 1) && (rxData_[uitemp - 1] != ACK1 || rxData_[uitemp - 1] != ACK2); ++uitemp) { + chksum ^= rxData_[uitemp]; + } + + if (chksum != rxData_[uitemp]) { + biox_Usart3_ClearRecBuffer(); + uctmp = NAK; + biox_Usart3_SendBlock(&uctmp,1); + brd_SendDiagStr("->IUC ASYNCHPOS Sending NACK (Checksum mismatch).",1); + return 3; //checksum mismatch + } else { + biox_Usart3_ClearRecBuffer(); + if (rxData_[rxLength - 2] == ETX1) { + uctmp = ACK1; + biox_Usart3_SendBlock(&uctmp,1); + brd_SendDiagStr("->IUC ASYNCHPOS Sending ACK1.",1); + //iucAsynchpoxDataContext = 0x01; + } else if (rxData_[rxLength - 2] == ETX2) { + uctmp = ACK2; + biox_Usart3_SendBlock(&uctmp,1); + brd_SendDiagStr("->IUC ASYNCHPOS Sending ACK2.",1); + //iucAsynchpoxDataContext = 0x00; + } else { + uctmp = NAK; + biox_Usart3_SendBlock(&uctmp,1); + brd_SendDiagStr("->IUC ASYNCHPOS Sending NACK (Wrong Byte).",1); + return 4; //We got something wrong and it's causing an error + } + } + + /*if (iuc_asynchpos_crc_old == rxData_[rxLength - 2]) { //We recieved that package already + iuc_asynchpos_crc_old = 0; + brd_SendDiagStr("->IUC ASYNCHPOS EXCEPTION: double package!",1); + + brd_SendDiagStr("->IUC ASYNCHPOS rx data: ",0); + brd_SendDiagBlock(rxData_,1,rxLength); + return 5; + } + + iuc_asynchpos_crc_old = rxData_[rxLength - 2];*/ + + //reformatting according to specs + for (uitemp = 0; uitemp < rxLength; ++uitemp) { + if (rxData_[uitemp] == DLE) { + rxData_[uitemp] = rxData_[uitemp + 1] - 0x30; + for (uitemp2 = uitemp + 2; uitemp2 < rxLength; ++uitemp2) { + rxData_[uitemp2 - 1] = rxData_[uitemp2]; + } + --rxLength; + } + } + + //Check if we received a logical ACK or NACK + if (rxCounter == 0) { + if (rxData_[3] == 0x0F) { + //NACK recieved, resend message + brd_SendDiagStr("-> IUC ANSNYCHPOS Message NOT ackknowledged",1); + if (asynchState < 0x02) { + iuc_asynchpos_sub_initArray(rxBuf,8); + rxBuf[0] = 0x45; + rxBuf[1] = 0x00; + rxBuf[2] = 0xFF; + vmc_SendWithBuffer(rxBuf,3,0x69,0); + } + return 0; + } + + if (rxData_[3] == 0x0A) { + //ACK recieved, do nothing + brd_SendDiagStr("-> IUC ANSNYCHPOS Message acknowledged",1); + if (asynchState < 0x02) { + asynchState = 0x02; + iuc_asynchpos_sub_initArray(rxBuf,8); + rxBuf[0] = 0x45; + rxBuf[1] = 0x00; + rxBuf[2] = 0x00; + vmc_SendWithBuffer(rxBuf,3,0x69,0); + } + return 0; + } + } + + if (rxCounter == 0) { + messageLength = ((UINT) rxData_[1] << 8) | rxData_[2]; + + if (GWstate.DebugLevel & 0x10) + { + biox_itoa(messageLength,messageLength_); + brd_SendDiagStr("->IUC ASYNCHPOS message length: ",0); + brd_SendDiagBlock(messageLength_,1,8); + } + + if (messageLength + 1 < IUC_ASYNCHPOS_MAX_RX_MESSAGE_SIZE) { + iuc_asynchpos_sub_initArray(messageData, /*messageLength + 1*/ IUC_ASYNCHPOS_MAX_RX_MESSAGE_SIZE); + } else { + messageLength = 0; + brd_SendDiagStr("->IUC ASYNCHPOS message too long!",0); + //iuc_asynchpos_sub_initArray(messageData, IUC_ASYNCHPOS_MAX_RX_MESSAGE_SIZE); + iuc_asynchpos_sub_initArray(rxBuf,8); + rxBuf[0] = 0x45; + rxBuf[1] = 0x00; + rxBuf[2] = 0xFF; + vmc_SendWithBuffer(rxBuf,3,0x69,0); + iuc_asynchpos_resetBuffers(0x00); + return 6; + } + } + + if (messageLength > 0) { + //add to rxData + uitemp = 1; + //while (rxData_[uitemp] != ETX1 && rxData_[uitemp] != ETX2 && rxData_[uitemp] != STX) { + while (/*rxData_[uitemp] != 0x02 && rxData_[uitemp] != 0x03*/uitemp < (rxLength - 2)) { //removing the STX, ETX, the checksum and additional zero at the end + rxAsynchData[(uitemp - 1) + rxCounter] = rxData_[uitemp]; + ++uitemp; + } + + rxCounter += uitemp - 1; + + if (GWstate.DebugLevel & 0x10) + { + biox_itoa(rxCounter,messageCounter_); + brd_SendDiagStr("->IUC ASYNCHPOS message counter: ",0); + brd_SendDiagBlock(messageCounter_,1,8); + + brd_SendDiagStr("->IUC ASYNCHPOS recieve buffer: ",0); + brd_SendDiagBlock(rxAsynchData,1,rxCounter); + } + + //NEXT Telegram + if (/*messageLength != 0 && messageLength <= (rxCounter + 5)*/ rxCounter >= (messageLength - 1)) { + if (GWstate.DebugLevel & 0x10) + { + biox_itoa(messageLength,messageLength_); + brd_SendDiagStr("->IUC ASYNCHPOS message length FINAL: ",0); + brd_SendDiagBlock(messageLength_,1,8); + + biox_itoa(rxCounter,messageCounter_); + brd_SendDiagStr("->IUC ASYNCHPOS message counter FINAL: ",0); + brd_SendDiagBlock(messageCounter_,1,8); + } + + if (rxAsynchData[2] != 0x0A) { + //iuc_asynchpos_sub_initArray(messageReturnData, 100);; //iuc_asynchpos_sub_initArray(messageData, messageLength + 1);//iuc_asynchpos_sub_initArray(messageReturnData, IUC_ASYNCHPOS_MAX_MESSAGE_SIZE); + + //if (!iuc_asynchpos_sub_confirm_message(messageData, IUC_ASYNCHPOS_MAX_ARRAY_SIZE))) { + //Send ACK to terminal + //iuc_asynchpos_resetBuffers(0x02); + + /*for (uitemp = 0; uitemp < rxAsynchData[11] + 9; ++uitemp) { + messageReturnData[uitemp + 3] = rxAsynchData[uitemp + 3]; + } + ++uitemp; + + //messageReturnData[0] = 0x02; + messageReturnData[0] = uitemp & (0xFF00); + messageReturnData[1] = uitemp & (0x00FF); + messageReturnData[2] = 0x0A;*/ + //messageReturnData[uitemp + 2] = ETX1; + + //calculate chksum + /*for (uitemp2 = 1; uitemp2 < uitemp + 2; ++uitemp2) { + messageReturnData[uitemp + 3] ^= messageReturnData[uitemp]; + }*/ + + //biox_Usart2_SendBlock(messageReturnData,uitemp + 4); + + //brd_SendDiagStr("->IUC ASYNCHPOS message ACKNOWLEDGE: ",0); + //brd_SendDiagBlock(messageReturnData,1,uitemp + 1); + //iuc_asynchpos_send_serial(messageReturnData,uitemp + 1,0x01,0x01); + + for (uitemp = 0; uitemp < rxCounter - (12 + rxAsynchData[11]); ++uitemp) { + messageData[uitemp] = rxAsynchData[uitemp + (12 + (UINT) rxAsynchData[11])]; + + if (messageData[uitemp] == 0x00) + messageData[uitemp] = 0x30; + } + + uitemp = biox_FindStrInBufferInt("PrintReceipt",messageData) | biox_FindStrInBufferInt("PRINTRECEIPT",messageData) + | biox_FindStrInBufferInt("AuthorizationResult",messageData) | biox_FindStrInBuffer("AUTHORIZATIONRESULT",messageData); + + if (uitemp) { + if (biox_FindStrInBufferInt("PrintReceipt",messageData) | biox_FindStrInBufferInt("PRINTRECEIPT",messageData)) { + biox_CopyBlock(rxAsynchData,3,terminalSignature,0,8); + } else { + biox_CopyBlock(rxAsynchData,3,terminalSignature,8,8); + } + } else { + iuc_asynchpos_sub_sendACK(0); + } + + if (GWstate.DebugLevel & 0x10) + { + brd_SendDiagStr("->IUC ASYNCHPOS full message: ",0); + brd_SendDiagBlock(messageData,1,rxCounter - (12 + ((UINT) rxAsynchData[11]))); + } + + iuc_asynchpos_handleMessage(messageData); + brd_SendDiagStr("-> IUC ANSNYCHPOS Data handled",1); + } + + /*brd_SendDiagStr("->IUC ASYNCHPOS full message: ",0); + brd_SendDiagBlock(messageData,1,rxCounter - (12 + rxAsynchData[11])); + + iuc_asynchpos_handleMessage(messageData); + brd_SendDiagStr("-> IUC ANSNYCHPOS Data handled",1);*/ + iuc_asynchpos_resetBuffers(0x00); + } + } + + return 1; //Still busy + } + } //else { + + if (ENQrecieved == 0 && (timeInitalized + 10) < GWglobTime.SecOfDay) { + brd_SendDiagStr("->IUC ASYNCHPOS waiting for initialization",1); + biox_Usart3_ClearRecBuffer(); + iuc_asynchpos_init(); + return 1; + } + + if (ism_islocked() && (timeHoldISMAS - GWglobTime.SecOfDay >= 1800)) + { + brd_SendDiagStr("->IUC ASYNCHPOS ISMAS holding timeout, ISMAS unlocked!",1); + ism_unlock(); + } + + if (iuc_asynch_PrintControl == 0xFF) { + iuc_asynch_keepAlive = 0x00; + iuc_asynchpos_sub_sendACK(1); + biox_delay_ms(2); + iuc_asynchpos_sub_sendACK(2); + biox_delay_ms(2); + iuc_asynchpos_command_print_Result(0x01); + biox_delay_ms(2); + if (0x04 == asynchState) { //Was the authorization successful? + brd_SendDiagStr("->IUC ASYNCHPOS Sending YES receipt to VMC.",1); + vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0x10); //Yes + } else { + brd_SendDiagStr("->IUC ASYNCHPOS Sending NO receipt to VMC.",1); + vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0x20); //No + } + iuc_asynch_PrintControl = 0; + + //VendRequest=0; + return 1; + } + + /*if (iuc_asynch_PrintControl == 0xFE) { + iuc_asynch_keepAlive = 0x00; + iuc_asynchpos_sub_initArray(rxBuf,8); + rxBuf[0] = 0x45; + rxBuf[1] = 0x00; + rxBuf[2] = 0x00; + vmc_SendWithBuffer(rxBuf,8,0x69,0); + iuc_asynch_PrintControl = 0; + return 1; + }*/ + + if (rxData_[0] != STX/* && rxLength > 0 && rxData_[0] != 0xFF*/) { + //brd_SendDiagStr("->IUC ASYNCHPOS No STX recieved, ISMAS unlocked, sending NACK!",1); + if (rxData_[0] != 0xFF) { + brd_SendDiagStr("->IUC ASYNCHPOS No STX recieved, ISMAS unlocked!",1); + ism_unlock(); + } + biox_Usart3_ClearRecBuffer(); + //uctmp = NAK; + //biox_Usart3_SendBlock(&uctmp,1); + } + + //Workaround for our terminal problem, which, sometimes, fails to send a Print Result + /*if (0xF0 == iuc_asynch_PrintControl) { + if (0x00 == iuc_asynch_printTimeout) { + iuc_asynchpos_sub_initArray(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + receiptData[0] = 0x50; + if (0x04 == asynchState) { //Was the authorization successful? + vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0x10); //Yes + } else { + vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0x20); //No + } + iuc_asynch_printTimeout = IUC_ASYNCHPOS_PRINTTIMOUT; + iuc_asynch_PrintControl = 0; + } else { + --iuc_asynch_printTimeout; + biox_delay_ms(1); + } + }*/ + //} + + if (waitforACK) + return 8; + return 0; +} + +//messagees + +void iuc_asynchpos_sub_synchTime() { + UINT uitemp = 0; + + //unsigned char timeStart[] = "2017-12-19 13:40:00"; + //biox_CopyBlock(timeStart,0,asynchBill.time,0,biox_StrLen(timeStart)); + + for (uitemp = 0; uitemp < 6; ++uitemp) { + switch (uitemp) { + case 0: //year + asynchBill.time[2] = (GWglobTime.year / 10) + 0x30;; + asynchBill.time[3] = (GWglobTime.year % 10) + 0x30; + + /*#ifdef IUC_ASYCHNPOS_TESTMODE + asynchBill.time[2] = 0x31; + asynchBill.time[3] = 0x39; + #endif*/ + break; + case 1: //month + asynchBill.time[5] = (GWglobTime.month / 10) + 0x30;; + asynchBill.time[6] = (GWglobTime.month % 10) + 0x30; + + /*#ifdef IUC_ASYCHNPOS_TESTMODE + asynchBill.time[5] = 0x31; + asynchBill.time[6] = 0x32; + #endif*/ + break; + case 2: //day + asynchBill.time[8] = (GWglobTime.dayOfMon / 10) + 0x30;; + asynchBill.time[9] = (GWglobTime.dayOfMon % 10) + 0x30; + + /*#ifdef IUC_ASYCHNPOS_TESTMODE + asynchBill.time[8] = 0x30; + asynchBill.time[9] = 0x32; + #endif*/ + break; + case 3: //hours + asynchBill.time[11] = (GWglobTime.hour / 10) + 0x30;; + asynchBill.time[12] = (GWglobTime.hour % 10) + 0x30; + + /*#ifdef IUC_ASYCHNPOS_TESTMODE + asynchBill.time[11] = 0x31; + asynchBill.time[12] = 0x32; + #endif*/ + break; + + case 4: //minutes + asynchBill.time[14] = (GWglobTime.min / 10) + 0x30;; + asynchBill.time[15] = (GWglobTime.min % 10) + 0x30; + + /*#ifdef IUC_ASYCHNPOS_TESTMODE + asynchBill.time[14] = 0x30; + asynchBill.time[15] = 0x30; + #endif*/ + break; + case 5: //seconds + asynchBill.time[17] = (GWglobTime.sec / 10) + 0x30;; + asynchBill.time[18] = (GWglobTime.sec % 10) + 0x30; + break; + } + } +} + +void iuc_asynchpos_command_ping_terminal() { + UCHAR message[IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE]; + UCHAR packetType = 0x00; + UINT uitemp = 0; + UCHAR command[] = "Ping"; + UCHAR tagName[] = "Time"; +// UCHAR tagValue[] = "2017-12-19 13:40:00"; + + //Constructing the message + iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE); + + //biox_CopyBlock(UCHAR *src, UINT srcPos, UCHAR *dest, UINT destPos, UINT len); + uitemp = (UCHAR) biox_StrLen(command); + message[0] = (UCHAR) uitemp + 0x80; //constructed element, tag name length + biox_CopyBlock(command,0,message,1,uitemp); //tag name + ++uitemp; + + message[uitemp] = (UCHAR) biox_StrLen(tagName);//data element, tag name length + ++uitemp; + biox_CopyBlock(tagName,0,message,uitemp, biox_StrLen(tagName));// tag name + uitemp += (1 + biox_StrLen(tagName)); + + iuc_asynchpos_sub_synchTime(); + message[uitemp] = (UCHAR) biox_StrLen(asynchBill.time);//value length + ++uitemp; + biox_CopyBlock(asynchBill.time,0,message,uitemp, biox_StrLen(asynchBill.time));//value + + uitemp += biox_StrLen(asynchBill.time)/* + 1*/; + + iuc_asynchpos_send(packetType,message,uitemp,0x00); +} + +//80 - d +void iuc_asynchpos_command_Login() { //Kasse registrieren + UCHAR message[IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE]; + UCHAR packetType = 0x00; + UINT uitemp = 0; + UCHAR command[] = "Login"; + UCHAR tagName[] = "Time"; + //UCHAR tag2Name[] = "IdleText"; + UCHAR tag3Name[] = "Flags"; + UCHAR tag3Value[] = "AP3"; + + //Constructing the message + iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE); + + uitemp = (UCHAR) biox_StrLen(command); + message[0] = (UCHAR) uitemp + 0x80; //constructed element, tag name length + biox_CopyBlock(command,0,message,1,uitemp); //tag name + ++uitemp; + + message[uitemp] = (UCHAR) biox_StrLen(tagName);//data element, tag name length + ++uitemp; + biox_CopyBlock(tagName,0,message,uitemp, biox_StrLen(tagName));// tag name + uitemp += (1 + biox_StrLen(tagName)); + + //Time + iuc_asynchpos_sub_synchTime(); + message[uitemp] = (UCHAR) biox_StrLen(asynchBill.time);//value length + ++uitemp; + biox_CopyBlock(asynchBill.time,0,message,uitemp, biox_StrLen(asynchBill.time));//value + uitemp += biox_StrLen(asynchBill.time); + + //Flags + message[uitemp] = (UCHAR) biox_StrLen(tag3Name);//data element, tag name length + ++uitemp; + biox_CopyBlock(tag3Name,0,message,uitemp, biox_StrLen(tag3Name));// tag name + uitemp += (1 + biox_StrLen(tag3Name)); + + message[uitemp] = (UCHAR) biox_StrLen(tag3Value);//value length + ++uitemp; + biox_CopyBlock(tag3Value,0,message,uitemp, biox_StrLen(tag3Value));//value + + uitemp += biox_StrLen(tag3Value)/* + 1*/; + + iuc_asynchpos_send(packetType,message,uitemp,0x01); +} + +//81 - d +void iuc_asynchpos_command_Logout () { //Kassenschluss + UCHAR message[IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE]; + UCHAR packetType = 0x00; + UINT uitemp = 0; + UCHAR command[] = "Logout"; + UCHAR tagName[] = "Time"; + + //Constructing the message + iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE); + + uitemp = (UCHAR) biox_StrLen(command); + message[0] = (UCHAR) uitemp + 0x80; //constructed element, tag name length + biox_CopyBlock(command,0,message,1,uitemp); //tag name + ++uitemp; + + message[uitemp] = (UCHAR) biox_StrLen(tagName);//data element, tag name length + ++uitemp; + biox_CopyBlock(tagName,0,message,uitemp, biox_StrLen(tagName));// tag name + uitemp += (1 + biox_StrLen(tagName)); + + iuc_asynchpos_sub_synchTime(); + message[uitemp] = (UCHAR) biox_StrLen(asynchBill.time);//value length + ++uitemp; + biox_CopyBlock(asynchBill.time,0,message,uitemp, biox_StrLen(asynchBill.time));//value + + uitemp += biox_StrLen(asynchBill.time)/* + 1*/; + + iuc_asynchpos_send(packetType,message,uitemp,0x01); + asynchState = 0x00; +} + +//54 - d +void iuc_asynchpos_command_authorize(unsigned int vkPreis) { + UCHAR message[IUC_ASYNCHPOS_MAX_ARRAY_SIZE]; + UCHAR packetType = 0x00; + UINT uitemp = 0; + UCHAR command[] = "Authorize"; + UCHAR tag1Name[] = "Amount"; + UCHAR tag2Name[] = "Cash"; + UCHAR tag3Name[] = "Currency"; + UCHAR tag4Name[] = "DocNr"; + UCHAR tag5Name[] = "Time"; + UCHAR tag6Name[] = "Lang"; + UCHAR tag1Value[10]; + UCHAR tag2Value[] = "0"; + UCHAR tag3Value[] = "978"; + UCHAR tag6Value[] = "lt"; + UINT vkPreis_ = vkPreis; + + iuc_asynch_PRNrecieved = 0; + + //Constructing the message + iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + iuc_asynchpos_sub_initArray(tag1Value,10); + + uitemp = (UCHAR) biox_StrLen(command); + message[0] = (UCHAR) uitemp + 0x80; //constructed element, tag name length + biox_CopyBlock(command,0,message,1,uitemp); //tag name + ++uitemp; + + //Amount + message[uitemp] = (UCHAR) biox_StrLen(tag1Name);//data element, tag name length + ++uitemp; + biox_CopyBlock(tag1Name,0,message,uitemp, biox_StrLen(tag1Name));// tag name + uitemp += (1 + biox_StrLen(tag1Name)); + + biox_itoa(vkPreis_,tag1Value); + message[uitemp] = (UCHAR) biox_StrLen(tag1Value);//value length + ++uitemp; + biox_CopyBlock(tag1Value,0,message,uitemp, biox_StrLen(tag1Value));//value + uitemp += (/*1 + */biox_StrLen(tag1Value)); + + //Cash + message[uitemp] = (UCHAR) biox_StrLen(tag2Name);//data element, tag name length + ++uitemp; + biox_CopyBlock(tag2Name,0,message,uitemp, biox_StrLen(tag2Name));// tag name + uitemp += (1 + biox_StrLen(tag2Name)); + + message[uitemp] = (UCHAR) biox_StrLen(tag2Value);//value length + ++uitemp; + biox_CopyBlock(tag2Value,0,message,uitemp, biox_StrLen(tag2Value));//value + uitemp += (/*1 + */biox_StrLen(tag2Value)); + + //Currency + message[uitemp] = (UCHAR) biox_StrLen(tag3Name);//data element, tag name length + ++uitemp; + biox_CopyBlock(tag3Name,0,message,uitemp, biox_StrLen(tag3Name));// tag name + uitemp += (1 + biox_StrLen(tag3Name)); + + message[uitemp] = (UCHAR) biox_StrLen(tag3Value);//value length + ++uitemp; + biox_CopyBlock(tag3Value,0,message,uitemp, biox_StrLen(tag3Value));//value + uitemp += (/*1 + */biox_StrLen(tag3Value)); + + //DocNr + message[uitemp] = (UCHAR) biox_StrLen(tag4Name);//data element, tag name length + ++uitemp; + biox_CopyBlock(tag4Name,0,message,uitemp, biox_StrLen(tag4Name));// tag name + uitemp += (1 + biox_StrLen(tag4Name)); + + //biox_ltoa(asynchBill.docuNr,asynchBill.docNr); + //++asynchBill.docuNr; + + generate_UniqueTransNr(asynchBill.docNr); + + message[uitemp] = (UCHAR) biox_StrLen(asynchBill.docNr);//value length + ++uitemp; + biox_CopyBlock(asynchBill.docNr,0,message,uitemp, biox_StrLen(asynchBill.docNr));//value + + uitemp += biox_StrLen(asynchBill.docNr)/* + 1*/; + + //Time + message[uitemp] = (UCHAR) biox_StrLen(tag5Name);//data element, tag name length + ++uitemp; + biox_CopyBlock(tag5Name,0,message,uitemp, biox_StrLen(tag5Name));// tag name + uitemp += (1 + biox_StrLen(tag5Name)); + + iuc_asynchpos_sub_synchTime(); + message[uitemp] = (UCHAR) biox_StrLen(asynchBill.time);//value length + ++uitemp; + biox_CopyBlock(asynchBill.time,0,message,uitemp, biox_StrLen(asynchBill.time));//value + + uitemp += biox_StrLen(asynchBill.time)/* + 1*/; + + //Language + message[uitemp] = (UCHAR) biox_StrLen(tag6Name);//data element, tag name length + ++uitemp; + biox_CopyBlock(tag6Name,0,message,uitemp, biox_StrLen(tag6Name));// tag name + uitemp += (1 + biox_StrLen(tag6Name)); + + message[uitemp] = (UCHAR) biox_StrLen(tag6Value);//value length + ++uitemp; + biox_CopyBlock(tag6Value,0,message,uitemp, biox_StrLen(tag6Value));//value + uitemp += biox_StrLen(tag6Value)/* + 1*/; + + iuc_asynchpos_send(packetType,message,uitemp,0x00); +} + +//73 - d +void iuc_asynchpos_command_cancel_authorize() { + UCHAR message[IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE]; + UCHAR packetType = 0x00; + UINT uitemp = 0; + UCHAR command[] = "AuthorizationCancelled"; + UCHAR tagName[] = "ID"; + + //Constructing the message + iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE); + + uitemp = biox_StrLen(command); + message[0] = (UCHAR) uitemp + 0x80; //constructed element, tag name length + biox_CopyBlock(command,0,message,1,uitemp); //tag name + + if (asynchBill.id[0] != 0x00) { + ++uitemp; + message[uitemp] = (UCHAR) biox_StrLen(tagName);//data element, tag name length + ++uitemp; + biox_CopyBlock(tagName,0,message,uitemp, biox_StrLen(tagName));// tag name + uitemp += (1 + biox_StrLen(tagName)); + + message[uitemp] = (UCHAR) biox_StrLen(asynchBill.id);//value length + ++uitemp; + biox_CopyBlock(asynchBill.id,0,message,uitemp, biox_StrLen(asynchBill.id));//value + + uitemp += biox_StrLen(asynchBill.id)/* + 1*/; + } + + iuc_asynchpos_send(packetType,message,uitemp,0x00); +} + +//77 - d +void iuc_asynchpos_command_close_Document(unsigned char isStorno) { //Finalize sale + UCHAR message[IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE]; + UCHAR packetType = 0x00; + UINT uitemp = 0; + UCHAR command[] = "DocClosed"; + UCHAR tagName[] = "DocNr"; + UCHAR tag2Name[] = "AuthID"; + + //Constructing the message + iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE); + + uitemp = biox_StrLen(command); + message[0] = (UCHAR) uitemp + 0x80; //constructed element, tag name length + biox_CopyBlock(command,0,message,1,uitemp); //tag name + ++uitemp; + + //DocNr + message[uitemp] = (UCHAR) biox_StrLen(tagName);//data element, tag name length + ++uitemp; + biox_CopyBlock(tagName,0,message,uitemp, biox_StrLen(tagName));// tag name + uitemp += (1 + biox_StrLen(tagName)); + + message[uitemp] = (UCHAR) biox_StrLen(asynchBill.docNr);//value length + ++uitemp; + biox_CopyBlock(asynchBill.docNr,0,message,uitemp, biox_StrLen(asynchBill.docNr));//value + uitemp += biox_StrLen(asynchBill.docNr); + + //AuthID + if (!isStorno) { + message[uitemp] = (UCHAR) biox_StrLen(tag2Name);//data element, tag name length + ++uitemp; + biox_CopyBlock(tag2Name,0,message,uitemp, biox_StrLen(tag2Name));// tag name + uitemp += (1 + biox_StrLen(tag2Name)); + + message[uitemp] = (UCHAR) biox_StrLen(asynchBill.id);//value length + ++uitemp; + biox_CopyBlock(asynchBill.id,0,message,uitemp, biox_StrLen(asynchBill.id));//value + uitemp += biox_StrLen(asynchBill.id)/* + 1*/; + } + + iuc_asynchpos_send(packetType,message,uitemp,0x00); +} + +void iuc_asynchpos_handleCommand(unsigned char command, unsigned char status) { + //r - registration, a - authorization, c - cancel, s - storno, k - kassenschnitt + UCHAR tempBuf[3]; + UCHAR rxBuf[8]; +// UINT uitemp = 0; +UINT uitmp= 700; + + tempBuf[0] = 0x00; + tempBuf[1] = 0x00; + tempBuf[2] = 0x00; + + timeHoldISMAS = GWglobTime.SecOfDay; + + iuc_asynchpos_sub_initArray(rxBuf,8); + //iuc_asynchpos_resetBuffers(0x00); + + switch (command) { + case 0x72: //registration + //iuc_asynchpos_init(); + asynchState = 0x01; + iuc_asynchpos_command_Login(); + GWstate.VendRequest=1; + break; + case 0x61: //authorisation + iuc_asynch_keepAlive = 0x01; + iuc_asynch_PrintControl = 0; + iuc_asynchpos_sub_clear_message(0x01); + //VendRequest=1; + iuc_asynchpos_resetBuffers(0x00); + ///#ifdef IUC_ASYCHNPOS_TESTMODE + //iuc_asynchpos_command_authorize(uitmp); + //#else + iuc_asynchpos_command_authorize(Vend.Amount); + //#endif + break; + case 0x63: //cancel + case 0x73: //storno + /*if (asynchState <= 0x02 != 0) { //Authorization result recieved? + iuc_asynchpos_command_cancel_authorize(); + } else {*/ + iuc_asynchpos_command_close_Document(0x01); + //} + iuc_asynch_keepAlive = 0x00; + //VendRequest=0; + break; + case 0x6B: //kassenschnitt + iuc_asynchpos_command_Logout(); + break; + case 0x62: //get last bill + //iuc_zvt_getLastBill(tempBuf); + break; + case 0x01: iuc_asynchpos_command_close_Document(0x00); + iuc_asynch_keepAlive = 0x00; + //VendRequest=0; + break; + case 0x70: iuc_asynchpos_command_ping_terminal(); + break; + default: + break; + } +} + +int iuc_asynchpos_checkTime() { + int retVal = 0; + + if ((GWglobTime.hour == 0) && asynchSessionClosed != 0x00) { + asynchSessionClosed = 0x00; + retVal = 1; + } else if ((GWglobTime.hour == 1) && asynchSessionClosed == 0x00) { + iuc_asynchpos_command_Logout(); + retVal = 1; + asynchSessionClosed = 0x01; + } else if ((GWglobTime.hour == 2) && asynchSessionClosed == 0x01) { + iuc_asynchpos_command_Login(); + retVal = 1; + asynchSessionClosed = 0x02; + } + + return retVal; +} + +unsigned char iuc_asynchpos_getIsSaleRunning() { + + //Print, when idle + /*if (iuc_print_counter && asynchState == 0x01) { + iuc_asynchpos_command_print_Result(0x01); + --iuc_print_counter; + return 1; + }*/ + + return iuc_asynch_keepAlive; +} + + +#endif diff --git a/main/cc_iuc_asynchpos.h b/main/cc_iuc_asynchpos.h new file mode 100755 index 0000000..628572e --- /dev/null +++ b/main/cc_iuc_asynchpos.h @@ -0,0 +1,113 @@ +#ifndef CC_IUC_ASYNCHPOS_H +#define CC_IUC_ASYNCHPOS_H + +/* + * cc_iuc_asynchpos.c + * + * Created: 21.11.2017 + * Author: Matthias + */ + +#include +#include + +//#define IUC_ASYCHNPOS_TESTMODE 1 + +#define IUC_ASYNCHPOS_COINCOIDE_H 0x09 +#define IUC_ASYNCHPOS_COINCOIDE_L 0x78 +#define IUC_ASYNCHPOS_MAX_ARRAY_SIZE 1024 +#define IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE 300 +#define IUC_ASYNCHPOS_MAX_RX_MESSAGE_SIZE 10000 // 17000 +#define IUC_ASYNCHPOS_MIN_PACKET_SIZE 16 +#define IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE 32 +#define IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE 16 +#define IUC_ASYNCHPOS_POLYNOME 0xedb88320 // 0x04C11DB7 +#define IUC_ASYNCHPOS_POLYNOME_INITIAL 0 // 0xFFFFFFFF +#define IUC_ASYNCHPOS_PRINTTIMOUT 1000 +//#define IUC_ASYNCHPOS_RECEIPT_LENGTH 16384 + +#define STX 0x01 +#define ETX1 0x02 +#define ETX2 0x03 +#define EOT 0x04 +#define ENQ 0x05 +#define ACK1 0x06 +#define ACK2 0x07 +#define DLE 0x10 +#define NAK 0x15 + +unsigned static char terminalID[IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE]; +unsigned static char terminalAPAK[IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE]; +unsigned static char rxAsynchData[IUC_ASYNCHPOS_MAX_RX_MESSAGE_SIZE]; +unsigned static char terminalSignature[16]; +//unsigned static char messageData[IUC_ASYNCHPOS_MAX_ARRAY_SIZE]; +unsigned static char receiptData[IUC_ASYNCHPOS_MAX_ARRAY_SIZE + 1]; +unsigned static char txAsynchData[IUC_ASYNCHPOS_MAX_ARRAY_SIZE]; +unsigned static char ENQrecieved; +unsigned static int rxCounter; +unsigned static int messageLength; +unsigned static long timeInitalized; +unsigned static long timeHoldISMAS; +unsigned static long crcTable[256]; +unsigned static char tableCreated; +unsigned static int asynchState; +unsigned static char asynchSessionClosed; +unsigned static char iuc_asynch_PRNrecieved; +unsigned static char iuc_asynch_keepAlive; +unsigned static char iuc_asynch_PrintControl; +unsigned static char iuc_asynchpos_crc_old; +unsigned static int iuc_print_counter; +unsigned static int iuc_asynch_printTimeout; +unsigned static char iucAsynchpoxDataContext; +//Prozessdaten - highly private +struct billAsynchData { + unsigned char time[20]; //UCHAR tagValue[] = "2017-12-19 13:40:00"; + unsigned char id[37]; + unsigned char printId[129]; + unsigned char docNr[33]; + //unsigned char amount[10]; + //unsigned char token[25]; + //unsigned char result[8]; + //unsigned char authCode[7]; + //unsigned char rrn[13]; + //unsigned char stan[7]; + //unsigned char cardtype[33]; + unsigned char errCode[17]; + //unsigned char receiptData[IUC_ASYNCHPOS_RECEIPT_LENGTH]; +}; + +//private +unsigned int iuc_asynchpos_send(unsigned char packetType, unsigned char* pData, unsigned int length, unsigned char needRTS); + +//void iuc_asynchpos_interpretCommand(unsigned int readLength_); + +//public +void iuc_asynchpos_setTerminalID(unsigned char *pID, unsigned int length); +void iuc_asynchpos_setTerminalAPAK(unsigned char *pAPAK, unsigned int length); +unsigned char iuc_asynchpos_recieve_serial(unsigned char waitforACK); +void iuc_asynchpos_init(); +void iuc_asynchpos_handleCommand(unsigned char command, unsigned char status); +int iuc_asynchpos_checkTime(); +unsigned char iuc_asynchpos_getIsSaleRunning(); + +//commands +void iuc_asynchpos_command_ping_terminal(void); +void iuc_asynchpos_command_Login(); +void iuc_asynchpos_command_Logout(); +void iuc_asynchpos_command_authorize(unsigned int vkPreis); +void iuc_asynchpos_command_cancel_authorize(); +void iuc_asynchpos_command_close_Document(unsigned char isStorno); +void iuc_asynchpos_command_print_Result(unsigned char status); + +//void iuc_asynchpos_handleCommand(unsigned char command, unsigned char status); +//void iuc_asynchpos_init(); +//int iuc_asynchpos_checkTime(); + +//unsigned char iuc_asynchpos_getCurrentStatus(); + +//int iuc_asynchpos_heartbeat(); + + +uint32_t iuc_asynchpos_sub_updateCRC(uint32_t crc, char* pData, size_t len); + +#endif diff --git a/main/main.cpp b/main/main.cpp index 18b76bb..60e7119 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -35,6 +35,9 @@ extern "C" char* strptime(const char* s, #include #include "calculator_functions.h" #include "calculate_price.h" +#include "aes128.h" +#include "cc_iuc_asynchpos.h" +#include "MessageHelper.h" #define SZEGED (0) #define SCHOENAU_KOENIGSEE (0) @@ -45,8 +48,8 @@ extern "C" char* strptime(const char* s, #define BAD_NEUENAHR_AHRWEILER (0) #define NEUHAUSER_CHRISTOPH_REISEN (0) #define NEUHAUSER_PERNEGG_AN_DER_MUR (0) -#define NEUHAUSER_STOCKERAU (0) -#define KLEIPEDA_LITAUEN (1) +#define NEUHAUSER_STOCKERAU (1) +#define KLEIPEDA_LITAUEN (0) #if NEUHAUSER_KIRCHDORF==1 static bool test_neuhauser_kirchdorf(int step, double cost) { @@ -205,7 +208,587 @@ static bool test_neuhauser_kirchdorf(int step, double cost) { return 0; */ + + + +//https://lxp32.github.io/docs/a-simple-example-crc32-calculation/ +uint32_t crc32(const char *s, size_t n) { + uint32_t crc=0xFFFFFFFF; + + for(size_t i=0;i>=1; + if(b) crc=crc^0xEDB88320; + ch>>=1; + } + } + + return ~crc; +} + +#define UINT unsigned int +#define UCHAR unsigned char + + +static struct billAsynchData asynchBill; + +void iuc_asynchpos_sub_initArray(unsigned char* pArray, int length) { + unsigned int uitemp = 0; + + for (uitemp = 0; uitemp < length; ++uitemp) + pArray[uitemp] = 0x00; +} + +unsigned int biox_StrLen(unsigned char *str) { + unsigned int zz; + for (zz=0; zz<0xF000; zz++) + if (str[zz]==0) + return(zz); + + return(0); +} + +void biox_CopyBlock(unsigned char *src, UINT srcPos, UCHAR *dest, UINT destPos, UINT len) { + UINT xx,yy,zz,ii; + + xx = srcPos; + yy = destPos; + zz = len; + + for (ii = 0; ii < zz; ++ii) { + dest[yy + ii] = src[xx + ii]; + } +} + +void iuc_asynchpos_sub_synchTime() { + QDateTime current = QDateTime::currentDateTime(); + current.setTime(QTime(12, 0, 0)); + QString const &s = current.toString(Qt::ISODate); + + QByteArray time(s.toStdString().c_str()); + time[10] = ' '; + + strncpy((char *)asynchBill.time, time.toStdString().c_str(), sizeof(asynchBill.time)); +} + +uint32_t iuc_asynchpos_sub_updateCRC(uint32_t crc, unsigned char* pData, size_t len) { + // berechne CRC32 nach Polynom x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 + + + QByteArray a((char *)pData, len); + qCritical() << "updateCRC" << a.toHex(' '); + qCritical() << "updateCRC" << len << hex << crc; + + int i = 0; + int j = 0; +// unsigned long rem; +// unsigned char octet; +// UCHAR *p, *q; + unsigned char ucCarry = 0x00; + + crc = ~crc; + while (len > 0) { + crc ^= (uint32_t) pData[i]; + ++i; + + for (j = 0; j < 8; ++j) { + ucCarry = crc & 1; + crc >>= 1; + + if (ucCarry) { + crc ^= IUC_ASYNCHPOS_POLYNOME; + } + } + --len; + } + + return ~crc; + +} + +unsigned char biox_ah2ui_char(unsigned char AscString) + { + // change hex ascii string ( of ascii numbers '0'..'9', 'A' or 'a' ...'F','f') to number + + unsigned char uctmp1; + unsigned char uitmp; + + uitmp = 0; + uctmp1=AscString;//[zz]; + + if (uctmp1>=0x30 && uctmp1<=0x39) + { + //uitmp<<=4; // nur wenn eine neue Ziffer dazukommt und vor der addition! + uctmp1-=0x30; + uitmp+=/*(UINT)*/uctmp1; + } else + + if (uctmp1>='A' && uctmp1<='F') + { + //uitmp<<=4; + uctmp1-=0x37; + uitmp+=/*(UINT)*/uctmp1; + } else + + if (uctmp1>='a' && uctmp1<='f') + { + //uitmp<<=4; + uctmp1-=0x57; + uitmp+=/*(UINT)*/uctmp1; + } + + return(uitmp); + +} + +unsigned char iuc_asynchpos_send_serial(unsigned char* pData, unsigned int length, unsigned char needRTS, unsigned char overrideACK) { + unsigned int uitmp = 0; + unsigned int uitmp2 = 0; + unsigned int uitmp3 = 0; + unsigned int txCounter = 0; + unsigned int dxCounter = 0; + unsigned char uctmp = 0x00; +// unsigned char uctmp2 =0x00; + unsigned char chksum = 0x00; + //unsigned char dataContext = 0x00; + unsigned int retryCount = 0; + unsigned long lastRetry = 0; + unsigned int dxLength; +// unsigned int dx = biox_StrLen(pData) + 1; + unsigned char rxBuf[8]; + //unsigned char pData_[IUC_ASYNCHPOS_MAX_ARRAY_SIZE]; +// unsigned int loopCount = 1000; +// unsigned char retVal = 0x01; + + //preparing to send + //if (needRTS) { + //brd_SendDiagStr("->IUC ASYNCHPOS sending 0x04 (EOT).",1); + // uctmp = iuc_asynchpos_rts(); + //} + + //sending data + if (!uctmp) { + //brd_SendDiagStr("----->IUC ASYNCHPOS",1); + iuc_asynchpos_sub_initArray(txAsynchData, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + //iuc_asynchpos_sub_initArray(pData_, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + + //biox_CopyBlock(pData,0,pData_,0,IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + + /*dxCounter = 0; + for (uitmp = 0; uitmp < dx + dxCounter; ++uitmp) { + if ((pData[uitmp] >= STX && pData[uitmp] <= ACK2) + || (pData[uitmp] == DLE) || (pData[uitmp] == NAK)) { + + pData[uitmp] = (pData[uitmp] + 0x30); + + for (uitmp2 = uitmp; uitmp2 < dx + dxCounter; ++uitmp2) { + pData[uitmp2 + 1] = pData[uitmp2]; + } + + pData[uitmp] = DLE; + ++dxCounter; + } + } + + dxCounter = 0;*/ + + for (uitmp = 0; uitmp < length; uitmp += IUC_ASYNCHPOS_MIN_PACKET_SIZE) { + + //if (dxCounter > 0) + //uitmp -= dxCounter; + + uctmp = 0x00; + dxCounter = 0; + chksum = 0x00; + dxLength = IUC_ASYNCHPOS_MIN_PACKET_SIZE; + + if (length - uitmp <= IUC_ASYNCHPOS_MIN_PACKET_SIZE) + dxLength = 2 + length - uitmp; + + iuc_asynchpos_sub_initArray(txAsynchData, 3 + IUC_ASYNCHPOS_MIN_PACKET_SIZE); + + //Packet structure is STX ETX1|ETX2 {LRC} + txAsynchData[0] = STX; + + for (txCounter = 0; (txCounter/* + dxCounter*/) < dxLength; ++txCounter) { + //for (txCounter = 0; txCounter < dxLength; ++txCounter) { + + /*if ((pData[uitmp + txCounter] >= STX && pData[uitmp + txCounter] <= ACK2) + || (pData[uitmp + txCounter] == DLE) || (pData[uitmp + txCounter] == NAK)) { + txAsynchData[1 + txCounter + dxCounter] = DLE; + uctmp = (pData[uitmp + txCounter] + 0x30); + ++dxCounter; + txAsynchData[1 + txCounter + dxCounter] = uctmp; //(pData[uitmp + txCounter] + 0x30); + } else {*/ + txAsynchData[1 + txCounter/* + dxCounter*/] = pData[uitmp + txCounter]; + + if ((pData[uitmp + txCounter] >= STX && pData[uitmp + txCounter] <= ACK2) + || (pData[uitmp + txCounter] == DLE) || (pData[uitmp + txCounter] == NAK)) { + ++dxCounter; + } + } + + for (uitmp2 = 1; uitmp2 < dxLength + dxCounter; ++uitmp2) { + if ((txAsynchData[uitmp2] >= STX && txAsynchData[uitmp2] <= ACK2) + || (txAsynchData[uitmp2] == DLE) || (txAsynchData[uitmp2] == NAK)) { + for (uitmp3 = dxLength + dxCounter; uitmp3 > uitmp2; --uitmp3) { + txAsynchData[uitmp3] = txAsynchData[uitmp3 - 1]; + } + txAsynchData[uitmp2 + 1] = (txAsynchData[uitmp2 + 1] + 0x30); + txAsynchData[uitmp2] = DLE; + } + } + + /*if (dxLength < IUC_ASYNCHPOS_MIN_PACKET_SIZE && txAsynchData[txCounter + dxCounter] != 0x00) { + ++dxCounter; + }*/ + + for (uitmp2 = 1; uitmp2 <= (txCounter + dxCounter); ++uitmp2) { + chksum ^= txAsynchData[uitmp2]; + } + + if (!iucAsynchpoxDataContext) { + txAsynchData[1 + txCounter + dxCounter] = ETX1; + chksum ^= ETX1; + } else { + txAsynchData[1 + txCounter + dxCounter] = ETX2; + chksum ^= ETX2; + } + + txAsynchData[2 + txCounter + dxCounter] = chksum; + + QByteArray c((char*)txAsynchData, 2 + txCounter + dxCounter + 1); + qCritical() << "txCounter" << txCounter; + qCritical() << "dxCounter" << dxCounter; + qCritical() << "check" << chksum; + qCritical() << "txAsyncData" << c.toHex(' '); + + + } + } + return 0; +} +unsigned int iuc_asynchpos_send(unsigned char packetType, + unsigned char* pData, + unsigned int length, + unsigned char needRTS) { + unsigned char txData_[IUC_ASYNCHPOS_MAX_ARRAY_SIZE]; + unsigned char tempID [IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE]; + unsigned char tempID_ [IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE]; + unsigned char tempAPAK [IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE]; + unsigned long uitmp = 0; + unsigned int posID = 0; + unsigned long chksum = 0; + unsigned int messageLength = length + 1; + unsigned int length_ = length + 1; + unsigned char pData_[IUC_ASYNCHPOS_MAX_ARRAY_SIZE]; + unsigned char uctemp = 0; +// unsigned char retries = 4; + unsigned char rxBuf[8]; + + iuc_asynchpos_crc_old = 0; + iuc_asynchpos_sub_initArray(rxBuf, 8); + iuc_asynchpos_sub_initArray(pData_, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + biox_CopyBlock(pData,0,pData_,0,length_); + + iuc_asynchpos_sub_initArray(txData_, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + iuc_asynchpos_sub_initArray(tempID, IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE); + iuc_asynchpos_sub_initArray(tempID_, IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE); + iuc_asynchpos_sub_initArray(tempAPAK, IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE); + + //header + /* + The header of the message is composed of: + ? 1 byte packet Type, which indicates the type of the packet; + ? 8 bytes Packet ID, a unique ID to achieve maximum security (for information on forming + Packet ID see chapter 3.4 Communication security); + ? 1 byte P.O.S. ID length; + ? ASCII encoded P.O.S. ID (up to 255 bytes); ((gemeint ist Terminal ID) + */ + + txData_[2] = packetType; + + //1 byte P.O.S. ID length + /*for (uitmp = 0; uitmp < 32 && terminalID[uitmp] != 0x00; ++uitmp) { + ++posID; // -= uitmp; + }*/ + + posID = biox_StrLen(terminalID)/* + 1*/; + + //++posID; + txData_[11] = (UCHAR) posID; + + messageLength += (10 + posID); //Added header + txData_[0] = (messageLength) & 0xFF00; //high byte + txData_[1] = (messageLength) & 0x00FF; //low byte + + //8 byte Packet ID + /* + Apak: 9D547268976ADE1BBB39DE90F3A449E5 + Terminal id: T-LT-OPT-01 + */ + + //calculate CRC32 + uctemp = (UCHAR) posID; + + fprintf(stderr, "POSID=%0X\n", uctemp); + + chksum = IUC_ASYNCHPOS_POLYNOME_INITIAL; + chksum = iuc_asynchpos_sub_updateCRC(chksum,&uctemp,1); + fprintf(stderr, "%d CRC32=%04X\n", __LINE__, chksum); + chksum = iuc_asynchpos_sub_updateCRC(chksum,terminalID,posID); + fprintf(stderr, "%d CRC32=%04X\n", __LINE__, chksum); + //for (uitmp = 0; uitmp < length_; ++uitmp) { + chksum = iuc_asynchpos_sub_updateCRC(chksum,pData_/*[uitmp]*/,length_); + fprintf(stderr, "%d CRC32=%04X\n", __LINE__, chksum); + //} + + //XOR crc value with APAK + //chksum = 2502456899; //HACK FOR TESTING, REMOVE LATER! + for(uitmp = 0; uitmp < IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE; ++uitmp) { + tempAPAK[uitmp] |= biox_ah2ui_char(terminalAPAK[uitmp * 2]) << 4; + tempAPAK[uitmp] |= biox_ah2ui_char(terminalAPAK[(uitmp * 2) + 1]); + //tempAPAK[uitmp] = (terminalAPAK[uitmp * 2] << 8) | (terminalAPAK[(uitmp * 2) + 1]); + } + + tempID[0] = (chksum >> 24) & 0xFF; + tempID[1] = (chksum >> 16) & 0xFF; + tempID[2] = (chksum >> 8) & 0xFF; + tempID[3] = chksum & 0xFF; + + for (uitmp = 0; uitmp < 4; ++uitmp) { + tempID[uitmp] ^= tempAPAK[uitmp]; //terminalAPAK[uitmp]; + } + + for (uitmp = 4; uitmp < IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE; ++uitmp) { + tempID[uitmp] = tempAPAK[uitmp]; //terminalAPAK[uitmp]; + } + + //Eyncrypt result with APAK, according to AES128 + + QByteArray x((char *)tempID, IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE); + QByteArray y((char *)tempID_, IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE); + QByteArray z((char *)tempAPAK, IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE); + + qCritical() << "X" << x.toHex(); + qCritical() << "Y" << y.toHex(); + qCritical() << "Z" << z.toHex(); + + + aes_encrypt(tempID,tempID_,tempAPAK); + + //get the leftmost 8 byte of that value and set then as Packet ID + for (uitmp = 0; uitmp < 8; ++uitmp) { + txData_[3 + uitmp] = tempID_[uitmp]; + fprintf(stderr, "%0X", txData_[3 + uitmp]); + } fprintf(stderr, "\n"); + + //P.O.S.ID + for (uitmp = 0; uitmp < posID; ++uitmp) { + txData_[12 + uitmp] = terminalID[uitmp]; + } + + //Message + //1 byte - marker + //0 . 7F bytes - tag name + //2 + N bytes - data + for (uitmp = 0; uitmp < length_; ++uitmp) { + txData_[12 + posID + uitmp] = pData_[uitmp]; + } + + QByteArray a((char *)(&txData_[0]), messageLength+1); + qCritical() << "MESSAGE" << a.toHex(' '); + + iuc_asynchpos_send_serial(txData_, (messageLength/* + 1*/),needRTS,0x00); + //QByteArray b((char *)(&txAsynchData[0]), IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + //qCritical() << "EXPANDED MESSAGE" << b.toHex(' '); + +#if 0 + brd_SendDiagStr("->IUC ASYNCHPOS send message: ",0); + brd_SendDiagBlock(txData_,1,messageLength); + + //Message compiled, now send it via serial + uitmp = 1; + //while (retries > 0 && uitmp > 0) { + //uitmp = iuc_asynchpos_send_serial(txData_, (messageLength + 1)); + //--retries; + if (iuc_asynchpos_send_serial(txData_, (messageLength/* + 1*/),needRTS,0x00)) { + //brd_SendDiagStr("->IUC ASYNCHPOS Message failed!",1); + //TODO Message sending failed -> Error handling here + //return 1; + uitmp = 0x00; + //brd_SendDiagStr("->IUC ASYNCHPOS Message NOT send",1); + } else { + //brd_SendDiagStr("->IUC ASYNCHPOS Message send",1); + } /*else { + --retries; + } + }*/ + + //if (!uitmp) + //return 1; + + /*if (retries == 0) { + brd_SendDiagStr("->IUC ASYNCHPOS Message failed!",1); + rxBuf[0] = 0x45; + rxBuf[1] = 0x00; + rxBuf[2] = 0xFF; + vmc_SendWithBuffer(rxBuf,20,0x69,0); + return 1; + } + + rxBuf[0] = 0x45; + rxBuf[1] = 0x00; + rxBuf[2] = 0x00; + vmc_SendWithBuffer(rxBuf,20,0x69,0);*/ + + //brd_SendDiagStr("->IUC ASYNCHPOS Message send",1); + //while(iuc_asynchpos_recieve_serial()); +#endif + return 0; +} + +void iuc_asynchpos_command_Login() { //Kasse registrieren + unsigned char message[IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE]; + unsigned char packetType = 0x00; + unsigned int uitemp = 0; + unsigned char command[] = "Login"; + unsigned char tagName[] = "Time"; + //unsigned char tag2Name[] = "IdleText"; + unsigned char tag3Name[] = "Flags"; + unsigned char tag3Value[] = "AP3|LR"; + + //Constructing the message + iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE); + uitemp = (unsigned char) biox_StrLen(command); + message[0] = (unsigned char) uitemp + 0x80; //constructed element, tag name length + biox_CopyBlock(command,0,message,1,uitemp); //tag name + ++uitemp; + + message[uitemp] = (unsigned char) biox_StrLen(tagName);//data element, tag name length + ++uitemp; + biox_CopyBlock(tagName,0,message,uitemp, biox_StrLen(tagName));// tag name + uitemp += (1 + biox_StrLen(tagName)); + + //Time + iuc_asynchpos_sub_synchTime(); + message[uitemp] = (unsigned char) biox_StrLen(asynchBill.time);//value length + ++uitemp; + biox_CopyBlock(asynchBill.time,0,message,uitemp, biox_StrLen(asynchBill.time));//value + uitemp += biox_StrLen(asynchBill.time); + + //Flags + message[uitemp] = (unsigned char) biox_StrLen(tag3Name);//data element, tag name length + ++uitemp; + biox_CopyBlock(tag3Name,0,message,uitemp, biox_StrLen(tag3Name));// tag name + uitemp += (1 + biox_StrLen(tag3Name)); + + message[uitemp] = (unsigned char) biox_StrLen(tag3Value);//value length + ++uitemp; + biox_CopyBlock(tag3Value,0,message,uitemp, biox_StrLen(tag3Value));//value + + uitemp += biox_StrLen(tag3Value)/* + 1*/; + + iuc_asynchpos_send(packetType,message,uitemp,0x01); +} + int main() { +#if 1 + + MessageHelper msgHelp; + + + msgHelp.createLoginMessageChunksToSend(0x02); + + + qCritical() << "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" << endl; + //return 0; + + // unsigned static char terminalID[IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE]; + // unsigned static char terminalAPAK[IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE]; + strncpy((char *)&terminalID[0], "T-TPS-SELF2002in", IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE); + strncpy((char *)&terminalAPAK[0], "8AC304380E0E476BA2558B75DB9E2516", IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE); + + iuc_asynchpos_command_Login(); + return 0; + + // test aes + aes_init(); + + uint32_t crc = 0; + + QByteArray a("T-TPS-SELF2002"); + qCritical() << a.toHex(' '); + + //QByteArray xx("\x0D\x54\x2D\x54\x50\x53\x2D\x53\x45\x4C\x46\x32\x30\x30\x32\x85\x4C\x6F\x67\x69\x6E\x04\x54\x69\x6D\x65\x00\x13\x32\x30\x32\x34\x2d\x30\x36\x2d\x31\x31\x20\x31\x33\x3a\x34\x34\x3a\x33\x35\x00\x02", + // 48); + + //QByteArray xx("123456789", 9); + + QByteArray xx("2E5450532D53454C4632303032854C6F67696E0454696D650013323032342d30362d31312031333a34343a333505466C616773000341505300", + 114); + unsigned char bb = 0; + //32:4b:e7:4e:1d:d7:b5:ae + QByteArray b("\x00\x46\x00\x32\x4b\xe7\x4e\x1d\xd7\xb5\xae\x0E\x54\x2D\x54\x50\x53\x2D\x53\x45\x4C\x46\x32\x30\x30\x32\x85\x4C\x6F\x67\x69\x6E\x04\x54\x69\x6D\x65\x00\x13\x32\x30\x32\x34\x2d\x30\x36\x2d\x31\x31\x20\x31\x33\x3a\x34\x34\x3a\x33\x35\x05\x46\x6C\x61\x67\x73\x00\x03\x41\x50\x53\x00\x02", + 71); + qCritical() << "B" << b.toHex(':'); + + for (int i=0; i < b.size(); ++i) { + //printf("%d %02x\n", i, (unsigned char)b.at(i)); + bb = bb ^ b.at(i); + } + printf("bb=%02x\n", bb); + + + + qCritical() << xx.size() << "xx" << xx.toHex(' '); + + crc = iuc_asynchpos_sub_updateCRC(crc, xx.data(), xx.size()); + + printf("111 crc=%04x\n", crc); + + crc = crc32(xx.data(), xx.size()); + printf("222 crc=%04x\n", crc); + + QByteArray ba("TEST\x0E\x0E\x47\x6B\xA2\x55\x8B\x75\xDB\x9E\x25\x16"); + + ba[0] = (crc >> 24); + ba[1] = (crc >> 16); + ba[2] = (crc >> 8); + ba[3] = (crc); + + qCritical() << ba.toHex(' '); + + QDateTime current = QDateTime::currentDateTime(); + QString const &s = current.toString(Qt::ISODate); + QByteArray time(s.toStdString().c_str()); + time[10] = ' '; + + qCritical() << time.toHex(' '); + + + + //unsigned char in[] = "TESTTESTTESTTEST"; + //unsigned char in[] = ba.data(); + unsigned char key[] = "8AC304380E0E476BA2558B75DB9E2516"; + //unsigned char key[] = "\x8A\xC3\x04\x38\x0E\x0E\x47\x6B\xA2\x55\x8B\x75\xDB\x9E\x25\x16"; + unsigned char output[256]; + + memset(output, 0, sizeof(output)); + + aes_encrypt((unsigned char*)ba.data(), output, key); + + qCritical() << ba.toHex(':') << endl; + qCritical() << QByteArray((char*)key).toHex(':') << endl; + qCritical() << QByteArray((char*)output).toHex(':') << endl; + + return 0; +#endif + +//char aes_encrypt(unsigned char *input,unsigned char *output,unsigned char *key); + #if KLEIPEDA_LITAUEN==1 std::ifstream input; int pop_min_time; @@ -237,6 +820,13 @@ int main() { qCritical() << " pop_min_price: " << pop_min_price; qCritical() << " pop_max_price: " << pop_max_price; + + QList timeSteps = Calculator::GetInstance().GetTimeSteps(&cfg); + qCritical() << "TimeSteps" << timeSteps; + + return 0; + + CalcState cs; double cost; int durationInMinutes = 0; @@ -272,9 +862,7 @@ int main() { } - // for (int minutes = 0; minutes < 1440; ++minutes) { - for (int minutes = 480; minutes <= 480; minutes += 60) { - //for (int minutes = 0; minutes < 1440; minutes += 60) { + for (int minutes = 0; minutes < 1440; ++minutes) { QDateTime start = s.addSecs(minutes * 60); QDateTime effectiveStart = start; @@ -329,13 +917,13 @@ int main() { } else { qCritical() << cs.toString(); } - qCritical() << "start ............................" << start.toString(Qt::ISODate); - qCritical() << "effectiveStart ..................." << effectiveStart.toString(Qt::ISODate); - qCritical() << "cost ............................." << cost; - qCritical() << "durationInMinutes ................" << durationInMinutes; - qCritical() << "offsetInMinutes .................." << offsetInMinutes; - qCritical() << "effectiveStart.secsTo(end) / 60 .." << effectiveStart.secsTo(end) / 60; - qCritical() << "end .............................." << end.toString(Qt::ISODate) << endl; + qCritical() << __LINE__ << "start ............................" << start.toString(Qt::ISODate); + qCritical() << __LINE__ << "effectiveStart ..................." << effectiveStart.toString(Qt::ISODate); + qCritical() << __LINE__ << "cost ............................." << cost; + qCritical() << __LINE__ << "durationInMinutes ................" << durationInMinutes; + qCritical() << __LINE__ << "offsetInMinutes .................." << offsetInMinutes; + qCritical() << __LINE__ << "effectiveStart.secsTo(end) / 60 .." << effectiveStart.secsTo(end) / 60; + qCritical() << __LINE__ << "end .............................." << end.toString(Qt::ISODate) << endl; exit(-1); } } @@ -380,11 +968,12 @@ int main() { int durationInMinutes; int offsetInMinutes = 0; - for (int day = Qt::Monday; day <= Qt::Sunday; ++day) { - QDateTime s(QDate(2024, 5, 19 + day), QTime()); // 20: (whit) monday,..., 26: sunday + //for (int day = Qt::Monday; day <= Qt::Sunday; ++day) { + for (int day = Qt::Tuesday; day <= Qt::Tuesday; ++day) { + QDateTime s(QDate(2024, 6, 9 + day), QTime()); // 20: (whit) monday,..., 26: sunday QDateTime end; - for (int minutes = 0; minutes < 1440; ++minutes) { + for (int minutes = 660; minutes <= 660; ++minutes) { //for (int minutes = 0; minutes < 1440; ++minutes) { QDateTime start = s.addSecs(minutes * 60); QDateTime effectiveStart = start; @@ -422,7 +1011,7 @@ int main() { effectiveStart.setTime(QTime(8,0,0)); // monday } - for (int i = 70; i <= 600; i += 10) { + for (int i = 700; i <= 700; i += 10) { cost = i; if ((cs = compute_duration_for_parking_ticket(&cfg, start, cost, end))) { // return value durationInMinutes = truncf(x * (i/10)); @@ -477,6 +1066,13 @@ int main() { } if ((durationInMinutes + offsetInMinutes) == (effectiveStart.secsTo(end) / 60)) { + qCritical() << "| start ............................" << start.toString(Qt::ISODate); + qCritical() << "| effectiveStart ..................." << effectiveStart.toString(Qt::ISODate); + qCritical() << "| cost ............................." << cost; + qCritical() << "| durationMinutes .................." << durationInMinutes; + qCritical() << "| offsetInMinutes .................." << offsetInMinutes; + qCritical() << "| effectiveStart.secsTo(end) / 60 .." << effectiveStart.secsTo(end) / 60; + qCritical() << "| end .............................." << end.toString(Qt::ISODate) << endl; continue; } } @@ -486,6 +1082,7 @@ int main() { } else { qCritical() << "SUCCESS"; } + qCritical() << "start ............................" << cs.toString(); qCritical() << "start ............................" << start.toString(Qt::ISODate); qCritical() << "effectiveStart ..................." << effectiveStart.toString(Qt::ISODate); qCritical() << "cost ............................." << cost; diff --git a/main/main.pro b/main/main.pro index 5ebb9d3..865dfd1 100644 --- a/main/main.pro +++ b/main/main.pro @@ -25,10 +25,16 @@ CONFIG(debug, debug|release) { } } -SOURCES += main.cpp +SOURCES += main.cpp \ + aes128.cpp \ + cc_iuc_asynchpos.cpp \ + terminal_utils.cpp \ + MessageHelper.cpp - -# HEADERS += \ +HEADERS += aes128.h \ + cc_iuc_asynchpos.h \ + terminal_utils.h \ + MessageHelper.h # OTHER_FILES += \ diff --git a/main/terminal_utils.cpp b/main/terminal_utils.cpp new file mode 100644 index 0000000..d2df754 --- /dev/null +++ b/main/terminal_utils.cpp @@ -0,0 +1,124 @@ +#include "terminal_utils.h" + +#include +#include +#include +#include +#include +#include + +namespace TU { + char const *terminalStatus(uint8_t status) { + switch (status) { + case TERMINAL_CB2_KEYS_NOT_PRESENT: + return "CB2 KEYS NOT PRESENT"; + case TERMINAL_NO_BANKING_PARAMETERS_PRESENT: + return "NO BANKING PARAMETERS PRESENT"; + case TERMINAL_IS_BLOCKED: + return "TERMINAL IS BLOCKED"; + case TERMINAL_NOT_OPERATIVE: + return "TERMINAL NOT OPERATIVE"; + case TERMINAL_IS_READY_AND_ACTIVE: + return "TERMINAL IS READY AND ACTIVE"; + case TERMINAL_IS_READY_AND_NOT_ACTIVE: + return "TERMINAL IS READY AND *NOT* ACTIVE"; + case TERMINAL_LOG_FULL: + return "TERMINAL LOG IS FULL"; + default: + return ""; + } + } + + QByteArray int2Hex(int i) { + return QByteArray::fromHex( + QString().setNum(i, 16).toLocal8Bit().constData()).toHex(); + } + + uint16_t getNextTransactionId() { + static std::atomic i{0}; + int j = 0; + + while ((j = (++i % 100)) == 0); // 1 <= j <= 99 + + return htobe16(((j / 10) + 0x30) << 8) | ((j % 10) + 0x30); + } + + //https://lxp32.github.io/docs/a-simple-example-crc32-calculation/ + uint32_t crc32(const char *s, size_t n) { + uint32_t crc=0xFFFFFFFF; + + for(size_t i=0;i>=1; + if(b) crc=crc^0xEDB88320; + ch>>=1; + } + } + + return ~crc; + } + + + uint32_t CRC32(uint32_t crc, unsigned char* pData, size_t len) { + + QByteArray a((char *)pData, len); + qCritical() << "updateCRC" << a.toHex(' '); + + int i = 0; + int j = 0; + unsigned char ucCarry = 0x00; + + crc = ~crc; + while (len > 0) { + crc ^= (uint32_t) pData[i]; + ++i; + + for (j = 0; j < 8; ++j) { + ucCarry = crc & 1; + crc >>= 1; + + if (ucCarry) { + crc ^= 0xedb88320; + } + } + --len; + } + + return ~crc; + + } + + uint32_t crc32(QByteArray const &ba) { + uint32_t crc = 0x00000000; + + unsigned char posIDLength = ba[0]; + crc = CRC32(crc, &posIDLength, 1); + + unsigned char *posID = (unsigned char *)ba.mid(1, 16).data(); + crc = CRC32(crc, posID, 16); + + unsigned char *rest = (unsigned char *)ba.mid(16).data(); + crc = CRC32(crc, rest, ba.size()-16); + + return crc; + } + + char lrc(QByteArray const &ba) { + char crc = 0; + for (int i = 0; i < ba.size(); ++i) { + crc ^= ba[i]; + } + return crc; + } + + bool isBigEndian() { + union { + uint32_t i; + char c[4]; + } bint = {0x01020304}; + + return bint.c[0] == 1; + } +} diff --git a/main/terminal_utils.h b/main/terminal_utils.h new file mode 100644 index 0000000..48d85eb --- /dev/null +++ b/main/terminal_utils.h @@ -0,0 +1,30 @@ +#ifndef TERMINAL_UTILS_H_INCLUDED +#define TERMINAL_UTILS_H_INCLUDED + +#include +#include + +namespace TU { + + enum STATUS : uint8_t { + TERMINAL_CB2_KEYS_NOT_PRESENT = 0x30, + TERMINAL_NO_BANKING_PARAMETERS_PRESENT = 0x31, + TERMINAL_IS_BLOCKED = 0x32, + TERMINAL_NOT_OPERATIVE = 0x33, + TERMINAL_IS_READY_AND_ACTIVE = 0x34, + TERMINAL_IS_READY_AND_NOT_ACTIVE = 0x35, + TERMINAL_LOG_FULL = 0x36 + }; + + char const *terminalStatus(uint8_t status); + QByteArray int2Hex(int i); + uint16_t getNextTransactionId(); + + uint32_t crc32(const char *s, size_t n); + uint32_t crc32(QByteArray const &ba); + uint32_t crc32(uint32_t crc, QByteArray const &ba); + + char lrc(QByteArray const &ba); + bool isBigEndian(); +} +#endif // TERMINAL_UTILS_H_INCLUDED