[PATCH v3] quectel: Power on/off with a gpio pulse

2020-10-06 Thread poeschel
From: Lars Poeschel 

Current implementation uses a gpio level of 1 for powering on quectel
modems using a gpio and a level of 0 for powering off.
Normally quectel modems are powered on or off by a gpio pulse on their
PWR_KEY pin. They turn on by the first pulse and turn then off by the
next pulse. The pulse length varies between different modems.
For power on the longest I could in the quectel hardware is "more than
2 seconds" from Quectel M95 Hardware Design Manual.
For Quectel EC21 this is ">= 100 ms".
For Quectel MC60 this is "recommended to be 100 ms".
For Quectel UC15 this is "at least 0.1 s".
For power off the four modems in question vary between a minimum pulse
length of 600-700ms.
This implements a 2100ms pulse for power on and 750ms for power off.

If you have some special circuitry that powers your modem by gpio level
and you need the old behaviour, you can switch to gpio level powering
by setting environment variable OFONO_QUECTEL_GPIO_LEVEL. The gpio goes
to high level for the modem to power on and to low level if it should
power off.

---
Changes in v3:
- switched to l_timeout_create_ms instead of g_timeout for the gpio
  pulse
- try to keep track of the gpio_timeout object
- combined patch with the level patch
---
 plugins/quectel.c | 45 +++--
 plugins/udevng.c  |  5 +
 2 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/plugins/quectel.c b/plugins/quectel.c
index 6456775d..aa519563 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -104,6 +104,7 @@ struct quectel_data {
int initial_ldisc;
struct l_gpio_writer *gpio;
struct l_timeout *init_timeout;
+   struct l_timeout *gpio_timeout;
size_t init_count;
guint init_cmd;
 };
@@ -191,6 +192,7 @@ static void quectel_remove(struct ofono_modem *modem)
 
ofono_modem_set_data(modem, NULL);
l_timeout_remove(data->init_timeout);
+   l_timeout_remove(data->gpio_timeout);
l_gpio_writer_free(data->gpio);
at_util_sim_state_query_free(data->sim_state_query);
g_at_chat_unref(data->aux);
@@ -234,10 +236,22 @@ static void close_ngsm(struct ofono_modem *modem)
ofono_warn("Failed to restore line discipline");
 }
 
+static void gpio_power_off_cb(struct l_timeout *timeout, void *user_data)
+{
+   struct ofono_modem *modem = (struct ofono_modem *)user_data;
+   struct quectel_data *data = ofono_modem_get_data(modem);
+   const uint32_t gpio_value = 0;
+
+   l_timeout_remove(timeout);
+   data->gpio_timeout = NULL;
+   l_gpio_writer_set(data->gpio, 1, _value);
+   ofono_modem_set_powered(modem, FALSE);
+}
+
 static void close_serial(struct ofono_modem *modem)
 {
struct quectel_data *data = ofono_modem_get_data(modem);
-   uint32_t gpio_value = 0;
+   uint32_t gpio_value = 1;
 
DBG("%p", modem);
 
@@ -258,7 +272,20 @@ static void close_serial(struct ofono_modem *modem)
else
close_ngsm(modem);
 
-   l_gpio_writer_set(data->gpio, 1, _value);
+   if (data->gpio) {
+   if (ofono_modem_get_boolean(modem, "GpioLevel")) {
+   gpio_value = 0;
+   l_gpio_writer_set(data->gpio, 1, _value);
+   } else {
+   l_gpio_writer_set(data->gpio, 1, _value);
+   l_timeout_remove(data->gpio_timeout);
+   data->gpio_timeout = l_timeout_create_ms(750,
+   gpio_power_off_cb,
+   modem, NULL);
+   return;
+   }
+   }
+
ofono_modem_set_powered(modem, FALSE);
 }
 
@@ -1096,6 +1123,16 @@ static void init_timeout_cb(struct l_timeout *timeout, 
void *user_data)
l_timeout_modify_ms(timeout, 500);
 }
 
+static void gpio_power_on_cb(struct l_timeout *timeout, void *user_data)
+{
+   struct quectel_data *data = user_data;
+   const uint32_t gpio_value = 0;
+
+   l_timeout_remove(timeout);
+   data->gpio_timeout = NULL;
+   l_gpio_writer_set(data->gpio, 1, _value);
+}
+
 static int open_serial(struct ofono_modem *modem)
 {
struct quectel_data *data = ofono_modem_get_data(modem);
@@ -1139,6 +1176,10 @@ static int open_serial(struct ofono_modem *modem)
return -EIO;
}
 
