1 /*
2  * Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2019 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_smartcard_emvsim.h"
10 
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.smartcard_emvsim"
14 #endif
15 
16 /*******************************************************************************
17  * Variables
18  ******************************************************************************/
19 /*! @brief Pointers to emvsim bases for each instance. */
20 static EMVSIM_Type *const s_emvsimBases[] = EMVSIM_BASE_PTRS;
21 
22 /*! @brief Pointers to emvsim IRQ number for each instance. */
23 static const IRQn_Type s_emvsimIRQ[] = EMVSIM_IRQS;
24 
25 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
26 /*! @brief Pointers to emvsim clocks for each instance. */
27 static const clock_ip_name_t s_emvsimClock[] = EMVSIM_CLOCKS;
28 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
29 
30 /* #define CARDSIM_EXTRADELAY_USED */
31 
32 /*******************************************************************************
33  * Private Functions
34  ******************************************************************************/
35 static void smartcard_emvsim_CompleteSendData(EMVSIM_Type *base, smartcard_context_t *context);
36 static void smartcard_emvsim_StartSendData(EMVSIM_Type *base, smartcard_context_t *context);
37 static void smartcard_emvsim_CompleteReceiveData(EMVSIM_Type *base, smartcard_context_t *context);
38 static void smartcard_emvsim_StartReceiveData(EMVSIM_Type *base, smartcard_context_t *context);
39 static void smartcard_emvsim_SetTransferType(EMVSIM_Type *base,
40                                              smartcard_context_t *context,
41                                              smartcard_control_t control);
42 static uint32_t smartcard_emvsim_GetInstance(EMVSIM_Type *base);
43 
44 /*******************************************************************************
45  * Code
46  ******************************************************************************/
47 /*!
48  * @brief Get the UART instance from peripheral base address.
49  *
50  * @param base UART peripheral base address.
51  * @return UART instance.
52  */
smartcard_emvsim_GetInstance(EMVSIM_Type * base)53 static uint32_t smartcard_emvsim_GetInstance(EMVSIM_Type *base)
54 {
55     uint8_t instance          = 0;
56     uint32_t emvsimArrayCount = (sizeof(s_emvsimBases) / sizeof(s_emvsimBases[0]));
57 
58     /* Find the instance index from base address mappings. */
59     for (instance = 0; instance < emvsimArrayCount; instance++)
60     {
61         if (s_emvsimBases[instance] == base)
62         {
63             break;
64         }
65     }
66 
67     assert(instance < emvsimArrayCount);
68 
69     return instance;
70 }
71 /*!
72  * @brief Finish up a transmit by completing the process of sending data and disabling the interrupt.
73  *
74  * @param base The EMVSIM peripheral base address.
75  * @param context A pointer to a SMARTCARD driver context structure.
76  */
smartcard_emvsim_CompleteSendData(EMVSIM_Type * base,smartcard_context_t * context)77 static void smartcard_emvsim_CompleteSendData(EMVSIM_Type *base, smartcard_context_t *context)
78 {
79     assert((NULL != context));
80 
81     /* Disable ETC and TDT interrupt */
82     base->INT_MASK |= (EMVSIM_INT_MASK_ETC_IM_MASK | EMVSIM_INT_MASK_TDT_IM_MASK);
83 
84     /* Disable transmitter */
85     base->CTRL &= ~EMVSIM_CTRL_XMT_EN_MASK;
86     /* Clear receive status flag */
87     base->RX_STATUS = EMVSIM_RX_STATUS_RX_DATA_MASK;
88     /* Enable Receiver */
89     base->CTRL |= EMVSIM_CTRL_RCV_EN_MASK;
90     /* Update the information of the module driver context */
91     context->xIsBusy       = false;
92     context->transferState = kSMARTCARD_IdleState;
93     /* Clear txSize to avoid any spurious transmit from ISR */
94     context->xSize = 0u;
95     /* Invoke user call-back */
96     if (NULL != context->transferCallback)
97     {
98         context->transferCallback(context, context->transferCallbackParam);
99     }
100 }
101 
102 /*!
103  * @brief Finish up a receive by completing the process of receiving data and disabling the interrupt.
104  *
105  * @param base The EMVSIM peripheral base address.
106  * @param context A pointer to a SMARTCARD driver context structure.
107  */
smartcard_emvsim_CompleteReceiveData(EMVSIM_Type * base,smartcard_context_t * context)108 static void smartcard_emvsim_CompleteReceiveData(EMVSIM_Type *base, smartcard_context_t *context)
109 {
110     assert((NULL != context));
111 
112     /* Disable RDT and RX_DATA interrupt */
113     base->INT_MASK |= (EMVSIM_INT_MASK_RDT_IM_MASK | EMVSIM_INT_MASK_RX_DATA_IM_MASK);
114 
115     /* Read data from fifo */
116     while (((base->RX_STATUS & EMVSIM_RX_STATUS_RX_CNT_MASK) != 0u) && ((context->xSize) > 0u))
117     {
118         /* Get data and put into receive buffer */
119         *context->xBuff = (uint8_t)(base->RX_BUF);
120         ++context->xBuff;
121         --context->xSize;
122     }
123 
124     /* Update the information of the module driver context */
125     context->xIsBusy = false;
126     /* Invoke user call-back */
127     if (NULL != context->transferCallback)
128     {
129         context->transferCallback(context, context->transferCallbackParam);
130     }
131 }
132 
133 /*!
134  * @brief Initiate (start) a transmit by beginning the process of sending data and enabling the interrupt.
135  *
136  * @param base The EMVSIM peripheral base address.
137  * @param context A pointer to a SMARTCARD driver context structure.
138  */
smartcard_emvsim_StartSendData(EMVSIM_Type * base,smartcard_context_t * context)139 static void smartcard_emvsim_StartSendData(EMVSIM_Type *base, smartcard_context_t *context)
140 {
141     assert((NULL != context));
142 
143     uint32_t delay   = 0u;
144     uint32_t control = 0u;
145 
146     /* Block guard time */
147     /* 22 etus (16 Receiver Clocks == 1 etu) */
148     delay = 22u * 16u;
149     /* Disable all functionality like protocol timers, NACK generation */
150     control       = base->CTRL;
151     base->CTRL    = 0u;
152     base->TX_GETU = context->cardParams.GTN;
153     /* Clear Global counter time-out flag */
154     base->TX_STATUS = EMVSIM_TX_STATUS_GPCNT1_TO_MASK;
155     /* Disable counter interrupt */
156     base->INT_MASK |= EMVSIM_INT_MASK_GPCNT1_IM_MASK;
157     /* Set counter value */
158     base->GPCNT1_VAL = delay;
159     /* Select the clock for GPCNT */
160     base->CLKCFG =
161         (base->CLKCFG & ~EMVSIM_CLKCFG_GPCNT1_CLK_SEL_MASK) | EMVSIM_CLKCFG_GPCNT1_CLK_SEL(kEMVSIM_GPCRxClock);
162     /* Trigger the counter */
163     base->CTRL |= EMVSIM_CTRL_RCV_EN_MASK;
164     /* Wait until counter overflow event occur */
165     while ((base->TX_STATUS & EMVSIM_TX_STATUS_GPCNT1_TO_MASK) == 0u)
166     {
167     }
168     /* Clear status flag and disable GPCNT1 clock */
169     base->TX_STATUS = EMVSIM_TX_STATUS_GPCNT1_TO_MASK;
170     base->CLKCFG &= ~EMVSIM_CLKCFG_GPCNT1_CLK_SEL_MASK;
171     /* Restore Control register */
172     base->CTRL = control & ~(EMVSIM_CTRL_XMT_EN_MASK | EMVSIM_CTRL_RCV_EN_MASK);
173     /* Update transferState */
174     context->transferState = kSMARTCARD_TransmittingState;
175     context->xIsBusy       = true;
176 
177     /* Flush transmitter */
178     base->CTRL |= EMVSIM_CTRL_FLSH_TX_MASK;
179 
180     /* Enable transmitter */
181     base->CTRL |= EMVSIM_CTRL_XMT_EN_MASK;
182 
183     /* Set transmitter data threshold value to 0 - TDTF is set when the fifo is empty */
184     base->TX_THD &= ~EMVSIM_TX_THD_TDT_MASK;
185 
186     /* Enable TDT interrupt */
187     base->INT_MASK &= ~EMVSIM_INT_MASK_TDT_IM_MASK;
188 }
189 
190 /*!
191  * @brief Initiate (start) a receive by beginning the process of receiving data and enabling the interrupt.
192  *
193  * @param base The EMVSIM peripheral base address.
194  * @param context A pointer to a SMARTCARD driver context structure.
195  */
smartcard_emvsim_StartReceiveData(EMVSIM_Type * base,smartcard_context_t * context)196 static void smartcard_emvsim_StartReceiveData(EMVSIM_Type *base, smartcard_context_t *context)
197 {
198     assert((NULL != context));
199 
200     /* Initialize the module driver context structure to indicate transfer in progress */
201     context->xIsBusy = true;
202     /* Enable BWT Timer interrupt to occur */
203     base->INT_MASK &= ~EMVSIM_INT_MASK_BWT_ERR_IM_MASK;
204     /* Disable transmitter */
205     base->CTRL &= ~EMVSIM_CTRL_XMT_EN_MASK;
206     /* Enable receiver and switch to receive direction */
207     base->CTRL |= EMVSIM_CTRL_RCV_EN_MASK;
208 
209     /* Set rx threshold value - number of bytes that must exist in the Receive FIFO to trigger the receive data
210      * threshold interrupt flag (RDTF).*/
211     if (context->xSize < context->rxFifoThreshold)
212     {
213         uint32_t rx_thd;
214         rx_thd = (base->RX_THD & ~EMVSIM_RX_THD_RDT_MASK);
215         rx_thd |= context->xSize;
216         base->RX_THD = rx_thd;
217     }
218     else
219     {
220         base->RX_THD = ((base->RX_THD & ~EMVSIM_RX_THD_RDT_MASK) | context->rxFifoThreshold);
221     }
222 
223     /* Enable RDT interrupt - count of bytes in rx fifo is equal or greater than threshold RX_THD[RDT] */
224     base->INT_MASK &= ~EMVSIM_INT_MASK_RDT_IM_MASK;
225 
226     if (context->tType == kSMARTCARD_T1Transport)
227     {
228         /* Enable interrupt when new byte is received - in T=1 is necessary to disable BWT interrupt and enable CWT
229          * interrupt after receiving the first byte */
230         base->INT_MASK &= ~EMVSIM_INT_MASK_RX_DATA_IM_MASK;
231     }
232 }
233 
234 /*!
235  * @brief Sets up the EMVSIM hardware for T=0 or T=1 protocol data exchange and initialize timer values.
236  *
237  * @param base The EMVSIM peripheral base address.
238  * @param context A pointer to a SMARTCARD driver context structure.
239  */
smartcard_emvsim_SetTransferType(EMVSIM_Type * base,smartcard_context_t * context,smartcard_control_t control)240 static void smartcard_emvsim_SetTransferType(EMVSIM_Type *base,
241                                              smartcard_context_t *context,
242                                              smartcard_control_t control)
243 {
244     assert((NULL != context));
245     assert((control == kSMARTCARD_SetupATRMode) || (control == kSMARTCARD_SetupT0Mode) ||
246            (control == kSMARTCARD_SetupT1Mode));
247 
248     uint16_t temp16 = 0u;
249     uint32_t bwiVal = 0u;
250     uint8_t tdt     = 0u;
251 
252     if (control == kSMARTCARD_SetupATRMode)
253     {
254         /* Disable all functionality at first */
255         base->CTRL &= ~(EMVSIM_CTRL_RCVR_11_MASK | EMVSIM_CTRL_XMT_CRC_LRC_MASK | EMVSIM_CTRL_LRC_EN_MASK |
256                         EMVSIM_CTRL_ANACK_MASK | EMVSIM_CTRL_ONACK_MASK | EMVSIM_CTRL_RCV_EN_MASK);
257         /* Set default values as per EMV specification */
258         context->cardParams.Fi       = 372u;
259         context->cardParams.Di       = 1u;
260         context->cardParams.currentD = 1u;
261         context->cardParams.WI       = 0x0Au;
262         context->cardParams.GTN      = 0x00u;
263         /* Set default baudrate/ETU time based on EMV parameters and card clock */
264         base->DIVISOR = (((uint32_t)context->cardParams.Fi / context->cardParams.currentD) & 0x1FFu);
265         /* EMV expectation: WWT = (960 x D x WI) + (D x 480)
266          * EMVSIM formula: BWT_VAL[15:0] = CWT_VAL[15:0] */
267         temp16 = (960u * context->cardParams.currentD * context->cardParams.WI) +
268                  (context->cardParams.currentD * 480u) + SMARTCARD_WWT_ADJUSTMENT;
269         base->CWT_VAL = temp16;
270         base->BWT_VAL = temp16;
271         /* Set Extended Guard Timer value
272          * EMV expectation: GT = GTN not equal to 255 -> 12 + GTN = GTN equal to 255 -> 12
273          * EMVSIM formula: same as above */
274         base->TX_GETU = context->cardParams.GTN;
275         /* Setting Rx threshold so that an interrupt is generated when a NACK is
276            sent either due to parity error or wrong INIT char*/
277         base->RX_THD = EMVSIM_RX_THD_RDT(1);
278         /* Setting up Tx NACK threshold */
279         tdt = (uint8_t)(((base->PARAM & EMVSIM_PARAM_TX_FIFO_DEPTH_MASK) >> EMVSIM_PARAM_TX_FIFO_DEPTH_SHIFT) - 1u);
280         base->TX_THD = (EMVSIM_TX_THD_TNCK_THD(SMARTCARD_EMV_TX_NACK_THRESHOLD) | EMVSIM_TX_THD_TDT(tdt));
281         /* Clear all pending interrupts */
282         base->RX_STATUS = 0xFFFFFFFFu;
283         /* Enable Tx NACK threshold interrupt to occur */
284         base->INT_MASK &= ~EMVSIM_INT_MASK_TNACK_IM_MASK;
285         /* Set transport type to T=0 in SMARTCARD context structure */
286         context->tType = kSMARTCARD_T0Transport;
287     }
288     else if (control == kSMARTCARD_SetupT0Mode)
289     {
290         /* Disable receiver at first if it's not, Disable T=0 mode counters 1st,
291          * Setup for single wire ISO7816 mode (setup 12 etu mode).
292          * Set transport protocol type to T=0, Disable initial character detection.*/
293         base->CTRL &=
294             ~(EMVSIM_CTRL_RCV_EN_MASK | EMVSIM_CTRL_CWT_EN_MASK | EMVSIM_CTRL_BWT_EN_MASK | EMVSIM_CTRL_RCVR_11_MASK |
295               EMVSIM_CTRL_XMT_CRC_LRC_MASK | EMVSIM_CTRL_LRC_EN_MASK | EMVSIM_CTRL_ICM_MASK);
296         /* EMV expectation: WWT = (960 x D x WI) + (D x 480)
297          * EMVSIM formula: BWT_VAL[15:0] = CWT_VAL[15:0]  */
298         temp16 = (960u * context->cardParams.currentD * context->cardParams.WI) +
299                  (context->cardParams.currentD * 480u) + SMARTCARD_WWT_ADJUSTMENT;
300         base->CWT_VAL = temp16;
301         base->BWT_VAL = temp16;
302         /* Set Extended Guard Timer value
303          * EMV expectation: GT = GTN not equal to 255 -> 12 + GTN = GTN equal to 255 -> 12
304          * EMVSIM formula: same as above for range [0:254]
305          * Fix for EMV. If TX_GETU == 0 in T0 mode, 3 stop bits are inserted. */
306         context->cardParams.GTN = (context->cardParams.GTN == 0xFFu) ? 0x00u : context->cardParams.GTN;
307         base->TX_GETU           = context->cardParams.GTN;
308         /* Setting Rx threshold so that an interrupt is generated when a NACK is
309         sent either due to parity error or wrong INIT char */
310         base->RX_THD = (EMVSIM_RX_THD_RNCK_THD(SMARTCARD_EMV_RX_NACK_THRESHOLD) | EMVSIM_RX_THD_RDT(1));
311         /* Setting up Tx NACK threshold */
312         tdt = (uint8_t)(((base->PARAM & EMVSIM_PARAM_TX_FIFO_DEPTH_MASK) >> EMVSIM_PARAM_TX_FIFO_DEPTH_SHIFT) - 1u);
313         base->TX_THD = (EMVSIM_TX_THD_TNCK_THD(SMARTCARD_EMV_TX_NACK_THRESHOLD) | EMVSIM_TX_THD_TDT(tdt));
314         /* Enable Tx NACK threshold interrupt to occur */
315         base->INT_MASK &= ~EMVSIM_INT_MASK_TNACK_IM_MASK;
316         /* Enable T=0 mode counters, Enable NACK on error interrupt and NACK on overflow interrupt */
317         base->CTRL |=
318             (EMVSIM_CTRL_CWT_EN_MASK | EMVSIM_CTRL_BWT_EN_MASK | EMVSIM_CTRL_ANACK_MASK | EMVSIM_CTRL_ONACK_MASK);
319         /* Set transport type to T=0 in SMARTCARD context structure */
320         context->tType = kSMARTCARD_T0Transport;
321     }
322     else
323     { /* Disable T=1 mode counters 1st, Disable NACK on error interrupt, Disable NACK on overflow interrupt */
324         base->CTRL &= ~(EMVSIM_CTRL_CWT_EN_MASK | EMVSIM_CTRL_BWT_EN_MASK | EMVSIM_CTRL_ANACK_MASK |
325                         EMVSIM_CTRL_ONACK_MASK | EMVSIM_CTRL_XMT_CRC_LRC_MASK | EMVSIM_CTRL_LRC_EN_MASK);
326         /* Calculate and set Block Wait Timer (BWT) value
327          * EMV expectation: BWT = 11 + (2^BWI x 960 x D) + (D x 960) = 11 + (2^BWI + 1) x 960 x D
328          * EMVSIM formula: BWT = Same */
329         bwiVal = 11u + ((((uint32_t)1u << context->cardParams.BWI) + 1u) * 960u * context->cardParams.currentD);
330 #ifdef CARDSIM_EXTRADELAY_USED
331         base->BWT_VAL = bwiVal + 100u;
332 #else
333         base->BWT_VAL = bwiVal;
334 #endif
335         /* Calculate and set Character Wait Timer (CWT) value
336          * EMV expectation: CWT = ((2^CWI + 11) + 4)
337          * EMVSIM formula: CWT = Same */
338         if (context->cardParams.currentD == 1u)
339         {
340 #ifdef CARDSIM_EXTRADELAY_USED
341             temp16 = ((uint16_t)1u << context->cardParams.CWI) + 16u;
342 #else
343             temp16 = ((uint16_t)1u << context->cardParams.CWI) + 15u;
344 #endif
345         }
346         else
347         {
348 #ifdef CARDSIM_EXTRADELAY_USED
349             temp16 = ((uint16_t)1u << context->cardParams.CWI) + 20u + SMARTCARD_CWT_ADJUSTMENT;
350 #else
351             temp16 = ((uint16_t)1u << context->cardParams.CWI) + 15u + SMARTCARD_CWT_ADJUSTMENT;
352 #endif
353         }
354         /* EMV = 15, ISO = 11,
355          * EMV expectation: BGT = 22
356          * EMVSIM formula: BGT = Same */
357         base->CWT_VAL           = temp16;
358         context->cardParams.BGI = 22u;
359         base->BGT_VAL           = context->cardParams.BGI;
360         /* Set Extended Guard Timer value
361          * EMV expectation: GT = GTN not equal to 255 -> 12 + GTN = GTN equal to 255 -> 11
362          * EMVSIM formula: same as above */
363         base->TX_GETU = context->cardParams.GTN;
364         /* Setup for single wire ISO7816 mode,
365          * Set transport protocol type to T=1, Enable T=0 mode counters */
366         base->CTRL |= (EMVSIM_CTRL_RCVR_11_MASK | EMVSIM_CTRL_CWT_EN_MASK | EMVSIM_CTRL_BWT_EN_MASK);
367         /* Setting Rx threshold */
368         base->RX_THD = (EMVSIM_RX_THD_RNCK_THD(SMARTCARD_EMV_RX_NACK_THRESHOLD) | EMVSIM_RX_THD_RDT(1));
369         /* Setting up Tx threshold */
370         tdt = (uint8_t)(((base->PARAM & EMVSIM_PARAM_TX_FIFO_DEPTH_MASK) >> EMVSIM_PARAM_TX_FIFO_DEPTH_SHIFT) - 1u);
371         base->TX_THD = (EMVSIM_TX_THD_TDT(tdt) | EMVSIM_TX_THD_TNCK_THD(SMARTCARD_EMV_TX_NACK_THRESHOLD));
372         /* Set transport type to T=1 in SMARTCARD context structure */
373         context->tType = kSMARTCARD_T1Transport;
374     }
375 }
376 
377 /*!
378  * brief Fills in the smartcard_card_params structure with default values according to the EMV 4.3 specification.
379  *
380  * param cardParams The configuration structure of type smartcard_interface_config_t.
381  * Function fill in members:
382  *        Fi = 372;
383  *        Di = 1;
384  *        currentD = 1;
385  *        WI = 0x0A;
386  *        GTN = 0x00;
387  * with default values.
388  */
SMARTCARD_EMVSIM_GetDefaultConfig(smartcard_card_params_t * cardParams)389 void SMARTCARD_EMVSIM_GetDefaultConfig(smartcard_card_params_t *cardParams)
390 {
391     /* Initializes the configure structure to zero. */
392     (void)memset(cardParams, 0, sizeof(*cardParams));
393 
394     /* EMV default values */
395     cardParams->Fi       = 372u;
396     cardParams->Di       = 1u;
397     cardParams->currentD = 1u;
398     cardParams->WI       = 0x0Au;
399     cardParams->GTN      = 0x00u;
400 }
401 
402 /*!
403  * brief Initializes an EMVSIM peripheral for the Smart card/ISO-7816 operation.
404  *
405  * This function un-gates the EMVSIM clock, initializes the module to EMV default settings,
406  * configures the IRQ, enables the module-level interrupt to the core and, initializes the driver context.
407  *
408  * param base The EMVSIM peripheral base address.
409  * param context A pointer to the smart card driver context structure.
410  * param srcClock_Hz Smart card clock generation module source clock.
411  *
412  * return An error code or kStatus_SMARTCARD_Success.
413  */
SMARTCARD_EMVSIM_Init(EMVSIM_Type * base,smartcard_context_t * context,uint32_t srcClock_Hz)414 status_t SMARTCARD_EMVSIM_Init(EMVSIM_Type *base, smartcard_context_t *context, uint32_t srcClock_Hz)
415 {
416     assert((NULL != base));
417 
418     if ((NULL == context) || (srcClock_Hz == 0u))
419     {
420         return kStatus_SMARTCARD_InvalidInput;
421     }
422 
423     uint32_t instance = smartcard_emvsim_GetInstance(base);
424 /* Set source clock for EMVSIM MCGPLLCLK */
425 #if (defined(FSL_FEATURE_SOC_MCG_COUNT) && FSL_FEATURE_SOC_MCG_COUNT)
426     CLOCK_SetEmvsimClock(1u);
427 #endif
428 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
429     /* Enable emvsim clock */
430     CLOCK_EnableClock(s_emvsimClock[instance]);
431 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
432     context->base = base;
433     /* Initialize EMVSIM to a known context. */
434     base->CLKCFG     = 0u;
435     base->DIVISOR    = 372u;
436     base->CTRL       = 0x300u;
437     base->INT_MASK   = 0x7FFFu;
438     base->RX_THD     = 1u;
439     base->TX_THD     = 0u;
440     base->PCSR       = 0x1000000u;
441     base->TX_GETU    = 0u;
442     base->CWT_VAL    = 0xFFFFu;
443     base->BWT_VAL    = 0xFFFFFFFFu;
444     base->BGT_VAL    = 0u;
445     base->GPCNT0_VAL = 0xFFFFu;
446     base->GPCNT1_VAL = 0xFFFFu;
447     /* Initialize EMVSIM module for SMARTCARD mode of default operation */
448     smartcard_emvsim_SetTransferType(base, context, kSMARTCARD_SetupATRMode);
449     /* Store information about tx fifo depth */
450     context->txFifoEntryCount =
451         (uint8_t)((base->PARAM & EMVSIM_PARAM_TX_FIFO_DEPTH_MASK) >> EMVSIM_PARAM_TX_FIFO_DEPTH_SHIFT);
452     /* Compute max value of rx fifo threshold */
453     context->rxFifoThreshold =
454         (uint8_t)((base->PARAM & EMVSIM_PARAM_RX_FIFO_DEPTH_MASK) >> EMVSIM_PARAM_RX_FIFO_DEPTH_SHIFT);
455     if ((EMVSIM_RX_THD_RDT_MASK >> EMVSIM_RX_THD_RDT_SHIFT) < context->rxFifoThreshold)
456     {
457         context->rxFifoThreshold = (EMVSIM_RX_THD_RDT_MASK >> EMVSIM_RX_THD_RDT_SHIFT);
458     }
459 /* Enable EMVSIM interrupt on NVIC level. */
460 #if defined(FSL_FEATURE_SOC_INTMUX_COUNT) && FSL_FEATURE_SOC_INTMUX_COUNT
461     if ((uint32_t)s_emvsimIRQ[instance] < (uint32_t)FSL_FEATURE_INTMUX_IRQ_START_INDEX)
462     {
463         NVIC_EnableIRQ(s_emvsimIRQ[instance]);
464     }
465 #else
466     NVIC_EnableIRQ(s_emvsimIRQ[instance]);
467 #endif
468     /* Finally, disable the EMVSIM receiver and transmitter */
469     base->CTRL &= ~EMVSIM_CTRL_XMT_EN_MASK & ~EMVSIM_CTRL_RCV_EN_MASK;
470 
471     return kStatus_SMARTCARD_Success;
472 }
473 
474 /*!
475  * brief This function disables the EMVSIM interrupts, disables the transmitter and receiver,
476  * flushes the FIFOs, and gates EMVSIM clock in SIM.
477  *
478  * param base The EMVSIM module base address.
479  */
SMARTCARD_EMVSIM_Deinit(EMVSIM_Type * base)480 void SMARTCARD_EMVSIM_Deinit(EMVSIM_Type *base)
481 {
482     uint32_t instance = 0u;
483     /* In case there is still data in the TX FIFO or shift register that is
484      * being transmitted wait till transmit is complete.
485      * Wait until the data is completely shifted out of shift register */
486     if ((base->TX_STATUS & EMVSIM_TX_STATUS_TX_CNT_MASK) != 0u)
487     {
488         while ((base->TX_STATUS & EMVSIM_TX_STATUS_ETCF_MASK) == 0u)
489         {
490         }
491     }
492     instance = smartcard_emvsim_GetInstance(base);
493     /* Disable TX and RX */
494     base->CTRL &= ~EMVSIM_CTRL_XMT_EN_MASK & ~EMVSIM_CTRL_RCV_EN_MASK;
495 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
496     /* Gate EMVSIM module clock */
497     CLOCK_DisableClock(s_emvsimClock[instance]);
498 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
499 /* Disable emvsim interrupt in NVIC */
500 #if defined(FSL_FEATURE_SOC_INTMUX_COUNT) && FSL_FEATURE_SOC_INTMUX_COUNT
501     if ((uint32_t)s_emvsimIRQ[instance] < (uint32_t)FSL_FEATURE_INTMUX_IRQ_START_INDEX)
502     {
503         NVIC_DisableIRQ(s_emvsimIRQ[instance]);
504     }
505 #else
506     NVIC_DisableIRQ(s_emvsimIRQ[instance]);
507 #endif
508 }
509 
510 /*!
511  * brief Transfer data using interrupts.
512  *
513  * A non-blocking (also known as asynchronous) function means that the function returns
514  * immediately after initiating the transfer function. The application has to get the
515  * transfer status to see when the transfer is complete. In other words, after calling the non-blocking
516  * (asynchronous) transfer function, the application must get the transfer status to check if the transmit
517  * is completed or not.
518  *
519  * param base The EMVSIM peripheral base address.
520  * param context A pointer to a smart card driver context structure.
521  * param xfer A pointer to the smart card transfer structure where the linked buffers and sizes are stored.
522  *
523  * return An error code or kStatus_SMARTCARD_Success.
524  */
SMARTCARD_EMVSIM_TransferNonBlocking(EMVSIM_Type * base,smartcard_context_t * context,smartcard_xfer_t * xfer)525 status_t SMARTCARD_EMVSIM_TransferNonBlocking(EMVSIM_Type *base, smartcard_context_t *context, smartcard_xfer_t *xfer)
526 {
527     if ((NULL == context) || (NULL == xfer) || (xfer->buff == NULL))
528     {
529         return kStatus_SMARTCARD_InvalidInput;
530     }
531 
532     /* Check input parameters */
533     if ((0u == xfer->size))
534     {
535         return kStatus_SMARTCARD_Success;
536     }
537     /* Check if some transfer is in progress */
538     if (0 != SMARTCARD_EMVSIM_GetTransferRemainingBytes(base, context))
539     {
540         if (kSMARTCARD_Receive == context->direction)
541         {
542             return kStatus_SMARTCARD_RxBusy;
543         }
544         else
545         {
546             return kStatus_SMARTCARD_TxBusy;
547         }
548     }
549     /* Initialize error check flags */
550     context->rxtCrossed  = false;
551     context->txtCrossed  = false;
552     context->parityError = false;
553     /* Initialize SMARTCARD context structure to start transfer */
554     context->xBuff = xfer->buff;
555     context->xSize = xfer->size;
556 
557     if (kSMARTCARD_Receive == xfer->direction)
558     {
559         context->direction     = xfer->direction;
560         context->transferState = kSMARTCARD_ReceivingState;
561         /* Start transfer */
562         smartcard_emvsim_StartReceiveData(base, context);
563     }
564     else if (kSMARTCARD_Transmit == xfer->direction)
565     {
566         context->direction     = xfer->direction;
567         context->transferState = kSMARTCARD_TransmittingState;
568         /* Start transfer */
569         smartcard_emvsim_StartSendData(base, context);
570     }
571     else
572     {
573         return kStatus_SMARTCARD_InvalidInput;
574     }
575 
576     return kStatus_SMARTCARD_Success;
577 }
578 
579 /*!
580  * brief Returns whether the previous EMVSIM transfer has finished.
581  *
582  * When performing an async transfer, call this function to ascertain the context of the
583  * current transfer: in progress (or busy) or complete (success). If the
584  * transfer is still in progress, the user can obtain the number of words that have not been
585  * transferred.
586  *
587  * param base The EMVSIM module base address.
588  * param context A pointer to a smart card driver context structure.
589  *
590  * return The number of bytes not transferred.
591  */
SMARTCARD_EMVSIM_GetTransferRemainingBytes(EMVSIM_Type * base,smartcard_context_t * context)592 int32_t SMARTCARD_EMVSIM_GetTransferRemainingBytes(EMVSIM_Type *base, smartcard_context_t *context)
593 {
594     if ((NULL == context))
595     {
596         return -1;
597     }
598     if (context->xIsBusy)
599     {
600         if (context->direction == kSMARTCARD_Transmit)
601         {
602             /* Count of bytes in buffer + data in fifo */
603             uint32_t count;
604             count = context->xSize;
605             count += ((base->TX_STATUS & EMVSIM_TX_STATUS_TX_CNT_MASK) >> EMVSIM_TX_STATUS_TX_CNT_SHIFT);
606             return (int32_t)count;
607         }
608         return (int32_t)context->xSize;
609     }
610 
611     return 0;
612 }
613 
614 /*!
615  * brief Terminates an asynchronous EMVSIM transfer early.
616  *
617  * During an async EMVSIM transfer, the user can terminate the transfer early
618  * if the transfer is still in progress.
619  *
620  * param base The EMVSIM peripheral address.
621  * param context A pointer to a smart card driver context structure.
622  * retval kStatus_SMARTCARD_Success The transmit abort was successful.
623  * retval kStatus_SMARTCARD_NoTransmitInProgress No transmission is currently in progress.
624  */
SMARTCARD_EMVSIM_AbortTransfer(EMVSIM_Type * base,smartcard_context_t * context)625 status_t SMARTCARD_EMVSIM_AbortTransfer(EMVSIM_Type *base, smartcard_context_t *context)
626 {
627     if ((NULL == context))
628     {
629         return kStatus_SMARTCARD_InvalidInput;
630     }
631 
632     context->abortTransfer = true;
633 
634     /* Check if a transfer is running. */
635     if ((!context->xIsBusy))
636     {
637         return kStatus_SMARTCARD_NoTransferInProgress;
638     }
639     /* Call transfer complete to abort transfer */
640     if (kSMARTCARD_Receive == context->direction)
641     { /* Stop the running transfer. */
642         smartcard_emvsim_CompleteReceiveData(base, context);
643     }
644     else if (kSMARTCARD_Transmit == context->direction)
645     { /* Stop the running transfer. */
646         smartcard_emvsim_CompleteSendData(base, context);
647     }
648     else
649     {
650         return kStatus_SMARTCARD_InvalidInput;
651     }
652 
653     return kStatus_SMARTCARD_Success;
654 }
655 
656 /*!
657  * brief Handles EMVSIM module interrupts.
658  *
659  * param base The EMVSIM peripheral base address.
660  * param context A pointer to a smart card driver context structure.
661  */
SMARTCARD_EMVSIM_IRQHandler(EMVSIM_Type * base,smartcard_context_t * context)662 void SMARTCARD_EMVSIM_IRQHandler(EMVSIM_Type *base, smartcard_context_t *context)
663 {
664     if (NULL == context)
665     {
666         return;
667     }
668 
669     /* Check card insertion/removal interrupt occurs, only EMVSIM DIRECT interface driver using enables this interrupt
670      * to occur */
671     if (((base->PCSR & EMVSIM_PCSR_SPDIM_MASK) == 0u) && ((base->PCSR & EMVSIM_PCSR_SPDIF_MASK) != 0u))
672     {
673         /* Clear card presence interrupt status */
674         base->PCSR |= EMVSIM_PCSR_SPDIF_MASK;
675         /* Set PD signal edge behaviour */
676         if (((emvsim_presence_detect_edge_t)(uint32_t)((base->PCSR & EMVSIM_PCSR_SPDES_MASK) >>
677                                                        EMVSIM_PCSR_SPDES_SHIFT) == kEMVSIM_DetectOnFallingEdge) &&
678             ((emvsim_presence_detect_status_t)(uint32_t)((base->PCSR & EMVSIM_PCSR_SPDP_MASK) >>
679                                                          EMVSIM_PCSR_SPDP_SHIFT) == kEMVSIM_DetectPinIsLow))
680         { /* Set rising edge interrupt */
681             base->PCSR |= EMVSIM_PCSR_SPDES_MASK;
682         }
683         if (((emvsim_presence_detect_edge_t)(uint32_t)((base->PCSR & EMVSIM_PCSR_SPDES_MASK) >>
684                                                        EMVSIM_PCSR_SPDES_SHIFT) == kEMVSIM_DetectOnRisingEdge) &&
685             ((emvsim_presence_detect_status_t)(uint32_t)((base->PCSR & EMVSIM_PCSR_SPDP_MASK) >>
686                                                          EMVSIM_PCSR_SPDP_SHIFT) == kEMVSIM_DetectPinIsHigh))
687         { /* Set falling edge interrupt */
688             base->PCSR &= ~EMVSIM_PCSR_SPDES_MASK;
689         }
690         /* Card presence(insertion)/removal detected */
691         /* Invoke callback if there is one */
692         if (NULL != context->interfaceCallback)
693         {
694             context->interfaceCallback(context, context->interfaceCallbackParam);
695         }
696         return;
697     }
698     /* Check if timer for initial character (TS) detection has expired */
699     if (((base->INT_MASK & EMVSIM_INT_MASK_GPCNT0_IM_MASK) >> EMVSIM_INT_MASK_GPCNT0_IM_SHIFT == 0u) &&
700         ((base->TX_STATUS & EMVSIM_TX_STATUS_GPCNT0_TO_MASK) != 0u))
701     {
702         /* Disable TS and ADT timers by clearing source clock to 0 */
703         base->CLKCFG &= ~(EMVSIM_CLKCFG_GPCNT0_CLK_SEL_MASK | EMVSIM_CLKCFG_GPCNT1_CLK_SEL_MASK);
704         context->timersState.initCharTimerExpired = true;
705         /* Disable and clear GPCNT interrupt */
706         base->INT_MASK |= EMVSIM_INT_MASK_GPCNT0_IM_MASK;
707         base->TX_STATUS = EMVSIM_TX_STATUS_GPCNT0_TO_MASK;
708         /* Down counter trigger, and clear any pending counter status flag */
709         base->CTRL &= ~EMVSIM_CTRL_RCV_EN_MASK;
710         base->CTRL |= EMVSIM_CTRL_RCV_EN_MASK;
711         context->transferState = kSMARTCARD_IdleState;
712         /* Unblock the caller */
713         smartcard_emvsim_CompleteReceiveData(base, context);
714         return;
715     }
716     /* Check if timer for ATR duration timer has expired */
717     if (((base->INT_MASK & EMVSIM_INT_MASK_GPCNT1_IM_MASK) == 0u) &&
718         ((base->TX_STATUS & EMVSIM_TX_STATUS_GPCNT1_TO_MASK) != 0u))
719     { /* Disable clock counter by clearing source clock to 0 */
720         base->CLKCFG &= ~EMVSIM_CLKCFG_GPCNT1_CLK_SEL_MASK;
721         /* Disable and clear GPCNT interrupt */
722         base->INT_MASK |= EMVSIM_INT_MASK_GPCNT1_IM_MASK;
723         base->TX_STATUS                 = EMVSIM_TX_STATUS_GPCNT1_TO_MASK;
724         context->timersState.adtExpired = true;
725         /* Unblock the caller */
726         smartcard_emvsim_CompleteReceiveData(base, context);
727         return;
728     }
729     /*
730      * Check if a parity error was indicated.
731      * A parity error will cause transmission of NACK if ANACK bit is set in
732      * CTRL register and PEF bit will not be asserted. When ANACK is not set,
733      * PEF will be asserted.
734      */
735     if ((base->RX_STATUS & EMVSIM_RX_STATUS_PEF_MASK) != 0u)
736     {
737         context->parityError = true;
738         /* Clear parity error indication */
739         base->RX_STATUS = EMVSIM_RX_STATUS_PEF_MASK;
740     }
741     /* Check if transmit NACK generation threshold was reached */
742     if ((base->TX_STATUS & EMVSIM_TX_STATUS_TNTE_MASK) != 0u)
743     {
744         context->txtCrossed = true;
745         /* Disable transmit NACK threshold interrupt */
746         base->INT_MASK |= EMVSIM_INT_MASK_TNACK_IM_MASK;
747         /* Clear transmit NACK threshold error flag */
748         base->TX_STATUS = EMVSIM_TX_STATUS_TNTE_MASK;
749         /* Unblock the caller */
750         smartcard_emvsim_CompleteSendData(base, context);
751         return;
752     }
753     /* Check if receive NACK generation threshold was reached */
754     if ((base->RX_STATUS & EMVSIM_RX_STATUS_RTE_MASK) != 0u)
755     {
756         context->rxtCrossed = true;
757         /* Clear receiver NACK threshold interrupt status */
758         base->RX_STATUS = EMVSIM_RX_STATUS_RTE_MASK;
759         if (context->xIsBusy)
760         { /* Unblock the caller */
761             smartcard_emvsim_CompleteReceiveData(base, context);
762         }
763     }
764     /* Check if a Character Wait Timer expired */
765     if (((base->INT_MASK & EMVSIM_INT_MASK_CWT_ERR_IM_MASK) == 0u) &&
766         ((base->RX_STATUS & EMVSIM_RX_STATUS_CWT_ERR_MASK) != 0u))
767     { /* Disable Character Wait Timer interrupt */
768         base->INT_MASK |= EMVSIM_INT_MASK_CWT_ERR_IM_MASK;
769         /* Reset the counter */
770         base->CTRL &= ~EMVSIM_CTRL_CWT_EN_MASK;
771         /* Clear interrupt status */
772         base->RX_STATUS = EMVSIM_RX_STATUS_CWT_ERR_MASK;
773         /* Enable CWT timer */
774         base->CTRL |= EMVSIM_CTRL_CWT_EN_MASK;
775         context->transferState = kSMARTCARD_IdleState;
776 
777         if (kSMARTCARD_T0Transport == context->tType)
778         { /* Indicate WWT expired */
779             context->timersState.wwtExpired = true;
780         }
781         else
782         { /* Indicate CWT expired */
783             context->timersState.cwtExpired = true;
784         }
785         if (context->xIsBusy)
786         { /* Terminate and unblock any caller */
787             smartcard_emvsim_CompleteReceiveData(base, context);
788         }
789     }
790     /* Check if a Block Wait Timer expired */
791     if (((base->INT_MASK & EMVSIM_INT_MASK_BWT_ERR_IM_MASK) == 0u) &&
792         ((base->RX_STATUS & EMVSIM_RX_STATUS_BWT_ERR_MASK) != 0u))
793     { /* Disable Block Wait Timer interrupt */
794         base->INT_MASK |= EMVSIM_INT_MASK_BWT_ERR_IM_MASK;
795         /* Clear interrupt status flag */
796         base->CTRL &= ~EMVSIM_CTRL_BWT_EN_MASK;
797         /* Clear error */
798         base->RX_STATUS = EMVSIM_RX_STATUS_BWT_ERR_MASK;
799         /* Enable BWT timer */
800         base->CTRL |= EMVSIM_CTRL_BWT_EN_MASK;
801 
802         if (kSMARTCARD_T0Transport == context->tType)
803         { /* Indicate WWT expired */
804             context->timersState.wwtExpired = true;
805         }
806         else
807         { /* Indicate BWT expired */
808             context->timersState.bwtExpired = true;
809         }
810         /* Check if Wait Time Extension(WTX) was requested */
811         if (context->wtxRequested)
812         { /* Reset WTX to default */
813             (void)SMARTCARD_EMVSIM_Control(base, context, kSMARTCARD_ResetWaitTimeMultiplier, 1u);
814         }
815         if (context->xIsBusy)
816         { /* Terminate and unblock any caller */
817             smartcard_emvsim_CompleteReceiveData(base, context);
818         }
819     }
820 
821     /* RX_DATA IRQ */
822     /* Used in T=1 after receive 1st byte - disable BWT and enable CWT interrupt */
823     if (((base->INT_MASK & EMVSIM_INT_MASK_RX_DATA_IM_MASK) == 0u) &&
824         ((base->RX_STATUS & EMVSIM_RX_STATUS_RX_DATA_MASK) != 0u))
825     {
826         if ((context->tType == kSMARTCARD_T1Transport) && (context->xSize > 0u) &&
827             ((base->INT_MASK & EMVSIM_INT_MASK_BWT_ERR_IM_MASK) == 0u))
828         {
829             context->timersState.cwtExpired = false;
830             /* Clear CWT error flag */
831             base->RX_STATUS = EMVSIM_RX_STATUS_CWT_ERR_MASK;
832             /* Enable CWT */
833             base->CTRL |= EMVSIM_CTRL_CWT_EN_MASK;
834             /* Only the 1st byte has been received, now time to disable BWT interrupt and enable CWT interrupt */
835             base->INT_MASK = (base->INT_MASK & ~EMVSIM_INT_MASK_CWT_ERR_IM_MASK) | EMVSIM_INT_MASK_BWT_ERR_IM_MASK;
836         }
837         /* Disable interrupt when is received new byte */
838         base->INT_MASK |= EMVSIM_INT_MASK_RX_DATA_IM_MASK;
839     }
840 
841     /* RDT IRQ - count of bytes in rx fifo reached the rx threshold value RX_THD[RDT] */
842     if (((base->INT_MASK & EMVSIM_INT_MASK_RDT_IM_MASK) == 0u) &&
843         ((base->RX_STATUS & EMVSIM_RX_STATUS_RDTF_MASK) != 0u))
844     {
845         if (kSMARTCARD_WaitingForTSState == context->transferState)
846         {
847             /* Read byte */
848             (void)(base->RX_BUF);
849 
850             if ((base->CTRL & EMVSIM_CTRL_ICM_MASK) != 0u)
851             { /* ICM mode still enabled, this is due to parity error */
852                 context->transferState = kSMARTCARD_InvalidTSDetecetedState;
853             }
854             else
855             { /* Received valid TS */
856                 context->transferState = kSMARTCARD_ReceivingState;
857                 /* Get Data Convention form by reading IC bit of EMVSIM_CTRL register */
858                 context->cardParams.convention =
859                     (smartcard_card_convention_t)(uint32_t)((base->CTRL & EMVSIM_CTRL_IC_MASK) >> EMVSIM_CTRL_IC_SHIFT);
860             }
861             if (kSMARTCARD_InvalidTSDetecetedState == context->transferState)
862             { /* Stop initial character (TS) detection timer, ADT timer and it's interrupt to occur */
863                 base->CLKCFG &= ~(EMVSIM_CLKCFG_GPCNT0_CLK_SEL_MASK | EMVSIM_CLKCFG_GPCNT1_CLK_SEL_MASK);
864                 base->INT_MASK |= EMVSIM_INT_MASK_GPCNT0_IM_MASK;
865                 smartcard_emvsim_CompleteReceiveData(base, context);
866             }
867             if (kSMARTCARD_ReceivingState == context->transferState)
868             { /* Stop initial character (TS) detection timer and disable ATR duration timer to reset it */
869                 base->CLKCFG &= ~(EMVSIM_CLKCFG_GPCNT0_CLK_SEL_MASK | EMVSIM_CLKCFG_GPCNT1_CLK_SEL_MASK);
870                 /* Start ATR duration counter (restart GPCNT) */
871                 base->CLKCFG |= EMVSIM_CLKCFG_GPCNT1_CLK_SEL(kEMVSIM_GPCTxClock);
872                 /* Start ATR duration counter, Disable counter 0 interrupt and Enable counter 1 interrupt */
873                 base->INT_MASK = (base->INT_MASK & ~EMVSIM_INT_MASK_GPCNT1_IM_MASK) | EMVSIM_INT_MASK_GPCNT0_IM_MASK;
874                 /* Complete receive transfer */
875                 smartcard_emvsim_CompleteReceiveData(base, context);
876             }
877             /* Return anyway */
878             return;
879         }
880 
881         while (((base->RX_STATUS & EMVSIM_RX_STATUS_RX_CNT_MASK) != 0u) && ((context->xSize) > 0u))
882         {
883             /* Get data and put into receive buffer */
884             *context->xBuff = (uint8_t)(base->RX_BUF);
885             ++context->xBuff;
886             --context->xSize;
887         }
888 
889         /* Check if the last byte was received */
890         if (context->xSize == 0u)
891         {
892             smartcard_emvsim_CompleteReceiveData(base, context);
893         }
894         else
895         {
896             /* If the count of remaining bytes to receive is less than depth of fifo, update the value of the receiver
897              * data threshold */
898             if (context->xSize < context->rxFifoThreshold)
899             {
900                 /* Set receiver data threshold value to count of remaining bytes */
901                 uint32_t rx_thd;
902                 rx_thd = (base->RX_THD & ~EMVSIM_RX_THD_RDT_MASK);
903                 rx_thd |= context->xSize;
904                 base->RX_THD = rx_thd;
905             }
906         }
907     }
908 
909     /* ETC IRQ - all data from fifo is transmitted */
910     if (((base->INT_MASK & EMVSIM_INT_MASK_ETC_IM_MASK) == 0u) &&
911         ((base->TX_STATUS & EMVSIM_TX_STATUS_ETCF_MASK) != 0u))
912     {
913         smartcard_emvsim_CompleteSendData(base, context);
914     }
915 
916     /* TDT IRQ - tx fifo is empty */
917     if (((base->INT_MASK & EMVSIM_INT_MASK_TDT_IM_MASK) == 0u) &&
918         ((base->TX_STATUS & EMVSIM_TX_STATUS_TDTF_MASK) != 0u))
919     {
920         if (context->xSize == 0u)
921         {
922             smartcard_emvsim_CompleteSendData(base, context);
923         }
924 
925         if (context->xSize == 1u)
926         {
927             /* Disable TDT interrupt */
928             base->INT_MASK |= EMVSIM_INT_MASK_TDT_IM_MASK;
929             /* When the TX_GETU is not zero while sending last byte, the transmitter sends one byte more */
930             base->TX_GETU = 0;
931 
932             /* Write data to fifo */
933             base->TX_BUF = *(context->xBuff);
934             ++context->xBuff;
935             --context->xSize;
936 
937             /* Last byte was written to fifo - wait for ETC interrupt */
938             /* Clear ETC flag and enable ETC interrupt */
939             base->TX_STATUS |= EMVSIM_TX_STATUS_ETCF_MASK;
940             base->INT_MASK &= ~EMVSIM_INT_MASK_ETC_IM_MASK;
941         }
942         else
943         {
944             /* To fifo will be written 2 or more bytes */
945             size_t getu_tail = (size_t)(base->TX_GETU > 0u);
946             while (((context->txFifoEntryCount - (uint8_t)((base->TX_STATUS & EMVSIM_TX_STATUS_TX_CNT_MASK) >>
947                                                            EMVSIM_TX_STATUS_TX_CNT_SHIFT)) > 0u) &&
948                    (context->xSize > getu_tail))
949             {
950                 /* Write data to fifo */
951                 base->TX_BUF = *(context->xBuff);
952                 ++context->xBuff;
953                 --context->xSize;
954             }
955 
956             if (context->xSize == 0u)
957             {
958                 /* Disable TDT interrupt */
959                 base->INT_MASK |= EMVSIM_INT_MASK_TDT_IM_MASK;
960 
961                 /* Clear ETC flag and enable ETC interrupt */
962                 base->TX_STATUS |= EMVSIM_TX_STATUS_ETCF_MASK;
963                 base->INT_MASK &= ~EMVSIM_INT_MASK_ETC_IM_MASK;
964             }
965         }
966     }
967     SDK_ISR_EXIT_BARRIER;
968 }
969 
970 /*!
971  * brief Controls the EMVSIM module per different user request.
972  *
973  * param base The EMVSIM peripheral base address.
974  * param context A pointer to a smart card driver context structure.
975  * param control Control type.
976  * param param Integer value of specific to control command.
977  *
978  * return kStatus_SMARTCARD_Success in success.
979  * return kStatus_SMARTCARD_OtherError in case of error.
980  */
SMARTCARD_EMVSIM_Control(EMVSIM_Type * base,smartcard_context_t * context,smartcard_control_t control,uint32_t param)981 status_t SMARTCARD_EMVSIM_Control(EMVSIM_Type *base,
982                                   smartcard_context_t *context,
983                                   smartcard_control_t control,
984                                   uint32_t param)
985 {
986     if ((NULL == context))
987     {
988         return kStatus_SMARTCARD_InvalidInput;
989     }
990 
991     status_t status = kStatus_SMARTCARD_Success;
992     uint32_t temp32 = 0u;
993 
994     switch (control)
995     {
996         case kSMARTCARD_EnableADT:
997             /* Do nothing, ADT counter has been loaded and started after reset
998              * and during starting TS delay counter only. This is because, once
999              * TS counter has been triggered with RCV_EN down-up, we should not
1000              * trigger again after TS is received(to avoid missing next character to
1001              * TS. Rather, after TS is received, the ATR duration counter should just
1002              * be restarted w/o re-triggering the counter. */
1003             break;
1004         case kSMARTCARD_DisableADT:
1005             base->CTRL &= ~EMVSIM_CTRL_RCV_EN_MASK;
1006             /* Stop ADT specific counter and it's interrupt to occur */
1007             base->CLKCFG &= ~EMVSIM_CLKCFG_GPCNT1_CLK_SEL_MASK;
1008             base->TX_STATUS = EMVSIM_TX_STATUS_GPCNT1_TO_MASK;
1009             base->INT_MASK |= EMVSIM_INT_MASK_GPCNT1_IM_MASK;
1010             break;
1011         case kSMARTCARD_EnableGTV:
1012             /* Enable GTV specific interrupt */
1013             base->INT_MASK &= ~EMVSIM_INT_MASK_BGT_ERR_IM_MASK;
1014             break;
1015         case kSMARTCARD_DisableGTV:
1016             /* Disable GTV specific interrupt */
1017             base->INT_MASK |= EMVSIM_INT_MASK_BGT_ERR_IM_MASK;
1018             break;
1019         case kSMARTCARD_ResetWWT:
1020             /* Reset WWT Timer */
1021             base->CTRL &= ~(EMVSIM_CTRL_CWT_EN_MASK | EMVSIM_CTRL_BWT_EN_MASK);
1022             base->CTRL |= (EMVSIM_CTRL_CWT_EN_MASK | EMVSIM_CTRL_BWT_EN_MASK);
1023             break;
1024         case kSMARTCARD_EnableWWT:
1025             /* BGT must be masked */
1026             base->INT_MASK |= EMVSIM_INT_MASK_BGT_ERR_IM_MASK;
1027             /* Enable WWT Timer interrupt to occur */
1028             base->INT_MASK &= (~EMVSIM_INT_MASK_CWT_ERR_IM_MASK & ~EMVSIM_INT_MASK_BWT_ERR_IM_MASK);
1029             break;
1030         case kSMARTCARD_DisableWWT:
1031             /* Disable WWT Timer interrupt to occur */
1032             base->INT_MASK |= (EMVSIM_INT_MASK_CWT_ERR_IM_MASK | EMVSIM_INT_MASK_BWT_ERR_IM_MASK);
1033             break;
1034         case kSMARTCARD_ResetCWT:
1035             /* Reset CWT Timer */
1036             base->CTRL &= ~EMVSIM_CTRL_CWT_EN_MASK;
1037             base->CTRL |= EMVSIM_CTRL_CWT_EN_MASK;
1038             break;
1039         case kSMARTCARD_EnableCWT:
1040             base->CTRL |= EMVSIM_CTRL_CWT_EN_MASK;
1041             /* Enable CWT Timer interrupt to occur */
1042             base->INT_MASK &= ~EMVSIM_INT_MASK_CWT_ERR_IM_MASK;
1043             break;
1044         case kSMARTCARD_DisableCWT:
1045             /* CWT counter is for receive mode only */
1046             base->CTRL &= ~EMVSIM_CTRL_CWT_EN_MASK;
1047             /* Disable CWT Timer interrupt to occur */
1048             base->INT_MASK |= EMVSIM_INT_MASK_CWT_ERR_IM_MASK;
1049             break;
1050         case kSMARTCARD_ResetBWT:
1051             /* Reset BWT Timer */
1052             base->CTRL &= ~EMVSIM_CTRL_BWT_EN_MASK;
1053             base->CTRL |= EMVSIM_CTRL_BWT_EN_MASK;
1054             break;
1055         case kSMARTCARD_EnableBWT:
1056             base->CTRL |= EMVSIM_CTRL_BWT_EN_MASK;
1057             /* Enable BWT Timer interrupt to occur */
1058             base->INT_MASK &= ~EMVSIM_INT_MASK_BWT_ERR_IM_MASK;
1059             break;
1060         case kSMARTCARD_DisableBWT:
1061             /* Disable BWT Timer interrupt to occur */
1062             base->INT_MASK |= EMVSIM_INT_MASK_BWT_ERR_IM_MASK;
1063             break;
1064         case kSMARTCARD_EnableInitDetect:
1065             /* Clear all ISO7816 interrupt flags */
1066             base->RX_STATUS = 0xFFFFFFFFu;
1067             /* Enable initial character detection : hardware method */
1068             context->transferState = kSMARTCARD_WaitingForTSState;
1069             /* Enable initial character detection */
1070             base->CTRL |= EMVSIM_CTRL_ICM_MASK;
1071             base->CTRL |= EMVSIM_CTRL_RCV_EN_MASK;
1072             break;
1073         case kSMARTCARD_EnableAnack:
1074             /* Enable NACK-on-error interrupt to occur */
1075             base->CTRL |= EMVSIM_CTRL_ANACK_MASK;
1076             break;
1077         case kSMARTCARD_DisableAnack:
1078             /* Disable NACK-on-error interrupt to occur */
1079             base->CTRL &= ~EMVSIM_CTRL_ANACK_MASK;
1080             break;
1081         case kSMARTCARD_ConfigureBaudrate:
1082             /* Set default baudrate/ETU time based on EMV parameters and card clock */
1083             base->DIVISOR = (((uint32_t)context->cardParams.Fi / context->cardParams.currentD) & 0x1FFu);
1084             break;
1085         case kSMARTCARD_SetupATRMode:
1086             /* Set in default ATR mode */
1087             smartcard_emvsim_SetTransferType(base, context, kSMARTCARD_SetupATRMode);
1088             break;
1089         case kSMARTCARD_SetupT0Mode:
1090             /* Set transport protocol type to T=0 */
1091             smartcard_emvsim_SetTransferType(base, context, kSMARTCARD_SetupT0Mode);
1092             break;
1093         case kSMARTCARD_SetupT1Mode:
1094             /* Set transport protocol type to T=1 */
1095             smartcard_emvsim_SetTransferType(base, context, kSMARTCARD_SetupT1Mode);
1096             break;
1097         case kSMARTCARD_EnableReceiverMode:
1098             /* Enable receiver mode and switch to receive direction */
1099             base->CTRL |= EMVSIM_CTRL_RCV_EN_MASK;
1100             /* Set receiver threshold value to 1 */
1101             base->RX_THD = ((base->RX_THD & ~EMVSIM_RX_THD_RDT_MASK) | 1u);
1102             /* Enable RDT interrupt */
1103             base->INT_MASK &= ~EMVSIM_INT_MASK_RDT_IM_MASK;
1104             break;
1105         case kSMARTCARD_DisableReceiverMode:
1106             /* Disable receiver */
1107             base->CTRL &= ~EMVSIM_CTRL_RCV_EN_MASK;
1108             break;
1109         case kSMARTCARD_EnableTransmitterMode:
1110             /* Enable transmitter mode and switch to transmit direction */
1111             base->CTRL |= EMVSIM_CTRL_XMT_EN_MASK;
1112             break;
1113         case kSMARTCARD_DisableTransmitterMode:
1114             /* Disable transmitter */
1115             base->CTRL &= ~EMVSIM_CTRL_XMT_EN_MASK;
1116             break;
1117         case kSMARTCARD_ResetWaitTimeMultiplier:
1118             base->CTRL &= ~EMVSIM_CTRL_BWT_EN_MASK;
1119             /* Reset Wait Timer Multiplier
1120              * EMV Formula : WTX x (11 + ((2^BWI + 1) x 960 x D)) */
1121             temp32 = ((uint8_t)param) *
1122                      (11u + ((((uint32_t)1u << context->cardParams.BWI) + 1u) * 960u * context->cardParams.currentD));
1123 #ifdef CARDSIM_EXTRADELAY_USED
1124             temp32 += context->cardParams.currentD * 50;
1125 #endif
1126             base->BWT_VAL = temp32;
1127             /* Set flag to SMARTCARD context accordingly */
1128             if (param > 1u)
1129             {
1130                 context->wtxRequested = true;
1131             }
1132             else
1133             {
1134                 context->wtxRequested = false;
1135             }
1136             base->CTRL |= EMVSIM_CTRL_BWT_EN_MASK;
1137             break;
1138         default:
1139             status = kStatus_SMARTCARD_InvalidInput;
1140             break;
1141     }
1142     return status;
1143 }
1144