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 #define LOG_TAG "StEse-SpiLayerComm"
21 #include "SpiLayerComm.h"
22 #include <errno.h>
23 #include <stdbool.h>
24 #include <string.h>
25 #include <sys/stat.h>
26 #include <sys/time.h>
27 #include <time.h>
28 #include "SpiLayerDriver.h"
29 #include "android_logmsg.h"
30 #include "utils-lib/Atp.h"
31 #include "utils-lib/Tpdu.h"
32 #include "utils-lib/Utils.h"
33 
34 int pollInterval;
35 
36 /*******************************************************************************
37 **
38 ** Function         SpiLayerComm_init
39 **
40 ** Description      Initialize
41 **
42 ** Parameters       spiDevPath - Spi device path.
43 **
44 ** Returns          null
45 **
46 *******************************************************************************/
SpiLayerComm_init(SpiDriver_config_t * tSpiDriver)47 void SpiLayerComm_init(SpiDriver_config_t* tSpiDriver) {
48   pollInterval = tSpiDriver->polling_interval;
49   STLOG_HAL_D("SpiLayerDriver_init  pollInterval=  %d us", pollInterval);
50 }
51 /*******************************************************************************
52 **
53 ** Function         SpiLayerComm_waitForAtpLength
54 **
55 ** Description      Starts the polling mechanism to read the length of the ATP.
56 **
57 ** Parameters       none.
58 **
59 ** Returns          0 if everything is ok, -1 otherwise.
60 **
61 *******************************************************************************/
62 
SpiLayerComm_waitForAtpLength()63 int SpiLayerComm_waitForAtpLength() {
64   STLOG_HAL_D("%s : Enter ", __func__);
65   uint8_t spiLecture;
66   struct timeval startTime;
67   struct timeval currentTime;
68   unsigned int elapsedTimeInMs = 0;
69 
70   // Wait PWT before to try to read the ATP length
71   gettimeofday(&startTime, 0);
72 
73   while (elapsedTimeInMs < DEFAULT_PWT) {
74     gettimeofday(&currentTime, 0);
75     elapsedTimeInMs = Utils_getElapsedTimeInMs(startTime, currentTime);
76   }
77 
78   // Try to read the ATP length
79   if (SpiLayerDriver_read(&spiLecture, 1) == -1) {
80     STLOG_HAL_E("Error reading the ATP length");
81     return -1;
82   }
83 
84   // Check if ATP length read is OK
85   if ((spiLecture == 0x00) || (spiLecture == 0xFF)) {
86     STLOG_HAL_E("Invalid ATP length read");
87     return -1;
88   }
89 
90   ATP.len = spiLecture;
91 
92   return 0;
93 }
94 
95 /*******************************************************************************
96 **
97 ** Function         SpiLayerComm_readAtp
98 **
99 ** Description      Reads the ATP and stores it in the ATP parameter.
100 **
101 ** Parameters       none.
102 **
103 ** Returns          0 if everything is ok, -1 otherwise.
104 **
105 *******************************************************************************/
106 
SpiLayerComm_readAtp()107 int SpiLayerComm_readAtp() {
108   uint8_t i;
109   STLOG_HAL_D("%s : Enter ", __func__);
110   // Read the ATP length
111   if (SpiLayerDriver_reset() != -1) {
112     if (SpiLayerComm_waitForAtpLength() != 0) {
113       return -1;
114     }
115   } else {
116     return -1;
117   }
118 
119   // Read the rest of the ATP (ATP.len is already set).
120   int atpArrayLength = ATP.len + LEN_LENGTH_IN_ATP;
121   uint8_t atpArray[atpArrayLength];
122 
123   if (SpiLayerDriver_read(atpArray, ATP.len) != ATP.len) {
124     STLOG_HAL_E("Error reading the rest of the ATP");
125     return -1;
126   }
127 
128   // Put the ATP length at the beginning of the atpArray
129   for (i = ATP.len; i > 0; i--) {
130     atpArray[i] = atpArray[i - 1];
131   }
132   atpArray[LEN_OFFSET_IN_ATP] = ATP.len;
133 
134   DispHal("Rx", atpArray, ATP.len);
135 
136   // Set-up the ATP into the corresponding struct
137   if (Atp_setAtp(atpArray) != 0) {
138     STLOG_HAL_E("Error setting ATP");
139     return -1;
140   }
141 
142   return 0;
143 }
144 
145 /*******************************************************************************
146 **
147 ** Function         SpiLayerComm_readAtpFromFile
148 **
149 ** Description      Reads the ATP previously stored in a file.
150 **
151 ** Parameters       none.
152 **
153 ** Returns          void.
154 **
155 *******************************************************************************/
SpiLayerComm_readAtpFromFile()156 void SpiLayerComm_readAtpFromFile() {
157   STLOG_HAL_D("%s : Enter ", __func__);
158 
159   FILE* atp_file = fopen(ATP_FILE_PATH, "rb");
160   if (atp_file) {
161     struct stat st;
162 
163     if (stat(ATP_FILE_PATH, &st) < 0) {
164       STLOG_HAL_E("Error reading ATP file.");
165     }
166 
167     uint8_t atpArray[st.st_size];
168     fread(atpArray, st.st_size, 1, atp_file);
169     // Check if error occurs
170     if (ferror(atp_file)) {
171       STLOG_HAL_E("An error occurred.");
172     }
173 
174     // Set-up the ATP into the corresponding struct
175     Atp_setAtp(atpArray);
176   }
177 }
178 
179 /*******************************************************************************
180 **
181 ** Function         SpiLayerComm_writeTpdu
182 **
183 ** Description      Writes the specified TPDU to the SPI interface.
184 **
185 ** Parameters       cmdTpdu The TPDU to be written.
186 **
187 ** Returns          The number of bytes written if everything went well, -1 if
188 **                  an error occurred.
189 **
190 *******************************************************************************/
191 
SpiLayerComm_writeTpdu(Tpdu * cmdTpdu)192 int SpiLayerComm_writeTpdu(Tpdu* cmdTpdu) {
193   int txBufferLength;
194   uint8_t txBuffer[TPDU_MAX_LENGTH];
195   STLOG_HAL_D("%s : Enter ", __func__);
196   // Build the tx buffer to allocate the array of bytes to be sent
197   switch (ATP.checksumType) {
198     case LRC:
199       txBufferLength = TPDU_PROLOGUE_LENGTH + cmdTpdu->len + TPDU_LRC_LENGTH;
200       break;
201     case CRC:
202       txBufferLength = TPDU_PROLOGUE_LENGTH + cmdTpdu->len + TPDU_CRC_LENGTH;
203       break;
204   }
205 
206   // Copy the array of bytes to be sent from the cmdTpdu struct
207   Tpdu_toByteArray(cmdTpdu, txBuffer);
208 
209   // Send the txBuffer through SPI
210   if (SpiLayerDriver_write(txBuffer, txBufferLength) != txBufferLength) {
211     STLOG_HAL_E("Error writing a TPDU through the spi");
212     return -1;
213   }
214 
215   return txBufferLength;
216 }
217 
218 /*******************************************************************************
219 **
220 ** Function         SpiLayerComm_waitForResponse
221 **
222 ** Description      Waits for a TPDU response to be available on the
223 **                  SPI interface.
224 **
225 ** Parameters       respTpdu The buffer where to store the TDPU.
226 **                  nBwt The maximum number of BWT to wait for the response.
227 **
228 ** Returns          0 if the response is available and the header could be read
229 **                  -2 if no response received before the timeout
230 **                  -1 otherwise.
231 **
232 *******************************************************************************/
SpiLayerComm_waitForResponse(Tpdu * respTpdu,int nBwt)233 int SpiLayerComm_waitForResponse(Tpdu* respTpdu, int nBwt) {
234   uint8_t pollingRxByte;
235   struct timeval startTime;
236   struct timeval currentTime;
237 
238   STLOG_HAL_D("Waiting for TPDU response (nBwt = %d).", nBwt);
239 
240   // Initialize the timeout mechanism if the BWT is under a given threshold.
241   bool isTimeoutRequired = false;
242   unsigned int maxWaitingTime = 0;
243   if (ATP.bwt < BWT_THRESHOlD) {
244     // Enable and init the timeout mechanism
245     isTimeoutRequired = true;
246     maxWaitingTime = ATP.bwt * nBwt;
247     STLOG_HAL_D("Maximum waiting time = %d", maxWaitingTime);
248     gettimeofday(&startTime, 0);
249   }
250 
251   // Start the polling mechanism
252   while (true) {
253     // Wait between each polling sequence
254     usleep(pollInterval);
255 
256     // Read the slave response by sending three null bytes
257     if (SpiLayerDriver_read(&pollingRxByte, 1) != 1) {
258       STLOG_HAL_E("Error reading a valid NAD from the slave.");
259       return -1;
260     }
261 
262     // Look for a start of valid frame
263     if (pollingRxByte == NAD_SLAVE_TO_HOST) {
264       STLOG_HAL_V("Start of valid frame detected");
265       break;
266     }
267 
268     // Check the timeout status (if required)
269     if (isTimeoutRequired) {
270       gettimeofday(&currentTime, 0);
271       unsigned int elapsedTimeInMs =
272           Utils_getElapsedTimeInMs(startTime, currentTime);
273       if (elapsedTimeInMs > maxWaitingTime) {
274         STLOG_HAL_E("BWT timed out after %d ms before receiving a valid NAD",
275                     elapsedTimeInMs);
276         return -2;
277       }
278     }
279   }
280 
281   // If the start of frame has been received continue reading the pending part
282   // of the epilogue (PCB and LEN).
283   uint8_t buffer[2];
284   if (SpiLayerDriver_read(buffer, 2) != 2) {
285     return -1;
286   }
287   // Save the prologue read into the tpduRx
288   respTpdu->nad = pollingRxByte;
289   respTpdu->pcb = buffer[0];
290   respTpdu->len = (uint8_t)buffer[1];
291 
292   return 0;
293 }
294 
295 /*******************************************************************************
296 **
297 ** Function         SpiLayerComm_readTpdu
298 **
299 ** Description      Reads the pending bytes of the response
300 **                  (data information and crc fields).
301 **
302 ** Parameters       respTpdu The buffer where to store the response.
303 **
304 ** Returns          0 if everything went well, -1 otherwise.
305 **
306 *******************************************************************************/
307 
SpiLayerComm_readTpdu(Tpdu * respTpdu)308 int SpiLayerComm_readTpdu(Tpdu* respTpdu) {
309   int pendingBytes;
310   unsigned int i;
311   // Set the number of bytes to be read.
312   switch (ATP.checksumType) {
313     case LRC:
314       pendingBytes = respTpdu->len + TPDU_LRC_LENGTH;
315       break;
316     case CRC:
317       pendingBytes = respTpdu->len + TPDU_CRC_LENGTH;
318       break;
319   }
320 
321   // Read and store them in a buffer.
322   uint8_t rxBuffer[pendingBytes];
323   int bytesRead;
324 
325   bytesRead = SpiLayerDriver_read(rxBuffer, pendingBytes);
326 
327   // Check if the amount of bytesRead matches with the expected
328   if (bytesRead != pendingBytes) {
329     STLOG_HAL_E("Tpdu bytes read does not match the expected %d %d", bytesRead,
330                 pendingBytes);
331     return -1;
332   }
333 
334   // Save data values in respTpdu
335   for (i = 0; i < respTpdu->len; i++) {
336     respTpdu->data[i] = rxBuffer[i];
337   }
338 
339   // Copy checksum read to its struct's position
340   switch (ATP.checksumType) {
341     case LRC:
342       respTpdu->checksum = Tpdu_getChecksumValue(rxBuffer, respTpdu->len, LRC);
343       break;
344     case CRC:
345       respTpdu->checksum = Tpdu_getChecksumValue(rxBuffer, respTpdu->len, CRC);
346       break;
347   }
348   // Return the struct length
349   // NAD + PCB + LEN + bytesRead (DATA + CHECKSUM).
350   STLOG_HAL_V("%s : bytesRead = %d", __func__, bytesRead);
351   return 3 + bytesRead;
352 }
353