Some Cinterion modems support AT^SPIC to fetch the 'unlock retries', but some
don't. Another method possibly available is to used AT+CSIM (as per Telit
plugin).
This aims to allow either method to be tried - if the first step of the first
method fails (e.g. SPIC not supported), then try again using the alternate.
I did wonder about a single array of commands but that would have meant
hard-coding in a 'goto' to get from A to B, hence prone to future changes
breaking it.
Bit more checking required yet, but at first glance it looks like basically
works.
I'm not sending this as a patch here, but just to get views on (or objections
to!) the general approach.
Note that I've coded it to make it easy to switch which method is tried first
(TBD? Configurable? Run-time based on the Model?) - see the #defines. And it's
another reason for having two separate arrays.
The CSIM parsing isn't shown here, but at the moment it's as per the Telit
helper.
Apologies in advance if my webmail screws up the line-wrapping.
/*****************************************************************************/
/* Load unlock retries (Modem interface) */
typedef struct {
MMBroadbandModemCinterion *self;
GSimpleAsyncResult *result;
MMUnlockRetries *retries;
gint i;
} LoadUnlockRetriesContext;
typedef struct {
MMModemLock lock;
const gchar *command;
} UnlockRetriesMap;
const UnlockRetriesMap *unlock_retries_map_ptr;
guint unlock_retries_map_size;
static const UnlockRetriesMap unlock_retries_map_spic [] = {
{ MM_MODEM_LOCK_SIM_PIN, "^SPIC=\"SC\"" },
{ MM_MODEM_LOCK_SIM_PUK, "^SPIC=\"SC\",1" },
{ MM_MODEM_LOCK_SIM_PIN2, "^SPIC=\"P2\"" },
{ MM_MODEM_LOCK_SIM_PUK2, "^SPIC=\"P2\",1" },
{ MM_MODEM_LOCK_PH_FSIM_PIN, "^SPIC=\"PS\"" },
{ MM_MODEM_LOCK_PH_FSIM_PUK, "^SPIC=\"PS\",1" },
{ MM_MODEM_LOCK_PH_NET_PIN, "^SPIC=\"PN\"" },
{ MM_MODEM_LOCK_PH_NET_PUK, "^SPIC=\"PN\",1" },
};
static const UnlockRetriesMap unlock_retries_map_csim [] = {
{ MM_MODEM_LOCK_SIM_PIN, "+CSIM=10,\"0020000100\"" },
{ MM_MODEM_LOCK_SIM_PUK, "+CSIM=10,\"002C000100\"" },
{ MM_MODEM_LOCK_SIM_PIN2, "+CSIM=10,\"0020008100\"" },
{ MM_MODEM_LOCK_SIM_PUK2, "+CSIM=10,\"002C008100\"" },
};
#define UNLOCK_RETRIES_FIRST_MAP unlock_retries_map_spic
#define UNLOCK_RETRIES_SECOND_MAP unlock_retries_map_csim
static void
load_unlock_retries_context_complete_and_free (LoadUnlockRetriesContext *ctx)
{
g_simple_async_result_complete (ctx->result);
g_object_unref (ctx->retries);
g_object_unref (ctx->result);
g_object_unref (ctx->self);
g_slice_free (LoadUnlockRetriesContext, ctx);
}
static MMUnlockRetries *
load_unlock_retries_finish (MMIfaceModem *self,
GAsyncResult *res,
GError **error)
{
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res),
error))
return NULL;
return (MMUnlockRetries *) g_object_ref
(g_simple_async_result_get_op_res_gpointer (
G_SIMPLE_ASYNC_RESULT (res)));
}
static void load_unlock_retries_context_step (LoadUnlockRetriesContext *ctx);
static void
load_unlock_retries_ready (MMBaseModem *self,
GAsyncResult *res,
LoadUnlockRetriesContext *ctx)
{
const gchar *response;
GError *error = NULL;
response = mm_base_modem_at_command_finish (self, res, &error);
if (!response) {
mm_dbg ("Couldn't load retry count for lock '%s': %s",
mm_modem_lock_get_string (unlock_retries_map_ptr[ctx->i].lock),
error->message);
g_error_free (error);
/* Switch to second map if first step of first one fails */
if ((unlock_retries_map_ptr == UNLOCK_RETRIES_FIRST_MAP) && !ctx->i) {
/* Set the second method to try */
unlock_retries_map_ptr = UNLOCK_RETRIES_SECOND_MAP;
unlock_retries_map_size = G_N_ELEMENTS (UNLOCK_RETRIES_SECOND_MAP);
/* Restart state machine */
ctx->i = -1;
}
} else {
gint val;
if (unlock_retries_map_ptr == unlock_retries_map_spic) {
response = mm_strip_tag (response, "^SPIC:");
if (!mm_get_uint_from_str (response, (guint *) &val))
val = -1;
} else if (unlock_retries_map_ptr == unlock_retries_map_csim) {
GError *error = NULL;
val = mm_cinterion_parse_csim_response (ctx->i, response, &error);
if (val < 0)
mm_warn ("Parse error in step %d: %s.", ctx->i, error->message);
}
if (val < 0)
mm_dbg ("Couldn't parse retry count value for lock '%s'",
mm_modem_lock_get_string
(unlock_retries_map_ptr[ctx->i].lock));
else
mm_unlock_retries_set (ctx->retries,
unlock_retries_map_ptr[ctx->i].lock, (guint) val);
}
/* Go to next lock value */
ctx->i++;
load_unlock_retries_context_step (ctx);
}
static void
load_unlock_retries_context_step (LoadUnlockRetriesContext *ctx)
{
if (ctx->i == unlock_retries_map_size) {
g_simple_async_result_set_op_res_gpointer (ctx->result,
g_object_ref (ctx->retries),
g_object_unref);
load_unlock_retries_context_complete_and_free (ctx);
return;
}
mm_base_modem_at_command (
MM_BASE_MODEM (ctx->self),
unlock_retries_map_ptr[ctx->i].command,
3,
FALSE,
(GAsyncReadyCallback)load_unlock_retries_ready,
ctx);
}
static void
load_unlock_retries (MMIfaceModem *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
LoadUnlockRetriesContext *ctx;
ctx = g_slice_new0 (LoadUnlockRetriesContext);
ctx->self = g_object_ref (self);
ctx->result = g_simple_async_result_new (G_OBJECT (self),
callback,
user_data,
load_unlock_retries);
ctx->retries = mm_unlock_retries_new ();
ctx->i = 0;
/* Set the first method to try */
unlock_retries_map_ptr = UNLOCK_RETRIES_FIRST_MAP;
unlock_retries_map_size = G_N_ELEMENTS (UNLOCK_RETRIES_FIRST_MAP);
load_unlock_retries_context_step (ctx);
}
_______________________________________________
ModemManager-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/modemmanager-devel