+   if (data->gpio && !ofono_modem_get_boolean(modem, "GpioLevel"))
+   data->gpio_timeout = l_timeout_create_ms(2100, gpio_power_on_cb,
+data, NULL);
+
/*
 * there are three different power-up scenarios:
 *
diff --git a/plugins/udevng.c b/plugins/udevng.c
index db13073e..8b1943aa 100644
--- a/plugins/udevng.c
+++ b/plugins/udevng.c

Re: [PATCH v2] quectel: Power on/off with a gpio pulse

2020-10-05 Thread Lars Poeschel
On Fri, Oct 02, 2020 at 09:50:22AM -0500, Denis Kenzior wrote:
> Hi Lars,
> 
> On 10/1/20 6:42 AM, poesc...@lemonage.de wrote:
> > From: Lars Poeschel 
> > 
> > Current implementation uses a gpio level of 1 for powering on quectel
> > modems using a gpio and a level of 0 for powering off.
> > This is wrong. Quectel modems use pulses for either power on and power
> > off. They turn on by the first pulse and turn then off by the next
> > pulse. The pulse length varies between different modems.
> > For power on the longest I could in the quectel hardware is "more than
> > 2 seconds" from Quectel M95 Hardware Design Manual.
> > For Quectel EC21 this is ">= 100 ms".
> > For Quectel MC60 this is "recommended to be 100 ms".
> > For Quectel UC15 this is "at least 0.1 s".
> > For power off the four modems in question vary between a minimum pulse
> > length of 600-700ms.
> > This implements a 2100ms pulse for power on and 750ms for power off.
> > ---
> >   plugins/quectel.c | 33 ++---
> >   1 file changed, 30 insertions(+), 3 deletions(-)
> > 
> > diff --git a/plugins/quectel.c b/plugins/quectel.c
> > index 6456775d..61ac906e 100644
> > --- a/plugins/quectel.c
> > +++ b/plugins/quectel.c
> > @@ -234,10 +234,21 @@ static void close_ngsm(struct ofono_modem *modem)
> > ofono_warn("Failed to restore line discipline");
> >   }
> > +static gboolean gpio_power_off_cb(gpointer user_data)
> > +{
> > +   struct ofono_modem *modem = (struct ofono_modem *)user_data;
> > +   struct quectel_data *data = ofono_modem_get_data(modem);
> > +   const uint32_t gpio_value = 0;
> > +
> > +   l_gpio_writer_set(data->gpio, 1, _value);
> > +   ofono_modem_set_powered(modem, FALSE);
> > +   return false;
> > +}
> > +
> 
> Ok, this makes sense now...
> 
> >   static void close_serial(struct ofono_modem *modem)
> >   {
> > struct quectel_data *data = ofono_modem_get_data(modem);
> > -   uint32_t gpio_value = 0;
> > +   uint32_t gpio_value = 1;
> > DBG("%p", modem);
> > @@ -258,8 +269,12 @@ static void close_serial(struct ofono_modem *modem)
> > else
> > close_ngsm(modem);
> > -   l_gpio_writer_set(data->gpio, 1, _value);
> > -   ofono_modem_set_powered(modem, FALSE);
> > +   if (data->gpio) {
> > +   l_gpio_writer_set(data->gpio, 1, _value);
> > +   g_timeout_add(750, gpio_power_off_cb, modem);
> 
> Have you considered what happens if the gpio_power_on_cb timeout is still
> running here?  For example, if the modem is turned on / off quickly?
> 
> Maybe the old timeout should be canceled just in case?

I am in a big luck here! :-)
Setting "Powered" on "org.ofono.Modem" is synchronous. And even if
another process is trying to unset "Powered" in the meantime. This is
blocked:

dbus.exceptions.DBusException: org.ofono.Error.InProgress: Operation already in 
progress

And powering on the modem is taking as long as the first replies from
the modem are received. This a lot of time after the timeout happened.

> > +   } else
> > +   ofono_modem_set_powered(modem, FALSE);
> > +
> >   }
> >   static void dbus_hw_reply_properties(struct dbus_hw *hw)
> > @@ -1096,6 +,15 @@ static void init_timeout_cb(struct l_timeout 
> > *timeout, void *user_data)
> > l_timeout_modify_ms(timeout, 500);
> >   }
> > +static gboolean gpio_power_on_cb(gpointer user_data)
> > +{
> > +   struct quectel_data *data = user_data;
> > +   const uint32_t gpio_value = 0;
> > +
> > +   l_gpio_writer_set(data->gpio, 1, _value);
> > +   return false;
> > +}
> 
> It seems that this timeout is completely independent of
> ofono_modem_set_powered(TRUE), so the core won't prevent the modem from
> being powered off while this is running...

What exactly are you concerned about ? What should not work ?
The ofono_modem_set_powered(TRUE) is done later either in cpin_cb or
qinistat_cb, after communication with the modem and mux are properly
set up.
Powering off during this phase is prevented by ofono:

root@bboxvx:/usr/lib/ofono/test# ./enable-modem & sleep 11; ./disable-modem

ofonod[507]: ../git/src/modem.c:get_modem_property() modem 0x583b80 property 
SystemPath
Connecting modem /quectel_0...
ofonod[507]: ../git/plugins/quectel.c:quectel_enable() 0x583b80
ofonod[507]: ../git/src/modem.c:get_modem_property() modem 0x583b80 property 
Device
ofonod[507]: ../git/plugins/quectel.c:open_serial() 0x583b80
ofonod[507]: ../git/sr

[PATCH] quectel: Possibility to switch power by gpio level

2020-10-02 Thread poeschel
From: Lars Poeschel 

This does apply on top of my previous patch:
[PATCH v2] quectel: Power on/off with a gpio pulse

-- >8 --
Subject: [PATCH] quectel: Possibility to switch power by gpio level

Normally quectel modems are powered on or off by a gpio pulse on their
PWR_KEY pin.
If you have some special circuitry that powers your modem by gpio level
then this here is for you. You can switch to level behaviour by setting
environment variable OFONO_QUECTEL_GPIO_LEVEL. The gpio goes to high
level for the modem to power on and to low level if it should power off.
---
 plugins/quectel.c | 17 -
 plugins/udevng.c  |  5 +
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/plugins/quectel.c b/plugins/quectel.c
index 6ab1d6fd..d4a49555 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -271,10 +271,17 @@ static void close_serial(struct ofono_modem *modem)
close_ngsm(modem);
 
if (data->gpio) {
-   l_gpio_writer_set(data->gpio, 1, _value);
-   g_timeout_add(750, gpio_power_off_cb, modem);
-   } else
-   ofono_modem_set_powered(modem, FALSE);
+   if (ofono_modem_get_boolean(modem, "GpioLevel")) {
+   gpio_value = 0;
+   l_gpio_writer_set(data->gpio, 1, _value);
+   } else {
+   l_gpio_writer_set(data->gpio, 1, _value);
+   g_timeout_add(750, gpio_power_off_cb, modem);
+   return;
+   }
+   }
+
+   ofono_modem_set_powered(modem, FALSE);
 
 }
 
@@ -1164,7 +1171,7 @@ static int open_serial(struct ofono_modem *modem)
return -EIO;
}
 
-   if (data->gpio)
+   if (data->gpio && !ofono_modem_get_boolean(modem, "GpioLevel"))
g_timeout_add(2100, gpio_power_on_cb, data);
 
/*
diff --git a/plugins/udevng.c b/plugins/udevng.c
index db13073e..8b1943aa 100644
--- a/plugins/udevng.c
+++ b/plugins/udevng.c
@@ -921,6 +921,11 @@ static gboolean setup_quectel_serial(struct modem_info 
*modem)
if (value)
ofono_modem_set_string(modem->modem, "GpioOffset", value);
 
+   value = udev_device_get_property_value(info->dev,
+   "OFONO_QUECTEL_GPIO_LEVEL");
+   if (value)
+   ofono_modem_set_boolean(modem->modem, "GpioLevel", TRUE);
+
value = udev_device_get_property_value(info->dev,
"OFONO_QUECTEL_MUX");
if (value)
-- 
2.28.0
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH v2] quectel: Power on/off with a gpio pulse

2020-10-01 Thread poeschel
From: Lars Poeschel 

Current implementation uses a gpio level of 1 for powering on quectel
modems using a gpio and a level of 0 for powering off.
This is wrong. Quectel modems use pulses for either power on and power
off. They turn on by the first pulse and turn then off by the next
pulse. The pulse length varies between different modems.
For power on the longest I could in the quectel hardware is "more than
2 seconds" from Quectel M95 Hardware Design Manual.
For Quectel EC21 this is ">= 100 ms".
For Quectel MC60 this is "recommended to be 100 ms".
For Quectel UC15 this is "at least 0.1 s".
For power off the four modems in question vary between a minimum pulse
length of 600-700ms.
This implements a 2100ms pulse for power on and 750ms for power off.
---
 plugins/quectel.c | 33 ++---
 1 file changed, 30 insertions(+), 3 deletions(-)

diff --git a/plugins/quectel.c b/plugins/quectel.c
index 6456775d..61ac906e 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -234,10 +234,21 @@ static void close_ngsm(struct ofono_modem *modem)
ofono_warn("Failed to restore line discipline");
 }
 
+static gboolean gpio_power_off_cb(gpointer user_data)
+{
+   struct ofono_modem *modem = (struct ofono_modem *)user_data;
+   struct quectel_data *data = ofono_modem_get_data(modem);
+   const uint32_t gpio_value = 0;
+
+   l_gpio_writer_set(data->gpio, 1, _value);
+   ofono_modem_set_powered(modem, FALSE);
+   return false;
+}
+
 static void close_serial(struct ofono_modem *modem)
 {
struct quectel_data *data = ofono_modem_get_data(modem);
-   uint32_t gpio_value = 0;
+   uint32_t gpio_value = 1;
 
DBG("%p", modem);
 
@@ -258,8 +269,12 @@ static void close_serial(struct ofono_modem *modem)
else
close_ngsm(modem);
 
-   l_gpio_writer_set(data->gpio, 1, _value);
-   ofono_modem_set_powered(modem, FALSE);
+   if (data->gpio) {
+   l_gpio_writer_set(data->gpio, 1, _value);
+   g_timeout_add(750, gpio_power_off_cb, modem);
+   } else
+   ofono_modem_set_powered(modem, FALSE);
+
 }
 
 static void dbus_hw_reply_properties(struct dbus_hw *hw)
@@ -1096,6 +,15 @@ static void init_timeout_cb(struct l_timeout *timeout, 
void *user_data)
l_timeout_modify_ms(timeout, 500);
 }
 
+static gboolean gpio_power_on_cb(gpointer user_data)
+{
+   struct quectel_data *data = user_data;
+   const uint32_t gpio_value = 0;
+
+   l_gpio_writer_set(data->gpio, 1, _value);
+   return false;
+}
+
 static int open_serial(struct ofono_modem *modem)
 {
struct quectel_data *data = ofono_modem_get_data(modem);
@@ -1139,6 +1163,9 @@ static int open_serial(struct ofono_modem *modem)
return -EIO;
}
 
+   if (data->gpio)
+   g_timeout_add(2100, gpio_power_on_cb, data);
+
/*
 * there are three different power-up scenarios:
 *
-- 
2.28.0
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


Re: [PATCH 2/2] quectel: Power on/off with a gpio pulse

2020-09-30 Thread Lars Poeschel
Hi Denis,

On Tue, Sep 29, 2020 at 09:22:26AM -0500, Denis Kenzior wrote:
> > @@ -237,7 +248,7 @@ static void close_ngsm(struct ofono_modem *modem)
> >   static void close_serial(struct ofono_modem *modem)
> >   {
> > struct quectel_data *data = ofono_modem_get_data(modem);
> > -   uint32_t gpio_value = 0;
> > +   uint32_t gpio_value = 1;
> > DBG("%p", modem);
> > @@ -258,7 +269,13 @@ static void close_serial(struct ofono_modem *modem)
> > else
> > close_ngsm(modem);
> > -   l_gpio_writer_set(data->gpio, 1, _value);
> > +   if (data->gpio) {
> > +   l_gpio_writer_set(data->gpio, 1, _value);
> > +   usleep(75);
> 
> usleep blocks the entire process, which is kinda bad if you have multiple
> modems / clients.  My normal rule of thumb is to NAK anything that can block
> for longer than 50-100ms...
> 
> Can this be done using g_timeout instead?

This was indeed not the first solution I tried. But I used the l_timeout_
thing that is used all over in quectel.c. I could not get this to work
in a way I was satisfied with. When I send a SIGTERM to the ofono
process close_serial is called but the timeout_callback never fires
and thus the modem does not power off. This is why I then tried usleep
and this works reliably.
Just to be sure I tried with g_timeout and this is the same like
l_timeout. The callback is not called.
Do you have another idea ?

Patch with g_timeout is below for reference

Regards,
Lars

-- >8 --
Subject: [PATCH] quectel: Power on/off with a gpio pulse

Current implementation uses a gpio level of 1 for powering on quectel
modems using a gpio and a level of 0 for powering off.
This is wrong. Quectel modems use pulses for either power on and power
off. They turn on by the first pulse and turn then off by the next
pulse. The pulse length varies between different modems.
For power on the longest I could in the quectel hardware is "more than
2 seconds" from Quectel M95 Hardware Design Manual.
For Quectel EC21 this is ">= 100 ms".
For Quectel MC60 this is "recommended to be 100 ms".
For Quectel UC15 this is "at least 0.1 s".
For power off the four modems in question vary between a minimum pulse
length of 600-700ms.
This implements a 2100ms pulse for power on and 750ms for power off.
---
 plugins/quectel.c | 33 +++--
 1 file changed, 31 insertions(+), 2 deletions(-)

diff --git a/plugins/quectel.c b/plugins/quectel.c
index 6456775d..9ddb15e8 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -103,6 +103,7 @@ struct quectel_data {
int mux_ready_count;
int initial_ldisc;
struct l_gpio_writer *gpio;
+   struct l_timeout *gpio_timeout;
struct l_timeout *init_timeout;
size_t init_count;
guint init_cmd;
@@ -133,6 +134,16 @@ static void quectel_debug(const char *str, void *user_data)
ofono_info("%s%s", prefix, str);
 }

+static void gpio_timeout_cb(struct l_timeout *timeout, void *user_data)
+{
+   const uint32_t gpio_value = 0;
+   struct quectel_data *data = user_data;
+
+   l_gpio_writer_set(data->gpio, 1, _value);
+   l_timeout_remove(data->gpio_timeout);
+   data->gpio_timeout = NULL;
+}
+
 static int quectel_probe_gpio(struct ofono_modem *modem)
 {
struct quectel_data *data = ofono_modem_get_data(modem);
@@ -234,10 +245,20 @@ static void close_ngsm(struct ofono_modem *modem)
ofono_warn("Failed to restore line discipline");
 }

+static gboolean gpio_cb(gpointer user_data)
+{
+   struct l_gpio_writer *gpio = (struct l_gpio_writer *)user_data;
+   uint32_t gpio_value = 0;
+   DBG("%s", __func__);
+
+   l_gpio_writer_set(gpio, 1, _value);
+   return false;
+}
+
 static void close_serial(struct ofono_modem *modem)
 {
struct quectel_data *data = ofono_modem_get_data(modem);
-   uint32_t gpio_value = 0;
+   uint32_t gpio_value = 1;

DBG("%p", modem);

@@ -258,7 +279,11 @@ static void close_serial(struct ofono_modem *modem)
else
close_ngsm(modem);

-   l_gpio_writer_set(data->gpio, 1, _value);
+   if (data->gpio) {
+   l_gpio_writer_set(data->gpio, 1, _value);
+   g_timeout_add(750, gpio_cb, data->gpio);
+   }
+
ofono_modem_set_powered(modem, FALSE);
 }

@@ -1139,6 +1164,10 @@ static int open_serial(struct ofono_modem *modem)
return -EIO;
}

+   if (data->gpio)
+   data->gpio_timeout = l_timeout_create_ms(2100, gpio_timeout_cb,
+   data, NULL);
+
/*
 * there are three different power-up scenarios:
 *
--
2.28.0
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


Re: [PATCH 2/2] quectel: Power on/off with a gpio pulse

2020-09-25 Thread Lars Poeschel
On Fri, Sep 25, 2020 at 08:43:15AM +0200, Martin Hundebøll wrote:
> Hi Lars and Janez,
> 
> On 24/09/2020 13.02, Martin Hundebøll wrote:
> > Hi Lars,
> > 
> > On 24/09/2020 12.38, poesc...@lemonage.de wrote:
> > > From: Lars Poeschel 
> > > 
> > > Current implementation uses a gpio level of 1 for powering on quectel
> > > modems using a gpio and a level of 0 for powering off.
> > 
> > We actually implemented this on the M95 by keeping the POWER pin always
> > high, and then controlling power using the RESET pin. This avoids the
> > need for pulses, which I find simpler.
> 
> Sorry, this is not accurate. We control the regulator supplying the modem,
> not the reset pin.

But this is bad also. The modem does a lot of things after you tell it
to power-off for example unregistering from the network gracefully. It
also might save some settings it uses internally or whatever.

You are using a way that does not seem to be intended by the vendor and
it reading the hardware design document it is also not obvious to me.
The obivous way to me is just using the PWR_KEY pin that every supported
quectel modem in ofono provides ready to use. And doing a pulse on this
is also not very hard.

I am open to discuss if we should power-off the modem with the pulse or
use the AT+QPOWD at command instead, but for power-on I think the pulse
is the way to go.

By the way this is not specific to the M95 or EC21. This does apply to
all ofono-supported quectel modems.

For me I don't have the choice. I have to support the pulse-approach
somehow, either ofono accepts it upstream or I have to maintain it as a
private patch, as I have to support a hardware that is built as is.
I can imagine the same somehow applies to you. The question is now: What
to do ?
I would like to see the pulse-approach in ofono as a default. We can
then work out a way to configure the level-solution you need maybe as a
new envionment option ?
What do others think ?

Regards,
Lars
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH 1/2] quectel: Extend power-on timeout

2020-09-24 Thread poeschel
From: Lars Poeschel 

More complicated modems emerge and they need longer start-up times. An
EC21 takes about 13 seconds to boot up. This is slightly longer than the
20 * 500 ms we have at the moment. This extends the retries to 30, so we
have 30 * 500 ms and this does successfully power up an EC21 modem.
---
 plugins/quectel.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/plugins/quectel.c b/plugins/quectel.c
index c3343008..6456775d 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -1086,8 +1086,8 @@ static void init_timeout_cb(struct l_timeout *timeout, 
void *user_data)
 
DBG("%p", modem);
 
-   if (data->init_count++ >= 20) {
-   ofono_error("failed to init modem after 20 attempts");
+   if (data->init_count++ >= 30) {
+   ofono_error("failed to init modem after 30 attempts");
close_serial(modem);
return;
}
-- 
2.28.0
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH 2/2] quectel: Power on/off with a gpio pulse

2020-09-24 Thread poeschel
From: Lars Poeschel 

Current implementation uses a gpio level of 1 for powering on quectel
modems using a gpio and a level of 0 for powering off.
This is wrong. Quectel modems use pulses for either power on and power
off. They turn on by the first pulse and turn then off by the next
pulse. The pulse length varies between different modems.
For power on the longest I could in the quectel hardware is "more than
2 seconds" from Quectel M95 Hardware Design Manual.
For Quectel EC21 this is ">= 100 ms".
For Quectel MC60 this is "recommended to be 100 ms".
For Quectel UC15 this is "at least 0.1 s".
For power off the four modems in question vary between a minimum pulse
length of 600-700ms.
This implements a 2100ms pulse for power on and 750ms for power off.
---
 plugins/quectel.c | 25 +++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/plugins/quectel.c b/plugins/quectel.c
index 6456775d..1d8da528 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -103,6 +103,7 @@ struct quectel_data {
int mux_ready_count;
int initial_ldisc;
struct l_gpio_writer *gpio;
+   struct l_timeout *gpio_timeout;
struct l_timeout *init_timeout;
size_t init_count;
guint init_cmd;
@@ -133,6 +134,16 @@ static void quectel_debug(const char *str, void *user_data)
ofono_info("%s%s", prefix, str);
 }
 
+static void gpio_timeout_cb(struct l_timeout *timeout, void *user_data)
+{
+   const uint32_t gpio_value = 0;
+   struct quectel_data *data = user_data;
+
+   l_gpio_writer_set(data->gpio, 1, _value);
+   l_timeout_remove(data->gpio_timeout);
+   data->gpio_timeout = NULL;
+}
+
 static int quectel_probe_gpio(struct ofono_modem *modem)
 {
struct quectel_data *data = ofono_modem_get_data(modem);
@@ -237,7 +248,7 @@ static void close_ngsm(struct ofono_modem *modem)
 static void close_serial(struct ofono_modem *modem)
 {
struct quectel_data *data = ofono_modem_get_data(modem);
-   uint32_t gpio_value = 0;
+   uint32_t gpio_value = 1;
 
DBG("%p", modem);
 
@@ -258,7 +269,13 @@ static void close_serial(struct ofono_modem *modem)
else
close_ngsm(modem);
 
-   l_gpio_writer_set(data->gpio, 1, _value);
+   if (data->gpio) {
+   l_gpio_writer_set(data->gpio, 1, _value);
+   usleep(75);
+   gpio_value = 0;
+   l_gpio_writer_set(data->gpio, 1, _value);
+   }
+
ofono_modem_set_powered(modem, FALSE);
 }
 
@@ -1139,6 +1156,10 @@ static int open_serial(struct ofono_modem *modem)
return -EIO;
}
 
+   if (data->gpio)
+   data->gpio_timeout = l_timeout_create_ms(2100, gpio_timeout_cb,
+   data, NULL);
+
/*
 * there are three different power-up scenarios:
 *
-- 
2.28.0
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[RFC PATCH] xmm7xxx: Fix non compiling file

2020-09-03 Thread poeschel
From: Lars Poeschel 

I get a compilation error on plugins/xmm7xx.c:

  CC   plugins/xmm7xxx.o
../plugins/xmm7xxx.c:63:10: fatal error: dbus.h: No such file or directory
   63 | #include "dbus.h"
  |  ^~~~
compilation terminated.

The commit that introduced this for me is: d2fd1721.
I do out-of-tree builds.
The fix is to simply delete the failing include. Since no other file in
ofono uses such an include i consider this as a mistake.
---
 plugins/xmm7xxx.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/plugins/xmm7xxx.c b/plugins/xmm7xxx.c
index bf90833d..5efdbe26 100644
--- a/plugins/xmm7xxx.c
+++ b/plugins/xmm7xxx.c
@@ -60,7 +60,6 @@
 #include "ofono.h"
 #include "gdbus.h"
 #include "util.h"
-#include "dbus.h"
 
 #define OFONO_COEX_INTERFACE OFONO_SERVICE ".intel.LteCoexistence"
 #define OFONO_COEX_AGENT_INTERFACE OFONO_SERVICE ".intel.LteCoexistenceAgent"
-- 
2.28.0
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


Re: Unable to establish ppp connection with Huawei dongle

2020-09-02 Thread Lars Poeschel
On Wed, Sep 02, 2020 at 10:46:27AM -, rakesp...@gmail.com wrote:
> Hi Lars ,
> 
> I have updated ofono to 1.31 
> 
> After that also same error message I am getting . I  captured pppdump for 
> this . I observe that I am not getting any response from the dongle. 

I think from the log you gave in your last mail that you are not
awaiting a response from the dongle but instead from your mobile
provider.

> So to verify if AT commands and APN settings are proper or not I followed 
> below steps using ofono & pppd .
> 
> 1. list-modems (ofono-testclient)
> 2. enable-modem (ofono-testclient)
> 3. create-internet-context airtelgprs.com(ofono-testclient)
> 4. online-modem (ofono-testclient)
> 5. echo -e -n 'AT+CGDCONT=1,"IP","airtelgprs.com"\r'  > /dev/ttyUSB0
> 6. echo -e -n 'AT+CGDATA="PPP",1\r'  > /dev/ttyUSB0
> 7. /usr/sbin/pppd ttyUSB0 115200 usepeerdns nodetach crtscts noauth passive 
> 
> With this ppp interface is up . 

And now what exactly is the difference between the pppdump you captured
from ofono and the pppdump captured with pppd ?

Regards,
Lars
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH v3] atmodem: Detect usage of AT+CGEREP

2020-09-01 Thread poeschel
From: Lars Poeschel 

Currently AT+CGEREP=2,1 is sent in case we don't know what the modem
needs. (default case) Not all modems understand this. So, we first query
what the modem supports with AT+CGEREP=? and then use this information
to be nice to the modem. This way modems, like the Quectel M95 that do
only understand AT+CGEREP=1 do also work nicely.
---
Changes since v2:
- (min <= 1 <= max)
- error handling

 drivers/atmodem/gprs.c | 64 --
 1 file changed, 62 insertions(+), 2 deletions(-)

diff --git a/drivers/atmodem/gprs.c b/drivers/atmodem/gprs.c
index 68470f11..c208f6e6 100644
--- a/drivers/atmodem/gprs.c
+++ b/drivers/atmodem/gprs.c
@@ -45,6 +45,7 @@
 #define MAX_CONTEXTS 255
 
 static const char *cgreg_prefix[] = { "+CGREG:", NULL };
+static const char *cgerep_prefix[] = { "+CGEREP:", NULL };
 static const char *cgdcont_prefix[] = { "+CGDCONT:", NULL };
 static const char *cgact_prefix[] = { "+CGACT:", NULL };
 static const char *none_prefix[] = { NULL };
@@ -648,6 +649,65 @@ static void gprs_initialized(gboolean ok, GAtResult 
*result, gpointer user_data)
ofono_gprs_register(gprs);
 }
 
+static void at_cgerep_test_cb(gboolean ok, GAtResult *result,
+   gpointer user_data)
+{
+   struct ofono_gprs *gprs = user_data;
+   struct gprs_data *gd = ofono_gprs_get_data(gprs);
+   GAtResultIter iter;
+   int min, max, arg1 = 0, arg2 = 0;
+   gboolean two_arguments = true;
+   char buf[20];
+
+   if (!ok) {
+   ofono_error("Error querying AT+CGEREP=? Failing...");
+   ofono_gprs_remove(gprs);
+   return;
+   }
+
+   g_at_result_iter_init(, result);
+
+   g_at_result_iter_next(, "+CGEREP:");
+
+   if (!g_at_result_iter_open_list()) {
+   ofono_error("Malformed reply from AT+CGEREP=? Failing...");
+   ofono_gprs_remove(gprs);
+   return;
+   }
+
+   while (g_at_result_iter_next_range(, , )) {
+   if ((min <= 1) && (max >= 1))
+   arg1 = 1;
+
+   if ((min <= 2) && (max >= 2))
+   arg1 = 2;
+   }
+
+   if (!g_at_result_iter_close_list())
+   goto out;
+
+   if (!g_at_result_iter_open_list()) {
+   two_arguments = false;
+   goto out;
+   }
+
+   while (g_at_result_iter_next_range(, , )) {
+   if ((min <= 1) && (max >= 1))
+   arg2 = 1;
+   }
+
+   g_at_result_iter_close_list();
+
+out:
+   if (two_arguments)
+   sprintf(buf, "AT+CGEREP=%u,%u", arg1, arg2);
+   else
+   sprintf(buf, "AT+CGEREP=%u", arg1);
+
+   g_at_chat_send(gd->chat, buf, none_prefix, gprs_initialized, gprs,
+   NULL);
+}
+
 static void at_cgreg_test_cb(gboolean ok, GAtResult *result,
gpointer user_data)
 {
@@ -702,8 +762,8 @@ retry:
gprs_initialized, gprs, NULL);
break;
default:
-   g_at_chat_send(gd->chat, "AT+CGEREP=2,1", none_prefix,
-   gprs_initialized, gprs, NULL);
+   g_at_chat_send(gd->chat, "AT+CGEREP=?", cgerep_prefix,
+   at_cgerep_test_cb, gprs, NULL);
break;
}
 
-- 
2.28.0
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


Re: Unable to establish ppp connection with Huawei dongle

2020-08-31 Thread Lars Poeschel
Hi,

I do notice two things looking at your logs:

On Thu, Aug 27, 2020 at 04:26:40AM -, rakesp...@gmail.com wrote:
> Hi ,
> 
> I am trying to enable lte connection with huawei dongle , but I am getting 
> below error log for activat/context. 
> 
> Aug 26 11:36:28 raspberrypi3 daemon.info ofonod[147]: Modem: > 
> AT+CGDCONT=1,"IP","airtelgprs.com"\r
> Aug 26 11:36:28 raspberrypi3 daemon.info ofonod[147]: Modem: < \r\nOK\r\n
> Aug 26 11:36:28 raspberrypi3 daemon.debug ofonod[147]: 
> ../ofono-1.24/drivers/atmodem/gprs-context.c:at_cgdcont_cb() ok 1

1. You use ofono-1.24 which is fairly old. Latest release is 1.31 so
far.

> Aug 26 11:36:28 raspberrypi3 daemon.info ofonod[147]: Modem: > 
> AT+CGDATA="PPP",1\r
> Aug 26 11:36:28 raspberrypi3 daemon.info ofonod[147]: Modem: < \r\nCONNECT 
> 1\r\n
> Aug 26 11:36:28 raspberrypi3 daemon.debug ofonod[147]: 
> ../ofono-1.24/drivers/atmodem/gprs-context.c:at_cgdata_cb() ok 1
> Aug 26 11:36:28 raspberrypi3 daemon.debug ofonod[147]: 
> ../ofono-1.24/drivers/atmodem/gprs-context.c:setup_ppp()
> Aug 26 11:36:28 raspberrypi3 daemon.info ofonod[147]: PPP: lcp: 
> pppcp_generate_event: current state 0:INITIAL
> Aug 26 11:36:28 raspberrypi3 daemon.info ofonod[147]: PPP: event: 0 (Up), 
> action: 2, new_state: 2 (CLOSED)
> Aug 26 11:36:28 raspberrypi3 daemon.info ofonod[147]: PPP: lcp: 
> pppcp_generate_event: current state 2:CLOSED
> Aug 26 11:36:28 raspberrypi3 daemon.info ofonod[147]: PPP: event: 2 (Open), 
> action: 1026, new_state: 6 (REQSENT)
> Aug 26 11:36:28 raspberrypi3 daemon.info ofonod[147]: PPP: lcp: 
> pppcp_initialize_restart_count: current state 2:CLOSED
> Aug 26 11:36:28 raspberrypi3 daemon.info ofonod[147]: PPP: lcp: 
> pppcp_send_configure_request: current state 2:CLOSED
> Aug 26 11:36:28 raspberrypi3 daemon.info ofonod[147]: PPP: 
> ../ofono-1.24/gatchat/gatppp.c:ppp_enter_phase() 1
> Aug 26 11:36:29 raspberrypi3 daemon.info ofonod[147]: PCUI: < 
> \r\n^BOOT:1113056,0,0,0,99\r\n
> Aug 26 11:36:30 raspberrypi3 daemon.info ofonod[147]: PCUI: < \r\n^RSSI:31\r\n
> Aug 26 11:36:30 raspberrypi3 daemon.info ofonod[147]: PCUI: < 
> \r\n^LTERSRP:-76,-6\r\n
> Aug 26 11:36:31 raspberrypi3 daemon.info ofonod[147]: PPP: lcp: 
> pppcp_timeout: current state 6:REQSENT
> Aug 26 11:36:31 raspberrypi3 daemon.info ofonod[147]: PPP: lcp: 
> pppcp_generate_event: current state 6:REQSENT
> Aug 26 11:36:31 raspberrypi3 daemon.info ofonod[147]: PPP: event: 4 (TO+), 
> action: 1006, new_state: 6 (REQSENT)

2. Ofono is trying to communicate with your provider here and sending
ppp configuration requests. It does timeout several times. That means
your mobile provider is not answering this requests.
At some time you should receive something other than a "(TO+)".
If I should guess, I would say this is because of wrong apn settings.
(username/password)

Regards,
Lars
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH v2] atmodem: Detect usage of AT+CGEREP

2020-08-31 Thread poeschel
From: Lars Poeschel 

Currently AT+CGEREP=2,1 is sent in case we don't know what the modem
needs. (default case) Not all modems understand this. So, we first query
what the modem supports with AT+CGEREP=? and then use this information
to be nice to the modem. This way modems, like the Quectel M95 that do
only understand AT+CGEREP=1 do also work nicely.
---
 drivers/atmodem/gprs.c | 59 --
 1 file changed, 57 insertions(+), 2 deletions(-)

diff --git a/drivers/atmodem/gprs.c b/drivers/atmodem/gprs.c
index 68470f11..443bdf77 100644
--- a/drivers/atmodem/gprs.c
+++ b/drivers/atmodem/gprs.c
@@ -45,6 +45,7 @@
 #define MAX_CONTEXTS 255
 
 static const char *cgreg_prefix[] = { "+CGREG:", NULL };
+static const char *cgerep_prefix[] = { "+CGEREP:", NULL };
 static const char *cgdcont_prefix[] = { "+CGDCONT:", NULL };
 static const char *cgact_prefix[] = { "+CGACT:", NULL };
 static const char *none_prefix[] = { NULL };
@@ -648,6 +649,60 @@ static void gprs_initialized(gboolean ok, GAtResult 
*result, gpointer user_data)
ofono_gprs_register(gprs);
 }
 
+static void at_cgerep_test_cb(gboolean ok, GAtResult *result,
+   gpointer user_data)
+{
+   struct ofono_gprs *gprs = user_data;
+   struct gprs_data *gd = ofono_gprs_get_data(gprs);
+   GAtResultIter iter;
+   int min, max, arg1 = 0, arg2 = 0;
+   gboolean two_arguments = true;
+   char buf[20];
+
+   if (!ok)
+   return;
+
+   g_at_result_iter_init(, result);
+
+   g_at_result_iter_next(, "+CGEREP:");
+
+   if (!g_at_result_iter_open_list())
+   return;
+
+   while (g_at_result_iter_next_range(, , )) {
+   if ((min <= 1) && (max >= 1))
+   arg1 = 1;
+
+   if ((min <= 2) && (max >= 2))
+   arg1 = 2;
+   }
+
+   if (!g_at_result_iter_close_list())
+   return;
+
+   if (!g_at_result_iter_open_list()) {
+   two_arguments = false;
+   goto out;
+   }
+
+   while (g_at_result_iter_next_range(, , )) {
+   if (min <= 1 <= max)
+   arg2 = 1;
+   }
+
+   if (!g_at_result_iter_close_list())
+   return;
+
+out:
+   if (two_arguments)
+   sprintf(buf, "AT+CGEREP=%u,%u", arg1, arg2);
+   else
+   sprintf(buf, "AT+CGEREP=%u", arg1);
+
+   g_at_chat_send(gd->chat, buf, none_prefix, gprs_initialized, gprs,
+   NULL);
+}
+
 static void at_cgreg_test_cb(gboolean ok, GAtResult *result,
gpointer user_data)
 {
@@ -702,8 +757,8 @@ retry:
gprs_initialized, gprs, NULL);
break;
default:
-   g_at_chat_send(gd->chat, "AT+CGEREP=2,1", none_prefix,
-   gprs_initialized, gprs, NULL);
+   g_at_chat_send(gd->chat, "AT+CGEREP=?", cgerep_prefix,
+   at_cgerep_test_cb, gprs, NULL);
break;
}
 
-- 
2.28.0
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


Re: [PATCH 1/2] atmodem: Detect usage of AT+CGEREP

2020-08-31 Thread Lars Poeschel
On Tue, Aug 25, 2020 at 11:49:02AM -0500, Denis Kenzior wrote:
> Hi Lars,
> 
> > > So in theory this could be written like:
> > > int max = -1;
> > > iter_open_list();
> > > 
> > > while (iter_next_range(, , )) {
> > >   if (max2 > max)
> > >   max = max2;
> > > }
> > > 
> > > iter_close_list();
> > 
> > I can do this and it does indeed work! :-)
> > 
> > This may be my personal thing, but I find this not very intuitive and
> > hard to read.
> > 
> > To make this more intuitive can we:
> > * move your proposed while loop to a new function
> > * name that function ...iter_next_range_or_list (or something like that)
> > * put that function into gatresult.c
> 
> I'm confused.  iter_next_range specifically handles ranges as defined by ITU
> v.250.  See section 5.7.3.1 "Range of Values".
> 
> Here's a small quote:
> "If more than one value is supported, then the values may be listed
> individually, separated by comma characters (IA5 2/12), or, when a
> continuous range of values is supported, by the first value in the range,
> followed by a hyphen character (IA5 2/13), followed by the last value in the
> range. The specification of single values and ranges of values may be
> intermixed within a single information text. In all cases, the supported
> values shall be indicated in ascending order."
> 
> The only thing the user has to do is open up a list, since some modems get
> this wrong and don't enclose the entire set in '()'
> 
> > * and in the new at_cgerep_test_cb just use this function ?
> 
> How would you return the set of supported settings?  I guess you could use
> something like l_uintset, but even knowing the valid theoretical range is
> tricky.
> 
> > 
> > I can imagine this new function can be of use at other places as well.
> > What do you think ?
> 
> Given my confusion above, no idea?

Well, given your various hints I think I slowly get how this is supposed
to work.
The main misunderstanding I had was about the role of iter_next_range().
I thought, it should iterate over the whole thing inside the paranthesis
'()' and give me the min and max of this thing. And it did not make
sense to me that it does behave differently for (0,1) and (0-1). Why
should I iterate multiple times inside of the paranthesis with its min -
max calling interface ?
This was what I meant with the function iter_next_range_or_list() as I
called it above that does what I originally expected from the
iter_next_range().

Ok, I will post a solution with your proposed while-loop.

Many thanks for your hints Denis!

Regards,
Lars
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH v2] atmodem: Signal quality on quectel serial modems

2020-08-21 Thread poeschel
From: Lars Poeschel 

As the default way of getting the signal quality with +CIND is also
unstable on quectel serial modems (the same as on quectel EC21). In fact
the signal quality is only updated on cell changes. Those trigger a
manual AT+CSQ in ofono and get an update this way, but the URCs do not
work.
So we implement a quectelish way here as well. The quectelish way is
very similar to the way ifx modems work. We can reuse their csq_notify
function.
---
 drivers/atmodem/network-registration.c | 24 +---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/drivers/atmodem/network-registration.c 
b/drivers/atmodem/network-registration.c
index 78b1994c..c1309f61 100644
--- a/drivers/atmodem/network-registration.c
+++ b/drivers/atmodem/network-registration.c
@@ -780,15 +780,26 @@ static void ifx_xciev_notify(GAtResult *result, gpointer 
user_data)
 */
 }
 
