blob: eb4ded63ad6915b4cf2b484cfd0ea826bd6bada4 [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 Quast578daaa2015-03-13 23:46:01 +010085static const Pin pins_bus[] = {PINS_BUS_DEFAULT};
Christina Quast32906bb2015-02-24 11:35:19 +010086/** ISO7816 RST pin */
87static const Pin pinIso7816RstMC = PIN_ISO7816_RST_PHONE;
88static uint8_t sim_inserted = 0;
89
90static const Pin pPwr[] = {
91 /* Enable power converter 4.5-6V to 3.3V; low: off */
92 {SIM_PWEN, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT},
93
94 /* Enable second power converter: VCC_PHONE to VCC_SIM; high: off */
95 {VCC_FWD, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
96};
97
98
99#define ISO7816_PHONE_RST {PIO_PA24, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEBOUNCE | PIO_DEGLITCH | PIO_IT_EDGE }
100static const Pin pinPhoneRST = ISO7816_PHONE_RST;
101//#define ISO7816_PHONE_CLK {PIO_PA23A_SCK1, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEBOUNCE | PIO_DEGLITCH | PIO_IT_EDGE }
102//static const Pin pinPhoneClk = ISO7816_PHONE_CLK;
103
104/* ===================================================*/
105/* Taken from iso7816_4.c */
106/* ===================================================*/
107/** Flip flop for send and receive char */
108#define USART_SEND 0
109#define USART_RCV 1
110/*-----------------------------------------------------------------------------
111 * Internal variables
112 *-----------------------------------------------------------------------------*/
113/** Variable for state of send and receive froom USART */
114static uint8_t StateUsartGlobal = USART_RCV;
Christina Quast32906bb2015-02-24 11:35:19 +0100115
Christina Quastc0aa7692015-02-25 14:02:01 +0100116extern uint32_t char_stat;
117extern uint8_t rcvdChar;
Christina Quast32906bb2015-02-24 11:35:19 +0100118
119/*-----------------------------------------------------------------------------
120 * Interrupt routines
121 *-----------------------------------------------------------------------------*/
Christina Quast578daaa2015-03-13 23:46:01 +0100122#define RESET 'R'
Christina Quast32906bb2015-02-24 11:35:19 +0100123static void ISR_PhoneRST( const Pin *pPin)
124{
Christina Quast578daaa2015-03-13 23:46:01 +0100125 int msg = RESET;
126 printf("+++ Int!!\n\r");
127 USBD_Write( INT, &msg, 1, 0, 0 );
128
Christina Quastc0aa7692015-02-25 14:02:01 +0100129 // FIXME: What to do on reset?
Christina Quast578daaa2015-03-13 23:46:01 +0100130// PIO_DisableIt( &pinPhoneRST ) ;
Christina Quast32906bb2015-02-24 11:35:19 +0100131}
132
133static void Config_PhoneRST_IrqHandler()
134{
135 PIO_Configure( &pinPhoneRST, 1);
136// PIO_Configure( &pinPhoneClk, 1);
137 PIO_ConfigureIt( &pinPhoneRST, ISR_PhoneRST ) ;
138// PIO_ConfigureIt( &pinPhoneClk, ISR_PhoneRST ) ;
139 PIO_EnableIt( &pinPhoneRST ) ;
140// PIO_EnableIt( &pinPhoneClk ) ;
141 NVIC_EnableIRQ( PIOA_IRQn );
142}
143
144/**
145 * Get a character from ISO7816
146 * \param pCharToReceive Pointer for store the received char
147 * \return 0: if timeout else status of US_CSR
148 */
149/* FIXME: This code is taken from cciddriver.c
150 --> Reuse the code!!! */
151uint32_t _ISO7816_GetChar( uint8_t *pCharToReceive )
152{
153 uint32_t status;
154 uint32_t timeout=0;
155
156 TRACE_DEBUG("--");
157
158 if( StateUsartGlobal == USART_SEND ) {
159 while((USART_PHONE->US_CSR & US_CSR_TXEMPTY) == 0) {}
160 USART_PHONE->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
161 StateUsartGlobal = USART_RCV;
162 }
163
164 /* Wait USART ready for reception */
165 while( ((USART_PHONE->US_CSR & US_CSR_RXRDY) == 0) ) {
166 if(timeout++ > 12000 * (BOARD_MCK/1000000)) {
167 TRACE_DEBUG("TimeOut\n\r");
168 return( 0 );
169 }
170 }
171
172 /* At least one complete character has been received and US_RHR has not yet been read. */
173
174 /* Get a char */
175 *pCharToReceive = ((USART_PHONE->US_RHR) & 0xFF);
176
177 status = (USART_PHONE->US_CSR&(US_CSR_OVRE|US_CSR_FRAME|
178 US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|
179 (1<<10)));
180
181 if (status != 0 ) {
182 TRACE_DEBUG("R:0x%X\n\r", status);
183 TRACE_DEBUG("R:0x%X\n\r", USART_PHONE->US_CSR);
184 TRACE_DEBUG("Nb:0x%X\n\r", USART_PHONE->US_NER );
185 USART_PHONE->US_CR = US_CR_RSTSTA;
186 }
187
188 /* Return status */
189 return( status );
190}
191
192/**
193 * Send a char to ISO7816
194 * \param CharToSend char to be send
195 * \return status of US_CSR
196 */
197uint32_t _ISO7816_SendChar( uint8_t CharToSend )
198{
199 uint32_t status;
200
201 TRACE_DEBUG("********** Send char: %c (0x%X)\n\r", CharToSend, CharToSend);
202
203 if( StateUsartGlobal == USART_RCV ) {
204 USART_PHONE->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
205 StateUsartGlobal = USART_SEND;
206 }
207
208 /* Wait USART ready for transmit */
209 while((USART_PHONE->US_CSR & US_CSR_TXRDY) == 0) {}
210 /* There is no character in the US_THR */
211
212 /* Transmit a char */
213 USART_PHONE->US_THR = CharToSend;
214
215 status = (USART_PHONE->US_CSR&(US_CSR_OVRE|US_CSR_FRAME|
216 US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|
217 (1<<10)));
218
219 if (status != 0 ) {
Christina Quastc0aa7692015-02-25 14:02:01 +0100220 TRACE_DEBUG("******* status: 0x%X (Overrun: %lu, NACK: %lu, Timeout: %lu, underrun: %lu)\n\r",
Christina Quast32906bb2015-02-24 11:35:19 +0100221 status, ((status & US_CSR_OVRE)>> 5), ((status & US_CSR_NACK) >> 13),
222 ((status & US_CSR_TIMEOUT) >> 8), ((status & (1 << 10)) >> 10));
223
224 TRACE_DEBUG("E (USART CSR reg):0x%X\n\r", USART_PHONE->US_CSR);
225 TRACE_DEBUG("Nb (Number of errors):0x%X\n\r", USART_PHONE->US_NER );
226 USART_PHONE->US_CR = US_CR_RSTSTA;
227 }
228
229 /* Return status */
230 return( status );
231}
232
Christina Quast32906bb2015-02-24 11:35:19 +0100233void Phone_Master_Init( void ) {
234
235 PIO_Configure( pinsISO7816_PHONE, PIO_LISTSIZE( pinsISO7816_PHONE ) ) ;
Christina Quast8043fdd2015-03-04 18:45:30 +0100236 PIO_Configure( pins_bus, PIO_LISTSIZE( pins_bus) ) ;
237
Christina Quast32906bb2015-02-24 11:35:19 +0100238 Config_PhoneRST_IrqHandler();
Christina Quast32906bb2015-02-24 11:35:19 +0100239
Christina Quastc0aa7692015-02-25 14:02:01 +0100240 _ISO7816_Init();
241
242 USART_SetTransmitterEnabled(USART_PHONE, 1);
243 USART_SetReceiverEnabled(USART_PHONE, 1);
Christina Quastfb524b92015-02-27 13:39:45 +0100244
245 /* Configure ISO7816 driver */
246 // FIXME: PIO_Configure(pPwr, PIO_LISTSIZE( pPwr ));
247
248
249
250
Christina Quast32906bb2015-02-24 11:35:19 +0100251// FIXME: Or do I need to call VBUS_CONFIGURE() here instead, which will call USBD_Connect() later?
252// USBD_Connect();
253// FIXME: USB clock? USB PMC?
254// NVIC_EnableIRQ( UDP_IRQn );
255
Christina Quast578daaa2015-03-13 23:46:01 +0100256 USART_EnableIt( USART_PHONE, US_IER_RXRDY) ;
Christina Quast32906bb2015-02-24 11:35:19 +0100257
258 // FIXME: At some point USBD_IrqHandler() should get called and set USBD_STATE_CONFIGURED
259 /* while (USBD_GetState() < USBD_STATE_CONFIGURED) {
260 int i = 1;
261 if ((i%10000) == 0) {
262 TRACE_DEBUG("%d: USB State: %x\n\r", i, USBD_GetState());
263 }
264 i++;
265 }
266*/
267
268}
Christina Quastfb524b92015-02-27 13:39:45 +0100269
Christina Quast578daaa2015-03-13 23:46:01 +0100270void send_ATR(uint8_t *ATR, uint8_t len)
271{
272 int i;
273 TRACE_INFO("Send %x %x %x", ATR[0], ATR[1], ATR[2]);
274 for ( i = 0; i < len; i++ ) {
275 _ISO7816_SendChar(*(ATR++));
276 }
277}
278
279void HandleIncommingData( void *pArg, uint8_t status, uint32_t transferred, uint32_t remaining)
280{
281 TRACE_INFO("HandleIncommingData ,stat: %X, transf: %x, remain: %x", status, transferred, remaining);
282
283 uint8_t ans[MAX_ANSWER_SIZE];
284 if (status == USBD_STATUS_SUCCESS) {
285 if (((uint8_t *)pArg)[0] == 0x3B) {
286 send_ATR(pArg, transferred);
287 return;
288 } else {
289 ISO7816_XfrBlockTPDU_T0(pArg, ans, transferred);
290 }
291 }
292 TRACE_INFO("Ans: %x %x %x", ans[0], ans[1], ans[2]);
293}
294
295#define PR TRACE_INFO
296extern ring_buffer buf;
297#define MAX_MSG_LEN 64
298
Christina Quastfb524b92015-02-27 13:39:45 +0100299void Phone_run( void )
300{
Christina Quast578daaa2015-03-13 23:46:01 +0100301 int ret;
302 uint8_t pBuffer[MAX_MSG_LEN];
303
304 if (rcvdChar != 0) {
305 /* DATA_IN for host side is data_out for simtrace side */
306 /* FIXME: Performancewise sending a USB packet for every byte is a disaster */
307 PR("----- %x %x %x ..\n\r", buf.buf[0], buf.buf[1],buf.buf[2] );
308 USBD_Write( DATAIN, buf.buf, BUFLEN, 0, 0 );
309 rcvdChar = 0;
310 }
311
312 if ((ret = USBD_Read(DATAOUT, pBuffer, MAX_MSG_LEN, (TransferCallback)&HandleIncommingData, pBuffer)) == USBD_STATUS_SUCCESS) {
313 TRACE_INFO("Reading started sucessfully");
314 TRACE_INFO("Recvd: %X %X %X %X %X", pBuffer[0], pBuffer[1], pBuffer[2], pBuffer[3], pBuffer[4]);
315 } else {
316// TRACE_INFO("USB Error: %X", ret);
317 }
318
Christina Quastfb524b92015-02-27 13:39:45 +0100319 // FIXME: Function Phone_run not implemented yet
320
321 /* Send and receive chars */
322 // ISO7816_GetChar(&rcv_char);
323 // ISO7816_SendChar(char_to_send);
324}