<p>laforge has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/simtrace2/+/24879">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">WIP: introduce support for new ngff_cardem board<br><br>This adds support for the new ngff_cardem board, a board that<br>basically combines a ngff breakout board with a built-in SIMtrace2.<br><br>The firmware support added by this ptach is currently untested,<br>and serves as a basis for testing the ngff_cardem prototypes.<br><br>Change-Id: I9649c853271c22d5403cdf3a7ec9029c9cecfa32<br>---<br>M contrib/flash.py<br>M contrib/simtrace.lua<br>A firmware/libboard/ngff_cardem/include/board.h<br>A firmware/libboard/ngff_cardem/include/card_pres.h<br>A firmware/libboard/ngff_cardem/include/wwan_led.h<br>A firmware/libboard/ngff_cardem/include/wwan_perst.h<br>A firmware/libboard/ngff_cardem/product_string.txt<br>A firmware/libboard/ngff_cardem/source/board_ngff_cardem.c<br>A firmware/libboard/ngff_cardem/source/card_pres.c<br>A firmware/libboard/ngff_cardem/source/sim_switch.c<br>A firmware/libboard/ngff_cardem/source/wwan_led.c<br>A firmware/libboard/ngff_cardem/source/wwan_perst.c<br>M firmware/libcommon/include/simtrace_usb.h<br>M host/contrib/99-simtrace2.rules<br>M host/lib/usb_util.c<br>15 files changed, 716 insertions(+), 1 deletion(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/simtrace2 refs/changes/79/24879/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/contrib/flash.py b/contrib/flash.py</span><br><span>index 21903bb..01fe7c9 100755</span><br><span>--- a/contrib/flash.py</span><br><span>+++ b/contrib/flash.py</span><br><span>@@ -28,7 +28,8 @@</span><br><span> 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"})</span><br><span> 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"})</span><br><span> 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"})</span><br><span style="color: hsl(0, 100%, 40%);">-DEVICES = [DEVICE_SIMTRACE, DEVICE_QMOD, DEVICE_OCTSIMTEST]</span><br><span style="color: hsl(120, 100%, 40%);">+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"})</span><br><span style="color: hsl(120, 100%, 40%);">+DEVICES = [DEVICE_SIMTRACE, DEVICE_QMOD, DEVICE_OCTSIMTEST, DEVICE_NGFF_CARDEM]</span><br><span> </span><br><span> # which firmware does the SIMtrace USN interface subclass correspond</span><br><span> FIRMWARE_SUBCLASS = {1: "trace", 2: "cardem"}</span><br><span>diff --git a/contrib/simtrace.lua b/contrib/simtrace.lua</span><br><span>index 68eb961..8298265 100644</span><br><span>--- a/contrib/simtrace.lua</span><br><span>+++ b/contrib/simtrace.lua</span><br><span>@@ -62,6 +62,7 @@</span><br><span> function usb_simtrace_protocol.init()</span><br><span> local usb_product_dissectors = DissectorTable.get("usb.product")</span><br><span> usb_product_dissectors:add(0x1d50616d, usb_simtrace_protocol)</span><br><span style="color: hsl(120, 100%, 40%);">+usb_product_dissectors:add(0x1d50616e, usb_simtrace_protocol)</span><br><span> </span><br><span> -- DissectorTable.get("usb.bulk"):add(0xffff, usb_simtrace_protocol)</span><br><span> end</span><br><span>diff --git a/firmware/libboard/ngff_cardem/include/board.h b/firmware/libboard/ngff_cardem/include/board.h</span><br><span>new file mode 100644</span><br><span>index 0000000..8520d6b</span><br><span>--- /dev/null</span><br><span>+++ b/firmware/libboard/ngff_cardem/include/board.h</span><br><span>@@ -0,0 +1,107 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* Osmocom ngff-cardem board definition</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2021 by Harald Welte <laforge@osmocom.org></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program; if not, write to the Free Software</span><br><span style="color: hsl(120, 100%, 40%);">+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+#include "board_common.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "simtrace_usb.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** Name of the board */</span><br><span style="color: hsl(120, 100%, 40%);">+#define BOARD_NAME "NGFF-CARDEM"</span><br><span style="color: hsl(120, 100%, 40%);">+/** Board definition */</span><br><span style="color: hsl(120, 100%, 40%);">+#define ngff_cardem</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** oscillator used as main clock source (in Hz) */</span><br><span style="color: hsl(120, 100%, 40%);">+#define BOARD_MAINOSC 12000000</span><br><span style="color: hsl(120, 100%, 40%);">+/** desired main clock frequency (in Hz, based on BOARD_MAINOSC) */</span><br><span style="color: hsl(120, 100%, 40%);">+#define BOARD_MCK 58000000 // 12.000 * 29 / 6</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/** MCU pin connected to red LED */</span><br><span style="color: hsl(120, 100%, 40%);">+#define PIO_LED_RED     PIO_PA17</span><br><span style="color: hsl(120, 100%, 40%);">+/** MCU pin connected to green LED */</span><br><span style="color: hsl(120, 100%, 40%);">+#define PIO_LED_GREEN   PIO_PA18</span><br><span style="color: hsl(120, 100%, 40%);">+/** red LED pin definition */</span><br><span style="color: hsl(120, 100%, 40%);">+#define PIN_LED_RED     {PIO_LED_RED, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}</span><br><span style="color: hsl(120, 100%, 40%);">+/** green LED pin definition */</span><br><span style="color: hsl(120, 100%, 40%);">+#define PIN_LED_GREEN   {PIO_LED_GREEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}</span><br><span style="color: hsl(120, 100%, 40%);">+/** LEDs pin definition */</span><br><span style="color: hsl(120, 100%, 40%);">+#define PINS_LEDS       PIN_LED_RED, PIN_LED_GREEN </span><br><span style="color: hsl(120, 100%, 40%);">+/** index for red LED in LEDs pin definition array */</span><br><span style="color: hsl(120, 100%, 40%);">+#define LED_NUM_RED     0</span><br><span style="color: hsl(120, 100%, 40%);">+/** index for green LED in LEDs pin definition array */</span><br><span style="color: hsl(120, 100%, 40%);">+#define LED_NUM_GREEN   1</span><br><span style="color: hsl(120, 100%, 40%);">+/** the green LED is actually red and used as indication for USIM1 */</span><br><span style="color: hsl(120, 100%, 40%);">+#define LED_USIM1    LED_GREEN</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* USIM 2 interface (USART) */</span><br><span style="color: hsl(120, 100%, 40%);">+#define PIN_USIM2_CLK              {PIO_PA2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}</span><br><span style="color: hsl(120, 100%, 40%);">+#define PIN_USIM2_IO               {PIO_PA6, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}</span><br><span style="color: hsl(120, 100%, 40%);">+#define PINS_ISO7816_USIM2 PIN_USIM2_CLK, PIN_USIM2_IO</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* USIM 2 interface (TC) */</span><br><span style="color: hsl(120, 100%, 40%);">+#define PIN_USIM2_IO_TC             {PIO_PA1, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}</span><br><span style="color: hsl(120, 100%, 40%);">+#define PIN_USIM2_CLK_TC   {PIO_PA4, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}</span><br><span style="color: hsl(120, 100%, 40%);">+#define PINS_TC_USIM2              PIN_USIM2_IO_TC, PIN_USIM2_CLK_TC</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* USIM 1 interface (USART) */</span><br><span style="color: hsl(120, 100%, 40%);">+#define PIN_USIM1_IO               {PIO_PA22, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}</span><br><span style="color: hsl(120, 100%, 40%);">+#define PIN_USIM1_CLK             {PIO_PA23, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}</span><br><span style="color: hsl(120, 100%, 40%);">+#define PINS_ISO7816_USIM1        PIN_USIM1_CLK, PIN_USIM1_IO</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* USIM 1 interface (TC) */</span><br><span style="color: hsl(120, 100%, 40%);">+#define PIN_USIM1_IO_TC             {PIO_PA27, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}</span><br><span style="color: hsl(120, 100%, 40%);">+#define PIN_USIM1_CLK_TC  {PIO_PA29, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}</span><br><span style="color: hsl(120, 100%, 40%);">+#define PINS_TC_USIM1             PIN_USIM1_IO_TC, PIN_USIM1_CLK_TC</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define PIN_USIM1_nRST             {PIO_PA24, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}</span><br><span style="color: hsl(120, 100%, 40%);">+#define PIN_USIM1_VCC                {PIO_PB2, PIOB, ID_PIOB, PIO_INPUT, PIO_DEFAULT}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define PIN_USIM2_nRST              {PIO_PA7, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}</span><br><span style="color: hsl(120, 100%, 40%);">+//#define PIN_USIM2_VCC               {PIO_PB2, PIOB, ID_PIOB, PIO_INPUT, PIO_DEFAULT}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define PINS_USIM1          PINS_TC_USIM1, PINS_ISO7816_USIM1, PIN_USIM1_nRST</span><br><span style="color: hsl(120, 100%, 40%);">+#define PINS_USIM2           PINS_TC_USIM2, PINS_ISO7816_USIM2, PIN_USIM2_nRST</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* from v3 and onwards only (!) */</span><br><span style="color: hsl(120, 100%, 40%);">+#define PIN_DET_USIM1_PRES     {PIO_PA8, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEGLITCH | PIO_IT_EDGE}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* inputs reading the WWAN LED level */</span><br><span style="color: hsl(120, 100%, 40%);">+#define PIN_WWAN1              {PIO_PA15, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEGLITCH | PIO_IT_EDGE}</span><br><span style="color: hsl(120, 100%, 40%);">+#define PINS_WWAN_IN             { PIN_WWAN1 }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* outputs controlling RESET input of modems */</span><br><span style="color: hsl(120, 100%, 40%);">+#define PIN_PERST1            {PIO_PA25, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_PULLUP}</span><br><span style="color: hsl(120, 100%, 40%);">+#define PINS_PERST         { PIN_PERST1 }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define PIN_VERSION_DET               {PIO_PA19, PIOA, ID_PIOA, PIO_PERIPH_D, PIO_DEFAULT}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* GPIO towards SPDT switches between real SIM and SAM3 */</span><br><span style="color: hsl(120, 100%, 40%);">+//#define PIN_SIM_SWITCH1 {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}</span><br><span style="color: hsl(120, 100%, 40%);">+//#define PIN_SIM_SWITCH2 {PIO_PA28, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define BOARD_USB_BMATTRIBUTES    USBConfigurationDescriptor_SELFPOWERED_NORWAKEUP</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define BOARD_USB_VENDOR_ID USB_VENDOR_OPENMOKO</span><br><span style="color: hsl(120, 100%, 40%);">+#define BOARD_USB_PRODUCT_ID       USB_PRODUCT_NGFF_CARDEM</span><br><span style="color: hsl(120, 100%, 40%);">+#define BOARD_DFU_USB_PRODUCT_ID USB_PRODUCT_NGFF_CARDEM</span><br><span style="color: hsl(120, 100%, 40%);">+#define BOARD_USB_RELEASE    0x010</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define DETECT_VCC_BY_ADC</span><br><span style="color: hsl(120, 100%, 40%);">+#define VCC_UV_THRESH_1V8   1500000</span><br><span style="color: hsl(120, 100%, 40%);">+#define VCC_UV_THRESH_3V       2500000</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define HAVE_CARDEM</span><br><span>diff --git a/firmware/libboard/ngff_cardem/include/card_pres.h b/firmware/libboard/ngff_cardem/include/card_pres.h</span><br><span>new file mode 100644</span><br><span>index 0000000..81f0613</span><br><span>--- /dev/null</span><br><span>+++ b/firmware/libboard/ngff_cardem/include/card_pres.h</span><br><span>@@ -0,0 +1,22 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* card presence utilities</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2016-2017 by Harald Welte <hwelte@hmw-consulting.de></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program; if not, write to the Free Software</span><br><span style="color: hsl(120, 100%, 40%);">+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int is_card_present(int port);</span><br><span style="color: hsl(120, 100%, 40%);">+int card_present_init(void);</span><br><span>diff --git a/firmware/libboard/ngff_cardem/include/wwan_led.h b/firmware/libboard/ngff_cardem/include/wwan_led.h</span><br><span>new file mode 100644</span><br><span>index 0000000..77887c7</span><br><span>--- /dev/null</span><br><span>+++ b/firmware/libboard/ngff_cardem/include/wwan_led.h</span><br><span>@@ -0,0 +1,20 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* Code to read/track the status of the WWAN LEDs of attached modems</span><br><span style="color: hsl(120, 100%, 40%);">+ * </span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program; if not, write to the Free Software</span><br><span style="color: hsl(120, 100%, 40%);">+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int wwan_led_active(int wwan);</span><br><span style="color: hsl(120, 100%, 40%);">+int wwan_led_init(void);</span><br><span>diff --git a/firmware/libboard/ngff_cardem/include/wwan_perst.h b/firmware/libboard/ngff_cardem/include/wwan_perst.h</span><br><span>new file mode 100644</span><br><span>index 0000000..c934afc</span><br><span>--- /dev/null</span><br><span>+++ b/firmware/libboard/ngff_cardem/include/wwan_perst.h</span><br><span>@@ -0,0 +1,21 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* Code to control the PERST lines of attached modems</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program; if not, write to the Free Software</span><br><span style="color: hsl(120, 100%, 40%);">+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int wwan_perst_set(int modem_nr, int active);</span><br><span style="color: hsl(120, 100%, 40%);">+int wwan_perst_do_reset_pulse(int modem_nr, unsigned int duration_ms);</span><br><span style="color: hsl(120, 100%, 40%);">+int wwan_perst_init(void);</span><br><span>diff --git a/firmware/libboard/ngff_cardem/product_string.txt b/firmware/libboard/ngff_cardem/product_string.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..09a33c6</span><br><span>--- /dev/null</span><br><span>+++ b/firmware/libboard/ngff_cardem/product_string.txt</span><br><span>@@ -0,0 +1 @@</span><br><span style="color: hsl(120, 100%, 40%);">+ngff-cardem</span><br><span>diff --git a/firmware/libboard/ngff_cardem/source/board_ngff_cardem.c b/firmware/libboard/ngff_cardem/source/board_ngff_cardem.c</span><br><span>new file mode 100644</span><br><span>index 0000000..742ec55</span><br><span>--- /dev/null</span><br><span>+++ b/firmware/libboard/ngff_cardem/source/board_ngff_cardem.c</span><br><span>@@ -0,0 +1,152 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* sysmocom quad-modem sysmoQMOD application code</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2021 Harald Welte <laforge@osmocom.org></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program; if not, write to the Free Software</span><br><span style="color: hsl(120, 100%, 40%);">+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#include "board.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "simtrace.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "utils.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "led.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "wwan_led.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "wwan_perst.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "sim_switch.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "boardver_adc.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "card_pres.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/timer.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include "usb_buf.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* array of generated USB Strings */</span><br><span style="color: hsl(120, 100%, 40%);">+extern unsigned char *usb_strings[];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* returns '1' in case we should break any endless loop */</span><br><span style="color: hsl(120, 100%, 40%);">+void board_exec_dbg_cmd(int ch)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      switch (ch) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case '?':</span><br><span style="color: hsl(120, 100%, 40%);">+             printf("\t?\thelp\n\r");</span><br><span style="color: hsl(120, 100%, 40%);">+            printf("\tR\treset SAM3\n\r");</span><br><span style="color: hsl(120, 100%, 40%);">+              printf("\tl\tswitch off LED 1\n\r");</span><br><span style="color: hsl(120, 100%, 40%);">+                printf("\tL\tswitch on  LED 1\n\r");</span><br><span style="color: hsl(120, 100%, 40%);">+                printf("\tg\tswitch off LED 2\n\r");</span><br><span style="color: hsl(120, 100%, 40%);">+                printf("\tG\tswitch on  LED 2\n\r");</span><br><span style="color: hsl(120, 100%, 40%);">+                printf("\tU\tProceed to USB Initialization\n\r");</span><br><span style="color: hsl(120, 100%, 40%);">+           printf("\t1\tGenerate 1ms reset pulse on WWAN1\n\r");</span><br><span style="color: hsl(120, 100%, 40%);">+               printf("\t!\tSwitch Channel A from physical -> remote\n\r");</span><br><span style="color: hsl(120, 100%, 40%);">+             printf("\t@\tSwitch Channel B from physical -> remote\n\r");</span><br><span style="color: hsl(120, 100%, 40%);">+             printf("\tt\t(pseudo)talloc report\n\r");</span><br><span style="color: hsl(120, 100%, 40%);">+           break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 'R':</span><br><span style="color: hsl(120, 100%, 40%);">+             printf("Asking NVIC to reset us\n\r");</span><br><span style="color: hsl(120, 100%, 40%);">+              USBD_Disconnect();</span><br><span style="color: hsl(120, 100%, 40%);">+            NVIC_SystemReset();</span><br><span style="color: hsl(120, 100%, 40%);">+           break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 'l':</span><br><span style="color: hsl(120, 100%, 40%);">+             led_blink(LED_GREEN, BLINK_ALWAYS_OFF);</span><br><span style="color: hsl(120, 100%, 40%);">+               printf("LED 1 switched off\n\r");</span><br><span style="color: hsl(120, 100%, 40%);">+           break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 'L':</span><br><span style="color: hsl(120, 100%, 40%);">+             led_blink(LED_GREEN, BLINK_ALWAYS_ON);</span><br><span style="color: hsl(120, 100%, 40%);">+                printf("LED 1 switched on\n\r");</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 'g':</span><br><span style="color: hsl(120, 100%, 40%);">+             led_blink(LED_RED, BLINK_ALWAYS_OFF);</span><br><span style="color: hsl(120, 100%, 40%);">+         printf("LED 2 switched off\n\r");</span><br><span style="color: hsl(120, 100%, 40%);">+           break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 'G':</span><br><span style="color: hsl(120, 100%, 40%);">+             led_blink(LED_RED, BLINK_ALWAYS_ON);</span><br><span style="color: hsl(120, 100%, 40%);">+          printf("LED 2 switched on\n\r");</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case '1':</span><br><span style="color: hsl(120, 100%, 40%);">+             printf("Resetting Modem\n\r");</span><br><span style="color: hsl(120, 100%, 40%);">+              wwan_perst_do_reset_pulse(0, 300);</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case '!':</span><br><span style="color: hsl(120, 100%, 40%);">+             sim_switch_use_physical(0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 't':</span><br><span style="color: hsl(120, 100%, 40%);">+             talloc_report(NULL, stdout);</span><br><span style="color: hsl(120, 100%, 40%);">+          break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              printf("Unknown command '%c'\n\r", ch);</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void board_main_top(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef APPLICATION_dfu</span><br><span style="color: hsl(120, 100%, 40%);">+ usb_buf_init();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     wwan_led_init();</span><br><span style="color: hsl(120, 100%, 40%);">+      wwan_perst_init();</span><br><span style="color: hsl(120, 100%, 40%);">+    sim_switch_init();</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Obtain the circuit board version (currently just prints voltage */</span><br><span style="color: hsl(120, 100%, 40%);">+ get_board_version_adc();</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef APPLICATION_dfu</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Initialize checking for card insert/remove events */</span><br><span style="color: hsl(120, 100%, 40%);">+       card_present_init();</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int uart_has_loopback_jumper(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+       const Pin uart_loopback_pins[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+            {PIO_PA9A_URXD0, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT},</span><br><span style="color: hsl(120, 100%, 40%);">+              {PIO_PA10A_UTXD0, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}</span><br><span style="color: hsl(120, 100%, 40%);">+   };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Configure UART pins as I/O */</span><br><span style="color: hsl(120, 100%, 40%);">+      PIO_Configure(uart_loopback_pins, PIO_LISTSIZE(uart_loopback_pins));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Send pattern over UART TX and check if it is received on RX</span><br><span style="color: hsl(120, 100%, 40%);">+         * If the loop doesn't get interrupted, RxD always follows TxD and thus a</span><br><span style="color: hsl(120, 100%, 40%);">+  * loopback jumper has been placed on RxD/TxD, and we will boot</span><br><span style="color: hsl(120, 100%, 40%);">+        * into DFU unconditionally</span><br><span style="color: hsl(120, 100%, 40%);">+    */</span><br><span style="color: hsl(120, 100%, 40%);">+   int has_loopback_jumper = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+  for (i = 0; i < 10; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+         /* Set TxD high; abort if RxD doesn't go high either */</span><br><span style="color: hsl(120, 100%, 40%);">+           PIO_Set(&uart_loopback_pins[1]);</span><br><span style="color: hsl(120, 100%, 40%);">+          if (!PIO_Get(&uart_loopback_pins[0])) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   has_loopback_jumper = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Set TxD low, abort if RxD doesn't go low either */</span><br><span style="color: hsl(120, 100%, 40%);">+             PIO_Clear(&uart_loopback_pins[1]);</span><br><span style="color: hsl(120, 100%, 40%);">+                if (PIO_Get(&uart_loopback_pins[0])) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    has_loopback_jumper = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Put pins back to UART mode */</span><br><span style="color: hsl(120, 100%, 40%);">+      const Pin uart_pins[] = {PINS_UART};</span><br><span style="color: hsl(120, 100%, 40%);">+  PIO_Configure(uart_pins, PIO_LISTSIZE(uart_pins));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return has_loopback_jumper;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int board_override_enter_dfu(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       /* If the loopback jumper is set, we enter DFU mode */</span><br><span style="color: hsl(120, 100%, 40%);">+        if (uart_has_loopback_jumper())</span><br><span style="color: hsl(120, 100%, 40%);">+               return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/firmware/libboard/ngff_cardem/source/card_pres.c b/firmware/libboard/ngff_cardem/source/card_pres.c</span><br><span>new file mode 100644</span><br><span>index 0000000..198318f</span><br><span>--- /dev/null</span><br><span>+++ b/firmware/libboard/ngff_cardem/source/card_pres.c</span><br><span>@@ -0,0 +1,76 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* card presence utilities</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2016-2021 by Harald Welte <hwelte@hmw-consulting.de></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program; if not, write to the Free Software</span><br><span style="color: hsl(120, 100%, 40%);">+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/timer.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include "board.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "utils.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "card_pres.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define NUM_CARDPRES      1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define TIMER_INTERVAL_MS  500</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const Pin pin_cardpres[NUM_CARDPRES] = { PIN_DET_USIM1_PRES };</span><br><span style="color: hsl(120, 100%, 40%);">+static int last_state[NUM_CARDPRES] = { -1 };</span><br><span style="color: hsl(120, 100%, 40%);">+static struct osmo_timer_list cardpres_timer;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Determine if a SIM card is present in the given slot */</span><br><span style="color: hsl(120, 100%, 40%);">+int is_card_present(int port)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    const Pin *pin;</span><br><span style="color: hsl(120, 100%, 40%);">+       int present;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (port < 0 || port >= NUM_CARDPRES)</span><br><span style="color: hsl(120, 100%, 40%);">+           return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    pin = &pin_cardpres[port];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Card present signals are low-active, as we have a switch</span><br><span style="color: hsl(120, 100%, 40%);">+    * against GND and an internal-pull-up in the SAM3 */</span><br><span style="color: hsl(120, 100%, 40%);">+ present = PIO_Get(pin) ? 0 : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     return present;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void cardpres_tmr_cb(void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 0; i < ARRAY_SIZE(pin_cardpres); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+           int state = is_card_present(i);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (state != last_state[i]) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 TRACE_INFO("%u: Card Detect Status %d -> %d\r\n", i, last_state[i], state);</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* FIXME: report to USB host */</span><br><span style="color: hsl(120, 100%, 40%);">+                       last_state[i] = state;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   osmo_timer_schedule(&cardpres_timer, 0, TIMER_INTERVAL_MS*1000);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int card_present_init(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     PIO_Configure(pin_cardpres, ARRAY_SIZE(pin_cardpres));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* start timer */</span><br><span style="color: hsl(120, 100%, 40%);">+     cardpres_timer.cb = cardpres_tmr_cb;</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_timer_schedule(&cardpres_timer, 0, TIMER_INTERVAL_MS*1000);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        return 2;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/firmware/libboard/ngff_cardem/source/sim_switch.c b/firmware/libboard/ngff_cardem/source/sim_switch.c</span><br><span>new file mode 100644</span><br><span>index 0000000..59513ad</span><br><span>--- /dev/null</span><br><span>+++ b/firmware/libboard/ngff_cardem/source/sim_switch.c</span><br><span>@@ -0,0 +1,90 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* Code to switch between local (physical) and remote (emulated) SIM</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program; if not, write to the Free Software</span><br><span style="color: hsl(120, 100%, 40%);">+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#include "board.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "trace.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "led.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "sim_switch.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef PIN_SIM_SWITCH1</span><br><span style="color: hsl(120, 100%, 40%);">+static const Pin pin_conn_usim1 = {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef PIN_SIM_SWITCH2</span><br><span style="color: hsl(120, 100%, 40%);">+static const Pin pin_conn_usim2 = {PIO_PA28, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int initialized = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int sim_switch_use_physical(unsigned int nr, int physical)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     const Pin *pin;</span><br><span style="color: hsl(120, 100%, 40%);">+       enum led led;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!initialized) {</span><br><span style="color: hsl(120, 100%, 40%);">+           TRACE_ERROR("Somebody forgot to call sim_switch_init()\r\n");</span><br><span style="color: hsl(120, 100%, 40%);">+               sim_switch_init();</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   TRACE_INFO("Modem %d: %s SIM\n\r", nr,</span><br><span style="color: hsl(120, 100%, 40%);">+                 physical ? "physical" : "virtual");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  switch (nr) {</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef PIN_SIM_SWITCH1</span><br><span style="color: hsl(120, 100%, 40%);">+ case 0:</span><br><span style="color: hsl(120, 100%, 40%);">+               pin = &pin_conn_usim1;</span><br><span style="color: hsl(120, 100%, 40%);">+            led = LED_USIM1;</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef PIN_SIM_SWITCH2</span><br><span style="color: hsl(120, 100%, 40%);">+        case 1:</span><br><span style="color: hsl(120, 100%, 40%);">+               pin = &pin_conn_usim2;</span><br><span style="color: hsl(120, 100%, 40%);">+            led = LED_USIM2;</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              TRACE_ERROR("Invalid SIM%u\n\r", nr);</span><br><span style="color: hsl(120, 100%, 40%);">+               return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (physical) {</span><br><span style="color: hsl(120, 100%, 40%);">+               TRACE_INFO("%u: Use local/physical SIM\r\n", nr);</span><br><span style="color: hsl(120, 100%, 40%);">+           PIO_Clear(pin);</span><br><span style="color: hsl(120, 100%, 40%);">+               led_blink(led, BLINK_ALWAYS_ON);</span><br><span style="color: hsl(120, 100%, 40%);">+      } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              TRACE_INFO("%u: Use remote/emulated SIM\r\n", nr);</span><br><span style="color: hsl(120, 100%, 40%);">+          PIO_Set(pin);</span><br><span style="color: hsl(120, 100%, 40%);">+         led_blink(led, BLINK_ALWAYS_OFF);</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int sim_switch_init(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  int num_switch = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef PIN_SIM_SWITCH1</span><br><span style="color: hsl(120, 100%, 40%);">+   PIO_Configure(&pin_conn_usim1, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+        num_switch++;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef PIN_SIM_SWITCH2</span><br><span style="color: hsl(120, 100%, 40%);">+ PIO_Configure(&pin_conn_usim2, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+        num_switch++;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+ initialized = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+      return num_switch;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/firmware/libboard/ngff_cardem/source/wwan_led.c b/firmware/libboard/ngff_cardem/source/wwan_led.c</span><br><span>new file mode 100644</span><br><span>index 0000000..b3b5693</span><br><span>--- /dev/null</span><br><span>+++ b/firmware/libboard/ngff_cardem/source/wwan_led.c</span><br><span>@@ -0,0 +1,93 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* Code to read/track the status of the WWAN LEDs of attached modems</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program; if not, write to the Free Software</span><br><span style="color: hsl(120, 100%, 40%);">+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+/* Depending on the board this is running on,  it might be possible</span><br><span style="color: hsl(120, 100%, 40%);">+ * for the controller to read the status of the WWAN LED output lines of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the cellular modem.  If the board supports this, it sets the</span><br><span style="color: hsl(120, 100%, 40%);">+ * PIN_WWAN1 and/or PIN_WWAN2 defines in its board.h file.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#include "board.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "wwan_led.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef PIN_WWAN1</span><br><span style="color: hsl(120, 100%, 40%);">+static const Pin pin_wwan1 = PIN_WWAN1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void wwan1_irqhandler(const Pin *pPin)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       int active = wwan_led_active(0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    TRACE_INFO("0: WWAN LED %u\r\n", active);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* TODO: notify host via USB */</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef PIN_WWAN2</span><br><span style="color: hsl(120, 100%, 40%);">+static const Pin pin_wwan2 = PIN_WWAN2;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void wwan2_irqhandler(const Pin *pPin)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   int active = wwan_led_active(1);</span><br><span style="color: hsl(120, 100%, 40%);">+      TRACE_INFO("1: WWAN LED %u\r\n", active);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* TODO: notify host via USB */</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* determine if a tiven WWAN led is currently active or not */</span><br><span style="color: hsl(120, 100%, 40%);">+int wwan_led_active(int wwan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        const Pin *pin;</span><br><span style="color: hsl(120, 100%, 40%);">+       int active;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (wwan) {</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef PIN_WWAN1</span><br><span style="color: hsl(120, 100%, 40%);">+     case 0:</span><br><span style="color: hsl(120, 100%, 40%);">+               pin = &pin_wwan1;</span><br><span style="color: hsl(120, 100%, 40%);">+         break;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef PIN_WWAN2</span><br><span style="color: hsl(120, 100%, 40%);">+      case 1:</span><br><span style="color: hsl(120, 100%, 40%);">+               pin = &pin_wwan2;</span><br><span style="color: hsl(120, 100%, 40%);">+         break;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   active = PIO_Get(pin) ? 0 : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+        return active;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int wwan_led_init(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       int num_leds = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef PIN_WWAN1</span><br><span style="color: hsl(120, 100%, 40%);">+ PIO_Configure(&pin_wwan1, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+     PIO_ConfigureIt(&pin_wwan1, wwan1_irqhandler);</span><br><span style="color: hsl(120, 100%, 40%);">+    PIO_EnableIt(&pin_wwan1);</span><br><span style="color: hsl(120, 100%, 40%);">+ num_leds++;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef PIN_WWAN2</span><br><span style="color: hsl(120, 100%, 40%);">+       PIO_Configure(&pin_wwan2, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+     PIO_ConfigureIt(&pin_wwan2, wwan2_irqhandler);</span><br><span style="color: hsl(120, 100%, 40%);">+    PIO_EnableIt(&pin_wwan2);</span><br><span style="color: hsl(120, 100%, 40%);">+ num_leds++;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+   return num_leds;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/firmware/libboard/ngff_cardem/source/wwan_perst.c b/firmware/libboard/ngff_cardem/source/wwan_perst.c</span><br><span>new file mode 100644</span><br><span>index 0000000..95a7c7b</span><br><span>--- /dev/null</span><br><span>+++ b/firmware/libboard/ngff_cardem/source/wwan_perst.c</span><br><span>@@ -0,0 +1,127 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* Code to control the PERST lines of attached modems</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program; if not, write to the Free Software</span><br><span style="color: hsl(120, 100%, 40%);">+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+/* Depending on the board this is running on,  it might be possible</span><br><span style="color: hsl(120, 100%, 40%);">+ * for the controller to set the status of the PERST input line of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the cellular modem.  If the board supports this, it sets the</span><br><span style="color: hsl(120, 100%, 40%);">+ * PIN_PERST1 and/or PIN_PERST2 defines in its board.h file.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#include "board.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "trace.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "wwan_perst.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/timer.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct wwan_perst {</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t idx;</span><br><span style="color: hsl(120, 100%, 40%);">+  const Pin pin;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct osmo_timer_list timer;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef PIN_PERST1</span><br><span style="color: hsl(120, 100%, 40%);">+static struct wwan_perst perst1 = {</span><br><span style="color: hsl(120, 100%, 40%);">+   .idx = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+     .pin = PIN_PERST1,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef PIN_PERST2</span><br><span style="color: hsl(120, 100%, 40%);">+static struct wwan_perst perst2 = {</span><br><span style="color: hsl(120, 100%, 40%);">+      .idx = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+     .pin = PIN_PERST2,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int initialized = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void perst_tmr_cb(void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct wwan_perst *perst = data;</span><br><span style="color: hsl(120, 100%, 40%);">+      /* release the (low-active) reset */</span><br><span style="color: hsl(120, 100%, 40%);">+  TRACE_INFO("%u: De-asserting modem reset\r\n", perst->idx);</span><br><span style="color: hsl(120, 100%, 40%);">+      PIO_Clear(&perst->pin);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct wwan_perst *get_perst_for_modem(int modem_nr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!initialized) {</span><br><span style="color: hsl(120, 100%, 40%);">+           TRACE_ERROR("Somebody forgot to call wwan_perst_init()\r\n");</span><br><span style="color: hsl(120, 100%, 40%);">+               wwan_perst_init();</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   switch (modem_nr) {</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef PIN_PERST1</span><br><span style="color: hsl(120, 100%, 40%);">+        case 0:</span><br><span style="color: hsl(120, 100%, 40%);">+               return &perst1;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef PIN_PERST2</span><br><span style="color: hsl(120, 100%, 40%);">+        case 1:</span><br><span style="color: hsl(120, 100%, 40%);">+               return &perst2;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+   default:</span><br><span style="color: hsl(120, 100%, 40%);">+              return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int wwan_perst_do_reset_pulse(int modem_nr, unsigned int duration_ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct wwan_perst *perst = get_perst_for_modem(modem_nr);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!perst)</span><br><span style="color: hsl(120, 100%, 40%);">+           return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  TRACE_INFO("%u: Asserting modem reset\r\n", modem_nr);</span><br><span style="color: hsl(120, 100%, 40%);">+      PIO_Set(&perst->pin);</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_timer_schedule(&perst->timer, duration_ms/1000, (duration_ms%1000)*1000);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int wwan_perst_set(int modem_nr, int active)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct wwan_perst *perst = get_perst_for_modem(modem_nr);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!perst)</span><br><span style="color: hsl(120, 100%, 40%);">+           return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_timer_del(&perst->timer);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (active) {</span><br><span style="color: hsl(120, 100%, 40%);">+         TRACE_INFO("%u: Asserting modem reset\r\n", modem_nr);</span><br><span style="color: hsl(120, 100%, 40%);">+              PIO_Set(&perst->pin);</span><br><span style="color: hsl(120, 100%, 40%);">+  } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              TRACE_INFO("%u: De-asserting modem reset\r\n", modem_nr);</span><br><span style="color: hsl(120, 100%, 40%);">+           PIO_Clear(&perst->pin);</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int wwan_perst_init(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  int num_perst = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef PIN_PERST1</span><br><span style="color: hsl(120, 100%, 40%);">+ PIO_Configure(&perst1.pin, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+    perst1.timer.cb = perst_tmr_cb;</span><br><span style="color: hsl(120, 100%, 40%);">+       perst1.timer.data = (void *) &perst1;</span><br><span style="color: hsl(120, 100%, 40%);">+     num_perst++;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef PIN_PERST2</span><br><span style="color: hsl(120, 100%, 40%);">+     PIO_Configure(&perst2.pin, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+    perst2.timer.cb = perst_tmr_cb;</span><br><span style="color: hsl(120, 100%, 40%);">+       perst2.timer.data = (void *) &perst2;</span><br><span style="color: hsl(120, 100%, 40%);">+     num_perst++;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+  initialized = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+      return num_perst;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/firmware/libcommon/include/simtrace_usb.h b/firmware/libcommon/include/simtrace_usb.h</span><br><span>index a232ac5..7bf401c 100644</span><br><span>--- a/firmware/libcommon/include/simtrace_usb.h</span><br><span>+++ b/firmware/libcommon/include/simtrace_usb.h</span><br><span>@@ -26,6 +26,7 @@</span><br><span> #define USB_PRODUCT_SIMTRACE2_DFU  0x60e3  /* was 0x60e2 */</span><br><span> #define USB_PRODUCT_SIMTRACE2               0x60e3</span><br><span> #define USB_PRODUCT_OCTSIMTEST                0x616d</span><br><span style="color: hsl(120, 100%, 40%);">+#define USB_PRODUCT_NGFF_CARDEM         0x616e</span><br><span> </span><br><span> /* USB proprietary class */</span><br><span> #define USB_CLASS_PROPRIETARY                      0xff</span><br><span>diff --git a/host/contrib/99-simtrace2.rules b/host/contrib/99-simtrace2.rules</span><br><span>index b576389..5ae04e2 100644</span><br><span>--- a/host/contrib/99-simtrace2.rules</span><br><span>+++ b/host/contrib/99-simtrace2.rules</span><br><span>@@ -18,6 +18,8 @@</span><br><span> ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="4004", GROUP="plugdev"</span><br><span> # sysmocom OCTSIMTEST</span><br><span> ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="616d", GROUP="plugdev"</span><br><span style="color: hsl(120, 100%, 40%);">+# ngff-cardem</span><br><span style="color: hsl(120, 100%, 40%);">+ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="616e", GROUP="plugdev"</span><br><span> </span><br><span> # All done</span><br><span> LABEL="simtrace2_rules_end"</span><br><span>diff --git a/host/lib/usb_util.c b/host/lib/usb_util.c</span><br><span>index 4d3b2b9..872d185 100644</span><br><span>--- a/host/lib/usb_util.c</span><br><span>+++ b/host/lib/usb_util.c</span><br><span>@@ -33,5 +33,6 @@</span><br><span>  { USB_VENDOR_OPENMOKO, USB_PRODUCT_QMOD_SAM3 },</span><br><span>      { USB_VENDOR_OPENMOKO, USB_PRODUCT_SIMTRACE2 },</span><br><span>      { USB_VENDOR_OPENMOKO, USB_PRODUCT_OCTSIMTEST },</span><br><span style="color: hsl(120, 100%, 40%);">+      { USB_VENDOR_OPENMOKO, USB_PRODUCT_NGFF_CARDEM },</span><br><span>    { 0, 0 }</span><br><span> };</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/simtrace2/+/24879">change 24879</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/simtrace2/+/24879"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: simtrace2 </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I9649c853271c22d5403cdf3a7ec9029c9cecfa32 </div>
<div style="display:none"> Gerrit-Change-Number: 24879 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>