Hi Denis,

On Mon, Oct 15, 2018 at 8:48 PM Denis Kenzior <[email protected]> wrote:
>
> Hi Giacinto,
>
> On 10/13/2018 03:09 AM, Giacinto Cifelli wrote:
> > Added a vendor-specific extension for handling PDP context creation
> > and authentication, using the actual formats for the vendor.
> >
>
> No, please don't do this.  atutil is only for generic / utility code
> that is vendor neutral.  E.g. stuff described in 27.007.  We made one
> exception here for parsing CREG/CGREG and that is because some vendors
> just can't implement AT commands properly.

ok

>
> > The formating code is in atutils, because it is shared also with
> > gprs-context.
> > ---
> >   drivers/atmodem/atutil.c | 103 +++++++++++++++++++++++++
> >   drivers/atmodem/atutil.h |  27 +++++++
> >   drivers/atmodem/lte.c    | 161 ++++++++++++++++++++++++++++++++++++---
> >   3 files changed, 281 insertions(+), 10 deletions(-)
> >
> > diff --git a/drivers/atmodem/atutil.c b/drivers/atmodem/atutil.c
> > index 6f4e8a20..1201dbf3 100644
> > --- a/drivers/atmodem/atutil.c
> > +++ b/drivers/atmodem/atutil.c
> > @@ -3,6 +3,7 @@
> >    *  oFono - Open Source Telephony
> >    *
> >    *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
> > + *  Copyright (C) 2018 Gemalto M2M
> >    *
> >    *  This program is free software; you can redistribute it and/or modify
> >    *  it under the terms of the GNU General Public License version 2 as
> > @@ -26,6 +27,7 @@
> >   #include <glib.h>
> >   #include <gatchat.h>
> >   #include <string.h>
> > +#include <stdio.h>
> >   #include <stdlib.h>
> >   #include <errno.h>
> >
> > @@ -33,6 +35,8 @@
> >   #include <ofono/log.h>
> >   #include <ofono/types.h>
> >
> > +#include "ofono.h"
> > +
> >   #include "atutil.h"
> >   #include "vendor.h"
> >
> > @@ -654,3 +658,102 @@ int at_util_get_ipv4_address_and_netmask(const char 
> > *addrnetmask,
> >
> >       return ret;
> >   }
> > +
> > +static int gemalto_get_auth_type(enum ofono_gprs_auth_method auth_method)
> > +{
> > +     switch (auth_method) {
> > +     case OFONO_GPRS_AUTH_METHOD_PAP:
> > +             return 1;
> > +     case OFONO_GPRS_AUTH_METHOD_CHAP:
> > +             return 2;
> > +     case OFONO_GPRS_AUTH_METHOD_NONE:
> > +             return 0;
> > +     }
> > +
> > +     return 0;
>
> This looks to be exact same enumeration that 27.007 uses...?

yes, and?
I still need to convert the enum to int. Is there a function somewhere?

>
> > +}
> > +
> > +gboolean gemalto_get_auth_command(struct ofono_modem *modem, int cid,
> > +                             enum ofono_gprs_auth_method auth_method,
> > +                             const char *username, const char *password,
> > +                             char *buf, guint buflen)
> > +{
> > +     int gemalto_auth = ofono_modem_get_integer(modem, "GemaltoAuthType");
>
> Why don't you just simply pass the gemalto auth into this function
> directly instead of having to pass in the modem object?

Because I need to pass further values in the future.
I still need handle the auto-provisioned modems.
I prefer that the calling function doesn't have to know how the buffer
is filled:
it will just receive the command.

>
> > +     int len;
> > +     /*
> > +      * 0x01: use sgauth (0=use cgauth)
> > +      * 0x02: pwd, user order (0=user, pwd order)
> > +      * 0x04: always use all: method, user, password
> > +      */
>
> But certain combinations are not valid?  E.g. can we have a +CGAUTH with
> a wrong username/password order?

yes, out of the 8 combinations possible, today I have counted 5 (the
R&D can be very creative sometimes),
If the point is to enumerate the configurations instead, this is how I
handled it in a previous submit, but was much worst
because there were switch-cases with 1, 2, or 3 labels together.
At least like this it is clear what the code is doing.

>
> Have you considered simply writing a gemalto specific gprs.c driver that
> will use SGAUTH and using the default atmodem one on the sane devices?

Even CGAUTH is not completely standard for some models, some require
all parameters for auth=NONE.
Besides, gemalto doesnt use the CID=0 as in the standard.

There are no sane and insane modems. At most standard and proprietary.

>
> > +
> > +     int auth_type = gemalto_get_auth_type(auth_method);
> > +
> > +     if (auth_type != 0 && (!*username || !*password))
> > +             return FALSE;
> > +
> > +     if (gemalto_auth & 0x01)
> > +             len = snprintf(buf, buflen, "AT^SGAUTH=%d", cid);
> > +     else
> > +             len = snprintf(buf, buflen, "AT+CGAUTH=%d", cid);
> > +
> > +     buflen -= len;
> > +
> > +     switch(auth_type) {
> > +     case 0:
> > +
> > +             if (gemalto_auth & 0x04)
> > +                     snprintf(buf+len, buflen, ",0,\"\",\"\"");
> > +             else
> > +                     snprintf(buf+len, buflen, ",0");
> > +
> > +             break;
> > +     case 1:
> > +     case 2:
> > +
> > +             if (gemalto_auth & 0x02)
> > +                     snprintf(buf+len, buflen, ",%d,\"%s\",\"%s\"",
> > +                                     auth_type, password, username);
> > +             else
> > +                     snprintf(buf+len, buflen, ",%d,\"%s\",\"%s\"",
> > +                                     auth_type, username, password);
> > +
> > +             break;
> > +     default:
> > +             return FALSE;
> > +     }
> > +
> > +     return TRUE;
> > +}
> > +
> > +void gemalto_get_cgdcont_command(struct ofono_modem *modem,
>
> Err, why do you need the modem object?

As above, to get the autoprovisioning properties later.

>
> > +                     guint cid, enum ofono_gprs_proto proto, const char 
> > *apn,
> > +                                                     char *buf, guint 
> > buflen)
>
> Why is CGDCONT specific to gemalto?  This looks pretty standard

