blob: 97455fbc35c1ffc7e52a4cab3b290451c5279878 [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"
27#include "osmocom/core/timer.h"
28
29unsigned int g_unique_id[4];
30
31/*------------------------------------------------------------------------------
32 * Internal variables
33 *------------------------------------------------------------------------------*/
34typedef struct {
35 /* static initialization, called whether or not the usb config is active */
36 void (*configure) (void);
37 /* initialization function after the config was selected */
38 void (*init) (void);
39 /* de-initialization before selecting new config */
40 void (*exit) (void);
41 /* main loop content for given configuration */
42 void (*run) (void);
Kévin Redon866d20b2018-06-25 15:57:44 +020043 /* Interrupt handler for USART0 */
Kévin Redonf9997e92018-06-04 16:21:23 +020044 void (*usart0_irq) (void);
45 /* Interrupt handler for USART1 */
46 void (*usart1_irq) (void);
47} conf_func;
48
49static const conf_func config_func_ptrs[] = {
50 /* array slot 0 is empty, usb configs start at 1 */
51#ifdef HAVE_SNIFFER
52 [CFG_NUM_SNIFF] = {
53 .configure = Sniffer_configure,
54 .init = Sniffer_init,
55 .exit = Sniffer_exit,
56 .run = Sniffer_run,
Kévin Redon45ad62d2018-06-07 18:56:41 +020057 .usart0_irq = Sniffer_usart0_irq,
Kévin Redon353351d2018-06-11 13:45:16 +020058 .usart1_irq = Sniffer_usart1_irq,
Kévin Redonf9997e92018-06-04 16:21:23 +020059 },
60#endif
61#ifdef HAVE_CCID
62 [CFG_NUM_CCID] = {
63 .configure = CCID_configure,
64 .init = CCID_init,
65 .exit = CCID_exit,
66 .run = CCID_run,
67 },
68#endif
69#ifdef HAVE_CARDEM
70 [CFG_NUM_PHONE] = {
71 .configure = mode_cardemu_configure,
72 .init = mode_cardemu_init,
73 .exit = mode_cardemu_exit,
74 .run = mode_cardemu_run,
75 .usart0_irq = mode_cardemu_usart0_irq,
76 .usart1_irq = mode_cardemu_usart1_irq,
77 },
78#endif
79#ifdef HAVE_MITM
80 [CFG_NUM_MITM] = {
81 .configure = MITM_configure,
82 .init = MITM_init,
83 .exit = MITM_exit,
84 .run = MITM_run,
85 },
86#endif
87};
88
89/*------------------------------------------------------------------------------
90 * Internal variables
91 *------------------------------------------------------------------------------*/
92#if defined(HAVE_SNIFFER)
93static volatile enum confNum simtrace_config = CFG_NUM_SNIFF;
94#elif defined(HAVE_CARDEM)
95static volatile enum confNum simtrace_config = CFG_NUM_PHONE;
96#elif defined(HAVE_CCID)
97static volatile enum confNum simtrace_config = CFG_NUM_CCID;
98#endif
99
100/*----------------------------------------------------------------------------
101 * Callbacks
102 *----------------------------------------------------------------------------*/
103
104void USBDDriverCallbacks_ConfigurationChanged(uint8_t cfgnum)
105{
106 TRACE_INFO_WP("cfgChanged%d ", cfgnum);
107 simtrace_config = cfgnum;
108}
109
110void USART1_IrqHandler(void)
111{
112 if (config_func_ptrs[simtrace_config].usart1_irq)
113 config_func_ptrs[simtrace_config].usart1_irq();
114}
115
116void USART0_IrqHandler(void)
117{
118 if (config_func_ptrs[simtrace_config].usart0_irq)
119 config_func_ptrs[simtrace_config].usart0_irq();
120}
121
122/* returns '1' in case we should break any endless loop */
123static void check_exec_dbg_cmd(void)
124{
125 int ch;
126
127 if (!UART_IsRxReady())
128 return;
129
130 ch = UART_GetChar();
131
132 board_exec_dbg_cmd(ch);
133}
134
135/*------------------------------------------------------------------------------
136 * Main
137 *------------------------------------------------------------------------------*/
138#define MAX_USB_ITER BOARD_MCK/72 // This should be around a second
139extern int main(void)
140{
141 uint8_t isUsbConnected = 0;
142 enum confNum last_simtrace_config = simtrace_config;
143 unsigned int i = 0;
144
Kévin Redonda5578b2018-07-08 16:32:20 +0200145 /* Configure LED output
146 * red on = power
147 * red blink = error
148 * green on = running
149 * green blink = activity
150 */
Kévin Redonf9997e92018-06-04 16:21:23 +0200151 led_init();
Kévin Redoncf599192018-06-27 16:38:31 +0200152 led_blink(LED_RED, BLINK_ALWAYS_ON);
Kévin Redonda5578b2018-07-08 16:32:20 +0200153 led_blink(LED_GREEN, BLINK_ALWAYS_ON);
Kévin Redonf9997e92018-06-04 16:21:23 +0200154
Kévin Redon866d20b2018-06-25 15:57:44 +0200155 /* Enable watchdog for 2000 ms, with no window */
Kévin Redonf9997e92018-06-04 16:21:23 +0200156 WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT |
Kévin Redon866d20b2018-06-25 15:57:44 +0200157 (WDT_GetPeriod(2000) << 16) | WDT_GetPeriod(2000));
Kévin Redonf9997e92018-06-04 16:21:23 +0200158
159 PIO_InitializeInterrupts(0);
160
161 EEFC_ReadUniqueID(g_unique_id);
162
Kévin Redon33d1eb72018-07-08 13:58:12 +0200163 printf("\n\r\n\r"
Kévin Redonf9997e92018-06-04 16:21:23 +0200164 "=============================================================================\n\r"
165 "SIMtrace2 firmware " GIT_VERSION " (C) 2010-2016 by Harald Welte\n\r"
166 "=============================================================================\n\r");
167
Harald Weltec3941092018-08-26 09:53:13 +0200168 TRACE_INFO("Chip ID: 0x%08lx (Ext 0x%08lx)\n\r", CHIPID->CHIPID_CIDR, CHIPID->CHIPID_EXID);
Kévin Redonf9997e92018-06-04 16:21:23 +0200169 TRACE_INFO("Serial Nr. %08x-%08x-%08x-%08x\n\r",
170 g_unique_id[0], g_unique_id[1],
171 g_unique_id[2], g_unique_id[3]);
Harald Weltec3941092018-08-26 09:53:13 +0200172 TRACE_INFO("Reset Cause: 0x%lx\n\r", (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos);
Kévin Redon45ad62d2018-06-07 18:56:41 +0200173 TRACE_INFO("USB configuration used: %d\n\r", simtrace_config);
Kévin Redonf9997e92018-06-04 16:21:23 +0200174
175 board_main_top();
176
177 TRACE_INFO("USB init...\n\r");
178 SIMtrace_USB_Initialize();
179
180 while (USBD_GetState() < USBD_STATE_CONFIGURED) {
181 WDT_Restart(WDT);
182 check_exec_dbg_cmd();
183#if 0
184 if (i >= MAX_USB_ITER * 3) {
185 TRACE_ERROR("Resetting board (USB could "
186 "not be configured)\n\r");
187 USBD_Disconnect();
188 NVIC_SystemReset();
189 }
190#endif
191 i++;
192 }
193
194 TRACE_INFO("calling configure of all configurations...\n\r");
King Kévin86f48fc2018-07-04 14:15:39 +0200195 for (i = 1; i < ARRAY_SIZE(config_func_ptrs); i++) {
Kévin Redonf9997e92018-06-04 16:21:23 +0200196 if (config_func_ptrs[i].configure)
197 config_func_ptrs[i].configure();
198 }
199
200 TRACE_INFO("calling init of config %u...\n\r", simtrace_config);
201 config_func_ptrs[simtrace_config].init();
202 last_simtrace_config = simtrace_config;
203
204 TRACE_INFO("entering main loop...\n\r");
205 while (1) {
206 WDT_Restart(WDT);
207#if TRACE_LEVEL >= TRACE_LEVEL_DEBUG
208 const char rotor[] = { '-', '\\', '|', '/' };
209 putchar('\b');
210 putchar(rotor[i++ % ARRAY_SIZE(rotor)]);
211#endif
212 check_exec_dbg_cmd();
213 osmo_timers_prepare();
214 osmo_timers_update();
215
216 if (USBD_GetState() < USBD_STATE_CONFIGURED) {
217
218 if (isUsbConnected) {
219 isUsbConnected = 0;
220 }
221 } else if (isUsbConnected == 0) {
222 TRACE_INFO("USB is now configured\n\r");
223
224 isUsbConnected = 1;
225 }
226 if (last_simtrace_config != simtrace_config) {
227 TRACE_INFO("USB config chg %u -> %u\n\r",
228 last_simtrace_config, simtrace_config);
229 config_func_ptrs[last_simtrace_config].exit();
230 config_func_ptrs[simtrace_config].init();
231 last_simtrace_config = simtrace_config;
232 } else {
233 config_func_ptrs[simtrace_config].run();
234 }
235 }
236}