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(¤tTime, 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(¤tTime, 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(¤tTime, 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(¤tTime, 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