aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2021-07-02 15:02:33 +0200
committerlaforge <laforge@osmocom.org>2021-08-02 09:22:46 +0000
commit4fe93be7257bbdd49bb6d7adf77fad244f1ab073 (patch)
treec0185e937eb90c13a99d130172550646c4c8baab
parent51d87fbb669729244066c16c31fecfb879dc2dd5 (diff)
introduce support for new ngff_cardem board
This adds support for the new ngff_cardem board, a board that basically combines a ngff breakout board with a built-in SIMtrace2. Cardem works, but depending on the modem it might need a adjusted ATR to ensure a lower baud rate is used by the modem, high rates might lead to weird power cycling of the card after a few transfers. Trace was also tested and appears to work as expected. Change-Id: Ia96124fbe8a752c98e7fd4096d542a3b2b9bc255
-rwxr-xr-xcontrib/flash.py3
-rw-r--r--contrib/simtrace.lua1
-rw-r--r--firmware/apps/cardem/main.c5
-rw-r--r--firmware/libboard/ngff_cardem/include/board.h166
-rw-r--r--firmware/libboard/ngff_cardem/include/card_pres.h22
-rw-r--r--firmware/libboard/ngff_cardem/include/wwan_led.h20
-rw-r--r--firmware/libboard/ngff_cardem/include/wwan_perst.h21
-rw-r--r--firmware/libboard/ngff_cardem/product_string.txt1
-rw-r--r--firmware/libboard/ngff_cardem/source/board_ngff_cardem.c159
-rw-r--r--firmware/libboard/ngff_cardem/source/card_pres.c76
-rw-r--r--firmware/libboard/ngff_cardem/source/sim_switch.c81
-rw-r--r--firmware/libboard/ngff_cardem/source/wwan_led.c93
-rw-r--r--firmware/libboard/ngff_cardem/source/wwan_perst.c127
-rw-r--r--firmware/libboard/simtrace/include/board.h2
-rw-r--r--firmware/libcommon/include/simtrace_usb.h1
-rw-r--r--firmware/libcommon/source/mode_cardemu.c24
-rw-r--r--host/contrib/99-simtrace2.rules2
-rw-r--r--host/lib/usb_util.c1
-rw-r--r--host/src/simtrace2-sniff.c1
19 files changed, 798 insertions, 8 deletions
diff --git a/contrib/flash.py b/contrib/flash.py
index 21903bb..01fe7c9 100755
--- a/contrib/flash.py
+++ b/contrib/flash.py
@@ -28,7 +28,8 @@ DEVICE_SIMTRACE = Device(usb_vendor_id=0x1d50, usb_product_id=0x60e3, name="SIMt
DEVICE_QMOD = Device(usb_vendor_id=0x1d50, usb_product_id=0x4004, name="sysmoQMOD (Quad Modem)", url={"cardem": "https://ftp.osmocom.org/binaries/simtrace2/firmware/latest/qmod-cardem-dfu-latest.bin"})
DEVICE_OWHW = Device(usb_vendor_id=0x1d50, usb_product_id=0x4001, name="OWHW", url={"cardem": "https://ftp.osmocom.org/binaries/simtrace2/firmware/latest/owhw-cardem-dfu-latest.bin"})
DEVICE_OCTSIMTEST = Device(usb_vendor_id=0x1d50, usb_product_id=0x616d, name="OCTSIMTEST", url={"cardem": "https://ftp.osmocom.org/binaries/simtrace2/firmware/latest/octsimtest-cardem-dfu-latest.bin"})
-DEVICES = [DEVICE_SIMTRACE, DEVICE_QMOD, DEVICE_OCTSIMTEST]
+DEVICE_NGFF_CARDEM = Device(usb_vendor_id=0x1d50, usb_product_id=0x616e, name="ngff-cardem", url={"cardem": "https://ftp.osmocom.org/binaries/simtrace2/firmware/latest/ngff_cardem-cardem-dfu-latest.bin"})
+DEVICES = [DEVICE_SIMTRACE, DEVICE_QMOD, DEVICE_OCTSIMTEST, DEVICE_NGFF_CARDEM]
# which firmware does the SIMtrace USN interface subclass correspond
FIRMWARE_SUBCLASS = {1: "trace", 2: "cardem"}
diff --git a/contrib/simtrace.lua b/contrib/simtrace.lua
index 68eb961..8298265 100644
--- a/contrib/simtrace.lua
+++ b/contrib/simtrace.lua
@@ -62,6 +62,7 @@ end
function usb_simtrace_protocol.init()
local usb_product_dissectors = DissectorTable.get("usb.product")
usb_product_dissectors:add(0x1d50616d, usb_simtrace_protocol)
+usb_product_dissectors:add(0x1d50616e, usb_simtrace_protocol)
-- DissectorTable.get("usb.bulk"):add(0xffff, usb_simtrace_protocol)
end
diff --git a/firmware/apps/cardem/main.c b/firmware/apps/cardem/main.c
index a30a211..95967ba 100644
--- a/firmware/apps/cardem/main.c
+++ b/firmware/apps/cardem/main.c
@@ -71,8 +71,13 @@ static const conf_func config_func_ptrs[] = {
.init = mode_cardemu_init,
.exit = mode_cardemu_exit,
.run = mode_cardemu_run,
+#if defined (ngff_cardem)
+ .usart0_irq = mode_cardemu_usart1_irq,
+ .usart1_irq = mode_cardemu_usart0_irq,
+#else
.usart0_irq = mode_cardemu_usart0_irq,
.usart1_irq = mode_cardemu_usart1_irq,
+#endif
},
#endif
#ifdef HAVE_MITM
diff --git a/firmware/libboard/ngff_cardem/include/board.h b/firmware/libboard/ngff_cardem/include/board.h
new file mode 100644
index 0000000..8be7b7f
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/include/board.h
@@ -0,0 +1,166 @@
+/* Osmocom ngff-cardem board definition
+ *
+ * (C) 2021 by Harald Welte <laforge@osmocom.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ */
+#pragma once
+#include "board_common.h"
+#include "simtrace_usb.h"
+
+/** Name of the board */
+#define BOARD_NAME "NGFF-CARDEM"
+/** Board definition */
+#define ngff_cardem
+
+/** oscillator used as main clock source (in Hz) */
+#define BOARD_MAINOSC 12000000
+/** desired main clock frequency (in Hz, based on BOARD_MAINOSC) */
+#define BOARD_MCK 58000000 // 12.000 * 29 / 6
+
+/** MCU pin connected to red LED */
+#define PIO_LED_RED PIO_PA17
+/** MCU pin connected to green LED */
+#define PIO_LED_GREEN PIO_PA18
+/** red LED pin definition */
+#define PIN_LED_RED {PIO_LED_RED, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+/** green LED pin definition */
+#define PIN_LED_GREEN {PIO_LED_GREEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+/** LEDs pin definition */
+#define PINS_LEDS PIN_LED_RED, PIN_LED_GREEN
+/** index for red LED in LEDs pin definition array */
+#define LED_NUM_RED 0
+/** index for green LED in LEDs pin definition array */
+#define LED_NUM_GREEN 1
+/** the green LED is actually red and used as indication for USIM1 */
+#define LED_USIM1 LED_GREEN
+
+/* USIM 2 interface (USART) */
+#define PIN_USIM2_CLK {PIO_PA2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
+#define PIN_USIM2_IO {PIO_PA6, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+#define PINS_ISO7816_USIM2 PIN_USIM2_CLK, PIN_USIM2_IO
+
+/* USIM 2 interface (TC) */
+#define PIN_USIM2_IO_TC {PIO_PA1, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
+#define PIN_USIM2_CLK_TC {PIO_PA4, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
+#define PINS_TC_USIM2 PIN_USIM2_IO_TC, PIN_USIM2_CLK_TC
+
+/* USIM 1 interface (USART) */
+#define PIN_USIM1_IO {PIO_PA22, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+#define PIN_USIM1_CLK {PIO_PA23, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+#define PINS_ISO7816_USIM1 PIN_USIM1_CLK, PIN_USIM1_IO
+
+/* USIM 1 interface (TC) */
+#define PIN_USIM1_IO_TC {PIO_PA27, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
+#define PIN_USIM1_CLK_TC {PIO_PA29, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
+#define PINS_TC_USIM1 PIN_USIM1_IO_TC, PIN_USIM1_CLK_TC
+
+#define PIN_USIM1_nRST {PIO_PA24, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
+#define PIN_USIM1_VCC {PIO_PB3, PIOB, ID_PIOB, PIO_INPUT, PIO_DEFAULT}
+
+#define PIN_USIM2_nRST {PIO_PA7, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
+//#define PIN_USIM2_VCC {PIO_PB2, PIOB, ID_PIOB, PIO_INPUT, PIO_DEFAULT}
+
+#define PINS_USIM1 PINS_TC_USIM1, PINS_ISO7816_USIM1, PIN_USIM1_nRST
+#define PINS_USIM2 PINS_TC_USIM2, PINS_ISO7816_USIM2, PIN_USIM2_nRST
+
+/* from v3 and onwards only (!) */
+#define PIN_DET_USIM1_PRES {PIO_PA8, PIOA, ID_PIOA, PIO_INPUT, PIO_DEGLITCH | PIO_IT_EDGE}
+
+/* inputs reading the WWAN LED level */
+#define PIN_WWAN1 {PIO_PA15, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEGLITCH | PIO_IT_EDGE}
+#define PINS_WWAN_IN { PIN_WWAN1 }
+
+#define PIN_MODEM_EN {PIO_PA11, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+#define PIN_N_MODEM_PWR_ON {PIO_PA26, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+
+/* outputs controlling RESET input of modems */
+#define PIN_PERST1 {PIO_PA25, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+#define PINS_PERST { PIN_PERST1 }
+
+#define PIN_VERSION_DET {PIO_PA19, PIOA, ID_PIOA, PIO_PERIPH_D, PIO_DEFAULT}
+
+/* GPIO towards SPDT switches between real SIM and SAM3 */
+//#define PIN_SIM_SWITCH1 {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+//#define PIN_SIM_SWITCH2 {PIO_PA28, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+
+#define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_SELFPOWERED_NORWAKEUP
+
+#define BOARD_USB_VENDOR_ID USB_VENDOR_OPENMOKO
+#define BOARD_USB_PRODUCT_ID USB_PRODUCT_NGFF_CARDEM
+#define BOARD_DFU_USB_PRODUCT_ID USB_PRODUCT_NGFF_CARDEM
+#define BOARD_USB_RELEASE 0x010
+
+#define DETECT_VCC_BY_ADC
+#define VCC_UV_THRESH_1V8 1500000
+#define VCC_UV_THRESH_3V VCC_UV_THRESH_1V8
+
+#ifdef APPLICATION_cardem
+#define HAVE_CARDEM
+#define HAVE_BOARD_CARDINSERT
+struct cardem_inst;
+void board_set_card_insert(struct cardem_inst *ci, bool card_insert);
+#endif
+
+#ifdef APPLICATION_trace
+#define HAVE_SNIFFER
+#endif
+
+/* Card I/O data signal input/output (I/O_SIM in schematic) */
+#define PIN_SIM_IO {PIO_PA6A_TXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/* Card CLK clock input (CLK_SIM in schematic) */
+#define PIN_SIM_CLK {PIO_PA2B_SCK0, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
+/* Card RST reset signal input (use as input since the phone will drive it) */
+#define PIN_SIM_RST_SNIFF {PIO_PA7, PIOA, ID_PIOA, PIO_INPUT, PIO_DEGLITCH | PIO_IT_EDGE}
+/* Pins used to sniff phone-card communication */
+#define PINS_SIM_SNIFF PIN_SIM_IO, PIN_SIM_CLK, PIN_SIM_RST_SNIFF
+
+/* Pin to measure card I/O timing (to start measuring the ETU on I/O activity; connected I/O_SIM in schematic) */
+#define PIN_SIM_IO_INPUT {PIO_PA1B_TIOB0, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
+/* Pin used as clock input (to measure the ETU duration; connected to CLK_SIM in schematic) */
+#define PIN_SIM_CLK_INPUT {PIO_PA4B_TCLK0, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
+/* Pins used to measure ETU timing (using timer counter) */
+#define PINS_TC PIN_SIM_IO_INPUT, PIN_SIM_CLK_INPUT
+
+//default state: NO uart connected, modem connected to physical sim, NO sim presence override, modem powers sim slot
+#define pin_conn_usim1_default {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+#define pin_conn_usim2_default {PIO_PA28, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+#define pin_conn_mdm_sim_default {PIO_PA0, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+#define pin_conn_set_sim_det_default {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+#define pin_en_st_sim_vdd_default {PIO_PB2, PIOB, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT}
+#define pin_en_mdm_sim_vdd_default {PIO_PA16, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+
+//cardem state: uart2 (!) connected, NO modem connected to physical sim, sim presence override, NOTHING powers sim slot
+#define pin_conn_usim1_cem {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+#define pin_conn_usim2_cem {PIO_PA28, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+#define pin_conn_mdm_sim_cem {PIO_PA0, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+#define pin_en_st_sim_vdd_cem {PIO_PB2, PIOB, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT}
+#define pin_en_mdm_sim_vdd_cem {PIO_PA16, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+
+//trace state: uart2 (!) connected, modem connected to physical sim, st powers sim slot
+#define pin_conn_usim1_trace {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+#define pin_conn_usim2_trace {PIO_PA28, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+#define pin_conn_mdm_sim_trace {PIO_PA0, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+#define pin_conn_set_sim_det_trace {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+#define pin_en_st_sim_vdd_trace {PIO_PB2, PIOB, ID_PIOB, PIO_OUTPUT_1, PIO_DEFAULT}
+#define pin_en_mdm_sim_vdd_trace {PIO_PA16, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+
+#define PIN_MODEM_EN_off {PIO_PA11, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+
+#define PINS_SIM_DEFAULT pin_conn_usim1_default, pin_conn_usim2_default, pin_conn_mdm_sim_default, pin_conn_set_sim_det_default, PIN_N_MODEM_PWR_ON, PIN_MODEM_EN, pin_en_st_sim_vdd_default, pin_en_mdm_sim_vdd_default
+#define PINS_SIM_CARDEM pin_conn_usim1_cem, pin_conn_usim2_cem, pin_conn_mdm_sim_cem, pin_en_mdm_sim_vdd_cem, pin_en_st_sim_vdd_cem// , pin_conn_set_sim_det_cem
+
+#define PINS_BUS_SNIFF pin_conn_usim1_trace, pin_conn_usim2_trace, pin_conn_mdm_sim_trace, pin_conn_set_sim_det_trace,PIN_MODEM_EN_off
+#define PINS_PWR_SNIFF PIN_N_MODEM_PWR_ON, PIN_MODEM_EN, pin_en_st_sim_vdd_trace, pin_en_mdm_sim_vdd_trace
diff --git a/firmware/libboard/ngff_cardem/include/card_pres.h b/firmware/libboard/ngff_cardem/include/card_pres.h
new file mode 100644
index 0000000..81f0613
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/include/card_pres.h
@@ -0,0 +1,22 @@
+/* card presence utilities
+ *
+ * (C) 2016-2017 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ */
+#pragma once
+
+int is_card_present(int port);
+int card_present_init(void);
diff --git a/firmware/libboard/ngff_cardem/include/wwan_led.h b/firmware/libboard/ngff_cardem/include/wwan_led.h
new file mode 100644
index 0000000..77887c7
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/include/wwan_led.h
@@ -0,0 +1,20 @@
+/* Code to read/track the status of the WWAN LEDs of attached modems
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ */
+#pragma once
+
+int wwan_led_active(int wwan);
+int wwan_led_init(void);
diff --git a/firmware/libboard/ngff_cardem/include/wwan_perst.h b/firmware/libboard/ngff_cardem/include/wwan_perst.h
new file mode 100644
index 0000000..c934afc
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/include/wwan_perst.h
@@ -0,0 +1,21 @@
+/* Code to control the PERST lines of attached modems
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ */
+#pragma once
+
+int wwan_perst_set(int modem_nr, int active);
+int wwan_perst_do_reset_pulse(int modem_nr, unsigned int duration_ms);
+int wwan_perst_init(void);
diff --git a/firmware/libboard/ngff_cardem/product_string.txt b/firmware/libboard/ngff_cardem/product_string.txt
new file mode 100644
index 0000000..09a33c6
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/product_string.txt
@@ -0,0 +1 @@
+ngff-cardem
diff --git a/firmware/libboard/ngff_cardem/source/board_ngff_cardem.c b/firmware/libboard/ngff_cardem/source/board_ngff_cardem.c
new file mode 100644
index 0000000..0ac9cd8
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/source/board_ngff_cardem.c
@@ -0,0 +1,159 @@
+/* sysmocom ngff-cardem application code
+ *
+ * (C) 2021 Harald Welte <laforge@osmocom.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ */
+#include "board.h"
+#include "simtrace.h"
+#include "utils.h"
+#include "led.h"
+#include "wwan_led.h"
+#include "wwan_perst.h"
+#include "sim_switch.h"
+#include "boardver_adc.h"
+#include "card_pres.h"
+#include <osmocom/core/timer.h>
+#include "usb_buf.h"
+
+/* array of generated USB Strings */
+extern unsigned char *usb_strings[];
+
+/* returns '1' in case we should break any endless loop */
+void board_exec_dbg_cmd(int ch)
+{
+ switch (ch) {
+ case '?':
+ printf("\t?\thelp\n\r");
+ printf("\tR\treset SAM3\n\r");
+ printf("\tl\tswitch off LED 1\n\r");
+ printf("\tL\tswitch on LED 1\n\r");
+ printf("\tg\tswitch off LED 2\n\r");
+ printf("\tG\tswitch on LED 2\n\r");
+ printf("\t1\tGenerate 1ms reset pulse on WWAN1\n\r");
+ printf("\t!\tSwitch Channel A from physical -> remote\n\r");
+ printf("\tt\t(pseudo)talloc report\n\r");
+ break;
+ case 'R':
+ printf("Asking NVIC to reset us\n\r");
+ USBD_Disconnect();
+ NVIC_SystemReset();
+ break;
+ case 'l':
+ led_blink(LED_GREEN, BLINK_ALWAYS_OFF);
+ printf("LED 1 switched off\n\r");
+ break;
+ case 'L':
+ led_blink(LED_GREEN, BLINK_ALWAYS_ON);
+ printf("LED 1 switched on\n\r");
+ break;
+ case 'g':
+ led_blink(LED_RED, BLINK_ALWAYS_OFF);
+ printf("LED 2 switched off\n\r");
+ break;
+ case 'G':
+ led_blink(LED_RED, BLINK_ALWAYS_ON);
+ printf("LED 2 switched on\n\r");
+ break;
+ case '1':
+ printf("Resetting Modem\n\r");
+ wwan_perst_do_reset_pulse(0, 300);
+ break;
+ case '!':
+ sim_switch_use_physical(0, 0);
+ break;
+ case 't':
+ talloc_report(NULL, stdout);
+ break;
+ default:
+ printf("Unknown command '%c'\n\r", ch);
+ break;
+ }
+}
+
+void board_main_top(void)
+{
+#ifndef APPLICATION_dfu
+ usb_buf_init();
+
+ wwan_led_init();
+ wwan_perst_init();
+ sim_switch_init();
+#endif
+
+ /* Obtain the circuit board version (currently just prints voltage) */
+ get_board_version_adc();
+#ifndef APPLICATION_dfu
+ /* Initialize checking for card insert/remove events */
+ card_present_init();
+#endif
+ wwan_perst_set(0, 0);
+}
+
+static int uart_has_loopback_jumper(void)
+{
+ unsigned int i;
+ const Pin uart_loopback_pins[] = {
+ {PIO_PA9A_URXD0, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT},
+ {PIO_PA10A_UTXD0, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+ };
+
+ /* Configure UART pins as I/O */
+ PIO_Configure(uart_loopback_pins, PIO_LISTSIZE(uart_loopback_pins));
+
+ /* Send pattern over UART TX and check if it is received on RX
+ * If the loop doesn't get interrupted, RxD always follows TxD and thus a
+ * loopback jumper has been placed on RxD/TxD, and we will boot
+ * into DFU unconditionally
+ */
+ int has_loopback_jumper = 1;
+ for (i = 0; i < 10; i++) {
+ /* Set TxD high; abort if RxD doesn't go high either */
+ PIO_Set(&uart_loopback_pins[1]);
+ if (!PIO_Get(&uart_loopback_pins[0])) {
+ has_loopback_jumper = 0;
+ break;
+ }
+ /* Set TxD low, abort if RxD doesn't go low either */
+ PIO_Clear(&uart_loopback_pins[1]);
+ if (PIO_Get(&uart_loopback_pins[0])) {
+ has_loopback_jumper = 0;
+ break;
+ }
+ }
+
+ /* Put pins back to UART mode */
+ const Pin uart_pins[] = {PINS_UART};
+ PIO_Configure(uart_pins, PIO_LISTSIZE(uart_pins));
+
+ return has_loopback_jumper;
+}
+
+int board_override_enter_dfu(void)
+{
+ /* If the loopback jumper is set, we enter DFU mode */
+ if (uart_has_loopback_jumper())
+ return 1;
+
+ return 0;
+}
+
+ static const Pin deton = {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
+ static const Pin detoff = {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT};
+
+void board_set_card_insert(struct cardem_inst *ci, bool card_insert)
+{
+ PIO_Configure(card_insert ? &deton : &detoff, 1);
+} \ No newline at end of file
diff --git a/firmware/libboard/ngff_cardem/source/card_pres.c b/firmware/libboard/ngff_cardem/source/card_pres.c
new file mode 100644
index 0000000..7d6c483
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/source/card_pres.c
@@ -0,0 +1,76 @@
+/* card presence utilities
+ *
+ * (C) 2016-2021 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ */
+#include <osmocom/core/timer.h>
+#include "board.h"
+#include "utils.h"
+#include "card_pres.h"
+
+#define NUM_CARDPRES 1
+
+#define TIMER_INTERVAL_MS 500
+
+static const Pin pin_cardpres[NUM_CARDPRES] = { PIN_DET_USIM1_PRES };
+static int last_state[NUM_CARDPRES] = { -1 };
+static struct osmo_timer_list cardpres_timer;
+
+/* Determine if a SIM card is present in the given slot */
+int is_card_present(int port)
+{
+ const Pin *pin;
+ int present;
+
+ if (port < 0 || port >= NUM_CARDPRES)
+ return -1;
+ pin = &pin_cardpres[port];
+
+
+ /* high active here */
+ present = PIO_Get(pin);
+
+ return present;
+}
+
+static void cardpres_tmr_cb(void *data)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(pin_cardpres); i++) {
+ int state = is_card_present(i);
+ if (state != last_state[i]) {
+ TRACE_INFO("%u: Card Detect Status %d -> %d\r\n", i, last_state[i], state);
+ /* FIXME: report to USB host */
+ last_state[i] = state;
+ }
+ }
+
+ osmo_timer_schedule(&cardpres_timer, 0, TIMER_INTERVAL_MS*1000);
+}
+
+int card_present_init(void)
+{
+ unsigned int i;
+
+ PIO_Configure(pin_cardpres, ARRAY_SIZE(pin_cardpres));
+
+ /* start timer */
+ cardpres_timer.cb = cardpres_tmr_cb;
+ osmo_timer_schedule(&cardpres_timer, 0, TIMER_INTERVAL_MS*1000);
+
+ return 2;
+}
diff --git a/firmware/libboard/ngff_cardem/source/sim_switch.c b/firmware/libboard/ngff_cardem/source/sim_switch.c
new file mode 100644
index 0000000..eb2d305
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/source/sim_switch.c
@@ -0,0 +1,81 @@
+/* Code to switch between local (physical) and remote (emulated) SIM
+ *
+ * (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ */
+#include "board.h"
+#include "trace.h"
+#include "led.h"
+#include "sim_switch.h"
+
+//uart12bus 2-20e pa20
+//uart22bus 1-20e pa28
+//usim2bus 1-10e pa0 pivot
+//sim det 2-10e pa13
+
+static const Pin pins_default[] = {PINS_SIM_DEFAULT};
+static const Pin pins_cem[] = {PINS_SIM_CARDEM};
+
+static int initialized = 0;
+
+int sim_switch_use_physical(unsigned int nr, int physical)
+{
+ const Pin pin = PIN_MODEM_EN;// PIN_N_MODEM_PWR_ON;
+ enum led led;
+
+ if (!initialized) {
+ TRACE_ERROR("Somebody forgot to call sim_switch_init()\r\n");
+ sim_switch_init();
+ }
+
+ TRACE_INFO("Modem %d: %s SIM\n\r", nr,
+ physical ? "physical" : "virtual");
+
+ switch (nr) {
+ case 0:
+ led = LED_USIM1;
+ break;
+
+ default:
+ TRACE_ERROR("Invalid SIM%u\n\r", nr);
+ return -1;
+ }
+
+ if (physical) {
+ TRACE_INFO("%u: Use local/physical SIM\r\n", nr);
+ PIO_Configure(pins_default, PIO_LISTSIZE(pins_default));
+ led_blink(led, BLINK_ALWAYS_ON);
+ } else {
+ TRACE_INFO("%u: Use remote/emulated SIM\r\n", nr);
+ PIO_Configure(pins_cem, PIO_LISTSIZE(pins_cem));
+ led_blink(led, BLINK_ALWAYS_OFF);
+ }
+
+ /* just power cycle the modem because this circumvents weird issues with unreliable signals */
+ PIO_Clear(&pin);
+ mdelay(200);
+ PIO_Set(&pin);
+
+
+ return 0;
+}
+
+int sim_switch_init(void)
+{
+ PIO_Configure(pins_default, PIO_LISTSIZE(pins_default));
+ initialized = 1;
+ return 1;
+}
diff --git a/firmware/libboard/ngff_cardem/source/wwan_led.c b/firmware/libboard/ngff_cardem/source/wwan_led.c
new file mode 100644
index 0000000..36eb0ec
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/source/wwan_led.c
@@ -0,0 +1,93 @@
+/* Code to read/track the status of the WWAN LEDs of attached modems
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ */
+/* Depending on the board this is running on, it might be possible
+ * for the controller to read the status of the WWAN LED output lines of
+ * the cellular modem. If the board supports this, it sets the
+ * PIN_WWAN1 and/or PIN_WWAN2 defines in its board.h file.
+ */
+#include "board.h"
+#include "wwan_led.h"
+
+#ifdef PIN_WWAN1
+static const Pin pin_wwan1 = PIN_WWAN1;
+
+static void wwan1_irqhandler(const Pin *pPin)
+{
+ int active = wwan_led_active(0);
+
+ TRACE_INFO("0: WWAN LED %u\r\n", active);
+
+ /* TODO: notify host via USB */
+}
+#endif
+
+#ifdef PIN_WWAN2
+static const Pin pin_wwan2 = PIN_WWAN2;
+
+static void wwan2_irqhandler(const Pin *pPin)
+{
+ int active = wwan_led_active(1);
+ TRACE_INFO("1: WWAN LED %u\r\n", active);
+
+ /* TODO: notify host via USB */
+}
+#endif
+
+/* determine if a given WWAN led is currently active or not */
+int wwan_led_active(int wwan)
+{
+ const Pin *pin;
+ int active;
+
+ switch (wwan) {
+#ifdef PIN_WWAN1
+ case 0:
+ pin = &pin_wwan1;
+ break;
+#endif
+#ifdef PIN_WWAN2
+ case 1:
+ pin = &pin_wwan2;
+ break;
+#endif
+ default:
+ return -1;
+ }
+
+ active = PIO_Get(pin) ? 0 : 1;
+ return active;
+}
+
+int wwan_led_init(void)
+{
+ int num_leds = 0;
+
+#ifdef PIN_WWAN1
+ PIO_Configure(&pin_wwan1, 1);
+ PIO_ConfigureIt(&pin_wwan1, wwan1_irqhandler);
+ PIO_EnableIt(&pin_wwan1);
+ num_leds++;
+#endif
+
+#ifdef PIN_WWAN2
+ PIO_Configure(&pin_wwan2, 1);
+ PIO_ConfigureIt(&pin_wwan2, wwan2_irqhandler);
+ PIO_EnableIt(&pin_wwan2);
+ num_leds++;
+#endif
+ return num_leds;
+}
diff --git a/firmware/libboard/ngff_cardem/source/wwan_perst.c b/firmware/libboard/ngff_cardem/source/wwan_perst.c
new file mode 100644
index 0000000..95a7c7b
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/source/wwan_perst.c
@@ -0,0 +1,127 @@
+/* Code to control the PERST lines of attached modems
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ */
+/* Depending on the board this is running on, it might be possible
+ * for the controller to set the status of the PERST input line of
+ * the cellular modem. If the board supports this, it sets the
+ * PIN_PERST1 and/or PIN_PERST2 defines in its board.h file.
+ */
+#include "board.h"
+#include "trace.h"
+#include "wwan_perst.h"
+#include <osmocom/core/timer.h>
+
+struct wwan_perst {
+ uint8_t idx;
+ const Pin pin;
+ struct osmo_timer_list timer;
+};
+
+#ifdef PIN_PERST1
+static struct wwan_perst perst1 = {
+ .idx = 0,
+ .pin = PIN_PERST1,
+};
+#endif
+
+#ifdef PIN_PERST2
+static struct wwan_perst perst2 = {
+ .idx = 1,
+ .pin = PIN_PERST2,
+};
+#endif
+
+static int initialized = 0;
+
+static void perst_tmr_cb(void *data)
+{
+ struct wwan_perst *perst = data;
+ /* release the (low-active) reset */
+ TRACE_INFO("%u: De-asserting modem reset\r\n", perst->idx);
+ PIO_Clear(&perst->pin);
+}
+
+static struct wwan_perst *get_perst_for_modem(int modem_nr)
+{
+ if (!initialized) {
+ TRACE_ERROR("Somebody forgot to call wwan_perst_init()\r\n");
+ wwan_perst_init();
+ }
+
+ switch (modem_nr) {
+#ifdef PIN_PERST1
+ case 0:
+ return &perst1;
+#endif
+#ifdef PIN_PERST2
+ case 1:
+ return &perst2;
+#endif
+ default:
+ return NULL;
+ }
+}
+
+int wwan_perst_do_reset_pulse(int modem_nr, unsigned int duration_ms)
+{
+ struct wwan_perst *perst = get_perst_for_modem(modem_nr);
+ if (!perst)
+ return -1;
+
+ TRACE_INFO("%u: Asserting modem reset\r\n", modem_nr);
+ PIO_Set(&perst->pin);
+ osmo_timer_schedule(&perst->timer, duration_ms/1000, (duration_ms%1000)*1000);
+
+ return 0;
+}
+
+int wwan_perst_set(int modem_nr, int active)
+{
+ struct wwan_perst *perst = get_perst_for_modem(modem_nr);
+ if (!perst)
+ return -1;
+
+ osmo_timer_del(&perst->timer);
+ if (active) {
+ TRACE_INFO("%u: Asserting modem reset\r\n", modem_nr);
+ PIO_Set(&perst->pin);
+ } else {
+ TRACE_INFO("%u: De-asserting modem reset\r\n", modem_nr);
+ PIO_Clear(&perst->pin);
+ }
+
+ return 0;
+}
+
+int wwan_perst_init(void)
+{
+ int num_perst = 0;
+#ifdef PIN_PERST1
+ PIO_Configure(&perst1.pin, 1);
+ perst1.timer.cb = perst_tmr_cb;
+ perst1.timer.data = (void *) &perst1;
+ num_perst++;
+#endif
+
+#ifdef PIN_PERST2
+ PIO_Configure(&perst2.pin, 1);
+ perst2.timer.cb = perst_tmr_cb;
+ perst2.timer.data = (void *) &perst2;
+ num_perst++;
+#endif
+ initialized = 1;
+ return num_perst;
+}
diff --git a/firmware/libboard/simtrace/include/board.h b/firmware/libboard/simtrace/include/board.h
index 4b6eda2..be18f64 100644
--- a/firmware/libboard/simtrace/include/board.h
+++ b/firmware/libboard/simtrace/include/board.h
@@ -40,7 +40,7 @@
/** green LED pin definition */
#define PIN_LED_GREEN {PIO_LED_GREEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/** LEDs pin definition */
-#define PINS_LEDS PIN_LED_RED, PIN_LED_GREEN
+#define PINS_LEDS PIN_LED_RED, PIN_LED_GREEN
/** index for red LED in LEDs pin definition array */
#define LED_NUM_RED 0
/** index for green LED in LEDs pin definition array */
diff --git a/firmware/libcommon/include/simtrace_usb.h b/firmware/libcommon/include/simtrace_usb.h
index a232ac5..7bf401c 100644
--- a/firmware/libcommon/include/simtrace_usb.h
+++ b/firmware/libcommon/include/simtrace_usb.h
@@ -26,6 +26,7 @@
#define USB_PRODUCT_SIMTRACE2_DFU 0x60e3 /* was 0x60e2 */
#define USB_PRODUCT_SIMTRACE2 0x60e3
#define USB_PRODUCT_OCTSIMTEST 0x616d
+#define USB_PRODUCT_NGFF_CARDEM 0x616e
/* USB proprietary class */
#define USB_CLASS_PROPRIETARY 0xff
diff --git a/firmware/libcommon/source/mode_cardemu.c b/firmware/libcommon/source/mode_cardemu.c
index 2440ec5..4a0b862 100644
--- a/firmware/libcommon/source/mode_cardemu.c
+++ b/firmware/libcommon/source/mode_cardemu.c
@@ -39,9 +39,21 @@ static const Pin pins_cardsim[] = PINS_CARDSIM;
#endif
/* UART pins */
+#if defined(ngff_cardem)
+static const Pin pins_usim1[] = {PINS_USIM2};
+static const Pin pin_usim1_rst = PIN_USIM2_nRST;
+#define FIRST_USART_BASE USART0
+#define FIRST_USART_ID ID_USART0
+#define FIRST_USART_IRQ USART0_IRQn
+#else
static const Pin pins_usim1[] = {PINS_USIM1};
static const Pin pin_usim1_rst = PIN_USIM1_nRST;
+#define FIRST_USART_BASE USART1
+#define FIRST_USART_ID ID_USART1
+#define FIRST_USART_IRQ USART1_IRQn
+#endif
static const Pin pin_usim1_vcc = PIN_USIM1_VCC;
+
#ifdef PIN_USIM1_IO_DIR
static const Pin pin_io_dir = PIN_USIM1_IO_DIR;
#endif
@@ -85,8 +97,8 @@ struct cardem_inst cardem_inst[] = {
{
.num = 0,
.usart_info = {
- .base = USART1,
- .id = ID_USART1,
+ .base = FIRST_USART_BASE,
+ .id = FIRST_USART_ID,
.state = USART_RCV
},
.ep_out = SIMTRACE_CARDEM_USB_EP_USIM1_DATAOUT,
@@ -569,7 +581,7 @@ void mode_cardemu_init(void)
/* configure USART as ISO-7816 slave (e.g. card) */
ISO7816_Init(&cardem_inst[0].usart_info, CLK_SLAVE);
- NVIC_EnableIRQ(USART1_IRQn);
+ NVIC_EnableIRQ(FIRST_USART_IRQ);
PIO_ConfigureIt(&pin_usim1_rst, usim1_rst_irqhandler);
PIO_EnableIt(&pin_usim1_rst);
@@ -627,9 +639,9 @@ void mode_cardemu_exit(void)
PIO_DisableIt(&pin_usim1_rst);
PIO_DisableIt(&pin_usim1_vcc);
- NVIC_DisableIRQ(USART1_IRQn);
- USART_SetTransmitterEnabled(USART1, 0);
- USART_SetReceiverEnabled(USART1, 0);
+ NVIC_DisableIRQ(FIRST_USART_IRQ);
+ USART_SetTransmitterEnabled(FIRST_USART_BASE, 0);
+ USART_SetReceiverEnabled(FIRST_USART_BASE, 0);
#ifdef CARDEMU_SECOND_UART
PIO_DisableIt(&pin_usim2_rst);
diff --git a/host/contrib/99-simtrace2.rules b/host/contrib/99-simtrace2.rules
index b576389..5ae04e2 100644
--- a/host/contrib/99-simtrace2.rules
+++ b/host/contrib/99-simtrace2.rules
@@ -18,6 +18,8 @@ ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="4003", GROUP="plugdev"
ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="4004", GROUP="plugdev"
# sysmocom OCTSIMTEST
ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="616d", GROUP="plugdev"
+# ngff-cardem
+ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="616e", GROUP="plugdev"
# All done
LABEL="simtrace2_rules_end"
diff --git a/host/lib/usb_util.c b/host/lib/usb_util.c
index 4d3b2b9..872d185 100644
--- a/host/lib/usb_util.c
+++ b/host/lib/usb_util.c
@@ -33,5 +33,6 @@ const struct dev_id osmo_st2_compatible_dev_ids[] = {
{ USB_VENDOR_OPENMOKO, USB_PRODUCT_QMOD_SAM3 },
{ USB_VENDOR_OPENMOKO, USB_PRODUCT_SIMTRACE2 },
{ USB_VENDOR_OPENMOKO, USB_PRODUCT_OCTSIMTEST },
+ { USB_VENDOR_OPENMOKO, USB_PRODUCT_NGFF_CARDEM },
{ 0, 0 }
};
diff --git a/host/src/simtrace2-sniff.c b/host/src/simtrace2-sniff.c
index 47d9e77..c44029a 100644
--- a/host/src/simtrace2-sniff.c
+++ b/host/src/simtrace2-sniff.c
@@ -315,6 +315,7 @@ static const struct option opts[] = {
/* Known USB device with SIMtrace firmware supporting sniffer */
static const struct dev_id compatible_dev_ids[] = {
{ USB_VENDOR_OPENMOKO, USB_PRODUCT_SIMTRACE2 },
+ { USB_VENDOR_OPENMOKO, USB_PRODUCT_NGFF_CARDEM },
{ 0, 0 }
};