blob: 5362a4e1e717c2b763b21c8957d8e55d8d4a531b [file] [log] [blame]
Christina Quast32a90ac2015-03-10 16:18:16 +01001/* ----------------------------------------------------------------------------
2 * ATMEL Microcontroller Software Support
3 * ----------------------------------------------------------------------------
4 * Copyright (c) 2009, Atmel Corporation
5 *
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * - Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the disclaimer below.
13 *
14 * Atmel's name may not be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
20 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * ----------------------------------------------------------------------------
28 */
29
30/**
31 * \file
32 *
33 * \section Purpose
34 *
35 * ISO 7816 driver
36 *
37 * \section Usage
38 *
39 * Explanation on the usage of the code made available through the header file.
40 */
41
42/*------------------------------------------------------------------------------
43 * Headers
44 *------------------------------------------------------------------------------*/
45
46#include "board.h"
47
48/*------------------------------------------------------------------------------
49 * Definitions
50 *------------------------------------------------------------------------------*/
51/** Case for APDU commands*/
52#define CASE1 1
53#define CASE2 2
54#define CASE3 3
55
56/** Flip flop for send and receive char */
57#define USART_SEND 0
58#define USART_RCV 1
59
Christina Quast32a90ac2015-03-10 16:18:16 +010060/*-----------------------------------------------------------------------------
61 * Internal variables
62 *-----------------------------------------------------------------------------*/
Christina Quast32a90ac2015-03-10 16:18:16 +010063/** Pin reset master card */
Christina Quast2fcef412015-03-10 15:51:21 +010064static Pin *st_pinIso7816RstMC;
Christina Quast32a90ac2015-03-10 16:18:16 +010065
Christina Quastec9c09e2015-04-16 10:45:39 +020066struct Usart_info usart_sim = {.base = USART_SIM, .id = ID_USART_SIM, .state = USART_RCV};
Christina Quaste24b9ac2015-04-10 17:44:49 +020067
Christina Quast32a90ac2015-03-10 16:18:16 +010068/*----------------------------------------------------------------------------
69 * Internal functions
70 *----------------------------------------------------------------------------*/
71
72/**
73 * Get a character from ISO7816
74 * \param pCharToReceive Pointer for store the received char
75 * \return 0: if timeout else status of US_CSR
76 */
Christina Quaste24b9ac2015-04-10 17:44:49 +020077uint32_t ISO7816_GetChar( uint8_t *pCharToReceive, Usart_info *usart)
Christina Quast32a90ac2015-03-10 16:18:16 +010078{
79 uint32_t status;
80 uint32_t timeout=0;
81
Christina Quaste24b9ac2015-04-10 17:44:49 +020082 Usart *us_base = usart->base;
83 uint32_t us_id = usart->id;
84
Christina Quastec9c09e2015-04-16 10:45:39 +020085 if( usart->state == USART_SEND ) {
Christina Quaste24b9ac2015-04-10 17:44:49 +020086 while((us_base->US_CSR & US_CSR_TXEMPTY) == 0) {}
87 us_base->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
Christina Quastec9c09e2015-04-16 10:45:39 +020088 usart->state = USART_RCV;
Christina Quast32a90ac2015-03-10 16:18:16 +010089 }
90
91 /* Wait USART ready for reception */
Christina Quaste24b9ac2015-04-10 17:44:49 +020092 while( ((us_base->US_CSR & US_CSR_RXRDY) == 0) ) {
Christina Quast32a90ac2015-03-10 16:18:16 +010093 if(timeout++ > 12000 * (BOARD_MCK/1000000)) {
94 TRACE_WARNING("TimeOut\n\r");
95 return( 0 );
96 }
97 }
98
99 /* At least one complete character has been received and US_RHR has not yet been read. */
100
101 /* Get a char */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200102 *pCharToReceive = ((us_base->US_RHR) & 0xFF);
Christina Quast32a90ac2015-03-10 16:18:16 +0100103
Christina Quaste24b9ac2015-04-10 17:44:49 +0200104 status = (us_base->US_CSR&(US_CSR_OVRE|US_CSR_FRAME|
Christina Quast32a90ac2015-03-10 16:18:16 +0100105 US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|
106 (1<<10)));
107
108 if (status != 0 ) {
109 TRACE_DEBUG("R:0x%" PRIX32 "\n\r", status);
Christina Quaste24b9ac2015-04-10 17:44:49 +0200110 TRACE_DEBUG("R:0x%" PRIX32 "\n\r", us_base->US_CSR);
111 TRACE_DEBUG("Nb:0x%" PRIX32 "\n\r", us_base->US_NER );
112 us_base->US_CR = US_CR_RSTSTA;
Christina Quast32a90ac2015-03-10 16:18:16 +0100113 }
114
115 /* Return status */
116 return( status );
117}
118
119
120/**
121 * Send a char to ISO7816
122 * \param CharToSend char to be send
123 * \return status of US_CSR
124 */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200125uint32_t ISO7816_SendChar( uint8_t CharToSend, Usart_info *usart )
Christina Quast32a90ac2015-03-10 16:18:16 +0100126{
127 uint32_t status;
128
Christina Quaste24b9ac2015-04-10 17:44:49 +0200129 Usart *us_base = usart->base;
130 uint32_t us_id = usart->id;
131
Christina Quastec9c09e2015-04-16 10:45:39 +0200132 if( usart->state == USART_RCV ) {
Christina Quaste24b9ac2015-04-10 17:44:49 +0200133 us_base->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
Christina Quastec9c09e2015-04-16 10:45:39 +0200134 usart->state = USART_SEND;
Christina Quast32a90ac2015-03-10 16:18:16 +0100135 }
136
137 /* Wait USART ready for transmit */
Christina Quast68cc8592015-04-16 11:08:32 +0200138 int i = 0;
139 while((us_base->US_CSR & (US_CSR_TXRDY)) == 0) {
140 i++;
141 if (!(i%1000000)) {
Harald Welte40901a02016-03-03 10:42:45 +0100142 printf("s: %x ", us_base->US_CSR);
143 printf("s: %x\r\n", us_base->US_RHR & 0xFF);
Christina Quast68cc8592015-04-16 11:08:32 +0200144 us_base->US_CR = US_CR_RSTTX;
145 us_base->US_CR = US_CR_RSTRX;
146 }
147 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100148 /* There is no character in the US_THR */
149
150 /* Transmit a char */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200151 us_base->US_THR = CharToSend;
Christina Quast32a90ac2015-03-10 16:18:16 +0100152
Harald Welte40901a02016-03-03 10:42:45 +0100153 TRACE_ERROR("Sx%02X\r\n", CharToSend);
154
Christina Quaste24b9ac2015-04-10 17:44:49 +0200155 status = (us_base->US_CSR&(US_CSR_OVRE|US_CSR_FRAME|
Christina Quast32a90ac2015-03-10 16:18:16 +0100156 US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|
157 (1<<10)));
158
159 if (status != 0 ) {
Christina Quast68cc8592015-04-16 11:08:32 +0200160 TRACE_INFO("******* status: 0x%" PRIX32 " (Overrun: %" PRIX32
Christina Quaste24b9ac2015-04-10 17:44:49 +0200161 ", NACK: %" PRIX32 ", Timeout: %" PRIX32 ", underrun: %" PRIX32 ")\n\r",
162 status, ((status & US_CSR_OVRE)>> 5), ((status & US_CSR_NACK) >> 13),
Christina Quast32a90ac2015-03-10 16:18:16 +0100163 ((status & US_CSR_TIMEOUT) >> 8), ((status & (1 << 10)) >> 10));
Christina Quast68cc8592015-04-16 11:08:32 +0200164 TRACE_INFO("E (USART CSR reg):0x%" PRIX32 "\n\r", us_base->US_CSR);
165 TRACE_INFO("Nb (Number of errors):0x%" PRIX32 "\n\r", us_base->US_NER );
Christina Quaste24b9ac2015-04-10 17:44:49 +0200166 us_base->US_CR = US_CR_RSTSTA;
Christina Quast32a90ac2015-03-10 16:18:16 +0100167 }
168
169 /* Return status */
170 return( status );
171}
172
173
174/**
175 * Iso 7816 ICC power on
176 */
177static void ISO7816_IccPowerOn( void )
178{
179 /* Set RESET Master Card */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200180 if (st_pinIso7816RstMC) {
181 PIO_Set(st_pinIso7816RstMC);
182 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100183}
184
185/*----------------------------------------------------------------------------
186 * Exported functions
187 *----------------------------------------------------------------------------*/
188
189/**
190 * Iso 7816 ICC power off
191 */
192void ISO7816_IccPowerOff( void )
193{
194 /* Clear RESET Master Card */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200195 if (st_pinIso7816RstMC) {
196 PIO_Clear(st_pinIso7816RstMC);
197 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100198}
199
200/**
Christina Quast73c2b642015-04-07 13:49:26 +0200201 * Transfert Block TPDU T=0
202 * \param pAPDU APDU buffer
203 * \param pMessage Message buffer
204 * \param wLength Block length
205 * \param indexMsg Message index
206 * \return 0 on success, content of US_CSR otherwise
Christina Quast32a90ac2015-03-10 16:18:16 +0100207 */
Christina Quast73c2b642015-04-07 13:49:26 +0200208uint32_t ISO7816_XfrBlockTPDU_T0(const uint8_t *pAPDU,
Christina Quast32a90ac2015-03-10 16:18:16 +0100209 uint8_t *pMessage,
Christina Quast73c2b642015-04-07 13:49:26 +0200210 uint16_t wLength,
211 uint16_t *retlen )
Christina Quast32a90ac2015-03-10 16:18:16 +0100212{
213 uint16_t NeNc;
214 uint16_t indexApdu = 4;
Christina Quast73c2b642015-04-07 13:49:26 +0200215 uint16_t indexMsg = 0;
Christina Quast32a90ac2015-03-10 16:18:16 +0100216 uint8_t SW1 = 0;
217 uint8_t procByte;
218 uint8_t cmdCase;
Christina Quast73c2b642015-04-07 13:49:26 +0200219 uint32_t status = 0;
Christina Quast32a90ac2015-03-10 16:18:16 +0100220
Christina Quastc63df592015-03-10 23:32:45 +0100221 TRACE_INFO("pAPDU[0]=0x%X\n\r",pAPDU[0]);
222 TRACE_INFO("pAPDU[1]=0x%X\n\r",pAPDU[1]);
223 TRACE_INFO("pAPDU[2]=0x%X\n\r",pAPDU[2]);
224 TRACE_INFO("pAPDU[3]=0x%X\n\r",pAPDU[3]);
225 TRACE_INFO("pAPDU[4]=0x%X\n\r",pAPDU[4]);
226 TRACE_INFO("pAPDU[5]=0x%X\n\r",pAPDU[5]);
227 TRACE_INFO("wlength=%d\n\r",wLength);
Christina Quast32a90ac2015-03-10 16:18:16 +0100228
Christina Quaste24b9ac2015-04-10 17:44:49 +0200229 ISO7816_SendChar( pAPDU[0], &usart_sim ); /* CLA */
230 ISO7816_SendChar( pAPDU[1], &usart_sim ); /* INS */
231 ISO7816_SendChar( pAPDU[2], &usart_sim ); /* P1 */
232 ISO7816_SendChar( pAPDU[3], &usart_sim ); /* P2 */
233 ISO7816_SendChar( pAPDU[4], &usart_sim ); /* P3 */
Christina Quast32a90ac2015-03-10 16:18:16 +0100234
235 /* Handle the four structures of command APDU */
Christina Quastc63df592015-03-10 23:32:45 +0100236 indexApdu = 5;
Christina Quast32a90ac2015-03-10 16:18:16 +0100237
238 if( wLength == 4 ) {
239 cmdCase = CASE1;
240 NeNc = 0;
241 }
242 else if( wLength == 5) {
243 cmdCase = CASE2;
244 NeNc = pAPDU[4]; /* C5 */
245 if (NeNc == 0) {
246 NeNc = 256;
247 }
248 }
249 else if( wLength == 6) {
250 NeNc = pAPDU[4]; /* C5 */
251 cmdCase = CASE3;
252 }
253 else if( wLength == 7) {
254 NeNc = pAPDU[4]; /* C5 */
255 if( NeNc == 0 ) {
256 cmdCase = CASE2;
257 NeNc = (pAPDU[5]<<8)+pAPDU[6];
258 }
259 else {
260 cmdCase = CASE3;
261 }
262 }
263 else {
264 NeNc = pAPDU[4]; /* C5 */
265 if( NeNc == 0 ) {
266 cmdCase = CASE3;
267 NeNc = (pAPDU[5]<<8)+pAPDU[6];
268 }
269 else {
270 cmdCase = CASE3;
271 }
272 }
273
274 TRACE_DEBUG("CASE=0x%X NeNc=0x%X\n\r", cmdCase, NeNc);
275
276 /* Handle Procedure Bytes */
277 do {
Christina Quaste24b9ac2015-04-10 17:44:49 +0200278 status = ISO7816_GetChar(&procByte, &usart_sim);
Christina Quast73c2b642015-04-07 13:49:26 +0200279 if (status != 0) {
280 return status;
281 }
Christina Quast2fcef412015-03-10 15:51:21 +0100282 TRACE_INFO("procByte: 0x%X\n\r", procByte);
Christina Quast32a90ac2015-03-10 16:18:16 +0100283 /* Handle NULL */
284 if ( procByte == ISO_NULL_VAL ) {
Christina Quast2fcef412015-03-10 15:51:21 +0100285 TRACE_INFO("INS\n\r");
Christina Quast32a90ac2015-03-10 16:18:16 +0100286 continue;
287 }
288 /* Handle SW1 */
289 else if ( ((procByte & 0xF0) ==0x60) || ((procByte & 0xF0) ==0x90) ) {
Christina Quast2fcef412015-03-10 15:51:21 +0100290 TRACE_INFO("SW1\n\r");
Christina Quast32a90ac2015-03-10 16:18:16 +0100291 SW1 = 1;
292 }
293 /* Handle INS */
294 else if ( pAPDU[1] == procByte) {
Christina Quast2fcef412015-03-10 15:51:21 +0100295 TRACE_INFO("HdlINS\n\r");
Christina Quast32a90ac2015-03-10 16:18:16 +0100296 if (cmdCase == CASE2) {
297 /* receive data from card */
298 do {
Christina Quaste24b9ac2015-04-10 17:44:49 +0200299 status = ISO7816_GetChar(&pMessage[indexMsg++], &usart_sim);
Christina Quast73c2b642015-04-07 13:49:26 +0200300 } while(( 0 != --NeNc) && (status == 0) );
301 if (status != 0) {
302 return status;
303 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100304 }
305 else {
306 /* Send data */
307 do {
Christina Quastc63df592015-03-10 23:32:45 +0100308 TRACE_INFO("Send %X", pAPDU[indexApdu]);
Christina Quaste24b9ac2015-04-10 17:44:49 +0200309 ISO7816_SendChar(pAPDU[indexApdu++], &usart_sim);
Christina Quast32a90ac2015-03-10 16:18:16 +0100310 } while( 0 != --NeNc );
311 }
312 }
313 /* Handle INS ^ 0xff */
Christina Quast767fdeb2015-04-07 13:50:20 +0200314 else
315 #pragma GCC diagnostic push
316 #pragma GCC diagnostic ignored "-Wsign-compare"
317 if ( pAPDU[1] == (procByte ^ 0xff)) {
318 #pragma GCC diagnostic pop
Christina Quast2fcef412015-03-10 15:51:21 +0100319 TRACE_INFO("HdlINS+\n\r");
Christina Quast32a90ac2015-03-10 16:18:16 +0100320 if (cmdCase == CASE2) {
321 /* receive data from card */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200322 status = ISO7816_GetChar(&pMessage[indexMsg++], &usart_sim);
Christina Quast73c2b642015-04-07 13:49:26 +0200323 if (status != 0) {
324 return status;
325 }
326 TRACE_INFO("Rcv: 0x%X\n\r", pMessage[indexMsg-1]);
Christina Quast32a90ac2015-03-10 16:18:16 +0100327 }
328 else {
Christina Quaste24b9ac2015-04-10 17:44:49 +0200329 status = ISO7816_SendChar(pAPDU[indexApdu++], &usart_sim);
Christina Quast73c2b642015-04-07 13:49:26 +0200330 if (status != 0) {
331 return status;
332 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100333 }
334 NeNc--;
335 }
336 else {
337 /* ?? */
Christina Quast2fcef412015-03-10 15:51:21 +0100338 TRACE_INFO("procByte=0x%X\n\r", procByte);
Christina Quast32a90ac2015-03-10 16:18:16 +0100339 break;
340 }
341 } while (NeNc != 0);
342
343 /* Status Bytes */
344 if (SW1 == 0) {
Christina Quaste24b9ac2015-04-10 17:44:49 +0200345 status = ISO7816_GetChar(&pMessage[indexMsg++], &usart_sim); /* SW1 */
Christina Quast73c2b642015-04-07 13:49:26 +0200346 if (status != 0) {
347 return status;
348 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100349 }
350 else {
Christina Quast73c2b642015-04-07 13:49:26 +0200351 pMessage[indexMsg++] = procByte;
Christina Quast32a90ac2015-03-10 16:18:16 +0100352 }
Christina Quaste24b9ac2015-04-10 17:44:49 +0200353 status = ISO7816_GetChar(&pMessage[indexMsg++], &usart_sim); /* SW2 */
Christina Quast73c2b642015-04-07 13:49:26 +0200354 if (status != 0) {
355 return status;
356 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100357
Christina Quast73c2b642015-04-07 13:49:26 +0200358 TRACE_WARNING("SW1=0x%X, SW2=0x%X\n\r", pMessage[indexMsg-2], pMessage[indexMsg-1]);
Christina Quast2fcef412015-03-10 15:51:21 +0100359
Christina Quast73c2b642015-04-07 13:49:26 +0200360 *retlen = indexMsg;
361 return status;
Christina Quast32a90ac2015-03-10 16:18:16 +0100362
363}
364
365/**
366 * Escape ISO7816
367 */
368void ISO7816_Escape( void )
369{
370 TRACE_DEBUG("For user, if needed\n\r");
371}
372
373/**
374 * Restart clock ISO7816
375 */
376void ISO7816_RestartClock( void )
377{
378 TRACE_DEBUG("ISO7816_RestartClock\n\r");
Christina Quaste24b9ac2015-04-10 17:44:49 +0200379 USART_SIM->US_BRGR = 13;
Christina Quast32a90ac2015-03-10 16:18:16 +0100380}
381
382/**
383 * Stop clock ISO7816
384 */
385void ISO7816_StopClock( void )
386{
387 TRACE_DEBUG("ISO7816_StopClock\n\r");
Christina Quaste24b9ac2015-04-10 17:44:49 +0200388 USART_SIM->US_BRGR = 0;
Christina Quast32a90ac2015-03-10 16:18:16 +0100389}
390
391/**
392 * T0 APDU
393 */
394void ISO7816_toAPDU( void )
395{
396 TRACE_DEBUG("ISO7816_toAPDU\n\r");
397 TRACE_DEBUG("Not supported at this time\n\r");
398}
399
400/**
401 * Answer To Reset (ATR)
402 * \param pAtr ATR buffer
403 * \param pLength Pointer for store the ATR length
404 * \return 0: if timeout else status of US_CSR
405 */
406uint32_t ISO7816_Datablock_ATR( uint8_t* pAtr, uint8_t* pLength )
407{
408 uint32_t i;
409 uint32_t j;
410 uint32_t y;
411 uint32_t status = 0;
412
413 *pLength = 0;
414
415 /* Read ATR TS */
416 // FIXME: There should always be a check for the GetChar return value..0 means timeout
Christina Quaste24b9ac2015-04-10 17:44:49 +0200417 status = ISO7816_GetChar(&pAtr[0], &usart_sim);
Christina Quast73c2b642015-04-07 13:49:26 +0200418 if (status != 0) {
Christina Quast32a90ac2015-03-10 16:18:16 +0100419 return status;
Christina Quast73c2b642015-04-07 13:49:26 +0200420 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100421
422 /* Read ATR T0 */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200423 status = ISO7816_GetChar(&pAtr[1], &usart_sim);
Christina Quast73c2b642015-04-07 13:49:26 +0200424 if (status != 0) {
425 return status;
426 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100427 y = pAtr[1] & 0xF0;
428 i = 2;
429
430 /* Read ATR Ti */
Christina Quast73c2b642015-04-07 13:49:26 +0200431 while (y && (status == 0)) {
Christina Quast32a90ac2015-03-10 16:18:16 +0100432
433 if (y & 0x10) { /* TA[i] */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200434 status = ISO7816_GetChar(&pAtr[i++], &usart_sim);
Christina Quast32a90ac2015-03-10 16:18:16 +0100435 }
436 if (y & 0x20) { /* TB[i] */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200437 status = ISO7816_GetChar(&pAtr[i++], &usart_sim);
Christina Quast32a90ac2015-03-10 16:18:16 +0100438 }
439 if (y & 0x40) { /* TC[i] */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200440 status = ISO7816_GetChar(&pAtr[i++], &usart_sim);
Christina Quast32a90ac2015-03-10 16:18:16 +0100441 }
442 if (y & 0x80) { /* TD[i] */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200443 status = ISO7816_GetChar(&pAtr[i], &usart_sim);
Christina Quast32a90ac2015-03-10 16:18:16 +0100444 y = pAtr[i++] & 0xF0;
445 }
446 else {
447 y = 0;
448 }
449 }
Christina Quast73c2b642015-04-07 13:49:26 +0200450 if (status != 0) {
451 return status;
452 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100453
454 /* Historical Bytes */
455 y = pAtr[1] & 0x0F;
Christina Quast73c2b642015-04-07 13:49:26 +0200456 for( j=0; (j < y) && (status == 0); j++ ) {
Christina Quaste24b9ac2015-04-10 17:44:49 +0200457 status = ISO7816_GetChar(&pAtr[i++], &usart_sim);
Christina Quast73c2b642015-04-07 13:49:26 +0200458 }
459
460 if (status != 0) {
461 return status;
Christina Quast32a90ac2015-03-10 16:18:16 +0100462 }
463
464 *pLength = i;
Christina Quast73c2b642015-04-07 13:49:26 +0200465 return status;
Christina Quast32a90ac2015-03-10 16:18:16 +0100466}
467
468/**
469 * Set data rate and clock frequency
470 * \param dwClockFrequency ICC clock frequency in KHz.
471 * \param dwDataRate ICC data rate in bpd
472 */
473void ISO7816_SetDataRateandClockFrequency( uint32_t dwClockFrequency, uint32_t dwDataRate )
474{
475 uint8_t ClockFrequency;
476
477 /* Define the baud rate divisor register */
478 /* CD = MCK / SCK */
479 /* SCK = FIDI x BAUD = 372 x 9600 */
480 /* BOARD_MCK */
481 /* CD = MCK/(FIDI x BAUD) = 48000000 / (372x9600) = 13 */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200482 USART_SIM->US_BRGR = BOARD_MCK / (dwClockFrequency*1000);
Christina Quast32a90ac2015-03-10 16:18:16 +0100483
Christina Quaste24b9ac2015-04-10 17:44:49 +0200484 ClockFrequency = BOARD_MCK / USART_SIM->US_BRGR;
Christina Quast32a90ac2015-03-10 16:18:16 +0100485
Christina Quaste24b9ac2015-04-10 17:44:49 +0200486 USART_SIM->US_FIDI = (ClockFrequency)/dwDataRate;
Christina Quast32a90ac2015-03-10 16:18:16 +0100487
488}
489
490/**
491 * Pin status for ISO7816 RESET
492 * \return 1 if the Pin RstMC is high; otherwise 0.
493 */
494uint8_t ISO7816_StatusReset( void )
495{
Christina Quaste24b9ac2015-04-10 17:44:49 +0200496 if (st_pinIso7816RstMC) {
497 return PIO_Get(st_pinIso7816RstMC);
498 }
499 return 0;
Christina Quast32a90ac2015-03-10 16:18:16 +0100500}
501
502/**
503 * cold reset
504 */
505void ISO7816_cold_reset( void )
506{
507 volatile uint32_t i;
508
Christina Quastc870b522015-04-09 13:31:58 +0200509 /* tb: wait ??? cycles*/
510 for( i=0; i<(400*(BOARD_MCK/1000000)); i++ ) {
Christina Quast32a90ac2015-03-10 16:18:16 +0100511 }
512
Christina Quaste24b9ac2015-04-10 17:44:49 +0200513 USART_SIM->US_RHR;
514 USART_SIM->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
Christina Quast32a90ac2015-03-10 16:18:16 +0100515
516 ISO7816_IccPowerOn();
517}
518
519/**
520 * Warm reset
521 */
522void ISO7816_warm_reset( void )
523{
524 volatile uint32_t i;
525
526// Clears Reset
527 ISO7816_IccPowerOff();
528
Christina Quastc870b522015-04-09 13:31:58 +0200529 /* tb: wait ??? cycles */
530 for( i=0; i<(400*(BOARD_MCK/1000000)); i++ ) {
Christina Quast32a90ac2015-03-10 16:18:16 +0100531 }
532
Christina Quaste24b9ac2015-04-10 17:44:49 +0200533 USART_SIM->US_RHR;
534 USART_SIM->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
Christina Quast32a90ac2015-03-10 16:18:16 +0100535
536// Sets Reset
537 ISO7816_IccPowerOn();
538}
539
540/**
541 * Decode ATR trace
542 * \param pAtr pointer on ATR buffer
543 */
544void ISO7816_Decode_ATR( uint8_t* pAtr )
545{
546 uint32_t i;
547 uint32_t j;
548 uint32_t y;
549 uint8_t offset;
550
551 printf("\n\r");
552 printf("ATR: Answer To Reset:\n\r");
553 printf("TS = 0x%X Initial character ",pAtr[0]);
554 if( pAtr[0] == 0x3B ) {
555
556 printf("Direct Convention\n\r");
557 }
558 else {
559 if( pAtr[0] == 0x3F ) {
560
561 printf("Inverse Convention\n\r");
562 }
563 else {
564 printf("BAD Convention\n\r");
565 }
566 }
567
568 printf("T0 = 0x%X Format caracter\n\r",pAtr[1]);
569 printf(" Number of historical bytes: K = %d\n\r", pAtr[1]&0x0F);
570 printf(" Presence further interface byte:\n\r");
571 if( pAtr[1]&0x80 ) {
572 printf("TA ");
573 }
574 if( pAtr[1]&0x40 ) {
575 printf("TB ");
576 }
577 if( pAtr[1]&0x20 ) {
578 printf("TC ");
579 }
580 if( pAtr[1]&0x10 ) {
581 printf("TD ");
582 }
583 if( pAtr[1] != 0 ) {
584 printf(" present\n\r");
585 }
586
587 i = 2;
588 y = pAtr[1] & 0xF0;
589
590 /* Read ATR Ti */
591 offset = 1;
592 while (y) {
593
594 if (y & 0x10) { /* TA[i] */
595 printf("TA[%d] = 0x%X ", offset, pAtr[i]);
596 if( offset == 1 ) {
597 printf("FI = %d ", (pAtr[i]>>8));
598 printf("DI = %d", (pAtr[i]&0x0F));
599 }
600 printf("\n\r");
601 i++;
602 }
603 if (y & 0x20) { /* TB[i] */
604 printf("TB[%d] = 0x%X\n\r", offset, pAtr[i]);
605 i++;
606 }
607 if (y & 0x40) { /* TC[i] */
608 printf("TC[%d] = 0x%X ", offset, pAtr[i]);
609 if( offset == 1 ) {
610 printf("Extra Guard Time: N = %d", pAtr[i]);
611 }
612 printf("\n\r");
613 i++;
614 }
615 if (y & 0x80) { /* TD[i] */
616 printf("TD[%d] = 0x%X\n\r", offset, pAtr[i]);
617 y = pAtr[i++] & 0xF0;
618 }
619 else {
620 y = 0;
621 }
622 offset++;
623 }
624
625 /* Historical Bytes */
626 printf("Historical bytes:\n\r");
627 y = pAtr[1] & 0x0F;
628 for( j=0; j < y; j++ ) {
629 printf(" 0x%X", pAtr[i]);
630 i++;
631 }
632 printf("\n\r\n\r");
633
634}
635
Christina Quaste24b9ac2015-04-10 17:44:49 +0200636void ISO7816_Set_Reset_Pin(const Pin *pPinIso7816RstMC) {
637 /* Pin ISO7816 initialize */
638 st_pinIso7816RstMC = (Pin *)pPinIso7816RstMC;
639}
640
Christina Quast32a90ac2015-03-10 16:18:16 +0100641/** Initializes a ISO driver
642 * \param pPinIso7816RstMC Pin ISO 7816 Rst MC
643 */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200644void ISO7816_Init( Usart_info *usart, bool master_clock )
Christina Quast32a90ac2015-03-10 16:18:16 +0100645{
Christina Quast3eab56e2015-04-10 15:38:49 +0200646 uint32_t clk;
Christina Quast32a90ac2015-03-10 16:18:16 +0100647 TRACE_DEBUG("ISO_Init\n\r");
648
Christina Quaste24b9ac2015-04-10 17:44:49 +0200649 Usart *us_base = usart->base;
650 uint32_t us_id = usart->id;
Christina Quast32a90ac2015-03-10 16:18:16 +0100651
Christina Quast3eab56e2015-04-10 15:38:49 +0200652 if (master_clock == true) {
653 clk = US_MR_USCLKS_MCK;
654 } else {
655 clk = US_MR_USCLKS_SCK;
656 }
657
Christina Quaste24b9ac2015-04-10 17:44:49 +0200658 USART_Configure( us_base,
Christina Quast32a90ac2015-03-10 16:18:16 +0100659 US_MR_USART_MODE_IS07816_T_0
Christina Quast3eab56e2015-04-10 15:38:49 +0200660 | clk
Christina Quast32a90ac2015-03-10 16:18:16 +0100661 | US_MR_NBSTOP_1_BIT
662 | US_MR_PAR_EVEN
663 | US_MR_CHRL_8_BIT
664 | US_MR_CLKO
Christina Quast68cc8592015-04-16 11:08:32 +0200665 | US_MR_INACK /* Inhibit errors */
666 | (3<<24), /* MAX_ITERATION */
Christina Quast32a90ac2015-03-10 16:18:16 +0100667 1,
668 0);
669
Christina Quast32a90ac2015-03-10 16:18:16 +0100670 /* Disable interrupts */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200671 us_base->US_IDR = (uint32_t) -1;
Christina Quast32a90ac2015-03-10 16:18:16 +0100672
Christina Quast68cc8592015-04-16 11:08:32 +0200673 /* Configure USART */
674 PMC_EnablePeripheral(us_id);
675
Christina Quaste24b9ac2015-04-10 17:44:49 +0200676 us_base->US_FIDI = 372; /* by default */
Christina Quast32a90ac2015-03-10 16:18:16 +0100677 /* Define the baud rate divisor register */
678 /* CD = MCK / SCK */
679 /* SCK = FIDI x BAUD = 372 x 9600 */
680 /* BOARD_MCK */
681 /* CD = MCK/(FIDI x BAUD) = 48000000 / (372x9600) = 13 */
Christina Quast4b814932015-04-17 18:47:34 +0200682 if (master_clock == true) {
683 us_base->US_BRGR = BOARD_MCK / (372*9600);
684 } else {
685 us_base->US_BRGR = US_BRGR_CD(1);
686 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100687}
688