blob: 9ee31ca7238371137bb8f0893e40d416819b61be [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"
Harald Welte54cb3d02016-02-29 14:12:40 +01004#include "utils.h"
Harald Welteacae4122016-03-02 10:27:58 +01005#include "linuxlist.h"
Harald Weltebd717682016-02-28 19:30:05 +01006
7#define TRACE_ENTRY() TRACE_DEBUG("%s entering\n", __func__)
Harald Welte2a6d3af2016-02-28 19:29:14 +01008
9static const Pin pins_cardsim[] = PINS_CARDSIM;
10
11/* UART pins */
12static const Pin pins_usim1[] = {PINS_USIM1};
13static const Pin pin_usim1_rst = PIN_USIM1_nRST;
14static const Pin pin_usim1_vcc = PIN_USIM1_VCC;
15
16#ifdef CARDEMU_SECOND_UART
17static const Pin pins_usim2[] = {PINS_USIM1};
18static const Pin pin_usim2_rst = PIN_USIM2_nRST;
19static const Pin pin_usim2_vcc = PIN_USIM2_VCC;
20#endif
21
22static struct card_handle *ch1, *ch2;
Harald Weltec0bd7f02016-02-29 10:13:33 +010023static struct ringbuf ch1_rb;
Harald Welte2a6d3af2016-02-28 19:29:14 +010024
25static struct Usart_info usart_info[] = {
26 {
27 .base = USART1,
28 .id = ID_USART1,
29 .state = USART_RCV
30 },
31#ifdef CARDEMU_SECOND_UART
32 {
33 .base = USART0,
34 .id = ID_USART0,
35 .state = USART_RCV
36 },
37#endif
38};
39
40static Usart *get_usart_by_chan(uint8_t uart_chan)
41{
42 switch (uart_chan) {
43 case 0:
44 return USART1;
45#ifdef CARDEMU_SECOND_UART
46 case 1:
47 return USART0;
48#endif
49 }
50 return NULL;
51}
52
53/***********************************************************************
54 * Call-Backs from card_emu.c
55 ***********************************************************************/
56
57/* call-back from card_emu.c to enable/disable transmit and/or receive */
58void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx)
59{
60 Usart *usart = get_usart_by_chan(uart_chan);
61 switch (rxtx) {
62 case ENABLE_TX:
Harald Welte9dbc46e2016-02-29 10:05:10 +010063 USART_DisableIt(usart, ~US_IER_TXRDY);
Harald Welte2a6d3af2016-02-28 19:29:14 +010064 USART_SetReceiverEnabled(usart, 0);
Harald Welte8a416b12016-03-01 00:42:04 +010065 usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
66 USART_EnableIt(usart, US_IER_TXRDY);
Harald Welte2a6d3af2016-02-28 19:29:14 +010067 USART_SetTransmitterEnabled(usart, 1);
68 break;
69 case ENABLE_RX:
Harald Welte9dbc46e2016-02-29 10:05:10 +010070 USART_DisableIt(usart, ~US_IER_RXRDY);
Harald Welte8a416b12016-03-01 00:42:04 +010071 USART_SetTransmitterEnabled(usart, 0);
72 usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
73 USART_EnableIt(usart, US_IER_RXRDY);
74 USART_SetReceiverEnabled(usart, 1);
Harald Welte2a6d3af2016-02-28 19:29:14 +010075 break;
76 case 0:
77 default:
78 USART_SetTransmitterEnabled(usart, 0);
79 USART_SetReceiverEnabled(usart, 0);
Harald Welte9dbc46e2016-02-29 10:05:10 +010080 USART_DisableIt(usart, 0xFFFFFFFF);
Harald Welte8a416b12016-03-01 00:42:04 +010081 usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
Harald Welte2a6d3af2016-02-28 19:29:14 +010082 break;
83 }
84}
85
86/* call-back from card_emu.c to transmit a byte */
87int card_emu_uart_tx(uint8_t uart_chan, uint8_t byte)
88{
89 Usart_info *ui = &usart_info[uart_chan];
90 ISO7816_SendChar(byte, ui);
91 return 1;
92}
93
94
95/* FIXME: integrate this with actual irq handler */
Harald Weltec0bd7f02016-02-29 10:13:33 +010096void usart_irq_rx(uint8_t uart)
Harald Welte2a6d3af2016-02-28 19:29:14 +010097{
Harald Weltec0bd7f02016-02-29 10:13:33 +010098 Usart *usart = get_usart_by_chan(uart);
Harald Welte2a6d3af2016-02-28 19:29:14 +010099 struct card_handle *ch = ch1;
Harald Weltec0bd7f02016-02-29 10:13:33 +0100100 uint32_t csr;
101 uint8_t byte = 0;
102
Harald Welte2a6d3af2016-02-28 19:29:14 +0100103#ifdef CARDEMU_SECOND_UART
Harald Weltec0bd7f02016-02-29 10:13:33 +0100104 if (uart == 1)
Harald Welte2a6d3af2016-02-28 19:29:14 +0100105 ch = ch2;
106#endif
Harald Weltec0bd7f02016-02-29 10:13:33 +0100107 csr = usart->US_CSR;
Harald Welte2a6d3af2016-02-28 19:29:14 +0100108
Harald Welte45688d42016-02-29 21:35:38 +0100109 if (csr & US_CSR_TXRDY) {
110 if (card_emu_tx_byte(ch) == 0)
111 USART_DisableIt(usart, US_IER_TXRDY);
112 }
Harald Welte2a6d3af2016-02-28 19:29:14 +0100113
Harald Weltec0bd7f02016-02-29 10:13:33 +0100114 if (csr & US_CSR_RXRDY) {
115 byte = (usart->US_RHR) & 0xFF;
116 rbuf_write(&ch1_rb, byte);
117 }
Harald Welte2a6d3af2016-02-28 19:29:14 +0100118
119 if (csr & (US_CSR_OVRE|US_CSR_FRAME|US_CSR_PARE|
120 US_CSR_TIMEOUT|US_CSR_NACK|(1<<10))) {
Harald Weltec0bd7f02016-02-29 10:13:33 +0100121 usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
122 TRACE_ERROR("e 0x%x st: 0x%x\n", byte, csr);
Harald Welte2a6d3af2016-02-28 19:29:14 +0100123 }
124}
125
Harald Weltebd717682016-02-28 19:30:05 +0100126/* call-back from card_emu.c to change UART baud rate */
127int card_emu_uart_update_fidi(uint8_t uart_chan, unsigned int fidi)
128{
129 int rc;
Harald Weltebd717682016-02-28 19:30:05 +0100130 Usart *usart = get_usart_by_chan(uart_chan);
131
Harald Welte99f62a62016-02-29 10:08:49 +0100132 usart->US_CR |= US_CR_RXDIS | US_CR_RSTRX;
133 usart->US_FIDI = fidi & 0x3ff;
134 usart->US_CR |= US_CR_RXEN | US_CR_STTTO;
135 return 0;
Harald Weltebd717682016-02-28 19:30:05 +0100136}
Harald Welte2a6d3af2016-02-28 19:29:14 +0100137
138/***********************************************************************
139 * Core USB / mainloop integration
140 ***********************************************************************/
141
Harald Weltec0bd7f02016-02-29 10:13:33 +0100142static void usim1_rst_irqhandler(const Pin *pPin)
143{
144 int active = PIO_Get(&pin_usim1_rst) ? 0 : 1;
145 card_emu_io_statechg(ch1, CARD_IO_RST, active);
146}
147
148static void usim1_vcc_irqhandler(const Pin *pPin)
149{
150 int active = PIO_Get(&pin_usim1_vcc) ? 1 : 0;
151 card_emu_io_statechg(ch1, CARD_IO_VCC, active);
152 /* FIXME do this for real */
153 card_emu_io_statechg(ch1, CARD_IO_CLK, active);
154}
155
Harald Welte2a6d3af2016-02-28 19:29:14 +0100156/* executed once at system boot for each config */
157void mode_cardemu_configure(void)
158{
Harald Weltebd717682016-02-28 19:30:05 +0100159 TRACE_ENTRY();
Harald Welte2a6d3af2016-02-28 19:29:14 +0100160}
161
162/* called if config is activated */
163void mode_cardemu_init(void)
164{
Harald Weltebd717682016-02-28 19:30:05 +0100165 TRACE_ENTRY();
166
Harald Weltec0bd7f02016-02-29 10:13:33 +0100167 rbuf_reset(&ch1_rb);
168
Harald Welte2a6d3af2016-02-28 19:29:14 +0100169 PIO_Configure(pins_cardsim, PIO_LISTSIZE(pins_cardsim));
170
171 PIO_Configure(pins_usim1, PIO_LISTSIZE(pins_usim1));
172 ISO7816_Init(&usart_info[0], CLK_SLAVE);
Harald Welte9dbc46e2016-02-29 10:05:10 +0100173 //USART_EnableIt(USART1, US_IER_RXRDY);
Harald Welte2a6d3af2016-02-28 19:29:14 +0100174 NVIC_EnableIRQ(USART1_IRQn);
Harald Weltec0bd7f02016-02-29 10:13:33 +0100175
176 PIO_ConfigureIt(&pin_usim1_rst, usim1_rst_irqhandler);
177 PIO_EnableIt(&pin_usim1_rst);
178 PIO_ConfigureIt(&pin_usim1_vcc, usim1_vcc_irqhandler);
179 PIO_EnableIt(&pin_usim1_vcc);
180
Harald Welte2a6d3af2016-02-28 19:29:14 +0100181 ch1 = card_emu_init(0, 2, 0);
182
183#ifdef CARDEMU_SECOND_UART
184 PIO_Configure(pins_usim2, PIO_LISTSIZE(pins_usim2));
185 ISO7816_Init(&usart_info[1], CLK_SLAVE);
Harald Welte9dbc46e2016-02-29 10:05:10 +0100186 //USART_EnableIt(USART0, US_IER_RXRDY);
Harald Welte2a6d3af2016-02-28 19:29:14 +0100187 NVIC_EnableIRQ(USART0_IRQn);
188 ch2 = card_emu_init(1, 0, 1);
189#endif
190}
191
192/* called if config is deactivated */
193void mode_cardemu_exit(void)
194{
Harald Weltebd717682016-02-28 19:30:05 +0100195 TRACE_ENTRY();
196
Harald Weltec0bd7f02016-02-29 10:13:33 +0100197 PIO_DisableIt(&pin_usim1_rst);
198 PIO_DisableIt(&pin_usim1_vcc);
199
Harald Welte2a6d3af2016-02-28 19:29:14 +0100200 NVIC_DisableIRQ(USART1_IRQn);
201 USART_SetTransmitterEnabled(USART1, 0);
202 USART_SetReceiverEnabled(USART1, 0);
203
204#ifdef CARDEMU_SECOND_UART
205 NVIC_DisableIRQ(USART0_IRQn);
206 USART_SetTransmitterEnabled(USART0, 0);
207 USART_SetReceiverEnabled(USART0, 0);
208#endif
209}
210
Harald Welteacae4122016-03-02 10:27:58 +0100211static int llist_count(struct llist_head *head)
212{
213 struct llist_head *list;
214 int i = 0;
215
216 llist_for_each(list, head)
217 i++;
218
219 return i;
220}
221
222static int usb_pending_old = 0;
223
Harald Welte2a6d3af2016-02-28 19:29:14 +0100224/* main loop function, called repeatedly */
225void mode_cardemu_run(void)
226{
Harald Welteacae4122016-03-02 10:27:58 +0100227 struct llist_head *queue;
228
Harald Welte2a6d3af2016-02-28 19:29:14 +0100229 if (ch1) {
Harald Welte54cb3d02016-02-29 14:12:40 +0100230 /* drain the ring buffer from UART into card_emu */
Harald Weltec0bd7f02016-02-29 10:13:33 +0100231 while (1) {
232 __disable_irq();
233 if (rbuf_is_empty(&ch1_rb)) {
234 __enable_irq();
235 break;
236 }
237 uint8_t byte = rbuf_read(&ch1_rb);
238 __enable_irq();
239 card_emu_process_rx_byte(ch1, byte);
Harald Welteacae4122016-03-02 10:27:58 +0100240 TRACE_ERROR("Rx%02x\r\n", byte);
Harald Weltec0bd7f02016-02-29 10:13:33 +0100241 }
Harald Welteacae4122016-03-02 10:27:58 +0100242
243 queue = card_emu_get_usb_tx_queue(ch1);
244 int usb_pending = llist_count(queue);
245 if (usb_pending != usb_pending_old) {
246// printf("usb_pending=%d\r\n", usb_pending);
247 usb_pending_old = usb_pending;
248 }
249 usb_refill_to_host(queue, PHONE_DATAIN);
250
251 queue = card_emu_get_uart_tx_queue(ch1);
252 usb_refill_from_host(queue, PHONE_DATAOUT);
253 if (llist_count(queue))
254 card_emu_have_new_uart_tx(ch1);
Harald Welte2a6d3af2016-02-28 19:29:14 +0100255 }
Harald Welte2a6d3af2016-02-28 19:29:14 +0100256
257#ifdef CARDEMU_SECOND_UART
258 if (ch2) {
259 rst_active = PIO_Get(&pin_usim2_rst) ? 0 : 1;
260 vcc_active = PIO_Get(&pin_usim2_vcc) ? 1 : 0;
261 card_emu_io_statechg(ch2, CARD_IO_RST, rst_active);
262 card_emu_io_statechg(ch2, CARD_IO_VCC, vcc_active);
263 /* FIXME: clock ? */
264 }
265 usb_from_host(FIXME);
266#endif
267}