<p>laforge has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-remsim/+/17361">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">client: major restructuring around new main_fsm<br><br>The remsim_client code already used FSMs for the connections<br>to both remsim-server and remsim-bankd. However the 'main' part of the<br>program was not yet implemented as a FSM, making it somewhat difficult<br>to perform the right actions in every possible situation.<br><br>This commit re-structures the code around a central main_fsm, which<br>gets notified from the per-connection FSMs and which handles the common<br>processing. It also handles the execution of external script commands,<br>and hence further unifies the code base between the different backends<br>(simtrace2, ifd_handler, shell)<br><br>Closes: #4414<br><br>Change-Id: I44a430bc5674dea00ed72a0b28729ac8bcb4e022<br>---<br>M src/client/Makefile.am<br>M src/client/client.h<br>A src/client/main_fsm.c<br>M src/client/remsim_client.c<br>M src/client/remsim_client_main.c<br>D src/client/simtrace2-remsim_client.c<br>M src/client/user_ifdhandler.c<br>M src/client/user_shell.c<br>A src/client/user_simtrace2.c<br>M src/rspro_client_fsm.c<br>10 files changed, 1,119 insertions(+), 1,392 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-remsim refs/changes/61/17361/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/client/Makefile.am b/src/client/Makefile.am</span><br><span>index f37126a..43b030f 100644</span><br><span>--- a/src/client/Makefile.am</span><br><span>+++ b/src/client/Makefile.am</span><br><span>@@ -7,7 +7,7 @@</span><br><span> bin_PROGRAMS = osmo-remsim-client-st2 osmo-remsim-client-shell</span><br><span> </span><br><span> osmo_remsim_client_shell_SOURCES = user_shell.c remsim_client_main.c \</span><br><span style="color: hsl(0, 100%, 40%);">- remsim_client.c ../rspro_client_fsm.c ../debug.c</span><br><span style="color: hsl(120, 100%, 40%);">+ remsim_client.c main_fsm.c ../rspro_client_fsm.c ../debug.c</span><br><span> osmo_remsim_client_shell_CFLAGS = $(AM_CFLAGS)</span><br><span> osmo_remsim_client_shell_LDADD = $(OSMOCORE_LIBS) $(OSMOGSM_LIBS) $(OSMOABIS_LIBS) \</span><br><span> $(top_builddir)/src/libosmo-rspro.la</span><br><span>@@ -19,15 +19,16 @@</span><br><span> bundlelinuxdir=$(bundledir)/Linux</span><br><span> bundlelinux_LTLIBRARIES = libifd_remsim_client.la</span><br><span> libifd_remsim_client_la_SOURCES = user_ifdhandler.c \</span><br><span style="color: hsl(0, 100%, 40%);">- remsim_client.c ../rspro_client_fsm.c ../debug.c</span><br><span style="color: hsl(120, 100%, 40%);">+ remsim_client.c main_fsm.c ../rspro_client_fsm.c ../debug.c</span><br><span> libifd_remsim_client_la_CFLAGS = $(AM_CFLAGS)</span><br><span> libifd_remsim_client_la_CPPFLAGS = $(PCSC_CFLAGS)</span><br><span> libifd_remsim_client_la_LDFLAGS = -no-undefined</span><br><span> libifd_remsim_client_la_LIBADD = $(OSMOCORE_LIBS) $(OSMOGSM_LIBS) $(OSMOABIS_LIBS) \</span><br><span> $(top_builddir)/src/libosmo-rspro.la</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-osmo_remsim_client_st2_SOURCES = simtrace2-remsim_client.c \</span><br><span style="color: hsl(0, 100%, 40%);">- ../rspro_client_fsm.c ../debug.c</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_remsim_client_st2_SOURCES = user_simtrace2.c remsim_client_main.c \</span><br><span style="color: hsl(120, 100%, 40%);">+ remsim_client.c main_fsm.c ../rspro_client_fsm.c ../debug.c</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_remsim_client_st2_CPPFLAGS = -DUSB_SUPPORT</span><br><span> osmo_remsim_client_st2_CFLAGS = $(AM_CFLAGS)</span><br><span> osmo_remsim_client_st2_LDADD = $(OSMOCORE_LIBS) $(OSMOGSM_LIBS) $(OSMOABIS_LIBS) \</span><br><span> $(OSMOUSB_LIBS) $(OSMOSIMTRACE2_LIBS) \</span><br><span>diff --git a/src/client/client.h b/src/client/client.h</span><br><span>index 0761255..b828882 100644</span><br><span>--- a/src/client/client.h</span><br><span>+++ b/src/client/client.h</span><br><span>@@ -10,9 +10,49 @@</span><br><span> #include "slotmap.h"</span><br><span> #include "debug.h"</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/***********************************************************************</span><br><span style="color: hsl(120, 100%, 40%);">+ * frontend interface</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%);">+struct bankd_client;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct frontend_phys_status {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* all members can be 0 (inactive), 1 (active) or -1 (not supported/known) */</span><br><span style="color: hsl(120, 100%, 40%);">+ int reset_active;</span><br><span style="color: hsl(120, 100%, 40%);">+ int vcc_present;</span><br><span style="color: hsl(120, 100%, 40%);">+ int clk_active;</span><br><span style="color: hsl(120, 100%, 40%);">+ int card_present;</span><br><span style="color: hsl(120, 100%, 40%);">+ } flags;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t voltage_mv;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t fi;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t di;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t wi;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t waiting_time;</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%);">+struct frontend_pts {</span><br><span style="color: hsl(120, 100%, 40%);">+ const uint8_t *buf;</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t len;</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%);">+struct frontend_tpdu {</span><br><span style="color: hsl(120, 100%, 40%);">+ const uint8_t *buf;</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t len;</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%);">+/* API from generic core to frontend (modem/cardem) */</span><br><span style="color: hsl(120, 100%, 40%);">+int frontend_request_card_insert(struct bankd_client *bc);</span><br><span style="color: hsl(120, 100%, 40%);">+int frontend_request_sim_remote(struct bankd_client *bc);</span><br><span style="color: hsl(120, 100%, 40%);">+int frontend_request_modem_reset(struct bankd_client *bc);</span><br><span style="color: hsl(120, 100%, 40%);">+int frontend_handle_card2modem(struct bankd_client *bc, const uint8_t *data, size_t len);</span><br><span style="color: hsl(120, 100%, 40%);">+int frontend_handle_set_atr(struct bankd_client *bc, const uint8_t *data, size_t len);</span><br><span style="color: hsl(120, 100%, 40%);">+int frontend_handle_slot_status(struct bankd_client *bc, const SlotPhysStatus_t *sts);</span><br><span style="color: hsl(120, 100%, 40%);">+int frontend_append_script_env(struct bankd_client *bc, char **env, size_t max_env);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* main.c */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct cardem_inst;</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_st2_cardem_inst;</span><br><span> </span><br><span> #define ATR_SIZE_MAX 55</span><br><span> struct client_config {</span><br><span>@@ -48,6 +88,8 @@</span><br><span> struct rspro_server_conn srv_conn;</span><br><span> /* connection to the remsim-bankd (data) */</span><br><span> struct rspro_server_conn bankd_conn;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* CLIENT_MAIN fsm */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_fsm_inst *main_fi;</span><br><span> </span><br><span> /* remote component ID */</span><br><span> struct app_comp_id peer_comp_id;</span><br><span>@@ -55,17 +97,43 @@</span><br><span> struct bank_slot bankd_slot;</span><br><span> </span><br><span> struct client_config *cfg;</span><br><span style="color: hsl(0, 100%, 40%);">- struct cardem_inst *cardem;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_st2_cardem_inst *cardem;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct frontend_phys_status last_status;</span><br><span> void *data;</span><br><span> };</span><br><span> </span><br><span> #define srvc2bankd_client(srvc) container_of(srvc, struct bankd_client, srv_conn)</span><br><span> #define bankdc2bankd_client(bdc) container_of(bdc, struct bankd_client, bankd_conn)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct bankd_client *remsim_client_create(void *ctx, const char *name, const char *software);</span><br><span style="color: hsl(120, 100%, 40%);">+struct client_config *client_config_init(void *ctx);</span><br><span style="color: hsl(120, 100%, 40%);">+struct bankd_client *remsim_client_create(void *ctx, const char *name, const char *software,</span><br><span style="color: hsl(120, 100%, 40%);">+ struct client_config *cfg);</span><br><span> void remsim_client_set_clslot(struct bankd_client *bc, int client_id, int slot_nr);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-extern int client_user_bankd_handle_rx(struct rspro_server_conn *bankdc, const RsproPDU_t *pdu);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> extern int client_user_main(struct bankd_client *g_client);</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%);">+ * main FSM</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%);">+enum main_fsm_event {</span><br><span style="color: hsl(120, 100%, 40%);">+ MF_E_SRVC_CONNECTED, /* connection to server established (TCP + RSPRO level) */</span><br><span style="color: hsl(120, 100%, 40%);">+ MF_E_SRVC_LOST, /* connection to server was lost */</span><br><span style="color: hsl(120, 100%, 40%);">+ MF_E_SRVC_CONFIG_BANK, /* server instructs us to connect to bankd/slot */</span><br><span style="color: hsl(120, 100%, 40%);">+ MF_E_SRVC_RESET_REQ, /* RsproPDUchoice_PR_ResetStateReq */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ MF_E_BANKD_CONNECTED, /* connection to bankd established (TCP + RSPRO level) */</span><br><span style="color: hsl(120, 100%, 40%);">+ MF_E_BANKD_LOST, /* connection to bankd was lost */</span><br><span style="color: hsl(120, 100%, 40%);">+ MF_E_BANKD_TPDU, /* RsproPDUchoice_PR_tpduCardToModem */</span><br><span style="color: hsl(120, 100%, 40%);">+ MF_E_BANKD_ATR, /* RsproPDUchoice_PR_setAtrReq */</span><br><span style="color: hsl(120, 100%, 40%);">+ MF_E_BANKD_SLOT_STATUS, /* bankSlotStatusInd */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ MF_E_MDM_STATUS_IND, /* status from modem/cardem */</span><br><span style="color: hsl(120, 100%, 40%);">+ MF_E_MDM_PTS_IND, /* PTS indication from modem/cardem */</span><br><span style="color: hsl(120, 100%, 40%);">+ MF_E_MDM_TPDU, /* TPDU from modem/cardem */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_fsm_inst *main_fsm_alloc(void *ctx, struct bankd_client *bc);</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>diff --git a/src/client/main_fsm.c b/src/client/main_fsm.c</span><br><span>new file mode 100644</span><br><span>index 0000000..b94af26</span><br><span>--- /dev/null</span><br><span>+++ b/src/client/main_fsm.c</span><br><span>@@ -0,0 +1,377 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* (C) 2020 by Harald Welte <laforge@gnumonks.org></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPDX-License-Identifier: GPL-2.0+</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 along</span><br><span style="color: hsl(120, 100%, 40%);">+ * with this program; if not, write to the Free Software Foundation, Inc.,</span><br><span style="color: hsl(120, 100%, 40%);">+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</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%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/talloc.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/logging.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/fsm.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/exec.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "rspro_util.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "client.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "debug.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define S(x) (1 << (x))</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%);">+/* build the (additional) environment for executing a script */</span><br><span style="color: hsl(120, 100%, 40%);">+static char **build_script_env(struct bankd_client *bc, const char *cause)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char **env = talloc_zero_size(bc, 256*sizeof(char *));</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc, i = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!env)</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%);">+ env[i++] = talloc_asprintf(env, "REMSIM_CLIENT_VERSION=%s", VERSION);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ env[i++] = talloc_asprintf(env, "REMSIM_SERVER_ADDR=%s:%u",</span><br><span style="color: hsl(120, 100%, 40%);">+ bc->srv_conn.server_host, bc->srv_conn.server_port);</span><br><span style="color: hsl(120, 100%, 40%);">+ env[i++] = talloc_asprintf(env, "REMSIM_SERVER_STATE=%s",</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_state_name(bc->srv_conn.fi));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ env[i++] = talloc_asprintf(env, "REMSIM_BANKD_ADDR=%s:%u",</span><br><span style="color: hsl(120, 100%, 40%);">+ bc->bankd_conn.server_host, bc->bankd_conn.server_port);</span><br><span style="color: hsl(120, 100%, 40%);">+ env[i++] = talloc_asprintf(env, "REMSIM_BANKD_STATE=%s",</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_state_name(bc->bankd_conn.fi));</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 (bc->srv_conn.clslot) {</span><br><span style="color: hsl(120, 100%, 40%);">+ env[i++] = talloc_asprintf(env, "REMSIM_CLIENT_SLOT=%lu:%lu",</span><br><span style="color: hsl(120, 100%, 40%);">+ bc->srv_conn.clslot->clientId,</span><br><span style="color: hsl(120, 100%, 40%);">+ bc->srv_conn.clslot->slotNr);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ env[i++] = talloc_asprintf(env, "REMSIM_BANKD_SLOT=%u:%u",</span><br><span style="color: hsl(120, 100%, 40%);">+ bc->bankd_slot.bank_id, bc->bankd_slot.slot_nr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ env[i++] = talloc_asprintf(env, "REMSIM_SIM_VCC=%u", bc->last_status.flags.vcc_present);</span><br><span style="color: hsl(120, 100%, 40%);">+ env[i++] = talloc_asprintf(env, "REMSIM_SIM_RST=%u", bc->last_status.flags.reset_active);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* TODO: SIM card state CLK */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ env[i++] = talloc_asprintf(env, "REMSIM_CAUSE=%s", cause);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* ask frontend to append any frontend-speccific additional environment vars */</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = frontend_append_script_env(bc, env+i, 256-i);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc > 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ i += rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* terminate last entry */</span><br><span style="color: hsl(120, 100%, 40%);">+ env[i++] = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ return env;</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 call_script(struct bankd_client *bc, const char *cause)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char **env, *cmd;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!bc->cfg->event_script)</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%);">+ env = build_script_env(bc, cause);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!env)</span><br><span style="color: hsl(120, 100%, 40%);">+ return -ENOMEM;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ cmd = talloc_asprintf(env, "%s %s", bc->cfg->event_script, cause);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(env);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -ENOMEM;</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%);">+ rc = osmo_system_nowait(cmd, osmo_environment_whitelist, env);</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(env);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return rc;</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%);">+/***********************************************************************/</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%);">+enum main_fsm_state {</span><br><span style="color: hsl(120, 100%, 40%);">+ MF_ST_INIT,</span><br><span style="color: hsl(120, 100%, 40%);">+ MF_ST_UNCONFIGURED, /* waiting for configuration from server */</span><br><span style="color: hsl(120, 100%, 40%);">+ MF_ST_WAIT_BANKD, /* configured; waiting for bankd conn */</span><br><span style="color: hsl(120, 100%, 40%);">+ MF_ST_OPERATIONAL, /* fully operational (configured + bankd conn live */</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 const struct value_string main_fsm_event_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_VALUE_STRING(MF_E_SRVC_CONNECTED),</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_VALUE_STRING(MF_E_SRVC_LOST),</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_VALUE_STRING(MF_E_SRVC_CONFIG_BANK),</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_VALUE_STRING(MF_E_SRVC_RESET_REQ),</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_VALUE_STRING(MF_E_BANKD_CONNECTED),</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_VALUE_STRING(MF_E_BANKD_LOST),</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_VALUE_STRING(MF_E_BANKD_TPDU),</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_VALUE_STRING(MF_E_BANKD_ATR),</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_VALUE_STRING(MF_E_BANKD_SLOT_STATUS),</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_VALUE_STRING(MF_E_MDM_STATUS_IND),</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_VALUE_STRING(MF_E_MDM_PTS_IND),</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_VALUE_STRING(MF_E_MDM_TPDU),</span><br><span style="color: hsl(120, 100%, 40%);">+ { 0, 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%);">+static void main_st_operational(struct osmo_fsm_inst *fi, uint32_t event, void *data);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void main_st_init(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct bankd_client *bc = (struct bankd_client *) fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case MF_E_SRVC_CONNECTED:</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_state_chg(fi, MF_ST_UNCONFIGURED, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ call_script(bc, "event-server-connect");</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%);">+ OSMO_ASSERT(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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void main_st_unconfigured_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct bankd_client *bc = (struct bankd_client *) fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* we might be called from a 'higher' state such as operational; clean up */</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_dispatch(bc->bankd_conn.fi, SRVC_E_DISCONNECT, 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%);">+static void main_st_unconfigured(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case MF_E_SRVC_CONFIG_BANK:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* same treatment as below */</span><br><span style="color: hsl(120, 100%, 40%);">+ main_st_operational(fi, event, data);</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%);">+ OSMO_ASSERT(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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void main_st_wait_bankd(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct bankd_client *bc = (struct bankd_client *) fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case MF_E_SRVC_CONFIG_BANK:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* same treatment as below */</span><br><span style="color: hsl(120, 100%, 40%);">+ main_st_operational(fi, event, data);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case MF_E_BANKD_CONNECTED:</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_state_chg(fi, MF_ST_OPERATIONAL, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ call_script(bc, "event-bankd-connect");</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%);">+ OSMO_ASSERT(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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void main_st_operational_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct bankd_client *bc = (struct bankd_client *) fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Simulate card-insert to modem */</span><br><span style="color: hsl(120, 100%, 40%);">+ frontend_request_card_insert(bc);</span><br><span style="color: hsl(120, 100%, 40%);">+ call_script(bc, "request-card-insert");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Select remote (forwarded) SIM */</span><br><span style="color: hsl(120, 100%, 40%);">+ frontend_request_sim_remote(bc);</span><br><span style="color: hsl(120, 100%, 40%);">+ call_script(bc, "request-sim-remote");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Set the ATR */</span><br><span style="color: hsl(120, 100%, 40%);">+ frontend_handle_set_atr(bc, bc->cfg->atr.data, bc->cfg->atr.len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Reset the modem */</span><br><span style="color: hsl(120, 100%, 40%);">+ frontend_request_modem_reset(bc);</span><br><span style="color: hsl(120, 100%, 40%);">+ call_script(bc, "request-modem-reset");</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 main_st_operational(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct bankd_client *bc = (struct bankd_client *) fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct frontend_phys_status *pstatus = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct frontend_pts *pts = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct frontend_tpdu *tpdu = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ RsproPDU_t *pdu_rx = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ RsproPDU_t *resp;</span><br><span style="color: hsl(120, 100%, 40%);">+ BankSlot_t bslot;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case MF_E_BANKD_LOST:</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_state_chg(fi, MF_ST_WAIT_BANKD, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case MF_E_SRVC_CONFIG_BANK:</span><br><span style="color: hsl(120, 100%, 40%);">+ pdu_rx = data;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(pdu_rx);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(pdu_rx->msg.present == RsproPDUchoice_PR_configClientBankReq);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* store/set the bankd ip/port as instructed by the server */</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_talloc_replace_string(bc, &bc->bankd_conn.server_host,</span><br><span style="color: hsl(120, 100%, 40%);">+ rspro_IpAddr2str(&pdu_rx->msg.choice.configClientBankReq.bankd.ip));</span><br><span style="color: hsl(120, 100%, 40%);">+ bc->bankd_conn.server_port = pdu_rx->msg.choice.configClientBankReq.bankd.port;</span><br><span style="color: hsl(120, 100%, 40%);">+ rspro2bank_slot(&bc->bankd_slot, &pdu_rx->msg.choice.configClientBankReq.bankSlot);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* bankd port 0 is a magic value to indicate "no bankd" */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bc->bankd_conn.server_port == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_state_chg(fi, MF_ST_UNCONFIGURED, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ else {</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_state_chg(fi, MF_ST_WAIT_BANKD, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* TODO: do we need to disconnect before? */</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_dispatch(bc->bankd_conn.fi, SRVC_E_ESTABLISH, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* send response to server */</span><br><span style="color: hsl(120, 100%, 40%);">+ resp = rspro_gen_ConfigClientBankRes(ResultCode_ok);</span><br><span style="color: hsl(120, 100%, 40%);">+ server_conn_send_rspro(&bc->srv_conn, resp);</span><br><span style="color: hsl(120, 100%, 40%);">+ call_script(bc, "event-config-bankd");</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case MF_E_BANKD_TPDU:</span><br><span style="color: hsl(120, 100%, 40%);">+ pdu_rx = data;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(pdu_rx);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(pdu_rx->msg.present == RsproPDUchoice_PR_tpduCardToModem);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* forward to modem/cardem (via API) */</span><br><span style="color: hsl(120, 100%, 40%);">+ frontend_handle_card2modem(bc, pdu_rx->msg.choice.tpduCardToModem.data.buf,</span><br><span style="color: hsl(120, 100%, 40%);">+ pdu_rx->msg.choice.tpduCardToModem.data.size);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* response happens indirectly via tpduModemToCard */</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case MF_E_BANKD_ATR:</span><br><span style="color: hsl(120, 100%, 40%);">+ pdu_rx = data;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(pdu_rx);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(pdu_rx->msg.present == RsproPDUchoice_PR_setAtrReq);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* forward to modem/cardem (via API) */</span><br><span style="color: hsl(120, 100%, 40%);">+ frontend_handle_set_atr(bc, pdu_rx->msg.choice.setAtrReq.atr.buf,</span><br><span style="color: hsl(120, 100%, 40%);">+ pdu_rx->msg.choice.setAtrReq.atr.size);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* send response to bankd */</span><br><span style="color: hsl(120, 100%, 40%);">+ resp = rspro_gen_SetAtrRes(ResultCode_ok);</span><br><span style="color: hsl(120, 100%, 40%);">+ server_conn_send_rspro(&bc->bankd_conn, resp);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case MF_E_BANKD_SLOT_STATUS:</span><br><span style="color: hsl(120, 100%, 40%);">+ pdu_rx = data;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(pdu_rx);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(pdu_rx->msg.present == RsproPDUchoice_PR_bankSlotStatusInd);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* forward to modem/cardem (via API) */</span><br><span style="color: hsl(120, 100%, 40%);">+ frontend_handle_slot_status(bc, &pdu_rx->msg.choice.bankSlotStatusInd.slotPhysStatus);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case MF_E_MDM_STATUS_IND:</span><br><span style="color: hsl(120, 100%, 40%);">+ pstatus = data;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(pstatus);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* forward to bankd */</span><br><span style="color: hsl(120, 100%, 40%);">+ bank_slot2rspro(&bslot, &bc->bankd_slot);</span><br><span style="color: hsl(120, 100%, 40%);">+ resp = rspro_gen_ClientSlotStatusInd(bc->srv_conn.clslot, &bslot,</span><br><span style="color: hsl(120, 100%, 40%);">+ pstatus->flags.reset_active,</span><br><span style="color: hsl(120, 100%, 40%);">+ pstatus->flags.vcc_present,</span><br><span style="color: hsl(120, 100%, 40%);">+ pstatus->flags.clk_active,</span><br><span style="color: hsl(120, 100%, 40%);">+ pstatus->flags.card_present);</span><br><span style="color: hsl(120, 100%, 40%);">+ server_conn_send_rspro(&bc->bankd_conn, resp);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!memcmp(&bc->last_status.flags, &pstatus->flags, sizeof(pstatus->flags)))</span><br><span style="color: hsl(120, 100%, 40%);">+ call_script(bc, "event-modem-status");</span><br><span style="color: hsl(120, 100%, 40%);">+ bc->last_status = *pstatus;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case MF_E_MDM_PTS_IND:</span><br><span style="color: hsl(120, 100%, 40%);">+ pts = data;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(pts);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* forward to bankd? */</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case MF_E_MDM_TPDU:</span><br><span style="color: hsl(120, 100%, 40%);">+ tpdu = data;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(tpdu);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* forward to bankd */</span><br><span style="color: hsl(120, 100%, 40%);">+ bank_slot2rspro(&bslot, &bc->bankd_slot);</span><br><span style="color: hsl(120, 100%, 40%);">+ resp = rspro_gen_TpduModem2Card(bc->srv_conn.clslot, &bslot, tpdu->buf, tpdu->len);</span><br><span style="color: hsl(120, 100%, 40%);">+ server_conn_send_rspro(&bc->bankd_conn, resp);</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%);">+ OSMO_ASSERT(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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void main_allstate_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case MF_E_SRVC_LOST:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* should we do anything? The SRVC fsm will take care of reconnect, and we</span><br><span style="color: hsl(120, 100%, 40%);">+ * can continue to talk to the bankd without any trouble... */</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case MF_E_SRVC_RESET_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_state_chg(fi, MF_ST_UNCONFIGURED, 0, 0);</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%);">+ OSMO_ASSERT(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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct osmo_fsm_state main_fsm_states[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ [MF_ST_INIT] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .name = "INIT",</span><br><span style="color: hsl(120, 100%, 40%);">+ .in_event_mask = S(MF_E_SRVC_CONNECTED),</span><br><span style="color: hsl(120, 100%, 40%);">+ .out_state_mask = S(MF_ST_UNCONFIGURED),</span><br><span style="color: hsl(120, 100%, 40%);">+ .action = main_st_init,</span><br><span style="color: hsl(120, 100%, 40%);">+ },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MF_ST_UNCONFIGURED] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .name = "UNCONFIGURED",</span><br><span style="color: hsl(120, 100%, 40%);">+ .in_event_mask = S(MF_E_SRVC_CONFIG_BANK),</span><br><span style="color: hsl(120, 100%, 40%);">+ .out_state_mask = S(MF_ST_INIT) | S(MF_ST_WAIT_BANKD),</span><br><span style="color: hsl(120, 100%, 40%);">+ .action = main_st_unconfigured,</span><br><span style="color: hsl(120, 100%, 40%);">+ .onenter = main_st_unconfigured_onenter,</span><br><span style="color: hsl(120, 100%, 40%);">+ },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MF_ST_WAIT_BANKD] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .name = "WAIT_BANKD",</span><br><span style="color: hsl(120, 100%, 40%);">+ .in_event_mask = S(MF_E_SRVC_CONFIG_BANK) | S(MF_E_BANKD_CONNECTED),</span><br><span style="color: hsl(120, 100%, 40%);">+ .out_state_mask = S(MF_ST_INIT) | S(MF_ST_UNCONFIGURED) | S(MF_ST_OPERATIONAL),</span><br><span style="color: hsl(120, 100%, 40%);">+ .action = main_st_wait_bankd,</span><br><span style="color: hsl(120, 100%, 40%);">+ },</span><br><span style="color: hsl(120, 100%, 40%);">+ [MF_ST_OPERATIONAL] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .name = "OPERATIONAL",</span><br><span style="color: hsl(120, 100%, 40%);">+ .in_event_mask = S(MF_E_SRVC_CONFIG_BANK) |</span><br><span style="color: hsl(120, 100%, 40%);">+ S(MF_E_BANKD_LOST) |</span><br><span style="color: hsl(120, 100%, 40%);">+ S(MF_E_BANKD_TPDU) |</span><br><span style="color: hsl(120, 100%, 40%);">+ S(MF_E_BANKD_ATR) |</span><br><span style="color: hsl(120, 100%, 40%);">+ S(MF_E_BANKD_SLOT_STATUS) |</span><br><span style="color: hsl(120, 100%, 40%);">+ S(MF_E_MDM_STATUS_IND) |</span><br><span style="color: hsl(120, 100%, 40%);">+ S(MF_E_MDM_PTS_IND) |</span><br><span style="color: hsl(120, 100%, 40%);">+ S(MF_E_MDM_TPDU),</span><br><span style="color: hsl(120, 100%, 40%);">+ .out_state_mask = S(MF_ST_INIT) | S(MF_ST_UNCONFIGURED) | S(MF_ST_WAIT_BANKD),</span><br><span style="color: hsl(120, 100%, 40%);">+ .action = main_st_operational,</span><br><span style="color: hsl(120, 100%, 40%);">+ .onenter = main_st_operational_onenter,</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%);">+static struct osmo_fsm client_main_fsm = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .name = "CLIENT_MAIN",</span><br><span style="color: hsl(120, 100%, 40%);">+ .states = main_fsm_states,</span><br><span style="color: hsl(120, 100%, 40%);">+ .num_states = ARRAY_SIZE(main_fsm_states),</span><br><span style="color: hsl(120, 100%, 40%);">+ .allstate_event_mask = S(MF_E_SRVC_LOST) | S(MF_E_SRVC_RESET_REQ),</span><br><span style="color: hsl(120, 100%, 40%);">+ .allstate_action = main_allstate_action,</span><br><span style="color: hsl(120, 100%, 40%);">+ .log_subsys = DMAIN,</span><br><span style="color: hsl(120, 100%, 40%);">+ .event_names = main_fsm_event_names,</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%);">+struct osmo_fsm_inst *main_fsm_alloc(void *ctx, struct bankd_client *bc)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return osmo_fsm_inst_alloc(&client_main_fsm, ctx, bc, LOGL_DEBUG, "main");</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 __attribute((constructor)) void on_dso_load_main_fsm(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(osmo_fsm_register(&client_main_fsm) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/client/remsim_client.c b/src/client/remsim_client.c</span><br><span>index dd78c8e..182894f 100644</span><br><span>--- a/src/client/remsim_client.c</span><br><span>+++ b/src/client/remsim_client.c</span><br><span>@@ -20,6 +20,10 @@</span><br><span> *</span><br><span> */</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* This file contains code shared among all remsim client applications,</span><br><span style="color: hsl(120, 100%, 40%);">+ * including the ifd-handler, which is not an executable program with a main()</span><br><span style="color: hsl(120, 100%, 40%);">+ * function or command line parsing, but a shared library */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #include <errno.h></span><br><span> #include <string.h></span><br><span> </span><br><span>@@ -33,8 +37,38 @@</span><br><span> #include "client.h"</span><br><span> #include "debug.h"</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct client_config *client_config_init(void *ctx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct client_config *cfg = talloc_zero(ctx, struct client_config);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!cfg)</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%);">+ cfg->server_host = talloc_strdup(cfg, "127.0.0.1");</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->server_port = 9998;</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->client_id = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->client_slot = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->gsmtap_host = talloc_strdup(cfg, "127.0.0.1");</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->keep_running = false;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->usb.vendor_id = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->usb.product_id = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->usb.config_id = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->usb.if_num = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->usb.altsetting = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->usb.addr = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->usb.path = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->atr.data[0] = 0x3B;</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->atr.data[1] = 0x00; // the shortest simplest ATR possible</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->atr.len = 2;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int bankd_handle_rx(struct rspro_server_conn *bankdc, const RsproPDU_t *pdu)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct bankd_client *bc = bankdc2bankd_client(bankdc);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> switch (pdu->msg.present) {</span><br><span> case RsproPDUchoice_PR_connectClientRes:</span><br><span> /* Store 'identity' of bankd to in peer_comp_id */</span><br><span>@@ -42,8 +76,11 @@</span><br><span> osmo_fsm_inst_dispatch(bankdc->fi, SRVC_E_CLIENT_CONN_RES, (void *) pdu);</span><br><span> break;</span><br><span> case RsproPDUchoice_PR_tpduCardToModem:</span><br><span style="color: hsl(120, 100%, 40%);">+ return osmo_fsm_inst_dispatch(bc->main_fi, MF_E_BANKD_TPDU, (void *) pdu);</span><br><span> case RsproPDUchoice_PR_setAtrReq:</span><br><span style="color: hsl(0, 100%, 40%);">- return client_user_bankd_handle_rx(bankdc, pdu);</span><br><span style="color: hsl(120, 100%, 40%);">+ return osmo_fsm_inst_dispatch(bc->main_fi, MF_E_BANKD_ATR, (void *) pdu);</span><br><span style="color: hsl(120, 100%, 40%);">+ case RsproPDUchoice_PR_bankSlotStatusInd:</span><br><span style="color: hsl(120, 100%, 40%);">+ return osmo_fsm_inst_dispatch(bc->main_fi, MF_E_BANKD_SLOT_STATUS, (void *) pdu);</span><br><span> default:</span><br><span> LOGPFSML(bankdc->fi, LOGL_ERROR, "Unknown/Unsupported RSPRO PDU %s\n",</span><br><span> rspro_msgt_name(pdu));</span><br><span>@@ -78,19 +115,7 @@</span><br><span> server_conn_send_rspro(srvc, resp);</span><br><span> break;</span><br><span> case RsproPDUchoice_PR_configClientBankReq:</span><br><span style="color: hsl(0, 100%, 40%);">- /* store/set the bankd ip/port as instructed by the server */</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_talloc_replace_string(bc, &bc->bankd_conn.server_host,</span><br><span style="color: hsl(0, 100%, 40%);">- rspro_IpAddr2str(&pdu->msg.choice.configClientBankReq.bankd.ip));</span><br><span style="color: hsl(0, 100%, 40%);">- rspro2bank_slot(&bc->bankd_slot, &pdu->msg.choice.configClientBankReq.bankSlot);</span><br><span style="color: hsl(0, 100%, 40%);">- bc->bankd_conn.server_port = pdu->msg.choice.configClientBankReq.bankd.port;</span><br><span style="color: hsl(0, 100%, 40%);">- /* bankd port 0 is a magic value to indicate "no bankd" */</span><br><span style="color: hsl(0, 100%, 40%);">- if (bc->bankd_conn.server_port == 0)</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_fsm_inst_dispatch(bc->bankd_conn.fi, SRVC_E_DISCONNECT, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- else</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_fsm_inst_dispatch(bc->bankd_conn.fi, SRVC_E_ESTABLISH, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- /* send response to server */</span><br><span style="color: hsl(0, 100%, 40%);">- resp = rspro_gen_ConfigClientBankRes(ResultCode_ok);</span><br><span style="color: hsl(0, 100%, 40%);">- server_conn_send_rspro(srvc, resp);</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_dispatch(bc->main_fi, MF_E_SRVC_CONFIG_BANK, (void *) pdu);</span><br><span> break;</span><br><span> default:</span><br><span> LOGPFSML(srvc->fi, LOGL_ERROR, "Unknown/Unsupported RSPRO PDU type: %s\n",</span><br><span>@@ -101,7 +126,8 @@</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct bankd_client *remsim_client_create(void *ctx, const char *name, const char *software)</span><br><span style="color: hsl(120, 100%, 40%);">+struct bankd_client *remsim_client_create(void *ctx, const char *name, const char *software,</span><br><span style="color: hsl(120, 100%, 40%);">+ struct client_config *cfg)</span><br><span> {</span><br><span> struct bankd_client *bc = talloc_zero(ctx, struct bankd_client);</span><br><span> struct rspro_server_conn *srvc, *bankdc;</span><br><span>@@ -110,10 +136,20 @@</span><br><span> if (!bc)</span><br><span> return NULL;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ bc->cfg = cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bc->main_fi = main_fsm_alloc(bc, bc);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!bc->main_fi) {</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stderr, "Unable to create main client FSM: %s\n", strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+ exit(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%);">+ remsim_client_set_clslot(bc, cfg->client_id, cfg->client_slot);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* create and [attempt to] establish connection to remsim-server */</span><br><span> srvc = &bc->srv_conn;</span><br><span style="color: hsl(0, 100%, 40%);">- srvc->server_host = "localhost";</span><br><span style="color: hsl(0, 100%, 40%);">- srvc->server_port = 9998;</span><br><span style="color: hsl(120, 100%, 40%);">+ srvc->server_host = cfg->server_host;</span><br><span style="color: hsl(120, 100%, 40%);">+ srvc->server_port = cfg->server_port;</span><br><span> srvc->handle_rx = srvc_handle_rx;</span><br><span> srvc->own_comp_id.type = ComponentType_remsimClient;</span><br><span> OSMO_STRLCPY_ARRAY(srvc->own_comp_id.name, name);</span><br><span>@@ -125,6 +161,9 @@</span><br><span> fprintf(stderr, "Unable to create Server conn FSM: %s\n", strerror(errno));</span><br><span> exit(1);</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_change_parent(srvc->fi, bc->main_fi, MF_E_SRVC_LOST);</span><br><span style="color: hsl(120, 100%, 40%);">+ srvc->parent_conn_evt = MF_E_SRVC_CONNECTED;</span><br><span style="color: hsl(120, 100%, 40%);">+ srvc->parent_disc_evt = MF_E_SRVC_LOST;</span><br><span> </span><br><span> bankdc = &bc->bankd_conn;</span><br><span> /* server_host / server_port are configured from remsim-server */</span><br><span>@@ -136,6 +175,9 @@</span><br><span> exit(1);</span><br><span> }</span><br><span> osmo_fsm_inst_update_id(bankdc->fi, "bankd");</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_change_parent(bankdc->fi, bc->main_fi, MF_E_BANKD_LOST);</span><br><span style="color: hsl(120, 100%, 40%);">+ bankdc->parent_conn_evt = MF_E_BANKD_CONNECTED;</span><br><span style="color: hsl(120, 100%, 40%);">+ bankdc->parent_disc_evt = MF_E_BANKD_LOST;</span><br><span> </span><br><span> return bc;</span><br><span> }</span><br><span>diff --git a/src/client/remsim_client_main.c b/src/client/remsim_client_main.c</span><br><span>index 95eb089..6587e6b 100644</span><br><span>--- a/src/client/remsim_client_main.c</span><br><span>+++ b/src/client/remsim_client_main.c</span><br><span>@@ -23,27 +23,56 @@</span><br><span> {</span><br><span> printf(</span><br><span> " -h --help Print this help message\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " -v --version Print program version\n"</span><br><span> " -i --server-ip A.B.C.D remsim-server IP address\n"</span><br><span> " -p --server-port 13245 remsim-server TCP port\n"</span><br><span style="color: hsl(0, 100%, 40%);">- " -i --client-id <0-65535> RSPRO ClientId of this client\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " -c --client-id <0-65535> RSPRO ClientId of this client\n"</span><br><span> " -n --client-slot <0-65535> RSPRO SlotNr of this client\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " -e --event-script <path> event script to be called by client\n"</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef USB_SUPPORT</span><br><span style="color: hsl(120, 100%, 40%);">+ " -V --usb-vendor VENDOR_ID\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " -P --usb-product PRODUCT_ID\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " -C --usb-config CONFIG_ID\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " -I --usb-interface INTERFACE_ID\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " -S --usb-altsetting ALTSETTING_ID\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " -A --usb-address ADDRESS\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " -H --usb-path PATH\n"</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> );</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void handle_options(struct bankd_client *bc, int argc, char **argv)</span><br><span style="color: hsl(120, 100%, 40%);">+static void handle_options(struct client_config *cfg, int argc, char **argv)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> while (1) {</span><br><span> int option_index = 0, c;</span><br><span> static const struct option long_options[] = {</span><br><span> { "help", 0, 0, 'h' },</span><br><span style="color: hsl(120, 100%, 40%);">+ { "version", 0, 0, 'v' },</span><br><span> { "server-ip", 1, 0, 'i' },</span><br><span> { "server-port", 1, 0, 'p' },</span><br><span> { "client-id", 1, 0, 'c' },</span><br><span> { "client-slot", 1, 0, 'n' },</span><br><span style="color: hsl(120, 100%, 40%);">+ { "atr", 1, 0, 'a' },</span><br><span style="color: hsl(120, 100%, 40%);">+ { "event-script", 1, 0, 'e' },</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef USB_SUPPORT</span><br><span style="color: hsl(120, 100%, 40%);">+ { "usb-vendor", 1, 0, 'V' },</span><br><span style="color: hsl(120, 100%, 40%);">+ { "usb-product", 1, 0, 'P' },</span><br><span style="color: hsl(120, 100%, 40%);">+ { "usb-config", 1, 0, 'C' },</span><br><span style="color: hsl(120, 100%, 40%);">+ { "usb-interface", 1, 0, 'I' },</span><br><span style="color: hsl(120, 100%, 40%);">+ { "usb-altsetting", 1, 0, 'S' },</span><br><span style="color: hsl(120, 100%, 40%);">+ { "usb-address", 1, 0, 'A' },</span><br><span style="color: hsl(120, 100%, 40%);">+ { "usb-path", 1, 0, 'H' },</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> { 0, 0, 0, 0 }</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- c = getopt_long(argc, argv, "hi:p:c:n:",</span><br><span style="color: hsl(120, 100%, 40%);">+ c = getopt_long(argc, argv, "hvi:p:c:n:e:"</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef USB_SUPPORT</span><br><span style="color: hsl(120, 100%, 40%);">+ "V:P:C:I:S:A:H:"</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+ ,</span><br><span> long_options, &option_index);</span><br><span> if (c == -1)</span><br><span> break;</span><br><span>@@ -53,18 +82,55 @@</span><br><span> printf_help();</span><br><span> exit(0);</span><br><span> break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 'v':</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("osmo-remsim-client version %s\n", VERSION);</span><br><span style="color: hsl(120, 100%, 40%);">+ exit(0);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span> case 'i':</span><br><span style="color: hsl(0, 100%, 40%);">- bc->srv_conn.server_host = optarg;</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_talloc_replace_string(cfg, &cfg->server_host, optarg);</span><br><span> break;</span><br><span> case 'p':</span><br><span style="color: hsl(0, 100%, 40%);">- bc->srv_conn.server_port = atoi(optarg);</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->server_port = atoi(optarg);</span><br><span> break;</span><br><span> case 'c':</span><br><span style="color: hsl(0, 100%, 40%);">- remsim_client_set_clslot(bc, atoi(optarg), -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->client_id = atoi(optarg);</span><br><span> break;</span><br><span> case 'n':</span><br><span style="color: hsl(0, 100%, 40%);">- remsim_client_set_clslot(bc, -1, atoi(optarg));</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->client_slot = atoi(optarg);</span><br><span> break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 'a':</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = osmo_hexparse(optarg, cfg->atr.data, ARRAY_SIZE(cfg->atr.data));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc < 2 || rc > ARRAY_SIZE(cfg->atr.data)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stderr, "ATR malformed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ exit(2);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 'e':</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_talloc_replace_string(cfg, &cfg->event_script, optarg);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef USB_SUPPORT</span><br><span style="color: hsl(120, 100%, 40%);">+ case 'V':</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->usb.vendor_id = strtol(optarg, NULL, 16);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 'P':</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->usb.product_id = strtol(optarg, NULL, 16);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 'C':</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->usb.config_id = atoi(optarg);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 'I':</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->usb.if_num = atoi(optarg);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 'S':</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->usb.altsetting = atoi(optarg);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 'A':</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->usb.addr = atoi(optarg);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 'H':</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->usb.path = optarg;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> default:</span><br><span> break;</span><br><span> }</span><br><span>@@ -74,6 +140,7 @@</span><br><span> int main(int argc, char **argv)</span><br><span> {</span><br><span> struct bankd_client *g_client;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct client_config *cfg;</span><br><span> char hostname[256];</span><br><span> </span><br><span> gethostname(hostname, sizeof(hostname));</span><br><span>@@ -84,9 +151,11 @@</span><br><span> </span><br><span> osmo_init_logging2(g_tall_ctx, &log_info);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- g_client = remsim_client_create(g_tall_ctx, hostname, "remsim-client");</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg = client_config_init(g_tall_ctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(cfg);</span><br><span style="color: hsl(120, 100%, 40%);">+ handle_options(cfg, argc, argv);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- handle_options(g_client, argc, argv);</span><br><span style="color: hsl(120, 100%, 40%);">+ g_client = remsim_client_create(g_tall_ctx, hostname, "remsim-client",cfg);</span><br><span> </span><br><span> osmo_fsm_inst_dispatch(g_client->srv_conn.fi, SRVC_E_ESTABLISH, NULL);</span><br><span> </span><br><span>diff --git a/src/client/simtrace2-remsim_client.c b/src/client/simtrace2-remsim_client.c</span><br><span>deleted file mode 100644</span><br><span>index e495f10..0000000</span><br><span>--- a/src/client/simtrace2-remsim_client.c</span><br><span>+++ /dev/null</span><br><span>@@ -1,1284 +0,0 @@</span><br><span style="color: hsl(0, 100%, 40%);">-/* (C) 2018-2020 by Harald Welte <laforge@gnumonks.org></span><br><span style="color: hsl(0, 100%, 40%);">- * (C) 2018 by sysmocom - s.f.m.c. GmbH, Author: Kevin Redon</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * All Rights Reserved</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * SPDX-License-Identifier: GPL-2.0+</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(0, 100%, 40%);">- * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(0, 100%, 40%);">- * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(0, 100%, 40%);">- * (at your option) any later version.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(0, 100%, 40%);">- * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(0, 100%, 40%);">- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span><br><span style="color: hsl(0, 100%, 40%);">- * GNU General Public License for more details.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * You should have received a copy of the GNU General Public License along</span><br><span style="color: hsl(0, 100%, 40%);">- * with this program; if not, write to the Free Software Foundation, Inc.,</span><br><span style="color: hsl(0, 100%, 40%);">- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include <errno.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <string.h></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include <talloc.h></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/core/msgb.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/core/fsm.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/core/utils.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/core/logging.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/core/application.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/core/exec.h></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/abis/ipa.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/gsm/protocol/ipaccess.h></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include "rspro_util.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "client.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "debug.h"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include <unistd.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <stdio.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <linux/limits.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <sys/stat.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <fcntl.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <signal.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <getopt.h></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include <libusb.h></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/usb/libusb.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/simtrace2/simtrace_prot.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/simtrace2/simtrace_usb.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/simtrace2/apdu_dispatch.h></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/core/gsmtap.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/core/gsmtap_util.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/core/utils.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/core/socket.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/core/msgb.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/sim/class_tables.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/sim/sim.h></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* transport to a SIMtrace device */</span><br><span style="color: hsl(0, 100%, 40%);">-struct st_transport {</span><br><span style="color: hsl(0, 100%, 40%);">- /* USB */</span><br><span style="color: hsl(0, 100%, 40%);">- struct libusb_device_handle *usb_devh;</span><br><span style="color: hsl(0, 100%, 40%);">- struct {</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t in;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t out;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t irq_in;</span><br><span style="color: hsl(0, 100%, 40%);">- } usb_ep;</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* a SIMtrace slot; communicates over a transport */</span><br><span style="color: hsl(0, 100%, 40%);">-struct st_slot {</span><br><span style="color: hsl(0, 100%, 40%);">- /* transport through which the slot can be reached */</span><br><span style="color: hsl(0, 100%, 40%);">- struct st_transport *transp;</span><br><span style="color: hsl(0, 100%, 40%);">- /* number of the slot within the transport */</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t slot_nr;</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* One istance of card emulation */</span><br><span style="color: hsl(0, 100%, 40%);">-struct cardem_inst {</span><br><span style="color: hsl(0, 100%, 40%);">- /* slot on which this card emulation instance runs */</span><br><span style="color: hsl(0, 100%, 40%);">- struct st_slot *slot;</span><br><span style="color: hsl(0, 100%, 40%);">- struct cardemu_usb_msg_status last_status;</span><br><span style="color: hsl(0, 100%, 40%);">- char *usb_path;</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* global GSMTAP instance */</span><br><span style="color: hsl(0, 100%, 40%);">-static struct gsmtap_inst *g_gti;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-struct bankd_client *g_client;</span><br><span style="color: hsl(0, 100%, 40%);">-static void *g_tall_ctx;</span><br><span style="color: hsl(0, 100%, 40%);">-void __thread *talloc_asn1_ctx;</span><br><span style="color: hsl(0, 100%, 40%);">-int asn_debug;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* should we leave main loop processing? */</span><br><span style="color: hsl(0, 100%, 40%);">-bool g_leave_main = false;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-__attribute__((unused)) static int gsmtap_send_sim(const uint8_t *apdu, unsigned int len)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsmtap_hdr *gh;</span><br><span style="color: hsl(0, 100%, 40%);">- unsigned int gross_len = len + sizeof(*gh);</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t *buf = malloc(gross_len);</span><br><span style="color: hsl(0, 100%, 40%);">- int rc;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!buf)</span><br><span style="color: hsl(0, 100%, 40%);">- return -ENOMEM;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- memset(buf, 0, sizeof(*gh));</span><br><span style="color: hsl(0, 100%, 40%);">- gh = (struct gsmtap_hdr *) buf;</span><br><span style="color: hsl(0, 100%, 40%);">- gh->version = GSMTAP_VERSION;</span><br><span style="color: hsl(0, 100%, 40%);">- gh->hdr_len = sizeof(*gh)/4;</span><br><span style="color: hsl(0, 100%, 40%);">- gh->type = GSMTAP_TYPE_SIM;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- memcpy(buf + sizeof(*gh), apdu, len);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- rc = write(gsmtap_inst_fd(g_gti), buf, gross_len);</span><br><span style="color: hsl(0, 100%, 40%);">- if (rc < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- perror("write gsmtap");</span><br><span style="color: hsl(0, 100%, 40%);">- free(buf);</span><br><span style="color: hsl(0, 100%, 40%);">- return rc;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- free(buf);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* build the (additional) environment for executing a script */</span><br><span style="color: hsl(0, 100%, 40%);">-static char **build_script_env(struct bankd_client *clnt, const char *cause)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct cardem_inst *ci = clnt->cardem;</span><br><span style="color: hsl(0, 100%, 40%);">- char **env = talloc_zero_size(clnt, 256*sizeof(char *));</span><br><span style="color: hsl(0, 100%, 40%);">- int i = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!env)</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- env[i++] = talloc_asprintf(env, "REMSIM_CLIENT_VERSION=%s", VERSION);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- env[i++] = talloc_asprintf(env, "REMSIM_SERVER_ADDR=%s:%u",</span><br><span style="color: hsl(0, 100%, 40%);">- clnt->srv_conn.server_host, clnt->srv_conn.server_port);</span><br><span style="color: hsl(0, 100%, 40%);">- env[i++] = talloc_asprintf(env, "REMSIM_SERVER_STATE=%s",</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_fsm_inst_state_name(clnt->srv_conn.fi));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- env[i++] = talloc_asprintf(env, "REMSIM_BANKD_ADDR=%s:%u",</span><br><span style="color: hsl(0, 100%, 40%);">- clnt->bankd_conn.server_host, clnt->bankd_conn.server_port);</span><br><span style="color: hsl(0, 100%, 40%);">- env[i++] = talloc_asprintf(env, "REMSIM_BANKD_STATE=%s",</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_fsm_inst_state_name(clnt->bankd_conn.fi));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (clnt->srv_conn.clslot) {</span><br><span style="color: hsl(0, 100%, 40%);">- env[i++] = talloc_asprintf(env, "REMSIM_CLIENT_SLOT=%lu:%lu",</span><br><span style="color: hsl(0, 100%, 40%);">- g_client->srv_conn.clslot->clientId,</span><br><span style="color: hsl(0, 100%, 40%);">- g_client->srv_conn.clslot->slotNr);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- env[i++] = talloc_asprintf(env, "REMSIM_BANKD_SLOT=%u:%u",</span><br><span style="color: hsl(0, 100%, 40%);">- clnt->bankd_slot.bank_id, clnt->bankd_slot.slot_nr);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- env[i++] = talloc_asprintf(env, "REMSIM_USB_PATH=%s", ci->usb_path);</span><br><span style="color: hsl(0, 100%, 40%);">- env[i++] = talloc_asprintf(env, "REMSIM_USB_INTERFACE=%u", clnt->cfg->usb.if_num);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* TODO: SIM card state VCC/CLK/RST */</span><br><span style="color: hsl(0, 100%, 40%);">- env[i++] = talloc_asprintf(env, "REMSIM_SIM_VCC=%u",</span><br><span style="color: hsl(0, 100%, 40%);">- !!(ci->last_status.flags & CEMU_STATUS_F_VCC_PRESENT));</span><br><span style="color: hsl(0, 100%, 40%);">- env[i++] = talloc_asprintf(env, "REMSIM_SIM_RST=%u",</span><br><span style="color: hsl(0, 100%, 40%);">- !!(ci->last_status.flags & CEMU_STATUS_F_RESET_ACTIVE));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- env[i++] = talloc_asprintf(env, "REMSIM_CAUSE=%s", cause);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* terminate last entry */</span><br><span style="color: hsl(0, 100%, 40%);">- env[i++] = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- return env;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int call_script(struct bankd_client *clnt, const char *cause)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- char **env, *cmd;</span><br><span style="color: hsl(0, 100%, 40%);">- int rc;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!clnt->cfg->event_script)</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- env = build_script_env(clnt, cause);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!env)</span><br><span style="color: hsl(0, 100%, 40%);">- return -ENOMEM;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- cmd = talloc_asprintf(env, "%s %s", clnt->cfg->event_script, cause);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!cmd) {</span><br><span style="color: hsl(0, 100%, 40%);">- talloc_free(env);</span><br><span style="color: hsl(0, 100%, 40%);">- return -ENOMEM;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- rc = osmo_system_nowait(cmd, osmo_environment_whitelist, env);</span><br><span style="color: hsl(0, 100%, 40%);">- talloc_free(env);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return rc;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/***********************************************************************</span><br><span style="color: hsl(0, 100%, 40%);">- * SIMTRACE core protocol</span><br><span style="color: hsl(0, 100%, 40%);">- ***********************************************************************/</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief allocate a message buffer for simtrace use */</span><br><span style="color: hsl(0, 100%, 40%);">-static struct msgb *st_msgb_alloc(void)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return msgb_alloc_headroom(1024+32, 32, "SIMtrace");</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#if 0</span><br><span style="color: hsl(0, 100%, 40%);">-static void apdu_out_cb(uint8_t *buf, unsigned int len, void *user_data)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- printf("APDU: %s\n", osmo_hexdump(buf, len));</span><br><span style="color: hsl(0, 100%, 40%);">- gsmtap_send_sim(buf, len);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-#endif</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void usb_out_xfer_cb(struct libusb_transfer *xfer)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct msgb *msg = xfer->user_data;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- switch (xfer->status) {</span><br><span style="color: hsl(0, 100%, 40%);">- case LIBUSB_TRANSFER_COMPLETED:</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case LIBUSB_TRANSFER_NO_DEVICE:</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "USB device disappeared\n");</span><br><span style="color: hsl(0, 100%, 40%);">- g_leave_main = true;</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- default:</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "USB OUT transfer failed, status=%u\n", xfer->status);</span><br><span style="color: hsl(0, 100%, 40%);">- g_leave_main = true;</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- libusb_free_transfer(xfer);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Transmit a given command to the SIMtrace2 device */</span><br><span style="color: hsl(0, 100%, 40%);">-int st_transp_tx_msg(struct st_transport *transp, struct msgb *msg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct libusb_transfer *xfer;</span><br><span style="color: hsl(0, 100%, 40%);">- int rc;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- printf("SIMtrace <- %s\n", msgb_hexdump(msg));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- xfer = libusb_alloc_transfer(0);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(xfer);</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->dev_handle = transp->usb_devh;</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->flags = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->type = LIBUSB_TRANSFER_TYPE_BULK;</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->endpoint = transp->usb_ep.out;</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->timeout = 1000;</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->user_data = msg;</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->length = msgb_length(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->buffer = msgb_data(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->callback = usb_out_xfer_cb;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* submit the OUT transfer */</span><br><span style="color: hsl(0, 100%, 40%);">- rc = libusb_submit_transfer(xfer);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(rc == 0);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return rc;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static struct simtrace_msg_hdr *st_push_hdr(struct msgb *msg, uint8_t msg_class, uint8_t msg_type,</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t slot_nr)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct simtrace_msg_hdr *sh;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- sh = (struct simtrace_msg_hdr *) msgb_push(msg, sizeof(*sh));</span><br><span style="color: hsl(0, 100%, 40%);">- memset(sh, 0, sizeof(*sh));</span><br><span style="color: hsl(0, 100%, 40%);">- sh->msg_class = msg_class;</span><br><span style="color: hsl(0, 100%, 40%);">- sh->msg_type = msg_type;</span><br><span style="color: hsl(0, 100%, 40%);">- sh->slot_nr = slot_nr;</span><br><span style="color: hsl(0, 100%, 40%);">- sh->msg_len = msgb_length(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return sh;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* transmit a given message to a specified slot. Expects all headers</span><br><span style="color: hsl(0, 100%, 40%);">- * present before calling the function */</span><br><span style="color: hsl(0, 100%, 40%);">-int st_slot_tx_msg(struct st_slot *slot, struct msgb *msg,</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t msg_class, uint8_t msg_type)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- st_push_hdr(msg, msg_class, msg_type, slot->slot_nr);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return st_transp_tx_msg(slot->transp, msg);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/***********************************************************************</span><br><span style="color: hsl(0, 100%, 40%);">- * Card Emulation protocol</span><br><span style="color: hsl(0, 100%, 40%);">- ***********************************************************************/</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Request the SIMtrace2 to generate a card-insert signal */</span><br><span style="color: hsl(0, 100%, 40%);">-static int cardem_request_card_insert(struct cardem_inst *ci, bool inserted)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct msgb *msg = st_msgb_alloc();</span><br><span style="color: hsl(0, 100%, 40%);">- struct cardemu_usb_msg_cardinsert *cins;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- cins = (struct cardemu_usb_msg_cardinsert *) msgb_put(msg, sizeof(*cins));</span><br><span style="color: hsl(0, 100%, 40%);">- memset(cins, 0, sizeof(*cins));</span><br><span style="color: hsl(0, 100%, 40%);">- if (inserted)</span><br><span style="color: hsl(0, 100%, 40%);">- cins->card_insert = 1;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return st_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_CARDINSERT);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Request the SIMtrace2 to transmit a Procedure Byte, then Rx */</span><br><span style="color: hsl(0, 100%, 40%);">-static int cardem_request_pb_and_rx(struct cardem_inst *ci, uint8_t pb, uint8_t le)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct msgb *msg = st_msgb_alloc();</span><br><span style="color: hsl(0, 100%, 40%);">- struct cardemu_usb_msg_tx_data *txd;</span><br><span style="color: hsl(0, 100%, 40%);">- txd = (struct cardemu_usb_msg_tx_data *) msgb_put(msg, sizeof(*txd));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- printf("SIMtrace <= %s(%02x, %d)\n", __func__, pb, le);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- memset(txd, 0, sizeof(*txd));</span><br><span style="color: hsl(0, 100%, 40%);">- txd->data_len = 1;</span><br><span style="color: hsl(0, 100%, 40%);">- txd->flags = CEMU_DATA_F_PB_AND_RX;</span><br><span style="color: hsl(0, 100%, 40%);">- /* one data byte */</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_put_u8(msg, pb);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return st_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_TX_DATA);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Request the SIMtrace2 to transmit a Procedure Byte, then Tx */</span><br><span style="color: hsl(0, 100%, 40%);">-static int cardem_request_pb_and_tx(struct cardem_inst *ci, uint8_t pb,</span><br><span style="color: hsl(0, 100%, 40%);">- const uint8_t *data, uint16_t data_len_in)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct msgb *msg = st_msgb_alloc();</span><br><span style="color: hsl(0, 100%, 40%);">- struct cardemu_usb_msg_tx_data *txd;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t *cur;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- txd = (struct cardemu_usb_msg_tx_data *) msgb_put(msg, sizeof(*txd));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- printf("SIMtrace <= %s(%02x, %s, %d)\n", __func__, pb,</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_hexdump(data, data_len_in), data_len_in);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- memset(txd, 0, sizeof(*txd));</span><br><span style="color: hsl(0, 100%, 40%);">- txd->data_len = 1 + data_len_in;</span><br><span style="color: hsl(0, 100%, 40%);">- txd->flags = CEMU_DATA_F_PB_AND_TX;</span><br><span style="color: hsl(0, 100%, 40%);">- /* procedure byte */</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_put_u8(msg, pb);</span><br><span style="color: hsl(0, 100%, 40%);">- /* data */</span><br><span style="color: hsl(0, 100%, 40%);">- cur = msgb_put(msg, data_len_in);</span><br><span style="color: hsl(0, 100%, 40%);">- memcpy(cur, data, data_len_in);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return st_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_TX_DATA);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Request the SIMtrace2 to send a Status Word */</span><br><span style="color: hsl(0, 100%, 40%);">-static int cardem_request_sw_tx(struct cardem_inst *ci, const uint8_t *sw)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct msgb *msg = st_msgb_alloc();</span><br><span style="color: hsl(0, 100%, 40%);">- struct cardemu_usb_msg_tx_data *txd;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t *cur;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- txd = (struct cardemu_usb_msg_tx_data *) msgb_put(msg, sizeof(*txd));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- printf("SIMtrace <= %s(%02x %02x)\n", __func__, sw[0], sw[1]);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- memset(txd, 0, sizeof(*txd));</span><br><span style="color: hsl(0, 100%, 40%);">- txd->data_len = 2;</span><br><span style="color: hsl(0, 100%, 40%);">- txd->flags = CEMU_DATA_F_PB_AND_TX | CEMU_DATA_F_FINAL;</span><br><span style="color: hsl(0, 100%, 40%);">- cur = msgb_put(msg, 2);</span><br><span style="color: hsl(0, 100%, 40%);">- cur[0] = sw[0];</span><br><span style="color: hsl(0, 100%, 40%);">- cur[1] = sw[1];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return st_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_TX_DATA);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Request the SIMtrace2 to send a Status Word */</span><br><span style="color: hsl(0, 100%, 40%);">-static int cardem_request_config(struct cardem_inst *ci, uint32_t features)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct msgb *msg = st_msgb_alloc();</span><br><span style="color: hsl(0, 100%, 40%);">- struct cardemu_usb_msg_config *cfg;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- cfg = (struct cardemu_usb_msg_config *) msgb_put(msg, sizeof(*cfg));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- printf("SIMtrace <= %s(%08x)\n", __func__, features);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- memset(cfg, 0, sizeof(*cfg));</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->features = features;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return st_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_BD_CEMU_CONFIG);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-// FIXME check if the ATR actually includes a checksum</span><br><span style="color: hsl(0, 100%, 40%);">-__attribute__((unused)) static void atr_update_csum(uint8_t *atr, unsigned int atr_len)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t csum = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- int i;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- for (i = 1; i < atr_len - 1; i++)</span><br><span style="color: hsl(0, 100%, 40%);">- csum = csum ^ atr[i];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- atr[atr_len-1] = csum;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int cardem_request_set_atr(struct cardem_inst *ci, const uint8_t *atr, unsigned int atr_len)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct msgb *msg = st_msgb_alloc();</span><br><span style="color: hsl(0, 100%, 40%);">- struct cardemu_usb_msg_set_atr *satr;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t *cur;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- satr = (struct cardemu_usb_msg_set_atr *) msgb_put(msg, sizeof(*satr));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- printf("SIMtrace <= %s(%s)\n", __func__, osmo_hexdump(atr, atr_len));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- memset(satr, 0, sizeof(*satr));</span><br><span style="color: hsl(0, 100%, 40%);">- satr->atr_len = atr_len;</span><br><span style="color: hsl(0, 100%, 40%);">- cur = msgb_put(msg, atr_len);</span><br><span style="color: hsl(0, 100%, 40%);">- memcpy(cur, atr, atr_len);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return st_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_SET_ATR);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/***********************************************************************</span><br><span style="color: hsl(0, 100%, 40%);">- * Modem Control protocol</span><br><span style="color: hsl(0, 100%, 40%);">- ***********************************************************************/</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int _modem_reset(struct st_slot *slot, uint8_t asserted, uint16_t pulse_ms)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct msgb *msg = st_msgb_alloc();</span><br><span style="color: hsl(0, 100%, 40%);">- struct st_modem_reset *sr ;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- sr = (struct st_modem_reset *) msgb_put(msg, sizeof(*sr));</span><br><span style="color: hsl(0, 100%, 40%);">- sr->asserted = asserted;</span><br><span style="color: hsl(0, 100%, 40%);">- sr->pulse_duration_msec = pulse_ms;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return st_slot_tx_msg(slot, msg, SIMTRACE_MSGC_MODEM, SIMTRACE_MSGT_DT_MODEM_RESET);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief pulse the RESET line of the modem for \a duration_ms milli-seconds*/</span><br><span style="color: hsl(0, 100%, 40%);">-int st_modem_reset_pulse(struct st_slot *slot, uint16_t duration_ms)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return _modem_reset(slot, 2, duration_ms);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief assert the RESET line of the modem */</span><br><span style="color: hsl(0, 100%, 40%);">-int st_modem_reset_active(struct st_slot *slot)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return _modem_reset(slot, 1, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief de-assert the RESET line of the modem */</span><br><span style="color: hsl(0, 100%, 40%);">-int st_modem_reset_inactive(struct st_slot *slot)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return _modem_reset(slot, 0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int _modem_sim_select(struct st_slot *slot, uint8_t remote_sim)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct msgb *msg = st_msgb_alloc();</span><br><span style="color: hsl(0, 100%, 40%);">- struct st_modem_sim_select *ss;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ss = (struct st_modem_sim_select *) msgb_put(msg, sizeof(*ss));</span><br><span style="color: hsl(0, 100%, 40%);">- ss->remote_sim = remote_sim;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return st_slot_tx_msg(slot, msg, SIMTRACE_MSGC_MODEM, SIMTRACE_MSGT_DT_MODEM_SIM_SELECT);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief select local (physical) SIM for given slot */</span><br><span style="color: hsl(0, 100%, 40%);">-int st_modem_sim_select_local(struct st_slot *slot)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return _modem_sim_select(slot, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief select remote (emulated/forwarded) SIM for given slot */</span><br><span style="color: hsl(0, 100%, 40%);">-int st_modem_sim_select_remote(struct st_slot *slot)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return _modem_sim_select(slot, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Request slot to send us status information about the modem */</span><br><span style="color: hsl(0, 100%, 40%);">-int st_modem_get_status(struct st_slot *slot)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct msgb *msg = st_msgb_alloc();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return st_slot_tx_msg(slot, msg, SIMTRACE_MSGC_MODEM, SIMTRACE_MSGT_BD_MODEM_STATUS);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/***********************************************************************</span><br><span style="color: hsl(0, 100%, 40%);">- * Incoming Messages</span><br><span style="color: hsl(0, 100%, 40%);">- ***********************************************************************/</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Process a STATUS message from the SIMtrace2 */</span><br><span style="color: hsl(0, 100%, 40%);">-static int process_do_status(struct cardem_inst *ci, uint8_t *buf, int len)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct cardemu_usb_msg_status *status;</span><br><span style="color: hsl(0, 100%, 40%);">- status = (struct cardemu_usb_msg_status *) buf;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- printf("SIMtrace => STATUS: flags=0x%x, fi=%u, di=%u, wi=%u wtime=%u\n",</span><br><span style="color: hsl(0, 100%, 40%);">- status->flags, status->fi, status->di, status->wi,</span><br><span style="color: hsl(0, 100%, 40%);">- status->waiting_time);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Process a PTS indication message from the SIMtrace2 */</span><br><span style="color: hsl(0, 100%, 40%);">-static int process_do_pts(struct cardem_inst *ci, uint8_t *buf, int len)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct cardemu_usb_msg_pts_info *pts;</span><br><span style="color: hsl(0, 100%, 40%);">- pts = (struct cardemu_usb_msg_pts_info *) buf;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- printf("SIMtrace => PTS req: %s\n", osmo_hexdump(pts->req, sizeof(pts->req)));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Process a ERROR indication message from the SIMtrace2 */</span><br><span style="color: hsl(0, 100%, 40%);">-__attribute__((unused)) static int process_do_error(struct cardem_inst *ci, uint8_t *buf, int len)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct cardemu_usb_msg_error *err;</span><br><span style="color: hsl(0, 100%, 40%);">- err = (struct cardemu_usb_msg_error *) buf;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- printf("SIMtrace => ERROR: %u/%u/%u: %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- err->severity, err->subsystem, err->code,</span><br><span style="color: hsl(0, 100%, 40%);">- err->msg_len ? (char *)err->msg : "");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static struct osmo_apdu_context ac; // this will hold the complete APDU (across calls)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Process a RX-DATA indication message from the SIMtrace2 */</span><br><span style="color: hsl(0, 100%, 40%);">-static int process_do_rx_da(struct cardem_inst *ci, uint8_t *buf, int len)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct cardemu_usb_msg_rx_data *data = (struct cardemu_usb_msg_rx_data *) buf; // cast the data from the USB message</span><br><span style="color: hsl(0, 100%, 40%);">- int rc;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- printf("SIMtrace => DATA: flags=%x, %s: ", data->flags,</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_hexdump(data->data, data->data_len));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- rc = osmo_apdu_segment_in(&ac, data->data, data->data_len,</span><br><span style="color: hsl(0, 100%, 40%);">- data->flags & CEMU_DATA_F_TPDU_HDR); // parse the APDU data in the USB message</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (rc & APDU_ACT_TX_CAPDU_TO_CARD) { // there is no pending data coming from the modem</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t apdu_command[sizeof(ac.hdr) + ac.lc.tot]; // to store the APDU command to send</span><br><span style="color: hsl(0, 100%, 40%);">- memcpy(apdu_command, &ac.hdr, sizeof(ac.hdr)); // copy APDU command header</span><br><span style="color: hsl(0, 100%, 40%);">- if (ac.lc.tot) {</span><br><span style="color: hsl(0, 100%, 40%);">- memcpy(apdu_command + sizeof(ac.hdr), ac.dc, ac.lc.tot); // copy APDU command data </span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- // send APDU to card</span><br><span style="color: hsl(0, 100%, 40%);">- BankSlot_t bslot;</span><br><span style="color: hsl(0, 100%, 40%);">- bank_slot2rspro(&bslot, &g_client->bankd_slot);</span><br><span style="color: hsl(0, 100%, 40%);">- RsproPDU_t *pdu = rspro_gen_TpduModem2Card(g_client->srv_conn.clslot, &bslot, apdu_command, sizeof(ac.hdr) + ac.lc.tot); // create RSPRO packet</span><br><span style="color: hsl(0, 100%, 40%);">- server_conn_send_rspro(&g_client->bankd_conn, pdu);</span><br><span style="color: hsl(0, 100%, 40%);">- // the response will come separately</span><br><span style="color: hsl(0, 100%, 40%);">- } else if (ac.lc.tot > ac.lc.cur) { // there is pending data from the modem</span><br><span style="color: hsl(0, 100%, 40%);">- cardem_request_pb_and_rx(ci, ac.hdr.ins, ac.lc.tot - ac.lc.cur); // send procedure byte to get remaining data</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#if 0</span><br><span style="color: hsl(0, 100%, 40%);">- case SIMTRACE_CMD_DO_ERROR</span><br><span style="color: hsl(0, 100%, 40%);">- rc = process_do_error(ci, buf, len);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">-#endif</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Process an incoming message from the SIMtrace2 */</span><br><span style="color: hsl(0, 100%, 40%);">-static int process_usb_msg(struct cardem_inst *ci, uint8_t *buf, int len)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct simtrace_msg_hdr *sh = (struct simtrace_msg_hdr *)buf;</span><br><span style="color: hsl(0, 100%, 40%);">- int rc;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- printf("SIMtrace -> %s\n", osmo_hexdump(buf, len));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- buf += sizeof(*sh);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- switch (sh->msg_type) {</span><br><span style="color: hsl(0, 100%, 40%);">- case SIMTRACE_MSGT_BD_CEMU_STATUS:</span><br><span style="color: hsl(0, 100%, 40%);">- rc = process_do_status(ci, buf, len);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case SIMTRACE_MSGT_DO_CEMU_PTS:</span><br><span style="color: hsl(0, 100%, 40%);">- rc = process_do_pts(ci, buf, len);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case SIMTRACE_MSGT_DO_CEMU_RX_DATA:</span><br><span style="color: hsl(0, 100%, 40%);">- rc = process_do_rx_da(ci, buf, len);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case SIMTRACE_MSGT_BD_CEMU_CONFIG:</span><br><span style="color: hsl(0, 100%, 40%);">- /* firmware confirms configuration change; ignore */</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- default:</span><br><span style="color: hsl(0, 100%, 40%);">- printf("unknown simtrace msg type 0x%02x\n", sh->msg_type);</span><br><span style="color: hsl(0, 100%, 40%);">- rc = -1;</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return rc;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Process a STATUS message on IRQ endpoint from the SIMtrace2 */</span><br><span style="color: hsl(0, 100%, 40%);">-static int process_irq_status(struct cardem_inst *ci, const uint8_t *buf, int len)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- const struct cardemu_usb_msg_status *status = (struct cardemu_usb_msg_status *) buf;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- printf("SIMtrace IRQ STATUS: flags=0x%x, fi=%u, di=%u, wi=%u wtime=%u\n",</span><br><span style="color: hsl(0, 100%, 40%);">- status->flags, status->fi, status->di, status->wi,</span><br><span style="color: hsl(0, 100%, 40%);">- status->waiting_time);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- BankSlot_t bslot;</span><br><span style="color: hsl(0, 100%, 40%);">- bank_slot2rspro(&bslot, &g_client->bankd_slot);</span><br><span style="color: hsl(0, 100%, 40%);">- RsproPDU_t *pdu = rspro_gen_ClientSlotStatusInd(g_client->srv_conn.clslot, &bslot,</span><br><span style="color: hsl(0, 100%, 40%);">- status->flags & CEMU_STATUS_F_RESET_ACTIVE,</span><br><span style="color: hsl(0, 100%, 40%);">- status->flags & CEMU_STATUS_F_VCC_PRESENT,</span><br><span style="color: hsl(0, 100%, 40%);">- status->flags & CEMU_STATUS_F_CLK_ACTIVE,</span><br><span style="color: hsl(0, 100%, 40%);">- -1 /* FIXME: make this dependent on board */);</span><br><span style="color: hsl(0, 100%, 40%);">- server_conn_send_rspro(&g_client->bankd_conn, pdu);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (ci->last_status.flags != status->flags) {</span><br><span style="color: hsl(0, 100%, 40%);">- ci->last_status = *status;</span><br><span style="color: hsl(0, 100%, 40%);">- call_script(g_client, "event-modem-status");</span><br><span style="color: hsl(0, 100%, 40%);">- } else</span><br><span style="color: hsl(0, 100%, 40%);">- ci->last_status = *status;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int process_usb_msg_irq(struct cardem_inst *ci, const uint8_t *buf, unsigned int len)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct simtrace_msg_hdr *sh = (struct simtrace_msg_hdr *)buf;</span><br><span style="color: hsl(0, 100%, 40%);">- int rc;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- printf("SIMtrace IRQ %s\n", osmo_hexdump(buf, len));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- buf += sizeof(*sh);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- switch (sh->msg_type) {</span><br><span style="color: hsl(0, 100%, 40%);">- case SIMTRACE_MSGT_BD_CEMU_STATUS:</span><br><span style="color: hsl(0, 100%, 40%);">- rc = process_irq_status(ci, buf, len);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- default:</span><br><span style="color: hsl(0, 100%, 40%);">- printf("unknown simtrace msg type 0x%02x\n", sh->msg_type);</span><br><span style="color: hsl(0, 100%, 40%);">- rc = -1;</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return rc;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void usb_in_xfer_cb(struct libusb_transfer *xfer)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct cardem_inst *ci = xfer->user_data;</span><br><span style="color: hsl(0, 100%, 40%);">- int rc;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- switch (xfer->status) {</span><br><span style="color: hsl(0, 100%, 40%);">- case LIBUSB_TRANSFER_COMPLETED:</span><br><span style="color: hsl(0, 100%, 40%);">- /* hand the message up the stack */</span><br><span style="color: hsl(0, 100%, 40%);">- process_usb_msg(ci, xfer->buffer, xfer->actual_length);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case LIBUSB_TRANSFER_NO_DEVICE:</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "USB device disappeared\n");</span><br><span style="color: hsl(0, 100%, 40%);">- g_leave_main = true;</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- default:</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "USB IN transfer failed, status=%u\n", xfer->status);</span><br><span style="color: hsl(0, 100%, 40%);">- g_leave_main = true;</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* re-submit the IN transfer */</span><br><span style="color: hsl(0, 100%, 40%);">- rc = libusb_submit_transfer(xfer);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(rc == 0);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void allocate_and_submit_in(struct cardem_inst *ci)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct st_transport *transp = ci->slot->transp;</span><br><span style="color: hsl(0, 100%, 40%);">- struct libusb_transfer *xfer;</span><br><span style="color: hsl(0, 100%, 40%);">- int rc;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- xfer = libusb_alloc_transfer(0);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(xfer);</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->dev_handle = transp->usb_devh;</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->flags = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->type = LIBUSB_TRANSFER_TYPE_BULK;</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->endpoint = transp->usb_ep.in;</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->timeout = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->user_data = ci;</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->length = 16*256;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->buffer = libusb_dev_mem_alloc(xfer->dev_handle, xfer->length);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(xfer->buffer);</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->callback = usb_in_xfer_cb;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* submit the IN transfer */</span><br><span style="color: hsl(0, 100%, 40%);">- rc = libusb_submit_transfer(xfer);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(rc == 0);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void usb_irq_xfer_cb(struct libusb_transfer *xfer)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct cardem_inst *ci = xfer->user_data;</span><br><span style="color: hsl(0, 100%, 40%);">- int rc;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- switch (xfer->status) {</span><br><span style="color: hsl(0, 100%, 40%);">- case LIBUSB_TRANSFER_COMPLETED:</span><br><span style="color: hsl(0, 100%, 40%);">- process_usb_msg_irq(ci, xfer->buffer, xfer->actual_length);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case LIBUSB_TRANSFER_NO_DEVICE:</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "USB device disappeared\n");</span><br><span style="color: hsl(0, 100%, 40%);">- g_leave_main = true;</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- default:</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "USB IRQ transfer failed, status=%u\n", xfer->status);</span><br><span style="color: hsl(0, 100%, 40%);">- g_leave_main = true;</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* re-submit the IN transfer */</span><br><span style="color: hsl(0, 100%, 40%);">- rc = libusb_submit_transfer(xfer);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(rc == 0);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void allocate_and_submit_irq(struct cardem_inst *ci)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct st_transport *transp = ci->slot->transp;</span><br><span style="color: hsl(0, 100%, 40%);">- struct libusb_transfer *xfer;</span><br><span style="color: hsl(0, 100%, 40%);">- int rc;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- xfer = libusb_alloc_transfer(0);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(xfer);</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->dev_handle = transp->usb_devh;</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->flags = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->type = LIBUSB_TRANSFER_TYPE_INTERRUPT;</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->endpoint = transp->usb_ep.irq_in;</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->timeout = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->user_data = ci;</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->length = 64;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->buffer = libusb_dev_mem_alloc(xfer->dev_handle, xfer->length);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(xfer->buffer);</span><br><span style="color: hsl(0, 100%, 40%);">- xfer->callback = usb_irq_xfer_cb;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* submit the IN transfer */</span><br><span style="color: hsl(0, 100%, 40%);">- rc = libusb_submit_transfer(xfer);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(rc == 0);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static struct st_transport _transp;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static struct st_slot _slot = {</span><br><span style="color: hsl(0, 100%, 40%);">- .transp = &_transp,</span><br><span style="color: hsl(0, 100%, 40%);">- .slot_nr = 0,</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static struct cardem_inst *g_ci;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void signal_handler(int signal)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- switch (signal) {</span><br><span style="color: hsl(0, 100%, 40%);">- case SIGINT:</span><br><span style="color: hsl(0, 100%, 40%);">- cardem_request_card_insert(g_ci, false);</span><br><span style="color: hsl(0, 100%, 40%);">- exit(0);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- default:</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/** remsim_client **/</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int bankd_handle_tpduCardToModem(struct bankd_client *bc, const RsproPDU_t *pdu)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(pdu);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(RsproPDUchoice_PR_tpduCardToModem == pdu->msg.present);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- const struct TpduCardToModem *card2modem = &pdu->msg.choice.tpduCardToModem;</span><br><span style="color: hsl(0, 100%, 40%);">- if (card2modem->data.size < 2) { // at least the two SW bytes are needed</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- // save SW to our current APDU context</span><br><span style="color: hsl(0, 100%, 40%);">- ac.sw[0] = card2modem->data.buf[card2modem->data.size - 2];</span><br><span style="color: hsl(0, 100%, 40%);">- ac.sw[1] = card2modem->data.buf[card2modem->data.size - 1];</span><br><span style="color: hsl(0, 100%, 40%);">- printf("SIMtrace <= SW=0x%02x%02x, len_rx=%d\n", ac.sw[0], ac.sw[1], card2modem->data.size - 2);</span><br><span style="color: hsl(0, 100%, 40%);">- if (card2modem->data.size > 2) { // send PB and data to modem</span><br><span style="color: hsl(0, 100%, 40%);">- cardem_request_pb_and_tx(bc->cardem, ac.hdr.ins, card2modem->data.buf, card2modem->data.size - 2);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- cardem_request_sw_tx(bc->cardem, ac.sw); // send SW to modem</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int bankd_handle_setAtrReq(struct bankd_client *bc, const RsproPDU_t *pdu)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- RsproPDU_t *resp;</span><br><span style="color: hsl(0, 100%, 40%);">- int rc;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(pdu);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(RsproPDUchoice_PR_setAtrReq == pdu->msg.present);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* FIXME: is this permitted at any time by the SIMtrace2 cardemfirmware? */</span><br><span style="color: hsl(0, 100%, 40%);">- rc = cardem_request_set_atr(bc->cardem, pdu->msg.choice.setAtrReq.atr.buf,</span><br><span style="color: hsl(0, 100%, 40%);">- pdu->msg.choice.setAtrReq.atr.size);</span><br><span style="color: hsl(0, 100%, 40%);">- if (rc == 0)</span><br><span style="color: hsl(0, 100%, 40%);">- resp = rspro_gen_SetAtrRes(ResultCode_ok);</span><br><span style="color: hsl(0, 100%, 40%);">- else</span><br><span style="color: hsl(0, 100%, 40%);">- resp = rspro_gen_SetAtrRes(ResultCode_cardTransmissionError);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!resp)</span><br><span style="color: hsl(0, 100%, 40%);">- return -ENOMEM;</span><br><span style="color: hsl(0, 100%, 40%);">- server_conn_send_rspro(&g_client->bankd_conn, resp);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* handle incoming message from bankd */</span><br><span style="color: hsl(0, 100%, 40%);">-static int bankd_handle_rx(struct rspro_server_conn *bankdc, const RsproPDU_t *pdu)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- switch (pdu->msg.present) {</span><br><span style="color: hsl(0, 100%, 40%);">- case RsproPDUchoice_PR_connectClientRes:</span><br><span style="color: hsl(0, 100%, 40%);">- /* Store 'identity' of bankd to in peer_comp_id */</span><br><span style="color: hsl(0, 100%, 40%);">- rspro_comp_id_retrieve(&bankdc->peer_comp_id, &pdu->msg.choice.connectClientRes.identity);</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_fsm_inst_dispatch(bankdc->fi, SRVC_E_CLIENT_CONN_RES, (void *) pdu);</span><br><span style="color: hsl(0, 100%, 40%);">- call_script(g_client, "event-bankd-connect");</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case RsproPDUchoice_PR_tpduCardToModem: // APDU response from card received</span><br><span style="color: hsl(0, 100%, 40%);">- bankd_handle_tpduCardToModem(g_client, pdu);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case RsproPDUchoice_PR_setAtrReq:</span><br><span style="color: hsl(0, 100%, 40%);">- bankd_handle_setAtrReq(g_client, pdu);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- default:</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPFSML(bankdc->fi, LOGL_ERROR, "Unknown/Unsuppoerted RSPRO PDU %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- rspro_msgt_name(pdu));</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* handle incoming messages from server */</span><br><span style="color: hsl(0, 100%, 40%);">-static int srvc_handle_rx(struct rspro_server_conn *srvc, const RsproPDU_t *pdu)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- RsproPDU_t *resp;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- switch (pdu->msg.present) {</span><br><span style="color: hsl(0, 100%, 40%);">- case RsproPDUchoice_PR_connectClientRes:</span><br><span style="color: hsl(0, 100%, 40%);">- /* Store 'identity' of server in srvc->peer_comp_id */</span><br><span style="color: hsl(0, 100%, 40%);">- rspro_comp_id_retrieve(&srvc->peer_comp_id, &pdu->msg.choice.connectClientRes.identity);</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_fsm_inst_dispatch(srvc->fi, SRVC_E_CLIENT_CONN_RES, (void *) pdu);</span><br><span style="color: hsl(0, 100%, 40%);">- call_script(g_client, "event-server-connect");</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case RsproPDUchoice_PR_configClientIdReq:</span><br><span style="color: hsl(0, 100%, 40%);">- /* store/set the clientID as instructed by the server */</span><br><span style="color: hsl(0, 100%, 40%);">- if (!g_client->srv_conn.clslot)</span><br><span style="color: hsl(0, 100%, 40%);">- g_client->srv_conn.clslot = talloc_zero(g_client, ClientSlot_t);</span><br><span style="color: hsl(0, 100%, 40%);">- *g_client->srv_conn.clslot = pdu->msg.choice.configClientIdReq.clientSlot;</span><br><span style="color: hsl(0, 100%, 40%);">- if (!g_client->bankd_conn.clslot)</span><br><span style="color: hsl(0, 100%, 40%);">- g_client->bankd_conn.clslot = talloc_zero(g_client, ClientSlot_t);</span><br><span style="color: hsl(0, 100%, 40%);">- *g_client->bankd_conn.clslot = *g_client->srv_conn.clslot;</span><br><span style="color: hsl(0, 100%, 40%);">- /* send response to server */</span><br><span style="color: hsl(0, 100%, 40%);">- resp = rspro_gen_ConfigClientIdRes(ResultCode_ok);</span><br><span style="color: hsl(0, 100%, 40%);">- server_conn_send_rspro(srvc, resp);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case RsproPDUchoice_PR_configClientBankReq:</span><br><span style="color: hsl(0, 100%, 40%);">- /* store/set the bankd ip/port as instructed by the server */</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_talloc_replace_string(g_client, &g_client->bankd_conn.server_host,</span><br><span style="color: hsl(0, 100%, 40%);">- rspro_IpAddr2str(&pdu->msg.choice.configClientBankReq.bankd.ip));</span><br><span style="color: hsl(0, 100%, 40%);">- rspro2bank_slot(&g_client->bankd_slot, &pdu->msg.choice.configClientBankReq.bankSlot);</span><br><span style="color: hsl(0, 100%, 40%);">- g_client->bankd_conn.server_port = pdu->msg.choice.configClientBankReq.bankd.port;</span><br><span style="color: hsl(0, 100%, 40%);">- /* bankd port 0 is a magic value to indicate "no bankd" */</span><br><span style="color: hsl(0, 100%, 40%);">- if (g_client->bankd_conn.server_port == 0)</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_fsm_inst_dispatch(g_client->bankd_conn.fi, SRVC_E_DISCONNECT, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- else</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_fsm_inst_dispatch(g_client->bankd_conn.fi, SRVC_E_ESTABLISH, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- /* send response to server */</span><br><span style="color: hsl(0, 100%, 40%);">- resp = rspro_gen_ConfigClientBankRes(ResultCode_ok);</span><br><span style="color: hsl(0, 100%, 40%);">- server_conn_send_rspro(srvc, resp);</span><br><span style="color: hsl(0, 100%, 40%);">- call_script(g_client, "event-config-bankd");</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- default:</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPFSML(srvc->fi, LOGL_ERROR, "Unknown/Unsupported RSPRO PDU type: %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- rspro_msgt_name(pdu));</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void handle_sig_usr1(int signal)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(signal == SIGUSR1);</span><br><span style="color: hsl(0, 100%, 40%);">- talloc_report_full(g_tall_ctx, stderr);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("===== NULL\n");</span><br><span style="color: hsl(0, 100%, 40%);">- talloc_report_full(NULL, stderr);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void print_welcome(void)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- printf("simtrace2-remsim-client - Remote SIM card client for SIMtrace\n"</span><br><span style="color: hsl(0, 100%, 40%);">- "(C) 2010-2020, Harald Welte <laforge@gnumonks.org>\n"</span><br><span style="color: hsl(0, 100%, 40%);">- "(C) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>\n\n");</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void print_help(void)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- printf( "\t-s\t--server-host HOST\n"</span><br><span style="color: hsl(0, 100%, 40%);">- "\t-p\t--server-port PORT\n"</span><br><span style="color: hsl(0, 100%, 40%);">- "\t-c\t--client-id <0-65535>\n"</span><br><span style="color: hsl(0, 100%, 40%);">- "\t-n\t--client-slot <0-65535>\n"</span><br><span style="color: hsl(0, 100%, 40%);">- "\t-h\t--help\n"</span><br><span style="color: hsl(0, 100%, 40%);">- "\t-v\t--version\n"</span><br><span style="color: hsl(0, 100%, 40%);">- "\t-i\t--gsmtap-ip\tA.B.C.D\n"</span><br><span style="color: hsl(0, 100%, 40%);">- "\t-k\t--keep-running\n"</span><br><span style="color: hsl(0, 100%, 40%);">- "\t-V\t--usb-vendor\tVENDOR_ID\n"</span><br><span style="color: hsl(0, 100%, 40%);">- "\t-P\t--usb-product\tPRODUCT_ID\n"</span><br><span style="color: hsl(0, 100%, 40%);">- "\t-C\t--usb-config\tCONFIG_ID\n"</span><br><span style="color: hsl(0, 100%, 40%);">- "\t-I\t--usb-interface\tINTERFACE_ID\n"</span><br><span style="color: hsl(0, 100%, 40%);">- "\t-S\t--usb-altsetting ALTSETTING_ID\n"</span><br><span style="color: hsl(0, 100%, 40%);">- "\t-A\t--usb-address\tADDRESS\n"</span><br><span style="color: hsl(0, 100%, 40%);">- "\t-H\t--usb-path\tPATH\n"</span><br><span style="color: hsl(0, 100%, 40%);">- "\t-a\t--atr\tATR\n"</span><br><span style="color: hsl(0, 100%, 40%);">- "\t-e\t--event-script\tPATH\n"</span><br><span style="color: hsl(0, 100%, 40%);">- "\n"</span><br><span style="color: hsl(0, 100%, 40%);">- );</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static struct client_config *client_config_init(void *ctx)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct client_config *cfg = talloc_zero(ctx, struct client_config);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!cfg)</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->server_host = talloc_strdup(cfg, "127.0.0.1");</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->server_port = 9998;</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->client_id = -1;</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->client_slot = -1;</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->gsmtap_host = talloc_strdup(cfg, "127.0.0.1");</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->keep_running = false;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->usb.vendor_id = -1;</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->usb.product_id = -1;</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->usb.config_id = -1;</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->usb.if_num = -1;</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->usb.altsetting = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->usb.addr = -1;</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->usb.path = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->atr.data[0] = 0x3B;</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->atr.data[1] = 0x00; // the shortest simplest ATR possible</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->atr.len = 2;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return cfg;</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void handle_options(struct client_config *cfg, int argc, char **argv)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- const struct option opts[] = {</span><br><span style="color: hsl(0, 100%, 40%);">- { "server-host", 1, 0, 's' },</span><br><span style="color: hsl(0, 100%, 40%);">- { "server-port", 1, 0, 'p' },</span><br><span style="color: hsl(0, 100%, 40%);">- { "client-id", 1, 0, 'c' },</span><br><span style="color: hsl(0, 100%, 40%);">- { "client-slot", 1, 0, 'n' },</span><br><span style="color: hsl(0, 100%, 40%);">- { "help", 0, 0, 'h' },</span><br><span style="color: hsl(0, 100%, 40%);">- { "version", 0, 0, 'v' },</span><br><span style="color: hsl(0, 100%, 40%);">- { "gsmtap-ip", 1, 0, 'i' },</span><br><span style="color: hsl(0, 100%, 40%);">- { "keep-running", 0, 0, 'k' },</span><br><span style="color: hsl(0, 100%, 40%);">- { "usb-vendor", 1, 0, 'V' },</span><br><span style="color: hsl(0, 100%, 40%);">- { "usb-product", 1, 0, 'P' },</span><br><span style="color: hsl(0, 100%, 40%);">- { "usb-config", 1, 0, 'C' },</span><br><span style="color: hsl(0, 100%, 40%);">- { "usb-interface", 1, 0, 'I' },</span><br><span style="color: hsl(0, 100%, 40%);">- { "usb-altsetting", 1, 0, 'S' },</span><br><span style="color: hsl(0, 100%, 40%);">- { "usb-address", 1, 0, 'A' },</span><br><span style="color: hsl(0, 100%, 40%);">- { "usb-path", 1, 0, 'H' },</span><br><span style="color: hsl(0, 100%, 40%);">- { "atr", 1, 0, 'a' },</span><br><span style="color: hsl(0, 100%, 40%);">- { "event-script", 1, 0, 'e' },</span><br><span style="color: hsl(0, 100%, 40%);">- { NULL, 0, 0, 0 }</span><br><span style="color: hsl(0, 100%, 40%);">- };</span><br><span style="color: hsl(0, 100%, 40%);">- int c, rc;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- while (1) {</span><br><span style="color: hsl(0, 100%, 40%);">- int option_index = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- c = getopt_long(argc, argv, "s:p:c:n:hvi:kV:P:C:I:S:A:H:a:e:", opts, &option_index);</span><br><span style="color: hsl(0, 100%, 40%);">- if (c == -1)</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- switch (c) {</span><br><span style="color: hsl(0, 100%, 40%);">- case 's':</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_talloc_replace_string(cfg, &cfg->server_host, optarg);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case 'p':</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->server_port = atoi(optarg);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case 'c':</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->client_id = atoi(optarg);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case 'n':</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->client_slot = atoi(optarg);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case 'h':</span><br><span style="color: hsl(0, 100%, 40%);">- print_help();</span><br><span style="color: hsl(0, 100%, 40%);">- exit(0);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case 'v':</span><br><span style="color: hsl(0, 100%, 40%);">- printf("osmo-remsim-client version %s\n", VERSION);</span><br><span style="color: hsl(0, 100%, 40%);">- exit(0);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case 'i':</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_talloc_replace_string(cfg, &cfg->gsmtap_host, optarg);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case 'k':</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->keep_running = 1;</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case 'V':</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->usb.vendor_id = strtol(optarg, NULL, 16);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case 'P':</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->usb.product_id = strtol(optarg, NULL, 16);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case 'C':</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->usb.config_id = atoi(optarg);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case 'I':</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->usb.if_num = atoi(optarg);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case 'S':</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->usb.altsetting = atoi(optarg);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case 'A':</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->usb.addr = atoi(optarg);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case 'H':</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->usb.path = optarg;</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case 'a':</span><br><span style="color: hsl(0, 100%, 40%);">- rc = osmo_hexparse(optarg, cfg->atr.data, ARRAY_SIZE(cfg->atr.data));</span><br><span style="color: hsl(0, 100%, 40%);">- if (rc < 2 || rc > ARRAY_SIZE(cfg->atr.data)) {</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "ATR malformed\n");</span><br><span style="color: hsl(0, 100%, 40%);">- exit(2);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- cfg->atr.len = rc;</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case 'e':</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_talloc_replace_string(cfg, &cfg->event_script, optarg);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (argc > optind) {</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "Unsupported positional arguments on command line\n");</span><br><span style="color: hsl(0, 100%, 40%);">- exit(2);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void main_body(struct cardem_inst *ci, struct client_config *cfg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct st_transport *transp = ci->slot->transp;</span><br><span style="color: hsl(0, 100%, 40%);">- struct usb_interface_match _ifm, *ifm = &_ifm;</span><br><span style="color: hsl(0, 100%, 40%);">- int rc, i;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ifm->vendor = cfg->usb.vendor_id;</span><br><span style="color: hsl(0, 100%, 40%);">- ifm->product = cfg->usb.product_id;</span><br><span style="color: hsl(0, 100%, 40%);">- ifm->configuration = cfg->usb.config_id;</span><br><span style="color: hsl(0, 100%, 40%);">- ifm->interface = cfg->usb.if_num;</span><br><span style="color: hsl(0, 100%, 40%);">- ifm->altsetting = cfg->usb.altsetting;</span><br><span style="color: hsl(0, 100%, 40%);">- ifm->addr = cfg->usb.addr;</span><br><span style="color: hsl(0, 100%, 40%);">- if (cfg->usb.path)</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_strlcpy(ifm->path, cfg->usb.path, sizeof(ifm->path));</span><br><span style="color: hsl(0, 100%, 40%);">- transp->usb_devh = osmo_libusb_open_claim_interface(NULL, NULL, ifm);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!transp->usb_devh) {</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "can't open USB device\n");</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* (re)determine the USB path of the opened device */</span><br><span style="color: hsl(0, 100%, 40%);">- talloc_free(ci->usb_path);</span><br><span style="color: hsl(0, 100%, 40%);">- ci->usb_path = osmo_libusb_dev_get_path_c(ci, libusb_get_device(transp->usb_devh));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- rc = libusb_claim_interface(transp->usb_devh, cfg->usb.if_num);</span><br><span style="color: hsl(0, 100%, 40%);">- if (rc < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "can't claim interface %d; rc=%d\n", cfg->usb.if_num, rc);</span><br><span style="color: hsl(0, 100%, 40%);">- goto close_exit;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- rc = osmo_libusb_get_ep_addrs(transp->usb_devh, cfg->usb.if_num, &transp->usb_ep.out,</span><br><span style="color: hsl(0, 100%, 40%);">- &transp->usb_ep.in, &transp->usb_ep.irq_in);</span><br><span style="color: hsl(0, 100%, 40%);">- if (rc < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "can't obtain EP addrs; rc=%d\n", rc);</span><br><span style="color: hsl(0, 100%, 40%);">- goto close_exit;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- // switch modem SIM port to emulated SIM on OWHW</span><br><span style="color: hsl(0, 100%, 40%);">- if (USB_VENDOR_OPENMOKO == ifm->vendor && USB_PRODUCT_OWHW_SAM3 == ifm->product) { // we are on the OWHW</span><br><span style="color: hsl(0, 100%, 40%);">- int modem = -1;</span><br><span style="color: hsl(0, 100%, 40%);">- switch (ifm->interface) { // the USB interface indicates for which modem we want to emulate the SIM</span><br><span style="color: hsl(0, 100%, 40%);">- case 0:</span><br><span style="color: hsl(0, 100%, 40%);">- modem = 1;</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case 1:</span><br><span style="color: hsl(0, 100%, 40%);">- modem = 2;</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- default:</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "unknown GPIO for SIMtrace interface %d\n", ifm->interface);</span><br><span style="color: hsl(0, 100%, 40%);">- goto close_exit;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- //</span><br><span style="color: hsl(0, 100%, 40%);">- char gpio_path[PATH_MAX];</span><br><span style="color: hsl(0, 100%, 40%);">- snprintf(gpio_path, sizeof(gpio_path), "/dev/gpio/connect_st_usim%d/value", modem);</span><br><span style="color: hsl(0, 100%, 40%);">- int connec_st_usim = open(gpio_path, O_WRONLY);</span><br><span style="color: hsl(0, 100%, 40%);">- if (-1 == connec_st_usim) {</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "can't open GPIO %s to switch modem %d to emulated USIM\n", gpio_path, modem);</span><br><span style="color: hsl(0, 100%, 40%);">- goto close_exit;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (1 != write(connec_st_usim, "1", 1)) {</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "can't write GPIO %s to switch modem %d to emulated USIM\n", gpio_path, modem);</span><br><span style="color: hsl(0, 100%, 40%);">- goto close_exit;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- printf("switched modem %d to emulated USIM\n", modem);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- snprintf(gpio_path, sizeof(gpio_path), "/dev/gpio/mdm%d_rst/value", modem);</span><br><span style="color: hsl(0, 100%, 40%);">- int mdm_rst = open(gpio_path, O_WRONLY);</span><br><span style="color: hsl(0, 100%, 40%);">- if (-1 == mdm_rst) {</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "can't open GPIO %s to reset modem %d\n", gpio_path, modem);</span><br><span style="color: hsl(0, 100%, 40%);">- goto close_exit;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (1 != write(mdm_rst, "1", 1)) {</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "can't write GPIO %s to reset modem %d\n", gpio_path, modem);</span><br><span style="color: hsl(0, 100%, 40%);">- goto close_exit;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- sleep(1); // wait a bit to ensure reset is effective</span><br><span style="color: hsl(0, 100%, 40%);">- if (1 != write(mdm_rst, "0", 1)) {</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "can't write GPIO %s to reset modem %d\n", gpio_path, modem);</span><br><span style="color: hsl(0, 100%, 40%);">- goto close_exit;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- printf("modem %d reset\n", modem);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* request firmware to generate STATUS on IRQ endpoint */</span><br><span style="color: hsl(0, 100%, 40%);">- cardem_request_config(ci, CEMU_FEAT_F_STATUS_IRQ);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* simulate card-insert to modem (owhw, not qmod) */</span><br><span style="color: hsl(0, 100%, 40%);">- cardem_request_card_insert(ci, true);</span><br><span style="color: hsl(0, 100%, 40%);">- call_script(g_client, "request-card-insert");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* select remote (forwarded) SIM */</span><br><span style="color: hsl(0, 100%, 40%);">- st_modem_sim_select_remote(ci->slot);</span><br><span style="color: hsl(0, 100%, 40%);">- call_script(g_client, "request-sim-remote");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* set the ATR */</span><br><span style="color: hsl(0, 100%, 40%);">- //atr_update_csum(real_atr, sizeof(real_atr));</span><br><span style="color: hsl(0, 100%, 40%);">- cardem_request_set_atr(ci, cfg->atr.data, cfg->atr.len);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* select remote (forwarded) SIM */</span><br><span style="color: hsl(0, 100%, 40%);">- st_modem_reset_pulse(ci->slot, 300);</span><br><span style="color: hsl(0, 100%, 40%);">- call_script(g_client, "request-modem-reset");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- printf("Entering main loop\n");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- allocate_and_submit_irq(ci);</span><br><span style="color: hsl(0, 100%, 40%);">- /* submit multiple IN URB in order to work around OS#4409 */</span><br><span style="color: hsl(0, 100%, 40%);">- for (i = 0; i < 4; i++)</span><br><span style="color: hsl(0, 100%, 40%);">- allocate_and_submit_in(ci);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- while (!g_leave_main) {</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_select_main(false);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- g_leave_main = false;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- libusb_release_interface(transp->usb_devh, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-close_exit:</span><br><span style="color: hsl(0, 100%, 40%);">- if (transp->usb_devh)</span><br><span style="color: hsl(0, 100%, 40%);">- libusb_close(transp-> usb_devh);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-int main(int argc, char **argv)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct rspro_server_conn *srvc, *bankdc;</span><br><span style="color: hsl(0, 100%, 40%);">- struct client_config *cfg;</span><br><span style="color: hsl(0, 100%, 40%);">- int rc;</span><br><span style="color: hsl(0, 100%, 40%);">- int ret = 1;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- print_welcome();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- talloc_enable_null_tracking();</span><br><span style="color: hsl(0, 100%, 40%);">- g_tall_ctx = talloc_named_const(NULL, 0, "global");</span><br><span style="color: hsl(0, 100%, 40%);">- talloc_asn1_ctx = talloc_named_const(g_tall_ctx, 0, "asn1");</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_talloc_ctx_init(g_tall_ctx, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_init_logging2(g_tall_ctx, &log_info);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- g_ci = talloc_zero(g_tall_ctx, struct cardem_inst);</span><br><span style="color: hsl(0, 100%, 40%);">- g_ci->slot = &_slot;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- cfg = client_config_init(g_ci);</span><br><span style="color: hsl(0, 100%, 40%);">- handle_options(cfg, argc, argv);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (cfg->usb.vendor_id < 0 || cfg->usb.product_id < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "You have to specify the vendor and product ID\n");</span><br><span style="color: hsl(0, 100%, 40%);">- goto do_exit;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- signal(SIGUSR1, handle_sig_usr1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- rc = osmo_libusb_init(NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- if (rc < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "libusb initialization failed\n");</span><br><span style="color: hsl(0, 100%, 40%);">- goto do_exit;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- g_gti = gsmtap_source_init(cfg->gsmtap_host, GSMTAP_UDP_PORT, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!g_gti) {</span><br><span style="color: hsl(0, 100%, 40%);">- perror("unable to open GSMTAP");</span><br><span style="color: hsl(0, 100%, 40%);">- goto close_exit;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- gsmtap_source_add_sink(g_gti);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- signal(SIGINT, &signal_handler);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- // initialize remote SIM client</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- g_client = talloc_zero(g_tall_ctx, struct bankd_client);</span><br><span style="color: hsl(0, 100%, 40%);">- g_client->cfg = cfg;</span><br><span style="color: hsl(0, 100%, 40%);">- g_client->cardem = g_ci;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (cfg->client_id != -1) {</span><br><span style="color: hsl(0, 100%, 40%);">- g_client->srv_conn.clslot = talloc_zero(g_client, ClientSlot_t);</span><br><span style="color: hsl(0, 100%, 40%);">- g_client->srv_conn.clslot->clientId = cfg->client_id;</span><br><span style="color: hsl(0, 100%, 40%);">- /* default to client slot 0 */</span><br><span style="color: hsl(0, 100%, 40%);">- if (cfg->client_slot == -1)</span><br><span style="color: hsl(0, 100%, 40%);">- g_client->srv_conn.clslot->slotNr = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- else</span><br><span style="color: hsl(0, 100%, 40%);">- g_client->srv_conn.clslot->slotNr = cfg->client_slot;</span><br><span style="color: hsl(0, 100%, 40%);">- g_client->bankd_conn.clslot = talloc_zero(g_client, ClientSlot_t);</span><br><span style="color: hsl(0, 100%, 40%);">- *g_client->bankd_conn.clslot = *g_client->srv_conn.clslot;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* create and [attempt to] establish connection to remsim-server */</span><br><span style="color: hsl(0, 100%, 40%);">- srvc = &g_client->srv_conn;</span><br><span style="color: hsl(0, 100%, 40%);">- srvc->server_host = cfg->server_host;</span><br><span style="color: hsl(0, 100%, 40%);">- srvc->server_port = cfg->server_port;</span><br><span style="color: hsl(0, 100%, 40%);">- srvc->handle_rx = srvc_handle_rx;</span><br><span style="color: hsl(0, 100%, 40%);">- srvc->own_comp_id.type = ComponentType_remsimClient;</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_STRLCPY_ARRAY(srvc->own_comp_id.name, "simtrace2-remsim-client");</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_STRLCPY_ARRAY(srvc->own_comp_id.software, "remsim-client");</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_STRLCPY_ARRAY(srvc->own_comp_id.sw_version, PACKAGE_VERSION);</span><br><span style="color: hsl(0, 100%, 40%);">- rc = server_conn_fsm_alloc(g_client, srvc);</span><br><span style="color: hsl(0, 100%, 40%);">- if (rc < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "Unable to create Server conn FSM: %s\n", strerror(errno));</span><br><span style="color: hsl(0, 100%, 40%);">- exit(1);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_fsm_inst_dispatch(srvc->fi, SRVC_E_ESTABLISH, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* create and not yet establish connection to remsim-bankd */</span><br><span style="color: hsl(0, 100%, 40%);">- srvc = &g_client->srv_conn;</span><br><span style="color: hsl(0, 100%, 40%);">- bankdc = &g_client->bankd_conn;</span><br><span style="color: hsl(0, 100%, 40%);">- /* server_host / server_port are configured from remsim-server */</span><br><span style="color: hsl(0, 100%, 40%);">- bankdc->handle_rx = bankd_handle_rx;</span><br><span style="color: hsl(0, 100%, 40%);">- memcpy(&bankdc->own_comp_id, &srvc->own_comp_id, sizeof(bankdc->own_comp_id));</span><br><span style="color: hsl(0, 100%, 40%);">- rc = server_conn_fsm_alloc(g_client, bankdc);</span><br><span style="color: hsl(0, 100%, 40%);">- if (rc < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "Unable to create bankd conn FSM: %s\n", strerror(errno));</span><br><span style="color: hsl(0, 100%, 40%);">- exit(1);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_fsm_inst_update_id(bankdc->fi, "bankd");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- asn_debug = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- // connect to SIMtrace2 cardem</span><br><span style="color: hsl(0, 100%, 40%);">- do {</span><br><span style="color: hsl(0, 100%, 40%);">- main_body(g_ci, cfg);</span><br><span style="color: hsl(0, 100%, 40%);">- sleep(1);</span><br><span style="color: hsl(0, 100%, 40%);">- } while (cfg->keep_running);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-close_exit:</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_libusb_exit(NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-do_exit:</span><br><span style="color: hsl(0, 100%, 40%);">- return ret;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span>diff --git a/src/client/user_ifdhandler.c b/src/client/user_ifdhandler.c</span><br><span>index 677b781..188d3a6 100644</span><br><span>--- a/src/client/user_ifdhandler.c</span><br><span>+++ b/src/client/user_ifdhandler.c</span><br><span>@@ -148,70 +148,66 @@</span><br><span> }</span><br><span> </span><br><span> /***********************************************************************</span><br><span style="color: hsl(0, 100%, 40%);">- * Incoming RSPRO messages from bank-daemon (SIM card)</span><br><span style="color: hsl(120, 100%, 40%);">+ * frontend to remsim-client main FSM code</span><br><span> ***********************************************************************/</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int bankd_handle_tpduCardToModem(struct bankd_client *bc, const RsproPDU_t *pdu)</span><br><span style="color: hsl(120, 100%, 40%);">+int frontend_request_card_insert(struct bankd_client *bc)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- const struct TpduCardToModem *card2modem;</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 frontend_request_sim_remote(struct bankd_client *bc)</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 frontend_request_modem_reset(struct bankd_client *bc)</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 frontend_handle_card2modem(struct bankd_client *bc, const uint8_t *data, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span> struct client_thread *ct = bc->data;</span><br><span> struct msgb *msg;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(pdu);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(RsproPDUchoice_PR_tpduCardToModem == pdu->msg.present);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(data);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- card2modem = &pdu->msg.choice.tpduCardToModem;</span><br><span style="color: hsl(0, 100%, 40%);">- DEBUGP(DMAIN, "R-APDU: %s\n", osmo_hexdump(card2modem->data.buf, card2modem->data.size));</span><br><span style="color: hsl(120, 100%, 40%);">+ DEBUGP(DMAIN, "R-APDU: %s\n", osmo_hexdump(data, len));</span><br><span> /* enqueue towards IFD thread */</span><br><span style="color: hsl(0, 100%, 40%);">- msg = itmsg_alloc(ITMSG_TYPE_R_APDU_IND, 0, card2modem->data.buf, card2modem->data.size);</span><br><span style="color: hsl(120, 100%, 40%);">+ msg = itmsg_alloc(ITMSG_TYPE_R_APDU_IND, 0, data, len);</span><br><span> OSMO_ASSERT(msg);</span><br><span> enqueue_to_ifd(ct, msg);</span><br><span> </span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int bankd_handle_setAtrReq(struct bankd_client *bc, const RsproPDU_t *pdu)</span><br><span style="color: hsl(120, 100%, 40%);">+int frontend_handle_set_atr(struct bankd_client *bc, const uint8_t *data, size_t len)</span><br><span> {</span><br><span> struct client_thread *ct = bc->data;</span><br><span style="color: hsl(0, 100%, 40%);">- RsproPDU_t *resp;</span><br><span> unsigned int atr_len;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(pdu);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(RsproPDUchoice_PR_setAtrReq == pdu->msg.present);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(data);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- DEBUGP(DMAIN, "SET_ATR: %s\n", osmo_hexdump(pdu->msg.choice.setAtrReq.atr.buf,</span><br><span style="color: hsl(0, 100%, 40%);">- pdu->msg.choice.setAtrReq.atr.size));</span><br><span style="color: hsl(120, 100%, 40%);">+ DEBUGP(DMAIN, "SET_ATR: %s\n", osmo_hexdump(data, len));</span><br><span> </span><br><span> /* store ATR in local data structure until somebody needs it */</span><br><span style="color: hsl(0, 100%, 40%);">- atr_len = pdu->msg.choice.setAtrReq.atr.size;</span><br><span style="color: hsl(120, 100%, 40%);">+ atr_len = len;</span><br><span> if (atr_len > sizeof(ct->atr))</span><br><span> atr_len = sizeof(ct->atr);</span><br><span style="color: hsl(0, 100%, 40%);">- memcpy(ct->atr, pdu->msg.choice.setAtrReq.atr.buf, atr_len);</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(ct->atr, data, atr_len);</span><br><span> ct->atr_len = atr_len;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- resp = rspro_gen_SetAtrRes(ResultCode_ok);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!resp)</span><br><span style="color: hsl(0, 100%, 40%);">- return -ENOMEM;</span><br><span style="color: hsl(0, 100%, 40%);">- server_conn_send_rspro(&bc->bankd_conn, resp);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-int client_user_bankd_handle_rx(struct rspro_server_conn *bankdc, const RsproPDU_t *pdu)</span><br><span style="color: hsl(120, 100%, 40%);">+int frontend_handle_slot_status(struct bankd_client *bc, const SlotPhysStatus_t *sts)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct bankd_client *bc = bankdc2bankd_client(bankdc);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- switch (pdu->msg.present) {</span><br><span style="color: hsl(0, 100%, 40%);">- case RsproPDUchoice_PR_tpduCardToModem:</span><br><span style="color: hsl(0, 100%, 40%);">- bankd_handle_tpduCardToModem(bc, pdu);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case RsproPDUchoice_PR_setAtrReq:</span><br><span style="color: hsl(0, 100%, 40%);">- bankd_handle_setAtrReq(bc, pdu);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- default:</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(0);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(120, 100%, 40%);">+int frontend_append_script_env(struct bankd_client *bc, char **env, size_t max_env)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span>@@ -363,6 +359,7 @@</span><br><span> static void *client_pthread_main(void *arg)</span><br><span> {</span><br><span> struct client_thread_cfg *cfg = arg;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct client_config *ccfg;</span><br><span> struct client_thread *ct;</span><br><span> int rc;</span><br><span> </span><br><span>@@ -373,17 +370,20 @@</span><br><span> ct = talloc_zero(OTC_GLOBAL, struct client_thread);</span><br><span> OSMO_ASSERT(ct);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ ccfg = client_config_init(ct);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ccfg);</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_talloc_replace_string(ccfg, &ccfg->server_host, cfg->server_host);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cfg->server_port >= 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ ccfg->server_port = cfg->server_port;</span><br><span style="color: hsl(120, 100%, 40%);">+ ccfg->client_id = cfg->client_id;</span><br><span style="color: hsl(120, 100%, 40%);">+ ccfg->client_slot = cfg->client_slot;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> if (!talloc_asn1_ctx)</span><br><span> talloc_asn1_ctx= talloc_named_const(ct, 0, "asn1");</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ct->bc = remsim_client_create(ct, cfg->name, "remsim_ifdhandler");</span><br><span style="color: hsl(120, 100%, 40%);">+ ct->bc = remsim_client_create(ct, cfg->name, "remsim_ifdhandler", ccfg);</span><br><span> OSMO_ASSERT(ct->bc);</span><br><span> ct->bc->data = ct;</span><br><span style="color: hsl(0, 100%, 40%);">- remsim_client_set_clslot(ct->bc, cfg->client_id, cfg->client_slot);</span><br><span style="color: hsl(0, 100%, 40%);">- if (cfg->server_host)</span><br><span style="color: hsl(0, 100%, 40%);">- ct->bc->srv_conn.server_host = (char *) cfg->server_host;</span><br><span style="color: hsl(0, 100%, 40%);">- if (cfg->server_port >= 0)</span><br><span style="color: hsl(0, 100%, 40%);">- ct->bc->srv_conn.server_port = cfg->server_port;</span><br><span> </span><br><span> INIT_LLIST_HEAD(&ct->it_msgq);</span><br><span> osmo_fd_setup(&ct->it_ofd, cfg->it_sock_fd, OSMO_FD_READ, &it_sock_fd_cb, ct, 0);</span><br><span>diff --git a/src/client/user_shell.c b/src/client/user_shell.c</span><br><span>index abe1542..40bcddd 100644</span><br><span>--- a/src/client/user_shell.c</span><br><span>+++ b/src/client/user_shell.c</span><br><span>@@ -12,58 +12,54 @@</span><br><span> </span><br><span> </span><br><span> /***********************************************************************</span><br><span style="color: hsl(0, 100%, 40%);">- * Incoming RSPRO messages from bank-daemon (SIM card)</span><br><span style="color: hsl(120, 100%, 40%);">+ * stdin frontend code to remsim-client</span><br><span> ***********************************************************************/</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int bankd_handle_tpduCardToModem(struct bankd_client *bc, const RsproPDU_t *pdu)</span><br><span style="color: hsl(120, 100%, 40%);">+int frontend_request_card_insert(struct bankd_client *bc)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(pdu);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(RsproPDUchoice_PR_tpduCardToModem == pdu->msg.present);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- const struct TpduCardToModem *card2modem = &pdu->msg.choice.tpduCardToModem;</span><br><span style="color: hsl(120, 100%, 40%);">+int frontend_request_sim_remote(struct bankd_client *bc)</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> </span><br><span style="color: hsl(0, 100%, 40%);">- printf("R-APDU: %s\n", osmo_hexdump(card2modem->data.buf, card2modem->data.size));</span><br><span style="color: hsl(120, 100%, 40%);">+int frontend_request_modem_reset(struct bankd_client *bc)</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 frontend_handle_card2modem(struct bankd_client *bc, const uint8_t *data, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(data);</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("R-APDU: %s\n", osmo_hexdump(data, len));</span><br><span> fflush(stdout);</span><br><span> </span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int bankd_handle_setAtrReq(struct bankd_client *bc, const RsproPDU_t *pdu)</span><br><span style="color: hsl(120, 100%, 40%);">+int frontend_handle_set_atr(struct bankd_client *bc, const uint8_t *data, size_t len)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- RsproPDU_t *resp;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(data);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(pdu);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(RsproPDUchoice_PR_setAtrReq == pdu->msg.present);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- printf("SET_ATR: %s\n", osmo_hexdump(pdu->msg.choice.setAtrReq.atr.buf,</span><br><span style="color: hsl(0, 100%, 40%);">- pdu->msg.choice.setAtrReq.atr.size));</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("SET_ATR: %s\n", osmo_hexdump(data, len));</span><br><span> fflush(stdout);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- resp = rspro_gen_SetAtrRes(ResultCode_ok);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!resp)</span><br><span style="color: hsl(0, 100%, 40%);">- return -ENOMEM;</span><br><span style="color: hsl(0, 100%, 40%);">- server_conn_send_rspro(&bc->bankd_conn, resp);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-int client_user_bankd_handle_rx(struct rspro_server_conn *bankdc, const RsproPDU_t *pdu)</span><br><span style="color: hsl(120, 100%, 40%);">+int frontend_handle_slot_status(struct bankd_client *bc, const SlotPhysStatus_t *sts)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct bankd_client *client = bankdc2bankd_client(bankdc);</span><br><span style="color: hsl(0, 100%, 40%);">- switch (pdu->msg.present) {</span><br><span style="color: hsl(0, 100%, 40%);">- case RsproPDUchoice_PR_tpduCardToModem:</span><br><span style="color: hsl(0, 100%, 40%);">- bankd_handle_tpduCardToModem(client, pdu);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case RsproPDUchoice_PR_setAtrReq:</span><br><span style="color: hsl(0, 100%, 40%);">- bankd_handle_setAtrReq(client, pdu);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- default:</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(0);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+int frontend_append_script_env(struct bankd_client *bc, char **env, size_t max_env)</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%);">+</span><br><span> /***********************************************************************</span><br><span> * Incoming command from the user application (stdin shell in our case)</span><br><span> ***********************************************************************/</span><br><span>diff --git a/src/client/user_simtrace2.c b/src/client/user_simtrace2.c</span><br><span>new file mode 100644</span><br><span>index 0000000..24a8d09</span><br><span>--- /dev/null</span><br><span>+++ b/src/client/user_simtrace2.c</span><br><span>@@ -0,0 +1,458 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* (C) 2018-2020 by Harald Welte <laforge@gnumonks.org></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPDX-License-Identifier: GPL-2.0+</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 along</span><br><span style="color: hsl(120, 100%, 40%);">+ * with this program; if not, write to the Free Software Foundation, Inc.,</span><br><span style="color: hsl(120, 100%, 40%);">+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</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%);">+#include <stdio.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <libusb.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/fsm.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/usb/libusb.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/simtrace2/apdu_dispatch.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/simtrace2/simtrace2_api.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/simtrace2/simtrace_prot.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "client.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "debug.h"</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%);">+ * Incoming Messages from cardem firmware</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%);">+/*! \brief Process a STATUS message from the SIMtrace2 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int process_do_status(struct osmo_st2_cardem_inst *ci, uint8_t *buf, int len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct cardemu_usb_msg_status *status;</span><br><span style="color: hsl(120, 100%, 40%);">+ status = (struct cardemu_usb_msg_status *) buf;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("SIMtrace => STATUS: flags=0x%x, fi=%u, di=%u, wi=%u wtime=%u\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ status->flags, status->fi, status->di, status->wi,</span><br><span style="color: hsl(120, 100%, 40%);">+ status->waiting_time);</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%);">+/*! \brief Process a PTS indication message from the SIMtrace2 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int process_do_pts(struct osmo_st2_cardem_inst *ci, uint8_t *buf, int len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct cardemu_usb_msg_pts_info *pts = (struct cardemu_usb_msg_pts_info *) buf;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct bankd_client *bc = ci->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct frontend_pts fpts = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .buf = pts->req,</span><br><span style="color: hsl(120, 100%, 40%);">+ .len = sizeof(pts->req),</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%);">+ printf("SIMtrace => PTS req: %s\n", osmo_hexdump(pts->req, sizeof(pts->req)));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_dispatch(bc->main_fi, MF_E_MDM_PTS_IND, &fpts);</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%);">+/*! \brief Process a ERROR indication message from the SIMtrace2 */</span><br><span style="color: hsl(120, 100%, 40%);">+__attribute__((unused)) static int process_do_error(struct osmo_st2_cardem_inst *ci, uint8_t *buf, int len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct cardemu_usb_msg_error *err;</span><br><span style="color: hsl(120, 100%, 40%);">+ err = (struct cardemu_usb_msg_error *) buf;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("SIMtrace => ERROR: %u/%u/%u: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ err->severity, err->subsystem, err->code,</span><br><span style="color: hsl(120, 100%, 40%);">+ err->msg_len ? (char *)err->msg : "");</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%);">+static struct osmo_apdu_context ac; // this will hold the complete APDU (across calls)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief Process a RX-DATA indication message from the SIMtrace2 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int process_do_rx_da(struct osmo_st2_cardem_inst *ci, uint8_t *buf, int len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct cardemu_usb_msg_rx_data *data = (struct cardemu_usb_msg_rx_data *) buf;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct bankd_client *bc = ci->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct frontend_tpdu ftpdu;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("SIMtrace => DATA: flags=%x, %s: ", data->flags,</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_hexdump(data->data, data->data_len));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* parse the APDU data in the USB message */</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = osmo_apdu_segment_in(&ac, data->data, data->data_len,</span><br><span style="color: hsl(120, 100%, 40%);">+ data->flags & CEMU_DATA_F_TPDU_HDR);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc & APDU_ACT_TX_CAPDU_TO_CARD) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* there is no pending data coming from the modem */</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t apdu_command[sizeof(ac.hdr) + ac.lc.tot];</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(apdu_command, &ac.hdr, sizeof(ac.hdr));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ac.lc.tot)</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(apdu_command + sizeof(ac.hdr), ac.dc, ac.lc.tot);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* send APDU to card */</span><br><span style="color: hsl(120, 100%, 40%);">+ ftpdu.buf = apdu_command;</span><br><span style="color: hsl(120, 100%, 40%);">+ ftpdu.len = sizeof(ac.hdr) + ac.lc.tot;</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_dispatch(bc->main_fi, MF_E_BANKD_TPDU, &ftpdu);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ac.lc.tot > ac.lc.cur) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* there is pending data from the modem: send procedure byte to get remaining data */</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_st2_cardem_request_pb_and_rx(ci, ac.hdr.ins, ac.lc.tot - ac.lc.cur);</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%);">+#if 0</span><br><span style="color: hsl(120, 100%, 40%);">+ case SIMTRACE_CMD_DO_ERROR</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = process_do_error(ci, buf, len);</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief Process an incoming message from the SIMtrace2 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int process_usb_msg(struct osmo_st2_cardem_inst *ci, uint8_t *buf, int len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct simtrace_msg_hdr *sh = (struct simtrace_msg_hdr *)buf;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("SIMtrace -> %s\n", osmo_hexdump(buf, len));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ buf += sizeof(*sh);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (sh->msg_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case SIMTRACE_MSGT_BD_CEMU_STATUS:</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = process_do_status(ci, buf, len);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case SIMTRACE_MSGT_DO_CEMU_PTS:</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = process_do_pts(ci, buf, len);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case SIMTRACE_MSGT_DO_CEMU_RX_DATA:</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = process_do_rx_da(ci, buf, len);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case SIMTRACE_MSGT_BD_CEMU_CONFIG:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* firmware confirms configuration change; ignore */</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 simtrace msg type 0x%02x\n", sh->msg_type);</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = -1;</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%);">+ return rc;</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%);">+/*! \brief Process a STATUS message on IRQ endpoint from the SIMtrace2 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int process_irq_status(struct osmo_st2_cardem_inst *ci, const uint8_t *buf, int len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct cardemu_usb_msg_status *status = (struct cardemu_usb_msg_status *) buf;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct bankd_client *bc = ci->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct frontend_phys_status pstatus = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .flags = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .reset_active = status->flags & CEMU_STATUS_F_RESET_ACTIVE,</span><br><span style="color: hsl(120, 100%, 40%);">+ .vcc_present = status->flags & CEMU_STATUS_F_VCC_PRESENT,</span><br><span style="color: hsl(120, 100%, 40%);">+ .clk_active = status->flags & CEMU_STATUS_F_CLK_ACTIVE,</span><br><span style="color: hsl(120, 100%, 40%);">+ .card_present = -1 /* FIXME: make this dependent on board */,</span><br><span style="color: hsl(120, 100%, 40%);">+ },</span><br><span style="color: hsl(120, 100%, 40%);">+ .voltage_mv = status->voltage_mv,</span><br><span style="color: hsl(120, 100%, 40%);">+ .fi = status->fi,</span><br><span style="color: hsl(120, 100%, 40%);">+ .di = status->di,</span><br><span style="color: hsl(120, 100%, 40%);">+ .wi = status->wi,</span><br><span style="color: hsl(120, 100%, 40%);">+ .waiting_time = status->waiting_time,</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%);">+ printf("SIMtrace IRQ STATUS: flags=0x%x, fi=%u, di=%u, wi=%u wtime=%u\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ status->flags, status->fi, status->di, status->wi,</span><br><span style="color: hsl(120, 100%, 40%);">+ status->waiting_time);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_dispatch(bc->main_fi, MF_E_MDM_STATUS_IND, &pstatus);</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%);">+static int process_usb_msg_irq(struct osmo_st2_cardem_inst *ci, const uint8_t *buf, unsigned int len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct simtrace_msg_hdr *sh = (struct simtrace_msg_hdr *)buf;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("SIMtrace IRQ %s\n", osmo_hexdump(buf, len));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ buf += sizeof(*sh);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (sh->msg_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case SIMTRACE_MSGT_BD_CEMU_STATUS:</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = process_irq_status(ci, buf, len);</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 simtrace msg type 0x%02x\n", sh->msg_type);</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = -1;</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%);">+ return rc;</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 usb_in_xfer_cb(struct libusb_transfer *xfer)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_st2_cardem_inst *ci = xfer->user_data;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (xfer->status) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case LIBUSB_TRANSFER_COMPLETED:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* hand the message up the stack */</span><br><span style="color: hsl(120, 100%, 40%);">+ process_usb_msg(ci, xfer->buffer, xfer->actual_length);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case LIBUSB_TRANSFER_NO_DEVICE:</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stderr, "USB device disappeared\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ exit(1);</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%);">+ fprintf(stderr, "USB IN transfer failed, status=%u\n", xfer->status);</span><br><span style="color: hsl(120, 100%, 40%);">+ exit(1);</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%);">+ /* re-submit the IN transfer */</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = libusb_submit_transfer(xfer);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(rc == 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void allocate_and_submit_in(struct osmo_st2_cardem_inst *ci)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_st2_transport *transp = ci->slot->transp;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct libusb_transfer *xfer;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ xfer = libusb_alloc_transfer(0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(xfer);</span><br><span style="color: hsl(120, 100%, 40%);">+ xfer->dev_handle = transp->usb_devh;</span><br><span style="color: hsl(120, 100%, 40%);">+ xfer->flags = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ xfer->type = LIBUSB_TRANSFER_TYPE_BULK;</span><br><span style="color: hsl(120, 100%, 40%);">+ xfer->endpoint = transp->usb_ep.in;</span><br><span style="color: hsl(120, 100%, 40%);">+ xfer->timeout = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ xfer->user_data = ci;</span><br><span style="color: hsl(120, 100%, 40%);">+ xfer->length = 16*256;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ xfer->buffer = libusb_dev_mem_alloc(xfer->dev_handle, xfer->length);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(xfer->buffer);</span><br><span style="color: hsl(120, 100%, 40%);">+ xfer->callback = usb_in_xfer_cb;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* submit the IN transfer */</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = libusb_submit_transfer(xfer);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(rc == 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void usb_irq_xfer_cb(struct libusb_transfer *xfer)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_st2_cardem_inst *ci = xfer->user_data;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (xfer->status) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case LIBUSB_TRANSFER_COMPLETED:</span><br><span style="color: hsl(120, 100%, 40%);">+ process_usb_msg_irq(ci, xfer->buffer, xfer->actual_length);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case LIBUSB_TRANSFER_NO_DEVICE:</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stderr, "USB device disappeared\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ exit(1);</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%);">+ fprintf(stderr, "USB IRQ transfer failed, status=%u\n", xfer->status);</span><br><span style="color: hsl(120, 100%, 40%);">+ exit(1);</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%);">+ /* re-submit the IN transfer */</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = libusb_submit_transfer(xfer);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(rc == 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void allocate_and_submit_irq(struct osmo_st2_cardem_inst *ci)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_st2_transport *transp = ci->slot->transp;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct libusb_transfer *xfer;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ xfer = libusb_alloc_transfer(0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(xfer);</span><br><span style="color: hsl(120, 100%, 40%);">+ xfer->dev_handle = transp->usb_devh;</span><br><span style="color: hsl(120, 100%, 40%);">+ xfer->flags = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ xfer->type = LIBUSB_TRANSFER_TYPE_INTERRUPT;</span><br><span style="color: hsl(120, 100%, 40%);">+ xfer->endpoint = transp->usb_ep.irq_in;</span><br><span style="color: hsl(120, 100%, 40%);">+ xfer->timeout = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ xfer->user_data = ci;</span><br><span style="color: hsl(120, 100%, 40%);">+ xfer->length = 64;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ xfer->buffer = libusb_dev_mem_alloc(xfer->dev_handle, xfer->length);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(xfer->buffer);</span><br><span style="color: hsl(120, 100%, 40%);">+ xfer->callback = usb_irq_xfer_cb;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* submit the IN transfer */</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = libusb_submit_transfer(xfer);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(rc == 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%);">+</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%);">+ * simtrace2 frontend code to remsim-client</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 frontend_request_card_insert(struct bankd_client *bc)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_st2_cardem_inst *ci = bc->cardem;</span><br><span style="color: hsl(120, 100%, 40%);">+ return osmo_st2_cardem_request_card_insert(ci, true);</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 frontend_request_sim_remote(struct bankd_client *bc)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_st2_cardem_inst *ci = bc->cardem;</span><br><span style="color: hsl(120, 100%, 40%);">+ return osmo_st2_modem_sim_select_remote(ci->slot);</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 frontend_request_modem_reset(struct bankd_client *bc)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_st2_cardem_inst *ci = bc->cardem;</span><br><span style="color: hsl(120, 100%, 40%);">+ return osmo_st2_modem_reset_pulse(ci->slot, 300);</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 frontend_handle_card2modem(struct bankd_client *bc, const uint8_t *data, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_st2_cardem_inst *ci = bc->cardem;</span><br><span style="color: hsl(120, 100%, 40%);">+ // save SW to our current APDU context</span><br><span style="color: hsl(120, 100%, 40%);">+ ac.sw[0] = data[len-2];</span><br><span style="color: hsl(120, 100%, 40%);">+ ac.sw[1] = data[len=1];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("SIMtrace <= SW=0x%02x%02x, len_rx=%zu\n", ac.sw[0], ac.sw[1], len-2);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (len > 2) { // send PB and data to modem</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_st2_cardem_request_pb_and_tx(ci, ac.hdr.ins, data, len-2);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_st2_cardem_request_sw_tx(ci, ac.sw); // send SW to modem</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 frontend_handle_set_atr(struct bankd_client *bc, const uint8_t *data, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_st2_cardem_inst *ci = bc->cardem;</span><br><span style="color: hsl(120, 100%, 40%);">+ return osmo_st2_cardem_request_set_atr(ci, data, len);</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 frontend_handle_slot_status(struct bankd_client *bc, const SlotPhysStatus_t *sts)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ /* we currently don't propagate bankd status to cardem */</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 frontend_append_script_env(struct bankd_client *bc, char **env, size_t max_env)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_st2_cardem_inst *ci = bc->cardem;</span><br><span style="color: hsl(120, 100%, 40%);">+ int i = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (max_env < 4)</span><br><span style="color: hsl(120, 100%, 40%);">+ return -ENOSPC;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ env[i++] = talloc_asprintf(env, "REMSIM_USB_PATH=%s", ci->usb_path);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* TODO: Configuration; Altsetting */</span><br><span style="color: hsl(120, 100%, 40%);">+ env[i++] = talloc_asprintf(env, "REMSIM_USB_INTERFACE=%u", bc->cfg->usb.if_num);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return i;</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%);">+/* FIXME: This must be cleaned up */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct osmo_st2_transport _transp;</span><br><span style="color: hsl(120, 100%, 40%);">+static struct osmo_st2_slot _slot = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .transp = &_transp,</span><br><span style="color: hsl(120, 100%, 40%);">+ .slot_nr = 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 client_user_main(struct bankd_client *bc)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct usb_interface_match _ifm, *ifm = &_ifm;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_st2_transport *transp;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_st2_cardem_inst *ci;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct client_config *cfg = bc->cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc, i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = osmo_libusb_init(NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stderr, "libusb initialization failed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return rc;</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%);">+ ci = talloc_zero(bc, struct osmo_st2_cardem_inst);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ci);</span><br><span style="color: hsl(120, 100%, 40%);">+ ci->slot = &_slot;</span><br><span style="color: hsl(120, 100%, 40%);">+ transp = ci->slot->transp;</span><br><span style="color: hsl(120, 100%, 40%);">+ ci->priv = bc;</span><br><span style="color: hsl(120, 100%, 40%);">+ bc->cardem = ci;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ifm->vendor = cfg->usb.vendor_id;</span><br><span style="color: hsl(120, 100%, 40%);">+ ifm->product = cfg->usb.product_id;</span><br><span style="color: hsl(120, 100%, 40%);">+ ifm->configuration = cfg->usb.config_id;</span><br><span style="color: hsl(120, 100%, 40%);">+ ifm->interface = cfg->usb.if_num;</span><br><span style="color: hsl(120, 100%, 40%);">+ ifm->altsetting = cfg->usb.altsetting;</span><br><span style="color: hsl(120, 100%, 40%);">+ ifm->addr = cfg->usb.addr;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cfg->usb.path)</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_strlcpy(ifm->path, cfg->usb.path, sizeof(ifm->path));</span><br><span style="color: hsl(120, 100%, 40%);">+ transp->usb_devh = osmo_libusb_open_claim_interface(NULL, NULL, ifm);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!transp->usb_devh) {</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stderr, "can't open USB device\n");</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%);">+ /* (re)determine the USB path of the opened device */</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(ci->usb_path);</span><br><span style="color: hsl(120, 100%, 40%);">+ ci->usb_path = osmo_libusb_dev_get_path_c(ci, libusb_get_device(transp->usb_devh));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = libusb_claim_interface(transp->usb_devh, cfg->usb.if_num);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stderr, "can't claim interface %d; rc=%d\n", cfg->usb.if_num, rc);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto close_exit;</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%);">+ rc = osmo_libusb_get_ep_addrs(transp->usb_devh, cfg->usb.if_num, &transp->usb_ep.out,</span><br><span style="color: hsl(120, 100%, 40%);">+ &transp->usb_ep.in, &transp->usb_ep.irq_in);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stderr, "can't obtain EP addrs; rc=%d\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto close_exit;</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%);">+ allocate_and_submit_irq(ci);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* submit multiple IN URB in order to work around OS#4409 */</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < 4; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+ allocate_and_submit_in(ci);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* request firmware to generate STATUS on IRQ endpoint */</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_st2_cardem_request_config(ci, CEMU_FEAT_F_STATUS_IRQ);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ while (1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_select_main(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%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+close_exit:</span><br><span style="color: hsl(120, 100%, 40%);">+ if (transp->usb_devh)</span><br><span style="color: hsl(120, 100%, 40%);">+ libusb_close(transp->usb_devh);</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_libusb_exit(NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/rspro_client_fsm.c b/src/rspro_client_fsm.c</span><br><span>index e55892c..36a3016 100644</span><br><span>--- a/src/rspro_client_fsm.c</span><br><span>+++ b/src/rspro_client_fsm.c</span><br><span>@@ -397,7 +397,7 @@</span><br><span> [SRVC_ST_INIT] = {</span><br><span> .name = "INIT",</span><br><span> .in_event_mask = 0, /* S(SRVC_E_ESTABLISH) via allstate */</span><br><span style="color: hsl(0, 100%, 40%);">- .out_state_mask = S(SRVC_ST_REESTABLISH),</span><br><span style="color: hsl(120, 100%, 40%);">+ .out_state_mask = S(SRVC_ST_INIT) | S(SRVC_ST_REESTABLISH),</span><br><span> .action = srvc_st_init,</span><br><span> },</span><br><span> [SRVC_ST_ESTABLISHED] = {</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-remsim/+/17361">change 17361</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/osmo-remsim/+/17361"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: osmo-remsim </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I44a430bc5674dea00ed72a0b28729ac8bcb4e022 </div>
<div style="display:none"> Gerrit-Change-Number: 17361 </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-CC: Jenkins Builder </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>