aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2021-07-02 15:02:33 +0200
committerHarald Welte <laforge@osmocom.org>2021-07-07 11:34:41 +0200
commit774330d413df0fa7b2bd6c661813072536456ed3 (patch)
treeb1bb072ff9302da7919dcef2ab54b016f1c53809
parent9d0d20c2537cc2d9ae274dcd9611f73e395e55e7 (diff)
WIP: introduce support for new ngff_cardem boardlaforge/ngff-cardem
This adds support for the new ngff_cardem board, a board that basically combines a ngff breakout board with a built-in SIMtrace2. The firmware support added by this ptach is currently untested, and serves as a basis for testing the ngff_cardem prototypes. Change-Id: I9649c853271c22d5403cdf3a7ec9029c9cecfa32
-rwxr-xr-xcontrib/flash.py3
-rw-r--r--contrib/simtrace.lua1
-rw-r--r--firmware/libboard/ngff_cardem/include/board.h107
-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.c152
-rw-r--r--firmware/libboard/ngff_cardem/source/card_pres.c76
-rw-r--r--firmware/libboard/ngff_cardem/source/sim_switch.c90
-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/libcommon/include/simtrace_usb.h1
-rw-r--r--host/contrib/99-simtrace2.rules2
-rw-r--r--host/lib/usb_util.c1
15 files changed, 716 insertions, 1 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/libboard/ngff_cardem/include/board.h b/firmware/libboard/ngff_cardem/include/board.h
new file mode 100644
index 0000000..8520d6b
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/include/board.h
@@ -0,0 +1,107 @@
+/* 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_PB2, 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_PULLUP | 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 }
+
+/* outputs controlling RESET input of modems */
+#define PIN_PERST1 {PIO_PA25, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_PULLUP}
+#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 2500000
+
+#define HAVE_CARDEM
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..742ec55
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/source/board_ngff_cardem.c
@@ -0,0 +1,152 @@
+/* sysmocom quad-modem sysmoQMOD 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("\tU\tProceed to USB Initialization\n\r");
+ printf("\t1\tGenerate 1ms reset pulse on WWAN1\n\r");
+ printf("\t!\tSwitch Channel A from physical -> remote\n\r");
+ printf("\t@\tSwitch Channel B 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
+}
+
+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;
+}
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..198318f
--- /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];
+
+ /* Card present signals are low-active, as we have a switch
+ * against GND and an internal-pull-up in the SAM3 */
+ present = PIO_Get(pin) ? 0 : 1;
+
+ 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..59513ad
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/source/sim_switch.c
@@ -0,0 +1,90 @@
+/* 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"
+
+#ifdef PIN_SIM_SWITCH1
+static const Pin pin_conn_usim1 = {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
+#endif
+#ifdef PIN_SIM_SWITCH2
+static const Pin pin_conn_usim2 = {PIO_PA28, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
+#endif
+
+static int initialized = 0;
+
+int sim_switch_use_physical(unsigned int nr, int physical)
+{
+ const Pin *pin;
+ 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) {
+#ifdef PIN_SIM_SWITCH1
+ case 0:
+ pin = &pin_conn_usim1;
+ led = LED_USIM1;
+ break;
+#endif
+#ifdef PIN_SIM_SWITCH2
+ case 1:
+ pin = &pin_conn_usim2;
+ led = LED_USIM2;
+ break;
+#endif
+ default:
+ TRACE_ERROR("Invalid SIM%u\n\r", nr);
+ return -1;
+ }
+
+ if (physical) {
+ TRACE_INFO("%u: Use local/physical SIM\r\n", nr);
+ PIO_Clear(pin);
+ led_blink(led, BLINK_ALWAYS_ON);
+ } else {
+ TRACE_INFO("%u: Use remote/emulated SIM\r\n", nr);
+ PIO_Set(pin);
+ led_blink(led, BLINK_ALWAYS_OFF);
+ }
+
+ return 0;
+}
+
+int sim_switch_init(void)
+{
+ int num_switch = 0;
+#ifdef PIN_SIM_SWITCH1
+ PIO_Configure(&pin_conn_usim1, 1);
+ num_switch++;
+#endif
+#ifdef PIN_SIM_SWITCH2
+ PIO_Configure(&pin_conn_usim2, 1);
+ num_switch++;
+#endif
+ initialized = 1;
+ return num_switch;
+}
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..b3b5693
--- /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 tiven 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/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/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 }
};