-static void ifx_xcsq_notify(GAtResult *result, gpointer user_data)
+static void ifx_quec_csq_notify(GAtResult *result, gpointer user_data)
 {
struct ofono_netreg *netreg = user_data;
+   struct at_netreg_data *nd = ofono_netreg_get_data(netreg);
int rssi, ber, strength;
GAtResultIter iter;
+   const char *prefix;
 
g_at_result_iter_init(, result);
 
-   if (!g_at_result_iter_next(, "+XCSQ:"))
+   switch (nd->vendor) {
+   case  OFONO_VENDOR_QUECTEL_SERIAL:
+   prefix = "+CSQN:";
+   break;
+   default:
+   prefix = "+XCSQ:";
+   break;
+   }
+
+   if (!g_at_result_iter_next(, prefix))
return;
 
if (!g_at_result_iter_next_number(, ))
@@ -2027,7 +2038,7 @@ static void at_creg_set_cb(gboolean ok, GAtResult 
*result, gpointer user_data)
/* Register for specific signal strength reports */
g_at_chat_register(nd->chat, "+XCIEV:", ifx_xciev_notify,
FALSE, netreg, NULL);
-   g_at_chat_register(nd->chat, "+XCSQ:", ifx_xcsq_notify,
+   g_at_chat_register(nd->chat, "+XCSQ:", ifx_quec_csq_notify,
FALSE, netreg, NULL);
g_at_chat_send(nd->chat, "AT+XCSQ=1", none_prefix,
NULL, NULL, NULL);
@@ -2118,6 +2129,13 @@ static void at_creg_set_cb(gboolean ok, GAtResult 
*result, gpointer user_data)
g_at_chat_send(nd->chat, "AT+QINDCFG=\"act\",1", none_prefix,
NULL, NULL, NULL);
break;
+   case OFONO_VENDOR_QUECTEL_SERIAL:
+   g_at_chat_register(nd->chat, "+CSQN:",
+   ifx_quec_csq_notify, FALSE, netreg, NULL);
+   /* Register for specific signal strength reports */
+   g_at_chat_send(nd->chat, "AT+QEXTUNSOL=\"SQ\",1", none_prefix,
+   NULL, NULL, NULL);
+   break;
default:
g_at_chat_send(nd->chat, "AT+CIND=?", cind_prefix,
cind_support_cb, netreg, NULL);
-- 
2.27.0
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


Re: [PATCH 1/2] atmodem: Detect usage of AT+CGEREP

2020-08-21 Thread Lars Poeschel
Hi Denis,

On Thu, Aug 20, 2020 at 09:41:28AM -0500, Denis Kenzior wrote:
> > > So why not just run iter_next_range in a loop?  it actually understands 
> > > both
> > > lists and ranges.  See cind_support_cb() for an example.
> > 
> > Ok, I can do this i a loop if you want.
> > 
> > > > +   /* if min1 == max1 we had no range but a list and that
> > > > +* means we are interested in the last number of that list*/
> > > > +   if (min1 == max1) {
> > > > +   while (!g_at_result_iter_close_list()) {
> > > > +   if (!g_at_result_iter_next_number(, ))
> > > > +   break;
> > > > +   }
> > > > +   }
> > > > +
> > > > +   if (!g_at_result_iter_skip_next()) {
> > > > +   two_arguments = false;
> > > > +   goto out;
> > > > +   }
> > > 
> > > Not sure what this is doing?  isn't +CGEREP just two lists ?  According 
> > > to 27.007:
> > > "+CGEREP: (list of supported s),(list of supported s)"
> > 
> > Well, we have to deal with very different +CGEREP results. For example
> > on the quectel EC21 I get this:
> > 
> > "+CGEREP: (0-2),(0,1)"
> > 
> > and on the quectel M95 I get this:
> > 
> > "+CGEREP: (0,1)"
> > 
> > So what the code does is this:
> > It tries to parse a range with
> > 
> > g_at_result_iter_next_range(, , )
> > 
> > Now two things can happen: It either parsed the range "(0-2)" then we
> > have min1 != max1, or it tried to parse a list "(0,1)". This time
> > iter_next_range() breaks on the comma ',' and exits with
> > min1 == max1 == 0. Then we know, we did not find the maximum value yet
> > and we enter the loop:
> > 
> > ▸··▸···while (!g_at_result_iter_close_list()) {
> > ▸··▸···▸···if (!g_at_result_iter_next_number(, ))
> > ▸··▸···▸···▸···break;
> > ▸··▸···}
> > 
> > This does then loop to the end of the list until iter_close_list()
> > becomes true, which is at the closing paranthesis ')'. max1 then
> > contains the last item in that list (which we suspect to be the
> > maximum value).
> 
> So in theory this could be written like:
> int max = -1;
> iter_open_list();
> 
> while (iter_next_range(, , )) {
>   if (max2 > max)
>   max = max2;
> }
> 
> iter_close_list();

I can do this and it does indeed work! :-)

This may be my personal thing, but I find this not very intuitive and
hard to read.

To make this more intuitive can we:
* move your proposed while loop to a new function
* name that function ...iter_next_range_or_list (or something like that)
* put that function into gatresult.c
* and in the new at_cgerep_test_cb just use this function ?

I can imagine this new function can be of use at other places as well.
What do you think ?

Regards,
Lars
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


Re: [RFC PATCH] atmodem: Signal quality on quectel serial modems

2020-08-20 Thread Lars Poeschel
On Wed, Aug 19, 2020 at 10:19:13AM -0500, Denis Kenzior wrote:
> Hi Lars,
> 
> On 8/19/20 7:43 AM, poesc...@lemonage.de wrote:
> > From: Lars Poeschel 
> > 
> > As the default way of getting the signal quality with +CIND is also
> > unstable on quectel serial modems (the same as on quectel EC21). In fact
> > the signal quality is only updated on cell changes. Those trigger a
> > manual AT+CSQ in ofono and get an update this way, but the URCs do not
> > work.
> > So we implement a quectelish way here as well.
> > 
> > --- >8 ---
> > 
> > I send this patch as a RFC because the quectel_csqn_notify function
> > very much duplicates the ifx_xcsq_notify function despite the "+CSQN"
> > string. I did not see a good way to reuse the already existing
> > function because the callback interface only has one user defined
> > pointer and this is used by the struct ofono_netreg pointer already.
> > Does anyone have a better idea ?
> 
> You could take advantage of the fact that at_netreg_data carries the vendor
> id in nd->vendor.  So if you wanted to make ifx_xcsq_notify you could do
> something like:
> 
> struct ofono_netreg *netreg = user_data;
> struct at_netreg_data *nd =
>   ofono_netreg_get_data(netreg);
> 
> switch (nd->vendor) {
> case ...
>   prefix = "+XCSQ:";
>   break;
> case ...
>   prefix = "+CSQN:";
>   break;
> }
> 

Denis, thank you for helping out!
I think I'll go for the vendor switch.

> Or just put the meat of ifx_xcsq_notify into a separate function that takes
> the prefix as a parameter...
> 
> Then ifx_xcsq_notify might look something like:
> 
> netreg_generic_strength_report("+XCSQ:");
> 

Regards,
Lars
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


Re: [PATCH 1/2] atmodem: Detect usage of AT+CGEREP

2020-08-20 Thread Lars Poeschel
On Wed, Aug 19, 2020 at 10:07:58AM -0500, Denis Kenzior wrote:
> Hi Lars,
> 
> On 8/19/20 7:13 AM, poesc...@lemonage.de wrote:
> > From: Lars Poeschel 
> > 
> > Currently AT+CGEREP=2,1 is sent in case we don't know what the modem
> > needs. (default case) Not all modems understand this. So, we first query
> > what the modem supports with AT+CGEREP=? and then use this information
> > to be nice to the modem. This way modems, like the Quectel M95 that do
> > only understand AT+CGEREP=1 do also work nicely.
> 
> I think this is a nice improvement, couple of comments below:

Thanks. :-)

> > ---
> >   drivers/atmodem/gprs.c | 75 --
> >   1 file changed, 73 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/atmodem/gprs.c b/drivers/atmodem/gprs.c
> > index d829e2e6..3900b95b 100644
> > --- a/drivers/atmodem/gprs.c
> > +++ b/drivers/atmodem/gprs.c
> > @@ -45,6 +45,7 @@
> >   #define MAX_CONTEXTS 255
> >   static const char *cgreg_prefix[] = { "+CGREG:", NULL };
> > +static const char *cgerep_prefix[] = { "+CGEREP:", NULL };
> >   static const char *cgdcont_prefix[] = { "+CGDCONT:", NULL };
> >   static const char *cgact_prefix[] = { "+CGACT:", NULL };
> >   static const char *none_prefix[] = { NULL };
> > @@ -647,6 +648,76 @@ static void gprs_initialized(gboolean ok, GAtResult 
> > *result, gpointer user_data)
> > ofono_gprs_register(gprs);
> >   }
> > +static void at_cgerep_test_cb(gboolean ok, GAtResult *result,
> > +   gpointer user_data)
> > +{
> > +   struct ofono_gprs *gprs = user_data;
> > +   struct gprs_data *gd = ofono_gprs_get_data(gprs);
> > +   GAtResultIter iter;
> > +   int min1, max1 = 1, min2, max2 = 1;
> > +   gboolean two_arguments = true;
> > +   char buf[20];
> > +
> > +   if (!ok)
> > +   return;
> 
> Hmm, maybe a good idea here is to print a warning and call
> ofono_gprs_remove(). Otherwise this will just fail silently for someone.

Ok, I will update this.

> > +
> > +   g_at_result_iter_init(, result);
> > +
> > +   g_at_result_iter_next(, "+CGEREP:");
> > +
> > +   if (!g_at_result_iter_open_list())
> > +   return;
> 
> Ditto here

Same here.

> > +
> > +   if (!g_at_result_iter_next_range(, , ))
> > +   return;
> > +
> 
> So why not just run iter_next_range in a loop?  it actually understands both
> lists and ranges.  See cind_support_cb() for an example.

Ok, I can do this i a loop if you want.

> > +   /* if min1 == max1 we had no range but a list and that
> > +* means we are interested in the last number of that list*/
> > +   if (min1 == max1) {
> > +   while (!g_at_result_iter_close_list()) {
> > +   if (!g_at_result_iter_next_number(, ))
> > +   break;
> > +   }
> > +   }
> > +
> > +   if (!g_at_result_iter_skip_next()) {
> > +   two_arguments = false;
> > +   goto out;
> > +   }
> 
> Not sure what this is doing?  isn't +CGEREP just two lists ?  According to 
> 27.007:
> "+CGEREP: (list of supported s),(list of supported s)"

Well, we have to deal with very different +CGEREP results. For example
on the quectel EC21 I get this:

"+CGEREP: (0-2),(0,1)"

and on the quectel M95 I get this:

"+CGEREP: (0,1)"

So what the code does is this:
It tries to parse a range with

g_at_result_iter_next_range(, , )

Now two things can happen: It either parsed the range "(0-2)" then we
have min1 != max1, or it tried to parse a list "(0,1)". This time
iter_next_range() breaks on the comma ',' and exits with
min1 == max1 == 0. Then we know, we did not find the maximum value yet
and we enter the loop:

▸··▸···while (!g_at_result_iter_close_list()) {
▸··▸···▸···if (!g_at_result_iter_next_number(, ))
▸··▸···▸···▸···break;
▸··▸···}

This does then loop to the end of the list until iter_close_list()
becomes true, which is at the closing paranthesis ')'. max1 then
contains the last item in that list (which we suspect to be the
maximum value).

Now we have min1 and max1 in both cases(list and range). Now if

g_at_result_iter_skip_next()

fails, we are at the end of the AT result and we had only one argument
to +CGEREP or we start trying to parse the second argument also. (See
below.)

At the end we construct our AT+CGEREP= string depending on if we had
two or only one argument.

Does this sound reasonable ?

> > +
> > +   if (!g_at_result_iter_open_list()) {
> > 

[RFC PATCH] atmodem: Signal quality on quectel serial modems

2020-08-19 Thread poeschel
From: Lars Poeschel 

As the default way of getting the signal quality with +CIND is also
unstable on quectel serial modems (the same as on quectel EC21). In fact
the signal quality is only updated on cell changes. Those trigger a
manual AT+CSQ in ofono and get an update this way, but the URCs do not
work.
So we implement a quectelish way here as well.

--- >8 ---

I send this patch as a RFC because the quectel_csqn_notify function
very much duplicates the ifx_xcsq_notify function despite the "+CSQN"
string. I did not see a good way to reuse the already existing
function because the callback interface only has one user defined
pointer and this is used by the struct ofono_netreg pointer already.
Does anyone have a better idea ?

Thanks,
Lars
---
 drivers/atmodem/network-registration.c | 34 ++
 1 file changed, 34 insertions(+)

diff --git a/drivers/atmodem/network-registration.c 
b/drivers/atmodem/network-registration.c
index 78b1994c..74829201 100644
--- a/drivers/atmodem/network-registration.c
+++ b/drivers/atmodem/network-registration.c
@@ -1017,6 +1017,33 @@ static void quectel_qind_notify(GAtResult *result, 
gpointer user_data)
}
 }
 
