<div dir="ltr"><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Hi, </div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">thank you for the quick and useful reply.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">I will submit a new patch with the changes you suggested</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Best regards,<br>Carlo</div></div><div class="gmail_extra"><br><div class="gmail_quote">On 14 December 2015 at 15:19, Aleksander Morgado <span dir="ltr"><<a href="mailto:aleksander@aleksander.es" target="_blank">aleksander@aleksander.es</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hey!<br>
<br>
See comments below.<br>
<span class=""><br>
On Mon, Dec 14, 2015 at 12:51 PM, Carlo Lobrano <<a href="mailto:c.lobrano@gmail.com">c.lobrano@gmail.com</a>> wrote:<br>
> ---<br>
> plugins/telit/mm-broadband-modem-telit.c | 169 +++++++++++++++++++++++++++++++<br>
> plugins/telit/mm-broadband-modem-telit.h | 2 +<br>
> 2 files changed, 171 insertions(+)<br>
><br>
> diff --git a/plugins/telit/mm-broadband-modem-telit.c b/plugins/telit/mm-broadband-modem-telit.c<br>
> index 0f77231..b34503d 100644<br>
> --- a/plugins/telit/mm-broadband-modem-telit.c<br>
> +++ b/plugins/telit/mm-broadband-modem-telit.c<br>
> @@ -39,6 +39,165 @@ G_DEFINE_TYPE_EXTENDED (MMBroadbandModemTelit, mm_broadband_modem_telit, MM_TYPE<br>
> G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)<br>
> G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init));<br>
><br>
> +typedef struct {<br>
> + gint pin;<br>
> + gint pin2;<br>
> + gint puk;<br>
> + gint puk2;<br>
> +} ModemLockRetries;<br>
> +<br>
> +struct _MMBroadbandModemTelitPrivate {<br>
> + ModemLockRetries mm_lock_retries;<br>
> +};<br>
> +<br>
<br>
</span>I would say that the context of a single operation shouldn't be stored<br>
in private info, which is common to all operations. I see that what<br>
you want to do is to be able to build the MMUnlockRetries object in<br>
the finish() function, using the values you cached in the private<br>
info. Instead of doing that, I'd instead create a context struct for<br>
the action like this:<br>
<br>
typedef struct {<br>
MMBaseModemTelit *self;<br>
GSimpleAsyncResult *result;<br>
ModemLockRetries *retries;<br>
} LoadUnlockRetriesContext;<br>
<br>
You would do this in the modem_load_unlock_retries() and pass it to<br>
the sequence handler method (as response_processor_context, so that<br>
you can use it in the response processor methods). Then, for each of<br>
the responses, you could update ctx->retries directly, and get it<br>
returned in finish() afterwards.<br>
<br>
Another option would be to create the ModemLockRetries object and pass<br>
it directly in response_processor_context, while passing the<br>
GSimpleAsyncResult in the sequence method user_data (e.g. see<br>
modem_3gpp_disable_unsolicited_events() in mm-broadband-modem-mtk.c<br>
for an example).<br>
<div><div class="h5"><br>
<br>
> +<br>
> +/*****************************************************************************/<br>
> +/* Load unlock retries (Modem interface) */<br>
> +<br>
> +#define CSIM_QUERY_PIN_RETRIES_STR "+CSIM=10,0020000100"<br>
> +#define CSIM_QUERY_PUK_RETRIES_STR "+CSIM=10,002C000100"<br>
> +#define CSIM_QUERY_PIN2_RETRIES_STR "+CSIM=10,0020008100"<br>
> +#define CSIM_QUERY_PUK2_RETRIES_STR "+CSIM=10,002C008100"<br>
> +<br>
> +static gboolean<br>
> +csim_query_response_processor (MMBaseModem *_self,<br>
> + gpointer none,<br>
> + const gchar *command,<br>
> + const gchar *response,<br>
> + gboolean last_command,<br>
> + const GError *error,<br>
> + GVariant **result,<br>
> + GError **result_error)<br>
> +{<br>
> + GRegex *r = NULL;<br>
> + GMatchInfo *match_info = NULL;<br>
> +<br>
> + r = g_regex_new ("\\+CSIM:\\s*.*63C(.*)\"", G_REGEX_RAW, 0, NULL);<br>
> + g_assert (NULL != r);<br>
> +<br>
<br>
</div></div>For the regex parsers we try to write them in a separate<br>
-helpers.[c|h] set of files, and write unit tests for them, so that if<br>
someone updates the parsers in a the future we can validate that they<br>
don't break the previous strings. Could you do that as well? (see e.g.<br>
Huawei plugin)<br>
<span class=""><br>
> + if (!g_regex_match (r, response, 0, &match_info)) {<br>
> + mm_err ("Could not parse +CSIM response '%s'", response);<br>
> + goto end;<br>
> + }<br>
> +<br>
> + if (!g_match_info_matches (match_info)) {<br>
> + mm_err ("Could not get SIM unlock retries for query '%s'. Response was '%s'",<br>
> + command,<br>
> + response);<br>
> + goto end;<br>
> + } else {<br>
> + MMBroadbandModemTelit *self = MM_BROADBAND_MODEM_TELIT (_self);<br>
> + gchar* retries_hex_str;<br>
> + guint retries;<br>
> +<br>
> + retries_hex_str = mm_get_string_unquoted_from_match_info (match_info, 1);<br>
> + g_assert (NULL != retries_hex_str);<br>
> +<br>
> + // convert hex value to uint<br>
<br>
</span>We follow GNOME coding style, so we usually put comments /* like this<br>
*/, no one-line comments with //. ;)<br>
<div><div class="h5"><br>
> + sscanf (retries_hex_str, "%x", &retries);<br>
> + mm_dbg ("%s: CSIM retries 0x%s => %d", command, retries_hex_str, retries);<br>
> +<br>
> + g_free (retries_hex_str);<br>
> +<br>
> + if(strstr(CSIM_QUERY_PIN_RETRIES_STR, command)) {<br>
> + self->priv->mm_lock_retries.pin = retries;<br>
> + } else if(strstr(CSIM_QUERY_PIN2_RETRIES_STR, command)) {<br>
> + self->priv->mm_lock_retries.pin2 = retries;<br>
> + } else if(strstr(CSIM_QUERY_PUK_RETRIES_STR, command)) {<br>
> + self->priv->mm_lock_retries.puk = retries;<br>
> + } else if(strstr(CSIM_QUERY_PUK2_RETRIES_STR, command)) {<br>
> + self->priv->mm_lock_retries.puk2 = retries;<br>
> + } else {<br>
> + mm_err ("Could not assign SIM unlock retry value: unrecognized command '%s'",<br>
> + command);<br>
> + }<br>
> + }<br>
> +<br>
> +end:<br>
> + g_match_info_free (match_info);<br>
> + g_regex_unref (r);<br>
> +<br>
> + return FALSE;<br>
> +}<br>
> +<br>
> +static const MMBaseModemAtCommand load_unlock_retries_sequence[] = {<br>
> + { CSIM_QUERY_PIN_RETRIES_STR, 10, FALSE, csim_query_response_processor },<br>
> + { CSIM_QUERY_PIN2_RETRIES_STR, 10, FALSE, csim_query_response_processor },<br>
> + { CSIM_QUERY_PUK_RETRIES_STR, 10, FALSE, csim_query_response_processor },<br>
> + { CSIM_QUERY_PUK2_RETRIES_STR, 10, FALSE, csim_query_response_processor },<br>
> + { NULL }<br>
> +};<br>
> +<br>
> +static MMUnlockRetries *<br>
> +modem_load_unlock_retries_finish (MMIfaceModem *_self,<br>
> + GAsyncResult *res,<br>
> + GError **error)<br>
> +{<br>
> + MMBroadbandModemTelit *self = MM_BROADBAND_MODEM_TELIT (_self);<br>
> + MMUnlockRetries* unlock_retries;<br>
> +<br>
> + mm_dbg("%s", __FUNCTION__);<br>
> +<br>
<br>
</div></div>No mm_dbg() with the function name please.<br>
<br>
Also, Looks like you're not handling errors in this finish() call.<br>
What if the response processor returned an error?<br>
<br>
This logic is also mixing two things. When you call<br>
mm_base_modem_at_sequence_full() there *must* be a call to<br>
mm_base_modem_at_sequence_full_finish() to get the action completed.<br>
If you pass the original callback and user_data in<br>
modem_load_unlock_retries() it means that you must call<br>
mm_base_modem_at_sequence_full_finish() in this<br>
modem_load_unlock_retries_finish() method to finish that operation.<br>
<br>
NOTE that you can only do this (passing original callback directly)<br>
because both mm_base_modem_at_sequence_full() and<br>
modem_load_unlock_retries_finish() take the modem object as first<br>
parameter (i.e. they are both actions on the same modem object). In<br>
other words, you must never do this if you're using SIM or Bearer<br>
objects (this is just some context, nothing to do with your patch).<br>
<br>
I'm personally not very happy with the at_sequence methods, they're<br>
quick to write but the logic behind is a bit hard to get... If you're<br>
more comfortable with some other logic not using the sequence, e.g.<br>
using a Context and a step enum (see e.g. load_access_technologies()<br>
in mm-broadband-modem-option.c), then that would be also good to have.<br>
<span class=""><br>
> +<br>
> + unlock_retries = mm_unlock_retries_new ();<br>
> + if (self->priv->mm_lock_retries.pin > 0) {<br>
> + mm_dbg("SIM PIN retries left:%d",self->priv->mm_lock_retries.pin);<br>
> + mm_unlock_retries_set (unlock_retries, MM_MODEM_LOCK_SIM_PIN,<br>
> + self->priv->mm_lock_retries.pin);<br>
> + } else {<br>
<br>
</span>If retries.pin == 0, shouldn't we better say SIM PIN retries left: 0?<br>
why UNKNOWN? i.e. shouldn't it be >= 0?<br>
<div><div class="h5"><br>
> + mm_dbg("SIM PIN retries left: UNKNOWN");<br>
> + }<br>
> +<br>
> + if (self->priv->mm_lock_retries.pin2 > 0) {<br>
> + mm_dbg("SIM PIN2 retries left:%d",self->priv->mm_lock_retries.pin2);<br>
> + mm_unlock_retries_set (unlock_retries, MM_MODEM_LOCK_SIM_PIN2,<br>
> + self->priv->mm_lock_retries.pin2);<br>
> + } else {<br>
> + mm_dbg("SIM PIN2 retries left: UNKNOWN");<br>
> + }<br>
> +<br>
> + if (self->priv->mm_lock_retries.puk > 0) {<br>
> + mm_dbg("SIM PUK retries left:%d",self->priv->mm_lock_retries.puk);<br>
> + mm_unlock_retries_set (unlock_retries, MM_MODEM_LOCK_SIM_PUK,<br>
> + self->priv->mm_lock_retries.puk);<br>
> + } else {<br>
> + mm_dbg("SIM PUK retries left: UNKNOWN");<br>
> + }<br>
> +<br>
> + if (self->priv->mm_lock_retries.puk2 > 0) {<br>
> + mm_dbg("SIM PUK2 retries left:%d",self->priv->mm_lock_retries.puk2);<br>
> + mm_unlock_retries_set (unlock_retries, MM_MODEM_LOCK_SIM_PUK2,<br>
> + self->priv->mm_lock_retries.puk2);<br>
> + } else {<br>
> + mm_dbg("SIM PUK2 retries left: UNKNOWN");<br>
> + }<br>
> +<br>
> + return unlock_retries;<br>
> +}<br>
> +<br>
> +static void<br>
> +modem_load_unlock_retries (MMIfaceModem *self,<br>
> + GAsyncReadyCallback callback,<br>
> + gpointer user_data)<br>
> +{<br>
> + GSimpleAsyncResult *result;<br>
> +<br>
> + mm_dbg("%s", __FUNCTION__);<br>
> +<br>
> + result = g_simple_async_result_new (G_OBJECT (self),<br>
> + callback,<br>
> + user_data,<br>
> + modem_load_unlock_retries);<br>
> +<br>
> + mm_base_modem_at_sequence (<br>
> + MM_BASE_MODEM (self),<br>
> + load_unlock_retries_sequence,<br>
> + NULL, /* response_processor_context */<br>
> + NULL, /* response_processor_context_free */<br>
> + callback,<br>
> + user_data);<br>
> +}<br>
> +<br>
> /*****************************************************************************/<br>
> /* Modem power down (Modem interface) */<br>
><br>
> @@ -331,11 +490,21 @@ mm_broadband_modem_telit_new (const gchar *device,<br>
> static void<br>
> mm_broadband_modem_telit_init (MMBroadbandModemTelit *self)<br>
> {<br>
> + /* Initialize private data */<br>
> + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,<br>
> + MM_TYPE_BROADBAND_MODEM_TELIT,<br>
> + MMBroadbandModemTelitPrivate);<br>
> + self->priv->mm_lock_retries.pin = -1;<br>
> + self->priv->mm_lock_retries.pin2 = -1;<br>
> + self->priv->mm_lock_retries.puk = -1;<br>
> + self->priv->mm_lock_retries.puk2 = -1;<br>
> }<br>
><br>
> static void<br>
> iface_modem_init (MMIfaceModem *iface)<br>
> {<br>
> + iface->load_unlock_retries_finish = modem_load_unlock_retries_finish;<br>
> + iface->load_unlock_retries = modem_load_unlock_retries;<br>
> iface->reset = modem_reset;<br>
> iface->reset_finish = modem_reset_finish;<br>
> iface->modem_power_down = modem_power_down;<br>
> diff --git a/plugins/telit/mm-broadband-modem-telit.h b/plugins/telit/mm-broadband-modem-telit.h<br>
> index 50e6365..9b32ec6 100644<br>
> --- a/plugins/telit/mm-broadband-modem-telit.h<br>
> +++ b/plugins/telit/mm-broadband-modem-telit.h<br>
> @@ -29,9 +29,11 @@<br>
><br>
> typedef struct _MMBroadbandModemTelit MMBroadbandModemTelit;<br>
> typedef struct _MMBroadbandModemTelitClass MMBroadbandModemTelitClass;<br>
> +typedef struct _MMBroadbandModemTelitPrivate MMBroadbandModemTelitPrivate;<br>
><br>
> struct _MMBroadbandModemTelit {<br>
> MMBroadbandModem parent;<br>
> + MMBroadbandModemTelitPrivate* priv;<br>
> };<br>
><br>
> struct _MMBroadbandModemTelitClass{<br>
> --<br>
> 2.1.4<br>
><br>
</div></div>> _______________________________________________<br>
> ModemManager-devel mailing list<br>
> <a href="mailto:ModemManager-devel@lists.freedesktop.org">ModemManager-devel@lists.freedesktop.org</a><br>
> <a href="http://lists.freedesktop.org/mailman/listinfo/modemmanager-devel" rel="noreferrer" target="_blank">http://lists.freedesktop.org/mailman/listinfo/modemmanager-devel</a><br>
<span class="HOEnZb"><font color="#888888"><br>
<br>
<br>
--<br>
Aleksander<br>
<a href="https://aleksander.es" rel="noreferrer" target="_blank">https://aleksander.es</a><br>
</font></span></blockquote></div><br></div>