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-SpiLayerInterface"
20 #include "SpiLayerInterface.h"
21 #include <errno.h>
22 #include <string.h>
23 #include <sys/time.h>
24 #include "SpiLayerComm.h"
25 #include "SpiLayerDriver.h"
26 #include "T1protocol.h"
27 #include "android_logmsg.h"
28 #include "utils-lib/Atp.h"
29 
30 #define SPI_BITS_PER_WORD 8
31 #define SPI_MODE SPI_MODE_0
32 
33 #define KHZ_TO_HZ 1000
34 
35 static bool mFirstActivation = false;
36 
37 /*******************************************************************************
38 **
39 ** Function         SpiLayerInterface_init
40 **
41 ** Description      Initialize the SPI link access
42 **
43 ** Parameters       tSpiDriver     - hardware information
44 **
45 ** Returns          0 if connection could be initialized, -1 otherwise.
46 **
47 *******************************************************************************/
SpiLayerInterface_init(SpiDriver_config_t * tSpiDriver)48 int SpiLayerInterface_init(SpiDriver_config_t* tSpiDriver) {
49   STLOG_HAL_D("Initializing SPI Driver interface...");
50 
51   // Configure the SPI before start the data exchange with the eSE
52   char* spiDevPath = tSpiDriver->pDevName;
53 
54   SpiLayerComm_init(tSpiDriver);
55   SpiLayerDriver_init(tSpiDriver);
56 
57   int DevHandle = SpiLayerDriver_open(spiDevPath);
58   tSpiDriver->pDevHandle = (void*)((intptr_t)DevHandle);
59   if (DevHandle == -1) {
60     // Error configuring the SPI bus
61     STLOG_HAL_E("Error configuring the SPI bus.");
62     return -1;
63   }
64 
65   if (!mFirstActivation) {
66     if (SpiLayerInterface_setup() == -1) {
67       return -1;
68     }
69     mFirstActivation = true;
70     STLOG_HAL_D("SPI bus working at ATP.msf =  %i KHz", ATP.msf);
71   }
72 
73   STLOG_HAL_D("SPI Driver interface initialized.");
74   return 0;
75 }
76 
77 /*******************************************************************************
78 **
79 ** Function         SpiLayerInterface_transcieveTpdu
80 **
81 ** Description       Sends a TPDU to the SE, waits for the response
82 **                   and returns it.
83 **
84 ** Parameters       cmdTpdu    -The TPDU to be sent.
85 **                  respTpdu   -The memory position where to store the response.
86 **                  numberOfBwt-The maximum number of BWT to wait.
87 **
88 ** Returns          bytesRead if data was read, 0 if timeout expired with
89 **                  no response, -1 otherwise
90 **
91 *******************************************************************************/
SpiLayerInterface_transcieveTpdu(Tpdu * cmdTpdu,Tpdu * respTpdu,int numberOfBwt)92 int SpiLayerInterface_transcieveTpdu(Tpdu* cmdTpdu, Tpdu* respTpdu,
93                                      int numberOfBwt) {
94   // Send the incoming Tpdu to the slave
95   if (SpiLayerComm_writeTpdu(cmdTpdu) < 0) {
96     return -1;
97   }
98 
99   if (numberOfBwt <= 0) {
100     STLOG_HAL_W("Buffer overflow happened, restoring numberOfBwt");
101     numberOfBwt = DEFAULT_NBWT;
102   }
103   // Wait for response
104   int result = SpiLayerComm_waitForResponse(respTpdu, numberOfBwt);
105 
106   // Unable to receive the response from slave
107   if (result == -1) {
108     return -1;
109   } else if (result == -2) {
110     // 0 bytes read
111     return 0;
112   }
113 
114   // Read the response
115   int bytesRead = SpiLayerComm_readTpdu(respTpdu);
116   if (bytesRead < 0) {
117     STLOG_HAL_E("Error when reading from SPI interface (%d).", bytesRead);
118     return -1;
119   }
120   STLOG_HAL_D("%d bytes read from SPI interface", bytesRead);
121 
122   uint8_t buffer[(5 + respTpdu->len)];
123   uint16_t length = Tpdu_toByteArray(respTpdu, buffer);
124   if (length > 0) {
125     DispHal("Rx", buffer, length);
126   }
127   return bytesRead;
128 }
129 
130 /*******************************************************************************
131 **
132 ** Function         SpiLayerInterface_close
133 **
134 ** Description      Close the device
135 **
136 ** Parameters       pDevHandle - device handle
137 **
138 ** Returns          None
139 **
140 *******************************************************************************/
SpiLayerInterface_close(void * pDevHandle)141 void SpiLayerInterface_close(void* pDevHandle) {
142   if (NULL != pDevHandle) {
143     STLOG_HAL_D("SpiLayerInterface_close");
144     SpiLayerDriver_close();
145   }
146 }
147 /*******************************************************************************
148 **
149 ** Function         SpiLayerInterface_setup
150 **
151 ** Description      Read the ATP by performing SE reset and negotiate the IFSD.
152 **
153 ** Parameters       pDevHandle - device handle
154 **
155 ** Returns          0 if connection could be initialized, -1 otherwise.
156 **
157 *******************************************************************************/
SpiLayerInterface_setup()158 int SpiLayerInterface_setup() {
159   const char ese_reset_property[] = "persist.vendor.se.reset";
160   // First of all, read the ATP from the slave
161   if (SpiLayerComm_readAtp() != 0) {
162     // Error reading the ATP
163     STLOG_HAL_E("Error reading the ATP.");
164     // eSE needs cold reset.
165     property_set(ese_reset_property, "needed");
166     return -1;
167   }
168   T1protocol_resetSequenceNumbers();
169 
170   uint8_t* pRsp = (uint8_t*)malloc(ATP.ifsc * sizeof(uint8_t));
171   int rc =
172       T1protocol_transcieveApduPart(0, 0, false, (StEse_data*)pRsp, S_IFS_REQ);
173 
174   if (rc < 0) {
175     STLOG_HAL_E(" %s ESE - Error transmitting IFS request\n", __FUNCTION__);
176     free(pRsp);
177     return -1;
178   }
179   // Set noneed if SPI worked normally.
180   property_set(ese_reset_property, "noneed");
181 
182   free(pRsp);
183   return 0;
184 }
185