Hi Denis,

On 27/09/2019 00.10, Denis Kenzior wrote:
On 9/26/19 2:27 PM, Martin Hundebøll wrote:
Simplify sim handling by querying cpin state directly from
quectel_pre_sim().

Don't initiate commands from pre_sim/post_sim/post_online callbacks please.  There's almost never a reason to.

Ok.


The query is conducted by issuing a AT+CPIN?, where only CME errors are
catched by the command response handler. The +CPIN: <state> response is
instead catched by a listener.

nit: s/catched/caught


The CME handler allows proper handling of the sim-busy and sim-not-
inserted states, which are returned as CME errors by the quectel
modems.

The +CPIN listener allows handling of both sim-locked and sim-ready
states. When the sim is not locked, the listener catches the +CPIN:
READY response from the query in quectel_pre_sim(). If the sim is
locked, the listener catched the +CPIN: READY indication received after
unlocking the sim.
---
  plugins/quectel.c | 401 +++++++++++++++++-----------------------------
  1 file changed, 149 insertions(+), 252 deletions(-)


<snip>

@@ -751,9 +534,8 @@ static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
      }
      dbus_hw_enable(modem);
-
-    g_at_chat_send(data->aux, "AT+CPIN?", cpin_prefix, cpin_query, modem,
-            NULL);
+    g_at_chat_send(data->aux, "AT+CFUN=4", none_prefix, NULL, NULL, NULL);

Don't you want to wait until this succeeds?

Might as well.

Also, you could issue a query for CPIN here and record whether the sim is inserted.  I assume no hot-swap of SIM is supported?

+    ofono_modem_set_powered(modem, true);
  }
  static void cfun_query(gboolean ok, GAtResult *result, gpointer user_data)

<snip>

+
+    if (ofono_sim_get_state(data->sim) == OFONO_SIM_STATE_INSERTED)
+        ofono_sim_initialized_notify(data->sim);
+    else
+        ofono_sim_inserted_notify(data->sim, true);

This is a strange dance.  Shouldn't the modem tell you up front that the SIM is inserted or not?  So then you only need to run QINISTAT when it goes from pin locked to unlocked?

These modems are really picky about when to do what.

If the sim is locked, we need to do some initial work to enable entering the pin.

If it is not, then we really need to wait with reading sim files until qinistat is ready.

I've made another attempt in the v2 sim-rework patch.

+}
+
+static void init_timer_cb(struct l_timeout *timeout, void *user_data)
+{
+    struct ofono_modem *modem = user_data;
+    struct quectel_data *data = ofono_modem_get_data(modem);
+
+    DBG("%p", modem);
+
+    g_at_chat_send(data->aux, "AT+QINISTAT", qinistat_prefix, qinistat_cb,
+            modem, NULL);
+}
+
+static void sim_watch_cb(GAtResult *result, void *user_data)
+{
+    struct ofono_modem *modem = user_data;
+    struct quectel_data *data = ofono_modem_get_data(modem);
+    enum ofono_sim_state state = ofono_sim_get_state(data->sim);
+    const char *path = ofono_modem_get_path(modem);
+    GAtResultIter iter;
+    const char *cpin;
+
+    DBG("%p", modem);
+
+    g_at_result_iter_init(&iter, result);
+
+    if (!g_at_result_iter_next(&iter, "+CPIN:"))
          return;
-    switch (data->sim_state) {
-    case OFONO_SIM_STATE_LOCKED_OUT:
-    case OFONO_SIM_STATE_READY:
+    g_at_result_iter_next_unquoted_string(&iter, &cpin);
+
+    if (g_strcmp0(cpin, "NOT INSERTED") == 0) {
+        ofono_warn("%s: sim not present", path);
+        return;
+    }
+
+    if (g_strcmp0(cpin, "READY") != 0) {
+        if (state != OFONO_SIM_STATE_INSERTED) {
+            ofono_info("%s: sim locked", path);
+            ofono_sim_inserted_notify(data->sim, true);

Okay, but  it might be easier to just know this up front whether the sim is inserted or not.

I think I am getting close in the v2 patch.

+        }
+
+        return;
+    }
+
+    g_at_chat_unregister(data->aux, data->sim_watch);
+    data->sim_watch = 0;
+
+    data->init_timeout = l_timeout_create_ms(500, init_timer_cb, modem, NULL);
+    if (!data->init_timeout) {
+        close_serial(modem);
+        return;
+    }

So then this READY case becomes simple.  Didn't you also say that Quectel sends +CPIN: READY unsolicited?

It does, but we might miss the initial one during the retry-dance after powerup, or if ofono is started long after the modem is initialized (sans gpio).

It does send a +CPIN: READY after the pin is entered, though.

+}
+
+static void cpin_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+    struct ofono_modem *modem = user_data;
+    struct quectel_data *data = ofono_modem_get_data(modem);
+    struct ofono_error error;
+
+    if (ok)
+        return;
+
+    decode_at_error(&error, g_at_result_final_response(result));
+
+    if (error.type != OFONO_ERROR_TYPE_CME)
+        return;
+
+    switch (error.error) {
+    case 5:
+    case 6:
+    case 7:
+    case 11:
+    case 12:
+    case 17:
+    case 18:
          ofono_sim_inserted_notify(data->sim, true);
          break;
-    default:
+    case 10:
+        ofono_warn("%s: sim not present", ofono_modem_get_path(modem));
+        break;
+    case 13:
+    case 14:
+    case 15:
+        /* wait for +CPIN: indication */
          break;
+    default:
+        ofono_error("unknown cpin error: %i", error.error);
      }
  }

at_util_sim_state_query_new does most of this for you btw...

Thanks for the hint.

I tried this once some time ago, but I needed not only present true/false, but also locked/unlocked. This is queried in the v2 patch now.

+static void quectel_pre_sim(struct ofono_modem *modem)
+{
+    struct quectel_data *data = ofono_modem_get_data(modem);
+
+    DBG("%p", modem);
+
+    ofono_voicecall_create(modem, data->vendor, "atmodem", data->aux);
+    data->sim = ofono_sim_create(modem, data->vendor, "atmodem", data->aux); +    data->sim_watch = g_at_chat_register(data->aux, "+CPIN:", sim_watch_cb,
+                        FALSE, modem, NULL);
+
+    /*
+     * unsolicited indications about a missing or locked sim can occur before
+     * the auto-baud dance in open_serial(), so issue a CPIN query here
+     *
+     * the callback is only called for CME errors to catch those. The +CPIN
+     * response is catched by the watch registered above

nit: caught

+     */
+    g_at_chat_send(data->aux, "AT+CPIN?", none_prefix, cpin_cb, modem, NULL);

So as mentioned before, don't run commands in pre_sim.  You can do this as part of .enable sequence instead, store sim presence info and simply call sim_create & sim_inserted if needed.

Got it.

// Martin
_______________________________________________
ofono mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to