1 /******************************************************************************
2 *
3 * Copyright (C) 2018 ST Microelectronics S.A.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *
18 ******************************************************************************/
19
20 #include "Tpdu.h"
21
22 #include "Iso13239CRC.h"
23
24 /*******************************************************************************
25 **
26 ** Function Tpdu_toByteArray
27 **
28 ** Description Forms a byte array representing the given TPDU.
29 **
30 ** Parameters structTpdu - TPDU struct to be converted to byte array.
31 ** baTpdu - Memory position where to store the formed
32 ** byte array.
33 **
34 ** Returns length of the formed array, -1 if there is an error.
35 **
36 *******************************************************************************/
Tpdu_toByteArray(Tpdu * structTpdu,uint8_t * baTpdu)37 uint16_t Tpdu_toByteArray(Tpdu *structTpdu, uint8_t *baTpdu) {
38 // NAD - Copy the nad into the nad array position
39 baTpdu[NAD_OFFSET_IN_TPDU] = structTpdu->nad;
40
41 // PCB - Copy the pcb into the pcb array position
42 baTpdu[PCB_OFFSET_IN_TPDU] = structTpdu->pcb;
43
44 // Length - Copy the length into the length array position
45 baTpdu[LEN_OFFSET_IN_TPDU] = structTpdu->len;
46
47 // Data - Copy the data into the data array position
48 uint8_t i;
49 for (i = 0; i < structTpdu->len; i++) {
50 baTpdu[DATA_OFFSET_IN_TPDU + i] = structTpdu->data[i];
51 }
52
53 // Compute where the checksum shall be stored.
54 uint16_t checksumOffsetInTpdu = DATA_OFFSET_IN_TPDU + structTpdu->len;
55
56 uint16_t length;
57 uint8_t checksum[2];
58 switch (ATP.checksumType) {
59 case LRC:
60 Tpdu_getChecksumBytes(structTpdu, checksum);
61 baTpdu[checksumOffsetInTpdu] = checksum[0];
62 length = checksumOffsetInTpdu + 1;
63 break;
64 case CRC:
65 default:
66 Tpdu_getChecksumBytes(structTpdu, checksum);
67 baTpdu[checksumOffsetInTpdu] = checksum[0];
68 baTpdu[checksumOffsetInTpdu + 1] = checksum[1];
69 length = checksumOffsetInTpdu + 2;
70 break;
71 }
72
73 return length;
74 }
75
76 /*******************************************************************************
77 **
78 ** Function Tpdu_isChecksumOk
79 **
80 ** Description Checks that the checksum in the TPDU is as expected.
81 **
82 ** Parameters tpdu - TPDU whose checksum needs to be checked.
83 **
84 ** Returns true if checksum is ok, false otherwise.
85 **
86 *******************************************************************************/
Tpdu_isChecksumOk(Tpdu * tpdu)87 bool Tpdu_isChecksumOk(Tpdu *tpdu) {
88 switch (ATP.checksumType) {
89 case LRC:
90 // TODO: implement
91 return false;
92 case CRC:;
93 uint8_t buffer[TPDU_MAX_LENGTH];
94 Tpdu_toByteArray(tpdu, buffer);
95 if (tpdu->checksum ==
96 computeCrc(buffer, (TPDU_PROLOGUE_LENGTH + tpdu->len))) {
97 return true;
98 } else {
99 return false;
100 }
101 }
102 }
103
104 /*******************************************************************************
105 **
106 ** Function Tpdu_formTpdu
107 **
108 ** Description Forms a TPDU with the specified fields.
109 **
110 ** Parameters nad - NAD byte of the TPDU.
111 ** pcb - PCB byte of the TPDU.
112 ** len - Length of the data
113 ** data - data of the TPDU
114 ** tpdu - output TPDU struct
115 **
116 ** Returns 0 if everything went ok, -1 otherwise.
117 **
118 *******************************************************************************/
Tpdu_formTpdu(uint8_t nad,uint8_t pcb,uint8_t len,uint8_t * data,Tpdu * tpdu)119 int Tpdu_formTpdu(uint8_t nad, uint8_t pcb, uint8_t len, uint8_t *data,
120 Tpdu *tpdu) {
121 uint8_t i;
122
123 if (len > TPDU_MAX_DATA_LENGTH) {
124 return -1;
125 }
126 // NAD - Copy the incoming nad into the tpdu nad
127 tpdu->nad = nad;
128 // PCB - Copy the incoming pcb into the tpdu pcb
129 tpdu->pcb = pcb;
130 // Length - Copy the incoming len into the tpdu len
131 tpdu->len = len;
132
133 // Data - Copy the incoming data into the tpdu data
134 // TODO: check if it will ever be overwritten
135 for (i = 0; i < len; i++) {
136 tpdu->data[i] = data[i];
137 }
138 // tpdu->data = data;
139 // Checksum - Calculate the checksum according to the prologue + data fields
140 // and copy into the tpdu checksum
141 switch (ATP.checksumType) {
142 case LRC:
143 // TODO: implement
144 return -1;
145 case CRC:
146 // Set temporally checksum to 0 to be able to convert the tpdu struct
147 // to an array
148 tpdu->checksum = 0;
149
150 // Create a buffer to store the tpdu to compute the CRC.
151 uint8_t buffer[TPDU_MAX_LENGTH];
152 Tpdu_toByteArray(tpdu, buffer);
153
154 // Calculate the crc
155 tpdu->checksum = computeCrc(buffer, (TPDU_PROLOGUE_LENGTH + tpdu->len));
156 break;
157 }
158
159 return 0;
160 }
161
162 /*******************************************************************************
163 **
164 ** Function Tpdu_getChecksumBytes
165 **
166 ** Description Get the checksum value in the form of a byte array.
167 **
168 ** Parameters tpdu - TPDU from where to get the checksum value.
169 ** checksumBytes - mem postion whre to store the result.
170 **
171 ** Returns void
172 **
173 *******************************************************************************/
Tpdu_getChecksumBytes(Tpdu * tpdu,uint8_t * checksumBytes)174 void Tpdu_getChecksumBytes(Tpdu *tpdu, uint8_t *checksumBytes) {
175 switch (ATP.checksumType) {
176 case LRC:
177 checksumBytes[0] = (uint8_t)tpdu->checksum;
178 break;
179 case CRC:
180 checksumBytes[0] = (uint8_t)tpdu->checksum;
181 checksumBytes[1] = (uint8_t)(tpdu->checksum >> 8);
182 break;
183 }
184 }
185
186 /*******************************************************************************
187 **
188 ** Function Tpdu_getChecksumValue
189 **
190 ** Description Gets the value of the checksum stored in the array.
191 **
192 ** Parameters array - array that contains the checksum.
193 ** checksumStartPosition
194 ** checksumType -Checksum type (LRC or CRC)
195 **
196 ** Returns checksum value
197 **
198 *******************************************************************************/
Tpdu_getChecksumValue(uint8_t * array,int checksumStartPosition,ChecksumType checksumType)199 uint16_t Tpdu_getChecksumValue(uint8_t *array, int checksumStartPosition,
200 ChecksumType checksumType) {
201 switch (checksumType) {
202 case LRC:
203 return (uint16_t)array[checksumStartPosition];
204 case CRC:
205 return (uint16_t)(array[checksumStartPosition + 1] << 8) |
206 array[checksumStartPosition];
207 }
208 }
209
210 /*******************************************************************************
211 **
212 ** Function Tpdu_getType
213 **
214 ** Description Returns the type of the TPDU.
215 **
216 ** Parameters tpdu - the tpdu the type has to be get.
217 **
218 ** Returns TPDU type (I-Block, R-Block or S-Block)
219 **
220 *******************************************************************************/
Tpdu_getType(Tpdu * tpdu)221 TpduType Tpdu_getType(Tpdu *tpdu) {
222 if ((tpdu->pcb & 0x80) == 0x00) {
223 return IBlock;
224 } else if ((tpdu->pcb & 0xC0) == 0x80) {
225 return RBlock;
226 } else {
227 return SBlock;
228 }
229 }
230
231 /*******************************************************************************
232 **
233 ** Function Tpdu_copy
234 **
235 ** Description Copy a Tpdu Struct to an another one.
236 **
237 ** Parameters dest - the destination tpdu
238 ** src - the tpdu to be copied
239 **
240 ** Returns void
241 **
242 *******************************************************************************/
Tpdu_copy(Tpdu * dest,Tpdu * src)243 void Tpdu_copy(Tpdu *dest, Tpdu *src) {
244 dest->checksum = src->checksum;
245 dest->len = src->len;
246 dest->nad = src->nad;
247 dest->pcb = src->pcb;
248 if (dest->data == NULL) {
249 dest->data = (uint8_t *)malloc(ATP.ifsc * sizeof(uint8_t));
250 }
251 if (((src->len) > 0) && ((src->len) < ATP.ifsc)) {
252 memcpy(dest->data, src->data, src->len);
253 }
254 }
255
256 /*******************************************************************************
257 **
258 ** Function Tpdu_toHexString
259 **
260 ** Description Converts the TPDU in hex string buffer.
261 **
262 ** Parameters tpdu - input tpdu
263 ** hexStringBuffer - output hex buffer
264 **
265 **
266 ** Returns void
267 **
268 *******************************************************************************/
Tpdu_toHexString(Tpdu * tpdu,uint8_t * hexStringBuffer)269 void Tpdu_toHexString(Tpdu *tpdu, uint8_t *hexStringBuffer) {
270 uint8_t buffer[tpdu->len + 5];
271 uint16_t length = Tpdu_toByteArray(tpdu, buffer);
272 char *ptr = (char *)hexStringBuffer;
273 int i;
274 for (i = 0; i < length; i++) {
275 ptr += sprintf(ptr, "%02X ", (char)buffer[i]);
276 }
277 }
278