CID=1 for the default APN (for the current models).
And because for auto-provisioning models I need to return a totally
different command in some cases (like: 'AT').
And there are no cgdcont-building functions around.

>
> > +{
> > +     int len = snprintf(buf, buflen, "AT+CGDCONT=%u", cid);
> > +     buflen -= len;
> > +
> > +     /*
> > +      * For future extension: verify if the module supports automatic
> > +      * context provisioning and if so, also if there is a manual override
> > +      * This is an ofono_modem_get_integer property
> > +      */
> > +
> > +     /*
> > +      * if apn is null, it will remove the context.
> > +      * but if apn is empty, it will create a context with empty apn
> > +      */
> > +     if (!apn)
> > +             return;
> > +
> > +     switch (proto) {
> > +     case OFONO_GPRS_PROTO_IPV6:
> > +             snprintf(buf+len, buflen, ",\"IPV6\",\"%s\"", apn);
> > +             break;
> > +     case OFONO_GPRS_PROTO_IPV4V6:
> > +             snprintf(buf+len, buflen, ",\"IPV4V6\",\"%s\"", apn);
> > +             break;
> > +     case OFONO_GPRS_PROTO_IP:
> > +             snprintf(buf+len, buflen, ",\"IP\",\"%s\"", apn);
> > +             break;
> > +     }
> > +}
> > diff --git a/drivers/atmodem/atutil.h b/drivers/atmodem/atutil.h
> > index 7113a4cd..b74db9fe 100644
> > --- a/drivers/atmodem/atutil.h
> > +++ b/drivers/atmodem/atutil.h
> > @@ -3,6 +3,7 @@
> >    *  oFono - Open Source Telephony
> >    *
> >    *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
> > + *  Copyright (C) 2018 Gemalto M2M
> >    *
> >    *  This program is free software; you can redistribute it and/or modify
> >    *  it under the terms of the GNU General Public License version 2 as
> > @@ -19,6 +20,8 @@
> >    *
> >    */
> >
> > +struct ofono_modem;
> > +
>
> This should not be necessary if you follow the above advice...
>
> >   enum at_util_sms_store {
> >       AT_UTIL_SMS_STORE_SM =  0,
> >       AT_UTIL_SMS_STORE_ME =  1,
> > @@ -86,6 +89,15 @@ void at_util_sim_state_query_free(struct 
> > at_util_sim_state_query *req);
> >   int at_util_get_ipv4_address_and_netmask(const char *addrnetmask,
> >                                               char *address, char *netmask);
> >
> > +gboolean gemalto_get_auth_command(struct ofono_modem *modem, int cid,
> > +                             enum ofono_gprs_auth_method auth_method,
> > +                             const char *username, const char *password,
> > +                             char *buf, guint buflen);
> > +
> > +void gemalto_get_cgdcont_command(struct ofono_modem *modem,
> > +                     guint cid, enum ofono_gprs_proto proto, const char 
> > *apn,
> > +                                             char *buf, guint buflen);
> > +
> >   struct cb_data {
> >       void *cb;
> >       void *data;
> > @@ -115,6 +127,21 @@ static inline int at_util_convert_signal_strength(int 
> > strength)
> >       return result;
> >   }
> >
> > +static inline int at_util_convert_signal_strength_cesq(int strength_GSM,
> > +                                     int strength_UTRAN, int 
> > strength_EUTRAN)
> > +{
> > +     int result = -1;
> > +
> > +     if (strength_GSM != 99)
> > +             result = (strength_GSM * 100) / 63;
> > +     else if (strength_UTRAN != 255)
> > +             result = (strength_UTRAN * 100) / 96;
> > +     else if (strength_EUTRAN != 255)
> > +             result = (strength_EUTRAN * 100) / 97;
> > +
> > +     return result;
> > +}
> > +
>
> How is this related to the current patch?

Sorry, I didn't see it. However I did submit a patch for it on the
21.09.2018 on which I have never received any feedback.


>
> >   #define CALLBACK_WITH_FAILURE(cb, args...)          \
> >       do {                                            \
> >               struct ofono_error cb_e;                \
> > diff --git a/drivers/atmodem/lte.c b/drivers/atmodem/lte.c
> > index efa4e5fe..41de4197 100644
> > --- a/drivers/atmodem/lte.c
> > +++ b/drivers/atmodem/lte.c
> > @@ -3,6 +3,7 @@
> >    *  oFono - Open Source Telephony
> >    *
> >    *  Copyright (C) 2017  Intel Corporation. All rights reserved.
> > + *  Copyright (C) 2018 Gemalto M2M
> >    *
> >    *  This program is free software; you can redistribute it and/or modify
> >    *  it under the terms of the GNU General Public License version 2 as
> > @@ -43,12 +44,65 @@
> >
> >   struct lte_driver_data {
> >       GAtChat *chat;
> > +     unsigned int vendor;
> >   };
> >
> > -static void at_lte_set_default_attach_info_cb(gboolean ok, GAtResult 
> > *result,
> > +struct lte_cbd {
> > +     gint ref_count; /* Ref count */
> > +     ofono_lte_cb_t cb;
> > +     void *data;
> > +     GAtChat *chat;
>
> Why don't you just include a pointer to lte_driver_data and not store
> all this redundant stuff like vendor, chat, etc.
>
> > +     const struct ofono_lte_default_attach_info *info;
>
> And as I pointed out last time, you can't do this.  The core is not
> obligated to keep the object pointed to around after the driver method
> has been called.  So this might be pointing out into the ether, invalid
> memory, etc.

yes, I have included the old version just for giving some context to
the patch I wanted commented.
I have changed this in the meanwhile.

>
> > +     unsigned int vendor;
> > +     struct ofono_modem *modem;
> > +};
> > +
> > +static struct lte_cbd *lte_cb_data_new0(void *cb, void *data,
> > +             GAtChat *chat, const struct ofono_lte_default_attach_info 
> > *info,
> > +             unsigned int vendor, struct ofono_modem *modem)
> > +{
> > +     struct lte_cbd *cbd = g_new0(struct lte_cbd, 1);
> > +
> > +     cbd->ref_count = 1;
> > +     cbd->cb = cb;
> > +     cbd->data = data;
> > +     cbd->chat = chat;
> > +     cbd->info = info;
> > +     cbd->vendor = vendor;
> > +     cbd->modem = modem;
> > +
> > +     return cbd;
> > +}
> > +
> > +static inline struct lte_cbd *lte_cb_data_ref(struct lte_cbd *cbd)
> > +{
> > +     if (cbd == NULL)
> > +             return NULL;
> > +
> > +     g_atomic_int_inc(&cbd->ref_count);
> > +
> > +     return cbd;
> > +}
> > +
> > +static void lte_cb_data_unref(gpointer user_data)
> > +{
> > +     gboolean is_zero;
> > +     struct lte_cbd *cbd = user_data;
> > +
> > +     if (cbd == NULL)
> > +             return;
> > +
> > +     is_zero = g_atomic_int_dec_and_test(&cbd->ref_count);
> > +
> > +     if (is_zero == TRUE)
> > +             g_free(cbd);
> > +}
> > +
> > +
> > +static void at_lte_set_auth_cb(gboolean ok, GAtResult *result,
> >                                                       gpointer user_data)
> >   {
> > -     struct cb_data *cbd = user_data;
> > +     struct lte_cbd *cbd = user_data;
> >       ofono_lte_cb_t cb = cbd->cb;
> >       struct ofono_error error;
> >
> > @@ -58,27 +112,113 @@ static void 
> > at_lte_set_default_attach_info_cb(gboolean ok, GAtResult *result,
> >       cb(&error, cbd->data);
> >   }
> >
> > +static void at_lte_set_default_attach_info_cb(gboolean ok, GAtResult 
> > *result,
> > +                                                     gpointer user_data)
> > +{
> > +     struct lte_cbd *cbd = user_data;
> > +     ofono_lte_cb_t cb = cbd->cb;
> > +     void *data = cbd->data;
> > +     struct ofono_error error;
> > +     char buf[32 + OFONO_GPRS_MAX_USERNAME_LENGTH +
> > +                                     OFONO_GPRS_MAX_PASSWORD_LENGTH  + 1];
> > +     size_t buflen = sizeof(buf);
> > +     size_t len;
> > +     enum ofono_gprs_auth_method auth_method;
> > +
> > +     if (!ok) {
> > +             lte_cb_data_unref(cbd);
> > +             decode_at_error(&error, g_at_result_final_response(result));
> > +             cb(&error, data);
> > +             return;
> > +     }
> > +
> > +
> > +     auth_method = cbd->info->auth_method;
> > +
> > +     /* change the authentication method if the  parameters are invalid */
> > +     if (!*cbd->info->username || !*cbd->info->password)
> > +             auth_method = OFONO_GPRS_AUTH_METHOD_NONE;
> > +
> > +     if (ldd->vendor == OFONO_VENDOR_GEMALTO) {
> > +
> > +             if (!gemalto_get_auth_command(modem, 1, auth_method,
> > +                                             info->username, 
> > info->password,
> > +                                             buf, sizeof(buf)))
> > +                     goto error;
> > +
> > +     } else { /* default vendor*/
> > +             len = snprintf(buf, buflen, "AT+CGAUTH=0,");
> > +             buflen -= len;
> > +
> > +             switch (auth_method) {
> > +             case OFONO_GPRS_AUTH_METHOD_PAP:
> > +                     snprintf(buf + len, buflen, "1,\"%s\",\"%s\"",
> > +                                     cbd->info->username, 
> > cbd->info->password);
> > +                     break;
> > +             case OFONO_GPRS_AUTH_METHOD_CHAP:
> > +                     snprintf(buf + len, buflen, "2,\"%s\",\"%s\"",
> > +                                     cbd->info->username, 
> > cbd->info->password);
> > +                     break;
> > +             case OFONO_GPRS_AUTH_METHOD_NONE:
> > +                     snprintf(buf + len, buflen, "0");
> > +                     break;
> > +             }
> > +     }
> > +
> > +     cbd = lte_cb_data_ref(cbd);
> > +     if (g_at_chat_send(cbd->chat, buf, NULL,
> > +                     at_lte_set_auth_cb, cbd, lte_cb_data_unref) > 0)
> > +             return;
> > +
> > +error:
> > +     lte_cb_data_unref(cbd);
> > +     CALLBACK_WITH_FAILURE(cb, data);
> > +}
> > +
> >   static void at_lte_set_default_attach_info(const struct ofono_lte *lte,
> >                       const struct ofono_lte_default_attach_info *info,
> >                       ofono_lte_cb_t cb, void *data)
> >   {
> >       struct lte_driver_data *ldd = ofono_lte_get_data(lte);
> >       char buf[32 + OFONO_GPRS_MAX_APN_LENGTH + 1];
> > -     struct cb_data *cbd = cb_data_new(cb, data);
> > +     const char *proto;
> > +     size_t len;
> > +     struct ofono_modem *modem = ofono_lte_get_modem(lte);
> > +     struct lte_cbd *cbd = lte_cb_data_new0(cb, data, ldd->chat, info,
> > +                                                     ldd->vendor, modem);
> >
>
> Again, have you considered just writing a Gemalto specific LTE driver?
> The whole thing is only 140 lines of code right now.

Ok.

>
> >       DBG("LTE config with APN: %s", info->apn);
> >
> > -     if (strlen(info->apn) > 0)
> > -             snprintf(buf, sizeof(buf), "AT+CGDCONT=0,\"IP\",\"%s\"",
> > -                             info->apn);
> > -     else
> > -             snprintf(buf, sizeof(buf), "AT+CGDCONT=0,\"IP\"");
> > +     if (ldd->vendor == OFONO_VENDOR_GEMALTO) {
> > +             gemalto_get_cgdcont_command(modem, 1, info->proto, info->apn,
> > +                                     buf, sizeof(buf));
> > +     } else { /* default vendor*/
> > +
> > +             switch (info->proto) {
> > +             case OFONO_GPRS_PROTO_IPV6:
> > +                     proto = "IPV6";
> > +                     break;
> > +             case OFONO_GPRS_PROTO_IPV4V6:
> > +                     proto = "IPV4V6";
> > +                     break;
> > +             case OFONO_GPRS_PROTO_IP:
> > +                     proto = "IP";
> > +                     break;
> > +             }
> > +
> > +             len = snprintf(buf, sizeof(buf), "AT+CGDCONT=0,\"%s\"", 
> > proto);
> > +
> > +             if (*info->apn)
> > +                     snprintf(buf+len, sizeof(buf)-len, ",\"%s\"",
> > +                                                             info->apn);
> > +     }
> >
> > -     /* We can't do much in case of failure so don't check response. */
> >       if (g_at_chat_send(ldd->chat, buf, NULL,
> > -                     at_lte_set_default_attach_info_cb, cbd, g_free) > 0)
> > +                     at_lte_set_default_attach_info_cb,
> > +                     cbd, lte_cb_data_unref) > 0)
> >               return;
> >
> > +     lte_cb_data_unref(cbd);
> >       CALLBACK_WITH_FAILURE(cb, data);
> >   }
> >
> > @@ -103,6 +243,7 @@ static int at_lte_probe(struct ofono_lte *lte, unsigned 
> > int vendor, void *data)
> >               return -ENOMEM;
> >
> >       ldd->chat = g_at_chat_clone(chat);
> > +     ldd->vendor = vendor;
> >
> >       ofono_lte_set_data(lte, ldd);
> >
> >
>
> Regards,
> -Denis

Regards,
Giacinto
_______________________________________________
ofono mailing list
[email protected]
https://lists.ofono.org/mailman/listinfo/ofono

Reply via email to