+static void quectel_csqn_notify(GAtResult *result, gpointer user_data)
+{
+   struct ofono_netreg *netreg = user_data;
+   int rssi, ber, strength;
+   GAtResultIter iter;
+
+   g_at_result_iter_init(, result);
+
+   if (!g_at_result_iter_next(, "+CSQN:"))
+   return;
+
+   if (!g_at_result_iter_next_number(, ))
+   return;
+
+   if (!g_at_result_iter_next_number(, ))
+   return;
+
+   DBG("rssi %d ber %d", rssi, ber);
+
+   if (rssi == 99)
+   strength = -1;
+   else
+   strength = (rssi * 100) / 31;
+
+   ofono_netreg_strength_notify(netreg, strength);
+}
+
 static gboolean notify_time(gpointer user_data)
 {
struct ofono_netreg *netreg = user_data;
@@ -2118,6 +2145,13 @@ static void at_creg_set_cb(gboolean ok, GAtResult 
*result, gpointer user_data)
g_at_chat_send(nd->chat, "AT+QINDCFG=\"act\",1", none_prefix,
NULL, NULL, NULL);
break;
+   case OFONO_VENDOR_QUECTEL_SERIAL:
+   g_at_chat_register(nd->chat, "+CSQN:",
+   quectel_csqn_notify, FALSE, netreg, NULL);
+   /* Register for specific signal strength reports */
+   g_at_chat_send(nd->chat, "AT+QEXTUNSOL=\"SQ\",1", none_prefix,
+   NULL, NULL, NULL);
+   break;
default:
g_at_chat_send(nd->chat, "AT+CIND=?", cind_prefix,
cind_support_cb, netreg, NULL);
-- 
2.27.0
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH 2/2] atmodem: Deactivate AT+CPSB for quectel serial modems

2020-08-19 Thread poeschel
From: Lars Poeschel 

There are at the moment two quectel modems in ofono vendored as
OFONO_VENDOR_QUECTEL_SERIAL: The M95 and the MC60.
Both modems are GSM only modems, and their official documentation does
not mention the AT+CPSB command.
I have a M95 here that gives an error on issuing the AT+CPSB=1 command.
So skip this command for these two modems.
---
 drivers/atmodem/gprs.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/atmodem/gprs.c b/drivers/atmodem/gprs.c
index 3900b95b..f4c714e8 100644
--- a/drivers/atmodem/gprs.c
+++ b/drivers/atmodem/gprs.c
@@ -626,6 +626,7 @@ static void gprs_initialized(gboolean ok, GAtResult 
*result, gpointer user_data)
NULL, NULL, NULL);
break;
case OFONO_VENDOR_QUECTEL_EC2X:
+   case OFONO_VENDOR_QUECTEL_SERIAL:
break;
default:
g_at_chat_register(gd->chat, "+CPSB:", cpsb_notify,
-- 
2.27.0
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH 1/2] atmodem: Detect usage of AT+CGEREP

2020-08-19 Thread poeschel
From: Lars Poeschel 

Currently AT+CGEREP=2,1 is sent in case we don't know what the modem
needs. (default case) Not all modems understand this. So, we first query
what the modem supports with AT+CGEREP=? and then use this information
to be nice to the modem. This way modems, like the Quectel M95 that do
only understand AT+CGEREP=1 do also work nicely.
---
 drivers/atmodem/gprs.c | 75 --
 1 file changed, 73 insertions(+), 2 deletions(-)

diff --git a/drivers/atmodem/gprs.c b/drivers/atmodem/gprs.c
index d829e2e6..3900b95b 100644
--- a/drivers/atmodem/gprs.c
+++ b/drivers/atmodem/gprs.c
@@ -45,6 +45,7 @@
 #define MAX_CONTEXTS 255
 
 static const char *cgreg_prefix[] = { "+CGREG:", NULL };
+static const char *cgerep_prefix[] = { "+CGEREP:", NULL };
 static const char *cgdcont_prefix[] = { "+CGDCONT:", NULL };
 static const char *cgact_prefix[] = { "+CGACT:", NULL };
 static const char *none_prefix[] = { NULL };
@@ -647,6 +648,76 @@ static void gprs_initialized(gboolean ok, GAtResult 
*result, gpointer user_data)
ofono_gprs_register(gprs);
 }
 
+static void at_cgerep_test_cb(gboolean ok, GAtResult *result,
+   gpointer user_data)
+{
+   struct ofono_gprs *gprs = user_data;
+   struct gprs_data *gd = ofono_gprs_get_data(gprs);
+   GAtResultIter iter;
+   int min1, max1 = 1, min2, max2 = 1;
+   gboolean two_arguments = true;
+   char buf[20];
+
+   if (!ok)
+   return;
+
+   g_at_result_iter_init(, result);
+
+   g_at_result_iter_next(, "+CGEREP:");
+
+   if (!g_at_result_iter_open_list())
+   return;
+
+   if (!g_at_result_iter_next_range(, , ))
+   return;
+
+   /* if min1 == max1 we had no range but a list and that
+* means we are interested in the last number of that list*/
+   if (min1 == max1) {
+   while (!g_at_result_iter_close_list()) {
+   if (!g_at_result_iter_next_number(, ))
+   break;
+   }
+   }
+
+   if (!g_at_result_iter_skip_next()) {
+   two_arguments = false;
+   goto out;
+   }
+
+   if (!g_at_result_iter_open_list()) {
+   two_arguments = false;
+   goto out;
+   }
+
+   if (!g_at_result_iter_next_range(, , )) {
+   two_arguments = false;
+   goto out;
+   }
+
+   if (min2 == max2) {
+   while (!g_at_result_iter_close_list()) {
+   if (!g_at_result_iter_next_number(, )) {
+   break;
+   }
+   }
+   }
+
+out:
+   if (max1 > 2)
+   max1 = 2;
+
+   if (max2 > 1)
+   max2 = 1;
+
+   if (two_arguments)
+   sprintf(buf, "AT+CGEREP=%u,%u", max1, max2);
+   else
+   sprintf(buf, "AT+CGEREP=%u", max1);
+
+   g_at_chat_send(gd->chat, buf, none_prefix, gprs_initialized, gprs, 
NULL);
+}
+
 static void at_cgreg_test_cb(gboolean ok, GAtResult *result,
gpointer user_data)
 {
@@ -701,8 +772,8 @@ retry:
gprs_initialized, gprs, NULL);
break;
default:
-   g_at_chat_send(gd->chat, "AT+CGEREP=2,1", none_prefix,
-   gprs_initialized, gprs, NULL);
+   g_at_chat_send(gd->chat, "AT+CGEREP=?", cgerep_prefix,
+   at_cgerep_test_cb, gprs, NULL);
break;
}
 
-- 
2.27.0
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH v4] gprs: Quectel EC21 does not understand AT+CPSB

2020-08-17 Thread poeschel
From: Lars Poeschel 

The Quectel EC21 modem does not understand the AT+CPSB command, and we
did not find a suitable replacement in the
Quectel_EC25_AT_Commands_Manual_V1.3.pdf
AT+CPSB gives an error on this modem, so we just skip it.
---
 drivers/atmodem/gprs.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/atmodem/gprs.c b/drivers/atmodem/gprs.c
index b637f733..d829e2e6 100644
--- a/drivers/atmodem/gprs.c
+++ b/drivers/atmodem/gprs.c
@@ -624,6 +624,8 @@ static void gprs_initialized(gboolean ok, GAtResult 
*result, gpointer user_data)
g_at_chat_send(gd->chat, "AT#PSNT=1", none_prefix,
NULL, NULL, NULL);
break;
+   case OFONO_VENDOR_QUECTEL_EC2X:
+   break;
default:
g_at_chat_register(gd->chat, "+CPSB:", cpsb_notify,
FALSE, gprs, NULL);
-- 
2.27.0
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


Re: [PATCH v3] gprs: Quectel EC21 does not understand AT+CPSB

2020-08-17 Thread Lars Poeschel
On Thu, Aug 13, 2020 at 10:03:12AM -0500, Denis Kenzior wrote:
> > @@ -624,6 +667,12 @@ static void gprs_initialized(gboolean ok, GAtResult 
> > *result, gpointer user_data)
> > g_at_chat_send(gd->chat, "AT#PSNT=1", none_prefix,
> > NULL, NULL, NULL);
> > break;
> > +   case OFONO_VENDOR_QUECTEL_EC2X:
> > +   g_at_chat_register(gd->chat, "+QIND",
> > +   quectel_qind_notify, FALSE, gprs, NULL);
> > +   /* The "QIND: \"act\", ..." URC is activated in
> > +* network-registration.c */
> 
> You're using the QIND in network-registration.c to notify CREG technology.
> And now you're trying to use this here in place of CPSB.  This seems fishy
> to me. Looking at the Quectel AT commands manual, I'd just guess they do not
> support this bearer concept at all...

Until here, you could tell me way more than the official quectel
support. Thank you for this!
I will post a new version of the patch that will just skip the AT+CPSB
command.

Thanks a lot!

Lars
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH v3] gprs: Quectel EC21 does not understand AT+CPSB

2020-08-13 Thread poeschel
From: Lars Poeschel 

The Quectel EC21 modem does not understand the AT+CPSB command, so
aquire the current packet switched bearer from quectel proprietary
QIND:"act" URC.
---
 drivers/atmodem/gprs.c | 49 ++
 1 file changed, 49 insertions(+)

diff --git a/drivers/atmodem/gprs.c b/drivers/atmodem/gprs.c
index b637f733..4e00d3cf 100644
--- a/drivers/atmodem/gprs.c
+++ b/drivers/atmodem/gprs.c
@@ -40,6 +40,7 @@
 #include "gatresult.h"
 
 #include "atmodem.h"
+#include "common.h"
 #include "vendor.h"
 
 #define MAX_CONTEXTS 255
@@ -596,6 +597,48 @@ static void cpsb_notify(GAtResult *result, gpointer 
user_data)
ofono_gprs_bearer_notify(gprs, bearer);
 }
 
+static void quectel_qind_notify(GAtResult *result, gpointer user_data)
+{
+   struct ofono_gprs *gprs = user_data;
+   struct gprs_data *gd = ofono_gprs_get_data(gprs);
+   int bearer;
+   const char *str;
+   GAtResultIter iter;
+
+   g_at_result_iter_init(, result);
+
+   if (!g_at_result_iter_next(, "+QIND:"))
+   return;
+
+   if (!g_at_result_iter_next_string(, ))
+   return;
+
+   if (g_str_equal("act", str)) {
+   if (!g_at_result_iter_next_string(, ))
+   return;
+
+   DBG("technology %s", str);
+   bearer = PACKET_BEARER_NONE;
+   if (g_str_equal("GSM", str))
+   bearer = PACKET_BEARER_GPRS;
+   else if (g_str_equal("EGPRS", str))
+   bearer = PACKET_BEARER_EGPRS;
+   else if (g_str_equal("WCDMA", str))
+   bearer = PACKET_BEARER_UMTS;
+   else if (g_str_equal("HSDPA", str))
+   bearer = PACKET_BEARER_HSDPA;
+   else if (g_str_equal("HSUPA", str))
+   bearer = PACKET_BEARER_HSUPA;
+   else if (g_str_equal("HSDPA", str))
+   bearer = PACKET_BEARER_HSUPA_HSDPA;
+   else if (g_str_equal("LTE", str))
+   bearer = PACKET_BEARER_EPS;
+
+   ofono_gprs_bearer_notify(gprs, bearer);
+   }
+}
+
+
 static void gprs_initialized(gboolean ok, GAtResult *result, gpointer 
user_data)
 {
struct ofono_gprs *gprs = user_data;
@@ -624,6 +667,12 @@ static void gprs_initialized(gboolean ok, GAtResult 
*result, gpointer user_data)
g_at_chat_send(gd->chat, "AT#PSNT=1", none_prefix,
NULL, NULL, NULL);
break;
+   case OFONO_VENDOR_QUECTEL_EC2X:
+   g_at_chat_register(gd->chat, "+QIND",
+   quectel_qind_notify, FALSE, gprs, NULL);
+   /* The "QIND: \"act\", ..." URC is activated in
+* network-registration.c */
+   break;
default:
g_at_chat_register(gd->chat, "+CPSB:", cpsb_notify,
FALSE, gprs, NULL);
-- 
2.27.0
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


Re: [PATCH v2 3/3] gprs: Quectel EC21 does not understand AT+CPSB

2020-08-12 Thread Lars Poeschel
On Tue, Aug 11, 2020 at 10:55:35AM -0500, Denis Kenzior wrote:
> Hi Lars,
> 
> On 8/11/20 6:42 AM, poesc...@lemonage.de wrote:
> > From: Lars Poeschel 
> > 
> > The Quectel EC21 modem does not understand the AT+CPSB command, so
> > aquire the current packet switched bearer from CGREG URC.
> > ---
> >   drivers/atmodem/gprs.c | 32 ++--
> >   1 file changed, 30 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/atmodem/gprs.c b/drivers/atmodem/gprs.c
> > index b637f733..5583d6fa 100644
> > --- a/drivers/atmodem/gprs.c
> > +++ b/drivers/atmodem/gprs.c
> > @@ -40,6 +40,7 @@
> >   #include "gatresult.h"
> >   #include "atmodem.h"
> > +#include "common.h"
> >   #include "vendor.h"
> >   #define MAX_CONTEXTS 255
> > @@ -98,6 +99,29 @@ static void list_contexts_data_unref(gpointer user_data)
> > g_free(ld);
> >   }
> > +static int act_to_bearer(int act)
> > +{
> > +   switch (act) {
> > +   case 0:
> > +   case 1:
> > +   return PACKET_BEARER_GPRS;
> > +   case 2:
> > +   return PACKET_BEARER_UMTS;
> > +   case 3:
> > +   return PACKET_BEARER_EGPRS;
> > +   case 4:
> > +   return PACKET_BEARER_HSDPA;
> > +   case 5:
> > +   return PACKET_BEARER_HSUPA;
> > +   case 6:
> > +   return PACKET_BEARER_HSUPA_HSDPA;
> > +   case 7:
> > +   return PACKET_BEARER_EPS;
> > +   default:
> > +   return PACKET_BEARER_NONE;
> > +   }
> > +};
> > +
> 
> oFono driver interface is based on 27.007.  So that means values defined in
> 27.007 do not need to be 'converted'.  You can simply feed them in directly
> if they follow 27.007.

Well, yes. I saw this. But unfortunately at this point what is expected
are the 27.007 values from AT+CPSB defined in 7.29 (that EC21 quectel
modem does not support) and I get the values from AT+CGREG defined in 7.2.

> To me this looks like a no-op.  Is there a non-obvious reason why this code
> is needed?

These are the values defined in 7.2 (CGREG) called access technology
0 - GSM
2 - UTRAN
3 - GSM W/EGPRS
4 - UTRAN W/HSDPA
5 - UTRAN W/HSUPA
6 - UTRAN W/HSDPA and HSUPA
7 - E-UTRAN

and these are the values defined in 7.29 (CPSB / ofono) called current
bearer:

1 - GPRS
2 - EGPRS
3 - Non-HSUPA in uplink and non-HSDPA in downlink.
4 - HSUPA in uplink and non-HSDPA in downlink.
5 - Non-HSUPA in uplink and HSDPA in downlink.
6 - HSUPA in uplink and HSDPA in downlink.
7 - EPS
8 - 5GS

You see ? They are similar but not the same. So I opted for the
conversion function.

