[-]
[+]
|
Changed |
_service:tar_git:ofono.changes
|
|
[-]
[+]
|
Changed |
_service:tar_git:ofono.spec
^
|
|
[-]
[+]
|
Changed |
_service
^
|
@@ -1,7 +1,7 @@
<services>
<service name="tar_git">
<param name="url">https://github.com/sailfish-on-dontbeevil/ofono-new</param>
- <param name="branch">branch-1.30-qmi</param>
+ <param name="branch">branch-1.31-qmi</param>
<param name="token"/>
<param name="debian">N</param>
<param name="dumb">N</param>
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.31+pp1.tar.bz2/ofono/ChangeLog
^
|
@@ -1,3 +1,8 @@
+ver 1.31:
+ Fix issue with handling CID 0 context identifier.
+ Fix issue with handling detach state and running LTE.
+ Fix issue with handling SIM states and Quectel modems.
+
ver 1.30:
Fix issue with handling of IPv6 address and xmm7xxx modems.
Fix issue with default context creation with an empty APN.
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.31+pp1.tar.bz2/ofono/configure.ac
^
|
@@ -1,5 +1,5 @@
AC_PREREQ(2.60)
-AC_INIT(ofono, 1.30)
+AC_INIT(ofono, 1.31)
AM_INIT_AUTOMAKE([foreign subdir-objects color-tests])
AC_CONFIG_HEADERS(config.h)
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.31+pp1.tar.bz2/ofono/doc/quectel-hardware-api.txt
^
|
@@ -16,9 +16,9 @@
by the modem.
Possible reasons:
- "VoltageLow" The supply voltage is too low
- "Normal" The PWRKEY pin was asserted
- "VoltageHigh" The supply voltage is too high
+ "voltagelow" The supply voltage is too low
+ "normal" The PWRKEY pin was asserted
+ "voltagehigh" The supply voltage is too high
PowerWarning(string reason)
@@ -26,8 +26,8 @@
voltage is close to its supported limits.
Possible reasons:
- "VoltageLow" The supply voltage is low
- "VoltageHigh" The supply voltage is high
+ "voltagelow" The supply voltage is low
+ "voltagehigh" The supply voltage is high
Properties int32 Voltage [readonly]
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.31+pp1.tar.bz2/ofono/drivers/atmodem/gprs.c
^
|
@@ -41,6 +41,8 @@
#include "atmodem.h"
#include "vendor.h"
+#define MAX_CONTEXTS 255
+
static const char *cgreg_prefix[] = { "+CGREG:", NULL };
static const char *cgdcont_prefix[] = { "+CGDCONT:", NULL };
static const char *cgact_prefix[] = { "+CGACT:", NULL };
@@ -54,6 +56,47 @@
int attached;
};
+struct list_contexts_data
+{
+ struct ofono_gprs *gprs;
+ void *cb;
+ void *data;
+ struct idmap *active_cids;
+ int ref_count;
+};
+
+static struct list_contexts_data * list_contexts_data_new(
+ struct ofono_gprs *gprs, void *cb, void *data)
+{
+ struct list_contexts_data *ret;
+
+ ret = g_new0(struct list_contexts_data, 1);
+ ret->ref_count = 1;
+ ret->gprs = gprs;
+ ret->cb = cb;
+ ret->data = data;
+
+ return ret;
+}
+
+static struct list_contexts_data * list_contexts_data_ref(
+ struct list_contexts_data *ld)
+{
+ ld->ref_count++;
+ return ld;
+}
+
+static void list_contexts_data_unref(gpointer user_data)
+{
+ struct list_contexts_data *ld = user_data;
+
+ if (--ld->ref_count)
+ return;
+
+ idmap_free(ld->active_cids);
+ g_free(ld);
+}
+
static void at_cgatt_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct cb_data *cbd = user_data;
@@ -146,14 +189,43 @@
CALLBACK_WITH_FAILURE(cb, -1, data);
}
+static void at_cgdcont_parse(struct ofono_gprs *gprs, GAtResult *result,
+ struct idmap *cids)
+{
+ GAtResultIter iter;
+
+ g_at_result_iter_init(&iter, result);
+
+ while (g_at_result_iter_next(&iter, "+CGDCONT:")) {
+ int read_cid;
+ const char *apn = NULL;
+
+ if (!g_at_result_iter_next_number(&iter, &read_cid))
+ break;
+
+ if (!idmap_find(cids, read_cid))
+ continue;
+
+ /* ignore protocol */
+ g_at_result_iter_skip_next(&iter);
+
+ g_at_result_iter_next_string(&iter, &apn);
+
+ if (apn)
+ ofono_gprs_cid_activated(gprs, read_cid, apn);
+ else
+ ofono_warn("cid %d: Activated but no apn present",
+ read_cid);
+ }
+}
+
static void at_cgdcont_read_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct ofono_gprs *gprs = user_data;
struct gprs_data *gd = ofono_gprs_get_data(gprs);
int activated_cid = gd->last_auto_context_id;
- const char *apn = NULL;
- GAtResultIter iter;
+ struct idmap *cids;
DBG("ok %d", ok);
@@ -162,47 +234,52 @@
return;
}
- if (gd->last_auto_context_id == -1) {
+ if (activated_cid == -1) {
DBG("Context got deactivated while calling CGDCONT");
return;
}
- g_at_result_iter_init(&iter, result);
+ cids = idmap_new(activated_cid);
- while (g_at_result_iter_next(&iter, "+CGDCONT:")) {
- int read_cid;
-
- if (!g_at_result_iter_next_number(&iter, &read_cid))
- break;
+ idmap_take(cids, activated_cid);
- if (read_cid != activated_cid)
- continue;
+ at_cgdcont_parse(gprs, result, cids);
- /* ignore protocol */
- g_at_result_iter_skip_next(&iter);
+ idmap_free(cids);
+}
- g_at_result_iter_next_string(&iter, &apn);
+static void at_cgdcont_act_read_cb(gboolean ok, GAtResult *result,
+ gpointer user_data)
+{
+ struct list_contexts_data *ld = user_data;
+ ofono_gprs_cb_t cb = ld->cb;
+ struct ofono_error error;
- break;
- }
+ decode_at_error(&error, g_at_result_final_response(result));
- if (apn)
- ofono_gprs_cid_activated(gprs, activated_cid, apn);
+ if (!ok)
+ ofono_warn("Can't read CGDCONT context.");
else
- ofono_warn("cid %u: Received activated but no apn present",
- activated_cid);
+ at_cgdcont_parse(ld->gprs, result, ld->active_cids);
+
+ cb(&error, ld->data);
}
static void at_cgact_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
- struct ofono_gprs *gprs = user_data;
- struct gprs_data *gd = ofono_gprs_get_data(gprs);
+ struct list_contexts_data *ld = user_data;
+ struct gprs_data *gd = ofono_gprs_get_data(ld->gprs);
+ ofono_gprs_cb_t cb = ld->cb;
+ struct ofono_error error;
GAtResultIter iter;
- DBG("ok %d", ok);
+ decode_at_error(&error, g_at_result_final_response(result));
if (!ok) {
ofono_warn("Can't read CGACT contexts.");
+
+ cb(&error, ld->data);
+
return;
}
@@ -222,19 +299,45 @@
continue;
/* Flag this as auto context as it was obviously active */
- if (gd->last_auto_context_id == 0)
+ if (gd->last_auto_context_id == -1)
gd->last_auto_context_id = read_cid;
- if (read_cid != gd->last_auto_context_id)
- continue;
+ if (!ld->active_cids)
+ ld->active_cids = idmap_new(MAX_CONTEXTS);
- g_at_chat_send(gd->chat, "AT+CGDCONT?", cgdcont_prefix,
- at_cgdcont_read_cb, gprs, NULL);
+ idmap_take(ld->active_cids, read_cid);
+ }
- break;
+ if (ld->active_cids != NULL) {
+ if (g_at_chat_send(gd->chat, "AT+CGDCONT?", cgdcont_prefix,
+ at_cgdcont_act_read_cb, ld,
+ list_contexts_data_unref)) {
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.31+pp1.tar.bz2/ofono/drivers/atmodem/network-registration.h
^
|
@@ -1,4 +1,3 @@
-#pragma once
struct at_netreg_data {
GAtChat *chat;
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.31+pp1.tar.bz2/ofono/drivers/atmodem/sim.c
^
|
@@ -1354,7 +1354,6 @@
case OFONO_VENDOR_HUAWEI:
case OFONO_VENDOR_SIMCOM:
case OFONO_VENDOR_SIERRA:
- case OFONO_VENDOR_QUECTEL_SERIAL:
/*
* On ZTE modems, after pin is entered, SIM state is checked
* by polling CPIN as their modem doesn't provide unsolicited
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.31+pp1.tar.bz2/ofono/drivers/atmodem/sms.c
^
|
@@ -843,6 +843,7 @@
case OFONO_VENDOR_HUAWEI:
case OFONO_VENDOR_ZTE:
case OFONO_VENDOR_SIMCOM:
+ case OFONO_VENDOR_QUECTEL:
/* MSM devices advertise support for mode 2, but return an
* error if we attempt to actually use it. */
mode = "1";
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.31+pp1.tar.bz2/ofono/drivers/atmodem/voicecall.c
^
|
@@ -266,14 +266,17 @@
poll_clcc, vc);
}
+static void send_clcc(struct voicecall_data *vd, struct ofono_voicecall *vc)
+{
+ g_at_chat_send(vd->chat, "AT+CLCC", clcc_prefix, clcc_poll_cb, vc, NULL);
+}
+
static gboolean poll_clcc(gpointer user_data)
{
struct ofono_voicecall *vc = user_data;
struct voicecall_data *vd = ofono_voicecall_get_data(vc);
- g_at_chat_send(vd->chat, "AT+CLCC", clcc_prefix,
- clcc_poll_cb, vc, NULL);
-
+ send_clcc(vd, vc);
vd->clcc_source = 0;
return FALSE;
@@ -299,8 +302,7 @@
}
}
- g_at_chat_send(vd->chat, "AT+CLCC", clcc_prefix,
- clcc_poll_cb, req->vc, NULL);
+ send_clcc(vd, req->vc);
/* We have to callback after we schedule a poll if required */
req->cb(&error, req->data);
@@ -318,8 +320,7 @@
if (ok)
vd->local_release = 1 << req->id;
- g_at_chat_send(vd->chat, "AT+CLCC", clcc_prefix,
- clcc_poll_cb, req->vc, NULL);
+ send_clcc(vd, req->vc);
/* We have to callback after we schedule a poll if required */
req->cb(&error, req->data);
@@ -964,8 +965,7 @@
struct ofono_voicecall *vc = user_data;
struct voicecall_data *vd = ofono_voicecall_get_data(vc);
- g_at_chat_send(vd->chat, "AT+CLCC", clcc_prefix,
- clcc_poll_cb, vc, NULL);
+ send_clcc(vd, vc);
}
static void no_answer_notify(GAtResult *result, gpointer user_data)
@@ -973,8 +973,7 @@
struct ofono_voicecall *vc = user_data;
struct voicecall_data *vd = ofono_voicecall_get_data(vc);
- g_at_chat_send(vd->chat, "AT+CLCC", clcc_prefix,
- clcc_poll_cb, vc, NULL);
+ send_clcc(vd, vc);
}
static void busy_notify(GAtResult *result, gpointer user_data)
@@ -986,8 +985,7 @@
* or UDUB on the other side
* TODO: Handle UDUB or other conditions somehow
*/
- g_at_chat_send(vd->chat, "AT+CLCC", clcc_prefix,
- clcc_poll_cb, vc, NULL);
+ send_clcc(vd, vc);
}
static void cssi_notify(GAtResult *result, gpointer user_data)
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.31+pp1.tar.bz2/ofono/drivers/huaweimodem/gprs-context.c
^
|
@@ -255,7 +255,7 @@
{
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
struct cb_data *cbd = cb_data_new(cb, data);
- char buf[64];
+ char buf[136];
/* IPv6 support not implemented */
if (ctx->proto != OFONO_GPRS_PROTO_IP)
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.31+pp1.tar.bz2/ofono/drivers/ifxmodem/gprs-context.c
^
|
@@ -353,6 +353,9 @@
DBG("DNS: %s, %s\n", gcd->dns1, gcd->dns2);
+ if (gw)
+ strncpy(gcd->gateway, gw, sizeof(gcd->gateway));
+
if (gcd->proto == OFONO_GPRS_PROTO_IP) {
if (!laddrnetmask ||
at_util_get_ipv4_address_and_netmask(laddrnetmask,
@@ -390,9 +393,6 @@
IPV6_DEFAULT_PREFIX_LEN);
}
- if (gw)
- strncpy(gcd->gateway, gw, sizeof(gcd->gateway));
-
gcd->state = STATE_ACTIVE;
DBG("address: %s\n", gcd->address);
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.31+pp1.tar.bz2/ofono/drivers/ubloxmodem/gprs-context.c
^
|
@@ -40,6 +40,8 @@
#include "ubloxmodem.h"
+#define UBLOX_FLAG_DEACTIVATING 0x01
+
static const char *none_prefix[] = { NULL };
static const char *cgcontrdp_prefix[] = { "+CGCONTRDP:", NULL };
static const char *uipaddr_prefix[] = { "+UIPADDR:", NULL };
@@ -57,6 +59,7 @@
ofono_gprs_context_cb_t cb;
void *cb_data;
enum netmode networking_mode;
+ int flags;
};
static void uipaddr_cb(gboolean ok, GAtResult *result, gpointer user_data)
@@ -426,6 +429,8 @@
DBG("ok %d", ok);
+ gcd->flags &= ~UBLOX_FLAG_DEACTIVATING;
+
if (!ok) {
CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data);
return;
@@ -448,6 +453,8 @@
gcd->cb = cb;
gcd->cb_data = data;
+ gcd->flags |= UBLOX_FLAG_DEACTIVATING;
+
snprintf(buf, sizeof(buf), "AT+CGACT=0,%u", gcd->active_context);
g_at_chat_send(gcd->chat, buf, none_prefix,
cgact_disable_cb, gc, NULL);
@@ -473,10 +480,16 @@
sscanf(event, "%*s %*s %*s %u", &cid);
else if (g_str_has_prefix(event, "NW DEACT"))
sscanf(event, "%*s %*s %u", &cid);
+ else if (!(gcd->flags & UBLOX_FLAG_DEACTIVATING) &&
+ g_str_has_prefix(event, "ME PDN DEACT"))
+ /* The modem might consider the ME deactivating without
+ * an explicit CGACT=0 beeing sent
+ */
+ sscanf(event, "%*s %*s %*s %u", &cid);
else
return;
- DBG("cid %d", cid);
+ DBG("cid %d, active cid: %d", cid, gcd->active_context);
if ((unsigned int) cid != gcd->active_context)
return;
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.31+pp1.tar.bz2/ofono/drivers/ubloxmodem/network-registration.c
^
|
@@ -28,6 +28,7 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
+#include <stdbool.h>
#include <glib.h>
@@ -47,17 +48,20 @@
static const char *none_prefix[] = { NULL };
static const char *cmer_prefix[] = { "+CMER:", NULL };
static const char *ureg_prefix[] = { "+UREG:", NULL };
+static const char *creg_prefix[] = { "+CREG:", NULL };
struct netreg_data {
struct at_netreg_data at_data;
const struct ublox_model *model;
+ bool updating_status : 1;
};
struct tech_query {
int status;
int lac;
int ci;
+ int tech;
struct ofono_netreg *netreg;
};
@@ -212,13 +216,75 @@
ofono_netreg_time_notify(netreg, &nd->time);
}
-static void ublox_query_tech_cb(gboolean ok, GAtResult *result,
+static int ublox_ureg_state_to_tech(int state)
+{
+ switch (state) {
+ case 1:
+ return ACCESS_TECHNOLOGY_GSM;
+ case 2:
+ return ACCESS_TECHNOLOGY_GSM_EGPRS;
+ case 3:
+ return ACCESS_TECHNOLOGY_UTRAN;
+ case 4:
+ return ACCESS_TECHNOLOGY_UTRAN_HSDPA;
+ case 5:
+ return ACCESS_TECHNOLOGY_UTRAN_HSUPA;
+ case 6:
+ return ACCESS_TECHNOLOGY_UTRAN_HSDPA_HSUPA;
+ case 7:
+ return ACCESS_TECHNOLOGY_EUTRAN;
+ case 8:
+ return ACCESS_TECHNOLOGY_GSM;
+ case 9:
+ return ACCESS_TECHNOLOGY_GSM_EGPRS;
+ default:
+ /* Not registered for PS (0) or something unknown (>9)... */
+ return -1;
+ }
+}
+
+static gboolean is_registered(int status)
+{
+ return status == NETWORK_REGISTRATION_STATUS_REGISTERED ||
+ status == NETWORK_REGISTRATION_STATUS_ROAMING;
+}
+
+static void ublox_creg_cb(gboolean ok, GAtResult *result,
+ gpointer user_data)
+{
+ struct tech_query *tq = user_data;
+ struct netreg_data *nd = ofono_netreg_get_data(tq->netreg);
+ int status;
+ int lac;
+ int ci;
+ int tech;
+
+ nd->updating_status = false;
+
+ if (!ok)
+ return;
+
+ if (at_util_parse_reg(result, "+CREG:", NULL, &status,
+ &lac, &ci, &tech, OFONO_VENDOR_GENERIC) == FALSE)
+ return;
+
+ /* The query provided a tech, use that */
+ if (is_registered(status) && tq->tech != -1)
+ tech = tq->tech;
+
+ ofono_netreg_status_notify(tq->netreg, status, lac, ci, tech);
+}
+
+static void ublox_ureg_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct tech_query *tq = user_data;
+ struct netreg_data *nd = ofono_netreg_get_data(tq->netreg);
GAtResultIter iter;
gint enabled, state;
- int tech = -1;
+ int tech = tq->tech;
+
+ nd->updating_status = false;
if (!ok)
goto error;
@@ -234,58 +300,88 @@
if (!g_at_result_iter_next_number(&iter, &state))
return;
- switch (state) {
- case 4:
- tech = 5;
- break;
- case 5:
- tech = 4;
- break;
- case 8:
- tech = 1;
- break;
- case 9:
- tech = 2;
- break;
- default:
- tech = state;
- }
+ tech = ublox_ureg_state_to_tech(state);
+ if (tech < 0)
+ /* No valid UREG status, we have to trust CREG... */
+ tech = tq->tech;
error:
ofono_netreg_status_notify(tq->netreg,
tq->status, tq->lac, tq->ci, tech);
}
+static void ureg_notify(GAtResult *result, gpointer user_data)
+{
+ struct ofono_netreg *netreg = user_data;
+ struct netreg_data *nd = ofono_netreg_get_data(netreg);
+ struct tech_query *tq;
+ GAtResultIter iter;
+ int state;
+
+ if (nd->updating_status)
+ return;
+
+ g_at_result_iter_init(&iter, result);
+
+ if (!g_at_result_iter_next(&iter, "+UREG:"))
+ return;
+
+ if (!g_at_result_iter_next_number(&iter, &state))
+ return;
+
+ tq = g_new0(struct tech_query, 1);
+
+ tq->tech = ublox_ureg_state_to_tech(state);
+ tq->netreg = netreg;
+
+ if (g_at_chat_send(nd->at_data.chat, "AT+CREG?", creg_prefix,
+ ublox_creg_cb, tq, g_free) > 0) {
+ nd->updating_status = true;
+ return;
+ }
+
+ g_free(tq);
+}
+
static void creg_notify(GAtResult *result, gpointer user_data)
{
struct ofono_netreg *netreg = user_data;
- int status, lac, ci, tech;
struct netreg_data *nd = ofono_netreg_get_data(netreg);
struct tech_query *tq;
+ int status;
+ int lac;
+ int ci;
+ int tech;
+
+ if (nd->updating_status)
+ return;
if (at_util_parse_reg_unsolicited(result, "+CREG:", &status,
&lac, &ci, &tech, OFONO_VENDOR_GENERIC) == FALSE)
return;
- if (status != 1 && status != 5)
+ if (!is_registered(status))
goto notify;
- if (ublox_is_toby_l4(nd->model)) {
+ if (ublox_is_toby_l4(nd->model) || ublox_is_toby_l2(nd->model)) {
tq = g_new0(struct tech_query, 1);
tq->status = status;
tq->lac = lac;
tq->ci = ci;
+ tq->tech = tech;
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.31+pp1.tar.bz2/ofono/gatchat/gatchat.c
^
|
@@ -1047,6 +1047,29 @@
return c->id;
}
+static gboolean at_chat_retry(struct at_chat *chat, guint id)
+{
+ struct at_command *cmd = g_queue_peek_head(chat->command_queue);
+
+ if (!cmd)
+ return FALSE;
+
+ /* do nothing if command is not yet started, or already finished */
+ if (cmd->id != id)
+ return FALSE;
+
+ /* do nothing if command is not fully written */
+ if (chat->cmd_bytes_written != strlen(cmd->cmd))
+ return FALSE;
+
+ /* reset number of written bytes to re-write command */
+ chat->cmd_bytes_written = 0;
+
+ chat_wakeup_writer(chat);
+
+ return TRUE;
+}
+
static struct at_notify *at_notify_create(struct at_chat *chat,
const char *prefix,
gboolean pdu)
@@ -1543,6 +1566,14 @@
NULL, func, user_data, notify);
}
+gboolean g_at_chat_retry(GAtChat *chat, guint id)
+{
+ if (chat == NULL || id == 0)
+ return FALSE;
+
+ return at_chat_retry(chat->parent, id);
+}
+
gboolean g_at_chat_cancel(GAtChat *chat, guint id)
{
/* We use id 0 for wakeup commands */
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.31+pp1.tar.bz2/ofono/gatchat/gatchat.h
^
|
@@ -147,6 +147,13 @@
const char **valid_resp, GAtResultFunc func,
gpointer user_data, GDestroyNotify notify);
+/*!
+ * Retry an already created command. This does nothing if the command is
+ * still waiting in the queue. If the command has been written to the channel,
+ * but no response is received yet, the retry writes the command again.
+ */
+gboolean g_at_chat_retry(GAtChat *chat, guint id);
+
gboolean g_at_chat_cancel(GAtChat *chat, guint id);
gboolean g_at_chat_cancel_all(GAtChat *chat);
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.31+pp1.tar.bz2/ofono/gatchat/gatmux.c
^
|
@@ -231,6 +231,7 @@
int i;
GIOStatus status;
gsize bytes_read;
+ gboolean buffer_full = FALSE;
if (cond & G_IO_NVAL)
return FALSE;
@@ -255,6 +256,8 @@
if (mux->buf_used > 0)
memmove(mux->buf, mux->buf + nread, mux->buf_used);
+ g_at_mux_ref(mux);
+
for (i = 1; i <= MAX_CHANNELS; i++) {
int offset = i / 8;
int bit = i % 8;
@@ -267,6 +270,10 @@
dispatch_sources(mux->dlcs[i-1], G_IO_IN);
}
+
+ buffer_full = mux->buf_used == sizeof(mux->buf);
+
+ g_at_mux_unref(mux);
}
if (cond & (G_IO_HUP | G_IO_ERR))
@@ -275,7 +282,7 @@
if (status != G_IO_STATUS_NORMAL && status != G_IO_STATUS_AGAIN)
return FALSE;
- if (mux->buf_used == sizeof(mux->buf))
+ if (buffer_full)
return FALSE;
return TRUE;
@@ -646,13 +653,6 @@
}
}
-static void read_watcher_destroy_notify(gpointer user_data)
-{
- GAtMux *mux = user_data;
-
- mux->read_watch = 0;
-}
-
gboolean g_at_mux_start(GAtMux *mux)
{
if (mux->channel == NULL)
@@ -666,8 +666,7 @@
mux->read_watch = g_io_add_watch_full(mux->channel, G_PRIORITY_DEFAULT,
G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- received_data, mux,
- read_watcher_destroy_notify);
+ received_data, mux, NULL);
mux->shutdown = FALSE;
@@ -684,8 +683,10 @@
if (mux->channel == NULL)
return FALSE;
- if (mux->read_watch > 0)
+ if (mux->read_watch > 0) {
g_source_remove(mux->read_watch);
+ mux->read_watch = 0;
+ }
if (mux->write_watch > 0)
g_source_remove(mux->write_watch);
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.31+pp1.tar.bz2/ofono/gisi/modem.c
^
|
@@ -33,6 +33,7 @@
#include <errno.h>
#include <glib.h>
+#pragma GCC diagnostic ignored "-Wpragmas"
#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
#include "message.h"
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.31+pp1.tar.bz2/ofono/gisi/socket.c
^
|
@@ -32,6 +32,7 @@
#include <fcntl.h>
#include <glib.h>
+#pragma GCC diagnostic ignored "-Wpragmas"
#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
#include "phonet.h"
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.31+pp1.tar.bz2/ofono/include/gprs.h
^
|
@@ -45,6 +45,8 @@
ofono_gprs_cb_t cb, void *data);
void (*attached_status)(struct ofono_gprs *gprs,
ofono_gprs_status_cb_t cb, void *data);
+ void (*list_active_contexts)(struct ofono_gprs *gprs,
+ ofono_gprs_cb_t cb, void *data);
};
enum gprs_suspend_cause {
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.31+pp1.tar.bz2/ofono/plugins/quectel.c
^
|
@@ -36,6 +36,7 @@
#include <linux/gsmmux.h>
#include <gatchat.h>
#include <gattty.h>
+#include <gatmux.h>
#define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono.h>
@@ -87,18 +88,23 @@
struct quectel_data {
GAtChat *modem;
GAtChat *aux;
- guint cpin_ready;
- guint call_ready;
- bool have_sim;
enum ofono_vendor vendor;
enum quectel_model model;
- struct l_timeout *sms_ready_timer;
+ struct at_util_sim_state_query *sim_state_query;
+ unsigned int sim_watch;
+ bool sim_locked;
+ bool sim_ready;
/* used by quectel uart driver */
+ GIOChannel *device;
GAtChat *uart;
+ GAtMux *mux;
int mux_ready_count;
int initial_ldisc;
struct l_gpio_writer *gpio;
+ struct l_timeout *init_timeout;
+ size_t init_count;
+ guint init_cmd;
};
struct dbus_hw {
@@ -184,73 +190,77 @@
DBG("%p", modem);
- if (data->cpin_ready != 0)
- g_at_chat_unregister(data->aux, data->cpin_ready);
-
ofono_modem_set_data(modem, NULL);
+ l_timeout_remove(data->init_timeout);
l_gpio_writer_free(data->gpio);
+ at_util_sim_state_query_free(data->sim_state_query);
g_at_chat_unref(data->aux);
g_at_chat_unref(data->modem);
g_at_chat_unref(data->uart);
+ g_at_mux_unref(data->mux);
+
+ if (data->device)
+ g_io_channel_unref(data->device);
+
g_free(data);
}
-static void close_mux_cb(struct l_timeout *timeout, void *user_data)
+static void close_mux(struct ofono_modem *modem)
+{
+ struct quectel_data *data = ofono_modem_get_data(modem);
+
+ DBG("%p", modem);
+
+ g_io_channel_unref(data->device);
+ data->device = NULL;
+
+ g_at_mux_unref(data->mux);
+ data->mux = NULL;
+}
+
+static void close_ngsm(struct ofono_modem *modem)
{
- struct ofono_modem *modem = user_data;
struct quectel_data *data = ofono_modem_get_data(modem);
- GIOChannel *device;
- uint32_t gpio_value = 0;
- ssize_t write_count;
int fd;
DBG("%p", modem);
- device = g_at_chat_get_channel(data->uart);
- fd = g_io_channel_unix_get_fd(device);
+ if (!data->device)
+ return;
+
+ fd = g_io_channel_unix_get_fd(data->device);
/* restore initial tty line discipline */
if (ioctl(fd, TIOCSETD, &data->initial_ldisc) < 0)
ofono_warn("Failed to restore line discipline");
-
- /* terminate gsm 0710 multiplexing on the modem side */
- write_count = write(fd, gsm0710_terminate, sizeof(gsm0710_terminate));
- if (write_count != sizeof(gsm0710_terminate))
- ofono_warn("Failed to terminate gsm multiplexing");
-
- g_at_chat_unref(data->uart);
- data->uart = NULL;
-
- l_timeout_remove(timeout);
- l_gpio_writer_set(data->gpio, 1, &gpio_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;
DBG("%p", modem);
+ at_util_sim_state_query_free(data->sim_state_query);
+ data->sim_state_query = NULL;
+
g_at_chat_unref(data->aux);
data->aux = NULL;
g_at_chat_unref(data->modem);
data->modem = NULL;
- /*
- * if gsm0710 multiplexing is used, the aux and modem file descriptors
- * must be closed before closing the underlying serial device to avoid
- * an old kernel dead-lock:
- * https://lists.ofono.org/pipermail/ofono/2011-March/009405.html
- *
- * setup a timer to iterate the mainloop once to let gatchat close the
- * virtual file descriptors unreferenced above
- */
- if (data->uart)
- l_timeout_create_ms(1, close_mux_cb, modem, NULL);
+ g_at_chat_unref(data->uart);
+ data->uart = NULL;
+
+ if (data->mux)
+ close_mux(modem);
else
- ofono_modem_set_powered(modem, false);
+ close_ngsm(modem);
+
+ l_gpio_writer_set(data->gpio, 1, &gpio_value);
+ ofono_modem_set_powered(modem, FALSE);
}
static void dbus_hw_reply_properties(struct dbus_hw *hw)
@@ -363,27 +373,27 @@
case LOW_POWER_DOWN:
close = true;
name = "PowerDown";
- reason = "VoltageLow";
+ reason = "voltagelow";
break;
case LOW_WARNING:
close = false;
name = "PowerWarning";
- reason = "VoltageLow";
+ reason = "voltagelow";
break;
case NORMAL_POWER_DOWN:
close = true;
name = "PowerDown";
- reason = "Normal";
+ reason = "normal";
break;
case HIGH_WARNING:
close = false;
name = "PowerWarning";
- reason = "VoltageHigh";
+ reason = "voltagehigh";
break;
case HIGH_POWER_DOWN:
close = true;
name = "PowerDown";
- reason = "VoltageHigh";
+ reason = "voltagehigh";
break;
default:
return;
@@ -525,12 +535,76 @@
ofono_modem_add_interface(modem, dbus_hw_interface);
}
-static void cpin_notify(GAtResult *result, gpointer user_data)
+static void qinistat_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
+ struct ofono_sim *sim = ofono_modem_get_sim(modem);
struct quectel_data *data = ofono_modem_get_data(modem);
- const char *sim_inserted;
GAtResultIter iter;
+ int ready = 0;
+ int status;
+
+ DBG("%p", modem);
+
+ g_at_result_iter_init(&iter, result);
+
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.31+pp1.tar.bz2/ofono/plugins/ublox.c
^
|
@@ -29,6 +29,7 @@
#include <glib.h>
#include <gatchat.h>
#include <gattty.h>
+#include <ell/ell.h>
#define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/plugin.h>
@@ -66,6 +67,10 @@
const struct ublox_model *model;
int flags;
+
+ struct l_timeout *init_timeout;
+ int init_count;
+ guint init_cmd;
};
static void ublox_debug(const char *str, void *user_data)
@@ -102,26 +107,25 @@
g_free(data);
}
-static GAtChat *open_device(struct ofono_modem *modem,
- const char *key, char *debug)
+static void close_devices(struct ofono_modem* modem)
{
- return at_util_open_device(modem, key, ublox_debug, debug,
- NULL);
+ struct ublox_data * data = ofono_modem_get_data(modem);
+
+ g_at_chat_unref(data->aux);
+ data->aux = NULL;
+ g_at_chat_unref(data->modem);
+ data->modem = NULL;
+ ofono_modem_set_powered(modem, FALSE);
}
static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
- struct ublox_data * data = ofono_modem_get_data(modem);
DBG("ok %d", ok);
if (!ok) {
- g_at_chat_unref(data->aux);
- data->aux = NULL;
- g_at_chat_unref(data->modem);
- data->modem = NULL;
- ofono_modem_set_powered(modem, FALSE);
+ close_devices(modem);
return;
}
@@ -172,11 +176,7 @@
return;
error:
- g_at_chat_unref(data->aux);
- data->aux = NULL;
- g_at_chat_unref(data->modem);
- data->modem = NULL;
- ofono_modem_set_powered(modem, FALSE);
+ close_devices(modem);
}
static void query_model_cb(gboolean ok, GAtResult *result, gpointer user_data)
@@ -223,11 +223,73 @@
return;
fail:
- g_at_chat_unref(data->aux);
- data->aux = NULL;
- g_at_chat_unref(data->modem);
- data->modem = NULL;
- ofono_modem_set_powered(modem, FALSE);
+ close_devices(modem);
+}
+
+static void init_cmd_cb(gboolean ok, GAtResult *result, void *user_data)
+{
+ struct ofono_modem *modem = user_data;
+ struct ublox_data *data = ofono_modem_get_data(modem);
+
+ DBG("%p", modem);
+
+ if (!ok)
+ goto fail;
+
+ /* When the 'init command' succeeds, we insert an additional
+ * delay of 1 second before proceeding with the actual
+ * intialization of the device. We reuse the init_timeout
+ * instance for this, just clearing the command to indicate
+ * that additional retries aren't necessary.
+ */
+ data->init_cmd = 0;
+ data->init_count = 0;
+ l_timeout_modify_ms(data->init_timeout, 1000);
+
+ return;
+
+fail:
+ l_timeout_remove(data->init_timeout);
+ data->init_timeout = NULL;
+
+ close_devices(modem);
+}
+
+static void init_timeout_cb(struct l_timeout *timeout, void *user_data)
+{
+ struct ofono_modem *modem = user_data;
+ struct ublox_data *data = ofono_modem_get_data(modem);
+
+ DBG("%p", modem);
+
+ /* As long as init_cmd is set we need to either keep retrying
+ * or fail everything after excessive retries
+ */
+ if (data->init_cmd && data->init_count++ < 20) {
+ g_at_chat_retry(data->aux, data->init_cmd);
+ l_timeout_modify_ms(timeout, 1000);
+ return;
+ }
+
+ l_timeout_remove(data->init_timeout);
+ data->init_timeout = NULL;
+
+ if (data->init_cmd) {
+ ofono_error("failed to init modem after 20 attempts");
+ goto fail;
+ }
+
+ g_at_chat_send(data->aux, "ATE0", none_prefix,
+ NULL, NULL, NULL);
+ g_at_chat_send(data->aux, "AT+CMEE=1", none_prefix,
+ NULL, NULL, NULL);
+
+ if (g_at_chat_send(data->aux, "AT+CGMM", NULL,
+ query_model_cb, modem, NULL) > 0)
+ return;
+
+fail:
+ close_devices(modem);
}
static int ublox_enable(struct ofono_modem *modem)
@@ -236,17 +298,20 @@
DBG("%p", modem);
- data->aux = open_device(modem, "Aux", "Aux: ");
+ data->aux = at_util_open_device(modem, "Aux",
+ ublox_debug, "Aux: ", NULL);
/* If this is a serial modem then the device may be behind
* the 'Device' attribute instead...
*/
if (data->aux == NULL) {
- data->aux = open_device(modem, "Device", "Aux: ");
+ data->aux = at_util_open_device(modem, "Device",
+ ublox_debug, "Aux: ", NULL);
if (data->aux == NULL)
return -EINVAL;
}
- data->modem = open_device(modem, "Modem", "Modem: ");
+ data->modem = at_util_open_device(modem, "Modem",
+ ublox_debug, "Modem: ", NULL);
if (data->modem) {
g_at_chat_set_slave(data->modem, data->aux);
g_at_chat_send(data->modem, "ATE0 +CMEE=1", none_prefix,
@@ -254,36 +319,48 @@
g_at_chat_send(data->modem, "AT&C0", NULL, NULL, NULL, NULL);
}
- /* The modem can take a while to wake up if just powered on. */
- g_at_chat_set_wakeup_command(data->aux, "AT\r", 1000, 11000);
-
- g_at_chat_send(data->aux, "ATE0", none_prefix,
- NULL, NULL, NULL);
- g_at_chat_send(data->aux, "AT+CMEE=1", none_prefix,
- NULL, NULL, NULL);
-
- if (g_at_chat_send(data->aux, "AT+CGMM", NULL,
- query_model_cb, modem, NULL) > 0)
- return -EINPROGRESS;
+ /*
+ * uBlox devices present their USB interfaces well before those
+ * interfaces are actually ready to use. The specs say to monitor
+ * the 'greeting text' to detect whether the device is ready to use;
+ * unfortunately, other than for the TOBY L4, the greeting text is
+ * not actually specified.
+ *
+ * What has been determined experimentally to work is to probe with
+ * an 'AT' command until it responds and then wait an additional
+ * second before continuing with device initialization. Even for
+ * the TOBY L4 where one should wait for the '+AT: READY' URC
+ * before intialization, this seems to be sufficient; the 'READY'
+ * indication always arrives within this time.
+ *
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.31+pp1.tar.bz2/ofono/plugins/udevng.c
^
|
@@ -41,6 +41,7 @@
enum modem_type {
MODEM_TYPE_USB,
MODEM_TYPE_SERIAL,
+ MODEM_TYPE_PCIE,
};
struct modem_info {
@@ -897,6 +898,11 @@
ofono_modem_set_string(modem->modem, "GpioOffset", value);
value = udev_device_get_property_value(info->dev,
+ "OFONO_QUECTEL_MUX");
+ if (value)
+ ofono_modem_set_string(modem->modem, "Mux", value);
+
+ value = udev_device_get_property_value(info->dev,
"OFONO_QUECTEL_RTSCTS");
ofono_modem_set_string(modem->modem, "RtsCts", value ? value : "off");
ofono_modem_set_string(modem->modem, "Device", info->devnode);
@@ -1232,26 +1238,47 @@
info->interface, info->number, info->label,
info->sysattr, info->subsystem);
- if (g_strcmp0(modem->model,"095a") == 0) {
- if (g_strcmp0(info->subsystem, "tty") == 0) {
- if (g_strcmp0(info->number, "00") == 0)
- mdm = info->devnode;
- } else if (g_strcmp0(info->subsystem, "net") == 0) {
- if (g_strcmp0(info->number, "06") == 0)
- net = info->devnode;
- if (g_strcmp0(info->number, "08") == 0)
- net2 = info->devnode;
- if (g_strcmp0(info->number, "0a") == 0)
- net3 = info->devnode;
+ if (g_strcmp0(info->subsystem, "pci") == 0) {
+ if ((g_strcmp0(modem->vendor, "0x8086") == 0) &&
+ (g_strcmp0(modem->model, "0x7560") == 0)) {
+ mdm = "/dev/iat";
+ net = "inm0";
+ net2 = "inm1";
+ net3 = "inm2";
+ ofono_modem_set_string(modem->modem,
+ "CtrlPath", "/PCIE/IOSM/CTRL/1");
+ ofono_modem_set_string(modem->modem, "DataPath",
+ "/PCIE/IOSM/IPS/");
}
- } else {
- if (g_strcmp0(info->subsystem, "tty") == 0) {
- if (g_strcmp0(info->number, "02") == 0)
- mdm = info->devnode;
- } else if (g_strcmp0(info->subsystem, "net") == 0) {
- if (g_strcmp0(info->number, "00") == 0)
- net = info->devnode;
+ } else { /* For USB */
+ if (g_strcmp0(modem->model, "095a") == 0) {
+ if (g_strcmp0(info->subsystem, "tty") == 0) {
+ if (g_strcmp0(info->number, "00") == 0)
+ mdm = info->devnode;
+ } else if (g_strcmp0(info->subsystem, "net")
+ == 0) {
+ if (g_strcmp0(info->number, "06") == 0)
+ net = info->devnode;
+ if (g_strcmp0(info->number, "08") == 0)
+ net2 = info->devnode;
+ if (g_strcmp0(info->number, "0a") == 0)
+ net3 = info->devnode;
+ }
+ } else {
+ if (g_strcmp0(info->subsystem, "tty") == 0) {
+ if (g_strcmp0(info->number, "02") == 0)
+ mdm = info->devnode;
+ } else if (g_strcmp0(info->subsystem, "net")
+ == 0) {
+ if (g_strcmp0(info->number, "00") == 0)
+ net = info->devnode;
+ }
}
+
+ ofono_modem_set_string(modem->modem, "CtrlPath",
+ "/USBCDC/0");
+ ofono_modem_set_string(modem->modem, "DataPath",
+ "/USBHS/NCM/");
}
}
@@ -1269,9 +1296,6 @@
if (net3)
ofono_modem_set_string(modem->modem, "NetworkInterface3", net3);
- ofono_modem_set_string(modem->modem, "CtrlPath", "/USBCDC/0");
- ofono_modem_set_string(modem->modem, "DataPath", "/USBHS/NCM/");
-
return TRUE;
}
@@ -1440,6 +1464,7 @@
switch (modem->type) {
case MODEM_TYPE_USB:
+ case MODEM_TYPE_PCIE:
for (list = modem->devices; list; list = list->next) {
struct device_info *info = list->data;
@@ -1470,6 +1495,7 @@
switch (modem->type) {
case MODEM_TYPE_USB:
+ case MODEM_TYPE_PCIE:
for (list = modem->devices; list; list = list->next) {
struct device_info *info = list->data;
@@ -1602,7 +1628,8 @@
static void add_device(const char *syspath, const char *devname,
const char *driver, const char *vendor,
- const char *model, struct udev_device *device)
+ const char *model, struct udev_device *device,
+ enum modem_type type)
{
struct udev_device *usb_interface;
const char *devpath, *devnode, *interface, *number;
@@ -1615,25 +1642,13 @@
if (devpath == NULL)
return;
- devnode = udev_device_get_devnode(device);
- if (devnode == NULL) {
- devnode = udev_device_get_property_value(device, "INTERFACE");
- if (devnode == NULL)
- return;
- }
-
- usb_interface = udev_device_get_parent_with_subsystem_devtype(device,
- "usb", "usb_interface");
- if (usb_interface == NULL)
- return;
-
modem = g_hash_table_lookup(modem_list, syspath);
if (modem == NULL) {
modem = g_try_new0(struct modem_info, 1);
if (modem == NULL)
return;
- modem->type = MODEM_TYPE_USB;
+ modem->type = type;
modem->syspath = g_strdup(syspath);
modem->devname = g_strdup(devname);
modem->driver = g_strdup(driver);
@@ -1645,8 +1660,37 @@
g_hash_table_replace(modem_list, modem->syspath, modem);
}
- interface = udev_device_get_property_value(usb_interface, "INTERFACE");
- number = udev_device_get_property_value(device, "ID_USB_INTERFACE_NUM");
+ if (modem->type == MODEM_TYPE_USB) {
+ devnode = udev_device_get_devnode(device);
+ if (devnode == NULL) {
+ devnode = udev_device_get_property_value(device,
+ "INTERFACE");
+ if (devnode == NULL)
+ return;
+ }
+
+ usb_interface = udev_device_get_parent_with_subsystem_devtype(
+ device, "usb",
+ "usb_interface");
+ if (usb_interface == NULL)
+ return;
+
+ interface = udev_device_get_property_value(usb_interface,
+ "INTERFACE");
+ number = udev_device_get_property_value(device,
+ "ID_USB_INTERFACE_NUM");
+
+ label = udev_device_get_property_value(device, "OFONO_LABEL");
+ if (!label)
+ label = udev_device_get_property_value(usb_interface,
+ "OFONO_LABEL");
+ } else {
+ devnode = NULL;
+ interface = udev_device_get_property_value(device,
+ "INTERFACE");
+ number = NULL;
+ label = NULL;
+ }
/* If environment variable is not set, get value from attributes (or parent's ones) */
if (number == NULL) {
@@ -1660,11 +1704,6 @@
}
}
- label = udev_device_get_property_value(device, "OFONO_LABEL");
- if (!label)
- label = udev_device_get_property_value(usb_interface,
- "OFONO_LABEL");
-
subsystem = udev_device_get_subsystem(device);
|
[-]
[+]
|
Changed |
_service:tar_git:ofono-1.31+pp1.tar.bz2/ofono/src/gprs.c
^
|
@@ -1263,7 +1263,6 @@
{
struct pri_context *pri_ctx = data;
struct ofono_gprs_context *gc = pri_ctx->context_driver;
- struct ofono_gprs *gprs = pri_ctx->gprs;
DBusConnection *conn = ofono_dbus_get_connection();
dbus_bool_t value;
@@ -1288,19 +1287,11 @@
value = pri_ctx->active;
- gprs->flags &= ~GPRS_FLAG_ATTACHING;
-
- gprs->driver_attached = TRUE;
- gprs_set_attached_property(gprs, TRUE);
+ gprs_set_attached_property(pri_ctx->gprs, TRUE);
ofono_dbus_signal_property_changed(conn, pri_ctx->path,
OFONO_CONNECTION_CONTEXT_INTERFACE,
"Active", DBUS_TYPE_BOOLEAN, &value);
-
- if (gprs->flags & GPRS_FLAG_RECHECK) {
- gprs->flags &= ~GPRS_FLAG_RECHECK;
- gprs_netreg_update(gprs);
- }
}
static DBusMessage *pri_set_apn(struct pri_context *ctx, DBusConnection *conn,
@@ -1948,6 +1939,27 @@
return FALSE;
}
+static gboolean have_detachable_active_contexts(struct ofono_gprs *gprs)
+{
+ GSList *l;
+
+ for (l = gprs->contexts; l; l = l->next) {
+ struct pri_context *ctx;
+ struct ofono_gprs_context *gc;
+
+ ctx = l->data;
+ gc = ctx->context_driver;
+
+ if (!gc || !gc->driver->detach_shutdown)
+ continue;
+
+ if (ctx->active == TRUE)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
#ifdef SAILFISH_OS
static bool have_read_settings(struct ofono_gprs *gprs)
{
@@ -1977,7 +1989,7 @@
"Active", DBUS_TYPE_BOOLEAN, &value);
}
-static void release_active_contexts(struct ofono_gprs *gprs)
+static void detach_active_contexts(struct ofono_gprs *gprs)
{
GSList *l;
struct pri_context *ctx;
@@ -2006,6 +2018,15 @@
}
}
+static gboolean on_lte(struct ofono_gprs *gprs)
+{
+ if (ofono_netreg_get_technology(gprs->netreg) ==
+ ACCESS_TECHNOLOGY_EUTRAN && have_read_settings(gprs))
+ return TRUE;
+
+ return FALSE;
+}
+
static void gprs_set_attached(struct ofono_gprs *gprs, ofono_bool_t attached)
{
if (attached == gprs->attached)
@@ -2016,21 +2037,27 @@
* at driver level. "Attached" = TRUE property can't be signalled to
* the applications registered on GPRS properties.
* Active contexts have to be release at driver level.
+ *
+ * Skip that for LTE since the condition to be attached on LTE
+ * is that a context gets activated
*/
- if (attached == FALSE) {
- release_active_contexts(gprs);
- gprs->bearer = -1;
- } else if (have_active_contexts(gprs) == TRUE) {
- /*
- * Some times the context activates after a detach event and
- * right before an attach. We close it to avoid unexpected open
- * contexts.
- */
- release_active_contexts(gprs);
- gprs->flags |= GPRS_FLAG_ATTACHED_UPDATE;
- return;
+ if (have_detachable_active_contexts(gprs) && !on_lte(gprs)) {
+ detach_active_contexts(gprs);
+
+ if (attached == TRUE) {
+ /*
+ * Some times the context activates after a detach event
+ * and right before an attach. We close it to avoid
+ * unexpected open contexts.
+ */
+ gprs->flags |= GPRS_FLAG_ATTACHED_UPDATE;
+ return;
+ }
}
+ if (attached == FALSE)
+ gprs->bearer = -1;
+
gprs_set_attached_property(gprs, attached);
}
@@ -2143,14 +2170,19 @@
* context activation if Attached stays FALSE.
*/
#ifdef SAILFISH_OS
- if (ofono_netreg_get_technology(gprs->netreg) ==
- ACCESS_TECHNOLOGY_EUTRAN && have_read_settings(gprs))
+ if (on_lte(gprs)) {
/*
* For LTE we set attached status only on successful
* context activation.
+ *
+ * The context could potentially be registered before the
+ * netreg update is received.
*/
return;
#endif
+ gprs_attached_update(gprs);
+ return;
+ }
if (gprs->driver_attached == attach)
return;
@@ -2430,7 +2462,12 @@
struct pri_context *pri_ctx;
struct ofono_gprs_context *gc;
- DBG("");
+ DBG("cid %u", cid);
+
+ if (!__ofono_atom_get_registered(gprs->atom)) {
+ DBG("cid %u activated before atom registered", cid);
+ return;
+ }
if (gprs_cid_taken(gprs, cid)) {
DBG("cid %u already activated", cid);
@@ -2486,14 +2523,6 @@
pri_settings_changed(pri_ctx);
}
- /* Prevent ofono_gprs_status_notify from changing the 'attached'
- * state until after the context has been set to 'active' in
- * the pri_read_settings_callback; this prevents a race where
- * the connection manager sees the modem as attached before there
- * is an active context.
- */
- gprs->flags |= GPRS_FLAG_ATTACHING;
-
gc->driver->read_settings(gc, cid, pri_read_settings_callback, pri_ctx);
}
@@ -3065,6 +3094,15 @@
{
DBG("%s", __ofono_atom_get_path(gprs->atom));
+ /*
+ * In case we are attaching let that finish, it will update to the
+ * correct status. If we fiddle with driver_attach and the
+ * attach fails, the code will invert back the state to attached,
+ * which would leave us in an incorrect state.
+ */
+ if (gprs->flags & GPRS_FLAG_ATTACHING)
+ return;
+
gprs->driver_attached = FALSE;
gprs_attached_update(gprs);
@@ -3084,7 +3122,16 @@
if (status != NETWORK_REGISTRATION_STATUS_REGISTERED &&
status != NETWORK_REGISTRATION_STATUS_ROAMING) {
- gprs_attached_update(gprs);
+ /*
+ * For LTE we attached status reflects successful context
+ * activation.
+ * Since we in gprs_netreg_update not even try to attach
+ * to GPRS if we are running on LTE, we can on some modems
+ * expect the gprs status to be unknown. That must not
|