blob: 9e65c80e0add30b3473afe10e5f8f86080e51c22 [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*/
65#define WTX_req 0b10000011
66#define WTX_req 0b10100011
67// Alternatively:
68/* For T = 0 Protocol: The firmware on receiving the NULL (0x60) Procedure byte from the card, notifies
69it to the driver using the RDR_to_PC_DataBlock response. During this period, the reception of bytes
70from the smart card is still in progress and hence the device cannot indefinitely wait for IN tokens on
71the USB bulk-in endpoint. Hence, it is required of the driver to readily supply β€˜IN’ tokens on the USB
72bulk-in endpoint. On failure to do so, some of the wait time extension responses, will not be queued to
73the driver.
74*/
75
Christina Quast32906bb2015-02-24 11:35:19 +010076/*------------------------------------------------------------------------------
77 * Internal variables
78 *------------------------------------------------------------------------------*/
79/** USB state: suspend, resume, idle */
80unsigned char USBState = STATE_IDLE;
81
82/** ISO7816 pins */
83static const Pin pinsISO7816_PHONE[] = {PINS_ISO7816_PHONE};
Christina Quast8043fdd2015-03-04 18:45:30 +010084/** Bus switch pins */
Christina Quast30418542015-04-05 10:08:06 +020085static const Pin pins_bus[] = {PINS_BUS_DEFAULT};
Christina Quast4bcc0232015-03-24 21:59:32 +010086// FIXME: temporary enable bus switch
Christina Quast30418542015-04-05 10:08:06 +020087//static const Pin pins_bus[] = {PINS_BUS_SNIFF};
Christina Quast4bcc0232015-03-24 21:59:32 +010088
Christina Quast32906bb2015-02-24 11:35:19 +010089/** ISO7816 RST pin */
90static const Pin pinIso7816RstMC = PIN_ISO7816_RST_PHONE;
91static uint8_t sim_inserted = 0;
92
93static const Pin pPwr[] = {
94 /* Enable power converter 4.5-6V to 3.3V; low: off */
95 {SIM_PWEN, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT},
96
97 /* Enable second power converter: VCC_PHONE to VCC_SIM; high: off */
98 {VCC_FWD, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
99};
100
101
Christina Quast8e5381c2015-04-03 11:37:17 +0200102static const Pin pinPhoneRST = PIN_ISO7816_RST_PHONE;
103
104#define PR TRACE_INFO
Christina Quast32906bb2015-02-24 11:35:19 +0100105
106/* ===================================================*/
107/* Taken from iso7816_4.c */
108/* ===================================================*/
109/** Flip flop for send and receive char */
110#define USART_SEND 0
111#define USART_RCV 1
Christina Quastce296b92015-03-18 18:41:19 +0100112
113#define NONE 9
114#define RST_RCVD 10
115#define WAIT_CMD_PHONE 11
116#define WAIT_CMD_PC 12
117#define WAIT_ATR 13
Christina Quast32906bb2015-02-24 11:35:19 +0100118/*-----------------------------------------------------------------------------
119 * Internal variables
120 *-----------------------------------------------------------------------------*/
121/** Variable for state of send and receive froom USART */
122static uint8_t StateUsartGlobal = USART_RCV;
Christina Quast32906bb2015-02-24 11:35:19 +0100123
Christina Quastce296b92015-03-18 18:41:19 +0100124static uint32_t state;
Christina Quastc0aa7692015-02-25 14:02:01 +0100125extern uint8_t rcvdChar;
Christina Quast32906bb2015-02-24 11:35:19 +0100126
Christina Quast0ca83902015-03-22 19:05:23 +0100127extern volatile uint8_t timeout_occured;
128
Christina Quast4bcc0232015-03-24 21:59:32 +0100129static rst_cnt = 0;
130
Christina Quast32906bb2015-02-24 11:35:19 +0100131/*-----------------------------------------------------------------------------
132 * Interrupt routines
133 *-----------------------------------------------------------------------------*/
Christina Quast578daaa2015-03-13 23:46:01 +0100134#define RESET 'R'
Christina Quast32906bb2015-02-24 11:35:19 +0100135static void ISR_PhoneRST( const Pin *pPin)
136{
Christina Quastd3630cc2015-04-03 11:38:24 +0200137 printf("+++ Int!! %x\n\r", pinPhoneRST.pio->PIO_ISR);
138 if ( ((pinPhoneRST.pio->PIO_ISR & pinPhoneRST.mask) != 0) )
139 {
140 if(PIO_Get( &pinPhoneRST ) == 0) {
141 printf(" 0 ");
142 } else {
143 printf(" 1 ");
144 }
145 }
Christina Quast4bcc0232015-03-24 21:59:32 +0100146 state = RST_RCVD;
147
148/* if (state == NONE || rst_cnt > 2) {
Christina Quastce296b92015-03-18 18:41:19 +0100149 state = RST_RCVD;
150 }
Christina Quast4bcc0232015-03-24 21:59:32 +0100151 rst_cnt++;
152*/
Christina Quastc0aa7692015-02-25 14:02:01 +0100153 // FIXME: What to do on reset?
Christina Quastce296b92015-03-18 18:41:19 +0100154 // FIXME: It seems like the phone is constantly sending a lot of these RSTs
Christina Quastbdaa9542015-04-06 00:52:08 +0200155 PIO_DisableIt( &pinPhoneRST ) ;
Christina Quast32906bb2015-02-24 11:35:19 +0100156}
157
158static void Config_PhoneRST_IrqHandler()
159{
160 PIO_Configure( &pinPhoneRST, 1);
161// PIO_Configure( &pinPhoneClk, 1);
162 PIO_ConfigureIt( &pinPhoneRST, ISR_PhoneRST ) ;
163// PIO_ConfigureIt( &pinPhoneClk, ISR_PhoneRST ) ;
164 PIO_EnableIt( &pinPhoneRST ) ;
165// PIO_EnableIt( &pinPhoneClk ) ;
166 NVIC_EnableIRQ( PIOA_IRQn );
167}
168
169/**
170 * Get a character from ISO7816
171 * \param pCharToReceive Pointer for store the received char
172 * \return 0: if timeout else status of US_CSR
173 */
174/* FIXME: This code is taken from cciddriver.c
175 --> Reuse the code!!! */
176uint32_t _ISO7816_GetChar( uint8_t *pCharToReceive )
177{
178 uint32_t status;
179 uint32_t timeout=0;
180
181 TRACE_DEBUG("--");
182
183 if( StateUsartGlobal == USART_SEND ) {
184 while((USART_PHONE->US_CSR & US_CSR_TXEMPTY) == 0) {}
185 USART_PHONE->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
186 StateUsartGlobal = USART_RCV;
187 }
188
189 /* Wait USART ready for reception */
190 while( ((USART_PHONE->US_CSR & US_CSR_RXRDY) == 0) ) {
191 if(timeout++ > 12000 * (BOARD_MCK/1000000)) {
192 TRACE_DEBUG("TimeOut\n\r");
193 return( 0 );
194 }
195 }
196
197 /* At least one complete character has been received and US_RHR has not yet been read. */
198
199 /* Get a char */
200 *pCharToReceive = ((USART_PHONE->US_RHR) & 0xFF);
201
202 status = (USART_PHONE->US_CSR&(US_CSR_OVRE|US_CSR_FRAME|
203 US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|
204 (1<<10)));
205
206 if (status != 0 ) {
207 TRACE_DEBUG("R:0x%X\n\r", status);
208 TRACE_DEBUG("R:0x%X\n\r", USART_PHONE->US_CSR);
209 TRACE_DEBUG("Nb:0x%X\n\r", USART_PHONE->US_NER );
210 USART_PHONE->US_CR = US_CR_RSTSTA;
211 }
212
213 /* Return status */
214 return( status );
215}
216
217/**
218 * Send a char to ISO7816
219 * \param CharToSend char to be send
220 * \return status of US_CSR
221 */
222uint32_t _ISO7816_SendChar( uint8_t CharToSend )
223{
224 uint32_t status;
225
226 TRACE_DEBUG("********** Send char: %c (0x%X)\n\r", CharToSend, CharToSend);
227
228 if( StateUsartGlobal == USART_RCV ) {
229 USART_PHONE->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
230 StateUsartGlobal = USART_SEND;
231 }
232
233 /* Wait USART ready for transmit */
234 while((USART_PHONE->US_CSR & US_CSR_TXRDY) == 0) {}
235 /* There is no character in the US_THR */
236
237 /* Transmit a char */
238 USART_PHONE->US_THR = CharToSend;
239
240 status = (USART_PHONE->US_CSR&(US_CSR_OVRE|US_CSR_FRAME|
241 US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|
242 (1<<10)));
243
244 if (status != 0 ) {
Christina Quastc0aa7692015-02-25 14:02:01 +0100245 TRACE_DEBUG("******* status: 0x%X (Overrun: %lu, NACK: %lu, Timeout: %lu, underrun: %lu)\n\r",
Christina Quast32906bb2015-02-24 11:35:19 +0100246 status, ((status & US_CSR_OVRE)>> 5), ((status & US_CSR_NACK) >> 13),
247 ((status & US_CSR_TIMEOUT) >> 8), ((status & (1 << 10)) >> 10));
248
249 TRACE_DEBUG("E (USART CSR reg):0x%X\n\r", USART_PHONE->US_CSR);
250 TRACE_DEBUG("Nb (Number of errors):0x%X\n\r", USART_PHONE->US_NER );
251 USART_PHONE->US_CR = US_CR_RSTSTA;
252 }
253
254 /* Return status */
255 return( status );
256}
257
Christina Quast32906bb2015-02-24 11:35:19 +0100258void Phone_Master_Init( void ) {
259
260 PIO_Configure( pinsISO7816_PHONE, PIO_LISTSIZE( pinsISO7816_PHONE ) ) ;
Christina Quast8043fdd2015-03-04 18:45:30 +0100261 PIO_Configure( pins_bus, PIO_LISTSIZE( pins_bus) ) ;
262
Christina Quast32906bb2015-02-24 11:35:19 +0100263 Config_PhoneRST_IrqHandler();
Christina Quast32906bb2015-02-24 11:35:19 +0100264
Christina Quastc0aa7692015-02-25 14:02:01 +0100265 _ISO7816_Init();
266
267 USART_SetTransmitterEnabled(USART_PHONE, 1);
268 USART_SetReceiverEnabled(USART_PHONE, 1);
Christina Quastfb524b92015-02-27 13:39:45 +0100269
270 /* Configure ISO7816 driver */
271 // FIXME: PIO_Configure(pPwr, PIO_LISTSIZE( pPwr ));
272
Christina Quastce296b92015-03-18 18:41:19 +0100273 state = NONE;
Christina Quastfb524b92015-02-27 13:39:45 +0100274
275
Christina Quast32906bb2015-02-24 11:35:19 +0100276// FIXME: Or do I need to call VBUS_CONFIGURE() here instead, which will call USBD_Connect() later?
277// USBD_Connect();
278// FIXME: USB clock? USB PMC?
279// NVIC_EnableIRQ( UDP_IRQn );
280
Christina Quast578daaa2015-03-13 23:46:01 +0100281 USART_EnableIt( USART_PHONE, US_IER_RXRDY) ;
Christina Quast32906bb2015-02-24 11:35:19 +0100282
283 // FIXME: At some point USBD_IrqHandler() should get called and set USBD_STATE_CONFIGURED
284 /* while (USBD_GetState() < USBD_STATE_CONFIGURED) {
285 int i = 1;
286 if ((i%10000) == 0) {
287 TRACE_DEBUG("%d: USB State: %x\n\r", i, USBD_GetState());
288 }
289 i++;
290 }
291*/
292
Christina Quast0ca83902015-03-22 19:05:23 +0100293 Timer_Init();
Christina Quast32906bb2015-02-24 11:35:19 +0100294}
Christina Quastfb524b92015-02-27 13:39:45 +0100295
Christina Quastce296b92015-03-18 18:41:19 +0100296void send_ATR(uint8_t *ATR, uint8_t status, uint32_t transferred, uint32_t remaining)
Christina Quast578daaa2015-03-13 23:46:01 +0100297{
298 int i;
Christina Quast14fbf9c2015-04-06 00:36:12 +0200299 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 +0100300 for ( i = 0; i < transferred; i++ ) {
Christina Quast578daaa2015-03-13 23:46:01 +0100301 _ISO7816_SendChar(*(ATR++));
302 }
Christina Quastce296b92015-03-18 18:41:19 +0100303 state = WAIT_CMD_PHONE;
Christina Quastbdaa9542015-04-06 00:52:08 +0200304 PIO_EnableIt( &pinPhoneRST ) ;
Christina Quast578daaa2015-03-13 23:46:01 +0100305}
306
Christina Quastce296b92015-03-18 18:41:19 +0100307void sendResponse( uint8_t *pArg, uint8_t status, uint32_t transferred, uint32_t remaining)
Christina Quast578daaa2015-03-13 23:46:01 +0100308{
Christina Quastce296b92015-03-18 18:41:19 +0100309 int i;
Christina Quast1d80ef22015-04-03 11:39:38 +0200310 PR("sendResp, stat: %X, trnsf: %x, rem: %x\n\r", status, transferred, remaining);
311 PR("Resp: %x %x %x .. %x", pArg[0], pArg[1], pArg[2], pArg[transferred-1]);
Christina Quast578daaa2015-03-13 23:46:01 +0100312
Christina Quastce296b92015-03-18 18:41:19 +0100313 for ( i = 0; i < transferred; i++ ) {
314 _ISO7816_SendChar(*(pArg++));
Christina Quast578daaa2015-03-13 23:46:01 +0100315 }
Christina Quast4bcc0232015-03-24 21:59:32 +0100316/*
317 if (*(pArg-1) == 0x8A) {
318 for (i=0; i<20000; i++) ;
319 _ISO7816_SendChar(0x90);
320 _ISO7816_SendChar(0x00);
321 }
322*/
Christina Quastce296b92015-03-18 18:41:19 +0100323 state = WAIT_CMD_PHONE;
Christina Quast578daaa2015-03-13 23:46:01 +0100324}
325
Christina Quast578daaa2015-03-13 23:46:01 +0100326extern ring_buffer buf;
327#define MAX_MSG_LEN 64
Christina Quastce296b92015-03-18 18:41:19 +0100328#define PR printf
329
330void wait_for_response(uint8_t pBuffer[]) {
331 int ret = 0;
332// uint8_t msg[] = {0xa0, 0xa4, 0x0, 0x0, 0x2};
333 if (rcvdChar != 0) {
334 printf(" rr ");
335 /* DATA_IN for host side is data_out for simtrace side */
336 /* FIXME: Performancewise sending a USB packet for every byte is a disaster */
Christina Quaste90dece2015-04-03 11:40:22 +0200337 ret = USBD_Write( PHONE_DATAIN, buf.buf, BUFLEN, 0, 0 );
338 //USBD_Write( PHONE_DATAIN, msg, BUFLEN, 0, 0 );
Christina Quast0ca83902015-03-22 19:05:23 +0100339 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 +0100340
341 rcvdChar = 0;
Christina Quast4bcc0232015-03-24 21:59:32 +0100342 } else if (timeout_occured && buf.idx != 0) {
Christina Quast0ca83902015-03-22 19:05:23 +0100343 printf(" to ");
Christina Quaste90dece2015-04-03 11:40:22 +0200344 ret = USBD_Write( PHONE_DATAIN, buf.buf, buf.idx, 0, 0 );
Christina Quast0ca83902015-03-22 19:05:23 +0100345 timeout_occured = 0;
346 buf.idx = 0;
347 rcvdChar = 0;
348 PR("b:%x %x %x %x %x.\n\r", buf.buf[0], buf.buf[1],buf.buf[2], buf.buf[3], buf.buf[4]);
349 } else {
Christina Quast0ca83902015-03-22 19:05:23 +0100350 return;
351 }
Christina Quaste90dece2015-04-03 11:40:22 +0200352 if ((ret = USBD_Read(PHONE_DATAOUT, pBuffer, MAX_MSG_LEN,
Christina Quast0ca83902015-03-22 19:05:23 +0100353 (TransferCallback)&sendResponse, pBuffer)) == USBD_STATUS_SUCCESS) {
Christina Quast1d80ef22015-04-03 11:39:38 +0200354 PR("wait_rsp\n\r");
Christina Quast0ca83902015-03-22 19:05:23 +0100355// state = WAIT_CMD_PC;
356 buf.idx = 0;
357 TC0_Counter_Reset();
358 } else {
Christina Quast1d80ef22015-04-03 11:39:38 +0200359 PR("USB Err: %X", ret);
Christina Quast0ca83902015-03-22 19:05:23 +0100360 return;
Christina Quastce296b92015-03-18 18:41:19 +0100361 }
362}
363
364// Sniffed Phone to SIM card communication:
365// phone > sim : RST
366// phone < sim : ATR
367// phone > sim : A0 A4 00 00 02 (Select File)
368// phone < sim : A4 (INS repeated)
369// phone > sim : 7F 02 (= ??)
370// phone < sim : 9F 16 (9F: success, can deliver 0x16 (=22) byte)
371// phone > sim : ?? (A0 C0 00 00 16)
372// phone < sim : C0 (INS repeated)
373// 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)
374// phone <? sim : 90 00 (OK, everything went fine)
375// phone ? sim : 00 (??)
Christina Quast578daaa2015-03-13 23:46:01 +0100376
Christina Quastfb524b92015-02-27 13:39:45 +0100377void Phone_run( void )
378{
Christina Quast578daaa2015-03-13 23:46:01 +0100379 int ret;
380 uint8_t pBuffer[MAX_MSG_LEN];
Christina Quastce296b92015-03-18 18:41:19 +0100381 int msg = RESET;
382// FIXME: remove:
383// uint8_t ATR[] = {0x3B, 0x9A, 0x94, 0x00, 0x92, 0x02, 0x75, 0x93, 0x11, 0x00, 0x01, 0x02, 0x02, 0x19};
384// send_ATR(ATR, (sizeof(ATR)/sizeof(ATR[0])));
Christina Quastce296b92015-03-18 18:41:19 +0100385 switch (state) {
386 case RST_RCVD:
Christina Quast6355ece2015-04-04 10:15:38 +0200387 if ((ret = USBD_Write( PHONE_INT, &msg, 1, 0, 0 )) != USBD_STATUS_SUCCESS) {
388 PR("USB Error: %X", ret);
389 }
Christina Quaste90dece2015-04-03 11:40:22 +0200390 //buf.idx = 0;
391 //rcvdChar = 0;
392// TC0_Counter_Reset();
Christina Quastce296b92015-03-18 18:41:19 +0100393 // send_ATR sets state to WAIT_CMD
Christina Quaste90dece2015-04-03 11:40:22 +0200394 if ((ret = USBD_Read(PHONE_DATAOUT, pBuffer, MAX_MSG_LEN, (TransferCallback)&send_ATR, pBuffer)) == USBD_STATUS_SUCCESS) {
395 PR("Reading started sucessfully (ATR)");
Christina Quastce296b92015-03-18 18:41:19 +0100396 state = WAIT_ATR;
397 } else {
Christina Quast1d80ef22015-04-03 11:39:38 +0200398 // PR("USB Error: %X", ret);
Christina Quastce296b92015-03-18 18:41:19 +0100399//FIXME: state = ERR;
400 }
401 break;
402 case WAIT_CMD_PHONE:
Christina Quast0ca83902015-03-22 19:05:23 +0100403// FIXME: TC0_Counter_Reset();
Christina Quastce296b92015-03-18 18:41:19 +0100404 wait_for_response(pBuffer);
405 break;
Christina Quast0ca83902015-03-22 19:05:23 +0100406 case NONE:
407 break;
Christina Quastce296b92015-03-18 18:41:19 +0100408 default:
Christina Quast1d80ef22015-04-03 11:39:38 +0200409// PR(":(");
Christina Quastce296b92015-03-18 18:41:19 +0100410 break;
Christina Quast578daaa2015-03-13 23:46:01 +0100411 }
412
Christina Quastfb524b92015-02-27 13:39:45 +0100413 // FIXME: Function Phone_run not implemented yet
414
415 /* Send and receive chars */
416 // ISO7816_GetChar(&rcv_char);
417 // ISO7816_SendChar(char_to_send);
418}