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