blob: 08d61200c037dfb64adf3213e658a7a36c098b5b [file] [log] [blame]
Kévin Redon9a12d682018-07-08 13:21:16 +02001/* SIMtrace 2 firmware sniffer application
2 *
3 * (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
4 * (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
Kévin Redonf9997e92018-06-04 16:21:23 +020020/*------------------------------------------------------------------------------
21 * Headers
22 *------------------------------------------------------------------------------*/
23
24#include "board.h"
25#include "simtrace.h"
26#include "utils.h"
Harald Weltee3b2de42020-01-11 12:31:51 +010027#include "main_common.h"
Kévin Redonf9997e92018-06-04 16:21:23 +020028#include "osmocom/core/timer.h"
29
Kévin Redonf9997e92018-06-04 16:21:23 +020030/*------------------------------------------------------------------------------
31 * Internal variables
32 *------------------------------------------------------------------------------*/
33typedef struct {
34 /* static initialization, called whether or not the usb config is active */
35 void (*configure) (void);
36 /* initialization function after the config was selected */
37 void (*init) (void);
38 /* de-initialization before selecting new config */
39 void (*exit) (void);
40 /* main loop content for given configuration */
41 void (*run) (void);
Kévin Redon866d20b2018-06-25 15:57:44 +020042 /* Interrupt handler for USART0 */
Kévin Redonf9997e92018-06-04 16:21:23 +020043 void (*usart0_irq) (void);
44 /* Interrupt handler for USART1 */
45 void (*usart1_irq) (void);
46} conf_func;
47
48static const conf_func config_func_ptrs[] = {
49 /* array slot 0 is empty, usb configs start at 1 */
50#ifdef HAVE_SNIFFER
51 [CFG_NUM_SNIFF] = {
52 .configure = Sniffer_configure,
53 .init = Sniffer_init,
54 .exit = Sniffer_exit,
55 .run = Sniffer_run,
Kévin Redon45ad62d2018-06-07 18:56:41 +020056 .usart0_irq = Sniffer_usart0_irq,
Kévin Redon353351d2018-06-11 13:45:16 +020057 .usart1_irq = Sniffer_usart1_irq,
Kévin Redonf9997e92018-06-04 16:21:23 +020058 },
59#endif
60#ifdef HAVE_CCID
61 [CFG_NUM_CCID] = {
62 .configure = CCID_configure,
63 .init = CCID_init,
64 .exit = CCID_exit,
65 .run = CCID_run,
66 },
67#endif
68#ifdef HAVE_CARDEM
69 [CFG_NUM_PHONE] = {
70 .configure = mode_cardemu_configure,
71 .init = mode_cardemu_init,
72 .exit = mode_cardemu_exit,
73 .run = mode_cardemu_run,
74 .usart0_irq = mode_cardemu_usart0_irq,
75 .usart1_irq = mode_cardemu_usart1_irq,
76 },
77#endif
78#ifdef HAVE_MITM
79 [CFG_NUM_MITM] = {
80 .configure = MITM_configure,
81 .init = MITM_init,
82 .exit = MITM_exit,
83 .run = MITM_run,
84 },
85#endif
86};
87
88/*------------------------------------------------------------------------------
89 * Internal variables
90 *------------------------------------------------------------------------------*/
91#if defined(HAVE_SNIFFER)
92static volatile enum confNum simtrace_config = CFG_NUM_SNIFF;
93#elif defined(HAVE_CARDEM)
94static volatile enum confNum simtrace_config = CFG_NUM_PHONE;
95#elif defined(HAVE_CCID)
96static volatile enum confNum simtrace_config = CFG_NUM_CCID;
97#endif
98
99/*----------------------------------------------------------------------------
100 * Callbacks
101 *----------------------------------------------------------------------------*/
102
103void USBDDriverCallbacks_ConfigurationChanged(uint8_t cfgnum)
104{
105 TRACE_INFO_WP("cfgChanged%d ", cfgnum);
106 simtrace_config = cfgnum;
107}
108
109void USART1_IrqHandler(void)
110{
111 if (config_func_ptrs[simtrace_config].usart1_irq)
112 config_func_ptrs[simtrace_config].usart1_irq();
113}
114
115void USART0_IrqHandler(void)
116{
117 if (config_func_ptrs[simtrace_config].usart0_irq)
118 config_func_ptrs[simtrace_config].usart0_irq();
119}
120
121/* returns '1' in case we should break any endless loop */
122static void check_exec_dbg_cmd(void)
123{
124 int ch;
125
126 if (!UART_IsRxReady())
127 return;
128
129 ch = UART_GetChar();
130
131 board_exec_dbg_cmd(ch);
132}
133
134/*------------------------------------------------------------------------------
135 * Main
136 *------------------------------------------------------------------------------*/
137#define MAX_USB_ITER BOARD_MCK/72 // This should be around a second
138extern int main(void)
139{
140 uint8_t isUsbConnected = 0;
141 enum confNum last_simtrace_config = simtrace_config;
142 unsigned int i = 0;
143
Kévin Redonda5578b2018-07-08 16:32:20 +0200144 /* Configure LED output
145 * red on = power
146 * red blink = error
147 * green on = running
148 * green blink = activity
149 */
Kévin Redonf9997e92018-06-04 16:21:23 +0200150 led_init();
Kévin Redoncf599192018-06-27 16:38:31 +0200151 led_blink(LED_RED, BLINK_ALWAYS_ON);
Kévin Redonda5578b2018-07-08 16:32:20 +0200152 led_blink(LED_GREEN, BLINK_ALWAYS_ON);
Kévin Redonf9997e92018-06-04 16:21:23 +0200153
Kévin Redon866d20b2018-06-25 15:57:44 +0200154 /* Enable watchdog for 2000 ms, with no window */
Kévin Redonf9997e92018-06-04 16:21:23 +0200155 WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT |
Kévin Redon866d20b2018-06-25 15:57:44 +0200156 (WDT_GetPeriod(2000) << 16) | WDT_GetPeriod(2000));
Kévin Redonf9997e92018-06-04 16:21:23 +0200157
158 PIO_InitializeInterrupts(0);
159
Harald Weltee3b2de42020-01-11 12:31:51 +0100160 print_banner();
Kévin Redonf9997e92018-06-04 16:21:23 +0200161 board_main_top();
162
163 TRACE_INFO("USB init...\n\r");
164 SIMtrace_USB_Initialize();
165
166 while (USBD_GetState() < USBD_STATE_CONFIGURED) {
167 WDT_Restart(WDT);
168 check_exec_dbg_cmd();
169#if 0
170 if (i >= MAX_USB_ITER * 3) {
171 TRACE_ERROR("Resetting board (USB could "
172 "not be configured)\n\r");
173 USBD_Disconnect();
174 NVIC_SystemReset();
175 }
176#endif
177 i++;
178 }
179
180 TRACE_INFO("calling configure of all configurations...\n\r");
King Kévin86f48fc2018-07-04 14:15:39 +0200181 for (i = 1; i < ARRAY_SIZE(config_func_ptrs); i++) {
Kévin Redonf9997e92018-06-04 16:21:23 +0200182 if (config_func_ptrs[i].configure)
183 config_func_ptrs[i].configure();
184 }
185
186 TRACE_INFO("calling init of config %u...\n\r", simtrace_config);
187 config_func_ptrs[simtrace_config].init();
188 last_simtrace_config = simtrace_config;
189
190 TRACE_INFO("entering main loop...\n\r");
191 while (1) {
192 WDT_Restart(WDT);
193#if TRACE_LEVEL >= TRACE_LEVEL_DEBUG
194 const char rotor[] = { '-', '\\', '|', '/' };
195 putchar('\b');
196 putchar(rotor[i++ % ARRAY_SIZE(rotor)]);
197#endif
198 check_exec_dbg_cmd();
199 osmo_timers_prepare();
200 osmo_timers_update();
201
202 if (USBD_GetState() < USBD_STATE_CONFIGURED) {
203
204 if (isUsbConnected) {
205 isUsbConnected = 0;
206 }
207 } else if (isUsbConnected == 0) {
208 TRACE_INFO("USB is now configured\n\r");
209
210 isUsbConnected = 1;
211 }
212 if (last_simtrace_config != simtrace_config) {
213 TRACE_INFO("USB config chg %u -> %u\n\r",
214 last_simtrace_config, simtrace_config);
215 config_func_ptrs[last_simtrace_config].exit();
216 config_func_ptrs[simtrace_config].init();
217 last_simtrace_config = simtrace_config;
218 } else {
219 config_func_ptrs[simtrace_config].run();
220 }
221 }
222}