blob: 59598ca4807e3430cefa230da5411fad67228b79 [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
132 TRACE_DEBUG("***Send char: 0x%X\n\r", CharToSend);
Christina Quast32a90ac2015-03-10 16:18:16 +0100133
Christina Quastec9c09e2015-04-16 10:45:39 +0200134 if( usart->state == USART_RCV ) {
Christina Quaste24b9ac2015-04-10 17:44:49 +0200135 us_base->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
Christina Quastec9c09e2015-04-16 10:45:39 +0200136 usart->state = USART_SEND;
Christina Quast32a90ac2015-03-10 16:18:16 +0100137 }
138
139 /* Wait USART ready for transmit */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200140 while((us_base->US_CSR & US_CSR_TXRDY) == 0) {}
Christina Quast32a90ac2015-03-10 16:18:16 +0100141 /* There is no character in the US_THR */
142
143 /* Transmit a char */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200144 us_base->US_THR = CharToSend;
Christina Quast32a90ac2015-03-10 16:18:16 +0100145
Christina Quaste24b9ac2015-04-10 17:44:49 +0200146 status = (us_base->US_CSR&(US_CSR_OVRE|US_CSR_FRAME|
Christina Quast32a90ac2015-03-10 16:18:16 +0100147 US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|
148 (1<<10)));
149
150 if (status != 0 ) {
Christina Quaste24b9ac2015-04-10 17:44:49 +0200151 TRACE_DEBUG("******* status: 0x%" PRIX32 " (Overrun: %" PRIX32
152 ", NACK: %" PRIX32 ", Timeout: %" PRIX32 ", underrun: %" PRIX32 ")\n\r",
153 status, ((status & US_CSR_OVRE)>> 5), ((status & US_CSR_NACK) >> 13),
Christina Quast32a90ac2015-03-10 16:18:16 +0100154 ((status & US_CSR_TIMEOUT) >> 8), ((status & (1 << 10)) >> 10));
Christina Quaste24b9ac2015-04-10 17:44:49 +0200155 TRACE_DEBUG("E (USART CSR reg):0x%" PRIX32 "\n\r", us_base->US_CSR);
156 TRACE_DEBUG("Nb (Number of errors):0x%" PRIX32 "\n\r", us_base->US_NER );
157 us_base->US_CR = US_CR_RSTSTA;
Christina Quast32a90ac2015-03-10 16:18:16 +0100158 }
159
160 /* Return status */
161 return( status );
162}
163
164
165/**
166 * Iso 7816 ICC power on
167 */
168static void ISO7816_IccPowerOn( void )
169{
170 /* Set RESET Master Card */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200171 if (st_pinIso7816RstMC) {
172 PIO_Set(st_pinIso7816RstMC);
173 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100174}
175
176/*----------------------------------------------------------------------------
177 * Exported functions
178 *----------------------------------------------------------------------------*/
179
180/**
181 * Iso 7816 ICC power off
182 */
183void ISO7816_IccPowerOff( void )
184{
185 /* Clear RESET Master Card */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200186 if (st_pinIso7816RstMC) {
187 PIO_Clear(st_pinIso7816RstMC);
188 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100189}
190
191/**
Christina Quast73c2b642015-04-07 13:49:26 +0200192 * Transfert Block TPDU T=0
193 * \param pAPDU APDU buffer
194 * \param pMessage Message buffer
195 * \param wLength Block length
196 * \param indexMsg Message index
197 * \return 0 on success, content of US_CSR otherwise
Christina Quast32a90ac2015-03-10 16:18:16 +0100198 */
Christina Quast73c2b642015-04-07 13:49:26 +0200199uint32_t ISO7816_XfrBlockTPDU_T0(const uint8_t *pAPDU,
Christina Quast32a90ac2015-03-10 16:18:16 +0100200 uint8_t *pMessage,
Christina Quast73c2b642015-04-07 13:49:26 +0200201 uint16_t wLength,
202 uint16_t *retlen )
Christina Quast32a90ac2015-03-10 16:18:16 +0100203{
204 uint16_t NeNc;
205 uint16_t indexApdu = 4;
Christina Quast73c2b642015-04-07 13:49:26 +0200206 uint16_t indexMsg = 0;
Christina Quast32a90ac2015-03-10 16:18:16 +0100207 uint8_t SW1 = 0;
208 uint8_t procByte;
209 uint8_t cmdCase;
Christina Quast73c2b642015-04-07 13:49:26 +0200210 uint32_t status = 0;
Christina Quast32a90ac2015-03-10 16:18:16 +0100211
Christina Quastc63df592015-03-10 23:32:45 +0100212 TRACE_INFO("pAPDU[0]=0x%X\n\r",pAPDU[0]);
213 TRACE_INFO("pAPDU[1]=0x%X\n\r",pAPDU[1]);
214 TRACE_INFO("pAPDU[2]=0x%X\n\r",pAPDU[2]);
215 TRACE_INFO("pAPDU[3]=0x%X\n\r",pAPDU[3]);
216 TRACE_INFO("pAPDU[4]=0x%X\n\r",pAPDU[4]);
217 TRACE_INFO("pAPDU[5]=0x%X\n\r",pAPDU[5]);
218 TRACE_INFO("wlength=%d\n\r",wLength);
Christina Quast32a90ac2015-03-10 16:18:16 +0100219
Christina Quaste24b9ac2015-04-10 17:44:49 +0200220 ISO7816_SendChar( pAPDU[0], &usart_sim ); /* CLA */
221 ISO7816_SendChar( pAPDU[1], &usart_sim ); /* INS */
222 ISO7816_SendChar( pAPDU[2], &usart_sim ); /* P1 */
223 ISO7816_SendChar( pAPDU[3], &usart_sim ); /* P2 */
224 ISO7816_SendChar( pAPDU[4], &usart_sim ); /* P3 */
Christina Quast32a90ac2015-03-10 16:18:16 +0100225
226 /* Handle the four structures of command APDU */
Christina Quastc63df592015-03-10 23:32:45 +0100227 indexApdu = 5;
Christina Quast32a90ac2015-03-10 16:18:16 +0100228
229 if( wLength == 4 ) {
230 cmdCase = CASE1;
231 NeNc = 0;
232 }
233 else if( wLength == 5) {
234 cmdCase = CASE2;
235 NeNc = pAPDU[4]; /* C5 */
236 if (NeNc == 0) {
237 NeNc = 256;
238 }
239 }
240 else if( wLength == 6) {
241 NeNc = pAPDU[4]; /* C5 */
242 cmdCase = CASE3;
243 }
244 else if( wLength == 7) {
245 NeNc = pAPDU[4]; /* C5 */
246 if( NeNc == 0 ) {
247 cmdCase = CASE2;
248 NeNc = (pAPDU[5]<<8)+pAPDU[6];
249 }
250 else {
251 cmdCase = CASE3;
252 }
253 }
254 else {
255 NeNc = pAPDU[4]; /* C5 */
256 if( NeNc == 0 ) {
257 cmdCase = CASE3;
258 NeNc = (pAPDU[5]<<8)+pAPDU[6];
259 }
260 else {
261 cmdCase = CASE3;
262 }
263 }
264
265 TRACE_DEBUG("CASE=0x%X NeNc=0x%X\n\r", cmdCase, NeNc);
266
267 /* Handle Procedure Bytes */
268 do {
Christina Quaste24b9ac2015-04-10 17:44:49 +0200269 status = ISO7816_GetChar(&procByte, &usart_sim);
Christina Quast73c2b642015-04-07 13:49:26 +0200270 if (status != 0) {
271 return status;
272 }
Christina Quast2fcef412015-03-10 15:51:21 +0100273 TRACE_INFO("procByte: 0x%X\n\r", procByte);
Christina Quast32a90ac2015-03-10 16:18:16 +0100274 /* Handle NULL */
275 if ( procByte == ISO_NULL_VAL ) {
Christina Quast2fcef412015-03-10 15:51:21 +0100276 TRACE_INFO("INS\n\r");
Christina Quast32a90ac2015-03-10 16:18:16 +0100277 continue;
278 }
279 /* Handle SW1 */
280 else if ( ((procByte & 0xF0) ==0x60) || ((procByte & 0xF0) ==0x90) ) {
Christina Quast2fcef412015-03-10 15:51:21 +0100281 TRACE_INFO("SW1\n\r");
Christina Quast32a90ac2015-03-10 16:18:16 +0100282 SW1 = 1;
283 }
284 /* Handle INS */
285 else if ( pAPDU[1] == procByte) {
Christina Quast2fcef412015-03-10 15:51:21 +0100286 TRACE_INFO("HdlINS\n\r");
Christina Quast32a90ac2015-03-10 16:18:16 +0100287 if (cmdCase == CASE2) {
288 /* receive data from card */
289 do {
Christina Quaste24b9ac2015-04-10 17:44:49 +0200290 status = ISO7816_GetChar(&pMessage[indexMsg++], &usart_sim);
Christina Quast73c2b642015-04-07 13:49:26 +0200291 } while(( 0 != --NeNc) && (status == 0) );
292 if (status != 0) {
293 return status;
294 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100295 }
296 else {
297 /* Send data */
298 do {
Christina Quastc63df592015-03-10 23:32:45 +0100299 TRACE_INFO("Send %X", pAPDU[indexApdu]);
Christina Quaste24b9ac2015-04-10 17:44:49 +0200300 ISO7816_SendChar(pAPDU[indexApdu++], &usart_sim);
Christina Quast32a90ac2015-03-10 16:18:16 +0100301 } while( 0 != --NeNc );
302 }
303 }
304 /* Handle INS ^ 0xff */
Christina Quast767fdeb2015-04-07 13:50:20 +0200305 else
306 #pragma GCC diagnostic push
307 #pragma GCC diagnostic ignored "-Wsign-compare"
308 if ( pAPDU[1] == (procByte ^ 0xff)) {
309 #pragma GCC diagnostic pop
Christina Quast2fcef412015-03-10 15:51:21 +0100310 TRACE_INFO("HdlINS+\n\r");
Christina Quast32a90ac2015-03-10 16:18:16 +0100311 if (cmdCase == CASE2) {
312 /* receive data from card */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200313 status = ISO7816_GetChar(&pMessage[indexMsg++], &usart_sim);
Christina Quast73c2b642015-04-07 13:49:26 +0200314 if (status != 0) {
315 return status;
316 }
317 TRACE_INFO("Rcv: 0x%X\n\r", pMessage[indexMsg-1]);
Christina Quast32a90ac2015-03-10 16:18:16 +0100318 }
319 else {
Christina Quaste24b9ac2015-04-10 17:44:49 +0200320 status = ISO7816_SendChar(pAPDU[indexApdu++], &usart_sim);
Christina Quast73c2b642015-04-07 13:49:26 +0200321 if (status != 0) {
322 return status;
323 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100324 }
325 NeNc--;
326 }
327 else {
328 /* ?? */
Christina Quast2fcef412015-03-10 15:51:21 +0100329 TRACE_INFO("procByte=0x%X\n\r", procByte);
Christina Quast32a90ac2015-03-10 16:18:16 +0100330 break;
331 }
332 } while (NeNc != 0);
333
334 /* Status Bytes */
335 if (SW1 == 0) {
Christina Quaste24b9ac2015-04-10 17:44:49 +0200336 status = ISO7816_GetChar(&pMessage[indexMsg++], &usart_sim); /* SW1 */
Christina Quast73c2b642015-04-07 13:49:26 +0200337 if (status != 0) {
338 return status;
339 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100340 }
341 else {
Christina Quast73c2b642015-04-07 13:49:26 +0200342 pMessage[indexMsg++] = procByte;
Christina Quast32a90ac2015-03-10 16:18:16 +0100343 }
Christina Quaste24b9ac2015-04-10 17:44:49 +0200344 status = ISO7816_GetChar(&pMessage[indexMsg++], &usart_sim); /* SW2 */
Christina Quast73c2b642015-04-07 13:49:26 +0200345 if (status != 0) {
346 return status;
347 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100348
Christina Quast73c2b642015-04-07 13:49:26 +0200349 TRACE_WARNING("SW1=0x%X, SW2=0x%X\n\r", pMessage[indexMsg-2], pMessage[indexMsg-1]);
Christina Quast2fcef412015-03-10 15:51:21 +0100350
Christina Quast73c2b642015-04-07 13:49:26 +0200351 *retlen = indexMsg;
352 return status;
Christina Quast32a90ac2015-03-10 16:18:16 +0100353
354}
355
356/**
357 * Escape ISO7816
358 */
359void ISO7816_Escape( void )
360{
361 TRACE_DEBUG("For user, if needed\n\r");
362}
363
364/**
365 * Restart clock ISO7816
366 */
367void ISO7816_RestartClock( void )
368{
369 TRACE_DEBUG("ISO7816_RestartClock\n\r");
Christina Quaste24b9ac2015-04-10 17:44:49 +0200370 USART_SIM->US_BRGR = 13;
Christina Quast32a90ac2015-03-10 16:18:16 +0100371}
372
373/**
374 * Stop clock ISO7816
375 */
376void ISO7816_StopClock( void )
377{
378 TRACE_DEBUG("ISO7816_StopClock\n\r");
Christina Quaste24b9ac2015-04-10 17:44:49 +0200379 USART_SIM->US_BRGR = 0;
Christina Quast32a90ac2015-03-10 16:18:16 +0100380}
381
382/**
383 * T0 APDU
384 */
385void ISO7816_toAPDU( void )
386{
387 TRACE_DEBUG("ISO7816_toAPDU\n\r");
388 TRACE_DEBUG("Not supported at this time\n\r");
389}
390
391/**
392 * Answer To Reset (ATR)
393 * \param pAtr ATR buffer
394 * \param pLength Pointer for store the ATR length
395 * \return 0: if timeout else status of US_CSR
396 */
397uint32_t ISO7816_Datablock_ATR( uint8_t* pAtr, uint8_t* pLength )
398{
399 uint32_t i;
400 uint32_t j;
401 uint32_t y;
402 uint32_t status = 0;
403
404 *pLength = 0;
405
406 /* Read ATR TS */
407 // FIXME: There should always be a check for the GetChar return value..0 means timeout
Christina Quaste24b9ac2015-04-10 17:44:49 +0200408 status = ISO7816_GetChar(&pAtr[0], &usart_sim);
Christina Quast73c2b642015-04-07 13:49:26 +0200409 if (status != 0) {
Christina Quast32a90ac2015-03-10 16:18:16 +0100410 return status;
Christina Quast73c2b642015-04-07 13:49:26 +0200411 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100412
413 /* Read ATR T0 */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200414 status = ISO7816_GetChar(&pAtr[1], &usart_sim);
Christina Quast73c2b642015-04-07 13:49:26 +0200415 if (status != 0) {
416 return status;
417 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100418 y = pAtr[1] & 0xF0;
419 i = 2;
420
421 /* Read ATR Ti */
Christina Quast73c2b642015-04-07 13:49:26 +0200422 while (y && (status == 0)) {
Christina Quast32a90ac2015-03-10 16:18:16 +0100423
424 if (y & 0x10) { /* TA[i] */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200425 status = ISO7816_GetChar(&pAtr[i++], &usart_sim);
Christina Quast32a90ac2015-03-10 16:18:16 +0100426 }
427 if (y & 0x20) { /* TB[i] */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200428 status = ISO7816_GetChar(&pAtr[i++], &usart_sim);
Christina Quast32a90ac2015-03-10 16:18:16 +0100429 }
430 if (y & 0x40) { /* TC[i] */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200431 status = ISO7816_GetChar(&pAtr[i++], &usart_sim);
Christina Quast32a90ac2015-03-10 16:18:16 +0100432 }
433 if (y & 0x80) { /* TD[i] */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200434 status = ISO7816_GetChar(&pAtr[i], &usart_sim);
Christina Quast32a90ac2015-03-10 16:18:16 +0100435 y = pAtr[i++] & 0xF0;
436 }
437 else {
438 y = 0;
439 }
440 }
Christina Quast73c2b642015-04-07 13:49:26 +0200441 if (status != 0) {
442 return status;
443 }
Christina Quast32a90ac2015-03-10 16:18:16 +0100444
445 /* Historical Bytes */
446 y = pAtr[1] & 0x0F;
Christina Quast73c2b642015-04-07 13:49:26 +0200447 for( j=0; (j < y) && (status == 0); j++ ) {
Christina Quaste24b9ac2015-04-10 17:44:49 +0200448 status = ISO7816_GetChar(&pAtr[i++], &usart_sim);
Christina Quast73c2b642015-04-07 13:49:26 +0200449 }
450
451 if (status != 0) {
452 return status;
Christina Quast32a90ac2015-03-10 16:18:16 +0100453 }
454
455 *pLength = i;
Christina Quast73c2b642015-04-07 13:49:26 +0200456 return status;
Christina Quast32a90ac2015-03-10 16:18:16 +0100457}
458
459/**
460 * Set data rate and clock frequency
461 * \param dwClockFrequency ICC clock frequency in KHz.
462 * \param dwDataRate ICC data rate in bpd
463 */
464void ISO7816_SetDataRateandClockFrequency( uint32_t dwClockFrequency, uint32_t dwDataRate )
465{
466 uint8_t ClockFrequency;
467
468 /* Define the baud rate divisor register */
469 /* CD = MCK / SCK */
470 /* SCK = FIDI x BAUD = 372 x 9600 */
471 /* BOARD_MCK */
472 /* CD = MCK/(FIDI x BAUD) = 48000000 / (372x9600) = 13 */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200473 USART_SIM->US_BRGR = BOARD_MCK / (dwClockFrequency*1000);
Christina Quast32a90ac2015-03-10 16:18:16 +0100474
Christina Quaste24b9ac2015-04-10 17:44:49 +0200475 ClockFrequency = BOARD_MCK / USART_SIM->US_BRGR;
Christina Quast32a90ac2015-03-10 16:18:16 +0100476
Christina Quaste24b9ac2015-04-10 17:44:49 +0200477 USART_SIM->US_FIDI = (ClockFrequency)/dwDataRate;
Christina Quast32a90ac2015-03-10 16:18:16 +0100478
479}
480
481/**
482 * Pin status for ISO7816 RESET
483 * \return 1 if the Pin RstMC is high; otherwise 0.
484 */
485uint8_t ISO7816_StatusReset( void )
486{
Christina Quaste24b9ac2015-04-10 17:44:49 +0200487 if (st_pinIso7816RstMC) {
488 return PIO_Get(st_pinIso7816RstMC);
489 }
490 return 0;
Christina Quast32a90ac2015-03-10 16:18:16 +0100491}
492
493/**
494 * cold reset
495 */
496void ISO7816_cold_reset( void )
497{
498 volatile uint32_t i;
499
Christina Quastc870b522015-04-09 13:31:58 +0200500 /* tb: wait ??? cycles*/
501 for( i=0; i<(400*(BOARD_MCK/1000000)); i++ ) {
Christina Quast32a90ac2015-03-10 16:18:16 +0100502 }
503
Christina Quaste24b9ac2015-04-10 17:44:49 +0200504 USART_SIM->US_RHR;
505 USART_SIM->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
Christina Quast32a90ac2015-03-10 16:18:16 +0100506
507 ISO7816_IccPowerOn();
508}
509
510/**
511 * Warm reset
512 */
513void ISO7816_warm_reset( void )
514{
515 volatile uint32_t i;
516
517// Clears Reset
518 ISO7816_IccPowerOff();
519
Christina Quastc870b522015-04-09 13:31:58 +0200520 /* tb: wait ??? cycles */
521 for( i=0; i<(400*(BOARD_MCK/1000000)); i++ ) {
Christina Quast32a90ac2015-03-10 16:18:16 +0100522 }
523
Christina Quaste24b9ac2015-04-10 17:44:49 +0200524 USART_SIM->US_RHR;
525 USART_SIM->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
Christina Quast32a90ac2015-03-10 16:18:16 +0100526
527// Sets Reset
528 ISO7816_IccPowerOn();
529}
530
531/**
532 * Decode ATR trace
533 * \param pAtr pointer on ATR buffer
534 */
535void ISO7816_Decode_ATR( uint8_t* pAtr )
536{
537 uint32_t i;
538 uint32_t j;
539 uint32_t y;
540 uint8_t offset;
541
542 printf("\n\r");
543 printf("ATR: Answer To Reset:\n\r");
544 printf("TS = 0x%X Initial character ",pAtr[0]);
545 if( pAtr[0] == 0x3B ) {
546
547 printf("Direct Convention\n\r");
548 }
549 else {
550 if( pAtr[0] == 0x3F ) {
551
552 printf("Inverse Convention\n\r");
553 }
554 else {
555 printf("BAD Convention\n\r");
556 }
557 }
558
559 printf("T0 = 0x%X Format caracter\n\r",pAtr[1]);
560 printf(" Number of historical bytes: K = %d\n\r", pAtr[1]&0x0F);
561 printf(" Presence further interface byte:\n\r");
562 if( pAtr[1]&0x80 ) {
563 printf("TA ");
564 }
565 if( pAtr[1]&0x40 ) {
566 printf("TB ");
567 }
568 if( pAtr[1]&0x20 ) {
569 printf("TC ");
570 }
571 if( pAtr[1]&0x10 ) {
572 printf("TD ");
573 }
574 if( pAtr[1] != 0 ) {
575 printf(" present\n\r");
576 }
577
578 i = 2;
579 y = pAtr[1] & 0xF0;
580
581 /* Read ATR Ti */
582 offset = 1;
583 while (y) {
584
585 if (y & 0x10) { /* TA[i] */
586 printf("TA[%d] = 0x%X ", offset, pAtr[i]);
587 if( offset == 1 ) {
588 printf("FI = %d ", (pAtr[i]>>8));
589 printf("DI = %d", (pAtr[i]&0x0F));
590 }
591 printf("\n\r");
592 i++;
593 }
594 if (y & 0x20) { /* TB[i] */
595 printf("TB[%d] = 0x%X\n\r", offset, pAtr[i]);
596 i++;
597 }
598 if (y & 0x40) { /* TC[i] */
599 printf("TC[%d] = 0x%X ", offset, pAtr[i]);
600 if( offset == 1 ) {
601 printf("Extra Guard Time: N = %d", pAtr[i]);
602 }
603 printf("\n\r");
604 i++;
605 }
606 if (y & 0x80) { /* TD[i] */
607 printf("TD[%d] = 0x%X\n\r", offset, pAtr[i]);
608 y = pAtr[i++] & 0xF0;
609 }
610 else {
611 y = 0;
612 }
613 offset++;
614 }
615
616 /* Historical Bytes */
617 printf("Historical bytes:\n\r");
618 y = pAtr[1] & 0x0F;
619 for( j=0; j < y; j++ ) {
620 printf(" 0x%X", pAtr[i]);
621 i++;
622 }
623 printf("\n\r\n\r");
624
625}
626
Christina Quaste24b9ac2015-04-10 17:44:49 +0200627void ISO7816_Set_Reset_Pin(const Pin *pPinIso7816RstMC) {
628 /* Pin ISO7816 initialize */
629 st_pinIso7816RstMC = (Pin *)pPinIso7816RstMC;
630}
631
Christina Quast32a90ac2015-03-10 16:18:16 +0100632/** Initializes a ISO driver
633 * \param pPinIso7816RstMC Pin ISO 7816 Rst MC
634 */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200635void ISO7816_Init( Usart_info *usart, bool master_clock )
Christina Quast32a90ac2015-03-10 16:18:16 +0100636{
Christina Quast3eab56e2015-04-10 15:38:49 +0200637 uint32_t clk;
Christina Quast32a90ac2015-03-10 16:18:16 +0100638 TRACE_DEBUG("ISO_Init\n\r");
639
Christina Quaste24b9ac2015-04-10 17:44:49 +0200640 Usart *us_base = usart->base;
641 uint32_t us_id = usart->id;
Christina Quast32a90ac2015-03-10 16:18:16 +0100642
Christina Quast3eab56e2015-04-10 15:38:49 +0200643 if (master_clock == true) {
644 clk = US_MR_USCLKS_MCK;
645 } else {
646 clk = US_MR_USCLKS_SCK;
647 }
648
Christina Quaste24b9ac2015-04-10 17:44:49 +0200649 USART_Configure( us_base,
Christina Quast32a90ac2015-03-10 16:18:16 +0100650 US_MR_USART_MODE_IS07816_T_0
Christina Quast3eab56e2015-04-10 15:38:49 +0200651 | clk
Christina Quast32a90ac2015-03-10 16:18:16 +0100652 | US_MR_NBSTOP_1_BIT
653 | US_MR_PAR_EVEN
654 | US_MR_CHRL_8_BIT
655 | US_MR_CLKO
Christina Quastfd069dc2015-04-12 13:32:12 +0200656 | (0<<24), /* MAX_ITERATION */
Christina Quast32a90ac2015-03-10 16:18:16 +0100657 1,
658 0);
659
660 /* Configure USART */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200661 PMC_EnablePeripheral(us_id);
Christina Quast32a90ac2015-03-10 16:18:16 +0100662 /* Disable interrupts */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200663 us_base->US_IDR = (uint32_t) -1;
Christina Quast32a90ac2015-03-10 16:18:16 +0100664
Christina Quaste24b9ac2015-04-10 17:44:49 +0200665 us_base->US_FIDI = 372; /* by default */
Christina Quast32a90ac2015-03-10 16:18:16 +0100666 /* Define the baud rate divisor register */
667 /* CD = MCK / SCK */
668 /* SCK = FIDI x BAUD = 372 x 9600 */
669 /* BOARD_MCK */
670 /* CD = MCK/(FIDI x BAUD) = 48000000 / (372x9600) = 13 */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200671 us_base->US_BRGR = BOARD_MCK / (372*9600);
Christina Quast32a90ac2015-03-10 16:18:16 +0100672
673 /* Write the Timeguard Register */
Christina Quaste24b9ac2015-04-10 17:44:49 +0200674 us_base->US_TTGR = 5;
Christina Quast32a90ac2015-03-10 16:18:16 +0100675
Christina Quaste24b9ac2015-04-10 17:44:49 +0200676 USART_SetTransmitterEnabled(us_base, 1);
677 USART_SetReceiverEnabled(us_base, 1);
Christina Quast32a90ac2015-03-10 16:18:16 +0100678
679}
680