/****************************************************************************** | |
* | |
* 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]); | |
} | |
} |