> >   static void at_cgatt_cb(gboolean ok, GAtResult *result, gpointer 
> > user_data)
> >   {
> > struct cb_data *cbd = user_data;
> > @@ -342,11 +366,11 @@ static void at_gprs_list_active_contexts(struct 
> > ofono_gprs *gprs,
> >   static void cgreg_notify(GAtResult *result, gpointer user_data)
> >   {
> > struct ofono_gprs *gprs = user_data;
> > -   int status;
> > +   int status, tech;
> > struct gprs_data *gd = ofono_gprs_get_data(gprs);
> > if (at_util_parse_reg_unsolicited(result, "+CGREG:", ,
> > -   NULL, NULL, NULL, gd->vendor) == FALSE)
> > +   NULL, NULL, , gd->vendor) == FALSE)
> > return;
> > /*
> > @@ -372,6 +396,8 @@ static void cgreg_notify(GAtResult *result, gpointer 
> > user_data)
> > }
> > ofono_gprs_status_notify(gprs, status);
> > +   if (gd->vendor == OFONO_VENDOR_QUECTEL_EC2X)
> > +   ofono_gprs_bearer_notify(gprs, act_to_bearer(tech));
> 
> To follow up from above, any reason not to omit act_to_bearer() here?

See above.

> >   }
> >   static void cgev_notify(GAtResult *result, gpointer user_data)
> > @@ -624,6 +650,8 @@ static void gprs_initialized(gboolean ok, GAtResult 
> > *result, gpointer user_data)
> > g_at_chat_send(gd->chat, "AT#PSNT=1", none_prefix,
> > NULL, NULL, NULL);
> > break;
> > +   case OFONO_VENDOR_QUECTEL_EC2X:
> > +   break;
> > default:
> > g_at_chat_register(gd->chat, "+CPSB:", cpsb_notify,
> > FALSE, gprs, NULL);
> > 

Regards,
Lars
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH v2 1/3] Add a vendor OFONO_VENDOR_QUECTEL_EC2X

2020-08-11 Thread poeschel
From: Lars Poeschel 

The distinction between OFONO_VENDOR_QUECTEL and
OFONO_VENDOR_QUECTEL_SERIAL does not suffice for EC21/EC25 in some
places, so introduce and use a new vendor:
OFONO_VENDOR_QUECTEL_EC2X
---
 drivers/atmodem/sim.c   | 1 +
 drivers/atmodem/sms.c   | 2 ++
 drivers/atmodem/vendor.h| 1 +
 drivers/atmodem/voicecall.c | 3 ++-
 plugins/quectel.c   | 2 +-
 5 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/atmodem/sim.c b/drivers/atmodem/sim.c
index e750a139..6ab91655 100644
--- a/drivers/atmodem/sim.c
+++ b/drivers/atmodem/sim.c
@@ -1213,6 +1213,7 @@ static void at_pin_retries_query(struct ofono_sim *sim,
return;
break;
case OFONO_VENDOR_QUECTEL:
+   case OFONO_VENDOR_QUECTEL_EC2X:
if (g_at_chat_send(sd->chat, "AT+QPINC?", qpinc_prefix,
at_qpinc_cb, cbd, g_free) > 0)
return;
diff --git a/drivers/atmodem/sms.c b/drivers/atmodem/sms.c
index d502da72..ed3b1370 100644
--- a/drivers/atmodem/sms.c
+++ b/drivers/atmodem/sms.c
@@ -337,6 +337,7 @@ static inline void at_ack_delivery(struct ofono_sms *sms)
if (data->cnma_ack_pdu) {
switch (data->vendor) {
case OFONO_VENDOR_GEMALTO:
+   case OFONO_VENDOR_QUECTEL_EC2X:
snprintf(buf, sizeof(buf), "AT+CNMA=1");
break;
case OFONO_VENDOR_QUECTEL_SERIAL:
@@ -845,6 +846,7 @@ static gboolean build_cnmi_string(char *buf, int *cnmi_opts,
case OFONO_VENDOR_ZTE:
case OFONO_VENDOR_SIMCOM:
case OFONO_VENDOR_QUECTEL:
+   case OFONO_VENDOR_QUECTEL_EC2X:
/* MSM devices advertise support for mode 2, but return an
 * error if we attempt to actually use it. */
mode = "1";
diff --git a/drivers/atmodem/vendor.h b/drivers/atmodem/vendor.h
index d839d1e0..6bac7f89 100644
--- a/drivers/atmodem/vendor.h
+++ b/drivers/atmodem/vendor.h
@@ -44,6 +44,7 @@ enum ofono_vendor {
OFONO_VENDOR_WAVECOM_Q2XXX,
OFONO_VENDOR_ALCATEL,
OFONO_VENDOR_QUECTEL,
+   OFONO_VENDOR_QUECTEL_EC2X,
OFONO_VENDOR_QUECTEL_SERIAL,
OFONO_VENDOR_UBLOX,
OFONO_VENDOR_XMM,
diff --git a/drivers/atmodem/voicecall.c b/drivers/atmodem/voicecall.c
index e7f24b60..4797227e 100644
--- a/drivers/atmodem/voicecall.c
+++ b/drivers/atmodem/voicecall.c
@@ -1114,7 +1114,8 @@ static int at_voicecall_probe(struct ofono_voicecall *vc, 
unsigned int vendor,
g_at_chat_send(vd->chat, "AT+CLIP=1", NULL, NULL, NULL, NULL);
g_at_chat_send(vd->chat, "AT+CDIP=1", NULL, NULL, NULL, NULL);
 
-   if (vd->vendor != OFONO_VENDOR_QUECTEL)
+   if ((vd->vendor != OFONO_VENDOR_QUECTEL) &&
+   (vd->vendor != OFONO_VENDOR_QUECTEL_EC2X))
g_at_chat_send(vd->chat, "AT+CNAP=1", NULL, NULL, NULL, NULL);
 
switch (vd->vendor) {
diff --git a/plugins/quectel.c b/plugins/quectel.c
index 203b702e..8ca901f2 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -1032,7 +1032,7 @@ static void cgmm_cb(int ok, GAtResult *result, void 
*user_data)
data->model = QUECTEL_MC60;
} else if (strcmp(model, "EC21") == 0) {
DBG("%p model EC21", modem);
-   data->vendor = OFONO_VENDOR_QUECTEL;
+   data->vendor = OFONO_VENDOR_QUECTEL_EC2X;
data->model = QUECTEL_EC21;
} else {
ofono_warn("%p unknown model: '%s'", modem, model);
-- 
2.27.0
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH v2 2/3] atmodem: Get strength and tech the quectel way on EC21

2020-08-11 Thread poeschel
From: Lars Poeschel 

I had some trouble getting network strengh and access technology the
standard way on Quectel EC21. It does work - but only kind of. I did not
get URCs when I am sure I should. This way through CIEV, CIND and CMER
is also not documented in Quectel documentation, so I suspect this to be
unsupported.
This is now changed to the "quectelish" way of gettings those values and
this does work more fine-grained and reliable on the Quectel EC21.
---
 drivers/atmodem/network-registration.c | 71 ++
 plugins/quectel.c  |  2 +-
 2 files changed, 72 insertions(+), 1 deletion(-)

diff --git a/drivers/atmodem/network-registration.c 
b/drivers/atmodem/network-registration.c
index cc702c2c..78b1994c 100644
--- a/drivers/atmodem/network-registration.c
+++ b/drivers/atmodem/network-registration.c
@@ -957,6 +957,66 @@ static void tlts_notify(GAtResult *result, gpointer 
user_data)
ofono_netreg_time_notify(netreg, >time);
 }
 
+static void quectel_qind_notify(GAtResult *result, gpointer user_data)
+{
+   struct ofono_netreg *netreg = user_data;
+   struct at_netreg_data *nd = ofono_netreg_get_data(netreg);
+   int rssi, ber, strength;
+   const char *str;
+   GAtResultIter iter;
+
+   g_at_result_iter_init(, result);
+
+   if (!g_at_result_iter_next(, "+QIND:"))
+   return;
+
+   if (!g_at_result_iter_next_string(, ))
+   return;
+
+   if (g_str_equal("csq", str)) {
+   if (!g_at_result_iter_next_number(, ))
+   return;
+
+   if (!g_at_result_iter_next_number(, ))
+   return;
+
+   DBG("rssi %d ber %d", rssi, ber);
+
+   if ((rssi == 99) || (rssi == 199))
+   strength = -1;
+   else if (rssi > 99) {
+   rssi -= 100;
+   strength = (rssi * 100) / 91;
+   } else
+   strength = (rssi * 100) / 31;
+
+   ofono_netreg_strength_notify(netreg, strength);
+   return;
+   }
+
+   if (g_str_equal("act", str)) {
+   nd->tech = -1;
+   if (!g_at_result_iter_next_string(, ))
+   return;
+
+   DBG("technology %s", str);
+   if (g_str_equal("GSM", str))
+   nd->tech = ACCESS_TECHNOLOGY_GSM;
+   else if (g_str_equal("EGPRS", str))
+   nd->tech = ACCESS_TECHNOLOGY_GSM_EGPRS;
+   else if (g_str_equal("WCDMA", str))
+   nd->tech = ACCESS_TECHNOLOGY_UTRAN;
+   else if (g_str_equal("HSDPA", str))
+   nd->tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA;
+   else if (g_str_equal("HSUPA", str))
+   nd->tech = ACCESS_TECHNOLOGY_UTRAN_HSUPA;
+   else if (g_str_equal("HSDPA", str))
+   nd->tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA_HSUPA;
+   else if (g_str_equal("LTE", str))
+   nd->tech = ACCESS_TECHNOLOGY_EUTRAN;
+   }
+}
+
 static gboolean notify_time(gpointer user_data)
 {
struct ofono_netreg *netreg = user_data;
@@ -2047,6 +2107,17 @@ static void at_creg_set_cb(gboolean ok, GAtResult 
*result, gpointer user_data)
case OFONO_VENDOR_SAMSUNG:
/* Signal strength reporting via CIND is not supported */
break;
+   case OFONO_VENDOR_QUECTEL_EC2X:
+   g_at_chat_register(nd->chat, "+QIND:",
+   quectel_qind_notify, FALSE, netreg, NULL);
+   /* Register for specific signal strength reports */
+   g_at_chat_send(nd->chat, "AT+QINDCFG=\"csq\",1", none_prefix,
+   NULL, NULL, NULL);
+
+   /* Register for network technology updates */
+   g_at_chat_send(nd->chat, "AT+QINDCFG=\"act\",1", none_prefix,
+   NULL, NULL, NULL);
+   break;
default:
g_at_chat_send(nd->chat, "AT+CIND=?", cind_prefix,
cind_support_cb, netreg, NULL);
diff --git a/plugins/quectel.c b/plugins/quectel.c
index 8ca901f2..c3343008 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -1286,7 +1286,7 @@ static void quectel_post_online(struct ofono_modem *modem)
 
DBG("%p", modem);
 
-   ofono_netreg_create(modem, 0, "atmodem", data->aux);
+   ofono_netreg_create(modem, data->vendor, "atmodem", data->aux);
 }
 
 static struct ofono_modem_driver quectel_driver = {
-- 
2.27.0
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH v2 3/3] gprs: Quectel EC21 does not understand AT+CPSB

2020-08-11 Thread poeschel
From: Lars Poeschel 

The Quectel EC21 modem does not understand the AT+CPSB command, so
aquire the current packet switched bearer from CGREG URC.
---
 drivers/atmodem/gprs.c | 32 ++--
 1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/drivers/atmodem/gprs.c b/drivers/atmodem/gprs.c
index b637f733..5583d6fa 100644
--- a/drivers/atmodem/gprs.c
+++ b/drivers/atmodem/gprs.c
@@ -40,6 +40,7 @@
 #include "gatresult.h"
 
 #include "atmodem.h"
+#include "common.h"
 #include "vendor.h"
 
 #define MAX_CONTEXTS 255
@@ -98,6 +99,29 @@ static void list_contexts_data_unref(gpointer user_data)
g_free(ld);
 }
 
+static int act_to_bearer(int act)
+{
+   switch (act) {
+   case 0:
+   case 1:
+   return PACKET_BEARER_GPRS;
+   case 2:
+   return PACKET_BEARER_UMTS;
+   case 3:
+   return PACKET_BEARER_EGPRS;
+   case 4:
+   return PACKET_BEARER_HSDPA;
+   case 5:
+   return PACKET_BEARER_HSUPA;
+   case 6:
+   return PACKET_BEARER_HSUPA_HSDPA;
+   case 7:
+   return PACKET_BEARER_EPS;
+   default:
+   return PACKET_BEARER_NONE;
+   }
+};
+
 static void at_cgatt_cb(gboolean ok, GAtResult *result, gpointer user_data)
 {
struct cb_data *cbd = user_data;
@@ -342,11 +366,11 @@ static void at_gprs_list_active_contexts(struct 
ofono_gprs *gprs,
 static void cgreg_notify(GAtResult *result, gpointer user_data)
 {
struct ofono_gprs *gprs = user_data;
-   int status;
+   int status, tech;
struct gprs_data *gd = ofono_gprs_get_data(gprs);
 
if (at_util_parse_reg_unsolicited(result, "+CGREG:", ,
-   NULL, NULL, NULL, gd->vendor) == FALSE)
+   NULL, NULL, , gd->vendor) == FALSE)
return;
 
/*
@@ -372,6 +396,8 @@ static void cgreg_notify(GAtResult *result, gpointer 
user_data)
}
 
ofono_gprs_status_notify(gprs, status);
+   if (gd->vendor == OFONO_VENDOR_QUECTEL_EC2X)
+   ofono_gprs_bearer_notify(gprs, act_to_bearer(tech));
 }
 
 static void cgev_notify(GAtResult *result, gpointer user_data)
@@ -624,6 +650,8 @@ static void gprs_initialized(gboolean ok, GAtResult 
*result, gpointer user_data)
g_at_chat_send(gd->chat, "AT#PSNT=1", none_prefix,
NULL, NULL, NULL);
break;
+   case OFONO_VENDOR_QUECTEL_EC2X:
+   break;
default:
g_at_chat_register(gd->chat, "+CPSB:", cpsb_notify,
FALSE, gprs, NULL);
-- 
2.27.0
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


Re: [PATCH 1/5] Add a vendor OFONO_VENDOR_QUECTEL_EC2X

2020-08-11 Thread Lars Poeschel
On Fri, Aug 07, 2020 at 11:09:19AM -0500, Denis Kenzior wrote:
> Hi Lars,
> 
> On 8/4/20 7:38 AM, poesc...@lemonage.de wrote:
> > From: Lars Poeschel 
> > 
> > The distinction between OFONO_VENDOR_QUECTEL and
> > OFONO_VENDOR_QUECTEL_SERIAL does not suffice for EC21/EC25 in some
> > places, so introduce and use a new vendor:
> > OFONO_VENDOR_QUECTEL_EC2X
> > ---
> >   drivers/atmodem/lte.c   | 2 +-
> >   drivers/atmodem/sim.c   | 1 +
> >   drivers/atmodem/sms.c   | 2 ++
> >   drivers/atmodem/vendor.h| 1 +
> >   drivers/atmodem/voicecall.c | 3 ++-
> >   plugins/quectel.c   | 2 +-
> >   6 files changed, 8 insertions(+), 3 deletions(-)
> > 
> 
> This doesn't apply:
> denkenz@localhost ~/ofono-master $ git am --3way ~/merge/\[PATCH\ 1_5\]\
> Add\ a\ vendor\ OFONO_VENDOR_QUECTEL_EC2X.eml
> Applying: Add a vendor OFONO_VENDOR_QUECTEL_EC2X
> error: sha1 information is lacking or useless (drivers/atmodem/lte.c).
> error: could not build fake ancestor
> Patch failed at 0001 Add a vendor OFONO_VENDOR_QUECTEL_EC2X
> 
> The chunk in drivers/atmodem/lte.c doesn't look like upstream code at all.

I am sorry. I started working on a lte context issue with this quectel
modem, but I am not sure I understood everything right. (This modem does
not support context ID zero.) So I decided to not submit this. I send
the remaining three patches as V2 rebased on master shortly.

Regards,
Lars
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH 3/5] atmodem: Get strength and tech the quectel way on EC21

2020-08-04 Thread poeschel
From: Lars Poeschel 

I had some trouble getting network strengh and access technology the
standard way on Quectel EC21. It does work - but only kind of. I did not
get URCs when I am sure I should. This way through CIEV, CIND and CMER
is also not documented in Quectel documentation, so I suspect this to be
unsupported.
This is now changed to the "quectelish" way of gettings those values and
this does work more fine-grained and reliable on the Quectel EC21.
---
 drivers/atmodem/network-registration.c | 71 ++
 plugins/quectel.c  |  2 +-
 2 files changed, 72 insertions(+), 1 deletion(-)

diff --git a/drivers/atmodem/network-registration.c 
b/drivers/atmodem/network-registration.c
index cc702c2c..78b1994c 100644
--- a/drivers/atmodem/network-registration.c
+++ b/drivers/atmodem/network-registration.c
@@ -957,6 +957,66 @@ static void tlts_notify(GAtResult *result, gpointer 
user_data)
ofono_netreg_time_notify(netreg, >time);
 }
 
+static void quectel_qind_notify(GAtResult *result, gpointer user_data)
+{
+   struct ofono_netreg *netreg = user_data;
+   struct at_netreg_data *nd = ofono_netreg_get_data(netreg);
+   int rssi, ber, strength;
+   const char *str;
+   GAtResultIter iter;
+
+   g_at_result_iter_init(, result);
+
+   if (!g_at_result_iter_next(, "+QIND:"))
+   return;
+
+   if (!g_at_result_iter_next_string(, ))
+   return;
+
+   if (g_str_equal("csq", str)) {
+   if (!g_at_result_iter_next_number(, ))
+   return;
+
+   if (!g_at_result_iter_next_number(, ))
+   return;
+
+   DBG("rssi %d ber %d", rssi, ber);
+
+   if ((rssi == 99) || (rssi == 199))
+   strength = -1;
+   else if (rssi > 99) {
+   rssi -= 100;
+   strength = (rssi * 100) / 91;
+   } else
+   strength = (rssi * 100) / 31;
+
+   ofono_netreg_strength_notify(netreg, strength);
+   return;
+   }
+
+   if (g_str_equal("act", str)) {
+   nd->tech = -1;
+   if (!g_at_result_iter_next_string(, ))
+   return;
+
+   DBG("technology %s", str);
+   if (g_str_equal("GSM", str))
+   nd->tech = ACCESS_TECHNOLOGY_GSM;
+   else if (g_str_equal("EGPRS", str))
+   nd->tech = ACCESS_TECHNOLOGY_GSM_EGPRS;
+   else if (g_str_equal("WCDMA", str))
+   nd->tech = ACCESS_TECHNOLOGY_UTRAN;
+   else if (g_str_equal("HSDPA", str))
+   nd->tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA;
+   else if (g_str_equal("HSUPA", str))
+   nd->tech = ACCESS_TECHNOLOGY_UTRAN_HSUPA;
+   else if (g_str_equal("HSDPA", str))
+   nd->tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA_HSUPA;
+   else if (g_str_equal("LTE", str))
+   nd->tech = ACCESS_TECHNOLOGY_EUTRAN;
+   }
+}
+
 static gboolean notify_time(gpointer user_data)
 {
struct ofono_netreg *netreg = user_data;
@@ -2047,6 +2107,17 @@ static void at_creg_set_cb(gboolean ok, GAtResult 
*result, gpointer user_data)
case OFONO_VENDOR_SAMSUNG:
/* Signal strength reporting via CIND is not supported */
break;
+   case OFONO_VENDOR_QUECTEL_EC2X:
+   g_at_chat_register(nd->chat, "+QIND:",
+   quectel_qind_notify, FALSE, netreg, NULL);
+   /* Register for specific signal strength reports */
+   g_at_chat_send(nd->chat, "AT+QINDCFG=\"csq\",1", none_prefix,
+   NULL, NULL, NULL);
+
+   /* Register for network technology updates */
+   g_at_chat_send(nd->chat, "AT+QINDCFG=\"act\",1", none_prefix,
+   NULL, NULL, NULL);
+   break;
default:
g_at_chat_send(nd->chat, "AT+CIND=?", cind_prefix,
cind_support_cb, netreg, NULL);
diff --git a/plugins/quectel.c b/plugins/quectel.c
index 50d1b5d3..9aa63c1c 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -1319,7 +1319,7 @@ static void quectel_post_online(struct ofono_modem *modem)
 
DBG("%p", modem);
 
-   ofono_netreg_create(modem, 0, "atmodem", data->aux);
+   ofono_netreg_create(modem, data->vendor, "atmodem", data->aux);
 }
 
 static struct ofono_modem_driver quectel_driver = {
-- 
2.27.0
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH 4/5] quectel: Try to update voltage only, when received "vbatt"

2020-08-04 Thread poeschel
From: Lars Poeschel 

As there are some more sources of +QIND: activated, do now only update
voltage when we get the
+QIND: "vbatt",-1
but not on things like
+QIND: "act","LTE"
or
+QIND: "csq",20,99
---
 plugins/quectel.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/plugins/quectel.c b/plugins/quectel.c
index 9aa63c1c..d11aba74 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -447,10 +447,12 @@ static void qind_notify(GAtResult *result, void 
*user_data)
if (!g_at_result_iter_next_string(, ))
return;
 
-   if (!g_at_result_iter_next_number(, ))
-   return;
+   if (g_strcmp0("vbatt", type)) {
+   if (!g_at_result_iter_next_number(, ))
+   return;
 
-   voltage_handle(hw->modem, event);
+   voltage_handle(hw->modem, event);
+   }
 }
 
 static void power_notify(GAtResult *result, void *user_data)
-- 
2.27.0
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH 1/5] Add a vendor OFONO_VENDOR_QUECTEL_EC2X

2020-08-04 Thread poeschel
From: Lars Poeschel 

The distinction between OFONO_VENDOR_QUECTEL and
OFONO_VENDOR_QUECTEL_SERIAL does not suffice for EC21/EC25 in some
places, so introduce and use a new vendor:
OFONO_VENDOR_QUECTEL_EC2X
---
 drivers/atmodem/lte.c   | 2 +-
 drivers/atmodem/sim.c   | 1 +
 drivers/atmodem/sms.c   | 2 ++
 drivers/atmodem/vendor.h| 1 +
 drivers/atmodem/voicecall.c | 3 ++-
 plugins/quectel.c   | 2 +-
 6 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/atmodem/lte.c b/drivers/atmodem/lte.c
