blob: 0cc5da01e318a015d0a37ddd69540b9c1d0c650e [file] [log] [blame]
Christina Quast32906bb2015-02-24 11:35:19 +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 * Headers
32 *------------------------------------------------------------------------------*/
33
34#include "board.h"
35
36#include <string.h>
37
38/*------------------------------------------------------------------------------
39 * Internal definitions
40 *------------------------------------------------------------------------------*/
41
42/** Maximum ucSize in bytes of the smartcard answer to a command.*/
43#define MAX_ANSWER_SIZE 10
44
45/** Maximum ATR ucSize in bytes.*/
46#define MAX_ATR_SIZE 55
47
48/** USB states */
49/// Use for power management
50#define STATE_IDLE 0
51/// The USB device is in suspend state
52#define STATE_SUSPEND 4
53/// The USB device is in resume state
54#define STATE_RESUME 5
55
Christina Quast578daaa2015-03-13 23:46:01 +010056/* WTX (Wait time extension):
57* R-block PCB begins with (msb) 10 , ends with 000011 for WTX req, 100011 for WTX resp
58*
59* The standard says:
60* Rule 3 β€” If the card requires more than BWT to process the previously received I-block, it transmits S(WTX
61* request) where INF conveys one byte encoding an integer multiplier of the BWT value. The interface device
62* shall acknowledge by S(WTX response) with the same INF.
63* The time allocated starts at the leading edge of the last character of S(WTX response).
64*/
Christina Quasta4d1d162015-04-06 20:41:50 +020065// FIXME: Two times the same name for the define, which one is right?
66//#define WTX_req 0b10000011
67//#define WTX_req 0b10100011
Christina Quast578daaa2015-03-13 23:46:01 +010068// Alternatively:
69/* For T = 0 Protocol: The firmware on receiving the NULL (0x60) Procedure byte from the card, notifies
70it to the driver using the RDR_to_PC_DataBlock response. During this period, the reception of bytes
71from the smart card is still in progress and hence the device cannot indefinitely wait for IN tokens on
72the USB bulk-in endpoint. Hence, it is required of the driver to readily supply β€˜IN’ tokens on the USB
73bulk-in endpoint. On failure to do so, some of the wait time extension responses, will not be queued to
74the driver.
75*/
76
Christina Quast32906bb2015-02-24 11:35:19 +010077/*------------------------------------------------------------------------------
78 * Internal variables
79 *------------------------------------------------------------------------------*/
80/** USB state: suspend, resume, idle */
81unsigned char USBState = STATE_IDLE;
82
83/** ISO7816 pins */
84static const Pin pinsISO7816_PHONE[] = {PINS_ISO7816_PHONE};
Christina Quast8043fdd2015-03-04 18:45:30 +010085/** Bus switch pins */
Christina Quast30418542015-04-05 10:08:06 +020086static const Pin pins_bus[] = {PINS_BUS_DEFAULT};
Christina Quast4bcc0232015-03-24 21:59:32 +010087// FIXME: temporary enable bus switch
Christina Quast30418542015-04-05 10:08:06 +020088//static const Pin pins_bus[] = {PINS_BUS_SNIFF};
Christina Quast4bcc0232015-03-24 21:59:32 +010089
Christina Quast32906bb2015-02-24 11:35:19 +010090/** ISO7816 RST pin */
91static const Pin pinIso7816RstMC = PIN_ISO7816_RST_PHONE;
92static uint8_t sim_inserted = 0;
93
94static const Pin pPwr[] = {
95 /* Enable power converter 4.5-6V to 3.3V; low: off */
96 {SIM_PWEN, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT},
97
98 /* Enable second power converter: VCC_PHONE to VCC_SIM; high: off */
99 {VCC_FWD, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
100};
101
102
Christina Quast8e5381c2015-04-03 11:37:17 +0200103static const Pin pinPhoneRST = PIN_ISO7816_RST_PHONE;
104
105#define PR TRACE_INFO
Christina Quast32906bb2015-02-24 11:35:19 +0100106
107/* ===================================================*/
108/* Taken from iso7816_4.c */
109/* ===================================================*/
110/** Flip flop for send and receive char */
111#define USART_SEND 0
112#define USART_RCV 1
Christina Quastce296b92015-03-18 18:41:19 +0100113
114#define NONE 9
115#define RST_RCVD 10
116#define WAIT_CMD_PHONE 11
117#define WAIT_CMD_PC 12
118#define WAIT_ATR 13
Christina Quast32906bb2015-02-24 11:35:19 +0100119/*-----------------------------------------------------------------------------
120 * Internal variables
121 *-----------------------------------------------------------------------------*/
122/** Variable for state of send and receive froom USART */
123static uint8_t StateUsartGlobal = USART_RCV;
Christina Quast32906bb2015-02-24 11:35:19 +0100124
Christina Quastce296b92015-03-18 18:41:19 +0100125static uint32_t state;
Christina Quastc0aa7692015-02-25 14:02:01 +0100126extern uint8_t rcvdChar;
Christina Quast32906bb2015-02-24 11:35:19 +0100127
Christina Quast0ca83902015-03-22 19:05:23 +0100128extern volatile uint8_t timeout_occured;
129
Christina Quast4bcc0232015-03-24 21:59:32 +0100130static rst_cnt = 0;
131
Christina Quast32906bb2015-02-24 11:35:19 +0100132/*-----------------------------------------------------------------------------
133 * Interrupt routines
134 *-----------------------------------------------------------------------------*/
Christina Quast578daaa2015-03-13 23:46:01 +0100135#define RESET 'R'
Christina Quast32906bb2015-02-24 11:35:19 +0100136static void ISR_PhoneRST( const Pin *pPin)
137{
Christina Quastd3630cc2015-04-03 11:38:24 +0200138 printf("+++ Int!! %x\n\r", pinPhoneRST.pio->PIO_ISR);
139 if ( ((pinPhoneRST.pio->PIO_ISR & pinPhoneRST.mask) != 0) )
140 {
141 if(PIO_Get( &pinPhoneRST ) == 0) {
142 printf(" 0 ");
143 } else {
144 printf(" 1 ");
145 }
146 }
Christina Quast4bcc0232015-03-24 21:59:32 +0100147 state = RST_RCVD;
148
149/* if (state == NONE || rst_cnt > 2) {
Christina Quastce296b92015-03-18 18:41:19 +0100150 state = RST_RCVD;
151 }
Christina Quast4bcc0232015-03-24 21:59:32 +0100152 rst_cnt++;
153*/
Christina Quastc0aa7692015-02-25 14:02:01 +0100154 // FIXME: What to do on reset?
Christina Quastce296b92015-03-18 18:41:19 +0100155 // FIXME: It seems like the phone is constantly sending a lot of these RSTs
Christina Quastbdaa9542015-04-06 00:52:08 +0200156 PIO_DisableIt( &pinPhoneRST ) ;
Christina Quast32906bb2015-02-24 11:35:19 +0100157}
158
159static void Config_PhoneRST_IrqHandler()
160{
161 PIO_Configure( &pinPhoneRST, 1);
162// PIO_Configure( &pinPhoneClk, 1);
163 PIO_ConfigureIt( &pinPhoneRST, ISR_PhoneRST ) ;
164// PIO_ConfigureIt( &pinPhoneClk, ISR_PhoneRST ) ;
165 PIO_EnableIt( &pinPhoneRST ) ;
166// PIO_EnableIt( &pinPhoneClk ) ;
167 NVIC_EnableIRQ( PIOA_IRQn );
168}
169
170/**
171 * Get a character from ISO7816
172 * \param pCharToReceive Pointer for store the received char
173 * \return 0: if timeout else status of US_CSR
174 */
175/* FIXME: This code is taken from cciddriver.c
176 --> Reuse the code!!! */
177uint32_t _ISO7816_GetChar( uint8_t *pCharToReceive )
178{
179 uint32_t status;
180 uint32_t timeout=0;
181
182 TRACE_DEBUG("--");
183
184 if( StateUsartGlobal == USART_SEND ) {
185 while((USART_PHONE->US_CSR & US_CSR_TXEMPTY) == 0) {}
186 USART_PHONE->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
187 StateUsartGlobal = USART_RCV;
188 }
189
190 /* Wait USART ready for reception */
191 while( ((USART_PHONE->US_CSR & US_CSR_RXRDY) == 0) ) {
192 if(timeout++ > 12000 * (BOARD_MCK/1000000)) {
193 TRACE_DEBUG("TimeOut\n\r");
194 return( 0 );
195 }
196 }
197
198 /* At least one complete character has been received and US_RHR has not yet been read. */
199
200 /* Get a char */
201 *pCharToReceive = ((USART_PHONE->US_RHR) & 0xFF);
202
203 status = (USART_PHONE->US_CSR&(US_CSR_OVRE|US_CSR_FRAME|
204 US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|
205 (1<<10)));
206
207 if (status != 0 ) {
208 TRACE_DEBUG("R:0x%X\n\r", status);
209 TRACE_DEBUG("R:0x%X\n\r", USART_PHONE->US_CSR);
210 TRACE_DEBUG("Nb:0x%X\n\r", USART_PHONE->US_NER );
211 USART_PHONE->US_CR = US_CR_RSTSTA;
212 }
213
214 /* Return status */
215 return( status );
216}
217
218/**
219 * Send a char to ISO7816
220 * \param CharToSend char to be send
221 * \return status of US_CSR
222 */
223uint32_t _ISO7816_SendChar( uint8_t CharToSend )
224{
225 uint32_t status;
226
227 TRACE_DEBUG("********** Send char: %c (0x%X)\n\r", CharToSend, CharToSend);
228
229 if( StateUsartGlobal == USART_RCV ) {
230 USART_PHONE->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
231 StateUsartGlobal = USART_SEND;
232 }
233
234 /* Wait USART ready for transmit */
235 while((USART_PHONE->US_CSR & US_CSR_TXRDY) == 0) {}
236 /* There is no character in the US_THR */
237
238 /* Transmit a char */
239 USART_PHONE->US_THR = CharToSend;
240
241 status = (USART_PHONE->US_CSR&(US_CSR_OVRE|US_CSR_FRAME|
242 US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|
243 (1<<10)));
244
245 if (status != 0 ) {
Christina Quastc0aa7692015-02-25 14:02:01 +0100246 TRACE_DEBUG("******* status: 0x%X (Overrun: %lu, NACK: %lu, Timeout: %lu, underrun: %lu)\n\r",
Christina Quast32906bb2015-02-24 11:35:19 +0100247 status, ((status & US_CSR_OVRE)>> 5), ((status & US_CSR_NACK) >> 13),
248 ((status & US_CSR_TIMEOUT) >> 8), ((status & (1 << 10)) >> 10));
249
250 TRACE_DEBUG("E (USART CSR reg):0x%X\n\r", USART_PHONE->US_CSR);
251 TRACE_DEBUG("Nb (Number of errors):0x%X\n\r", USART_PHONE->US_NER );
252 USART_PHONE->US_CR = US_CR_RSTSTA;
253 }
254
255 /* Return status */
256 return( status );
257}
258
Christina Quast32906bb2015-02-24 11:35:19 +0100259void Phone_Master_Init( void ) {
260
261 PIO_Configure( pinsISO7816_PHONE, PIO_LISTSIZE( pinsISO7816_PHONE ) ) ;
Christina Quast8043fdd2015-03-04 18:45:30 +0100262 PIO_Configure( pins_bus, PIO_LISTSIZE( pins_bus) ) ;
263
Christina Quast32906bb2015-02-24 11:35:19 +0100264 Config_PhoneRST_IrqHandler();
Christina Quast32906bb2015-02-24 11:35:19 +0100265
Christina Quastc0aa7692015-02-25 14:02:01 +0100266 _ISO7816_Init();
267
268 USART_SetTransmitterEnabled(USART_PHONE, 1);
269 USART_SetReceiverEnabled(USART_PHONE, 1);
Christina Quastfb524b92015-02-27 13:39:45 +0100270
271 /* Configure ISO7816 driver */
272 // FIXME: PIO_Configure(pPwr, PIO_LISTSIZE( pPwr ));
273
Christina Quastce296b92015-03-18 18:41:19 +0100274 state = NONE;
Christina Quastfb524b92015-02-27 13:39:45 +0100275
276
Christina Quast32906bb2015-02-24 11:35:19 +0100277// FIXME: Or do I need to call VBUS_CONFIGURE() here instead, which will call USBD_Connect() later?
278// USBD_Connect();
279// FIXME: USB clock? USB PMC?
280// NVIC_EnableIRQ( UDP_IRQn );
281
Christina Quast578daaa2015-03-13 23:46:01 +0100282 USART_EnableIt( USART_PHONE, US_IER_RXRDY) ;
Christina Quast32906bb2015-02-24 11:35:19 +0100283
284 // FIXME: At some point USBD_IrqHandler() should get called and set USBD_STATE_CONFIGURED
285 /* while (USBD_GetState() < USBD_STATE_CONFIGURED) {
286 int i = 1;
287 if ((i%10000) == 0) {
288 TRACE_DEBUG("%d: USB State: %x\n\r", i, USBD_GetState());
289 }
290 i++;
291 }
292*/
293
Christina Quast0ca83902015-03-22 19:05:23 +0100294 Timer_Init();
Christina Quast32906bb2015-02-24 11:35:19 +0100295}
Christina Quastfb524b92015-02-27 13:39:45 +0100296
Christina Quastce296b92015-03-18 18:41:19 +0100297void send_ATR(uint8_t *ATR, uint8_t status, uint32_t transferred, uint32_t remaining)
Christina Quast578daaa2015-03-13 23:46:01 +0100298{
299 int i;
Christina Quast14fbf9c2015-04-06 00:36:12 +0200300 PR("Send %x %x .. %x (tr: %d, st: %x)", ATR[0], ATR[1], ATR[transferred-1], transferred, status);
Christina Quastce296b92015-03-18 18:41:19 +0100301 for ( i = 0; i < transferred; i++ ) {
Christina Quast578daaa2015-03-13 23:46:01 +0100302 _ISO7816_SendChar(*(ATR++));
303 }
Christina Quastce296b92015-03-18 18:41:19 +0100304 state = WAIT_CMD_PHONE;
Christina Quastbdaa9542015-04-06 00:52:08 +0200305 PIO_EnableIt( &pinPhoneRST ) ;
Christina Quast578daaa2015-03-13 23:46:01 +0100306}
307
Christina Quastce296b92015-03-18 18:41:19 +0100308void sendResponse( uint8_t *pArg, uint8_t status, uint32_t transferred, uint32_t remaining)
Christina Quast578daaa2015-03-13 23:46:01 +0100309{
Christina Quastce296b92015-03-18 18:41:19 +0100310 int i;
Christina Quast1d80ef22015-04-03 11:39:38 +0200311 PR("sendResp, stat: %X, trnsf: %x, rem: %x\n\r", status, transferred, remaining);
312 PR("Resp: %x %x %x .. %x", pArg[0], pArg[1], pArg[2], pArg[transferred-1]);
Christina Quast578daaa2015-03-13 23:46:01 +0100313
Christina Quastce296b92015-03-18 18:41:19 +0100314 for ( i = 0; i < transferred; i++ ) {
315 _ISO7816_SendChar(*(pArg++));
Christina Quast578daaa2015-03-13 23:46:01 +0100316 }
Christina Quast4bcc0232015-03-24 21:59:32 +0100317/*
318 if (*(pArg-1) == 0x8A) {
319 for (i=0; i<20000; i++) ;
320 _ISO7816_SendChar(0x90);
321 _ISO7816_SendChar(0x00);
322 }
323*/
Christina Quastce296b92015-03-18 18:41:19 +0100324 state = WAIT_CMD_PHONE;
Christina Quast578daaa2015-03-13 23:46:01 +0100325}
326
Christina Quast578daaa2015-03-13 23:46:01 +0100327extern ring_buffer buf;
328#define MAX_MSG_LEN 64
Christina Quastce296b92015-03-18 18:41:19 +0100329#define PR printf
330
331void wait_for_response(uint8_t pBuffer[]) {
332 int ret = 0;
333// uint8_t msg[] = {0xa0, 0xa4, 0x0, 0x0, 0x2};
334 if (rcvdChar != 0) {
335 printf(" rr ");
336 /* DATA_IN for host side is data_out for simtrace side */
337 /* FIXME: Performancewise sending a USB packet for every byte is a disaster */
Christina Quaste90dece2015-04-03 11:40:22 +0200338 ret = USBD_Write( PHONE_DATAIN, buf.buf, BUFLEN, 0, 0 );
339 //USBD_Write( PHONE_DATAIN, msg, BUFLEN, 0, 0 );
Christina Quast0ca83902015-03-22 19:05:23 +0100340 PR("b:%x %x %x %x %x.\n\r", buf.buf[0], buf.buf[1],buf.buf[2], buf.buf[3], buf.buf[4]);
Christina Quastce296b92015-03-18 18:41:19 +0100341
342 rcvdChar = 0;
Christina Quast4bcc0232015-03-24 21:59:32 +0100343 } else if (timeout_occured && buf.idx != 0) {
Christina Quast0ca83902015-03-22 19:05:23 +0100344 printf(" to ");
Christina Quaste90dece2015-04-03 11:40:22 +0200345 ret = USBD_Write( PHONE_DATAIN, buf.buf, buf.idx, 0, 0 );
Christina Quast0ca83902015-03-22 19:05:23 +0100346 timeout_occured = 0;
347 buf.idx = 0;
348 rcvdChar = 0;
349 PR("b:%x %x %x %x %x.\n\r", buf.buf[0], buf.buf[1],buf.buf[2], buf.buf[3], buf.buf[4]);
350 } else {
Christina Quast0ca83902015-03-22 19:05:23 +0100351 return;
352 }
Christina Quaste90dece2015-04-03 11:40:22 +0200353 if ((ret = USBD_Read(PHONE_DATAOUT, pBuffer, MAX_MSG_LEN,
Christina Quast0ca83902015-03-22 19:05:23 +0100354 (TransferCallback)&sendResponse, pBuffer)) == USBD_STATUS_SUCCESS) {
Christina Quast1d80ef22015-04-03 11:39:38 +0200355 PR("wait_rsp\n\r");
Christina Quast0ca83902015-03-22 19:05:23 +0100356// state = WAIT_CMD_PC;
357 buf.idx = 0;
358 TC0_Counter_Reset();
359 } else {
Christina Quast1d80ef22015-04-03 11:39:38 +0200360 PR("USB Err: %X", ret);
Christina Quast0ca83902015-03-22 19:05:23 +0100361 return;
Christina Quastce296b92015-03-18 18:41:19 +0100362 }
363}
364
365// Sniffed Phone to SIM card communication:
366// phone > sim : RST
367// phone < sim : ATR
368// phone > sim : A0 A4 00 00 02 (Select File)
369// phone < sim : A4 (INS repeated)
370// phone > sim : 7F 02 (= ??)
371// phone < sim : 9F 16 (9F: success, can deliver 0x16 (=22) byte)
372// phone > sim : ?? (A0 C0 00 00 16)
373// phone < sim : C0 (INS repeated)
374// phone < sim : 00 00 00 00 7F 20 02 00 00 00 00 00 09 91 00 17 04 00 83 8A (data of length 22 -2)
375// phone <? sim : 90 00 (OK, everything went fine)
376// phone ? sim : 00 (??)
Christina Quast578daaa2015-03-13 23:46:01 +0100377
Christina Quastfb524b92015-02-27 13:39:45 +0100378void Phone_run( void )
379{
Christina Quast578daaa2015-03-13 23:46:01 +0100380 int ret;
381 uint8_t pBuffer[MAX_MSG_LEN];
Christina Quastce296b92015-03-18 18:41:19 +0100382 int msg = RESET;
383// FIXME: remove:
384// uint8_t ATR[] = {0x3B, 0x9A, 0x94, 0x00, 0x92, 0x02, 0x75, 0x93, 0x11, 0x00, 0x01, 0x02, 0x02, 0x19};
385// send_ATR(ATR, (sizeof(ATR)/sizeof(ATR[0])));
Christina Quastce296b92015-03-18 18:41:19 +0100386 switch (state) {
387 case RST_RCVD:
Christina Quast6355ece2015-04-04 10:15:38 +0200388 if ((ret = USBD_Write( PHONE_INT, &msg, 1, 0, 0 )) != USBD_STATUS_SUCCESS) {
389 PR("USB Error: %X", ret);
390 }
Christina Quaste90dece2015-04-03 11:40:22 +0200391 //buf.idx = 0;
392 //rcvdChar = 0;
393// TC0_Counter_Reset();
Christina Quastce296b92015-03-18 18:41:19 +0100394 // send_ATR sets state to WAIT_CMD
Christina Quaste90dece2015-04-03 11:40:22 +0200395 if ((ret = USBD_Read(PHONE_DATAOUT, pBuffer, MAX_MSG_LEN, (TransferCallback)&send_ATR, pBuffer)) == USBD_STATUS_SUCCESS) {
396 PR("Reading started sucessfully (ATR)");
Christina Quastce296b92015-03-18 18:41:19 +0100397 state = WAIT_ATR;
398 } else {
Christina Quast1d80ef22015-04-03 11:39:38 +0200399 // PR("USB Error: %X", ret);
Christina Quastce296b92015-03-18 18:41:19 +0100400//FIXME: state = ERR;
401 }
402 break;
403 case WAIT_CMD_PHONE:
Christina Quast0ca83902015-03-22 19:05:23 +0100404// FIXME: TC0_Counter_Reset();
Christina Quastce296b92015-03-18 18:41:19 +0100405 wait_for_response(pBuffer);
406 break;
Christina Quast0ca83902015-03-22 19:05:23 +0100407 case NONE:
408 break;
Christina Quastce296b92015-03-18 18:41:19 +0100409 default:
Christina Quast1d80ef22015-04-03 11:39:38 +0200410// PR(":(");
Christina Quastce296b92015-03-18 18:41:19 +0100411 break;
Christina Quast578daaa2015-03-13 23:46:01 +0100412 }
413
Christina Quastfb524b92015-02-27 13:39:45 +0100414 // FIXME: Function Phone_run not implemented yet
415
416 /* Send and receive chars */
417 // ISO7816_GetChar(&rcv_char);
418 // ISO7816_SendChar(char_to_send);
419}