blob: 2b11df6896c850345470d46fe582c1b21b66a41f [file] [log] [blame]
/******************************************************************************
*
* Copyright (C) 2018 ST Microelectronics S.A.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
******************************************************************************/
#include "Tpdu.h"
#include "Iso13239CRC.h"
/*******************************************************************************
**
** Function Tpdu_toByteArray
**
** Description Forms a byte array representing the given TPDU.
**
** Parameters structTpdu - TPDU struct to be converted to byte array.
** baTpdu - Memory position where to store the formed
** byte array.
**
** Returns length of the formed array, -1 if there is an error.
**
*******************************************************************************/
uint16_t Tpdu_toByteArray(Tpdu *structTpdu, uint8_t *baTpdu) {
// NAD - Copy the nad into the nad array position
baTpdu[NAD_OFFSET_IN_TPDU] = structTpdu->nad;
// PCB - Copy the pcb into the pcb array position
baTpdu[PCB_OFFSET_IN_TPDU] = structTpdu->pcb;
// Length - Copy the length into the length array position
baTpdu[LEN_OFFSET_IN_TPDU] = structTpdu->len;
// Data - Copy the data into the data array position
uint8_t i;
for (i = 0; i < structTpdu->len; i++) {
baTpdu[DATA_OFFSET_IN_TPDU + i] = structTpdu->data[i];
}
// Compute where the checksum shall be stored.
uint16_t checksumOffsetInTpdu = DATA_OFFSET_IN_TPDU + structTpdu->len;
uint16_t length;
uint8_t checksum[2];
switch (ATP.checksumType) {
case LRC:
Tpdu_getChecksumBytes(structTpdu, checksum);
baTpdu[checksumOffsetInTpdu] = checksum[0];
length = checksumOffsetInTpdu + 1;
break;
case CRC:
default:
Tpdu_getChecksumBytes(structTpdu, checksum);
baTpdu[checksumOffsetInTpdu] = checksum[0];
baTpdu[checksumOffsetInTpdu + 1] = checksum[1];
length = checksumOffsetInTpdu + 2;
break;
}
return length;
}
/*******************************************************************************
**
** Function Tpdu_isChecksumOk
**
** Description Checks that the checksum in the TPDU is as expected.
**
** Parameters tpdu - TPDU whose checksum needs to be checked.
**
** Returns true if checksum is ok, false otherwise.
**
*******************************************************************************/
bool Tpdu_isChecksumOk(Tpdu *tpdu) {
switch (ATP.checksumType) {
case LRC:
// TODO: implement
return false;
case CRC:;
uint8_t buffer[TPDU_MAX_LENGTH];
Tpdu_toByteArray(tpdu, buffer);
if (tpdu->checksum ==
computeCrc(buffer, (TPDU_PROLOGUE_LENGTH + tpdu->len))) {
return true;
} else {
return false;
}
}
}
/*******************************************************************************
**
** Function Tpdu_formTpdu
**
** Description Forms a TPDU with the specified fields.
**
** Parameters nad - NAD byte of the TPDU.
** pcb - PCB byte of the TPDU.
** len - Length of the data
** data - data of the TPDU
** tpdu - output TPDU struct
**
** Returns 0 if everything went ok, -1 otherwise.
**
*******************************************************************************/
int Tpdu_formTpdu(uint8_t nad, uint8_t pcb, uint8_t len, uint8_t *data,
Tpdu *tpdu) {
uint8_t i;
if (len > TPDU_MAX_DATA_LENGTH) {
return -1;
}
// NAD - Copy the incoming nad into the tpdu nad
tpdu->nad = nad;
// PCB - Copy the incoming pcb into the tpdu pcb
tpdu->pcb = pcb;
// Length - Copy the incoming len into the tpdu len
tpdu->len = len;
// Data - Copy the incoming data into the tpdu data
// TODO: check if it will ever be overwritten
for (i = 0; i < len; i++) {
tpdu->data[i] = data[i];
}
// tpdu->data = data;
// Checksum - Calculate the checksum according to the prologue + data fields
// and copy into the tpdu checksum
switch (ATP.checksumType) {
case LRC:
// TODO: implement
return -1;
case CRC:
// Set temporally checksum to 0 to be able to convert the tpdu struct
// to an array
tpdu->checksum = 0;
// Create a buffer to store the tpdu to compute the CRC.
uint8_t buffer[TPDU_MAX_LENGTH];
Tpdu_toByteArray(tpdu, buffer);
// Calculate the crc
tpdu->checksum = computeCrc(buffer, (TPDU_PROLOGUE_LENGTH + tpdu->len));
break;
}
return 0;
}
/*******************************************************************************
**
** Function Tpdu_getChecksumBytes
**
** Description Get the checksum value in the form of a byte array.
**
** Parameters tpdu - TPDU from where to get the checksum value.
** checksumBytes - mem postion whre to store the result.
**
** Returns void
**
*******************************************************************************/
void Tpdu_getChecksumBytes(Tpdu *tpdu, uint8_t *checksumBytes) {
switch (ATP.checksumType) {
case LRC:
checksumBytes[0] = (uint8_t)tpdu->checksum;
break;
case CRC:
checksumBytes[0] = (uint8_t)tpdu->checksum;
checksumBytes[1] = (uint8_t)(tpdu->checksum >> 8);
break;
}
}
/*******************************************************************************
**
** Function Tpdu_getChecksumValue
**
** Description Gets the value of the checksum stored in the array.
**
** Parameters array - array that contains the checksum.
** checksumStartPosition
** checksumType -Checksum type (LRC or CRC)
**
** Returns checksum value
**
*******************************************************************************/
uint16_t Tpdu_getChecksumValue(uint8_t *array, int checksumStartPosition,
ChecksumType checksumType) {
switch (checksumType) {
case LRC:
return (uint16_t)array[checksumStartPosition];
case CRC:
return (uint16_t)(array[checksumStartPosition + 1] << 8) |
array[checksumStartPosition];
}
}
/*******************************************************************************
**
** Function Tpdu_getType
**
** Description Returns the type of the TPDU.
**
** Parameters tpdu - the tpdu the type has to be get.
**
** Returns TPDU type (I-Block, R-Block or S-Block)
**
*******************************************************************************/
TpduType Tpdu_getType(Tpdu *tpdu) {
if ((tpdu->pcb & 0x80) == 0x00) {
return IBlock;
} else if ((tpdu->pcb & 0xC0) == 0x80) {
return RBlock;
} else {
return SBlock;
}
}
/*******************************************************************************
**
** Function Tpdu_copy
**
** Description Copy a Tpdu Struct to an another one.
**
** Parameters dest - the destination tpdu
** src - the tpdu to be copied
**
** Returns void
**
*******************************************************************************/
void Tpdu_copy(Tpdu *dest, Tpdu *src) {
dest->checksum = src->checksum;
dest->len = src->len;
dest->nad = src->nad;
dest->pcb = src->pcb;
if (dest->data == NULL) {
dest->data = (uint8_t *)malloc(ATP.ifsc * sizeof(uint8_t));
}
if (((src->len) > 0) && ((src->len) < ATP.ifsc)) {
memcpy(dest->data, src->data, src->len);
}
}
/*******************************************************************************
**
** Function Tpdu_toHexString
**
** Description Converts the TPDU in hex string buffer.
**
** Parameters tpdu - input tpdu
** hexStringBuffer - output hex buffer
**
**
** Returns void
**
*******************************************************************************/
void Tpdu_toHexString(Tpdu *tpdu, uint8_t *hexStringBuffer) {
uint8_t buffer[tpdu->len + 5];
uint16_t length = Tpdu_toByteArray(tpdu, buffer);
char *ptr = (char *)hexStringBuffer;
int i;
for (i = 0; i < length; i++) {
ptr += sprintf(ptr, "%02X ", (char)buffer[i]);
}
}