<p>laforge has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-remsim/+/17160">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">client: ifd_handler (PC/SC reader driver) as remsim-client<br><br>This adds a "libifd_remsim_client.so" PC/SC driver that can be<br>used to make normal PC/SC client programs (like pySim, sysmo-usim-tool,<br>osmo-sim-test, osmo-usim-auth, ...) talk to a remote SIM bank.<br><br>Change-Id: Ib8707c6e0e46407ab39a693adfec2fa71892f6ee<br>---<br>M src/client/Makefile.am<br>M src/client/client.h<br>A src/client/user_ifdhandler.c<br>3 files changed, 948 insertions(+), 0 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/60/17160/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 ac0d707..5b88c50 100644</span><br><span>--- a/src/client/Makefile.am</span><br><span>+++ b/src/client/Makefile.am</span><br><span>@@ -6,13 +6,24 @@</span><br><span> </span><br><span> bin_PROGRAMS = osmo-remsim-client-st2 osmo-remsim-client-shell</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+lib_LTLIBRARIES = libifd_remsim_client.la</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> osmo_remsim_client_shell_SOURCES = user_shell.c remsim_client_main.c \</span><br><span>                                    remsim_client.c ../rspro_client_fsm.c ../debug.c</span><br><span style="color: hsl(120, 100%, 40%);">+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> </span><br><span style="color: hsl(120, 100%, 40%);">+libifd_remsim_client_la_SOURCES = user_ifdhandler.c \</span><br><span style="color: hsl(120, 100%, 40%);">+                            remsim_client.c ../rspro_client_fsm.c ../debug.c</span><br><span style="color: hsl(120, 100%, 40%);">+libifd_remsim_client_la_LDFLAGS = -no-undefined</span><br><span style="color: hsl(120, 100%, 40%);">+libifd_remsim_client_la_CPPFLAGS = $(PCSC_CFLAGS)</span><br><span style="color: hsl(120, 100%, 40%);">+libifd_remsim_client_la_LIBADD = $(OSMOCORE_LIBS) $(OSMOGSM_LIBS) $(OSMOABIS_LIBS) \</span><br><span style="color: hsl(120, 100%, 40%);">+               $(top_builddir)/src/libosmo-rspro.la</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> osmo_remsim_client_st2_SOURCES = simtrace2-remsim_client.c \</span><br><span>                                  ../rspro_client_fsm.c ../debug.c</span><br><span style="color: hsl(120, 100%, 40%);">+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>                              $(USB_LIBS) $(OSMOSIM_LIBS) \</span><br><span>diff --git a/src/client/client.h b/src/client/client.h</span><br><span>index 80381fa..0761255 100644</span><br><span>--- a/src/client/client.h</span><br><span>+++ b/src/client/client.h</span><br><span>@@ -56,6 +56,7 @@</span><br><span> </span><br><span>        struct client_config *cfg;</span><br><span>   struct cardem_inst *cardem;</span><br><span style="color: hsl(120, 100%, 40%);">+   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>diff --git a/src/client/user_ifdhandler.c b/src/client/user_ifdhandler.c</span><br><span>new file mode 100644</span><br><span>index 0000000..677b781</span><br><span>--- /dev/null</span><br><span>+++ b/src/client/user_ifdhandler.c</span><br><span>@@ -0,0 +1,936 @@</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%);">+/* This is a remsim-client that provides an IFD_Handler (reader driver)</span><br><span style="color: hsl(120, 100%, 40%);">+ * towards the PC/SC services.  This effectively allows any local PC/SC client</span><br><span style="color: hsl(120, 100%, 40%);">+ * application to use a remote smartcard via osmo-remsim.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * In order to use this, you will need an /etc/reader.conf.d/osmo-remsim-client</span><br><span style="color: hsl(120, 100%, 40%);">+ * file with the following content:</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *    FRIENDLYNAME "osmo-remsim-client"</span><br><span style="color: hsl(120, 100%, 40%);">+ *         DEVICENAME   0:0:192.168.11.10:9998</span><br><span style="color: hsl(120, 100%, 40%);">+ * LIBPATH      /usr/lib/pcsc/drivers/serial/libifd_remsim_client.so</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Where  DEVICENAME has the following format:</span><br><span style="color: hsl(120, 100%, 40%);">+ *       [ClientID:[SlotNr:[ServerIp:[ServerPort]]]]</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 <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <unistd.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <pthread.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/select.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/application.h></span><br><span style="color: hsl(120, 100%, 40%);">+extern int osmo_ctx_init(const char *id);</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* ensure this current thread has an osmo_ctx and hence can use OTC_GLOBAL and friends */</span><br><span style="color: hsl(120, 100%, 40%);">+static void ensure_osmo_ctx(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!osmo_ctx)</span><br><span style="color: hsl(120, 100%, 40%);">+                osmo_ctx_init("");</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* inter-thread messages between IFD thread and remsim-client thread */</span><br><span style="color: hsl(120, 100%, 40%);">+enum itmsg_type {</span><br><span style="color: hsl(120, 100%, 40%);">+ ITMSG_TYPE_NONE,</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* card present? */</span><br><span style="color: hsl(120, 100%, 40%);">+   ITMSG_TYPE_CARD_PRES_REQ,</span><br><span style="color: hsl(120, 100%, 40%);">+     ITMSG_TYPE_CARD_PRES_RESP,</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* obtain ATR */</span><br><span style="color: hsl(120, 100%, 40%);">+      ITMSG_TYPE_ATR_REQ,</span><br><span style="color: hsl(120, 100%, 40%);">+   ITMSG_TYPE_ATR_RESP,</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* transceive APDU: Send C-APDU, receive R-APDU */</span><br><span style="color: hsl(120, 100%, 40%);">+    ITMSG_TYPE_C_APDU_REQ,</span><br><span style="color: hsl(120, 100%, 40%);">+        ITMSG_TYPE_R_APDU_IND,</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* power off the card */</span><br><span style="color: hsl(120, 100%, 40%);">+      ITMSG_TYPE_POWER_OFF_REQ,</span><br><span style="color: hsl(120, 100%, 40%);">+     ITMSG_TYPE_POWER_OFF_RESP,</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* power on the card */</span><br><span style="color: hsl(120, 100%, 40%);">+       ITMSG_TYPE_POWER_ON_REQ,</span><br><span style="color: hsl(120, 100%, 40%);">+      ITMSG_TYPE_POWER_ON_RESP,</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* reset the card */</span><br><span style="color: hsl(120, 100%, 40%);">+  ITMSG_TYPE_RESET_REQ,</span><br><span style="color: hsl(120, 100%, 40%);">+ ITMSG_TYPE_RESET_RESP,</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 itmsg {</span><br><span style="color: hsl(120, 100%, 40%);">+  enum itmsg_type type;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t status;        /* 0 == success */</span><br><span style="color: hsl(120, 100%, 40%);">+    uint16_t len;           /* length of 'data' */</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t data[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%);">+/* allocate + initialize msgb-wrapped inter-thread message (struct itmsg) */</span><br><span style="color: hsl(120, 100%, 40%);">+struct msgb *itmsg_alloc(enum itmsg_type type, uint16_t status, const uint8_t *data, uint16_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct msgb *msg = msgb_alloc_c(OTC_GLOBAL, sizeof(struct itmsg)+len, "Tx itmsg");</span><br><span style="color: hsl(120, 100%, 40%);">+  struct itmsg *im;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!msg)</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%);">+        im = (struct itmsg *) msgb_put(msg, sizeof(struct itmsg) + len);</span><br><span style="color: hsl(120, 100%, 40%);">+      im->type = type;</span><br><span style="color: hsl(120, 100%, 40%);">+   im->status = status;</span><br><span style="color: hsl(120, 100%, 40%);">+       im->len = len;</span><br><span style="color: hsl(120, 100%, 40%);">+     if (len)</span><br><span style="color: hsl(120, 100%, 40%);">+              memcpy(im->data, data, len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     return msg;</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%);">+ * remsim_client thread</span><br><span style="color: hsl(120, 100%, 40%);">+ ***********************************************************************/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void __thread *talloc_asn1_ctx;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct client_thread {</span><br><span style="color: hsl(120, 100%, 40%);">+   /* bankd client runningi inside this thread */</span><br><span style="color: hsl(120, 100%, 40%);">+        struct bankd_client *bc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* inter-thread osmo-fd; communication with IFD/PCSC thread */</span><br><span style="color: hsl(120, 100%, 40%);">+        struct osmo_fd it_ofd;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct llist_head it_msgq;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* ATR as received from remsim-bankd */</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t atr[ATR_SIZE_MAX];</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t atr_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%);">+/* configuration of client thread; passed in from IFD thread */</span><br><span style="color: hsl(120, 100%, 40%);">+struct client_thread_cfg {</span><br><span style="color: hsl(120, 100%, 40%);">+   const char *name;</span><br><span style="color: hsl(120, 100%, 40%);">+     const char *server_host;</span><br><span style="color: hsl(120, 100%, 40%);">+      int server_port;</span><br><span style="color: hsl(120, 100%, 40%);">+      int client_id;</span><br><span style="color: hsl(120, 100%, 40%);">+        int client_slot;</span><br><span style="color: hsl(120, 100%, 40%);">+      int it_sock_fd;</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%);">+/* enqueue a msgb (containg 'struct itmsg') towards the IFD-handler thread */</span><br><span style="color: hsl(120, 100%, 40%);">+static void enqueue_to_ifd(struct client_thread *ct, struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!msg)</span><br><span style="color: hsl(120, 100%, 40%);">+             return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     msgb_enqueue(&ct->it_msgq, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+       ct->it_ofd.when |= OSMO_FD_WRITE;</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 RSPRO messages from bank-daemon (SIM card)</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 bankd_handle_tpduCardToModem(struct bankd_client *bc, const RsproPDU_t *pdu)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  const struct TpduCardToModem *card2modem;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct client_thread *ct = bc->data;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct msgb *msg;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(pdu);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(RsproPDUchoice_PR_tpduCardToModem == pdu->msg.present);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      card2modem = &pdu->msg.choice.tpduCardToModem;</span><br><span style="color: hsl(120, 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%);">+     /* enqueue towards IFD thread */</span><br><span style="color: hsl(120, 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%);">+       OSMO_ASSERT(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+     enqueue_to_ifd(ct, 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 int bankd_handle_setAtrReq(struct bankd_client *bc, const RsproPDU_t *pdu)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct client_thread *ct = bc->data;</span><br><span style="color: hsl(120, 100%, 40%);">+       RsproPDU_t *resp;</span><br><span style="color: hsl(120, 100%, 40%);">+     unsigned int atr_len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(pdu);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(RsproPDUchoice_PR_setAtrReq == pdu->msg.present);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    DEBUGP(DMAIN, "SET_ATR: %s\n", osmo_hexdump(pdu->msg.choice.setAtrReq.atr.buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                pdu->msg.choice.setAtrReq.atr.size));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* store ATR in local data structure until somebody needs it */</span><br><span style="color: hsl(120, 100%, 40%);">+       atr_len = pdu->msg.choice.setAtrReq.atr.size;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (atr_len > sizeof(ct->atr))</span><br><span style="color: hsl(120, 100%, 40%);">+          atr_len = sizeof(ct->atr);</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(ct->atr, pdu->msg.choice.setAtrReq.atr.buf, atr_len);</span><br><span style="color: hsl(120, 100%, 40%);">+    ct->atr_len = atr_len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   resp = rspro_gen_SetAtrRes(ResultCode_ok);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!resp)</span><br><span style="color: hsl(120, 100%, 40%);">+            return -ENOMEM;</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%);">+</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 style="color: hsl(120, 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%);">+{</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 style="color: hsl(120, 100%, 40%);">+      switch (pdu->msg.present) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case RsproPDUchoice_PR_tpduCardToModem:</span><br><span style="color: hsl(120, 100%, 40%);">+               bankd_handle_tpduCardToModem(bc, pdu);</span><br><span style="color: hsl(120, 100%, 40%);">+                break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case RsproPDUchoice_PR_setAtrReq:</span><br><span style="color: hsl(120, 100%, 40%);">+             bankd_handle_setAtrReq(bc, pdu);</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%);">+     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 style="color: hsl(120, 100%, 40%);">+ * Incoming command from the user application</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%);">+/* handle a single msgb-wrapped 'struct itmsg' from the IFD-handler thread */</span><br><span style="color: hsl(120, 100%, 40%);">+static void handle_it_msg(struct client_thread *ct, struct itmsg *itmsg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct bankd_client *bc = ct->bc;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct msgb *tx = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+       RsproPDU_t *pdu;</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%);">+   bank_slot2rspro(&bslot, &ct->bc->bankd_slot);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (itmsg->type) {</span><br><span style="color: hsl(120, 100%, 40%);">+     case ITMSG_TYPE_CARD_PRES_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+                if (bc->bankd_conn.fi->state == 2 /*SRVC_ST_CONNECTED*/)</span><br><span style="color: hsl(120, 100%, 40%);">+                        tx = itmsg_alloc(ITMSG_TYPE_CARD_PRES_RESP, 0, NULL, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+              else</span><br><span style="color: hsl(120, 100%, 40%);">+                  tx = itmsg_alloc(ITMSG_TYPE_CARD_PRES_RESP, 0xffff, NULL, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+         OSMO_ASSERT(tx);</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%);">+      case ITMSG_TYPE_ATR_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+              /* respond to IFD */</span><br><span style="color: hsl(120, 100%, 40%);">+          tx = itmsg_alloc(ITMSG_TYPE_ATR_RESP, 0, ct->atr, ct->atr_len);</span><br><span style="color: hsl(120, 100%, 40%);">+         OSMO_ASSERT(tx);</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%);">+      case ITMSG_TYPE_POWER_OFF_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+                pdu = rspro_gen_ClientSlotStatusInd(bc->srv_conn.clslot, &bslot,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                   true, false, false, true);</span><br><span style="color: hsl(120, 100%, 40%);">+                server_conn_send_rspro(&bc->bankd_conn, pdu);</span><br><span style="color: hsl(120, 100%, 40%);">+          /* respond to IFD */</span><br><span style="color: hsl(120, 100%, 40%);">+          tx = itmsg_alloc(ITMSG_TYPE_POWER_OFF_RESP, 0, NULL, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+              OSMO_ASSERT(tx);</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%);">+      case ITMSG_TYPE_POWER_ON_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+         pdu = rspro_gen_ClientSlotStatusInd(bc->srv_conn.clslot, &bslot,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                   false, true, true, true);</span><br><span style="color: hsl(120, 100%, 40%);">+         server_conn_send_rspro(&bc->bankd_conn, pdu);</span><br><span style="color: hsl(120, 100%, 40%);">+          /* respond to IFD */</span><br><span style="color: hsl(120, 100%, 40%);">+          tx = itmsg_alloc(ITMSG_TYPE_POWER_ON_RESP, 0, NULL, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+               OSMO_ASSERT(tx);</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%);">+      case ITMSG_TYPE_RESET_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+            /* reset the [remote] card */</span><br><span style="color: hsl(120, 100%, 40%);">+         pdu = rspro_gen_ClientSlotStatusInd(bc->srv_conn.clslot, &bslot,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                   true, true, true, true);</span><br><span style="color: hsl(120, 100%, 40%);">+          server_conn_send_rspro(&bc->bankd_conn, pdu);</span><br><span style="color: hsl(120, 100%, 40%);">+          /* and take it out of reset again */</span><br><span style="color: hsl(120, 100%, 40%);">+          pdu = rspro_gen_ClientSlotStatusInd(bc->srv_conn.clslot, &bslot,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                   false, true, true, true);</span><br><span style="color: hsl(120, 100%, 40%);">+         server_conn_send_rspro(&bc->bankd_conn, pdu);</span><br><span style="color: hsl(120, 100%, 40%);">+          /* respond to IFD */</span><br><span style="color: hsl(120, 100%, 40%);">+          tx = itmsg_alloc(ITMSG_TYPE_RESET_RESP, 0, NULL, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+          OSMO_ASSERT(tx);</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case ITMSG_TYPE_C_APDU_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+           if (!bc->srv_conn.clslot) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        LOGP(DMAIN, LOGL_ERROR, "Cannot send command; no client slot\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                   /* FIXME: Response? */</span><br><span style="color: hsl(120, 100%, 40%);">+                        return;</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%);">+           /* Send CMD APDU to [remote] card */</span><br><span style="color: hsl(120, 100%, 40%);">+          pdu = rspro_gen_TpduModem2Card(bc->srv_conn.clslot, &bslot, itmsg->data, itmsg->len);</span><br><span style="color: hsl(120, 100%, 40%);">+            server_conn_send_rspro(&bc->bankd_conn, pdu);</span><br><span style="color: hsl(120, 100%, 40%);">+          /* response will come in asynchronously */</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%);">+              LOGP(DMAIN, LOGL_ERROR, "Unknown inter-thread msg type %u\n", itmsg->type);</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%);">+   if (tx)</span><br><span style="color: hsl(120, 100%, 40%);">+               enqueue_to_ifd(ct, tx);</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%);">+/* call-back function for inter-thread socket */</span><br><span style="color: hsl(120, 100%, 40%);">+static int it_sock_fd_cb(struct osmo_fd *ofd, unsigned int what)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct client_thread *ct = ofd->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%);">+     if (what & OSMO_FD_READ) {</span><br><span style="color: hsl(120, 100%, 40%);">+                struct msgb *msg = msgb_alloc_c(OTC_GLOBAL, 1024, "Rx it_fd");</span><br><span style="color: hsl(120, 100%, 40%);">+              struct itmsg *itmsg;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                OSMO_ASSERT(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+             rc = read(ofd->fd, msg->tail, msgb_tailroom(msg));</span><br><span style="color: hsl(120, 100%, 40%);">+              if (rc <= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     LOGP(DMAIN, LOGL_ERROR, "Error reading from inter-thread fd: %d\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+                    pthread_exit(NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+             msgb_put(msg, rc);</span><br><span style="color: hsl(120, 100%, 40%);">+            itmsg = (struct itmsg *) msgb_data(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+              if (msgb_length(msg) < sizeof(*itmsg) ||</span><br><span style="color: hsl(120, 100%, 40%);">+               msgb_length(msg) < sizeof(*itmsg) + itmsg->len) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   LOGP(DMAIN, LOGL_ERROR, "Dropping short inter-thread message\n");</span><br><span style="color: hsl(120, 100%, 40%);">+           } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      handle_it_msg(ct, itmsg);</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+             msgb_free(msg);</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 (what & OSMO_FD_WRITE) {</span><br><span style="color: hsl(120, 100%, 40%);">+               struct msgb *msg = msgb_dequeue(&ct->it_msgq);</span><br><span style="color: hsl(120, 100%, 40%);">+         if (!msg) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   /* last message: disable write events */</span><br><span style="color: hsl(120, 100%, 40%);">+                      ofd->when &= ~OSMO_FD_WRITE;</span><br><span style="color: hsl(120, 100%, 40%);">+           } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      unsigned int len = msgb_length(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+                  rc = write(ofd->fd, msgb_data(msg), len);</span><br><span style="color: hsl(120, 100%, 40%);">+                  msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+                       if (rc < len) {</span><br><span style="color: hsl(120, 100%, 40%);">+                            LOGP(DMAIN, LOGL_ERROR, "Short write on inter-thread fd: %d < %d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                  rc, 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%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* release all resources allocated by thread */</span><br><span style="color: hsl(120, 100%, 40%);">+static void client_pthread_cleanup(void *arg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct client_thread *ct = arg;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     LOGP(DMAIN, LOGL_INFO, "Cleaning up remsim-client thread\n");</span><br><span style="color: hsl(120, 100%, 40%);">+       //FIXME remsim_client_destroy(ct->bc);</span><br><span style="color: hsl(120, 100%, 40%);">+     ct->bc = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+     msgb_queue_free(&ct->it_msgq);</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fd_unregister(&ct->it_ofd);</span><br><span style="color: hsl(120, 100%, 40%);">+       close(ct->it_ofd.fd);</span><br><span style="color: hsl(120, 100%, 40%);">+      ct->it_ofd.fd = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+        talloc_free(ct);</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 function of remsim-client pthread */</span><br><span style="color: hsl(120, 100%, 40%);">+static void *client_pthread_main(void *arg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct client_thread_cfg *cfg = arg;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct client_thread *ct;</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%);">+     osmo_select_init();</span><br><span style="color: hsl(120, 100%, 40%);">+   rc = osmo_ctx_init("client");</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%);">+       ct = talloc_zero(OTC_GLOBAL, struct client_thread);</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(ct);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!talloc_asn1_ctx)</span><br><span style="color: hsl(120, 100%, 40%);">+        talloc_asn1_ctx= talloc_named_const(ct, 0, "asn1");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        ct->bc = remsim_client_create(ct, cfg->name, "remsim_ifdhandler");</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_ASSERT(ct->bc);</span><br><span style="color: hsl(120, 100%, 40%);">+       ct->bc->data = ct;</span><br><span style="color: hsl(120, 100%, 40%);">+      remsim_client_set_clslot(ct->bc, cfg->client_id, cfg->client_slot);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (cfg->server_host)</span><br><span style="color: hsl(120, 100%, 40%);">+              ct->bc->srv_conn.server_host = (char *) 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%);">+              ct->bc->srv_conn.server_port = cfg->server_port;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   INIT_LLIST_HEAD(&ct->it_msgq);</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fd_setup(&ct->it_ofd, cfg->it_sock_fd, OSMO_FD_READ, &it_sock_fd_cb, ct, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+       osmo_fd_register(&ct->it_ofd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* ensure we get properly cleaned up if cancelled */</span><br><span style="color: hsl(120, 100%, 40%);">+  pthread_cleanup_push(client_pthread_cleanup, ct);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   osmo_fsm_inst_dispatch(ct->bc->srv_conn.fi, SRVC_E_ESTABLISH, NULL);</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%);">+   pthread_cleanup_pop(1);</span><br><span style="color: hsl(120, 100%, 40%);">+       return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/***********************************************************************</span><br><span style="color: hsl(120, 100%, 40%);">+ * PC/SC ifd_handler API functions</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 <ifdhandler.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <debuglog.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <sys/types.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <sys/socket.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct value_string ifd_status_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_VALUE_STRING(IFD_SUCCESS),</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_VALUE_STRING(IFD_ERROR_TAG),</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_VALUE_STRING(IFD_ERROR_SET_FAILURE),</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_VALUE_STRING(IFD_ERROR_VALUE_READ_ONLY),</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_VALUE_STRING(IFD_ERROR_PTS_FAILURE),</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_VALUE_STRING(IFD_ERROR_NOT_SUPPORTED),</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_VALUE_STRING(IFD_PROTOCOL_NOT_SUPPORTED),</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_VALUE_STRING(IFD_ERROR_POWER_ACTION),</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_VALUE_STRING(IFD_ERROR_SWALLOW),</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_VALUE_STRING(IFD_ERROR_EJECT),</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_VALUE_STRING(IFD_ERROR_CONFISCATE),</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_VALUE_STRING(IFD_COMMUNICATION_ERROR),</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_VALUE_STRING(IFD_RESPONSE_TIMEOUT),</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_VALUE_STRING(IFD_NOT_SUPPORTED),</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_VALUE_STRING(IFD_ICC_PRESENT),</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_VALUE_STRING(IFD_ICC_NOT_PRESENT),</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_VALUE_STRING(IFD_NO_SUCH_DEVICE),</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_VALUE_STRING(IFD_ERROR_INSUFFICIENT_BUFFER),</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 const struct value_string ifd_tag_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_VALUE_STRING(TAG_IFD_ATR),</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_VALUE_STRING(TAG_IFD_SLOTNUM),</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_VALUE_STRING(TAG_IFD_SLOT_THREAD_SAFE),</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_VALUE_STRING(TAG_IFD_THREAD_SAFE),</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_VALUE_STRING(TAG_IFD_SLOTS_NUMBER),</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_VALUE_STRING(TAG_IFD_SIMULTANEOUS_ACCESS),</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_VALUE_STRING(TAG_IFD_POLLING_THREAD),</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_VALUE_STRING(TAG_IFD_POLLING_THREAD_KILLABLE),</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_VALUE_STRING(TAG_IFD_STOP_POLLING_THREAD),</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_VALUE_STRING(TAG_IFD_POLLING_THREAD_WITH_TIMEOUT),</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%);">+#define LOG_EXIT(Lun, r) \</span><br><span style="color: hsl(120, 100%, 40%);">+ Log4(r == IFD_SUCCESS || r == IFD_ICC_NOT_PRESENT ? PCSC_LOG_DEBUG : PCSC_LOG_ERROR, \</span><br><span style="color: hsl(120, 100%, 40%);">+             "%s(0x%08lx) => %s\n", __func__, Lun, get_value_string(ifd_status_names, r))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define LOG_EXITF(Lun, r, fmt, args...) \</span><br><span style="color: hsl(120, 100%, 40%);">+   Log5(r == IFD_SUCCESS ? PCSC_LOG_DEBUG : PCSC_LOG_ERROR, \</span><br><span style="color: hsl(120, 100%, 40%);">+         "%s(0x%08lx) "fmt" => %s\n", __func__, Lun, ## args, get_value_string(ifd_status_names, r))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* IFD side handle for a remsim-client [thread] */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ifd_client {</span><br><span style="color: hsl(120, 100%, 40%);">+    /* the client pthread itself */</span><br><span style="color: hsl(120, 100%, 40%);">+       pthread_t pthread;</span><br><span style="color: hsl(120, 100%, 40%);">+    /* socket to talk to thread */</span><br><span style="color: hsl(120, 100%, 40%);">+        int it_fd;</span><br><span style="color: hsl(120, 100%, 40%);">+    /* configuration passed into the thread */</span><br><span style="color: hsl(120, 100%, 40%);">+    struct client_thread_cfg cfg;</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 msgb *ifd_xceive_client(struct ifd_client *ic, struct msgb *tx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *rx = msgb_alloc_c(OTC_GLOBAL, 1024, "ifd_rx itmsg");</span><br><span style="color: hsl(120, 100%, 40%);">+   struct itmsg *rx_it;</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%);">+     rc = write(ic->it_fd, msgb_data(tx), msgb_length(tx));</span><br><span style="color: hsl(120, 100%, 40%);">+     msgb_free(tx);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (rc < msgb_length(tx)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                Log2(PCSC_LOG_ERROR, "Short write IFD->client thread: %d\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+                msgb_free(rx);</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%);">+     rc = read(ic->it_fd, rx->tail, msgb_tailroom(rx));</span><br><span style="color: hsl(120, 100%, 40%);">+      if (rc <= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+             Log2(PCSC_LOG_ERROR, "Short read IFD<-client thread: %d\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+         msgb_free(rx);</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%);">+     msgb_put(rx, rc);</span><br><span style="color: hsl(120, 100%, 40%);">+     rx_it = (struct itmsg *) msgb_data(rx);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (msgb_length(rx) < sizeof(*rx_it) + rx_it->len) {</span><br><span style="color: hsl(120, 100%, 40%);">+            Log2(PCSC_LOG_ERROR, "Short itmsg IFD<-client thread: %d\n", msgb_length(rx));</span><br><span style="color: hsl(120, 100%, 40%);">+           msgb_free(rx);</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%);">+     return rx;</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%);">+/* function called on IFD side to create socketpair + start remsim-client thread */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ifd_client *create_ifd_client(const struct client_thread_cfg *cfg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ifd_client *ic = talloc_zero(OTC_GLOBAL, struct ifd_client);</span><br><span style="color: hsl(120, 100%, 40%);">+   int sp[2];</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%);">+     /* copy over configuration */</span><br><span style="color: hsl(120, 100%, 40%);">+ ic->cfg = *cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* create socket pair for communication between threads */</span><br><span style="color: hsl(120, 100%, 40%);">+    rc = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sp);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (rc != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                talloc_free(ic);</span><br><span style="color: hsl(120, 100%, 40%);">+              return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ic->it_fd = sp[0];</span><br><span style="color: hsl(120, 100%, 40%);">+ ic->cfg.it_sock_fd = sp[1];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* start the thread */</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = pthread_create(&ic->pthread, NULL, client_pthread_main, &ic->cfg);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                Log1(PCSC_LOG_ERROR, "Error creating remsim-client pthread\n");</span><br><span style="color: hsl(120, 100%, 40%);">+             close(sp[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+         close(sp[1]);</span><br><span style="color: hsl(120, 100%, 40%);">+         talloc_free(ic);</span><br><span style="color: hsl(120, 100%, 40%);">+              return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return ic;</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%);">+/* function called on IFD side to destroy (terminate) remsim-client thread */</span><br><span style="color: hsl(120, 100%, 40%);">+static void destroy_ifd_client(struct ifd_client *ic)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!ic)</span><br><span style="color: hsl(120, 100%, 40%);">+              return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     pthread_cancel(ic->pthread);</span><br><span style="color: hsl(120, 100%, 40%);">+       pthread_join(ic->pthread, 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%);">+#define MAX_SLOTS     256</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ifd_client *ifd_client[MAX_SLOTS];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define LUN2SLOT(lun) ((lun) & 0xffff)</span><br><span style="color: hsl(120, 100%, 40%);">+#define LUN2RDR(lun) ((lun) >> 16)</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%);">+RESPONSECODE IFDHCreateChannel(DWORD Lun, DWORD Channel)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        return IFD_COMMUNICATION_ERROR;</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%);">+RESPONSECODE IFDHCreateChannelByName(DWORD Lun, LPSTR DeviceName)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ifd_client *ic;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct client_thread_cfg cfg = {</span><br><span style="color: hsl(120, 100%, 40%);">+              .name = "fixme-name",</span><br><span style="color: hsl(120, 100%, 40%);">+               .server_host = "127.0.0.1",</span><br><span style="color: hsl(120, 100%, 40%);">+         .server_port = -1,</span><br><span style="color: hsl(120, 100%, 40%);">+            .client_id = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+               .client_slot = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+     };</span><br><span style="color: hsl(120, 100%, 40%);">+    char *r, *client_id, *slot_nr, *host, *port;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (LUN2RDR(Lun) != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                return IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (LUN2SLOT(Lun) >= ARRAY_SIZE(ifd_client))</span><br><span style="color: hsl(120, 100%, 40%);">+               return IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  ensure_osmo_ctx();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  client_id = strtok_r(DeviceName, ":", &r);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!client_id)</span><br><span style="color: hsl(120, 100%, 40%);">+               goto end_parse;</span><br><span style="color: hsl(120, 100%, 40%);">+       cfg.client_id = atoi(client_id);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    slot_nr = strtok_r(NULL, ":", &r);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!slot_nr)</span><br><span style="color: hsl(120, 100%, 40%);">+         goto end_parse;</span><br><span style="color: hsl(120, 100%, 40%);">+       cfg.client_slot = atoi(slot_nr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    host = strtok_r(NULL, ":", &r);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!host)</span><br><span style="color: hsl(120, 100%, 40%);">+            goto end_parse;</span><br><span style="color: hsl(120, 100%, 40%);">+       cfg.server_host = strdup(host);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     port = strtok_r(NULL, ":", &r);</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg.server_port = atoi(port);</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%);">+end_parse:</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DMAIN, LOGL_NOTICE, "remsim-client C%d:%d bankd=%s:%d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+              cfg.client_id, cfg.client_slot, cfg.server_host, cfg.server_port);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  ic = create_ifd_client(&cfg);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (ic) {</span><br><span style="color: hsl(120, 100%, 40%);">+             ifd_client[LUN2SLOT(Lun)] = ic;</span><br><span style="color: hsl(120, 100%, 40%);">+               return IFD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+   } else</span><br><span style="color: hsl(120, 100%, 40%);">+                return IFD_COMMUNICATION_ERROR;</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%);">+RESPONSECODE IFDHControl(DWORD Lun, DWORD dwControlCode, PUCHAR TxBuffer, DWORD TxLength,</span><br><span style="color: hsl(120, 100%, 40%);">+                        PUCHAR RxBuffer, DWORD RxLength, LPDWORD pdwBytesReturned)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        RESPONSECODE r = IFD_COMMUNICATION_ERROR;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ensure_osmo_ctx();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (LUN2RDR(Lun) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              r = IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+               goto err;</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 (LUN2SLOT(Lun) >= ARRAY_SIZE(ifd_client)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             r = IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+               goto err;</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 (pdwBytesReturned)</span><br><span style="color: hsl(120, 100%, 40%);">+         *pdwBytesReturned = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      r = IFD_ERROR_NOT_SUPPORTED;</span><br><span style="color: hsl(120, 100%, 40%);">+err:</span><br><span style="color: hsl(120, 100%, 40%);">+    LOG_EXIT(Lun, r);</span><br><span style="color: hsl(120, 100%, 40%);">+     return r;</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%);">+RESPONSECODE IFDHCloseChannel(DWORD Lun)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   RESPONSECODE r = IFD_COMMUNICATION_ERROR;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ensure_osmo_ctx();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (LUN2RDR(Lun) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              r = IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+               goto err;</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 (LUN2SLOT(Lun) >= ARRAY_SIZE(ifd_client)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             r = IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+               goto err;</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%);">+   destroy_ifd_client(ifd_client[LUN2SLOT(Lun)]);</span><br><span style="color: hsl(120, 100%, 40%);">+        ifd_client[LUN2SLOT(Lun)] = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   r = IFD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+err:</span><br><span style="color: hsl(120, 100%, 40%);">+        LOG_EXIT(Lun, r);</span><br><span style="color: hsl(120, 100%, 40%);">+     return r;</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%);">+RESPONSECODE IFDHGetCapabilities(DWORD Lun, DWORD Tag, PDWORD Length, PUCHAR Value)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        RESPONSECODE r = IFD_COMMUNICATION_ERROR;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ifd_client *ic;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct msgb *rx, *tx;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct itmsg *rx_it;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        ensure_osmo_ctx();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (LUN2RDR(Lun) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              r = IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+               goto err;</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 (LUN2SLOT(Lun) >= ARRAY_SIZE(ifd_client)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             r = IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+               goto err;</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%);">+   ic = ifd_client[LUN2SLOT(Lun)];</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!ic) {</span><br><span style="color: hsl(120, 100%, 40%);">+            r = IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+               goto err;</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 (!Length || !Value)</span><br><span style="color: hsl(120, 100%, 40%);">+                goto err;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   switch (Tag) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case TAG_IFD_ATR:</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Return the ATR and its size */</span><br><span style="color: hsl(120, 100%, 40%);">+             tx = itmsg_alloc(ITMSG_TYPE_ATR_REQ, 0, NULL, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+             OSMO_ASSERT(tx);</span><br><span style="color: hsl(120, 100%, 40%);">+              rx = ifd_xceive_client(ic, tx);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (!rx) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    r = IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+                       goto err;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+             rx_it = (struct itmsg *)msgb_data(rx);</span><br><span style="color: hsl(120, 100%, 40%);">+                if (*Length > rx_it->len)</span><br><span style="color: hsl(120, 100%, 40%);">+                       *Length = rx_it->len;</span><br><span style="color: hsl(120, 100%, 40%);">+              memcpy(Value, rx_it->data, *Length);</span><br><span style="color: hsl(120, 100%, 40%);">+               msgb_free(rx);</span><br><span style="color: hsl(120, 100%, 40%);">+                break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case TAG_IFD_SIMULTANEOUS_ACCESS:</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Return the number of sessions (readers) the driver</span><br><span style="color: hsl(120, 100%, 40%);">+          * can handle in Value[0]. This is used for multiple</span><br><span style="color: hsl(120, 100%, 40%);">+           * readers sharing the same driver. */</span><br><span style="color: hsl(120, 100%, 40%);">+                if (*Length < 1)</span><br><span style="color: hsl(120, 100%, 40%);">+                   goto err;</span><br><span style="color: hsl(120, 100%, 40%);">+             *Value = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+           *Length = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+          break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case TAG_IFD_SLOTS_NUMBER:</span><br><span style="color: hsl(120, 100%, 40%);">+            /* Return the number of slots in this reader in Value[0] */</span><br><span style="color: hsl(120, 100%, 40%);">+           if (*Length < 1)</span><br><span style="color: hsl(120, 100%, 40%);">+                   goto err;</span><br><span style="color: hsl(120, 100%, 40%);">+             *Value = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+           *Length = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+          break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case TAG_IFD_THREAD_SAFE:</span><br><span style="color: hsl(120, 100%, 40%);">+             /* If the driver supports more than one reader (see</span><br><span style="color: hsl(120, 100%, 40%);">+            * TAG_IFD_SIMULTANEOUS_ACCESS above) this tag indicates</span><br><span style="color: hsl(120, 100%, 40%);">+               * if the driver supports access to multiple readers at</span><br><span style="color: hsl(120, 100%, 40%);">+                * the same time.  */</span><br><span style="color: hsl(120, 100%, 40%);">+         if (*Length < 1)</span><br><span style="color: hsl(120, 100%, 40%);">+                   goto err;</span><br><span style="color: hsl(120, 100%, 40%);">+             *Value = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+           *Length = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+          break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case TAG_IFD_SLOT_THREAD_SAFE:</span><br><span style="color: hsl(120, 100%, 40%);">+                /* If the reader has more than one slot (see</span><br><span style="color: hsl(120, 100%, 40%);">+           * TAG_IFD_SLOTS_NUMBER above) this tag indicates if the</span><br><span style="color: hsl(120, 100%, 40%);">+               * driver supports access to multiple slots of the same</span><br><span style="color: hsl(120, 100%, 40%);">+                * reader at the same time. */</span><br><span style="color: hsl(120, 100%, 40%);">+                if (*Length < 1)</span><br><span style="color: hsl(120, 100%, 40%);">+                   goto err;</span><br><span style="color: hsl(120, 100%, 40%);">+             *Value = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+           *Length = 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%);">+              r = IFD_ERROR_TAG;</span><br><span style="color: hsl(120, 100%, 40%);">+            goto err;</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%);">+   r = IFD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+err:</span><br><span style="color: hsl(120, 100%, 40%);">+      if (r != IFD_SUCCESS && Length)</span><br><span style="color: hsl(120, 100%, 40%);">+               *Length = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        LOG_EXITF(Lun, r, "%s", get_value_string(ifd_tag_names, Tag));</span><br><span style="color: hsl(120, 100%, 40%);">+      return r;</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%);">+RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag, DWORD Length, PUCHAR Value)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ ensure_osmo_ctx();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (LUN2RDR(Lun) != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                return IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (LUN2SLOT(Lun) >= ARRAY_SIZE(ifd_client))</span><br><span style="color: hsl(120, 100%, 40%);">+               return IFD_NO_SUCH_DEVICE;</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%);">+        LOG_EXIT(Lun, IFD_NOT_SUPPORTED);</span><br><span style="color: hsl(120, 100%, 40%);">+     return IFD_NOT_SUPPORTED;</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%);">+RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol, UCHAR Flags, UCHAR PTS1,</span><br><span style="color: hsl(120, 100%, 40%);">+                                    UCHAR PTS2, UCHAR PTS3)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    ensure_osmo_ctx();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (LUN2RDR(Lun) != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                return IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (LUN2SLOT(Lun) >= ARRAY_SIZE(ifd_client))</span><br><span style="color: hsl(120, 100%, 40%);">+               return IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  LOG_EXIT(Lun, IFD_SUCCESS);</span><br><span style="color: hsl(120, 100%, 40%);">+   return IFD_SUCCESS;</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%);">+RESPONSECODE IFDHPowerICC(DWORD Lun, DWORD Action, PUCHAR Atr, PDWORD AtrLength)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ RESPONSECODE r = IFD_COMMUNICATION_ERROR;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ifd_client *ic;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct msgb *rx, *tx;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       ensure_osmo_ctx();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (LUN2RDR(Lun) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              r = IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+               goto err;</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 (LUN2SLOT(Lun) >= ARRAY_SIZE(ifd_client)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             r = IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+               goto err;</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%);">+   ic = ifd_client[LUN2SLOT(Lun)];</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!ic) {</span><br><span style="color: hsl(120, 100%, 40%);">+            r = IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+               goto err;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   switch (Action) {</span><br><span style="color: hsl(120, 100%, 40%);">+     case IFD_POWER_DOWN:</span><br><span style="color: hsl(120, 100%, 40%);">+          tx = itmsg_alloc(ITMSG_TYPE_POWER_OFF_REQ, 0, NULL, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+               break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case IFD_POWER_UP:</span><br><span style="color: hsl(120, 100%, 40%);">+            tx = itmsg_alloc(ITMSG_TYPE_POWER_ON_REQ, 0, NULL, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case IFD_RESET:</span><br><span style="color: hsl(120, 100%, 40%);">+               tx = itmsg_alloc(ITMSG_TYPE_RESET_REQ, 0, NULL, 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%);">+              r = IFD_NOT_SUPPORTED;</span><br><span style="color: hsl(120, 100%, 40%);">+                goto err;</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%);">+   rx = ifd_xceive_client(ic, tx);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!rx) {</span><br><span style="color: hsl(120, 100%, 40%);">+            r = IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+               goto err;</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%);">+   r = IFD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+      msgb_free(rx);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+err:</span><br><span style="color: hsl(120, 100%, 40%);">+        if (r != IFD_SUCCESS && AtrLength)</span><br><span style="color: hsl(120, 100%, 40%);">+            *AtrLength = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       else</span><br><span style="color: hsl(120, 100%, 40%);">+          r = IFDHGetCapabilities(Lun, TAG_IFD_ATR, AtrLength, Atr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  LOG_EXIT(Lun, r);</span><br><span style="color: hsl(120, 100%, 40%);">+     return r;</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%);">+RESPONSECODE IFDHTransmitToICC(DWORD Lun, SCARD_IO_HEADER SendPci, PUCHAR TxBuffer,</span><br><span style="color: hsl(120, 100%, 40%);">+                          DWORD TxLength, PUCHAR RxBuffer, PDWORD RxLength,</span><br><span style="color: hsl(120, 100%, 40%);">+                             PSCARD_IO_HEADER RecvPci)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   RESPONSECODE r = IFD_COMMUNICATION_ERROR;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ifd_client *ic;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct msgb *rx, *tx;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct itmsg *rx_it;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        ensure_osmo_ctx();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (LUN2RDR(Lun) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              r = IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+               goto err;</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 (LUN2SLOT(Lun) >= ARRAY_SIZE(ifd_client)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             r = IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+               goto err;</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%);">+   ic = ifd_client[LUN2SLOT(Lun)];</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!ic) {</span><br><span style="color: hsl(120, 100%, 40%);">+            r = IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+               goto err;</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%);">+   tx = itmsg_alloc(ITMSG_TYPE_C_APDU_REQ, 0, TxBuffer, TxLength);</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(tx);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* transmit C-APDU to remote reader + blocking wait for response from peer */</span><br><span style="color: hsl(120, 100%, 40%);">+ rx = ifd_xceive_client(ic, tx);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!rx) {</span><br><span style="color: hsl(120, 100%, 40%);">+            r = IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+               goto err;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     rx_it = (struct itmsg *) msgb_data(rx);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (*RxLength > rx_it->len)</span><br><span style="color: hsl(120, 100%, 40%);">+             *RxLength = rx_it->len;</span><br><span style="color: hsl(120, 100%, 40%);">+    memcpy(RxBuffer, rx_it->data, *RxLength);</span><br><span style="color: hsl(120, 100%, 40%);">+  msgb_free(rx);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      r = IFD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+err:</span><br><span style="color: hsl(120, 100%, 40%);">+        if (r != IFD_SUCCESS && RxLength)</span><br><span style="color: hsl(120, 100%, 40%);">+             *RxLength = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      LOG_EXIT(Lun, r);</span><br><span style="color: hsl(120, 100%, 40%);">+     return r;</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%);">+RESPONSECODE IFDHICCPresence(DWORD Lun)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    RESPONSECODE r = IFD_COMMUNICATION_ERROR;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ifd_client *ic;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct msgb *rx, *tx;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct itmsg *rx_it;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        ensure_osmo_ctx();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (LUN2RDR(Lun) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              r = IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+               goto err;</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 (LUN2SLOT(Lun) >= ARRAY_SIZE(ifd_client)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             r = IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+               goto err;</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%);">+   ic = ifd_client[LUN2SLOT(Lun)];</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!ic) {</span><br><span style="color: hsl(120, 100%, 40%);">+            r = IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+               goto err;</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%);">+   tx = itmsg_alloc(ITMSG_TYPE_CARD_PRES_REQ, 0, NULL, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(tx);</span><br><span style="color: hsl(120, 100%, 40%);">+      rx = ifd_xceive_client(ic, tx);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!rx) {</span><br><span style="color: hsl(120, 100%, 40%);">+            r = IFD_NO_SUCH_DEVICE;</span><br><span style="color: hsl(120, 100%, 40%);">+               goto err;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     rx_it = (struct itmsg *) msgb_data(rx);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (rx_it->status == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+            r = IFD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+      else</span><br><span style="color: hsl(120, 100%, 40%);">+          r = IFD_ICC_NOT_PRESENT;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+err:</span><br><span style="color: hsl(120, 100%, 40%);">+      LOG_EXIT(Lun, r);</span><br><span style="color: hsl(120, 100%, 40%);">+     return r;</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_ifd(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     void *g_tall_ctx = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+      ensure_osmo_ctx();</span><br><span style="color: hsl(120, 100%, 40%);">+    osmo_init_logging2(g_tall_ctx, &log_info);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-remsim/+/17160">change 17160</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/+/17160"/><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: Ib8707c6e0e46407ab39a693adfec2fa71892f6ee </div>
<div style="display:none"> Gerrit-Change-Number: 17160 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>