blob: 21f3735ed12264c81ed680574d86852bf1bb2db9 [file] [log] [blame]
Harald Welte2a6d3af2016-02-28 19:29:14 +01001#include "board.h"
2#include "card_emu.h"
Harald Weltebd717682016-02-28 19:30:05 +01003#include "iso7816_fidi.h"
4
5#define TRACE_ENTRY() TRACE_DEBUG("%s entering\n", __func__)
Harald Welte2a6d3af2016-02-28 19:29:14 +01006
7static const Pin pins_cardsim[] = PINS_CARDSIM;
8
9/* UART pins */
10static const Pin pins_usim1[] = {PINS_USIM1};
11static const Pin pin_usim1_rst = PIN_USIM1_nRST;
12static const Pin pin_usim1_vcc = PIN_USIM1_VCC;
13
14#ifdef CARDEMU_SECOND_UART
15static const Pin pins_usim2[] = {PINS_USIM1};
16static const Pin pin_usim2_rst = PIN_USIM2_nRST;
17static const Pin pin_usim2_vcc = PIN_USIM2_VCC;
18#endif
19
20static struct card_handle *ch1, *ch2;
Harald Weltec0bd7f02016-02-29 10:13:33 +010021static struct ringbuf ch1_rb;
Harald Welte2a6d3af2016-02-28 19:29:14 +010022
23static struct Usart_info usart_info[] = {
24 {
25 .base = USART1,
26 .id = ID_USART1,
27 .state = USART_RCV
28 },
29#ifdef CARDEMU_SECOND_UART
30 {
31 .base = USART0,
32 .id = ID_USART0,
33 .state = USART_RCV
34 },
35#endif
36};
37
38static Usart *get_usart_by_chan(uint8_t uart_chan)
39{
40 switch (uart_chan) {
41 case 0:
42 return USART1;
43#ifdef CARDEMU_SECOND_UART
44 case 1:
45 return USART0;
46#endif
47 }
48 return NULL;
49}
50
51/***********************************************************************
52 * Call-Backs from card_emu.c
53 ***********************************************************************/
54
55/* call-back from card_emu.c to enable/disable transmit and/or receive */
56void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx)
57{
58 Usart *usart = get_usart_by_chan(uart_chan);
59 switch (rxtx) {
60 case ENABLE_TX:
Harald Welte9dbc46e2016-02-29 10:05:10 +010061 USART_EnableIt(usart, US_IER_TXRDY);
62 USART_DisableIt(usart, ~US_IER_TXRDY);
Harald Welte2a6d3af2016-02-28 19:29:14 +010063 USART_SetReceiverEnabled(usart, 0);
64 USART_SetTransmitterEnabled(usart, 1);
65 break;
66 case ENABLE_RX:
67 USART_SetTransmitterEnabled(usart, 0);
68 USART_SetReceiverEnabled(usart, 1);
Harald Welte9dbc46e2016-02-29 10:05:10 +010069 USART_EnableIt(usart, US_IER_RXRDY);
70 USART_DisableIt(usart, ~US_IER_RXRDY);
Harald Welte2a6d3af2016-02-28 19:29:14 +010071 break;
72 case 0:
73 default:
74 USART_SetTransmitterEnabled(usart, 0);
75 USART_SetReceiverEnabled(usart, 0);
Harald Welte9dbc46e2016-02-29 10:05:10 +010076 USART_DisableIt(usart, 0xFFFFFFFF);
Harald Welte2a6d3af2016-02-28 19:29:14 +010077 break;
78 }
79}
80
81/* call-back from card_emu.c to transmit a byte */
82int card_emu_uart_tx(uint8_t uart_chan, uint8_t byte)
83{
84 Usart_info *ui = &usart_info[uart_chan];
85 ISO7816_SendChar(byte, ui);
86 return 1;
87}
88
89
90/* FIXME: integrate this with actual irq handler */
Harald Weltec0bd7f02016-02-29 10:13:33 +010091void usart_irq_rx(uint8_t uart)
Harald Welte2a6d3af2016-02-28 19:29:14 +010092{
Harald Weltec0bd7f02016-02-29 10:13:33 +010093 Usart *usart = get_usart_by_chan(uart);
Harald Welte2a6d3af2016-02-28 19:29:14 +010094 struct card_handle *ch = ch1;
Harald Weltec0bd7f02016-02-29 10:13:33 +010095 uint32_t csr;
96 uint8_t byte = 0;
97
Harald Welte2a6d3af2016-02-28 19:29:14 +010098#ifdef CARDEMU_SECOND_UART
Harald Weltec0bd7f02016-02-29 10:13:33 +010099 if (uart == 1)
Harald Welte2a6d3af2016-02-28 19:29:14 +0100100 ch = ch2;
101#endif
Harald Weltec0bd7f02016-02-29 10:13:33 +0100102 csr = usart->US_CSR;
Harald Welte2a6d3af2016-02-28 19:29:14 +0100103
104 if (csr & US_CSR_TXRDY)
105 card_emu_tx_byte(ch);
106
Harald Weltec0bd7f02016-02-29 10:13:33 +0100107 if (csr & US_CSR_RXRDY) {
108 byte = (usart->US_RHR) & 0xFF;
109 rbuf_write(&ch1_rb, byte);
110 }
Harald Welte2a6d3af2016-02-28 19:29:14 +0100111
112 if (csr & (US_CSR_OVRE|US_CSR_FRAME|US_CSR_PARE|
113 US_CSR_TIMEOUT|US_CSR_NACK|(1<<10))) {
Harald Weltec0bd7f02016-02-29 10:13:33 +0100114 usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
115 TRACE_ERROR("e 0x%x st: 0x%x\n", byte, csr);
Harald Welte2a6d3af2016-02-28 19:29:14 +0100116 }
117}
118
Harald Weltebd717682016-02-28 19:30:05 +0100119/* call-back from card_emu.c to change UART baud rate */
120int card_emu_uart_update_fidi(uint8_t uart_chan, unsigned int fidi)
121{
122 int rc;
Harald Weltebd717682016-02-28 19:30:05 +0100123 Usart *usart = get_usart_by_chan(uart_chan);
124
Harald Welte99f62a62016-02-29 10:08:49 +0100125 usart->US_CR |= US_CR_RXDIS | US_CR_RSTRX;
126 usart->US_FIDI = fidi & 0x3ff;
127 usart->US_CR |= US_CR_RXEN | US_CR_STTTO;
128 return 0;
Harald Weltebd717682016-02-28 19:30:05 +0100129}
Harald Welte2a6d3af2016-02-28 19:29:14 +0100130
131/***********************************************************************
132 * Core USB / mainloop integration
133 ***********************************************************************/
134
Harald Weltec0bd7f02016-02-29 10:13:33 +0100135static void usim1_rst_irqhandler(const Pin *pPin)
136{
137 int active = PIO_Get(&pin_usim1_rst) ? 0 : 1;
138 card_emu_io_statechg(ch1, CARD_IO_RST, active);
139}
140
141static void usim1_vcc_irqhandler(const Pin *pPin)
142{
143 int active = PIO_Get(&pin_usim1_vcc) ? 1 : 0;
144 card_emu_io_statechg(ch1, CARD_IO_VCC, active);
145 /* FIXME do this for real */
146 card_emu_io_statechg(ch1, CARD_IO_CLK, active);
147}
148
Harald Welte2a6d3af2016-02-28 19:29:14 +0100149/* executed once at system boot for each config */
150void mode_cardemu_configure(void)
151{
Harald Weltebd717682016-02-28 19:30:05 +0100152 TRACE_ENTRY();
Harald Welte2a6d3af2016-02-28 19:29:14 +0100153}
154
155/* called if config is activated */
156void mode_cardemu_init(void)
157{
Harald Weltebd717682016-02-28 19:30:05 +0100158 TRACE_ENTRY();
159
Harald Weltec0bd7f02016-02-29 10:13:33 +0100160 rbuf_reset(&ch1_rb);
161
Harald Welte2a6d3af2016-02-28 19:29:14 +0100162 PIO_Configure(pins_cardsim, PIO_LISTSIZE(pins_cardsim));
163
164 PIO_Configure(pins_usim1, PIO_LISTSIZE(pins_usim1));
165 ISO7816_Init(&usart_info[0], CLK_SLAVE);
Harald Welte9dbc46e2016-02-29 10:05:10 +0100166 //USART_EnableIt(USART1, US_IER_RXRDY);
Harald Welte2a6d3af2016-02-28 19:29:14 +0100167 NVIC_EnableIRQ(USART1_IRQn);
Harald Weltec0bd7f02016-02-29 10:13:33 +0100168
169 PIO_ConfigureIt(&pin_usim1_rst, usim1_rst_irqhandler);
170 PIO_EnableIt(&pin_usim1_rst);
171 PIO_ConfigureIt(&pin_usim1_vcc, usim1_vcc_irqhandler);
172 PIO_EnableIt(&pin_usim1_vcc);
173
Harald Welte2a6d3af2016-02-28 19:29:14 +0100174 ch1 = card_emu_init(0, 2, 0);
175
176#ifdef CARDEMU_SECOND_UART
177 PIO_Configure(pins_usim2, PIO_LISTSIZE(pins_usim2));
178 ISO7816_Init(&usart_info[1], CLK_SLAVE);
Harald Welte9dbc46e2016-02-29 10:05:10 +0100179 //USART_EnableIt(USART0, US_IER_RXRDY);
Harald Welte2a6d3af2016-02-28 19:29:14 +0100180 NVIC_EnableIRQ(USART0_IRQn);
181 ch2 = card_emu_init(1, 0, 1);
182#endif
183}
184
185/* called if config is deactivated */
186void mode_cardemu_exit(void)
187{
Harald Weltebd717682016-02-28 19:30:05 +0100188 TRACE_ENTRY();
189
Harald Weltec0bd7f02016-02-29 10:13:33 +0100190 PIO_DisableIt(&pin_usim1_rst);
191 PIO_DisableIt(&pin_usim1_vcc);
192
Harald Welte2a6d3af2016-02-28 19:29:14 +0100193 NVIC_DisableIRQ(USART1_IRQn);
194 USART_SetTransmitterEnabled(USART1, 0);
195 USART_SetReceiverEnabled(USART1, 0);
196
197#ifdef CARDEMU_SECOND_UART
198 NVIC_DisableIRQ(USART0_IRQn);
199 USART_SetTransmitterEnabled(USART0, 0);
200 USART_SetReceiverEnabled(USART0, 0);
201#endif
202}
203
204/* main loop function, called repeatedly */
205void mode_cardemu_run(void)
206{
Harald Welte2a6d3af2016-02-28 19:29:14 +0100207
208 /* usb_to_host() is handled by main() */
209
210 if (ch1) {
Harald Weltec0bd7f02016-02-29 10:13:33 +0100211 while (1) {
212 __disable_irq();
213 if (rbuf_is_empty(&ch1_rb)) {
214 __enable_irq();
215 break;
216 }
217 uint8_t byte = rbuf_read(&ch1_rb);
218 __enable_irq();
219 card_emu_process_rx_byte(ch1, byte);
220 }
Harald Welte2a6d3af2016-02-28 19:29:14 +0100221 }
222 usb_from_host(PHONE_DATAOUT);
223
224#ifdef CARDEMU_SECOND_UART
225 if (ch2) {
226 rst_active = PIO_Get(&pin_usim2_rst) ? 0 : 1;
227 vcc_active = PIO_Get(&pin_usim2_vcc) ? 1 : 0;
228 card_emu_io_statechg(ch2, CARD_IO_RST, rst_active);
229 card_emu_io_statechg(ch2, CARD_IO_VCC, vcc_active);
230 /* FIXME: clock ? */
231 }
232 usb_from_host(FIXME);
233#endif
234}