index 4c21f822..b55b03c8 100644
--- a/drivers/atmodem/lte.c
+++ b/drivers/atmodem/lte.c
@@ -118,7 +118,7 @@ static void at_lte_set_default_attach_info(const struct 
ofono_lte *lte,
 
ldd->cid = 0;
 
-   if (ldd->vendor == OFONO_VENDOR_QUECTEL) {
+   if (ldd->vendor == OFONO_VENDOR_QUECTEL_EC2X) {
atom = __ofono_modem_find_atom(ofono_lte_get_modem(lte), 
OFONO_ATOM_TYPE_GPRS);
if (atom != NULL) {
struct ofono_gprs *gprs = __ofono_atom_get_data(atom);
diff --git a/drivers/atmodem/sim.c b/drivers/atmodem/sim.c
index e750a139..6ab91655 100644
--- a/drivers/atmodem/sim.c
+++ b/drivers/atmodem/sim.c
@@ -1213,6 +1213,7 @@ static void at_pin_retries_query(struct ofono_sim *sim,
return;
break;
case OFONO_VENDOR_QUECTEL:
+   case OFONO_VENDOR_QUECTEL_EC2X:
if (g_at_chat_send(sd->chat, "AT+QPINC?", qpinc_prefix,
at_qpinc_cb, cbd, g_free) > 0)
return;
diff --git a/drivers/atmodem/sms.c b/drivers/atmodem/sms.c
index d502da72..ed3b1370 100644
--- a/drivers/atmodem/sms.c
+++ b/drivers/atmodem/sms.c
@@ -337,6 +337,7 @@ static inline void at_ack_delivery(struct ofono_sms *sms)
if (data->cnma_ack_pdu) {
switch (data->vendor) {
case OFONO_VENDOR_GEMALTO:
+   case OFONO_VENDOR_QUECTEL_EC2X:
snprintf(buf, sizeof(buf), "AT+CNMA=1");
break;
case OFONO_VENDOR_QUECTEL_SERIAL:
@@ -845,6 +846,7 @@ static gboolean build_cnmi_string(char *buf, int *cnmi_opts,
case OFONO_VENDOR_ZTE:
case OFONO_VENDOR_SIMCOM:
case OFONO_VENDOR_QUECTEL:
+   case OFONO_VENDOR_QUECTEL_EC2X:
/* MSM devices advertise support for mode 2, but return an
 * error if we attempt to actually use it. */
mode = "1";
diff --git a/drivers/atmodem/vendor.h b/drivers/atmodem/vendor.h
index d839d1e0..6bac7f89 100644
--- a/drivers/atmodem/vendor.h
+++ b/drivers/atmodem/vendor.h
@@ -44,6 +44,7 @@ enum ofono_vendor {
OFONO_VENDOR_WAVECOM_Q2XXX,
OFONO_VENDOR_ALCATEL,
OFONO_VENDOR_QUECTEL,
+   OFONO_VENDOR_QUECTEL_EC2X,
OFONO_VENDOR_QUECTEL_SERIAL,
OFONO_VENDOR_UBLOX,
OFONO_VENDOR_XMM,
diff --git a/drivers/atmodem/voicecall.c b/drivers/atmodem/voicecall.c
index e7f24b60..4797227e 100644
--- a/drivers/atmodem/voicecall.c
+++ b/drivers/atmodem/voicecall.c
@@ -1114,7 +1114,8 @@ static int at_voicecall_probe(struct ofono_voicecall *vc, 
unsigned int vendor,
g_at_chat_send(vd->chat, "AT+CLIP=1", NULL, NULL, NULL, NULL);
g_at_chat_send(vd->chat, "AT+CDIP=1", NULL, NULL, NULL, NULL);
 
-   if (vd->vendor != OFONO_VENDOR_QUECTEL)
+   if ((vd->vendor != OFONO_VENDOR_QUECTEL) &&
+   (vd->vendor != OFONO_VENDOR_QUECTEL_EC2X))
g_at_chat_send(vd->chat, "AT+CNAP=1", NULL, NULL, NULL, NULL);
 
switch (vd->vendor) {
diff --git a/plugins/quectel.c b/plugins/quectel.c
index 871c7af2..feddb378 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -1060,7 +1060,7 @@ static void cgmm_cb(int ok, GAtResult *result, void 
*user_data)
data->model = QUECTEL_MC60;
} else if (strcmp(model, "EC21") == 0) {
DBG("%p model EC21", modem);
-   data->vendor = OFONO_VENDOR_QUECTEL;
+   data->vendor = OFONO_VENDOR_QUECTEL_EC2X;
data->model = QUECTEL_EC21;
/*
data->mux_order = mux_order_ec21;
-- 
2.27.0
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH 5/5] gprs: Quectel EC21 does not understand AT+CPSB

2020-08-04 Thread poeschel
From: Lars Poeschel 

The Quectel EC21 modem does not understand the AT+CPSB command, so
aquire the current packet switched bearer from CGREG URC.
---
 drivers/atmodem/gprs.c | 32 ++--
 1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/drivers/atmodem/gprs.c b/drivers/atmodem/gprs.c
index b637f733..5583d6fa 100644
--- a/drivers/atmodem/gprs.c
+++ b/drivers/atmodem/gprs.c
@@ -40,6 +40,7 @@
 #include "gatresult.h"
 
 #include "atmodem.h"
+#include "common.h"
 #include "vendor.h"
 
 #define MAX_CONTEXTS 255
@@ -98,6 +99,29 @@ static void list_contexts_data_unref(gpointer user_data)
g_free(ld);
 }
 
+static int act_to_bearer(int act)
+{
+   switch (act) {
+   case 0:
+   case 1:
+   return PACKET_BEARER_GPRS;
+   case 2:
+   return PACKET_BEARER_UMTS;
+   case 3:
+   return PACKET_BEARER_EGPRS;
+   case 4:
+   return PACKET_BEARER_HSDPA;
+   case 5:
+   return PACKET_BEARER_HSUPA;
+   case 6:
+   return PACKET_BEARER_HSUPA_HSDPA;
+   case 7:
+   return PACKET_BEARER_EPS;
+   default:
+   return PACKET_BEARER_NONE;
+   }
+};
+
 static void at_cgatt_cb(gboolean ok, GAtResult *result, gpointer user_data)
 {
struct cb_data *cbd = user_data;
@@ -342,11 +366,11 @@ static void at_gprs_list_active_contexts(struct 
ofono_gprs *gprs,
 static void cgreg_notify(GAtResult *result, gpointer user_data)
 {
struct ofono_gprs *gprs = user_data;
-   int status;
+   int status, tech;
struct gprs_data *gd = ofono_gprs_get_data(gprs);
 
if (at_util_parse_reg_unsolicited(result, "+CGREG:", ,
-   NULL, NULL, NULL, gd->vendor) == FALSE)
+   NULL, NULL, , gd->vendor) == FALSE)
return;
 
/*
@@ -372,6 +396,8 @@ static void cgreg_notify(GAtResult *result, gpointer 
user_data)
}
 
ofono_gprs_status_notify(gprs, status);
+   if (gd->vendor == OFONO_VENDOR_QUECTEL_EC2X)
+   ofono_gprs_bearer_notify(gprs, act_to_bearer(tech));
 }
 
 static void cgev_notify(GAtResult *result, gpointer user_data)
@@ -624,6 +650,8 @@ static void gprs_initialized(gboolean ok, GAtResult 
*result, gpointer user_data)
g_at_chat_send(gd->chat, "AT#PSNT=1", none_prefix,
NULL, NULL, NULL);
break;
+   case OFONO_VENDOR_QUECTEL_EC2X:
+   break;
default:
g_at_chat_register(gd->chat, "+CPSB:", cpsb_notify,
FALSE, gprs, NULL);
-- 
2.27.0
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH 2/5] quectel: Set URC port to uart1 on EC21

2020-08-04 Thread poeschel
From: Lars Poeschel 

Set the URC port of the Quectel EC21 to uart1 when it is used through
it's serial port. This setting is saved to non-volatile storage by the
modem automatically.
---
 plugins/quectel.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/plugins/quectel.c b/plugins/quectel.c
index feddb378..50d1b5d3 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -795,10 +795,12 @@ static void setup_aux(struct ofono_modem *modem)
 
g_at_chat_set_slave(data->modem, data->aux);
 
-   if (data->model == QUECTEL_EC21)
+   if (data->model == QUECTEL_EC21) {
g_at_chat_send(data->aux, "ATE0;  +CMEE=1", none_prefix,
NULL, NULL, NULL);
-   else
+   g_at_chat_send(data->aux, "AT+QURCCFG=\"urcport\",\"uart1\"", 
none_prefix,
+   NULL, NULL, NULL);
+   } else
g_at_chat_send(data->aux, "ATE0;  +CMEE=1; +QIURC=0",
none_prefix, NULL, NULL, NULL);
 
-- 
2.27.0
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH] Revert "quectel: EC21 needs aux channel to be the first mux channel"

2020-08-04 Thread poeschel
From: Lars Poeschel 

This reverts commit 1868dbf2b3e5929a7081b03a8ff76d214fd38624.
Development for this was done on EC21 firmware version
EC21EFAR06A01M4G_BETA0318. It now turns out, that actual release
firmware versions for this modem again need the original mux order with
aux channel as the second mux channel. (We know for sure for firmware
version EC21EFAR06A03M4G.)
We do not know for sure when and for what firmware versions quectel did
the switch back on the mux order, but we suspect that the "BETA"
firmware is the only one with the reversed mux order. This "BETA"
firmware was only given out for development purposes and will not appear
"in the wild", so we revert the patch here and hope for the best.
---
 plugins/quectel.c | 61 +++
 1 file changed, 14 insertions(+), 47 deletions(-)

diff --git a/plugins/quectel.c b/plugins/quectel.c
index cb15e147..043d39f9 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -78,27 +78,6 @@ static const uint8_t gsm0710_terminate[] = {
0xf9, /* close flag */
 };
 
-enum mux_type {
-   QUECTEL_MUX_TYPE_AUX = 0,
-   QUECTEL_MUX_TYPE_MODEM,
-   QUECTEL_MUX_TYPE_MAX,
-};
-
-struct mux_initialization_data {
-   enum mux_type mux_type;
-   char *chat_debug;
-   const char *n_gsm_key;
-   const char *n_gsm_value;
-};
-
-static const struct mux_initialization_data mux_order_default[] = {
-   { QUECTEL_MUX_TYPE_MODEM, "Modem: ", "Modem", "/dev/gsmtty1"},
-   { QUECTEL_MUX_TYPE_AUX, "Aux: ", "Aux", "/dev/gsmtty2"} };
-
-static const struct mux_initialization_data mux_order_ec21[] = {
-   { QUECTEL_MUX_TYPE_AUX, "Aux: ", "Aux", "/dev/gsmtty1"},
-   { QUECTEL_MUX_TYPE_MODEM, "Modem: ", "Modem", "/dev/gsmtty2"} };
-
 enum quectel_model {
QUECTEL_UNKNOWN,
QUECTEL_UC15,
@@ -127,7 +106,6 @@ struct quectel_data {
struct l_timeout *init_timeout;
size_t init_count;
guint init_cmd;
-   const struct mux_initialization_data *mux_order;
 };
 
 struct dbus_hw {
@@ -860,7 +838,6 @@ static GAtChat *create_chat(struct ofono_modem *modem, char 
*debug)
 static void cmux_gatmux(struct ofono_modem *modem)
 {
struct quectel_data *data = ofono_modem_get_data(modem);
-   GAtChat *chat;
 
DBG("%p", modem);
 
@@ -876,21 +853,18 @@ static void cmux_gatmux(struct ofono_modem *modem)
 
g_at_mux_start(data->mux);
 
-   for (int i = 0; i < QUECTEL_MUX_TYPE_MAX; i++) {
-   chat = create_chat(modem, data->mux_order[i].chat_debug);
-
-   if (!chat) {
-   ofono_error("failed to create %schannel",
-   data->mux_order[i].chat_debug);
-   close_serial(modem);
-   return;
-   }
-
-   if (data->mux_order[i].mux_type == QUECTEL_MUX_TYPE_AUX)
-   data->aux = chat;
-   else
-   data->modem = chat;
+   data->modem = create_chat(modem, "Modem: ");
+   if (!data->modem) {
+   ofono_error("failed to create modem channel");
+   close_serial(modem);
+   return;
+   }
 
+   data->aux = create_chat(modem, "Aux: ");
+   if (!data->aux) {
+   ofono_error("failed to create aux channel");
+   close_serial(modem);
+   return;
}
 
setup_aux(modem);
@@ -906,9 +880,7 @@ static void mux_ready_cb(struct l_timeout *timeout, void 
*user_data)
DBG("%p", modem);
 
/* check if the last (and thus all) virtual gsm tty's are created */
-   ret = stat(ofono_modem_get_string(modem,
-   data->mux_order[QUECTEL_MUX_TYPE_MAX - 1].n_gsm_key),
-   );
+   ret = stat(ofono_modem_get_string(modem, "Modem"), );
if (ret < 0) {
if (data->mux_ready_count++ < 5) {
/* not ready yet; try again in 100 ms*/
@@ -985,10 +957,8 @@ static void cmux_ngsm(struct ofono_modem *modem)
 * the kernel does not yet support mapping the underlying serial device
 * to its virtual gsm ttys, so hard-code gsmtty1 gsmtty2 for now
 */
-   for (int i = 0; i < QUECTEL_MUX_TYPE_MAX; i++) {
-   ofono_modem_set_string(modem, data->mux_order[i].n_gsm_key,
-   data->mux_order[i].n_gsm_value);
-   }
+   ofono_modem_set_string(modem, "Modem", "/dev/gsmtty1");
+   ofono_modem_set_string(modem, "Aux", "/dev/gsmtty2");
 
/* wait for gsmtty devices to appear *

Re: [PATCH v3] quectel: EC21 needs aux channel to be the first mux channel

2020-07-24 Thread Lars Poeschel
On Tue, May 26, 2020 at 10:22:46PM -0500, Denis Kenzior wrote:
> Hi Lars,
> 
> On 5/29/20 7:43 AM, poesc...@lemonage.de wrote:
> > From: Lars Poeschel 
> > 
> > The Quectel EC21 does only work correctly, if the mux channel used for
> > aux is the first mux channel. It does only put it's URC messages in the
> > first mux channel, so this has to be the aux channel in our case.
> > To be flexible on the mux order we introduce two arrays here, that then
> > contain the initialization data in their needed order.
> > Initialization data is then applied by for-looping over this array.
> > ---
> >   plugins/quectel.c | 61 ---
> >   1 file changed, 47 insertions(+), 14 deletions(-)
> > 
> 
> Applied, thanks.

Unfortunately I must come back to this issue.
I got hands on a few new EC21s here and guess what ?
The mux order is back to the original one again. This means, the aux
channel has to be the second channel.
So I did a bit of investigation why and when this happened. But
information is rare.
The modems I originally worked on and created the patch for have
Firmware EC21EFAR06A01M4G_BETA0318. (Reversed mux order)
The new ones do have version EC21EFAR06A03M4G. (original mux order)
I know that there was a version EC21EFAR02A02M4G that did not support
cmux at all.
Due to some Quectel Confidential Document in a firmware version
"R02A03" some bug was fixed in cmux, so cmux must be in there since
then.
The EC21EFAR06A01M4G_BETA0318 that I have is dated inbetween
EC21EFAR02A02M4G and this "R02A03".
The mux order must have changed between EC21EFAR06A01M4G_BETA0318 and
EC21EFAR06A03M4G.
I suspect (without knowing for sure) due to the beta-nature of my
firmware, that this is the only firmware with reversed mux order and
that they changed it after that and "R02A03" up until
EC21EFAR06A03M4G share the same original mux order. According to Quectel
the EC21EFAR06A01M4G_BETA0318 firmware I have here is not "out in the
wild". The modems I have here are the only ones with this firmware.

So my question is what's best to do now ?

I feel the best would be to revert this patch. I am very sorry for this.
New modems will work and I suspect old modems "out in the wild" will
work also. I don't care about supporting the few "BETA0318" modems I
have here.

Another way would be to leave this patch and implement some firmware
switch and use reversed mux order for the "BETA0318" only I have and use
normal original mux order for all other cases.

What do you think?

Thank you,
Lars
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH v3] quectel: EC21 needs aux channel to be the first mux channel

2020-05-29 Thread poeschel
From: Lars Poeschel 

The Quectel EC21 does only work correctly, if the mux channel used for
aux is the first mux channel. It does only put it's URC messages in the
first mux channel, so this has to be the aux channel in our case.
To be flexible on the mux order we introduce two arrays here, that then
contain the initialization data in their needed order.
Initialization data is then applied by for-looping over this array.
---
 plugins/quectel.c | 61 ---
 1 file changed, 47 insertions(+), 14 deletions(-)

diff --git a/plugins/quectel.c b/plugins/quectel.c
index 043d39f9..cb15e147 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -78,6 +78,27 @@ static const uint8_t gsm0710_terminate[] = {
0xf9, /* close flag */
 };
 
+enum mux_type {
+   QUECTEL_MUX_TYPE_AUX = 0,
+   QUECTEL_MUX_TYPE_MODEM,
+   QUECTEL_MUX_TYPE_MAX,
+};
+
+struct mux_initialization_data {
+   enum mux_type mux_type;
+   char *chat_debug;
+   const char *n_gsm_key;
+   const char *n_gsm_value;
+};
+
+static const struct mux_initialization_data mux_order_default[] = {
+   { QUECTEL_MUX_TYPE_MODEM, "Modem: ", "Modem", "/dev/gsmtty1"},
+   { QUECTEL_MUX_TYPE_AUX, "Aux: ", "Aux", "/dev/gsmtty2"} };
+
+static const struct mux_initialization_data mux_order_ec21[] = {
+   { QUECTEL_MUX_TYPE_AUX, "Aux: ", "Aux", "/dev/gsmtty1"},
+   { QUECTEL_MUX_TYPE_MODEM, "Modem: ", "Modem", "/dev/gsmtty2"} };
+
 enum quectel_model {
QUECTEL_UNKNOWN,
QUECTEL_UC15,
@@ -106,6 +127,7 @@ struct quectel_data {
struct l_timeout *init_timeout;
size_t init_count;
guint init_cmd;
+   const struct mux_initialization_data *mux_order;
 };
 
 struct dbus_hw {
@@ -838,6 +860,7 @@ static GAtChat *create_chat(struct ofono_modem *modem, char 
*debug)
 static void cmux_gatmux(struct ofono_modem *modem)
 {
struct quectel_data *data = ofono_modem_get_data(modem);
+   GAtChat *chat;
 
DBG("%p", modem);
 
@@ -853,18 +876,21 @@ static void cmux_gatmux(struct ofono_modem *modem)
 
g_at_mux_start(data->mux);
 
-   data->modem = create_chat(modem, "Modem: ");
-   if (!data->modem) {
-   ofono_error("failed to create modem channel");
-   close_serial(modem);
-   return;
-   }
+   for (int i = 0; i < QUECTEL_MUX_TYPE_MAX; i++) {
+   chat = create_chat(modem, data->mux_order[i].chat_debug);
+
+   if (!chat) {
+   ofono_error("failed to create %schannel",
+   data->mux_order[i].chat_debug);
+   close_serial(modem);
+   return;
+   }
+
+   if (data->mux_order[i].mux_type == QUECTEL_MUX_TYPE_AUX)
+   data->aux = chat;
+   else
+   data->modem = chat;
 
-   data->aux = create_chat(modem, "Aux: ");
-   if (!data->aux) {
-   ofono_error("failed to create aux channel");
-   close_serial(modem);
-   return;
}
 
setup_aux(modem);
@@ -880,7 +906,9 @@ static void mux_ready_cb(struct l_timeout *timeout, void 
*user_data)
DBG("%p", modem);
 
/* check if the last (and thus all) virtual gsm tty's are created */
-   ret = stat(ofono_modem_get_string(modem, "Modem"), );
+   ret = stat(ofono_modem_get_string(modem,
+   data->mux_order[QUECTEL_MUX_TYPE_MAX - 1].n_gsm_key),
+   );
if (ret < 0) {
if (data->mux_ready_count++ < 5) {
/* not ready yet; try again in 100 ms*/
@@ -957,8 +985,10 @@ static void cmux_ngsm(struct ofono_modem *modem)
 * the kernel does not yet support mapping the underlying serial device
 * to its virtual gsm ttys, so hard-code gsmtty1 gsmtty2 for now
 */
-   ofono_modem_set_string(modem, "Modem", "/dev/gsmtty1");
-   ofono_modem_set_string(modem, "Aux", "/dev/gsmtty2");
+   for (int i = 0; i < QUECTEL_MUX_TYPE_MAX; i++) {
+   ofono_modem_set_string(modem, data->mux_order[i].n_gsm_key,
+   data->mux_order[i].n_gsm_value);
+   }
 
/* wait for gsmtty devices to appear */
if (!l_timeout_create_ms(100, mux_ready_cb, modem, NULL)) {
@@ -1014,6 +1044,8 @@ static void cgmm_cb(int ok, GAtResult *result, void 
*user_data)
return;
}
 
+   data->mux_order = mux_order_default;
+
if (strcmp(model, "UC15") == 0) {
DB

Re: [PATCH] Adds optional phone number parameter to ofono-phonesim

2020-05-28 Thread Lars Poeschel
Hi Bettina-Jennifer,

whatever way you chose to send your patches, this is totally messed up.
It would be very hard to extract usable information from this email. It
looks like you wanted to send two patches, but it is just one email.
Your email does include text and html parts, which is also not good.
If you want someone to:
* look at your patches
* try them out
* comment on them
* or even include them in the ofono repository
you have to follow the steps documented in the HACKING file of ofono.
Especially the "Submitting patches" section.
Really please use git send-email to send your patches or at least send
them in a format that is acceptable by git am.

Regards,
Lars

On Wed, May 27, 2020 at 09:51:37AM +, Bettina Jennifer Riedl wrote:
> Hello,
> 
> this patch adds an optional phone number parameter to ofono-phonesim, instead 
> of using the default number.
> 
> Greetings
> Bettina
> 
> Michael Klemm:
> Added phone number as additional parameter (1/2)
> AUTHORS: Mention Michael's contributions  (2/2)
> 
> (1/2)
> diff --git a/src/main.cpp b/src/main.cpp
> index 712e767..a20bc1a 100644
> --- a/src/main.cpp
> +++ b/src/main.cpp
> @@ -28,13 +28,14 @@ static void usage()
> {
>  qWarning() << "Usage:"
> << 
> QFileInfo(QCoreApplication::instance()->applicationFilePath()).fileName().toLocal8Bit().constData()
> -   << "[-v] [-p port] [-gui] filename";
> +   << "[-v] [-p port] [-gui] [-n number] filename";
>  exit(-1);
> }
>  int main(int argc, char **argv)
> {
>  QString filename = nullptr;
> +QString number = "+491701234567";
>  QCoreApplication *app;
>  int port = 12345;
>  int index;
> @@ -61,6 +62,15 @@ int main(int argc, char **argv)
>  } else if ( strcmp(argv[index],"-h") == 0
>  || strcmp(argv[index],"-help") == 0 ) {
>  usage();
> +} else if ( strcmp(argv[index],"-n") == 0
> +|| strcmp(argv[index],"-num") == 0 ) {
> +index++;
> +if (index >= argc) {
> +qWarning() << "ERROR: Got -n but missing phone number";
> +usage();
> +} else {
> +number = argv[index];
> +}
>  } else {
>  // must be filename.  SHOULD be last argument.
>  if (index != argc-1) {
> @@ -85,7 +95,7 @@ int main(int argc, char **argv)
>  } else
>  app = new QCoreApplication(argc, argv);
> -PhoneSimServer *pss = new PhoneSimServer(filename, port, nullptr);
> +PhoneSimServer *pss = new PhoneSimServer(filename, port, number, 
> nullptr);
> 
> diff --git a/src/server.cpp b/src/server.cpp
> index 3ff7def..856a90f 100644
> --- a/src/server.cpp
> +++ b/src/server.cpp
> @@ -22,13 +22,12 @@
> #include "hardwaremanipulator.h"
> #include 
> -static int phonenumber = 555000;
> -
> -PhoneSimServer::PhoneSimServer(const QString , quint16 port, QObject 
> *parent)
> +PhoneSimServer::PhoneSimServer(const QString , quint16 port, const QString 
> , QObject *parent)
>  : QTcpServer(parent), fact(nullptr), currentRules(nullptr)
> {
>  listen( QHostAddress::Any, port );
>  filename = f;
> +number = n;
> }
>  PhoneSimServer::~PhoneSimServer()
> @@ -47,7 +46,6 @@ void 
> PhoneSimServer::setHardwareManipulator(HardwareManipulatorFactory *f)
> void PhoneSimServer::incomingConnection(qintptr s)
> {
>SimRules *sr = new SimRules(s, this, filename, fact);
> -sr->setPhoneNumber(QString::number(phonenumber));
> -phonenumber++;
> +sr->setPhoneNumber(number);
>  currentRules = sr;
> }
> 
> diff --git a/src/server.h b/src/server.h
> index 9175359..6790be4 100644
> --- a/src/server.h
> +++ b/src/server.h
> @@ -32,7 +32,7 @@ class HardwareManipulatorFactory;
> class PhoneSimServer : public QTcpServer
> {
> public:
> -PhoneSimServer(const QString &, quint16 port, QObject *parent = nullptr);
> +PhoneSimServer(const QString &, quint16 port, const QString &, QObject 
> *parent = nullptr);
>  ~PhoneSimServer() override;
>  void setHardwareManipulator(HardwareManipulatorFactory *f);
> @@ -44,6 +44,7 @@ protected:
>  private:
>  QString filename;
> +QString number;
> 
> 
> 
> (2/2)
> diff --git a/AUTHORS b/AUTHORS
> index 9b8a840..d8e107f 100644
> --- a/AUTHORS
> +++ b/AUTHORS
> @@ -15,3 +15,4 @@ Jussi Pakkanen 
> James Prestwood 
> Simon Busch 
> Jonah Brüchert 
> +Michael Klemm 
> _
> 
> Expleo Germany GmbH
> Sitz der Gesellschaft | Corporate Headquarters: München
> Handelsregister | Commercial Register: Amtsgericht München HRB 83252
> Geschäftsführung | Management: Ralph Gillessen, Josef Mitterhuber
> 
> This message contains information that may be privileged or confidential. It 
> is intended only for the person to whom it is addressed.
> If you are not the intended recipient, you are not authorized to read, print, 
> retain, copy, disseminate, distribute, 

Re: Quectel BG95 Support

2020-05-28 Thread Lars Poeschel
Hello!

On Thu, May 14, 2020 at 02:27:22PM -, arash.javanm...@inro-et.de wrote:
> Hello,
> unfortunately there is no support for Quectel BG95 in ofono.  But 
> nevertheless i tried to adapt the existing Quectel implementation for BG95.
> So i added:
> 
> udevng.c
> --- 8< -
>   { "quectelqmi", "qmi_wwan", "2c7c", "0700"  },
>   { "quectelqmi", "qcserial", "2c7c", "0700"  },
>   { "quectel","option",   "2c7c", "0700"  },
> --- >8 -

I do not know for sure, but I think this is wrong. Either your modem is
serial and using the quectel driver or it is a qmi modem with quectelqmi
as driver, but not both.
Well, maybe your modem supports both, but you can only use one at a
time.

Regards,
Lars
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH v2] quectel: EC21 needs aux channel to be the first mux channel

2020-05-28 Thread poeschel
From: Lars Poeschel 

The Quectel EC21 does only work correctly, if the mux channel used for
aux is the first mux channel. It does only put it's URC messages in the
first mux channel, so this has to be the aux channel in our case.
To be flexible on the mux order we introduce an array here, that
contains the initialization data in it's needed order and is then simply
applied by a for-loop. Initialization of this array is done after we
queried the modem model.
---
 plugins/quectel.c | 72 ++-
 1 file changed, 58 insertions(+), 14 deletions(-)

diff --git a/plugins/quectel.c b/plugins/quectel.c
index 043d39f9..1cad35d6 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -78,6 +78,21 @@ static const uint8_t gsm0710_terminate[] = {
0xf9, /* close flag */
 };
 
+enum mux_type {
+   QUECTEL_MUX_TYPE_AUX = 0,
+   QUECTEL_MUX_TYPE_MODEM,
+   QUECTEL_MUX_TYPE_MAX,
+};
+
+struct mux_initialization_data {
+   enum mux_type mux_type;
+   char *chat_debug;
+   const char *n_gsm_key;
+   const char *n_gsm_value;
+};
+
+static struct mux_initialization_data mux_order[QUECTEL_MUX_TYPE_MAX];
+
 enum quectel_model {
QUECTEL_UNKNOWN,
QUECTEL_UC15,
@@ -838,6 +853,7 @@ static GAtChat *create_chat(struct ofono_modem *modem, char 
*debug)
 static void cmux_gatmux(struct ofono_modem *modem)
 {
struct quectel_data *data = ofono_modem_get_data(modem);
+   GAtChat *chat;
 
DBG("%p", modem);
 
@@ -853,18 +869,21 @@ static void cmux_gatmux(struct ofono_modem *modem)
 
g_at_mux_start(data->mux);
 
-   data->modem = create_chat(modem, "Modem: ");
-   if (!data->modem) {
-   ofono_error("failed to create modem channel");
-   close_serial(modem);
-   return;
-   }
+   for (int i = 0; i < QUECTEL_MUX_TYPE_MAX; i++) {
+   chat = create_chat(modem, mux_order[i].chat_debug);
+
+   if (!chat) {
+   ofono_error("failed to create %schannel",
+   mux_order[i].chat_debug);
+   close_serial(modem);
+   return;
+   }
+
+   if (mux_order[i].mux_type == QUECTEL_MUX_TYPE_AUX)
+   data->aux = chat;
+   else
+   data->modem = chat;
 
-   data->aux = create_chat(modem, "Aux: ");
-   if (!data->aux) {
-   ofono_error("failed to create aux channel");
-   close_serial(modem);
-   return;
}
 
setup_aux(modem);
@@ -880,7 +899,9 @@ static void mux_ready_cb(struct l_timeout *timeout, void 
*user_data)
DBG("%p", modem);
 
/* check if the last (and thus all) virtual gsm tty's are created */
-   ret = stat(ofono_modem_get_string(modem, "Modem"), );
+   ret = stat(ofono_modem_get_string(modem,
+   mux_order[QUECTEL_MUX_TYPE_MAX - 1].n_gsm_key),
+   );
if (ret < 0) {
if (data->mux_ready_count++ < 5) {
/* not ready yet; try again in 100 ms*/
@@ -957,8 +978,10 @@ static void cmux_ngsm(struct ofono_modem *modem)
 * the kernel does not yet support mapping the underlying serial device
 * to its virtual gsm ttys, so hard-code gsmtty1 gsmtty2 for now
 */
-   ofono_modem_set_string(modem, "Modem", "/dev/gsmtty1");
-   ofono_modem_set_string(modem, "Aux", "/dev/gsmtty2");
+   for (int i = 0; i < QUECTEL_MUX_TYPE_MAX; i++) {
+   ofono_modem_set_string(modem, mux_order[i].n_gsm_key,
+   mux_order[i].n_gsm_value);
+   }
 
/* wait for gsmtty devices to appear */
if (!l_timeout_create_ms(100, mux_ready_cb, modem, NULL)) {
@@ -1014,6 +1037,17 @@ static void cgmm_cb(int ok, GAtResult *result, void 
*user_data)
return;
}
 
+   mux_order[0] = (struct mux_initialization_data)
+   { QUECTEL_MUX_TYPE_MODEM,
+   "Modem: ",
+   "Modem",
+   "/dev/gsmtty1"};
+   mux_order[1] = (struct mux_initialization_data)
+   { QUECTEL_MUX_TYPE_AUX,
+   "Aux: ",
+   "Aux",
+   "/dev/gsmtty2"};
+
if (strcmp(model, "UC15") == 0) {
DBG("%p model UC15", modem);
data->vendor = OFONO_VENDOR_QUECTEL;
@@ -1030,6 +1064,16 @@ static void cgmm_cb(int ok, GAtResult *result, void 
*user_data)
DBG("%p model EC21", modem);
data->vendor = OFONO_VENDO

Re: [PATCH 4/7] quectel: EC21 needs aux channel to be the first mux channel

2020-05-27 Thread Lars Poeschel
On Thu, May 21, 2020 at 08:32:07AM -0500, Denis Kenzior wrote:
> Hi Lars,
> 
> On 5/26/20 5:16 AM, poesc...@lemonage.de wrote:
> > From: Lars Poeschel 
> > 
> > The Quectel EC21 does only work correctly, if the mux channel used for
> > aux is the first mux channel. It does only put it's URC messages in the
> > first mux channel, so this has to be the aux channel in our case.
> > ---
> >   plugins/quectel.c | 51 +++
> >   1 file changed, 38 insertions(+), 13 deletions(-)
> > 
> > diff --git a/plugins/quectel.c b/plugins/quectel.c
> > index 1d312c45..9ff75516 100644
> > --- a/plugins/quectel.c
> > +++ b/plugins/quectel.c
> > @@ -847,18 +847,38 @@ static void cmux_gatmux(struct ofono_modem *modem)
> > g_at_mux_start(data->mux);
> > -   data->modem = create_chat(modem, "Modem: ");
> > -   if (!data->modem) {
> > -   ofono_error("failed to create modem channel");
> > -   close_serial(modem);
> > -   return;
> > -   }
> > +   if (data->model == QUECTEL_EC21) {
> > +   data->aux = create_chat(modem, "Aux: ");
> > -   data->aux = create_chat(modem, "Aux: ");
> > -   if (!data->aux) {
> > -   ofono_error("failed to create aux channel");
> > -   close_serial(modem);
> > -   return;
> > +   if (!data->aux) {
> > +   ofono_error("failed to create aux channel");
> > +   close_serial(modem);
> > +   return;
> > +   }
> > +
> > +   data->modem = create_chat(modem, "Modem: ");
> > +
> > +   if (!data->modem) {
> > +   ofono_error("failed to create modem channel");
> > +   close_serial(modem);
> > +   return;
> > +   }
> > +   } else {
> > +   data->modem = create_chat(modem, "Modem: ");
> > +
> > +   if (!data->modem) {
> > +   ofono_error("failed to create modem channel");
> > +   close_serial(modem);
> > +   return;
> > +   }
> > +
> > +   data->aux = create_chat(modem, "Aux: ");
> > +
> > +   if (!data->aux) {
> > +   ofono_error("failed to create aux channel");
> > +   close_serial(modem);
> > +   return;
> > +   }
> > }
> 
> Can we be smarter about this and just store the per-model creation sequence
> as an array or something?  Then have a loop that calls create_chat from the
> array info?  The proposed copy-pasting approach is not maintainable long
> term.

I will post a follow-up with a proposed solution tomorrow.

> > setup_aux(modem);
> > @@ -951,8 +971,13 @@ static void cmux_ngsm(struct ofono_modem *modem)
> >  * the kernel does not yet support mapping the underlying serial device
> >  * to its virtual gsm ttys, so hard-code gsmtty1 gsmtty2 for now
> >  */
> > -   ofono_modem_set_string(modem, "Modem", "/dev/gsmtty1");
> > -   ofono_modem_set_string(modem, "Aux", "/dev/gsmtty2");
> > +   if (data->model == QUECTEL_EC21) {
> > +   ofono_modem_set_string(modem, "Modem", "/dev/gsmtty2");
> > +   ofono_modem_set_string(modem, "Aux", "/dev/gsmtty1");
> > +   } else {
> > +   ofono_modem_set_string(modem, "Modem", "/dev/gsmtty1");
> > +   ofono_modem_set_string(modem, "Aux", "/dev/gsmtty2");
> > +   }
> 
> Doesn't this break the logic in mux_ready_cb, particularly the 'check if the
> last virtual gsm tty's are created'

Well, I guess, yes. I missed indeed missed that. The follow-up will
contain a fix for this as well.

> > /* wait for gsmtty devices to appear */
> > if (!l_timeout_create_ms(100, mux_ready_cb, modem, NULL)) {
> > 
> 
> Regards,
> -Denis

Thank you for reviewing and applying the other patches! :-)

Lars
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH 5/7] quectel: EC21 does not understand AT+QIURC

2020-05-26 Thread poeschel
From: Lars Poeschel 

Because the Quectel EC21 does not understand the AT+QIURC command, we
leave that out during initialisation.
---
 plugins/quectel.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/plugins/quectel.c b/plugins/quectel.c
index 9ff75516..574de44e 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -772,8 +772,14 @@ static void setup_aux(struct ofono_modem *modem)
DBG("%p", modem);
 
g_at_chat_set_slave(data->modem, data->aux);
-   g_at_chat_send(data->aux, "ATE0;  +CMEE=1; +QIURC=0", none_prefix,
-   NULL, NULL, NULL);
+
+   if (data->model == QUECTEL_EC21)
+   g_at_chat_send(data->aux, "ATE0;  +CMEE=1", none_prefix,
+   NULL, NULL, NULL);
+   else
+   g_at_chat_send(data->aux, "ATE0;  +CMEE=1; +QIURC=0",
+   none_prefix, NULL, NULL, NULL);
+
g_at_chat_send(data->aux, "AT+CFUN?", cfun_prefix, cfun_query, modem,
NULL);
 }
-- 
2.26.2
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH 6/7] voicecall: Quectel modem do not understand AT+CNAP

2020-05-26 Thread poeschel
From: Lars Poeschel 

---
 drivers/atmodem/voicecall.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/atmodem/voicecall.c b/drivers/atmodem/voicecall.c
index 7ab6567f..e7f24b60 100644
--- a/drivers/atmodem/voicecall.c
+++ b/drivers/atmodem/voicecall.c
@@ -1113,7 +1113,9 @@ static int at_voicecall_probe(struct ofono_voicecall *vc, 
unsigned int vendor,
g_at_chat_send(vd->chat, "AT+CRC=1", NULL, NULL, NULL, NULL);
g_at_chat_send(vd->chat, "AT+CLIP=1", NULL, NULL, NULL, NULL);
g_at_chat_send(vd->chat, "AT+CDIP=1", NULL, NULL, NULL, NULL);
-   g_at_chat_send(vd->chat, "AT+CNAP=1", NULL, NULL, NULL, NULL);
+
+   if (vd->vendor != OFONO_VENDOR_QUECTEL)
+   g_at_chat_send(vd->chat, "AT+CNAP=1", NULL, NULL, NULL, NULL);
 
switch (vd->vendor) {
case OFONO_VENDOR_QUALCOMM_MSM:
-- 
2.26.2
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH 7/7] quectel: EC21 add ussd with atmodem driver

2020-05-26 Thread poeschel
From: Lars Poeschel 

---
 plugins/quectel.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/plugins/quectel.c b/plugins/quectel.c
index 574de44e..a8fbc75a 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -1295,8 +1295,10 @@ static void quectel_post_sim(struct ofono_modem *modem)
ofono_phonebook_create(modem, data->vendor, "atmodem", data->aux);
ofono_call_volume_create(modem, data->vendor, "atmodem", data->aux);
 
-   if (data->model == QUECTEL_EC21)
+   if (data->model == QUECTEL_EC21) {
+   ofono_ussd_create(modem, data->vendor, "atmodem", data->aux);
ofono_lte_create(modem, data->vendor, "atmodem", data->aux);
+   }
 }
 
 static void quectel_post_online(struct ofono_modem *modem)
-- 
2.26.2
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH 4/7] quectel: EC21 needs aux channel to be the first mux channel

2020-05-26 Thread poeschel
From: Lars Poeschel 

The Quectel EC21 does only work correctly, if the mux channel used for
aux is the first mux channel. It does only put it's URC messages in the
first mux channel, so this has to be the aux channel in our case.
---
 plugins/quectel.c | 51 +++
 1 file changed, 38 insertions(+), 13 deletions(-)

diff --git a/plugins/quectel.c b/plugins/quectel.c
index 1d312c45..9ff75516 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -847,18 +847,38 @@ static void cmux_gatmux(struct ofono_modem *modem)
 
g_at_mux_start(data->mux);
 
-   data->modem = create_chat(modem, "Modem: ");
-   if (!data->modem) {
-   ofono_error("failed to create modem channel");
-   close_serial(modem);
-   return;
-   }
+   if (data->model == QUECTEL_EC21) {
+   data->aux = create_chat(modem, "Aux: ");
 
-   data->aux = create_chat(modem, "Aux: ");
-   if (!data->aux) {
-   ofono_error("failed to create aux channel");
-   close_serial(modem);
-   return;
+   if (!data->aux) {
+   ofono_error("failed to create aux channel");
+   close_serial(modem);
+   return;
+   }
+
+   data->modem = create_chat(modem, "Modem: ");
+
+   if (!data->modem) {
+   ofono_error("failed to create modem channel");
+   close_serial(modem);
+   return;
+   }
+   } else {
+   data->modem = create_chat(modem, "Modem: ");
+
+   if (!data->modem) {
+   ofono_error("failed to create modem channel");
+   close_serial(modem);
+   return;
+   }
+
+   data->aux = create_chat(modem, "Aux: ");
+
+   if (!data->aux) {
+   ofono_error("failed to create aux channel");
+   close_serial(modem);
+   return;
+   }
}
 
setup_aux(modem);
@@ -951,8 +971,13 @@ static void cmux_ngsm(struct ofono_modem *modem)
 * the kernel does not yet support mapping the underlying serial device
 * to its virtual gsm ttys, so hard-code gsmtty1 gsmtty2 for now
 */
-   ofono_modem_set_string(modem, "Modem", "/dev/gsmtty1");
-   ofono_modem_set_string(modem, "Aux", "/dev/gsmtty2");
+   if (data->model == QUECTEL_EC21) {
+   ofono_modem_set_string(modem, "Modem", "/dev/gsmtty2");
+   ofono_modem_set_string(modem, "Aux", "/dev/gsmtty1");
+   } else {
+   ofono_modem_set_string(modem, "Modem", "/dev/gsmtty1");
+   ofono_modem_set_string(modem, "Aux", "/dev/gsmtty2");
+   }
 
/* wait for gsmtty devices to appear */
if (!l_timeout_create_ms(100, mux_ready_cb, modem, NULL)) {
-- 
2.26.2
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH 0/7] Add quectel EC21 in serial mode

2020-05-26 Thread poeschel
From: Lars Poeschel 

This patchset adds support for the quectel EC21 LTE modem connected
through its serial port.

Lars Poeschel (7):
  quectel: Add Quectel EC21 to known serial modems
  quectel: use lte atom on EC21
  quectel: Query the model before setting up the mux
  quectel: EC21 needs aux channel to be the first mux channel
  quectel: EC21 does not understand AT+QIURC
  voicecall: Quectel modem do not understand AT+CNAP
  quectel: EC21 add ussd with atmodem driver

 drivers/atmodem/voicecall.c |   4 +-
 plugins/quectel.c   | 153 +++-
 2 files changed, 101 insertions(+), 56 deletions(-)

-- 
2.26.2
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH 3/7] quectel: Query the model before setting up the mux

2020-05-26 Thread poeschel
From: Lars Poeschel 

This is a change for the EC21. It will require specific handling before
and right after setting up the mux. So this change prepares this. It
queries the modem model before the mux (CMUX) is activated.
---
 plugins/quectel.c | 86 +++
 1 file changed, 43 insertions(+), 43 deletions(-)

diff --git a/plugins/quectel.c b/plugins/quectel.c
index 0f6896b1..1d312c45 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -765,46 +765,6 @@ static void cfun_query(gboolean ok, GAtResult *result, 
gpointer user_data)
cfun_enable(TRUE, NULL, modem);
 }
 
-static void cgmm_cb(int ok, GAtResult *result, void *user_data)
-{
-   struct ofono_modem *modem = user_data;
-   struct quectel_data *data = ofono_modem_get_data(modem);
-   const char *model;
-
-   DBG("%p ok %d", modem, ok);
-
-   if (!at_util_parse_attr(result, "", )) {
-   ofono_error("Failed to query modem model");
-   close_serial(modem);
-   return;
-   }
-
-   if (strcmp(model, "UC15") == 0) {
-   DBG("%p model UC15", modem);
-   data->vendor = OFONO_VENDOR_QUECTEL;
-   data->model = QUECTEL_UC15;
-   } else if (strcmp(model, "Quectel_M95") == 0) {
-   DBG("%p model M95", modem);
-   data->vendor = OFONO_VENDOR_QUECTEL_SERIAL;
-   data->model = QUECTEL_M95;
-   } else if (strcmp(model, "Quectel_MC60") == 0) {
-   DBG("%p model MC60", modem);
-   data->vendor = OFONO_VENDOR_QUECTEL_SERIAL;
-   data->model = QUECTEL_MC60;
-   } else if (strcmp(model, "EC21") == 0) {
-   DBG("%p model EC21", modem);
-   data->vendor = OFONO_VENDOR_QUECTEL;
-   data->model = QUECTEL_EC21;
-   } else {
-   ofono_warn("%p unknown model: '%s'", modem, model);
-   data->vendor = OFONO_VENDOR_QUECTEL;
-   data->model = QUECTEL_UNKNOWN;
-   }
-
-   g_at_chat_send(data->aux, "AT+CFUN?", cfun_prefix, cfun_query, modem,
-   NULL);
-}
-
 static void setup_aux(struct ofono_modem *modem)
 {
struct quectel_data *data = ofono_modem_get_data(modem);
@@ -814,7 +774,7 @@ static void setup_aux(struct ofono_modem *modem)
g_at_chat_set_slave(data->modem, data->aux);
g_at_chat_send(data->aux, "ATE0;  +CMEE=1; +QIURC=0", none_prefix,
NULL, NULL, NULL);
-   g_at_chat_send(data->aux, "AT+CGMM", cgmm_prefix, cgmm_cb, modem,
+   g_at_chat_send(data->aux, "AT+CFUN?", cfun_prefix, cfun_query, modem,
NULL);
 }
 
@@ -1034,17 +994,57 @@ static void cmux_cb(gboolean ok, GAtResult *result, 
gpointer user_data)
close_serial(modem);
 }
 
-static void ate_cb(int ok, GAtResult *result, void *user_data)
+static void cgmm_cb(int ok, GAtResult *result, void *user_data)
 {
struct ofono_modem *modem = user_data;
struct quectel_data *data = ofono_modem_get_data(modem);
+   const char *model;
 
-   DBG("%p", modem);
+   DBG("%p ok %d", modem, ok);
+
+   if (!at_util_parse_attr(result, "", )) {
+   ofono_error("Failed to query modem model");
+   close_serial(modem);
+   return;
+   }
+
+   if (strcmp(model, "UC15") == 0) {
+   DBG("%p model UC15", modem);
+   data->vendor = OFONO_VENDOR_QUECTEL;
+   data->model = QUECTEL_UC15;
+   } else if (strcmp(model, "Quectel_M95") == 0) {
+   DBG("%p model M95", modem);
+   data->vendor = OFONO_VENDOR_QUECTEL_SERIAL;
+   data->model = QUECTEL_M95;
+   } else if (strcmp(model, "Quectel_MC60") == 0) {
+   DBG("%p model MC60", modem);
+   data->vendor = OFONO_VENDOR_QUECTEL_SERIAL;
+   data->model = QUECTEL_MC60;
+   } else if (strcmp(model, "EC21") == 0) {
+   DBG("%p model EC21", modem);
+   data->vendor = OFONO_VENDOR_QUECTEL;
+   data->model = QUECTEL_EC21;
+   } else {
+   ofono_warn("%p unknown model: '%s'", modem, model);
+   data->vendor = OFONO_VENDOR_QUECTEL;
+   data->model = QUECTEL_UNKNOWN;
+   }
 
g_at_chat_send(data->uart, "AT+CMUX=0,0,5,127,10,3,30,10,2", NULL,
cmux_cb, modem, NULL);
 }
 
+static void ate_cb(int ok, GAtResult *result, void *user_data)
+{
+   struct ofono_modem *modem = user_data;
+   struct quectel_data *data =

[PATCH 2/7] quectel: use lte atom on EC21

2020-05-26 Thread poeschel
From: Lars Poeschel 

---
 plugins/quectel.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/plugins/quectel.c b/plugins/quectel.c
index 1a49a5b3..0f6896b1 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -1263,6 +1263,9 @@ static void quectel_post_sim(struct ofono_modem *modem)
ofono_sms_create(modem, data->vendor, "atmodem", data->aux);
ofono_phonebook_create(modem, data->vendor, "atmodem", data->aux);
ofono_call_volume_create(modem, data->vendor, "atmodem", data->aux);
+
+   if (data->model == QUECTEL_EC21)
+   ofono_lte_create(modem, data->vendor, "atmodem", data->aux);
 }
 
 static void quectel_post_online(struct ofono_modem *modem)
-- 
2.26.2
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


[PATCH 1/7] quectel: Add Quectel EC21 to known serial modems

2020-05-26 Thread poeschel
From: Lars Poeschel 

This adds the Quectel EC21 to the known modems of the quectel driver and
therefore allows to use it with its serial interface.
---
 plugins/quectel.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/plugins/quectel.c b/plugins/quectel.c
index 5d3ad470..1a49a5b3 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -64,7 +64,7 @@ static const char *cpin_prefix[] = { "+CPIN:", NULL };
 static const char *cbc_prefix[] = { "+CBC:", NULL };
 static const char *qinistat_prefix[] = { "+QINISTAT:", NULL };
 static const char *cgmm_prefix[] = { "UC15", "Quectel_M95", "Quectel_MC60",
-   NULL };
+   "EC21", NULL };
 static const char *none_prefix[] = { NULL };
 
 static const uint8_t gsm0710_terminate[] = {
@@ -83,6 +83,7 @@ enum quectel_model {
QUECTEL_UC15,
QUECTEL_M95,
QUECTEL_MC60,
+   QUECTEL_EC21,
 };
 
 struct quectel_data {
@@ -512,6 +513,7 @@ static void dbus_hw_enable(struct ofono_modem *modem)
 
switch (data->model) {
case QUECTEL_UC15:
+   case QUECTEL_EC21:
g_at_chat_register(data->aux, "+QIND",  qind_notify, FALSE, hw,
NULL);
break;
@@ -556,6 +558,7 @@ static void qinistat_cb(gboolean ok, GAtResult *result, 
gpointer user_data)
 
switch (data->model) {
case QUECTEL_UC15:
+   case QUECTEL_EC21:
/* UC15 uses a bitmap of 1 + 2 + 4 = 7 */
ready = 7;
break;
@@ -788,6 +791,10 @@ static void cgmm_cb(int ok, GAtResult *result, void 
*user_data)
DBG("%p model MC60", modem);
data->vendor = OFONO_VENDOR_QUECTEL_SERIAL;
data->model = QUECTEL_MC60;
+   } else if (strcmp(model, "EC21") == 0) {
+   DBG("%p model EC21", modem);
+   data->vendor = OFONO_VENDOR_QUECTEL;
+   data->model = QUECTEL_EC21;
} else {
ofono_warn("%p unknown model: '%s'", modem, model);
data->vendor = OFONO_VENDOR_QUECTEL;
-- 
2.26.2
___
ofono mailing list -- ofono@ofono.org
To unsubscribe send an email to ofono-le...@ofono.org


Re: [PATCH 09/10] quectel: add basic support for serial connected modems

2019-07-08 Thread Lars Poeschel
On Fri, Jul 05, 2019 at 05:57:05PM -0500, Denis Kenzior wrote:
> Hi Martin,
> 
> On 07/03/2019 01:09 PM, Martin Hundebøll wrote:
> > Setup GSM 07.10 multiplexing using the kernel n_gsm line discpline
> > driver, and use the virtual tty devices as Aux and Modem channels.
> > 
> > The driver supports rts/cts on the underlying serial device. This is
> > enabled with OFONO_QUECTED_RTSCTS udev environment, e.g.:
> > 
> > KERNEL=="ttymxc0", ENV{OFONO_DRIVER}="quectel", \
> >  ENV{OFONO_QUECTEL_RTSCTS}="on"
> 
> So from what I recall the kernel multiplexer was pretty much hard-coded as
> to how many DLCs you could request and it was up to the driver to do that.
> GAtMux has no such limitations...  We tried it with the ifx driver, but in
> the end GAtMux was more flexible.  Plus you actually get support for
> multiple devices...
> 
> So are you sure you want to use the kernel one?

I would also opt for a way to use the kernel multiplexer. This does not
mean to make the ofono GAtMux obsolete.
Some time ago I also wrote a patch for ofono to use the kernel
multiplexer and it worked quite well. Unfortunately I did not find the
time to clean it up properly for submission.
I choose to use the kernel multiplexer because I had some experience
with it and - well - the ofono one was not flexible enough. ;-) It did
not support the mux parameters I needed.
The number of DLCs in the kernel multiplexer is not hardcoded. It
presents all possible DLCs to userspace (/dev/gsmtty1 - /dev/gsmtty64)
and as soon as an application tries to open that specific file it sets
up the DLC on mux level.

So, besides from the code review comments, count this as my vote for the
kernel multiplexer.

Thanks,
Lars
___
ofono mailing list
ofono@ofono.org
https://lists.ofono.org/mailman/listinfo/ofono


Re: [BUG] plugins: sim900 support broken for tty port users

2018-06-22 Thread poeschel

On 06/19/2018 03:19 AM, poesc...@lemonage.de wrote:

Hi!

I think I found a bug.

Commit 1d63b1d35 essentially breaks the sim900 driver for serial port 
users.


Right.  This looks like some wires being crossed.  sim900 driver is
only meant for serial port usage.  So listing it for 'option' isn't
correct. Also, setup_sim900 was renamed from setup_simcom (introduced
in f2bfaed17).  Unfortunately I don't think we ever had a simcom
driver (e.g. plugins/simcom.c) for non-serial SIM COM modems until
support for SIM 7100 was added.

It adds a new entry in plugins/udevng.c driver_list with name 
"sim900".

There are two entries with the same name then: The new one which calls
the new setup_sim900 function and the old one which wants to call
the old setup_serial_modem function. Since driver_list is scanned
by name of the driver from top to button, serial driver users don't
have a chance to reach the entry with setup_serial_modem anymore.
Calling setup_sim900 does not work on a modem that was added through
add_serial_device, because the union serial/devices is written a
struct serial_device_info * that can not be used as GSList *.
Maybe I am missing something, but I think the new driver name in
driver_list should be different from the old one.


Right.  I've gone ahead and pushed out
06f3a85ee3d187888640be71d5dd5293e6970d05 that should fix this.  Please
let me know if it does.


I don't see 06f3a85ee3d187888640be71d5dd5293e6970d05 in public git,
but I guess 08796aa39186568402dd657704151079f1105dae (at the moment
on top of master) will also do. ;-)

I tested it. It chooses the right sim900 driver now and does start
communicating as I would expect it. Unfortunately I can't test much
more, because I don't own a sim900. Sorry.

Thank you for the quick fix,
Lars

___
ofono mailing list
ofono@ofono.org
https://lists.ofono.org/mailman/listinfo/ofono


[BUG] plugins: sim900 support broken for tty port users

2018-06-19 Thread poeschel

Hi!

I think I found a bug.

Commit 1d63b1d35 essentially breaks the sim900 driver for serial port 
users.

It adds a new entry in plugins/udevng.c driver_list with name "sim900".
There are two entries with the same name then: The new one which calls
the new setup_sim900 function and the old one which wants to call
the old setup_serial_modem function. Since driver_list is scanned
by name of the driver from top to button, serial driver users don't
have a chance to reach the entry with setup_serial_modem anymore.
Calling setup_sim900 does not work on a modem that was added through
add_serial_device, because the union serial/devices is written a
struct serial_device_info * that can not be used as GSList *.
Maybe I am missing something, but I think the new driver name in
driver_list should be different from the old one.

Regards,
Lars
___
ofono mailing list
ofono@ofono.org
https://lists.ofono.org/mailman/listinfo/ofono