blob: 39e3fd3496bf841c3d08dc3dc0f09f5380bfd34d [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 Quast4bcc0232015-03-24 21:59:32 +010085//static const Pin pins_bus[] = {PINS_BUS_DEFAULT};
86// FIXME: temporary enable bus switch
87static const Pin pins_bus[] = {PINS_BUS_SNIFF};
88
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
102#define ISO7816_PHONE_RST {PIO_PA24, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEBOUNCE | PIO_DEGLITCH | PIO_IT_EDGE }
103static const Pin pinPhoneRST = ISO7816_PHONE_RST;
104//#define ISO7816_PHONE_CLK {PIO_PA23A_SCK1, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEBOUNCE | PIO_DEGLITCH | PIO_IT_EDGE }
105//static const Pin pinPhoneClk = ISO7816_PHONE_CLK;
106
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 Quast578daaa2015-03-13 23:46:01 +0100138 printf("+++ Int!!\n\r");
Christina Quast4bcc0232015-03-24 21:59:32 +0100139 state = RST_RCVD;
140
141/* if (state == NONE || rst_cnt > 2) {
Christina Quastce296b92015-03-18 18:41:19 +0100142 state = RST_RCVD;
143 }
Christina Quast4bcc0232015-03-24 21:59:32 +0100144 rst_cnt++;
145*/
Christina Quastc0aa7692015-02-25 14:02:01 +0100146 // FIXME: What to do on reset?
Christina Quastce296b92015-03-18 18:41:19 +0100147 // FIXME: It seems like the phone is constantly sending a lot of these RSTs
Christina Quast578daaa2015-03-13 23:46:01 +0100148// PIO_DisableIt( &pinPhoneRST ) ;
Christina Quast32906bb2015-02-24 11:35:19 +0100149}
150
151static void Config_PhoneRST_IrqHandler()
152{
153 PIO_Configure( &pinPhoneRST, 1);
154// PIO_Configure( &pinPhoneClk, 1);
155 PIO_ConfigureIt( &pinPhoneRST, ISR_PhoneRST ) ;
156// PIO_ConfigureIt( &pinPhoneClk, ISR_PhoneRST ) ;
157 PIO_EnableIt( &pinPhoneRST ) ;
158// PIO_EnableIt( &pinPhoneClk ) ;
159 NVIC_EnableIRQ( PIOA_IRQn );
160}
161
162/**
163 * Get a character from ISO7816
164 * \param pCharToReceive Pointer for store the received char
165 * \return 0: if timeout else status of US_CSR
166 */
167/* FIXME: This code is taken from cciddriver.c
168 --> Reuse the code!!! */
169uint32_t _ISO7816_GetChar( uint8_t *pCharToReceive )
170{
171 uint32_t status;
172 uint32_t timeout=0;
173
174 TRACE_DEBUG("--");
175
176 if( StateUsartGlobal == USART_SEND ) {
177 while((USART_PHONE->US_CSR & US_CSR_TXEMPTY) == 0) {}
178 USART_PHONE->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
179 StateUsartGlobal = USART_RCV;
180 }
181
182 /* Wait USART ready for reception */
183 while( ((USART_PHONE->US_CSR & US_CSR_RXRDY) == 0) ) {
184 if(timeout++ > 12000 * (BOARD_MCK/1000000)) {
185 TRACE_DEBUG("TimeOut\n\r");
186 return( 0 );
187 }
188 }
189
190 /* At least one complete character has been received and US_RHR has not yet been read. */
191
192 /* Get a char */
193 *pCharToReceive = ((USART_PHONE->US_RHR) & 0xFF);
194
195 status = (USART_PHONE->US_CSR&(US_CSR_OVRE|US_CSR_FRAME|
196 US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|
197 (1<<10)));
198
199 if (status != 0 ) {
200 TRACE_DEBUG("R:0x%X\n\r", status);
201 TRACE_DEBUG("R:0x%X\n\r", USART_PHONE->US_CSR);
202 TRACE_DEBUG("Nb:0x%X\n\r", USART_PHONE->US_NER );
203 USART_PHONE->US_CR = US_CR_RSTSTA;
204 }
205
206 /* Return status */
207 return( status );
208}
209
210/**
211 * Send a char to ISO7816
212 * \param CharToSend char to be send
213 * \return status of US_CSR
214 */
215uint32_t _ISO7816_SendChar( uint8_t CharToSend )
216{
217 uint32_t status;
218
219 TRACE_DEBUG("********** Send char: %c (0x%X)\n\r", CharToSend, CharToSend);
220
221 if( StateUsartGlobal == USART_RCV ) {
222 USART_PHONE->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
223 StateUsartGlobal = USART_SEND;
224 }
225
226 /* Wait USART ready for transmit */
227 while((USART_PHONE->US_CSR & US_CSR_TXRDY) == 0) {}
228 /* There is no character in the US_THR */
229
230 /* Transmit a char */
231 USART_PHONE->US_THR = CharToSend;
232
233 status = (USART_PHONE->US_CSR&(US_CSR_OVRE|US_CSR_FRAME|
234 US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|
235 (1<<10)));
236
237 if (status != 0 ) {
Christina Quastc0aa7692015-02-25 14:02:01 +0100238 TRACE_DEBUG("******* status: 0x%X (Overrun: %lu, NACK: %lu, Timeout: %lu, underrun: %lu)\n\r",
Christina Quast32906bb2015-02-24 11:35:19 +0100239 status, ((status & US_CSR_OVRE)>> 5), ((status & US_CSR_NACK) >> 13),
240 ((status & US_CSR_TIMEOUT) >> 8), ((status & (1 << 10)) >> 10));
241
242 TRACE_DEBUG("E (USART CSR reg):0x%X\n\r", USART_PHONE->US_CSR);
243 TRACE_DEBUG("Nb (Number of errors):0x%X\n\r", USART_PHONE->US_NER );
244 USART_PHONE->US_CR = US_CR_RSTSTA;
245 }
246
247 /* Return status */
248 return( status );
249}
250
Christina Quast32906bb2015-02-24 11:35:19 +0100251void Phone_Master_Init( void ) {
252
253 PIO_Configure( pinsISO7816_PHONE, PIO_LISTSIZE( pinsISO7816_PHONE ) ) ;
Christina Quast8043fdd2015-03-04 18:45:30 +0100254 PIO_Configure( pins_bus, PIO_LISTSIZE( pins_bus) ) ;
255
Christina Quast32906bb2015-02-24 11:35:19 +0100256 Config_PhoneRST_IrqHandler();
Christina Quast32906bb2015-02-24 11:35:19 +0100257
Christina Quastc0aa7692015-02-25 14:02:01 +0100258 _ISO7816_Init();
259
260 USART_SetTransmitterEnabled(USART_PHONE, 1);
261 USART_SetReceiverEnabled(USART_PHONE, 1);
Christina Quastfb524b92015-02-27 13:39:45 +0100262
263 /* Configure ISO7816 driver */
264 // FIXME: PIO_Configure(pPwr, PIO_LISTSIZE( pPwr ));
265
Christina Quastce296b92015-03-18 18:41:19 +0100266 state = NONE;
Christina Quastfb524b92015-02-27 13:39:45 +0100267
268
Christina Quast32906bb2015-02-24 11:35:19 +0100269// FIXME: Or do I need to call VBUS_CONFIGURE() here instead, which will call USBD_Connect() later?
270// USBD_Connect();
271// FIXME: USB clock? USB PMC?
272// NVIC_EnableIRQ( UDP_IRQn );
273
Christina Quast578daaa2015-03-13 23:46:01 +0100274 USART_EnableIt( USART_PHONE, US_IER_RXRDY) ;
Christina Quast32906bb2015-02-24 11:35:19 +0100275
276 // FIXME: At some point USBD_IrqHandler() should get called and set USBD_STATE_CONFIGURED
277 /* while (USBD_GetState() < USBD_STATE_CONFIGURED) {
278 int i = 1;
279 if ((i%10000) == 0) {
280 TRACE_DEBUG("%d: USB State: %x\n\r", i, USBD_GetState());
281 }
282 i++;
283 }
284*/
285
Christina Quast0ca83902015-03-22 19:05:23 +0100286 Timer_Init();
Christina Quast32906bb2015-02-24 11:35:19 +0100287}
Christina Quastfb524b92015-02-27 13:39:45 +0100288
Christina Quastce296b92015-03-18 18:41:19 +0100289void send_ATR(uint8_t *ATR, uint8_t status, uint32_t transferred, uint32_t remaining)
Christina Quast578daaa2015-03-13 23:46:01 +0100290{
291 int i;
Christina Quastce296b92015-03-18 18:41:19 +0100292 TRACE_INFO("Send %x %x %x.. %x", ATR[0], ATR[1], ATR[2], ATR[transferred-1]);
293 for ( i = 0; i < transferred; i++ ) {
Christina Quast578daaa2015-03-13 23:46:01 +0100294 _ISO7816_SendChar(*(ATR++));
295 }
Christina Quastce296b92015-03-18 18:41:19 +0100296 state = WAIT_CMD_PHONE;
Christina Quast578daaa2015-03-13 23:46:01 +0100297}
298
Christina Quastce296b92015-03-18 18:41:19 +0100299void sendResponse( uint8_t *pArg, uint8_t status, uint32_t transferred, uint32_t remaining)
Christina Quast578daaa2015-03-13 23:46:01 +0100300{
Christina Quastce296b92015-03-18 18:41:19 +0100301 int i;
Christina Quast0ca83902015-03-22 19:05:23 +0100302 TRACE_INFO("sendResp, stat: %X, trnsf: %x, rem: %x\n\r", status, transferred, remaining);
Christina Quastce296b92015-03-18 18:41:19 +0100303 TRACE_INFO("Resp: %x %x %x .. %x", pArg[0], pArg[1], pArg[2], pArg[transferred-1]);
Christina Quast578daaa2015-03-13 23:46:01 +0100304
Christina Quastce296b92015-03-18 18:41:19 +0100305 for ( i = 0; i < transferred; i++ ) {
306 _ISO7816_SendChar(*(pArg++));
Christina Quast578daaa2015-03-13 23:46:01 +0100307 }
Christina Quast4bcc0232015-03-24 21:59:32 +0100308/*
309 if (*(pArg-1) == 0x8A) {
310 for (i=0; i<20000; i++) ;
311 _ISO7816_SendChar(0x90);
312 _ISO7816_SendChar(0x00);
313 }
314*/
Christina Quastce296b92015-03-18 18:41:19 +0100315 state = WAIT_CMD_PHONE;
Christina Quast578daaa2015-03-13 23:46:01 +0100316}
317
Christina Quast578daaa2015-03-13 23:46:01 +0100318extern ring_buffer buf;
319#define MAX_MSG_LEN 64
Christina Quastce296b92015-03-18 18:41:19 +0100320#define PR printf
321
322void wait_for_response(uint8_t pBuffer[]) {
323 int ret = 0;
324// uint8_t msg[] = {0xa0, 0xa4, 0x0, 0x0, 0x2};
325 if (rcvdChar != 0) {
326 printf(" rr ");
327 /* DATA_IN for host side is data_out for simtrace side */
328 /* FIXME: Performancewise sending a USB packet for every byte is a disaster */
Christina Quast0ca83902015-03-22 19:05:23 +0100329 ret = USBD_Write( DATAIN, buf.buf, BUFLEN, 0, 0 );
Christina Quastce296b92015-03-18 18:41:19 +0100330 //USBD_Write( DATAIN, msg, BUFLEN, 0, 0 );
Christina Quast0ca83902015-03-22 19:05:23 +0100331 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 +0100332
333 rcvdChar = 0;
Christina Quast4bcc0232015-03-24 21:59:32 +0100334 } else if (timeout_occured && buf.idx != 0) {
Christina Quast0ca83902015-03-22 19:05:23 +0100335 printf(" to ");
336 ret = USBD_Write( DATAIN, buf.buf, buf.idx, 0, 0 );
337 timeout_occured = 0;
338 buf.idx = 0;
339 rcvdChar = 0;
340 PR("b:%x %x %x %x %x.\n\r", buf.buf[0], buf.buf[1],buf.buf[2], buf.buf[3], buf.buf[4]);
341 } else {
342 printf(".");
343 return;
344 }
345 if ((ret = USBD_Read(DATAOUT, pBuffer, MAX_MSG_LEN,
346 (TransferCallback)&sendResponse, pBuffer)) == USBD_STATUS_SUCCESS) {
347 TRACE_INFO("wait_rsp\n\r");
348// state = WAIT_CMD_PC;
349 buf.idx = 0;
350 TC0_Counter_Reset();
351 } else {
352 TRACE_INFO("USB Err: %X", ret);
353 return;
Christina Quastce296b92015-03-18 18:41:19 +0100354 }
355}
356
357// Sniffed Phone to SIM card communication:
358// phone > sim : RST
359// phone < sim : ATR
360// phone > sim : A0 A4 00 00 02 (Select File)
361// phone < sim : A4 (INS repeated)
362// phone > sim : 7F 02 (= ??)
363// phone < sim : 9F 16 (9F: success, can deliver 0x16 (=22) byte)
364// phone > sim : ?? (A0 C0 00 00 16)
365// phone < sim : C0 (INS repeated)
366// 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)
367// phone <? sim : 90 00 (OK, everything went fine)
368// phone ? sim : 00 (??)
Christina Quast578daaa2015-03-13 23:46:01 +0100369
Christina Quastfb524b92015-02-27 13:39:45 +0100370void Phone_run( void )
371{
Christina Quast578daaa2015-03-13 23:46:01 +0100372 int ret;
373 uint8_t pBuffer[MAX_MSG_LEN];
Christina Quastce296b92015-03-18 18:41:19 +0100374 int msg = RESET;
375// FIXME: remove:
376// uint8_t ATR[] = {0x3B, 0x9A, 0x94, 0x00, 0x92, 0x02, 0x75, 0x93, 0x11, 0x00, 0x01, 0x02, 0x02, 0x19};
377// send_ATR(ATR, (sizeof(ATR)/sizeof(ATR[0])));
Christina Quastce296b92015-03-18 18:41:19 +0100378 switch (state) {
379 case RST_RCVD:
380 USBD_Write( INT, &msg, 1, 0, 0 );
Christina Quast4bcc0232015-03-24 21:59:32 +0100381 TC0_Counter_Reset();
Christina Quastce296b92015-03-18 18:41:19 +0100382 // send_ATR sets state to WAIT_CMD
383 if ((ret = USBD_Read(DATAOUT, pBuffer, MAX_MSG_LEN, (TransferCallback)&send_ATR, pBuffer)) == USBD_STATUS_SUCCESS) {
384 TRACE_INFO("Reading started sucessfully (ATR)");
385 state = WAIT_ATR;
386 } else {
387 TRACE_INFO("USB Error: %X", ret);
388//FIXME: state = ERR;
389 }
390 break;
391 case WAIT_CMD_PHONE:
Christina Quast0ca83902015-03-22 19:05:23 +0100392// FIXME: TC0_Counter_Reset();
Christina Quastce296b92015-03-18 18:41:19 +0100393 wait_for_response(pBuffer);
394 break;
Christina Quast0ca83902015-03-22 19:05:23 +0100395 case NONE:
396 break;
Christina Quastce296b92015-03-18 18:41:19 +0100397 default:
Christina Quast0ca83902015-03-22 19:05:23 +0100398// TRACE_INFO(":(");
Christina Quastce296b92015-03-18 18:41:19 +0100399 break;
Christina Quast578daaa2015-03-13 23:46:01 +0100400 }
401
Christina Quastfb524b92015-02-27 13:39:45 +0100402 // FIXME: Function Phone_run not implemented yet
403
404 /* Send and receive chars */
405 // ISO7816_GetChar(&rcv_char);
406 // ISO7816_SendChar(char_to_send);
407}