blob: efebe18fd6909b19011a2f9718ed0351532eada9 [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;
21
22static struct Usart_info usart_info[] = {
23 {
24 .base = USART1,
25 .id = ID_USART1,
26 .state = USART_RCV
27 },
28#ifdef CARDEMU_SECOND_UART
29 {
30 .base = USART0,
31 .id = ID_USART0,
32 .state = USART_RCV
33 },
34#endif
35};
36
37static Usart *get_usart_by_chan(uint8_t uart_chan)
38{
39 switch (uart_chan) {
40 case 0:
41 return USART1;
42#ifdef CARDEMU_SECOND_UART
43 case 1:
44 return USART0;
45#endif
46 }
47 return NULL;
48}
49
50/***********************************************************************
51 * Call-Backs from card_emu.c
52 ***********************************************************************/
53
54/* call-back from card_emu.c to enable/disable transmit and/or receive */
55void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx)
56{
57 Usart *usart = get_usart_by_chan(uart_chan);
58 switch (rxtx) {
59 case ENABLE_TX:
Harald Welte9dbc46e2016-02-29 10:05:10 +010060 USART_EnableIt(usart, US_IER_TXRDY);
61 USART_DisableIt(usart, ~US_IER_TXRDY);
Harald Welte2a6d3af2016-02-28 19:29:14 +010062 USART_SetReceiverEnabled(usart, 0);
63 USART_SetTransmitterEnabled(usart, 1);
64 break;
65 case ENABLE_RX:
66 USART_SetTransmitterEnabled(usart, 0);
67 USART_SetReceiverEnabled(usart, 1);
Harald Welte9dbc46e2016-02-29 10:05:10 +010068 USART_EnableIt(usart, US_IER_RXRDY);
69 USART_DisableIt(usart, ~US_IER_RXRDY);
Harald Welte2a6d3af2016-02-28 19:29:14 +010070 break;
71 case 0:
72 default:
73 USART_SetTransmitterEnabled(usart, 0);
74 USART_SetReceiverEnabled(usart, 0);
Harald Welte9dbc46e2016-02-29 10:05:10 +010075 USART_DisableIt(usart, 0xFFFFFFFF);
Harald Welte2a6d3af2016-02-28 19:29:14 +010076 break;
77 }
78}
79
80/* call-back from card_emu.c to transmit a byte */
81int card_emu_uart_tx(uint8_t uart_chan, uint8_t byte)
82{
83 Usart_info *ui = &usart_info[uart_chan];
84 ISO7816_SendChar(byte, ui);
85 return 1;
86}
87
88
89/* FIXME: integrate this with actual irq handler */
90void usart_irq_rx(uint8_t uart, uint32_t csr, uint8_t byte)
91{
92 struct card_handle *ch = ch1;
93#ifdef CARDEMU_SECOND_UART
94 if (uart == 0)
95 ch = ch2;
96#endif
97
98 if (csr & US_CSR_TXRDY)
99 card_emu_tx_byte(ch);
100
101 if (csr & US_CSR_RXRDY)
102 card_emu_process_rx_byte(ch, byte);
103
104 if (csr & (US_CSR_OVRE|US_CSR_FRAME|US_CSR_PARE|
105 US_CSR_TIMEOUT|US_CSR_NACK|(1<<10))) {
106 TRACE_DEBUG("e 0x%x st: 0x%x\n", byte, csr);
107 }
108}
109
Harald Weltebd717682016-02-28 19:30:05 +0100110/* call-back from card_emu.c to change UART baud rate */
111int card_emu_uart_update_fidi(uint8_t uart_chan, unsigned int fidi)
112{
113 int rc;
114 uint8_t fi = fidi >> 4;
115 uint8_t di = fidi & 0xf;
116 Usart *usart = get_usart_by_chan(uart_chan);
117
118 rc = compute_fidi_ratio(fi, di);
119 if (rc > 0 && rc < 0x400) {
120 TRACE_INFO("computed Fi(%u) Di(%u) ratio: %d", fi, di, rc);
121 usart->US_CR |= US_CR_RXDIS | US_CR_RSTRX;
122 usart->US_FIDI = rc & 0x3ff;
123 usart->US_CR |= US_CR_RXEN | US_CR_STTTO;
124 return 0;
125 } else {
126 TRACE_INFO("computed FiDi ratio %d unsupported", rc);
127 return -1;
128 }
129}
Harald Welte2a6d3af2016-02-28 19:29:14 +0100130
131/***********************************************************************
132 * Core USB / mainloop integration
133 ***********************************************************************/
134
135/* executed once at system boot for each config */
136void mode_cardemu_configure(void)
137{
Harald Weltebd717682016-02-28 19:30:05 +0100138 TRACE_ENTRY();
Harald Welte2a6d3af2016-02-28 19:29:14 +0100139}
140
141/* called if config is activated */
142void mode_cardemu_init(void)
143{
Harald Weltebd717682016-02-28 19:30:05 +0100144 TRACE_ENTRY();
145
Harald Welte2a6d3af2016-02-28 19:29:14 +0100146 PIO_Configure(pins_cardsim, PIO_LISTSIZE(pins_cardsim));
147
148 PIO_Configure(pins_usim1, PIO_LISTSIZE(pins_usim1));
149 ISO7816_Init(&usart_info[0], CLK_SLAVE);
Harald Welte9dbc46e2016-02-29 10:05:10 +0100150 //USART_EnableIt(USART1, US_IER_RXRDY);
Harald Welte2a6d3af2016-02-28 19:29:14 +0100151 NVIC_EnableIRQ(USART1_IRQn);
152 ch1 = card_emu_init(0, 2, 0);
153
154#ifdef CARDEMU_SECOND_UART
155 PIO_Configure(pins_usim2, PIO_LISTSIZE(pins_usim2));
156 ISO7816_Init(&usart_info[1], CLK_SLAVE);
Harald Welte9dbc46e2016-02-29 10:05:10 +0100157 //USART_EnableIt(USART0, US_IER_RXRDY);
Harald Welte2a6d3af2016-02-28 19:29:14 +0100158 NVIC_EnableIRQ(USART0_IRQn);
159 ch2 = card_emu_init(1, 0, 1);
160#endif
161}
162
163/* called if config is deactivated */
164void mode_cardemu_exit(void)
165{
Harald Weltebd717682016-02-28 19:30:05 +0100166 TRACE_ENTRY();
167
Harald Welte2a6d3af2016-02-28 19:29:14 +0100168 NVIC_DisableIRQ(USART1_IRQn);
169 USART_SetTransmitterEnabled(USART1, 0);
170 USART_SetReceiverEnabled(USART1, 0);
171
172#ifdef CARDEMU_SECOND_UART
173 NVIC_DisableIRQ(USART0_IRQn);
174 USART_SetTransmitterEnabled(USART0, 0);
175 USART_SetReceiverEnabled(USART0, 0);
176#endif
177}
178
179/* main loop function, called repeatedly */
180void mode_cardemu_run(void)
181{
182 int rst_active, vcc_active;
183
184 /* usb_to_host() is handled by main() */
185
186 if (ch1) {
187 rst_active = PIO_Get(&pin_usim1_rst) ? 0 : 1;
188 vcc_active = PIO_Get(&pin_usim1_vcc) ? 1 : 0;
189 card_emu_io_statechg(ch1, CARD_IO_RST, rst_active);
190 card_emu_io_statechg(ch1, CARD_IO_VCC, vcc_active);
191 /* FIXME: clock ? */
192 }
193 usb_from_host(PHONE_DATAOUT);
194
195#ifdef CARDEMU_SECOND_UART
196 if (ch2) {
197 rst_active = PIO_Get(&pin_usim2_rst) ? 0 : 1;
198 vcc_active = PIO_Get(&pin_usim2_vcc) ? 1 : 0;
199 card_emu_io_statechg(ch2, CARD_IO_RST, rst_active);
200 card_emu_io_statechg(ch2, CARD_IO_VCC, vcc_active);
201 /* FIXME: clock ? */
202 }
203 usb_from_host(FIXME);
204#endif
205}