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 #define LOG_TAG "StEse-SpiLayerDriver"
20 #include "SpiLayerDriver.h"
21 #include <errno.h>
22 #include <string.h>
23 #include <sys/time.h>
24 #include "android_logmsg.h"
25 #include "utils-lib/Utils.h"
26 
27 int spiDeviceId;
28 int currentMode;
29 struct timeval lastRxTxTime;
30 #define LINUX_DBGBUFFER_SIZE 300
31 int BGT = 1000;  // in us
32 
33 /*******************************************************************************
34 **
35 ** Function         SpiLayerDriver_init
36 **
37 ** Description      Initialize
38 **
39 ** Parameters       spiDevPath - Spi device path.
40 **
41 ** Returns          null
42 **
43 *******************************************************************************/
SpiLayerDriver_init(SpiDriver_config_t * tSpiDriver)44 void SpiLayerDriver_init(SpiDriver_config_t* tSpiDriver) {
45   BGT = tSpiDriver->bgt;
46   STLOG_HAL_D("SpiLayerDriver_init  BGT=  %d us", BGT);
47 }
48 /*******************************************************************************
49 **
50 ** Function         SpiLayerDriver_open
51 **
52 ** Description      Open the spi device driver.
53 **
54 ** Parameters       spiDevPath - Spi device path.
55 **
56 ** Returns          the file descriptor if everything is ok, -1 otherwise.
57 **
58 *******************************************************************************/
SpiLayerDriver_open(char * spiDevPath)59 int SpiLayerDriver_open(char* spiDevPath) {
60   char* spiDeviceName = spiDevPath;
61   STLOG_HAL_D("%s : Enter ", __func__);
62   // Open the master spi device and save the spi device identifier
63   spiDeviceId = open(spiDeviceName, O_RDWR | O_NOCTTY);
64   STLOG_HAL_V(" spiDeviceId: %d", spiDeviceId);
65   if (spiDeviceId < 0) {
66     return -1;
67   }
68   currentMode = MODE_RX;
69   gettimeofday(&lastRxTxTime, 0);
70 
71   return spiDeviceId;
72 }
73 
74 /*******************************************************************************
75 **
76 ** Function         SpiLayerDriver_close
77 **
78 ** Description      Close the spi device driver.
79 **
80 ** Parameters       none
81 **
82 ** Returns          void
83 **
84 *******************************************************************************/
SpiLayerDriver_close()85 void SpiLayerDriver_close() {
86   if (spiDeviceId > 0) {
87     close(spiDeviceId);
88   }
89 }
90 
91 /*******************************************************************************
92 **
93 ** Function         SpiLayerDriver_read
94 **
95 ** Description      Reads bytesToRead bytes from the SPI interface.
96 **
97 ** Parameters       rxBuffer    - Buffer to store recieved datas.
98 **                  bytesToRead - Expected number of bytes to be read.
99 **
100 ** Returns          The amount of bytes read from the slave, -1 if something
101 **                  failed.
102 **
103 *******************************************************************************/
SpiLayerDriver_read(uint8_t * rxBuffer,unsigned int bytesToRead)104 int SpiLayerDriver_read(uint8_t* rxBuffer, unsigned int bytesToRead) {
105   int retries = 0;
106   int rc = -1;
107 
108   if (currentMode != MODE_RX) {
109     currentMode = MODE_RX;
110     STLOG_HAL_V(" Last TX: %ld,%ld", lastRxTxTime.tv_sec, lastRxTxTime.tv_usec);
111     struct timeval currentTime;
112     gettimeofday(&currentTime, 0);
113     STLOG_HAL_V("     Now: %ld,%ld", currentTime.tv_sec, currentTime.tv_usec);
114 
115     int elapsedTimeUs = Utils_getElapsedTimeInUs(lastRxTxTime, currentTime);
116     if (elapsedTimeUs < BGT) {
117       int waitTime = BGT - elapsedTimeUs;
118       STLOG_HAL_V("Waiting %d us to switch from TX to RX", waitTime);
119       usleep(waitTime);
120     }
121     gettimeofday(&currentTime, 0);
122     STLOG_HAL_V("Start RX: %ld,%ld", currentTime.tv_sec, currentTime.tv_usec);
123   }
124 
125   while (retries < 3) {
126     rc = read(spiDeviceId, rxBuffer, bytesToRead);
127 
128     if (rc < 0) {
129       int e = errno;
130 
131       /* unexpected result */
132       char msg[LINUX_DBGBUFFER_SIZE];
133       strerror_r(e, msg, LINUX_DBGBUFFER_SIZE);
134       STLOG_HAL_E("##  SpiRead returns %d errno %d (%s)", rc, e, msg);
135       /* delays are different and increasing for the three retries. */
136       static const uint8_t delayTab[] = {2, 3, 5};
137       int delay = delayTab[retries];
138 
139       retries++;
140       usleep(delay * 1000);
141       STLOG_HAL_W("##  SpiRead retry %d/3 in %d milliseconds.", retries, delay);
142     } else if (rc > 0) {
143       gettimeofday(&lastRxTxTime, 0);
144       return rc;
145     } else {
146       STLOG_HAL_W("read on spi failed, retrying\n");
147       usleep(4000);
148       retries++;
149     }
150   }
151   gettimeofday(&lastRxTxTime, 0);
152 
153   if (bytesToRead == 1 && rxBuffer[0] != 0 && rxBuffer[0] != 0x12 &&
154       rxBuffer[0] != 0x25) {
155     STLOG_HAL_D("Unexpected byte read from SPI: 0x%02X", rxBuffer[0]);
156   }
157   return rc;
158 }
159 
160 /*******************************************************************************
161 **
162 ** Function         SpiLayerDriver_write
163 **
164 ** Description      Write txBufferLength bytes to the SPI interface.
165 **
166 ** Parameters       txBuffer       - Buffer to transmit.
167 **                  txBufferLength - Number of bytes to be written.
168 **
169 ** Returns          The amount of bytes written to the slave, -1 if something
170 **                  failed.
171 **
172 *******************************************************************************/
SpiLayerDriver_write(uint8_t * txBuffer,unsigned int txBufferLength)173 int SpiLayerDriver_write(uint8_t* txBuffer, unsigned int txBufferLength) {
174   int retries = 0;
175   int rc = 0;
176 
177   if (currentMode != MODE_TX) {
178     currentMode = MODE_TX;
179     STLOG_HAL_V(" Last RX: %ld,%ld", lastRxTxTime.tv_sec, lastRxTxTime.tv_usec);
180     struct timeval currentTime;
181     gettimeofday(&currentTime, 0);
182 
183     int elapsedTimeUs = Utils_getElapsedTimeInUs(lastRxTxTime, currentTime);
184     if (elapsedTimeUs < BGT) {
185       int waitTime = BGT - elapsedTimeUs;
186       STLOG_HAL_V("Waiting %d us to switch from RX to TX", waitTime);
187       usleep(waitTime);
188     }
189     gettimeofday(&currentTime, 0);
190     STLOG_HAL_V("Start TX: %ld,%ld", currentTime.tv_sec, currentTime.tv_usec);
191   }
192 
193   DispHal("Tx", txBuffer, txBufferLength);
194 
195   while (retries < 3) {
196     rc = write(spiDeviceId, txBuffer, txBufferLength);
197 
198     if (rc < 0) {
199       int e = errno;
200 
201       /* unexpected result */
202       char msg[LINUX_DBGBUFFER_SIZE];
203       strerror_r(e, msg, LINUX_DBGBUFFER_SIZE);
204       STLOG_HAL_E("##  Spiwrite returns %d errno %d (%s)", rc, e, msg);
205       /* delays are different and increasing for the three retries. */
206       static const uint8_t delayTab[] = {2, 3, 5};
207       int delay = delayTab[retries];
208 
209       retries++;
210       usleep(delay * 1000);
211       STLOG_HAL_W("##  SpiWrite retry %d/3 in %d milliseconds.", retries,
212                   delay);
213 
214     } else if (rc > 0) {
215       gettimeofday(&lastRxTxTime, 0);
216       return rc;
217     } else {
218       STLOG_HAL_W("write on spi failed, retrying\n");
219       usleep(4000);
220       retries++;
221     }
222   }
223 
224   gettimeofday(&lastRxTxTime, 0);
225   return rc;
226 }
227 
228 /*******************************************************************************
229 **
230 ** Function         SpiLayerDriver_reset
231 **
232 ** Description      Send a Reset pulse to the eSE.
233 **
234 ** Parameters       none
235 **
236 ** Returns          O if success, -1 otherwise
237 **
238 *******************************************************************************/
SpiLayerDriver_reset()239 int SpiLayerDriver_reset() {
240   int rc = ioctl(spiDeviceId, ST54J_SE_PULSE_RESET, NULL);
241   if (rc < 0) {
242     char msg[LINUX_DBGBUFFER_SIZE];
243 
244     strerror_r(errno, msg, LINUX_DBGBUFFER_SIZE);
245     STLOG_HAL_E("! Se reset!!, errno is '%s'", msg);
246   }
247   return rc;
248 }
249