<p>Vadim Yanitskiy has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/12441">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">layer23/sap_interface.c: reimplement SAP interface<br><br>Change-Id: I77bb108615bb2c94c441568f195b04e0a5421643<br>---<br>M src/host/layer23/include/osmocom/bb/common/Makefile.am<br>M src/host/layer23/include/osmocom/bb/common/osmocom_data.h<br>A src/host/layer23/include/osmocom/bb/common/sap_fsm.h<br>M src/host/layer23/include/osmocom/bb/common/sap_interface.h<br>A src/host/layer23/include/osmocom/bb/common/sap_proto.h<br>M src/host/layer23/include/osmocom/bb/mobile/subscriber.h<br>M src/host/layer23/src/common/Makefile.am<br>A src/host/layer23/src/common/sap_fsm.c<br>M src/host/layer23/src/common/sap_interface.c<br>A src/host/layer23/src/common/sap_proto.c<br>M src/host/layer23/src/common/sim.c<br>M src/host/layer23/src/mobile/app_mobile.c<br>M src/host/layer23/src/mobile/subscriber.c<br>13 files changed, 1,342 insertions(+), 562 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/41/12441/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/host/layer23/include/osmocom/bb/common/Makefile.am b/src/host/layer23/include/osmocom/bb/common/Makefile.am</span><br><span>index cd3437e..d66be98 100644</span><br><span>--- a/src/host/layer23/include/osmocom/bb/common/Makefile.am</span><br><span>+++ b/src/host/layer23/include/osmocom/bb/common/Makefile.am</span><br><span>@@ -1,2 +1,3 @@</span><br><span> noinst_HEADERS = l1ctl.h l1l2_interface.h l23_app.h logging.h \</span><br><span style="color: hsl(0, 100%, 40%);">-          networks.h gps.h sysinfo.h osmocom_data.h utils.h</span><br><span style="color: hsl(120, 100%, 40%);">+             networks.h gps.h sysinfo.h osmocom_data.h utils.h \</span><br><span style="color: hsl(120, 100%, 40%);">+           sap_proto.h sap_fsm.h sap_interface.h</span><br><span>diff --git a/src/host/layer23/include/osmocom/bb/common/osmocom_data.h b/src/host/layer23/include/osmocom/bb/common/osmocom_data.h</span><br><span>index 0399f5f..9bbacd8 100644</span><br><span>--- a/src/host/layer23/include/osmocom/bb/common/osmocom_data.h</span><br><span>+++ b/src/host/layer23/include/osmocom/bb/common/osmocom_data.h</span><br><span>@@ -23,8 +23,17 @@</span><br><span> #include <osmocom/bb/common/l1ctl.h></span><br><span> </span><br><span> struct osmosap_entity {</span><br><span style="color: hsl(0, 100%, 40%);">-       uint8_t sap_state;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct osmo_fsm_inst *fi;</span><br><span>    uint16_t max_msg_size;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t card_status;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Optional (connection state) event call-backs */</span><br><span style="color: hsl(120, 100%, 40%);">+    sap_idle_cb_t idle_cb;</span><br><span style="color: hsl(120, 100%, 40%);">+        sap_rel_cb_t rel_cb;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Optional (ATR, APDU) event call-backs */</span><br><span style="color: hsl(120, 100%, 40%);">+   sap_apdu_cb_t apdu_cb;</span><br><span style="color: hsl(120, 100%, 40%);">+        sap_atr_cb_t atr_cb;</span><br><span> };</span><br><span> </span><br><span> struct osmol1_entity {</span><br><span>diff --git a/src/host/layer23/include/osmocom/bb/common/sap_fsm.h b/src/host/layer23/include/osmocom/bb/common/sap_fsm.h</span><br><span>new file mode 100644</span><br><span>index 0000000..797e023</span><br><span>--- /dev/null</span><br><span>+++ b/src/host/layer23/include/osmocom/bb/common/sap_fsm.h</span><br><span>@@ -0,0 +1,32 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bb/common/osmocom_data.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* How long should we wait for connection establishment */</span><br><span style="color: hsl(120, 100%, 40%);">+#define SAP_FSM_CONN_EST_TIMEOUT 5</span><br><span style="color: hsl(120, 100%, 40%);">+#define SAP_FSM_CONN_EST_T 0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* How long should we wait for connection release */</span><br><span style="color: hsl(120, 100%, 40%);">+#define SAP_FSM_CONN_REL_TIMEOUT 3</span><br><span style="color: hsl(120, 100%, 40%);">+#define SAP_FSM_CONN_REL_T 1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* How long should we wait for request to complete */</span><br><span style="color: hsl(120, 100%, 40%);">+#define SAP_FSM_PROC_REQ_TIMEOUT 5</span><br><span style="color: hsl(120, 100%, 40%);">+#define SAP_FSM_PROC_REQ_T 2</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum sap_fsm_state {</span><br><span style="color: hsl(120, 100%, 40%);">+   SAP_STATE_NOT_CONNECTED,</span><br><span style="color: hsl(120, 100%, 40%);">+      SAP_STATE_CONNECTING,</span><br><span style="color: hsl(120, 100%, 40%);">+ SAP_STATE_DISCONNECTING, /* Auxiliary state (not from specs) */</span><br><span style="color: hsl(120, 100%, 40%);">+       SAP_STATE_WAIT_FOR_CARD, /* Auxiliary state (not from specs) */</span><br><span style="color: hsl(120, 100%, 40%);">+       SAP_STATE_IDLE,</span><br><span style="color: hsl(120, 100%, 40%);">+       SAP_STATE_PROC_ATR_REQ,</span><br><span style="color: hsl(120, 100%, 40%);">+       SAP_STATE_PROC_APDU_REQ,</span><br><span style="color: hsl(120, 100%, 40%);">+      SAP_STATE_PROC_RESET_REQ,</span><br><span style="color: hsl(120, 100%, 40%);">+     SAP_STATE_PROC_STATUS_REQ,</span><br><span style="color: hsl(120, 100%, 40%);">+    SAP_STATE_PROC_SET_TP_REQ,</span><br><span style="color: hsl(120, 100%, 40%);">+    SAP_STATE_PROC_POWERON_REQ,</span><br><span style="color: hsl(120, 100%, 40%);">+   SAP_STATE_PROC_POWEROFF_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%);">+int sap_fsm_alloc(struct osmocom_ms *ms);</span><br><span>diff --git a/src/host/layer23/include/osmocom/bb/common/sap_interface.h b/src/host/layer23/include/osmocom/bb/common/sap_interface.h</span><br><span>index 78e3846..bde6822 100644</span><br><span>--- a/src/host/layer23/include/osmocom/bb/common/sap_interface.h</span><br><span>+++ b/src/host/layer23/include/osmocom/bb/common/sap_interface.h</span><br><span>@@ -1,98 +1,24 @@</span><br><span> #pragma once</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/msgb.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bb/common/osmocom_data.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+typedef int (*sap_idle_cb_t)(struct osmocom_ms *ms);</span><br><span style="color: hsl(120, 100%, 40%);">+typedef int (*sap_rel_cb_t)(struct osmocom_ms *ms);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+typedef int (*sap_apdu_cb_t)(struct osmocom_ms *ms, struct msgb *msg);</span><br><span style="color: hsl(120, 100%, 40%);">+typedef int (*sap_atr_cb_t)(struct osmocom_ms *ms,</span><br><span style="color: hsl(120, 100%, 40%);">+   const uint8_t *atr, uint16_t atr_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void sap_init(struct osmocom_ms *ms);</span><br><span> int sap_open(struct osmocom_ms *ms);</span><br><span> int sap_close(struct osmocom_ms *ms);</span><br><span style="color: hsl(0, 100%, 40%);">-int osmosap_send_apdu(struct osmocom_ms *ms, uint8_t *data, uint16_t length);</span><br><span style="color: hsl(0, 100%, 40%);">-int osmosap_init(struct osmocom_ms *ms);</span><br><span style="color: hsl(120, 100%, 40%);">+int _sap_close_sock(struct osmocom_ms *ms);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-enum osmosap_state {</span><br><span style="color: hsl(0, 100%, 40%);">-      SAP_SOCKET_ERROR,</span><br><span style="color: hsl(0, 100%, 40%);">-       SAP_NOT_CONNECTED,</span><br><span style="color: hsl(0, 100%, 40%);">-      SAP_IDLE,</span><br><span style="color: hsl(0, 100%, 40%);">-       SAP_CONNECTION_UNDER_NEGOTIATION,</span><br><span style="color: hsl(0, 100%, 40%);">-       SAP_PROCESSING_ATR_REQUEST,</span><br><span style="color: hsl(0, 100%, 40%);">-     SAP_PROCESSING_APDU_REQUEST</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(120, 100%, 40%);">+int sap_send_poweron_req(struct osmocom_ms *ms);</span><br><span style="color: hsl(120, 100%, 40%);">+int sap_send_poweroff_req(struct osmocom_ms *ms);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* Table 5.1: Message Overview */</span><br><span style="color: hsl(0, 100%, 40%);">-enum osmosap_msg_type {</span><br><span style="color: hsl(0, 100%, 40%);">-  SAP_CONNECT_REQ = 0x00,</span><br><span style="color: hsl(0, 100%, 40%);">- SAP_CONNECT_RESP = 0x01,</span><br><span style="color: hsl(0, 100%, 40%);">-        SAP_DISCONNECT_REQ = 0x02,</span><br><span style="color: hsl(0, 100%, 40%);">-      SAP_DISCONNECT_RESP = 0x03,</span><br><span style="color: hsl(0, 100%, 40%);">-     SAP_DISCONNECT_IND = 0x04,</span><br><span style="color: hsl(0, 100%, 40%);">-      SAP_TRANSFER_APDU_REQ = 0x05,</span><br><span style="color: hsl(0, 100%, 40%);">-   SAP_TRANSFER_APDU_RESP = 0x06,</span><br><span style="color: hsl(0, 100%, 40%);">-  SAP_TRANSFER_ATR_REQ = 0x07,</span><br><span style="color: hsl(0, 100%, 40%);">-    SAP_TRANSFER_ATR_RESP = 0x08,</span><br><span style="color: hsl(0, 100%, 40%);">-   SAP_POWER_SIM_OFF_REQ = 0x09,</span><br><span style="color: hsl(0, 100%, 40%);">-   SAP_POWER_SIM_OFF_RESP = 0x0A,</span><br><span style="color: hsl(0, 100%, 40%);">-  SAP_POWER_SIM_ON_REQ = 0x0B,</span><br><span style="color: hsl(0, 100%, 40%);">-    SAP_POWER_SIM_ON_RESP = 0x0C,</span><br><span style="color: hsl(0, 100%, 40%);">-   SAP_RESET_SIM_REQ = 0x0D,</span><br><span style="color: hsl(0, 100%, 40%);">-       SAP_RESET_SIM_RESP = 0x0E,</span><br><span style="color: hsl(0, 100%, 40%);">-      SAP_TRANSFER_CARD_READER_STATUS_REQ = 0x0F,</span><br><span style="color: hsl(0, 100%, 40%);">-     SAP_TRANSFER_CARD_READER_STATUS_RESP = 0x10,</span><br><span style="color: hsl(0, 100%, 40%);">-    SAP_STATUS_IND = 0x11,</span><br><span style="color: hsl(0, 100%, 40%);">-  SAP_ERROR_RESP = 0x12,</span><br><span style="color: hsl(0, 100%, 40%);">-  SAP_SET_TRANSPORT_PROTOCOL_REQ = 0x13,</span><br><span style="color: hsl(0, 100%, 40%);">-  SAP_SET_TRANSPORT_PROTOCOL_RESP = 0x14</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%);">-/* Table 5.15: List of Parameter IDs */</span><br><span style="color: hsl(0, 100%, 40%);">-enum osmosap_param_type {</span><br><span style="color: hsl(0, 100%, 40%);">-        SAP_MAX_MSG_SIZE = 0x00,</span><br><span style="color: hsl(0, 100%, 40%);">-        SAP_CONNECTION_STATUS = 0x01,</span><br><span style="color: hsl(0, 100%, 40%);">-   SAP_RESULT_CODE = 0x02,</span><br><span style="color: hsl(0, 100%, 40%);">- SAP_DISCONNECTION_TYPE = 0x03,</span><br><span style="color: hsl(0, 100%, 40%);">-  SAP_COMMAND_APDU = 0x04,</span><br><span style="color: hsl(0, 100%, 40%);">-        SAP_COMMAND_APDU_7816 = 0x10,</span><br><span style="color: hsl(0, 100%, 40%);">-   SAP_RESPONSE_APDU = 0x05,</span><br><span style="color: hsl(0, 100%, 40%);">-       SAP_ATR = 0x06,</span><br><span style="color: hsl(0, 100%, 40%);">- SAP_CARD_READER_STATUS = 0x07,</span><br><span style="color: hsl(0, 100%, 40%);">-  SAP_STATUS_CHANGE = 0x08,</span><br><span style="color: hsl(0, 100%, 40%);">-       SAP_TRANSPORT_PROTOCOL = 0x09</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%);">-/* Table 5.18: Possible values for ResultCode */</span><br><span style="color: hsl(0, 100%, 40%);">-enum sap_result_type {</span><br><span style="color: hsl(0, 100%, 40%);">-   SAP_RESULT_OK_REQ_PROC_CORR = 0x00,</span><br><span style="color: hsl(0, 100%, 40%);">-     SAP_RESULT_ERROR_NO_REASON = 0x01,</span><br><span style="color: hsl(0, 100%, 40%);">-      SAP_RESULT_ERROR_CARD_NOT_ACC = 0x02,</span><br><span style="color: hsl(0, 100%, 40%);">-   SAP_RESULT_ERROR_CARD_POWERED_OFF = 0x03,</span><br><span style="color: hsl(0, 100%, 40%);">-       SAP_RESULT_ERROR_CARD_REMOVED = 0x04,</span><br><span style="color: hsl(0, 100%, 40%);">-   SAP_RESULT_ERROR_CARD_POWERED_ON = 0x05,</span><br><span style="color: hsl(0, 100%, 40%);">-        SAP_RESULT_ERROR_DATA_UNAVAIL = 0x06,</span><br><span style="color: hsl(0, 100%, 40%);">-   SAP_RESULT_ERROR_NOT_SUPPORTED = 0x07,</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%);">-/* Table 5.19: Possible values for StatusChange */</span><br><span style="color: hsl(0, 100%, 40%);">-enum sap_status_chg_type {</span><br><span style="color: hsl(0, 100%, 40%);">-    SAP_STATUS_CHG_UNKNOWN_ERROR = 0x00,</span><br><span style="color: hsl(0, 100%, 40%);">-    SAP_STATUS_CHG_CARD_RESET = 0x01,</span><br><span style="color: hsl(0, 100%, 40%);">-       SAP_STATUS_CHG_CARD_NOT_ACC = 0x02,</span><br><span style="color: hsl(0, 100%, 40%);">-     SAP_STATUS_CHG_CARD_REMOVED = 0x03,</span><br><span style="color: hsl(0, 100%, 40%);">-     SAP_STATUS_CHG_CARD_INSERTED = 0x04,</span><br><span style="color: hsl(0, 100%, 40%);">-    SAP_STATUS_CHG_CARD_RECOVERED = 0x05,</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%);">-/* Table 5.16: Possible values for ConnectionStatus */</span><br><span style="color: hsl(0, 100%, 40%);">-enum sap_conn_status_type {</span><br><span style="color: hsl(0, 100%, 40%);">-        SAP_CONN_STATUS_OK_READY = 0x00,</span><br><span style="color: hsl(0, 100%, 40%);">-        SAP_CONN_STATUS_ERROR_CONN = 0x01,</span><br><span style="color: hsl(0, 100%, 40%);">-      SAP_CONN_STATUS_ERROR_MAX_MSG_SIZE = 0x02,</span><br><span style="color: hsl(0, 100%, 40%);">-      SAP_CONN_STATUS_ERROR_SMALL_MSG_SIZE = 0x03,</span><br><span style="color: hsl(0, 100%, 40%);">-    SAP_CONN_STATUS_OK_CALL = 0x04,</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%);">-struct sap_param {</span><br><span style="color: hsl(0, 100%, 40%);">-     uint8_t id;</span><br><span style="color: hsl(0, 100%, 40%);">-     uint16_t len;</span><br><span style="color: hsl(0, 100%, 40%);">-   uint8_t *value;</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%);">-struct sap_msg {</span><br><span style="color: hsl(0, 100%, 40%);">-       uint8_t id;</span><br><span style="color: hsl(0, 100%, 40%);">-     uint8_t num_params;</span><br><span style="color: hsl(0, 100%, 40%);">-     struct sap_param *params;</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(120, 100%, 40%);">+int sap_send_atr_req(struct osmocom_ms *ms);</span><br><span style="color: hsl(120, 100%, 40%);">+int sap_send_apdu(struct osmocom_ms *ms, uint8_t *apdu, uint16_t apdu_len);</span><br><span>diff --git a/src/host/layer23/include/osmocom/bb/common/sap_proto.h b/src/host/layer23/include/osmocom/bb/common/sap_proto.h</span><br><span>new file mode 100644</span><br><span>index 0000000..1c3b2d5</span><br><span>--- /dev/null</span><br><span>+++ b/src/host/layer23/include/osmocom/bb/common/sap_proto.h</span><br><span>@@ -0,0 +1,121 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+</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/msgb.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Table 5.1: Message Overview</span><br><span style="color: hsl(120, 100%, 40%);">+ * NOTE: messages are used as events for SAP FSM */</span><br><span style="color: hsl(120, 100%, 40%);">+enum sap_msg_type {</span><br><span style="color: hsl(120, 100%, 40%);">+        SAP_CONNECT_REQ = 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+       SAP_CONNECT_RESP = 0x01,</span><br><span style="color: hsl(120, 100%, 40%);">+      SAP_DISCONNECT_REQ = 0x02,</span><br><span style="color: hsl(120, 100%, 40%);">+    SAP_DISCONNECT_RESP = 0x03,</span><br><span style="color: hsl(120, 100%, 40%);">+   SAP_DISCONNECT_IND = 0x04,</span><br><span style="color: hsl(120, 100%, 40%);">+    SAP_TRANSFER_APDU_REQ = 0x05,</span><br><span style="color: hsl(120, 100%, 40%);">+ SAP_TRANSFER_APDU_RESP = 0x06,</span><br><span style="color: hsl(120, 100%, 40%);">+        SAP_TRANSFER_ATR_REQ = 0x07,</span><br><span style="color: hsl(120, 100%, 40%);">+  SAP_TRANSFER_ATR_RESP = 0x08,</span><br><span style="color: hsl(120, 100%, 40%);">+ SAP_POWER_SIM_OFF_REQ = 0x09,</span><br><span style="color: hsl(120, 100%, 40%);">+ SAP_POWER_SIM_OFF_RESP = 0x0A,</span><br><span style="color: hsl(120, 100%, 40%);">+        SAP_POWER_SIM_ON_REQ = 0x0B,</span><br><span style="color: hsl(120, 100%, 40%);">+  SAP_POWER_SIM_ON_RESP = 0x0C,</span><br><span style="color: hsl(120, 100%, 40%);">+ SAP_RESET_SIM_REQ = 0x0D,</span><br><span style="color: hsl(120, 100%, 40%);">+     SAP_RESET_SIM_RESP = 0x0E,</span><br><span style="color: hsl(120, 100%, 40%);">+    SAP_TRANSFER_CARD_READER_STATUS_REQ = 0x0F,</span><br><span style="color: hsl(120, 100%, 40%);">+   SAP_TRANSFER_CARD_READER_STATUS_RESP = 0x10,</span><br><span style="color: hsl(120, 100%, 40%);">+  SAP_STATUS_IND = 0x11,</span><br><span style="color: hsl(120, 100%, 40%);">+        SAP_ERROR_RESP = 0x12,</span><br><span style="color: hsl(120, 100%, 40%);">+        SAP_SET_TRANSPORT_PROTOCOL_REQ = 0x13,</span><br><span style="color: hsl(120, 100%, 40%);">+        SAP_SET_TRANSPORT_PROTOCOL_RESP = 0x14</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%);">+/* Table 5.15: List of Parameter IDs */</span><br><span style="color: hsl(120, 100%, 40%);">+enum sap_param_type {</span><br><span style="color: hsl(120, 100%, 40%);">+  SAP_MAX_MSG_SIZE = 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+      SAP_CONNECTION_STATUS = 0x01,</span><br><span style="color: hsl(120, 100%, 40%);">+ SAP_RESULT_CODE = 0x02,</span><br><span style="color: hsl(120, 100%, 40%);">+       SAP_DISCONNECTION_TYPE = 0x03,</span><br><span style="color: hsl(120, 100%, 40%);">+        SAP_COMMAND_APDU = 0x04,</span><br><span style="color: hsl(120, 100%, 40%);">+      SAP_COMMAND_APDU_7816 = 0x10,</span><br><span style="color: hsl(120, 100%, 40%);">+ SAP_RESPONSE_APDU = 0x05,</span><br><span style="color: hsl(120, 100%, 40%);">+     SAP_ATR = 0x06,</span><br><span style="color: hsl(120, 100%, 40%);">+       SAP_CARD_READER_STATUS = 0x07,</span><br><span style="color: hsl(120, 100%, 40%);">+        SAP_STATUS_CHANGE = 0x08,</span><br><span style="color: hsl(120, 100%, 40%);">+     SAP_TRANSPORT_PROTOCOL = 0x09</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%);">+/* Table 5.18: Possible values for ResultCode */</span><br><span style="color: hsl(120, 100%, 40%);">+enum sap_result_type {</span><br><span style="color: hsl(120, 100%, 40%);">+ SAP_RESULT_OK_REQ_PROC_CORR = 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+   SAP_RESULT_ERROR_NO_REASON = 0x01,</span><br><span style="color: hsl(120, 100%, 40%);">+    SAP_RESULT_ERROR_CARD_NOT_ACC = 0x02,</span><br><span style="color: hsl(120, 100%, 40%);">+ SAP_RESULT_ERROR_CARD_POWERED_OFF = 0x03,</span><br><span style="color: hsl(120, 100%, 40%);">+     SAP_RESULT_ERROR_CARD_REMOVED = 0x04,</span><br><span style="color: hsl(120, 100%, 40%);">+ SAP_RESULT_ERROR_CARD_POWERED_ON = 0x05,</span><br><span style="color: hsl(120, 100%, 40%);">+      SAP_RESULT_ERROR_DATA_UNAVAIL = 0x06,</span><br><span style="color: hsl(120, 100%, 40%);">+ SAP_RESULT_ERROR_NOT_SUPPORTED = 0x07,</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%);">+/* Table 5.19: Possible values for StatusChange */</span><br><span style="color: hsl(120, 100%, 40%);">+enum sap_card_status_type {</span><br><span style="color: hsl(120, 100%, 40%);">+ SAP_CARD_STATUS_UNKNOWN_ERROR = 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+ SAP_CARD_STATUS_CARD_RESET = 0x01,</span><br><span style="color: hsl(120, 100%, 40%);">+    SAP_CARD_STATUS_CARD_NOT_ACC = 0x02,</span><br><span style="color: hsl(120, 100%, 40%);">+  SAP_CARD_STATUS_CARD_REMOVED = 0x03,</span><br><span style="color: hsl(120, 100%, 40%);">+  SAP_CARD_STATUS_CARD_INSERTED = 0x04,</span><br><span style="color: hsl(120, 100%, 40%);">+ SAP_CARD_STATUS_CARD_RECOVERED = 0x05,</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%);">+/* Table 5.16: Possible values for ConnectionStatus */</span><br><span style="color: hsl(120, 100%, 40%);">+enum sap_conn_status_type {</span><br><span style="color: hsl(120, 100%, 40%);">+     SAP_CONN_STATUS_OK_READY = 0x00,</span><br><span style="color: hsl(120, 100%, 40%);">+      SAP_CONN_STATUS_ERROR_CONN = 0x01,</span><br><span style="color: hsl(120, 100%, 40%);">+    SAP_CONN_STATUS_ERROR_MAX_MSG_SIZE = 0x02,</span><br><span style="color: hsl(120, 100%, 40%);">+    SAP_CONN_STATUS_ERROR_SMALL_MSG_SIZE = 0x03,</span><br><span style="color: hsl(120, 100%, 40%);">+  SAP_CONN_STATUS_OK_CALL = 0x04,</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%);">+extern const struct value_string sap_param_names[];</span><br><span style="color: hsl(120, 100%, 40%);">+extern const struct value_string sap_msg_names[];</span><br><span style="color: hsl(120, 100%, 40%);">+extern const struct value_string sap_result_names[];</span><br><span style="color: hsl(120, 100%, 40%);">+extern const struct value_string sap_card_status_names[];</span><br><span style="color: hsl(120, 100%, 40%);">+extern const struct value_string sap_conn_status_names[];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Figure 5.2: Payload Coding */</span><br><span style="color: hsl(120, 100%, 40%);">+struct sap_param {</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Parameter ID, see \ref enum sap_param_type */</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t param_id;</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Reserved for further use (shall be set to 0x00) */</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t reserved[1];</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Parameter length */</span><br><span style="color: hsl(120, 100%, 40%);">+        uint16_t length;</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Parameter value (and optional padding) */</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t value[0];</span><br><span style="color: hsl(120, 100%, 40%);">+} __attribute__((packed));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Figure 5.1 Message Format */</span><br><span style="color: hsl(120, 100%, 40%);">+struct sap_message {</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Message ID, see \ref enum sap_msg_type */</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t msg_id;</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Number of parameters */</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t num_params;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Reserved for further use (shall be set to 0x00) */</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t reserved[2];</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Payload, see \ref struct sap_param */</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t payload[0];</span><br><span style="color: hsl(120, 100%, 40%);">+} __attribute__((packed));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define GSM_SAP_LENGTH 300</span><br><span style="color: hsl(120, 100%, 40%);">+#define GSM_SAP_HEADROOM 32</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct msgb *sap_msgb_alloc(uint8_t msg_id);</span><br><span style="color: hsl(120, 100%, 40%);">+const struct sap_message *sap_msg_parse(const uint8_t *buf, size_t buf_len);</span><br><span style="color: hsl(120, 100%, 40%);">+int sap_check_result_code(const struct sap_message *sap_msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void sap_msgb_add_param(struct msgb *msg,</span><br><span style="color: hsl(120, 100%, 40%);">+  enum sap_param_type param_type,</span><br><span style="color: hsl(120, 100%, 40%);">+       uint16_t param_len, uint8_t *param_value);</span><br><span style="color: hsl(120, 100%, 40%);">+struct sap_param *sap_get_param(const struct sap_message *sap_msg,</span><br><span style="color: hsl(120, 100%, 40%);">+        enum sap_param_type param_type, uint16_t *param_len);</span><br><span>diff --git a/src/host/layer23/include/osmocom/bb/mobile/subscriber.h b/src/host/layer23/include/osmocom/bb/mobile/subscriber.h</span><br><span>index c747af9..37b6db7 100644</span><br><span>--- a/src/host/layer23/include/osmocom/bb/mobile/subscriber.h</span><br><span>+++ b/src/host/layer23/include/osmocom/bb/mobile/subscriber.h</span><br><span>@@ -93,6 +93,7 @@</span><br><span> int gsm_subscr_sapcard(struct osmocom_ms *ms);</span><br><span> int gsm_subscr_remove_sapcard(struct osmocom_ms *ms);</span><br><span> int gsm_subscr_simcard(struct osmocom_ms *ms);</span><br><span style="color: hsl(120, 100%, 40%);">+int subscr_sim_request(struct osmocom_ms *ms);</span><br><span> void gsm_subscr_sim_pin(struct osmocom_ms *ms, char *pin1, char *pin2,</span><br><span>    int8_t mode);</span><br><span> int gsm_subscr_write_loci(struct osmocom_ms *ms);</span><br><span>diff --git a/src/host/layer23/src/common/Makefile.am b/src/host/layer23/src/common/Makefile.am</span><br><span>index b76094c..a8d9f7e 100644</span><br><span>--- a/src/host/layer23/src/common/Makefile.am</span><br><span>+++ b/src/host/layer23/src/common/Makefile.am</span><br><span>@@ -2,5 +2,5 @@</span><br><span> AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBGPS_CFLAGS)</span><br><span> </span><br><span> noinst_LIBRARIES = liblayer23.a</span><br><span style="color: hsl(0, 100%, 40%);">-liblayer23_a_SOURCES = l1ctl.c l1l2_interface.c sap_interface.c \</span><br><span style="color: hsl(120, 100%, 40%);">+liblayer23_a_SOURCES = l1ctl.c l1l2_interface.c sap_fsm.c sap_proto.c sap_interface.c \</span><br><span>      logging.c networks.c sim.c sysinfo.c gps.c l1ctl_lapdm_glue.c utils.c</span><br><span>diff --git a/src/host/layer23/src/common/sap_fsm.c b/src/host/layer23/src/common/sap_fsm.c</span><br><span>new file mode 100644</span><br><span>index 0000000..94a46a7</span><br><span>--- /dev/null</span><br><span>+++ b/src/host/layer23/src/common/sap_fsm.c</span><br><span>@@ -0,0 +1,679 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * SAP (SIM Access Profile) FSM definition</span><br><span style="color: hsl(120, 100%, 40%);">+ * based on Bluetooth SAP specification</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2018 by Vadim Yanitskiy <axilirator@gmail.com></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%);">+ * 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 <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <unistd.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <arpa/inet.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/socket.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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bb/common/osmocom_data.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bb/common/logging.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bb/common/sap_interface.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bb/common/sap_proto.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bb/common/sap_fsm.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Send encoded SAP message to the Server</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ms MS instance with active SAP connection</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] msg encoded SAP message buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns 0 in case of success, negative in case of error</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int sap_send_msgb(struct osmocom_ms *ms, struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</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 = osmo_wqueue_enqueue(&ms->sap_wq, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+             LOGP(DSAP, LOGL_ERROR, "Failed to enqueue SAP message\n");</span><br><span style="color: hsl(120, 100%, 40%);">+          msgb_free(msg);</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%);">+   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 void sap_fsm_tear_down(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 osmocom_ms *ms = (struct osmocom_ms *) fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Flush buffers, close socket */</span><br><span style="color: hsl(120, 100%, 40%);">+     _sap_close_sock(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Call release call-back (if present) */</span><br><span style="color: hsl(120, 100%, 40%);">+     if (ms->sap_entity.rel_cb)</span><br><span style="color: hsl(120, 100%, 40%);">+         ms->sap_entity.rel_cb(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Trigger self-destruction :/ */</span><br><span style="color: hsl(120, 100%, 40%);">+     osmo_fsm_inst_free(ms->sap_entity.fi);</span><br><span style="color: hsl(120, 100%, 40%);">+     ms->sap_entity.fi = 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 sap_fsm_connect(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 osmocom_ms *ms = (struct osmocom_ms *) fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct msgb *msg;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint16_t size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Section 5.1.1, CONNECT_REQ */</span><br><span style="color: hsl(120, 100%, 40%);">+      msg = sap_msgb_alloc(SAP_CONNECT_REQ);</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%);">+     /* Section 4.1.1, start MaxMsgSize negotiation */</span><br><span style="color: hsl(120, 100%, 40%);">+     size = htons(ms->sap_entity.max_msg_size);</span><br><span style="color: hsl(120, 100%, 40%);">+ sap_msgb_add_param(msg, SAP_MAX_MSG_SIZE,</span><br><span style="color: hsl(120, 100%, 40%);">+             sizeof(size), (uint8_t *) &size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       sap_send_msgb(ms, 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%);">+static void sap_negotiate_msg_size(struct osmosap_entity *sap,</span><br><span style="color: hsl(120, 100%, 40%);">+  const struct sap_message *sap_msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t size, param_len;</span><br><span style="color: hsl(120, 100%, 40%);">+     const char *cause = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct sap_param *param;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    param = sap_get_param(sap_msg, SAP_MAX_MSG_SIZE, &param_len);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!param) {</span><br><span style="color: hsl(120, 100%, 40%);">+         cause = "missing expected MaxMsgSize parameter";</span><br><span style="color: hsl(120, 100%, 40%);">+            goto error;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (param_len != sizeof(size)) {</span><br><span style="color: hsl(120, 100%, 40%);">+              cause = "MaxMsgSize parameter has wrong length";</span><br><span style="color: hsl(120, 100%, 40%);">+            goto 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%);">+   /* Parse MaxMsgSize suggested by server */</span><br><span style="color: hsl(120, 100%, 40%);">+    size = ntohs((uint16_t *) param->value);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (size > SAP_MAX_MSG_SIZE) {</span><br><span style="color: hsl(120, 100%, 40%);">+             cause = "suggested MaxMsgSize is too big for us";</span><br><span style="color: hsl(120, 100%, 40%);">+           goto 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%);">+   /* Attempt to initiate connection again */</span><br><span style="color: hsl(120, 100%, 40%);">+    sap->max_msg_size = size;</span><br><span style="color: hsl(120, 100%, 40%);">+  sap_fsm_connect(sap->fi, sap->fi->state);</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%);">+error:</span><br><span style="color: hsl(120, 100%, 40%);">+     LOGP(DSAP, LOGL_ERROR, "MaxMsgSize negotiation failed: %s\n", cause);</span><br><span style="color: hsl(120, 100%, 40%);">+       osmo_fsm_inst_state_chg(sap->fi, SAP_STATE_NOT_CONNECTED, 0, 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 void sap_fsm_conn_handler(struct osmo_fsm_inst *fi,</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        const struct sap_message *sap_msg = (const struct sap_message *) data;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct osmocom_ms *ms = (struct osmocom_ms *) fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct sap_param *param;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint16_t param_len;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t status;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Section 5.1.2, CONNECT_RESP */</span><br><span style="color: hsl(120, 100%, 40%);">+     param = sap_get_param(sap_msg, SAP_CONNECTION_STATUS, &param_len);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!param || param_len != sizeof(status)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          LOGP(DSAP, LOGL_ERROR, "Missing mandatory connection status\n");</span><br><span style="color: hsl(120, 100%, 40%);">+            osmo_fsm_inst_state_chg(fi, SAP_STATE_NOT_CONNECTED, 0, 0);</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%);">+   /* Parse connection status */</span><br><span style="color: hsl(120, 100%, 40%);">+ status = param->value[0];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        LOGP(DSAP, LOGL_INFO, "SAP connection status (0x%02x): %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+               status, get_value_string(sap_conn_status_names, status));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   switch (status) {</span><br><span style="color: hsl(120, 100%, 40%);">+     case SAP_CONN_STATUS_OK_CALL:</span><br><span style="color: hsl(120, 100%, 40%);">+         ms->sap_entity.card_status = SAP_CARD_STATUS_CARD_NOT_ACC;</span><br><span style="color: hsl(120, 100%, 40%);">+         /* fall-through */</span><br><span style="color: hsl(120, 100%, 40%);">+    case SAP_CONN_STATUS_OK_READY:</span><br><span style="color: hsl(120, 100%, 40%);">+                osmo_fsm_inst_state_chg(fi, SAP_STATE_WAIT_FOR_CARD, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+           break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case SAP_CONN_STATUS_ERROR_SMALL_MSG_SIZE:</span><br><span style="color: hsl(120, 100%, 40%);">+    case SAP_CONN_STATUS_ERROR_CONN:</span><br><span style="color: hsl(120, 100%, 40%);">+              osmo_fsm_inst_state_chg(fi, SAP_STATE_NOT_CONNECTED, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+           break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Section 4.1.1, MaxMsgSize negotiation */</span><br><span style="color: hsl(120, 100%, 40%);">+   case SAP_CONN_STATUS_ERROR_MAX_MSG_SIZE:</span><br><span style="color: hsl(120, 100%, 40%);">+              sap_negotiate_msg_size(&ms->sap_entity, sap_msg);</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void sap_fsm_conn_release(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 osmocom_ms *ms = (struct osmocom_ms *) fi->priv;</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%);">+   LOGP(DSAP, LOGL_DEBUG, "Client initiated connection release\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* We don't care about possible allocating / sending errors */</span><br><span style="color: hsl(120, 100%, 40%);">+    msg = sap_msgb_alloc(SAP_DISCONNECT_REQ);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (msg != NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+              sap_send_msgb(ms, 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%);">+static void sap_fsm_release_handler(struct osmo_fsm_inst *fi,</span><br><span style="color: hsl(120, 100%, 40%);">+   uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        LOGP(DSAP, LOGL_DEBUG, "Client initiated release complete\n");</span><br><span style="color: hsl(120, 100%, 40%);">+      osmo_fsm_inst_state_chg(fi, SAP_STATE_NOT_CONNECTED, 0, 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 void sap_fsm_idle_enter(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%);">+    switch (prev_state) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case SAP_STATE_CONNECTING:</span><br><span style="color: hsl(120, 100%, 40%);">+    case SAP_STATE_WAIT_FOR_CARD:</span><br><span style="color: hsl(120, 100%, 40%);">+         /* Sent ATR request (required by the specs) */</span><br><span style="color: hsl(120, 100%, 40%);">+                sap_send_atr_req((struct osmocom_ms *) fi->priv);</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%);">+              /* Do nothing */</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void sap_fsm_idle_handler(struct osmo_fsm_inst *fi,</span><br><span style="color: hsl(120, 100%, 40%);">+    uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct osmocom_ms *ms = (struct osmocom_ms *) fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct msgb *msg = (struct msgb *) data;</span><br><span style="color: hsl(120, 100%, 40%);">+      enum sap_fsm_state state;</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%);">+     /* Map event to the corresponding state */</span><br><span style="color: hsl(120, 100%, 40%);">+    switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case SAP_TRANSFER_ATR_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+            state = SAP_STATE_PROC_ATR_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+               break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case SAP_TRANSFER_APDU_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+           state = SAP_STATE_PROC_APDU_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case SAP_RESET_SIM_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+               state = SAP_STATE_PROC_RESET_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case SAP_TRANSFER_CARD_READER_STATUS_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+             state = SAP_STATE_PROC_STATUS_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case SAP_SET_TRANSPORT_PROTOCOL_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+          state = SAP_STATE_PROC_SET_TP_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case SAP_POWER_SIM_ON_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+            state = SAP_STATE_PROC_POWERON_REQ;</span><br><span style="color: hsl(120, 100%, 40%);">+           break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case SAP_POWER_SIM_OFF_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+           state = SAP_STATE_PROC_POWEROFF_REQ;</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%);">+              /* Shall not happen */</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%);">+   rc = sap_send_msgb(ms, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (rc)</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%);">+     osmo_fsm_inst_state_chg(fi, state,</span><br><span style="color: hsl(120, 100%, 40%);">+            SAP_FSM_PROC_REQ_TIMEOUT, SAP_FSM_PROC_REQ_T);</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 sap_fsm_proc_atr_handler(struct osmo_fsm_inst *fi,</span><br><span style="color: hsl(120, 100%, 40%);">+   uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        const struct sap_message *sap_msg = (const struct sap_message *) data;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct osmocom_ms *ms = (struct osmocom_ms *) fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct sap_param *param;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint16_t param_len;</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 (event != SAP_TRANSFER_ATR_RESP) {</span><br><span style="color: hsl(120, 100%, 40%);">+         LOGP(DSAP, LOGL_ERROR, "Event unhandled (yet)\n");</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%);">+   /* We're done with ATR request now */</span><br><span style="color: hsl(120, 100%, 40%);">+     osmo_fsm_inst_state_chg(fi, SAP_STATE_IDLE, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Check the ResultCode */</span><br><span style="color: hsl(120, 100%, 40%);">+    rc = sap_check_result_code(sap_msg);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (rc != SAP_RESULT_OK_REQ_PROC_CORR) {</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGP(DSAP, LOGL_NOTICE, "Bad ResultCode: '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                   get_value_string(sap_result_names, rc));</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%);">+   param = sap_get_param(sap_msg, SAP_ATR, &param_len);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!param) {</span><br><span style="color: hsl(120, 100%, 40%);">+         LOGP(DSAP, LOGL_ERROR, "Missing mandatory '%s' parameter\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                        get_value_string(sap_param_names, SAP_ATR));</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%);">+   LOGP(DSAP, LOGL_DEBUG, "RX ATR response: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+             osmo_hexdump(param->value, param_len));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Forward to ATR handler (if present) */</span><br><span style="color: hsl(120, 100%, 40%);">+     if (ms->sap_entity.atr_cb)</span><br><span style="color: hsl(120, 100%, 40%);">+         ms->sap_entity.atr_cb(ms, param->value, param_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* We are ready to process APDU requests now */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (ms->sap_entity.idle_cb)</span><br><span style="color: hsl(120, 100%, 40%);">+                ms->sap_entity.idle_cb(ms);</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 sap_fsm_proc_apdu_handler(struct osmo_fsm_inst *fi,</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        const struct sap_message *sap_msg = (const struct sap_message *) data;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct osmocom_ms *ms = (struct osmocom_ms *) fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct sap_param *param;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint16_t param_len;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct msgb *msg;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t *apdu;</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 (event != SAP_TRANSFER_APDU_RESP) {</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGP(DSAP, LOGL_ERROR, "Event unhandled (yet)\n");</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%);">+   /* We're done with APDU request now */</span><br><span style="color: hsl(120, 100%, 40%);">+    osmo_fsm_inst_state_chg(fi, SAP_STATE_IDLE, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Check the ResultCode */</span><br><span style="color: hsl(120, 100%, 40%);">+    rc = sap_check_result_code(sap_msg);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (rc != SAP_RESULT_OK_REQ_PROC_CORR) {</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGP(DSAP, LOGL_NOTICE, "Bad ResultCode: '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                   get_value_string(sap_result_names, rc));</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%);">+   param = sap_get_param(sap_msg, SAP_RESPONSE_APDU, &param_len);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!param) {</span><br><span style="color: hsl(120, 100%, 40%);">+         LOGP(DSAP, LOGL_ERROR, "Missing mandatory '%s' parameter\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                        get_value_string(sap_param_names, SAP_RESPONSE_APDU));</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%);">+   /* Forward to APDU handler (if present) */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!ms->sap_entity.apdu_cb) {</span><br><span style="color: hsl(120, 100%, 40%);">+             LOGP(DSAP, LOGL_NOTICE, "No handler set, response APDU ignored\n");</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%);">+   /* FIXME: why do we use this length?!? */</span><br><span style="color: hsl(120, 100%, 40%);">+     msg = msgb_alloc(GSM_SAP_LENGTH, "sim_apdu");</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!msg) {</span><br><span style="color: hsl(120, 100%, 40%);">+           LOGP(DSAP, LOGL_ERROR, "Failed to allocate memory\n");</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%);">+   apdu = msgb_put(msg, param_len);</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(apdu, param->value, param_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Forward to APDU handler (if present) */</span><br><span style="color: hsl(120, 100%, 40%);">+    LOGP(DSAP, LOGL_DEBUG, "Forwarding APDU to the handler\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ ms->sap_entity.apdu_cb(ms, 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%);">+/* Generates mask for a single state or event */</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%);">+/* Figure 4.13: Simplified State Machine */</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct osmo_fsm_state sap_fsm_states[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+       [SAP_STATE_NOT_CONNECTED] = {</span><br><span style="color: hsl(120, 100%, 40%);">+         .name = "NOT_CONNECTED",</span><br><span style="color: hsl(120, 100%, 40%);">+            .out_state_mask = S(SAP_STATE_CONNECTING),</span><br><span style="color: hsl(120, 100%, 40%);">+            .onenter = &sap_fsm_tear_down,</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    [SAP_STATE_CONNECTING] = {</span><br><span style="color: hsl(120, 100%, 40%);">+            .name = "CONNECTING",</span><br><span style="color: hsl(120, 100%, 40%);">+               .out_state_mask = S(SAP_STATE_NOT_CONNECTED)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_WAIT_FOR_CARD),</span><br><span style="color: hsl(120, 100%, 40%);">+         .in_event_mask  = S(SAP_CONNECT_RESP),</span><br><span style="color: hsl(120, 100%, 40%);">+                .onenter = &sap_fsm_connect,</span><br><span style="color: hsl(120, 100%, 40%);">+              .action = &sap_fsm_conn_handler,</span><br><span style="color: hsl(120, 100%, 40%);">+  },</span><br><span style="color: hsl(120, 100%, 40%);">+    /* NOTE: this is a custom state (i.e. not defined by the specs).</span><br><span style="color: hsl(120, 100%, 40%);">+       * We need it in order to do release procedure correctly. */</span><br><span style="color: hsl(120, 100%, 40%);">+  [SAP_STATE_DISCONNECTING] = {</span><br><span style="color: hsl(120, 100%, 40%);">+         .name = "DISCONNECTING",</span><br><span style="color: hsl(120, 100%, 40%);">+            .out_state_mask = S(SAP_STATE_NOT_CONNECTED),</span><br><span style="color: hsl(120, 100%, 40%);">+         .in_event_mask  = S(SAP_DISCONNECT_RESP),</span><br><span style="color: hsl(120, 100%, 40%);">+             .onenter = &sap_fsm_conn_release,</span><br><span style="color: hsl(120, 100%, 40%);">+         .action = &sap_fsm_release_handler,</span><br><span style="color: hsl(120, 100%, 40%);">+       },</span><br><span style="color: hsl(120, 100%, 40%);">+    /* NOTE: this is a custom state (i.e. not defined by the specs).</span><br><span style="color: hsl(120, 100%, 40%);">+       * We need it in order to wait until SIM card becomes available.</span><br><span style="color: hsl(120, 100%, 40%);">+       * SAP_STATUS_IND event is handled by sap_fsm_allstate_action(). */</span><br><span style="color: hsl(120, 100%, 40%);">+   [SAP_STATE_WAIT_FOR_CARD] = {</span><br><span style="color: hsl(120, 100%, 40%);">+         .name = "WAIT_FOR_CARD",</span><br><span style="color: hsl(120, 100%, 40%);">+            .out_state_mask = S(SAP_STATE_NOT_CONNECTED)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_DISCONNECTING)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_IDLE),</span><br><span style="color: hsl(120, 100%, 40%);">+  },</span><br><span style="color: hsl(120, 100%, 40%);">+    [SAP_STATE_IDLE] = {</span><br><span style="color: hsl(120, 100%, 40%);">+          .name = "IDLE",</span><br><span style="color: hsl(120, 100%, 40%);">+             .out_state_mask = S(SAP_STATE_NOT_CONNECTED)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_DISCONNECTING)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_WAIT_FOR_CARD)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_PROC_APDU_REQ)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_PROC_ATR_REQ)</span><br><span style="color: hsl(120, 100%, 40%);">+                           | S(SAP_STATE_PROC_RESET_REQ)</span><br><span style="color: hsl(120, 100%, 40%);">+                         | S(SAP_STATE_PROC_STATUS_REQ)</span><br><span style="color: hsl(120, 100%, 40%);">+                                | S(SAP_STATE_PROC_SET_TP_REQ)</span><br><span style="color: hsl(120, 100%, 40%);">+                                | S(SAP_STATE_PROC_POWERON_REQ)</span><br><span style="color: hsl(120, 100%, 40%);">+                               | S(SAP_STATE_PROC_POWEROFF_REQ),</span><br><span style="color: hsl(120, 100%, 40%);">+             .in_event_mask  = S(SAP_TRANSFER_ATR_REQ)</span><br><span style="color: hsl(120, 100%, 40%);">+                             | S(SAP_TRANSFER_APDU_REQ)</span><br><span style="color: hsl(120, 100%, 40%);">+                            | S(SAP_RESET_SIM_REQ)</span><br><span style="color: hsl(120, 100%, 40%);">+                                | S(SAP_TRANSFER_CARD_READER_STATUS_REQ)</span><br><span style="color: hsl(120, 100%, 40%);">+                              | S(SAP_SET_TRANSPORT_PROTOCOL_REQ)</span><br><span style="color: hsl(120, 100%, 40%);">+                           | S(SAP_POWER_SIM_ON_REQ)</span><br><span style="color: hsl(120, 100%, 40%);">+                             | S(SAP_POWER_SIM_OFF_REQ),</span><br><span style="color: hsl(120, 100%, 40%);">+           .onenter = &sap_fsm_idle_enter,</span><br><span style="color: hsl(120, 100%, 40%);">+           .action = &sap_fsm_idle_handler,</span><br><span style="color: hsl(120, 100%, 40%);">+  },</span><br><span style="color: hsl(120, 100%, 40%);">+    [SAP_STATE_PROC_ATR_REQ] = {</span><br><span style="color: hsl(120, 100%, 40%);">+          .name = "PROC_ATR_REQ",</span><br><span style="color: hsl(120, 100%, 40%);">+             .out_state_mask = S(SAP_STATE_NOT_CONNECTED)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_DISCONNECTING)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_WAIT_FOR_CARD)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_IDLE)</span><br><span style="color: hsl(120, 100%, 40%);">+                           | S(SAP_STATE_PROC_RESET_REQ)</span><br><span style="color: hsl(120, 100%, 40%);">+                         | S(SAP_STATE_PROC_POWEROFF_REQ),</span><br><span style="color: hsl(120, 100%, 40%);">+             .in_event_mask  = S(SAP_TRANSFER_ATR_RESP)</span><br><span style="color: hsl(120, 100%, 40%);">+                            | S(SAP_RESET_SIM_REQ)</span><br><span style="color: hsl(120, 100%, 40%);">+                                | S(SAP_POWER_SIM_OFF_REQ),</span><br><span style="color: hsl(120, 100%, 40%);">+           .action = &sap_fsm_proc_atr_handler,</span><br><span style="color: hsl(120, 100%, 40%);">+      },</span><br><span style="color: hsl(120, 100%, 40%);">+    [SAP_STATE_PROC_APDU_REQ] = {</span><br><span style="color: hsl(120, 100%, 40%);">+         .name = "PROC_APDU_REQ",</span><br><span style="color: hsl(120, 100%, 40%);">+            .out_state_mask = S(SAP_STATE_NOT_CONNECTED)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_DISCONNECTING)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_WAIT_FOR_CARD)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_IDLE)</span><br><span style="color: hsl(120, 100%, 40%);">+                           | S(SAP_STATE_PROC_RESET_REQ)</span><br><span style="color: hsl(120, 100%, 40%);">+                         | S(SAP_STATE_PROC_POWEROFF_REQ),</span><br><span style="color: hsl(120, 100%, 40%);">+             .in_event_mask  = S(SAP_TRANSFER_APDU_RESP)</span><br><span style="color: hsl(120, 100%, 40%);">+                           | S(SAP_RESET_SIM_REQ)</span><br><span style="color: hsl(120, 100%, 40%);">+                                | S(SAP_POWER_SIM_OFF_REQ),</span><br><span style="color: hsl(120, 100%, 40%);">+           .action = &sap_fsm_proc_apdu_handler,</span><br><span style="color: hsl(120, 100%, 40%);">+     },</span><br><span style="color: hsl(120, 100%, 40%);">+    [SAP_STATE_PROC_RESET_REQ] = {</span><br><span style="color: hsl(120, 100%, 40%);">+                .name = "PROC_RESET_REQ",</span><br><span style="color: hsl(120, 100%, 40%);">+           .out_state_mask = S(SAP_STATE_NOT_CONNECTED)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_DISCONNECTING)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_WAIT_FOR_CARD)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_IDLE)</span><br><span style="color: hsl(120, 100%, 40%);">+                           | S(SAP_STATE_PROC_POWEROFF_REQ),</span><br><span style="color: hsl(120, 100%, 40%);">+             .in_event_mask  = S(SAP_RESET_SIM_RESP)</span><br><span style="color: hsl(120, 100%, 40%);">+                               | S(SAP_POWER_SIM_OFF_REQ),</span><br><span style="color: hsl(120, 100%, 40%);">+           // .action = sap_fsm_proc_handler,</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    [SAP_STATE_PROC_STATUS_REQ] = {</span><br><span style="color: hsl(120, 100%, 40%);">+               .name = "PROC_STATUS_REQ",</span><br><span style="color: hsl(120, 100%, 40%);">+          .out_state_mask = S(SAP_STATE_NOT_CONNECTED)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_DISCONNECTING)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_WAIT_FOR_CARD)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_IDLE)</span><br><span style="color: hsl(120, 100%, 40%);">+                           | S(SAP_STATE_PROC_RESET_REQ)</span><br><span style="color: hsl(120, 100%, 40%);">+                         | S(SAP_STATE_PROC_POWEROFF_REQ),</span><br><span style="color: hsl(120, 100%, 40%);">+             .in_event_mask  = S(SAP_TRANSFER_CARD_READER_STATUS_RESP)</span><br><span style="color: hsl(120, 100%, 40%);">+                             | S(SAP_RESET_SIM_REQ)</span><br><span style="color: hsl(120, 100%, 40%);">+                                | S(SAP_POWER_SIM_OFF_REQ),</span><br><span style="color: hsl(120, 100%, 40%);">+           // .action = sap_fsm_proc_handler,</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    [SAP_STATE_PROC_SET_TP_REQ] = {</span><br><span style="color: hsl(120, 100%, 40%);">+               .name = "PROC_SET_TP_REQ",</span><br><span style="color: hsl(120, 100%, 40%);">+          .out_state_mask = S(SAP_STATE_NOT_CONNECTED)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_DISCONNECTING)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_WAIT_FOR_CARD)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_IDLE),</span><br><span style="color: hsl(120, 100%, 40%);">+          .in_event_mask  = S(SAP_SET_TRANSPORT_PROTOCOL_RESP),</span><br><span style="color: hsl(120, 100%, 40%);">+         // .action = sap_fsm_proc_handler,</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    [SAP_STATE_PROC_POWERON_REQ] = {</span><br><span style="color: hsl(120, 100%, 40%);">+              .name = "PROC_POWERON_REQ",</span><br><span style="color: hsl(120, 100%, 40%);">+         .out_state_mask = S(SAP_STATE_NOT_CONNECTED)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_DISCONNECTING)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_WAIT_FOR_CARD)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_IDLE)</span><br><span style="color: hsl(120, 100%, 40%);">+                           | S(SAP_STATE_PROC_POWEROFF_REQ),</span><br><span style="color: hsl(120, 100%, 40%);">+             .in_event_mask  = S(SAP_POWER_SIM_ON_RESP)</span><br><span style="color: hsl(120, 100%, 40%);">+                            | S(SAP_POWER_SIM_OFF_REQ),</span><br><span style="color: hsl(120, 100%, 40%);">+           // .action = sap_fsm_proc_handler,</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    [SAP_STATE_PROC_POWEROFF_REQ] = {</span><br><span style="color: hsl(120, 100%, 40%);">+             .name = "PROC_POWEROFF_REQ",</span><br><span style="color: hsl(120, 100%, 40%);">+                .out_state_mask = S(SAP_STATE_NOT_CONNECTED)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_DISCONNECTING)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_WAIT_FOR_CARD)</span><br><span style="color: hsl(120, 100%, 40%);">+                          | S(SAP_STATE_IDLE),</span><br><span style="color: hsl(120, 100%, 40%);">+          .in_event_mask  = S(SAP_POWER_SIM_OFF_RESP),</span><br><span style="color: hsl(120, 100%, 40%);">+          // .action = sap_fsm_proc_handler,</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 sap_fsm_handle_card_status_ind(struct osmo_fsm_inst *fi,</span><br><span style="color: hsl(120, 100%, 40%);">+        const struct sap_message *sap_msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmocom_ms *ms = (struct osmocom_ms *) fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct sap_param *param;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint16_t param_len;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t status;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     param = sap_get_param(sap_msg, SAP_STATUS_CHANGE, &param_len);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!param || param_len != sizeof(status)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          LOGP(DSAP, LOGL_ERROR, "Missing mandatory '%s' parameter\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                        get_value_string(sap_param_names, SAP_STATUS_CHANGE));</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%);">+   status = param->value[0];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (ms->sap_entity.card_status != status) {</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGP(DSAP, LOGL_NOTICE, "(SIM) card status change '%s' -> '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                       get_value_string(sap_card_status_names, ms->sap_entity.card_status),</span><br><span style="color: hsl(120, 100%, 40%);">+                       get_value_string(sap_card_status_names, status));</span><br><span style="color: hsl(120, 100%, 40%);">+             ms->sap_entity.card_status = status;</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 (status) {</span><br><span style="color: hsl(120, 100%, 40%);">+     /* SIM card is ready */</span><br><span style="color: hsl(120, 100%, 40%);">+       case SAP_CARD_STATUS_CARD_RESET:</span><br><span style="color: hsl(120, 100%, 40%);">+              if (fi->state != SAP_STATE_IDLE)</span><br><span style="color: hsl(120, 100%, 40%);">+                   osmo_fsm_inst_state_chg(fi, SAP_STATE_IDLE, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* SIM card has recovered after unaccessful state */</span><br><span style="color: hsl(120, 100%, 40%);">+  case SAP_CARD_STATUS_CARD_RECOVERED:</span><br><span style="color: hsl(120, 100%, 40%);">+          if (fi->state != SAP_STATE_IDLE)</span><br><span style="color: hsl(120, 100%, 40%);">+                   osmo_fsm_inst_state_chg(fi, SAP_STATE_IDLE, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* SIM care inserted, we need to power it on */</span><br><span style="color: hsl(120, 100%, 40%);">+       case SAP_CARD_STATUS_CARD_INSERTED:</span><br><span style="color: hsl(120, 100%, 40%);">+           if (fi->state != SAP_STATE_IDLE)</span><br><span style="color: hsl(120, 100%, 40%);">+                   osmo_fsm_inst_state_chg(fi, SAP_STATE_IDLE, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+            sap_send_poweron_req(ms);</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 SAP_CARD_STATUS_UNKNOWN_ERROR:</span><br><span style="color: hsl(120, 100%, 40%);">+   case SAP_CARD_STATUS_CARD_NOT_ACC:</span><br><span style="color: hsl(120, 100%, 40%);">+    case SAP_CARD_STATUS_CARD_REMOVED:</span><br><span style="color: hsl(120, 100%, 40%);">+    default: /* Unknown card status */</span><br><span style="color: hsl(120, 100%, 40%);">+            if (fi->state != SAP_STATE_WAIT_FOR_CARD)</span><br><span style="color: hsl(120, 100%, 40%);">+                  osmo_fsm_inst_state_chg(fi, SAP_STATE_WAIT_FOR_CARD, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+           break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void sap_fsm_allstate_action(struct osmo_fsm_inst *fi,</span><br><span style="color: hsl(120, 100%, 40%);">+ 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%);">+      /* Disconnect indication initiated by the Server.</span><br><span style="color: hsl(120, 100%, 40%);">+      * FIXME: at the moment, immediate release is always assumed,</span><br><span style="color: hsl(120, 100%, 40%);">+  * but ideally we should check type of release (using *data) */</span><br><span style="color: hsl(120, 100%, 40%);">+       case SAP_DISCONNECT_IND:</span><br><span style="color: hsl(120, 100%, 40%);">+              /* This message may arrive in any of the sub-states of</span><br><span style="color: hsl(120, 100%, 40%);">+                 * the "Connected" state (i.e. connection shall exist) */</span><br><span style="color: hsl(120, 100%, 40%);">+           if (fi->state < SAP_STATE_WAIT_FOR_CARD)</span><br><span style="color: hsl(120, 100%, 40%);">+                        goto not_peritted;</span><br><span style="color: hsl(120, 100%, 40%);">+            /* fall-through */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Disconnect initiated by the Client */</span><br><span style="color: hsl(120, 100%, 40%);">+      case SAP_DISCONNECT_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+              /* If we have no active connection, tear-down immediately */</span><br><span style="color: hsl(120, 100%, 40%);">+          if (fi->state < SAP_STATE_WAIT_FOR_CARD) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      osmo_fsm_inst_state_chg(fi,</span><br><span style="color: hsl(120, 100%, 40%);">+                           SAP_STATE_NOT_CONNECTED, 0, 0);</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%);">+           /* Trigger Client-initiater connection release */</span><br><span style="color: hsl(120, 100%, 40%);">+             osmo_fsm_inst_state_chg(fi, SAP_STATE_DISCONNECTING,</span><br><span style="color: hsl(120, 100%, 40%);">+                  SAP_FSM_CONN_REL_TIMEOUT, SAP_FSM_CONN_REL_T);</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%);">+      /* SIM status indication (inserted or ejected) */</span><br><span style="color: hsl(120, 100%, 40%);">+     case SAP_STATUS_IND:</span><br><span style="color: hsl(120, 100%, 40%);">+          /* This message may arrive in any of the sub-states of</span><br><span style="color: hsl(120, 100%, 40%);">+                 * the "Connected" state (i.e. connection shall exist) */</span><br><span style="color: hsl(120, 100%, 40%);">+           if (fi->state < SAP_STATE_WAIT_FOR_CARD)</span><br><span style="color: hsl(120, 100%, 40%);">+                        goto not_peritted;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          sap_fsm_handle_card_status_ind(fi,</span><br><span style="color: hsl(120, 100%, 40%);">+                    (const struct sap_message *) data);</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 SAP_ERROR_RESP:</span><br><span style="color: hsl(120, 100%, 40%);">+          if (fi->state == SAP_STATE_CONNECTING) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   /* Connection establishment error */</span><br><span style="color: hsl(120, 100%, 40%);">+                  osmo_fsm_inst_state_chg(fi,</span><br><span style="color: hsl(120, 100%, 40%);">+                           SAP_STATE_NOT_CONNECTED, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+               } else if (fi->state > SAP_STATE_IDLE) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        /* Error replaces any Request message */</span><br><span style="color: hsl(120, 100%, 40%);">+                      osmo_fsm_inst_state_chg(fi,</span><br><span style="color: hsl(120, 100%, 40%);">+                           SAP_STATE_IDLE, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* Should not happen in general */</span><br><span style="color: hsl(120, 100%, 40%);">+                    goto not_peritted;</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      default:</span><br><span style="color: hsl(120, 100%, 40%);">+              /* Shall not happen */</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%);">+   return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+not_peritted:</span><br><span style="color: hsl(120, 100%, 40%);">+      LOGPFSML(fi, LOGL_NOTICE, "Event '%s' is not "</span><br><span style="color: hsl(120, 100%, 40%);">+              "permitted in state '%s', please fix!\n",</span><br><span style="color: hsl(120, 100%, 40%);">+           osmo_fsm_event_name(fi->fsm, event),</span><br><span style="color: hsl(120, 100%, 40%);">+               osmo_fsm_state_name(fi->fsm, fi->state));</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int sap_fsm_timer_cb(struct osmo_fsm_inst *fi)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        switch (fi->state) {</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Connection establishment / release timeout */</span><br><span style="color: hsl(120, 100%, 40%);">+      case SAP_STATE_DISCONNECTING:</span><br><span style="color: hsl(120, 100%, 40%);">+ case SAP_STATE_CONNECTING:</span><br><span style="color: hsl(120, 100%, 40%);">+            LOGP(DSAP, LOGL_NOTICE, "Connection timeout\n");</span><br><span style="color: hsl(120, 100%, 40%);">+            osmo_fsm_inst_state_chg(fi, SAP_STATE_NOT_CONNECTED, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+           break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Request processing timeout */</span><br><span style="color: hsl(120, 100%, 40%);">+      case SAP_STATE_PROC_ATR_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+  case SAP_STATE_PROC_APDU_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+ case SAP_STATE_PROC_RESET_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+        case SAP_STATE_PROC_STATUS_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+       case SAP_STATE_PROC_SET_TP_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+       case SAP_STATE_PROC_POWERON_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+      case SAP_STATE_PROC_POWEROFF_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+             LOGP(DSAP, LOGL_NOTICE, "Timeout waiting for '%s' to complete, "</span><br><span style="color: hsl(120, 100%, 40%);">+                    "going back to IDLE\n", osmo_fsm_inst_state_name(fi));</span><br><span style="color: hsl(120, 100%, 40%);">+              osmo_fsm_inst_state_chg(fi, SAP_STATE_IDLE, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      default:</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGP(DSAP, LOGL_ERROR, "Unhandled state '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                    osmo_fsm_inst_state_name(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%);">+   /* Do not tear-down FSM */</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_fsm sap_fsm_def = {</span><br><span style="color: hsl(120, 100%, 40%);">+        .name = "sap_fsm",</span><br><span style="color: hsl(120, 100%, 40%);">+  .log_subsys = DSAP,</span><br><span style="color: hsl(120, 100%, 40%);">+   .states = sap_fsm_states,</span><br><span style="color: hsl(120, 100%, 40%);">+     .num_states = ARRAY_SIZE(sap_fsm_states),</span><br><span style="color: hsl(120, 100%, 40%);">+     .event_names = sap_msg_names,</span><br><span style="color: hsl(120, 100%, 40%);">+ .timer_cb = &sap_fsm_timer_cb,</span><br><span style="color: hsl(120, 100%, 40%);">+    .allstate_action = &sap_fsm_allstate_action,</span><br><span style="color: hsl(120, 100%, 40%);">+      .allstate_event_mask = 0</span><br><span style="color: hsl(120, 100%, 40%);">+              | S(SAP_DISCONNECT_REQ)</span><br><span style="color: hsl(120, 100%, 40%);">+               | S(SAP_DISCONNECT_IND)</span><br><span style="color: hsl(120, 100%, 40%);">+               | S(SAP_STATUS_IND)</span><br><span style="color: hsl(120, 100%, 40%);">+           | S(SAP_ERROR_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%);">+int sap_fsm_alloc(struct osmocom_ms *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct osmosap_entity *sap;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ sap = &ms->sap_entity;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(sap->fi == NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Register our FSM (if required) */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!osmo_fsm_find_by_name(sap_fsm_def.name))</span><br><span style="color: hsl(120, 100%, 40%);">+         OSMO_ASSERT(osmo_fsm_register(&sap_fsm_def) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Allocate an instance using ms as talloc context */</span><br><span style="color: hsl(120, 100%, 40%);">+ sap->fi = osmo_fsm_inst_alloc(&sap_fsm_def, ms,</span><br><span style="color: hsl(120, 100%, 40%);">+                ms, LOGL_DEBUG, ms->name);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!sap->fi) {</span><br><span style="color: hsl(120, 100%, 40%);">+            LOGP(DSAP, LOGL_ERROR, "Failed to allocate SAP FSM\n");</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%);">+   return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/host/layer23/src/common/sap_interface.c b/src/host/layer23/src/common/sap_interface.c</span><br><span>index c31d07b..4ed457f 100644</span><br><span>--- a/src/host/layer23/src/common/sap_interface.c</span><br><span>+++ b/src/host/layer23/src/common/sap_interface.c</span><br><span>@@ -4,6 +4,7 @@</span><br><span>  * (C) 2010,2018 by Harald Welte <laforge@gnumonks.org></span><br><span>  * (C) 2010 by Andreas Eversberg <jolly@eversberg.eu></span><br><span>  * (C) 2011 by Nico Golde <nico@ngolde.de></span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2018 by Vadim Yanitskiy <axilirator@gmail.com></span><br><span>  *</span><br><span>  * All Rights Reserved</span><br><span>  *</span><br><span>@@ -23,536 +24,272 @@</span><br><span>  *</span><br><span>  */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/bb/common/osmocom_data.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/bb/common/logging.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/bb/common/sap_interface.h></span><br><span style="color: hsl(0, 100%, 40%);">-</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/talloc.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/core/socket.h></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include <sys/socket.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <sys/un.h></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include <arpa/inet.h></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#define _GNU_SOURCE</span><br><span> #include <unistd.h></span><br><span> #include <errno.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <string.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <stdlib.h></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#define GSM_SAP_LENGTH 300</span><br><span style="color: hsl(0, 100%, 40%);">-#define GSM_SAP_HEADROOM 32</span><br><span style="color: hsl(120, 100%, 40%);">+#include <sys/socket.h></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void sap_connect(struct osmocom_ms *ms);</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/write_queue.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/socket.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/msgb.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/fsm.h></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* Table 5.15: List of Parameter IDs */</span><br><span style="color: hsl(0, 100%, 40%);">-static const struct value_string sap_param_names[] = {</span><br><span style="color: hsl(0, 100%, 40%);">-     { SAP_MAX_MSG_SIZE,             "MaxMsgSize" },</span><br><span style="color: hsl(0, 100%, 40%);">-       { SAP_CONNECTION_STATUS,        "ConnectionStatus" },</span><br><span style="color: hsl(0, 100%, 40%);">- { SAP_RESULT_CODE,              "ResultCode" },</span><br><span style="color: hsl(0, 100%, 40%);">-       { SAP_DISCONNECTION_TYPE,       "DisconnectionType" },</span><br><span style="color: hsl(0, 100%, 40%);">-        { SAP_COMMAND_APDU,             "CommandAPDU" },</span><br><span style="color: hsl(0, 100%, 40%);">-      { SAP_COMMAND_APDU_7816,        "CommandAPDU7816" },</span><br><span style="color: hsl(0, 100%, 40%);">-  { SAP_RESPONSE_APDU,            "ResponseAPDU" },</span><br><span style="color: hsl(0, 100%, 40%);">-     { SAP_ATR,                      "ATR" },</span><br><span style="color: hsl(0, 100%, 40%);">-      { SAP_CARD_READER_STATUS,       "CardReaderStatus" },</span><br><span style="color: hsl(0, 100%, 40%);">- { SAP_STATUS_CHANGE,            "StatusChange" },</span><br><span style="color: hsl(0, 100%, 40%);">-     { SAP_TRANSPORT_PROTOCOL,       "TransportProtocol" },</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bb/common/osmocom_data.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bb/common/logging.h></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* Table 5.1: Message Overview */</span><br><span style="color: hsl(0, 100%, 40%);">-static const struct value_string sap_msg_names[] = {</span><br><span style="color: hsl(0, 100%, 40%);">-    { SAP_CONNECT_REQ,                      "CONNECT_REQ" },</span><br><span style="color: hsl(0, 100%, 40%);">-      { SAP_CONNECT_RESP,                     "CONNECT_RESP" },</span><br><span style="color: hsl(0, 100%, 40%);">-     { SAP_DISCONNECT_REQ,                   "DISCONNECT_REQ" },</span><br><span style="color: hsl(0, 100%, 40%);">-   { SAP_DISCONNECT_RESP,                  "DISCONNECT_RESP" },</span><br><span style="color: hsl(0, 100%, 40%);">-  { SAP_DISCONNECT_IND,                   "DISCONNECT_IND" },</span><br><span style="color: hsl(0, 100%, 40%);">-   { SAP_TRANSFER_APDU_REQ,                "TRANSFER_APDU_REQ" },</span><br><span style="color: hsl(0, 100%, 40%);">-        { SAP_TRANSFER_APDU_RESP,               "TRANSFER_APDU_RESP" },</span><br><span style="color: hsl(0, 100%, 40%);">-       { SAP_TRANSFER_ATR_REQ,                 "TRANSFER_ATR_REQ" },</span><br><span style="color: hsl(0, 100%, 40%);">- { SAP_TRANSFER_ATR_RESP,                "TRANSFER_ATR_RESP" },</span><br><span style="color: hsl(0, 100%, 40%);">-        { SAP_POWER_SIM_OFF_REQ,                "POWER_SIM_OFF_REQ" },</span><br><span style="color: hsl(0, 100%, 40%);">-        { SAP_POWER_SIM_OFF_RESP,               "POWER_SIM_OFF_RESP" },</span><br><span style="color: hsl(0, 100%, 40%);">-       { SAP_POWER_SIM_ON_REQ,                 "POWER_SIM_ON_REQ" },</span><br><span style="color: hsl(0, 100%, 40%);">- { SAP_POWER_SIM_ON_RESP,                "POWER_SIM_ON_RESP" },</span><br><span style="color: hsl(0, 100%, 40%);">-        { SAP_RESET_SIM_REQ,                    "RESET_SIM_REQ" },</span><br><span style="color: hsl(0, 100%, 40%);">-    { SAP_RESET_SIM_RESP,                   "RESET_SIM_RESP" },</span><br><span style="color: hsl(0, 100%, 40%);">-   { SAP_TRANSFER_CARD_READER_STATUS_REQ,  "TRANSFER_CARD_READER_STATUS_REQ" },</span><br><span style="color: hsl(0, 100%, 40%);">-  { SAP_TRANSFER_CARD_READER_STATUS_RESP, "TRANSFER_CARD_READER_STATUS_RESP" },</span><br><span style="color: hsl(0, 100%, 40%);">- { SAP_STATUS_IND,                       "STATUS_IND" },</span><br><span style="color: hsl(0, 100%, 40%);">-       { SAP_ERROR_RESP,                       "ERROR_RESP" },</span><br><span style="color: hsl(0, 100%, 40%);">-       { SAP_SET_TRANSPORT_PROTOCOL_REQ,       "SET_TRANSPORT_PROTOCOL_REQ" },</span><br><span style="color: hsl(0, 100%, 40%);">-       { SAP_SET_TRANSPORT_PROTOCOL_RESP,      "SET_TRANSPORT_PROTOCOL_RESP" },</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bb/common/sap_interface.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bb/common/sap_proto.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bb/common/sap_fsm.h></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* Table 5.18: Possible values for ResultCode */</span><br><span style="color: hsl(0, 100%, 40%);">-static const struct value_string sap_result_names[] = {</span><br><span style="color: hsl(0, 100%, 40%);">-       { SAP_RESULT_OK_REQ_PROC_CORR,          "OK, request processed correctly" },</span><br><span style="color: hsl(0, 100%, 40%);">-  { SAP_RESULT_ERROR_NO_REASON,           "Error, no reason defined" },</span><br><span style="color: hsl(0, 100%, 40%);">- { SAP_RESULT_ERROR_CARD_NOT_ACC,        "Error, card not accessible" },</span><br><span style="color: hsl(0, 100%, 40%);">-       { SAP_RESULT_ERROR_CARD_POWERED_OFF,    "Error, card (already) powered off" },</span><br><span style="color: hsl(0, 100%, 40%);">-        { SAP_RESULT_ERROR_CARD_REMOVED,        "Error, card removed" },</span><br><span style="color: hsl(0, 100%, 40%);">-      { SAP_RESULT_ERROR_CARD_POWERED_ON,     "Error, card already powered on" },</span><br><span style="color: hsl(0, 100%, 40%);">-   { SAP_RESULT_ERROR_DATA_UNAVAIL,        "Error, data not available" },</span><br><span style="color: hsl(0, 100%, 40%);">-        { SAP_RESULT_ERROR_NOT_SUPPORTED,       "Error, not supported "}</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%);">-/* Table 5.19: Possible values for StatusChange */</span><br><span style="color: hsl(0, 100%, 40%);">-static const struct value_string sap_status_change_names[] = {</span><br><span style="color: hsl(0, 100%, 40%);">-    { SAP_STATUS_CHG_UNKNOWN_ERROR,         "Unknown Error" },</span><br><span style="color: hsl(0, 100%, 40%);">-    { SAP_STATUS_CHG_CARD_RESET,            "Card reset" },</span><br><span style="color: hsl(0, 100%, 40%);">-       { SAP_STATUS_CHG_CARD_NOT_ACC,          "Card not accessible" },</span><br><span style="color: hsl(0, 100%, 40%);">-      { SAP_STATUS_CHG_CARD_REMOVED,          "Card removed" },</span><br><span style="color: hsl(0, 100%, 40%);">-     { SAP_STATUS_CHG_CARD_INSERTED,         "Card inserted" },</span><br><span style="color: hsl(0, 100%, 40%);">-    { SAP_STATUS_CHG_CARD_RECOVERED,        "Card recovered" },</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%);">-/* Table 5.16: Possible values for ConnectionStatus */</span><br><span style="color: hsl(0, 100%, 40%);">-static const struct value_string sap_status_names[] = {</span><br><span style="color: hsl(0, 100%, 40%);">-    { SAP_CONN_STATUS_OK_READY,             "OK, Server can fulfill requirements" },</span><br><span style="color: hsl(0, 100%, 40%);">-      { SAP_CONN_STATUS_ERROR_CONN,           "Error, Server unable to establish connection" },</span><br><span style="color: hsl(0, 100%, 40%);">-     { SAP_CONN_STATUS_ERROR_MAX_MSG_SIZE,   "Error, Server does not support maximum message size" },</span><br><span style="color: hsl(0, 100%, 40%);">-      { SAP_CONN_STATUS_ERROR_SMALL_MSG_SIZE, "Error, maximum message size by Client is too small" },</span><br><span style="color: hsl(0, 100%, 40%);">-       { SAP_CONN_STATUS_OK_CALL,              "OK, ongoing call" },</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 msgb *sap_create_msg(uint8_t id, uint8_t num_params, struct sap_param *params)</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Send ATR request to the Server.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ms MS instance with active SAP connection</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns 0 in case of success, negative in case of error</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int sap_send_atr_req(struct osmocom_ms *ms)</span><br><span> {</span><br><span>      struct msgb *msg;</span><br><span style="color: hsl(0, 100%, 40%);">-       uint8_t *msgp;</span><br><span style="color: hsl(0, 100%, 40%);">-  uint8_t i, plen, padding = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     msg = msgb_alloc(GSM_SAP_LENGTH, "osmosap");</span><br><span style="color: hsl(0, 100%, 40%);">-  if (!msg) {</span><br><span style="color: hsl(0, 100%, 40%);">-             LOGP(DSAP, LOGL_ERROR, "Failed to allocate msg.\n");</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%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* BTSAP 5.1 */</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_put_u8(msg, id);</span><br><span style="color: hsl(0, 100%, 40%);">-   msgb_put_u8(msg, num_params);</span><br><span style="color: hsl(0, 100%, 40%);">-   msgb_put_u16(msg, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   for(i=0; i<num_params; i++){</span><br><span style="color: hsl(0, 100%, 40%);">-         plen = params[i].len;</span><br><span style="color: hsl(0, 100%, 40%);">-           msgb_put_u8(msg, params[i].id);</span><br><span style="color: hsl(0, 100%, 40%);">-         msgb_put_u8(msg, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-            msgb_put_u16(msg, plen);</span><br><span style="color: hsl(0, 100%, 40%);">-                if(plen % 4){</span><br><span style="color: hsl(0, 100%, 40%);">-                   padding = 4 - (plen % 4);</span><br><span style="color: hsl(0, 100%, 40%);">-               }</span><br><span style="color: hsl(0, 100%, 40%);">-               msgp = msgb_put(msg, plen + padding);</span><br><span style="color: hsl(0, 100%, 40%);">-           memcpy(msgp, params[i].value, plen);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-            if(padding){</span><br><span style="color: hsl(0, 100%, 40%);">-                    memset(msgp + plen, 0, padding);</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%);">-       return 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%);">-static int osmosap_send(struct osmocom_ms *ms, struct msgb *msg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-   if(ms->sap_entity.sap_state == SAP_NOT_CONNECTED)</span><br><span style="color: hsl(0, 100%, 40%);">-            sap_connect(ms);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        if (ms->sap_wq.bfd.fd <= 0)</span><br><span style="color: hsl(0, 100%, 40%);">-               return -EINVAL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (osmo_wqueue_enqueue(&ms->sap_wq, msg) != 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                LOGP(DSAP, LOGL_ERROR, "Failed to enqueue msg.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-           msgb_free(msg);</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 int sap_parse_result(struct sap_param *param)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if(param->id != SAP_RESULT_CODE){</span><br><span style="color: hsl(0, 100%, 40%);">-            LOGP(DSAP, LOGL_INFO, "> Parameter id: %u no valid result type\n", param->id);</span><br><span style="color: hsl(0, 100%, 40%);">-          return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                LOGP(DSAP, LOGL_INFO, "> RESULT CODE: %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                               get_value_string(sap_result_names, param->value[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(param->value[0] > ARRAY_SIZE(sap_result_names)){</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 uint8_t *sap_get_param(uint8_t *data, struct sap_param *param)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-        uint8_t *dptr = data;</span><br><span style="color: hsl(0, 100%, 40%);">-   uint8_t padlen;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- param->id = *dptr++;</span><br><span style="color: hsl(0, 100%, 40%);">- /* skip reserved byte */</span><br><span style="color: hsl(0, 100%, 40%);">-        dptr++;</span><br><span style="color: hsl(0, 100%, 40%);">- param->len = *dptr << 8;</span><br><span style="color: hsl(0, 100%, 40%);">-       dptr++;</span><br><span style="color: hsl(0, 100%, 40%);">- param->len |= *dptr++;</span><br><span style="color: hsl(0, 100%, 40%);">-       param->value = talloc_zero_size(NULL, param->len);</span><br><span style="color: hsl(0, 100%, 40%);">-        memcpy(param->value, dptr, param->len);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   /* skip parameter and padding and return pointer to next parameter */</span><br><span style="color: hsl(0, 100%, 40%);">-   dptr += param->len;</span><br><span style="color: hsl(0, 100%, 40%);">-  if(param->len % 4){</span><br><span style="color: hsl(0, 100%, 40%);">-          padlen = (4 - param->len % 4);</span><br><span style="color: hsl(0, 100%, 40%);">-       } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                padlen = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-     }</span><br><span style="color: hsl(0, 100%, 40%);">-       dptr += padlen;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return dptr;</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 sap_msg_free(struct sap_msg *msg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-     uint8_t i;</span><br><span style="color: hsl(0, 100%, 40%);">-      for(i=0; i<msg->num_params; i++){</span><br><span style="color: hsl(0, 100%, 40%);">-         talloc_free(msg->params[i].value);</span><br><span style="color: hsl(0, 100%, 40%);">-           talloc_free(msg->params);</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(0, 100%, 40%);">-       talloc_free(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%);">-static struct sap_msg *sap_parse_msg(uint8_t *data)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-  struct sap_msg *msg = talloc_zero(NULL, struct sap_msg);</span><br><span style="color: hsl(0, 100%, 40%);">-        uint8_t *ptr = data;</span><br><span style="color: hsl(0, 100%, 40%);">-    uint8_t i;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      if(!msg){</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%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       msg->id = *ptr++;</span><br><span style="color: hsl(0, 100%, 40%);">-    LOGP(DSAP, LOGL_INFO, "> %s \n", get_value_string(sap_msg_names, msg->id));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     msg->num_params = *ptr++;</span><br><span style="color: hsl(0, 100%, 40%);">-    /* skip two reserved null bytes, BTSAP 5.1 */</span><br><span style="color: hsl(0, 100%, 40%);">-   ptr += 2;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       msg->params = talloc_zero_size(NULL, sizeof(struct sap_param) * msg->num_params);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- for(i=0; i<msg->num_params; i++){</span><br><span style="color: hsl(0, 100%, 40%);">-         ptr = sap_get_param(ptr, &msg->params[i]);</span><br><span style="color: hsl(0, 100%, 40%);">-               LOGP(DSAP, LOGL_INFO, "> %s %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                         get_value_string(sap_param_names, msg->params[i].id),</span><br><span style="color: hsl(0, 100%, 40%);">-                                osmo_hexdump(msg->params[i].value, msg->params[i].len));</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 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%);">-static void sap_apdu_resp(struct osmocom_ms *ms, uint8_t *data, uint16_t len)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-      struct msgb *msg;</span><br><span style="color: hsl(0, 100%, 40%);">-       uint8_t *apdu;</span><br><span style="color: hsl(0, 100%, 40%);">-  msg = msgb_alloc(GSM_SAP_LENGTH, "osmosap");</span><br><span style="color: hsl(0, 100%, 40%);">-  if(!msg){</span><br><span style="color: hsl(0, 100%, 40%);">-               LOGP(DSAP, LOGL_ERROR, "Failed to allocate memory.\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%);">-       apdu = msgb_put(msg, len);</span><br><span style="color: hsl(0, 100%, 40%);">-      memcpy(apdu, data, len);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        LOGP(DSAP, LOGL_DEBUG, "Forwarding APDU to SIM handler.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-  sim_apdu_resp(ms, 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%);">-static int sap_adapt_msg_size(struct osmocom_ms *ms, struct sap_param *param)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-  uint16_t size;</span><br><span style="color: hsl(0, 100%, 40%);">-  size = (param->value[0] << 8) | param->value[1];</span><br><span style="color: hsl(0, 100%, 40%);">-    if(size != ms->sap_entity.max_msg_size && size > 0){</span><br><span style="color: hsl(0, 100%, 40%);">-              LOGP(DSAP, LOGL_NOTICE, "Server can not handle max_msg_size, adapting.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-           ms->sap_entity.max_msg_size = size;</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%);">-       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 sap_atr(struct osmocom_ms *ms)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-   struct msgb *msg;</span><br><span style="color: hsl(0, 100%, 40%);">-       if(ms->sap_entity.sap_state != SAP_IDLE){</span><br><span style="color: hsl(0, 100%, 40%);">-            LOGP(DSAP, LOGL_ERROR, "Attempting to send ATR request while not being idle.\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%);">-       msg = sap_create_msg(SAP_TRANSFER_ATR_REQ, 0, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-    if(!msg)</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%);">- osmosap_send(ms, msg);</span><br><span style="color: hsl(0, 100%, 40%);">-  ms->sap_entity.sap_state = SAP_PROCESSING_ATR_REQUEST;</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 sap_parse_resp(struct osmocom_ms *ms, uint8_t *data, uint16_t len)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-       struct sap_msg *msg;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    msg = sap_parse_msg(data);</span><br><span style="color: hsl(0, 100%, 40%);">-      if (!msg) {</span><br><span style="color: hsl(0, 100%, 40%);">-             LOGP(DSAP, LOGL_ERROR, "Failed to parse SAP message\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%);">-       switch(msg->id){</span><br><span style="color: hsl(0, 100%, 40%);">-     case SAP_CONNECT_RESP:</span><br><span style="color: hsl(0, 100%, 40%);">-          LOGP(DSAP, LOGL_INFO, "Status: %s\n", get_value_string(sap_status_names, msg->params[0].value[0]));</span><br><span style="color: hsl(0, 100%, 40%);">-                if(msg->params[0].value[0] == 0){</span><br><span style="color: hsl(0, 100%, 40%);">-                    ms->sap_entity.sap_state = SAP_IDLE;</span><br><span style="color: hsl(0, 100%, 40%);">-         }</span><br><span style="color: hsl(0, 100%, 40%);">-               if(msg->num_params == 2 && msg->params[1].len == 2){</span><br><span style="color: hsl(0, 100%, 40%);">-                      if(sap_adapt_msg_size(ms, &msg->params[1]) < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                             ms->sap_entity.sap_state = SAP_NOT_CONNECTED;</span><br><span style="color: hsl(0, 100%, 40%);">-                        } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                                sap_atr(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%);">-               break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case SAP_DISCONNECT_RESP:</span><br><span style="color: hsl(0, 100%, 40%);">-               ms->sap_entity.sap_state = SAP_NOT_CONNECTED;</span><br><span style="color: hsl(0, 100%, 40%);">-                break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case SAP_STATUS_IND:</span><br><span style="color: hsl(0, 100%, 40%);">-            LOGP(DSAP, LOGL_INFO, "New card state: %s\n", get_value_string(sap_status_change_names,</span><br><span style="color: hsl(0, 100%, 40%);">-                                       msg->params[0].value[0]));</span><br><span style="color: hsl(0, 100%, 40%);">-           if(msg->params[0].value[0] != 1){</span><br><span style="color: hsl(0, 100%, 40%);">-                    /* TODO: handle case in which the card is not ready yet */</span><br><span style="color: hsl(0, 100%, 40%);">-              }</span><br><span style="color: hsl(0, 100%, 40%);">-               break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case SAP_TRANSFER_ATR_RESP:</span><br><span style="color: hsl(0, 100%, 40%);">-             if(ms->sap_entity.sap_state != SAP_PROCESSING_ATR_REQUEST){</span><br><span style="color: hsl(0, 100%, 40%);">-                  LOGP(DSAP, LOGL_ERROR, "got ATR resp in state: %u\n", ms->sap_entity.sap_state);</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%);">-               if(msg->num_params >= 2){</span><br><span style="color: hsl(0, 100%, 40%);">-                 LOGP(DSAP, LOGL_INFO, "ATR: %s\n", osmo_hexdump(msg->params[1].value, msg->params[1].len));</span><br><span style="color: hsl(0, 100%, 40%);">-             }</span><br><span style="color: hsl(0, 100%, 40%);">-               ms->sap_entity.sap_state = SAP_IDLE;</span><br><span style="color: hsl(0, 100%, 40%);">-         break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case SAP_TRANSFER_APDU_RESP:</span><br><span style="color: hsl(0, 100%, 40%);">-            if(ms->sap_entity.sap_state != SAP_PROCESSING_APDU_REQUEST){</span><br><span style="color: hsl(0, 100%, 40%);">-                 LOGP(DSAP, LOGL_ERROR, "got APDU resp in state: %u\n", ms->sap_entity.sap_state);</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%);">-               if(msg->num_params != 2){</span><br><span style="color: hsl(0, 100%, 40%);">-                    LOGP(DSAP, LOGL_ERROR, "wrong number of parameters %u in APDU response\n", msg->num_params);</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%);">-               ms->sap_entity.sap_state = SAP_IDLE;</span><br><span style="color: hsl(0, 100%, 40%);">-         if(sap_parse_result(&msg->params[0]) == 0){</span><br><span style="color: hsl(0, 100%, 40%);">-                      /* back apdu resp to layer23 */</span><br><span style="color: hsl(0, 100%, 40%);">-                 sap_apdu_resp(ms, msg->params[1].value, msg->params[1].len);</span><br><span style="color: hsl(0, 100%, 40%);">-                      LOGP(DSAP, LOGL_INFO, "sap_apdu_resp called, sending data back to layer23\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                }</span><br><span style="color: hsl(0, 100%, 40%);">-               break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case SAP_ERROR_RESP:</span><br><span style="color: hsl(0, 100%, 40%);">-            if(ms->sap_entity.sap_state == SAP_CONNECTION_UNDER_NEGOTIATION){</span><br><span style="color: hsl(0, 100%, 40%);">-                    ms->sap_entity.sap_state = SAP_NOT_CONNECTED;</span><br><span style="color: hsl(0, 100%, 40%);">-                } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                        ms->sap_entity.sap_state = SAP_IDLE;</span><br><span style="color: hsl(0, 100%, 40%);">-         }</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%);">-                LOGP(DSAP, LOGL_ERROR, "got unknown or not implemented SAP msgid: %u\n", msg->id);</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%);">-static int sap_read(struct osmo_fd *fd)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-      struct msgb *msg = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-        struct osmocom_ms *ms = (struct osmocom_ms *) fd->data;</span><br><span style="color: hsl(0, 100%, 40%);">-      uint8_t *sap_buffer;</span><br><span style="color: hsl(0, 100%, 40%);">-    ssize_t rc;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     sap_buffer = talloc_zero_size(NULL, ms->sap_entity.max_msg_size);</span><br><span style="color: hsl(0, 100%, 40%);">-    if(!sap_buffer){</span><br><span style="color: hsl(0, 100%, 40%);">-                LOGP(DSAP, LOGL_ERROR, "Failed to allocate memory\n");</span><br><span style="color: hsl(120, 100%, 40%);">+      msg = sap_msgb_alloc(SAP_TRANSFER_ATR_REQ);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!msg)</span><br><span>            return -ENOMEM;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   rc = read(fd->fd, sap_buffer, ms->sap_entity.max_msg_size - 1);</span><br><span style="color: hsl(0, 100%, 40%);">-   if (rc < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                LOGP(DSAP, LOGL_ERROR,"SAP socket failed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+       rc = osmo_fsm_inst_dispatch(ms->sap_entity.fi,</span><br><span style="color: hsl(120, 100%, 40%);">+             SAP_TRANSFER_ATR_REQ, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (rc) {</span><br><span>            msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-         sap_close(ms);</span><br><span>               return rc;</span><br><span>   }</span><br><span style="color: hsl(0, 100%, 40%);">-       if(rc == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-           LOGP(DSAP, LOGL_NOTICE, "SAP socket closed by server\n");</span><br><span style="color: hsl(0, 100%, 40%);">-             msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-         sap_close(ms);</span><br><span style="color: hsl(0, 100%, 40%);">-          return -ECONNREFUSED;</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%);">-       sap_buffer[rc] = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-     LOGP(DSAP, LOGL_INFO, "Received %zd bytes: %s\n", rc, osmo_hexdump(sap_buffer, rc));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  sap_parse_resp(ms, sap_buffer, rc);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     talloc_free(sap_buffer);</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 sap_write(struct osmo_fd *fd, struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Send APDU request to the Server.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ms MS instance with active SAP connection</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] apdu APDU to be send</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] apdu_len length of APDU</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns 0 in case of success, negative in case of error</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int sap_send_apdu(struct osmocom_ms *ms, uint8_t *apdu, uint16_t apdu_len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct msgb *msg;</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%);">+     msg = sap_msgb_alloc(SAP_TRANSFER_APDU_REQ);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!msg)</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%);">+     sap_msgb_add_param(msg, SAP_COMMAND_APDU, apdu_len, apdu);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  rc = osmo_fsm_inst_dispatch(ms->sap_entity.fi,</span><br><span style="color: hsl(120, 100%, 40%);">+             SAP_TRANSFER_APDU_REQ, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+             msgb_free(msg);</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%);">+   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%);">+/*! Send (SIM) power on request to the Server.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ms MS instance with active SAP connection</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns 0 in case of success, negative in case of error</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int sap_send_poweron_req(struct osmocom_ms *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg;</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%);">+     msg = sap_msgb_alloc(SAP_POWER_SIM_ON_REQ);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!msg)</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%);">+     rc = osmo_fsm_inst_dispatch(ms->sap_entity.fi,</span><br><span style="color: hsl(120, 100%, 40%);">+             SAP_POWER_SIM_ON_REQ, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+             msgb_free(msg);</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%);">+   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%);">+/*! Send (SIM) power off request to the Server.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ms MS instance with active SAP connection</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns 0 in case of success, negative in case of error</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int sap_send_poweroff_req(struct osmocom_ms *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct msgb *msg;</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%);">+     msg = sap_msgb_alloc(SAP_POWER_SIM_OFF_REQ);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!msg)</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%);">+     rc = osmo_fsm_inst_dispatch(ms->sap_entity.fi,</span><br><span style="color: hsl(120, 100%, 40%);">+             SAP_POWER_SIM_OFF_REQ, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+             msgb_free(msg);</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%);">+   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 sap_read_cb(struct osmo_fd *fd)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmocom_ms *ms = (struct osmocom_ms *) fd->data;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct osmosap_entity *sap = &ms->sap_entity;</span><br><span style="color: hsl(120, 100%, 40%);">+  const struct sap_message *sap_msg;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t buf[GSM_SAP_LENGTH];</span><br><span style="color: hsl(120, 100%, 40%);">+  ssize_t rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Prevent buffer overflow */</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(sap->max_msg_size <= GSM_SAP_LENGTH);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     rc = read(fd->fd, buf, sap->max_msg_size);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGP(DSAP, LOGL_ERROR, "SAP socket failed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              rc = -EIO;</span><br><span style="color: hsl(120, 100%, 40%);">+            goto error;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (rc == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGP(DSAP, LOGL_NOTICE, "SAP socket closed by server\n");</span><br><span style="color: hsl(120, 100%, 40%);">+           rc = -ECONNREFUSED;</span><br><span style="color: hsl(120, 100%, 40%);">+           goto 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%);">+   LOGP(DSAP, LOGL_DEBUG, "RX SAP message (len=%zd): %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+            rc, osmo_hexdump(buf, rc));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Parse SAP message */</span><br><span style="color: hsl(120, 100%, 40%);">+       sap_msg = sap_msg_parse(buf, rc);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!sap_msg) {</span><br><span style="color: hsl(120, 100%, 40%);">+               LOGP(DSAP, LOGL_ERROR, "Failed to parse SAP message\n");</span><br><span style="color: hsl(120, 100%, 40%);">+            return -EINVAL;</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%);">+   /* Pass received message to our FSM using message</span><br><span style="color: hsl(120, 100%, 40%);">+      * type as the FSM event name */</span><br><span style="color: hsl(120, 100%, 40%);">+      osmo_fsm_inst_dispatch(sap->fi, sap_msg->msg_id, sap_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%);">+error:</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Immediately tear-down FSM */</span><br><span style="color: hsl(120, 100%, 40%);">+       osmo_fsm_inst_state_chg(sap->fi, SAP_STATE_NOT_CONNECTED, 0, 0);</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 int sap_write_cb(struct osmo_fd *fd, struct msgb *msg)</span><br><span> {</span><br><span>  ssize_t rc;</span><br><span> </span><br><span>      if (fd->fd <= 0)</span><br><span>               return -EINVAL;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     LOGP(DSAP, LOGL_INFO, "< %s\n", osmo_hexdump(msg->data, msg->len));</span><br><span>       rc = write(fd->fd, msg->data, msg->len);</span><br><span>    if (rc != msg->len) {</span><br><span style="color: hsl(0, 100%, 40%);">-                LOGP(DSAP, LOGL_ERROR, "Failed to write data: rc: %zd\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGP(DSAP, LOGL_ERROR, "Failed to write data\n");</span><br><span>          return rc;</span><br><span>   }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DSAP, LOGL_DEBUG, "TX SAP message (len=%u): %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+             msg->len, osmo_hexdump(msg->data, msg->len));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>     return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void sap_connect(struct osmocom_ms *ms)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-       uint8_t buffer[3];</span><br><span style="color: hsl(0, 100%, 40%);">-      struct msgb *msg;</span><br><span style="color: hsl(0, 100%, 40%);">-       uint16_t size = ms->sap_entity.max_msg_size;</span><br><span style="color: hsl(0, 100%, 40%);">- struct sap_param params[1];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     params[0].id = SAP_MAX_MSG_SIZE;</span><br><span style="color: hsl(0, 100%, 40%);">-        params[0].len = 2;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      if(ms->sap_entity.sap_state != SAP_NOT_CONNECTED) {</span><br><span style="color: hsl(0, 100%, 40%);">-          LOGP(DSAP, LOGL_ERROR, "Attempting to connect while there is an active connection.\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%);">-       buffer[0] = (size >> 8) & 0xFF;</span><br><span style="color: hsl(0, 100%, 40%);">-       buffer[1] = size & 0xFF;</span><br><span style="color: hsl(0, 100%, 40%);">-    buffer[2] = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-  params[0].value = buffer;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       msg = sap_create_msg(SAP_CONNECT_REQ, 1, params);</span><br><span style="color: hsl(0, 100%, 40%);">-       if(!msg)</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%);">- osmosap_send(ms, msg);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  ms->sap_entity.sap_state = SAP_CONNECTION_UNDER_NEGOTIATION;</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 sap_disconnect(struct osmocom_ms *ms)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-      struct msgb *msg;</span><br><span style="color: hsl(0, 100%, 40%);">-       if(ms->sap_entity.sap_state != SAP_NOT_CONNECTED && ms->sap_entity.sap_state != SAP_CONNECTION_UNDER_NEGOTIATION){</span><br><span style="color: hsl(0, 100%, 40%);">-                LOGP(DSAP, LOGL_ERROR, "Attempting to disconnect while no active connection.\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%);">-       msg = sap_create_msg(SAP_DISCONNECT_REQ, 0, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-      if(!msg)</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%);">- osmosap_send(ms, msg);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  ms->sap_entity.sap_state = SAP_NOT_CONNECTED;</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 sap_apdu(struct osmocom_ms *ms, uint8_t *data, uint16_t len)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-       struct msgb *msg;</span><br><span style="color: hsl(0, 100%, 40%);">-       struct sap_param params[1];</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%);">- params[0].id = SAP_COMMAND_APDU;</span><br><span style="color: hsl(0, 100%, 40%);">-        params[0].len = len;</span><br><span style="color: hsl(0, 100%, 40%);">-    params[0].value = data;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if(ms->sap_entity.sap_state != SAP_IDLE){</span><br><span style="color: hsl(0, 100%, 40%);">-            LOGP(DSAP, LOGL_ERROR, "Attempting to send APDU request while not being idle.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-            return -EIO;</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%);">-       msg = sap_create_msg(SAP_TRANSFER_APDU_REQ, 1, params);</span><br><span style="color: hsl(0, 100%, 40%);">- if(!msg)</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%);">- rc = osmosap_send(ms, msg);</span><br><span style="color: hsl(0, 100%, 40%);">-     if (rc)</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%);">-      ms->sap_entity.sap_state = SAP_PROCESSING_APDU_REQUEST;</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(120, 100%, 40%);">+/*! Establishes SAP connection to the Server,</span><br><span style="color: hsl(120, 100%, 40%);">+ *  allocates SAP FSM, and triggers connection procedure.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ms MS instance with configured SAP socket path</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns 0 in case of success, negative in case of error</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span> int sap_open(struct osmocom_ms *ms)</span><br><span> {</span><br><span>     int rc;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+   LOGP(DSAP, LOGL_INFO, "Establishing SAP connection "</span><br><span style="color: hsl(120, 100%, 40%);">+                "(using socket '%s')\n", ms->settings.sap_socket_path);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>       rc = osmo_sock_unix_init_ofd(&ms->sap_wq.bfd, SOCK_STREAM, 0,</span><br><span>                 ms->settings.sap_socket_path, OSMO_SOCK_F_CONNECT);</span><br><span>       if (rc < 0) {</span><br><span>             LOGP(DSAP, LOGL_ERROR, "Failed to create unix domain socket %s: %s\n",</span><br><span>                  ms->settings.sap_socket_path, strerror(-rc));</span><br><span style="color: hsl(0, 100%, 40%);">-           ms->sap_entity.sap_state = SAP_SOCKET_ERROR;</span><br><span>              return rc;</span><br><span>   }</span><br><span> </span><br><span>        osmo_wqueue_init(&ms->sap_wq, 100);</span><br><span>   ms->sap_wq.bfd.data = ms;</span><br><span style="color: hsl(0, 100%, 40%);">-    ms->sap_wq.read_cb = sap_read;</span><br><span style="color: hsl(0, 100%, 40%);">-       ms->sap_wq.write_cb = sap_write;</span><br><span style="color: hsl(120, 100%, 40%);">+   ms->sap_wq.read_cb = &sap_read_cb;</span><br><span style="color: hsl(120, 100%, 40%);">+     ms->sap_wq.write_cb = &sap_write_cb;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- sap_connect(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Allocate a SAP FSM for a given ms */</span><br><span style="color: hsl(120, 100%, 40%);">+       rc = sap_fsm_alloc(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+             _sap_close_sock(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+          return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Initiate SAP connection with Server */</span><br><span style="color: hsl(120, 100%, 40%);">+     LOGP(DSAP, LOGL_DEBUG, "Connecting to the Server...\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    return osmo_fsm_inst_state_chg(ms->sap_entity.fi, SAP_STATE_CONNECTING,</span><br><span style="color: hsl(120, 100%, 40%);">+            SAP_FSM_CONN_EST_TIMEOUT, SAP_FSM_CONN_EST_T);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Closes SAP connection with the Server.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ms MS instance with active SAP connection</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns 0 in case of success, negative in case of error</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span> int sap_close(struct osmocom_ms *ms)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+   if (ms->sap_entity.fi == NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+           LOGP(DSAP, LOGL_NOTICE, "No active SAP connection (no FSM)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+             return -EINVAL;</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%);">+   LOGP(DSAP, LOGL_INFO, "Closing SAP connection\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  return osmo_fsm_inst_dispatch(ms->sap_entity.fi,</span><br><span style="color: hsl(120, 100%, 40%);">+           SAP_DISCONNECT_REQ, 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%);">+/*! Low-level function for closing SAP (socket) connection.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ms MS instance with active SAP connection</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns 0 in case of success, negative in case of error</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int _sap_close_sock(struct osmocom_ms *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span>       if (ms->sap_wq.bfd.fd <= 0)</span><br><span>            return -EINVAL;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     sap_disconnect(ms);</span><br><span>  close(ms->sap_wq.bfd.fd);</span><br><span>         ms->sap_wq.bfd.fd = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>         osmo_fd_unregister(&ms->sap_wq.bfd);</span><br><span>  osmo_wqueue_clear(&ms->sap_wq);</span><br><span> </span><br><span>   return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* same signature as in L1CTL, so it can be called from sim.c */</span><br><span style="color: hsl(0, 100%, 40%);">-int osmosap_send_apdu(struct osmocom_ms *ms, uint8_t *data, uint16_t length)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- //LOGP(DSAP, LOGL_ERROR, "Received the following APDU from sim.c: %s\n" ,</span><br><span style="color: hsl(0, 100%, 40%);">-     //     osmo_hexdump(data, length));</span><br><span style="color: hsl(0, 100%, 40%);">-     return sap_apdu(ms, data, length);</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%);">-/* init */</span><br><span style="color: hsl(0, 100%, 40%);">-int osmosap_init(struct osmocom_ms *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Initiates SAP client state for a given MS. */</span><br><span style="color: hsl(120, 100%, 40%);">+void sap_init(struct osmocom_ms *ms)</span><br><span> {</span><br><span>   struct osmosap_entity *sap = &ms->sap_entity;</span><br><span> </span><br><span>     LOGP(DSAP, LOGL_INFO, "init SAP client\n");</span><br><span style="color: hsl(0, 100%, 40%);">-   sap->sap_state = SAP_NOT_CONNECTED;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Default MaxMsgSize (to be negotiated) */</span><br><span>  sap->max_msg_size = GSM_SAP_LENGTH;</span><br><span style="color: hsl(120, 100%, 40%);">+        /* SIM card status is not known yet */</span><br><span style="color: hsl(120, 100%, 40%);">+        sap->card_status = SAP_CARD_STATUS_CARD_NOT_ACC;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Optional event call-backs */</span><br><span style="color: hsl(120, 100%, 40%);">+       sap->idle_cb = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+       sap->rel_cb = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+        sap->apdu_cb = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+       sap->atr_cb = NULL;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>diff --git a/src/host/layer23/src/common/sap_proto.c b/src/host/layer23/src/common/sap_proto.c</span><br><span>new file mode 100644</span><br><span>index 0000000..b170eb6</span><br><span>--- /dev/null</span><br><span>+++ b/src/host/layer23/src/common/sap_proto.c</span><br><span>@@ -0,0 +1,271 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * SAP (SIM Access Profile) protocol definition</span><br><span style="color: hsl(120, 100%, 40%);">+ * based on Bluetooth SAP specification</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2011 by Nico Golde <nico@ngolde.de></span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2018 by Vadim Yanitskiy <axilirator@gmail.com></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%);">+ * 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 <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.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 <arpa/inet.h></span><br><span style="color: hsl(120, 100%, 40%);">+</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/talloc.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/msgb.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bb/common/sap_proto.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bb/common/logging.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Table 5.15: List of Parameter IDs */</span><br><span style="color: hsl(120, 100%, 40%);">+const struct value_string sap_param_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ { SAP_MAX_MSG_SIZE,             "MaxMsgSize" },</span><br><span style="color: hsl(120, 100%, 40%);">+     { SAP_CONNECTION_STATUS,        "ConnectionStatus" },</span><br><span style="color: hsl(120, 100%, 40%);">+       { SAP_RESULT_CODE,              "ResultCode" },</span><br><span style="color: hsl(120, 100%, 40%);">+     { SAP_DISCONNECTION_TYPE,       "DisconnectionType" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { SAP_COMMAND_APDU,             "CommandAPDU" },</span><br><span style="color: hsl(120, 100%, 40%);">+    { SAP_COMMAND_APDU_7816,        "CommandAPDU7816" },</span><br><span style="color: hsl(120, 100%, 40%);">+        { SAP_RESPONSE_APDU,            "ResponseAPDU" },</span><br><span style="color: hsl(120, 100%, 40%);">+   { SAP_ATR,                      "ATR" },</span><br><span style="color: hsl(120, 100%, 40%);">+    { SAP_CARD_READER_STATUS,       "CardReaderStatus" },</span><br><span style="color: hsl(120, 100%, 40%);">+       { SAP_STATUS_CHANGE,            "StatusChange" },</span><br><span style="color: hsl(120, 100%, 40%);">+   { SAP_TRANSPORT_PROTOCOL,       "TransportProtocol" },</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%);">+/* Table 5.1: Message Overview */</span><br><span style="color: hsl(120, 100%, 40%);">+const struct value_string sap_msg_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+      { SAP_CONNECT_REQ,                      "CONNECT_REQ" },</span><br><span style="color: hsl(120, 100%, 40%);">+    { SAP_CONNECT_RESP,                     "CONNECT_RESP" },</span><br><span style="color: hsl(120, 100%, 40%);">+   { SAP_DISCONNECT_REQ,                   "DISCONNECT_REQ" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { SAP_DISCONNECT_RESP,                  "DISCONNECT_RESP" },</span><br><span style="color: hsl(120, 100%, 40%);">+        { SAP_DISCONNECT_IND,                   "DISCONNECT_IND" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { SAP_TRANSFER_APDU_REQ,                "TRANSFER_APDU_REQ" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { SAP_TRANSFER_APDU_RESP,               "TRANSFER_APDU_RESP" },</span><br><span style="color: hsl(120, 100%, 40%);">+     { SAP_TRANSFER_ATR_REQ,                 "TRANSFER_ATR_REQ" },</span><br><span style="color: hsl(120, 100%, 40%);">+       { SAP_TRANSFER_ATR_RESP,                "TRANSFER_ATR_RESP" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { SAP_POWER_SIM_OFF_REQ,                "POWER_SIM_OFF_REQ" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { SAP_POWER_SIM_OFF_RESP,               "POWER_SIM_OFF_RESP" },</span><br><span style="color: hsl(120, 100%, 40%);">+     { SAP_POWER_SIM_ON_REQ,                 "POWER_SIM_ON_REQ" },</span><br><span style="color: hsl(120, 100%, 40%);">+       { SAP_POWER_SIM_ON_RESP,                "POWER_SIM_ON_RESP" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { SAP_RESET_SIM_REQ,                    "RESET_SIM_REQ" },</span><br><span style="color: hsl(120, 100%, 40%);">+  { SAP_RESET_SIM_RESP,                   "RESET_SIM_RESP" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { SAP_TRANSFER_CARD_READER_STATUS_REQ,  "TRANSFER_CARD_READER_STATUS_REQ" },</span><br><span style="color: hsl(120, 100%, 40%);">+        { SAP_TRANSFER_CARD_READER_STATUS_RESP, "TRANSFER_CARD_READER_STATUS_RESP" },</span><br><span style="color: hsl(120, 100%, 40%);">+       { SAP_STATUS_IND,                       "STATUS_IND" },</span><br><span style="color: hsl(120, 100%, 40%);">+     { SAP_ERROR_RESP,                       "ERROR_RESP" },</span><br><span style="color: hsl(120, 100%, 40%);">+     { SAP_SET_TRANSPORT_PROTOCOL_REQ,       "SET_TRANSPORT_PROTOCOL_REQ" },</span><br><span style="color: hsl(120, 100%, 40%);">+     { SAP_SET_TRANSPORT_PROTOCOL_RESP,      "SET_TRANSPORT_PROTOCOL_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%);">+/* Table 5.18: Possible values for ResultCode */</span><br><span style="color: hsl(120, 100%, 40%);">+const struct value_string sap_result_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+  { SAP_RESULT_OK_REQ_PROC_CORR,          "OK, request processed correctly" },</span><br><span style="color: hsl(120, 100%, 40%);">+        { SAP_RESULT_ERROR_NO_REASON,           "Error, no reason defined" },</span><br><span style="color: hsl(120, 100%, 40%);">+       { SAP_RESULT_ERROR_CARD_NOT_ACC,        "Error, card not accessible" },</span><br><span style="color: hsl(120, 100%, 40%);">+     { SAP_RESULT_ERROR_CARD_POWERED_OFF,    "Error, card (already) powered off" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { SAP_RESULT_ERROR_CARD_REMOVED,        "Error, card removed" },</span><br><span style="color: hsl(120, 100%, 40%);">+    { SAP_RESULT_ERROR_CARD_POWERED_ON,     "Error, card already powered on" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { SAP_RESULT_ERROR_DATA_UNAVAIL,        "Error, data not available" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { SAP_RESULT_ERROR_NOT_SUPPORTED,       "Error, 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%);">+/* Table 5.19: Possible values for StatusChange */</span><br><span style="color: hsl(120, 100%, 40%);">+const struct value_string sap_card_status_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+   { SAP_CARD_STATUS_UNKNOWN_ERROR,        "Unknown Error" },</span><br><span style="color: hsl(120, 100%, 40%);">+  { SAP_CARD_STATUS_CARD_RESET,           "Card reset" },</span><br><span style="color: hsl(120, 100%, 40%);">+     { SAP_CARD_STATUS_CARD_NOT_ACC,         "Card not accessible" },</span><br><span style="color: hsl(120, 100%, 40%);">+    { SAP_CARD_STATUS_CARD_REMOVED,         "Card removed" },</span><br><span style="color: hsl(120, 100%, 40%);">+   { SAP_CARD_STATUS_CARD_INSERTED,        "Card inserted" },</span><br><span style="color: hsl(120, 100%, 40%);">+  { SAP_CARD_STATUS_CARD_RECOVERED,       "Card recovered" },</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%);">+/* Table 5.16: Possible values for ConnectionStatus */</span><br><span style="color: hsl(120, 100%, 40%);">+const struct value_string sap_conn_status_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+    { SAP_CONN_STATUS_OK_READY,             "OK, Server can fulfill requirements" },</span><br><span style="color: hsl(120, 100%, 40%);">+    { SAP_CONN_STATUS_ERROR_CONN,           "Error, Server unable to establish connection" },</span><br><span style="color: hsl(120, 100%, 40%);">+   { SAP_CONN_STATUS_ERROR_MAX_MSG_SIZE,   "Error, Server does not support maximum message size" },</span><br><span style="color: hsl(120, 100%, 40%);">+    { SAP_CONN_STATUS_ERROR_SMALL_MSG_SIZE, "Error, maximum message size by Client is too small" },</span><br><span style="color: hsl(120, 100%, 40%);">+     { SAP_CONN_STATUS_OK_CALL,              "OK, ongoing call" },</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 msgb *sap_msgb_alloc(uint8_t msg_id)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct sap_message *sap_msg;</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%);">+   msg = msgb_alloc(GSM_SAP_LENGTH, "sap_msg");</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!msg) {</span><br><span style="color: hsl(120, 100%, 40%);">+           LOGP(DSAP, LOGL_ERROR, "Failed to allocate SAP message\n");</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%);">+   sap_msg = (struct sap_message *) msgb_put(msg, sizeof(*sap_msg));</span><br><span style="color: hsl(120, 100%, 40%);">+     sap_msg->msg_id = msg_id;</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%);">+void sap_msgb_add_param(struct msgb *msg,</span><br><span style="color: hsl(120, 100%, 40%);">+   enum sap_param_type param_type,</span><br><span style="color: hsl(120, 100%, 40%);">+       uint16_t param_len, uint8_t *param_value)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct sap_message *sap_msg;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct sap_param *param;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t padding;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t *buf;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Update number of parameters */</span><br><span style="color: hsl(120, 100%, 40%);">+     sap_msg = (struct sap_message *) msg->data;</span><br><span style="color: hsl(120, 100%, 40%);">+        sap_msg->num_params++;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Allocate a new parameter */</span><br><span style="color: hsl(120, 100%, 40%);">+        param = (struct sap_param *) msgb_put(msg, sizeof(*param));</span><br><span style="color: hsl(120, 100%, 40%);">+   param->param_id = param_type;</span><br><span style="color: hsl(120, 100%, 40%);">+      param->reserved[0] = 0x00;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Encode parameter value and length */</span><br><span style="color: hsl(120, 100%, 40%);">+       param->length = htons(param_len);</span><br><span style="color: hsl(120, 100%, 40%);">+  buf = msgb_put(msg, param_len);</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(buf, param_value, param_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Optional padding */</span><br><span style="color: hsl(120, 100%, 40%);">+        padding = 4 - (param_len % 4);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (padding) {</span><br><span style="color: hsl(120, 100%, 40%);">+                buf = msgb_put(msg, padding);</span><br><span style="color: hsl(120, 100%, 40%);">+         memset(buf, 0x00, padding);</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%);">+struct sap_param *sap_get_param(const struct sap_message *sap_msg,</span><br><span style="color: hsl(120, 100%, 40%);">+    enum sap_param_type param_type, uint16_t *param_len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       const uint8_t *ptr = sap_msg->payload;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct sap_param *param = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+       uint16_t plen;</span><br><span style="color: hsl(120, 100%, 40%);">+        int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* We assume that message is parsed already,</span><br><span style="color: hsl(120, 100%, 40%);">+   * so we don't check for buffer overflows */</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = 0; i < sap_msg->num_params; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Parse one parameter */</span><br><span style="color: hsl(120, 100%, 40%);">+             param = (struct sap_param *) ptr;</span><br><span style="color: hsl(120, 100%, 40%);">+             plen = ntohs(param->length);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Match against a given ID */</span><br><span style="color: hsl(120, 100%, 40%);">+                if (param->param_id == param_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       if (param_len != NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+                                *param_len = plen;</span><br><span style="color: hsl(120, 100%, 40%);">+                    return param;</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%);">+           /* Shift pointer to the next parameter */</span><br><span style="color: hsl(120, 100%, 40%);">+             ptr += sizeof(*param) + plen;</span><br><span style="color: hsl(120, 100%, 40%);">+         /* Optional padding */</span><br><span style="color: hsl(120, 100%, 40%);">+                ptr += 4 - (plen % 4);</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 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%);">+const struct sap_message *sap_msg_parse(const uint8_t *buf, size_t buf_len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     const struct sap_message *sap_msg;</span><br><span style="color: hsl(120, 100%, 40%);">+    const uint8_t *ptr;</span><br><span style="color: hsl(120, 100%, 40%);">+   int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Message header is mandatory */</span><br><span style="color: hsl(120, 100%, 40%);">+     if (buf_len < sizeof(*sap_msg)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          LOGP(DSAP, LOGL_ERROR, "Missing SAP message header\n");</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%);">+   sap_msg = (const struct sap_message *) buf;</span><br><span style="color: hsl(120, 100%, 40%);">+   buf_len -= sizeof(*sap_msg);</span><br><span style="color: hsl(120, 100%, 40%);">+  ptr = sap_msg->payload;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  LOGP(DSAP, LOGL_DEBUG, "SAP message '%s' has %u parameter(s)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+            get_value_string(sap_msg_names, sap_msg->msg_id),</span><br><span style="color: hsl(120, 100%, 40%);">+          sap_msg->num_params);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    for (i = 0; i < sap_msg->num_params; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+             struct sap_param *param;</span><br><span style="color: hsl(120, 100%, 40%);">+              uint16_t param_len;</span><br><span style="color: hsl(120, 100%, 40%);">+           uint16_t offset;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            /* Prevent buffer overflow */</span><br><span style="color: hsl(120, 100%, 40%);">+         if (buf_len < sizeof(*param))</span><br><span style="color: hsl(120, 100%, 40%);">+                      goto malformed;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Parse one parameter */</span><br><span style="color: hsl(120, 100%, 40%);">+             param = (struct sap_param *) ptr;</span><br><span style="color: hsl(120, 100%, 40%);">+             param_len = ntohs(param->length);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGP(DSAP, LOGL_DEBUG, "SAP parameter '%s' (len=%u): %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                 get_value_string(sap_param_names, param->param_id),</span><br><span style="color: hsl(120, 100%, 40%);">+                        param_len, osmo_hexdump(param->value, param_len));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               /* Calculate relative offset */</span><br><span style="color: hsl(120, 100%, 40%);">+               offset  = sizeof(*param) + param_len;</span><br><span style="color: hsl(120, 100%, 40%);">+         offset += 4 - (param_len % 4); /* Optional padding */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               /* Prevent buffer overflow */</span><br><span style="color: hsl(120, 100%, 40%);">+         if (offset > buf_len)</span><br><span style="color: hsl(120, 100%, 40%);">+                      goto malformed;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             buf_len -= offset;</span><br><span style="color: hsl(120, 100%, 40%);">+            ptr += offset;</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 sap_msg;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+malformed:</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DSAP, LOGL_ERROR, "Malformed SAP message "</span><br><span style="color: hsl(120, 100%, 40%);">+             "(parameter %i/%u)\n", i + 1, sap_msg->num_params);</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%);">+int sap_check_result_code(const struct sap_message *sap_msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct sap_param *param;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint16_t param_len;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t res_code;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   param = sap_get_param(sap_msg, SAP_RESULT_CODE, &param_len);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!param || param_len != sizeof(res_code)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGP(DSAP, LOGL_ERROR, "Missing mandatory '%s' parameter\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                        get_value_string(sap_param_names, SAP_RESULT_CODE));</span><br><span style="color: hsl(120, 100%, 40%);">+          return -EINVAL;</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%);">+   res_code = param->value[0];</span><br><span style="color: hsl(120, 100%, 40%);">+        if (res_code > ARRAY_SIZE(sap_result_names)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             LOGP(DSAP, LOGL_ERROR, "Unknown SAP ResultCode=0x%02x\n", res_code);</span><br><span style="color: hsl(120, 100%, 40%);">+                return -EINVAL;</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%);">+   LOGP(DSAP, LOGL_DEBUG, "SAP ResultCode is '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+          get_value_string(sap_result_names, res_code));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return res_code;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/host/layer23/src/common/sim.c b/src/host/layer23/src/common/sim.c</span><br><span>index 9d14cd3..a63ae2a 100644</span><br><span>--- a/src/host/layer23/src/common/sim.c</span><br><span>+++ b/src/host/layer23/src/common/sim.c</span><br><span>@@ -205,7 +205,7 @@</span><br><span>    * it makes more sense to do it here then in L1CTL */</span><br><span>        if (ms->subscr.sim_type == GSM_SIM_TYPE_SAP) {</span><br><span>            LOGP(DSIM, LOGL_INFO, "Using SAP backend\n");</span><br><span style="color: hsl(0, 100%, 40%);">-         rc = osmosap_send_apdu(ms, data, length);</span><br><span style="color: hsl(120, 100%, 40%);">+             rc = sap_send_apdu(ms, data, length);</span><br><span>        } else {</span><br><span>             LOGP(DSIM, LOGL_INFO, "Using built-in SIM reader\n");</span><br><span>              rc = l1ctl_tx_sim_req(ms, data, length);</span><br><span>diff --git a/src/host/layer23/src/mobile/app_mobile.c b/src/host/layer23/src/mobile/app_mobile.c</span><br><span>index 17c0c76..1f473a7 100644</span><br><span>--- a/src/host/layer23/src/mobile/app_mobile.c</span><br><span>+++ b/src/host/layer23/src/mobile/app_mobile.c</span><br><span>@@ -200,7 +200,11 @@</span><br><span>         lapdm_channel_set_l1(&ms->lapdm_channel, l1ctl_ph_prim_cb, ms);</span><br><span> </span><br><span>   /* init SAP client before SIM card starts up */</span><br><span style="color: hsl(0, 100%, 40%);">- osmosap_init(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+     sap_init(ms);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* TODO: remove SIM card on sap_entity.rel_cb() */</span><br><span style="color: hsl(120, 100%, 40%);">+    ms->sap_entity.idle_cb = &subscr_sim_request;</span><br><span style="color: hsl(120, 100%, 40%);">+  ms->sap_entity.apdu_cb = &sim_apdu_resp;</span><br><span> </span><br><span>  gsm_sim_init(ms);</span><br><span>    gsm48_cc_init(ms);</span><br><span>diff --git a/src/host/layer23/src/mobile/subscriber.c b/src/host/layer23/src/mobile/subscriber.c</span><br><span>index b2be554..e8c0ae3 100644</span><br><span>--- a/src/host/layer23/src/mobile/subscriber.c</span><br><span>+++ b/src/host/layer23/src/mobile/subscriber.c</span><br><span>@@ -544,7 +544,7 @@</span><br><span> };</span><br><span> </span><br><span> /* request file from SIM */</span><br><span style="color: hsl(0, 100%, 40%);">-static int subscr_sim_request(struct osmocom_ms *ms)</span><br><span style="color: hsl(120, 100%, 40%);">+int subscr_sim_request(struct osmocom_ms *ms)</span><br><span> {</span><br><span>       struct gsm_subscriber *subscr = &ms->subscr;</span><br><span>  struct subscr_sim_file *sf = &subscr_sim_files[subscr->sim_file_index];</span><br><span>@@ -1275,6 +1275,7 @@</span><br><span>       gsm_subscr_exit(ms);</span><br><span>         gsm_subscr_init(ms);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+      subscr->ustate = GSM_SIM_U2_NOT_UPDATED;</span><br><span>  subscr->sim_type = GSM_SIM_TYPE_SAP;</span><br><span>      sprintf(subscr->sim_name, "sap");</span><br><span>       subscr->sim_valid = 1;</span><br><span>@@ -1297,8 +1298,6 @@</span><br><span> </span><br><span>                return rc;</span><br><span>   }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return 0;</span><br><span> }</span><br><span> </span><br><span> /* Deattach sapcard */</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/12441">change 12441</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/12441"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmocom-bb </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I77bb108615bb2c94c441568f195b04e0a5421643 </div>
<div style="display:none"> Gerrit-Change-Number: 12441 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Vadim Yanitskiy <axilirator@gmail.com> </div>