From b035437293ac46ec477f21c459d2e096dbabf8f4 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 23 Jan 2019 19:15:50 +0100 Subject: [PATCH 001/320] gitignore: unit/test-idmap binary --- ofono/.gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/ofono/.gitignore b/ofono/.gitignore index 1bef6a9b4..6e75fe9f7 100644 --- a/ofono/.gitignore +++ b/ofono/.gitignore @@ -36,7 +36,6 @@ test-driver test-suite.log unit/test-common unit/test-util -unit/test-idmap unit/test-sms unit/test-sms-root unit/test-simutil From 81c3d4a5eaf92b16a5dd401062371408f169500d Mon Sep 17 00:00:00 2001 From: Nandini Rebello Date: Wed, 16 Jan 2019 12:07:17 +0530 Subject: [PATCH 002/320] sim: Sim PIN1 cache upon modem reset/crash Adding SIM PIN caching feature to oFono. oFono now caches the SIM PIN1 type against the ICCID throughout its lifetime in a link list and enters implicitly upon modem reset/crash. Note, that this behavior can violate 3GPP spec 21.111, section 5.3 - User Data stored in ME if that section is interpreted very strictly. However, our interpretation is that firmware resets are allowed, based on historic precedent. Helps in user experience by not barring out cellular services unless pin is entered manually. Handles cases of incorrect pin and sim pin changed externally. Clear cached PIN incase modem disabled manually and selectively when sim is removed. Seperate 'pin_cache_enter_cb' added without dbus calls to handle implict entering of cached pin. For now this behavior is applicable to all modems by default. In the future it may be needed to make this behavior opt in or otherwise configurable. --- ofono/src/ofono.h | 1 + ofono/src/sim.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) diff --git a/ofono/src/ofono.h b/ofono/src/ofono.h index 0d15352ba..f9455a66a 100644 --- a/ofono/src/ofono.h +++ b/ofono/src/ofono.h @@ -428,6 +428,7 @@ const struct sim_aid *__ofono_sim_session_get_aid( struct ofono_sim_aid_session *session); const char *__ofono_sim_get_impi(struct ofono_sim *sim); +void __ofono_sim_clear_cached_pins(struct ofono_sim *sim); #include diff --git a/ofono/src/sim.c b/ofono/src/sim.c index dd2a20287..b978e0014 100644 --- a/ofono/src/sim.c +++ b/ofono/src/sim.c @@ -144,6 +144,11 @@ struct ofono_sim { bool wait_initialized : 1; }; +struct cached_pin { + char *id; + char *pin; +}; + struct msisdn_set_request { struct ofono_sim *sim; int pending; @@ -179,6 +184,8 @@ static void sim_own_numbers_update(struct ofono_sim *sim); static GSList *g_drivers = NULL; +static GSList *cached_pins = NULL; + static const char *sim_passwd_name(enum ofono_sim_password_type type) { return passwd_name[type]; @@ -567,6 +574,68 @@ static DBusMessage *sim_get_properties(DBusConnection *conn, return reply; } +static struct cached_pin *pin_cache_lookup(const char *iccid) +{ + struct cached_pin *c; + GSList *l; + + if (cached_pins == NULL) + return NULL; + + for (l = cached_pins; l; l = l->next) { + c = l->data; + + if (g_strcmp0(iccid, c->id) == 0) + return c; + } + + return NULL; +} + +static void pin_cache_update(const char *iccid, const char *pin) +{ + struct cached_pin *pin_cached = pin_cache_lookup(iccid); + struct cached_pin *cpins; + + if (pin_cached != NULL) { + g_free(pin_cached->pin); + pin_cached->pin = g_strdup(pin); + return; + } + + cpins = g_new0(struct cached_pin, 1); + + cpins->id = g_strdup(iccid); + cpins->pin = g_strdup(pin); + cached_pins = g_slist_prepend(cached_pins, cpins); +} + +static void pin_cache_remove(const char *iccid) +{ + struct cached_pin *pin_cached = pin_cache_lookup(iccid); + + if (pin_cached == NULL) + return; + + cached_pins = g_slist_remove(cached_pins, pin_cached); +} + +static void pin_cache_enter_cb(const struct ofono_error *error, void *data) +{ + struct ofono_sim *sim = data; + + if (error->type != OFONO_ERROR_TYPE_NO_ERROR) { + pin_cache_remove(sim->iccid); + + __ofono_sim_recheck_pin(sim); + + return; + } + + sim->wait_initialized = true; + DBG("Waiting for ofono_sim_initialized_notify"); +} + static void sim_pin_retries_query_cb(const struct ofono_error *error, int retries[OFONO_SIM_PASSWORD_INVALID], void *data) @@ -785,6 +854,11 @@ static void sim_locked_cb(struct ofono_sim *sim, gboolean locked) OFONO_SIM_MANAGER_INTERFACE, "LockedPins", DBUS_TYPE_STRING, &locked_pins); + + /* Cache pin only for SIM PIN type */ + if (g_strcmp0(typestr, "pin") == 0) + pin_cache_update(sim->iccid, pin); + g_strfreev(locked_pins); sim_pin_retries_check(sim); @@ -886,6 +960,14 @@ static DBusMessage *sim_unlock_pin(DBusConnection *conn, DBusMessage *msg, static void sim_change_pin_cb(const struct ofono_error *error, void *data) { struct ofono_sim *sim = data; + const char *typestr; + const char *old; + const char *new; + + dbus_message_get_args(sim->pending, NULL, DBUS_TYPE_STRING, &typestr, + DBUS_TYPE_STRING, &old, + DBUS_TYPE_STRING, &new, + DBUS_TYPE_INVALID); if (error->type != OFONO_ERROR_TYPE_NO_ERROR) { __ofono_dbus_pending_reply(&sim->pending, @@ -896,6 +978,10 @@ static void sim_change_pin_cb(const struct ofono_error *error, void *data) return; } + /* Cache pin only for SIM PIN type */ + if (g_strcmp0(typestr, "pin") == 0) + pin_cache_update(sim->iccid, new); + __ofono_dbus_pending_reply(&sim->pending, dbus_message_new_method_return(sim->pending)); @@ -950,8 +1036,14 @@ static DBusMessage *sim_change_pin(DBusConnection *conn, DBusMessage *msg, static void sim_enter_pin_cb(const struct ofono_error *error, void *data) { struct ofono_sim *sim = data; + const char *typestr; + const char *pin; DBusMessage *reply; + dbus_message_get_args(sim->pending, NULL, DBUS_TYPE_STRING, &typestr, + DBUS_TYPE_STRING, &pin, + DBUS_TYPE_INVALID); + if (error->type != OFONO_ERROR_TYPE_NO_ERROR) reply = __ofono_error_failed(sim->pending); else @@ -963,6 +1055,10 @@ static void sim_enter_pin_cb(const struct ofono_error *error, void *data) if (sim->initialized || error->type != OFONO_ERROR_TYPE_NO_ERROR) goto recheck; + /* Cache pin only for SIM PIN type */ + if (g_strcmp0(typestr, "pin") == 0) + pin_cache_update(sim->iccid, pin); + if (sim->pin_type == OFONO_SIM_PASSWORD_SIM_PIN || sim->pin_type == OFONO_SIM_PASSWORD_SIM_PUK) { sim->wait_initialized = true; @@ -2918,6 +3014,8 @@ void ofono_sim_inserted_notify(struct ofono_sim *sim, ofono_bool_t inserted) sim->pin_retries[OFONO_SIM_PASSWORD_SIM_PIN2] = -1; sim->pin_retries[OFONO_SIM_PASSWORD_SIM_PUK2] = -1; + pin_cache_remove(sim->iccid); + sim_free_state(sim); } } @@ -3191,6 +3289,7 @@ static void sim_pin_query_cb(const struct ofono_error *error, struct ofono_sim *sim = data; DBusConnection *conn = ofono_dbus_get_connection(); const char *path = __ofono_atom_get_path(sim->atom); + struct cached_pin *cpins = pin_cache_lookup(sim->iccid); const char *pin_name; char **locked_pins; gboolean lock_changed; @@ -3235,6 +3334,10 @@ static void sim_pin_query_cb(const struct ofono_error *error, &pin_name); } + if (g_strcmp0(pin_name, "pin") == 0 && cpins != NULL) + sim->driver->send_passwd(sim, cpins->pin, + pin_cache_enter_cb, sim); + switch (pin_type) { case OFONO_SIM_PASSWORD_NONE: case OFONO_SIM_PASSWORD_SIM_PIN2: @@ -3475,6 +3578,14 @@ void ofono_sim_register(struct ofono_sim *sim) __ofono_atom_register(sim->atom, sim_unregister); } +void __ofono_sim_clear_cached_pins(struct ofono_sim *sim) +{ + if (cached_pins == NULL) + return; + + pin_cache_remove(sim->iccid); +} + void ofono_sim_remove(struct ofono_sim *sim) { __ofono_atom_free(sim->atom); From 9867e5359734b552be1df791818a3e577ad286bc Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Wed, 23 Jan 2019 17:46:36 -0600 Subject: [PATCH 003/320] sim: Fix memory leaks introduced by sim pin caching --- ofono/src/sim.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ofono/src/sim.c b/ofono/src/sim.c index b978e0014..eb9beeed0 100644 --- a/ofono/src/sim.c +++ b/ofono/src/sim.c @@ -618,6 +618,10 @@ static void pin_cache_remove(const char *iccid) return; cached_pins = g_slist_remove(cached_pins, pin_cached); + + g_free(pin_cached->pin); + g_free(pin_cached->id); + g_free(pin_cached); } static void pin_cache_enter_cb(const struct ofono_error *error, void *data) From 466f627db86f9148bdb46c63f31dc94c8e0cf189 Mon Sep 17 00:00:00 2001 From: Nandini Rebello Date: Wed, 16 Jan 2019 12:15:31 +0530 Subject: [PATCH 004/320] modem: add support to clear cached pins. If the modem is powered off via D-Bus, clear any cached PINs to make sure that automatic PIN entry behavior is not activated. --- ofono/src/modem.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ofono/src/modem.c b/ofono/src/modem.c index e94adeccb..55ab4168c 100644 --- a/ofono/src/modem.c +++ b/ofono/src/modem.c @@ -1150,6 +1150,9 @@ static DBusMessage *modem_set_property(DBusConnection *conn, if (modem->lockdown) return __ofono_error_access_denied(msg); + if (!powered) + __ofono_sim_clear_cached_pins(modem->sim); + err = set_powered(modem, powered); if (err < 0) { if (err != -EINPROGRESS) From ea6eba778f25fc1d88645d125e3be7eda488d156 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Fri, 1 Feb 2019 22:00:56 +0100 Subject: [PATCH 005/320] test: better help text for dial-number Better help text for "dial-number". Without details, user may be tempted to pass 0|1 (as send-sms uses) or true|false. --- ofono/test/dial-number | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ofono/test/dial-number b/ofono/test/dial-number index fe5adad3c..4c0ee1429 100755 --- a/ofono/test/dial-number +++ b/ofono/test/dial-number @@ -4,7 +4,8 @@ import sys import dbus if (len(sys.argv) < 2): - print("Usage: %s [modem] [hide_callerid]" % (sys.argv[0])) + print("Usage: %s [modem] [enabled|disabled|default]" % (sys.argv[0])) + print("Last argument enables/disables callerid") sys.exit(1) bus = dbus.SystemBus() From df311665cddb1b805b17c6d749b7424a2dd10d19 Mon Sep 17 00:00:00 2001 From: Nicolas Serafini Date: Fri, 25 Jan 2019 13:15:02 +0000 Subject: [PATCH 006/320] qmimodem: Notify when SIM is initialized Since the commit that introduced the notification API of a SIM inserted and initialized I can not unlock the SIM card on a WP7607 modem. The previously mentioned commit: 54d56d763e40bc44c99a9b24aa0477bd373ea085 --- ofono/drivers/qmimodem/sim-legacy.c | 1 + ofono/drivers/qmimodem/sim.c | 1 + 2 files changed, 2 insertions(+) diff --git a/ofono/drivers/qmimodem/sim-legacy.c b/ofono/drivers/qmimodem/sim-legacy.c index af8576935..30eb46134 100644 --- a/ofono/drivers/qmimodem/sim-legacy.c +++ b/ofono/drivers/qmimodem/sim-legacy.c @@ -250,6 +250,7 @@ static void process_uim_state(struct ofono_sim *sim, uint8_t state) switch (state) { case QMI_DMS_UIM_STATE_INIT_COMPLETE: ofono_sim_inserted_notify(sim, TRUE); + ofono_sim_initialized_notify(sim); break; case QMI_DMS_UIM_STATE_INIT_FAILED: case QMI_DMS_UIM_STATE_NOT_PRESENT: diff --git a/ofono/drivers/qmimodem/sim.c b/ofono/drivers/qmimodem/sim.c index 8edabb806..e91c6578a 100644 --- a/ofono/drivers/qmimodem/sim.c +++ b/ofono/drivers/qmimodem/sim.c @@ -791,6 +791,7 @@ static void get_card_status_cb(struct qmi_result *result, void *user_data) break; case 0x01: /* Present */ ofono_sim_inserted_notify(sim, TRUE); + ofono_sim_initialized_notify(sim); break; } } From 24c1d190d1c3de035792a0c6d492783d4bb5dbc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pi=C4=8Dugins=20Arsenijs?= Date: Mon, 4 Feb 2019 22:16:54 +0200 Subject: [PATCH 007/320] sim800: fix typo in model check code Fixing a copy-paste error in SIM800 code that results in a SIM900 modem being detected as a SIM800 modem. --- ofono/plugins/sim900.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/plugins/sim900.c b/ofono/plugins/sim900.c index eeeb248f7..256483ead 100644 --- a/ofono/plugins/sim900.c +++ b/ofono/plugins/sim900.c @@ -115,7 +115,7 @@ static void check_model(gboolean ok, GAtResult *result, gpointer user_data) if (strstr(model, "SIM800")) data->modem_type = SIM800; else if (strstr(model, "SIM900")) - data->modem_type = SIM800; + data->modem_type = SIM900; else data->modem_type = SIMCOM_UNKNOWN; } From 08c225900112cb8476b583a5c8dd322bfc4c4fb6 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 11 Feb 2019 17:51:16 -0600 Subject: [PATCH 008/320] gprs: Let gprs_context interface be settable once This patch allows a driver to set the interface only once, instead of at every context activation. The previous way was originally designed for PPP and RAW_IP based contexts which would have a (potentially) differently named interface after each context activation due to use of TUN/TAP. This also worked for static high-speed interface setups as well, since these usually had a single interface only. For devices that support multiple high-speed interfaces it would be advantageous to have each gprs_context get an interface assignment right in the modem driver and skip having to setup the interface on every activation. --- ofono/src/gprs.c | 70 +++++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/ofono/src/gprs.c b/ofono/src/gprs.c index 4ef44e7c9..31e273cda 100644 --- a/ofono/src/gprs.c +++ b/ofono/src/gprs.c @@ -110,7 +110,6 @@ struct ipv6_settings { }; struct context_settings { - char *interface; struct ipv4_settings *ipv4; struct ipv6_settings *ipv6; }; @@ -121,6 +120,7 @@ struct ofono_gprs_context { ofono_bool_t inuse; const struct ofono_gprs_context_driver *driver; void *driver_data; + char *interface; struct context_settings *settings; struct ofono_atom *atom; }; @@ -361,12 +361,10 @@ static void context_settings_free(struct context_settings *settings) g_free(settings->ipv6); settings->ipv6 = NULL; } - - g_free(settings->interface); - settings->interface = NULL; } static void context_settings_append_ipv4(struct context_settings *settings, + const char *interface, DBusMessageIter *iter) { DBusMessageIter variant; @@ -391,7 +389,7 @@ static void context_settings_append_ipv4(struct context_settings *settings, goto done; ofono_dbus_dict_append(&array, "Interface", - DBUS_TYPE_STRING, &settings->interface); + DBUS_TYPE_STRING, &interface); if (settings->ipv4->proxy) ofono_dbus_dict_append(&array, "Proxy", DBUS_TYPE_STRING, @@ -433,6 +431,7 @@ static void context_settings_append_ipv4(struct context_settings *settings, } static void context_settings_append_ipv4_dict(struct context_settings *settings, + const char *interface, DBusMessageIter *dict) { DBusMessageIter entry; @@ -443,12 +442,13 @@ static void context_settings_append_ipv4_dict(struct context_settings *settings, dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key); - context_settings_append_ipv4(settings, &entry); + context_settings_append_ipv4(settings, interface, &entry); dbus_message_iter_close_container(dict, &entry); } static void context_settings_append_ipv6(struct context_settings *settings, + const char *interface, DBusMessageIter *iter) { DBusMessageIter variant; @@ -472,7 +472,7 @@ static void context_settings_append_ipv6(struct context_settings *settings, goto done; ofono_dbus_dict_append(&array, "Interface", - DBUS_TYPE_STRING, &settings->interface); + DBUS_TYPE_STRING, &interface); if (settings->ipv6->ip) ofono_dbus_dict_append(&array, "Address", DBUS_TYPE_STRING, @@ -503,6 +503,7 @@ static void context_settings_append_ipv6(struct context_settings *settings, } static void context_settings_append_ipv6_dict(struct context_settings *settings, + const char *interface, DBusMessageIter *dict) { DBusMessageIter entry; @@ -513,13 +514,14 @@ static void context_settings_append_ipv6_dict(struct context_settings *settings, dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key); - context_settings_append_ipv6(settings, &entry); + context_settings_append_ipv6(settings, interface, &entry); dbus_message_iter_close_container(dict, &entry); } static void signal_settings(struct pri_context *ctx, const char *prop, - void (*append)(struct context_settings *, DBusMessageIter *)) + void (*append)(struct context_settings *, + const char *, DBusMessageIter *)) { DBusConnection *conn = ofono_dbus_get_connection(); @@ -527,6 +529,7 @@ static void signal_settings(struct pri_context *ctx, const char *prop, DBusMessage *signal; DBusMessageIter iter; struct context_settings *settings; + const char *interface; signal = dbus_message_new_signal(path, OFONO_CONNECTION_CONTEXT_INTERFACE, @@ -538,12 +541,15 @@ static void signal_settings(struct pri_context *ctx, const char *prop, dbus_message_iter_init_append(signal, &iter); dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &prop); - if (ctx->context_driver) + if (ctx->context_driver) { settings = ctx->context_driver->settings; - else + interface = ctx->context_driver->interface; + } else { settings = NULL; + interface = NULL; + } - append(settings, &iter); + append(settings, interface, &iter); g_dbus_send_message(conn, signal); } @@ -781,18 +787,16 @@ static void pri_setproxy(const char *interface, const char *proxy) static void pri_reset_context_settings(struct pri_context *ctx) { struct context_settings *settings; - char *interface; + const char *interface; gboolean signal_ipv4; gboolean signal_ipv6; if (ctx->context_driver == NULL) return; + interface = ctx->context_driver->interface; settings = ctx->context_driver->settings; - interface = settings->interface; - settings->interface = NULL; - signal_ipv4 = settings->ipv4 != NULL; signal_ipv6 = settings->ipv6 != NULL; @@ -809,8 +813,6 @@ static void pri_reset_context_settings(struct pri_context *ctx) } pri_ifupdown(interface, FALSE); - - g_free(interface); } static void pri_update_mms_context_settings(struct pri_context *ctx) @@ -826,10 +828,10 @@ static void pri_update_mms_context_settings(struct pri_context *ctx) DBG("proxy %s port %u", ctx->proxy_host, ctx->proxy_port); - pri_set_ipv4_addr(settings->interface, settings->ipv4->ip); + pri_set_ipv4_addr(gc->interface, settings->ipv4->ip); if (ctx->proxy_host) - pri_setproxy(settings->interface, ctx->proxy_host); + pri_setproxy(gc->interface, ctx->proxy_host); } static gboolean pri_str_changed(const char *val, const char *newval) @@ -1056,6 +1058,7 @@ static void append_context_properties(struct pri_context *ctx, dbus_bool_t value; const char *strvalue; struct context_settings *settings; + const char *interface; ofono_dbus_dict_append(dict, "Name", DBUS_TYPE_STRING, &name); @@ -1092,13 +1095,16 @@ static void append_context_properties(struct pri_context *ctx, DBUS_TYPE_STRING, &strvalue); } - if (ctx->context_driver) + if (ctx->context_driver) { settings = ctx->context_driver->settings; - else + interface = ctx->context_driver->interface; + } else { settings = NULL; + interface = NULL; + } - context_settings_append_ipv4_dict(settings, dict); - context_settings_append_ipv6_dict(settings, dict); + context_settings_append_ipv4_dict(settings, interface, dict); + context_settings_append_ipv6_dict(settings, interface, dict); } static DBusMessage *pri_get_properties(DBusConnection *conn, @@ -1147,8 +1153,8 @@ static void pri_activate_callback(const struct ofono_error *error, void *data) __ofono_dbus_pending_reply(&ctx->pending, dbus_message_new_method_return(ctx->pending)); - if (gc->settings->interface != NULL) { - pri_ifupdown(gc->settings->interface, TRUE); + if (gc->interface != NULL) { + pri_ifupdown(gc->interface, TRUE); if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_MMS && gc->settings->ipv4) @@ -1241,8 +1247,8 @@ static void pri_read_settings_callback(const struct ofono_error *error, pri_ctx->active = TRUE; - if (gc->settings->interface != NULL) { - pri_ifupdown(gc->settings->interface, TRUE); + if (gc->interface != NULL) { + pri_ifupdown(gc->interface, TRUE); pri_context_signal_settings(pri_ctx, gc->settings->ipv4 != NULL, gc->settings->ipv6 != NULL); @@ -1810,7 +1816,7 @@ static gboolean context_dbus_unregister(struct pri_context *ctx) if (ctx->active == TRUE) { const char *interface = - ctx->context_driver->settings->interface; + ctx->context_driver->interface; if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_MMS) pri_set_ipv4_addr(interface, NULL); @@ -3298,10 +3304,8 @@ enum ofono_gprs_context_type ofono_gprs_context_get_type( void ofono_gprs_context_set_interface(struct ofono_gprs_context *gc, const char *interface) { - struct context_settings *settings = gc->settings; - - g_free(settings->interface); - settings->interface = g_strdup(interface); + g_free(gc->interface); + gc->interface = g_strdup(interface); } void ofono_gprs_context_set_ipv4_address(struct ofono_gprs_context *gc, From 5bf4676c3bb7bfe1e30332cd707e94dae9e055ae Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Tue, 12 Feb 2019 17:21:35 +0530 Subject: [PATCH 009/320] udevng: Detect multiple network interfaces for xmm7xxx --- ofono/plugins/udevng.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/ofono/plugins/udevng.c b/ofono/plugins/udevng.c index 2b0524b61..0d6e16ab4 100644 --- a/ofono/plugins/udevng.c +++ b/ofono/plugins/udevng.c @@ -1179,7 +1179,7 @@ static gboolean setup_gemalto(struct modem_info* modem) static gboolean setup_xmm7xxx(struct modem_info *modem) { - const char *mdm = NULL, *net = NULL; + const char *mdm = NULL, *net = NULL, *net2 = NULL, *net3 = NULL; GSList *list; DBG("%s %s %s %s %s %s\n", modem->syspath, modem->devname, @@ -1199,6 +1199,10 @@ static gboolean setup_xmm7xxx(struct modem_info *modem) } 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) { @@ -1219,6 +1223,15 @@ static gboolean setup_xmm7xxx(struct modem_info *modem) ofono_modem_set_string(modem->modem, "Modem", mdm); ofono_modem_set_string(modem->modem, "NetworkInterface", net); + if (net2) + ofono_modem_set_string(modem->modem, "NetworkInterface2", net2); + + 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; } From fff812ce2198cce1de9640828105fd3e62b2fa27 Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Tue, 12 Feb 2019 17:21:35 +0530 Subject: [PATCH 010/320] xmm7modem: Change in xmm7mode plugin for multiple PDP Made changes in xmm7modem plugin to allow mutiple PDP context activation and to assign correct network interface to the activated PDP context. --- ofono/plugins/xmm7xxx.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/ofono/plugins/xmm7xxx.c b/ofono/plugins/xmm7xxx.c index 237c62cc2..90e52fbbb 100644 --- a/ofono/plugins/xmm7xxx.c +++ b/ofono/plugins/xmm7xxx.c @@ -1269,6 +1269,7 @@ static void xmm7xxx_post_online(struct ofono_modem *modem) struct xmm7xxx_data *data = ofono_modem_get_data(modem); struct ofono_gprs *gprs; struct ofono_gprs_context *gc; + const char *interface = NULL; DBG("%p", modem); @@ -1276,11 +1277,39 @@ static void xmm7xxx_post_online(struct ofono_modem *modem) gprs = ofono_gprs_create(modem, OFONO_VENDOR_IFX, "atmodem", data->chat); + + interface = ofono_modem_get_string(modem, "NetworkInterface"); gc = ofono_gprs_context_create(modem, OFONO_VENDOR_XMM, "ifxmodem", data->chat); - if (gprs && gc) + if (gprs && gc) { ofono_gprs_add_context(gprs, gc); + ofono_gprs_context_set_interface(gc, interface); + } + + interface = ofono_modem_get_string(modem, "NetworkInterface2"); + + if (interface) { + gc = ofono_gprs_context_create(modem, OFONO_VENDOR_XMM, + "ifxmodem", data->chat); + + if (gprs && gc) { + ofono_gprs_add_context(gprs, gc); + ofono_gprs_context_set_interface(gc, interface); + } + } + + interface = ofono_modem_get_string(modem, "NetworkInterface3"); + + if (interface) { + gc = ofono_gprs_context_create(modem, OFONO_VENDOR_XMM, + "ifxmodem", data->chat); + + if (gprs && gc) { + ofono_gprs_add_context(gprs, gc); + ofono_gprs_context_set_interface(gc, interface); + } + } ofono_ims_create(modem, "xmm7modem", data->chat); ofono_netmon_create(modem, 0, "xmm7modem", data->chat); From ec919547e0fdb752a87487428ba440a2c22dcc29 Mon Sep 17 00:00:00 2001 From: Christophe Ronco Date: Fri, 15 Feb 2019 15:37:24 +0100 Subject: [PATCH 011/320] qmi: support sim hotplug Use card status indication to detect SIM removal and insertions --- ofono/drivers/qmimodem/sim.c | 44 ++++++++++++++++++++++++++++++++---- ofono/drivers/qmimodem/uim.h | 2 +- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/ofono/drivers/qmimodem/sim.c b/ofono/drivers/qmimodem/sim.c index e91c6578a..b96f8efb9 100644 --- a/ofono/drivers/qmimodem/sim.c +++ b/ofono/drivers/qmimodem/sim.c @@ -524,7 +524,7 @@ static bool get_card_status(const struct qmi_uim_slot_info *slot, return need_retry; } -static enum get_card_status_result handle_get_card_status_result( +static enum get_card_status_result handle_get_card_status_data( struct qmi_result *result, struct sim_status *sim_stat) { const void *ptr; @@ -533,9 +533,6 @@ static enum get_card_status_result handle_get_card_status_result( uint8_t i; enum get_card_status_result res = GET_CARD_STATUS_RESULT_ERROR; - if (qmi_result_set_error(result, NULL)) - goto done; - ptr = qmi_result_get(result, QMI_UIM_RESULT_CARD_STATUS, &len); if (!ptr) goto done; @@ -578,6 +575,15 @@ static enum get_card_status_result handle_get_card_status_result( return res; } +static enum get_card_status_result handle_get_card_status_result( + struct qmi_result *result, struct sim_status *sim_stat) +{ + if (qmi_result_set_error(result, NULL)) + return GET_CARD_STATUS_RESULT_ERROR; + + return handle_get_card_status_data(result, sim_stat); +} + static gboolean query_passwd_state_retry(gpointer userdata) { struct cb_data *cbd = userdata; @@ -796,6 +802,33 @@ static void get_card_status_cb(struct qmi_result *result, void *user_data) } } +static void card_status_notify(struct qmi_result *result, void *user_data) +{ + struct ofono_sim *sim = user_data; + struct sim_data *data = ofono_sim_get_data(sim); + struct sim_status sim_stat; + + DBG(""); + + if (handle_get_card_status_data(result, &sim_stat) != + GET_CARD_STATUS_RESULT_OK) { + data->app_type = 0; /* Unknown */ + sim_stat.card_state = 0x00; /* Absent */ + } else { + data->app_type = sim_stat.app_type; + } + + switch (sim_stat.card_state) { + case 0x00: /* Absent */ + case 0x02: /* Error */ + ofono_sim_inserted_notify(sim, FALSE); + break; + case 0x01: /* Present */ + ofono_sim_inserted_notify(sim, TRUE); + break; + } +} + static void event_registration_cb(struct qmi_result *result, void *user_data) { struct ofono_sim *sim = user_data; @@ -811,6 +844,9 @@ static void event_registration_cb(struct qmi_result *result, void *user_data) goto error; DBG("event mask 0x%04x", data->event_mask); + if (data->event_mask & 0x0001) + qmi_service_register(data->uim, QMI_UIM_GET_CARD_STATUS_EVENT, + card_status_notify, sim, NULL); if (qmi_service_send(data->uim, QMI_UIM_GET_CARD_STATUS, NULL, get_card_status_cb, sim, NULL) > 0) diff --git a/ofono/drivers/qmimodem/uim.h b/ofono/drivers/qmimodem/uim.h index cd10e684b..9003aba30 100644 --- a/ofono/drivers/qmimodem/uim.h +++ b/ofono/drivers/qmimodem/uim.h @@ -29,7 +29,7 @@ #define QMI_UIM_EVENT_REGISTRATION 46 /* Register for indications */ #define QMI_UIM_GET_CARD_STATUS 47 /* Get card status */ - +#define QMI_UIM_GET_CARD_STATUS_EVENT 50 /* Card status indication */ /* Register for indications */ #define QMI_UIM_PARAM_EVENT_MASK 0x01 /* uint32 */ From 832fb596454b8d21a31d19fceb301023ee4c387c Mon Sep 17 00:00:00 2001 From: Philippe De Swert Date: Fri, 15 Feb 2019 14:11:41 +0200 Subject: [PATCH 012/320] common: Add new NB-IoT technologies Add lte-cat-m1 and lte-cat-nb1 technology identifiers. --- ofono/include/types.h | 4 +++- ofono/src/common.c | 6 ++++++ ofono/src/common.h | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/ofono/include/types.h b/ofono/include/types.h index fc2021630..0cb4d1031 100644 --- a/ofono/include/types.h +++ b/ofono/include/types.h @@ -55,7 +55,9 @@ enum ofono_access_technology { OFONO_ACCESS_TECHNOLOGY_UTRAN_HSDPA = 4, OFONO_ACCESS_TECHNOLOGY_UTRAN_HSUPA = 5, OFONO_ACCESS_TECHNOLOGY_UTRAN_HSDPA_HSUPA = 6, - OFONO_ACCESS_TECHNOLOGY_EUTRAN = 7 + OFONO_ACCESS_TECHNOLOGY_EUTRAN = 7, + OFONO_ACCESS_TECHNOLOGY_NB_IOT_M1 = 8, + OFONO_ACCESS_TECHNOLOGY_NB_IOT_NB1 = 9 }; /* 27.007 Section 6.2 */ diff --git a/ofono/src/common.c b/ofono/src/common.c index a92d6d24c..68721d8b4 100644 --- a/ofono/src/common.c +++ b/ofono/src/common.c @@ -706,8 +706,14 @@ const char *registration_tech_to_string(enum ofono_access_technology tech) return "hspa"; case ACCESS_TECHNOLOGY_EUTRAN: return "lte"; + case ACCESS_TECHNOLOGY_NB_IOT_M1: + return "lte-cat-m1"; + case ACCESS_TECHNOLOGY_NB_IOT_NB1: + return "lte-cat-nb1"; case OFONO_ACCESS_TECHNOLOGY_NONE: break; + default: + return ""; } return ""; } diff --git a/ofono/src/common.h b/ofono/src/common.h index 0e6ebbd03..08673e6f0 100644 --- a/ofono/src/common.h +++ b/ofono/src/common.h @@ -42,6 +42,10 @@ OFONO_ACCESS_TECHNOLOGY_UTRAN_HSDPA_HSUPA /* 6 */ #define ACCESS_TECHNOLOGY_EUTRAN \ OFONO_ACCESS_TECHNOLOGY_EUTRAN /* 7 */ +#define ACCESS_TECHNOLOGY_NB_IOT_M1 \ + OFONO_ACCESS_TECHNOLOGY_NB_IOT_M1 /* 8 */ +#define ACCESS_TECHNOLOGY_NB_IOT_NB1 \ + OFONO_ACCESS_TECHNOLOGY_NB_IOT_NB1 /* 9 */ /* 27.007 Section 7.2 */ #define NETWORK_REGISTRATION_STATUS_NOT_REGISTERED \ From 8b92f972db8f15c8b4f16feaeb78d2a0844f02c0 Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Fri, 15 Feb 2019 17:12:51 +0530 Subject: [PATCH 013/320] gprs-context: adding get function for network interface Added declaration of get function to get network interface for gprs-context --- ofono/include/gprs-context.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ofono/include/gprs-context.h b/ofono/include/gprs-context.h index b77826221..b733d25da 100644 --- a/ofono/include/gprs-context.h +++ b/ofono/include/gprs-context.h @@ -93,6 +93,8 @@ void ofono_gprs_context_set_type(struct ofono_gprs_context *gc, enum ofono_gprs_context_type ofono_gprs_context_get_type( struct ofono_gprs_context *gc); +const char *ofono_gprs_context_get_interface(struct ofono_gprs_context *gc); + void ofono_gprs_context_set_interface(struct ofono_gprs_context *gc, const char *interface); From 0ae08603e8449da2ce946aea9d9ebdfcbbae4408 Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Fri, 15 Feb 2019 17:37:15 +0530 Subject: [PATCH 014/320] gprs-context: Adding get function for inteface Added definition of get function to get interface value in gprs-context --- ofono/src/gprs.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ofono/src/gprs.c b/ofono/src/gprs.c index 31e273cda..9b6d6485b 100644 --- a/ofono/src/gprs.c +++ b/ofono/src/gprs.c @@ -3301,6 +3301,11 @@ enum ofono_gprs_context_type ofono_gprs_context_get_type( return gc->type; } +const char *ofono_gprs_context_get_interface(struct ofono_gprs_context *gc) +{ + return gc->interface; +} + void ofono_gprs_context_set_interface(struct ofono_gprs_context *gc, const char *interface) { From ecc0ad97e74ed4bf4172adfa64deb05b47914e1f Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Wed, 27 Feb 2019 15:33:22 +0530 Subject: [PATCH 015/320] xmm7modem: data channel setup for xmm7modem Added the implementation required to setup data channel in ifxmodem gprs-context driver for xmm7modem vendor --- ofono/drivers/ifxmodem/gprs-context.c | 51 ++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/ofono/drivers/ifxmodem/gprs-context.c b/ofono/drivers/ifxmodem/gprs-context.c index 18382ae60..774505d18 100644 --- a/ofono/drivers/ifxmodem/gprs-context.c +++ b/ofono/drivers/ifxmodem/gprs-context.c @@ -260,6 +260,36 @@ static void address_cb(gboolean ok, GAtResult *result, gpointer user_data) failed_setup(gc, NULL, TRUE); } +static void cgdata_cb(gboolean ok, GAtResult *result, gpointer user_data) +{ + struct ofono_gprs_context *gc = user_data; + struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); + + DBG("ok %d", ok); + + if (!ok) { + ofono_error("Failed to establish session"); + failed_setup(gc, result, TRUE); + return; + } + + CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data); +} + +static void get_datapath(struct ofono_modem *modem, const char *interface, + char* datapath) +{ + if (!datapath) + return; + + if (!strcmp(interface, ofono_modem_get_string(modem, "NetworkInterface"))) + sprintf(datapath, "%s0", ofono_modem_get_string(modem, "DataPath")); + else if (!strcmp(interface, ofono_modem_get_string(modem, "NetworkInterface2"))) + sprintf(datapath, "%s1", ofono_modem_get_string(modem, "DataPath")); + else if (!strcmp(interface, ofono_modem_get_string(modem, "NetworkInterface3"))) + sprintf(datapath, "%s2", ofono_modem_get_string(modem, "DataPath")); +} + static void cgcontrdp_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_gprs_context *gc = user_data; @@ -269,8 +299,11 @@ static void cgcontrdp_cb(gboolean ok, GAtResult *result, gpointer user_data) const char *laddrnetmask = NULL; const char *gw = NULL; - const char *interface; const char *dns[3]; + const char *ctrlpath; + char datapath[50]; + char buf[100]; + const char *interface; DBG("ok %d", ok); @@ -327,9 +360,10 @@ static void cgcontrdp_cb(gboolean ok, GAtResult *result, gpointer user_data) DBG("DNS2: %s\n", gcd->dns2); DBG("Gateway: %s\n", gcd->gateway); - interface = ofono_modem_get_string(modem, "NetworkInterface"); + ctrlpath = ofono_modem_get_string(modem, "CtrlPath"); + interface = ofono_gprs_context_get_interface(gc); + get_datapath(modem, interface, datapath); - ofono_gprs_context_set_interface(gc, interface); ofono_gprs_context_set_ipv4_address(gc, gcd->address, TRUE); if (gcd->netmask[0]) @@ -340,7 +374,16 @@ static void cgcontrdp_cb(gboolean ok, GAtResult *result, gpointer user_data) ofono_gprs_context_set_ipv4_dns_servers(gc, dns); - CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data); + sprintf(buf, "AT+XDATACHANNEL=1,1,\"%s\",\"%s\",2,%u", ctrlpath, + datapath, gcd->active_context); + g_at_chat_send(gcd->chat, buf, none_prefix, NULL, NULL, NULL); + sprintf(buf, "AT+CGDATA=\"M-RAW_IP\",%u", gcd->active_context); + + if (g_at_chat_send(gcd->chat, buf, none_prefix, cgdata_cb, + gc, NULL) > 0) + return; + + CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data); } static void ifx_read_settings(struct ofono_gprs_context *gc) From 5dca71e33ab3576ae4ab9ef185db9aab9f7418e8 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 4 Mar 2019 13:34:13 -0600 Subject: [PATCH 016/320] ifxmodem: Clean up the previous commit slightly The if statements were over 80 characters and breaking them up made the code look a bit uglier. So refactor the if statements to just figure out the data path 'n' parameter or return an error. On success, form the datapath string and return it. Also bump the buffer size and use snprintf to be safe(r). --- ofono/drivers/ifxmodem/gprs-context.c | 42 +++++++++++++++++---------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/ofono/drivers/ifxmodem/gprs-context.c b/ofono/drivers/ifxmodem/gprs-context.c index 774505d18..1dc3d452e 100644 --- a/ofono/drivers/ifxmodem/gprs-context.c +++ b/ofono/drivers/ifxmodem/gprs-context.c @@ -276,18 +276,27 @@ static void cgdata_cb(gboolean ok, GAtResult *result, gpointer user_data) CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data); } -static void get_datapath(struct ofono_modem *modem, const char *interface, - char* datapath) +static const char *get_datapath(struct ofono_modem *modem, + const char *interface) { - if (!datapath) - return; + static char datapath[256]; + char n; + + if (!strcmp(interface, + ofono_modem_get_string(modem, "NetworkInterface"))) + n = '0'; + else if (!strcmp(interface, + ofono_modem_get_string(modem, "NetworkInterface2"))) + n = '1'; + else if (!strcmp(interface, + ofono_modem_get_string(modem, "NetworkInterface3"))) + n = '2'; + else + return NULL; - if (!strcmp(interface, ofono_modem_get_string(modem, "NetworkInterface"))) - sprintf(datapath, "%s0", ofono_modem_get_string(modem, "DataPath")); - else if (!strcmp(interface, ofono_modem_get_string(modem, "NetworkInterface2"))) - sprintf(datapath, "%s1", ofono_modem_get_string(modem, "DataPath")); - else if (!strcmp(interface, ofono_modem_get_string(modem, "NetworkInterface3"))) - sprintf(datapath, "%s2", ofono_modem_get_string(modem, "DataPath")); + snprintf(datapath, sizeof(datapath), "%s%c", + ofono_modem_get_string(modem, "DataPath"), n); + return datapath; } static void cgcontrdp_cb(gboolean ok, GAtResult *result, gpointer user_data) @@ -301,8 +310,8 @@ static void cgcontrdp_cb(gboolean ok, GAtResult *result, gpointer user_data) const char *gw = NULL; const char *dns[3]; const char *ctrlpath; - char datapath[50]; - char buf[100]; + const char *datapath; + char buf[512]; const char *interface; DBG("ok %d", ok); @@ -362,7 +371,7 @@ static void cgcontrdp_cb(gboolean ok, GAtResult *result, gpointer user_data) ctrlpath = ofono_modem_get_string(modem, "CtrlPath"); interface = ofono_gprs_context_get_interface(gc); - get_datapath(modem, interface, datapath); + datapath = get_datapath(modem, interface); ofono_gprs_context_set_ipv4_address(gc, gcd->address, TRUE); @@ -374,10 +383,11 @@ static void cgcontrdp_cb(gboolean ok, GAtResult *result, gpointer user_data) ofono_gprs_context_set_ipv4_dns_servers(gc, dns); - sprintf(buf, "AT+XDATACHANNEL=1,1,\"%s\",\"%s\",2,%u", ctrlpath, - datapath, gcd->active_context); + snprintf(buf, sizeof(buf), "AT+XDATACHANNEL=1,1,\"%s\",\"%s\",2,%u", + ctrlpath, datapath, gcd->active_context); g_at_chat_send(gcd->chat, buf, none_prefix, NULL, NULL, NULL); - sprintf(buf, "AT+CGDATA=\"M-RAW_IP\",%u", gcd->active_context); + snprintf(buf, sizeof(buf), "AT+CGDATA=\"M-RAW_IP\",%u", + gcd->active_context); if (g_at_chat_send(gcd->chat, buf, none_prefix, cgdata_cb, gc, NULL) > 0) From 80c182332bf10ae79169d0800349815f2bb4dade Mon Sep 17 00:00:00 2001 From: Anirudh Gargi Date: Thu, 7 Mar 2019 10:53:38 +0530 Subject: [PATCH 017/320] sim: fix segfault in sim atom While adding the sim pin cache feature, pin_name could cause issue in cases when sim pin is not there. log: ofonod[27810]: drivers/atmodem/sim.c:at_cpin_cb() crsm_pin_cb: READY ofonod[27810]: src/sim.c:sim_pin_query_cb() sim->pin_type: 0, pin_type: 0 ofonod[27810]: Aborting (signal 11) [./src/ofonod] ofonod[27810]: ++++++++ backtrace ++++++++ ofonod[27810]: #0 0x7fb7a7586cb0 in /lib/x86_64-linux-gnu/libc.so.6 ofonod[27810]: #1 0x7fb7a7693cd8 in /lib/x86_64-linux-gnu/libc.so.6 ofonod[27810]: #2 0x4d899b in sim_pin_query_cb() at src/sim.c:3174 ofonod[27810]: #3 0x4649e7 in at_cpin_cb() at drivers/atmodem/sim.c:1304 ofonod[27810]: #4 0x4a5d70 in at_chat_finish_command() at gatchat/gatchat.c:462 --- ofono/src/sim.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ofono/src/sim.c b/ofono/src/sim.c index eb9beeed0..e3b792bbb 100644 --- a/ofono/src/sim.c +++ b/ofono/src/sim.c @@ -3294,7 +3294,7 @@ static void sim_pin_query_cb(const struct ofono_error *error, DBusConnection *conn = ofono_dbus_get_connection(); const char *path = __ofono_atom_get_path(sim->atom); struct cached_pin *cpins = pin_cache_lookup(sim->iccid); - const char *pin_name; + const char *pin_name = sim_passwd_name(pin_type); char **locked_pins; gboolean lock_changed; @@ -3307,7 +3307,6 @@ static void sim_pin_query_cb(const struct ofono_error *error, if (sim->pin_type != pin_type) { sim->pin_type = pin_type; - pin_name = sim_passwd_name(pin_type); if (pin_type != OFONO_SIM_PASSWORD_NONE && password_is_pin(pin_type) == FALSE) From 1b4d1988a8b242c18268e6ba7b889c9076f565ba Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Tue, 12 Mar 2019 12:09:55 +0100 Subject: [PATCH 018/320] Fix whitespace weirdness --- ofono/drivers/atmodem/network-registration.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ofono/drivers/atmodem/network-registration.c b/ofono/drivers/atmodem/network-registration.c index 2482dfc3a..331b60470 100644 --- a/ofono/drivers/atmodem/network-registration.c +++ b/ofono/drivers/atmodem/network-registration.c @@ -1559,12 +1559,12 @@ static void creg_notify(GAtResult *result, gpointer user_data) option_query_tech_cb, tq, g_free) > 0) return; break; - case OFONO_VENDOR_GEMALTO: - if (g_at_chat_send(nd->chat, "AT^SMONI", - smoni_prefix, - gemalto_query_tech_cb, tq, g_free) > 0) - return; - break; + case OFONO_VENDOR_GEMALTO: + if (g_at_chat_send(nd->chat, "AT^SMONI", + smoni_prefix, + gemalto_query_tech_cb, tq, g_free) > 0) + return; + break; } g_free(tq); From 21170c9a87b5b32c3f70a6277476b99c8ce205a0 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Tue, 12 Mar 2019 12:09:56 +0100 Subject: [PATCH 019/320] atmodem: drop vendor type for Toby L2 model The 'Toby L2'-specific vendor type is used only to prevent the CMER command from attempting to set mode '3'. For all u-blox models, mode '3' is just an alias for mode '1'. As such, mode '1' can be used in place of mode '3', removing the model-specific quirk in favour of a vendor-specific quirk. With this change, the L2-specific vendor type is no longer needed. --- ofono/drivers/atmodem/gprs.c | 1 - ofono/drivers/atmodem/network-registration.c | 7 +++++-- ofono/drivers/atmodem/sim.c | 1 - 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/ofono/drivers/atmodem/gprs.c b/ofono/drivers/atmodem/gprs.c index de7c78640..d3fd893cc 100644 --- a/ofono/drivers/atmodem/gprs.c +++ b/ofono/drivers/atmodem/gprs.c @@ -455,7 +455,6 @@ static void gprs_initialized(gboolean ok, GAtResult *result, gpointer user_data) FALSE, gprs, NULL); break; case OFONO_VENDOR_UBLOX: - case OFONO_VENDOR_UBLOX_TOBY_L2: g_at_chat_register(gd->chat, "+UREG:", ublox_ureg_notify, FALSE, gprs, NULL); g_at_chat_send(gd->chat, "AT+UREG=1", none_prefix, diff --git a/ofono/drivers/atmodem/network-registration.c b/ofono/drivers/atmodem/network-registration.c index 331b60470..67380b733 100644 --- a/ofono/drivers/atmodem/network-registration.c +++ b/ofono/drivers/atmodem/network-registration.c @@ -1655,8 +1655,11 @@ static ofono_bool_t build_cmer_string(char *buf, int *cmer_opts, DBG(""); switch (nd->vendor) { - case OFONO_VENDOR_UBLOX_TOBY_L2: - /* UBX-13002752 R33: TOBY L2 doesn't support mode 2 and 3 */ + case OFONO_VENDOR_UBLOX: + /* For all u-blox models, mode 3 is equivalent to mode 1; + * since some models do not support setting modes 2 nor 3 + * (see UBX-13002752), we prefer mode 1 for all models. + */ mode = "1"; break; default: diff --git a/ofono/drivers/atmodem/sim.c b/ofono/drivers/atmodem/sim.c index 51f84818e..5f66a09ce 100644 --- a/ofono/drivers/atmodem/sim.c +++ b/ofono/drivers/atmodem/sim.c @@ -1221,7 +1221,6 @@ static void at_pin_retries_query(struct ofono_sim *sim, return; break; case OFONO_VENDOR_UBLOX: - case OFONO_VENDOR_UBLOX_TOBY_L2: if (g_at_chat_send(sd->chat, "AT+UPINCNT", upincnt_prefix, upincnt_cb, cbd, g_free) > 0) return; From c0735b6bd935f8d374ce76c1fb2834e23e8de265 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Tue, 12 Mar 2019 12:09:56 +0100 Subject: [PATCH 020/320] ublox: drop vendor type for Toby L2 model --- ofono/plugins/ublox.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ofono/plugins/ublox.c b/ofono/plugins/ublox.c index 2b3fc5ebc..4b9d0410c 100644 --- a/ofono/plugins/ublox.c +++ b/ofono/plugins/ublox.c @@ -169,13 +169,12 @@ static int ublox_enable(struct ofono_modem *modem) */ data->model_id = atoi(model_str); + data->vendor_family = OFONO_VENDOR_UBLOX; + switch (data->model_id) { case SARA_G270: - data->vendor_family = OFONO_VENDOR_UBLOX; - break; case TOBYL2_COMPATIBLE_MODE: case TOBYL2_HIGH_THROUGHPUT_MODE: - data->vendor_family = OFONO_VENDOR_UBLOX_TOBY_L2; break; case TOBYL2_MEDIUM_THROUGHPUT_MODE: DBG("low/medium throughtput profile unsupported"); @@ -189,7 +188,7 @@ static int ublox_enable(struct ofono_modem *modem) if (data->aux == NULL) return -EINVAL; - if (data->vendor_family == OFONO_VENDOR_UBLOX) { + if (data->model_id == SARA_G270) { data->modem = open_device(modem, "Modem", "Modem: "); if (data->modem == NULL) { g_at_chat_unref(data->aux); From 72358f3929d82ca743af3e24ca7b3cbb1cb55e5e Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Tue, 12 Mar 2019 12:09:56 +0100 Subject: [PATCH 021/320] atmodem: Remove TOBY_L2 vendor --- ofono/drivers/atmodem/vendor.h | 1 - 1 file changed, 1 deletion(-) diff --git a/ofono/drivers/atmodem/vendor.h b/ofono/drivers/atmodem/vendor.h index cd70c283b..10c043159 100644 --- a/ofono/drivers/atmodem/vendor.h +++ b/ofono/drivers/atmodem/vendor.h @@ -46,7 +46,6 @@ enum ofono_vendor { OFONO_VENDOR_QUECTEL, OFONO_VENDOR_QUECTEL_M95, OFONO_VENDOR_UBLOX, - OFONO_VENDOR_UBLOX_TOBY_L2, OFONO_VENDOR_XMM, OFONO_VENDOR_GEMALTO, }; From 8ebf632130461ccdaec6e21fd9b602048a6e27dc Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Tue, 12 Mar 2019 12:09:57 +0100 Subject: [PATCH 022/320] ublox: make device selection more flexible Many ublox modems can sit on either the USB bus or talk directly to a UART. The udev plugin mostly takes care of figuring out what ports to talk to and the protocol is common for all devices after that. This patch simplifies the setup a bit: i) There must always be an aux channel for communication with the modem ii) The aux channel may be found behind the string Aux for USB modems or Device for serial modems iii) If the Modem string is set, use it; if not set, assume it's not available. --- ofono/plugins/ublox.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/ofono/plugins/ublox.c b/ofono/plugins/ublox.c index 4b9d0410c..32cf1e619 100644 --- a/ofono/plugins/ublox.c +++ b/ofono/plugins/ublox.c @@ -185,19 +185,18 @@ static int ublox_enable(struct ofono_modem *modem) } data->aux = open_device(modem, "Aux", "Aux: "); - if (data->aux == NULL) - return -EINVAL; - - if (data->model_id == SARA_G270) { - data->modem = open_device(modem, "Modem", "Modem: "); - if (data->modem == NULL) { - g_at_chat_unref(data->aux); - data->aux = NULL; - return -EIO; - } + /* 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: "); + if (data->aux == NULL) + return -EINVAL; + } + data->modem = open_device(modem, "Modem", "Modem: "); + if (data->modem) { g_at_chat_set_slave(data->modem, data->aux); - g_at_chat_send(data->modem, "ATE0 +CMEE=1", none_prefix, NULL, NULL, NULL); From 2be5f2613d3603d99198f5cf0b550311c554f9e9 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Tue, 12 Mar 2019 12:09:58 +0100 Subject: [PATCH 023/320] ublox: create model data structures This sets up some device model data structures and adds some helpers for manipulating them. These data structures are a first step to trying to support the large number of devices that ublox produces with a common driver structure. --- ofono/drivers/ubloxmodem/ubloxmodem.c | 57 +++++++++++++++++++++++++++ ofono/drivers/ubloxmodem/ubloxmodem.h | 14 +++++++ 2 files changed, 71 insertions(+) diff --git a/ofono/drivers/ubloxmodem/ubloxmodem.c b/ofono/drivers/ubloxmodem/ubloxmodem.c index a325b1f08..c60b6d3f6 100644 --- a/ofono/drivers/ubloxmodem/ubloxmodem.c +++ b/ofono/drivers/ubloxmodem/ubloxmodem.c @@ -23,6 +23,8 @@ #include #endif +#include + #include #include @@ -33,6 +35,61 @@ #include "ubloxmodem.h" +const struct ublox_model ublox_models[] = { + { + .name = "SARA-G270", + }, + /* TOBY L2 series */ + { + .name = "TOBY-L200", + .flags = UBLOX_F_TOBY_L2, + }, + { + .name = "TOBY-L201", + .flags = UBLOX_F_TOBY_L2, + }, + { + .name = "TOBY-L210", + .flags = UBLOX_F_TOBY_L2, + }, + { + .name = "TOBY-L220", + .flags = UBLOX_F_TOBY_L2, + }, + { + .name = "TOBY-L280", + .flags = UBLOX_F_TOBY_L2, + }, + { /* sentinel */ }, +}; + +const struct ublox_model *ublox_model_from_name(const char *name) +{ + const struct ublox_model *m; + + for (m = ublox_models; m->name; m++) { + if (!strcmp(name, m->name)) + return m; + } + + return NULL; +} + +const struct ublox_model *ublox_model_from_id(int id) +{ + return ublox_models + id; +} + +int ublox_model_to_id(const struct ublox_model *model) +{ + return model - ublox_models; +} + +int ublox_is_toby_l2(const struct ublox_model *model) +{ + return model->flags & UBLOX_F_TOBY_L2; +} + static int ubloxmodem_init(void) { ublox_gprs_context_init(); diff --git a/ofono/drivers/ubloxmodem/ubloxmodem.h b/ofono/drivers/ubloxmodem/ubloxmodem.h index bfb010647..7c7b159a7 100644 --- a/ofono/drivers/ubloxmodem/ubloxmodem.h +++ b/ofono/drivers/ubloxmodem/ubloxmodem.h @@ -23,6 +23,20 @@ #define UBLOXMODEM "ubloxmodem" +enum ublox_flags { + UBLOX_F_TOBY_L2 = (1 << 0), +}; + +struct ublox_model { + char *name; + int flags; +}; + +const struct ublox_model *ublox_model_from_name(const char *name); +const struct ublox_model *ublox_model_from_id(int id); +int ublox_model_to_id(const struct ublox_model *model); +int ublox_is_toby_l2(const struct ublox_model *model); + extern void ublox_gprs_context_init(void); extern void ublox_gprs_context_exit(void); From ef48b951445345b036e68222664bdfaf5f011751 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Wed, 13 Mar 2019 21:23:15 +0100 Subject: [PATCH 024/320] ublox: query device model This patch adds a call to CGMM into the modem_enable path in order to establish the specific device model. From this device model string, a model-specific capabilities structure can be selected. --- ofono/plugins/ublox.c | 107 ++++++++++++++++++++++++++++++------------ 1 file changed, 77 insertions(+), 30 deletions(-) diff --git a/ofono/plugins/ublox.c b/ofono/plugins/ublox.c index 32cf1e619..20e20567d 100644 --- a/ofono/plugins/ublox.c +++ b/ofono/plugins/ublox.c @@ -42,9 +42,10 @@ #include #include -#include #include +#include + static const char *none_prefix[] = { NULL }; enum supported_models { @@ -59,6 +60,8 @@ struct ublox_data { GAtChat *aux; int model_id; enum ofono_vendor vendor_family; + + const struct ublox_model *model; }; static void ublox_debug(const char *str, void *user_data) @@ -152,38 +155,79 @@ static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data) ofono_modem_set_powered(modem, TRUE); } -static int ublox_enable(struct ofono_modem *modem) +static void query_model_cb(gboolean ok, GAtResult *result, gpointer user_data) { + struct ofono_modem *modem = user_data; struct ublox_data *data = ofono_modem_get_data(modem); - const char *model_str = NULL; + struct ofono_error error; + const char *model; + const struct ublox_model *m; + const char *model_str; - DBG("%p", modem); + decode_at_error(&error, g_at_result_final_response(result)); - model_str = ofono_modem_get_string(modem, "Model"); - if (model_str == NULL) - return -EINVAL; + if (!ok) + goto fail; - /* - * Toby L2 devices are more complex and special than previously - * supported U-Blox devices. So they need a vendor of their own. - */ - data->model_id = atoi(model_str); - - data->vendor_family = OFONO_VENDOR_UBLOX; - - switch (data->model_id) { - case SARA_G270: - case TOBYL2_COMPATIBLE_MODE: - case TOBYL2_HIGH_THROUGHPUT_MODE: - break; - case TOBYL2_MEDIUM_THROUGHPUT_MODE: - DBG("low/medium throughtput profile unsupported"); - break; - default: - DBG("unknown ublox model id %d", data->model_id); - return -EINVAL; + if (at_util_parse_attr(result, "", &model) == FALSE) { + ofono_error("Failed to query modem model"); + goto fail; + } + + m = ublox_model_from_name(model); + if (!m) { + ofono_error("Unrecognized model: %s", model); + goto fail; + } + + data->model = m; + + DBG("Model: %s", data->model->name); + + if (data->model->flags & UBLOX_F_TOBY_L2) { + model_str = ofono_modem_get_string(modem, "Model"); + if (!model_str) + goto fail; + + /* + * Toby L2 devices are more complex and special than previously + * supported U-Blox devices. So they need a vendor of their own. + */ + data->model_id = strtoul(model_str, NULL, 10); + + switch (data->model_id) { + case TOBYL2_COMPATIBLE_MODE: + case TOBYL2_HIGH_THROUGHPUT_MODE: + break; + case TOBYL2_MEDIUM_THROUGHPUT_MODE: + DBG("low/medium throughtput profile unsupported"); + break; + default: + DBG("unknown ublox model id %d", data->model_id); + goto fail; + } + } else { + data->vendor_family = OFONO_VENDOR_UBLOX; } + if (g_at_chat_send(data->aux, "AT+CFUN=4", none_prefix, + cfun_enable, modem, NULL)) + 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); +} + +static int ublox_enable(struct ofono_modem *modem) +{ + struct ublox_data *data = ofono_modem_get_data(modem); + + DBG("%p", modem); + data->aux = open_device(modem, "Aux", "Aux: "); /* If this is a serial modem then the device may be behind * the 'Device' attribute instead... @@ -199,7 +243,6 @@ static int ublox_enable(struct ofono_modem *modem) g_at_chat_set_slave(data->modem, data->aux); g_at_chat_send(data->modem, "ATE0 +CMEE=1", none_prefix, NULL, NULL, NULL); - g_at_chat_send(data->modem, "AT&C0", NULL, NULL, NULL, NULL); } @@ -209,10 +252,14 @@ static int ublox_enable(struct ofono_modem *modem) g_at_chat_send(data->aux, "ATE0 +CMEE=1", none_prefix, NULL, NULL, NULL); - g_at_chat_send(data->aux, "AT+CFUN=4", none_prefix, - cfun_enable, modem, NULL); + if (g_at_chat_send(data->aux, "AT+CGMM", NULL, + query_model_cb, modem, NULL) > 0) + return -EINPROGRESS; - return -EINPROGRESS; + g_at_chat_unref(data->aux); + data->aux = NULL; + + return -EINVAL; } static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data) From d9216386c481514cd1b4f2f0e9988d6ce37e98e6 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Wed, 13 Mar 2019 21:23:16 +0100 Subject: [PATCH 025/320] ublox: add model flag HAVE_USBCONF This flag should be set on devices that support multiple USB profiles and will be used to determine whether or not querying USB profiles is appropriate/necessary. --- ofono/drivers/ubloxmodem/ubloxmodem.c | 10 +++++----- ofono/drivers/ubloxmodem/ubloxmodem.h | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/ofono/drivers/ubloxmodem/ubloxmodem.c b/ofono/drivers/ubloxmodem/ubloxmodem.c index c60b6d3f6..0630fcdfa 100644 --- a/ofono/drivers/ubloxmodem/ubloxmodem.c +++ b/ofono/drivers/ubloxmodem/ubloxmodem.c @@ -42,23 +42,23 @@ const struct ublox_model ublox_models[] = { /* TOBY L2 series */ { .name = "TOBY-L200", - .flags = UBLOX_F_TOBY_L2, + .flags = UBLOX_F_TOBY_L2|UBLOX_F_HAVE_USBCONF, }, { .name = "TOBY-L201", - .flags = UBLOX_F_TOBY_L2, + .flags = UBLOX_F_TOBY_L2|UBLOX_F_HAVE_USBCONF, }, { .name = "TOBY-L210", - .flags = UBLOX_F_TOBY_L2, + .flags = UBLOX_F_TOBY_L2|UBLOX_F_HAVE_USBCONF, }, { .name = "TOBY-L220", - .flags = UBLOX_F_TOBY_L2, + .flags = UBLOX_F_TOBY_L2|UBLOX_F_HAVE_USBCONF, }, { .name = "TOBY-L280", - .flags = UBLOX_F_TOBY_L2, + .flags = UBLOX_F_TOBY_L2|UBLOX_F_HAVE_USBCONF, }, { /* sentinel */ }, }; diff --git a/ofono/drivers/ubloxmodem/ubloxmodem.h b/ofono/drivers/ubloxmodem/ubloxmodem.h index 7c7b159a7..1f5b64933 100644 --- a/ofono/drivers/ubloxmodem/ubloxmodem.h +++ b/ofono/drivers/ubloxmodem/ubloxmodem.h @@ -25,6 +25,7 @@ enum ublox_flags { UBLOX_F_TOBY_L2 = (1 << 0), + UBLOX_F_HAVE_USBCONF = (1 << 2), }; struct ublox_model { From 0fa18575f47e07e46f04097cfd38c206e7a366d1 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Wed, 13 Mar 2019 21:46:57 +0100 Subject: [PATCH 026/320] ublox: query USBCONF for applicable devices The TOBY L2 series of modems presents a number of different configurations with different throughtput characteristics. These configurations are packaged up as USB profiles; moreover, changing the profile actually changes the USB model ID so this is even more like selecting a different "device" altogether. Nonetheless, all we need to know is which profile is selected in order to set things up correctly and this can be queried directly. This patch adds a call to UUSBCONF for applicable modems in order to query the USB configuration to find out which profile is active. --- ofono/plugins/ublox.c | 83 +++++++++++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 23 deletions(-) diff --git a/ofono/plugins/ublox.c b/ofono/plugins/ublox.c index 20e20567d..1a412def7 100644 --- a/ofono/plugins/ublox.c +++ b/ofono/plugins/ublox.c @@ -46,6 +46,7 @@ #include +static const char *uusbconf_prefix[] = { "+UUSBCONF:", NULL }; static const char *none_prefix[] = { NULL }; enum supported_models { @@ -155,6 +156,58 @@ static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data) ofono_modem_set_powered(modem, TRUE); } +static void query_usbconf_cb(gboolean ok, + GAtResult *result, gpointer user_data) +{ + struct ofono_modem *modem = user_data; + struct ublox_data *data = ofono_modem_get_data(modem); + GAtResultIter iter; + int profile; + + if (!ok) { + ofono_error("Unable to query USB configuration"); + goto error; + } + + g_at_result_iter_init(&iter, result); + +retry: + if (!g_at_result_iter_next(&iter, "+UUSBCONF")) { + ofono_error("Unable to query USB configuration"); + goto error; + } + + if (!g_at_result_iter_next_number(&iter, &profile)) + goto retry; + + switch (profile) { + case 0: /* Fairly back compatible */ + case 1: /* Fairly back compatible plus audio */ + data->model_id = TOBYL2_COMPATIBLE_MODE; + break; + case 2: /* Low/medium throughput */ + data->model_id = TOBYL2_MEDIUM_THROUGHPUT_MODE; + break; + case 3: /* High throughput mode */ + data->model_id = TOBYL2_HIGH_THROUGHPUT_MODE; + break; + default: + ofono_error("Unexpected USB profile: %d", profile); + goto error; + } + + if (g_at_chat_send(data->aux, "AT+CFUN=4", none_prefix, + cfun_enable, modem, NULL)) + 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); +} + static void query_model_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_modem *modem = user_data; @@ -162,7 +215,6 @@ static void query_model_cb(gboolean ok, GAtResult *result, gpointer user_data) struct ofono_error error; const char *model; const struct ublox_model *m; - const char *model_str; decode_at_error(&error, g_at_result_final_response(result)); @@ -184,28 +236,13 @@ static void query_model_cb(gboolean ok, GAtResult *result, gpointer user_data) DBG("Model: %s", data->model->name); - if (data->model->flags & UBLOX_F_TOBY_L2) { - model_str = ofono_modem_get_string(modem, "Model"); - if (!model_str) - goto fail; - - /* - * Toby L2 devices are more complex and special than previously - * supported U-Blox devices. So they need a vendor of their own. - */ - data->model_id = strtoul(model_str, NULL, 10); - - switch (data->model_id) { - case TOBYL2_COMPATIBLE_MODE: - case TOBYL2_HIGH_THROUGHPUT_MODE: - break; - case TOBYL2_MEDIUM_THROUGHPUT_MODE: - DBG("low/medium throughtput profile unsupported"); - break; - default: - DBG("unknown ublox model id %d", data->model_id); - goto fail; - } + if (data->model->flags & UBLOX_F_HAVE_USBCONF) { + if (g_at_chat_send(data->aux, "AT+UUSBCONF?", uusbconf_prefix, + query_usbconf_cb, modem, NULL)) + return; + + ofono_error("Unable to query USB configuration"); + goto fail; } else { data->vendor_family = OFONO_VENDOR_UBLOX; } From fd0806fbb8d093a755aee4ccc37e224256bc962d Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Wed, 13 Mar 2019 21:23:18 +0100 Subject: [PATCH 027/320] udevng: ublox: Model string no longer used --- ofono/plugins/udevng.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ofono/plugins/udevng.c b/ofono/plugins/udevng.c index 0d6e16ab4..c626532bc 100644 --- a/ofono/plugins/udevng.c +++ b/ofono/plugins/udevng.c @@ -1111,7 +1111,6 @@ static gboolean setup_ublox(struct modem_info *modem) ofono_modem_set_string(modem->modem, "Aux", aux); ofono_modem_set_string(modem->modem, "Modem", mdm); - ofono_modem_set_string(modem->modem, "Model", modem->model); ofono_modem_set_string(modem->modem, "NetworkInterface", net); return TRUE; From 5598130210de5b66845ba6aaca4d5af389921e47 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Wed, 13 Mar 2019 22:35:56 +0100 Subject: [PATCH 028/320] ublox: add device flags Some aspects of a device are detectable at runtime, like the USB profile detection that was added in a patch preceding this one. This patch switches the driver over from creating a new "vendor id" for each profile to just setting a flag. This is more easily extensible as we detect other features of the modem. --- ofono/plugins/ublox.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/ofono/plugins/ublox.c b/ofono/plugins/ublox.c index 1a412def7..d99f5c45c 100644 --- a/ofono/plugins/ublox.c +++ b/ofono/plugins/ublox.c @@ -49,20 +49,17 @@ static const char *uusbconf_prefix[] = { "+UUSBCONF:", NULL }; static const char *none_prefix[] = { NULL }; -enum supported_models { - SARA_G270 = 1102, - TOBYL2_COMPATIBLE_MODE = 1141, - TOBYL2_MEDIUM_THROUGHPUT_MODE = 1143, - TOBYL2_HIGH_THROUGHPUT_MODE = 1146, +enum ublox_device_flags { + UBLOX_DEVICE_F_HIGH_THROUGHPUT_MODE = (1 << 0), }; struct ublox_data { GAtChat *modem; GAtChat *aux; - int model_id; enum ofono_vendor vendor_family; const struct ublox_model *model; + int flags; }; static void ublox_debug(const char *str, void *user_data) @@ -148,7 +145,7 @@ static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data) return; } - if (data->model_id == TOBYL2_HIGH_THROUGHPUT_MODE) + if (data->flags & UBLOX_DEVICE_F_HIGH_THROUGHPUT_MODE) /* use bridged mode until routed mode support is added */ g_at_chat_send(data->aux, "AT+UBMCONF=2", none_prefix, NULL, NULL, NULL); @@ -183,13 +180,12 @@ static void query_usbconf_cb(gboolean ok, switch (profile) { case 0: /* Fairly back compatible */ case 1: /* Fairly back compatible plus audio */ - data->model_id = TOBYL2_COMPATIBLE_MODE; break; case 2: /* Low/medium throughput */ - data->model_id = TOBYL2_MEDIUM_THROUGHPUT_MODE; - break; + ofono_error("Medium throughput mode not supported"); + goto error; case 3: /* High throughput mode */ - data->model_id = TOBYL2_HIGH_THROUGHPUT_MODE; + data->flags |= UBLOX_DEVICE_F_HIGH_THROUGHPUT_MODE; break; default: ofono_error("Unexpected USB profile: %d", profile); @@ -390,10 +386,10 @@ static void ublox_post_sim(struct ofono_modem *modem) struct ofono_gprs *gprs; struct ofono_gprs_context *gc; GAtChat *chat = data->modem ? data->modem : data->aux; - const char *driver = data->model_id == TOBYL2_HIGH_THROUGHPUT_MODE ? + const char *driver = data->flags & UBLOX_DEVICE_F_HIGH_THROUGHPUT_MODE ? "ubloxmodem" : "atmodem"; /* Toby L2: Create same number of contexts as supported PDP contexts. */ - int ncontexts = data->model_id == TOBYL2_HIGH_THROUGHPUT_MODE ? 8 : 1; + int ncontexts = data->flags & UBLOX_DEVICE_F_HIGH_THROUGHPUT_MODE ? 8 : 1; DBG("%p", modem); From c9a0cd82b2c360d8e33aa45e32bb1929da895a71 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Wed, 13 Mar 2019 22:35:57 +0100 Subject: [PATCH 029/320] ublox: add TOBY L4 models --- ofono/drivers/ubloxmodem/ubloxmodem.c | 22 ++++++++++++++++++++++ ofono/drivers/ubloxmodem/ubloxmodem.h | 2 ++ 2 files changed, 24 insertions(+) diff --git a/ofono/drivers/ubloxmodem/ubloxmodem.c b/ofono/drivers/ubloxmodem/ubloxmodem.c index 0630fcdfa..a52a67ea0 100644 --- a/ofono/drivers/ubloxmodem/ubloxmodem.c +++ b/ofono/drivers/ubloxmodem/ubloxmodem.c @@ -60,6 +60,23 @@ const struct ublox_model ublox_models[] = { .name = "TOBY-L280", .flags = UBLOX_F_TOBY_L2|UBLOX_F_HAVE_USBCONF, }, + /* TOBY L4 series */ + { + .name = "TOBY-L4006", + .flags = UBLOX_F_TOBY_L4, + }, + { + .name = "TOBY-L4106", + .flags = UBLOX_F_TOBY_L4, + }, + { + .name = "TOBY-L4206", + .flags = UBLOX_F_TOBY_L4, + }, + { + .name = "TOBY-L4906", + .flags = UBLOX_F_TOBY_L4, + }, { /* sentinel */ }, }; @@ -90,6 +107,11 @@ int ublox_is_toby_l2(const struct ublox_model *model) return model->flags & UBLOX_F_TOBY_L2; } +int ublox_is_toby_l4(const struct ublox_model *model) +{ + return model->flags & UBLOX_F_TOBY_L4; +} + static int ubloxmodem_init(void) { ublox_gprs_context_init(); diff --git a/ofono/drivers/ubloxmodem/ubloxmodem.h b/ofono/drivers/ubloxmodem/ubloxmodem.h index 1f5b64933..2c5b74336 100644 --- a/ofono/drivers/ubloxmodem/ubloxmodem.h +++ b/ofono/drivers/ubloxmodem/ubloxmodem.h @@ -25,6 +25,7 @@ enum ublox_flags { UBLOX_F_TOBY_L2 = (1 << 0), + UBLOX_F_TOBY_L4 = (1 << 1), UBLOX_F_HAVE_USBCONF = (1 << 2), }; @@ -37,6 +38,7 @@ const struct ublox_model *ublox_model_from_name(const char *name); const struct ublox_model *ublox_model_from_id(int id); int ublox_model_to_id(const struct ublox_model *model); int ublox_is_toby_l2(const struct ublox_model *model); +int ublox_is_toby_l4(const struct ublox_model *model); extern void ublox_gprs_context_init(void); extern void ublox_gprs_context_exit(void); From 485b2b48f4487da62e75f93780016743fe20d722 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Wed, 13 Mar 2019 22:35:58 +0100 Subject: [PATCH 030/320] udevng: detect ublox TOBY L4 ttyACM0 (USB interface 02) is reportedly unreliable (breaking DHCP setup) so the recommended approach is to use ttyACM2 (USB interface 06) exclusively. --- ofono/plugins/udevng.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/ofono/plugins/udevng.c b/ofono/plugins/udevng.c index c626532bc..1c0fb2bd1 100644 --- a/ofono/plugins/udevng.c +++ b/ofono/plugins/udevng.c @@ -1090,11 +1090,17 @@ static gboolean setup_ublox(struct modem_info *modem) * - high throughput profile : 224/1/3 */ } else if (g_strcmp0(info->interface, "2/2/1") == 0) { - if (g_strcmp0(info->number, "02") == 0) - aux = info->devnode; - else if (g_strcmp0(info->number, "00") == 0) + if (!g_strcmp0(modem->model, "1010")) { + if (g_strcmp0(info->number, "06") == 0) + aux = info->devnode; + } else { + if (g_strcmp0(info->number, "02") == 0) + aux = info->devnode; + } + if (g_strcmp0(info->number, "00") == 0) mdm = info->devnode; } else if (g_strcmp0(info->interface, "2/6/0") == 0 || + g_strcmp0(info->interface, "2/13/0") == 0 || g_strcmp0(info->interface, "10/0/0") == 0 || g_strcmp0(info->interface, "224/1/3") == 0) { net = info->devnode; @@ -1690,6 +1696,8 @@ static struct { { "quectelqmi", "qcserial", "2c7c", "0121" }, { "quectelqmi", "qmi_wwan", "2c7c", "0125" }, { "quectelqmi", "qcserial", "2c7c", "0125" }, + { "ublox", "cdc_acm", "1546", "1010" }, + { "ublox", "cdc_ncm", "1546", "1010" }, { "ublox", "cdc_acm", "1546", "1102" }, { "ublox", "rndis_host", "1546", "1146" }, { "ublox", "cdc_acm", "1546", "1146" }, From 8717b529db3e07974a3ffb34233fe8c4b6b238e4 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Wed, 13 Mar 2019 22:35:59 +0100 Subject: [PATCH 031/320] Separate ATE and AT+CMEE commands The TOBY L4 doesn't seem to like seeing these two commands on the same line... --- ofono/plugins/ublox.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ofono/plugins/ublox.c b/ofono/plugins/ublox.c index d99f5c45c..10660ff01 100644 --- a/ofono/plugins/ublox.c +++ b/ofono/plugins/ublox.c @@ -282,7 +282,9 @@ static int ublox_enable(struct ofono_modem *modem) /* 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 +CMEE=1", none_prefix, + 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, From 2992f71d298466785eba0b9a7e84d8eb7ae7da96 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Wed, 13 Mar 2019 22:36:00 +0100 Subject: [PATCH 032/320] ublox: extend LTE driver There are a couple of semi-independent changes here: * use the 'vendor' parameter to pass the modem 'model' * support TOBY L4 modem which uses a fixed CID for configuring the EPS default bearer * add the setup of authentication parameters that was recently added to the atmodem LTE driver --- ofono/drivers/ubloxmodem/lte.c | 101 +++++++++++++++++++++++++++++---- 1 file changed, 89 insertions(+), 12 deletions(-) diff --git a/ofono/drivers/ubloxmodem/lte.c b/ofono/drivers/ubloxmodem/lte.c index 34397dfe1..eb9062d98 100644 --- a/ofono/drivers/ubloxmodem/lte.c +++ b/ofono/drivers/ubloxmodem/lte.c @@ -39,24 +39,85 @@ #include "ubloxmodem.h" -static const char *ucgdflt_prefix[] = { "+UCGDFLT:", NULL }; +static const char *none_prefix[] = { NULL }; struct lte_driver_data { GAtChat *chat; + const struct ublox_model *model; + struct ofono_lte_default_attach_info pending_info; }; -static void ucgdflt_cb(gboolean ok, GAtResult *result, gpointer user_data) +static void at_lte_set_auth_cb(gboolean ok, GAtResult *result, + gpointer user_data) { struct cb_data *cbd = user_data; ofono_lte_cb_t cb = cbd->cb; struct ofono_error error; - DBG("ok %d", ok); - decode_at_error(&error, g_at_result_final_response(result)); cb(&error, cbd->data); } +static void at_lte_set_default_attach_info_cb(gboolean ok, GAtResult *result, + gpointer user_data) +{ + struct cb_data *cbd = user_data; + ofono_lte_cb_t cb = cbd->cb; + void *data = cbd->data; + struct lte_driver_data *ldd = cbd->user; + struct ofono_error error; + char buf[32 + OFONO_GPRS_MAX_USERNAME_LENGTH + + OFONO_GPRS_MAX_PASSWORD_LENGTH + 1]; + enum ofono_gprs_auth_method auth_method; + int cid; + + if (!ok) { + decode_at_error(&error, g_at_result_final_response(result)); + cb(&error, data); + return; + } + + if (ublox_is_toby_l2(ldd->model)) { + /* If CGDCONT has already been used to set up cid 4 then + * the EPS default bearer will be configured from another + * cid (see documentation for how this is selected). Avoid + * doing so as this assumes as much... + */ + cid = 4; + } else if (ublox_is_toby_l4(ldd->model)) { + cid = 1; + } else { + ofono_error("Unknown model; " + "unable to determine EPS default bearer CID"); + goto out; + } + + auth_method = ldd->pending_info.auth_method; + + /* change the authentication method if the parameters are invalid */ + if (!*ldd->pending_info.username || !*ldd->pending_info.password) + auth_method = OFONO_GPRS_AUTH_METHOD_NONE; + + /* In contrast to CGAUTH, all four parameters are _required_ here; + * if auth type is NONE then username and password must be set to + * empty strings. + */ + sprintf(buf, "AT+UAUTHREQ=%d,%d,\"%s\",\"%s\"", + cid, + at_util_gprs_auth_method_to_auth_prot(auth_method), + ldd->pending_info.username, + ldd->pending_info.password); + + cbd = cb_data_ref(cbd); + if (g_at_chat_send(ldd->chat, buf, none_prefix, + at_lte_set_auth_cb, cbd, cb_data_unref) > 0) + return; + +out: + cb_data_unref(cbd); + CALLBACK_WITH_FAILURE(cb, data); +} + static void ublox_lte_set_default_attach_info(const struct ofono_lte *lte, const struct ofono_lte_default_attach_info *info, ofono_lte_cb_t cb, void *data) @@ -67,17 +128,32 @@ static void ublox_lte_set_default_attach_info(const struct ofono_lte *lte, DBG("LTE config with APN: %s", info->apn); - if (strlen(info->apn) > 0) - snprintf(buf, sizeof(buf), "AT+UCGDFLT=0,\"IP\",\"%s\"", + cbd->user = ldd; + memcpy(&ldd->pending_info, info, sizeof(ldd->pending_info)); + + if (ublox_is_toby_l2(ldd->model)) { + if (strlen(info->apn) > 0) + snprintf(buf, sizeof(buf), "AT+UCGDFLT=0,%s,\"%s\"", + at_util_gprs_proto_to_pdp_type(info->proto), + info->apn); + else + snprintf(buf, sizeof(buf), "AT+UCGDFLT=0"); + + } else if (ublox_is_toby_l4(ldd->model)) { + if (strlen(info->apn) > 0) + snprintf(buf, sizeof(buf), "AT+CGDCONT=1,%s,\"%s\"", + at_util_gprs_proto_to_pdp_type(info->proto), info->apn); - else - snprintf(buf, sizeof(buf), "AT+UCGDFLT=0"); + else + snprintf(buf, sizeof(buf), "AT+CGDCONT=1"); + } - /* We can't do much in case of failure so don't check response. */ - if (g_at_chat_send(ldd->chat, buf, ucgdflt_prefix, - ucgdflt_cb, cbd, g_free) > 0) + if (g_at_chat_send(ldd->chat, buf, none_prefix, + at_lte_set_default_attach_info_cb, + cbd, cb_data_unref) > 0) return; + cb_data_unref(cbd); CALLBACK_WITH_FAILURE(cb, data); } @@ -91,7 +167,7 @@ static gboolean lte_delayed_register(gpointer user_data) } static int ublox_lte_probe(struct ofono_lte *lte, - unsigned int vendor, void *data) + unsigned int model_id, void *data) { GAtChat *chat = data; struct lte_driver_data *ldd; @@ -103,6 +179,7 @@ static int ublox_lte_probe(struct ofono_lte *lte, return -ENOMEM; ldd->chat = g_at_chat_clone(chat); + ldd->model = ublox_model_from_id(model_id); ofono_lte_set_data(lte, ldd); From 93d7db91337683de3139c5441e9cbfb78d6d23fe Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Wed, 13 Mar 2019 22:36:01 +0100 Subject: [PATCH 033/320] ublox: pass model id to LTE plugin --- ofono/plugins/ublox.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ofono/plugins/ublox.c b/ofono/plugins/ublox.c index 10660ff01..1c74fe097 100644 --- a/ofono/plugins/ublox.c +++ b/ofono/plugins/ublox.c @@ -408,7 +408,8 @@ static void ublox_post_sim(struct ofono_modem *modem) --ncontexts; } - ofono_lte_create(modem, 0, "ubloxmodem", data->aux); + ofono_lte_create(modem, + ublox_model_to_id(data->model), "ubloxmodem", data->aux); } static void ublox_post_online(struct ofono_modem *modem) From fe212b2418b367cb5ed49740358f189617ce37c6 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Thu, 14 Mar 2019 23:28:39 +0100 Subject: [PATCH 034/320] ublox: gprs-context: take model parameter --- ofono/drivers/ubloxmodem/gprs-context.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ofono/drivers/ubloxmodem/gprs-context.c b/ofono/drivers/ubloxmodem/gprs-context.c index 9c319804f..67e58b76f 100644 --- a/ofono/drivers/ubloxmodem/gprs-context.c +++ b/ofono/drivers/ubloxmodem/gprs-context.c @@ -45,6 +45,7 @@ static const char *cgcontrdp_prefix[] = { "+CGCONTRDP:", NULL }; static const char *uipaddr_prefix[] = { "+UIPADDR:", NULL }; struct gprs_context_data { + const struct ublox_model *model; GAtChat *chat; unsigned int active_context; ofono_gprs_context_cb_t cb; @@ -462,7 +463,7 @@ static void cgev_notify(GAtResult *result, gpointer user_data) } static int ublox_gprs_context_probe(struct ofono_gprs_context *gc, - unsigned int vendor, void *data) + unsigned int model_id, void *data) { GAtChat *chat = data; struct gprs_context_data *gcd; @@ -473,6 +474,10 @@ static int ublox_gprs_context_probe(struct ofono_gprs_context *gc, if (gcd == NULL) return -ENOMEM; + gcd->model = ublox_model_from_id(model_id); + if (!gcd->model) + return -EINVAL; + gcd->chat = g_at_chat_clone(chat); ofono_gprs_context_set_data(gc, gcd); From b745f27ecb80fffafb40e0c1ccf62cd3e68e0422 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Thu, 14 Mar 2019 23:28:40 +0100 Subject: [PATCH 035/320] ublox: pass model_id to gprs-context driver Depending on the transport used on the data connection we want either the "atmodem" (PPP) driver or the "ubloxmodem". For the "ubloxmodem", we want to pass the model data so this patch wrangles some parameters to make sure that right driver and right variant data are passed. --- ofono/plugins/ublox.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/ofono/plugins/ublox.c b/ofono/plugins/ublox.c index 1c74fe097..8100dfba9 100644 --- a/ofono/plugins/ublox.c +++ b/ofono/plugins/ublox.c @@ -388,19 +388,34 @@ static void ublox_post_sim(struct ofono_modem *modem) struct ofono_gprs *gprs; struct ofono_gprs_context *gc; GAtChat *chat = data->modem ? data->modem : data->aux; - const char *driver = data->flags & UBLOX_DEVICE_F_HIGH_THROUGHPUT_MODE ? - "ubloxmodem" : "atmodem"; + const char *driver; /* Toby L2: Create same number of contexts as supported PDP contexts. */ int ncontexts = data->flags & UBLOX_DEVICE_F_HIGH_THROUGHPUT_MODE ? 8 : 1; + int variant; DBG("%p", modem); gprs = ofono_gprs_create(modem, data->vendor_family, "atmodem", data->aux); + if (ublox_is_toby_l4(data->model)) { + driver = "ubloxmodem"; + variant = ublox_model_to_id(data->model); + } else if (ublox_is_toby_l2(data->model)) { + if (data->flags & UBLOX_DEVICE_F_HIGH_THROUGHPUT_MODE) { + driver = "ubloxmodem"; + variant = ublox_model_to_id(data->model); + } else { + driver = "atmodem"; + variant = OFONO_VENDOR_UBLOX; + } + } else { + driver = "atmodem"; + variant = OFONO_VENDOR_UBLOX; + } + while (ncontexts) { - gc = ofono_gprs_context_create(modem, data->vendor_family, - driver, chat); + gc = ofono_gprs_context_create(modem, variant, driver, chat); if (gprs && gc) ofono_gprs_add_context(gprs, gc); From dc81c6e0554853dfd1c3469c10535d750405b3ac Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Thu, 14 Mar 2019 23:28:41 +0100 Subject: [PATCH 036/320] ublox: TOBY L4 supports only router mode The TOBY L4 supports only "router mode" where the modem presents a network interface that one can run a DHCP client against. Behind this interface, the modem takes care of routing packets via NAT by: i) selecting the relevant context based on destination IP ii) using the first activated context as the default route In order to have the connection manager, thus, do the right thing, the context only needs to report itself as being active and with the IP settings set to method "dhcp". There's no need for the connection manager to know details like what IP address the context was assigned. Tested with connman that does the right thing when it finds an active "dhcp" context. --- ofono/drivers/ubloxmodem/gprs-context.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ofono/drivers/ubloxmodem/gprs-context.c b/ofono/drivers/ubloxmodem/gprs-context.c index 67e58b76f..308c5a6a8 100644 --- a/ofono/drivers/ubloxmodem/gprs-context.c +++ b/ofono/drivers/ubloxmodem/gprs-context.c @@ -240,6 +240,15 @@ static void ublox_gprs_read_settings(struct ofono_gprs_context *gc, DBG("cid %u", cid); + if (ublox_is_toby_l4(gcd->model)) { + /* Use DHCP */ + gcd->active_context = cid; + set_gprs_context_interface(gc); + ofono_gprs_context_set_ipv4_address(gc, NULL, 0); + CALLBACK_WITH_SUCCESS(cb, data); + return; + } + gcd->active_context = cid; gcd->cb = cb; gcd->cb_data = data; From 9147fdb3c613db079da983bb375f33e7cf71f42f Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Thu, 14 Mar 2019 23:28:42 +0100 Subject: [PATCH 037/320] ublox: gprs-context: query networking mode for TOBY L2 The TOBY L2 may run in either "bridge" mode or "router" mode. For this model, query the configured mode so that the appropriate settings are communicated when the context is activated. --- ofono/drivers/ubloxmodem/gprs-context.c | 54 ++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/ofono/drivers/ubloxmodem/gprs-context.c b/ofono/drivers/ubloxmodem/gprs-context.c index 308c5a6a8..96ffbf688 100644 --- a/ofono/drivers/ubloxmodem/gprs-context.c +++ b/ofono/drivers/ubloxmodem/gprs-context.c @@ -43,6 +43,12 @@ static const char *none_prefix[] = { NULL }; static const char *cgcontrdp_prefix[] = { "+CGCONTRDP:", NULL }; static const char *uipaddr_prefix[] = { "+UIPADDR:", NULL }; +static const char *ubmconf_prefix[] = { "+UBMCONF:", NULL }; + +enum netmode { + NETWORKING_MODE_ROUTER, + NETWORKING_MODE_BRIDGE, +}; struct gprs_context_data { const struct ublox_model *model; @@ -50,6 +56,7 @@ struct gprs_context_data { unsigned int active_context; ofono_gprs_context_cb_t cb; void *cb_data; + enum netmode networking_mode; }; static void uipaddr_cb(gboolean ok, GAtResult *result, gpointer user_data) @@ -240,7 +247,7 @@ static void ublox_gprs_read_settings(struct ofono_gprs_context *gc, DBG("cid %u", cid); - if (ublox_is_toby_l4(gcd->model)) { + if (gcd->networking_mode == NETWORKING_MODE_ROUTER) { /* Use DHCP */ gcd->active_context = cid; set_gprs_context_interface(gc); @@ -471,6 +478,42 @@ static void cgev_notify(GAtResult *result, gpointer user_data) gcd->active_context = 0; } +static void at_ubmconf_read_cb(gboolean ok, GAtResult *result, + gpointer user_data) +{ + struct ofono_gprs_context *gc = user_data; + struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); + GAtResultIter iter; + int mode; + + if (!ok) + goto error; + + g_at_result_iter_init(&iter, result); + if (!g_at_result_iter_next(&iter, "+UBMCONF:")) + goto error; + + if (!g_at_result_iter_next_number(&iter, &mode)) + goto error; + + switch (mode) { + case 1: + gcd->networking_mode = NETWORKING_MODE_ROUTER; + break; + case 2: + gcd->networking_mode = NETWORKING_MODE_BRIDGE; + break; + default: + goto error; + } + + return; + +error: + ofono_error("AT+UBMCONF? failed; assuming router mode"); + gcd->networking_mode = NETWORKING_MODE_ROUTER; +} + static int ublox_gprs_context_probe(struct ofono_gprs_context *gc, unsigned int model_id, void *data) { @@ -491,6 +534,15 @@ static int ublox_gprs_context_probe(struct ofono_gprs_context *gc, ofono_gprs_context_set_data(gc, gcd); + if (ublox_is_toby_l2(gcd->model)) { + g_at_chat_send(chat, "AT+UBMCONF?", ubmconf_prefix, + at_ubmconf_read_cb, gc, NULL); + } else if (ublox_is_toby_l4(gcd->model)) { + gcd->networking_mode = NETWORKING_MODE_ROUTER; + } else { + gcd->networking_mode = NETWORKING_MODE_ROUTER; + } + g_at_chat_register(chat, "+CGEV:", cgev_notify, FALSE, gc, NULL); return 0; From 086cd89725cba0d7fd3a58e290c98a0cd639b60e Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Thu, 14 Mar 2019 23:28:43 +0100 Subject: [PATCH 038/320] ublox: do not set bridge mode for TOBY L2 Trying to set the networking mode to "bridge" mode in the plugin is bogus because the setting does not apply until after the device has been reset. Instead, the current setting should be queried. If a user wants to set the modem networking mode, the setting should be made outside of ofono. The gprs-context driver has already been adjusted to query the networking mode and to set things up accordingly. --- ofono/plugins/ublox.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ofono/plugins/ublox.c b/ofono/plugins/ublox.c index 8100dfba9..dc0017654 100644 --- a/ofono/plugins/ublox.c +++ b/ofono/plugins/ublox.c @@ -145,11 +145,6 @@ static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data) return; } - if (data->flags & UBLOX_DEVICE_F_HIGH_THROUGHPUT_MODE) - /* use bridged mode until routed mode support is added */ - g_at_chat_send(data->aux, "AT+UBMCONF=2", none_prefix, - NULL, NULL, NULL); - ofono_modem_set_powered(modem, TRUE); } From b2300023f8062bfdaff75fb034fe86065c1bebb3 Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Thu, 28 Mar 2019 17:34:36 +0530 Subject: [PATCH 039/320] doc: Added new properties to SimManager for DSSA Adding two new properties to sim manager interface to handle dual SIM single active use case. CardSlotCount [readonly] Contains the count of number of SIM card slots available. ActiveCardSlot [readwrite] Contains the index of the currently active SIM card slot for dual SIM single active mode. --- ofono/doc/sim-api.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ofono/doc/sim-api.txt b/ofono/doc/sim-api.txt index bce47c121..b1428b10f 100644 --- a/ofono/doc/sim-api.txt +++ b/ofono/doc/sim-api.txt @@ -205,3 +205,15 @@ Properties boolean Present [readonly] Contains the SIM's ImsPrivateIdentity, read from the ISIM. + + uint32 CardSlotCount [readonly, experimental] + + Contains the count of number of SIM card slots available. + + uint32 ActiveCardSlot [readwrite, experimental] + + Contains the index of the currently active SIM card slot + for dual SIM single active mode. + + This property will range from 1 (default) to + CardSlotCount (max) value. From 7cb25afe6b8e90b49e61e926e8864bcf59416e36 Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Thu, 28 Mar 2019 17:35:21 +0530 Subject: [PATCH 040/320] sim: Added set function for CardSlotCount and ActiveCardSlot Adding set function definition for CardSlotCount and ActiveCardSlot properties. --- ofono/include/sim.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/ofono/include/sim.h b/ofono/include/sim.h index 3bce459fa..9f5dee5c4 100644 --- a/ofono/include/sim.h +++ b/ofono/include/sim.h @@ -138,6 +138,10 @@ typedef void (*ofono_sim_close_channel_cb_t)(const struct ofono_error *error, typedef void (*ofono_sim_logical_access_cb_t)(const struct ofono_error *error, const unsigned char *resp, unsigned int len, void *data); +typedef void (*ofono_sim_set_active_card_slot_cb_t)( + const struct ofono_error *error, + void *data); + struct ofono_sim_driver { const char *name; int (*probe)(struct ofono_sim *sim, unsigned int vendor, void *data); @@ -211,7 +215,9 @@ struct ofono_sim_driver { void (*logical_access)(struct ofono_sim *sim, int session_id, const unsigned char *pdu, unsigned int len, ofono_sim_logical_access_cb_t cb, void *data); - /* Since mer/1.23+git28 */ + void (*set_active_card_slot)(struct ofono_sim *sim, unsigned int index, + ofono_sim_set_active_card_slot_cb_t cb, void *data); + /* Since mer/1.23+git28 */ void (*open_channel2)(struct ofono_sim *sim, const unsigned char *aid, unsigned int len, ofono_sim_open_channel_cb_t cb, void *data); @@ -229,6 +235,9 @@ void ofono_sim_remove(struct ofono_sim *sim); void ofono_sim_set_data(struct ofono_sim *sim, void *data); void *ofono_sim_get_data(struct ofono_sim *sim); +void ofono_sim_set_card_slot_count(struct ofono_sim *sim, unsigned int val); +void ofono_sim_set_active_card_slot(struct ofono_sim *sim, + unsigned int val); const char *ofono_sim_get_imsi(struct ofono_sim *sim); const char *ofono_sim_get_mcc(struct ofono_sim *sim); From 2fe9958cf3f2b45c2c7d40e55125a0b8b4c5f562 Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Thu, 28 Mar 2019 17:36:02 +0530 Subject: [PATCH 041/320] sim: handling of dual sim single active feature Added implementation for handling CardSlotCount and ActiveCardSlot properties for DSSA use case. --- ofono/src/sim.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/ofono/src/sim.c b/ofono/src/sim.c index e3b792bbb..ae471a3fc 100644 --- a/ofono/src/sim.c +++ b/ofono/src/sim.c @@ -132,6 +132,10 @@ struct ofono_sim { struct ofono_atom *atom; unsigned int hfp_watch; + unsigned int card_slot_count; + unsigned int active_card_slot; + unsigned int pending_active_card_slot; + GSList *aid_sessions; GSList *aid_list; char *impi; @@ -565,6 +569,13 @@ static DBusMessage *sim_get_properties(DBusConnection *conn, get_pin_retries(sim, &pin_retries_dict, &dbus_retries); ofono_dbus_dict_append_dict(&dict, "Retries", DBUS_TYPE_BYTE, &pin_retries_dict); + + ofono_dbus_dict_append(&dict, "CardSlotCount", DBUS_TYPE_UINT32, + &sim->card_slot_count); + + ofono_dbus_dict_append(&dict, "ActiveCardSlot", DBUS_TYPE_UINT32, + &sim->active_card_slot); + g_free(pin_retries_dict); g_free(dbus_retries); @@ -756,6 +767,28 @@ static gboolean sim_allow(DBusMessage *msg, OFONO_DBUS_ACCESS_INTF_SIMMGR, method, arg); } +static void sim_set_slot_callback(const struct ofono_error *error, void *data) +{ + struct ofono_sim *sim = data; + DBusMessage *reply; + + if (error->type != OFONO_ERROR_TYPE_NO_ERROR) { + DBG("Error setting radio access mode"); + + sim->pending_active_card_slot = sim->active_card_slot; + + reply = __ofono_error_failed(sim->pending); + __ofono_dbus_pending_reply(&sim->pending, reply); + + return; + } + + sim->active_card_slot = sim->pending_active_card_slot; + + reply = dbus_message_new_method_return(sim->pending); + __ofono_dbus_pending_reply(&sim->pending, reply); +} + static DBusMessage *sim_set_property(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -826,6 +859,37 @@ static DBusMessage *sim_set_property(DBusConnection *conn, DBusMessage *msg, if (set_ok) return NULL; + } else if (!strcmp(name, "ActiveCardSlot")) { + dbus_uint32_t value; + + dbus_message_iter_next(&iter); + + if (sim->driver->set_active_card_slot == NULL) + return __ofono_error_not_implemented(msg); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) + return __ofono_error_invalid_args(msg); + + dbus_message_iter_recurse(&iter, &var); + + if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_UINT32) + return __ofono_error_invalid_args(msg); + + dbus_message_iter_get_basic(&var, &value); + + if (value <= 0 || value > sim->card_slot_count) + return __ofono_error_invalid_args(msg); + + if (sim->active_card_slot == value) + return dbus_message_new_method_return(msg); + + sim->pending = dbus_message_ref(msg); + sim->pending_active_card_slot = value; + + sim->driver->set_active_card_slot(sim, value - 1, + sim_set_slot_callback, + sim); + return NULL; } return __ofono_error_invalid_args(msg); @@ -4004,3 +4068,15 @@ int ofono_sim_logical_access(struct ofono_sim *sim, int session_id, return 0; } + +void ofono_sim_set_card_slot_count(struct ofono_sim *sim, unsigned int val) +{ + if (sim) + sim->card_slot_count = val; +} + +void ofono_sim_set_active_card_slot(struct ofono_sim *sim, unsigned int val) +{ + if (sim) + sim->active_card_slot = val; +} From 48582c4750cc899be1af1593c4c43d9265b94737 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Thu, 28 Mar 2019 21:03:21 -0500 Subject: [PATCH 042/320] sim: Emit PropertyChanged for ActiveCardSlot changes --- ofono/src/sim.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ofono/src/sim.c b/ofono/src/sim.c index ae471a3fc..f5f6b1ff5 100644 --- a/ofono/src/sim.c +++ b/ofono/src/sim.c @@ -770,6 +770,8 @@ static gboolean sim_allow(DBusMessage *msg, static void sim_set_slot_callback(const struct ofono_error *error, void *data) { struct ofono_sim *sim = data; + DBusConnection *conn = ofono_dbus_get_connection(); + const char *path = __ofono_atom_get_path(sim->atom); DBusMessage *reply; if (error->type != OFONO_ERROR_TYPE_NO_ERROR) { @@ -787,6 +789,12 @@ static void sim_set_slot_callback(const struct ofono_error *error, void *data) reply = dbus_message_new_method_return(sim->pending); __ofono_dbus_pending_reply(&sim->pending, reply); + + ofono_dbus_signal_property_changed(conn, path, + OFONO_SIM_MANAGER_INTERFACE, + "ActiveCardSlot", + DBUS_TYPE_UINT32, + &sim->active_card_slot); } static DBusMessage *sim_set_property(DBusConnection *conn, DBusMessage *msg, From af8e1f9700cbc9678d59aa37c9101ebfb4f5ea98 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Thu, 28 Mar 2019 21:05:04 -0500 Subject: [PATCH 043/320] sim: Initialize card_slot_count and active_card_slot Initialize both to 1 so that SimManager does not erroneously show ActiveCardSlot as 0 for drivers that do not (yet) setup these values. --- ofono/src/sim.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ofono/src/sim.c b/ofono/src/sim.c index f5f6b1ff5..20f9aba96 100644 --- a/ofono/src/sim.c +++ b/ofono/src/sim.c @@ -3555,6 +3555,9 @@ struct ofono_sim *ofono_sim_create(struct ofono_modem *modem, for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++) sim->pin_retries[i] = -1; + sim->active_card_slot = 1; + sim->card_slot_count = 1; + for (l = g_drivers; l; l = l->next) { const struct ofono_sim_driver *drv = l->data; From 4902ea54a37052cc69be714cba19e0c0a31ca1fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Sun, 31 Mar 2019 23:19:19 +0200 Subject: [PATCH 044/320] ublox: Do not leave vendor_family unset In a recent patch vendor family was only set if the device did not support USBCONF, but that resulted in drivers being registered the "generic" vendor. That caused for instance netreg to use incorrect cmer mode and fail on TOBY-L210. --- ofono/plugins/ublox.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ofono/plugins/ublox.c b/ofono/plugins/ublox.c index dc0017654..355bdf9e9 100644 --- a/ofono/plugins/ublox.c +++ b/ofono/plugins/ublox.c @@ -227,6 +227,8 @@ static void query_model_cb(gboolean ok, GAtResult *result, gpointer user_data) DBG("Model: %s", data->model->name); + data->vendor_family = OFONO_VENDOR_UBLOX; + if (data->model->flags & UBLOX_F_HAVE_USBCONF) { if (g_at_chat_send(data->aux, "AT+UUSBCONF?", uusbconf_prefix, query_usbconf_cb, modem, NULL)) @@ -234,8 +236,6 @@ static void query_model_cb(gboolean ok, GAtResult *result, gpointer user_data) ofono_error("Unable to query USB configuration"); goto fail; - } else { - data->vendor_family = OFONO_VENDOR_UBLOX; } if (g_at_chat_send(data->aux, "AT+CFUN=4", none_prefix, From 6900764908ead4c445e23a0abd898292d53ec186 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Sun, 31 Mar 2019 22:18:46 +0200 Subject: [PATCH 045/320] ublox: Correct the USBCONF reply prefix According to the u-blox AT Commands Manual and my tests the response prefix of AT+UUSBCONF is "+UUSBCONF:", including a colon. The colon was missing in the code, causing next step to parse a number to fail, since a colon is not a number. --- ofono/plugins/ublox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/plugins/ublox.c b/ofono/plugins/ublox.c index 355bdf9e9..1ca0030a2 100644 --- a/ofono/plugins/ublox.c +++ b/ofono/plugins/ublox.c @@ -164,7 +164,7 @@ static void query_usbconf_cb(gboolean ok, g_at_result_iter_init(&iter, result); retry: - if (!g_at_result_iter_next(&iter, "+UUSBCONF")) { + if (!g_at_result_iter_next(&iter, "+UUSBCONF:")) { ofono_error("Unable to query USB configuration"); goto error; } From 3a15b1d04099c0b306c2613b0c156f72c855140a Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Tue, 2 Apr 2019 11:55:25 +0530 Subject: [PATCH 046/320] sim: added error handling in set slot callback Adding the handling of error when the driver returns CME ERROR:4. This error will be returned for non xmm vendor modems using ifxmodem driver for sim. --- ofono/src/sim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/src/sim.c b/ofono/src/sim.c index 20f9aba96..b8b3a78ba 100644 --- a/ofono/src/sim.c +++ b/ofono/src/sim.c @@ -779,7 +779,7 @@ static void sim_set_slot_callback(const struct ofono_error *error, void *data) sim->pending_active_card_slot = sim->active_card_slot; - reply = __ofono_error_failed(sim->pending); + reply = __ofono_error_from_error(error, sim->pending); __ofono_dbus_pending_reply(&sim->pending, reply); return; From 4eed681a29a9dfab0b3184cbbd9b0dff096bc0ce Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Tue, 2 Apr 2019 11:54:02 +0530 Subject: [PATCH 047/320] xmm7modem: handling of dual sim single active feature Handled DSSA use case for xmm7modem. Added driver function to switch between available card slots for SIM. Only one SIM will be active at a given time. On calling this function the active SIM will be removed and the card slot made inactive and SIM in the other card slot will be made active. Use case is similar to a SIM swap/change where one SIM is replaced another SIM in the same slot. --- ofono/drivers/atmodem/sim.c | 126 +++++++++++++++++++++++++++++++++++- 1 file changed, 125 insertions(+), 1 deletion(-) diff --git a/ofono/drivers/atmodem/sim.c b/ofono/drivers/atmodem/sim.c index 5f66a09ce..520b3dbf5 100644 --- a/ofono/drivers/atmodem/sim.c +++ b/ofono/drivers/atmodem/sim.c @@ -75,6 +75,7 @@ static const char *cuad_prefix[] = { "+CUAD:", NULL }; static const char *ccho_prefix[] = { "+CCHO:", NULL }; static const char *crla_prefix[] = { "+CRLA:", NULL }; static const char *cgla_prefix[] = { "+CGLA:", NULL }; +static const char *xcmscsc_prefix[] = { "+XCMSCSC:", NULL}; static const char *none_prefix[] = { NULL }; static void append_file_path(char *buf, const unsigned char *path, @@ -1160,6 +1161,7 @@ static void at_pin_retries_query(struct ofono_sim *sim, DBG(""); switch (sd->vendor) { + case OFONO_VENDOR_XMM: case OFONO_VENDOR_IFX: if (g_at_chat_send(sd->chat, "AT+XPINCNT", xpincnt_prefix, xpincnt_cb, cbd, g_free) > 0) @@ -1920,6 +1922,83 @@ static void at_logical_access(struct ofono_sim *sim, int session_id, CALLBACK_WITH_FAILURE(cb, NULL, 0, data); } +static void xcmscsc_query_cb(gboolean ok, GAtResult *result, gpointer user) +{ + struct ofono_sim *sim = user; + struct sim_data *sd = ofono_sim_get_data(sim); + GAtResultIter iter; + int active_slot; + + if (!ok) + goto done; + + g_at_result_iter_init(&iter, result); + + if (!g_at_result_iter_next(&iter, "+XCMSCSC:")) + goto done; + + g_at_result_iter_skip_next(&iter); + g_at_result_iter_skip_next(&iter); + + g_at_result_iter_next_number(&iter, &active_slot); + + /* set active SIM slot */ + ofono_sim_set_active_card_slot(sim, active_slot + 1); + +done: + /* Query supported s */ + g_at_chat_send(sd->chat, "AT+CLCK=?", clck_prefix, + at_clck_query_cb, sim, NULL); +} + +static void at_xcmscsc_test_cb(gboolean ok, GAtResult *result, gpointer user) +{ + struct ofono_sim *sim = user; + struct sim_data *sd = ofono_sim_get_data(sim); + GAtResultIter iter; + int card_slot_count; + + if (!ok) + goto done; + + g_at_result_iter_init(&iter, result); + + if (!g_at_result_iter_next(&iter, "+XCMSCSC:")) + goto done; + + g_at_result_iter_skip_next(&iter); + g_at_result_iter_skip_next(&iter); + + if (!g_at_result_iter_open_list(&iter)) + goto done; + + g_at_result_iter_skip_next(&iter); + + if (!g_at_result_iter_next_number(&iter, &card_slot_count)) + goto done; + + /* Set num slots */ + ofono_sim_set_card_slot_count(sim, card_slot_count + 1); + + /* + * enable reporting of MSIM remap status information + * and enable automatic acceptance of MSIM Remap + * acknowledgement + */ + g_at_chat_send(sd->chat, "AT+XCMSRS=2", none_prefix, + NULL, NULL, NULL); + + /* Query active card slot */ + g_at_chat_send(sd->chat, "AT+XCMSCSC?", xcmscsc_prefix, + xcmscsc_query_cb, sim, NULL); + return; + +done: + /* Query supported s */ + g_at_chat_send(sd->chat, "AT+CLCK=?", clck_prefix, + at_clck_query_cb, sim, NULL); +} + static int at_sim_probe(struct ofono_sim *sim, unsigned int vendor, void *data) { @@ -1938,6 +2017,10 @@ static int at_sim_probe(struct ofono_sim *sim, unsigned int vendor, if (at_clck_cpwd_fac[i]) sd->passwd_type_mask |= (1 << i); + if (sd->vendor == OFONO_VENDOR_XMM) + return g_at_chat_send(sd->chat, "AT+XCMSCSC=?", xcmscsc_prefix, + at_xcmscsc_test_cb, sim, NULL) ? 0 : -1; + /* Query supported s */ return g_at_chat_send(sd->chat, "AT+CLCK=?", clck_prefix, at_clck_query_cb, sim, NULL) ? 0 : -1; @@ -1957,6 +2040,46 @@ static void at_sim_remove(struct ofono_sim *sim) g_free(sd); } +static void xcmscsc_cb(gboolean ok, GAtResult *result, + gpointer user_data) +{ + struct cb_data *cbd = user_data; + ofono_sim_set_active_card_slot_cb_t cb = cbd->cb; + struct ofono_error error; + + decode_at_error(&error, g_at_result_final_response(result)); + + if (cb) + cb(&error, cbd->data); +} + +static void at_set_active_card_slot(struct ofono_sim *sim, unsigned int index, + ofono_sim_set_active_card_slot_cb_t cb, void *data) +{ + struct sim_data *sd = ofono_sim_get_data(sim); + struct cb_data *cbd = cb_data_new(cb, data); + char cmd[43]; + + if (sd->vendor != OFONO_VENDOR_XMM) { + struct ofono_error error; + error.type = OFONO_ERROR_TYPE_CME; + error.error = 4; + + cb(&error, data); + return; + } + + /* Enable single SIM mode for indicated card slot id */ + snprintf(cmd, sizeof(cmd), "AT+XCMSCSC=1,0,%u,1", index); + + if (g_at_chat_send(sd->chat, cmd, none_prefix, xcmscsc_cb, + cbd, g_free) > 0) + return; + + g_free(cbd); + CALLBACK_WITH_FAILURE(cb, data); +} + static const struct ofono_sim_driver driver = { .name = "atmodem", .probe = at_sim_probe, @@ -1982,7 +2105,8 @@ static const struct ofono_sim_driver driver = { .session_read_binary = at_session_read_binary, .session_read_record = at_session_read_record, .session_read_info = at_session_read_info, - .logical_access = at_logical_access + .logical_access = at_logical_access, + .set_active_card_slot = at_set_active_card_slot }; static const struct ofono_sim_driver driver_noef = { From 2e533b56ddeca8499aa7cfdd8dac00c459c756d4 Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Tue, 2 Apr 2019 11:54:42 +0530 Subject: [PATCH 048/320] xmm7modem: Changes in plugin for DSSA functionality Changed the sim driver vendor for xmm7modem from OFONO_VENDOR_IFX to OFONO_VENDOR_XMM to handle DSSA functionality. --- ofono/plugins/xmm7xxx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/plugins/xmm7xxx.c b/ofono/plugins/xmm7xxx.c index 90e52fbbb..23a7d4e41 100644 --- a/ofono/plugins/xmm7xxx.c +++ b/ofono/plugins/xmm7xxx.c @@ -1223,7 +1223,7 @@ static void xmm7xxx_pre_sim(struct ofono_modem *modem) DBG("%p", modem); ofono_devinfo_create(modem, OFONO_VENDOR_IFX, "atmodem", data->chat); - data->sim = ofono_sim_create(modem, OFONO_VENDOR_IFX, "atmodem", + data->sim = ofono_sim_create(modem, OFONO_VENDOR_XMM, "atmodem", data->chat); } From d8b94f266f33ee024a0f969939541bb32166f1b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Wed, 3 Apr 2019 23:11:16 +0200 Subject: [PATCH 049/320] ublox: gprs-context: Fix router mode IP settings. The ublox modems always run DHCP when in router mode. Unfortunately the code overwrote the IP settings with static IP settings while activating. Now we respect the networking_mode regardless if we read settings during activation or read settings phase. --- ofono/drivers/ubloxmodem/gprs-context.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/ofono/drivers/ubloxmodem/gprs-context.c b/ofono/drivers/ubloxmodem/gprs-context.c index 96ffbf688..3b48062a7 100644 --- a/ofono/drivers/ubloxmodem/gprs-context.c +++ b/ofono/drivers/ubloxmodem/gprs-context.c @@ -235,6 +235,14 @@ static void ublox_read_settings(struct ofono_gprs_context *gc) { struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); + if (gcd->networking_mode == NETWORKING_MODE_ROUTER) { + /* Use DHCP */ + set_gprs_context_interface(gc); + ofono_gprs_context_set_ipv4_address(gc, NULL, 0); + CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data); + return; + } + if (ublox_send_cgcontrdp(gc) < 0) CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data); } @@ -247,15 +255,6 @@ static void ublox_gprs_read_settings(struct ofono_gprs_context *gc, DBG("cid %u", cid); - if (gcd->networking_mode == NETWORKING_MODE_ROUTER) { - /* Use DHCP */ - gcd->active_context = cid; - set_gprs_context_interface(gc); - ofono_gprs_context_set_ipv4_address(gc, NULL, 0); - CALLBACK_WITH_SUCCESS(cb, data); - return; - } - gcd->active_context = cid; gcd->cb = cb; gcd->cb_data = data; From 478de3f36e27dc49cd64d6eb49c0271264951387 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 12 Apr 2019 22:13:00 +0200 Subject: [PATCH 050/320] Release 1.29 --- ofono/ChangeLog | 6 ++++++ ofono/configure.ac | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ofono/ChangeLog b/ofono/ChangeLog index e2937659c..2a426bce9 100644 --- a/ofono/ChangeLog +++ b/ofono/ChangeLog @@ -1,3 +1,9 @@ +ver 1.29: + Fix issue with QMI and SIM initialized notification. + Add support for multiple PDP contexts and xmm7xxx modems. + Add support for handling Dual SIM Single Active feature + Add support for SIM PIN caching feature. + ver 1.28: Fix issue with SIM initialization and Gemalto modems. diff --git a/ofono/configure.ac b/ofono/configure.ac index 302815a53..397983972 100644 --- a/ofono/configure.ac +++ b/ofono/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.60) -AC_INIT(ofono, 1.28) +AC_INIT(ofono, 1.29) AM_INIT_AUTOMAKE([foreign subdir-objects color-tests]) AC_CONFIG_HEADERS(config.h) From 43cce71603635a2f6e991878026ef62591bfe302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Tue, 16 Apr 2019 08:09:26 +0200 Subject: [PATCH 051/320] gprs: Always store RoamingAllowed as a boolean. In one instance it was stored as boolean and another as int. Since its always parsed as a boolean and it is a boolean, always store it as boolean. --- ofono/src/gprs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/src/gprs.c b/ofono/src/gprs.c index 9b6d6485b..d25001a54 100644 --- a/ofono/src/gprs.c +++ b/ofono/src/gprs.c @@ -2224,7 +2224,7 @@ static DBusMessage *gprs_set_property(DBusConnection *conn, gprs->roaming_allowed = value; if (gprs->settings) { - g_key_file_set_integer(gprs->settings, SETTINGS_GROUP, + g_key_file_set_boolean(gprs->settings, SETTINGS_GROUP, "RoamingAllowed", gprs->roaming_allowed); storage_sync(gprs->imsi, SETTINGS_STORE, From 725c72ff8b7fc113866012d66efa8a814f5826c0 Mon Sep 17 00:00:00 2001 From: Tom Nguyen Date: Fri, 12 Apr 2019 11:52:26 -0400 Subject: [PATCH 052/320] qmimodem: return all serial numbers Some modems, eg. Quectel EC25E, return the ESN, IMEI, and MEID even though they support only one network type in a region. Current serial number query gives precedence to the ESN if it exists, and does not consider the IMEI and MEID. Add a check of the supported radio interfaces in deciding which serial number to return. If radio interfaces are 3GPP based, then return the IMEI, else return the ESN. If neither exist, return MEID if available, else fail. --- ofono/drivers/qmimodem/devinfo.c | 88 +++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 13 deletions(-) diff --git a/ofono/drivers/qmimodem/devinfo.c b/ofono/drivers/qmimodem/devinfo.c index af976b772..365ff02b4 100644 --- a/ofono/drivers/qmimodem/devinfo.c +++ b/ofono/drivers/qmimodem/devinfo.c @@ -36,6 +36,7 @@ struct devinfo_data { struct qmi_service *dms; + bool device_is_3gpp; }; static void string_cb(struct qmi_result *result, void *user_data) @@ -116,7 +117,12 @@ static void qmi_query_revision(struct ofono_devinfo *devinfo, static void get_ids_cb(struct qmi_result *result, void *user_data) { struct cb_data *cbd = user_data; + struct ofono_devinfo *devinfo = cbd->user; + struct devinfo_data *data = ofono_devinfo_get_data(devinfo); ofono_devinfo_query_cb_t cb = cbd->cb; + char *esn; + char *imei; + char *meid; char *str; DBG(""); @@ -126,20 +132,28 @@ static void get_ids_cb(struct qmi_result *result, void *user_data) return; } - str = qmi_result_get_string(result, QMI_DMS_RESULT_ESN); - /* Telit qmi modems return a "0" string when ESN is not available. */ - if (!str || strcmp(str, "0") == 0) { - qmi_free(str); - str = qmi_result_get_string(result, QMI_DMS_RESULT_IMEI); - if (!str) { - CALLBACK_WITH_FAILURE(cb, NULL, cbd->data); - return; - } - } + esn = qmi_result_get_string(result, QMI_DMS_RESULT_ESN); + imei = qmi_result_get_string(result, QMI_DMS_RESULT_IMEI); + meid = qmi_result_get_string(result, QMI_DMS_RESULT_MEID); - CALLBACK_WITH_SUCCESS(cb, str, cbd->data); + str = NULL; - qmi_free(str); + if (data->device_is_3gpp && imei && strcmp(imei, "0")) + str = imei; + else if (esn && strcmp(esn, "0")) + str = esn; + + if (str == NULL && meid && strcmp(meid, "0")) + str = meid; + + if (str) + CALLBACK_WITH_SUCCESS(cb, str, cbd->data); + else + CALLBACK_WITH_FAILURE(cb, NULL, cbd->data); + + qmi_free(esn); + qmi_free(imei); + qmi_free(meid); } static void qmi_query_serial(struct ofono_devinfo *devinfo, @@ -150,6 +164,8 @@ static void qmi_query_serial(struct ofono_devinfo *devinfo, DBG(""); + cbd->user = devinfo; + if (qmi_service_send(data->dms, QMI_DMS_GET_IDS, NULL, get_ids_cb, cbd, g_free) > 0) return; @@ -159,6 +175,51 @@ static void qmi_query_serial(struct ofono_devinfo *devinfo, g_free(cbd); } +static void get_caps_cb(struct qmi_result *result, void *user_data) +{ + struct ofono_devinfo *devinfo = user_data; + struct devinfo_data *data = ofono_devinfo_get_data(devinfo); + const struct qmi_dms_device_caps *caps; + uint8_t i; + + DBG(""); + + if (qmi_result_set_error(result, NULL)) + goto error; + + caps = qmi_result_get(result, QMI_DMS_RESULT_DEVICE_CAPS, NULL); + if (caps == NULL) + goto error; + + data->device_is_3gpp = false; + + for (i = 0; i < caps->radio_if_count; i++) { + switch (caps->radio_if[i]) { + case QMI_DMS_RADIO_IF_GSM: + case QMI_DMS_RADIO_IF_UMTS: + case QMI_DMS_RADIO_IF_LTE: + data->device_is_3gpp = true; + break; + } + } + +error: + ofono_devinfo_register(devinfo); +} + +static void qmi_query_caps(struct ofono_devinfo *devinfo) +{ + struct devinfo_data *data = ofono_devinfo_get_data(devinfo); + + DBG(""); + + if (qmi_service_send(data->dms, QMI_DMS_GET_CAPS, NULL, + get_caps_cb, devinfo, NULL) > 0) + return; + + ofono_devinfo_register(devinfo); +} + static void create_dms_cb(struct qmi_service *service, void *user_data) { struct ofono_devinfo *devinfo = user_data; @@ -173,8 +234,9 @@ static void create_dms_cb(struct qmi_service *service, void *user_data) } data->dms = qmi_service_ref(service); + data->device_is_3gpp = false; - ofono_devinfo_register(devinfo); + qmi_query_caps(devinfo); } static int qmi_devinfo_probe(struct ofono_devinfo *devinfo, From 0f75708d4682634ca205786ccf4336c7445080d3 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Tue, 16 Apr 2019 11:52:56 -0500 Subject: [PATCH 053/320] AUTHORS: Mention Tom's contributions --- ofono/AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/ofono/AUTHORS b/ofono/AUTHORS index 758d571e7..4f7ba4a9f 100644 --- a/ofono/AUTHORS +++ b/ofono/AUTHORS @@ -141,3 +141,4 @@ Nandini Rebello Giacinto Cifelli Khaled Romdhani Pavel Machek +Tom Nguyen From 8278dbc699215131cbe617093005fb30bfd1cf54 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 26 Apr 2019 12:20:45 -0500 Subject: [PATCH 054/320] AUTHORS: Mention Alexander's contributions --- ofono/AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/ofono/AUTHORS b/ofono/AUTHORS index 4f7ba4a9f..96bcc432c 100644 --- a/ofono/AUTHORS +++ b/ofono/AUTHORS @@ -126,6 +126,7 @@ Lukasz Nowak Jonas Bonn Matthijs Kooijman Clayton Craft +Alexander Couzens Joey Hewitt Richard Röjfors Philippe De Swert From c55904ddf857edb7ea9c91ae820c1c090d675802 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 26 Apr 2019 12:21:53 -0500 Subject: [PATCH 055/320] AUTHORS: Mention Pau's contributions --- ofono/AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/ofono/AUTHORS b/ofono/AUTHORS index 96bcc432c..bd9568111 100644 --- a/ofono/AUTHORS +++ b/ofono/AUTHORS @@ -140,6 +140,7 @@ Martin Hundebøll Julien Tournier Nandini Rebello Giacinto Cifelli +Pau Espin Pedrol Khaled Romdhani Pavel Machek Tom Nguyen From db3e8114c6a11744a4e0a56bee441de627453772 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sat, 27 Apr 2019 16:16:48 +0200 Subject: [PATCH 056/320] network/ofono_netreg_status_notify: debug log the lac and ci --- ofono/src/network.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ofono/src/network.c b/ofono/src/network.c index 2882e2d24..657d393fa 100644 --- a/ofono/src/network.c +++ b/ofono/src/network.c @@ -1391,8 +1391,8 @@ void ofono_netreg_status_notify(struct ofono_netreg *netreg, int status, if (netreg == NULL) return; - DBG("%s status %d tech %d", __ofono_atom_get_path(netreg->atom), - status, tech); + DBG("%s status %d tech %d lac %d ci %d", + __ofono_atom_get_path(netreg->atom), status, tech, lac, ci); if (netreg->status != status) { struct ofono_modem *modem; From de23a3b3e642fa50c1a30ae1a2c0697a24d7a7f5 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sat, 27 Apr 2019 16:16:49 +0200 Subject: [PATCH 057/320] network: debug log the network time on update --- ofono/src/network.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ofono/src/network.c b/ofono/src/network.c index 657d393fa..4d1775f60 100644 --- a/ofono/src/network.c +++ b/ofono/src/network.c @@ -1447,6 +1447,11 @@ void ofono_netreg_time_notify(struct ofono_netreg *netreg, if (info == NULL) return; + DBG("net time %d-%02d-%02d %02d:%02d:%02d utcoff %d dst %d", + info->year, info->mon, info->mday, + info->hour, info->min, info->sec, + info->utcoff, info->dst); + __ofono_nettime_info_received(modem, info); } From 48e0cea90337bffc71dc80e15f24cc3f679da24c Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 28 Apr 2019 13:28:14 +0200 Subject: [PATCH 058/320] gprs: netreg_status_changed: output the status as human readable string --- ofono/src/gprs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/src/gprs.c b/ofono/src/gprs.c index d25001a54..e8216cf37 100644 --- a/ofono/src/gprs.c +++ b/ofono/src/gprs.c @@ -2121,7 +2121,7 @@ static void netreg_status_changed(int status, int lac, int ci, int tech, { struct ofono_gprs *gprs = data; - DBG("%d", status); + DBG("%d (%s)", status, registration_status_to_string(status)); gprs->netreg_status = status; From e2de5fc8d5e1d46fe235269a19a6fa274f557091 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 28 Apr 2019 13:28:15 +0200 Subject: [PATCH 059/320] qmi: netmon: fix crashs on get_rssi_cb when BER or RSSI are empty The message can be emitted without the fields being present. In this case ber or rssi are 0 resulting in a null pointer deref. --- ofono/drivers/qmimodem/netmon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ofono/drivers/qmimodem/netmon.c b/ofono/drivers/qmimodem/netmon.c index 14a55632e..729879ce7 100644 --- a/ofono/drivers/qmimodem/netmon.c +++ b/ofono/drivers/qmimodem/netmon.c @@ -89,8 +89,8 @@ static void get_rssi_cb(struct qmi_result *result, void *user_data) /* RSSI */ rssi = qmi_result_get(result, 0x11, &len); - num = GUINT16_FROM_LE(rssi->count); if (rssi) { + num = GUINT16_FROM_LE(rssi->count); for (i = 0; i < num; i++) { DBG("RSSI: %hhu on RAT %hhd", rssi->info[i].rssi, @@ -126,8 +126,8 @@ static void get_rssi_cb(struct qmi_result *result, void *user_data) /* Bit error rate */ ber = qmi_result_get(result, 0x15, &len); - num = GUINT16_FROM_LE(ber->count); if (ber) { + num = GUINT16_FROM_LE(ber->count); for (i = 0; i < ber->count; i++) { DBG("Bit error rate: %hu on RAT %hhd", GUINT16_FROM_LE(ber->info[i].rate), From 2c902081154aeef9e757b3e176208a663a2e2ce3 Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Wed, 24 Apr 2019 11:24:50 +0530 Subject: [PATCH 060/320] xmm7modem: handling of IPv6 address for activated context Handled IPv6 address after activating PDP context. Received IPv6 address is of format addr + netmask in the same string in the form of "a1.a2.a3.a4.a5.a6.a7.a8.a9.a10.a11.a12.a13.a14.a15.a16. m1.m2.m3.m4.m5.m6.m7.m8.m9.m10.m11.m12.m13.m14.m15.m16" --- ofono/drivers/atmodem/atutil.c | 39 ++++++++++++++++++++++ ofono/drivers/atmodem/atutil.h | 3 ++ ofono/drivers/ifxmodem/gprs-context.c | 48 +++++++++++++++++++-------- 3 files changed, 77 insertions(+), 13 deletions(-) diff --git a/ofono/drivers/atmodem/atutil.c b/ofono/drivers/atmodem/atutil.c index fa9ed72f7..7ed347813 100644 --- a/ofono/drivers/atmodem/atutil.c +++ b/ofono/drivers/atmodem/atutil.c @@ -656,6 +656,45 @@ int at_util_get_ipv4_address_and_netmask(const char *addrnetmask, return ret; } +/* + * CGCONTRDP returns addr + netmask in the same string in the form + * of "a1.a2.a3.a4.a5.a6.a7.a8.a9.a10.a11.a12.a13.a14.a15.a16.m1.m2. + * m3.m4.m5.m6.m7.m8.m9.m10.m11.m12.m13.m14.m15.m16" for IPv6. + * address/netmask must be able to hold 64 characters. + */ +int at_util_get_ipv6_address_and_netmask(const char *addrnetmask, + char *address, char *netmask) +{ + const char *s = addrnetmask; + const char *net = NULL; + + int ret = -EINVAL; + int i; + + /* Count 31 dots for ipv6, less or more means error. */ + for (i = 0; i < 33; i++, s++) { + s = strchr(s, '.'); + + if (!s) + break; + + if (i == 15) { + /* set netmask ptr and break the string */ + net = s + 1; + } + } + + if (i == 31) { + memcpy(address, addrnetmask, net - addrnetmask); + address[net - addrnetmask - 1] = '\0'; + strcpy(netmask, net); + + ret = 0; + } + + return ret; +} + int at_util_gprs_auth_method_to_auth_prot( enum ofono_gprs_auth_method auth_method) { diff --git a/ofono/drivers/atmodem/atutil.h b/ofono/drivers/atmodem/atutil.h index 69e8b499d..61800ff4a 100644 --- a/ofono/drivers/atmodem/atutil.h +++ b/ofono/drivers/atmodem/atutil.h @@ -86,6 +86,9 @@ void at_util_sim_state_query_free(struct at_util_sim_state_query *req); int at_util_get_ipv4_address_and_netmask(const char *addrnetmask, char *address, char *netmask); +int at_util_get_ipv6_address_and_netmask(const char *addrnetmask, + char *address, char *netmask); + int at_util_gprs_auth_method_to_auth_prot( enum ofono_gprs_auth_method auth_method); diff --git a/ofono/drivers/ifxmodem/gprs-context.c b/ofono/drivers/ifxmodem/gprs-context.c index 1dc3d452e..07787e7b5 100644 --- a/ofono/drivers/ifxmodem/gprs-context.c +++ b/ofono/drivers/ifxmodem/gprs-context.c @@ -44,6 +44,7 @@ #define TUN_DEV "/dev/net/tun" #define STATIC_IP_NETMASK "255.255.255.255" +#define IPV6_DEFAULT_PREFIX_LEN 8 static const char *none_prefix[] = { NULL }; static const char *xdns_prefix[] = { "+XDNS:", NULL }; @@ -352,10 +353,41 @@ static void cgcontrdp_cb(gboolean ok, GAtResult *result, gpointer user_data) DBG("DNS: %s, %s\n", gcd->dns1, gcd->dns2); - if (!laddrnetmask || at_util_get_ipv4_address_and_netmask(laddrnetmask, + if (gcd->proto == OFONO_GPRS_PROTO_IP) { + if (!laddrnetmask || + at_util_get_ipv4_address_and_netmask(laddrnetmask, gcd->address, gcd->netmask) < 0) { - failed_setup(gc, NULL, TRUE); - return; + failed_setup(gc, NULL, TRUE); + return; + } + + ofono_gprs_context_set_ipv4_address(gc, gcd->address, TRUE); + + if (gcd->netmask[0]) + ofono_gprs_context_set_ipv4_netmask(gc, gcd->netmask); + + if (gcd->gateway[0]) + ofono_gprs_context_set_ipv4_gateway(gc, gcd->gateway); + + ofono_gprs_context_set_ipv4_dns_servers(gc, dns); + } + + if (gcd->proto == OFONO_GPRS_PROTO_IPV6) { + if (!laddrnetmask || + at_util_get_ipv6_address_and_netmask(laddrnetmask, + gcd->address, gcd->netmask) < 0) { + failed_setup(gc, NULL, TRUE); + return; + } + + ofono_gprs_context_set_ipv6_address(gc, gcd->address); + + if (gcd->gateway[0]) + ofono_gprs_context_set_ipv6_gateway(gc, gcd->gateway); + + ofono_gprs_context_set_ipv6_dns_servers(gc, dns); + ofono_gprs_context_set_ipv6_prefix_length(gc, + IPV6_DEFAULT_PREFIX_LEN); } if (gw) @@ -373,16 +405,6 @@ static void cgcontrdp_cb(gboolean ok, GAtResult *result, gpointer user_data) interface = ofono_gprs_context_get_interface(gc); datapath = get_datapath(modem, interface); - ofono_gprs_context_set_ipv4_address(gc, gcd->address, TRUE); - - if (gcd->netmask[0]) - ofono_gprs_context_set_ipv4_netmask(gc, gcd->netmask); - - if (gcd->gateway[0]) - ofono_gprs_context_set_ipv4_gateway(gc, gcd->gateway); - - ofono_gprs_context_set_ipv4_dns_servers(gc, dns); - snprintf(buf, sizeof(buf), "AT+XDATACHANNEL=1,1,\"%s\",\"%s\",2,%u", ctrlpath, datapath, gcd->active_context); g_at_chat_send(gcd->chat, buf, none_prefix, NULL, NULL, NULL); From 717708d9126bdbc00604fe160409ef97527ebdd5 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Apr 2019 13:59:36 -0500 Subject: [PATCH 061/320] atmodem: Remove unneeded if statement if (ctx->apn) is always true since apn is an array variable --- ofono/drivers/atmodem/gprs-context.c | 53 ++++++++++++++-------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/ofono/drivers/atmodem/gprs-context.c b/ofono/drivers/atmodem/gprs-context.c index b86c63893..b34b070a7 100644 --- a/ofono/drivers/atmodem/gprs-context.c +++ b/ofono/drivers/atmodem/gprs-context.c @@ -285,35 +285,36 @@ static void at_gprs_activate_primary(struct ofono_gprs_context *gc, len = snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IP\"", ctx->cid); - if (ctx->apn) { - switch (gcd->vendor) { - case OFONO_VENDOR_UBLOX: - /* - * U-blox modems require a magic prefix to the APN to - * specify the authentication method to use in the - * network. See UBX-13002752 - R21. - * - * As the response of the read command omits this magic - * prefix, this is the least invasive place to set it. - */ - switch (ctx->auth_method) { - case OFONO_GPRS_AUTH_METHOD_ANY: - case OFONO_GPRS_AUTH_METHOD_NONE: - case OFONO_GPRS_AUTH_METHOD_CHAP: - snprintf(buf + len, sizeof(buf) - len - 3, - ",\"CHAP:%s\"", ctx->apn); - break; - case OFONO_GPRS_AUTH_METHOD_PAP: - snprintf(buf + len, sizeof(buf) - len - 3, - ",\"PAP:%s\"", ctx->apn); - break; - } + switch (gcd->vendor) { + case OFONO_VENDOR_UBLOX: + /* + * U-blox modems require a magic prefix to the APN to + * specify the authentication method to use in the + * network. See UBX-13002752 - R21. + * + * As the response of the read command omits this magic + * prefix, this is the least invasive place to set it. + */ + switch (ctx->auth_method) { + case OFONO_GPRS_AUTH_METHOD_ANY: + case OFONO_GPRS_AUTH_METHOD_CHAP: + snprintf(buf + len, sizeof(buf) - len - 3, + ",\"CHAP:%s\"", ctx->apn); + break; + case OFONO_GPRS_AUTH_METHOD_PAP: + snprintf(buf + len, sizeof(buf) - len - 3, + ",\"PAP:%s\"", ctx->apn); break; - default: - snprintf(buf + len, sizeof(buf) - len - 3, ",\"%s\"", - ctx->apn); + case OFONO_GPRS_AUTH_METHOD_NONE: + snprintf(buf + len, sizeof(buf) - len - 3, + ",\"%s\"", ctx->apn); break; } + break; + default: + snprintf(buf + len, sizeof(buf) - len - 3, ",\"%s\"", + ctx->apn); + break; } if (g_at_chat_send(gcd->chat, buf, none_prefix, From 9bba783c6f5942599e5b4701b1d69aa1479eb6cc Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Apr 2019 14:00:42 -0500 Subject: [PATCH 062/320] ifxmodem: Remove unneeded if statement if (ctx->apn) always evalues to true since it is an array member --- ofono/drivers/ifxmodem/gprs-context.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ofono/drivers/ifxmodem/gprs-context.c b/ofono/drivers/ifxmodem/gprs-context.c index 07787e7b5..42d232a29 100644 --- a/ofono/drivers/ifxmodem/gprs-context.c +++ b/ofono/drivers/ifxmodem/gprs-context.c @@ -561,9 +561,7 @@ static void ifx_gprs_activate_primary(struct ofono_gprs_context *gc, break; } - if (ctx->apn) - snprintf(buf + len, sizeof(buf) - len - 3, - ",\"%s\"", ctx->apn); + snprintf(buf + len, sizeof(buf) - len - 3, ",\"%s\"", ctx->apn); if (g_at_chat_send(gcd->chat, buf, none_prefix, setup_cb, gc, NULL) > 0) From 2385f7db4806353ce49a5e5b6db5b3849db06223 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Apr 2019 14:01:41 -0500 Subject: [PATCH 063/320] swmodem: Remove unneeded if statement --- ofono/drivers/swmodem/gprs-context.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ofono/drivers/swmodem/gprs-context.c b/ofono/drivers/swmodem/gprs-context.c index 5ac9a9754..002053cf9 100644 --- a/ofono/drivers/swmodem/gprs-context.c +++ b/ofono/drivers/swmodem/gprs-context.c @@ -177,9 +177,7 @@ static void sw_gprs_activate_primary(struct ofono_gprs_context *gc, break; } - if (ctx->apn) - snprintf(buf + len, sizeof(buf) - len - 3, - ",\"%s\"", ctx->apn); + snprintf(buf + len, sizeof(buf) - len - 3, ",\"%s\"", ctx->apn); if (g_at_chat_send(gcd->chat, buf, none_prefix, at_cgdcont_cb, cbd, g_free) > 0) From 944aee2d5ee20dd9cab08b3cefd0cf6dd1c10df4 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Apr 2019 14:02:35 -0500 Subject: [PATCH 064/320] hsomodem: Remove unneeded if statement --- ofono/drivers/hsomodem/gprs-context.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/ofono/drivers/hsomodem/gprs-context.c b/ofono/drivers/hsomodem/gprs-context.c index 340092fae..ca622480c 100644 --- a/ofono/drivers/hsomodem/gprs-context.c +++ b/ofono/drivers/hsomodem/gprs-context.c @@ -150,7 +150,6 @@ static void hso_gprs_activate_primary(struct ofono_gprs_context *gc, struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); struct cb_data *cbd = cb_data_new(cb, data); char buf[AUTH_BUF_LENGTH]; - int len; /* IPv6 support not implemented */ if (ctx->proto != OFONO_GPRS_PROTO_IP) @@ -173,11 +172,8 @@ static void hso_gprs_activate_primary(struct ofono_gprs_context *gc, NULL, NULL, NULL) == 0) goto error; - len = snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IP\"", ctx->cid); - - if (ctx->apn) - snprintf(buf + len, sizeof(buf) - len - 3, ",\"%s\"", - ctx->apn); + snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IP\",\"%s\"", + ctx->cid, ctx->apn); if (g_at_chat_send(gcd->chat, buf, none_prefix, hso_cgdcont_cb, cbd, g_free) > 0) From 4b7b30cba1d75c8b6ed79890a8ec34f12e42d2b0 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Apr 2019 14:03:08 -0500 Subject: [PATCH 065/320] icera: Remove unneeded if statement --- ofono/drivers/iceramodem/gprs-context.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ofono/drivers/iceramodem/gprs-context.c b/ofono/drivers/iceramodem/gprs-context.c index 395a9dc56..41d9d9bf5 100644 --- a/ofono/drivers/iceramodem/gprs-context.c +++ b/ofono/drivers/iceramodem/gprs-context.c @@ -332,9 +332,7 @@ static void icera_gprs_activate_primary(struct ofono_gprs_context *gc, break; } - if (ctx->apn) - snprintf(buf + len, sizeof(buf) - len - 3, - ",\"%s\"", ctx->apn); + snprintf(buf + len, sizeof(buf) - len - 3, ",\"%s\"", ctx->apn); if (g_at_chat_send(gcd->chat, buf, none_prefix, at_cgdcont_cb, cbd, g_free) > 0) From 0273831cdabb2811730736824d8afe1ffbd6c5d8 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Apr 2019 14:05:04 -0500 Subject: [PATCH 066/320] huawei: Remove unneeded if statement --- ofono/drivers/huaweimodem/gprs-context.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/ofono/drivers/huaweimodem/gprs-context.c b/ofono/drivers/huaweimodem/gprs-context.c index cae401c85..7e72ad922 100644 --- a/ofono/drivers/huaweimodem/gprs-context.c +++ b/ofono/drivers/huaweimodem/gprs-context.c @@ -256,7 +256,6 @@ static void huawei_gprs_activate_primary(struct ofono_gprs_context *gc, struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); struct cb_data *cbd = cb_data_new(cb, data); char buf[64]; - int len; /* IPv6 support not implemented */ if (ctx->proto != OFONO_GPRS_PROTO_IP) @@ -265,14 +264,10 @@ static void huawei_gprs_activate_primary(struct ofono_gprs_context *gc, DBG("cid %u", ctx->cid); gcd->active_context = ctx->cid; - cbd->user = gc; - len = snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IP\"", ctx->cid); - - if (ctx->apn) - snprintf(buf + len, sizeof(buf) - len - 3, ",\"%s\"", - ctx->apn); + snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IP\",\"%s\"", + ctx->cid, ctx->apn); if (g_at_chat_send(gcd->chat, buf, none_prefix, at_cgdcont_cb, cbd, g_free) > 0) From 2fb7b491a470dd38e81ad95e0c85b57d0e7110ea Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Apr 2019 14:07:59 -0500 Subject: [PATCH 067/320] telit: Remove unneeded if --- ofono/drivers/telitmodem/gprs-context-ncm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ofono/drivers/telitmodem/gprs-context-ncm.c b/ofono/drivers/telitmodem/gprs-context-ncm.c index 244a3dc25..e2eece77f 100644 --- a/ofono/drivers/telitmodem/gprs-context-ncm.c +++ b/ofono/drivers/telitmodem/gprs-context-ncm.c @@ -346,9 +346,7 @@ static void telitncm_gprs_activate_primary(struct ofono_gprs_context *gc, break; } - if (ctx->apn) - snprintf(buf + len, sizeof(buf) - len - 3, - ",\"%s\"", ctx->apn); + snprintf(buf + len, sizeof(buf) - len - 3, ",\"%s\"", ctx->apn); if (g_at_chat_send(gcd->chat, buf, none_prefix, setup_cb, gc, NULL) > 0) From 9aef3eb11f1325252cfb3d6965604781a8721eee Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Apr 2019 14:09:11 -0500 Subject: [PATCH 068/320] stemodem: Remove unneeded if --- ofono/drivers/stemodem/gprs-context.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/ofono/drivers/stemodem/gprs-context.c b/ofono/drivers/stemodem/gprs-context.c index 56b34388e..fb279c5a6 100644 --- a/ofono/drivers/stemodem/gprs-context.c +++ b/ofono/drivers/stemodem/gprs-context.c @@ -277,7 +277,6 @@ static void ste_gprs_activate_primary(struct ofono_gprs_context *gc, struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); struct cb_data *cbd = cb_data_new(cb, data); char buf[AUTH_BUF_LENGTH]; - int len; /* IPv6 support not implemented */ if (ctx->proto != OFONO_GPRS_PROTO_IP) @@ -291,11 +290,8 @@ static void ste_gprs_activate_primary(struct ofono_gprs_context *gc, goto error; } - len = snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IP\"", ctx->cid); - - if (ctx->apn) - snprintf(buf + len, sizeof(buf) - len, ",\"%s\"", - ctx->apn); + snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IP\",\"%s\"", + ctx->cid, ctx->apn); if (g_at_chat_send(gcd->chat, buf, none_prefix, ste_cgdcont_cb, cbd, g_free) == 0) From 422a899c422e0b5a74b8b1140f49b60308b4dda7 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Apr 2019 14:09:56 -0500 Subject: [PATCH 069/320] phoneseim: Remove unneeded if --- ofono/plugins/phonesim.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ofono/plugins/phonesim.c b/ofono/plugins/phonesim.c index 7f17c2d33..2209a35bd 100644 --- a/ofono/plugins/phonesim.c +++ b/ofono/plugins/phonesim.c @@ -161,9 +161,7 @@ static void phonesim_activate_primary(struct ofono_gprs_context *gc, break; } - if (ctx->apn) - snprintf(buf + len, sizeof(buf) - len - 3, ",\"%s\"", - ctx->apn); + snprintf(buf + len, sizeof(buf) - len - 3, ",\"%s\"", ctx->apn); /* Assume always succeeds */ if (g_at_chat_send(gcd->chat, buf, none_prefix, NULL, NULL, NULL) == 0) From fc24aafa5581869b641a38eec49822a9ea8e20ee Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Apr 2019 14:11:22 -0500 Subject: [PATCH 070/320] mbmmodem: Remove unneeded if --- ofono/drivers/mbmmodem/gprs-context.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/ofono/drivers/mbmmodem/gprs-context.c b/ofono/drivers/mbmmodem/gprs-context.c index c48e7260f..f873e2835 100644 --- a/ofono/drivers/mbmmodem/gprs-context.c +++ b/ofono/drivers/mbmmodem/gprs-context.c @@ -367,7 +367,6 @@ static void mbm_gprs_activate_primary(struct ofono_gprs_context *gc, struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); struct cb_data *cbd = cb_data_new(cb, data); char buf[AUTH_BUF_LENGTH]; - int len; /* IPv6 support not implemented */ if (ctx->proto != OFONO_GPRS_PROTO_IP) @@ -376,14 +375,10 @@ static void mbm_gprs_activate_primary(struct ofono_gprs_context *gc, DBG("cid %u", ctx->cid); gcd->active_context = ctx->cid; - cbd->user = gc; - len = snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IP\"", ctx->cid); - - if (ctx->apn) - snprintf(buf + len, sizeof(buf) - len - 3, ",\"%s\"", - ctx->apn); + snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IP\",\"%s\"", + ctx->cid, ctx->apn); if (g_at_chat_send(gcd->chat, buf, none_prefix, mbm_cgdcont_cb, cbd, g_free) == 0) From 95109f8912131c625930d0a267e3e1cdcbb75274 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Apr 2019 14:16:17 -0500 Subject: [PATCH 071/320] log: Fix potential buffer overflow We pass in the maximum size of the buffer to the read system call. On the astronomically unlikely chance that we indeed read the full buffer full of data, the subsequent assignment will overflow it. Fix this by passing sizeof(buf) - 1 to the read system call instead. --- ofono/src/log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/src/log.c b/ofono/src/log.c index 999b2d88b..a58472114 100644 --- a/ofono/src/log.c +++ b/ofono/src/log.c @@ -238,7 +238,7 @@ static void print_backtrace(unsigned int offset) if (written < 0) break; - len = read(infd[0], buf, sizeof(buf)); + len = read(infd[0], buf, sizeof(buf) - 1); if (len < 0) break; From ce3056f474c58e284182f3430262b2577387bead Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Apr 2019 14:20:25 -0500 Subject: [PATCH 072/320] qmimodem: Fix potential memory leak In case strlen(ICCID) > 20, we simply return without freeing the ICCID value first. --- ofono/drivers/qmimodem/sim-legacy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/drivers/qmimodem/sim-legacy.c b/ofono/drivers/qmimodem/sim-legacy.c index 30eb46134..601e721d1 100644 --- a/ofono/drivers/qmimodem/sim-legacy.c +++ b/ofono/drivers/qmimodem/sim-legacy.c @@ -83,13 +83,13 @@ static void get_iccid_cb(struct qmi_result *result, void *user_data) len = strlen(str); if (len > 20) { + qmi_free(str); CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data); return; } sim_encode_bcd_number(str, iccid); iccid_len = len / 2; - qmi_free(str); CALLBACK_WITH_SUCCESS(cb, iccid, iccid_len, cbd->data); From 1425e3d2373be43e74f2b2a7678817b4761ddbd7 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Apr 2019 14:24:48 -0500 Subject: [PATCH 073/320] sim: Dereference only after validating !NULL --- ofono/src/sim.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ofono/src/sim.c b/ofono/src/sim.c index b8b3a78ba..32562d0ab 100644 --- a/ofono/src/sim.c +++ b/ofono/src/sim.c @@ -2603,11 +2603,13 @@ struct ofono_sim_context *ofono_sim_context_create(struct ofono_sim *sim) struct ofono_sim_context *ofono_sim_context_create_isim( struct ofono_sim *sim) { - GSList *iter = sim->aid_sessions; + GSList *iter; if (sim == NULL || sim->simfs_isim == NULL) return NULL; + iter = sim->aid_sessions; + /* Find the AID */ while (iter) { struct ofono_sim_aid_session *session = iter->data; From d81097a02a884cbc673cfb556dc2ad2d90ddecf7 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Apr 2019 14:26:43 -0500 Subject: [PATCH 074/320] handsfree: Dereference after validating !NULL --- ofono/src/handsfree.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ofono/src/handsfree.c b/ofono/src/handsfree.c index 921e0bd7e..dccc449c6 100644 --- a/ofono/src/handsfree.c +++ b/ofono/src/handsfree.c @@ -174,7 +174,7 @@ void ofono_handsfree_battchg_notify(struct ofono_handsfree *hf, unsigned char level) { DBusConnection *conn = ofono_dbus_get_connection(); - const char *path = __ofono_atom_get_path(hf->atom); + const char *path; if (hf == NULL) return; @@ -187,6 +187,7 @@ void ofono_handsfree_battchg_notify(struct ofono_handsfree *hf, if (__ofono_atom_get_registered(hf->atom) == FALSE) return; + path = __ofono_atom_get_path(hf->atom); ofono_dbus_signal_property_changed(conn, path, OFONO_HANDSFREE_INTERFACE, "BatteryChargeLevel", DBUS_TYPE_BYTE, From 2a4f68bcdecf560eff9cc1db614c68daa391d146 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Apr 2019 14:27:54 -0500 Subject: [PATCH 075/320] siri: Dereference after validating !NULL --- ofono/src/siri.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ofono/src/siri.c b/ofono/src/siri.c index 88888dcf9..82715d384 100644 --- a/ofono/src/siri.c +++ b/ofono/src/siri.c @@ -54,7 +54,7 @@ struct ofono_siri { void ofono_siri_set_status(struct ofono_siri *siri, int value) { DBusConnection *conn = ofono_dbus_get_connection(); - const char *path = __ofono_atom_get_path(siri->atom); + const char *path; dbus_bool_t siri_status; if (siri == NULL) @@ -70,6 +70,7 @@ void ofono_siri_set_status(struct ofono_siri *siri, int value) if (__ofono_atom_get_registered(siri->atom) == FALSE) return; + path = __ofono_atom_get_path(siri->atom); ofono_dbus_signal_property_changed(conn, path, OFONO_SIRI_INTERFACE, "Enabled", DBUS_TYPE_BOOLEAN, &siri_status); From 5c8ede46b31921ece93e6d8db36d831c201f9e31 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Apr 2019 14:29:21 -0500 Subject: [PATCH 076/320] gatchat: Remove unneeded if --- ofono/gatchat/gatmux.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ofono/gatchat/gatmux.c b/ofono/gatchat/gatmux.c index 9660006b0..757a5123a 100644 --- a/ofono/gatchat/gatmux.c +++ b/ofono/gatchat/gatmux.c @@ -952,8 +952,7 @@ gboolean g_at_mux_setup_gsm0710(GAtChat *chat, mux_query_cb, msd, msd_free) > 0) return TRUE; - if (msd) - msd_free(msd); + msd_free(msd); return FALSE; } From 764b0a2ade4869d1fc62a509d89717146132dd30 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Apr 2019 14:34:00 -0500 Subject: [PATCH 077/320] stkutil: Call va_end on failure --- ofono/src/stkutil.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ofono/src/stkutil.c b/ofono/src/stkutil.c index da5ecd5ec..dfce9ec4f 100644 --- a/ofono/src/stkutil.c +++ b/ofono/src/stkutil.c @@ -5417,8 +5417,10 @@ static bool build_dataobj(struct stk_tlv_builder *tlv, const void *data = va_arg(args, const void *); bool cr = (flags & DATAOBJ_FLAG_CR) ? true : false; - if (!builder_func(tlv, data, cr)) + if (!builder_func(tlv, data, cr)) { + va_end(args); return false; + } builder_func = va_arg(args, dataobj_writer); } From bd4caed9915793ebb3d43025514a7da4587ea4da Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Apr 2019 19:16:07 -0500 Subject: [PATCH 078/320] phonebook: fix invalid sprintf sequence --- ofono/src/phonebook.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/src/phonebook.c b/ofono/src/phonebook.c index 391b7d306..007cb76eb 100644 --- a/ofono/src/phonebook.c +++ b/ofono/src/phonebook.c @@ -179,7 +179,7 @@ static void vcard_printf_number(GString *vcards, const char *number, int type, if ((type == TYPE_INTERNATIONAL) && (number[0] != '+')) intl = "+"; - snprintf(buf, sizeof(buf), "TEL;TYPE=\%s%s:\%s\%s", pref, + snprintf(buf, sizeof(buf), "TEL;TYPE=%s%s:%s%s", pref, category_string, intl, number); vcard_printf(vcards, buf, number); } From ebe6734dbe6763ffd40172132873df377b4e0be3 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Apr 2019 19:25:57 -0500 Subject: [PATCH 079/320] gprs: Remove unneeded if statement if (ctx->message_proxy) always resolves to TRUE --- ofono/src/gprs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ofono/src/gprs.c b/ofono/src/gprs.c index e8216cf37..ef39a87cb 100644 --- a/ofono/src/gprs.c +++ b/ofono/src/gprs.c @@ -820,8 +820,7 @@ static void pri_update_mms_context_settings(struct pri_context *ctx) struct ofono_gprs_context *gc = ctx->context_driver; struct context_settings *settings = gc->settings; - if (ctx->message_proxy) - settings->ipv4->proxy = g_strdup(ctx->message_proxy); + settings->ipv4->proxy = g_strdup(ctx->message_proxy); if (!pri_parse_proxy(ctx, ctx->message_proxy)) pri_parse_proxy(ctx, ctx->message_center); From 7ec592d97e64a446b6327ecb47d5f37c8567742c Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Apr 2019 19:27:29 -0500 Subject: [PATCH 080/320] gprs: Fix invalid string comparison The default context created when provisioning fails is simply a context with an empty APN --- ofono/src/gprs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/src/gprs.c b/ofono/src/gprs.c index ef39a87cb..d7ec775a5 100644 --- a/ofono/src/gprs.c +++ b/ofono/src/gprs.c @@ -2320,7 +2320,7 @@ static struct pri_context *find_usable_context(struct ofono_gprs *gprs, for (l = gprs->contexts; l; l = l->next) { pri_ctx = l->data; - if (pri_ctx->context.apn == NULL) + if (pri_ctx->context.apn[0] == '\0') return pri_ctx; } From 0621b18a1f8985ca6a66c0ced3669d784763f10e Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Apr 2019 19:28:59 -0500 Subject: [PATCH 081/320] gprs: Remove unneeded if conditions ctx->message_center and ctx->message_proxy are arrays and thus always evaluate as true --- ofono/src/gprs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ofono/src/gprs.c b/ofono/src/gprs.c index d7ec775a5..13a0ada9f 100644 --- a/ofono/src/gprs.c +++ b/ofono/src/gprs.c @@ -1458,7 +1458,7 @@ static DBusMessage *pri_set_message_proxy(struct pri_context *ctx, if (strlen(proxy) > MAX_MESSAGE_PROXY_LENGTH) return __ofono_error_invalid_format(msg); - if (ctx->message_proxy && g_str_equal(ctx->message_proxy, proxy)) + if (g_str_equal(ctx->message_proxy, proxy)) return dbus_message_new_method_return(msg); strcpy(ctx->message_proxy, proxy); @@ -1487,7 +1487,7 @@ static DBusMessage *pri_set_message_center(struct pri_context *ctx, if (strlen(center) > MAX_MESSAGE_CENTER_LENGTH) return __ofono_error_invalid_format(msg); - if (ctx->message_center && g_str_equal(ctx->message_center, center)) + if (g_str_equal(ctx->message_center, center)) return dbus_message_new_method_return(msg); strcpy(ctx->message_center, center); From c871cc57a923ecd65b8622fae71eed088f6029ea Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Apr 2019 19:38:12 -0500 Subject: [PATCH 082/320] message-waiting: Fix logic error --- ofono/src/message-waiting.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ofono/src/message-waiting.c b/ofono/src/message-waiting.c index a356e9016..6115d495f 100644 --- a/ofono/src/message-waiting.c +++ b/ofono/src/message-waiting.c @@ -753,8 +753,8 @@ static void mw_set_indicator(struct ofono_message_waiting *mw, int profile, efmwis[0] = mw->messages[0].indication ? 0xa : 0x5; if (mw->ef_cphs_mwis_length > 1) - efmwis[1] = mw->messages[1].indication ? 0xa : 0x5 | - mw->messages[3].indication ? 0xa0 : 0x50; + efmwis[1] = (mw->messages[1].indication ? 0xa : 0x5) | + (mw->messages[3].indication ? 0xa0 : 0x50); if (ofono_sim_write(mw->sim_context, SIM_EF_CPHS_MWIS_FILEID, mw_mwis_write_cb, From ca45c591058d41d2dcb09ce59ad76240aef42f04 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Tue, 30 Apr 2019 11:09:52 -0500 Subject: [PATCH 083/320] sim-auth: Use memcpy instead of strncpy The code is not really copying strings but 2 or 3 character sof the MNC. Make this clearer. --- ofono/src/sim-auth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ofono/src/sim-auth.c b/ofono/src/sim-auth.c index c23b44fba..0e94a2249 100644 --- a/ofono/src/sim-auth.c +++ b/ofono/src/sim-auth.c @@ -679,10 +679,10 @@ static char *build_nai(const char *imsi) strncpy(mcc, imsi, 3); if (strlen(imsi) == 16) { - strncpy(mnc, imsi + 3, 3); + memcpy(mnc, imsi + 3, 3); } else { mnc[0] = '0'; - strncpy(mnc + 1, imsi + 3, 2); + memcpy(mnc + 1, imsi + 3, 2); } nai = g_strdup_printf("%s@ims.mnc%.3s.mcc%.3s.3gppnetwork.org", From 2ed75bc603274fd3c4a79b0842f55f9d114deb31 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Tue, 30 Apr 2019 11:38:36 -0500 Subject: [PATCH 084/320] netmon: Fix logic error --- ofono/src/netmon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/src/netmon.c b/ofono/src/netmon.c index 62e0ec0b8..6c19df523 100644 --- a/ofono/src/netmon.c +++ b/ofono/src/netmon.c @@ -288,7 +288,7 @@ static DBusMessage *netmon_get_serving_cell_info(DBusConnection *conn, { struct ofono_netmon *netmon = data; - if (!netmon->driver && !netmon->driver->request_update) + if (!netmon->driver->request_update) return __ofono_error_not_implemented(msg); if (netmon->pending) From f71949ca85b419faeaa346d54f964eabd5c99ef4 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Tue, 30 Apr 2019 11:40:17 -0500 Subject: [PATCH 085/320] voicecall: Fix possible crash --- ofono/src/voicecall.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ofono/src/voicecall.c b/ofono/src/voicecall.c index 5e956dfae..3a5c7f4a2 100644 --- a/ofono/src/voicecall.c +++ b/ofono/src/voicecall.c @@ -4469,6 +4469,9 @@ void __ofono_voicecall_tone_cancel(struct ofono_voicecall *vc, int id) if (entry->id == id) break; + if (!entry) + return; + tone_request_finish(vc, entry, 0, FALSE); /* From cc941d505253090f6f9b87418e84da85a70c475c Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Tue, 30 Apr 2019 11:41:39 -0500 Subject: [PATCH 086/320] sierra: Abort initialization on CFUN failure --- ofono/plugins/sierra.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ofono/plugins/sierra.c b/ofono/plugins/sierra.c index 458fec2ff..70d0d11bd 100644 --- a/ofono/plugins/sierra.c +++ b/ofono/plugins/sierra.c @@ -149,6 +149,8 @@ static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data) if (!ok) { g_at_chat_unref(data->modem); data->modem = NULL; + ofono_modem_set_powered(modem, FALSE); + return; } data->sim_state_query = at_util_sim_state_query_new(data->modem, From a6d442913c53f833ef108cdc5f1fc62e84822b39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Wed, 8 May 2019 09:27:56 +0200 Subject: [PATCH 087/320] atmodem: Fix a race if a context get deactivated while read When a context gets activated we read its settings, but if the context gets deactivated during this time we should not indicate that the context is activated when the settings are received. --- ofono/drivers/atmodem/gprs.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ofono/drivers/atmodem/gprs.c b/ofono/drivers/atmodem/gprs.c index d3fd893cc..dd734585c 100644 --- a/ofono/drivers/atmodem/gprs.c +++ b/ofono/drivers/atmodem/gprs.c @@ -161,6 +161,11 @@ static void at_cgdcont_read_cb(gboolean ok, GAtResult *result, return; } + if (gd->last_auto_context_id == 0) { + DBG("Context got deactivated while calling CGDCONT"); + return; + } + g_at_result_iter_init(&iter, result); while (g_at_result_iter_next(&iter, "+CGDCONT:")) { @@ -251,6 +256,12 @@ static void cgev_notify(GAtResult *result, gpointer user_data) g_at_chat_send(gd->chat, "AT+CGDCONT?", cgdcont_prefix, at_cgdcont_read_cb, gprs, NULL); + } else if (g_str_has_prefix(event, "ME PDN DEACT")) { + unsigned int context_id; + sscanf(event, "%*s %*s %*s %u", &context_id); + /* Indicate that this cid is not activated anymore */ + if (gd->last_auto_context_id == context_id) + gd->last_auto_context_id = 0; } } From 8b583a7233dbf2d135370bf3ad19ef7c6cddbee7 Mon Sep 17 00:00:00 2001 From: Stefan Herbrechtsmeier Date: Wed, 8 May 2019 14:01:12 +0000 Subject: [PATCH 088/320] udevng: add SIMCom SIM7600 modem support The SIMCom SIM7100 and SIM7600 modem use the same vendor and product id but require different drivers (sim7100 vs gobi). --- ofono/plugins/udevng.c | 72 +++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 22 deletions(-) diff --git a/ofono/plugins/udevng.c b/ofono/plugins/udevng.c index 1c0fb2bd1..f0474681f 100644 --- a/ofono/plugins/udevng.c +++ b/ofono/plugins/udevng.c @@ -1240,9 +1240,11 @@ static gboolean setup_xmm7xxx(struct modem_info *modem) return TRUE; } -static gboolean setup_sim7100(struct modem_info *modem) +static gboolean setup_sim7x00(struct modem_info *modem) { - const char *at = NULL, *ppp = NULL, *gps = NULL, *diag = NULL, *audio = NULL; + const char *audio = NULL, *diag = NULL, *gps = NULL; + const char *mdm = NULL, *net = NULL, *ppp = NULL; + const char *qmi = NULL; GSList *list; DBG("%s", modem->syspath); @@ -1250,10 +1252,12 @@ static gboolean setup_sim7100(struct modem_info *modem) for (list = modem->devices; list; list = list->next) { struct device_info *info = list->data; - DBG("%s %s", info->devnode, info->number); + DBG("%s %s %s %s %s %s", info->devnode, info->interface, + info->number, info->label, + info->sysattr, info->subsystem); /* - * Serial port layout: + * SIM7100 serial port layout: * 0: QCDM/DIAG * 1: NMEA * 2: AT @@ -1262,29 +1266,52 @@ static gboolean setup_sim7100(struct modem_info *modem) * * -- https://www.spinics.net/lists/linux-usb/msg135728.html */ - if (g_strcmp0(info->number, "00") == 0) - diag = info->devnode; - else if (g_strcmp0(info->number, "01") == 0) - gps = info->devnode; - else if (g_strcmp0(info->number, "02") == 0) - at = info->devnode; - else if (g_strcmp0(info->number, "03") == 0) - ppp = info->devnode; - else if (g_strcmp0(info->number, "04") == 0) - audio = info->devnode; + if (g_strcmp0(info->subsystem, "usbmisc") == 0) /* cdc-wdm */ + qmi = info->devnode; /* SIM7600 */ + else if (g_strcmp0(info->subsystem, "net") == 0) /* wwan */ + net = info->devnode; /* SIM7600 */ + else if (g_strcmp0(info->subsystem, "tty") == 0) { + if (g_strcmp0(info->interface, "255/255/255") == 0) { + if (g_strcmp0(info->number, "00") == 0) + diag = info->devnode; /* SIM7x00 */ + } else if (g_strcmp0(info->interface, "255/0/0") == 0) { + if (g_strcmp0(info->number, "01") == 0) + gps = info->devnode; /* SIM7x00 */ + else if (g_strcmp0(info->number, "02") == 0) + mdm = info->devnode; /* SIM7x00 */ + else if (g_strcmp0(info->number, "03") == 0) + ppp = info->devnode; /* SIM7100 */ + else if (g_strcmp0(info->number, "04") == 0) + audio = info->devnode; /* SIM7100 */ + } + } } - if (at == NULL) + if (mdm == NULL) return FALSE; - DBG("at=%s ppp=%s gps=%s diag=%s, audio=%s", at, ppp, gps, diag, audio); + if (qmi != NULL && net != NULL) { + DBG("qmi=%s net=%s mdm=%s gps=%s diag=%s", + qmi, net, mdm, gps, diag); + + ofono_modem_set_driver(modem->modem, "gobi"); + + ofono_modem_set_string(modem->modem, "Device", qmi); + ofono_modem_set_string(modem->modem, "Modem", mdm); + ofono_modem_set_string(modem->modem, "NetworkInterface", net); + } else { + DBG("at=%s ppp=%s gps=%s diag=%s, audio=%s", + mdm, ppp, gps, diag, audio); + + ofono_modem_set_driver(modem->modem, "sim7100"); + + ofono_modem_set_string(modem->modem, "AT", mdm); + ofono_modem_set_string(modem->modem, "PPP", ppp); + ofono_modem_set_string(modem->modem, "Audio", audio); + } - ofono_modem_set_string(modem->modem, "AT", at); - ofono_modem_set_string(modem->modem, "PPP", ppp); ofono_modem_set_string(modem->modem, "GPS", gps); ofono_modem_set_string(modem->modem, "Diag", diag); - ofono_modem_set_string(modem->modem, "Audio", audio); - return TRUE; } @@ -1308,7 +1335,7 @@ static struct { { "telit", setup_telit, "device/interface" }, { "telitqmi", setup_telitqmi }, { "simcom", setup_simcom }, - { "sim7100", setup_sim7100 }, + { "sim7x00", setup_sim7x00 }, { "zte", setup_zte }, { "icera", setup_icera }, { "samsung", setup_samsung }, @@ -1681,7 +1708,8 @@ static struct { { "novatel", "option", "1410" }, { "zte", "option", "19d2" }, { "simcom", "option", "05c6", "9000" }, - { "sim7100", "option", "1e0e", "9001" }, + { "sim7x00", "option", "1e0e", "9001" }, + { "sim7x00", "qmi_wwan", "1e0e", "9001" }, { "telit", "usbserial", "1bc7" }, { "telit", "option", "1bc7" }, { "telit", "cdc_acm", "1bc7", "0021" }, From caf4265cb73351e260015af7af47e9b9b3ebff4e Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Wed, 8 May 2019 09:47:16 -0500 Subject: [PATCH 089/320] AUTHORS: Mention Stefan's contributions --- ofono/AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/ofono/AUTHORS b/ofono/AUTHORS index bd9568111..796b2680f 100644 --- a/ofono/AUTHORS +++ b/ofono/AUTHORS @@ -144,3 +144,4 @@ Pau Espin Pedrol Khaled Romdhani Pavel Machek Tom Nguyen +Stefan Herbrechtsmeier From e4d0a3baa4d441620803b72bbf89df61f067746c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 15 May 2019 09:39:44 +0200 Subject: [PATCH 090/320] build: Add check for explicit_bzero support --- ofono/configure.ac | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ofono/configure.ac b/ofono/configure.ac index 397983972..7c4d92027 100644 --- a/ofono/configure.ac +++ b/ofono/configure.ac @@ -55,6 +55,8 @@ AC_ARG_ENABLE(pie, AC_HELP_STRING([--enable-pie], fi ]) +AC_CHECK_FUNCS(explicit_bzero) + AC_CHECK_FUNC(signalfd, dummy=yes, AC_MSG_ERROR(signalfd support is required)) From 3d386f158d2a448ee3dde26bc06f3aa32ffafcbd Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 15 May 2019 17:04:16 +0200 Subject: [PATCH 091/320] gatchat: Avoid string overflow warning in debug function --- ofono/gatchat/gatutil.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ofono/gatchat/gatutil.c b/ofono/gatchat/gatutil.c index a2528e13a..ea433bcb1 100644 --- a/ofono/gatchat/gatutil.c +++ b/ofono/gatchat/gatutil.c @@ -67,8 +67,7 @@ void g_at_util_debug_chat(gboolean in, const char *str, gsize len, escaped_str[0] = type; escaped_str[1] = ' '; - escaped_str[2] = '\0'; - escaped_str[escaped] = '\0'; + memset(escaped_str + 2, '\0', escaped - 2); for (escaped = 2, i = 0; i < len; i++) { unsigned char c = str[i]; @@ -87,11 +86,11 @@ void g_at_util_debug_chat(gboolean in, const char *str, gsize len, escaped_str[escaped++] = 'n'; break; case 26: - strncpy(&escaped_str[escaped], ctrlz, ctrlz_size); + memcpy(escaped_str + escaped, ctrlz, ctrlz_size); escaped += ctrlz_size; break; case 25: - strncpy(&escaped_str[escaped], esc, esc_size); + memcpy(escaped_str + escaped, esc, esc_size); escaped += esc_size; break; default: From 5e08e3d54b440845ab54f0d39d5d6e63b9f132f4 Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Mon, 13 May 2019 14:19:15 +0530 Subject: [PATCH 092/320] radio-settings: adding UE dual mode operation property Added two new values for TechnologyPreference property as follows: "umts,gsm" Dual mode operation with UMTS and GSM radio access whith preference for UMTS. "lte,umts" Dual mode operation with LTE and UMTS radio access with preference for LTE. --- ofono/doc/radio-settings-api.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ofono/doc/radio-settings-api.txt b/ofono/doc/radio-settings-api.txt index 03868a9b1..9663b07f9 100644 --- a/ofono/doc/radio-settings-api.txt +++ b/ofono/doc/radio-settings-api.txt @@ -44,6 +44,12 @@ Properties string TechnologyPreference [readwrite] "gsm" Only GSM used for radio access. "umts" Only UMTS used for radio access. "lte" Only LTE used for radio access. + "umts,gsm" Dual mode operation with UMTS + and GSM radio access whith preference + for UMTS. + "lte,umts" Dual mode operation with LTE + and UMTS radio access with preference + for LTE. array{string} AvailableTechnologies [readonly, optional] From 2e895ba29b5015acb98bfa57218072b9d089a33b Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Mon, 13 May 2019 14:20:12 +0530 Subject: [PATCH 093/320] radio-settings: handling of dual mode technology preference Handled two new dual mode technology preferences "umts,gsm" and "lte,umts". --- ofono/src/radio-settings.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/ofono/src/radio-settings.c b/ofono/src/radio-settings.c index 9063a8fa2..6d4169a5a 100644 --- a/ofono/src/radio-settings.c +++ b/ofono/src/radio-settings.c @@ -86,9 +86,15 @@ const char *ofono_radio_access_mode_to_string(enum ofono_radio_access_mode m) return "umts"; case OFONO_RADIO_ACCESS_MODE_LTE: return "lte"; - default: - return NULL; } + + if (m == (OFONO_RADIO_ACCESS_MODE_UMTS|OFONO_RADIO_ACCESS_MODE_GSM)) + return "umts,gsm"; + + if (m == (OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_UMTS)) + return "lte,umts"; + + return NULL; } #define radio_access_mode_from_string ofono_radio_access_mode_from_string @@ -110,6 +116,12 @@ ofono_bool_t ofono_radio_access_mode_from_string(const char *str, } else if (g_str_equal(str, "lte")) { *mode = OFONO_RADIO_ACCESS_MODE_LTE; return TRUE; + } else if (g_str_equal(str, "umts,gsm")) { + *mode = OFONO_RADIO_ACCESS_MODE_UMTS|OFONO_RADIO_ACCESS_MODE_GSM; + return TRUE; + } else if (g_str_equal(str, "lte,umts")) { + *mode = OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_UMTS; + return TRUE; } return FALSE; From 6e5a5b7843415e8c3b1e3f15a94b48dbf6e80084 Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Mon, 13 May 2019 14:20:43 +0530 Subject: [PATCH 094/320] xmm7modem: handling of dual mode technology preference Handled dual mode technology preference "umts,gsm" and "lte,umts" for xmm7modem. --- ofono/drivers/xmm7modem/radio-settings.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/ofono/drivers/xmm7modem/radio-settings.c b/ofono/drivers/xmm7modem/radio-settings.c index f1eb1aa9b..c7c2ce0e8 100644 --- a/ofono/drivers/xmm7modem/radio-settings.c +++ b/ofono/drivers/xmm7modem/radio-settings.c @@ -84,10 +84,10 @@ static void xact_query_cb(gboolean ok, GAtResult *result, gpointer user_data) mode = OFONO_RADIO_ACCESS_MODE_LTE; break; case 3: - mode = OFONO_RADIO_ACCESS_MODE_UMTS; + mode = OFONO_RADIO_ACCESS_MODE_UMTS|OFONO_RADIO_ACCESS_MODE_GSM; break; case 4: - mode = OFONO_RADIO_ACCESS_MODE_LTE; + mode = OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_UMTS; break; case 5: mode = OFONO_RADIO_ACCESS_MODE_LTE; @@ -158,7 +158,16 @@ static void xmm_set_rat_mode(struct ofono_radio_settings *rs, break; } - if (value == 6) + if (mode == + (OFONO_RADIO_ACCESS_MODE_UMTS|OFONO_RADIO_ACCESS_MODE_GSM)) { + value = 3; + preferred = 1; + } + + if (mode == (OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_UMTS)) + value = 4; + + if (value == 6 || value == 3 || value == 4) snprintf(buf, sizeof(buf), "AT+XACT=%u,%u", value, preferred); else snprintf(buf, sizeof(buf), "AT+XACT=%u", value); From 531eaed9114ab86cfea035fb0918db00b9e5df24 Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Wed, 15 May 2019 16:40:13 +0530 Subject: [PATCH 095/320] xmm7modem: enabling simtoolkit in modem driver handled enabling of stk for xmm7modem vendor in atmodem driver. --- ofono/drivers/atmodem/stk.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ofono/drivers/atmodem/stk.c b/ofono/drivers/atmodem/stk.c index f0dc5c036..b2d208159 100644 --- a/ofono/drivers/atmodem/stk.c +++ b/ofono/drivers/atmodem/stk.c @@ -191,6 +191,19 @@ static gboolean at_stk_register(gpointer user) g_at_chat_register(sd->chat, "*HCMD:", phonesim_hcmd_notify, FALSE, stk, NULL); + if (sd->vendor == OFONO_VENDOR_XMM) { + /* enabling stk */ + g_at_chat_send(sd->chat, "AT+CFUN=6", none_prefix, + NULL, NULL, NULL); + /* Here ofono has missed stk menu proactive command + * that comes after sim initialization only. Doing a + * sim reset will enable the stk driver to get the + * missed +CUSATP notifications. + */ + g_at_chat_send(sd->chat, "AT+CFUN=27,1", none_prefix, + NULL, NULL, NULL); + } + ofono_stk_register(stk); return FALSE; From ce343b18684815cb13a744f26b7523e907714fdf Mon Sep 17 00:00:00 2001 From: Adam Pigg Date: Sun, 13 Feb 2022 17:30:07 +0000 Subject: [PATCH 096/320] stemodem: Quiet warning about strncpy use --- ofono/drivers/stemodem/caif_rtnl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/drivers/stemodem/caif_rtnl.c b/ofono/drivers/stemodem/caif_rtnl.c index 1a42c144c..584c5a4a7 100644 --- a/ofono/drivers/stemodem/caif_rtnl.c +++ b/ofono/drivers/stemodem/caif_rtnl.c @@ -85,7 +85,7 @@ static void parse_newlink_param(struct ifinfomsg *msg, int size, if (attr->rta_type == IFLA_IFNAME && ifname != NULL) { - strncpy(ifname, RTA_DATA(attr), IF_NAMESIZE); + strncpy(ifname, RTA_DATA(attr), IF_NAMESIZE - 1); ifname[IF_NAMESIZE-1] = '\0'; break; } From 8312c988e806f6995bcd2d2eea2a731fe39173ea Mon Sep 17 00:00:00 2001 From: Adam Pigg Date: Sun, 13 Feb 2022 17:35:00 +0000 Subject: [PATCH 097/320] core: Quiet warning about strncpy use --- ofono/src/handsfree.c | 2 +- ofono/src/sim-auth.c | 2 +- ofono/src/voicecall.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ofono/src/handsfree.c b/ofono/src/handsfree.c index dccc449c6..aea5fa5f4 100644 --- a/ofono/src/handsfree.c +++ b/ofono/src/handsfree.c @@ -296,7 +296,7 @@ static void hf_cnum_callback(const struct ofono_error *error, int total, subscriber_number->type = numbers[num].type; strncpy(subscriber_number->number, numbers[num].number, - OFONO_MAX_PHONE_NUMBER_LENGTH + 1); + OFONO_MAX_PHONE_NUMBER_LENGTH); hf->subscriber_numbers = g_slist_prepend(hf->subscriber_numbers, subscriber_number); diff --git a/ofono/src/sim-auth.c b/ofono/src/sim-auth.c index 0e94a2249..269b38933 100644 --- a/ofono/src/sim-auth.c +++ b/ofono/src/sim-auth.c @@ -676,7 +676,7 @@ static char *build_nai(const char *imsi) char mnc[3]; char *nai; - strncpy(mcc, imsi, 3); + memcpy(mcc, imsi, 3); if (strlen(imsi) == 16) { memcpy(mnc, imsi + 3, 3); diff --git a/ofono/src/voicecall.c b/ofono/src/voicecall.c index 3a5c7f4a2..a49488ef9 100644 --- a/ofono/src/voicecall.c +++ b/ofono/src/voicecall.c @@ -4032,7 +4032,7 @@ static void emulator_atd_cb(struct ofono_emulator *em, emulator_dial(em, vc, num); } else { - strncpy(number, str, len - 1); + memcpy(number, str, len - 1); number[len - 1] = '\0'; emulator_dial(em, vc, number); From e3f8f4cbfb7fe5e26d966726e0cc1be486f9fc10 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Thu, 16 May 2019 15:10:53 -0500 Subject: [PATCH 098/320] main: Quiet ld errors with external ell When oFono is built with --enable-external-ell, the compiler for some reason does not generate a debug section on some systems. This is due to the fact that l_debug is never called. However, ell also does not call l_debug, yet when built-in ell is used, the section is created by the compiler. For now work around this by adding a no-op l_debug() call in main.c. The real fix is to migrate all of the oFono logging functionality to use ell instead. --- ofono/src/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ofono/src/main.c b/ofono/src/main.c index 5bca6d582..dbb0a13bb 100644 --- a/ofono/src/main.c +++ b/ofono/src/main.c @@ -249,6 +249,7 @@ int main(int argc, char **argv) #ifdef HAVE_ELL l_log_set_stderr(); + l_debug(""); l_debug_enable("*"); l_main_init(); From 55d75943b97230a941f7d704fd8055e56c944a0d Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 24 May 2019 12:27:27 -0500 Subject: [PATCH 099/320] qmi: Fix style issues --- ofono/drivers/qmimodem/qmi.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ofono/drivers/qmimodem/qmi.c b/ofono/drivers/qmimodem/qmi.c index 19ec13038..4cd1530f4 100644 --- a/ofono/drivers/qmimodem/qmi.c +++ b/ofono/drivers/qmimodem/qmi.c @@ -477,7 +477,8 @@ static const char *__error_to_string(uint16_t error) return NULL; } -int qmi_error_to_ofono_cme(int qmi_error) { +int qmi_error_to_ofono_cme(int qmi_error) +{ switch (qmi_error) { case 0x0019: return 4; /* Not Supported */ @@ -1209,10 +1210,10 @@ static void discover_callback(uint16_t message, uint16_t length, if (name) __debug_device(device, "found service [%s %d.%d]", - name, major, minor); + name, major, minor); else __debug_device(device, "found service [%d %d.%d]", - type, major, minor); + type, major, minor); if (type == QMI_SERVICE_CONTROL) { device->control_major = major; From 051afd1adf0299c96f9ad8580263aa30b15f905e Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Thu, 30 May 2019 14:50:31 +0530 Subject: [PATCH 100/320] netmon: adding method to fetch neighbouring cell mesurement Added new method to fetch neighbouring cell information. --- ofono/doc/networkmonitor-api.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/ofono/doc/networkmonitor-api.txt b/ofono/doc/networkmonitor-api.txt index f8cc1c2e9..1cc73d2ca 100644 --- a/ofono/doc/networkmonitor-api.txt +++ b/ofono/doc/networkmonitor-api.txt @@ -22,6 +22,23 @@ Methods a{sv} GetServingCellInformation() are available, their valid value ranges and applicability to different cell types. + a{a{sv}} GetNeighbouringCellsInformation() + + Requests the neighbouring cells information and basic + measurements from oFono. The returned value is a + dictionary with the possible key / values documented + below. The type of cell is given by the 'Technology' + property. + + Based on the type of cell, the dictionary will contain + additional key/value pairs. If a given key/value pair + is not present, then it is not known or unsupported + by the underlying driver. + + Refer to the sections below for which property types + are available, their valid value ranges and + applicability to different cell types. + void RegisterAgent(object path) Registers an agent which will be called whenever the From 6a074960c6bcb5fe13f3d35b62c0957b3f3c367d Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 31 May 2019 10:57:38 -0500 Subject: [PATCH 101/320] hfp_ag_bluez5: Remove unneeded forward declarations --- ofono/plugins/hfp_ag_bluez5.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/ofono/plugins/hfp_ag_bluez5.c b/ofono/plugins/hfp_ag_bluez5.c index 7653c4df2..edba5666d 100644 --- a/ofono/plugins/hfp_ag_bluez5.c +++ b/ofono/plugins/hfp_ag_bluez5.c @@ -38,9 +38,6 @@ #include #include -typedef struct GAtChat GAtChat; -typedef struct GAtResult GAtResult; - #include "drivers/atmodem/atutil.h" #include "hfp.h" From 958e5fd45f8a0741a0936825054fbb82163e38a5 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 31 May 2019 11:05:17 -0500 Subject: [PATCH 102/320] atutil: Introduce at_util_open_device --- ofono/drivers/atmodem/atutil.c | 55 ++++++++++++++++++++++++++++++++-- ofono/drivers/atmodem/atutil.h | 8 +++++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/ofono/drivers/atmodem/atutil.c b/ofono/drivers/atmodem/atutil.c index 7ed347813..631a5b36f 100644 --- a/ofono/drivers/atmodem/atutil.c +++ b/ofono/drivers/atmodem/atutil.c @@ -24,15 +24,17 @@ #include #endif -#include -#include #include #include #include +#include +#include + #define OFONO_API_SUBJECT_TO_CHANGE #include #include +#include #include "atutil.h" #include "vendor.h" @@ -737,3 +739,52 @@ char *at_util_get_cgdcont_command(guint cid, enum ofono_gprs_proto proto, return g_strdup_printf("AT+CGDCONT=%u,\"%s\",\"%s\"", cid, pdp_type, apn); } + +GAtChat *at_util_open_device(struct ofono_modem *modem, const char *key, + GAtDebugFunc debug_func, char *debug_prefix, + char *tty_option, ...) +{ + const char *device; + va_list args; + GIOChannel *channel; + GAtSyntax *syntax; + GAtChat *chat; + GHashTable *options = NULL; + + device = ofono_modem_get_string(modem, key); + if (device == NULL) + return NULL; + + if (tty_option) { + options = g_hash_table_new(g_str_hash, g_str_equal); + if (options == NULL) + return NULL; + + va_start(args, tty_option); + while (tty_option) { + gpointer value = (gpointer) va_arg(args, const char *); + + g_hash_table_insert(options, tty_option, value); + tty_option = (gpointer) va_arg(args, const char *); + } + } + + channel = g_at_tty_open(device, options); + g_hash_table_destroy(options); + + if (channel == NULL) + return NULL; + + syntax = g_at_syntax_new_gsm_permissive(); + chat = g_at_chat_new(channel, syntax); + g_at_syntax_unref(syntax); + g_io_channel_unref(channel); + + if (chat == NULL) + return NULL; + + if (getenv("OFONO_AT_DEBUG")) + g_at_chat_set_debug(chat, debug_func, debug_prefix); + + return chat; +} diff --git a/ofono/drivers/atmodem/atutil.h b/ofono/drivers/atmodem/atutil.h index 61800ff4a..fe2acb390 100644 --- a/ofono/drivers/atmodem/atutil.h +++ b/ofono/drivers/atmodem/atutil.h @@ -20,6 +20,10 @@ * */ +#include + +struct ofono_modem; + enum at_util_sms_store { AT_UTIL_SMS_STORE_SM = 0, AT_UTIL_SMS_STORE_ME = 1, @@ -169,3 +173,7 @@ static inline int at_util_convert_signal_strength(int strength) e.error = 0; \ f(&e, ##args); \ } while (0) + +GAtChat *at_util_open_device(struct ofono_modem *modem, const char *key, + GAtDebugFunc debug_func, char *debug_prefix, + char *tty_option, ...); From a16f127af6f173038bc1fc0910cdbe60ef989797 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 31 May 2019 11:18:32 -0500 Subject: [PATCH 103/320] wavecom: Use at_util_open_device --- ofono/plugins/wavecom.c | 48 +++++++---------------------------------- 1 file changed, 8 insertions(+), 40 deletions(-) diff --git a/ofono/plugins/wavecom.c b/ofono/plugins/wavecom.c index 7f24eae91..03830bf51 100644 --- a/ofono/plugins/wavecom.c +++ b/ofono/plugins/wavecom.c @@ -48,6 +48,7 @@ #include #include +#include #include @@ -70,52 +71,19 @@ static void wavecom_debug(const char *str, void *user_data) static int wavecom_enable(struct ofono_modem *modem) { GAtChat *chat; - GIOChannel *channel; - GAtSyntax *syntax; - const char *device; - GHashTable *options; DBG("%p", modem); - device = ofono_modem_get_string(modem, "Device"); - if (device == NULL) + chat = at_util_open_device(modem, "Device", wavecom_debug, "", + "Baud", "115200", + "Parity", "none", + "StopBits", "1", + "DataBits", "8", + NULL); + if (!chat) return -EINVAL; - options = g_hash_table_new(g_str_hash, g_str_equal); - - if (options == NULL) - return -ENOMEM; - - g_hash_table_insert(options, "Baud", "115200"); - g_hash_table_insert(options, "Parity", "none"); - g_hash_table_insert(options, "StopBits", "1"); - g_hash_table_insert(options, "DataBits", "8"); - - channel = g_at_tty_open(device, options); - - g_hash_table_destroy(options); - - if (channel == NULL) - return -EIO; - - /* - * Could not figure out whether it is fully compliant or not, use - * permissive for now - * */ - syntax = g_at_syntax_new_gsm_permissive(); - - chat = g_at_chat_new(channel, syntax); - g_at_syntax_unref(syntax); - g_io_channel_unref(channel); - - if (chat == NULL) - return -ENOMEM; - g_at_chat_add_terminator(chat, "+CPIN:", 6, TRUE); - - if (getenv("OFONO_AT_DEBUG")) - g_at_chat_set_debug(chat, wavecom_debug, ""); - ofono_modem_set_data(modem, chat); return 0; From b2cabfc6aa03a17efaffb3418877a0161576761c Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 31 May 2019 11:18:44 -0500 Subject: [PATCH 104/320] xmm7xxx: Use at_util_open_device --- ofono/plugins/xmm7xxx.c | 38 +++----------------------------------- 1 file changed, 3 insertions(+), 35 deletions(-) diff --git a/ofono/plugins/xmm7xxx.c b/ofono/plugins/xmm7xxx.c index 23a7d4e41..a544798aa 100644 --- a/ofono/plugins/xmm7xxx.c +++ b/ofono/plugins/xmm7xxx.c @@ -965,41 +965,9 @@ static void xmm7xxx_debug(const char *str, void *user_data) static GAtChat *open_device(struct ofono_modem *modem, const char *key, char *debug) { - const char *device; - GAtSyntax *syntax; - GIOChannel *channel; - GAtChat *chat; - GHashTable *options; - - device = ofono_modem_get_string(modem, key); - if (device == NULL) - return NULL; - - DBG("%s %s", key, device); - - options = g_hash_table_new(g_str_hash, g_str_equal); - if (options == NULL) - return NULL; - - g_hash_table_insert(options, "Baud", "115200"); - channel = g_at_tty_open(device, options); - g_hash_table_destroy(options); - - if (channel == NULL) - return NULL; - - syntax = g_at_syntax_new_gsm_permissive(); - chat = g_at_chat_new(channel, syntax); - g_at_syntax_unref(syntax); - g_io_channel_unref(channel); - - if (chat == NULL) - return NULL; - - if (getenv("OFONO_AT_DEBUG")) - g_at_chat_set_debug(chat, xmm7xxx_debug, debug); - - return chat; + return at_util_open_device(modem, key, xmm7xxx_debug, debug, + "Baud", "115200", + NULL); } static void switch_sim_state_status(struct ofono_modem *modem, int status) From c5fc120c33664c2047ec60f008dedc9260a21ac5 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 31 May 2019 11:18:58 -0500 Subject: [PATCH 105/320] zte: Use at_util_open_device --- ofono/plugins/zte.c | 55 +++++++++------------------------------------ 1 file changed, 10 insertions(+), 45 deletions(-) diff --git a/ofono/plugins/zte.c b/ofono/plugins/zte.c index 53beefe08..b6093af97 100644 --- a/ofono/plugins/zte.c +++ b/ofono/plugins/zte.c @@ -99,51 +99,16 @@ static void zte_debug(const char *str, void *user_data) static GAtChat *open_device(struct ofono_modem *modem, const char *key, char *debug) { - const char *device; - GIOChannel *channel; - GAtSyntax *syntax; - GAtChat *chat; - GHashTable *options; - - device = ofono_modem_get_string(modem, key); - if (device == NULL) - return NULL; - - DBG("%s %s", key, device); - - options = g_hash_table_new(g_str_hash, g_str_equal); - if (options == NULL) - return NULL; - - g_hash_table_insert(options, "Baud", "115200"); - g_hash_table_insert(options, "Parity", "none"); - g_hash_table_insert(options, "StopBits", "1"); - g_hash_table_insert(options, "DataBits", "8"); - g_hash_table_insert(options, "XonXoff", "off"); - g_hash_table_insert(options, "RtsCts", "on"); - g_hash_table_insert(options, "Local", "on"); - g_hash_table_insert(options, "Read", "on"); - - channel = g_at_tty_open(device, options); - - g_hash_table_destroy(options); - - if (channel == NULL) - return NULL; - - syntax = g_at_syntax_new_gsm_permissive(); - chat = g_at_chat_new(channel, syntax); - g_at_syntax_unref(syntax); - - g_io_channel_unref(channel); - - if (chat == NULL) - return NULL; - - if (getenv("OFONO_AT_DEBUG")) - g_at_chat_set_debug(chat, zte_debug, debug); - - return chat; + return at_util_open_device(modem, key, zte_debug, debug, + "Baud", "115200", + "Parity", "none", + "StopBits", "1", + "DataBits", "8", + "XonXoff", "off", + "RtsCts", "on", + "Local", "on", + "Read", "on", + NULL); } static void zoprt_enable(gboolean ok, GAtResult *result, gpointer user_data) From 3fa69555c704ff75287df2df596bb16aa7c4803a Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 31 May 2019 11:21:42 -0500 Subject: [PATCH 106/320] ublox: Use at_util_open_device --- ofono/plugins/ublox.c | 31 ++----------------------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/ofono/plugins/ublox.c b/ofono/plugins/ublox.c index 1ca0030a2..ff08a6a1b 100644 --- a/ofono/plugins/ublox.c +++ b/ofono/plugins/ublox.c @@ -43,7 +43,6 @@ #include #include - #include static const char *uusbconf_prefix[] = { "+UUSBCONF:", NULL }; @@ -99,34 +98,8 @@ static void ublox_remove(struct ofono_modem *modem) static GAtChat *open_device(struct ofono_modem *modem, const char *key, char *debug) { - const char *device; - GAtSyntax *syntax; - GIOChannel *channel; - GAtChat *chat; - - device = ofono_modem_get_string(modem, key); - if (device == NULL) - return NULL; - - DBG("%s %s", key, device); - - channel = g_at_tty_open(device, NULL); - if (channel == NULL) - return NULL; - - syntax = g_at_syntax_new_gsm_permissive(); - chat = g_at_chat_new(channel, syntax); - g_at_syntax_unref(syntax); - - g_io_channel_unref(channel); - - if (chat == NULL) - return NULL; - - if (getenv("OFONO_AT_DEBUG")) - g_at_chat_set_debug(chat, ublox_debug, debug); - - return chat; + return at_util_open_device(modem, key, ublox_debug, debug, + NULL); } static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data) From feb05e77002e5c6329d198fe22838477fb54754d Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 31 May 2019 11:24:04 -0500 Subject: [PATCH 107/320] telit: Use at_util_open_device --- ofono/plugins/telit.c | 38 +++----------------------------------- 1 file changed, 3 insertions(+), 35 deletions(-) diff --git a/ofono/plugins/telit.c b/ofono/plugins/telit.c index 1a3ade070..094d762f0 100644 --- a/ofono/plugins/telit.c +++ b/ofono/plugins/telit.c @@ -116,41 +116,9 @@ static void telit_debug(const char *str, void *user_data) static GAtChat *open_device(struct ofono_modem *modem, const char *key, char *debug) { - const char *device; - GAtSyntax *syntax; - GIOChannel *channel; - GAtChat *chat; - GHashTable *options; - - device = ofono_modem_get_string(modem, key); - if (device == NULL) - return NULL; - - DBG("%s %s", key, device); - - options = g_hash_table_new(g_str_hash, g_str_equal); - if (options == NULL) - return NULL; - - g_hash_table_insert(options, "Baud", "115200"); - channel = g_at_tty_open(device, options); - g_hash_table_destroy(options); - - if (channel == NULL) - return NULL; - - syntax = g_at_syntax_new_gsm_permissive(); - chat = g_at_chat_new(channel, syntax); - g_at_syntax_unref(syntax); - g_io_channel_unref(channel); - - if (chat == NULL) - return NULL; - - if (getenv("OFONO_AT_DEBUG")) - g_at_chat_set_debug(chat, telit_debug, debug); - - return chat; + return at_util_open_device(modem, key, telit_debug, debug, + "Baud", "115200", + NULL); } static void switch_sim_state_status(struct ofono_modem *modem, int status) From 4469b50e85ca371eaa69982998d2a68d9a1a16ae Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 31 May 2019 11:26:15 -0500 Subject: [PATCH 108/320] speedup: Use at_util_open_device --- ofono/plugins/speedup.c | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/ofono/plugins/speedup.c b/ofono/plugins/speedup.c index d1ea35a12..0b5d22892 100644 --- a/ofono/plugins/speedup.c +++ b/ofono/plugins/speedup.c @@ -109,34 +109,7 @@ static void speedup_debug(const char *str, void *user_data) static GAtChat *open_device(struct ofono_modem *modem, const char *key, char *debug) { - const char *device; - GIOChannel *channel; - GAtSyntax *syntax; - GAtChat *chat; - - device = ofono_modem_get_string(modem, key); - if (device == NULL) - return NULL; - - DBG("%s %s", key, device); - - channel = g_at_tty_open(device, NULL); - if (channel == NULL) - return NULL; - - syntax = g_at_syntax_new_gsm_permissive(); - chat = g_at_chat_new(channel, syntax); - g_at_syntax_unref(syntax); - - g_io_channel_unref(channel); - - if (chat == NULL) - return NULL; - - if (getenv("OFONO_AT_DEBUG")) - g_at_chat_set_debug(chat, speedup_debug, debug); - - return chat; + return at_util_open_device(modem, key, speedup_debug, debug, NULL); } static void sim_state_cb(gboolean present, gpointer user_data) From d033e3672180010df560d30901b8ba6b4fe5c378 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 31 May 2019 11:27:21 -0500 Subject: [PATCH 109/320] speedupcdma: Use at_util_open_device --- ofono/plugins/speedupcdma.c | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/ofono/plugins/speedupcdma.c b/ofono/plugins/speedupcdma.c index 8e5f32431..779c37bd1 100644 --- a/ofono/plugins/speedupcdma.c +++ b/ofono/plugins/speedupcdma.c @@ -38,6 +38,7 @@ #include #include +#include "drivers/atmodem/atutil.h" #include "drivers/atmodem/vendor.h" struct speedupcdma_data { @@ -102,34 +103,7 @@ static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data) static GAtChat *open_device(struct ofono_modem *modem, const char *key, char *debug) { - const char *device; - GIOChannel *channel; - GAtSyntax *syntax; - GAtChat *chat; - - device = ofono_modem_get_string(modem, key); - if (device == NULL) - return NULL; - - DBG("%s %s", key, device); - - channel = g_at_tty_open(device, NULL); - if (channel == NULL) - return NULL; - - syntax = g_at_syntax_new_gsm_permissive(); - chat = g_at_chat_new(channel, syntax); - g_at_syntax_unref(syntax); - - g_io_channel_unref(channel); - - if (chat == NULL) - return NULL; - - if (getenv("OFONO_AT_DEBUG")) - g_at_chat_set_debug(chat, speedupcdma_debug, debug); - - return chat; + return at_util_open_device(modem, key, speedupcdma_debug, debug, NULL); } static int speedupcdma_enable(struct ofono_modem *modem) From 4cac144067bfdf7b15d231ff0c05e8cc1ceb3745 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 31 May 2019 11:31:39 -0500 Subject: [PATCH 110/320] sierra: Use at_util_open_device --- ofono/plugins/sierra.c | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/ofono/plugins/sierra.c b/ofono/plugins/sierra.c index 70d0d11bd..0cc1f3a7d 100644 --- a/ofono/plugins/sierra.c +++ b/ofono/plugins/sierra.c @@ -94,34 +94,7 @@ static void sierra_remove(struct ofono_modem *modem) static GAtChat *open_device(struct ofono_modem *modem, const char *key, char *debug) { - const char *device; - GAtSyntax *syntax; - GIOChannel *channel; - GAtChat *chat; - - device = ofono_modem_get_string(modem, key); - if (device == NULL) - return NULL; - - DBG("%s %s", key, device); - - channel = g_at_tty_open(device, NULL); - if (channel == NULL) - return NULL; - - syntax = g_at_syntax_new_gsm_permissive(); - chat = g_at_chat_new(channel, syntax); - g_at_syntax_unref(syntax); - - g_io_channel_unref(channel); - - if (chat == NULL) - return NULL; - - if (getenv("OFONO_AT_DEBUG")) - g_at_chat_set_debug(chat, sierra_debug, debug); - - return chat; + return at_util_open_device(modem, key, sierra_debug, debug, NULL); } static void sim_state_cb(gboolean present, gpointer user_data) From 7b884199cc1788089a02eb6ac691300ee1587206 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 31 May 2019 11:34:58 -0500 Subject: [PATCH 111/320] samsung: Use at_util_open_device --- ofono/plugins/samsung.c | 48 ++++++++++------------------------------- 1 file changed, 11 insertions(+), 37 deletions(-) diff --git a/ofono/plugins/samsung.c b/ofono/plugins/samsung.c index 68a9b0a6d..1780943be 100644 --- a/ofono/plugins/samsung.c +++ b/ofono/plugins/samsung.c @@ -149,47 +149,21 @@ static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data) static int samsung_enable(struct ofono_modem *modem) { struct samsung_data *data = ofono_modem_get_data(modem); - GAtSyntax *syntax; - GIOChannel *channel; - GHashTable *options; - const char *device; - - device = ofono_modem_get_string(modem, "ControlPort"); - if (device == NULL) - return -EINVAL; - - options = g_hash_table_new(g_str_hash, g_str_equal); - if (options == NULL) - return -ENOMEM; - - g_hash_table_insert(options, "Baud", "115200"); - g_hash_table_insert(options, "Parity", "none"); - g_hash_table_insert(options, "StopBits", "1"); - g_hash_table_insert(options, "DataBits", "8"); - g_hash_table_insert(options, "XonXoff", "off"); - g_hash_table_insert(options, "RtsCts", "on"); - g_hash_table_insert(options, "Local", "on"); - g_hash_table_insert(options, "Read", "on"); - - channel = g_at_tty_open(device, options); - - g_hash_table_destroy(options); - - if (channel == NULL) - return -EIO; - - syntax = g_at_syntax_new_gsm_permissive(); - data->chat = g_at_chat_new(channel, syntax); - g_at_syntax_unref(syntax); - - g_io_channel_unref(channel); + data->chat = at_util_open_device(modem, "ControlPort", + samsung_debug, "Device: ", + "Baud", "115200", + "Parity", "none", + "StopBits", "1", + "DataBits", "8", + "XonXoff", "off", + "RtsCts", "on", + "Local", "on", + "Read", "on", + NULL); if (data->chat == NULL) return -ENOMEM; - if (getenv("OFONO_AT_DEBUG")) - g_at_chat_set_debug(data->chat, samsung_debug, "Device: "); - g_at_chat_send(data->chat, "ATE0", NULL, NULL, NULL, NULL); g_at_chat_send(data->chat, "AT+CMEE=1", NULL, NULL, NULL, NULL); From 798b0c7353f6eaf1722c347c515d2a050161ccfd Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 31 May 2019 11:36:52 -0500 Subject: [PATCH 112/320] quectel: Use at_util_open_device --- ofono/plugins/quectel.c | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index ba1aa42da..6ab97027d 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -94,34 +94,7 @@ static void quectel_remove(struct ofono_modem *modem) static GAtChat *open_device(struct ofono_modem *modem, const char *key, char *debug) { - const char *device; - GAtSyntax *syntax; - GIOChannel *channel; - GAtChat *chat; - - device = ofono_modem_get_string(modem, key); - if (device == NULL) - return NULL; - - DBG("%s %s", key, device); - - channel = g_at_tty_open(device, NULL); - if (channel == NULL) - return NULL; - - syntax = g_at_syntax_new_gsm_permissive(); - chat = g_at_chat_new(channel, syntax); - g_at_syntax_unref(syntax); - - g_io_channel_unref(channel); - - if (chat == NULL) - return NULL; - - if (getenv("OFONO_AT_DEBUG")) - g_at_chat_set_debug(chat, quectel_debug, debug); - - return chat; + return at_util_open_device(modem, key, quectel_debug, debug, NULL); } static void cpin_notify(GAtResult *result, gpointer user_data) From b640936a19cc00eaaf78caecd08afcdfdb3e218f Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 31 May 2019 11:38:10 -0500 Subject: [PATCH 113/320] novatel: Use at_util_open_device --- ofono/plugins/novatel.c | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/ofono/plugins/novatel.c b/ofono/plugins/novatel.c index a64364d16..c01aa5485 100644 --- a/ofono/plugins/novatel.c +++ b/ofono/plugins/novatel.c @@ -96,32 +96,7 @@ static void novatel_debug(const char *str, void *user_data) static GAtChat *open_device(struct ofono_modem *modem, const char *key, char *debug) { - GAtChat *chat; - GAtSyntax *syntax; - GIOChannel *channel; - const char *device; - - device = ofono_modem_get_string(modem, key); - if (device == NULL) - return NULL; - - channel = g_at_tty_open(device, NULL); - if (channel == NULL) - return NULL; - - syntax = g_at_syntax_new_gsm_permissive(); - chat = g_at_chat_new(channel, syntax); - g_at_syntax_unref(syntax); - - g_io_channel_unref(channel); - - if (chat == NULL) - return NULL; - - if (getenv("OFONO_AT_DEBUG")) - g_at_chat_set_debug(chat, novatel_debug, debug); - - return chat; + return at_util_open_device(modem, key, novatel_debug, debug, NULL); } static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data) From 1668c177674a0196fb82d65b149afb96b838d84c Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 31 May 2019 11:39:32 -0500 Subject: [PATCH 114/320] nokia: Use at_util_open_device --- ofono/plugins/nokia.c | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/ofono/plugins/nokia.c b/ofono/plugins/nokia.c index ef598fa4b..7f19ce968 100644 --- a/ofono/plugins/nokia.c +++ b/ofono/plugins/nokia.c @@ -43,6 +43,7 @@ #include #include +#include #include static const char *none_prefix[] = { NULL }; @@ -91,34 +92,7 @@ static void nokia_debug(const char *str, void *user_data) static GAtChat *open_device(struct ofono_modem *modem, const char *key, char *debug) { - const char *device; - GAtSyntax *syntax; - GIOChannel *channel; - GAtChat *chat; - - device = ofono_modem_get_string(modem, key); - if (device == NULL) - return NULL; - - DBG("%s %s", key, device); - - channel = g_at_tty_open(device, NULL); - if (channel == NULL) - return NULL; - - syntax = g_at_syntax_new_gsm_permissive(); - chat = g_at_chat_new(channel, syntax); - g_at_syntax_unref(syntax); - - g_io_channel_unref(channel); - - if (chat == NULL) - return NULL; - - if (getenv("OFONO_AT_DEBUG")) - g_at_chat_set_debug(chat, nokia_debug, debug); - - return chat; + return at_util_open_device(modem, key, nokia_debug, debug, NULL); } static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data) From a4b00c1aa329c325af167c4a9177b6f390a0b82b Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 31 May 2019 11:44:54 -0500 Subject: [PATCH 115/320] mbm: Use at_util_open_device --- ofono/plugins/mbm.c | 43 +++++++------------------------------------ 1 file changed, 7 insertions(+), 36 deletions(-) diff --git a/ofono/plugins/mbm.c b/ofono/plugins/mbm.c index b787aeb79..38297d747 100644 --- a/ofono/plugins/mbm.c +++ b/ofono/plugins/mbm.c @@ -285,35 +285,12 @@ static void emrdy_query(gboolean ok, GAtResult *result, gpointer user_data) cfun_query, modem, NULL); } -static GAtChat *create_port(const char *device) +static GAtChat *open_device(struct ofono_modem *modem, const char *key, + char *debug) { - GAtSyntax *syntax; - GIOChannel *channel; - GAtChat *chat; - GHashTable *options; - - options = g_hash_table_new(g_str_hash, g_str_equal); - if (options == NULL) - return NULL; - - g_hash_table_insert(options, "Baud", "115200"); - - channel = g_at_tty_open(device, options); - - g_hash_table_destroy(options); - - if (channel == NULL) - return NULL; - - syntax = g_at_syntax_new_gsm_permissive(); - chat = g_at_chat_new(channel, syntax); - g_at_syntax_unref(syntax); - g_io_channel_unref(channel); - - if (chat == NULL) - return NULL; - - return chat; + return at_util_open_device(modem, key, mbm_debug, debug, + "Baud", "115200", + NULL); } static int mbm_enable(struct ofono_modem *modem) @@ -332,14 +309,11 @@ static int mbm_enable(struct ofono_modem *modem) if (modem_dev == NULL || data_dev == NULL) return -EINVAL; - data->modem_port = create_port(modem_dev); + data->modem_port = open_device(modem, "ModemDevice", "Modem: "); if (data->modem_port == NULL) return -EIO; - if (getenv("OFONO_AT_DEBUG")) - g_at_chat_set_debug(data->modem_port, mbm_debug, "Modem: "); - - data->data_port = create_port(data_dev); + data->data_port = open_device(modem, "DataDevice", "Data: "); if (data->data_port == NULL) { g_at_chat_unref(data->modem_port); data->modem_port = NULL; @@ -347,9 +321,6 @@ static int mbm_enable(struct ofono_modem *modem) return -EIO; } - if (getenv("OFONO_AT_DEBUG")) - g_at_chat_set_debug(data->data_port, mbm_debug, "Data: "); - g_at_chat_register(data->modem_port, "*EMRDY:", emrdy_notifier, FALSE, modem, NULL); From cd4bada43e24582ca58d5f113866b91e1df41230 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 31 May 2019 11:46:18 -0500 Subject: [PATCH 116/320] linktop: Use at_util_open_device --- ofono/plugins/linktop.c | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/ofono/plugins/linktop.c b/ofono/plugins/linktop.c index bb0d7b8ea..2b8acf769 100644 --- a/ofono/plugins/linktop.c +++ b/ofono/plugins/linktop.c @@ -91,34 +91,7 @@ static void linktop_debug(const char *str, void *user_data) static GAtChat *open_device(struct ofono_modem *modem, const char *key, char *debug) { - const char *device; - GIOChannel *channel; - GAtSyntax *syntax; - GAtChat *chat; - - device = ofono_modem_get_string(modem, key); - if (device == NULL) - return NULL; - - DBG("%s %s", key, device); - - channel = g_at_tty_open(device, NULL); - if (channel == NULL) - return NULL; - - syntax = g_at_syntax_new_gsm_permissive(); - chat = g_at_chat_new(channel, syntax); - g_at_syntax_unref(syntax); - - g_io_channel_unref(channel); - - if (chat == NULL) - return NULL; - - if (getenv("OFONO_AT_DEBUG")) - g_at_chat_set_debug(chat, linktop_debug, debug); - - return chat; + return at_util_open_device(modem, key, linktop_debug, debug, NULL); } static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data) From 8ec9581f98ff2ae97d574d79d3778f5c083b9cfb Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 31 May 2019 11:47:35 -0500 Subject: [PATCH 117/320] icera: Use at_util_open_device --- ofono/plugins/icera.c | 39 +++------------------------------------ 1 file changed, 3 insertions(+), 36 deletions(-) diff --git a/ofono/plugins/icera.c b/ofono/plugins/icera.c index 7df5ffd76..90aca221b 100644 --- a/ofono/plugins/icera.c +++ b/ofono/plugins/icera.c @@ -96,42 +96,9 @@ static void icera_debug(const char *str, void *user_data) static GAtChat *open_device(struct ofono_modem *modem, const char *key, char *debug) { - GAtChat *chat; - GAtSyntax *syntax; - GIOChannel *channel; - GHashTable *options; - const char *device; - - device = ofono_modem_get_string(modem, key); - if (device == NULL) - return NULL; - - options = g_hash_table_new(g_str_hash, g_str_equal); - if (options == NULL) - return NULL; - - g_hash_table_insert(options, "Baud", "115200"); - - channel = g_at_tty_open(device, options); - - g_hash_table_destroy(options); - - if (channel == NULL) - return NULL; - - syntax = g_at_syntax_new_gsm_permissive(); - chat = g_at_chat_new(channel, syntax); - g_at_syntax_unref(syntax); - - g_io_channel_unref(channel); - - if (chat == NULL) - return NULL; - - if (getenv("OFONO_AT_DEBUG")) - g_at_chat_set_debug(chat, icera_debug, debug); - - return chat; + return at_util_open_device(modem, key, icera_debug, debug, + "Baud", "115200", + NULL); } static void ussdmode_query(gboolean ok, GAtResult *result, From 0db57c3274feb26ea43ae4b647244d87e089885f Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 31 May 2019 11:50:03 -0500 Subject: [PATCH 118/320] huawei: Use at_util_open_device --- ofono/plugins/huawei.c | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/ofono/plugins/huawei.c b/ofono/plugins/huawei.c index 817ee66ae..bdf7bc397 100644 --- a/ofono/plugins/huawei.c +++ b/ofono/plugins/huawei.c @@ -553,36 +553,15 @@ static void gcap_support(gboolean ok, GAtResult *result, gpointer user_data) static GAtChat *open_device(struct ofono_modem *modem, const char *key, char *debug) { - const char *device; - GIOChannel *channel; - GAtSyntax *syntax; - GAtChat *chat; + GAtChat *chat = at_util_open_device(modem, key, huawei_debug, debug, + NULL); - device = ofono_modem_get_string(modem, key); - if (device == NULL) - return NULL; - - DBG("%s %s", key, device); - - channel = g_at_tty_open(device, NULL); - if (channel == NULL) - return NULL; - - syntax = g_at_syntax_new_gsm_permissive(); - chat = g_at_chat_new(channel, syntax); - g_at_syntax_unref(syntax); - - g_io_channel_unref(channel); - - if (chat == NULL) + if (!chat) return NULL; g_at_chat_add_terminator(chat, "COMMAND NOT SUPPORT", -1, FALSE); g_at_chat_add_terminator(chat, "TOO MANY PARAMETERS", -1, FALSE); - if (getenv("OFONO_AT_DEBUG")) - g_at_chat_set_debug(chat, huawei_debug, debug); - return chat; } From 14b46de54b5a26c5f7233592e10489573b1716b4 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 31 May 2019 11:51:03 -0500 Subject: [PATCH 119/320] hso: Use at_util_open_device --- ofono/plugins/hso.c | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/ofono/plugins/hso.c b/ofono/plugins/hso.c index 249bb2caa..b58bf2a53 100644 --- a/ofono/plugins/hso.c +++ b/ofono/plugins/hso.c @@ -301,34 +301,7 @@ static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data) static GAtChat *open_device(struct ofono_modem *modem, const char *key, char *debug) { - const char *device; - GIOChannel *channel; - GAtSyntax *syntax; - GAtChat *chat; - - device = ofono_modem_get_string(modem, key); - if (device == NULL) - return NULL; - - DBG("%s %s", key, device); - - channel = g_at_tty_open(device, NULL); - if (channel == NULL) - return NULL; - - syntax = g_at_syntax_new_gsm_permissive(); - chat = g_at_chat_new(channel, syntax); - g_at_syntax_unref(syntax); - - g_io_channel_unref(channel); - - if (chat == NULL) - return NULL; - - if (getenv("OFONO_AT_DEBUG")) - g_at_chat_set_debug(chat, hso_debug, debug); - - return chat; + return at_util_open_device(modem, key, hso_debug, debug, NULL); } static int hso_enable(struct ofono_modem *modem) From e27f0031b01f163bf1f252402572922c51dc2025 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 31 May 2019 11:57:38 -0500 Subject: [PATCH 120/320] alcatel: Use at_util_open_device --- ofono/plugins/alcatel.c | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/ofono/plugins/alcatel.c b/ofono/plugins/alcatel.c index fb1d1ae57..8da06192a 100644 --- a/ofono/plugins/alcatel.c +++ b/ofono/plugins/alcatel.c @@ -91,34 +91,7 @@ static void alcatel_debug(const char *str, void *user_data) static GAtChat *open_device(struct ofono_modem *modem, const char *key, char *debug) { - const char *device; - GIOChannel *channel; - GAtSyntax *syntax; - GAtChat *chat; - - device = ofono_modem_get_string(modem, key); - if (device == NULL) - return NULL; - - DBG("%s %s", key, device); - - channel = g_at_tty_open(device, NULL); - if (channel == NULL) - return NULL; - - syntax = g_at_syntax_new_gsm_permissive(); - chat = g_at_chat_new(channel, syntax); - g_at_syntax_unref(syntax); - - g_io_channel_unref(channel); - - if (chat == NULL) - return NULL; - - if (getenv("OFONO_AT_DEBUG")) - g_at_chat_set_debug(chat, alcatel_debug, debug); - - return chat; + return at_util_open_device(modem, key, alcatel_debug, debug, NULL); } static void sim_state_cb(gboolean present, gpointer user_data) From faa495902b3019673dcfd5170067927a2a89842a Mon Sep 17 00:00:00 2001 From: Tom Nguyen Date: Wed, 5 Jun 2019 12:26:23 -0400 Subject: [PATCH 121/320] qmimodem: change msg class none to store/notify Change message class none configuration from directly delivering a new message in the event indication to storing it in the modem's NV then sending an event indication identifying the new message. Also, add checking for stored, unread messages at boot up. This fixes a scenario where the modem powers on, automatically connects to the network, receives a message, and sends an indication before oFono has fully initialized. Now, the message is saved and retrieved after initialization. This also helps with suspend/resume on platforms where the modem, supports waking the host CPU upon SMS reception. And, the platform design limitation is that the modem's interfaces (eg, cdc-wdm, wwan, etc) disconnect on suspend and reconnect on resume. This causes oFono to re-initialize and miss the message indication because it was sent before oFono is ready. Now, the wake up message is saved and retrieved after initialization. --- ofono/drivers/qmimodem/sms.c | 368 ++++++++++++++++++++++++++++++----- ofono/drivers/qmimodem/wms.h | 77 ++++++-- 2 files changed, 377 insertions(+), 68 deletions(-) diff --git a/ofono/drivers/qmimodem/sms.c b/ofono/drivers/qmimodem/sms.c index 1e9303966..2e9624297 100644 --- a/ofono/drivers/qmimodem/sms.c +++ b/ofono/drivers/qmimodem/sms.c @@ -39,8 +39,17 @@ struct sms_data { struct qmi_service *wms; uint16_t major; uint16_t minor; + struct qmi_wms_read_msg_id rd_msg_id; + struct qmi_wms_result_msg_list *msg_list; + uint32_t rd_msg_num; + uint8_t msg_mode; + bool msg_mode_all; + bool msg_list_chk; }; +static void get_msg_list(struct ofono_sms *sms); +static void raw_read(struct ofono_sms *sms, uint8_t type, uint32_t ndx); + static void get_smsc_addr_cb(struct qmi_result *result, void *user_data) { struct cb_data *cbd = user_data; @@ -334,21 +343,95 @@ static void qmi_bearer_set(struct ofono_sms *sms, int bearer, g_free(cbd); } +static void delete_msg_cb(struct qmi_result *result, void *user_data) +{ + struct ofono_sms *sms = user_data; + struct sms_data *data = ofono_sms_get_data(sms); + uint16_t err; + + DBG(""); + + if (qmi_result_set_error(result, &err)) + DBG("Err: delete %d - %s", err, qmi_result_get_error(result)); + + /* + * Continue processing msg list. If error occurred, something + * serious happened, then don't bother. + */ + if (data->msg_list && data->msg_list_chk) { + uint32_t msg = ++data->rd_msg_num; + + /* + * Get another msg. If list is empty check for more. Once query + * returns empty, rely on event indication to get new msgs. + */ + if (msg < data->msg_list->cnt) + raw_read(sms, data->msg_list->msg[msg].type, + GUINT32_FROM_LE(data->msg_list->msg[msg].ndx)); + else + get_msg_list(sms); + } +} + +static void delete_msg(struct ofono_sms *sms, uint8_t tag) +{ + struct sms_data *data = ofono_sms_get_data(sms); + struct qmi_param *param; + qmi_result_func_t func = NULL; + + DBG(""); + + param = qmi_param_new(); + if (param == NULL) + goto done; + + qmi_param_append_uint8(param, QMI_WMS_PARAM_DEL_STORE, + QMI_WMS_STORAGE_TYPE_NV); + + if (tag == QMI_WMS_MT_UNDEFINE) { + DBG("delete read msg type %d ndx %d", data->rd_msg_id.type, + data->rd_msg_id.ndx); + + /* delete 1 msg */ + qmi_param_append_uint32(param, QMI_WMS_PARAM_DEL_NDX, + data->rd_msg_id.ndx); + func = delete_msg_cb; + } else { + DBG("delete msg tag %d mode %d", tag, data->msg_mode); + + /* delete all msgs from 1 tag type */ + qmi_param_append_uint8(param, QMI_WMS_PARAM_DEL_TYPE, tag); + } + + qmi_param_append_uint8(param, QMI_WMS_PARAM_DEL_MODE, data->msg_mode); + + if (qmi_service_send(data->wms, QMI_WMS_DELETE, param, + func, sms, NULL) > 0) + return; + + qmi_param_free(param); + +done: + data->msg_list_chk = false; +} + static void raw_read_cb(struct qmi_result *result, void *user_data) { struct ofono_sms *sms = user_data; - const struct qmi_wms_raw_message* msg; - uint16_t len; - uint16_t error; + struct sms_data *data = ofono_sms_get_data(sms); + const struct qmi_wms_raw_message *msg; + uint16_t err; - if (qmi_result_set_error(result, &error)) { - DBG("Raw read error: %d (%s)", error, - qmi_result_get_error(result)); + DBG(""); + + if (qmi_result_set_error(result, &err)) { + DBG("Err: read %d - %s", err, qmi_result_get_error(result)); + data->msg_list_chk = false; return; } /* Raw message data */ - msg = qmi_result_get(result, 0x01, &len); + msg = qmi_result_get(result, QMI_WMS_RESULT_READ_MSG, NULL); if (msg) { uint16_t plen; uint16_t tpdu_len; @@ -357,9 +440,174 @@ static void raw_read_cb(struct qmi_result *result, void *user_data) tpdu_len = plen - msg->msg_data[0] - 1; ofono_sms_deliver_notify(sms, msg->msg_data, plen, tpdu_len); + } else + DBG("Err: no data in type %d ndx %d", data->rd_msg_id.type, + data->rd_msg_id.ndx); + + /* delete read msg */ + delete_msg(sms, QMI_WMS_MT_UNDEFINE); +} + +static void raw_read(struct ofono_sms *sms, uint8_t type, uint32_t ndx) +{ + struct sms_data *data = ofono_sms_get_data(sms); + struct qmi_param *param; + + DBG(""); + + param = qmi_param_new(); + if (param == NULL) + goto done; + + data->rd_msg_id.type = type; + data->rd_msg_id.ndx = ndx; + + DBG("read type %d ndx %d", data->rd_msg_id.type, data->rd_msg_id.ndx); + + qmi_param_append(param, QMI_WMS_PARAM_READ_MSG, + sizeof(data->rd_msg_id), &data->rd_msg_id); + qmi_param_append_uint8(param, QMI_WMS_PARAM_READ_MODE, data->msg_mode); + + if (qmi_service_send(data->wms, QMI_WMS_RAW_READ, param, + raw_read_cb, sms, NULL) > 0) + return; + + qmi_param_free(param); + +done: + data->msg_list_chk = false; +} + +static void get_msg_list_cb(struct qmi_result *result, void *user_data) +{ + struct ofono_sms *sms = user_data; + struct sms_data *data = ofono_sms_get_data(sms); + const struct qmi_wms_result_msg_list *list; + uint32_t cnt = 0; + uint16_t tmp; + + DBG(""); + + if (qmi_result_set_error(result, &tmp)) { + DBG("Err: get msg list mode=%d %d=%s", data->msg_mode, tmp, + qmi_result_get_error(result)); + goto done; + } + + list = qmi_result_get(result, QMI_WMS_RESULT_MSG_LIST, NULL); + if (list == NULL) { + DBG("Err: get msg list empty"); + goto done; + } + + cnt = GUINT32_FROM_LE(list->cnt); + DBG("msgs found %d", cnt); + + for (tmp = 0; tmp < cnt; tmp++) { + DBG("unread type %d ndx %d", list->msg[tmp].type, + GUINT32_FROM_LE(list->msg[tmp].ndx)); + } + + /* free list from last time */ + if (data->msg_list) { + g_free(data->msg_list); + data->msg_list = NULL; + } + + /* save list and get 1st msg */ + if (cnt) { + int msg_size = cnt * sizeof(list->msg[0]); + + data->msg_list = g_try_malloc0(sizeof(list->cnt) + msg_size); + if (data->msg_list == NULL) + goto done; + + data->msg_list->cnt = cnt; + memcpy(data->msg_list->msg, list->msg, msg_size); + + data->rd_msg_num = 0; + raw_read(sms, data->msg_list->msg[0].type, + GUINT32_FROM_LE(data->msg_list->msg[0].ndx)); + return; + } + +done: + data->msg_list_chk = false; + + /* if both protocols supported, check the other */ + if (data->msg_mode_all) { + data->msg_mode_all = false; + data->msg_mode = QMI_WMS_MESSAGE_MODE_GSMWCDMA; + get_msg_list(sms); + } +} + +static void get_msg_list(struct ofono_sms *sms) +{ + struct sms_data *data = ofono_sms_get_data(sms); + struct qmi_param *param; + + DBG(""); + + param = qmi_param_new(); + if (param == NULL) + return; + + data->msg_list_chk = true; + + /* query NOT_READ msg list */ + qmi_param_append_uint8(param, QMI_WMS_PARAM_STORAGE_TYPE, + QMI_WMS_STORAGE_TYPE_NV); + qmi_param_append_uint8(param, QMI_WMS_PARAM_TAG_TYPE, + QMI_WMS_MT_NOT_READ); + qmi_param_append_uint8(param, QMI_WMS_PARAM_MESSAGE_MODE, + data->msg_mode); + + if (qmi_service_send(data->wms, QMI_WMS_GET_MSG_LIST, param, + get_msg_list_cb, sms, NULL) > 0) + return; + + data->msg_list_chk = false; + qmi_param_free(param); +} + +static void get_msg_protocol_cb(struct qmi_result *result, void *user_data) +{ + struct ofono_sms *sms = user_data; + struct sms_data *data = ofono_sms_get_data(sms); + uint16_t err; + + DBG(""); + + if (qmi_result_set_error(result, &err) && + (err != QMI_ERR_OP_DEVICE_UNSUPPORTED)) { + DBG("Err: protocol %d - %s", err, qmi_result_get_error(result)); + return; + } + + if (err != QMI_ERR_OP_DEVICE_UNSUPPORTED) { + /* modem supports only 1 protocol */ + qmi_result_get_uint8(result, QMI_WMS_PARAM_PROTOCOL, + &data->msg_mode); } else { - DBG("No message data available at requested position"); + /* check both, start with 1 then switch to other */ + DBG("device supports CDMA and WCDMA msg protocol"); + data->msg_mode_all = true; + data->msg_mode = QMI_WMS_MESSAGE_MODE_CDMA; } + + /* check for messages */ + get_msg_list(sms); +} + +static void get_msg_protocol(struct ofono_sms *sms) +{ + struct sms_data *data = ofono_sms_get_data(sms); + + DBG(""); + + qmi_service_send(data->wms, QMI_WMS_GET_MSG_PROTOCOL, NULL, + get_msg_protocol_cb, sms, NULL); } static void event_notify(struct qmi_result *result, void *user_data) @@ -367,66 +615,78 @@ static void event_notify(struct qmi_result *result, void *user_data) struct ofono_sms *sms = user_data; struct sms_data *data = ofono_sms_get_data(sms); const struct qmi_wms_result_new_msg_notify *notify; - const struct qmi_wms_result_message *message; - uint16_t len; DBG(""); - notify = qmi_result_get(result, QMI_WMS_RESULT_NEW_MSG_NOTIFY, &len); + /* + * The 2 types of MT message TLVs are mutually exclusive, depending on + * how the route action is configured. If action is store and notify, + * then the MT message TLV is sent. If action is transfer only or + * transfer and ack, then the transfer route MT message TLV is sent. + */ + notify = qmi_result_get(result, QMI_WMS_RESULT_NEW_MSG_NOTIFY, NULL); if (notify) { - DBG("storage type %d index %d", notify->storage_type, - GUINT32_FROM_LE(notify->storage_index)); - } + /* route is store and notify */ + if (!qmi_result_get_uint8(result, QMI_WMS_RESULT_MSG_MODE, + &data->msg_mode)) + DBG("msg mode not found, use mode %d", data->msg_mode); + + DBG("msg type %d ndx %d mode %d", notify->storage_type, + GUINT32_FROM_LE(notify->storage_index), data->msg_mode); + + /* don't read if list is being processed, get this msg later */ + if (!data->msg_list_chk) + raw_read(sms, notify->storage_type, + GUINT32_FROM_LE(notify->storage_index)); + } else { + /* route is either transfer only or transfer and ACK */ + const struct qmi_wms_result_message *message; - message = qmi_result_get(result, QMI_WMS_RESULT_MESSAGE, &len); - if (message) { - uint16_t plen; + message = qmi_result_get(result, QMI_WMS_RESULT_MESSAGE, NULL); + if (message) { + uint16_t plen; - plen = GUINT16_FROM_LE(message->msg_length); + plen = GUINT16_FROM_LE(message->msg_length); - DBG("ack_required %d transaction id %u", message->ack_required, + DBG("ack_required %d transaction id %u", + message->ack_required, GUINT32_FROM_LE(message->transaction_id)); - DBG("msg format %d PDU length %d", message->msg_format, plen); + DBG("msg format %d PDU length %d", + message->msg_format, plen); - ofono_sms_deliver_notify(sms, message->msg_data, plen, plen); - } else { - /* The Quectel EC21, at least, does not provide the - * message data in the event notification, so a 'raw read' - * needs to be issued in order to query the message itself - */ - struct qmi_param *param; - - param = qmi_param_new(); - if (!param) - return; - - /* Message memory storage ID */ - qmi_param_append(param, 0x01, sizeof(*notify), notify); - /* The 'message mode' parameter is documented as optional, - * but the Quectel EC21 errors out with error 17 (missing - * argument) if it is not provided... we default to 3GPP - * here because that's what works for me and it's not clear - * how to actually query what this should be otherwise... - */ - /* Message mode */ - qmi_param_append_uint8(param, 0x10, - QMI_WMS_MESSAGE_MODE_GSMWCDMA); - - if (qmi_service_send(data->wms, QMI_WMS_RAW_READ, param, - raw_read_cb, sms, NULL) > 0) - return; - - qmi_param_free(param); + ofono_sms_deliver_notify(sms, message->msg_data, + plen, plen); + } } } static void set_routes_cb(struct qmi_result *result, void *user_data) { struct ofono_sms *sms = user_data; + struct sms_data *data = ofono_sms_get_data(sms); DBG(""); ofono_sms_register(sms); + + /* + * Modem storage is limited. As a fail safe, delete processed messages + * to free device memory to prevent blockage of new messages. + */ + data->msg_mode = QMI_WMS_MESSAGE_MODE_CDMA; + delete_msg(sms, QMI_WMS_MT_READ); + delete_msg(sms, QMI_WMS_MO_SENT); + data->msg_mode = QMI_WMS_MESSAGE_MODE_GSMWCDMA; + delete_msg(sms, QMI_WMS_MT_READ); + delete_msg(sms, QMI_WMS_MO_SENT); + + /* + * Subsystem initialized, now start process to check for unread + * messages. First, query msg protocol/mode. If modem supports both + * modes, then check messages for both modes since there's no way to + * query which mode is active. + */ + get_msg_protocol(sms); } static void get_routes_cb(struct qmi_result *result, void *user_data) @@ -468,8 +728,8 @@ static void get_routes_cb(struct qmi_result *result, void *user_data) new_list->count = GUINT16_TO_LE(1); new_list->route[0].msg_type = QMI_WMS_MSG_TYPE_P2P; new_list->route[0].msg_class = QMI_WMS_MSG_CLASS_NONE; - new_list->route[0].storage_type = QMI_WMS_STORAGE_TYPE_NONE; - new_list->route[0].action = QMI_WMS_ACTION_TRANSFER_AND_ACK; + new_list->route[0].storage_type = QMI_WMS_STORAGE_TYPE_NV; + new_list->route[0].action = QMI_WMS_ACTION_STORE_AND_NOTIFY; param = qmi_param_new(); if (!param) @@ -524,6 +784,9 @@ static void create_wms_cb(struct qmi_service *service, void *user_data) data->wms = qmi_service_ref(service); + memset(&data->rd_msg_id, 0, sizeof(data->rd_msg_id)); + data->msg_mode = QMI_WMS_MESSAGE_MODE_GSMWCDMA; + qmi_service_register(data->wms, QMI_WMS_EVENT, event_notify, sms, NULL); @@ -568,6 +831,9 @@ static void qmi_sms_remove(struct ofono_sms *sms) qmi_service_unref(data->wms); + if (data->msg_list) + g_free(data->msg_list); + g_free(data); } diff --git a/ofono/drivers/qmimodem/wms.h b/ofono/drivers/qmimodem/wms.h index 7e18ec9d4..f53fc1bdf 100644 --- a/ofono/drivers/qmimodem/wms.h +++ b/ofono/drivers/qmimodem/wms.h @@ -25,8 +25,9 @@ #define QMI_WMS_RAW_SEND 32 /* Send a raw message */ -#define QMI_WMS_RAW_READ 34 /* Read raw message from storage*/ - +#define QMI_WMS_RAW_READ 34 /* Read raw message from storage */ +#define QMI_WMS_DELETE 36 /* Delete message */ +#define QMI_WMS_GET_MSG_PROTOCOL 48 /* Get message protocol */ #define QMI_WMS_GET_MSG_LIST 49 /* Get list of messages from the device */ #define QMI_WMS_SET_ROUTES 50 /* Set routes for message memory storage */ #define QMI_WMS_GET_ROUTES 51 /* Get routes for message memory storage */ @@ -45,6 +46,17 @@ struct qmi_wms_result_new_msg_notify { uint32_t storage_index; } __attribute__((__packed__)); +#define QMI_WMS_RESULT_MESSAGE 0x11 +struct qmi_wms_result_message { + uint8_t ack_required; /* bool */ + uint32_t transaction_id; + uint8_t msg_format; + uint16_t msg_length; + uint8_t msg_data[0]; +} __attribute__((__packed__)); + +#define QMI_WMS_RESULT_MSG_MODE 0x12 + /* Set new message conditions */ #define QMI_WMS_PARAM_NEW_MSG_REPORT 0x10 /* bool */ @@ -57,23 +69,59 @@ struct qmi_wms_param_message { } __attribute__((__packed__)); #define QMI_WMS_RESULT_MESSAGE_ID 0x01 /* uint16 */ +/* Read a raw message */ +#define QMI_WMS_PARAM_READ_MSG 0x01 +struct qmi_wms_read_msg_id { + uint8_t type; + uint32_t ndx; +} __attribute__((__packed__)); + +#define QMI_WMS_PARAM_READ_MODE 0x10 + +#define QMI_WMS_RESULT_READ_MSG 0x01 +struct qmi_wms_raw_message { + uint8_t msg_tag; + uint8_t msg_format; + uint16_t msg_length; + uint8_t msg_data[0]; +} __attribute__((__packed__)); + +/* Delete messages */ +#define QMI_WMS_PARAM_DEL_STORE 0x01 +#define QMI_WMS_PARAM_DEL_NDX 0x10 +#define QMI_WMS_PARAM_DEL_TYPE 0x11 +#define QMI_WMS_PARAM_DEL_MODE 0x12 + +/* Get message protocol */ +#define QMI_WMS_PARAM_PROTOCOL 0x01 + /* Get list of messages from the device */ #define QMI_WMS_PARAM_STORAGE_TYPE 0x01 /* uint8 */ +#define QMI_WMS_PARAM_TAG_TYPE 0x10 #define QMI_WMS_PARAM_MESSAGE_MODE 0x11 /* uint8 */ +#define QMI_WMS_RESULT_MSG_LIST 0x01 +struct qmi_wms_result_msg_list { + uint32_t cnt; + struct { + uint32_t ndx; + uint8_t type; + } __attribute__((__packed__)) msg[0]; +} __attribute__((__packed__)); + #define QMI_WMS_STORAGE_TYPE_UIM 0 #define QMI_WMS_STORAGE_TYPE_NV 1 #define QMI_WMS_STORAGE_TYPE_UNKNOWN 2 #define QMI_WMS_STORAGE_TYPE_NONE 255 -#define QMI_WMS_MESSAGE_MODE_GSMWCDMA 1 +#define QMI_WMS_MT_READ 0x00 +#define QMI_WMS_MT_NOT_READ 0x01 +#define QMI_WMS_MO_SENT 0x02 +#define QMI_WMS_MO_NOT_SENT 0x03 +#define QMI_WMS_MT_UNDEFINE 0xff -struct qmi_wms_raw_message { - uint8_t msg_tag; - uint8_t msg_format; - uint16_t msg_length; - uint8_t msg_data[0]; -} __attribute__((__packed__)); +#define QMI_WMS_MESSAGE_MODE_CDMA 0x00 +#define QMI_WMS_MESSAGE_MODE_GSMWCDMA 0x01 /* Get routes for message memory storage */ #define QMI_WMS_RESULT_ROUTE_LIST 0x01 @@ -89,14 +137,6 @@ struct qmi_wms_route_list { } __attribute__((__packed__)); #define QMI_WMS_RESULT_STATUS_REPORT 0x10 /* bool */ #define QMI_WMS_PARAM_STATUS_REPORT 0x10 /* bool */ -#define QMI_WMS_RESULT_MESSAGE 0x11 -struct qmi_wms_result_message { - uint8_t ack_required; /* bool */ - uint32_t transaction_id; - uint8_t msg_format; - uint16_t msg_length; - uint8_t msg_data[0]; -} __attribute__((__packed__)); #define QMI_WMS_MSG_TYPE_P2P 0x00 #define QMI_WMS_MSG_TYPE_BROADCAST 0x01 @@ -134,3 +174,6 @@ struct qmi_wms_result_smsc_addr { #define QMI_WMS_DOMAIN_PS_PREFERRED 0x01 #define QMI_WMS_DOMAIN_CS_ONLY 0x02 #define QMI_WMS_DOMAIN_PS_ONLY 0x03 + +/* Error code */ +#define QMI_ERR_OP_DEVICE_UNSUPPORTED 0x19 From 714ab26bcf256a387e408d6ed84382a07e83975d Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Fri, 7 Jun 2019 11:56:55 +0530 Subject: [PATCH 122/320] netmon: adding get function for neighbouring cell information Added declaration of functions and structures required for getting neighbouring cell information. --- ofono/include/netmon.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ofono/include/netmon.h b/ofono/include/netmon.h index c8fcafa62..a99d6ca92 100644 --- a/ofono/include/netmon.h +++ b/ofono/include/netmon.h @@ -43,6 +43,8 @@ struct ofono_netmon_driver { unsigned int enable, unsigned int period, ofono_netmon_cb_t cb, void *data); + void (*neighbouring_cell_update)(struct ofono_netmon *netmon, + ofono_netmon_cb_t cb, void *data); }; enum ofono_netmon_cell_type { @@ -104,6 +106,10 @@ void ofono_netmon_set_data(struct ofono_netmon *netmon, void *data); void *ofono_netmon_get_data(struct ofono_netmon *netmon); +void ofono_netmon_neighbouring_cell_notify(struct ofono_netmon *netmon, + enum ofono_netmon_cell_type type, + int info_type, ...); + #ifdef __cplusplus } #endif From d2c8d1e164d2b18dab09db355dcf14b6d7accace Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Fri, 7 Jun 2019 11:17:52 +0530 Subject: [PATCH 123/320] netmon: adding get functionality for neighbouring cell information Handled the get neighbouring cell information function which returns an array of signal strength of all neighbouring cells. --- ofono/src/netmon.c | 253 ++++++++++++++++++++++++++++++++------------- 1 file changed, 184 insertions(+), 69 deletions(-) diff --git a/ofono/src/netmon.c b/ofono/src/netmon.c index 6c19df523..9eacb3ca5 100644 --- a/ofono/src/netmon.c +++ b/ofono/src/netmon.c @@ -50,6 +50,8 @@ struct ofono_netmon { const struct ofono_netmon_driver *driver; DBusMessage *pending; DBusMessage *reply; + DBusMessageIter iter; + DBusMessageIter arr; void *driver_data; struct ofono_atom *atom; struct netmon_agent *agent; @@ -69,174 +71,145 @@ static const char *cell_type_to_tech_name(enum ofono_netmon_cell_type type) return NULL; } -void ofono_netmon_serving_cell_notify(struct ofono_netmon *netmon, - enum ofono_netmon_cell_type type, - int info_type, ...) +static void netmon_cell_info_dict_append(DBusMessageIter *dict, + va_list *arglist, int info_type) { - va_list arglist; - DBusMessage *agent_notify = NULL; - DBusMessageIter iter; - DBusMessageIter dict; - enum ofono_netmon_info next_info_type = info_type; - const char *technology = cell_type_to_tech_name(type); char *mcc; char *mnc; int intval; - - if (netmon->pending != NULL) { - netmon->reply = dbus_message_new_method_return(netmon->pending); - dbus_message_iter_init_append(netmon->reply, &iter); - } else if (netmon->agent != NULL) { - agent_notify = netmon_agent_new_method_call(netmon->agent, - "ServingCellInformationChanged"); - - dbus_message_iter_init_append(agent_notify, &iter); - } else - return; - - dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, - OFONO_PROPERTIES_ARRAY_SIGNATURE, - &dict); - - va_start(arglist, info_type); - - if (technology == NULL) - goto done; - - ofono_dbus_dict_append(&dict, "Technology", - DBUS_TYPE_STRING, &technology); + enum ofono_netmon_info next_info_type = info_type; while (next_info_type != OFONO_NETMON_INFO_INVALID) { switch (next_info_type) { case OFONO_NETMON_INFO_MCC: - mcc = va_arg(arglist, char *); + mcc = va_arg(*arglist, char *); if (mcc && strlen(mcc)) - ofono_dbus_dict_append(&dict, + ofono_dbus_dict_append(dict, "MobileCountryCode", DBUS_TYPE_STRING, &mcc); break; case OFONO_NETMON_INFO_MNC: - mnc = va_arg(arglist, char *); + mnc = va_arg(*arglist, char *); if (mnc && strlen(mnc)) - ofono_dbus_dict_append(&dict, + ofono_dbus_dict_append(dict, "MobileNetworkCode", DBUS_TYPE_STRING, &mnc); break; case OFONO_NETMON_INFO_LAC: - intval = va_arg(arglist, int); + intval = va_arg(*arglist, int); - CELL_INFO_DICT_APPEND(&dict, "LocationAreaCode", + CELL_INFO_DICT_APPEND(dict, "LocationAreaCode", intval, uint16_t, DBUS_TYPE_UINT16); break; case OFONO_NETMON_INFO_CI: - intval = va_arg(arglist, int); + intval = va_arg(*arglist, int); - CELL_INFO_DICT_APPEND(&dict, "CellId", + CELL_INFO_DICT_APPEND(dict, "CellId", intval, uint32_t, DBUS_TYPE_UINT32); break; case OFONO_NETMON_INFO_ARFCN: - intval = va_arg(arglist, int); + intval = va_arg(*arglist, int); - CELL_INFO_DICT_APPEND(&dict, "ARFCN", + CELL_INFO_DICT_APPEND(dict, "ARFCN", intval, uint16_t, DBUS_TYPE_UINT16); break; case OFONO_NETMON_INFO_BSIC: - intval = va_arg(arglist, int); + intval = va_arg(*arglist, int); - CELL_INFO_DICT_APPEND(&dict, "BSIC", + CELL_INFO_DICT_APPEND(dict, "BSIC", intval, uint8_t, DBUS_TYPE_BYTE); break; case OFONO_NETMON_INFO_RXLEV: - intval = va_arg(arglist, int); + intval = va_arg(*arglist, int); - CELL_INFO_DICT_APPEND(&dict, "ReceivedSignalStrength", + CELL_INFO_DICT_APPEND(dict, "ReceivedSignalStrength", intval, uint8_t, DBUS_TYPE_BYTE); break; case OFONO_NETMON_INFO_TIMING_ADVANCE: - intval = va_arg(arglist, int); + intval = va_arg(*arglist, int); - CELL_INFO_DICT_APPEND(&dict, "TimingAdvance", + CELL_INFO_DICT_APPEND(dict, "TimingAdvance", intval, uint8_t, DBUS_TYPE_BYTE); break; case OFONO_NETMON_INFO_PSC: - intval = va_arg(arglist, int); + intval = va_arg(*arglist, int); - CELL_INFO_DICT_APPEND(&dict, "PrimaryScramblingCode", + CELL_INFO_DICT_APPEND(dict, "PrimaryScramblingCode", intval, uint16_t, DBUS_TYPE_UINT16); break; case OFONO_NETMON_INFO_BER: - intval = va_arg(arglist, int); + intval = va_arg(*arglist, int); - CELL_INFO_DICT_APPEND(&dict, "BitErrorRate", + CELL_INFO_DICT_APPEND(dict, "BitErrorRate", intval, uint8_t, DBUS_TYPE_BYTE); break; case OFONO_NETMON_INFO_RSSI: - intval = va_arg(arglist, int); + intval = va_arg(*arglist, int); - CELL_INFO_DICT_APPEND(&dict, "Strength", + CELL_INFO_DICT_APPEND(dict, "Strength", intval, uint8_t, DBUS_TYPE_BYTE); break; case OFONO_NETMON_INFO_RSCP: - intval = va_arg(arglist, int); + intval = va_arg(*arglist, int); - CELL_INFO_DICT_APPEND(&dict, "ReceivedSignalCodePower", + CELL_INFO_DICT_APPEND(dict, "ReceivedSignalCodePower", intval, uint8_t, DBUS_TYPE_BYTE); break; case OFONO_NETMON_INFO_ECN0: - intval = va_arg(arglist, int); + intval = va_arg(*arglist, int); - CELL_INFO_DICT_APPEND(&dict, "ReceivedEnergyRatio", + CELL_INFO_DICT_APPEND(dict, "ReceivedEnergyRatio", intval, uint8_t, DBUS_TYPE_BYTE); break; case OFONO_NETMON_INFO_RSRQ: - intval = va_arg(arglist, int); + intval = va_arg(*arglist, int); - CELL_INFO_DICT_APPEND(&dict, + CELL_INFO_DICT_APPEND(dict, "ReferenceSignalReceivedQuality", intval, uint8_t, DBUS_TYPE_BYTE); break; case OFONO_NETMON_INFO_RSRP: - intval = va_arg(arglist, int); + intval = va_arg(*arglist, int); - CELL_INFO_DICT_APPEND(&dict, + CELL_INFO_DICT_APPEND(dict, "ReferenceSignalReceivedPower", intval, uint8_t, DBUS_TYPE_BYTE); break; case OFONO_NETMON_INFO_EARFCN: - intval = va_arg(arglist, int); + intval = va_arg(*arglist, int); - CELL_INFO_DICT_APPEND(&dict, "EARFCN", + CELL_INFO_DICT_APPEND(dict, "EARFCN", intval, uint16_t, DBUS_TYPE_UINT16); break; case OFONO_NETMON_INFO_EBAND: - intval = va_arg(arglist, int); + intval = va_arg(*arglist, int); - CELL_INFO_DICT_APPEND(&dict, "EBand", + CELL_INFO_DICT_APPEND(dict, "EBand", intval, uint8_t, DBUS_TYPE_BYTE); break; case OFONO_NETMON_INFO_CQI: - intval = va_arg(arglist, int); + intval = va_arg(*arglist, int); - CELL_INFO_DICT_APPEND(&dict, "ChannelQualityIndicator", + CELL_INFO_DICT_APPEND(dict, "ChannelQualityIndicator", intval, uint8_t, DBUS_TYPE_BYTE); break; @@ -244,8 +217,44 @@ void ofono_netmon_serving_cell_notify(struct ofono_netmon *netmon, break; } - next_info_type = va_arg(arglist, int); + next_info_type = va_arg(*arglist, int); } +} + +void ofono_netmon_serving_cell_notify(struct ofono_netmon *netmon, + enum ofono_netmon_cell_type type, + int info_type, ...) +{ + va_list arglist; + DBusMessage *agent_notify = NULL; + DBusMessageIter iter; + DBusMessageIter dict; + const char *technology = cell_type_to_tech_name(type); + + if (netmon->pending != NULL) { + netmon->reply = dbus_message_new_method_return(netmon->pending); + dbus_message_iter_init_append(netmon->reply, &iter); + } else if (netmon->agent != NULL) { + agent_notify = netmon_agent_new_method_call(netmon->agent, + "ServingCellInformationChanged"); + + dbus_message_iter_init_append(agent_notify, &iter); + } else + return; + + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + OFONO_PROPERTIES_ARRAY_SIGNATURE, + &dict); + + va_start(arglist, info_type); + + if (technology == NULL) + goto done; + + ofono_dbus_dict_append(&dict, "Technology", + DBUS_TYPE_STRING, &technology); + + netmon_cell_info_dict_append(&dict, &arglist, info_type); done: va_end(arglist); @@ -403,6 +412,109 @@ static DBusMessage *netmon_unregister_agent(DBusConnection *conn, return dbus_message_new_method_return(msg); } + +void ofono_netmon_neighbouring_cell_notify(struct ofono_netmon *netmon, + enum ofono_netmon_cell_type type, + int info_type, ...) +{ + va_list arglist; + DBusMessageIter dict; + DBusMessageIter strct; + const char *tech = cell_type_to_tech_name(type); + + if (netmon->pending == NULL) + return; + + if (!netmon->reply) { + netmon->reply = dbus_message_new_method_return(netmon->pending); + dbus_message_iter_init_append(netmon->reply, &netmon->iter); + + dbus_message_iter_open_container(&netmon->iter, DBUS_TYPE_ARRAY, + DBUS_STRUCT_BEGIN_CHAR_AS_STRING + DBUS_TYPE_ARRAY_AS_STRING + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING + DBUS_STRUCT_END_CHAR_AS_STRING, + &netmon->arr); + } + + tech = cell_type_to_tech_name(type); + + dbus_message_iter_open_container(&netmon->arr, DBUS_TYPE_STRUCT, + NULL, &strct); + dbus_message_iter_open_container(&strct, DBUS_TYPE_ARRAY, + OFONO_PROPERTIES_ARRAY_SIGNATURE, + &dict); + + va_start(arglist, info_type); + + if (tech == NULL) + goto done; + + ofono_dbus_dict_append(&dict, "Technology", + DBUS_TYPE_STRING, &tech); + + netmon_cell_info_dict_append(&dict, &arglist, info_type); + +done: + va_end(arglist); + + dbus_message_iter_close_container(&strct, &dict); + dbus_message_iter_close_container(&netmon->arr, &strct); +} + +static void neighbouring_cell_info_callback(const struct ofono_error *error, + void *data) +{ + struct ofono_netmon *netmon = data; + DBusMessage *reply = netmon->reply; + + DBG(""); + + if (error->type != OFONO_ERROR_TYPE_NO_ERROR) { + if (reply) + dbus_message_unref(reply); + + reply = __ofono_error_failed(netmon->pending); + } else if (!reply) { + DBusMessageIter iter; + DBusMessageIter dict; + + reply = dbus_message_new_method_return(netmon->pending); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + OFONO_PROPERTIES_ARRAY_SIGNATURE, + &dict); + dbus_message_iter_close_container(&iter, &dict); + } else { + dbus_message_iter_close_container(&netmon->iter, &netmon->arr); + } + + netmon->reply = NULL; + __ofono_dbus_pending_reply(&netmon->pending, reply); +} + +static DBusMessage *netmon_get_neighbouring_cell_info(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct ofono_netmon *netmon = data; + + if (!netmon->driver->neighbouring_cell_update) + return __ofono_error_not_implemented(msg); + + if (netmon->pending) + return __ofono_error_busy(msg); + + netmon->pending = dbus_message_ref(msg); + + netmon->driver->neighbouring_cell_update(netmon, + neighbouring_cell_info_callback, netmon); + + return NULL; +} + static const GDBusMethodTable netmon_methods[] = { { GDBUS_ASYNC_METHOD("GetServingCellInformation", NULL, GDBUS_ARGS({ "cellinfo", "a{sv}" }), @@ -413,6 +525,9 @@ static const GDBusMethodTable netmon_methods[] = { { GDBUS_METHOD("UnregisterAgent", GDBUS_ARGS({ "agent", "o" }), NULL, netmon_unregister_agent) }, + { GDBUS_ASYNC_METHOD("GetNeighbouringCellInformation", + NULL, GDBUS_ARGS({ "cellinfo", "a(a{sv})" }), + netmon_get_neighbouring_cell_info) }, { } }; From 8a274b8c8967deabf267e5479bca7d37e2ba83f5 Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Fri, 7 Jun 2019 11:18:10 +0530 Subject: [PATCH 124/320] xmm7modem: adding netmon changes for reporting neighbouring cell Added netmon changes for xmm7modem driver to fetch neighbouring cell information. --- ofono/drivers/xmm7modem/netmon.c | 102 +++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 19 deletions(-) diff --git a/ofono/drivers/xmm7modem/netmon.c b/ofono/drivers/xmm7modem/netmon.c index ba70e2bd6..0e958abef 100644 --- a/ofono/drivers/xmm7modem/netmon.c +++ b/ofono/drivers/xmm7modem/netmon.c @@ -47,6 +47,7 @@ static const char *xmci_prefix[] = { "+XMCI:", NULL }; struct netmon_driver_data { GAtChat *chat; + int xmci_mode; }; enum xmci_ofono_type_info { @@ -85,6 +86,7 @@ static void xmci_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct cb_data *cbd = user_data; struct ofono_netmon *netmon = cbd->data; + struct netmon_driver_data *nmd = ofono_netmon_get_data(netmon); ofono_netmon_cb_t cb = cbd->cb; struct ofono_error error; GAtResultIter iter; @@ -96,6 +98,11 @@ static void xmci_cb(gboolean ok, GAtResult *result, gpointer user_data) int ecn0 = -1; int rsrq = -1; int tech = -1; + int type = -1; + int ci = -1; + const char *cell_id; + char mcc[3]; + char mnc[3]; DBG("ok %d", ok); @@ -109,18 +116,23 @@ static void xmci_cb(gboolean ok, GAtResult *result, gpointer user_data) g_at_result_iter_init(&iter, result); while (g_at_result_iter_next(&iter, "+XMCI:")) { - if (!g_at_result_iter_next_number(&iter, &number)) + if (!g_at_result_iter_next_number(&iter, &type)) break; - tech = xmm7modem_map_radio_access_technology(number); + tech = xmm7modem_map_radio_access_technology(type); - switch (number) { + switch (type) { + case XMCI_GSM_NEIGH_CELL: case XMCI_GSM_SERV_CELL: - /* skip ,,,, */ - g_at_result_iter_skip_next(&iter); - g_at_result_iter_skip_next(&iter); - g_at_result_iter_skip_next(&iter); + /* ,,,, */ + g_at_result_iter_next_number(&iter, &number); + snprintf(mcc, 3, "%d", number); + g_at_result_iter_next_number(&iter, &number); + snprintf(mnc, 3, "%d", number); g_at_result_iter_skip_next(&iter); + g_at_result_iter_next_string(&iter, &cell_id); + sscanf(&cell_id[2], "%x", &number); + ci = number != -1 ? number : 0; g_at_result_iter_skip_next(&iter); g_at_result_iter_next_number(&iter, &number); @@ -129,15 +141,20 @@ static void xmci_cb(gboolean ok, GAtResult *result, gpointer user_data) g_at_result_iter_next_number(&iter, &number); ber = number != 99 ? number : ber; break; + case XMCI_UMTS_NEIGH_CELL: case XMCI_UMTS_SERV_CELL: /* - * skip ,,,,, + * ,,,,, * ,, */ + g_at_result_iter_next_number(&iter, &number); + snprintf(mcc, 3, "%d", number); + g_at_result_iter_next_number(&iter, &number); + snprintf(mnc, 3, "%d", number); g_at_result_iter_skip_next(&iter); - g_at_result_iter_skip_next(&iter); - g_at_result_iter_skip_next(&iter); - g_at_result_iter_skip_next(&iter); + g_at_result_iter_next_string(&iter, &cell_id); + sscanf(&cell_id[2], "%x", &number); + ci = number != -1 ? number : 0; g_at_result_iter_skip_next(&iter); g_at_result_iter_skip_next(&iter); g_at_result_iter_skip_next(&iter); @@ -150,15 +167,20 @@ static void xmci_cb(gboolean ok, GAtResult *result, gpointer user_data) g_at_result_iter_next_number(&iter, &number); ecn0 = number != 255 ? number : ecn0; break; + case XMCI_LTE_NEIGH_CELL: case XMCI_LTE_SERV_CELL: /* - * skip ,,,,,, + * ,,,,,, * , */ + g_at_result_iter_next_number(&iter, &number); + snprintf(mcc, 3, "%d", number); + g_at_result_iter_next_number(&iter, &number); + snprintf(mnc, 3, "%d", number); g_at_result_iter_skip_next(&iter); - g_at_result_iter_skip_next(&iter); - g_at_result_iter_skip_next(&iter); - g_at_result_iter_skip_next(&iter); + g_at_result_iter_next_string(&iter, &cell_id); + sscanf(&cell_id[2], "%x", &number); + ci = number != -1 ? number : 0; g_at_result_iter_skip_next(&iter); g_at_result_iter_skip_next(&iter); g_at_result_iter_skip_next(&iter); @@ -174,8 +196,15 @@ static void xmci_cb(gboolean ok, GAtResult *result, gpointer user_data) break; } - ofono_netmon_serving_cell_notify(netmon, + if ((nmd->xmci_mode == 0) && + (type == XMCI_GSM_NEIGH_CELL || + type == XMCI_UMTS_NEIGH_CELL || + type == XMCI_LTE_NEIGH_CELL)) { + ofono_netmon_neighbouring_cell_notify(netmon, tech, + OFONO_NETMON_INFO_MCC, mcc, + OFONO_NETMON_INFO_MNC, mnc, + OFONO_NETMON_INFO_CI, ci, OFONO_NETMON_INFO_RXLEV, rxlev, OFONO_NETMON_INFO_BER, ber, OFONO_NETMON_INFO_RSCP, rscp, @@ -183,10 +212,25 @@ static void xmci_cb(gboolean ok, GAtResult *result, gpointer user_data) OFONO_NETMON_INFO_RSRQ, rsrq, OFONO_NETMON_INFO_RSRP, rsrp, OFONO_NETMON_INFO_INVALID); - - CALLBACK_WITH_SUCCESS(cb, cbd->data); - break; + } else if ((nmd->xmci_mode == 1) && + (type == XMCI_GSM_SERV_CELL || + type == XMCI_UMTS_SERV_CELL || + type == XMCI_LTE_SERV_CELL)) { + ofono_netmon_serving_cell_notify(netmon, + tech, + OFONO_NETMON_INFO_RXLEV, rxlev, + OFONO_NETMON_INFO_BER, ber, + OFONO_NETMON_INFO_RSCP, rscp, + OFONO_NETMON_INFO_ECN0, ecn0, + OFONO_NETMON_INFO_RSRQ, rsrq, + OFONO_NETMON_INFO_RSRP, rsrp, + OFONO_NETMON_INFO_INVALID); + break; + } } + + CALLBACK_WITH_SUCCESS(cb, cbd->data); + nmd->xmci_mode = -1; } static void xmm7modem_netmon_request_update(struct ofono_netmon *netmon, @@ -194,6 +238,7 @@ static void xmm7modem_netmon_request_update(struct ofono_netmon *netmon, { struct netmon_driver_data *nmd = ofono_netmon_get_data(netmon); struct cb_data *cbd = cb_data_new(cb, data); + nmd->xmci_mode = 1; DBG("xmm7modem netmon request update"); @@ -205,6 +250,23 @@ static void xmm7modem_netmon_request_update(struct ofono_netmon *netmon, CALLBACK_WITH_FAILURE(cb, data); } +static void xmm7modem_neighbouring_cell_update(struct ofono_netmon *netmon, + ofono_netmon_cb_t cb, void *data) +{ + struct netmon_driver_data *nmd = ofono_netmon_get_data(netmon); + struct cb_data *cbd = cb_data_new(cb, data); + nmd->xmci_mode = 0; + + DBG("xmm7modem netmon request neighbouring cell update"); + + if (g_at_chat_send(nmd->chat, "AT+XMCI=0", xmci_prefix, + xmci_cb, cbd, g_free) > 0) + return; + + g_free(cbd); + CALLBACK_WITH_FAILURE(cb, data); +} + static gboolean ril_delayed_register(gpointer user_data) { struct ofono_netmon *netmon = user_data; @@ -224,6 +286,7 @@ static int xmm7modem_netmon_probe(struct ofono_netmon *netmon, nmd = g_new0(struct netmon_driver_data, 1); nmd->chat = g_at_chat_clone(chat); + nmd->xmci_mode = -1; ofono_netmon_set_data(netmon, nmd); @@ -250,6 +313,7 @@ static const struct ofono_netmon_driver driver = { .probe = xmm7modem_netmon_probe, .remove = xmm7modem_netmon_remove, .request_update = xmm7modem_netmon_request_update, + .neighbouring_cell_update = xmm7modem_neighbouring_cell_update, }; void xmm_netmon_init(void) From 70ceaf6a3f03440b2e0d0fff487c11d1dd71d04f Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Fri, 14 Jun 2019 14:56:36 +0530 Subject: [PATCH 125/320] atmodem: fix to activate context with cid zero xmm7xxx based devices (among others) return 0 as cid for default pdp context. Fix the atmodem gprs driver logic to work with such devices by initializing last_auto_context_id to -1 instead of 0 to indicate a deactivated context. --- ofono/drivers/atmodem/gprs.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ofono/drivers/atmodem/gprs.c b/ofono/drivers/atmodem/gprs.c index dd734585c..fbee5c949 100644 --- a/ofono/drivers/atmodem/gprs.c +++ b/ofono/drivers/atmodem/gprs.c @@ -48,7 +48,7 @@ static const char *none_prefix[] = { NULL }; struct gprs_data { GAtChat *chat; unsigned int vendor; - unsigned int last_auto_context_id; + int last_auto_context_id; gboolean telit_try_reattach; int attached; }; @@ -161,7 +161,7 @@ static void at_cgdcont_read_cb(gboolean ok, GAtResult *result, return; } - if (gd->last_auto_context_id == 0) { + if (gd->last_auto_context_id == -1) { DBG("Context got deactivated while calling CGDCONT"); return; } @@ -257,11 +257,11 @@ static void cgev_notify(GAtResult *result, gpointer user_data) g_at_chat_send(gd->chat, "AT+CGDCONT?", cgdcont_prefix, at_cgdcont_read_cb, gprs, NULL); } else if (g_str_has_prefix(event, "ME PDN DEACT")) { - unsigned int context_id; + int context_id; sscanf(event, "%*s %*s %*s %u", &context_id); /* Indicate that this cid is not activated anymore */ if (gd->last_auto_context_id == context_id) - gd->last_auto_context_id = 0; + gd->last_auto_context_id = -1; } } @@ -632,6 +632,7 @@ static int at_gprs_probe(struct ofono_gprs *gprs, gd->chat = g_at_chat_clone(chat); gd->vendor = vendor; + gd->last_auto_context_id = -1; ofono_gprs_set_data(gprs, gd); From c2f50a60d7f3ff51e5a3f1fdbd7e84fc92ecd471 Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Mon, 17 Jun 2019 14:38:04 -0400 Subject: [PATCH 126/320] isimodem: gprs-context: properly null terminate cd->password MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It looks like a previous line was copied and cd->username was re-terminated instead of password. This also fixes a compiler error when using GCC 9: In function ‘strncpy’, inlined from ‘isi_gprs_activate_primary’ at drivers/isimodem/gprs-context.c:546:3: /usr/include/bits/string_fortified.h:106:10: error: ‘__builtin_strncpy’ output may be truncated copying 53 bytes from a string of length 255 [-Werror=stringop-truncation] 106 | return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --- ofono/drivers/isimodem/gprs-context.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/ofono/drivers/isimodem/gprs-context.c b/ofono/drivers/isimodem/gprs-context.c index 5258cb17f..4076ed8b4 100644 --- a/ofono/drivers/isimodem/gprs-context.c +++ b/ofono/drivers/isimodem/gprs-context.c @@ -537,11 +537,15 @@ static void isi_gprs_activate_primary(struct ofono_gprs_context *gc, strncpy(cd->apn, ctx->apn, GPDS_MAX_APN_STRING_LENGTH); cd->apn[GPDS_MAX_APN_STRING_LENGTH] = '\0'; - strncpy(cd->username, ctx->username, GPDS_MAX_USERNAME_LENGTH); - cd->username[GPDS_MAX_USERNAME_LENGTH] = '\0'; - - strncpy(cd->password, ctx->password, GPDS_MAX_PASSWORD_LENGTH); - cd->username[GPDS_MAX_PASSWORD_LENGTH] = '\0'; + if (ctx->auth_method == OFONO_GPRS_AUTH_METHOD_NONE) { + memset(cd->username, 0, sizeof(cd->username)); + memset(cd->password, 0, sizeof(cd->password)); + } else { + strncpy(cd->username, ctx->username, GPDS_MAX_USERNAME_LENGTH); + cd->username[GPDS_MAX_USERNAME_LENGTH] = '\0'; + strncpy(cd->password, ctx->password, GPDS_MAX_PASSWORD_LENGTH); + cd->password[GPDS_MAX_PASSWORD_LENGTH] = '\0'; + } cd->pep = g_isi_pep_create(cd->idx, NULL, NULL); if (cd->pep == NULL) From f225cc9ab120bad4c1b930c54e22bb4c1ce6f198 Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Thu, 20 Jun 2019 17:37:23 +0530 Subject: [PATCH 127/320] xmm7modem: disabling reporting of intermediate results for CGDATA Setting in AT+XDATACHANNEL set command to 0. This will disable intermediate result reporting of "CONNECT" and "NO CARRIER" on control channel. This resolves the issue of getting failure response for offline-modem since "NO CARRIER" is received as result of AT+CFUN operation instead of "OK". --- ofono/drivers/ifxmodem/gprs-context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/drivers/ifxmodem/gprs-context.c b/ofono/drivers/ifxmodem/gprs-context.c index 42d232a29..e17beae49 100644 --- a/ofono/drivers/ifxmodem/gprs-context.c +++ b/ofono/drivers/ifxmodem/gprs-context.c @@ -405,7 +405,7 @@ static void cgcontrdp_cb(gboolean ok, GAtResult *result, gpointer user_data) interface = ofono_gprs_context_get_interface(gc); datapath = get_datapath(modem, interface); - snprintf(buf, sizeof(buf), "AT+XDATACHANNEL=1,1,\"%s\",\"%s\",2,%u", + snprintf(buf, sizeof(buf), "AT+XDATACHANNEL=1,1,\"%s\",\"%s\",0,%u", ctrlpath, datapath, gcd->active_context); g_at_chat_send(gcd->chat, buf, none_prefix, NULL, NULL, NULL); snprintf(buf, sizeof(buf), "AT+CGDATA=\"M-RAW_IP\",%u", From aa02471758ce0af5839f13e1b73b7368cb677e2b Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 21 Jun 2019 12:47:18 -0500 Subject: [PATCH 128/320] mbim: Fix warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC drivers/mbimmodem/mbim-message.o drivers/mbimmodem/mbim-message.c: In function ‘_iter_copy_string’: drivers/mbimmodem/mbim-message.c:199:18: error: cast increases required alignment of target type [-Werror=cast-align] --- ofono/drivers/mbimmodem/mbim-message.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ofono/drivers/mbimmodem/mbim-message.c b/ofono/drivers/mbimmodem/mbim-message.c index 781aff223..cd392c703 100644 --- a/ofono/drivers/mbimmodem/mbim-message.c +++ b/ofono/drivers/mbimmodem/mbim-message.c @@ -152,8 +152,8 @@ static bool _iter_copy_string(struct mbim_message_iter *iter, uint32_t offset, uint32_t len, char **out) { - uint8_t buf[len]; - uint8_t *dest = buf; + uint16_t buf[len / 2 + 1]; + uint8_t *dest = (uint8_t *) buf; uint32_t remaining = len; uint32_t iov_start = 0; uint32_t i = 0; @@ -195,7 +195,7 @@ static bool _iter_copy_string(struct mbim_message_iter *iter, /* Strings are in UTF16-LE, so convert to UTF16-CPU first if needed */ if (L_CPU_TO_LE16(0x8000) != 0x8000) { - uint16_t *le = (uint16_t *) buf; + uint16_t *le = buf; for (i = 0; i < len / 2; i++) le[i] = __builtin_bswap16(le[i]); From 99138351ada615245b7820f333e7509f28b841d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Fri, 21 Jun 2019 11:56:08 +0200 Subject: [PATCH 129/320] ubloxmodem: fix maybe-unitialized error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: ../git/drivers/ubloxmodem/gprs-context.c: In function ‘ublox_gprs_activate_primary’: ../git/drivers/ubloxmodem/gprs-context.c:339:2: error: ‘auth’ may be used uninitialized in this function [-Werror=maybe-uninitialized] snprintf(buf, sizeof(buf), "AT+UAUTHREQ=%u,%u,\"%s\",\"%s\"", ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gcd->active_context, auth, username, password); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../git/drivers/ubloxmodem/gprs-context.c:324:11: note: ‘auth’ was declared here unsigned auth; ^~~~ --- ofono/drivers/ubloxmodem/gprs-context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/drivers/ubloxmodem/gprs-context.c b/ofono/drivers/ubloxmodem/gprs-context.c index 3b48062a7..732364200 100644 --- a/ofono/drivers/ubloxmodem/gprs-context.c +++ b/ofono/drivers/ubloxmodem/gprs-context.c @@ -321,7 +321,7 @@ static void ublox_send_uauthreq(struct ofono_gprs_context *gc, { struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); char buf[UBLOX_MAX_USER_LEN + UBLOX_MAX_PASS_LEN + 32]; - unsigned auth; + unsigned auth = 0; switch (auth_method) { case OFONO_GPRS_AUTH_METHOD_PAP: From 5591a16e1ffced52566cd5070b7ca653be3d7001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Wed, 3 Jul 2019 20:09:46 +0200 Subject: [PATCH 130/320] gatresult: include glib header The gatresult data types embeds GSList members, and the function prototypes uses glib types. Add include of glib.h to allow use of gatresult.h without also including glib.h --- ofono/gatchat/gatresult.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ofono/gatchat/gatresult.h b/ofono/gatchat/gatresult.h index 589dd3dd6..e92d38ba0 100644 --- a/ofono/gatchat/gatresult.h +++ b/ofono/gatchat/gatresult.h @@ -22,6 +22,8 @@ #ifndef __GATCHAT_RESULT_H #define __GATCHAT_RESULT_H +#include + #ifdef __cplusplus extern "C" { #endif From 4578df7fc856e092206109d3427dbb0ac11bafec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Wed, 3 Jul 2019 20:09:47 +0200 Subject: [PATCH 131/320] atutil: guard call to g_hash_table_destroy() Glib emits a warning when g_hash_table_destroy() is called on a NULL pointer: GLib-CRITICAL **: 13:27:40.269: g_hash_table_destroy: assertion 'hash_table != NULL' failed Add a check to avoid this warning. --- ofono/drivers/atmodem/atutil.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ofono/drivers/atmodem/atutil.c b/ofono/drivers/atmodem/atutil.c index 631a5b36f..073f86b31 100644 --- a/ofono/drivers/atmodem/atutil.c +++ b/ofono/drivers/atmodem/atutil.c @@ -770,7 +770,9 @@ GAtChat *at_util_open_device(struct ofono_modem *modem, const char *key, } channel = g_at_tty_open(device, options); - g_hash_table_destroy(options); + + if (options) + g_hash_table_destroy(options); if (channel == NULL) return NULL; From 5ea0d23cc63ab6d2679fa789fa18f35af11864d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Wed, 3 Jul 2019 20:09:48 +0200 Subject: [PATCH 132/320] quectel: improve coding style --- ofono/plugins/quectel.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 6ab97027d..f99b1ff8e 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -91,8 +91,8 @@ static void quectel_remove(struct ofono_modem *modem) g_free(data); } -static GAtChat *open_device(struct ofono_modem *modem, - const char *key, char *debug) +static GAtChat *open_device(struct ofono_modem *modem, const char *key, + char *debug) { return at_util_open_device(modem, key, quectel_debug, debug, NULL); } @@ -151,8 +151,8 @@ static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data) data->cpin_ready = g_at_chat_register(data->aux, "+CPIN", cpin_notify, FALSE, modem, NULL); - g_at_chat_send(data->aux, "AT+CPIN?", cpin_prefix, cpin_query, - modem, NULL); + g_at_chat_send(data->aux, "AT+CPIN?", cpin_prefix, cpin_query, modem, + NULL); } static void cfun_query(gboolean ok, GAtResult *result, gpointer user_data) @@ -185,8 +185,8 @@ static void cfun_query(gboolean ok, GAtResult *result, gpointer user_data) */ if (status != 1) { - g_at_chat_send(data->aux, "AT+CFUN=4", none_prefix, - cfun_enable, modem, NULL); + g_at_chat_send(data->aux, "AT+CFUN=4", none_prefix, cfun_enable, + modem, NULL); return; } @@ -212,13 +212,12 @@ static int quectel_enable(struct ofono_modem *modem) g_at_chat_set_slave(data->modem, data->aux); - g_at_chat_send(data->modem, "ATE0 &C0 +CMEE=1", none_prefix, - NULL, NULL, NULL); - g_at_chat_send(data->aux, "ATE0 &C0 +CMEE=1", none_prefix, - NULL, NULL, NULL); - - g_at_chat_send(data->aux, "AT+CFUN?", cfun_prefix, - cfun_query, modem, NULL); + g_at_chat_send(data->modem, "ATE0 &C0 +CMEE=1", none_prefix, NULL, NULL, + NULL); + g_at_chat_send(data->aux, "ATE0 &C0 +CMEE=1", none_prefix, NULL, NULL, + NULL); + g_at_chat_send(data->aux, "AT+CFUN?", cfun_prefix, cfun_query, modem, + NULL); return -EINPROGRESS; } @@ -277,8 +276,8 @@ static void quectel_set_online(struct ofono_modem *modem, ofono_bool_t online, DBG("modem %p %s", modem, online ? "online" : "offline"); - if (g_at_chat_send(data->aux, command, cfun_prefix, set_online_cb, - cbd, g_free) > 0) + if (g_at_chat_send(data->aux, command, cfun_prefix, set_online_cb, cbd, + g_free) > 0) return; CALLBACK_WITH_FAILURE(cb, cbd->data); @@ -295,7 +294,7 @@ static void quectel_pre_sim(struct ofono_modem *modem) ofono_devinfo_create(modem, 0, "atmodem", data->aux); sim = ofono_sim_create(modem, OFONO_VENDOR_QUECTEL, "atmodem", - data->aux); + data->aux); if (sim && data->have_sim == TRUE) ofono_sim_inserted_notify(sim, TRUE); From c5dca89eb7fd4dff7578e0785c5c8ce810fceecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Thu, 4 Jul 2019 13:03:50 +0200 Subject: [PATCH 133/320] quectel: fix initial channel/device configuration The three-commands-in-one-go results in error on some quectel devices (e.g. m95). Add semicolons between the commands to fix it. --- ofono/plugins/quectel.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index f99b1ff8e..37969097f 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -212,9 +212,9 @@ static int quectel_enable(struct ofono_modem *modem) g_at_chat_set_slave(data->modem, data->aux); - g_at_chat_send(data->modem, "ATE0 &C0 +CMEE=1", none_prefix, NULL, NULL, - NULL); - g_at_chat_send(data->aux, "ATE0 &C0 +CMEE=1", none_prefix, NULL, NULL, + g_at_chat_send(data->modem, "ATE0; &C0; +CMEE=1", none_prefix, NULL, + NULL, NULL); + g_at_chat_send(data->aux, "ATE0; &C0; +CMEE=1", none_prefix, NULL, NULL, NULL); g_at_chat_send(data->aux, "AT+CFUN?", cfun_prefix, cfun_query, modem, NULL); From 24897ee3db40de7f9c67b9147c2129d8d98269fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Wed, 10 Jul 2019 23:51:40 +0200 Subject: [PATCH 134/320] atmodem: sms: add quectel m95 quirks CNMA isn't mentioned in the m95 documentation, but trial'n'error has revealed some details: * the CSMS query returns the list (0,128) instead of a range * CNMA is enabled by setting 128 as CSMS service * once enabled, SMS deliveries are acked by sending AT+CNMA without a value setting Add m95 quirks to the atmodem driver, so that CNMA is correctly detected, configured, and used. --- ofono/drivers/atmodem/sms.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/ofono/drivers/atmodem/sms.c b/ofono/drivers/atmodem/sms.c index 277d65175..ee21b9d03 100644 --- a/ofono/drivers/atmodem/sms.c +++ b/ofono/drivers/atmodem/sms.c @@ -338,6 +338,9 @@ static inline void at_ack_delivery(struct ofono_sms *sms) case OFONO_VENDOR_GEMALTO: snprintf(buf, sizeof(buf), "AT+CNMA=1"); break; + case OFONO_VENDOR_QUECTEL_M95: + snprintf(buf, sizeof(buf), "AT+CNMA"); + break; default: snprintf(buf, sizeof(buf), "AT+CNMA=1,%d\r%s", data->cnma_ack_pdu_len, @@ -1237,7 +1240,7 @@ static void at_csms_status_cb(gboolean ok, GAtResult *result, if (!g_at_result_iter_next_number(&iter, &mo)) goto out; - if (service == 1) + if (service == 1 || service == 128) data->cnma_enabled = TRUE; if (mt == 1 && mo == 1) @@ -1268,10 +1271,10 @@ static void at_csms_query_cb(gboolean ok, GAtResult *result, { struct ofono_sms *sms = user_data; struct sms_data *data = ofono_sms_get_data(sms); - gboolean cnma_supported = FALSE; GAtResultIter iter; int status_min, status_max; char buf[128]; + int csms = 0; if (!ok) return at_sms_not_supported(sms); @@ -1284,14 +1287,25 @@ static void at_csms_query_cb(gboolean ok, GAtResult *result, if (!g_at_result_iter_open_list(&iter)) goto out; - while (g_at_result_iter_next_range(&iter, &status_min, &status_max)) + switch (data->vendor) { + case OFONO_VENDOR_QUECTEL_M95: + g_at_result_iter_next_number(&iter, &status_min); + g_at_result_iter_next_number(&iter, &status_max); if (status_min <= 1 && 1 <= status_max) - cnma_supported = TRUE; + csms = 128; + break; + default: + while (g_at_result_iter_next_range(&iter, &status_min, + &status_max)) + if (status_min <= 1 && 1 <= status_max) + csms = 1; + break; + } DBG("CSMS query parsed successfully"); out: - snprintf(buf, sizeof(buf), "AT+CSMS=%d", cnma_supported ? 1 : 0); + snprintf(buf, sizeof(buf), "AT+CSMS=%d", csms); g_at_chat_send(data->chat, buf, csms_prefix, at_csms_set_cb, sms, NULL); } From 0d43f04b808235716583321e0d90521045c2b46d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Wed, 10 Jul 2019 23:51:41 +0200 Subject: [PATCH 135/320] quectel: always print modem pointer in debug messages --- ofono/plugins/quectel.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 37969097f..e1a5ffa47 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -127,7 +127,7 @@ static void cpin_notify(GAtResult *result, gpointer user_data) static void cpin_query(gboolean ok, GAtResult *result, gpointer user_data) { - DBG("ok %d", ok); + DBG("%p ok %d", user_data, ok); if (ok) cpin_notify(result, user_data); @@ -138,7 +138,7 @@ static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data) struct ofono_modem *modem = user_data; struct quectel_data *data = ofono_modem_get_data(modem); - DBG("ok %d", ok); + DBG("%p ok %d", modem, ok); if (!ok) { g_at_chat_unref(data->aux); @@ -162,7 +162,7 @@ static void cfun_query(gboolean ok, GAtResult *result, gpointer user_data) GAtResultIter iter; int status; - DBG("ok %d", ok); + DBG("%p ok %d", modem, ok); if (!ok) return; @@ -227,7 +227,7 @@ static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data) struct ofono_modem *modem = user_data; struct quectel_data *data = ofono_modem_get_data(modem); - DBG(""); + DBG("%p", modem); g_at_chat_unref(data->aux); data->aux = NULL; @@ -263,6 +263,8 @@ static void set_online_cb(gboolean ok, GAtResult *result, gpointer user_data) ofono_modem_online_cb_t cb = cbd->cb; struct ofono_error error; + DBG("%p", user_data); + decode_at_error(&error, g_at_result_final_response(result)); cb(&error, cbd->data); } @@ -319,6 +321,8 @@ static void quectel_post_online(struct ofono_modem *modem) { struct quectel_data *data = ofono_modem_get_data(modem); + DBG("%p", modem); + ofono_netreg_create(modem, 0, "atmodem", data->aux); } From 93160e06fbded99fed0c7894db442bc7f1b668de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Wed, 10 Jul 2019 23:51:42 +0200 Subject: [PATCH 136/320] quectel: unwrap call to at_util_open_device() --- ofono/plugins/quectel.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index e1a5ffa47..faad16cc0 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -91,12 +91,6 @@ static void quectel_remove(struct ofono_modem *modem) g_free(data); } -static GAtChat *open_device(struct ofono_modem *modem, const char *key, - char *debug) -{ - return at_util_open_device(modem, key, quectel_debug, debug, NULL); -} - static void cpin_notify(GAtResult *result, gpointer user_data) { struct ofono_modem *modem = user_data; @@ -199,11 +193,13 @@ static int quectel_enable(struct ofono_modem *modem) DBG("%p", modem); - data->modem = open_device(modem, "Modem", "Modem: "); + data->modem = at_util_open_device(modem, "Modem", quectel_debug, + "Modem: ", NULL); if (data->modem == NULL) return -EINVAL; - data->aux = open_device(modem, "Aux", "Aux: "); + data->aux = at_util_open_device(modem, "Aux", quectel_debug, "Aux: ", + NULL); if (data->aux == NULL) { g_at_chat_unref(data->modem); data->modem = NULL; From d6320b485af59165a277ab39d5843d84d6cefc32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Wed, 10 Jul 2019 23:51:44 +0200 Subject: [PATCH 137/320] quectel: add basic support for serial connected modems 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" --- ofono/plugins/quectel.c | 274 +++++++++++++++++++++++++++++++++++----- ofono/plugins/udevng.c | 24 +++- 2 files changed, 266 insertions(+), 32 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index faad16cc0..5db0bdb07 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -25,8 +25,14 @@ #include #include +#include +#include #include +#include +#include +#include +#include #include #include @@ -47,11 +53,27 @@ static const char *cfun_prefix[] = { "+CFUN:", NULL }; static const char *cpin_prefix[] = { "+CPIN:", NULL }; static const char *none_prefix[] = { NULL }; +static const uint8_t gsm0710_terminate[] = { + 0xf9, /* open flag */ + 0x03, /* channel 0 */ + 0xef, /* UIH frame */ + 0x05, /* 2 data bytes */ + 0xc3, /* terminate 1 */ + 0x01, /* terminate 2 */ + 0xf2, /* crc */ + 0xf9, /* close flag */ +}; + struct quectel_data { GAtChat *modem; GAtChat *aux; guint cpin_ready; - gboolean have_sim; + bool have_sim; + + /* used by quectel uart driver */ + GAtChat *uart; + int mux_ready_count; + int initial_ldisc; }; static void quectel_debug(const char *str, void *user_data) @@ -88,9 +110,66 @@ static void quectel_remove(struct ofono_modem *modem) ofono_modem_set_data(modem, NULL); g_at_chat_unref(data->aux); g_at_chat_unref(data->modem); + g_at_chat_unref(data->uart); g_free(data); } +static void close_mux_cb(struct l_timeout *timeout, void *user_data) +{ + struct ofono_modem *modem = user_data; + struct quectel_data *data = ofono_modem_get_data(modem); + GIOChannel *device; + 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); + + /* 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); + ofono_modem_set_powered(modem, FALSE); +} + +static void close_serial(struct ofono_modem *modem) +{ + struct quectel_data *data = ofono_modem_get_data(modem); + + DBG("%p", modem); + + 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); + else + ofono_modem_set_powered(modem, false); +} + static void cpin_notify(GAtResult *result, gpointer user_data) { struct ofono_modem *modem = user_data; @@ -108,7 +187,7 @@ static void cpin_notify(GAtResult *result, gpointer user_data) g_at_result_iter_next_unquoted_string(&iter, &sim_inserted); if (g_strcmp0(sim_inserted, "NOT INSERTED") != 0) - data->have_sim = TRUE; + data->have_sim = true; ofono_modem_set_powered(modem, TRUE); @@ -135,11 +214,7 @@ static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data) DBG("%p ok %d", modem, 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_serial(modem); return; } @@ -154,19 +229,23 @@ static void cfun_query(gboolean ok, GAtResult *result, gpointer user_data) struct ofono_modem *modem = user_data; struct quectel_data *data = ofono_modem_get_data(modem); GAtResultIter iter; - int status; + int cfun; DBG("%p ok %d", modem, ok); - if (!ok) + if (!ok) { + close_serial(modem); return; + } g_at_result_iter_init(&iter, result); - if (g_at_result_iter_next(&iter, "+CFUN:") == FALSE) + if (g_at_result_iter_next(&iter, "+CFUN:") == FALSE) { + close_serial(modem); return; + } - g_at_result_iter_next_number(&iter, &status); + g_at_result_iter_next_number(&iter, &cfun); /* * The modem firmware powers up in CFUN=1 but will respond to AT+CFUN=4 @@ -174,20 +253,18 @@ static void cfun_query(gboolean ok, GAtResult *result, gpointer user_data) * passes. Empirical evidence suggests that the firmware will report an * unsolicited +CPIN: notification when it is ready to be useful. * - * Work around this feature by only transitioning to CFUN=4 after we've - * received an unsolicited +CPIN: notification. + * Work around this feature by only transitioning to CFUN=4 if the + * modem is not in CFUN=1 or until after we've received an unsolicited + * +CPIN: notification. */ - - if (status != 1) { + if (cfun != 1) g_at_chat_send(data->aux, "AT+CFUN=4", none_prefix, cfun_enable, modem, NULL); - return; - } - - cfun_enable(TRUE, NULL, modem); + else + cfun_enable(TRUE, NULL, modem); } -static int quectel_enable(struct ofono_modem *modem) +static int open_ttys(struct ofono_modem *modem) { struct quectel_data *data = ofono_modem_get_data(modem); @@ -218,18 +295,156 @@ static int quectel_enable(struct ofono_modem *modem) return -EINPROGRESS; } -static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data) +static void mux_ready_cb(struct l_timeout *timeout, void *user_data) { struct ofono_modem *modem = user_data; struct quectel_data *data = ofono_modem_get_data(modem); + struct stat st; + int ret; DBG("%p", modem); - g_at_chat_unref(data->aux); - data->aux = NULL; + /* check if the last (and thus all) virtual gsm tty's are created */ + ret = stat(ofono_modem_get_string(modem, "Modem"), &st); + if (ret < 0) { + if (data->mux_ready_count++ < 5) { + /* not ready yet; try again in 100 ms*/ + l_timeout_modify_ms(timeout, 100); + return; + } + + /* not ready after 500 ms; bail out */ + close_serial(modem); + return; + } - if (ok) - ofono_modem_set_powered(modem, FALSE); + /* virtual gsm tty's are ready */ + l_timeout_remove(timeout); + + if (open_ttys(modem) != -EINPROGRESS) + close_serial(modem); + + g_at_chat_set_slave(data->uart, data->modem); +} + +static void cmux_cb(gboolean ok, GAtResult *result, gpointer user_data) +{ + struct ofono_modem *modem = user_data; + struct quectel_data *data = ofono_modem_get_data(modem); + struct gsm_config gsm_config; + GIOChannel *device; + int ldisc = N_GSM0710; + int fd; + + DBG("%p", modem); + + device = g_at_chat_get_channel(data->uart); + fd = g_io_channel_unix_get_fd(device); + + /* get initial line discipline to restore after use */ + if (ioctl(fd, TIOCGETD, &data->initial_ldisc) < 0) { + ofono_error("Failed to get current line discipline: %s", + strerror(errno)); + close_serial(modem); + return; + } + + /* enable gsm 0710 multiplexing line discipline */ + if (ioctl(fd, TIOCSETD, &ldisc) < 0) { + ofono_error("Failed to set multiplexer line discipline: %s", + strerror(errno)); + close_serial(modem); + return; + } + + /* get n_gsm configuration */ + if (ioctl(fd, GSMIOC_GETCONF, &gsm_config) < 0) { + ofono_error("Failed to get gsm config: %s", strerror(errno)); + close_serial(modem); + return; + } + + gsm_config.initiator = 1; /* cpu side is initiating multiplexing */ + gsm_config.encapsulation = 0; /* basic transparency encoding */ + gsm_config.mru = 127; /* 127 bytes rx mtu */ + gsm_config.mtu = 127; /* 127 bytes tx mtu */ + gsm_config.t1 = 10; /* 100 ms ack timer */ + gsm_config.n2 = 3; /* 3 retries */ + gsm_config.t2 = 30; /* 300 ms response timer */ + gsm_config.t3 = 10; /* 100 ms wake up response timer */ + gsm_config.i = 1; /* subset */ + + /* set the new configuration */ + if (ioctl(fd, GSMIOC_SETCONF, &gsm_config) < 0) { + ofono_error("Failed to set gsm config: %s", strerror(errno)); + close_serial(modem); + return; + } + + /* + * 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, "Aux", "/dev/gsmtty1"); + ofono_modem_set_string(modem, "Modem", "/dev/gsmtty2"); + + /* wait for gsmtty devices to appear */ + if (!l_timeout_create_ms(100, mux_ready_cb, modem, NULL)) { + close_serial(modem); + return; + } +} + +static int open_serial(struct ofono_modem *modem) +{ + struct quectel_data *data = ofono_modem_get_data(modem); + const char *rts_cts; + + DBG("%p", modem); + + rts_cts = ofono_modem_get_string(modem, "RtsCts"); + + data->uart = at_util_open_device(modem, "Device", quectel_debug, + "UART: ", + "Baud", "115200", + "Parity", "none", + "StopBits", "1", + "DataBits", "8", + "XonXoff", "off", + "Local", "on", + "Read", "on", + "RtsCts", rts_cts, + NULL); + if (data->uart == NULL) + return -EINVAL; + + g_at_chat_send(data->uart, "ATE0", none_prefix, NULL, NULL, + NULL); + + /* setup multiplexing */ + g_at_chat_send(data->uart, "AT+CMUX=0,0,5,127,10,3,30,10,2", NULL, + cmux_cb, modem, NULL); + + return -EINPROGRESS; +} + +static int quectel_enable(struct ofono_modem *modem) +{ + DBG("%p", modem); + + if (ofono_modem_get_string(modem, "Device")) + return open_serial(modem); + else + return open_ttys(modem); +} + +static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data) +{ + struct ofono_modem *modem = user_data; + + DBG("%p", modem); + + close_serial(modem); } static int quectel_disable(struct ofono_modem *modem) @@ -241,14 +456,11 @@ static int quectel_disable(struct ofono_modem *modem) g_at_chat_cancel_all(data->modem); g_at_chat_unregister_all(data->modem); - g_at_chat_unref(data->modem); - data->modem = NULL; - g_at_chat_cancel_all(data->aux); g_at_chat_unregister_all(data->aux); - g_at_chat_send(data->aux, "AT+CFUN=0", cfun_prefix, - cfun_disable, modem, NULL); + g_at_chat_send(data->aux, "AT+CFUN=0", cfun_prefix, cfun_disable, modem, + NULL); return -EINPROGRESS; } @@ -294,7 +506,7 @@ static void quectel_pre_sim(struct ofono_modem *modem) sim = ofono_sim_create(modem, OFONO_VENDOR_QUECTEL, "atmodem", data->aux); - if (sim && data->have_sim == TRUE) + if (sim && data->have_sim == true) ofono_sim_inserted_notify(sim, TRUE); } diff --git a/ofono/plugins/udevng.c b/ofono/plugins/udevng.c index f0474681f..738fd6d58 100644 --- a/ofono/plugins/udevng.c +++ b/ofono/plugins/udevng.c @@ -837,7 +837,7 @@ static gboolean setup_samsung(struct modem_info *modem) return TRUE; } -static gboolean setup_quectel(struct modem_info *modem) +static gboolean setup_quectel_usb(struct modem_info *modem) { const char *aux = NULL, *mdm = NULL; GSList *list; @@ -877,6 +877,28 @@ static gboolean setup_quectel(struct modem_info *modem) return TRUE; } +static gboolean setup_quectel_serial(struct modem_info *modem) +{ + struct serial_device_info *info = modem->serial; + const char *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); + + return TRUE; +} + +static gboolean setup_quectel(struct modem_info *modem) +{ + if (modem->serial) + return setup_quectel_serial(modem); + else + return setup_quectel_usb(modem); +} + static gboolean setup_quectelqmi(struct modem_info *modem) { const char *qmi = NULL, *net = NULL, *gps = NULL, *aux = NULL; From f23e4ba6619ac47ef1173d237bf52a633b52d832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Wed, 10 Jul 2019 23:51:45 +0200 Subject: [PATCH 138/320] quectel: support gpio to power on/off the modem This adds support for configuring a gpio in udev to control the modem power. To enable gpio control, specify OFONO_QUECTEL_GPIO_CHIP and OFONO_QUECTEL_GPIO_OFFSET in the udev environment, for example: KERNEL=="ttymxc0", ENV{OFONO_DRIVER}="quectel", \ ENV{OFONO_QUECTEL_GPIO_CHIP}="gpiochip2", \ ENV{OFONO_QUECTEL_GPIO_OFFSET}="26" --- ofono/plugins/quectel.c | 85 ++++++++++++++++++++++++++++++++++++++--- ofono/plugins/udevng.c | 11 +++++- 2 files changed, 89 insertions(+), 7 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 5db0bdb07..d71c1c531 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -74,6 +74,7 @@ struct quectel_data { GAtChat *uart; int mux_ready_count; int initial_ldisc; + struct l_gpio_writer *gpio; }; static void quectel_debug(const char *str, void *user_data) @@ -83,6 +84,43 @@ static void quectel_debug(const char *str, void *user_data) ofono_info("%s%s", prefix, str); } +static int quectel_probe_gpio(struct ofono_modem *modem) +{ + struct quectel_data *data = ofono_modem_get_data(modem); + struct l_gpio_chip *gpiochip; + uint32_t offset; + const char *chip_name, *offset_str; + uint32_t value = 0; + + DBG("%p", modem); + + chip_name = ofono_modem_get_string(modem, "GpioChip"); + if (!chip_name) + return 0; + + offset_str = ofono_modem_get_string(modem, "GpioOffset"); + if (!offset_str) + return -EINVAL; + + offset = strtoul(offset_str, NULL, 0); + if (!offset) + return -EINVAL; + + gpiochip = l_gpio_chip_new(chip_name); + if (!gpiochip) + return -ENODEV; + + data->gpio = l_gpio_writer_new(gpiochip, "ofono", 1, &offset, + &value); + + l_gpio_chip_free(gpiochip); + + if (!data->gpio) + return -EIO; + + return 0; +} + static int quectel_probe(struct ofono_modem *modem) { struct quectel_data *data; @@ -95,7 +133,7 @@ static int quectel_probe(struct ofono_modem *modem) ofono_modem_set_data(modem, data); - return 0; + return quectel_probe_gpio(modem); } static void quectel_remove(struct ofono_modem *modem) @@ -108,6 +146,7 @@ static void quectel_remove(struct ofono_modem *modem) g_at_chat_unregister(data->aux, data->cpin_ready); ofono_modem_set_data(modem, NULL); + l_gpio_writer_free(data->gpio); g_at_chat_unref(data->aux); g_at_chat_unref(data->modem); g_at_chat_unref(data->uart); @@ -119,6 +158,7 @@ static void close_mux_cb(struct l_timeout *timeout, void *user_data) 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; @@ -140,6 +180,7 @@ static void close_mux_cb(struct l_timeout *timeout, void *user_data) data->uart = NULL; l_timeout_remove(timeout); + l_gpio_writer_set(data->gpio, 1, &gpio_value); ofono_modem_set_powered(modem, FALSE); } @@ -395,9 +436,22 @@ static void cmux_cb(gboolean ok, GAtResult *result, gpointer user_data) } } +static void ate_cb(int ok, GAtResult *result, void *user_data) +{ + struct ofono_modem *modem = user_data; + struct quectel_data *data = ofono_modem_get_data(modem); + + DBG("%p", modem); + + g_at_chat_set_wakeup_command(data->uart, NULL, 0, 0); + g_at_chat_send(data->uart, "AT+CMUX=0,0,5,127,10,3,30,10,2", NULL, + cmux_cb, modem, NULL); +} + static int open_serial(struct ofono_modem *modem) { struct quectel_data *data = ofono_modem_get_data(modem); + const uint32_t gpio_value = 1; const char *rts_cts; DBG("%p", modem); @@ -418,12 +472,31 @@ static int open_serial(struct ofono_modem *modem) if (data->uart == NULL) return -EINVAL; - g_at_chat_send(data->uart, "ATE0", none_prefix, NULL, NULL, - NULL); + if (data->gpio && !l_gpio_writer_set(data->gpio, 1, &gpio_value)) { + close_serial(modem); + return -EIO; + } - /* setup multiplexing */ - g_at_chat_send(data->uart, "AT+CMUX=0,0,5,127,10,3,30,10,2", NULL, - cmux_cb, modem, NULL); + /* + * there are three different power-up scenarios: + * + * 1) the gpio has just been toggled on, so the modem is not ready + * until it prints RDY + * + * 2) the modem has been on for a while and ready to respond to + * commands, so there will be no RDY notification + * + * 3) either of the previous to scenarious is the case, but the modem + * UART is not configured to a fixed bitrate. In this case it needs + * a few 'AT' bytes to detect the host UART bitrate, but the RDY is + * lost. + * + * the wakeup command feature is (mis)used to support all three + * scenarious by sending AT commands until the modem responds with OK, + * at which point the modem is ready. + */ + g_at_chat_set_wakeup_command(data->uart, "AT\r", 500, 10000); + g_at_chat_send(data->uart, "ATE0", none_prefix, ate_cb, modem, NULL); return -EINPROGRESS; } diff --git a/ofono/plugins/udevng.c b/ofono/plugins/udevng.c index 738fd6d58..19fd9c1a2 100644 --- a/ofono/plugins/udevng.c +++ b/ofono/plugins/udevng.c @@ -883,8 +883,17 @@ static gboolean setup_quectel_serial(struct modem_info *modem) const char *value; value = udev_device_get_property_value(info->dev, - "OFONO_QUECTEL_RTSCTS"); + "OFONO_QUECTEL_GPIO_CHIP"); + if (value) + ofono_modem_set_string(modem->modem, "GpioChip", value); + value = udev_device_get_property_value(info->dev, + "OFONO_QUECTEL_GPIO_OFFSET"); + if (value) + ofono_modem_set_string(modem->modem, "GpioOffset", 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); From 2c0b370ef727923d58b49fe2b60e81796bd533c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Wed, 10 Jul 2019 23:51:46 +0200 Subject: [PATCH 139/320] quectel: configure flow control when enabled --- ofono/plugins/quectel.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index d71c1c531..b142c0b5e 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -496,7 +496,13 @@ static int open_serial(struct ofono_modem *modem) * at which point the modem is ready. */ g_at_chat_set_wakeup_command(data->uart, "AT\r", 500, 10000); - g_at_chat_send(data->uart, "ATE0", none_prefix, ate_cb, modem, NULL); + + if (strcmp(rts_cts, "on") == 0) + g_at_chat_send(data->uart, "AT+IFC=2,2; E0", none_prefix, + ate_cb, modem, NULL); + else + g_at_chat_send(data->uart, "ATE0", none_prefix, ate_cb, modem, + NULL); return -EINPROGRESS; } From 24d67b03f78aea14384b5fd1ec27f54cf9a74be9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Wed, 10 Jul 2019 23:51:47 +0200 Subject: [PATCH 140/320] quectel: query device model to enable vendor quirks --- ofono/plugins/quectel.c | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index b142c0b5e..53049ed0a 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -51,6 +51,7 @@ static const char *cfun_prefix[] = { "+CFUN:", NULL }; static const char *cpin_prefix[] = { "+CPIN:", NULL }; +static const char *cgmm_prefix[] = { "UC15", "Quectel_M95", NULL }; static const char *none_prefix[] = { NULL }; static const uint8_t gsm0710_terminate[] = { @@ -69,6 +70,7 @@ struct quectel_data { GAtChat *aux; guint cpin_ready; bool have_sim; + enum ofono_vendor vendor; /* used by quectel uart driver */ GAtChat *uart; @@ -305,6 +307,35 @@ 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, "", &model)) { + 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; + } else if (strcmp(model, "Quectel_M95") == 0) { + DBG("%p model M95", modem); + data->vendor = OFONO_VENDOR_QUECTEL_M95; + } else { + ofono_warn("%p unknown model: '%s'", modem, model); + data->vendor = OFONO_VENDOR_QUECTEL; + } + + g_at_chat_send(data->aux, "AT+CFUN?", cfun_prefix, cfun_query, modem, + NULL); +} + static int open_ttys(struct ofono_modem *modem) { struct quectel_data *data = ofono_modem_get_data(modem); @@ -330,7 +361,7 @@ static int open_ttys(struct ofono_modem *modem) NULL, NULL); g_at_chat_send(data->aux, "ATE0; &C0; +CMEE=1", none_prefix, NULL, NULL, NULL); - g_at_chat_send(data->aux, "AT+CFUN?", cfun_prefix, cfun_query, modem, + g_at_chat_send(data->aux, "AT+CGMM", cgmm_prefix, cgmm_cb, modem, NULL); return -EINPROGRESS; @@ -582,8 +613,7 @@ static void quectel_pre_sim(struct ofono_modem *modem) DBG("%p", modem); ofono_devinfo_create(modem, 0, "atmodem", data->aux); - sim = ofono_sim_create(modem, OFONO_VENDOR_QUECTEL, "atmodem", - data->aux); + sim = ofono_sim_create(modem, data->vendor, "atmodem", data->aux); if (sim && data->have_sim == true) ofono_sim_inserted_notify(sim, TRUE); From 00add5ed8c3d3a2a2b01d0ab8b6a86b0e1b05657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Wed, 10 Jul 2019 23:51:48 +0200 Subject: [PATCH 141/320] quectel: initialize call, phonebook and sms when ready The Quectel M95 modem issues a "Call ready" notification when call and phonebook are ready, so set up a listener for that. The only way to know when sms is ready is to issue QINITSTAT queries. Since sms is always ready after call and phonebook, the queries are initiated after creating call/phonebook. --- ofono/plugins/quectel.c | 74 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 53049ed0a..4b1448413 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -42,6 +42,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -51,6 +54,7 @@ static const char *cfun_prefix[] = { "+CFUN:", NULL }; static const char *cpin_prefix[] = { "+CPIN:", NULL }; +static const char *qinistat_prefix[] = { "+QINISTAT:", NULL }; static const char *cgmm_prefix[] = { "UC15", "Quectel_M95", NULL }; static const char *none_prefix[] = { NULL }; @@ -69,8 +73,10 @@ struct quectel_data { GAtChat *modem; GAtChat *aux; guint cpin_ready; + guint call_ready; bool have_sim; enum ofono_vendor vendor; + struct l_timeout *sms_ready_timer; /* used by quectel uart driver */ GAtChat *uart; @@ -336,6 +342,66 @@ static void cgmm_cb(int ok, GAtResult *result, void *user_data) NULL); } +static void qinistat_cb(gboolean ok, GAtResult *result, gpointer user_data) +{ + struct ofono_modem *modem = user_data; + struct quectel_data *data = ofono_modem_get_data(modem); + GAtResultIter iter; + int status; + + DBG("%p", modem); + + g_at_result_iter_init(&iter, result); + + if (!g_at_result_iter_next(&iter, "+QINISTAT:")) + return; + + if (!g_at_result_iter_next_number(&iter, &status)) + return; + + DBG("qinistat: %d", status); + + if (status != 3) { + l_timeout_modify_ms(data->sms_ready_timer, 500); + return; + } + + ofono_sms_create(modem, data->vendor, "atmodem", data->aux); + l_timeout_remove(data->sms_ready_timer); + data->sms_ready_timer = NULL; +} + +static void sms_ready_cb(struct l_timeout *timeout, void *user_data) +{ + struct ofono_modem *modem = user_data; + struct quectel_data *data = ofono_modem_get_data(modem); + + DBG("%p", modem); + + g_at_chat_send(data->aux, "AT+QINISTAT", qinistat_prefix, qinistat_cb, + modem, NULL); +} + +static void call_ready_notify(GAtResult *result, void *user_data) +{ + struct ofono_modem *modem = user_data; + struct quectel_data *data = ofono_modem_get_data(modem); + + DBG("%p", modem); + + g_at_chat_unregister(data->aux, data->call_ready); + data->call_ready = 0; + data->sms_ready_timer = l_timeout_create_ms(500, sms_ready_cb, modem, + NULL); + if (!data->sms_ready_timer) { + close_serial(modem); + return; + } + + ofono_phonebook_create(modem, 0, "atmodem", data->aux); + ofono_voicecall_create(modem, 0, "atmodem", data->aux); +} + static int open_ttys(struct ofono_modem *modem) { struct quectel_data *data = ofono_modem_get_data(modem); @@ -355,6 +421,14 @@ static int open_ttys(struct ofono_modem *modem) return -EIO; } + data->call_ready = g_at_chat_register(data->aux, "Call Ready", + call_ready_notify, false, + modem, NULL); + if (!data->call_ready) { + close_serial(modem); + return -ENOTTY; + } + g_at_chat_set_slave(data->modem, data->aux); g_at_chat_send(data->modem, "ATE0; &C0; +CMEE=1", none_prefix, NULL, From 93cf35705ba9c8c12abdb9dfc4a2379f45ba7891 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Tue, 16 Jul 2019 23:13:55 -0500 Subject: [PATCH 142/320] gatchat: Fix use of unterminated strings escaped_str was allocated of size escaped + 1. But we were only memsetting the first escaped characters. --- ofono/gatchat/gatutil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/gatchat/gatutil.c b/ofono/gatchat/gatutil.c index ea433bcb1..be691b2aa 100644 --- a/ofono/gatchat/gatutil.c +++ b/ofono/gatchat/gatutil.c @@ -67,7 +67,7 @@ void g_at_util_debug_chat(gboolean in, const char *str, gsize len, escaped_str[0] = type; escaped_str[1] = ' '; - memset(escaped_str + 2, '\0', escaped - 2); + memset(escaped_str + 2, '\0', escaped - 1); for (escaped = 2, i = 0; i < len; i++) { unsigned char c = str[i]; From 78218e194f65e4764665c684343eb926c20016e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Tue, 16 Jul 2019 21:10:47 +0200 Subject: [PATCH 143/320] gatresult: strip trailing spaces from unquoted strings Some vendors might print trailing spaces after unsolicited result codes. Avoid duplicating and stripping the string after calling g_at_result_iter_next_unquoted_string() by stripping the spaces in gatresult instead. --- ofono/gatchat/gatresult.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ofono/gatchat/gatresult.c b/ofono/gatchat/gatresult.c index 2659db28c..883b4105f 100644 --- a/ofono/gatchat/gatresult.c +++ b/ofono/gatchat/gatresult.c @@ -111,6 +111,7 @@ gboolean g_at_result_iter_next_unquoted_string(GAtResultIter *iter, unsigned int pos; unsigned int end; unsigned int len; + unsigned int stripped; char *line; if (iter == NULL) @@ -139,7 +140,12 @@ gboolean g_at_result_iter_next_unquoted_string(GAtResultIter *iter, while (end < len && line[end] != ',' && line[end] != ')') end += 1; - iter->buf[end] = '\0'; + stripped = end; + + while (line[stripped - 1] == ' ') + stripped -= 1; + + iter->buf[stripped] = '\0'; out: iter->line_pos = skip_to_next_field(line, end, len); From 7733673c3a7995eb529d819fa3c9547c3d2b80ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Tue, 16 Jul 2019 21:10:48 +0200 Subject: [PATCH 144/320] atmodem: rename OFONO_VENDOR_QUECTEL_M95 Other serial connected modems (i.e the MC60 model) from is AT-compatible with the M95 model, so rename the M95 vendor id to be common for both. --- ofono/drivers/atmodem/sim.c | 4 ++-- ofono/drivers/atmodem/sms.c | 4 ++-- ofono/drivers/atmodem/vendor.h | 2 +- ofono/plugins/quectel.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ofono/drivers/atmodem/sim.c b/ofono/drivers/atmodem/sim.c index 520b3dbf5..dd42cac43 100644 --- a/ofono/drivers/atmodem/sim.c +++ b/ofono/drivers/atmodem/sim.c @@ -1217,7 +1217,7 @@ static void at_pin_retries_query(struct ofono_sim *sim, at_qpinc_cb, cbd, g_free) > 0) return; break; - case OFONO_VENDOR_QUECTEL_M95: + case OFONO_VENDOR_QUECTEL_SERIAL: if (g_at_chat_send(sd->chat, "AT+QTRPIN", qtrpin_prefix, at_qtrpin_cb, cbd, g_free) > 0) return; @@ -1354,7 +1354,7 @@ static void at_pin_send_cb(gboolean ok, GAtResult *result, case OFONO_VENDOR_HUAWEI: case OFONO_VENDOR_SIMCOM: case OFONO_VENDOR_SIERRA: - case OFONO_VENDOR_QUECTEL_M95: + 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 diff --git a/ofono/drivers/atmodem/sms.c b/ofono/drivers/atmodem/sms.c index ee21b9d03..de8a28059 100644 --- a/ofono/drivers/atmodem/sms.c +++ b/ofono/drivers/atmodem/sms.c @@ -338,7 +338,7 @@ static inline void at_ack_delivery(struct ofono_sms *sms) case OFONO_VENDOR_GEMALTO: snprintf(buf, sizeof(buf), "AT+CNMA=1"); break; - case OFONO_VENDOR_QUECTEL_M95: + case OFONO_VENDOR_QUECTEL_SERIAL: snprintf(buf, sizeof(buf), "AT+CNMA"); break; default: @@ -1288,7 +1288,7 @@ static void at_csms_query_cb(gboolean ok, GAtResult *result, goto out; switch (data->vendor) { - case OFONO_VENDOR_QUECTEL_M95: + case OFONO_VENDOR_QUECTEL_SERIAL: g_at_result_iter_next_number(&iter, &status_min); g_at_result_iter_next_number(&iter, &status_max); if (status_min <= 1 && 1 <= status_max) diff --git a/ofono/drivers/atmodem/vendor.h b/ofono/drivers/atmodem/vendor.h index 10c043159..d839d1e0f 100644 --- a/ofono/drivers/atmodem/vendor.h +++ b/ofono/drivers/atmodem/vendor.h @@ -44,7 +44,7 @@ enum ofono_vendor { OFONO_VENDOR_WAVECOM_Q2XXX, OFONO_VENDOR_ALCATEL, OFONO_VENDOR_QUECTEL, - OFONO_VENDOR_QUECTEL_M95, + OFONO_VENDOR_QUECTEL_SERIAL, OFONO_VENDOR_UBLOX, OFONO_VENDOR_XMM, OFONO_VENDOR_GEMALTO, diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 4b1448413..722570c2e 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -332,7 +332,7 @@ static void cgmm_cb(int ok, GAtResult *result, void *user_data) data->vendor = OFONO_VENDOR_QUECTEL; } else if (strcmp(model, "Quectel_M95") == 0) { DBG("%p model M95", modem); - data->vendor = OFONO_VENDOR_QUECTEL_M95; + data->vendor = OFONO_VENDOR_QUECTEL_SERIAL; } else { ofono_warn("%p unknown model: '%s'", modem, model); data->vendor = OFONO_VENDOR_QUECTEL; From 86b87eb43d3a5d5eb90633a9bc1b27b5f3df8001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Tue, 16 Jul 2019 21:10:49 +0200 Subject: [PATCH 145/320] quectel: enable call volume settings --- ofono/plugins/quectel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 722570c2e..7346c0744 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -400,6 +401,7 @@ static void call_ready_notify(GAtResult *result, void *user_data) ofono_phonebook_create(modem, 0, "atmodem", data->aux); ofono_voicecall_create(modem, 0, "atmodem", data->aux); + ofono_call_volume_create(modem, 0, "atmodem", data->aux); } static int open_ttys(struct ofono_modem *modem) From d9ddf43a4947f5d5a816fddcba4ad48a3ebd5675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Tue, 16 Jul 2019 21:10:50 +0200 Subject: [PATCH 146/320] quectel: store model id in private data Some Quectel models supports different features such as GNSS or different URC strings. Add a field in the quectel data structure to be used when adding support for said features. --- ofono/plugins/quectel.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 7346c0744..d64ebb4fb 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -70,6 +70,13 @@ static const uint8_t gsm0710_terminate[] = { 0xf9, /* close flag */ }; +enum quectel_model { + QUECTEL_UNKNOWN, + QUECTEL_UC15, + QUECTEL_M95, + QUECTEL_MC60, +}; + struct quectel_data { GAtChat *modem; GAtChat *aux; @@ -77,6 +84,7 @@ struct quectel_data { guint call_ready; bool have_sim; enum ofono_vendor vendor; + enum quectel_model model; struct l_timeout *sms_ready_timer; /* used by quectel uart driver */ @@ -331,12 +339,15 @@ static void cgmm_cb(int ok, GAtResult *result, void *user_data) 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 { 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, From cc7f572edc57b56652d35dd85ed92bb7b9b9f983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Tue, 16 Jul 2019 21:10:51 +0200 Subject: [PATCH 147/320] quectel: add support for the Quectel MC60 modem The modem is AT-compatible with the Quectel M95 modem, but also features a GNSS module. --- ofono/plugins/quectel.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index d64ebb4fb..00a3bccef 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -56,7 +56,8 @@ static const char *cfun_prefix[] = { "+CFUN:", NULL }; static const char *cpin_prefix[] = { "+CPIN:", NULL }; static const char *qinistat_prefix[] = { "+QINISTAT:", NULL }; -static const char *cgmm_prefix[] = { "UC15", "Quectel_M95", NULL }; +static const char *cgmm_prefix[] = { "UC15", "Quectel_M95", "Quectel_MC60", + NULL }; static const char *none_prefix[] = { NULL }; static const uint8_t gsm0710_terminate[] = { @@ -344,6 +345,10 @@ static void cgmm_cb(int ok, GAtResult *result, void *user_data) 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 { ofono_warn("%p unknown model: '%s'", modem, model); data->vendor = OFONO_VENDOR_QUECTEL; From 3812f038b170851e84bc3fc086fc9ea02dcba8a8 Mon Sep 17 00:00:00 2001 From: Christophe Ronco Date: Wed, 17 Jul 2019 15:29:24 +0200 Subject: [PATCH 148/320] qmimodem: remember lac and cellid Lac and cellid information are optional in ss_info notifications. Remember them in order to give a correct information each time a notification is received. --- ofono/drivers/qmimodem/network-registration.c | 53 ++++++++++++------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/ofono/drivers/qmimodem/network-registration.c b/ofono/drivers/qmimodem/network-registration.c index 1fccb5737..04f20c669 100644 --- a/ofono/drivers/qmimodem/network-registration.c +++ b/ofono/drivers/qmimodem/network-registration.c @@ -42,6 +42,8 @@ struct netreg_data { struct qmi_service *nas; struct ofono_network_operator operator; uint8_t current_rat; + int lac; + int cellid; bool is_roaming; }; @@ -166,6 +168,31 @@ static bool extract_ss_info(struct qmi_result *result, int *status, return true; } +static int remember_ss_info(struct netreg_data *data, int status, int lac, + int cellid, enum roaming_status roaming) +{ + if (roaming == ROAMING_STATUS_ON) + data->is_roaming = true; + else if (roaming == ROAMING_STATUS_OFF) + data->is_roaming = false; + + if (status == QMI_NAS_REGISTRATION_STATE_REGISTERED) { + if (lac >= 0) + data->lac = lac; + if (cellid >= 0) + data->cellid = cellid; + } else { + data->lac = -1; + data->cellid = -1; + } + + if (status == QMI_NAS_REGISTRATION_STATE_REGISTERED && + data->is_roaming) + status = NETWORK_REGISTRATION_STATUS_ROAMING; + + return status; +} + static void ss_info_notify(struct qmi_result *result, void *user_data) { struct ofono_netreg *netreg = user_data; @@ -183,16 +210,10 @@ static void ss_info_notify(struct qmi_result *result, void *user_data) &data->operator)) return; - if (roaming == ROAMING_STATUS_ON) - data->is_roaming = true; - else if (roaming == ROAMING_STATUS_OFF) - data->is_roaming = false; - - if (status == QMI_NAS_REGISTRATION_STATE_REGISTERED && - data->is_roaming) - status = NETWORK_REGISTRATION_STATUS_ROAMING; + status = remember_ss_info(data, status, lac, cellid, roaming); - ofono_netreg_status_notify(netreg, status, lac, cellid, tech); + ofono_netreg_status_notify(netreg, status, data->lac, data->cellid, + tech); } static void get_ss_info_cb(struct qmi_result *result, void *user_data) @@ -216,16 +237,10 @@ static void get_ss_info_cb(struct qmi_result *result, void *user_data) return; } - if (roaming == ROAMING_STATUS_ON) - data->is_roaming = true; - else if (roaming == ROAMING_STATUS_OFF) - data->is_roaming = false; - - if (status == QMI_NAS_REGISTRATION_STATE_REGISTERED && - data->is_roaming) - status = NETWORK_REGISTRATION_STATUS_ROAMING; + status = remember_ss_info(data, status, lac, cellid, roaming); - CALLBACK_WITH_SUCCESS(cb, status, lac, cellid, tech, cbd->data); + CALLBACK_WITH_SUCCESS(cb, status, data->lac, data->cellid, tech, + cbd->data); } static void qmi_registration_status(struct ofono_netreg *netreg, @@ -613,6 +628,8 @@ static int qmi_netreg_probe(struct ofono_netreg *netreg, data->current_rat = QMI_NAS_NETWORK_RAT_NO_CHANGE; data->is_roaming = false; + data->lac = -1; + data->cellid = -1; ofono_netreg_set_data(netreg, data); From ffb0efcb7d02fdb8efbdc0a446b0f010de3e8a33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Thu, 18 Jul 2019 13:49:34 +0200 Subject: [PATCH 149/320] test: process-context-settings: use ip instead of ifconfig/route --- ofono/test/process-context-settings | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ofono/test/process-context-settings b/ofono/test/process-context-settings index 1d30b30df..a536a7718 100755 --- a/ofono/test/process-context-settings +++ b/ofono/test/process-context-settings @@ -41,14 +41,14 @@ for path, properties in modems: print(" IP address is %s" % (address)) print(" Gateway is %s" % (gateway)) - cmd = "ifconfig " + interface + " " + address - cmd += " netmask 255.255.255.255" + cmd = "ip address add dev " + interface + " " + address + cmd += "/32" os.system(cmd); for i in settings["DomainNameServers"]: print(" Nameserver is %s" % (i)) - cmd = "route add -host " + i + cmd = "ip route add " + i cmd +=" dev " + interface os.system(cmd); print('') From c073911fab33ca9375a5b6bda3073573cf823fc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Thu, 18 Jul 2019 13:49:35 +0200 Subject: [PATCH 150/320] test: process-context-settings: print settings to stderr Prepare the test to print commands to execute and let the caller evaluate those. In that way, more commands can be added to also set up name servers and default routes without secretly breaking the existing system network setup. --- ofono/test/process-context-settings | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/ofono/test/process-context-settings b/ofono/test/process-context-settings index a536a7718..7ffb12b30 100755 --- a/ofono/test/process-context-settings +++ b/ofono/test/process-context-settings @@ -1,6 +1,7 @@ #!/usr/bin/python3 import os +import sys import dbus bus = dbus.SystemBus() @@ -23,13 +24,14 @@ for path, properties in modems: if properties["Active"] == dbus.Boolean(0): continue - print("Configuring %s" % (path)) + print("Configuring %s" % (path), file=sys.stderr) settings = properties["Settings"] interface = settings["Interface"] if settings["Method"] == "dhcp": - print(" Run DHCP on interface %s" % (interface)) + print(" Run DHCP on interface %s" % (interface), + file=sys.stderr) else: address = settings["Address"] try: @@ -37,18 +39,22 @@ for path, properties in modems: except: gateway = "0.0.0.0"; - print(" Interface is %s" % (interface)) - print(" IP address is %s" % (address)) - print(" Gateway is %s" % (gateway)) + print(" Interface is %s" % (interface), + file=sys.stderr) + print(" IP address is %s" % (address), + file=sys.stderr) + print(" Gateway is %s" % (gateway), + file=sys.stderr) cmd = "ip address add dev " + interface + " " + address cmd += "/32" os.system(cmd); for i in settings["DomainNameServers"]: - print(" Nameserver is %s" % (i)) + print(" Nameserver is %s" % (i), + file=sys.stderr) cmd = "ip route add " + i cmd +=" dev " + interface os.system(cmd); - print('') + print('', file=sys.stderr) From cc3395dd800f771f5243659bf8e3e47c48a35dfc Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Thu, 18 Jul 2019 12:23:05 +0200 Subject: [PATCH 151/320] atmodem: export generic netreg funcs An upcoming netreg driver for uBlox modems will need to override the probe method in order to set itself up, but for further functionality the "generic" AT implementations are sufficient. The easiest way to do this is to just set up a vtable with a custom probe implementation and defer all other methods to the common/generic methods. The problem is that the AT methods are not actually exported. This generic AT functionality was not intended to be hooked directly into other drivers. This patch exports all the methods of the atmodem network-registration driver implementation so that they can be used as generic/common implementations for other drivers. --- ofono/drivers/atmodem/network-registration.c | 16 +++++++++------- ofono/drivers/atmodem/network-registration.h | 17 +++++++++++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) create mode 100644 ofono/drivers/atmodem/network-registration.h diff --git a/ofono/drivers/atmodem/network-registration.c b/ofono/drivers/atmodem/network-registration.c index 67380b733..0f83977b8 100644 --- a/ofono/drivers/atmodem/network-registration.c +++ b/ofono/drivers/atmodem/network-registration.c @@ -41,6 +41,8 @@ #include "atmodem.h" #include "vendor.h" +#include "network-registration.h" + static const char *none_prefix[] = { NULL }; static const char *creg_prefix[] = { "+CREG:", NULL }; static const char *cops_prefix[] = { "+COPS:", NULL }; @@ -270,7 +272,7 @@ static void option_tech_cb(gboolean ok, GAtResult *result, gpointer user_data) nd->tech = -1; } -static void at_registration_status(struct ofono_netreg *netreg, +void at_registration_status(struct ofono_netreg *netreg, ofono_netreg_status_cb_t cb, void *data) { @@ -450,7 +452,7 @@ static void cops_numeric_cb(gboolean ok, GAtResult *result, gpointer user_data) g_free(cbd); } -static void at_current_operator(struct ofono_netreg *netreg, +void at_current_operator(struct ofono_netreg *netreg, ofono_netreg_operator_cb_t cb, void *data) { struct netreg_data *nd = ofono_netreg_get_data(netreg); @@ -589,7 +591,7 @@ static void cops_list_cb(gboolean ok, GAtResult *result, gpointer user_data) g_free(list); } -static void at_list_operators(struct ofono_netreg *netreg, +void at_list_operators(struct ofono_netreg *netreg, ofono_netreg_operator_list_cb_t cb, void *data) { struct netreg_data *nd = ofono_netreg_get_data(netreg); @@ -615,7 +617,7 @@ static void register_cb(gboolean ok, GAtResult *result, gpointer user_data) cb(&error, cbd->data); } -static void at_register_auto(struct ofono_netreg *netreg, +void at_register_auto(struct ofono_netreg *netreg, ofono_netreg_register_cb_t cb, void *data) { struct netreg_data *nd = ofono_netreg_get_data(netreg); @@ -630,7 +632,7 @@ static void at_register_auto(struct ofono_netreg *netreg, CALLBACK_WITH_FAILURE(cb, data); } -static void at_register_manual(struct ofono_netreg *netreg, +void at_register_manual(struct ofono_netreg *netreg, const char *mcc, const char *mnc, ofono_netreg_register_cb_t cb, void *data) { @@ -1228,7 +1230,7 @@ static void csq_cb(gboolean ok, GAtResult *result, gpointer user_data) cb(&error, strength, cbd->data); } -static void at_signal_strength(struct ofono_netreg *netreg, +void at_signal_strength(struct ofono_netreg *netreg, ofono_netreg_strength_cb_t cb, void *data) { struct netreg_data *nd = ofono_netreg_get_data(netreg); @@ -2144,7 +2146,7 @@ static int at_netreg_probe(struct ofono_netreg *netreg, unsigned int vendor, return 0; } -static void at_netreg_remove(struct ofono_netreg *netreg) +void at_netreg_remove(struct ofono_netreg *netreg) { struct netreg_data *nd = ofono_netreg_get_data(netreg); diff --git a/ofono/drivers/atmodem/network-registration.h b/ofono/drivers/atmodem/network-registration.h new file mode 100644 index 000000000..0f6224110 --- /dev/null +++ b/ofono/drivers/atmodem/network-registration.h @@ -0,0 +1,17 @@ +#pragma once + +void at_registration_status(struct ofono_netreg *netreg, + ofono_netreg_status_cb_t cb, + void *data); +void at_current_operator(struct ofono_netreg *netreg, + ofono_netreg_operator_cb_t cb, void *data); +void at_list_operators(struct ofono_netreg *netreg, + ofono_netreg_operator_list_cb_t cb, void *data); +void at_register_auto(struct ofono_netreg *netreg, + ofono_netreg_register_cb_t cb, void *data); +void at_register_manual(struct ofono_netreg *netreg, + const char *mcc, const char *mnc, + ofono_netreg_register_cb_t cb, void *data); +void at_signal_strength(struct ofono_netreg *netreg, + ofono_netreg_strength_cb_t cb, void *data); +void at_netreg_remove(struct ofono_netreg *netreg); From 2f9403644c552fdfa92dac06eafdfb134c4f3177 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Thu, 18 Jul 2019 12:23:06 +0200 Subject: [PATCH 152/320] atmodem: export struct netreg In order to do inheritance by composition. --- ofono/drivers/atmodem/network-registration.c | 94 +++++++++----------- ofono/drivers/atmodem/network-registration.h | 14 +++ 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/ofono/drivers/atmodem/network-registration.c b/ofono/drivers/atmodem/network-registration.c index 0f83977b8..cc702c2c2 100644 --- a/ofono/drivers/atmodem/network-registration.c +++ b/ofono/drivers/atmodem/network-registration.c @@ -53,20 +53,6 @@ static const char *smoni_prefix[] = { "^SMONI:", NULL }; static const char *zpas_prefix[] = { "+ZPAS:", NULL }; static const char *option_tech_prefix[] = { "_OCTI:", "_OUWCTI:", NULL }; -struct netreg_data { - GAtChat *chat; - char mcc[OFONO_MAX_MCC_LENGTH + 1]; - char mnc[OFONO_MAX_MNC_LENGTH + 1]; - int signal_index; /* If strength is reported via CIND */ - int signal_min; /* min strength reported via CIND */ - int signal_max; /* max strength reported via CIND */ - int signal_invalid; /* invalid strength reported via CIND */ - int tech; - struct ofono_network_time time; - guint nitz_timeout; - unsigned int vendor; -}; - struct tech_query { int status; int lac; @@ -211,7 +197,7 @@ static void at_creg_cb(gboolean ok, GAtResult *result, gpointer user_data) ofono_netreg_status_cb_t cb = cbd->cb; int status, lac, ci, tech; struct ofono_error error; - struct netreg_data *nd = cbd->user; + struct at_netreg_data *nd = cbd->user; decode_at_error(&error, g_at_result_final_response(result)); @@ -252,7 +238,7 @@ static void zte_tech_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct cb_data *cbd = user_data; struct ofono_netreg *netreg = cbd->data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); if (ok) nd->tech = zte_parse_tech(result); @@ -264,7 +250,7 @@ static void option_tech_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct cb_data *cbd = user_data; struct ofono_netreg *netreg = cbd->data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); if (ok) nd->tech = option_parse_tech(result); @@ -276,7 +262,7 @@ void at_registration_status(struct ofono_netreg *netreg, ofono_netreg_status_cb_t cb, void *data) { - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); struct cb_data *cbd = cb_data_new(cb, data); cbd->user = nd; @@ -339,7 +325,7 @@ void at_registration_status(struct ofono_netreg *netreg, static void cops_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct cb_data *cbd = user_data; - struct netreg_data *nd = ofono_netreg_get_data(cbd->user); + struct at_netreg_data *nd = ofono_netreg_get_data(cbd->user); ofono_netreg_operator_cb_t cb = cbd->cb; struct ofono_network_operator op; GAtResultIter iter; @@ -400,7 +386,7 @@ static void cops_cb(gboolean ok, GAtResult *result, gpointer user_data) static void cops_numeric_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct cb_data *cbd = user_data; - struct netreg_data *nd = ofono_netreg_get_data(cbd->user); + struct at_netreg_data *nd = ofono_netreg_get_data(cbd->user); ofono_netreg_operator_cb_t cb = cbd->cb; GAtResultIter iter; const char *str; @@ -455,7 +441,7 @@ static void cops_numeric_cb(gboolean ok, GAtResult *result, gpointer user_data) void at_current_operator(struct ofono_netreg *netreg, ofono_netreg_operator_cb_t cb, void *data) { - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); struct cb_data *cbd = cb_data_new(cb, data); gboolean ok; @@ -594,7 +580,7 @@ static void cops_list_cb(gboolean ok, GAtResult *result, gpointer user_data) void at_list_operators(struct ofono_netreg *netreg, ofono_netreg_operator_list_cb_t cb, void *data) { - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); struct cb_data *cbd = cb_data_new(cb, data); if (g_at_chat_send(nd->chat, "AT+COPS=?", cops_prefix, @@ -620,7 +606,7 @@ static void register_cb(gboolean ok, GAtResult *result, gpointer user_data) void at_register_auto(struct ofono_netreg *netreg, ofono_netreg_register_cb_t cb, void *data) { - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); struct cb_data *cbd = cb_data_new(cb, data); if (g_at_chat_send(nd->chat, "AT+COPS=0", none_prefix, @@ -636,7 +622,7 @@ void at_register_manual(struct ofono_netreg *netreg, const char *mcc, const char *mnc, ofono_netreg_register_cb_t cb, void *data) { - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); struct cb_data *cbd = cb_data_new(cb, data); char buf[128]; @@ -725,7 +711,7 @@ static void ifx_xhomezr_notify(GAtResult *result, gpointer user_data) static void ifx_xreg_notify(GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); int state; const char *band; GAtResultIter iter; @@ -824,7 +810,7 @@ static void ifx_xcsq_notify(GAtResult *result, gpointer user_data) static void ciev_notify(GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); int strength, ind; GAtResultIter iter; @@ -853,7 +839,7 @@ static void ciev_notify(GAtResult *result, gpointer user_data) static void telit_ciev_notify(GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); const char *signal_identifier = "rssi"; const char *ind_str; int strength; @@ -884,7 +870,7 @@ static void telit_ciev_notify(GAtResult *result, gpointer user_data) static void gemalto_ciev_notify(GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); const char *signal_identifier = "rssi"; const char *ind_str; int strength; @@ -917,7 +903,7 @@ static void gemalto_ciev_notify(GAtResult *result, gpointer user_data) static void ctzv_notify(GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); const char *tz; GAtResultIter iter; @@ -939,7 +925,7 @@ static void ctzv_notify(GAtResult *result, gpointer user_data) static void tlts_notify(GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); int year, mon, mday, hour, min, sec; char tz[4]; const char *time; @@ -974,7 +960,7 @@ static void tlts_notify(GAtResult *result, gpointer user_data) static gboolean notify_time(gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); nd->nitz_timeout = 0; @@ -986,7 +972,7 @@ static gboolean notify_time(gpointer user_data) static void ifx_ctzv_notify(GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); int year, mon, mday, hour, min, sec; const char *tz, *time; GAtResultIter iter; @@ -1024,7 +1010,7 @@ static void ifx_ctzv_notify(GAtResult *result, gpointer user_data) static void ifx_ctzdst_notify(GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); int dst; GAtResultIter iter; @@ -1052,7 +1038,7 @@ static void cind_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct cb_data *cbd = user_data; ofono_netreg_strength_cb_t cb = cbd->cb; - struct netreg_data *nd = cbd->user; + struct at_netreg_data *nd = cbd->user; int index; int strength; GAtResultIter iter; @@ -1106,7 +1092,7 @@ static void huawei_rssi_notify(GAtResult *result, gpointer user_data) static void huawei_mode_notify(GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); GAtResultIter iter; int mode, submode; @@ -1134,7 +1120,7 @@ static void huawei_mode_notify(GAtResult *result, gpointer user_data) static void huawei_hcsq_notify(GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); GAtResultIter iter; const char *mode; @@ -1155,7 +1141,7 @@ static void huawei_hcsq_notify(GAtResult *result, gpointer user_data) static void huawei_nwtime_notify(GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); int year, mon, mday, hour, min, sec; char tz[4]; const char *date, *time, *dst; @@ -1233,7 +1219,7 @@ static void csq_cb(gboolean ok, GAtResult *result, gpointer user_data) void at_signal_strength(struct ofono_netreg *netreg, ofono_netreg_strength_cb_t cb, void *data) { - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); struct cb_data *cbd = cb_data_new(cb, data); cbd->user = nd; @@ -1260,7 +1246,7 @@ void at_signal_strength(struct ofono_netreg *netreg, static void mbm_etzv_notify(GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); int year, mon, mday, hour, min, sec; const char *tz, *time, *timestamp; GAtResultIter iter; @@ -1309,7 +1295,7 @@ static void mbm_etzv_notify(GAtResult *result, gpointer user_data) static void mbm_erinfo_notify(GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); GAtResultIter iter; int mode, gsm, umts; @@ -1361,7 +1347,7 @@ static void mbm_erinfo_notify(GAtResult *result, gpointer user_data) static void icera_nwstate_notify(GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); GAtResultIter iter; const char *mccmnc, *tech, *state; int rssi; @@ -1429,7 +1415,7 @@ static int cnti_to_tech(const char *cnti) static void gobi_cnti_notify(GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); GAtResultIter iter; const char *tech; int option; @@ -1454,7 +1440,7 @@ static void gobi_cnti_notify(GAtResult *result, gpointer user_data) static void nw_cnti_notify(GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); GAtResultIter iter; const char *tech; int option; @@ -1480,7 +1466,7 @@ static void cnti_query_tech_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct tech_query *tq = user_data; - struct netreg_data *nd = ofono_netreg_get_data(tq->netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(tq->netreg); ofono_netreg_status_notify(tq->netreg, tq->status, tq->lac, tq->ci, nd->tech); @@ -1520,7 +1506,7 @@ 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 at_netreg_data *nd = ofono_netreg_get_data(netreg); struct tech_query *tq; if (at_util_parse_reg_unsolicited(result, "+CREG:", &status, @@ -1589,7 +1575,7 @@ static void at_cmer_not_supported(struct ofono_netreg *netreg) static void at_cmer_set_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); if (!ok) { at_cmer_not_supported(netreg); @@ -1648,7 +1634,7 @@ static inline ofono_bool_t append_cmer_element(char *buf, int *len, int cap, } static ofono_bool_t build_cmer_string(char *buf, int *cmer_opts, - struct netreg_data *nd) + struct at_netreg_data *nd) { const char *ind; int len = sprintf(buf, "AT+CMER="); @@ -1717,7 +1703,7 @@ static void at_cmer_query_cb(ofono_bool_t ok, GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); GAtResultIter iter; int cmer_opts_cnt = 5; /* See 27.007 Section 8.10 */ int cmer_opts[cmer_opts_cnt]; @@ -1765,7 +1751,7 @@ static void at_cmer_query_cb(ofono_bool_t ok, GAtResult *result, static void cind_support_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); GAtResultIter iter; const char *str; char *signal_identifier = "signal"; @@ -1872,7 +1858,7 @@ static void cind_support_cb(gboolean ok, GAtResult *result, gpointer user_data) static void at_creg_set_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); if (!ok) { ofono_error("Unable to initialize Network Registration"); @@ -2075,7 +2061,7 @@ static void at_creg_set_cb(gboolean ok, GAtResult *result, gpointer user_data) static void at_creg_test_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); gint range[2]; GAtResultIter iter; int creg1 = 0; @@ -2123,9 +2109,9 @@ static int at_netreg_probe(struct ofono_netreg *netreg, unsigned int vendor, void *data) { GAtChat *chat = data; - struct netreg_data *nd; + struct at_netreg_data *nd; - nd = g_new0(struct netreg_data, 1); + nd = g_new0(struct at_netreg_data, 1); nd->chat = g_at_chat_clone(chat); nd->vendor = vendor; @@ -2148,7 +2134,7 @@ static int at_netreg_probe(struct ofono_netreg *netreg, unsigned int vendor, void at_netreg_remove(struct ofono_netreg *netreg) { - struct netreg_data *nd = ofono_netreg_get_data(netreg); + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); if (nd->nitz_timeout) g_source_remove(nd->nitz_timeout); diff --git a/ofono/drivers/atmodem/network-registration.h b/ofono/drivers/atmodem/network-registration.h index 0f6224110..8a5401cf8 100644 --- a/ofono/drivers/atmodem/network-registration.h +++ b/ofono/drivers/atmodem/network-registration.h @@ -1,5 +1,19 @@ #pragma once +struct at_netreg_data { + GAtChat *chat; + char mcc[OFONO_MAX_MCC_LENGTH + 1]; + char mnc[OFONO_MAX_MNC_LENGTH + 1]; + int signal_index; /* If strength is reported via CIND */ + int signal_min; /* min strength reported via CIND */ + int signal_max; /* max strength reported via CIND */ + int signal_invalid; /* invalid strength reported via CIND */ + int tech; + struct ofono_network_time time; + guint nitz_timeout; + unsigned int vendor; +}; + void at_registration_status(struct ofono_netreg *netreg, ofono_netreg_status_cb_t cb, void *data); From 35866eb1dc34b2b0fdbc965c0e96a4090e00a267 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Thu, 18 Jul 2019 12:23:10 +0200 Subject: [PATCH 153/320] ublox: determine gprs-context driver from network interface Some u-blox devices present a USB network class device for data and some just switch to PPP on (one of) the communication channel(s). Whether the atmodem or ubloxmodem gprs-context driver should be used depends on whether or not the network interface is present; check this condition directly when deciding which driver to us. --- ofono/plugins/ublox.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/ofono/plugins/ublox.c b/ofono/plugins/ublox.c index ff08a6a1b..8c8297dc2 100644 --- a/ofono/plugins/ublox.c +++ b/ofono/plugins/ublox.c @@ -359,6 +359,7 @@ static void ublox_post_sim(struct ofono_modem *modem) const char *driver; /* Toby L2: Create same number of contexts as supported PDP contexts. */ int ncontexts = data->flags & UBLOX_DEVICE_F_HIGH_THROUGHPUT_MODE ? 8 : 1; + const char *iface; int variant; DBG("%p", modem); @@ -366,17 +367,10 @@ static void ublox_post_sim(struct ofono_modem *modem) gprs = ofono_gprs_create(modem, data->vendor_family, "atmodem", data->aux); - if (ublox_is_toby_l4(data->model)) { + iface = ofono_modem_get_string(modem, "NetworkInterface"); + if (iface) { driver = "ubloxmodem"; variant = ublox_model_to_id(data->model); - } else if (ublox_is_toby_l2(data->model)) { - if (data->flags & UBLOX_DEVICE_F_HIGH_THROUGHPUT_MODE) { - driver = "ubloxmodem"; - variant = ublox_model_to_id(data->model); - } else { - driver = "atmodem"; - variant = OFONO_VENDOR_UBLOX; - } } else { driver = "atmodem"; variant = OFONO_VENDOR_UBLOX; From b6471b88a79950ffb15c6ac23c5b119c2eccb477 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Thu, 18 Jul 2019 12:23:11 +0200 Subject: [PATCH 154/320] ublox: create only 1 gprs context Some uBlox modems support multiple, simultaneously active contexts. These contexts are either bridged to the network interface or handled transparently by the modem acting like a router. The problem with this approach is that ofono and ofono clients (e.g. mmsd) expect a dedicated _local_ network interface for each context. As such, it doesn't make sense for ofono to set up the multiple gprs contexts. --- ofono/plugins/ublox.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/ofono/plugins/ublox.c b/ofono/plugins/ublox.c index 8c8297dc2..dcb592c66 100644 --- a/ofono/plugins/ublox.c +++ b/ofono/plugins/ublox.c @@ -357,8 +357,6 @@ static void ublox_post_sim(struct ofono_modem *modem) struct ofono_gprs_context *gc; GAtChat *chat = data->modem ? data->modem : data->aux; const char *driver; - /* Toby L2: Create same number of contexts as supported PDP contexts. */ - int ncontexts = data->flags & UBLOX_DEVICE_F_HIGH_THROUGHPUT_MODE ? 8 : 1; const char *iface; int variant; @@ -376,14 +374,9 @@ static void ublox_post_sim(struct ofono_modem *modem) variant = OFONO_VENDOR_UBLOX; } - while (ncontexts) { - gc = ofono_gprs_context_create(modem, variant, driver, chat); - - if (gprs && gc) - ofono_gprs_add_context(gprs, gc); - - --ncontexts; - } + gc = ofono_gprs_context_create(modem, variant, driver, chat); + if (gprs && gc) + ofono_gprs_add_context(gprs, gc); ofono_lte_create(modem, ublox_model_to_id(data->model), "ubloxmodem", data->aux); From 1ac2c292b51407e38323f02aaef3203767deeb7b Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Thu, 18 Jul 2019 12:23:12 +0200 Subject: [PATCH 155/320] ublox: add voicecall support --- ofono/plugins/ublox.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/ofono/plugins/ublox.c b/ofono/plugins/ublox.c index dcb592c66..4e6dadbbc 100644 --- a/ofono/plugins/ublox.c +++ b/ofono/plugins/ublox.c @@ -41,6 +41,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include #include @@ -356,6 +362,7 @@ static void ublox_post_sim(struct ofono_modem *modem) struct ofono_gprs *gprs; struct ofono_gprs_context *gc; GAtChat *chat = data->modem ? data->modem : data->aux; + struct ofono_message_waiting *mw; const char *driver; const char *iface; int variant; @@ -380,6 +387,16 @@ static void ublox_post_sim(struct ofono_modem *modem) ofono_lte_create(modem, ublox_model_to_id(data->model), "ubloxmodem", data->aux); + + ofono_ussd_create(modem, 0, "atmodem", data->aux); + ofono_call_forwarding_create(modem, 0, "atmodem", data->aux); + ofono_call_settings_create(modem, 0, "atmodem", data->aux); + ofono_call_meter_create(modem, 0, "atmodem", data->aux); + ofono_call_barring_create(modem, 0, "atmodem", data->aux); + + mw = ofono_message_waiting_create(modem); + if (mw) + ofono_message_waiting_register(mw); } static void ublox_post_online(struct ofono_modem *modem) From 6b7b1e12e6f2cf59c7d765a9a29a65709c3b2173 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Thu, 18 Jul 2019 12:23:13 +0200 Subject: [PATCH 156/320] ublox: add SMS support --- ofono/plugins/ublox.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ofono/plugins/ublox.c b/ofono/plugins/ublox.c index 4e6dadbbc..231578fba 100644 --- a/ofono/plugins/ublox.c +++ b/ofono/plugins/ublox.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -388,6 +389,8 @@ static void ublox_post_sim(struct ofono_modem *modem) ofono_lte_create(modem, ublox_model_to_id(data->model), "ubloxmodem", data->aux); + ofono_sms_create(modem, 0, "atmodem", data->aux); + ofono_ussd_create(modem, 0, "atmodem", data->aux); ofono_call_forwarding_create(modem, 0, "atmodem", data->aux); ofono_call_settings_create(modem, 0, "atmodem", data->aux); From ffc611ec424b406d5c770140eb2964a308ec04be Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Thu, 18 Jul 2019 12:23:14 +0200 Subject: [PATCH 157/320] ublox: be explicit about lack of IPv6 The TOBY L4 has no IPv6 support whatsoever. --- ofono/drivers/ubloxmodem/gprs-context.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ofono/drivers/ubloxmodem/gprs-context.c b/ofono/drivers/ubloxmodem/gprs-context.c index 732364200..5bc449195 100644 --- a/ofono/drivers/ubloxmodem/gprs-context.c +++ b/ofono/drivers/ubloxmodem/gprs-context.c @@ -388,6 +388,14 @@ static void ublox_gprs_activate_primary(struct ofono_gprs_context *gc, { struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); + if (ublox_is_toby_l4(gcd->model)) { + /* TOBY L4 does not support IPv6 */ + if (ctx->proto != OFONO_GPRS_PROTO_IP) { + CALLBACK_WITH_FAILURE(cb, data); + return; + } + } + /* IPv6 support not implemented */ if (ctx->proto != OFONO_GPRS_PROTO_IP) { CALLBACK_WITH_FAILURE(cb, data); From 1b1161c83cfbc214c0f3be8b7fa4634d8cfacb28 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Fri, 19 Jul 2019 08:51:01 +0200 Subject: [PATCH 158/320] ublox: network-registration atom For uBlox modems, a bit of custom setup is required, but after that the generic "atmodem" (27.007-compatible) method implementations are sufficient. This driver, therefore, just puts the custom probe method into place and defers remaining functionality to the recently exported atmodem implementations. --- ofono/Makefile.am | 1 + .../drivers/ubloxmodem/network-registration.c | 427 ++++++++++++++++++ ofono/drivers/ubloxmodem/ubloxmodem.c | 2 + ofono/drivers/ubloxmodem/ubloxmodem.h | 3 + 4 files changed, 433 insertions(+) create mode 100644 ofono/drivers/ubloxmodem/network-registration.c diff --git a/ofono/Makefile.am b/ofono/Makefile.am index d067817db..9a9378f5e 100644 --- a/ofono/Makefile.am +++ b/ofono/Makefile.am @@ -404,6 +404,7 @@ builtin_sources += drivers/atmodem/atutil.h \ drivers/ubloxmodem/ubloxmodem.h \ drivers/ubloxmodem/ubloxmodem.c \ drivers/ubloxmodem/gprs-context.c \ + drivers/ubloxmodem/network-registration.c \ drivers/ubloxmodem/netmon.c \ drivers/ubloxmodem/lte.c diff --git a/ofono/drivers/ubloxmodem/network-registration.c b/ofono/drivers/ubloxmodem/network-registration.c new file mode 100644 index 000000000..64ef8076b --- /dev/null +++ b/ofono/drivers/ubloxmodem/network-registration.c @@ -0,0 +1,427 @@ +/* + * + * oFono - Open Source Telephony + * + * Copyright (C) 2008-2011 Intel Corporation. All rights reserved. + * Copyright (C) 2010 ST-Ericsson AB. + * Copyright (C) 2019 Norrbonn AB + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include +#include +#include + +#include "gatchat.h" +#include "gatresult.h" + +#include "common.h" +#include "ubloxmodem.h" +#include "drivers/atmodem/vendor.h" + +#include "drivers/atmodem/network-registration.h" + +static const char *none_prefix[] = { NULL }; +static const char *cmer_prefix[] = { "+CMER:", NULL }; +static const char *ureg_prefix[] = { "+UREG:", NULL }; + +struct netreg_data { + struct at_netreg_data at_data; + + const struct ublox_model *model; +}; + +struct tech_query { + int status; + int lac; + int ci; + struct ofono_netreg *netreg; +}; + +static void ciev_notify(GAtResult *result, gpointer user_data) +{ + struct ofono_netreg *netreg = user_data; + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); + int strength, ind; + GAtResultIter iter; + + g_at_result_iter_init(&iter, result); + + if (!g_at_result_iter_next(&iter, "+CIEV:")) + return; + + if (!g_at_result_iter_next_number(&iter, &ind)) + return; + + if (ind != nd->signal_index) + return; + + if (!g_at_result_iter_next_number(&iter, &strength)) + return; + + if (strength == nd->signal_invalid) + strength = -1; + else + strength = (strength * 100) / (nd->signal_max - nd->signal_min); + + ofono_netreg_strength_notify(netreg, strength); +} + +static gboolean notify_time(gpointer user_data) +{ + struct ofono_netreg *netreg = user_data; + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); + + nd->nitz_timeout = 0; + + ofono_netreg_time_notify(netreg, &nd->time); + + return FALSE; +} + +static void ctzdst_notify(GAtResult *result, gpointer user_data) +{ + struct ofono_netreg *netreg = user_data; + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); + int dst; + GAtResultIter iter; + + g_at_result_iter_init(&iter, result); + + if (!g_at_result_iter_next(&iter, "+CTZDST:")) + return; + + if (!g_at_result_iter_next_number(&iter, &dst)) + return; + + DBG("dst %d", dst); + + nd->time.dst = dst; + + if (nd->nitz_timeout > 0) { + g_source_remove(nd->nitz_timeout); + nd->nitz_timeout = 0; + } + + ofono_netreg_time_notify(netreg, &nd->time); +} + +static void ctzv_notify(GAtResult *result, gpointer user_data) +{ + struct ofono_netreg *netreg = user_data; + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); + int year, mon, mday, hour, min, sec; + const char *tz, *time; + GAtResultIter iter; + + g_at_result_iter_init(&iter, result); + + if (!g_at_result_iter_next(&iter, "+CTZV:")) + return; + + if (!g_at_result_iter_next_unquoted_string(&iter, &tz)) + return; + + if (!g_at_result_iter_next_string(&iter, &time)) + return; + + DBG("tz %s time %s", tz, time); + + if (sscanf(time, "%u/%u/%u,%u:%u:%u", &year, &mon, &mday, + &hour, &min, &sec) != 6) + return; + + nd->time.sec = sec; + nd->time.min = min; + nd->time.hour = hour; + nd->time.mday = mday; + nd->time.mon = mon; + nd->time.year = 2000 + year; + + nd->time.utcoff = atoi(tz) * 15 * 60; + + /* Delay notification in case there's a DST update coming */ + if (nd->nitz_timeout > 0) + g_source_remove(nd->nitz_timeout); + + nd->nitz_timeout = g_timeout_add_seconds(1, notify_time, user_data); +} + +static void ctze_notify(GAtResult *result, gpointer user_data) +{ + struct ofono_netreg *netreg = user_data; + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); + int year, mon, mday, hour, min, sec; + int dst; + const char *tz, *time; + GAtResultIter iter; + + g_at_result_iter_init(&iter, result); + + if (!g_at_result_iter_next(&iter, "+CTZE:")) + return; + + if (!g_at_result_iter_next_unquoted_string(&iter, &tz)) + return; + + if (!g_at_result_iter_next_number(&iter, &dst)) + return; + + if (!g_at_result_iter_next_string(&iter, &time)) + return; + + DBG("tz %s dst %d time %s", tz, dst, time); + + if (sscanf(time, "%u/%u/%u,%u:%u:%u", &year, &mon, &mday, + &hour, &min, &sec) != 6) + return; + + nd->time.sec = sec; + nd->time.min = min; + nd->time.hour = hour; + nd->time.mday = mday; + nd->time.mon = mon; + nd->time.year = 2000 + year; + + nd->time.utcoff = atoi(tz) * 15 * 60; + nd->time.dst = dst; + + ofono_netreg_time_notify(netreg, &nd->time); +} + +static void ublox_query_tech_cb(gboolean ok, GAtResult *result, + gpointer user_data) +{ + struct tech_query *tq = user_data; + GAtResultIter iter; + gint enabled, state; + int tech = -1; + + if (!ok) + goto error; + + g_at_result_iter_init(&iter, result); + + if (!g_at_result_iter_next(&iter, "+UREG:")) + return; + + if (!g_at_result_iter_next_number(&iter, &enabled)) + return; + + 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; + } + +error: + ofono_netreg_status_notify(tq->netreg, + tq->status, tq->lac, tq->ci, tech); +} + +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; + + if (at_util_parse_reg_unsolicited(result, "+CREG:", &status, + &lac, &ci, &tech, OFONO_VENDOR_GENERIC) == FALSE) + return; + + if (status != 1 && status != 5) + goto notify; + + if (ublox_is_toby_l4(nd->model)) { + tq = g_new0(struct tech_query, 1); + + tq->status = status; + tq->lac = lac; + tq->ci = ci; + tq->netreg = netreg; + + if (g_at_chat_send(nd->at_data.chat, "AT+UREG?", ureg_prefix, + ublox_query_tech_cb, tq, g_free) > 0) + return; + + g_free(tq); + } + + if ((status == 1 || status == 5) && tech == -1) + tech = nd->at_data.tech; + +notify: + ofono_netreg_status_notify(netreg, status, lac, ci, tech); +} + +static void at_cmer_not_supported(struct ofono_netreg *netreg) +{ + ofono_error("+CMER not supported by this modem. If this is an error" + " please submit patches to support this hardware"); + + ofono_netreg_remove(netreg); +} + +static void ublox_cmer_set_cb(gboolean ok, + GAtResult *result, gpointer user_data) +{ + struct ofono_netreg *netreg = user_data; + struct at_netreg_data *nd = ofono_netreg_get_data(netreg); + + if (!ok) { + at_cmer_not_supported(netreg); + return; + } + + g_at_chat_register(nd->chat, "+CIEV:", + ciev_notify, FALSE, netreg, NULL); + + g_at_chat_register(nd->chat, "+CREG:", + creg_notify, FALSE, netreg, NULL); + + ofono_netreg_register(netreg); +} + +static void ublox_creg_set_cb(gboolean ok, + GAtResult *result, gpointer user_data) +{ + struct ofono_netreg *netreg = user_data; + struct netreg_data *nd = ofono_netreg_get_data(netreg); + + if (!ok) { + ofono_error("Unable to initialize Network Registration"); + ofono_netreg_remove(netreg); + return; + } + + if (ublox_is_toby_l4(nd->model)) { + /* FIXME */ + ofono_error("TOBY L4 requires polling of ECSQ"); + ofono_error("TOBY L4 wants UREG notifications for" + " tech updates"); + } + + /* Register for network time update reports */ + if (ublox_is_toby_l2(nd->model)) { + /* TOBY L2 does not support CTZDST */ + g_at_chat_register(nd->at_data.chat, "+CTZE:", ctze_notify, + FALSE, netreg, NULL); + g_at_chat_send(nd->at_data.chat, "AT+CTZR=2", none_prefix, + NULL, NULL, NULL); + } else { + g_at_chat_register(nd->at_data.chat, "+CTZV:", ctzv_notify, + FALSE, netreg, NULL); + g_at_chat_register(nd->at_data.chat, "+CTZDST:", ctzdst_notify, + FALSE, netreg, NULL); + g_at_chat_send(nd->at_data.chat, "AT+CTZR=1", none_prefix, + NULL, NULL, NULL); + } + + /* AT+CMER NOTES: + * - For all u-blox models, mode 3 is equivalent to mode 1; + * since some models do not support setting modes 2 nor 3 + * (see UBX-13002752), we prefer mode 1 for all models. + * - The TOBY L4 does not support ind=2 + */ + g_at_chat_send(nd->at_data.chat, "AT+CMER=1,0,0,1", cmer_prefix, + ublox_cmer_set_cb, netreg, NULL); +} + +/* + * uBlox netreg atom probe. + * - takes uBlox model ID parameter instead of AT vendor ID + */ +static int ublox_netreg_probe(struct ofono_netreg *netreg, + unsigned int model_id, + void *data) +{ + GAtChat *chat = data; + struct netreg_data *nd; + + nd = g_new0(struct netreg_data, 1); + + nd->model = ublox_model_from_id(model_id); + + /* There should be no uBlox-specific quirks in the 'generic' + * AT driver + */ + nd->at_data.vendor = OFONO_VENDOR_GENERIC; + + nd->at_data.chat = g_at_chat_clone(chat); + nd->at_data.tech = -1; + nd->at_data.time.sec = -1; + nd->at_data.time.min = -1; + nd->at_data.time.hour = -1; + nd->at_data.time.mday = -1; + nd->at_data.time.mon = -1; + nd->at_data.time.year = -1; + nd->at_data.time.dst = 0; + nd->at_data.time.utcoff = 0; + ofono_netreg_set_data(netreg, nd); + + /* All uBlox devices support n=2 so no need to query this */ + g_at_chat_send(nd->at_data.chat, "AT+CREG=2", none_prefix, + ublox_creg_set_cb, netreg, NULL); + + return 0; +} + +static const struct ofono_netreg_driver driver = { + .name = "ubloxmodem", + .probe = ublox_netreg_probe, + .remove = at_netreg_remove, + .registration_status = at_registration_status, + .current_operator = at_current_operator, + .list_operators = at_list_operators, + .register_auto = at_register_auto, + .register_manual = at_register_manual, + .strength = at_signal_strength, +}; + +void ublox_netreg_init(void) +{ + ofono_netreg_driver_register(&driver); +} + +void ublox_netreg_exit(void) +{ + ofono_netreg_driver_unregister(&driver); +} diff --git a/ofono/drivers/ubloxmodem/ubloxmodem.c b/ofono/drivers/ubloxmodem/ubloxmodem.c index a52a67ea0..719c77a0a 100644 --- a/ofono/drivers/ubloxmodem/ubloxmodem.c +++ b/ofono/drivers/ubloxmodem/ubloxmodem.c @@ -115,6 +115,7 @@ int ublox_is_toby_l4(const struct ublox_model *model) static int ubloxmodem_init(void) { ublox_gprs_context_init(); + ublox_netreg_init(); ublox_netmon_init(); ublox_lte_init(); @@ -124,6 +125,7 @@ static int ubloxmodem_init(void) static void ubloxmodem_exit(void) { ublox_gprs_context_exit(); + ublox_netreg_exit(); ublox_netmon_exit(); ublox_lte_exit(); } diff --git a/ofono/drivers/ubloxmodem/ubloxmodem.h b/ofono/drivers/ubloxmodem/ubloxmodem.h index 2c5b74336..81fe94813 100644 --- a/ofono/drivers/ubloxmodem/ubloxmodem.h +++ b/ofono/drivers/ubloxmodem/ubloxmodem.h @@ -43,6 +43,9 @@ int ublox_is_toby_l4(const struct ublox_model *model); extern void ublox_gprs_context_init(void); extern void ublox_gprs_context_exit(void); +void ublox_netreg_init(void); +void ublox_netreg_exit(void); + extern void ublox_netmon_init(void); extern void ublox_netmon_exit(void); From c5e88d33e428dcbe52b167022639765e82de8fa2 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Fri, 19 Jul 2019 08:51:02 +0200 Subject: [PATCH 159/320] ublox: use custom netreg atom --- ofono/plugins/ublox.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ofono/plugins/ublox.c b/ofono/plugins/ublox.c index 231578fba..b65bc52a7 100644 --- a/ofono/plugins/ublox.c +++ b/ofono/plugins/ublox.c @@ -406,7 +406,8 @@ static void ublox_post_online(struct ofono_modem *modem) { struct ublox_data *data = ofono_modem_get_data(modem); - ofono_netreg_create(modem, data->vendor_family, "atmodem", data->aux); + ofono_netreg_create(modem, + ublox_model_to_id(data->model), "ubloxmodem", data->aux); ofono_netmon_create(modem, data->vendor_family, "ubloxmodem", data->aux); } From fc3e89db2c4c8cfd0124557e6ff1cee3c623d81d Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Fri, 19 Jul 2019 09:04:15 +0200 Subject: [PATCH 160/320] ubloxmodem: Add model entries for LARA R2 series --- ofono/drivers/ubloxmodem/ubloxmodem.c | 9 +++++++++ ofono/drivers/ubloxmodem/ubloxmodem.h | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/ofono/drivers/ubloxmodem/ubloxmodem.c b/ofono/drivers/ubloxmodem/ubloxmodem.c index 719c77a0a..034f7db1a 100644 --- a/ofono/drivers/ubloxmodem/ubloxmodem.c +++ b/ofono/drivers/ubloxmodem/ubloxmodem.c @@ -77,6 +77,15 @@ const struct ublox_model ublox_models[] = { .name = "TOBY-L4906", .flags = UBLOX_F_TOBY_L4, }, + /* LARA L2 series */ + { + .name = "LARA-R202", + .flags = UBLOX_F_LARA_R2, + }, + { + .name = "LARA-R211", + .flags = UBLOX_F_LARA_R2, + }, { /* sentinel */ }, }; diff --git a/ofono/drivers/ubloxmodem/ubloxmodem.h b/ofono/drivers/ubloxmodem/ubloxmodem.h index 81fe94813..0bd7ef239 100644 --- a/ofono/drivers/ubloxmodem/ubloxmodem.h +++ b/ofono/drivers/ubloxmodem/ubloxmodem.h @@ -26,7 +26,8 @@ enum ublox_flags { UBLOX_F_TOBY_L2 = (1 << 0), UBLOX_F_TOBY_L4 = (1 << 1), - UBLOX_F_HAVE_USBCONF = (1 << 2), + UBLOX_F_LARA_R2 = (1 << 2), + UBLOX_F_HAVE_USBCONF = (1 << 3), }; struct ublox_model { From a35e47c11cadff05cf4af8d39b5c8e79971d981c Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Fri, 19 Jul 2019 09:04:15 +0200 Subject: [PATCH 161/320] udevng: detect LARA R2 series --- ofono/plugins/udevng.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ofono/plugins/udevng.c b/ofono/plugins/udevng.c index 19fd9c1a2..928881da7 100644 --- a/ofono/plugins/udevng.c +++ b/ofono/plugins/udevng.c @@ -1758,6 +1758,8 @@ static struct { { "ublox", "cdc_acm", "1546", "1010" }, { "ublox", "cdc_ncm", "1546", "1010" }, { "ublox", "cdc_acm", "1546", "1102" }, + { "ublox", "cdc_acm", "1546", "110a" }, + { "ublox", "cdc_ncm", "1546", "110a" }, { "ublox", "rndis_host", "1546", "1146" }, { "ublox", "cdc_acm", "1546", "1146" }, { "gemalto", "option", "1e2d", "0053" }, From 38b3e8abe42c24403ee350f943e58d12571434cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Fri, 19 Jul 2019 12:27:45 +0200 Subject: [PATCH 162/320] atmodem: gprs-context: parse list-less CGDATA response The Quectel M95 and MC60 modems respond to AT+CGDATA=? with a single +CGDATA="PPP", but the callback in gprs-context expects a list of protocols. Avoid falling back to the old-style ATD*99 by not expecting a list of protocols for serial quectel modems. --- ofono/drivers/atmodem/gprs-context.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ofono/drivers/atmodem/gprs-context.c b/ofono/drivers/atmodem/gprs-context.c index b34b070a7..403a300dd 100644 --- a/ofono/drivers/atmodem/gprs-context.c +++ b/ofono/drivers/atmodem/gprs-context.c @@ -406,9 +406,11 @@ static void at_cgdata_test_cb(gboolean ok, GAtResult *result, goto error; } - if (!g_at_result_iter_open_list(&iter)) { - DBG("no list found"); - goto error; + if (gcd->vendor != OFONO_VENDOR_QUECTEL_SERIAL) { + if (!g_at_result_iter_open_list(&iter)) { + DBG("no list found"); + goto error; + } } while (!found && g_at_result_iter_next_string(&iter, &data_type)) { From 62c6778466ee74b14e65ef757eb86b15544b1c04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Fri, 19 Jul 2019 12:27:46 +0200 Subject: [PATCH 163/320] quectel: pass vendor id to gprs and gprs-context The gprs-context does special casing on the quectel serial modem when probing the supported layer 2 protocols, so pass the vendor id when setting up the atoms. --- ofono/plugins/quectel.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 00a3bccef..27ac92566 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -719,8 +719,9 @@ static void quectel_post_sim(struct ofono_modem *modem) DBG("%p", modem); - gprs = ofono_gprs_create(modem, 0, "atmodem", data->aux); - gc = ofono_gprs_context_create(modem, 0, "atmodem", data->modem); + gprs = ofono_gprs_create(modem, data->vendor, "atmodem", data->aux); + gc = ofono_gprs_context_create(modem, data->vendor, "atmodem", + data->modem); if (gprs && gc) ofono_gprs_add_context(gprs, gc); From 658f075b1f1f893fdb6b916d45a52b6a067e0364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Fri, 19 Jul 2019 14:39:55 +0200 Subject: [PATCH 164/320] doc: add documentaion for Quectel hardware API --- ofono/doc/quectel-hardware-api.txt | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 ofono/doc/quectel-hardware-api.txt diff --git a/ofono/doc/quectel-hardware-api.txt b/ofono/doc/quectel-hardware-api.txt new file mode 100644 index 000000000..c6cce4e8a --- /dev/null +++ b/ofono/doc/quectel-hardware-api.txt @@ -0,0 +1,32 @@ +Hardware hierarchy +================== + +Service org.ofono +Interface org.ofono.quectel.Hardware +Object path /{device0,device1,...} + +Methods array{string,variant} GetProperties + + Returns hardware properties for the modem object. See + the properties section for available properties. + +Properties int32 Voltage [readonly] + + Integer with the modem supply voltage in mV. + + int32 ChargeStatus [readonly,optional] + + Integer with one of either: + + 0: Modem is not charging + 1: Modem is charging + 2: Charging is finished + + This property is available on UC15 + + int32 ChargeLevel [readonly,optional] + + Integer representing the battery charge level in + percent (from 0 to 100). + + This property is available on UC15 From e63fd551b6c770fda3b3ea5cc19c2bd6c679787f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Fri, 19 Jul 2019 14:39:54 +0200 Subject: [PATCH 165/320] quectel: add dbus hardware interface For now the interface only exposes the modem supply voltage, but is added as a preparation for signaling power events. --- ofono/plugins/quectel.c | 158 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 27ac92566..e1f889447 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -37,6 +37,7 @@ #include #define OFONO_API_SUBJECT_TO_CHANGE +#include #include #include #include @@ -49,12 +50,16 @@ #include #include #include +#include + +#include #include #include static const char *cfun_prefix[] = { "+CFUN:", NULL }; 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 }; @@ -95,6 +100,16 @@ struct quectel_data { struct l_gpio_writer *gpio; }; +struct dbus_hw { + DBusMessage *msg; + struct ofono_modem *modem; + int32_t charge_status; + int32_t charge_level; + int32_t voltage; +}; + +static const char dbus_hw_interface[] = OFONO_SERVICE ".quectel.Hardware"; + static void quectel_debug(const char *str, void *user_data) { const char *prefix = user_data; @@ -229,6 +244,142 @@ static void close_serial(struct ofono_modem *modem) ofono_modem_set_powered(modem, false); } +static void dbus_hw_reply_properties(struct dbus_hw *hw) +{ + struct quectel_data *data = ofono_modem_get_data(hw->modem); + DBusMessage *reply; + DBusMessageIter dbus_iter; + DBusMessageIter dbus_dict; + + DBG("%p", hw->modem); + + reply = dbus_message_new_method_return(hw->msg); + dbus_message_iter_init_append(reply, &dbus_iter); + dbus_message_iter_open_container(&dbus_iter, DBUS_TYPE_ARRAY, + OFONO_PROPERTIES_ARRAY_SIGNATURE, + &dbus_dict); + + /* + * the charge status/level received from m95 and mc60 are invalid so + * only return those for the UC15 modem. + */ + if (data->model == QUECTEL_UC15) { + ofono_dbus_dict_append(&dbus_dict, "ChargeStatus", + DBUS_TYPE_INT32, &hw->charge_status); + + ofono_dbus_dict_append(&dbus_dict, "ChargeLevel", + DBUS_TYPE_INT32, &hw->charge_level); + } + + ofono_dbus_dict_append(&dbus_dict, "Voltage", DBUS_TYPE_INT32, + &hw->voltage); + + dbus_message_iter_close_container(&dbus_iter, &dbus_dict); + + __ofono_dbus_pending_reply(&hw->msg, reply); +} + +static void cbc_cb(gboolean ok, GAtResult *result, gpointer user_data) +{ + struct dbus_hw *hw = user_data; + GAtResultIter iter; + + DBG("%p", hw->modem); + + if (!hw->msg) + return; + + if (!ok) + goto error; + + g_at_result_iter_init(&iter, result); + + if (!g_at_result_iter_next(&iter, "+CBC:")) + goto error; + + /* the returned charge status is valid only for uc15 */ + if (!g_at_result_iter_next_number(&iter, &hw->charge_status)) + goto error; + + /* the returned charge level is valid only for uc15 */ + if (!g_at_result_iter_next_number(&iter, &hw->charge_level)) + goto error; + + /* now comes the millivolts */ + if (!g_at_result_iter_next_number(&iter, &hw->voltage)) + goto error; + + dbus_hw_reply_properties(hw); + + return; + +error: + __ofono_dbus_pending_reply(&hw->msg, __ofono_error_failed(hw->msg)); +} + +static DBusMessage *dbus_hw_get_properties(DBusConnection *conn, + DBusMessage *msg, + void *user_data) +{ + struct dbus_hw *hw = user_data; + struct quectel_data *data = ofono_modem_get_data(hw->modem); + + DBG("%p", hw->modem); + + if (hw->msg != NULL) + return __ofono_error_busy(msg); + + if (!g_at_chat_send(data->aux, "AT+CBC", cbc_prefix, cbc_cb, hw, NULL)) + return __ofono_error_failed(msg); + + hw->msg = dbus_message_ref(msg); + + return NULL; +} + +static const GDBusMethodTable dbus_hw_methods[] = { + { GDBUS_ASYNC_METHOD("GetProperties", + NULL, GDBUS_ARGS({ "properties", "a{sv}" }), + dbus_hw_get_properties) }, + {} +}; + +static void dbus_hw_cleanup(void *data) +{ + struct dbus_hw *hw = data; + + DBG("%p", hw->modem); + + if (hw->msg) + __ofono_dbus_pending_reply(&hw->msg, + __ofono_error_canceled(hw->msg)); + + l_free(hw); +} + +static void dbus_hw_enable(struct ofono_modem *modem) +{ + DBusConnection *conn = ofono_dbus_get_connection(); + const char *path = ofono_modem_get_path(modem); + struct dbus_hw *hw; + + DBG("%p", modem); + + hw = l_new(struct dbus_hw, 1); + hw->modem = modem; + + if (!g_dbus_register_interface(conn, path, dbus_hw_interface, + dbus_hw_methods, NULL, NULL, + hw, dbus_hw_cleanup)) { + ofono_error("Could not register %s interface under %s", + dbus_hw_interface, path); + l_free(hw); + return; + } + + ofono_modem_add_interface(modem, dbus_hw_interface); +} + static void cpin_notify(GAtResult *result, gpointer user_data) { struct ofono_modem *modem = user_data; @@ -255,6 +406,8 @@ static void cpin_notify(GAtResult *result, gpointer user_data) g_at_chat_unregister(data->aux, data->cpin_ready); data->cpin_ready = 0; + + dbus_hw_enable(modem); } static void cpin_query(gboolean ok, GAtResult *result, gpointer user_data) @@ -652,6 +805,8 @@ static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data) static int quectel_disable(struct ofono_modem *modem) { struct quectel_data *data = ofono_modem_get_data(modem); + DBusConnection *conn = ofono_dbus_get_connection(); + const char *path = ofono_modem_get_path(modem); DBG("%p", modem); @@ -661,6 +816,9 @@ static int quectel_disable(struct ofono_modem *modem) g_at_chat_cancel_all(data->aux); g_at_chat_unregister_all(data->aux); + if (g_dbus_unregister_interface(conn, path, dbus_hw_interface)) + ofono_modem_remove_interface(modem, dbus_hw_interface); + g_at_chat_send(data->aux, "AT+CFUN=0", cfun_prefix, cfun_disable, modem, NULL); From c98881a95965aaa49418b8ef12032a497e0e0c78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Fri, 19 Jul 2019 14:39:57 +0200 Subject: [PATCH 166/320] doc: document power-event signals for quectel Hardware API --- ofono/doc/quectel-hardware-api.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/ofono/doc/quectel-hardware-api.txt b/ofono/doc/quectel-hardware-api.txt index c6cce4e8a..139a0dc1d 100644 --- a/ofono/doc/quectel-hardware-api.txt +++ b/ofono/doc/quectel-hardware-api.txt @@ -10,6 +10,25 @@ Methods array{string,variant} GetProperties Returns hardware properties for the modem object. See the properties section for available properties. +Signals PowerDown(string reason) + + This signal is emitted on gracefull shutdowns initiated + 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 + + PowerWarning(string reason) + + This signal is emitted when the modem detects its supply + voltage is close to its supported limits. + + Possible reasons: + "VoltageLow" The supply voltage is low + "VoltageHigh" The supply voltage is high + Properties int32 Voltage [readonly] Integer with the modem supply voltage in mV. From 8a138dc0d0896edb987fd5a9960ff2de18efe5a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Fri, 19 Jul 2019 14:39:56 +0200 Subject: [PATCH 167/320] quectel: implement dbus signals for modem power notifications The Quectel modems issues unsolicited strings in case of power related events. The UC15 uses +QIND: for the events, while M95 and MC60 uses descriptive strings. (UC15 also uses a string for normal power down). Register listeners for these strings/codes. The handler emits an appropriate dbus signal, and closes down the modem if needed. --- ofono/plugins/quectel.c | 146 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 145 insertions(+), 1 deletion(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index e1f889447..03c10dcfa 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -108,6 +108,14 @@ struct dbus_hw { int32_t voltage; }; +enum quectel_power_event { + LOW_POWER_DOWN = -2, + LOW_WARNING = -1, + NORMAL_POWER_DOWN = 0, + HIGH_WARNING = 1, + HIGH_POWER_DOWN = 2, +}; + static const char dbus_hw_interface[] = OFONO_SERVICE ".quectel.Hardware"; static void quectel_debug(const char *str, void *user_data) @@ -337,6 +345,110 @@ static DBusMessage *dbus_hw_get_properties(DBusConnection *conn, return NULL; } +static void voltage_handle(struct ofono_modem *modem, + enum quectel_power_event event) +{ + DBusConnection *conn = ofono_dbus_get_connection(); + DBusMessage *signal; + DBusMessageIter iter; + const char *path = ofono_modem_get_path(modem); + const char *name; + const char *reason; + bool close; + + DBG("%p", modem); + + switch (event) { + case LOW_POWER_DOWN: + close = true; + name = "PowerDown"; + reason = "VoltageLow"; + break; + case LOW_WARNING: + close = false; + name = "PowerWarning"; + reason = "VoltageLow"; + break; + case NORMAL_POWER_DOWN: + close = true; + name = "PowerDown"; + reason = "Normal"; + break; + case HIGH_WARNING: + close = false; + name = "PowerWarning"; + reason = "VoltageHigh"; + break; + case HIGH_POWER_DOWN: + close = true; + name = "PowerDown"; + reason = "VoltageHigh"; + break; + default: + return; + } + + signal = dbus_message_new_signal(path, dbus_hw_interface, name); + if (signal) { + dbus_message_iter_init_append(signal, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, + &reason); + g_dbus_send_message(conn, signal); + } + + if (close) + close_serial(modem); +} + +static void qind_notify(GAtResult *result, void *user_data) +{ + struct dbus_hw *hw = user_data; + GAtResultIter iter; + enum quectel_power_event event; + const char *type; + + DBG("%p", hw->modem); + + g_at_result_iter_init(&iter, result); + g_at_result_iter_next(&iter, "+QIND:"); + + if (!g_at_result_iter_next_string(&iter, &type)) + return; + + if (!g_at_result_iter_next_number(&iter, &event)) + return; + + voltage_handle(hw->modem, event); +} + +static void power_notify(GAtResult *result, void *user_data) +{ + struct dbus_hw *hw = user_data; + GAtResultIter iter; + const char *event; + + DBG("%p", hw->modem); + + g_at_result_iter_init(&iter, result); + g_at_result_iter_next(&iter, NULL); + + if (!g_at_result_iter_next_unquoted_string(&iter, &event)) + return; + + DBG("event: %s", event); + + if (g_strcmp0(event, "UNDER_VOLTAGE POWER DOWN") == 0) + voltage_handle(hw->modem, LOW_POWER_DOWN); + else if (g_strcmp0(event, "UNDER_VOLTAGE WARNING") == 0) + voltage_handle(hw->modem, LOW_WARNING); + else if (g_strcmp0(event, "NORMAL POWER DOWN") == 0) + voltage_handle(hw->modem, NORMAL_POWER_DOWN); + else if (g_strcmp0(event, "OVER_VOLTAGE WARNING") == 0) + voltage_handle(hw->modem, HIGH_WARNING); + else if (g_strcmp0(event, "OVER_VOLTAGE POWER DOWN") == 0) + voltage_handle(hw->modem, HIGH_POWER_DOWN); +} + static const GDBusMethodTable dbus_hw_methods[] = { { GDBUS_ASYNC_METHOD("GetProperties", NULL, GDBUS_ARGS({ "properties", "a{sv}" }), @@ -344,6 +456,14 @@ static const GDBusMethodTable dbus_hw_methods[] = { {} }; +static const GDBusSignalTable dbus_hw_signals[] = { + { GDBUS_SIGNAL("PowerDown", + GDBUS_ARGS({ "reason", "s" })) }, + { GDBUS_SIGNAL("PowerWarning", + GDBUS_ARGS({ "reason", "s" })) }, + { } +}; + static void dbus_hw_cleanup(void *data) { struct dbus_hw *hw = data; @@ -360,6 +480,7 @@ static void dbus_hw_cleanup(void *data) static void dbus_hw_enable(struct ofono_modem *modem) { DBusConnection *conn = ofono_dbus_get_connection(); + struct quectel_data *data = ofono_modem_get_data(modem); const char *path = ofono_modem_get_path(modem); struct dbus_hw *hw; @@ -369,7 +490,7 @@ static void dbus_hw_enable(struct ofono_modem *modem) hw->modem = modem; if (!g_dbus_register_interface(conn, path, dbus_hw_interface, - dbus_hw_methods, NULL, NULL, + dbus_hw_methods, dbus_hw_signals, NULL, hw, dbus_hw_cleanup)) { ofono_error("Could not register %s interface under %s", dbus_hw_interface, path); @@ -377,6 +498,29 @@ static void dbus_hw_enable(struct ofono_modem *modem) return; } + g_at_chat_register(data->aux, "NORMAL POWER DOWN", power_notify, FALSE, + hw, NULL); + + switch (data->model) { + case QUECTEL_UC15: + g_at_chat_register(data->aux, "+QIND", qind_notify, FALSE, hw, + NULL); + break; + case QUECTEL_M95: + case QUECTEL_MC60: + g_at_chat_register(data->aux, "OVER_VOLTAGE POWER DOWN", + power_notify, FALSE, hw, NULL); + g_at_chat_register(data->aux, "UNDER_VOLTAGE POWER DOWN", + power_notify, FALSE, hw, NULL); + g_at_chat_register(data->aux, "OVER_VOLTAGE WARNING", + power_notify, FALSE, hw, NULL); + g_at_chat_register(data->aux, "UNDER_VOLTAGE WARNING", + power_notify, FALSE, hw, NULL); + break; + case QUECTEL_UNKNOWN: + break; + } + ofono_modem_add_interface(modem, dbus_hw_interface); } From 467a44f611f5c41a90a82d4092faa11cfff05db6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Wed, 24 Jul 2019 19:24:19 +0200 Subject: [PATCH 168/320] atmodem: Check for auto activated contexts during init To detect if a context gets activated before we register for unsolicited events we need to check if any is already activated, and flag it auto activated. --- ofono/drivers/atmodem/gprs.c | 47 ++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/ofono/drivers/atmodem/gprs.c b/ofono/drivers/atmodem/gprs.c index fbee5c949..101082817 100644 --- a/ofono/drivers/atmodem/gprs.c +++ b/ofono/drivers/atmodem/gprs.c @@ -43,6 +43,7 @@ static const char *cgreg_prefix[] = { "+CGREG:", NULL }; static const char *cgdcont_prefix[] = { "+CGDCONT:", NULL }; +static const char *cgact_prefix[] = { "+CGACT:", NULL }; static const char *none_prefix[] = { NULL }; struct gprs_data { @@ -192,6 +193,48 @@ static void at_cgdcont_read_cb(gboolean ok, GAtResult *result, activated_cid); } +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); + GAtResultIter iter; + + DBG("ok %d", ok); + + if (!ok) { + ofono_warn("Can't read CGACT contexts."); + return; + } + + g_at_result_iter_init(&iter, result); + + while (g_at_result_iter_next(&iter, "+CGACT:")) { + int read_cid = -1; + int read_status = -1; + + if (!g_at_result_iter_next_number(&iter, &read_cid)) + break; + + if (!g_at_result_iter_next_number(&iter, &read_status)) + break; + + if (read_status != 1) + continue; + + /* Flag this as auto context as it was obviously active */ + if (gd->last_auto_context_id == 0) + gd->last_auto_context_id = read_cid; + + if (read_cid != gd->last_auto_context_id) + continue; + + g_at_chat_send(gd->chat, "AT+CGDCONT?", cgdcont_prefix, + at_cgdcont_read_cb, gprs, NULL); + + break; + } +} + static void cgreg_notify(GAtResult *result, gpointer user_data) { struct ofono_gprs *gprs = user_data; @@ -495,6 +538,10 @@ static void gprs_initialized(gboolean ok, GAtResult *result, gpointer user_data) break; } + /* Check if there is any already activated contexts at init */ + g_at_chat_send(gd->chat, "AT+CGACT?", cgact_prefix, + at_cgact_cb, gprs, NULL); + ofono_gprs_register(gprs); } From cd0a724f69409998aa139aa8edc1d2cb10df7e2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Tue, 6 Aug 2019 08:33:56 +0000 Subject: [PATCH 169/320] gprs: Use -1 as netreg status during init. Previously the valid "unknown" netreg status was set during startup, but its a bit problematic for gprs. There might be cases where a LTE context is activated before netreg is finished updating its status. Resulting in gprs taking faulty actions. Instead we set the status to -1 until we are updated with a known value. During the time the status is -1, gprs postpones actions until the status is valid (>= 0). --- ofono/src/gprs.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/ofono/src/gprs.c b/ofono/src/gprs.c index 13a0ada9f..01571aedb 100644 --- a/ofono/src/gprs.c +++ b/ofono/src/gprs.c @@ -2076,6 +2076,15 @@ static void gprs_netreg_update(struct ofono_gprs *gprs) { ofono_bool_t attach; + /* + * This function can get called by other reasons than netreg + * updating its status. So check if we have a valid netreg status yet. + * The only reason for not having a valid status is basically during + * startup while the netreg atom is fetching the status. + */ + if (gprs->netreg_status < 0) + return; + attach = gprs->netreg_status == NETWORK_REGISTRATION_STATUS_REGISTERED; attach = attach || (gprs->roaming_allowed && @@ -3623,7 +3632,7 @@ struct ofono_gprs *ofono_gprs_create(struct ofono_modem *modem, } gprs->status = NETWORK_REGISTRATION_STATUS_UNKNOWN; - gprs->netreg_status = NETWORK_REGISTRATION_STATUS_UNKNOWN; + gprs->netreg_status = -1; gprs->pid_map = idmap_new(MAX_CONTEXTS); gprs->filters = __ofono_gprs_filter_chain_new(gprs); @@ -3635,6 +3644,7 @@ static void netreg_watch(struct ofono_atom *atom, void *data) { struct ofono_gprs *gprs = data; + int status; if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) { gprs_netreg_removed(gprs); @@ -3642,7 +3652,16 @@ static void netreg_watch(struct ofono_atom *atom, } gprs->netreg = __ofono_atom_get_data(atom); - gprs->netreg_status = ofono_netreg_get_status(gprs->netreg); + status = ofono_netreg_get_status(gprs->netreg); + + /* + * If the status is known, assign it, otherwise keep the init value + * to indicate that the netreg atom is not initialised with a known + * value + */ + if (status != NETWORK_REGISTRATION_STATUS_UNKNOWN) + gprs->netreg_status = status; + gprs->status_watch = __ofono_netreg_add_status_watch(gprs->netreg, netreg_status_changed, gprs, NULL); From 4d459f45ae03b4648fabfe1ad41ab9ffac6d8776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Tue, 6 Aug 2019 23:11:09 +0000 Subject: [PATCH 170/320] gprs: Do not leak CID on failure to assign context --- ofono/src/gprs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ofono/src/gprs.c b/ofono/src/gprs.c index 01571aedb..92a1f3741 100644 --- a/ofono/src/gprs.c +++ b/ofono/src/gprs.c @@ -305,6 +305,8 @@ static gboolean assign_context(struct pri_context *ctx, int use_cid) return TRUE; } + ctx->context.cid = 0; + return FALSE; } From 7924bacaf340737f6eb6d6169cba518d55b34dad Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 12 Aug 2019 19:36:42 +0200 Subject: [PATCH 171/320] isimodem: Fix size calculation for address array --- ofono/drivers/isimodem/voicecall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/drivers/isimodem/voicecall.c b/ofono/drivers/isimodem/voicecall.c index 9a63f1004..3fb150f62 100644 --- a/ofono/drivers/isimodem/voicecall.c +++ b/ofono/drivers/isimodem/voicecall.c @@ -227,7 +227,7 @@ static void isi_call_any_address_sb_proc(struct isi_voicecall *ivc, call->addr_type = type | 0x80; call->presentation = pres; - strncpy(call->address, addr, sizeof(call->address)); + strncpy(call->address, addr, sizeof(call->address) - 1); g_free(addr); } From 23167666e6bcee7c38ee176cedac9832422d9b9d Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 12 Aug 2019 19:38:06 +0200 Subject: [PATCH 172/320] gisi: Fix compiler warnings from -Waddress-of-packed-member --- ofono/gisi/modem.c | 2 ++ ofono/gisi/socket.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/ofono/gisi/modem.c b/ofono/gisi/modem.c index ef0c04911..2eb015dfa 100644 --- a/ofono/gisi/modem.c +++ b/ofono/gisi/modem.c @@ -33,6 +33,8 @@ #include #include +#pragma GCC diagnostic ignored "-Waddress-of-packed-member" + #include "message.h" #include "common.h" #include "modem.h" diff --git a/ofono/gisi/socket.c b/ofono/gisi/socket.c index 2428f5d58..8c4af1bd3 100644 --- a/ofono/gisi/socket.c +++ b/ofono/gisi/socket.c @@ -32,6 +32,8 @@ #include #include +#pragma GCC diagnostic ignored "-Waddress-of-packed-member" + #include "phonet.h" #include "socket.h" From 0eb85ec69c59fa543832701051f8763358b03550 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 12 Aug 2019 19:46:17 +0200 Subject: [PATCH 173/320] build: Add internal copy of linux/gpio.h for older systems --- linux/gpio.h | 158 ++++++++++++++++++++++++++++++++++++++++++++++ ofono/Makefile.am | 3 +- 2 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 linux/gpio.h diff --git a/linux/gpio.h b/linux/gpio.h new file mode 100644 index 000000000..778ebc356 --- /dev/null +++ b/linux/gpio.h @@ -0,0 +1,158 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * - userspace ABI for the GPIO character devices + * + * Copyright (C) 2016 Linus Walleij + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ +#ifndef _GPIO_H_ +#define _GPIO_H_ + +#include +#include + +/** + * struct gpiochip_info - Information about a certain GPIO chip + * @name: the Linux kernel name of this GPIO chip + * @label: a functional name for this GPIO chip, such as a product + * number, may be NULL + * @lines: number of GPIO lines on this chip + */ +struct gpiochip_info { + char name[32]; + char label[32]; + __u32 lines; +}; + +/* Informational flags */ +#define GPIOLINE_FLAG_KERNEL (1UL << 0) /* Line used by the kernel */ +#define GPIOLINE_FLAG_IS_OUT (1UL << 1) +#define GPIOLINE_FLAG_ACTIVE_LOW (1UL << 2) +#define GPIOLINE_FLAG_OPEN_DRAIN (1UL << 3) +#define GPIOLINE_FLAG_OPEN_SOURCE (1UL << 4) + +/** + * struct gpioline_info - Information about a certain GPIO line + * @line_offset: the local offset on this GPIO device, fill this in when + * requesting the line information from the kernel + * @flags: various flags for this line + * @name: the name of this GPIO line, such as the output pin of the line on the + * chip, a rail or a pin header name on a board, as specified by the gpio + * chip, may be NULL + * @consumer: a functional name for the consumer of this GPIO line as set by + * whatever is using it, will be NULL if there is no current user but may + * also be NULL if the consumer doesn't set this up + */ +struct gpioline_info { + __u32 line_offset; + __u32 flags; + char name[32]; + char consumer[32]; +}; + +/* Maximum number of requested handles */ +#define GPIOHANDLES_MAX 64 + +/* Linerequest flags */ +#define GPIOHANDLE_REQUEST_INPUT (1UL << 0) +#define GPIOHANDLE_REQUEST_OUTPUT (1UL << 1) +#define GPIOHANDLE_REQUEST_ACTIVE_LOW (1UL << 2) +#define GPIOHANDLE_REQUEST_OPEN_DRAIN (1UL << 3) +#define GPIOHANDLE_REQUEST_OPEN_SOURCE (1UL << 4) + +/** + * struct gpiohandle_request - Information about a GPIO handle request + * @lineoffsets: an array of desired lines, specified by offset index for the + * associated GPIO device + * @flags: desired flags for the desired GPIO lines, such as + * GPIOHANDLE_REQUEST_OUTPUT, GPIOHANDLE_REQUEST_ACTIVE_LOW etc, OR:ed + * together. Note that even if multiple lines are requested, the same flags + * must be applicable to all of them, if you want lines with individual + * flags set, request them one by one. It is possible to select + * a batch of input or output lines, but they must all have the same + * characteristics, i.e. all inputs or all outputs, all active low etc + * @default_values: if the GPIOHANDLE_REQUEST_OUTPUT is set for a requested + * line, this specifies the default output value, should be 0 (low) or + * 1 (high), anything else than 0 or 1 will be interpreted as 1 (high) + * @consumer_label: a desired consumer label for the selected GPIO line(s) + * such as "my-bitbanged-relay" + * @lines: number of lines requested in this request, i.e. the number of + * valid fields in the above arrays, set to 1 to request a single line + * @fd: if successful this field will contain a valid anonymous file handle + * after a GPIO_GET_LINEHANDLE_IOCTL operation, zero or negative value + * means error + */ +struct gpiohandle_request { + __u32 lineoffsets[GPIOHANDLES_MAX]; + __u32 flags; + __u8 default_values[GPIOHANDLES_MAX]; + char consumer_label[32]; + __u32 lines; + int fd; +}; + +/** + * struct gpiohandle_data - Information of values on a GPIO handle + * @values: when getting the state of lines this contains the current + * state of a line, when setting the state of lines these should contain + * the desired target state + */ +struct gpiohandle_data { + __u8 values[GPIOHANDLES_MAX]; +}; + +#define GPIOHANDLE_GET_LINE_VALUES_IOCTL _IOWR(0xB4, 0x08, struct gpiohandle_data) +#define GPIOHANDLE_SET_LINE_VALUES_IOCTL _IOWR(0xB4, 0x09, struct gpiohandle_data) + +/* Eventrequest flags */ +#define GPIOEVENT_REQUEST_RISING_EDGE (1UL << 0) +#define GPIOEVENT_REQUEST_FALLING_EDGE (1UL << 1) +#define GPIOEVENT_REQUEST_BOTH_EDGES ((1UL << 0) | (1UL << 1)) + +/** + * struct gpioevent_request - Information about a GPIO event request + * @lineoffset: the desired line to subscribe to events from, specified by + * offset index for the associated GPIO device + * @handleflags: desired handle flags for the desired GPIO line, such as + * GPIOHANDLE_REQUEST_ACTIVE_LOW or GPIOHANDLE_REQUEST_OPEN_DRAIN + * @eventflags: desired flags for the desired GPIO event line, such as + * GPIOEVENT_REQUEST_RISING_EDGE or GPIOEVENT_REQUEST_FALLING_EDGE + * @consumer_label: a desired consumer label for the selected GPIO line(s) + * such as "my-listener" + * @fd: if successful this field will contain a valid anonymous file handle + * after a GPIO_GET_LINEEVENT_IOCTL operation, zero or negative value + * means error + */ +struct gpioevent_request { + __u32 lineoffset; + __u32 handleflags; + __u32 eventflags; + char consumer_label[32]; + int fd; +}; + +/** + * GPIO event types + */ +#define GPIOEVENT_EVENT_RISING_EDGE 0x01 +#define GPIOEVENT_EVENT_FALLING_EDGE 0x02 + +/** + * struct gpioevent_data - The actual event being pushed to userspace + * @timestamp: best estimate of time of event occurrence, in nanoseconds + * @id: event identifier + */ +struct gpioevent_data { + __u64 timestamp; + __u32 id; +}; + +#define GPIO_GET_CHIPINFO_IOCTL _IOR(0xB4, 0x01, struct gpiochip_info) +#define GPIO_GET_LINEINFO_IOCTL _IOWR(0xB4, 0x02, struct gpioline_info) +#define GPIO_GET_LINEHANDLE_IOCTL _IOWR(0xB4, 0x03, struct gpiohandle_request) +#define GPIO_GET_LINEEVENT_IOCTL _IOWR(0xB4, 0x04, struct gpioevent_request) + +#endif /* _GPIO_H_ */ diff --git a/ofono/Makefile.am b/ofono/Makefile.am index 9a9378f5e..bbfc7e58e 100644 --- a/ofono/Makefile.am +++ b/ofono/Makefile.am @@ -696,7 +696,8 @@ endif sbin_PROGRAMS = src/ofonod -src_ofonod_SOURCES = $(builtin_sources) $(gatchat_sources) src/ofono.ver \ +src_ofonod_SOURCES = $(builtin_sources) $(gatchat_sources) \ + linux/gpio.h src/ofono.ver \ src/main.c src/ofono.h src/log.c src/plugin.c \ src/modem.c src/common.h src/common.c \ src/manager.c src/dbus.c src/util.h src/util.c \ From 554b87153b9f194119489cf2c6bde02d0e482783 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 12 Aug 2019 19:53:40 +0200 Subject: [PATCH 174/320] build: Add internal copy of linux/gsmmux.h for older systems --- linux/gsmmux.h | 41 +++++++++++++++++++++++++++++++++++++++++ ofono/Makefile.am | 2 +- 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 linux/gsmmux.h diff --git a/linux/gsmmux.h b/linux/gsmmux.h new file mode 100644 index 000000000..101d3c469 --- /dev/null +++ b/linux/gsmmux.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LINUX_GSMMUX_H +#define _LINUX_GSMMUX_H + +#include +#include +#include + +struct gsm_config +{ + unsigned int adaption; + unsigned int encapsulation; + unsigned int initiator; + unsigned int t1; + unsigned int t2; + unsigned int t3; + unsigned int n2; + unsigned int mru; + unsigned int mtu; + unsigned int k; + unsigned int i; + unsigned int unused[8]; /* Padding for expansion without + breaking stuff */ +}; + +#define GSMIOC_GETCONF _IOR('G', 0, struct gsm_config) +#define GSMIOC_SETCONF _IOW('G', 1, struct gsm_config) + +struct gsm_netconfig { + unsigned int adaption; /* Adaption to use in network mode */ + unsigned short protocol;/* Protocol to use - only ETH_P_IP supported */ + unsigned short unused2; + char if_name[IFNAMSIZ]; /* interface name format string */ + __u8 unused[28]; /* For future use */ +}; + +#define GSMIOC_ENABLE_NET _IOW('G', 2, struct gsm_netconfig) +#define GSMIOC_DISABLE_NET _IO('G', 3) + + +#endif diff --git a/ofono/Makefile.am b/ofono/Makefile.am index bbfc7e58e..33c06d0dc 100644 --- a/ofono/Makefile.am +++ b/ofono/Makefile.am @@ -697,7 +697,7 @@ endif sbin_PROGRAMS = src/ofonod src_ofonod_SOURCES = $(builtin_sources) $(gatchat_sources) \ - linux/gpio.h src/ofono.ver \ + linux/gsmmux.h linux/gpio.h src/ofono.ver \ src/main.c src/ofono.h src/log.c src/plugin.c \ src/modem.c src/common.h src/common.c \ src/manager.c src/dbus.c src/util.h src/util.c \ From af5f3f7020d9e3d2b7c727f66592d927620db41a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 12 Aug 2019 20:02:34 +0200 Subject: [PATCH 175/320] quectel: Add missing include for sys/socket.h --- ofono/plugins/quectel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 03c10dcfa..037d4834b 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include From a3f519fd43865464fbee5a561c27acac1170e0f0 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 12 Aug 2019 20:14:32 +0200 Subject: [PATCH 176/320] build: Add missing drivers/atmodem/network-registration.h --- ofono/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/ofono/Makefile.am b/ofono/Makefile.am index 33c06d0dc..088932e62 100644 --- a/ofono/Makefile.am +++ b/ofono/Makefile.am @@ -267,6 +267,7 @@ builtin_sources += drivers/atmodem/atmodem.h \ drivers/atmodem/cbs.c \ drivers/atmodem/call-forwarding.c \ drivers/atmodem/call-meter.c \ + drivers/atmodem/network-registration.h \ drivers/atmodem/network-registration.c \ drivers/atmodem/sim.c \ drivers/atmodem/stk.c \ From 77df5b2370c32c5f66d4c2d10341562f9561fb97 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 12 Aug 2019 20:54:02 +0200 Subject: [PATCH 177/320] Release 1.30 --- ofono/ChangeLog | 6 ++++++ ofono/configure.ac | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ofono/ChangeLog b/ofono/ChangeLog index 2a426bce9..283f3b5b2 100644 --- a/ofono/ChangeLog +++ b/ofono/ChangeLog @@ -1,3 +1,9 @@ +ver 1.30: + Fix issue with handling of IPv6 address and xmm7xxx modems. + Fix issue with default context creation with an empty APN. + Fix issue with activation of context with CID zero. + Add support for Quectel MC60 modems. + ver 1.29: Fix issue with QMI and SIM initialized notification. Add support for multiple PDP contexts and xmm7xxx modems. diff --git a/ofono/configure.ac b/ofono/configure.ac index 7c4d92027..05efb3503 100644 --- a/ofono/configure.ac +++ b/ofono/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.60) -AC_INIT(ofono, 1.29) +AC_INIT(ofono, 1.30) AM_INIT_AUTOMAKE([foreign subdir-objects color-tests]) AC_CONFIG_HEADERS(config.h) From 18283c1c4126c00d4b8120181a2350b66823b5d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Mon, 12 Aug 2019 22:37:56 +0200 Subject: [PATCH 178/320] gprs: Do not detach when running LTE and GPRS is unavailable. There are cases where the gprs status might updated to for instance "unknown" while LTE is the bearer. In that case we should not set the attach state to FALSE, since then running LTE the conext activation reflects the attached state. --- ofono/src/gprs.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/ofono/src/gprs.c b/ofono/src/gprs.c index 92a1f3741..d73edfa37 100644 --- a/ofono/src/gprs.c +++ b/ofono/src/gprs.c @@ -2074,6 +2074,15 @@ static void gprs_netreg_removed(struct ofono_gprs *gprs) gprs_attached_update(gprs); } +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_netreg_update(struct ofono_gprs *gprs) { ofono_bool_t attach; @@ -2102,8 +2111,7 @@ static void gprs_netreg_update(struct ofono_gprs *gprs) * 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. @@ -3041,7 +3049,16 @@ void ofono_gprs_status_notify(struct ofono_gprs *gprs, int status) 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 + * result in detaching... + */ + if (!on_lte(gprs)) + gprs_attached_update(gprs); return; } From 616f4a42b933f9985ff3807ebb6facfdc8a209af Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 13 Aug 2019 00:53:18 +0200 Subject: [PATCH 179/320] gisi: Fix compiler warnings from -Wpragmas --- ofono/gisi/modem.c | 1 + ofono/gisi/socket.c | 1 + 2 files changed, 2 insertions(+) diff --git a/ofono/gisi/modem.c b/ofono/gisi/modem.c index 2eb015dfa..894235983 100644 --- a/ofono/gisi/modem.c +++ b/ofono/gisi/modem.c @@ -33,6 +33,7 @@ #include #include +#pragma GCC diagnostic ignored "-Wpragmas" #pragma GCC diagnostic ignored "-Waddress-of-packed-member" #include "message.h" diff --git a/ofono/gisi/socket.c b/ofono/gisi/socket.c index 8c4af1bd3..017bbb319 100644 --- a/ofono/gisi/socket.c +++ b/ofono/gisi/socket.c @@ -32,6 +32,7 @@ #include #include +#pragma GCC diagnostic ignored "-Wpragmas" #pragma GCC diagnostic ignored "-Waddress-of-packed-member" #include "phonet.h" From 4c90eac98b210b9f714b51aa1b3b753cff519ecf Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 13 Aug 2019 00:54:27 +0200 Subject: [PATCH 180/320] atmodem: Remove the pointless #pragma once --- ofono/drivers/atmodem/network-registration.h | 1 - 1 file changed, 1 deletion(-) diff --git a/ofono/drivers/atmodem/network-registration.h b/ofono/drivers/atmodem/network-registration.h index 8a5401cf8..1ec1b7241 100644 --- a/ofono/drivers/atmodem/network-registration.h +++ b/ofono/drivers/atmodem/network-registration.h @@ -1,4 +1,3 @@ -#pragma once struct at_netreg_data { GAtChat *chat; From e599d1d2578225fbae82066ce8f78fed48274d45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Mon, 12 Aug 2019 23:31:28 +0200 Subject: [PATCH 181/320] gprs: Add list_active_contexts This is useful for instance during startup where early activated contexts can be listed at a suitable point in time. --- ofono/include/gprs.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ofono/include/gprs.h b/ofono/include/gprs.h index c8d8c9659..7ff0bd471 100644 --- a/ofono/include/gprs.h +++ b/ofono/include/gprs.h @@ -45,6 +45,8 @@ struct ofono_gprs_driver { 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 { From 9dfb07a0128fb5256f88ff431d4fa9c4b44aa992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Mon, 12 Aug 2019 23:31:29 +0200 Subject: [PATCH 182/320] gprs: Ignore activated contexts during init, list them later There is an issue if an context gets auto activated early, then provisioning might not have run yet for instance, so a "new" context is created, which might be duplicated by a provisioning context later. So ignore the activated contexts until gprs is ready, then it calls the driver to list active contexts. --- ofono/src/gprs.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/ofono/src/gprs.c b/ofono/src/gprs.c index d73edfa37..ddfa561b4 100644 --- a/ofono/src/gprs.c +++ b/ofono/src/gprs.c @@ -2395,7 +2395,12 @@ void ofono_gprs_cid_activated(struct ofono_gprs *gprs, unsigned int cid, 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); @@ -3894,11 +3899,18 @@ static void gprs_load_settings(struct ofono_gprs *gprs, const char *imsi) storage_sync(imsi, SETTINGS_STORE, gprs->settings); } +static void gprs_list_active_contexts_callback(const struct ofono_error *error, + void *data) +{ + DBG("error = %d", error->type); +} + static void ofono_gprs_finish_register(struct ofono_gprs *gprs) { DBusConnection *conn = ofono_dbus_get_connection(); struct ofono_modem *modem = __ofono_atom_get_modem(gprs->atom); const char *path = __ofono_atom_get_path(gprs->atom); + const struct ofono_gprs_driver *driver = gprs->driver; configure_remaining_contexts(gprs); @@ -3921,6 +3933,12 @@ static void ofono_gprs_finish_register(struct ofono_gprs *gprs) netreg_watch, gprs, NULL); __ofono_atom_register(gprs->atom, gprs_unregister); + + /* Find any context activated during init */ + if (driver->list_active_contexts) + driver->list_active_contexts(gprs, + gprs_list_active_contexts_callback, + gprs); } static void spn_read_cb(const char *spn, const char *dc, void *data) From 1c0d3da230a2b0512944b35657df3de3c40dbcf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Mon, 12 Aug 2019 23:31:30 +0200 Subject: [PATCH 183/320] atmodem: Implement the list_activated_contexts callback The callback calls cgact and cgdcont to get information regarding any activate context. --- ofono/drivers/atmodem/gprs.c | 234 +++++++++++++++++++++++++++++------ 1 file changed, 199 insertions(+), 35 deletions(-) diff --git a/ofono/drivers/atmodem/gprs.c b/ofono/drivers/atmodem/gprs.c index 101082817..673a8b3cf 100644 --- a/ofono/drivers/atmodem/gprs.c +++ b/ofono/drivers/atmodem/gprs.c @@ -29,6 +29,7 @@ #include #include +#include "idmap.h" #include #include @@ -41,7 +42,10 @@ #include "atmodem.h" #include "vendor.h" +#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 }; @@ -54,6 +58,47 @@ struct gprs_data { 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 +191,43 @@ static void at_gprs_registration_status(struct ofono_gprs *gprs, 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 +236,52 @@ static void at_cgdcont_read_cb(gboolean ok, GAtResult *result, 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; + idmap_take(cids, activated_cid); - if (!g_at_result_iter_next_number(&iter, &read_cid)) - break; - - 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 +301,45 @@ static void at_cgact_cb(gboolean ok, GAtResult *result, gpointer user_data) 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)) { + list_contexts_data_ref(ld); + return; + } + + CALLBACK_WITH_FAILURE(cb, ld->data); + } else { + /* No active contexts found */ + cb(&error, ld->data); } } +static void at_gprs_list_active_contexts(struct ofono_gprs *gprs, + ofono_gprs_cb_t cb, void *data) +{ + struct gprs_data *gd = ofono_gprs_get_data(gprs); + struct list_contexts_data *ld = list_contexts_data_new(gprs, cb, data); + + if (g_at_chat_send(gd->chat, "AT+CGACT?", cgact_prefix, + at_cgact_cb, ld, list_contexts_data_unref)) + return; + + list_contexts_data_unref(ld); + + CALLBACK_WITH_FAILURE(cb, data); +} + static void cgreg_notify(GAtResult *result, gpointer user_data) { struct ofono_gprs *gprs = user_data; @@ -520,6 +625,9 @@ 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: + case OFONO_VENDOR_QUECTEL_SERIAL: + break; default: g_at_chat_register(gd->chat, "+CPSB:", cpsb_notify, FALSE, gprs, NULL); @@ -538,13 +646,68 @@ static void gprs_initialized(gboolean ok, GAtResult *result, gpointer user_data) break; } - /* Check if there is any already activated contexts at init */ - g_at_chat_send(gd->chat, "AT+CGACT?", cgact_prefix, - at_cgact_cb, gprs, NULL); - 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(&iter, result); + + g_at_result_iter_next(&iter, "+CGEREP:"); + + if (!g_at_result_iter_open_list(&iter)) { + ofono_error("Malformed reply from AT+CGEREP=? Failing..."); + ofono_gprs_remove(gprs); + return; + } + + while (g_at_result_iter_next_range(&iter, &min, &max)) { + if ((min <= 1) && (max >= 1)) + arg1 = 1; + + if ((min <= 2) && (max >= 2)) + arg1 = 2; + } + + if (!g_at_result_iter_close_list(&iter)) + goto out; + + if (!g_at_result_iter_open_list(&iter)) { + two_arguments = FALSE; + goto out; + } + + while (g_at_result_iter_next_range(&iter, &min, &max)) { + if ((min <= 1) && (max >= 1)) + arg2 = 1; + } + + g_at_result_iter_close_list(&iter); + +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) { @@ -599,8 +762,8 @@ static void at_cgreg_test_cb(gboolean ok, GAtResult *result, 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; } @@ -705,6 +868,7 @@ static const struct ofono_gprs_driver driver = { .remove = at_gprs_remove, .set_attached = at_gprs_set_attached, .attached_status = at_gprs_registration_status, + .list_active_contexts = at_gprs_list_active_contexts, }; void at_gprs_init(void) From c2106c5148b3f8c97983128af5f9b3ac4eca8880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Mon, 12 Aug 2019 22:38:31 +0200 Subject: [PATCH 184/320] gatchat: add g_at_chat_retry() The current API doesn't support canceling an in-progress command; instead g_at_chat_cancel() simply removes the callback. In cases where the modem doesn't respond at all to a command, a chat is simply stalled without any way to write new commands to the modem. Support that case by adding a g_at_chat_retry() function to the API. The function does nothing if the command is not yet in-progress, or if the command is finished. Otherwise, it resets the bytes-written counter to re-write the command string. --- ofono/gatchat/gatchat.c | 31 +++++++++++++++++++++++++++++++ ofono/gatchat/gatchat.h | 7 +++++++ 2 files changed, 38 insertions(+) diff --git a/ofono/gatchat/gatchat.c b/ofono/gatchat/gatchat.c index 3f290ac20..9e7771074 100644 --- a/ofono/gatchat/gatchat.c +++ b/ofono/gatchat/gatchat.c @@ -1047,6 +1047,29 @@ static guint at_chat_send_common(struct at_chat *chat, guint gid, 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 @@ guint g_at_chat_send_and_expect_short_prompt(GAtChat *chat, const char *cmd, 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 */ diff --git a/ofono/gatchat/gatchat.h b/ofono/gatchat/gatchat.h index 7290b34fa..328703181 100644 --- a/ofono/gatchat/gatchat.h +++ b/ofono/gatchat/gatchat.h @@ -147,6 +147,13 @@ guint g_at_chat_send_and_expect_short_prompt(GAtChat *chat, const char *cmd, 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); From 5a9ca0de82d3d1d0c49ca1a0ce8846cfb8a7ec5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Mon, 12 Aug 2019 22:38:32 +0200 Subject: [PATCH 185/320] quectel: replace g_at_chat_set_wakeup_command() with g_at_chat_retry() If the modem isn't powered on, the use of g_at_chat_set_wakeup_command() makes ofono send out AT strings in an endless loop. Avoid this by using g_at_chat_retry() in a timer instead. --- ofono/plugins/quectel.c | 64 ++++++++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 037d4834b..c1eccfa9e 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -99,6 +99,9 @@ struct quectel_data { 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 { @@ -188,6 +191,7 @@ static void quectel_remove(struct ofono_modem *modem) 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); g_at_chat_unref(data->aux); g_at_chat_unref(data->modem); @@ -869,6 +873,47 @@ static void ate_cb(int ok, GAtResult *result, void *user_data) cmux_cb, modem, NULL); } +static void init_cmd_cb(gboolean ok, GAtResult *result, void *user_data) +{ + struct ofono_modem *modem = user_data; + struct quectel_data *data = ofono_modem_get_data(modem); + const char *rts_cts; + + DBG("%p", modem); + + if (!ok) + return; + + rts_cts = ofono_modem_get_string(modem, "RtsCts"); + + if (strcmp(rts_cts, "on") == 0) + g_at_chat_send(data->uart, "AT+IFC=2,2; E0", none_prefix, + ate_cb, modem, NULL); + else + g_at_chat_send(data->uart, "ATE0", none_prefix, ate_cb, modem, + NULL); + + l_timeout_remove(data->init_timeout); + data->init_timeout = NULL; +} + +static void init_timeout_cb(struct l_timeout *timeout, void *user_data) +{ + struct ofono_modem *modem = user_data; + struct quectel_data *data = ofono_modem_get_data(modem); + + DBG("%p", modem); + + if (data->init_count++ >= 20) { + ofono_error("failed to init modem after 20 attempts"); + close_serial(modem); + return; + } + + g_at_chat_retry(data->uart, data->init_cmd); + l_timeout_modify_ms(timeout, 500); +} + static int open_serial(struct ofono_modem *modem) { struct quectel_data *data = ofono_modem_get_data(modem); @@ -912,18 +957,15 @@ static int open_serial(struct ofono_modem *modem) * a few 'AT' bytes to detect the host UART bitrate, but the RDY is * lost. * - * the wakeup command feature is (mis)used to support all three - * scenarious by sending AT commands until the modem responds with OK, - * at which point the modem is ready. + * Handle all three cases by issuing a plain AT command. The modem + * answers with OK when it is ready. Create a timer to re-issue + * the AT command at regular intervals until the modem answers. */ - g_at_chat_set_wakeup_command(data->uart, "AT\r", 500, 10000); - - if (strcmp(rts_cts, "on") == 0) - g_at_chat_send(data->uart, "AT+IFC=2,2; E0", none_prefix, - ate_cb, modem, NULL); - else - g_at_chat_send(data->uart, "ATE0", none_prefix, ate_cb, modem, - NULL); + data->init_count = 0; + data->init_cmd = g_at_chat_send(data->uart, "AT", none_prefix, + init_cmd_cb, modem, NULL); + data->init_timeout = l_timeout_create_ms(500, init_timeout_cb, modem, + NULL); return -EINPROGRESS; } From 572d5365dbe71731b843e13ca284d23d706086df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Tue, 13 Aug 2019 20:08:52 +0200 Subject: [PATCH 186/320] doc: convert quectel power event reasons to lower case --- ofono/doc/quectel-hardware-api.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ofono/doc/quectel-hardware-api.txt b/ofono/doc/quectel-hardware-api.txt index 139a0dc1d..c24332820 100644 --- a/ofono/doc/quectel-hardware-api.txt +++ b/ofono/doc/quectel-hardware-api.txt @@ -16,9 +16,9 @@ Signals PowerDown(string reason) 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 @@ Signals PowerDown(string reason) 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] From 73dd1b4042a35453fda425a2ba152c1c0f7bd674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Tue, 13 Aug 2019 20:08:53 +0200 Subject: [PATCH 187/320] quectel: convert power event reasons to lower case --- ofono/plugins/quectel.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index c1eccfa9e..24a7b7b6c 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -367,27 +367,27 @@ static void voltage_handle(struct ofono_modem *modem, 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; From 27100f8fd9a149e3ab35a2250887f616099a3caa Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Fri, 16 Aug 2019 22:27:04 +0200 Subject: [PATCH 188/320] atmodem: introduce send_clcc() to reduce code duplication Reduce code duplication by introducing send_clcc function. --- ofono/drivers/atmodem/voicecall.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/ofono/drivers/atmodem/voicecall.c b/ofono/drivers/atmodem/voicecall.c index d55cf0089..7ab6567fa 100644 --- a/ofono/drivers/atmodem/voicecall.c +++ b/ofono/drivers/atmodem/voicecall.c @@ -264,14 +264,17 @@ static void clcc_poll_cb(gboolean ok, GAtResult *result, gpointer user_data) 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; @@ -297,8 +300,7 @@ static void generic_cb(gboolean ok, GAtResult *result, gpointer user_data) } } - 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); @@ -316,8 +318,7 @@ static void release_id_cb(gboolean ok, GAtResult *result, 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); @@ -962,8 +963,7 @@ static void no_carrier_notify(GAtResult *result, 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); } static void no_answer_notify(GAtResult *result, gpointer user_data) @@ -971,8 +971,7 @@ static void no_answer_notify(GAtResult *result, 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); } static void busy_notify(GAtResult *result, gpointer user_data) @@ -984,8 +983,7 @@ static void busy_notify(GAtResult *result, gpointer user_data) * 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) From f9045f5442c8fc390161e21b2b676e6b6ee9d37f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Tue, 20 Aug 2019 17:56:51 +0200 Subject: [PATCH 189/320] gprs: Remove prior attaching state logic Commit 1fd419e5b4b3a87673f8e0219edb0f3ed9fca774 and 0167c3339ca8f17a653592af995f439d24405de8 introduced logic that treated ofono_gprs_cid_activated as an 'attaching' state. Since gprs_attached_update now guarantees that we will not get attached without having a context activated in LTE, this is not needed anymore. It also potentially interferes in case the driver was actually attaching. --- ofono/src/gprs.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/ofono/src/gprs.c b/ofono/src/gprs.c index ddfa561b4..76d814cc2 100644 --- a/ofono/src/gprs.c +++ b/ofono/src/gprs.c @@ -1232,7 +1232,6 @@ static void pri_read_settings_callback(const struct ofono_error *error, { 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; @@ -1257,19 +1256,11 @@ static void pri_read_settings_callback(const struct ofono_error *error, 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, @@ -2456,14 +2447,6 @@ void ofono_gprs_cid_activated(struct ofono_gprs *gprs, unsigned int cid, 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); } From 00cc9b2be4b0f98a204494363d4c65b968cb51ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Mon, 2 Sep 2019 23:17:59 +0200 Subject: [PATCH 190/320] quectel: swap cmuxed ports According to the manual, when using CMUX on the UC15, it outputs unsolicited indications on port 2 (i.e. /dev/gsmtty2), so the quectel plugin must use this when registering for such. --- ofono/plugins/quectel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 24a7b7b6c..bc95d2a55 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -851,8 +851,8 @@ static void cmux_cb(gboolean ok, GAtResult *result, gpointer user_data) * 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, "Aux", "/dev/gsmtty1"); - ofono_modem_set_string(modem, "Modem", "/dev/gsmtty2"); + 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)) { From c850478633a4321f4641b12be81d501cac9f8870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Tue, 3 Sep 2019 16:06:11 +0200 Subject: [PATCH 191/320] ublox: gprs: React on context deactivation In case a context get deactivated when a AT+CGACT=0 is not issued, indicate that to gprs core. This can happen if the device has an auto activated LTE context and modem switches over to for instance UTRAN. --- ofono/drivers/ubloxmodem/gprs-context.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/ofono/drivers/ubloxmodem/gprs-context.c b/ofono/drivers/ubloxmodem/gprs-context.c index 5bc449195..b46c746e6 100644 --- a/ofono/drivers/ubloxmodem/gprs-context.c +++ b/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 @@ struct gprs_context_data { 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 @@ static void cgact_disable_cb(gboolean ok, GAtResult *result, gpointer user_data) DBG("ok %d", ok); + gcd->flags &= ~UBLOX_FLAG_DEACTIVATING; + if (!ok) { CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data); return; @@ -448,6 +453,8 @@ static void ublox_gprs_deactivate_primary(struct ofono_gprs_context *gc, 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 @@ static void cgev_notify(GAtResult *result, gpointer user_data) 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; From e1835b83eeb0794287f271c80ad5cd7905a1a498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Thu, 5 Sep 2019 11:16:55 +0200 Subject: [PATCH 192/320] atmodem: sms: don't request URC buffering for Quectel UC15 modems Add a vendor quirk to avoid an error being returned when setting up sms notification for Quectel UC15 modems. --- ofono/drivers/atmodem/sms.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ofono/drivers/atmodem/sms.c b/ofono/drivers/atmodem/sms.c index de8a28059..ee3c40239 100644 --- a/ofono/drivers/atmodem/sms.c +++ b/ofono/drivers/atmodem/sms.c @@ -843,6 +843,7 @@ static gboolean build_cnmi_string(char *buf, int *cnmi_opts, 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"; From b08e5ef48f4a503991dd2d070451490816f54c64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Thu, 5 Sep 2019 12:33:20 +0200 Subject: [PATCH 193/320] quectel: handle sim states The quectel M95 and MC60 modems are picky about when the sim is properly initialized, so the logic to detect this needs to be in the quectel plugin. After doing basic initialization, a CPIN query is issued to detect sim state. If the sim is unlocked and ready, a timer is created to wait for the modem state (AT+QINISTAT) to complete. At this point ofono is notified about the initialized sim. If the sim is locked, a listener for "+CPIN: READY" is set up to know when a pin is entered. Once the indication is received, the timer is set up as if the sim was unlocked from the beginning. If the sim is busy/resetting, the CPIN query is issued again. --- ofono/plugins/quectel.c | 336 ++++++++++++++++++++++++++++------------ 1 file changed, 237 insertions(+), 99 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index bc95d2a55..b4b9c5ed7 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -84,15 +84,22 @@ enum quectel_model { QUECTEL_MC60, }; +enum quectel_state { + QUECTEL_STATE_INITIALIZING = 0, + QUECTEL_STATE_POST_SIM, + QUECTEL_STATE_READY, + QUECTEL_STATE_INITIALIZED, +}; + 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; + enum quectel_state state; + struct ofono_sim *sim; + enum ofono_sim_state sim_state; + unsigned int sim_watch; /* used by quectel uart driver */ GAtChat *uart; @@ -187,9 +194,6 @@ static void quectel_remove(struct ofono_modem *modem) 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); @@ -529,42 +533,211 @@ static void dbus_hw_enable(struct ofono_modem *modem) 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 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); - if (!g_at_result_iter_next(&iter, "+CPIN:")) + if (!g_at_result_iter_next(&iter, "+QINISTAT:")) return; - g_at_result_iter_next_unquoted_string(&iter, &sim_inserted); + if (!g_at_result_iter_next_number(&iter, &status)) + return; - if (g_strcmp0(sim_inserted, "NOT INSERTED") != 0) - data->have_sim = true; + DBG("qinistat: %d", status); - ofono_modem_set_powered(modem, TRUE); + switch (data->model) { + case QUECTEL_UC15: + /* UC15 uses a bitmap of 1 + 2 + 4 = 7 */ + ready = 7; + break; + case QUECTEL_M95: + case QUECTEL_MC60: + /* M95 and MC60 uses a counter to 3 */ + ready = 3; + break; + case QUECTEL_UNKNOWN: + ready = 0; + break; + } - /* Turn off the radio. */ - g_at_chat_send(data->aux, "AT+CFUN=4", none_prefix, NULL, NULL, NULL); + if (status != ready) { + l_timeout_modify_ms(data->init_timeout, 500); + return; + } - g_at_chat_unregister(data->aux, data->cpin_ready); - data->cpin_ready = 0; + l_timeout_remove(data->init_timeout); + data->init_timeout = NULL; - dbus_hw_enable(modem); + if (data->sim_state == OFONO_SIM_STATE_READY) { + /* + * when initializing with a non-locked sim card, the sim atom + * isn't created until now to avoid accessing it before the + * modem is ready. + * + * call ofono_modem_set_powered() to make ofono call + * quectel_pre_sim() where the sim atom is created. + */ + ofono_modem_set_powered(modem, true); + } else { + /* + * When initialized with a locked sim card, the modem is already + * powered up, and the inserted signal has been sent to allow + * the pin to be entered. So simply update the state, and notify + * about the finished initialization below. + */ + data->sim_state = OFONO_SIM_STATE_READY; + } + + ofono_sim_initialized_notify(data->sim); + + /* + * If quectel_post_sim() has not yet been called, then postpone atom + * creation until it is called. Otherwise create the atoms now. + */ + if (data->state != QUECTEL_STATE_POST_SIM) { + data->state = QUECTEL_STATE_READY; + return; + } + + ofono_sms_create(modem, data->vendor, "atmodem", data->aux); + ofono_phonebook_create(modem, data->vendor, "atmodem", data->aux); + ofono_voicecall_create(modem, data->vendor, "atmodem", data->aux); + ofono_call_volume_create(modem, data->vendor, "atmodem", data->aux); + data->state = QUECTEL_STATE_INITIALIZED; +} + +static void init_timer_cb(struct l_timeout *timeout, void *user_data) +{ + struct ofono_modem *modem = user_data; + struct quectel_data *data = ofono_modem_get_data(modem); + + DBG("%p", modem); + + g_at_chat_send(data->aux, "AT+QINISTAT", qinistat_prefix, qinistat_cb, + modem, NULL); +} + +static void sim_watch_cb(GAtResult *result, void *user_data) +{ + struct ofono_modem *modem = user_data; + struct quectel_data *data = ofono_modem_get_data(modem); + + DBG("%p", modem); + + g_at_chat_unregister(data->aux, data->sim_watch); + data->sim_watch = 0; + + data->init_timeout = l_timeout_create_ms(500, init_timer_cb, modem, NULL); + if (!data->init_timeout) { + close_serial(modem); + return; + } +} + +static enum ofono_sim_state cme_parse(GAtResult *result) +{ + struct ofono_error error; + + decode_at_error(&error, g_at_result_final_response(result)); + + if (error.type != OFONO_ERROR_TYPE_CME) + return OFONO_SIM_STATE_RESETTING; + + switch (error.error) { + case 5: + case 6: + case 7: + case 11: + case 12: + case 17: + case 18: + return OFONO_SIM_STATE_LOCKED_OUT; + case 10: + return OFONO_SIM_STATE_NOT_PRESENT; + case 13: + case 14: + case 15: + return OFONO_SIM_STATE_RESETTING; + default: + ofono_error("unknown cpin error: %i", error.error); + return OFONO_SIM_STATE_RESETTING; + } +} + +static enum ofono_sim_state cpin_parse(GAtResult *result) +{ + GAtResultIter iter; + const char *cpin; + + g_at_result_iter_init(&iter, result); + + if (!g_at_result_iter_next(&iter, "+CPIN:")) + return OFONO_SIM_STATE_RESETTING; + + g_at_result_iter_next_unquoted_string(&iter, &cpin); + + if (g_strcmp0(cpin, "NOT INSERTED") == 0) + return OFONO_SIM_STATE_NOT_PRESENT; + + if (g_strcmp0(cpin, "READY") == 0) + return OFONO_SIM_STATE_READY; + + return OFONO_SIM_STATE_LOCKED_OUT; } static void cpin_query(gboolean ok, GAtResult *result, gpointer user_data) { - DBG("%p ok %d", user_data, ok); + struct ofono_modem *modem = user_data; + struct quectel_data *data = ofono_modem_get_data(modem); + + DBG("%p ok %i", modem, ok); if (ok) - cpin_notify(result, user_data); + data->sim_state = cpin_parse(result); + else + data->sim_state = cme_parse(result); + + /* Turn off the radio. */ + g_at_chat_send(data->aux, "AT+CFUN=4", none_prefix, NULL, NULL, NULL); + + switch (data->sim_state) { + case OFONO_SIM_STATE_LOCKED_OUT: + ofono_modem_set_powered(modem, true); + data->sim_watch = g_at_chat_register(data->aux, "+CPIN: READY", + sim_watch_cb, FALSE, + modem, NULL); + if (!data->sim_watch) { + ofono_error("failed to create sim watch"); + close_serial(modem); + return; + } + break; + case OFONO_SIM_STATE_READY: + data->init_timeout = l_timeout_create_ms(500, init_timer_cb, + modem, NULL); + if (!data->init_timeout) { + ofono_error("failed to create qinitstat timer"); + close_serial(modem); + return; + } + break; + case OFONO_SIM_STATE_RESETTING: + case OFONO_SIM_STATE_INSERTED: + g_at_chat_send(data->aux, "AT+CPIN?", cpin_prefix, cpin_query, + modem, NULL); + break; + case OFONO_SIM_STATE_NOT_PRESENT: + ofono_warn("%s: sim not present", ofono_modem_get_path(modem)); + ofono_modem_set_powered(modem, true); + } } static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data) @@ -579,8 +752,8 @@ static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data) return; } - data->cpin_ready = g_at_chat_register(data->aux, "+CPIN", cpin_notify, - FALSE, modem, NULL); + dbus_hw_enable(modem); + g_at_chat_send(data->aux, "AT+CPIN?", cpin_prefix, cpin_query, modem, NULL); } @@ -661,67 +834,6 @@ static void cgmm_cb(int ok, GAtResult *result, void *user_data) NULL); } -static void qinistat_cb(gboolean ok, GAtResult *result, gpointer user_data) -{ - struct ofono_modem *modem = user_data; - struct quectel_data *data = ofono_modem_get_data(modem); - GAtResultIter iter; - int status; - - DBG("%p", modem); - - g_at_result_iter_init(&iter, result); - - if (!g_at_result_iter_next(&iter, "+QINISTAT:")) - return; - - if (!g_at_result_iter_next_number(&iter, &status)) - return; - - DBG("qinistat: %d", status); - - if (status != 3) { - l_timeout_modify_ms(data->sms_ready_timer, 500); - return; - } - - ofono_sms_create(modem, data->vendor, "atmodem", data->aux); - l_timeout_remove(data->sms_ready_timer); - data->sms_ready_timer = NULL; -} - -static void sms_ready_cb(struct l_timeout *timeout, void *user_data) -{ - struct ofono_modem *modem = user_data; - struct quectel_data *data = ofono_modem_get_data(modem); - - DBG("%p", modem); - - g_at_chat_send(data->aux, "AT+QINISTAT", qinistat_prefix, qinistat_cb, - modem, NULL); -} - -static void call_ready_notify(GAtResult *result, void *user_data) -{ - struct ofono_modem *modem = user_data; - struct quectel_data *data = ofono_modem_get_data(modem); - - DBG("%p", modem); - - g_at_chat_unregister(data->aux, data->call_ready); - data->call_ready = 0; - data->sms_ready_timer = l_timeout_create_ms(500, sms_ready_cb, modem, - NULL); - if (!data->sms_ready_timer) { - close_serial(modem); - return; - } - - ofono_phonebook_create(modem, 0, "atmodem", data->aux); - ofono_voicecall_create(modem, 0, "atmodem", data->aux); - ofono_call_volume_create(modem, 0, "atmodem", data->aux); -} - static int open_ttys(struct ofono_modem *modem) { struct quectel_data *data = ofono_modem_get_data(modem); @@ -741,20 +853,10 @@ static int open_ttys(struct ofono_modem *modem) return -EIO; } - data->call_ready = g_at_chat_register(data->aux, "Call Ready", - call_ready_notify, false, - modem, NULL); - if (!data->call_ready) { - close_serial(modem); - return -ENOTTY; - } - g_at_chat_set_slave(data->modem, data->aux); - g_at_chat_send(data->modem, "ATE0; &C0; +CMEE=1", none_prefix, NULL, - NULL, NULL); - g_at_chat_send(data->aux, "ATE0; &C0; +CMEE=1", none_prefix, NULL, NULL, - NULL); + g_at_chat_send(data->aux, "ATE0; &C0; +CMEE=1; +QIURC=0", none_prefix, + NULL, NULL, NULL); g_at_chat_send(data->aux, "AT+CGMM", cgmm_prefix, cgmm_cb, modem, NULL); @@ -1009,6 +1111,8 @@ static int quectel_disable(struct ofono_modem *modem) g_at_chat_send(data->aux, "AT+CFUN=0", cfun_prefix, cfun_disable, modem, NULL); + data->state = QUECTEL_STATE_INITIALIZING; + return -EINPROGRESS; } @@ -1050,10 +1154,18 @@ static void quectel_pre_sim(struct ofono_modem *modem) DBG("%p", modem); ofono_devinfo_create(modem, 0, "atmodem", data->aux); - sim = ofono_sim_create(modem, data->vendor, "atmodem", data->aux); + data->sim = ofono_sim_create(modem, data->vendor, "atmodem", data->aux); + if (!data->sim) + return; - if (sim && data->have_sim == true) - ofono_sim_inserted_notify(sim, TRUE); + switch (data->sim_state) { + case OFONO_SIM_STATE_LOCKED_OUT: + case OFONO_SIM_STATE_READY: + ofono_sim_inserted_notify(data->sim, true); + break; + default: + break; + } } static void quectel_post_sim(struct ofono_modem *modem) @@ -1070,6 +1182,32 @@ static void quectel_post_sim(struct ofono_modem *modem) if (gprs && gc) ofono_gprs_add_context(gprs, gc); + + /* + * the sim related atoms must not be created until the modem is really + * ready, so check the state here + */ + switch (data->state) { + case QUECTEL_STATE_INITIALIZING: + /* + * the modem is still initializing, so postpone the atom + * creation until qinistat_cb() determines the modem is + * ready + */ + data->state = QUECTEL_STATE_POST_SIM; + return; + case QUECTEL_STATE_READY: + /* the modem is ready, so create atoms below */ + break; + default: + return; + } + + ofono_sms_create(modem, data->vendor, "atmodem", data->aux); + ofono_phonebook_create(modem, data->vendor, "atmodem", data->aux); + ofono_voicecall_create(modem, data->vendor, "atmodem", data->aux); + ofono_call_volume_create(modem, data->vendor, "atmodem", data->aux); + data->state = QUECTEL_STATE_INITIALIZED; } static void quectel_post_online(struct ofono_modem *modem) From 9f39a96958b348e9ce531b0dc98ad40c536a91fa Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Wed, 18 Sep 2019 18:23:27 +0530 Subject: [PATCH 194/320] xmm7modem: Fix to set gateway in pdp context gateway was not being listed in context settings. Fixed teh bug to show correct gateway address. --- ofono/drivers/ifxmodem/gprs-context.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ofono/drivers/ifxmodem/gprs-context.c b/ofono/drivers/ifxmodem/gprs-context.c index e17beae49..27349dc19 100644 --- a/ofono/drivers/ifxmodem/gprs-context.c +++ b/ofono/drivers/ifxmodem/gprs-context.c @@ -353,6 +353,9 @@ static void cgcontrdp_cb(gboolean ok, GAtResult *result, gpointer user_data) 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 @@ static void cgcontrdp_cb(gboolean ok, GAtResult *result, gpointer user_data) IPV6_DEFAULT_PREFIX_LEN); } - if (gw) - strncpy(gcd->gateway, gw, sizeof(gcd->gateway)); - gcd->state = STATE_ACTIVE; DBG("address: %s\n", gcd->address); From 38e406d1ce9e6174b0612c0b6f7ecb9c2d40044a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Tue, 17 Sep 2019 18:25:48 +0200 Subject: [PATCH 195/320] gprs: Only release detachable context on de-attach Currently there is an issue if the attach state changes and there are active contexts of which the driver does not implement the detach_shutdown. In that case we just release the context (clears CID and active state), but nothing is signalled on D-Bus or towards the modem. Ofono is then out of sync with both the connection manager and the modem, this manifests itself later on if the modem changes state of the context, then ofono will not find it since the CID is cleared, and the connection manager won't be notified. --- ofono/src/gprs.c | 71 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/ofono/src/gprs.c b/ofono/src/gprs.c index 76d814cc2..01401c7db 100644 --- a/ofono/src/gprs.c +++ b/ofono/src/gprs.c @@ -1898,6 +1898,27 @@ static gboolean have_active_contexts(struct ofono_gprs *gprs) 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) { @@ -1927,7 +1948,7 @@ static void pri_context_signal_active(struct pri_context *ctx) "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; @@ -1956,6 +1977,15 @@ static void release_active_contexts(struct ofono_gprs *gprs) } } +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) @@ -1966,21 +1996,27 @@ static void gprs_set_attached(struct ofono_gprs *gprs, ofono_bool_t attached) * 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); } @@ -2065,15 +2101,6 @@ static void gprs_netreg_removed(struct ofono_gprs *gprs) gprs_attached_update(gprs); } -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_netreg_update(struct ofono_gprs *gprs) { ofono_bool_t attach; From 7119679762d5fd00d6fc348fb9508a452e4eef10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Sun, 22 Sep 2019 22:53:21 +0200 Subject: [PATCH 196/320] plugins: quectel: Fix compiler warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit plugins/quectel.c: In function ‘quectel_pre_sim’: plugins/quectel.c:1150:20: error: unused variable ‘sim’ [-Werror=unused-variable] struct ofono_sim *sim; --- ofono/plugins/quectel.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index b4b9c5ed7..135989e6a 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -1149,7 +1149,6 @@ static void quectel_set_online(struct ofono_modem *modem, ofono_bool_t online, static void quectel_pre_sim(struct ofono_modem *modem) { struct quectel_data *data = ofono_modem_get_data(modem); - struct ofono_sim *sim; DBG("%p", modem); From 52ce10a41985141c21f7ab99adff4be8a1e597a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Mon, 23 Sep 2019 09:15:46 +0200 Subject: [PATCH 197/320] gprs: Do nothing on detached when attaching. Its incorrect to fiddle with the driver attach state when attaching. When attaching the state is transitioning, and the correct state will now always be assigned in the end of the attach process, regardless of result. --- ofono/src/gprs.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ofono/src/gprs.c b/ofono/src/gprs.c index 01401c7db..02f1042b1 100644 --- a/ofono/src/gprs.c +++ b/ofono/src/gprs.c @@ -3045,6 +3045,15 @@ void ofono_gprs_detached_notify(struct ofono_gprs *gprs) { 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); From ce8459c4b6e3066bafe6bba7d25dd3b36935e2d5 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Tue, 24 Sep 2019 13:33:31 +0200 Subject: [PATCH 198/320] ublox: raise call to open device --- ofono/plugins/ublox.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/ofono/plugins/ublox.c b/ofono/plugins/ublox.c index b65bc52a7..9ee38a6bd 100644 --- a/ofono/plugins/ublox.c +++ b/ofono/plugins/ublox.c @@ -102,13 +102,6 @@ static void ublox_remove(struct ofono_modem *modem) g_free(data); } -static GAtChat *open_device(struct ofono_modem *modem, - const char *key, char *debug) -{ - return at_util_open_device(modem, key, ublox_debug, debug, - NULL); -} - static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_modem *modem = user_data; @@ -236,17 +229,20 @@ static int ublox_enable(struct ofono_modem *modem) 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, From c870e4280cc7eaf2fa433a48b2287c38565ce606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Tue, 24 Sep 2019 18:11:12 +0200 Subject: [PATCH 199/320] ublox: network-registration: Check ureg for tech also for L2 modems It seems like the CREG reporting from the L2 modems are quite buggy. An example for a L210 where CREG reports UTRAN while COPS and UREG reports LTE. A manual poll also indicates LTE. I also found that the technology mapping was incorrect, probably confused with enum packet_bearer. A commented log showing where CREG is not trustable: UREG indicates LTE 21:59:29 : < \r\n+UREG: 7\r\n 21:59:29 : < \r\n+CIEV: 9,2\r\n 21:59:29 : < \r\n+CGEV: NW MODIFY 1,0,0\r\n 21:59:31 : < \r\n+CIEV: 2,2\r\n 21:59:39 : < \r\n+CIEV: 2,3\r\n 21:59:44 : < \r\n+CIEV: 2,2\r\n 22:01:38 : < \r\n+CIEV: 2,3\r\n 22:01:43 : < \r\n+CIEV: 2,2\r\n A CREG indicating UTRAN with HSDPA and HSUPA 22:29:39 : < \r\n+CREG: 5,"0000","00000000",6\r\n 22:29:39 : > AT\r 22:29:39 : < \r\nOK\r\n 22:29:39 : > AT+COPS=3,2\r 22:29:39 : < \r\n+CIEV: 9,2\r\n 22:29:39 : < \r\nOK\r\n 22:29:39 : > AT+COPS?\r An immediate cops indicating LTE 22:29:39 : < \r\n+COPS: 0,2,"24007",7\r\n 22:29:39 : < \r\nOK\r\n 22:29:39 : > AT+CSQ\r 22:29:39 : < \r\n+CIEV: 2,4\r\n 22:29:39 : < \r\n+CSQ: 26,4\r\n 22:29:39 : < \r\nOK\r\n 22:29:39 : > AT+CGATT=1\r 22:29:39 : < \r\nOK\r\n 22:29:39 : > AT+COPS=3,0\r 22:29:39 : < \r\nOK\r\n 22:29:39 : > AT+COPS?\r Another cops also indicates LTE 22:29:39 : < \r\n+COPS: 0,0,"Tele2",7\r\n <- 7: LTE 22:29:39 : < \r\nOK\r\n 22:29:39 : > AT+CGREG?\r CGREG indicates unknown -> normal on LTE 22:29:39 : < \r\n+CGREG: 2,4\r\n 22:29:39 : < \r\nOK\r\n 22:29:44 : < \r\n+CIEV: 9,2\r\n 22:29:46 : < \r\n+CIEV: 2,2\r\n 22:56:23 : < \r\n+CIEV: 2,3\r\n 22:56:28 : < \r\n+CIEV: 2,2\r\n 22:59:40 : < \r\n+CIEV: 2,4\r\n Manual poll shows we are running LTE at+creg? +CREG: 2,5,"2AFC","01DB0206",7 OK --- .../drivers/ubloxmodem/network-registration.c | 34 +++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/ofono/drivers/ubloxmodem/network-registration.c b/ofono/drivers/ubloxmodem/network-registration.c index 64ef8076b..69af46447 100644 --- a/ofono/drivers/ubloxmodem/network-registration.c +++ b/ofono/drivers/ubloxmodem/network-registration.c @@ -58,6 +58,7 @@ struct tech_query { int status; int lac; int ci; + int tech; struct ofono_netreg *netreg; }; @@ -235,20 +236,40 @@ static void ublox_query_tech_cb(gboolean ok, GAtResult *result, return; switch (state) { + case 0: + /* Not registered for PS, then we have to trust CREG... */ + tech = tq->tech; + break; + case 1: + tech = ACCESS_TECHNOLOGY_GSM; + break; + case 2: + tech = ACCESS_TECHNOLOGY_GSM_EGPRS; + break; + case 3: + tech = ACCESS_TECHNOLOGY_UTRAN; + break; case 4: - tech = 5; + tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA; break; case 5: - tech = 4; + tech = ACCESS_TECHNOLOGY_UTRAN_HSUPA; + break; + case 6: + tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA_HSUPA; + break; + case 7: + tech = ACCESS_TECHNOLOGY_EUTRAN; break; case 8: - tech = 1; + tech = ACCESS_TECHNOLOGY_GSM; break; case 9: - tech = 2; + tech = ACCESS_TECHNOLOGY_GSM_EGPRS; break; default: - tech = state; + /* Not registered for PS or something unknown, trust CREG... */ + tech = tq->tech; } error: @@ -270,12 +291,13 @@ static void creg_notify(GAtResult *result, gpointer user_data) if (status != 1 && status != 5) 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; tq->netreg = netreg; if (g_at_chat_send(nd->at_data.chat, "AT+UREG?", ureg_prefix, From 7715ad7b513393d419711c0c6764e9b6364f5db7 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Wed, 25 Sep 2019 06:35:05 +0200 Subject: [PATCH 200/320] ublox: consolidate teardown in common function The code for closing all the modem devices and flagging the modem as unpowered is repeated several times in the driver... this patch puts this code into a common helper for readability. --- ofono/plugins/ublox.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/ofono/plugins/ublox.c b/ofono/plugins/ublox.c index 9ee38a6bd..60a734ce9 100644 --- a/ofono/plugins/ublox.c +++ b/ofono/plugins/ublox.c @@ -102,19 +102,25 @@ static void ublox_remove(struct ofono_modem *modem) g_free(data); } +static void close_devices(struct ofono_modem* modem) +{ + 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; } @@ -165,11 +171,7 @@ static void query_usbconf_cb(gboolean ok, 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) @@ -216,11 +218,7 @@ static void query_model_cb(gboolean ok, GAtResult *result, gpointer user_data) 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 int ublox_enable(struct ofono_modem *modem) From b60197c977d3517a867ded3818ad33bc0d775461 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Wed, 25 Sep 2019 06:35:06 +0200 Subject: [PATCH 201/320] ublox: use common close_devices when modem disabled Just reshuffling the code a bit and the 'disable' path can use the close_devices() helper to finish up. This also prevents a bug should the CFUN command fail to disable the modem whereby the 'aux' device remains open but the 'modem' device has already been closed. --- ofono/plugins/ublox.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/ofono/plugins/ublox.c b/ofono/plugins/ublox.c index 60a734ce9..22350462e 100644 --- a/ofono/plugins/ublox.c +++ b/ofono/plugins/ublox.c @@ -269,15 +269,15 @@ static int ublox_enable(struct ofono_modem *modem) static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_modem *modem = user_data; - struct ublox_data *data = ofono_modem_get_data(modem); DBG(""); - g_at_chat_unref(data->aux); - data->aux = NULL; + if (!ok) { + ofono_error("Failed to disable modem"); + return; + } - if (ok) - ofono_modem_set_powered(modem, FALSE); + close_devices(modem); } static int ublox_disable(struct ofono_modem *modem) @@ -288,8 +288,6 @@ static int ublox_disable(struct ofono_modem *modem) g_at_chat_cancel_all(data->modem); g_at_chat_unregister_all(data->modem); - g_at_chat_unref(data->modem); - data->modem = NULL; g_at_chat_cancel_all(data->aux); g_at_chat_unregister_all(data->aux); From 8134a0230820e2ccc694ea8fbdee5c450416e4af Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Wed, 25 Sep 2019 06:35:07 +0200 Subject: [PATCH 202/320] ublox: rework device initialization sequence uBlox devices present their USB interfaces well before those interfaces are ready to respond to any commands. The documentation says to monitor the 'greeting text' to detect readiness, but this 'greeting text' is not actually specified for any device other than the TOBY L4. What seems to work is to probe the device with 'AT' commands until the device responds, and then to wait an additional second before proceeding. The TOBY L4 reliably sends its 'greeting text' (+AT: READY) within this interval. It would be more rigorous to actually wait for the 'READY' indication for the TOBY L4, but that would require knowing the device model before the device model is actually queried. This is doable via the USB product ID, but overkill when the above heuristic seems to work reliably. Before this patch, the ublox plugin was trying to achieve something like the above with the g_at_chat_set_wakeup_command() function, but that had some issues: i) it did not work reliably, in particular failing badly on the TOBY L4 with responses getting out of sync with commands ii) it was an inappropriate use of the wakeup_command which is intended for devices that may sleep when there is no communication during some interval This patch adds an init sequence that probes the device for readiness before continuing with initialization. --- ofono/plugins/ublox.c | 113 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 99 insertions(+), 14 deletions(-) diff --git a/ofono/plugins/ublox.c b/ofono/plugins/ublox.c index 22350462e..efcd40cff 100644 --- a/ofono/plugins/ublox.c +++ b/ofono/plugins/ublox.c @@ -29,6 +29,7 @@ #include #include #include +#include #define OFONO_API_SUBJECT_TO_CHANGE #include @@ -66,6 +67,10 @@ struct ublox_data { 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) @@ -221,6 +226,72 @@ static void query_model_cb(gboolean ok, GAtResult *result, gpointer user_data) 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) { struct ublox_data *data = ofono_modem_get_data(modem); @@ -248,22 +319,34 @@ static int ublox_enable(struct ofono_modem *modem) 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. + * + * (It would be more rigorous to actually wait for the 'READY' + * indication, but that would require knowing the device model + * before the device model is actually queried. Do-able via + * USB Product ID, but overkill when the above seems to work + * reliably.) + */ - g_at_chat_unref(data->aux); - data->aux = NULL; + data->init_count = 0; + data->init_cmd = g_at_chat_send(data->aux, "AT", none_prefix, + init_cmd_cb, modem, NULL); + data->init_timeout = l_timeout_create_ms(500, init_timeout_cb, modem, + NULL); - return -EINVAL; + return -EINPROGRESS; } static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data) @@ -286,6 +369,8 @@ static int ublox_disable(struct ofono_modem *modem) DBG("%p", modem); + l_timeout_remove(data->init_timeout); + g_at_chat_cancel_all(data->modem); g_at_chat_unregister_all(data->modem); From 447d6d6c479d9be5668f133cdb1fd96e963d0124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Thu, 26 Sep 2019 21:45:00 +0200 Subject: [PATCH 203/320] gprs: free interface name in gprs_context_remove() --- ofono/src/gprs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ofono/src/gprs.c b/ofono/src/gprs.c index 02f1042b1..fd86f71da 100644 --- a/ofono/src/gprs.c +++ b/ofono/src/gprs.c @@ -3277,6 +3277,7 @@ static void gprs_context_remove(struct ofono_atom *atom) if (gc->gprs) __ofono_gprs_filter_chain_cancel(gc->gprs->filters, gc); + g_free(gc->interface); g_free(gc); } From b6636ac7024ffb0ba308af336e36ca5b49ef4ae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Thu, 26 Sep 2019 21:27:22 +0200 Subject: [PATCH 204/320] atmodem: sim: remove quectel serial vendor quirk The sim inserted/initialized state is handled properly in the quectel plugin now, so remove the "auto-initialized" quirk from the atmodem sim driver. --- ofono/drivers/atmodem/sim.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ofono/drivers/atmodem/sim.c b/ofono/drivers/atmodem/sim.c index dd42cac43..e750a1399 100644 --- a/ofono/drivers/atmodem/sim.c +++ b/ofono/drivers/atmodem/sim.c @@ -1354,7 +1354,6 @@ static void at_pin_send_cb(gboolean ok, GAtResult *result, 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 From 6c6eff688984e288ca8d5f8a8d3c9745fb98481b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Thu, 26 Sep 2019 21:27:23 +0200 Subject: [PATCH 205/320] quectel: remove leftover reset of wakeup command --- ofono/plugins/quectel.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 135989e6a..30b205afd 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -970,7 +970,6 @@ static void ate_cb(int ok, GAtResult *result, void *user_data) DBG("%p", modem); - g_at_chat_set_wakeup_command(data->uart, NULL, 0, 0); g_at_chat_send(data->uart, "AT+CMUX=0,0,5,127,10,3,30,10,2", NULL, cmux_cb, modem, NULL); } From bcc0e323c78c8162ba6fb8a46858f01ac47778d7 Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Fri, 27 Sep 2019 11:21:20 +0530 Subject: [PATCH 206/320] udev: Adding PCIe as a subsystem in udev Adding support for enumerating PCIe types of modems in ofono --- ofono/plugins/udevng.c | 178 +++++++++++++++++++++++++++++++---------- 1 file changed, 135 insertions(+), 43 deletions(-) diff --git a/ofono/plugins/udevng.c b/ofono/plugins/udevng.c index 928881da7..2e211e20c 100644 --- a/ofono/plugins/udevng.c +++ b/ofono/plugins/udevng.c @@ -41,6 +41,7 @@ enum modem_type { MODEM_TYPE_USB, MODEM_TYPE_SERIAL, + MODEM_TYPE_PCIE, }; struct modem_info { @@ -1228,26 +1229,47 @@ static gboolean setup_xmm7xxx(struct modem_info *modem) 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/"); } } @@ -1265,9 +1287,6 @@ static gboolean setup_xmm7xxx(struct modem_info *modem) 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; } @@ -1436,6 +1455,7 @@ static void destroy_modem(gpointer data) 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; @@ -1466,6 +1486,7 @@ static gboolean check_remove(gpointer key, gpointer value, gpointer user_data) 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; @@ -1598,7 +1619,8 @@ static void add_serial_device(struct udev_device *dev) 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; @@ -1611,25 +1633,13 @@ static void add_device(const char *syspath, const char *devname, 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); @@ -1641,8 +1651,37 @@ static void add_device(const char *syspath, const char *devname, 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) { @@ -1656,11 +1695,6 @@ static void add_device(const char *syspath, const char *devname, } } - 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); if (modem->sysattr != NULL) @@ -1854,9 +1888,64 @@ static void check_usb_device(struct udev_device *device) return; } - add_device(syspath, devname, driver, vendor, model, device); + add_device(syspath, devname, driver, vendor, model, device, + MODEM_TYPE_USB); } +static const struct { + const char *driver; + const char *drv; + const char *vid; + const char *pid; +} pci_driver_list[] = { + { "xmm7xxx", "imc_ipc", "0x8086", "0x7560"}, + { } +}; + +static void check_pci_device(struct udev_device *device) +{ + const char *syspath, *devname, *driver; + const char *vendor = NULL, *model = NULL, *drv = NULL; + unsigned int i; + + syspath = udev_device_get_syspath(device); + + if (syspath == NULL) + return; + + devname = udev_device_get_devnode(device); + vendor = udev_device_get_sysattr_value(device, "vendor"); + model = udev_device_get_sysattr_value(device, "device"); + driver = udev_device_get_property_value(device, "OFONO_DRIVER"); + drv = udev_device_get_property_value(device, "DRIVER"); + DBG("%s [%s:%s]", drv, vendor, model); + + if (vendor == NULL || model == NULL || drv == NULL) + return; + + for (i = 0; pci_driver_list[i].driver; i++) { + if (g_str_equal(pci_driver_list[i].drv, drv) == FALSE) + continue; + + if (pci_driver_list[i].vid) { + if (!g_str_equal(pci_driver_list[i].vid, vendor)) + continue; + } + + if (pci_driver_list[i].pid) { + if (!g_str_equal(pci_driver_list[i].pid, model)) + continue; + } + + driver = pci_driver_list[i].driver; + } + + if (driver == NULL) + return; + + add_device(syspath, devname, driver, vendor, model, device, + MODEM_TYPE_PCIE); +} static void check_device(struct udev_device *device) { const char *bus; @@ -1871,6 +1960,8 @@ static void check_device(struct udev_device *device) if ((g_str_equal(bus, "usb") == TRUE) || (g_str_equal(bus, "usbmisc") == TRUE)) check_usb_device(device); + else if (g_str_equal(bus, "pci") == TRUE) + check_pci_device(device); else add_serial_device(device); @@ -1931,6 +2022,7 @@ static void enumerate_devices(struct udev *context) udev_enumerate_add_match_subsystem(enumerate, "usbmisc"); udev_enumerate_add_match_subsystem(enumerate, "net"); udev_enumerate_add_match_subsystem(enumerate, "hsi"); + udev_enumerate_add_match_subsystem(enumerate, "pci"); udev_enumerate_scan_devices(enumerate); From 6fc72be290c224d6f49a9a0846759039502040b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Fri, 27 Sep 2019 07:22:47 +0200 Subject: [PATCH 207/320] ublox: netreg: Also subscribe to UREG URC's It turns out that both L2xx and L4xx modems are a bit buggy when it comes to send CREG URC's when the tech changes. Try to overcome this by subscribing to both UREG and CREG, and poll the other when any of the URC's are received. Protect from doing simultaneous polls though. --- .../drivers/ubloxmodem/network-registration.c | 205 +++++++++++++----- 1 file changed, 154 insertions(+), 51 deletions(-) diff --git a/ofono/drivers/ubloxmodem/network-registration.c b/ofono/drivers/ubloxmodem/network-registration.c index 69af46447..25f239a60 100644 --- a/ofono/drivers/ubloxmodem/network-registration.c +++ b/ofono/drivers/ubloxmodem/network-registration.c @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -47,11 +48,13 @@ 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 { @@ -213,13 +216,75 @@ static void ctze_notify(GAtResult *result, gpointer user_data) 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; @@ -235,60 +300,67 @@ static void ublox_query_tech_cb(gboolean ok, GAtResult *result, if (!g_at_result_iter_next_number(&iter, &state)) return; - switch (state) { - case 0: - /* Not registered for PS, then we have to trust CREG... */ + tech = ublox_ureg_state_to_tech(state); + if (tech < 0) + /* No valid UREG status, we have to trust CREG... */ tech = tq->tech; - break; - case 1: - tech = ACCESS_TECHNOLOGY_GSM; - break; - case 2: - tech = ACCESS_TECHNOLOGY_GSM_EGPRS; - break; - case 3: - tech = ACCESS_TECHNOLOGY_UTRAN; - break; - case 4: - tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA; - break; - case 5: - tech = ACCESS_TECHNOLOGY_UTRAN_HSUPA; - break; - case 6: - tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA_HSUPA; - break; - case 7: - tech = ACCESS_TECHNOLOGY_EUTRAN; - break; - case 8: - tech = ACCESS_TECHNOLOGY_GSM; - break; - case 9: - tech = ACCESS_TECHNOLOGY_GSM_EGPRS; - break; - default: - /* Not registered for PS or something unknown, 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) || ublox_is_toby_l2(nd->model)) { @@ -301,13 +373,15 @@ static void creg_notify(GAtResult *result, gpointer user_data) tq->netreg = netreg; if (g_at_chat_send(nd->at_data.chat, "AT+UREG?", ureg_prefix, - ublox_query_tech_cb, tq, g_free) > 0) + ublox_ureg_cb, tq, g_free) > 0) { + nd->updating_status = true; return; + } g_free(tq); } - if ((status == 1 || status == 5) && tech == -1) + if (tech == -1) tech = nd->at_data.tech; notify: @@ -322,24 +396,56 @@ static void at_cmer_not_supported(struct ofono_netreg *netreg) ofono_netreg_remove(netreg); } +static void ublox_finish_registration(struct ofono_netreg *netreg) +{ + struct netreg_data *nd = ofono_netreg_get_data(netreg); + + if (ublox_is_toby_l4(nd->model) || ublox_is_toby_l2(nd->model)) + g_at_chat_register(nd->at_data.chat, "+UREG:", + ureg_notify, FALSE, netreg, NULL); + + g_at_chat_register(nd->at_data.chat, "+CIEV:", + ciev_notify, FALSE, netreg, NULL); + + g_at_chat_register(nd->at_data.chat, "+CREG:", + creg_notify, FALSE, netreg, NULL); + + ofono_netreg_register(netreg); +} + +static void ublox_ureg_set_cb(gboolean ok, + GAtResult *result, gpointer user_data) +{ + struct ofono_netreg *netreg = user_data; + + if (!ok) { + ofono_error("Unable to initialize Network Registration"); + ofono_netreg_remove(netreg); + return; + } + + ublox_finish_registration(netreg); +} + static void ublox_cmer_set_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_netreg *netreg = user_data; - struct at_netreg_data *nd = ofono_netreg_get_data(netreg); + struct netreg_data *nd = ofono_netreg_get_data(netreg); if (!ok) { at_cmer_not_supported(netreg); return; } - g_at_chat_register(nd->chat, "+CIEV:", - ciev_notify, FALSE, netreg, NULL); + if (ublox_is_toby_l4(nd->model) || ublox_is_toby_l2(nd->model)) { + g_at_chat_send(nd->at_data.chat, "AT+UREG=1", none_prefix, + ublox_ureg_set_cb, netreg, NULL); - g_at_chat_register(nd->chat, "+CREG:", - creg_notify, FALSE, netreg, NULL); + return; + } - ofono_netreg_register(netreg); + ublox_finish_registration(netreg); } static void ublox_creg_set_cb(gboolean ok, @@ -354,12 +460,9 @@ static void ublox_creg_set_cb(gboolean ok, return; } - if (ublox_is_toby_l4(nd->model)) { + if (ublox_is_toby_l4(nd->model)) /* FIXME */ ofono_error("TOBY L4 requires polling of ECSQ"); - ofono_error("TOBY L4 wants UREG notifications for" - " tech updates"); - } /* Register for network time update reports */ if (ublox_is_toby_l2(nd->model)) { From 14b2b5504ce825d08b4f5a670a7b972d87ce7b06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Tue, 8 Oct 2019 20:44:40 +0200 Subject: [PATCH 208/320] gatmux: take reference to mux object while processing incoming data When closing down a cmux object, the address sanitizer detects a use-after-free in gatmux.c (see below). Avoid this by taking a reference to the mux object during the processing in received_data(). ofonod[3640549]: ../git/plugins/quectel.c:cfun_disable() 0x610000000b40 ofonod[3640549]: ../git/plugins/quectel.c:close_serial() 0x610000000b40 ofonod[3640549]: ../git/plugins/quectel.c:close_mux() 0x610000000b40 ofonod[3640549]: ../git/examples/emulator.c:powered_watch() Removing modem 0x610000000b40 from the list ofonod[3640549]: ../git/examples/emulator.c:powered_watch() Removing server watch: 106 ofonod[3640549]: ../git/src/modem.c:modem_change_state() old state: 0, new state: 0 ================================================================= ==3640549==ERROR: AddressSanitizer: heap-use-after-free on address 0x62100073dd28 at pc 0x5566b6402a21 bp 0x7ffe7a2db0e0 sp 0x7ffe7a2db0d0 READ of size 8 at 0x62100073dd28 thread T0 #0 0x5566b6402a20 in debug ../git/gatchat/gatmux.c:109 #1 0x5566b6404bd7 in channel_close ../git/gatchat/gatmux.c:525 #2 0x7fa0516e44a6 in g_io_channel_shutdown (/usr/lib/libglib-2.0.so.0+0x774a6) #3 0x7fa0516e4644 in g_io_channel_unref (/usr/lib/libglib-2.0.so.0+0x77644) #4 0x5566b64048a4 in watch_finalize ../git/gatchat/gatmux.c:474 #5 0x7fa0516d6f6f (/usr/lib/libglib-2.0.so.0+0x69f6f) #6 0x7fa0516ac6a7 in g_slist_foreach (/usr/lib/libglib-2.0.so.0+0x3f6a7) #7 0x7fa0516b277b in g_slist_free_full (/usr/lib/libglib-2.0.so.0+0x4577b) #8 0x5566b6403413 in dispatch_sources ../git/gatchat/gatmux.c:224 #9 0x5566b64039ea in received_data ../git/gatchat/gatmux.c:268 #10 0x7fa0516d727e in g_main_context_dispatch (/usr/lib/libglib-2.0.so.0+0x6a27e) #11 0x7fa0516d91c0 (/usr/lib/libglib-2.0.so.0+0x6c1c0) #12 0x7fa0516da0d2 in g_main_loop_run (/usr/lib/libglib-2.0.so.0+0x6d0d2) #13 0x5566b6429b1b in main ../git/src/main.c:286 #14 0x7fa05147fee2 in __libc_start_main (/usr/lib/libc.so.6+0x26ee2) #15 0x5566b62531ad in _start (/home/martin/projects/ofono/x86/src/ofonod+0xfc1ad) 0x62100073dd28 is located 40 bytes inside of 4672-byte region [0x62100073dd00,0x62100073ef40) freed by thread T0 here: #0 0x7fa0519256c0 in __interceptor_free /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:122 #1 0x5566b64052d7 in g_at_mux_unref ../git/gatchat/gatmux.c:645 #2 0x5566b63d6d19 in close_mux ../git/plugins/quectel.c:199 #3 0x5566b63d7047 in close_serial ../git/plugins/quectel.c:223 #4 0x5566b63db62a in cfun_disable ../git/plugins/quectel.c:1056 #5 0x5566b63f6ae1 in at_chat_finish_command ../git/gatchat/gatchat.c:459 #6 0x5566b63f701b in at_chat_handle_command_response ../git/gatchat/gatchat.c:521 #7 0x5566b63f785b in have_line ../git/gatchat/gatchat.c:600 #8 0x5566b63f87f1 in new_bytes ../git/gatchat/gatchat.c:759 #9 0x5566b640174c in received_data ../git/gatchat/gatio.c:122 #10 0x5566b64047b4 in watch_dispatch ../git/gatchat/gatmux.c:464 #11 0x5566b640313b in dispatch_sources ../git/gatchat/gatmux.c:183 #12 0x5566b64039ea in received_data ../git/gatchat/gatmux.c:268 #13 0x7fa0516d727e in g_main_context_dispatch (/usr/lib/libglib-2.0.so.0+0x6a27e) previously allocated by thread T0 here: #0 0x7fa051925ce8 in __interceptor_calloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:153 #1 0x5566b6405009 in g_at_mux_new ../git/gatchat/gatmux.c:606 #2 0x5566b6407f6b in g_at_mux_new_gsm0710_basic ../git/gatchat/gatmux.c:1165 #3 0x5566b63da9ba in cmux_cb ../git/plugins/quectel.c:882 #4 0x5566b63f6ae1 in at_chat_finish_command ../git/gatchat/gatchat.c:459 #5 0x5566b63f701b in at_chat_handle_command_response ../git/gatchat/gatchat.c:521 #6 0x5566b63f785b in have_line ../git/gatchat/gatchat.c:600 #7 0x5566b63f87f1 in new_bytes ../git/gatchat/gatchat.c:759 #8 0x5566b640174c in received_data ../git/gatchat/gatio.c:122 #9 0x7fa0516d727e in g_main_context_dispatch (/usr/lib/libglib-2.0.so.0+0x6a27e) SUMMARY: AddressSanitizer: heap-use-after-free ../git/gatchat/gatmux.c:109 in debug Shadow bytes around the buggy address: 0x0c42800dfb50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c42800dfb60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c42800dfb70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c42800dfb80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c42800dfb90: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa =>0x0c42800dfba0: fd fd fd fd fd[fd]fd fd fd fd fd fd fd fd fd fd 0x0c42800dfbb0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c42800dfbc0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c42800dfbd0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c42800dfbe0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c42800dfbf0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb Shadow gap: cc ==3640549==ABORTING --- ofono/gatchat/gatmux.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ofono/gatchat/gatmux.c b/ofono/gatchat/gatmux.c index 757a5123a..d50e53610 100644 --- a/ofono/gatchat/gatmux.c +++ b/ofono/gatchat/gatmux.c @@ -231,6 +231,7 @@ static gboolean received_data(GIOChannel *channel, GIOCondition cond, int i; GIOStatus status; gsize bytes_read; + gboolean buffer_full = FALSE; if (cond & G_IO_NVAL) return FALSE; @@ -255,6 +256,8 @@ static gboolean received_data(GIOChannel *channel, GIOCondition cond, 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 @@ static gboolean received_data(GIOChannel *channel, GIOCondition cond, 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 @@ static gboolean received_data(GIOChannel *channel, GIOCondition cond, 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; From 49f7c6e0642252f26b390f52d80f4a4d339f2505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Tue, 8 Oct 2019 20:44:41 +0200 Subject: [PATCH 209/320] gatmux: disable destroy notification on read watcher With the reference in place in received_data(), the address sanitizer now encounters a use-after-free when the destroy notification is dispatched for the read watcher (see below). Fix this by remove the destroy notification callback, as it isn't really used except in the shutdown function. ==5797==ERROR: AddressSanitizer: heap-use-after-free on address 0x621000ac5904 at pc 0x55c1243b1f14 bp 0x7ffdef001340 sp 0x7ffdef001330 WRITE of size 4 at 0x621000ac5904 thread T0 #0 0x55c1243b1f13 in read_watcher_destroy_notify ../git/gatchat/gatmux.c:660 #1 0x7f08a8676742 (/usr/lib/libglib-2.0.so.0+0x62742) #2 0x7f08a867e2e4 in g_main_context_dispatch (/usr/lib/libglib-2.0.so.0+0x6a2e4) #3 0x7f08a8680210 (/usr/lib/libglib-2.0.so.0+0x6c210) #4 0x7f08a8681122 in g_main_loop_run (/usr/lib/libglib-2.0.so.0+0x6d122) #5 0x55c1243d6703 in main ../git/src/main.c:286 #6 0x7f08a8423152 in __libc_start_main (/usr/lib/libc.so.6+0x27152) #7 0x55c1241fe1ad in _start (/home/martin/projects/ofono/x86/src/ofonod+0xfd1ad) 0x621000ac5904 is located 4 bytes inside of 4672-byte region [0x621000ac5900,0x621000ac6b40) freed by thread T0 here: #0 0x7f08a88cc6b0 in __interceptor_free /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:122 #1 0x55c1243b1ebf in g_at_mux_unref ../git/gatchat/gatmux.c:652 #2 0x55c1243b062c in received_data ../git/gatchat/gatmux.c:276 #3 0x7f08a867e2ce in g_main_context_dispatch (/usr/lib/libglib-2.0.so.0+0x6a2ce) previously allocated by thread T0 here: #0 0x7f08a88cccd8 in __interceptor_calloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:153 #1 0x55c1243b1bf1 in g_at_mux_new ../git/gatchat/gatmux.c:613 #2 0x55c1243b4b53 in g_at_mux_new_gsm0710_basic ../git/gatchat/gatmux.c:1172 #3 0x55c124386abd in cmux_gatmux ../git/plugins/quectel.c:871 #4 0x55c12438779f in cmux_cb ../git/plugins/quectel.c:1023 #5 0x55c1243a368e in at_chat_finish_command ../git/gatchat/gatchat.c:459 #6 0x55c1243a3bc8 in at_chat_handle_command_response ../git/gatchat/gatchat.c:521 #7 0x55c1243a4408 in have_line ../git/gatchat/gatchat.c:600 #8 0x55c1243a539e in new_bytes ../git/gatchat/gatchat.c:759 #9 0x55c1243ae2f9 in received_data ../git/gatchat/gatio.c:122 #10 0x7f08a867e2ce in g_main_context_dispatch (/usr/lib/libglib-2.0.so.0+0x6a2ce) SUMMARY: AddressSanitizer: heap-use-after-free ../git/gatchat/gatmux.c:660 in read_watcher_destroy_notify Shadow bytes around the buggy address: 0x0c4280150ad0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c4280150ae0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c4280150af0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c4280150b00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c4280150b10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa =>0x0c4280150b20:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c4280150b30: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c4280150b40: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c4280150b50: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c4280150b60: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c4280150b70: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb Shadow gap: cc ==5797==ABORTING --- ofono/gatchat/gatmux.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/ofono/gatchat/gatmux.c b/ofono/gatchat/gatmux.c index d50e53610..4d89f0398 100644 --- a/ofono/gatchat/gatmux.c +++ b/ofono/gatchat/gatmux.c @@ -653,13 +653,6 @@ void g_at_mux_unref(GAtMux *mux) } } -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) @@ -673,8 +666,7 @@ gboolean g_at_mux_start(GAtMux *mux) 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; @@ -691,8 +683,10 @@ gboolean g_at_mux_shutdown(GAtMux *mux) 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); From 02c14f217f23e39410db7b2d0ab1b8fbb7a14768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Mon, 7 Oct 2019 23:39:58 +0200 Subject: [PATCH 210/320] quectel: rework sim detection Use at_util_sim_state_query_new() to query the sim inserted state. Once that returns, the locked state is queried by issuing a AT+CPIN? command. If not locked, a timer is started to query the quectel init status of the sim. Once the init status is ready, the sim atom is created, and the modem is set to powered, and the sim is signaled both inserted, and initialized. If locked, the modem is set to powered, and the sim atom is created. This allows users to enter the pin to unlock the sim. Once the sim is unlocked, a +CPIN: READY indication is caught to query the quectel init status. Once the init status is ready, the sim is signaled initialized. All the above is needed, because the modem indicated +CPIN: READY before the sim is really ready. The only way to be certain, is to wait for the quectel init status to be ready. Even signaling the sim inserted prematurely can cause to modem to hang during the initial AT+CRSM commands. --- ofono/plugins/quectel.c | 255 +++++++++++++++------------------------- 1 file changed, 94 insertions(+), 161 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 30b205afd..86a066ee6 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -84,22 +84,15 @@ enum quectel_model { QUECTEL_MC60, }; -enum quectel_state { - QUECTEL_STATE_INITIALIZING = 0, - QUECTEL_STATE_POST_SIM, - QUECTEL_STATE_READY, - QUECTEL_STATE_INITIALIZED, -}; - struct quectel_data { GAtChat *modem; GAtChat *aux; enum ofono_vendor vendor; enum quectel_model model; - enum quectel_state state; - struct ofono_sim *sim; - enum ofono_sim_state sim_state; + struct at_util_sim_state_query *sim_state_query; unsigned int sim_watch; + bool sim_locked; + bool sim_ready; /* used by quectel uart driver */ GAtChat *uart; @@ -197,6 +190,7 @@ static void quectel_remove(struct ofono_modem *modem) 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); @@ -240,6 +234,9 @@ static void close_serial(struct ofono_modem *modem) 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; @@ -536,6 +533,7 @@ static void dbus_hw_enable(struct ofono_modem *modem) 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); GAtResultIter iter; int ready = 0; @@ -576,42 +574,13 @@ static void qinistat_cb(gboolean ok, GAtResult *result, gpointer user_data) l_timeout_remove(data->init_timeout); data->init_timeout = NULL; - if (data->sim_state == OFONO_SIM_STATE_READY) { - /* - * when initializing with a non-locked sim card, the sim atom - * isn't created until now to avoid accessing it before the - * modem is ready. - * - * call ofono_modem_set_powered() to make ofono call - * quectel_pre_sim() where the sim atom is created. - */ - ofono_modem_set_powered(modem, true); - } else { - /* - * When initialized with a locked sim card, the modem is already - * powered up, and the inserted signal has been sent to allow - * the pin to be entered. So simply update the state, and notify - * about the finished initialization below. - */ - data->sim_state = OFONO_SIM_STATE_READY; - } - - ofono_sim_initialized_notify(data->sim); - - /* - * If quectel_post_sim() has not yet been called, then postpone atom - * creation until it is called. Otherwise create the atoms now. - */ - if (data->state != QUECTEL_STATE_POST_SIM) { - data->state = QUECTEL_STATE_READY; + if (data->sim_locked) { + ofono_sim_initialized_notify(sim); return; } - ofono_sms_create(modem, data->vendor, "atmodem", data->aux); - ofono_phonebook_create(modem, data->vendor, "atmodem", data->aux); - ofono_voicecall_create(modem, data->vendor, "atmodem", data->aux); - ofono_call_volume_create(modem, data->vendor, "atmodem", data->aux); - data->state = QUECTEL_STATE_INITIALIZED; + data->sim_ready = true; + ofono_modem_set_powered(modem, TRUE); } static void init_timer_cb(struct l_timeout *timeout, void *user_data) @@ -629,118 +598,94 @@ static void sim_watch_cb(GAtResult *result, void *user_data) { struct ofono_modem *modem = user_data; struct quectel_data *data = ofono_modem_get_data(modem); + GAtResultIter iter; + const char *cpin; DBG("%p", modem); - g_at_chat_unregister(data->aux, data->sim_watch); - data->sim_watch = 0; + g_at_result_iter_init(&iter, result); - data->init_timeout = l_timeout_create_ms(500, init_timer_cb, modem, NULL); - if (!data->init_timeout) { - close_serial(modem); + if (!g_at_result_iter_next(&iter, "+CPIN:")) return; - } -} -static enum ofono_sim_state cme_parse(GAtResult *result) -{ - struct ofono_error error; + g_at_result_iter_next_unquoted_string(&iter, &cpin); - decode_at_error(&error, g_at_result_final_response(result)); + if (g_strcmp0(cpin, "READY") != 0) + return; - if (error.type != OFONO_ERROR_TYPE_CME) - return OFONO_SIM_STATE_RESETTING; - - switch (error.error) { - case 5: - case 6: - case 7: - case 11: - case 12: - case 17: - case 18: - return OFONO_SIM_STATE_LOCKED_OUT; - case 10: - return OFONO_SIM_STATE_NOT_PRESENT; - case 13: - case 14: - case 15: - return OFONO_SIM_STATE_RESETTING; - default: - ofono_error("unknown cpin error: %i", error.error); - return OFONO_SIM_STATE_RESETTING; - } + g_at_chat_unregister(data->aux, data->sim_watch); + data->sim_watch = 0; + + data->init_timeout = l_timeout_create_ms(500, init_timer_cb, modem, NULL); } -static enum ofono_sim_state cpin_parse(GAtResult *result) +static void cpin_cb(gboolean ok, GAtResult *result, gpointer user_data) { + struct ofono_modem *modem = user_data; + struct quectel_data *data = ofono_modem_get_data(modem); + const char *path = ofono_modem_get_path(modem); GAtResultIter iter; const char *cpin; + DBG("%p", modem); + + if (!ok) { + close_serial(modem); + return; + } + g_at_result_iter_init(&iter, result); - if (!g_at_result_iter_next(&iter, "+CPIN:")) - return OFONO_SIM_STATE_RESETTING; + if (!g_at_result_iter_next(&iter, "+CPIN:")) { + close_serial(modem); + return; + } g_at_result_iter_next_unquoted_string(&iter, &cpin); - if (g_strcmp0(cpin, "NOT INSERTED") == 0) - return OFONO_SIM_STATE_NOT_PRESENT; + if (g_strcmp0(cpin, "READY") == 0) { + data->init_timeout = l_timeout_create_ms(500, init_timer_cb, + modem, NULL); + return; + } - if (g_strcmp0(cpin, "READY") == 0) - return OFONO_SIM_STATE_READY; + if (g_strcmp0(cpin, "SIM PIN") != 0) { + close_serial(modem); + return; + } - return OFONO_SIM_STATE_LOCKED_OUT; + ofono_info("%s: sim locked", path); + data->sim_locked = true; + data->sim_watch = g_at_chat_register(data->aux, "+CPIN:", + sim_watch_cb, FALSE, + modem, NULL); + ofono_modem_set_powered(modem, TRUE); } -static void cpin_query(gboolean ok, GAtResult *result, gpointer user_data) +static void sim_state_cb(gboolean present, gpointer user_data) { struct ofono_modem *modem = user_data; struct quectel_data *data = ofono_modem_get_data(modem); + const char *path = ofono_modem_get_path(modem); - DBG("%p ok %i", modem, ok); + DBG("%p present %d", modem, present); - if (ok) - data->sim_state = cpin_parse(result); - else - data->sim_state = cme_parse(result); - - /* Turn off the radio. */ - g_at_chat_send(data->aux, "AT+CFUN=4", none_prefix, NULL, NULL, NULL); - - switch (data->sim_state) { - case OFONO_SIM_STATE_LOCKED_OUT: - ofono_modem_set_powered(modem, true); - data->sim_watch = g_at_chat_register(data->aux, "+CPIN: READY", - sim_watch_cb, FALSE, - modem, NULL); - if (!data->sim_watch) { - ofono_error("failed to create sim watch"); - close_serial(modem); - return; - } - break; - case OFONO_SIM_STATE_READY: - data->init_timeout = l_timeout_create_ms(500, init_timer_cb, - modem, NULL); - if (!data->init_timeout) { - ofono_error("failed to create qinitstat timer"); - close_serial(modem); - return; - } - break; - case OFONO_SIM_STATE_RESETTING: - case OFONO_SIM_STATE_INSERTED: - g_at_chat_send(data->aux, "AT+CPIN?", cpin_prefix, cpin_query, - modem, NULL); - break; - case OFONO_SIM_STATE_NOT_PRESENT: - ofono_warn("%s: sim not present", ofono_modem_get_path(modem)); - ofono_modem_set_powered(modem, true); + at_util_sim_state_query_free(data->sim_state_query); + data->sim_state_query = NULL; + data->sim_locked = false; + data->sim_ready = false; + + if (!present) { + ofono_modem_set_powered(modem, TRUE); + ofono_warn("%s: sim not present", path); + return; } + + g_at_chat_send(data->aux, "AT+CPIN?", cpin_prefix, cpin_cb, modem, + NULL); } -static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data) +static void cfun_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_modem *modem = user_data; struct quectel_data *data = ofono_modem_get_data(modem); @@ -753,8 +698,24 @@ static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data) } dbus_hw_enable(modem); + data->sim_state_query = at_util_sim_state_query_new(data->aux, + 2, 20, sim_state_cb, modem, + NULL); +} + +static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data) +{ + struct ofono_modem *modem = user_data; + struct quectel_data *data = ofono_modem_get_data(modem); - g_at_chat_send(data->aux, "AT+CPIN?", cpin_prefix, cpin_query, modem, + DBG("%p ok %d", modem, ok); + + if (!ok) { + close_serial(modem); + return; + } + + g_at_chat_send(data->aux, "AT+CFUN=4", none_prefix, cfun_cb, modem, NULL); } @@ -1110,8 +1071,6 @@ static int quectel_disable(struct ofono_modem *modem) g_at_chat_send(data->aux, "AT+CFUN=0", cfun_prefix, cfun_disable, modem, NULL); - data->state = QUECTEL_STATE_INITIALIZING; - return -EINPROGRESS; } @@ -1148,22 +1107,18 @@ static void quectel_set_online(struct ofono_modem *modem, ofono_bool_t online, static void quectel_pre_sim(struct ofono_modem *modem) { struct quectel_data *data = ofono_modem_get_data(modem); + struct ofono_sim *sim; DBG("%p", modem); - ofono_devinfo_create(modem, 0, "atmodem", data->aux); - data->sim = ofono_sim_create(modem, data->vendor, "atmodem", data->aux); - if (!data->sim) - return; + ofono_voicecall_create(modem, data->vendor, "atmodem", data->aux); + sim = ofono_sim_create(modem, data->vendor, "atmodem", data->aux); - switch (data->sim_state) { - case OFONO_SIM_STATE_LOCKED_OUT: - case OFONO_SIM_STATE_READY: - ofono_sim_inserted_notify(data->sim, true); - break; - default: - break; - } + if (data->sim_locked || data->sim_ready) + ofono_sim_inserted_notify(sim, true); + + if (data->sim_ready) + ofono_sim_initialized_notify(sim); } static void quectel_post_sim(struct ofono_modem *modem) @@ -1181,31 +1136,9 @@ static void quectel_post_sim(struct ofono_modem *modem) if (gprs && gc) ofono_gprs_add_context(gprs, gc); - /* - * the sim related atoms must not be created until the modem is really - * ready, so check the state here - */ - switch (data->state) { - case QUECTEL_STATE_INITIALIZING: - /* - * the modem is still initializing, so postpone the atom - * creation until qinistat_cb() determines the modem is - * ready - */ - data->state = QUECTEL_STATE_POST_SIM; - return; - case QUECTEL_STATE_READY: - /* the modem is ready, so create atoms below */ - break; - default: - return; - } - ofono_sms_create(modem, data->vendor, "atmodem", data->aux); ofono_phonebook_create(modem, data->vendor, "atmodem", data->aux); - ofono_voicecall_create(modem, data->vendor, "atmodem", data->aux); ofono_call_volume_create(modem, data->vendor, "atmodem", data->aux); - data->state = QUECTEL_STATE_INITIALIZED; } static void quectel_post_online(struct ofono_modem *modem) From e289a47876394980b032b3b3b5cbb9b7c56c02b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Mon, 7 Oct 2019 23:39:59 +0200 Subject: [PATCH 211/320] quectel: support both internal and n_gsm muxes The in-kernel implementation of gsm0710 causes deadlocks in the kernel[1], so switch the default back to the user-space implementation in ofono. The change also removes the timeout-callback used to defer disabling the n_gsm line discipline, as that is no longer needed[2] To enable use of the kernel line discipline, add an udev env entry with OFONO_QUECTEL_MUX="n_gsm". [1] https://lore.kernel.org/lkml/4b2455c0-25ba-0187-6df6-c63b4ccc6a6e@geanix.com/ [2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7030082a7415d18e3befdf1f9ec05b3d5de98de4 --- ofono/plugins/quectel.c | 203 +++++++++++++++++++++++++++++++--------- 1 file changed, 161 insertions(+), 42 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 86a066ee6..80beb921d 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -36,6 +36,7 @@ #include #include #include +#include #define OFONO_API_SUBJECT_TO_CHANGE #include @@ -95,7 +96,9 @@ struct quectel_data { 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; @@ -194,43 +197,48 @@ static void quectel_remove(struct ofono_modem *modem) 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); @@ -243,19 +251,16 @@ static void close_serial(struct ofono_modem *modem) 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) @@ -795,6 +800,19 @@ static void cgmm_cb(int ok, GAtResult *result, void *user_data) NULL); } +static void setup_aux(struct ofono_modem *modem) +{ + struct quectel_data *data = ofono_modem_get_data(modem); + + DBG("%p", modem); + + g_at_chat_set_slave(data->modem, data->aux); + g_at_chat_send(data->aux, "ATE0; &C0; +CMEE=1; +QIURC=0", none_prefix, + NULL, NULL, NULL); + g_at_chat_send(data->aux, "AT+CGMM", cgmm_prefix, cgmm_cb, modem, + NULL); +} + static int open_ttys(struct ofono_modem *modem) { struct quectel_data *data = ofono_modem_get_data(modem); @@ -814,16 +832,73 @@ static int open_ttys(struct ofono_modem *modem) return -EIO; } - g_at_chat_set_slave(data->modem, data->aux); - - g_at_chat_send(data->aux, "ATE0; &C0; +CMEE=1; +QIURC=0", none_prefix, - NULL, NULL, NULL); - g_at_chat_send(data->aux, "AT+CGMM", cgmm_prefix, cgmm_cb, modem, - NULL); + setup_aux(modem); return -EINPROGRESS; } +static GAtChat *create_chat(struct ofono_modem *modem, char *debug) +{ + struct quectel_data *data = ofono_modem_get_data(modem); + GIOChannel *channel; + GAtSyntax *syntax; + GAtChat *chat; + + DBG("%p", modem); + + channel = g_at_mux_create_channel(data->mux); + if (channel == NULL) + return NULL; + + syntax = g_at_syntax_new_gsmv1(); + chat = g_at_chat_new(channel, syntax); + g_at_syntax_unref(syntax); + g_io_channel_unref(channel); + + if (chat == NULL) + return NULL; + + if (getenv("OFONO_AT_DEBUG")) + g_at_chat_set_debug(chat, quectel_debug, debug); + + return chat; +} + +static void cmux_gatmux(struct ofono_modem *modem) +{ + struct quectel_data *data = ofono_modem_get_data(modem); + + DBG("%p", modem); + + data->mux = g_at_mux_new_gsm0710_basic(data->device, 127); + if (data->mux == NULL) { + ofono_error("failed to create gsm0710 mux"); + close_serial(modem); + return; + } + + if (getenv("OFONO_MUX_DEBUG")) + g_at_mux_set_debug(data->mux, quectel_debug, "Mux: "); + + 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; + } + + data->aux = create_chat(modem, "Aux: "); + if (!data->aux) { + ofono_error("failed to create aux channel"); + close_serial(modem); + return; + } + + setup_aux(modem); +} + static void mux_ready_cb(struct l_timeout *timeout, void *user_data) { struct ofono_modem *modem = user_data; @@ -856,19 +931,16 @@ static void mux_ready_cb(struct l_timeout *timeout, void *user_data) g_at_chat_set_slave(data->uart, data->modem); } -static void cmux_cb(gboolean ok, GAtResult *result, gpointer user_data) +static void cmux_ngsm(struct ofono_modem *modem) { - struct ofono_modem *modem = user_data; struct quectel_data *data = ofono_modem_get_data(modem); struct gsm_config gsm_config; - GIOChannel *device; int ldisc = N_GSM0710; int fd; DBG("%p", modem); - device = g_at_chat_get_channel(data->uart); - fd = g_io_channel_unix_get_fd(device); + fd = g_io_channel_unix_get_fd(data->device); /* get initial line discipline to restore after use */ if (ioctl(fd, TIOCGETD, &data->initial_ldisc) < 0) { @@ -924,6 +996,39 @@ static void cmux_cb(gboolean ok, GAtResult *result, gpointer user_data) } } +static void cmux_cb(gboolean ok, GAtResult *result, gpointer user_data) +{ + struct ofono_modem *modem = user_data; + struct quectel_data *data = ofono_modem_get_data(modem); + const char *mux = ofono_modem_get_string(modem, "Mux"); + + DBG("%p", modem); + + g_at_chat_unref(data->uart); + data->uart = NULL; + + if (!ok) { + close_serial(modem); + return; + } + + if (!mux) + mux = "internal"; + + if (strcmp(mux, "n_gsm") == 0) { + cmux_ngsm(modem); + return; + } + + if (strcmp(mux, "internal") == 0) { + cmux_gatmux(modem); + return; + } + + ofono_error("unsupported mux setting: '%s'", mux); + close_serial(modem); +} + static void ate_cb(int ok, GAtResult *result, void *user_data) { struct ofono_modem *modem = user_data; @@ -981,6 +1086,8 @@ static int open_serial(struct ofono_modem *modem) struct quectel_data *data = ofono_modem_get_data(modem); const uint32_t gpio_value = 1; const char *rts_cts; + ssize_t written; + int fd; DBG("%p", modem); @@ -1000,6 +1107,18 @@ static int open_serial(struct ofono_modem *modem) if (data->uart == NULL) return -EINVAL; + data->device = g_at_chat_get_channel(data->uart); + g_io_channel_ref(data->device); + + /* + * terminate gsm 0710 multiplexing on the modem side to make sure it + * responds to plain AT commands + * */ + fd = g_io_channel_unix_get_fd(data->device); + written = write(fd, gsm0710_terminate, sizeof(gsm0710_terminate)); + if (written != sizeof(gsm0710_terminate)) + ofono_warn("Failed to terminate gsm multiplexing"); + if (data->gpio && !l_gpio_writer_set(data->gpio, 1, &gpio_value)) { close_serial(modem); return -EIO; From 0e791e7182c2b9d2bc2de29ab570ccf000c7ff57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Mon, 7 Oct 2019 23:39:59 +0200 Subject: [PATCH 212/320] udevng: Support quectel MUX settings --- ofono/plugins/udevng.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ofono/plugins/udevng.c b/ofono/plugins/udevng.c index 2e211e20c..25593c6a9 100644 --- a/ofono/plugins/udevng.c +++ b/ofono/plugins/udevng.c @@ -893,6 +893,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_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"); From fac77040cc7c6dbc1deb9727464ec571ddebbe4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Fri, 11 Oct 2019 12:29:17 -0500 Subject: [PATCH 213/320] gprs: update attached on netreg updates when running LTE There was a race condition where a context might be registered before the netreg status updates to LTE. The code took for granted the context is activated after the technology update. With this change, any order is is accepted. --- ofono/src/gprs.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ofono/src/gprs.c b/ofono/src/gprs.c index fd86f71da..e7e9c1ed2 100644 --- a/ofono/src/gprs.c +++ b/ofono/src/gprs.c @@ -2129,13 +2129,19 @@ static void gprs_netreg_update(struct ofono_gprs *gprs) * context activation if Attached stays FALSE. */ #ifdef SAILFISH_OS - if (on_lte(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; From aed4bb908015e58bdd50e4f9160e8022c27a68d3 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 31 Oct 2019 08:38:47 +0100 Subject: [PATCH 214/320] huawei: Increase string buffer to avoid overflow --- ofono/drivers/huaweimodem/gprs-context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/drivers/huaweimodem/gprs-context.c b/ofono/drivers/huaweimodem/gprs-context.c index 7e72ad922..de07b055d 100644 --- a/ofono/drivers/huaweimodem/gprs-context.c +++ b/ofono/drivers/huaweimodem/gprs-context.c @@ -255,7 +255,7 @@ static void huawei_gprs_activate_primary(struct ofono_gprs_context *gc, { 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) From caa9c5197d7f7fba7cb325e6b1410bf3ac482d65 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 31 Oct 2019 08:58:24 +0100 Subject: [PATCH 215/320] Release 1.31 --- ofono/ChangeLog | 5 +++++ ofono/configure.ac | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ofono/ChangeLog b/ofono/ChangeLog index 283f3b5b2..0fc32a86d 100644 --- a/ofono/ChangeLog +++ b/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. diff --git a/ofono/configure.ac b/ofono/configure.ac index 05efb3503..3b0d6c550 100644 --- a/ofono/configure.ac +++ b/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) From 4cc8f871af236b4372a891d00212ae9da917c062 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Wed, 13 Nov 2019 15:34:46 -0600 Subject: [PATCH 216/320] log: Remove dead code --- ofono/src/log.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/ofono/src/log.c b/ofono/src/log.c index a58472114..4d0f1c8f8 100644 --- a/ofono/src/log.c +++ b/ofono/src/log.c @@ -329,20 +329,11 @@ void __ofono_log_enable(struct ofono_debug_desc *start, struct ofono_debug_desc *stop) { struct ofono_debug_desc *desc; - const char *name = NULL, *file = NULL; if (start == NULL || stop == NULL) return; for (desc = start; desc < stop; desc++) { - if (file != NULL || name != NULL) { - if (g_strcmp0(desc->file, file) == 0) { - if (desc->name == NULL) - desc->name = name; - } else - file = NULL; - } - if (is_enabled(desc) && !(desc->flags & OFONO_DEBUG_FLAG_PRINT)) { desc->flags |= OFONO_DEBUG_FLAG_PRINT; From eb155e6d971500b8737d815ac14fe82d20d3df5b Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Wed, 13 Nov 2019 15:48:14 -0600 Subject: [PATCH 217/320] gprs: Remove pointless check name is declared as an array, so the check will always evaluate to true --- ofono/src/gprs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/src/gprs.c b/ofono/src/gprs.c index e7e9c1ed2..ee6e2513d 100644 --- a/ofono/src/gprs.c +++ b/ofono/src/gprs.c @@ -1423,7 +1423,7 @@ static DBusMessage *pri_set_name(struct pri_context *ctx, DBusConnection *conn, if (strlen(name) > MAX_CONTEXT_NAME_LENGTH) return __ofono_error_invalid_format(msg); - if (ctx->name && g_str_equal(ctx->name, name)) + if (g_str_equal(ctx->name, name)) return dbus_message_new_method_return(msg); strcpy(ctx->name, name); From 0c34e3dcc9a38998914fbc2a77ec8b0ce875852a Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Wed, 13 Nov 2019 16:26:37 -0600 Subject: [PATCH 218/320] mbim: Don't copy too much _mbim_message_build doesn't really care about the fragmentation header contents, so just don't copy those unnecessarily. --- ofono/drivers/mbimmodem/mbim-message.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/drivers/mbimmodem/mbim-message.c b/ofono/drivers/mbimmodem/mbim-message.c index cd392c703..25e998b37 100644 --- a/ofono/drivers/mbimmodem/mbim-message.c +++ b/ofono/drivers/mbimmodem/mbim-message.c @@ -711,7 +711,7 @@ struct mbim_message *_mbim_message_build(const void *header, msg = l_new(struct mbim_message, 1); msg->ref_count = 1; - memcpy(msg->header, header, HEADER_SIZE); + memcpy(msg->header, header, sizeof(struct mbim_message_header)); msg->frags = frags; msg->n_frags = n_frags; msg->sealed = true; From e10cbdfb3d74435ba16ae15b7acba3d157b65701 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Wed, 13 Nov 2019 16:46:07 -0600 Subject: [PATCH 219/320] gatchat: Make sure to set out length for omitted hexstrings --- ofono/gatchat/gatresult.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ofono/gatchat/gatresult.c b/ofono/gatchat/gatresult.c index 883b4105f..1f9e2a68b 100644 --- a/ofono/gatchat/gatresult.c +++ b/ofono/gatchat/gatresult.c @@ -231,6 +231,7 @@ gboolean g_at_result_iter_next_hexstring(GAtResultIter *iter, if (line[pos] == ',') { end = pos; iter->buf[pos] = '\0'; + *length = 0; goto out; } From 76430350f726a4562bd690210d6b3531610b3d00 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Wed, 13 Nov 2019 16:51:26 -0600 Subject: [PATCH 220/320] xmm7xxx: Remove unreachable statement --- ofono/plugins/xmm7xxx.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/ofono/plugins/xmm7xxx.c b/ofono/plugins/xmm7xxx.c index a544798aa..32c024eb6 100644 --- a/ofono/plugins/xmm7xxx.c +++ b/ofono/plugins/xmm7xxx.c @@ -570,8 +570,6 @@ static DBusMessage *coex_set_property(DBusConnection *conn, } else { return __ofono_error_invalid_args(msg); } - - return dbus_message_new_method_return(msg); } static void coex_default_agent_notify(gpointer user_data) From 12c0b6a99e4a4b3f0a2d9adc6bcdba29352c3f43 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Wed, 13 Nov 2019 16:53:36 -0600 Subject: [PATCH 221/320] atutil: Add missing va_end --- ofono/drivers/atmodem/atutil.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ofono/drivers/atmodem/atutil.c b/ofono/drivers/atmodem/atutil.c index 073f86b31..477ac2f98 100644 --- a/ofono/drivers/atmodem/atutil.c +++ b/ofono/drivers/atmodem/atutil.c @@ -767,6 +767,7 @@ GAtChat *at_util_open_device(struct ofono_modem *modem, const char *key, g_hash_table_insert(options, tty_option, value); tty_option = (gpointer) va_arg(args, const char *); } + va_end(args); } channel = g_at_tty_open(device, options); From 66477fea01f90a760833bf024005d988c03f583c Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sun, 17 Nov 2019 22:03:24 +0000 Subject: [PATCH 222/320] test: make all files executable This sets the executable bit on the only two files in the test directory that do not already have it set. --- ofono/test/set-sms-alphabet | 0 ofono/test/test-serving-cell-info | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 ofono/test/set-sms-alphabet mode change 100644 => 100755 ofono/test/test-serving-cell-info diff --git a/ofono/test/set-sms-alphabet b/ofono/test/set-sms-alphabet old mode 100644 new mode 100755 diff --git a/ofono/test/test-serving-cell-info b/ofono/test/test-serving-cell-info old mode 100644 new mode 100755 From cd41bc794652e4ae10a06b42352b74ebb52919d1 Mon Sep 17 00:00:00 2001 From: Jimmy Gysens Date: Tue, 19 Nov 2019 10:53:20 +0000 Subject: [PATCH 223/320] huawei: Fix infinite loop on modem removal After unplugging a Huawei USB dongle, the 'atoms' in oFono are removed via 'flush_atoms'. Every atom has a destruct function pointer, used as destructor. This includes the gprs_context atom that is currently active. The function calls are: flush_atoms -> destruct -> gprs_context_remove -> at_gprs_context_remove -> modem_disconnect Because the device is physically removed, the IO channel for the AT port is gone. In 'at_gprs_context_remove', there is an attempt to resume communication over that AT port, but that is not possible. This is detected, and 'io_disconnect' (pointer to 'modem_disconnect') is called. 'modem_disconnect' has the same atom and tries to remove it again, so it calls the same destructor. This continues infinitely. This patch moves the GPRS context removal so that it only happens if the modem port could be re-opened successfully. If the port cannot be re-opened (in the case of modem removal), the atom is already in the process of being removed by the process kicked off in flush_atoms. This fix is limited to Huawei devices and has been tested using the following devices: - E3531i-2 - E3372 - E3531s-2 - E369 - E1552 --- ofono/plugins/huawei.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ofono/plugins/huawei.c b/ofono/plugins/huawei.c index bdf7bc397..bb8767018 100644 --- a/ofono/plugins/huawei.c +++ b/ofono/plugins/huawei.c @@ -583,9 +583,6 @@ static void modem_disconnect(gpointer user_data) g_at_chat_unref(data->modem); data->modem = NULL; - /* close gprs context driver */ - ofono_gprs_context_remove(data->gc); - /* reopen modem channel */ data->modem = open_device(modem, "Modem", "Modem: "); @@ -594,6 +591,10 @@ static void modem_disconnect(gpointer user_data) return; } + /* close previous gprs context driver */ + if (data->gc) + ofono_gprs_context_remove(data->gc); + /* configure modem channel */ g_at_chat_set_disconnect_function(data->modem, modem_disconnect, modem); g_at_chat_set_slave(data->modem, data->pcui); From cdd329f195979838b2f2fb8709b6b62517550d8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Wed, 11 Dec 2019 20:13:17 +0100 Subject: [PATCH 224/320] gprs: Update attach state on context deactivation for LTE To be considered attached on LTE a context should be activated. But in case the context got deactivated we did not update the attached state, it remained attached. That caused the connection manager to try to re-activate the context manually, but for LTE thats done automatically. In the case of ublox it returns errors, which is passed on to the connection manager, which tries again and again, until we get attached again. It looked like this: 12:03:18 ofonod[547]: Aux: < \r\n+CIEV: 2,3\r\n 12:03:23 ofonod[547]: Aux: < \r\n+CIEV: 2,2\r\n Deactivated 12:16:01 ofonod[547]: Aux: < \r\n+CGEV: NW PDN DEACT 4\r\n 12:16:01 ofonod[547]: drivers/ubloxmodem/gprs-context.c:cgev_notify() cid 4, active cid: 4 12:16:01 ofonod[547]: src/gprs.c:ofono_gprs_context_deactivated() 0x1743e50 0x17424a8 4 Connection manager now try to activate, over and over again because Attached remains TRUE 12:16:01 ofonod[547]: drivers/ubloxmodem/gprs-context.c:ublox_gprs_activate_primary() cid 1 12:16:01 ofonod[547]: Aux: > AT+CGDCONT=1,"IP","apn"\r 12:16:01 ofonod[547]: Aux: < \r\nOK\r\n 12:16:01 ofonod[547]: drivers/ubloxmodem/gprs-context.c:cgdcont_cb() ok 1 12:16:01 ofonod[547]: Aux: > AT+CGACT=1,1\r 12:16:01 ofonod[547]: Aux: < \r\n+CME ERROR: 30\r\n 12:16:01 ofonod[547]: drivers/ubloxmodem/gprs-context.c:cgact_enable_cb() ok 0 12:16:01 ofonod[547]: src/gprs.c:pri_activate_callback() 0x17475c0 12:16:01 ofonod[547]: src/gprs.c:pri_activate_callback() Activating context failed with error: No network service 12:16:01 ofonod[547]: drivers/ubloxmodem/gprs-context.c:ublox_gprs_activate_primary() cid 1 12:16:02 ofonod[547]: Aux: > AT+CGDCONT=1,"IP","apn"\r 12:16:02 ofonod[547]: Aux: < \r\nOK\r\n 12:16:02 ofonod[547]: drivers/ubloxmodem/gprs-context.c:cgdcont_cb() ok 1 12:16:02 ofonod[547]: Aux: > AT+CGACT=1,1\r 12:16:02 ofonod[547]: Aux: < \r\n+CME ERROR: 30\r\n 12:16:02 ofonod[547]: drivers/ubloxmodem/gprs-context.c:cgact_enable_cb() ok 0 12:16:02 ofonod[547]: src/gprs.c:pri_activate_callback() 0x17475c0 12:16:02 ofonod[547]: src/gprs.c:pri_activate_callback() Activating context failed with error: No network service . . . 12:16:14 ofonod[547]: drivers/ubloxmodem/gprs-context.c:ublox_gprs_activate_primary() cid 1 12:16:14 ofonod[547]: Aux: > AT+CGDCONT=1,"IP","apn"\r 12:16:14 ofonod[547]: Aux: < \r\nOK\r\n 12:16:14 ofonod[547]: drivers/ubloxmodem/gprs-context.c:cgdcont_cb() ok 1 12:16:14 ofonod[547]: Aux: > AT+CGACT=1,1\r 12:16:14 ofonod[547]: Aux: < \r\n+CME ERROR: 30\r\n 12:16:14 ofonod[547]: drivers/ubloxmodem/gprs-context.c:cgact_enable_cb() ok 0 12:16:14 ofonod[547]: src/gprs.c:pri_activate_callback() 0x17475c0 12:16:14 ofonod[547]: src/gprs.c:pri_activate_callback() Activating context failed with error: No network service 12:16:14 ofonod[547]: drivers/ubloxmodem/gprs-context.c:ublox_gprs_activate_primary() cid 1 12:16:14 ofonod[547]: Aux: > AT+CGDCONT=1,"IP","apn"\r 12:16:14 ofonod[547]: Aux: < \r\nOK\r\n 12:16:14 ofonod[547]: drivers/ubloxmodem/gprs-context.c:cgdcont_cb() ok 1 12:16:14 ofonod[547]: Aux: > AT+CGACT=1,1\r The context got activated again 12:16:14 ofonod[547]: Aux: < \r\n+CGEV: ME PDN ACT 4\r\n\r\n+CIEV: 9,2\r\n\r\n+CTZE: +04,0,"19/12/11,13:17:58"\r\n 12:16:14 ofonod[547]: drivers/ubloxmodem/network-registration.c:ctze_notify() tz +04 dst 0 time 19/12/11,13:17:58 12:16:14 ofonod[547]: src/network.c:ofono_netreg_time_notify() net time 2019-12-11 13:17:58 utcoff 3600 dst 0 12:16:14 ofonod[547]: Aux: < \r\n+CME ERROR: 100\r\n 12:16:14 ofonod[547]: drivers/ubloxmodem/gprs-context.c:cgact_enable_cb() ok 0 12:16:14 ofonod[547]: src/gprs.c:pri_activate_callback() 0x17475c0 12:16:14 ofonod[547]: src/gprs.c:pri_activate_callback() Activating context failed with error: Unknown error --- ofono/src/gprs.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/ofono/src/gprs.c b/ofono/src/gprs.c index ee6e2513d..96f770400 100644 --- a/ofono/src/gprs.c +++ b/ofono/src/gprs.c @@ -3211,14 +3211,15 @@ void ofono_gprs_context_deactivated(struct ofono_gprs_context *gc, unsigned int cid) { DBusConnection *conn = ofono_dbus_get_connection(); + struct ofono_gprs *gprs = gc->gprs; GSList *l; struct pri_context *ctx; dbus_bool_t value; - if (gc->gprs == NULL) + if (gprs == NULL) return; - for (l = gc->gprs->contexts; l; l = l->next) { + for (l = gprs->contexts; l; l = l->next) { ctx = l->data; if (ctx->context.cid != cid) @@ -3240,10 +3241,13 @@ void ofono_gprs_context_deactivated(struct ofono_gprs_context *gc, * If "Attached" property was about to be signalled as TRUE but there * were still active contexts, try again to signal "Attached" property * to registered applications after active contexts have been released. + * + * "Attached" could also change to FALSE in case of LTE and getting + * deactivated */ - if (gc->gprs->flags & GPRS_FLAG_ATTACHED_UPDATE) { - gc->gprs->flags &= ~GPRS_FLAG_ATTACHED_UPDATE; - gprs_attached_update(gc->gprs); + if (on_lte(gprs) || gprs->flags & GPRS_FLAG_ATTACHED_UPDATE) { + gprs->flags &= ~GPRS_FLAG_ATTACHED_UPDATE; + gprs_attached_update(gprs); } } From 7d0afcb90a319be70b4ecb7e100f09daa1d4c482 Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Thu, 19 Dec 2019 18:26:04 +0530 Subject: [PATCH 225/320] xmm7xxx: modified handling of XSIM states for xmm modems +XSIM:7 state as defined in xmm7560 functional AT specification only indicates ready for attach. +CPIN: READY is received after SIM is completely initialized. Also indicating readiness of Phonebook and SMS. Hence moving the creation of SMS and Phonebook atom to xmm7xxx_post_sim function. +XSIM:4 PUK needed state was not handled. It must be handled same as PIN needed state. Added handling of this case to switch_sim_state_status function. --- ofono/plugins/xmm7xxx.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/ofono/plugins/xmm7xxx.c b/ofono/plugins/xmm7xxx.c index 32c024eb6..b3aaf8526 100644 --- a/ofono/plugins/xmm7xxx.c +++ b/ofono/plugins/xmm7xxx.c @@ -106,8 +106,8 @@ struct xmm7xxx_data { GAtChat *chat; /* AT chat */ struct ofono_sim *sim; ofono_bool_t have_sim; - ofono_bool_t sms_phonebook_added; unsigned int netreg_watch; + int xsim_status; }; /* Coex Implementation */ @@ -980,10 +980,10 @@ static void switch_sim_state_status(struct ofono_modem *modem, int status) if (data->have_sim == TRUE) { ofono_sim_inserted_notify(data->sim, FALSE); data->have_sim = FALSE; - data->sms_phonebook_added = FALSE; } break; case 1: /* SIM inserted, PIN verification needed */ + case 4: /* SIM inserted, PUK verification needed */ if (data->have_sim == FALSE) { ofono_sim_inserted_notify(data->sim, TRUE); data->have_sim = TRUE; @@ -991,30 +991,26 @@ static void switch_sim_state_status(struct ofono_modem *modem, int status) break; case 2: /* SIM inserted, PIN verification not needed - READY */ case 3: /* SIM inserted, PIN verified - READY */ - case 7: /* SIM inserted, SMS and phonebook - READY */ + case 7: /* SIM inserted, Ready for ATTACH - READY */ if (data->have_sim == FALSE) { ofono_sim_inserted_notify(data->sim, TRUE); data->have_sim = TRUE; } ofono_sim_initialized_notify(data->sim); - - if (data->sms_phonebook_added == FALSE) { - ofono_phonebook_create(modem, 0, "atmodem", data->chat); - ofono_sms_create(modem, 0, "atmodem", data->chat); - data->sms_phonebook_added = TRUE; - } - break; default: ofono_warn("Unknown SIM state %d received", status); break; } + + data->xsim_status = status; } static void xsimstate_notify(GAtResult *result, gpointer user_data) { struct ofono_modem *modem = user_data; + struct xmm7xxx_data *data = ofono_modem_get_data(modem); int status; GAtResultIter iter; @@ -1029,7 +1025,8 @@ static void xsimstate_notify(GAtResult *result, gpointer user_data) DBG("status=%d\n", status); - switch_sim_state_status(modem, status); + if (data->xsim_status != status) + switch_sim_state_status(modem, status); } static void xsimstate_query_cb(gboolean ok, GAtResult *result, @@ -1083,7 +1080,7 @@ static void cfun_enable_cb(gboolean ok, GAtResult *result, gpointer user_data) g_at_chat_send(data->chat, "AT&C0", NULL, NULL, NULL, NULL); data->have_sim = FALSE; - data->sms_phonebook_added = FALSE; + data->xsim_status = -1; ofono_modem_set_powered(modem, TRUE); @@ -1239,6 +1236,9 @@ static void xmm7xxx_post_online(struct ofono_modem *modem) DBG("%p", modem); + ofono_phonebook_create(modem, 0, "atmodem", data->chat); + ofono_sms_create(modem, 0, "atmodem", data->chat); + ofono_netreg_create(modem, OFONO_VENDOR_IFX, "atmodem", data->chat); gprs = ofono_gprs_create(modem, OFONO_VENDOR_IFX, "atmodem", From 796ea56afa4cd826ed8f2aeb5e42ea1f6085b7eb Mon Sep 17 00:00:00 2001 From: Antara Borwankar Date: Thu, 19 Dec 2019 18:27:49 +0530 Subject: [PATCH 226/320] sim: handling crash in error scenario for SIM PIN query In case of error in sim_pin_query_cb function. pin_type is set to -1. This is causing segmentation fault in function sim_passwd_name due to invalid index pin_type = -1. Fixing this issue by handling error case before calling sim_passwd_name function. --- ofono/src/sim.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ofono/src/sim.c b/ofono/src/sim.c index 32562d0ab..b3c7708a6 100644 --- a/ofono/src/sim.c +++ b/ofono/src/sim.c @@ -3368,7 +3368,7 @@ static void sim_pin_query_cb(const struct ofono_error *error, DBusConnection *conn = ofono_dbus_get_connection(); const char *path = __ofono_atom_get_path(sim->atom); struct cached_pin *cpins = pin_cache_lookup(sim->iccid); - const char *pin_name = sim_passwd_name(pin_type); + const char *pin_name; char **locked_pins; gboolean lock_changed; @@ -3379,6 +3379,8 @@ static void sim_pin_query_cb(const struct ofono_error *error, return; } + pin_name = sim_passwd_name(pin_type); + if (sim->pin_type != pin_type) { sim->pin_type = pin_type; From e6aa85e02f6e62e4f9506768e5b85c00d6b3b861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Fri, 7 Feb 2020 10:49:10 -0600 Subject: [PATCH 227/320] Instead of implementing an own copy of requesting and parsing CREG, reuse the existing one from at-modem. --- .../drivers/ubloxmodem/network-registration.c | 40 ++++++++----------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/ofono/drivers/ubloxmodem/network-registration.c b/ofono/drivers/ubloxmodem/network-registration.c index 25f239a60..6a524f478 100644 --- a/ofono/drivers/ubloxmodem/network-registration.c +++ b/ofono/drivers/ubloxmodem/network-registration.c @@ -48,7 +48,6 @@ 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; @@ -249,30 +248,28 @@ static gboolean is_registered(int status) status == NETWORK_REGISTRATION_STATUS_ROAMING; } -static void ublox_creg_cb(gboolean ok, GAtResult *result, - gpointer user_data) +static void registration_status_cb(const struct ofono_error *error, + int status, int lac, int ci, int tech, + void *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; + struct ofono_netreg *netreg = tq->netreg; /* 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); + g_free(tq); + + nd->updating_status = false; + + if (error->type != OFONO_ERROR_TYPE_NO_ERROR) { + DBG("Error during registration status query"); + return; + } + + ofono_netreg_status_notify(netreg, status, lac, ci, tech); } static void ublox_ureg_cb(gboolean ok, GAtResult *result, @@ -334,13 +331,8 @@ static void ureg_notify(GAtResult *result, gpointer user_data) 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); + nd->updating_status = true; + at_registration_status(netreg, registration_status_cb, tq); } static void creg_notify(GAtResult *result, gpointer user_data) From dfc3e820e8bb873a20aee20620ba1b7337e9e9d9 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 7 Feb 2020 11:06:32 -0600 Subject: [PATCH 228/320] allowed-apns: Do not try to unregister unnecessarily allowed-apns plugin will try to uregister the AllowedAccessPoints interface whenever the sim state changes, even when not registered. This results in the (benign) error being printed inside ofono_modem_remove_interface: Interface org.ofono.AllowedAccessPoints not found on the interface_list --- ofono/plugins/allowed-apns.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ofono/plugins/allowed-apns.c b/ofono/plugins/allowed-apns.c index b222b91c3..b18b71873 100644 --- a/ofono/plugins/allowed-apns.c +++ b/ofono/plugins/allowed-apns.c @@ -29,6 +29,7 @@ #include #include #include +#include #define OFONO_API_SUBJECT_TO_CHANGE #include @@ -52,6 +53,7 @@ struct allowed_apns_ctx { struct ofono_sim_context *sim_context; DBusMessage *pending; DBusMessage *reply; + bool registered; }; static void context_destroy(gpointer data) @@ -162,6 +164,9 @@ static void sim_state_watch(enum ofono_sim_state new_state, void *data) DBusConnection *conn = ofono_dbus_get_connection(); if (new_state != OFONO_SIM_STATE_READY) { + if (!ctx->registered) + return; + g_dbus_unregister_interface(conn, ofono_modem_get_path(ctx->modem), ALLOWED_ACCESS_POINTS_INTERFACE); @@ -169,6 +174,7 @@ static void sim_state_watch(enum ofono_sim_state new_state, void *data) ofono_modem_remove_interface(ctx->modem, ALLOWED_ACCESS_POINTS_INTERFACE); + ctx->registered = false; return; } @@ -183,6 +189,7 @@ static void sim_state_watch(enum ofono_sim_state new_state, void *data) return; } + ctx->registered = true; ofono_modem_add_interface(ctx->modem, ALLOWED_ACCESS_POINTS_INTERFACE); } From 368969c7b447f035dd77818474e0993bb7f26ece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Fri, 14 Feb 2020 11:20:04 -0600 Subject: [PATCH 229/320] ublox: network-registration: Handle UREG unsolicited during poll In the case a unsolicited indication for UREG was received while the status was polled. The poll response failed to parse. This since the unsolicited indication only carries one parameter, while the poll response is expected to carry two. Update the code to loop until the response is found. The log below shows a case where this happened. 10:07:55 ofonod[520]: Aux: > AT+UREG?\r 10:07:55 ofonod[520]: Aux: < \r\n+CGREG: 4\r\n\r\n+UREG: 0\r\n\r\n+CIEV: 9,1\r\n 10:07:55 ofonod[520]: src/gprs.c:ofono_gprs_status_notify() /ublox_0 status unknown (4) 10:07:55 ofonod[520]: src/gprs.c:ofono_gprs_detached_notify() /ublox_0 10:07:55 ofonod[520]: Aux: < \r\n+UREG: 1,0\r\n 10:07:55 ofonod[520]: Aux: < \r\nOK\r\n --- .../drivers/ubloxmodem/network-registration.c | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/ofono/drivers/ubloxmodem/network-registration.c b/ofono/drivers/ubloxmodem/network-registration.c index 6a524f478..7c16e5745 100644 --- a/ofono/drivers/ubloxmodem/network-registration.c +++ b/ofono/drivers/ubloxmodem/network-registration.c @@ -279,7 +279,7 @@ static void ublox_ureg_cb(gboolean ok, GAtResult *result, struct netreg_data *nd = ofono_netreg_get_data(tq->netreg); GAtResultIter iter; gint enabled, state; - int tech = tq->tech; + int tech = -1; nd->updating_status = false; @@ -288,21 +288,23 @@ static void ublox_ureg_cb(gboolean ok, GAtResult *result, g_at_result_iter_init(&iter, result); - if (!g_at_result_iter_next(&iter, "+UREG:")) - return; + while (g_at_result_iter_next(&iter, "+UREG:")) { + if (!g_at_result_iter_next_number(&iter, &enabled)) + return; - if (!g_at_result_iter_next_number(&iter, &enabled)) - return; + /* Sometimes we get an unsolicited UREG here, skip it */ + if (!g_at_result_iter_next_number(&iter, &state)) + continue; - if (!g_at_result_iter_next_number(&iter, &state)) - return; + tech = ublox_ureg_state_to_tech(state); + break; + } - tech = ublox_ureg_state_to_tech(state); +error: 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); } From 17342e0930bf50d5c3e4f9fada0dfd86595f8d6c Mon Sep 17 00:00:00 2001 From: Adam Pigg Date: Wed, 16 Feb 2022 11:26:19 +0000 Subject: [PATCH 230/320] build: require dbus >= 1.6 dbus_validate_path() is used several times. dbus's NEWS says it was added in 1.5.12. --- ofono/configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ofono/configure.ac b/ofono/configure.ac index 3b0d6c550..1c316412f 100644 --- a/ofono/configure.ac +++ b/ofono/configure.ac @@ -78,8 +78,8 @@ PKG_CHECK_MODULES(GIO, gio-2.0, dummy=yes, GLIB_CFLAGS="$GLIB_CFLAGS $GIO_CFLAGS" GLIB_LIBS="$GLIB_LIBS $GIO_LIBS" -PKG_CHECK_MODULES(DBUS, dbus-1 >= 1.4, dummy=yes, - AC_MSG_ERROR(D-Bus >= 1.4 is required)) +PKG_CHECK_MODULES(DBUS, dbus-1 >= 1.6, dummy=yes, + AC_MSG_ERROR(D-Bus >= 1.6 is required)) AC_SUBST(DBUS_CFLAGS) AC_SUBST(DBUS_LIBS) From 282ff351a89d4dfc1ce8c0dbf03a313d79ce472b Mon Sep 17 00:00:00 2001 From: JongSeok Won Date: Sun, 5 Apr 2020 20:26:13 +0900 Subject: [PATCH 231/320] rilmodem: update call direction from the isMT value oFono cannot determines the call of direction when the voicecall is triggered in rilmodem --- ofono/drivers/rilmodem/voicecall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/drivers/rilmodem/voicecall.c b/ofono/drivers/rilmodem/voicecall.c index 13dc50716..6c1691665 100644 --- a/ofono/drivers/rilmodem/voicecall.c +++ b/ofono/drivers/rilmodem/voicecall.c @@ -177,7 +177,7 @@ static void clcc_poll_cb(struct ril_msg *message, gpointer user_data) call->id = parcel_r_int32(&rilp); call->phone_number.type = parcel_r_int32(&rilp); parcel_r_int32(&rilp); /* isMpty */ - parcel_r_int32(&rilp); /* isMT */ + call->direction = parcel_r_int32(&rilp); /* isMT */ parcel_r_int32(&rilp); /* als */ call->type = parcel_r_int32(&rilp); /* isVoice */ parcel_r_int32(&rilp); /* isVoicePrivacy */ From 4ab4e70435105b7a3cc43131c41bc47031da084e Mon Sep 17 00:00:00 2001 From: Lars Poeschel Date: Tue, 26 May 2020 12:16:19 +0200 Subject: [PATCH 232/320] quectel: Add Quectel EC21 to known serial modems This adds the Quectel EC21 to the known modems of the quectel driver and therefore allows to use it with its serial interface. --- ofono/plugins/quectel.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 80beb921d..cf814ddf7 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/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 { @@ -514,6 +515,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; @@ -558,6 +560,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; @@ -790,6 +793,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; From 8ce1696d75173736a59ea004bab7c7b6c32fd61f Mon Sep 17 00:00:00 2001 From: Lars Poeschel Date: Tue, 26 May 2020 12:16:20 +0200 Subject: [PATCH 233/320] quectel: use lte atom on EC21 --- ofono/plugins/quectel.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index cf814ddf7..1e004e81d 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -1265,6 +1265,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) From b28dc78a61554bfa1f59367c92ff330519cff6dc Mon Sep 17 00:00:00 2001 From: Lars Poeschel Date: Tue, 26 May 2020 12:16:21 +0200 Subject: [PATCH 234/320] quectel: Query the model before setting up the mux 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. --- ofono/plugins/quectel.c | 86 ++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 1e004e81d..6823fc0b6 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -767,46 +767,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, "", &model)) { - 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); @@ -816,7 +776,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; &C0; +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); } @@ -1036,17 +996,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, "", &model)) { + 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 = ofono_modem_get_data(modem); + + DBG("%p", modem); + + g_at_chat_send(data->uart, "AT+CGMM", cgmm_prefix, cgmm_cb, modem, + NULL); +} + static void init_cmd_cb(gboolean ok, GAtResult *result, void *user_data) { struct ofono_modem *modem = user_data; From 10c20c09cf5b1b584ec63dd2f34e849617047a00 Mon Sep 17 00:00:00 2001 From: Lars Poeschel Date: Tue, 26 May 2020 12:16:23 +0200 Subject: [PATCH 235/320] quectel: EC21 does not understand AT+QIURC Because the Quectel EC21 does not understand the AT+QIURC command, we leave that out during initialisation. --- ofono/plugins/quectel.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 6823fc0b6..96599459d 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -774,8 +774,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; &C0; +CMEE=1; +QIURC=0", none_prefix, - NULL, NULL, NULL); + + if (data->model == QUECTEL_EC21) + g_at_chat_send(data->aux, "ATE0; &C0; +CMEE=1", none_prefix, + NULL, NULL, NULL); + else + g_at_chat_send(data->aux, "ATE0; &C0; +CMEE=1; +QIURC=0", + none_prefix, NULL, NULL, NULL); + g_at_chat_send(data->aux, "AT+CFUN?", cfun_prefix, cfun_query, modem, NULL); } From d09b45513f3cd7c3f96aeafa78fbbd718b8a1f9a Mon Sep 17 00:00:00 2001 From: Lars Poeschel Date: Tue, 26 May 2020 12:16:24 +0200 Subject: [PATCH 236/320] voicecall: Quectel modem do not understand AT+CNAP --- ofono/drivers/atmodem/voicecall.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ofono/drivers/atmodem/voicecall.c b/ofono/drivers/atmodem/voicecall.c index 7ab6567fa..e7f24b60c 100644 --- a/ofono/drivers/atmodem/voicecall.c +++ b/ofono/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: From 21b59aaedb6db69681db5e046b63eb3426d2f862 Mon Sep 17 00:00:00 2001 From: Lars Poeschel Date: Tue, 26 May 2020 12:16:25 +0200 Subject: [PATCH 237/320] quectel: EC21 add ussd with atmodem driver --- ofono/plugins/quectel.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 96599459d..7a9ef1e98 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -1272,8 +1272,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) From 28be770370f63a809d6cce8fd44c86cf46575093 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Thu, 21 May 2020 08:28:45 -0500 Subject: [PATCH 238/320] AUTHORS: Mention Lars' contributions --- ofono/AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/ofono/AUTHORS b/ofono/AUTHORS index 796b2680f..24b7dabf0 100644 --- a/ofono/AUTHORS +++ b/ofono/AUTHORS @@ -145,3 +145,4 @@ Khaled Romdhani Pavel Machek Tom Nguyen Stefan Herbrechtsmeier +Lars Poeschel From 98c0f17fdf97893bcc39f77afcea292c9dd7f292 Mon Sep 17 00:00:00 2001 From: Lars Poeschel Date: Fri, 29 May 2020 14:43:47 +0200 Subject: [PATCH 239/320] quectel: EC21 needs aux channel to be the first mux channel 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. --- ofono/plugins/quectel.c | 61 +++++++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 14 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 7a9ef1e98..9c13e8aa7 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/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 { @@ -840,6 +862,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); @@ -855,18 +878,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); @@ -882,7 +908,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"), &st); + ret = stat(ofono_modem_get_string(modem, + data->mux_order[QUECTEL_MUX_TYPE_MAX - 1].n_gsm_key), + &st); if (ret < 0) { if (data->mux_ready_count++ < 5) { /* not ready yet; try again in 100 ms*/ @@ -959,8 +987,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)) { @@ -1016,6 +1046,8 @@ static void cgmm_cb(int ok, GAtResult *result, void *user_data) return; } + data->mux_order = mux_order_default; + if (strcmp(model, "UC15") == 0) { DBG("%p model UC15", modem); data->vendor = OFONO_VENDOR_QUECTEL; @@ -1032,6 +1064,7 @@ static void cgmm_cb(int ok, GAtResult *result, void *user_data) DBG("%p model EC21", modem); data->vendor = OFONO_VENDOR_QUECTEL; data->model = QUECTEL_EC21; + data->mux_order = mux_order_ec21; } else { ofono_warn("%p unknown model: '%s'", modem, model); data->vendor = OFONO_VENDOR_QUECTEL; From e98d74870e0c1e8d1ade3e831a6f22d1b9b2fa4b Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Tue, 26 May 2020 22:23:58 -0500 Subject: [PATCH 240/320] doc: sim-api was missing SetProperty method --- ofono/doc/sim-api.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ofono/doc/sim-api.txt b/ofono/doc/sim-api.txt index b1428b10f..419d8ec3e 100644 --- a/ofono/doc/sim-api.txt +++ b/ofono/doc/sim-api.txt @@ -79,6 +79,16 @@ Methods dict GetProperties() [service].Error.InvalidArguments [service].Error.Failed + void SetProperty(string property, variant value) + + Sets the given property value to that specified in + call parameter. + + Possible Errors: [service].Error.InProgress + [service].Error.NotImplemented + [service].Error.InvalidArguments + [service].Error.Failed + Signals PropertyChanged(string name, variant value) This signal indicates a changed value of the given From b06b9cc166e23da0e85e2fcaf727d413318a46e5 Mon Sep 17 00:00:00 2001 From: Marius Gripsgard Date: Wed, 10 Jun 2020 15:44:18 +0200 Subject: [PATCH 241/320] qmimodem: Implement data capability bearer notify This implements data capability bearer notify to qmi modem. Since this is included in the serving system response this just adds a new data extraction for dc. --- ofono/drivers/qmimodem/gprs.c | 27 ++++++++++++++++++++++++++ ofono/drivers/qmimodem/nas.c | 36 +++++++++++++++++++++++++++++++++++ ofono/drivers/qmimodem/nas.h | 23 ++++++++++++++++++++++ 3 files changed, 86 insertions(+) diff --git a/ofono/drivers/qmimodem/gprs.c b/ofono/drivers/qmimodem/gprs.c index 07adbe9ab..896a9e4c2 100644 --- a/ofono/drivers/qmimodem/gprs.c +++ b/ofono/drivers/qmimodem/gprs.c @@ -68,6 +68,28 @@ static bool extract_ss_info(struct qmi_result *result, int *status, int *tech) return true; } +static bool extract_dc_info(struct qmi_result *result, int *bearer_tech) +{ + const struct qmi_nas_data_capability *dc; + uint16_t len; + int i; + + DBG(""); + + dc = qmi_result_get(result, QMI_NAS_RESULT_DATA_CAPABILITY_STATUS, &len); + if (!dc) + return false; + + *bearer_tech = -1; + for (i = 0; i < dc->cap_count; i++) { + DBG("radio tech in use %d", dc->cap[i]); + + *bearer_tech = qmi_nas_cap_to_bearer_tech(dc->cap[i]); + } + + return true; +} + static void get_lte_attach_param_cb(struct qmi_result *result, void *user_data) { struct ofono_gprs *gprs = user_data; @@ -188,6 +210,7 @@ static int handle_ss_info(struct qmi_result *result, struct ofono_gprs *gprs) struct gprs_data *data = ofono_gprs_get_data(gprs); int status; int tech; + int bearer_tech; DBG(""); @@ -209,6 +232,10 @@ static int handle_ss_info(struct qmi_result *result, struct ofono_gprs *gprs) data->last_auto_context_id = 0; } + /* DC is optional so only notify on successful extraction */ + if (extract_dc_info(result, &bearer_tech)) + ofono_gprs_bearer_notify(gprs, bearer_tech); + return status; } diff --git a/ofono/drivers/qmimodem/nas.c b/ofono/drivers/qmimodem/nas.c index 48d7f11cc..630f901d8 100644 --- a/ofono/drivers/qmimodem/nas.c +++ b/ofono/drivers/qmimodem/nas.c @@ -36,3 +36,39 @@ int qmi_nas_rat_to_tech(uint8_t rat) return -1; } + +int qmi_nas_cap_to_bearer_tech(int cap_tech) +{ + + switch (cap_tech) { + case QMI_NAS_DATA_CAPABILITY_GSM: + case QMI_NAS_DATA_CAPABILITY_NONE: + return PACKET_BEARER_NONE; + case QMI_NAS_DATA_CAPABILITY_GPRS: + return PACKET_BEARER_GPRS; + case QMI_NAS_DATA_CAPABILITY_EDGE: + return PACKET_BEARER_EGPRS; + case QMI_NAS_DATA_CAPABILITY_EVDO_REV_0: + case QMI_NAS_DATA_CAPABILITY_EVDO_REV_A: + case QMI_NAS_DATA_CAPABILITY_EVDO_REV_B: + return PACKET_BEARER_UMTS; + case QMI_NAS_DATA_CAPABILITY_HSDPA: + return PACKET_BEARER_HSDPA; + case QMI_NAS_DATA_CAPABILITY_HSUPA: + return PACKET_BEARER_HSUPA; + case QMI_NAS_DATA_CAPABILITY_HSDPA_PLUS: + case QMI_NAS_DATA_CAPABILITY_DC_HSDPA_PLUS: + /* + * HSPAP is HSPA+; which ofono doesn't define; + * so, if differentiating HSPA and HSPA+ is + * important, then ofono needs to be patched, + * and we probably also need to introduce a + * new indicator icon. + */ + return PACKET_BEARER_HSUPA_HSDPA; + case QMI_NAS_DATA_CAPABILITY_LTE: + return PACKET_BEARER_EPS; + default: + return PACKET_BEARER_NONE; + } +} diff --git a/ofono/drivers/qmimodem/nas.h b/ofono/drivers/qmimodem/nas.h index 9f67707ea..30badabe7 100644 --- a/ofono/drivers/qmimodem/nas.h +++ b/ofono/drivers/qmimodem/nas.h @@ -135,6 +135,28 @@ struct qmi_nas_serving_system { uint8_t radio_if[0]; } __attribute__((__packed__)); #define QMI_NAS_RESULT_ROAMING_STATUS 0x10 /* uint8 */ + +#define QMI_NAS_RESULT_DATA_CAPABILITY_STATUS 0x11 /* uint8 */ +struct qmi_nas_data_capability { + uint8_t cap_count; + uint8_t cap[0]; +} __attribute__((__packed__)); + +#define QMI_NAS_DATA_CAPABILITY_NONE 0x00 +#define QMI_NAS_DATA_CAPABILITY_GPRS 0x01 +#define QMI_NAS_DATA_CAPABILITY_EDGE 0x02 +#define QMI_NAS_DATA_CAPABILITY_HSDPA 0x03 +#define QMI_NAS_DATA_CAPABILITY_HSUPA 0x04 +#define QMI_NAS_DATA_CAPABILITY_WCDMA 0x05 +#define QMI_NAS_DATA_CAPABILITY_CDMA 0x06 +#define QMI_NAS_DATA_CAPABILITY_EVDO_REV_0 0x07 +#define QMI_NAS_DATA_CAPABILITY_EVDO_REV_A 0x08 +#define QMI_NAS_DATA_CAPABILITY_GSM 0x09 +#define QMI_NAS_DATA_CAPABILITY_EVDO_REV_B 0x0A +#define QMI_NAS_DATA_CAPABILITY_LTE 0x0B +#define QMI_NAS_DATA_CAPABILITY_HSDPA_PLUS 0x0C +#define QMI_NAS_DATA_CAPABILITY_DC_HSDPA_PLUS 0x0D + #define QMI_NAS_RESULT_CURRENT_PLMN 0x12 struct qmi_nas_current_plmn { uint16_t mcc; @@ -188,3 +210,4 @@ struct qmi_nas_home_network { #define QMI_NAS_RESULT_SYSTEM_SELECTION_PREF_MODE 0x11 int qmi_nas_rat_to_tech(uint8_t rat); +int qmi_nas_cap_to_bearer_tech(int cap_tech); From 659455f5dda1cd8296b53a89265216898e7d7e38 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Wed, 10 Jun 2020 14:23:28 -0500 Subject: [PATCH 242/320] AUTHORS: Mention Marius' contributions --- ofono/AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/ofono/AUTHORS b/ofono/AUTHORS index 24b7dabf0..d8be35b7e 100644 --- a/ofono/AUTHORS +++ b/ofono/AUTHORS @@ -146,3 +146,4 @@ Pavel Machek Tom Nguyen Stefan Herbrechtsmeier Lars Poeschel +Marius Gripsgard From be078c7925ed0e28d4f2560b21520ac87c40ff2a Mon Sep 17 00:00:00 2001 From: Christophe Ronco Date: Thu, 11 Jun 2020 11:12:26 +0200 Subject: [PATCH 243/320] huawei: use AT^SYSCFG for radio setting operations on 3G only modems AT^SYSCFGEX must be used on LTE Huawei modems to enable LTE support. But some modems (or firmwares?) do not support this command and AT^SYSCFG must be used to get/set radio settings. This has been introduced in commit: 22adf6402c828f8b8cca1b65d8a46ba7792eb787 There is a bug in this commit and AT^SYSCFGEX commands are used even on modems not supporting it. --- ofono/drivers/huaweimodem/radio-settings.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ofono/drivers/huaweimodem/radio-settings.c b/ofono/drivers/huaweimodem/radio-settings.c index 40431d380..20181d2b7 100644 --- a/ofono/drivers/huaweimodem/radio-settings.c +++ b/ofono/drivers/huaweimodem/radio-settings.c @@ -532,6 +532,7 @@ static void syscfgex_support_cb(gboolean ok, GAtResult *result, if (!ok) { g_at_chat_send(rsd->chat, "AT^SYSCFG=?", syscfg_prefix, syscfg_support_cb, rs, NULL); + return; } rsd->syscfgex_cap = 1; From 9c137f8ca87cd8665a38243da9e06a1afdd21b98 Mon Sep 17 00:00:00 2001 From: Slava Monich Date: Wed, 17 Jun 2020 01:40:14 +0300 Subject: [PATCH 244/320] lte: Use the right D-Bus interface for property change signal --- ofono/src/lte.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/src/lte.c b/ofono/src/lte.c index fbe01168d..951a06fd7 100644 --- a/ofono/src/lte.c +++ b/ofono/src/lte.c @@ -212,7 +212,7 @@ static void lte_set_default_attach_info_cb(const struct ofono_error *error, } ofono_dbus_signal_property_changed(conn, path, - OFONO_CONNECTION_CONTEXT_INTERFACE, + OFONO_LTE_INTERFACE, key, DBUS_TYPE_STRING, &value); From 3bcae1c00cc229b8c2cbf42ac6ae65978f78a16f Mon Sep 17 00:00:00 2001 From: Jimmy Gysens Date: Thu, 25 Jun 2020 11:29:42 +0200 Subject: [PATCH 245/320] huawei: the AT^SYSCFGEX command supports additional modes - LTE and UMTS preferred (acqorder = 0302); AT^SYSCFGEX="0302",40000000,2,4,40000000 - UMTS and GSM preferred (acqorder = 0201); AT^SYSCFGEX="0201",40000000,2,4,40000000 For AT^SYSCFG, the modes are not available. --- ofono/drivers/huaweimodem/radio-settings.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ofono/drivers/huaweimodem/radio-settings.c b/ofono/drivers/huaweimodem/radio-settings.c index 20181d2b7..ff7be48a8 100644 --- a/ofono/drivers/huaweimodem/radio-settings.c +++ b/ofono/drivers/huaweimodem/radio-settings.c @@ -207,6 +207,10 @@ static void syscfgex_query_mode_cb(gboolean ok, GAtResult *result, strstr(acqorder, "02") && strstr(acqorder, "03"))) mode = OFONO_RADIO_ACCESS_MODE_ANY; + else if (strstr(acqorder, "0302")) + mode = (OFONO_RADIO_ACCESS_MODE_LTE | OFONO_RADIO_ACCESS_MODE_UMTS); + else if (strstr(acqorder, "0201")) + mode = (OFONO_RADIO_ACCESS_MODE_UMTS | OFONO_RADIO_ACCESS_MODE_LTE); else if (strstr(acqorder, "03")) mode = OFONO_RADIO_ACCESS_MODE_LTE; else if (strstr(acqorder, "02")) @@ -281,6 +285,8 @@ static void syscfg_set_rat_mode(struct radio_settings_data *rsd, break; case OFONO_RADIO_ACCESS_MODE_LTE: goto error; + default: + goto error; } snprintf(buf, sizeof(buf), "AT^SYSCFG=%u,%u,40000000,2,4", @@ -318,8 +324,15 @@ static void syscfgex_set_rat_mode(struct radio_settings_data *rsd, case OFONO_RADIO_ACCESS_MODE_LTE: acqorder = "03"; break; + default: + break; } + if (mode == (OFONO_RADIO_ACCESS_MODE_LTE | OFONO_RADIO_ACCESS_MODE_UMTS)) + acqorder = "0302"; + else if (mode == (OFONO_RADIO_ACCESS_MODE_UMTS | OFONO_RADIO_ACCESS_MODE_LTE)) + acqorder = "0201"; + snprintf(buf, sizeof(buf), atcmd, acqorder); if (g_at_chat_send(rsd->chat, buf, none_prefix, From 9f9d0022e96bce6936a93f7f0308ccc41f185291 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Thu, 25 Jun 2020 11:35:09 -0500 Subject: [PATCH 246/320] AUTHORS: Mention Jimmy's contributions --- ofono/AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/ofono/AUTHORS b/ofono/AUTHORS index d8be35b7e..52ec07134 100644 --- a/ofono/AUTHORS +++ b/ofono/AUTHORS @@ -147,3 +147,4 @@ Tom Nguyen Stefan Herbrechtsmeier Lars Poeschel Marius Gripsgard +Jimmy Gysens From ca50fc3fe0ebd34185bb1c8a8e8afbfb46538130 Mon Sep 17 00:00:00 2001 From: Jimmy Gysens Date: Thu, 25 Jun 2020 11:29:54 +0200 Subject: [PATCH 247/320] huawei: send restore settings command on startup When initializing a Huawei device, send the AT&F0 command to restore the default AT settings on device restart. Huawei stores all APN settings, which can cause issues when changing the APN. The AT&F0 command makes sure the device starts from a clean state. --- ofono/plugins/huawei.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ofono/plugins/huawei.c b/ofono/plugins/huawei.c index bb8767018..c524cdd32 100644 --- a/ofono/plugins/huawei.c +++ b/ofono/plugins/huawei.c @@ -419,6 +419,10 @@ static void sysinfo_enable_cb(gboolean ok, GAtResult *result, g_at_chat_send(data->modem, "AT&C0", NULL, NULL, NULL, NULL); g_at_chat_send(data->pcui, "AT&C0", NULL, NULL, NULL, NULL); + /* Restore settings after restart */ + g_at_chat_send(data->modem, "AT&F0", NULL, NULL, NULL, NULL); + g_at_chat_send(data->pcui, "AT&F0", NULL, NULL, NULL, NULL); + /* * Ensure that the modem is using GSM character set and not IRA, * otherwise weirdness with umlauts and other non-ASCII characters From 142b2bf2260b1be1c2a8cdd91f80996a04a3cc9a Mon Sep 17 00:00:00 2001 From: Jimmy Gysens Date: Fri, 26 Jun 2020 08:36:40 +0200 Subject: [PATCH 248/320] huawei: fix AT^SYSCFGEX acqorder "0201" Commit 6c574ee24a57d0397e4e3c617016bf026405960a ("huawei: the AT^SYSCFGEX command supports additional modes") has a mistake for acqorder "0201". It should be UMTS and GSM preferred. --- ofono/drivers/huaweimodem/radio-settings.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ofono/drivers/huaweimodem/radio-settings.c b/ofono/drivers/huaweimodem/radio-settings.c index ff7be48a8..c8ebcba04 100644 --- a/ofono/drivers/huaweimodem/radio-settings.c +++ b/ofono/drivers/huaweimodem/radio-settings.c @@ -210,7 +210,7 @@ static void syscfgex_query_mode_cb(gboolean ok, GAtResult *result, else if (strstr(acqorder, "0302")) mode = (OFONO_RADIO_ACCESS_MODE_LTE | OFONO_RADIO_ACCESS_MODE_UMTS); else if (strstr(acqorder, "0201")) - mode = (OFONO_RADIO_ACCESS_MODE_UMTS | OFONO_RADIO_ACCESS_MODE_LTE); + mode = (OFONO_RADIO_ACCESS_MODE_UMTS | OFONO_RADIO_ACCESS_MODE_GSM); else if (strstr(acqorder, "03")) mode = OFONO_RADIO_ACCESS_MODE_LTE; else if (strstr(acqorder, "02")) @@ -330,7 +330,7 @@ static void syscfgex_set_rat_mode(struct radio_settings_data *rsd, if (mode == (OFONO_RADIO_ACCESS_MODE_LTE | OFONO_RADIO_ACCESS_MODE_UMTS)) acqorder = "0302"; - else if (mode == (OFONO_RADIO_ACCESS_MODE_UMTS | OFONO_RADIO_ACCESS_MODE_LTE)) + else if (mode == (OFONO_RADIO_ACCESS_MODE_UMTS | OFONO_RADIO_ACCESS_MODE_GSM)) acqorder = "0201"; snprintf(buf, sizeof(buf), atcmd, acqorder); From c678d18e444434afb139bc4d22de9fab9deb06ed Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Sat, 27 Jun 2020 14:08:37 +0300 Subject: [PATCH 249/320] plugins: udevng: detect Centirion ELS81x modem Enable detection of Centirion ELS81x modem. --- ofono/plugins/udevng.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ofono/plugins/udevng.c b/ofono/plugins/udevng.c index 25593c6a9..1208625d8 100644 --- a/ofono/plugins/udevng.c +++ b/ofono/plugins/udevng.c @@ -1806,6 +1806,8 @@ static struct { { "gemalto", "qmi_wwan", "1e2d", "0053" }, { "gemalto", "cdc_acm", "1e2d", "0061" }, { "gemalto", "cdc_ether", "1e2d", "0061" }, + { "gemalto", "cdc_acm", "1e2d", "005b" }, + { "gemalto", "cdc_ether", "1e2d", "005b" }, { "telit", "cdc_ncm", "1bc7", "0036" }, { "telit", "cdc_acm", "1bc7", "0036" }, { "xmm7xxx", "cdc_acm", "8087" }, From 075160d501dc8af5d1c006a1167524384931a2f6 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Sat, 27 Jun 2020 14:08:38 +0300 Subject: [PATCH 250/320] plugins: gemalto: enable LTE for ELS81x Enable LTE atom for Cinterion ELS81x modems. --- ofono/plugins/gemalto.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ofono/plugins/gemalto.c b/ofono/plugins/gemalto.c index 297aaea30..13950742f 100644 --- a/ofono/plugins/gemalto.c +++ b/ofono/plugins/gemalto.c @@ -58,6 +58,8 @@ #define GEMALTO_MODEL_PHS8P "0053" /* ALS3, PLS8-E, and PLS8-X family */ #define GEMALTO_MODEL_ALS3_PLS8x "0061" +/* ELS81 modem */ +#define GEMALTO_MODEL_ELS81x "005b" static const char *none_prefix[] = { NULL }; static const char *sctm_prefix[] = { "^SCTM:", NULL }; @@ -601,7 +603,8 @@ static void gemalto_post_sim(struct ofono_modem *modem) ofono_ussd_create(modem, 0, "atmodem", data->app); - if (!g_strcmp0(model, GEMALTO_MODEL_ALS3_PLS8x)) + if (!g_strcmp0(model, GEMALTO_MODEL_ALS3_PLS8x) || + !g_strcmp0(model, GEMALTO_MODEL_ELS81x)) ofono_lte_create(modem, OFONO_VENDOR_GEMALTO, "atmodem", data->app); } From 7cdd37d0b134c0451ea4c09f3e904c8d333ed9ef Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 29 Jun 2020 10:20:28 -0500 Subject: [PATCH 251/320] AUTHORS: Mention Sergey's contributions --- ofono/AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/ofono/AUTHORS b/ofono/AUTHORS index 52ec07134..1433319df 100644 --- a/ofono/AUTHORS +++ b/ofono/AUTHORS @@ -148,3 +148,4 @@ Stefan Herbrechtsmeier Lars Poeschel Marius Gripsgard Jimmy Gysens +Sergey Matyukevich From b9911971531ca9f8a823eebeb1ade0d5fcce7325 Mon Sep 17 00:00:00 2001 From: Shweta Jain Date: Mon, 6 Jul 2020 22:39:20 +0300 Subject: [PATCH 252/320] gatchat: increase line buffer max size Some modems might transfer results that are larger than the current buffer. Increase it. --- ofono/gatchat/gatresult.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/gatchat/gatresult.h b/ofono/gatchat/gatresult.h index e92d38ba0..5993b2338 100644 --- a/ofono/gatchat/gatresult.h +++ b/ofono/gatchat/gatresult.h @@ -35,7 +35,7 @@ struct _GAtResult { typedef struct _GAtResult GAtResult; -#define G_AT_RESULT_LINE_LENGTH_MAX 2048 +#define G_AT_RESULT_LINE_LENGTH_MAX 4096 struct _GAtResultIter { GAtResult *result; From 4206352c91e53918dfb07453c92810540167740b Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Wed, 8 Jul 2020 11:49:10 -0500 Subject: [PATCH 253/320] AUTHORS: Mention Shweta's contributions --- ofono/AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/ofono/AUTHORS b/ofono/AUTHORS index 1433319df..34f736a9e 100644 --- a/ofono/AUTHORS +++ b/ofono/AUTHORS @@ -149,3 +149,4 @@ Lars Poeschel Marius Gripsgard Jimmy Gysens Sergey Matyukevich +Shweta Jain From 4260b8b4b330933036d6e359318834cbb598e52f Mon Sep 17 00:00:00 2001 From: Sean Nyekjaer Date: Sat, 11 Jul 2020 14:04:50 +0200 Subject: [PATCH 254/320] udevng: Add support for Quectel BG96 modem --- ofono/plugins/udevng.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ofono/plugins/udevng.c b/ofono/plugins/udevng.c index 1208625d8..1452e8f6a 100644 --- a/ofono/plugins/udevng.c +++ b/ofono/plugins/udevng.c @@ -1794,6 +1794,8 @@ static struct { { "quectelqmi", "qcserial", "2c7c", "0121" }, { "quectelqmi", "qmi_wwan", "2c7c", "0125" }, { "quectelqmi", "qcserial", "2c7c", "0125" }, + { "quectelqmi", "qmi_wwan", "2c7c", "0296" }, + { "quectelqmi", "qcserial", "2c7c", "0296" }, { "ublox", "cdc_acm", "1546", "1010" }, { "ublox", "cdc_ncm", "1546", "1010" }, { "ublox", "cdc_acm", "1546", "1102" }, From e0cd6829c490ac36d1247c2b9a98932f02eb5ed0 Mon Sep 17 00:00:00 2001 From: JongSeok Won Date: Mon, 20 Jul 2020 16:34:50 +0900 Subject: [PATCH 255/320] rilmodem: fix typo error in netmon.c --- ofono/drivers/rilmodem/netmon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/drivers/rilmodem/netmon.c b/ofono/drivers/rilmodem/netmon.c index 7dd3a5624..547ebccc8 100644 --- a/ofono/drivers/rilmodem/netmon.c +++ b/ofono/drivers/rilmodem/netmon.c @@ -201,7 +201,7 @@ static int process_cellinfo_list(struct ril_msg *message, lac = (lac >= 0 && lac <= 65535) ? lac : -1; cid = (cid >= 0 && cid <= 268435455) ? cid : -1; - psc = (psc >= 0 && rssi <= 511) ? psc : -1; + psc = (psc >= 0 && psc <= 511) ? psc : -1; rssi = (rssi >= 0 && rssi <= 31) ? rssi : -1; ber = (ber >= 0 && ber <= 7) ? ber : -1; From 3e6c98786137433f8c18cf561697d1bbe3df90f3 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Tue, 21 Jul 2020 08:42:21 -0500 Subject: [PATCH 256/320] AUTHORS: Mention JongSeok's contributions --- ofono/AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/ofono/AUTHORS b/ofono/AUTHORS index 34f736a9e..b5cb0f793 100644 --- a/ofono/AUTHORS +++ b/ofono/AUTHORS @@ -150,3 +150,4 @@ Marius Gripsgard Jimmy Gysens Sergey Matyukevich Shweta Jain +JongSeok Won From 96d03a67f115862a15cc73b3841e9b2821c1269e Mon Sep 17 00:00:00 2001 From: JongSeok Won Date: Mon, 20 Jul 2020 18:16:03 +0900 Subject: [PATCH 257/320] rilmodem: set proto type during setting initial attach apn Added the protocol type of initial attach apn depends on protocol type in LTE Atom. --- ofono/drivers/rilmodem/lte.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ofono/drivers/rilmodem/lte.c b/ofono/drivers/rilmodem/lte.c index 61718961f..b613d354f 100644 --- a/ofono/drivers/rilmodem/lte.c +++ b/ofono/drivers/rilmodem/lte.c @@ -71,6 +71,7 @@ static void ril_lte_set_default_attach_info(const struct ofono_lte *lte, struct cb_data *cbd = cb_data_new(cb, data, (struct ofono_lte *)lte); struct parcel rilp; char buf[OFONO_GPRS_MAX_APN_LENGTH + 1]; + const char *proto = ril_util_gprs_proto_to_ril_string(info->proto); DBG("%s", info->apn); @@ -80,10 +81,11 @@ static void ril_lte_set_default_attach_info(const struct ofono_lte *lte, if (strlen(info->apn) > 0) { sprintf(buf, "%s", info->apn); parcel_w_string(&rilp, buf); - } else + } else { parcel_w_string(&rilp, ""); /* apn */ + } - parcel_w_string(&rilp, "ip"); /* protocol */ + parcel_w_string(&rilp, proto); /* protocol */ parcel_w_int32(&rilp, 0); /* auth type */ parcel_w_string(&rilp, ""); /* username */ parcel_w_string(&rilp, ""); /* password */ From 3605ed7aab1a9719abda1b277bc79222952ed909 Mon Sep 17 00:00:00 2001 From: JongSeok Won Date: Fri, 31 Jul 2020 11:21:03 +0900 Subject: [PATCH 258/320] doc: added PCI, TAC, SNR property in networkmonitor-api --- ofono/doc/networkmonitor-api.txt | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/ofono/doc/networkmonitor-api.txt b/ofono/doc/networkmonitor-api.txt index 1cc73d2ca..af56f04b1 100644 --- a/ofono/doc/networkmonitor-api.txt +++ b/ofono/doc/networkmonitor-api.txt @@ -118,7 +118,7 @@ uint16 PrimaryScramblingCode [optional, umts] Contains the scrambling code. Valid range of values is 0-512. -byte TimingAdvance [optional, gsm] +byte TimingAdvance [optional, gsm, lte] Contains the Timing Advance. Valid range of values is 0-219. @@ -165,3 +165,17 @@ byte ChannelQualityIndicator [optional, lte] Contains Channel Quality Indicator. Refer to Channel Quality Indicator definition in 36.213, Section 7.2.3 for more details. + +uint16 PhysicalCellId [optional, lte] + + Contains Physical Cell Id. Valid range of values is 0-503. + +uint16 TrackingAreaCode [optional, lte] + + Contains Tracking Area Code. Valid range of values is 0-65535. + +int32 SingalToNoiseRatio [optional, lte] + + Contains Signal To Noise Ratio. Valid range of values is -200 to +300. + The value is in 0.1 dB units. (-200 = -20.0 dB, +300 = 30dB) + Refer to in 36.101, Section 8.1.1 for more details. From 754305ef7e81e6a7b1ed567a25decd5b9e09a533 Mon Sep 17 00:00:00 2001 From: JongSeok Won Date: Fri, 31 Jul 2020 11:20:38 +0900 Subject: [PATCH 259/320] netmon: added PCI, TAC, SNR value To support cell type LTE, the value of PCI, TAC, SNR is added --- ofono/include/netmon.h | 3 +++ ofono/src/netmon.c | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/ofono/include/netmon.h b/ofono/include/netmon.h index a99d6ca92..53f9d393f 100644 --- a/ofono/include/netmon.h +++ b/ofono/include/netmon.h @@ -72,6 +72,9 @@ enum ofono_netmon_info { OFONO_NETMON_INFO_EARFCN, /* int */ OFONO_NETMON_INFO_EBAND, /* int */ OFONO_NETMON_INFO_CQI, /* int */ + OFONO_NETMON_INFO_PCI, /* int */ + OFONO_NETMON_INFO_TAC, /* int */ + OFONO_NETMON_INFO_SNR, /* int */ OFONO_NETMON_INFO_INVALID, }; diff --git a/ofono/src/netmon.c b/ofono/src/netmon.c index 9eacb3ca5..10e3ee2b4 100644 --- a/ofono/src/netmon.c +++ b/ofono/src/netmon.c @@ -213,6 +213,27 @@ static void netmon_cell_info_dict_append(DBusMessageIter *dict, intval, uint8_t, DBUS_TYPE_BYTE); break; + case OFONO_NETMON_INFO_PCI: + intval = va_arg(*arglist, int); + + CELL_INFO_DICT_APPEND(dict, "PhysicalCellId", + intval, uint16_t, DBUS_TYPE_UINT16); + break; + + case OFONO_NETMON_INFO_TAC: + intval = va_arg(*arglist, int); + + CELL_INFO_DICT_APPEND(dict, "TrackingAreaCode", + intval, uint16_t, DBUS_TYPE_UINT16); + break; + + case OFONO_NETMON_INFO_SNR: + intval = va_arg(*arglist, int); + + ofono_dbus_dict_append(dict, "SingalToNoiseRatio", + DBUS_TYPE_INT32, &intval); + break; + case OFONO_NETMON_INFO_INVALID: break; } From 3a20056c8078e49f35f030d372eb785b00b821c2 Mon Sep 17 00:00:00 2001 From: JongSeok Won Date: Fri, 31 Jul 2020 11:20:52 +0900 Subject: [PATCH 260/320] rilmodem: support cell type LTE for netmon --- ofono/drivers/rilmodem/netmon.c | 51 +++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/ofono/drivers/rilmodem/netmon.c b/ofono/drivers/rilmodem/netmon.c index 547ebccc8..9f3a11914 100644 --- a/ofono/drivers/rilmodem/netmon.c +++ b/ofono/drivers/rilmodem/netmon.c @@ -109,6 +109,9 @@ static int process_cellinfo_list(struct ril_msg *message, int mcc, mnc; int lac, cid, psc; int rssi, ber; + int ci, pci, tac; + int rsrp, rsrq, rssnr; + int cqi, tadv; char s_mcc[OFONO_MAX_MCC_LENGTH + 1]; char s_mnc[OFONO_MAX_MNC_LENGTH + 1]; int i, j; @@ -216,6 +219,54 @@ static int process_cellinfo_list(struct ril_msg *message, OFONO_NETMON_INFO_BER, ber, OFONO_NETMON_INFO_INVALID); + } else if (cell_type == NETMON_RIL_CELLINFO_TYPE_LTE) { + mcc = parcel_r_int32(&rilp); + mnc = parcel_r_int32(&rilp); + ci = parcel_r_int32(&rilp); + pci = parcel_r_int32(&rilp); + tac = parcel_r_int32(&rilp); + rssi = parcel_r_int32(&rilp); + rsrp = parcel_r_int32(&rilp); + rsrq = parcel_r_int32(&rilp); + rssnr = parcel_r_int32(&rilp); + cqi = parcel_r_int32(&rilp); + tadv = parcel_r_int32(&rilp); + + if (mcc >= 0 && mcc <= 999) + snprintf(s_mcc, sizeof(s_mcc), "%03d", mcc); + else + strcpy(s_mcc, ""); + + if (mnc >= 0 && mnc <= 999) + snprintf(s_mnc, sizeof(s_mnc), "%03d", mnc); + else + strcpy(s_mnc, ""); + + ci = (ci >= 0 && ci <= 268435455) ? ci : -1; + pci = (pci >= 0 && pci <= 503) ? pci : -1; + tac = (tac >= 0 && tac <= 65535) ? tac : -1; + rssi = (rssi >= 0 && rssi <= 31) ? rssi : -1; + rsrp = (rsrp >= 44 && rsrp <= 140) ? -rsrp : -1; + rsrq = (rsrq >= 3 && rsrq <= 20) ? -rsrq : -1; + rssnr = (rssnr >= -200 && rssnr <= 300) ? rssnr : -1; + cqi = (cqi >= 0 && cqi <= 15) ? cqi : -1; + tadv = (tadv >=0 && tadv <= 63) ? tadv : -1; + + ofono_netmon_serving_cell_notify(netmon, + OFONO_NETMON_CELL_TYPE_LTE, + OFONO_NETMON_INFO_MCC, s_mcc, + OFONO_NETMON_INFO_MNC, s_mnc, + OFONO_NETMON_INFO_CI, ci, + OFONO_NETMON_INFO_PCI, pci, + OFONO_NETMON_INFO_TAC, tac, + OFONO_NETMON_INFO_RSSI, rssi, + OFONO_NETMON_INFO_RSRP, rsrp, + OFONO_NETMON_INFO_RSRQ, rsrq, + OFONO_NETMON_INFO_SNR, rssnr, + OFONO_NETMON_INFO_CQI, cqi, + OFONO_NETMON_INFO_TIMING_ADVANCE, tadv, + OFONO_NETMON_INFO_INVALID); + } return OFONO_ERROR_TYPE_NO_ERROR; From 5aa79684ce80c55825e6fb0ee9d4d6ef829de511 Mon Sep 17 00:00:00 2001 From: Lars Poeschel Date: Tue, 4 Aug 2020 13:56:49 +0200 Subject: [PATCH 261/320] Revert "quectel: EC21 needs aux channel to be the first mux channel" 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. --- ofono/plugins/quectel.c | 61 ++++++++++------------------------------- 1 file changed, 14 insertions(+), 47 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 9c13e8aa7..7a9ef1e98 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/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 { @@ -862,7 +840,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); @@ -878,21 +855,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); @@ -908,9 +882,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), - &st); + ret = stat(ofono_modem_get_string(modem, "Modem"), &st); if (ret < 0) { if (data->mux_ready_count++ < 5) { /* not ready yet; try again in 100 ms*/ @@ -987,10 +959,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 */ if (!l_timeout_create_ms(100, mux_ready_cb, modem, NULL)) { @@ -1046,8 +1016,6 @@ static void cgmm_cb(int ok, GAtResult *result, void *user_data) return; } - data->mux_order = mux_order_default; - if (strcmp(model, "UC15") == 0) { DBG("%p model UC15", modem); data->vendor = OFONO_VENDOR_QUECTEL; @@ -1064,7 +1032,6 @@ static void cgmm_cb(int ok, GAtResult *result, void *user_data) DBG("%p model EC21", modem); data->vendor = OFONO_VENDOR_QUECTEL; data->model = QUECTEL_EC21; - data->mux_order = mux_order_ec21; } else { ofono_warn("%p unknown model: '%s'", modem, model); data->vendor = OFONO_VENDOR_QUECTEL; From bd71d940390184f5c8e955611425d1565f36c86c Mon Sep 17 00:00:00 2001 From: Lars Poeschel Date: Tue, 4 Aug 2020 14:38:46 +0200 Subject: [PATCH 262/320] quectel: Set URC port to uart1 on EC21 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. --- ofono/plugins/quectel.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 7a9ef1e98..67b08c863 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -775,10 +775,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; &C0; +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; &C0; +CMEE=1; +QIURC=0", none_prefix, NULL, NULL, NULL); From 5cf4dfb4a4512317a8af531b777db490327f2f43 Mon Sep 17 00:00:00 2001 From: Lars Poeschel Date: Tue, 4 Aug 2020 14:38:48 +0200 Subject: [PATCH 263/320] quectel: Try to update voltage only, when received "vbatt" 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 --- ofono/plugins/quectel.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 67b08c863..6f0be0b36 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -427,10 +427,12 @@ static void qind_notify(GAtResult *result, void *user_data) if (!g_at_result_iter_next_string(&iter, &type)) return; - if (!g_at_result_iter_next_number(&iter, &event)) - return; + if (g_strcmp0("vbatt", type)) { + if (!g_at_result_iter_next_number(&iter, &event)) + return; - voltage_handle(hw->modem, event); + voltage_handle(hw->modem, event); + } } static void power_notify(GAtResult *result, void *user_data) From 087357f47cb7758fc938efd5684589d577a0c643 Mon Sep 17 00:00:00 2001 From: Lars Poeschel Date: Tue, 11 Aug 2020 13:42:15 +0200 Subject: [PATCH 264/320] Add a vendor OFONO_VENDOR_QUECTEL_EC2X 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 --- ofono/drivers/atmodem/sim.c | 1 + ofono/drivers/atmodem/sms.c | 2 ++ ofono/drivers/atmodem/vendor.h | 1 + ofono/drivers/atmodem/voicecall.c | 3 ++- ofono/plugins/quectel.c | 2 +- 5 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ofono/drivers/atmodem/sim.c b/ofono/drivers/atmodem/sim.c index e750a1399..6ab916552 100644 --- a/ofono/drivers/atmodem/sim.c +++ b/ofono/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/ofono/drivers/atmodem/sms.c b/ofono/drivers/atmodem/sms.c index ee3c40239..5b5dd4b77 100644 --- a/ofono/drivers/atmodem/sms.c +++ b/ofono/drivers/atmodem/sms.c @@ -336,6 +336,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: @@ -844,6 +845,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/ofono/drivers/atmodem/vendor.h b/ofono/drivers/atmodem/vendor.h index d839d1e0f..6bac7f896 100644 --- a/ofono/drivers/atmodem/vendor.h +++ b/ofono/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/ofono/drivers/atmodem/voicecall.c b/ofono/drivers/atmodem/voicecall.c index e7f24b60c..65db0000e 100644 --- a/ofono/drivers/atmodem/voicecall.c +++ b/ofono/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/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 6f0be0b36..e5eb41e78 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -1034,7 +1034,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); From 57fe42a4bbcdc0e138a9bdf59a860aa52b2f3e0b Mon Sep 17 00:00:00 2001 From: Lars Poeschel Date: Tue, 11 Aug 2020 13:42:16 +0200 Subject: [PATCH 265/320] atmodem: Get strength and tech the quectel way on EC21 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. --- ofono/drivers/atmodem/network-registration.c | 71 ++++++++++++++++++++ ofono/plugins/quectel.c | 2 +- 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/ofono/drivers/atmodem/network-registration.c b/ofono/drivers/atmodem/network-registration.c index cc702c2c2..78b1994cb 100644 --- a/ofono/drivers/atmodem/network-registration.c +++ b/ofono/drivers/atmodem/network-registration.c @@ -957,6 +957,66 @@ static void tlts_notify(GAtResult *result, gpointer user_data) ofono_netreg_time_notify(netreg, &nd->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(&iter, result); + + if (!g_at_result_iter_next(&iter, "+QIND:")) + return; + + if (!g_at_result_iter_next_string(&iter, &str)) + return; + + if (g_str_equal("csq", str)) { + if (!g_at_result_iter_next_number(&iter, &rssi)) + return; + + if (!g_at_result_iter_next_number(&iter, &ber)) + 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(&iter, &str)) + 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&HSUPA", 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/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index e5eb41e78..8a21d09f4 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -1288,7 +1288,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 = { From 6c2a9467e1f7fcc52a5bfcb4dbcb537d84d4a607 Mon Sep 17 00:00:00 2001 From: Shweta Jain Date: Thu, 30 Jul 2020 22:37:56 +0300 Subject: [PATCH 266/320] xmm7xxx-enable-esim-feature-in-xmm_ofono --- ofono/plugins/xmm7xxx.c | 391 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 391 insertions(+) diff --git a/ofono/plugins/xmm7xxx.c b/ofono/plugins/xmm7xxx.c index b3aaf8526..bf90833d4 100644 --- a/ofono/plugins/xmm7xxx.c +++ b/ofono/plugins/xmm7xxx.c @@ -59,9 +59,12 @@ #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" +#define OFONO_EUICC_LPA_INTERFACE OFONO_SERVICE ".intel.EuiccLpa" #define NET_BAND_LTE_INVALID 0 #define NET_BAND_LTE_1 101 @@ -73,6 +76,8 @@ static const char *none_prefix[] = { NULL }; static const char *xsimstate_prefix[] = { "+XSIMSTATE:", NULL }; static const char *xnvmplmn_prefix[] = { "+XNVMPLMN:", NULL }; +static const char *ccho_prefix[] = { "+CCHO:", NULL }; +static const char *cgla_prefix[] = { "+CGLA:", NULL }; struct bt_coex_info { int safe_tx_min; @@ -108,8 +113,380 @@ struct xmm7xxx_data { ofono_bool_t have_sim; unsigned int netreg_watch; int xsim_status; + ofono_bool_t stk_enable; + ofono_bool_t enable_euicc; }; +/* eUICC Implementation */ +#define EUICC_EID_CMD "80e2910006BF3E035C015A00" +#define EUICC_ISDR_AID "A0000005591010FFFFFFFF8900000100" + +struct xmm7xxx_euicc { + GAtChat *chat; + struct ofono_modem *modem; + char *eid; + int channel; + char *command; + int length; + DBusMessage *pending; + ofono_bool_t is_registered; +}; + +static void euicc_cleanup(void *data) +{ + struct xmm7xxx_euicc *euicc = data; + + g_free(euicc->command); + g_free(euicc->eid); + + if (euicc->pending) + dbus_message_unref(euicc->pending); + + g_free(euicc); +} + +static void euicc_release_isdr(struct xmm7xxx_euicc *euicc) +{ + char buff[20]; + + snprintf(buff, sizeof(buff), "AT+CCHC=%u", euicc->channel); + + g_at_chat_send(euicc->chat, buff, none_prefix, NULL, NULL, NULL); + + euicc->channel = -1; + g_free(euicc->command); + euicc->command = NULL; + euicc->length = 0; +} + +static void euicc_pending_reply(struct xmm7xxx_euicc *euicc, + const char *resp) +{ + DBusMessage *reply; + DBusMessageIter iter, array; + unsigned char *response = NULL; + long length; + int bufferBytesSize = strlen(resp) / 2; + + reply = dbus_message_new_method_return(euicc->pending); + if (reply == NULL) + goto done; + + response = g_new0(unsigned char, bufferBytesSize); + decode_hex_own_buf(resp, strlen(resp), &length, '\0', response ); + + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + DBUS_TYPE_BYTE_AS_STRING, &array); + dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE, + &response, length); + dbus_message_iter_close_container(&iter, &array); + + g_free(response); +done: + __ofono_dbus_pending_reply(&euicc->pending, reply); +} + +static DBusMessage *euicc_get_properties(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct xmm7xxx_euicc *euicc = data; + DBusMessage *reply; + DBusMessageIter iter; + DBusMessageIter dict; + const char *eid = NULL; + + reply = dbus_message_new_method_return(msg); + if (reply == NULL) + return NULL; + + dbus_message_iter_init_append(reply, &iter); + + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + OFONO_PROPERTIES_ARRAY_SIGNATURE, + &dict); + + eid = euicc->eid; + ofono_dbus_dict_append(&dict, "EID", DBUS_TYPE_STRING, &eid); + + dbus_message_iter_close_container(&iter, &dict); + + return reply; +} + +static DBusMessage *euicc_transmit_pdu(DBusConnection *conn, + DBusMessage *msg, void *data); +static DBusMessage *euicc_select_isdr_req(DBusConnection *conn, + DBusMessage *msg, void *data); +static DBusMessage *euicc_release_isdr_req(DBusConnection *conn, + DBusMessage *msg, void *data); + +static const GDBusMethodTable euicc_methods[] = { + { GDBUS_ASYNC_METHOD("TransmitLpaApdu", + GDBUS_ARGS({ "pdu", "ay" }), + GDBUS_ARGS({ "pdu", "ay" }), + euicc_transmit_pdu) }, + { GDBUS_ASYNC_METHOD("SelectISDR", + NULL, NULL, euicc_select_isdr_req) }, + { GDBUS_ASYNC_METHOD("ReleaseISDR", + NULL, NULL, euicc_release_isdr_req) }, + { GDBUS_ASYNC_METHOD("GetProperties", + NULL, GDBUS_ARGS({ "properties", "a{sv}" }), + euicc_get_properties) }, + { } +}; + +static const GDBusSignalTable euicc_signals[] = { + { GDBUS_SIGNAL("PropertyChanged", + GDBUS_ARGS({ "name", "s" }, { "value", "v" })) }, + { } +}; + +static void euicc_register(struct xmm7xxx_euicc *euicc) +{ + DBusConnection *conn = ofono_dbus_get_connection(); + const char *path = ofono_modem_get_path(euicc->modem); + + DBG("euicc_register"); + + if (!g_dbus_register_interface(conn, path, OFONO_EUICC_LPA_INTERFACE, + euicc_methods, + euicc_signals, + NULL, euicc, euicc_cleanup)) { + ofono_error("Could not register %s interface under %s", + OFONO_EUICC_LPA_INTERFACE, path); + return; + } + + ofono_modem_add_interface(euicc->modem, OFONO_EUICC_LPA_INTERFACE); + euicc->is_registered = TRUE; + + ofono_dbus_signal_property_changed(conn, path, + OFONO_EUICC_LPA_INTERFACE, "EID", + DBUS_TYPE_STRING, &euicc->eid); +} + +static void euicc_send_cmd_cb(gboolean ok, GAtResult *result, + gpointer user_data) +{ + struct xmm7xxx_euicc *euicc = user_data; + GAtResultIter iter; + int length; + const char *resp; + + DBG("ok %d", ok); + + if (!ok) { + g_free(euicc->command); + + if (!euicc->is_registered) { + g_free(euicc->eid); + g_free(euicc); + } + + return; + } + + DBG("Success"); + + g_at_result_iter_init(&iter, result); + DBG("Iter init"); + + if (!g_at_result_iter_next(&iter, "+CGLA:")) + return; + + DBG("CGLA"); + + if (!g_at_result_iter_next_number(&iter, &length)) + return; + + DBG("length = %d", length); + + if (!g_at_result_iter_next_string(&iter, &resp)) + return; + + DBG("resp = %s", resp); + + if (!euicc->is_registered) { + g_free(euicc->eid); + euicc->eid = g_strdup(resp+10); + euicc_release_isdr(euicc); + + /* eid is present register interface*/ + euicc_register(euicc); + } + + DBG("pending = %p", euicc->pending); + + if (euicc->pending) + euicc_pending_reply(euicc, resp); +} + +static void euicc_send_cmd(struct xmm7xxx_euicc *euicc) +{ + char *buff = g_new0(char, euicc->length + 20); + + sprintf(buff, "AT+CGLA=%u,%u,\"%s\"", + euicc->channel, euicc->length, euicc->command); + + g_at_chat_send(euicc->chat, buff, cgla_prefix, + euicc_send_cmd_cb, euicc, NULL); + + g_free(buff); +} + +static void euicc_select_isdr_cb(gboolean ok, GAtResult *result, + gpointer user_data) +{ + struct xmm7xxx_euicc *euicc = user_data; + GAtResultIter iter; + + DBG("ok %d", ok); + + if (!ok) { + g_free (euicc->command); + + if (!euicc->is_registered) { + g_free(euicc->eid); + g_free(euicc); + } + + return; + } + + g_at_result_iter_init(&iter, result); + + if (!g_at_result_iter_next(&iter, "+CCHO:")) + return; + + g_at_result_iter_next_number(&iter, &euicc->channel); + + if (!euicc->is_registered) + euicc_send_cmd(euicc); + + if (euicc->pending) + __ofono_dbus_pending_reply(&euicc->pending, + dbus_message_new_method_return(euicc->pending)); +} + +static void euicc_select_isdr(struct xmm7xxx_euicc *euicc) +{ + char buff[50]; + + snprintf(buff, sizeof(buff), "AT+CCHO=\"%s\"", EUICC_ISDR_AID); + + g_at_chat_send(euicc->chat, buff, ccho_prefix, + euicc_select_isdr_cb, euicc, NULL); +} + +static DBusMessage *euicc_transmit_pdu(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct xmm7xxx_euicc *euicc = data; + DBusMessageIter iter, array; + const unsigned char *command; + int length; + + DBG("euicc_transmit_pdu"); + + if (euicc->pending) + return __ofono_error_busy(msg); + + if (euicc->channel < 0) + return __ofono_error_not_available(msg); + + if (!dbus_message_iter_init(msg, &iter)) + return __ofono_error_invalid_args(msg); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) + return __ofono_error_invalid_args(msg); + + dbus_message_iter_recurse(&iter, &array); + + if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_BYTE) + return __ofono_error_invalid_args(msg); + + dbus_message_iter_get_fixed_array(&array, &command, &length); + + g_free(euicc->command); + euicc->length = length * 2; + euicc->command = g_new0(char, euicc->length + 1); + encode_hex_own_buf(command,(long)length,0, euicc->command); + euicc->pending = dbus_message_ref(msg); + + euicc_send_cmd(euicc); + + return NULL; +} + +static DBusMessage *euicc_select_isdr_req(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct xmm7xxx_euicc *euicc = data; + + DBG("euicc_select_isdr_req"); + + if (euicc->pending) + return __ofono_error_busy(msg); + + euicc_select_isdr(euicc); + + euicc->pending = dbus_message_ref(msg); + + return NULL; +} + +static DBusMessage *euicc_release_isdr_req(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct xmm7xxx_euicc *euicc = data; + + DBG("euicc_release_isdr_req"); + + if (euicc->pending) + return __ofono_error_busy(msg); + + euicc_release_isdr(euicc); + + return dbus_message_new_method_return(msg); +} + +static void euicc_update_eid(struct xmm7xxx_euicc *euicc) +{ + g_free(euicc->command); + euicc->command = g_strdup(EUICC_EID_CMD); + euicc->length = sizeof(EUICC_EID_CMD) - 1; + + euicc_select_isdr(euicc); +} + +static void xmm_euicc_enable(struct ofono_modem *modem, void *data) +{ + struct xmm7xxx_euicc *euicc = g_new0(struct xmm7xxx_euicc, 1); + + DBG("euicc enable"); + + euicc->chat = data; + euicc->modem = modem; + euicc->eid = g_strdup("INVALID"); + euicc->channel = -1; + euicc->command = NULL; + euicc->pending = NULL; + euicc->is_registered = FALSE; + + euicc_update_eid(euicc); +} + +static void xmm_euicc_disable(struct ofono_modem *modem) +{ + DBusConnection *conn = ofono_dbus_get_connection(); + const char *path = ofono_modem_get_path(modem); + + if (g_dbus_unregister_interface(conn, path, OFONO_EUICC_LPA_INTERFACE)) + ofono_modem_remove_interface(modem, OFONO_EUICC_LPA_INTERFACE); +} +/* eUICC Implementation Ends */ + /* Coex Implementation */ enum wlan_bw { WLAN_BW_UNSUPPORTED = -1, @@ -999,6 +1376,9 @@ static void switch_sim_state_status(struct ofono_modem *modem, int status) ofono_sim_initialized_notify(data->sim); break; + case 18: + data->enable_euicc = TRUE; + break; default: ofono_warn("Unknown SIM state %d received", status); break; @@ -1176,6 +1556,7 @@ static int xmm7xxx_disable(struct ofono_modem *modem) data->netreg_watch = 0; } + xmm_euicc_disable(modem); return -EINPROGRESS; } @@ -1188,6 +1569,8 @@ static void xmm7xxx_pre_sim(struct ofono_modem *modem) ofono_devinfo_create(modem, OFONO_VENDOR_IFX, "atmodem", data->chat); data->sim = ofono_sim_create(modem, OFONO_VENDOR_XMM, "atmodem", data->chat); + xmm_euicc_enable(modem, data->chat); + ofono_stk_create(modem, 0, "atmodem", data->chat); } static void set_online_cb(gboolean ok, GAtResult *result, gpointer user_data) @@ -1195,8 +1578,15 @@ static void set_online_cb(gboolean ok, GAtResult *result, gpointer user_data) struct cb_data *cbd = user_data; ofono_modem_online_cb_t cb = cbd->cb; struct ofono_error error; + struct ofono_modem *modem = cbd->data; + struct xmm7xxx_data *data = ofono_modem_get_data(modem); decode_at_error(&error, g_at_result_final_response(result)); + + if (data->enable_euicc == TRUE && data->stk_enable == TRUE) + g_at_chat_send(data->chat, "AT+CFUN=16", none_prefix, + NULL, NULL, NULL); + cb(&error, cbd->data); } @@ -1208,6 +1598,7 @@ static void xmm7xxx_set_online(struct ofono_modem *modem, ofono_bool_t online, char const *command = online ? "AT+CFUN=1" : "AT+CFUN=4"; DBG("modem %p %s", modem, online ? "online" : "offline"); + data->stk_enable = online; if (g_at_chat_send(data->chat, command, none_prefix, set_online_cb, cbd, g_free) > 0) From e086f7ebba14cf7487142012704ac6de7d50423d Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Tue, 18 Aug 2020 23:43:45 +0300 Subject: [PATCH 267/320] drivers: gemalto: add gprs-context driver Some gemalto modems provide USB ethernet interfaces for data path. Implement gprs-context driver for such modems to send data via USB ethernet rather than fallback to PPP. --- ofono/Makefile.am | 3 +- ofono/drivers/gemaltomodem/gemaltomodem.c | 4 +- ofono/drivers/gemaltomodem/gemaltomodem.h | 3 + ofono/drivers/gemaltomodem/gprs-context.c | 278 ++++++++++++++++++++++ 4 files changed, 286 insertions(+), 2 deletions(-) create mode 100644 ofono/drivers/gemaltomodem/gprs-context.c diff --git a/ofono/Makefile.am b/ofono/Makefile.am index 088932e62..1988fbe68 100644 --- a/ofono/Makefile.am +++ b/ofono/Makefile.am @@ -415,7 +415,8 @@ builtin_sources += drivers/atmodem/atutil.h \ drivers/gemaltomodem/gemaltomodem.h \ drivers/gemaltomodem/gemaltomodem.c \ drivers/gemaltomodem/location-reporting.c \ - drivers/gemaltomodem/voicecall.c + drivers/gemaltomodem/voicecall.c \ + drivers/gemaltomodem/gprs-context.c builtin_modules += xmm7modem builtin_sources += drivers/atmodem/atutil.h \ diff --git a/ofono/drivers/gemaltomodem/gemaltomodem.c b/ofono/drivers/gemaltomodem/gemaltomodem.c index 4818ac66f..4b20dd1b8 100644 --- a/ofono/drivers/gemaltomodem/gemaltomodem.c +++ b/ofono/drivers/gemaltomodem/gemaltomodem.c @@ -36,6 +36,7 @@ static int gemaltomodem_init(void) { gemalto_location_reporting_init(); + gemalto_gprs_context_init(); gemalto_voicecall_init(); return 0; @@ -43,8 +44,9 @@ static int gemaltomodem_init(void) static void gemaltomodem_exit(void) { - gemalto_voicecall_exit(); gemalto_location_reporting_exit(); + gemalto_gprs_context_exit(); + gemalto_voicecall_exit(); } OFONO_PLUGIN_DEFINE(gemaltomodem, "Gemalto modem driver", VERSION, diff --git a/ofono/drivers/gemaltomodem/gemaltomodem.h b/ofono/drivers/gemaltomodem/gemaltomodem.h index 27b1460ed..dc0d346bd 100644 --- a/ofono/drivers/gemaltomodem/gemaltomodem.h +++ b/ofono/drivers/gemaltomodem/gemaltomodem.h @@ -27,3 +27,6 @@ extern void gemalto_location_reporting_exit(); extern void gemalto_voicecall_init(); extern void gemalto_voicecall_exit(); + +extern void gemalto_gprs_context_init(); +extern void gemalto_gprs_context_exit(); diff --git a/ofono/drivers/gemaltomodem/gprs-context.c b/ofono/drivers/gemaltomodem/gprs-context.c new file mode 100644 index 000000000..73cf81a8e --- /dev/null +++ b/ofono/drivers/gemaltomodem/gprs-context.c @@ -0,0 +1,278 @@ +/* + * + * oFono - Open Source Telephony + * + * Copyright (C) 2020 Sergey Matyukevich. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "gatchat.h" +#include "gatresult.h" +#include "gattty.h" + +#include "gemaltomodem.h" + +static const char *none_prefix[] = { NULL }; + +struct gprs_context_data { + GAtChat *chat; + unsigned int active_context; + ofono_gprs_context_cb_t cb; + void *cb_data; +}; + +static void cgact_enable_cb(gboolean ok, GAtResult *result, + gpointer user_data) +{ + struct ofono_gprs_context *gc = user_data; + struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); + struct ofono_modem *modem; + const char *interface; + char buf[64]; + + DBG("ok %d", ok); + + if (!ok) { + struct ofono_error error; + + gcd->active_context = 0; + + decode_at_error(&error, g_at_result_final_response(result)); + gcd->cb(&error, gcd->cb_data); + + return; + } + + snprintf(buf, sizeof(buf), "AT^SWWAN=1,%u", gcd->active_context); + g_at_chat_send(gcd->chat, buf, none_prefix, NULL, NULL, NULL); + + modem = ofono_gprs_context_get_modem(gc); + interface = ofono_modem_get_string(modem, "NetworkInterface"); + ofono_gprs_context_set_interface(gc, interface); + + /* Use DHCP */ + ofono_gprs_context_set_ipv4_address(gc, NULL, 0); + + CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data); +} + +static void cgdcont_enable_cb(gboolean ok, GAtResult *result, + gpointer user_data) +{ + struct ofono_gprs_context *gc = user_data; + struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); + char buf[64]; + + DBG("ok %d", ok); + + if (!ok) { + struct ofono_error error; + + gcd->active_context = 0; + + decode_at_error(&error, g_at_result_final_response(result)); + gcd->cb(&error, gcd->cb_data); + + return; + } + + snprintf(buf, sizeof(buf), "AT+CGACT=1,%u", gcd->active_context); + + if (g_at_chat_send(gcd->chat, buf, none_prefix, + cgact_enable_cb, gc, NULL) == 0) + goto error; + + return; + +error: + CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data); +} + +static void gemalto_gprs_activate_primary(struct ofono_gprs_context *gc, + const struct ofono_gprs_primary_context *ctx, + ofono_gprs_context_cb_t cb, void *data) +{ + struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); + char buf[OFONO_GPRS_MAX_APN_LENGTH + 128]; + int len = 0; + + DBG("cid %u", ctx->cid); + + /* IPv6 support not implemented */ + if (ctx->proto != OFONO_GPRS_PROTO_IP) + goto error; + + gcd->active_context = ctx->cid; + gcd->cb_data = data; + gcd->cb = cb; + + len = snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IP\"", ctx->cid); + + if (ctx->apn) + snprintf(buf + len, sizeof(buf) - len - 3, ",\"%s\"", ctx->apn); + + if (g_at_chat_send(gcd->chat, buf, none_prefix, + cgdcont_enable_cb, gc, NULL) == 0) + goto error; + + return; + +error: + CALLBACK_WITH_FAILURE(cb, data); +} + +static void cgact_disable_cb(gboolean ok, GAtResult *result, + gpointer user_data) +{ + struct ofono_gprs_context *gc = user_data; + struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); + char buf[64]; + + DBG("ok %d", ok); + + if (!ok) { + CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data); + return; + } + + snprintf(buf, sizeof(buf), "AT^SWWAN=0,%u", gcd->active_context); + g_at_chat_send(gcd->chat, buf, none_prefix, NULL, NULL, NULL); + + gcd->active_context = 0; + + CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data); +} + +static void gemalto_gprs_deactivate_primary(struct ofono_gprs_context *gc, + unsigned int cid, + ofono_gprs_context_cb_t cb, + void *data) +{ + struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); + char buf[64]; + + DBG("cid %u", cid); + + gcd->cb = cb; + gcd->cb_data = data; + + snprintf(buf, sizeof(buf), "AT+CGACT=0,%u", cid); + + if (g_at_chat_send(gcd->chat, buf, none_prefix, + cgact_disable_cb, gc, NULL) == 0) + goto error; + + return; + +error: + CALLBACK_WITH_FAILURE(cb, data); + +} + +static void cgev_notify(GAtResult *result, gpointer user_data) +{ + struct ofono_gprs_context *gc = user_data; + struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); + GAtResultIter iter; + const char *event; + gint cid; + + g_at_result_iter_init(&iter, result); + + if (!g_at_result_iter_next(&iter, "+CGEV:")) + return; + + if (!g_at_result_iter_next_unquoted_string(&iter, &event)) + return; + + if (g_str_has_prefix(event, "NW PDN DEACT")) + sscanf(event, "%*s %*s %*s %u", &cid); + else if (g_str_has_prefix(event, "NW DEACT")) + sscanf(event, "%*s %*s %u", &cid); + else + return; + + DBG("cid %d, active cid: %d", cid, gcd->active_context); + + if ((unsigned int) cid != gcd->active_context) + return; + + ofono_gprs_context_deactivated(gc, gcd->active_context); + gcd->active_context = 0; +} + +static int gemalto_gprs_context_probe(struct ofono_gprs_context *gc, + unsigned int vendor, void *data) +{ + GAtChat *chat = data; + struct gprs_context_data *gcd; + + DBG(""); + + gcd = g_new0(struct gprs_context_data, 1); + + gcd->chat = g_at_chat_clone(chat); + + ofono_gprs_context_set_data(gc, gcd); + g_at_chat_register(chat, "+CGEV:", cgev_notify, FALSE, gc, NULL); + + return 0; +} + +static void gemalto_gprs_context_remove(struct ofono_gprs_context *gc) +{ + struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); + + DBG(""); + + ofono_gprs_context_set_data(gc, NULL); + g_at_chat_unref(gcd->chat); + g_free(gcd); +} + +static const struct ofono_gprs_context_driver driver = { + .name = "gemaltomodem", + .probe = gemalto_gprs_context_probe, + .remove = gemalto_gprs_context_remove, + .activate_primary = gemalto_gprs_activate_primary, + .deactivate_primary = gemalto_gprs_deactivate_primary, +}; + +void gemalto_gprs_context_init(void) +{ + ofono_gprs_context_driver_register(&driver); +} + +void gemalto_gprs_context_exit(void) +{ + ofono_gprs_context_driver_unregister(&driver); +} From df6589641cb01acbfe5f31fa4e53d0abb3335725 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Tue, 18 Aug 2020 23:43:46 +0300 Subject: [PATCH 268/320] plugins: udevng: detect gemalto network interfaces Some gemalto modems, including ELS81x, may provide more than one USB ethernet interface. Detect and save both network interfaces rather than only the last one. --- ofono/plugins/udevng.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/ofono/plugins/udevng.c b/ofono/plugins/udevng.c index 1452e8f6a..64dd9b7a0 100644 --- a/ofono/plugins/udevng.c +++ b/ofono/plugins/udevng.c @@ -1162,7 +1162,7 @@ static gboolean setup_ublox(struct modem_info *modem) static gboolean setup_gemalto(struct modem_info* modem) { const char *app = NULL, *gps = NULL, *mdm = NULL, - *net = NULL, *qmi = NULL; + *net = NULL, *qmi = NULL, *net2 = NULL; GSList *list; @@ -1197,9 +1197,14 @@ static gboolean setup_gemalto(struct modem_info* modem) else if (g_strcmp0(info->number, "04") == 0) gps = info->devnode; } + if (g_strcmp0(info->interface, "2/6/0") == 0) { - if (g_strcmp0(info->subsystem, "net") == 0) - net = info->devnode; + if (g_strcmp0(info->subsystem, "net") == 0) { + if (g_strcmp0(info->number, "0a") == 0) + net = info->devnode; + if (g_strcmp0(info->number, "0c") == 0) + net2 = info->devnode; + } } } @@ -1216,6 +1221,9 @@ static gboolean setup_gemalto(struct modem_info* modem) ofono_modem_set_string(modem->modem, "Model", modem->model); ofono_modem_set_string(modem->modem, "NetworkInterface", net); + if (net2) + ofono_modem_set_string(modem->modem, "NetworkInterface2", net2); + return TRUE; } From 3a06c7a4bd3c16e6288698b4a29f8e5339a23ce3 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Tue, 18 Aug 2020 23:43:47 +0300 Subject: [PATCH 269/320] plugins: gemalto: alternative gprs-context driver Use alternative gprs context driver for gemalto modems that provide USB ethernet interfaces for data path. --- ofono/plugins/gemalto.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ofono/plugins/gemalto.c b/ofono/plugins/gemalto.c index 13950742f..238c7cc49 100644 --- a/ofono/plugins/gemalto.c +++ b/ofono/plugins/gemalto.c @@ -588,6 +588,8 @@ static void gemalto_post_sim(struct ofono_modem *modem) struct ofono_gprs *gprs; struct ofono_gprs_context *gc; const char *model = ofono_modem_get_string(modem, "Model"); + const char *driver = NULL; + const char *iface = NULL; DBG("%p", modem); @@ -596,7 +598,15 @@ static void gemalto_post_sim(struct ofono_modem *modem) ofono_sms_create(modem, OFONO_VENDOR_GEMALTO, "atmodem", data->app); gprs = ofono_gprs_create(modem, 0, "atmodem", data->app); - gc = ofono_gprs_context_create(modem, 0, "atmodem", data->mdm); + + iface = ofono_modem_get_string(modem, "NetworkInterface"); + if (iface) { + driver = "gemaltomodem"; + } else { + driver = "atmodem"; + } + + gc = ofono_gprs_context_create(modem, 0, driver, data->mdm); if (gprs && gc) ofono_gprs_add_context(gprs, gc); From 1d4976ba9867bf133c7bb6ed16b781556255c17b Mon Sep 17 00:00:00 2001 From: Lars Poeschel Date: Fri, 21 Aug 2020 11:24:02 +0200 Subject: [PATCH 270/320] atmodem: Signal quality on quectel serial modems 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. --- ofono/drivers/atmodem/network-registration.c | 24 +++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/ofono/drivers/atmodem/network-registration.c b/ofono/drivers/atmodem/network-registration.c index 78b1994cb..c1309f612 100644 --- a/ofono/drivers/atmodem/network-registration.c +++ b/ofono/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(&iter, result); - if (!g_at_result_iter_next(&iter, "+XCSQ:")) + switch (nd->vendor) { + case OFONO_VENDOR_QUECTEL_SERIAL: + prefix = "+CSQN:"; + break; + default: + prefix = "+XCSQ:"; + break; + } + + if (!g_at_result_iter_next(&iter, prefix)) return; if (!g_at_result_iter_next_number(&iter, &rssi)) @@ -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); From 5bdfb2d247d7cd0eb6f36f3b64a925807840ae01 Mon Sep 17 00:00:00 2001 From: Lars Poeschel Date: Thu, 3 Sep 2020 11:43:21 +0200 Subject: [PATCH 271/320] xmm7xxx: Fix non compiling file CC plugins/xmm7xxx.o ../plugins/xmm7xxx.c:63:10: fatal error: dbus.h: No such file or directory 63 | #include "dbus.h" | ^~~~~~~~ compilation terminated. --- ofono/plugins/xmm7xxx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ofono/plugins/xmm7xxx.c b/ofono/plugins/xmm7xxx.c index bf90833d4..5efdbe260 100644 --- a/ofono/plugins/xmm7xxx.c +++ b/ofono/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" From 814948d0e30c41c81d8145db318c305f0f33a8c5 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Tue, 8 Sep 2020 11:19:54 -0500 Subject: [PATCH 272/320] qmimodem: Fix format warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ../../drivers/qmimodem/network-registration.c: In function ‘extract_ss_info’: ../../drivers/qmimodem/network-registration.c:131:54: warning: ‘%03d’ directive output may be truncated writing between 3 and 5 bytes into a region of size 4 [-Wformat-truncation=] 131 | snprintf(operator->mcc, OFONO_MAX_MCC_LENGTH + 1, "%03d", | ^~~~ ../../drivers/qmimodem/network-registration.c:131:53: note: directive argument in the range [0, 65535] 131 | snprintf(operator->mcc, OFONO_MAX_MCC_LENGTH + 1, "%03d", | ^~~~~~ The MCC/MNC fields are limited to three digits. Clamp the input to 999 to avoid the warning. --- ofono/drivers/qmimodem/network-registration.c | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/ofono/drivers/qmimodem/network-registration.c b/ofono/drivers/qmimodem/network-registration.c index 04f20c669..ecdc6054d 100644 --- a/ofono/drivers/qmimodem/network-registration.c +++ b/ofono/drivers/qmimodem/network-registration.c @@ -128,10 +128,18 @@ static bool extract_ss_info(struct qmi_result *result, int *status, plmn = qmi_result_get(result, QMI_NAS_RESULT_CURRENT_PLMN, &len); if (plmn) { - snprintf(operator->mcc, OFONO_MAX_MCC_LENGTH + 1, "%03d", - GUINT16_FROM_LE(plmn->mcc)); - snprintf(operator->mnc, OFONO_MAX_MNC_LENGTH + 1, "%02d", - GUINT16_FROM_LE(plmn->mnc)); + uint16_t mcc = GUINT16_FROM_LE(plmn->mcc); + uint16_t mnc = GUINT16_FROM_LE(plmn->mnc); + + if (mcc > 999) + mcc = 999; + + if (mnc > 999) + mnc = 999; + + snprintf(operator->mcc, OFONO_MAX_MCC_LENGTH + 1, "%03d", mcc); + snprintf(operator->mnc, OFONO_MAX_MNC_LENGTH + 1, "%03d", mnc); + opname_len = plmn->desc_len; if (opname_len > OFONO_MAX_OPERATOR_NAME_LENGTH) opname_len = OFONO_MAX_OPERATOR_NAME_LENGTH; @@ -311,11 +319,17 @@ static void scan_nets_cb(struct qmi_result *result, void *user_data) for (i = 0; i < num; i++) { const struct qmi_nas_network_info *netinfo = ptr + offset; + uint16_t mcc = GUINT16_FROM_LE(netinfo->mcc); + uint16_t mnc = GUINT16_FROM_LE(netinfo->mnc); + + if (mcc > 999) + mcc = 999; + + if (mnc > 999) + mnc = 999; - snprintf(list[i].mcc, OFONO_MAX_MCC_LENGTH + 1, "%03d", - GUINT16_FROM_LE(netinfo->mcc)); - snprintf(list[i].mnc, OFONO_MAX_MNC_LENGTH + 1, "%02d", - GUINT16_FROM_LE(netinfo->mnc)); + snprintf(list[i].mcc, OFONO_MAX_MCC_LENGTH + 1, "%03d", mcc); + snprintf(list[i].mnc, OFONO_MAX_MNC_LENGTH + 1, "%03d", mnc); strncpy(list[i].name, netinfo->desc, netinfo->desc_len); list[i].name[netinfo->desc_len] = '\0'; From a6d3c335295d4ffa3603c18dbf053970428af234 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Tue, 15 Sep 2020 15:23:01 +0200 Subject: [PATCH 273/320] droid 4: add special handling required for voice calls and SIM Droid 4 modem is "special" (aka broken) so it seems to need a bit of error handling. --- ofono/drivers/atmodem/sim.c | 1 + ofono/drivers/atmodem/vendor.h | 1 + ofono/drivers/atmodem/voicecall.c | 5 +++++ 3 files changed, 7 insertions(+) diff --git a/ofono/drivers/atmodem/sim.c b/ofono/drivers/atmodem/sim.c index 6ab916552..50eda6987 100644 --- a/ofono/drivers/atmodem/sim.c +++ b/ofono/drivers/atmodem/sim.c @@ -199,6 +199,7 @@ static void at_sim_read_info(struct ofono_sim *sim, int fileid, case OFONO_VENDOR_SPEEDUP: case OFONO_VENDOR_QUALCOMM_MSM: case OFONO_VENDOR_SIMCOM: + case OFONO_VENDOR_DROID: /* Maximum possible length */ len += sprintf(buf + len, ",0,0,255"); break; diff --git a/ofono/drivers/atmodem/vendor.h b/ofono/drivers/atmodem/vendor.h index 6bac7f896..82284e44b 100644 --- a/ofono/drivers/atmodem/vendor.h +++ b/ofono/drivers/atmodem/vendor.h @@ -27,6 +27,7 @@ enum ofono_vendor { OFONO_VENDOR_MBM, OFONO_VENDOR_GOBI, OFONO_VENDOR_QUALCOMM_MSM, + OFONO_VENDOR_DROID, OFONO_VENDOR_OPTION_HSO, OFONO_VENDOR_ZTE, OFONO_VENDOR_HUAWEI, diff --git a/ofono/drivers/atmodem/voicecall.c b/ofono/drivers/atmodem/voicecall.c index 65db0000e..afd128fae 100644 --- a/ofono/drivers/atmodem/voicecall.c +++ b/ofono/drivers/atmodem/voicecall.c @@ -161,6 +161,11 @@ static void clcc_poll_cb(gboolean ok, GAtResult *result, gpointer user_data) goto poll_again; } + if (vd->vendor == OFONO_VENDOR_DROID) { + poll_again = TRUE; + goto poll_again; + } + ofono_error("We are polling CLCC and received an error"); ofono_error("All bets are off for call management"); return; From b0c5a3d5ae946c2a5410b95e3ce27384e35d716a Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Tue, 15 Sep 2020 15:23:13 +0200 Subject: [PATCH 274/320] droid 4: special handling for SMSes Droid 4 modem is "special" (aka broken) so and getting incoming SMSes to work is quite tricky. This should get it right. --- ofono/drivers/atmodem/sms.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/ofono/drivers/atmodem/sms.c b/ofono/drivers/atmodem/sms.c index 5b5dd4b77..fcb9b8f10 100644 --- a/ofono/drivers/atmodem/sms.c +++ b/ofono/drivers/atmodem/sms.c @@ -463,7 +463,8 @@ static void at_cmt_notify(GAtResult *result, gpointer user_data) decode_hex_own_buf(hexpdu, -1, &pdu_len, 0, pdu); ofono_sms_deliver_notify(sms, pdu, pdu_len, tpdu_len); - if (data->vendor != OFONO_VENDOR_SIMCOM) + if (data->vendor != OFONO_VENDOR_SIMCOM && + data->vendor != OFONO_VENDOR_DROID) at_ack_delivery(sms); return; @@ -846,6 +847,7 @@ static gboolean build_cnmi_string(char *buf, int *cnmi_opts, case OFONO_VENDOR_SIMCOM: case OFONO_VENDOR_QUECTEL: case OFONO_VENDOR_QUECTEL_EC2X: + case OFONO_VENDOR_DROID: /* MSM devices advertise support for mode 2, but return an * error if we attempt to actually use it. */ mode = "1"; @@ -859,9 +861,15 @@ static gboolean build_cnmi_string(char *buf, int *cnmi_opts, if (!append_cnmi_element(buf, &len, cnmi_opts[0], mode, FALSE)) return FALSE; + mode = "21"; + if (!data->cnma_enabled) + mode = "1"; + + if (data->vendor == OFONO_VENDOR_DROID) + mode = "2"; + /* Prefer to deliver SMS via +CMT if CNMA is supported */ - if (!append_cnmi_element(buf, &len, cnmi_opts[1], - data->cnma_enabled ? "21" : "1", FALSE)) + if (!append_cnmi_element(buf, &len, cnmi_opts[1], mode, FALSE)) return FALSE; switch (data->vendor) { @@ -1291,6 +1299,8 @@ static void at_csms_query_cb(gboolean ok, GAtResult *result, goto out; switch (data->vendor) { + case OFONO_VENDOR_DROID: + break; case OFONO_VENDOR_QUECTEL_SERIAL: g_at_result_iter_next_number(&iter, &status_min); g_at_result_iter_next_number(&iter, &status_max); From 9be48fb904337c14c6e6f1aaee7abbcbe55de323 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Tue, 15 Sep 2020 15:23:25 +0200 Subject: [PATCH 275/320] droid 4: Add probing. Probe Droid 4 modem. This should result in basic support working. --- ofono/Makefile.am | 3 + ofono/plugins/droid.c | 206 +++++++++++++++++++++++++++++++++++++++++ ofono/plugins/udevng.c | 31 +++++++ 3 files changed, 240 insertions(+) create mode 100644 ofono/plugins/droid.c diff --git a/ofono/Makefile.am b/ofono/Makefile.am index 1988fbe68..35655f35d 100644 --- a/ofono/Makefile.am +++ b/ofono/Makefile.am @@ -542,6 +542,9 @@ builtin_sources += plugins/connman.c builtin_modules += mnclength builtin_sources += plugins/mnclength.c +builtin_modules += droid +builtin_sources += plugins/droid.c + if BLUETOOTH if BLUEZ4 builtin_modules += sap diff --git a/ofono/plugins/droid.c b/ofono/plugins/droid.c new file mode 100644 index 000000000..220d440b6 --- /dev/null +++ b/ofono/plugins/droid.c @@ -0,0 +1,206 @@ +/* + * + * oFono - Open Source Telephony + * + * Copyright (C) 2008-2011 Intel Corporation. All rights reserved. + * Copyright (C) 2009 Collabora Ltd. All rights reserved. + * Copyright (C) 2020 Pavel Machek. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include +#include + +#define OFONO_API_SUBJECT_TO_CHANGE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static void droid_debug(const char *str, void *user_data) +{ + const char *prefix = user_data; + + ofono_info("%s%s", prefix, str); +} + +/* Detect hardware, and initialize if found */ +static int droid_probe(struct ofono_modem *modem) +{ + DBG(""); + + return 0; +} + +static void droid_remove(struct ofono_modem *modem) +{ + GAtChat *chat = ofono_modem_get_data(modem); + + DBG(""); + + if (chat) { + g_at_chat_unref(chat); + ofono_modem_set_data(modem, NULL); + } +} + +static void cfun_set_on_cb(gboolean ok, GAtResult *result, gpointer user_data) +{ + struct ofono_modem *modem = user_data; + + DBG(""); + + if (ok) + ofono_modem_set_powered(modem, TRUE); +} + +/* power up hardware */ +static int droid_enable(struct ofono_modem *modem) +{ + GAtChat *chat; + + DBG(""); + + chat = at_util_open_device(modem, "Device", droid_debug, "", NULL); + ofono_modem_set_data(modem, chat); + + /* ensure modem is in a known state; verbose on, echo/quiet off */ + g_at_chat_send(chat, "ATE0Q0V1", NULL, NULL, NULL, NULL); + + /* power up modem */ + g_at_chat_send(chat, "AT+CFUN=1", NULL, cfun_set_on_cb, modem, NULL); + + return 0; +} + +static void cfun_set_off_cb(gboolean ok, GAtResult *result, gpointer user_data) +{ + struct ofono_modem *modem = user_data; + GAtChat *chat = ofono_modem_get_data(modem); + + DBG(""); + + g_at_chat_unref(chat); + ofono_modem_set_data(modem, NULL); + + if (ok) + ofono_modem_set_powered(modem, FALSE); +} + +static int droid_disable(struct ofono_modem *modem) +{ + GAtChat *chat = ofono_modem_get_data(modem); + + DBG(""); + + /* power down modem */ + g_at_chat_cancel_all(chat); + g_at_chat_unregister_all(chat); + g_at_chat_send(chat, "AT+CFUN=0", NULL, cfun_set_off_cb, modem, NULL); + + return -EINPROGRESS; +} + +static void droid_pre_sim(struct ofono_modem *modem) +{ + GAtChat *chat = ofono_modem_get_data(modem); + struct ofono_sim *sim; + + DBG(""); + + ofono_devinfo_create(modem, 0, "atmodem", chat); + sim = ofono_sim_create(modem, OFONO_VENDOR_DROID, "atmodem", chat); + ofono_voicecall_create(modem, OFONO_VENDOR_DROID, "atmodem", chat); + + if (sim) + ofono_sim_inserted_notify(sim, TRUE); +} + +static void droid_post_sim(struct ofono_modem *modem) +{ + GAtChat *chat = ofono_modem_get_data(modem); + struct ofono_message_waiting *mw; + + DBG(""); + + ofono_ussd_create(modem, 0, "atmodem", chat); + ofono_call_forwarding_create(modem, 0, "atmodem", chat); + ofono_call_settings_create(modem, 0, "atmodem", chat); + ofono_netreg_create(modem, 0, "atmodem", chat); + /* + * Droid 4 modem has problems with AT+CPUC?, avoid call meter for now. + */ + ofono_call_barring_create(modem, 0, "atmodem", chat); + ofono_sms_create(modem, OFONO_VENDOR_DROID, "atmodem", chat); + ofono_phonebook_create(modem, 0, "atmodem", chat); + + mw = ofono_message_waiting_create(modem); + if (mw) + ofono_message_waiting_register(mw); +} + +static struct ofono_modem_driver droid_driver = { + .name = "droid", + .probe = droid_probe, + .remove = droid_remove, + .enable = droid_enable, + .disable = droid_disable, + .pre_sim = droid_pre_sim, + .post_sim = droid_post_sim, +}; + +static int droid_init(void) +{ + return ofono_modem_driver_register(&droid_driver); +} + +static void droid_exit(void) +{ + ofono_modem_driver_unregister(&droid_driver); +} + +/* Modem in Motorola Droid has few different interfaces: + * -- gsmmux over serial -- using very non-standard commands + * -- QMI -- unfortunately not usable without gsmmux + * -- standard AT over ttyUSB4 -- unfortunately quite broken + * + * This driver is for the standard AT commands. + */ + +OFONO_PLUGIN_DEFINE(droid, "Motorola Droid modem driver", VERSION, + OFONO_PLUGIN_PRIORITY_DEFAULT, droid_init, droid_exit) diff --git a/ofono/plugins/udevng.c b/ofono/plugins/udevng.c index 64dd9b7a0..95779d7c6 100644 --- a/ofono/plugins/udevng.c +++ b/ofono/plugins/udevng.c @@ -712,6 +712,34 @@ static gboolean setup_telitqmi(struct modem_info *modem) return TRUE; } +static gboolean setup_droid(struct modem_info *modem) +{ + const char *at = NULL; + GSList *list; + + DBG("%s", modem->syspath); + + for (list = modem->devices; list; list = list->next) { + struct device_info *info = list->data; + + DBG("%s %s %s %s %s", info->devnode, info->interface, + info->number, info->label, info->subsystem); + + if (g_strcmp0(info->interface, "255/255/255") == 0 && + g_strcmp0(info->number, "04") == 0) { + at = info->devnode; + } + } + + if (at == NULL) + return FALSE; + + ofono_modem_set_string(modem->modem, "Device", at); + ofono_modem_set_driver(modem->modem, "droid"); + + return TRUE; +} + /* TODO: Not used as we have no simcom driver */ static gboolean setup_simcom(struct modem_info *modem) { @@ -1408,6 +1436,7 @@ static struct { { "gemalto", setup_gemalto }, { "xmm7xxx", setup_xmm7xxx }, { "mbim", setup_mbim }, + { "droid", setup_droid }, /* Following are non-USB modems */ { "ifx", setup_ifx }, { "u8500", setup_isi_serial }, @@ -1793,6 +1822,8 @@ static struct { { "telit", "cdc_acm", "1bc7", "0021" }, { "telitqmi", "qmi_wwan", "1bc7", "1201" }, { "telitqmi", "option", "1bc7", "1201" }, + { "droid", "qmi_wwan", "22b8", "2a70" }, + { "droid", "option", "22b8", "2a70" }, { "nokia", "option", "0421", "060e" }, { "nokia", "option", "0421", "0623" }, { "samsung", "option", "04e8", "6889" }, From dc50e4d6158742eea8d730f7fcf696e7304e1525 Mon Sep 17 00:00:00 2001 From: Christophe Ronco Date: Mon, 28 Sep 2020 09:38:09 +0200 Subject: [PATCH 276/320] common: APN with a dot in second position are not invalid APN with a dot in second position (example: "t.est") are wrongly considered invalid. --- ofono/src/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/src/common.c b/ofono/src/common.c index 68721d8b4..ff2f26169 100644 --- a/ofono/src/common.c +++ b/ofono/src/common.c @@ -721,7 +721,7 @@ const char *registration_tech_to_string(enum ofono_access_technology tech) gboolean is_valid_apn(const char *apn) { int i; - int last_period = 0; + int last_period = -1; if (apn == NULL) return FALSE; From a1ba388750d8afa2155575d38b8d8426089ac119 Mon Sep 17 00:00:00 2001 From: Nikhil Jha Date: Tue, 25 Aug 2020 13:12:39 -0700 Subject: [PATCH 277/320] build: remove obsolete m4 macro As per https://www.gnu.org/software/libtool/manual/html_node/LT_005fINIT.html LT_INIT should be used instead. --- ofono/configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/configure.ac b/ofono/configure.ac index 1c316412f..9eca52fcd 100644 --- a/ofono/configure.ac +++ b/ofono/configure.ac @@ -28,7 +28,7 @@ m4_define([_LT_AC_TAGCONFIG], []) m4_ifdef([AC_LIBTOOL_TAGS], [AC_LIBTOOL_TAGS([])]) AC_DISABLE_STATIC -AC_PROG_LIBTOOL +LT_INIT AC_ARG_ENABLE(optimization, AC_HELP_STRING([--disable-optimization], [disable code optimization through compiler]), [ From 6c062dcdfd1597c52e0d555ddbc22d0841385292 Mon Sep 17 00:00:00 2001 From: Lars Poeschel Date: Thu, 24 Sep 2020 12:38:05 +0200 Subject: [PATCH 278/320] quectel: Extend power-on timeout 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. --- ofono/plugins/quectel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 8a21d09f4..d634d29f6 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -1088,8 +1088,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; } From d7b62834796bc987b5ed76f4e75de1197531914f Mon Sep 17 00:00:00 2001 From: Lars Poeschel Date: Tue, 6 Oct 2020 12:10:22 +0200 Subject: [PATCH 279/320] 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. 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. --- ofono/plugins/quectel.c | 45 +++++++++++++++++++++++++++++++++++++++-- ofono/plugins/udevng.c | 5 +++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index d634d29f6..2dff96847 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/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; }; @@ -193,6 +194,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); @@ -236,10 +238,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 = 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, &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; + uint32_t gpio_value = 1; DBG("%p", modem); @@ -260,7 +274,20 @@ static void close_serial(struct ofono_modem *modem) else close_ngsm(modem); - l_gpio_writer_set(data->gpio, 1, &gpio_value); + if (data->gpio) { + if (ofono_modem_get_boolean(modem, "GpioLevel")) { + gpio_value = 0; + l_gpio_writer_set(data->gpio, 1, &gpio_value); + } else { + l_gpio_writer_set(data->gpio, 1, &gpio_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); } @@ -1098,6 +1125,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, &gpio_value); +} + static int open_serial(struct ofono_modem *modem) { struct quectel_data *data = ofono_modem_get_data(modem); @@ -1141,6 +1178,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/ofono/plugins/udevng.c b/ofono/plugins/udevng.c index 95779d7c6..2abb40820 100644 --- a/ofono/plugins/udevng.c +++ b/ofono/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) From b524a928cd649b0abf48b1ce6c698d0fd5ccd0b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Sun, 20 Dec 2020 11:18:27 +0000 Subject: [PATCH 280/320] huawei: Fix implicit enum conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GCC 10 warns about this implicit conversion: drivers/huaweimodem/radio-settings.c: In function ‘band_gsm_from_huawei’: drivers/huaweimodem/radio-settings.c:107:10: error: implicit conversion from ‘enum ofono_radio_band_umts’ to ‘enum ofono_radio_band_gsm’ [-Werror=enum-conversion] 107 | return OFONO_RADIO_BAND_UMTS_ANY; Member from the incorrect enum was returned, both had the value 0, so the code would still work. --- ofono/drivers/huaweimodem/radio-settings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/drivers/huaweimodem/radio-settings.c b/ofono/drivers/huaweimodem/radio-settings.c index c8ebcba04..b3f31e56c 100644 --- a/ofono/drivers/huaweimodem/radio-settings.c +++ b/ofono/drivers/huaweimodem/radio-settings.c @@ -104,7 +104,7 @@ static enum ofono_radio_band_gsm band_gsm_from_huawei(unsigned int band) size_t i; if (band == HUAWEI_BAND_ANY) - return OFONO_RADIO_BAND_UMTS_ANY; + return OFONO_RADIO_BAND_GSM_ANY; for (i = ARRAY_SIZE(huawei_band_gsm_table) - 1; i > 0; i--) { if (huawei_band_gsm_table[i].band_huawei & band) From c5d51f101ff1ccd23a3f169d69be7f3b0f9766bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Sun, 20 Dec 2020 11:18:27 +0000 Subject: [PATCH 281/320] util: Fix implicit enum conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GCC10 complains about the following: src/smsutil.c: In function ‘sms_text_prepare_with_alphabet’: src/smsutil.c:3594:8: error: implicit conversion from ‘enum sms_alphabet’ to ‘enum gsm_dialect’ [-Werror=enum-conversion] 3594 | alphabet, &used_locking, smsutil and util has an enum each for representing the same thing; The SMS alphabet. They share the same values, so an explicit type cast makes GCC happy. --- ofono/src/smsutil.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ofono/src/smsutil.c b/ofono/src/smsutil.c index 20c201a70..747429aea 100644 --- a/ofono/src/smsutil.c +++ b/ofono/src/smsutil.c @@ -3571,6 +3571,7 @@ GSList *sms_text_prepare_with_alphabet(const char *to, const char *utf8, GSList *r = NULL; enum gsm_dialect used_locking; enum gsm_dialect used_single; + enum gsm_dialect dialect; memset(&template, 0, sizeof(struct sms)); template.type = SMS_TYPE_SUBMIT; @@ -3582,12 +3583,14 @@ GSList *sms_text_prepare_with_alphabet(const char *to, const char *utf8, template.submit.vp.relative = 0xA7; /* 24 Hours */ sms_address_from_string(&template.submit.daddr, to); + /* There are two enums for the same thing */ + dialect = (enum gsm_dialect)alphabet; /* * UDHI, UDL, UD and DCS actually depend on the contents of * the text, and also on the GSM dialect we use to encode it. */ gsm_encoded = convert_utf8_to_gsm_best_lang(utf8, -1, NULL, &written, 0, - alphabet, &used_locking, + dialect, &used_locking, &used_single); if (gsm_encoded == NULL) { gsize converted; From ee77578321dac21fe8342ba54c6b491591d3291a Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Tue, 22 Dec 2020 10:32:12 -0600 Subject: [PATCH 282/320] build: Add check for rawmemchr Otherwise the build will complain about multiple definitions --- ofono/configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/ofono/configure.ac b/ofono/configure.ac index 9eca52fcd..40c6004a6 100644 --- a/ofono/configure.ac +++ b/ofono/configure.ac @@ -56,6 +56,7 @@ AC_ARG_ENABLE(pie, AC_HELP_STRING([--enable-pie], ]) AC_CHECK_FUNCS(explicit_bzero) +AC_CHECK_FUNCS(rawmemchr) AC_CHECK_FUNC(signalfd, dummy=yes, AC_MSG_ERROR(signalfd support is required)) From 02e542d9ea1e32921072bb204dd450370d40fe73 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Mon, 21 Dec 2020 23:01:29 +0300 Subject: [PATCH 283/320] plugin: gemalto: fix source of gprs notifications Modem USB interface does not receive certain gprs context notifications. Fix gprs chat: use Application USB interface to receive all the modem notifications. --- ofono/plugins/gemalto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ofono/plugins/gemalto.c b/ofono/plugins/gemalto.c index 238c7cc49..28ee3affa 100644 --- a/ofono/plugins/gemalto.c +++ b/ofono/plugins/gemalto.c @@ -606,7 +606,7 @@ static void gemalto_post_sim(struct ofono_modem *modem) driver = "atmodem"; } - gc = ofono_gprs_context_create(modem, 0, driver, data->mdm); + gc = ofono_gprs_context_create(modem, 0, driver, data->app); if (gprs && gc) ofono_gprs_add_context(gprs, gc); From ca71e5e9459b22e59f0be710d0b8aef49787e584 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Mon, 21 Dec 2020 23:01:30 +0300 Subject: [PATCH 284/320] gemalto: gprs: cgev gprs context deactivation Gemalto ELS81x modems use 'ME PDN DEACT' message to notify about gprs context deactivation. Process this 'deactivate' event in CGEV handler. --- ofono/drivers/gemaltomodem/gprs-context.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ofono/drivers/gemaltomodem/gprs-context.c b/ofono/drivers/gemaltomodem/gprs-context.c index 73cf81a8e..322a5f985 100644 --- a/ofono/drivers/gemaltomodem/gprs-context.c +++ b/ofono/drivers/gemaltomodem/gprs-context.c @@ -216,6 +216,8 @@ static void cgev_notify(GAtResult *result, gpointer user_data) if (g_str_has_prefix(event, "NW PDN DEACT")) sscanf(event, "%*s %*s %*s %u", &cid); + else if (g_str_has_prefix(event, "ME PDN DEACT")) + sscanf(event, "%*s %*s %*s %u", &cid); else if (g_str_has_prefix(event, "NW DEACT")) sscanf(event, "%*s %*s %u", &cid); else From b727bd3db7eb52db6fe5385e596fa2de6e4a0ed9 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Mon, 21 Dec 2020 23:01:32 +0300 Subject: [PATCH 285/320] gemalto: gprs: support different gprs protocols Add support for IPv6 and dual mode gprs contexts. --- ofono/drivers/gemaltomodem/gprs-context.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/ofono/drivers/gemaltomodem/gprs-context.c b/ofono/drivers/gemaltomodem/gprs-context.c index 322a5f985..9bf89c84b 100644 --- a/ofono/drivers/gemaltomodem/gprs-context.c +++ b/ofono/drivers/gemaltomodem/gprs-context.c @@ -46,6 +46,7 @@ static const char *none_prefix[] = { NULL }; struct gprs_context_data { GAtChat *chat; unsigned int active_context; + enum ofono_gprs_proto proto; ofono_gprs_context_cb_t cb; void *cb_data; }; @@ -127,15 +128,25 @@ static void gemalto_gprs_activate_primary(struct ofono_gprs_context *gc, DBG("cid %u", ctx->cid); - /* IPv6 support not implemented */ - if (ctx->proto != OFONO_GPRS_PROTO_IP) - goto error; - gcd->active_context = ctx->cid; gcd->cb_data = data; gcd->cb = cb; - len = snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IP\"", ctx->cid); + + switch (ctx->proto) { + case OFONO_GPRS_PROTO_IP: + len = snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IP\"", + ctx->cid); + break; + case OFONO_GPRS_PROTO_IPV6: + len = snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IPV6\"", + ctx->cid); + break; + case OFONO_GPRS_PROTO_IPV4V6: + len = snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IPV4V6\"", + ctx->cid); + break; + } if (ctx->apn) snprintf(buf + len, sizeof(buf) - len - 3, ",\"%s\"", ctx->apn); @@ -146,7 +157,6 @@ static void gemalto_gprs_activate_primary(struct ofono_gprs_context *gc, return; -error: CALLBACK_WITH_FAILURE(cb, data); } From 67de2ff25bbf926c6c299417e230203992e72465 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Sat, 26 Dec 2020 11:35:24 -0600 Subject: [PATCH 286/320] gemalto: Fix compiler error Fix compiler error introduced due to a bad merge Fixes: de0d5a19 ("gemalto: gprs: support different gprs protocols") --- ofono/drivers/gemaltomodem/gprs-context.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ofono/drivers/gemaltomodem/gprs-context.c b/ofono/drivers/gemaltomodem/gprs-context.c index 9bf89c84b..13a858d46 100644 --- a/ofono/drivers/gemaltomodem/gprs-context.c +++ b/ofono/drivers/gemaltomodem/gprs-context.c @@ -152,10 +152,8 @@ static void gemalto_gprs_activate_primary(struct ofono_gprs_context *gc, snprintf(buf + len, sizeof(buf) - len - 3, ",\"%s\"", ctx->apn); if (g_at_chat_send(gcd->chat, buf, none_prefix, - cgdcont_enable_cb, gc, NULL) == 0) - goto error; - - return; + cgdcont_enable_cb, gc, NULL) > 0) + return; CALLBACK_WITH_FAILURE(cb, data); } From dade1d504d0b8812eef7540cb6e5959d7629d745 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Sat, 26 Dec 2020 23:56:41 +0300 Subject: [PATCH 287/320] gemalto: gprs: support automatic context activation Implement read_settings function to get configuration for automatic contexts. AT^SWWAN command activates PDP context unless it has been already activated automatically, and then starts DHCP server in the ME. So AT^SWWAN command should be run for automatic context as well in order to obtain IP settings from the ME. This commit also fixes the issue uncovered by the added support for automatic contexts: as per modem specs, AT+CGACT context should not be reused for AT^SWWAN. Though that worked for some reason when automatic context was reactivated without proper deactivation. Note that in both cases success code is reported to the core before AT^SWWAN response. This is because the ME waits until DHCP negotiation has finished before sending the "OK" or "ERROR" result code. --- ofono/drivers/gemaltomodem/gprs-context.c | 116 +++++++++++++--------- 1 file changed, 69 insertions(+), 47 deletions(-) diff --git a/ofono/drivers/gemaltomodem/gprs-context.c b/ofono/drivers/gemaltomodem/gprs-context.c index 13a858d46..99cb4114b 100644 --- a/ofono/drivers/gemaltomodem/gprs-context.c +++ b/ofono/drivers/gemaltomodem/gprs-context.c @@ -51,70 +51,63 @@ struct gprs_context_data { void *cb_data; }; -static void cgact_enable_cb(gboolean ok, GAtResult *result, - gpointer user_data) +static void set_gprs_context_interface(struct ofono_gprs_context *gc) { - struct ofono_gprs_context *gc = user_data; - struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); struct ofono_modem *modem; const char *interface; - char buf[64]; + + modem = ofono_gprs_context_get_modem(gc); + interface = ofono_modem_get_string(modem, "NetworkInterface"); + ofono_gprs_context_set_interface(gc, interface); + + /* Use DHCP */ + ofono_gprs_context_set_ipv4_address(gc, NULL, 0); +} + +static void swwan_cb(gboolean ok, GAtResult *result, gpointer user_data) +{ + struct ofono_gprs_context *gc = user_data; + struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); + struct ofono_error error; DBG("ok %d", ok); if (!ok) { - struct ofono_error error; - + ofono_error("Unable to activate context"); + ofono_gprs_context_deactivated(gc, gcd->active_context); gcd->active_context = 0; - decode_at_error(&error, g_at_result_final_response(result)); gcd->cb(&error, gcd->cb_data); - return; } - - snprintf(buf, sizeof(buf), "AT^SWWAN=1,%u", gcd->active_context); - g_at_chat_send(gcd->chat, buf, none_prefix, NULL, NULL, NULL); - - modem = ofono_gprs_context_get_modem(gc); - interface = ofono_modem_get_string(modem, "NetworkInterface"); - ofono_gprs_context_set_interface(gc, interface); - - /* Use DHCP */ - ofono_gprs_context_set_ipv4_address(gc, NULL, 0); - - CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data); } static void cgdcont_enable_cb(gboolean ok, GAtResult *result, - gpointer user_data) + gpointer user_data) { struct ofono_gprs_context *gc = user_data; struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); + struct ofono_error error; char buf[64]; DBG("ok %d", ok); if (!ok) { - struct ofono_error error; - gcd->active_context = 0; - decode_at_error(&error, g_at_result_final_response(result)); gcd->cb(&error, gcd->cb_data); - return; } - snprintf(buf, sizeof(buf), "AT+CGACT=1,%u", gcd->active_context); + snprintf(buf, sizeof(buf), "AT^SWWAN=1,%u", gcd->active_context); - if (g_at_chat_send(gcd->chat, buf, none_prefix, - cgact_enable_cb, gc, NULL) == 0) - goto error; + if (g_at_chat_send(gcd->chat, buf, none_prefix, swwan_cb, gc, NULL)) { + set_gprs_context_interface(gc); - return; + CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data); + return; + } -error: CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data); } @@ -152,31 +145,27 @@ static void gemalto_gprs_activate_primary(struct ofono_gprs_context *gc, snprintf(buf + len, sizeof(buf) - len - 3, ",\"%s\"", ctx->apn); if (g_at_chat_send(gcd->chat, buf, none_prefix, - cgdcont_enable_cb, gc, NULL) > 0) + cgdcont_enable_cb, gc, NULL)) return; CALLBACK_WITH_FAILURE(cb, data); } -static void cgact_disable_cb(gboolean ok, GAtResult *result, - gpointer user_data) +static void deactivate_cb(gboolean ok, GAtResult *result, + gpointer user_data) { struct ofono_gprs_context *gc = user_data; struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); - char buf[64]; DBG("ok %d", ok); + gcd->active_context = 0; + if (!ok) { CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data); return; } - snprintf(buf, sizeof(buf), "AT^SWWAN=0,%u", gcd->active_context); - g_at_chat_send(gcd->chat, buf, none_prefix, NULL, NULL, NULL); - - gcd->active_context = 0; - CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data); } @@ -193,17 +182,49 @@ static void gemalto_gprs_deactivate_primary(struct ofono_gprs_context *gc, gcd->cb = cb; gcd->cb_data = data; - snprintf(buf, sizeof(buf), "AT+CGACT=0,%u", cid); + snprintf(buf, sizeof(buf), "AT^SWWAN=0,%u", gcd->active_context); if (g_at_chat_send(gcd->chat, buf, none_prefix, - cgact_disable_cb, gc, NULL) == 0) - goto error; - - return; + deactivate_cb, gc, NULL)) + return; -error: CALLBACK_WITH_FAILURE(cb, data); +} +static void gemalto_gprs_read_settings(struct ofono_gprs_context *gc, + unsigned int cid, + ofono_gprs_context_cb_t cb, void *data) +{ + struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); + char buf[64]; + + DBG("cid %u", cid); + + gcd->active_context = cid; + gcd->cb = cb; + gcd->cb_data = data; + + /* + * AT^SWWAN command activates PDP context unless it has been already + * activated automatically, and then starts DHCP server in the ME. + * So AT^SWWAN command should be run in both cases: + * - when activate context and then obtain IP address from the ME + * - when obtain IP address from the automatically activated context + * + * Note that the ME waits until DHCP negotiation has finished before + * sending the "OK" or "ERROR" result code. So success is reported + * to the core before AT^SWWAN response. + */ + snprintf(buf, sizeof(buf), "AT^SWWAN=1,%u", gcd->active_context); + + if (g_at_chat_send(gcd->chat, buf, none_prefix, swwan_cb, gc, NULL)) { + set_gprs_context_interface(gc); + + CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data); + return; + } + + CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data); } static void cgev_notify(GAtResult *result, gpointer user_data) @@ -275,6 +296,7 @@ static const struct ofono_gprs_context_driver driver = { .remove = gemalto_gprs_context_remove, .activate_primary = gemalto_gprs_activate_primary, .deactivate_primary = gemalto_gprs_deactivate_primary, + .read_settings = gemalto_gprs_read_settings, }; void gemalto_gprs_context_init(void) From d4bc0f2fcf7cacd64e46a12cd59ce577cc1b61b9 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Sat, 26 Dec 2020 23:56:42 +0300 Subject: [PATCH 288/320] gemalto: gprs: support authentication settings Add support for gprs contexts with username, password, and specific authentication type. --- ofono/drivers/gemaltomodem/gprs-context.c | 53 ++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/ofono/drivers/gemaltomodem/gprs-context.c b/ofono/drivers/gemaltomodem/gprs-context.c index 99cb4114b..c0837bedb 100644 --- a/ofono/drivers/gemaltomodem/gprs-context.c +++ b/ofono/drivers/gemaltomodem/gprs-context.c @@ -46,6 +46,9 @@ static const char *none_prefix[] = { NULL }; struct gprs_context_data { GAtChat *chat; unsigned int active_context; + char username[OFONO_GPRS_MAX_USERNAME_LENGTH + 1]; + char password[OFONO_GPRS_MAX_PASSWORD_LENGTH + 1]; + int auth_type; enum ofono_gprs_proto proto; ofono_gprs_context_cb_t cb; void *cb_data; @@ -82,7 +85,7 @@ static void swwan_cb(gboolean ok, GAtResult *result, gpointer user_data) } } -static void cgdcont_enable_cb(gboolean ok, GAtResult *result, +static void sgauth_enable_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_gprs_context *gc = user_data; @@ -111,6 +114,38 @@ static void cgdcont_enable_cb(gboolean ok, GAtResult *result, CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data); } +static void cgdcont_enable_cb(gboolean ok, GAtResult *result, + gpointer user_data) +{ + struct ofono_gprs_context *gc = user_data; + struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); + struct ofono_error error; + char buf[384]; + + DBG("ok %d", ok); + + if (!ok) { + gcd->active_context = 0; + decode_at_error(&error, g_at_result_final_response(result)); + gcd->cb(&error, gcd->cb_data); + return; + } + + if (gcd->username[0] && gcd->password[0]) + sprintf(buf, "AT^SGAUTH=%u,%u,\"%s\",\"%s\"", + gcd->active_context, gcd->auth_type, + gcd->username, gcd->password); + else + sprintf(buf, "AT^SGAUTH=%u,%u,\"\",\"\"", + gcd->active_context, gcd->auth_type); + + if (g_at_chat_send(gcd->chat, buf, none_prefix, + sgauth_enable_cb, gc, NULL) > 0) + return; + + CALLBACK_WITH_FAILURE(gcd->cb, gcd->cb_data); +} + static void gemalto_gprs_activate_primary(struct ofono_gprs_context *gc, const struct ofono_gprs_primary_context *ctx, ofono_gprs_context_cb_t cb, void *data) @@ -125,6 +160,22 @@ static void gemalto_gprs_activate_primary(struct ofono_gprs_context *gc, gcd->cb_data = data; gcd->cb = cb; + memcpy(gcd->username, ctx->username, sizeof(ctx->username)); + memcpy(gcd->password, ctx->password, sizeof(ctx->password)); + gcd->proto = ctx->proto; + + switch (ctx->auth_method) { + case OFONO_GPRS_AUTH_METHOD_PAP: + gcd->auth_type = 1; + break; + case OFONO_GPRS_AUTH_METHOD_CHAP: + gcd->auth_type = 2; + break; + case OFONO_GPRS_AUTH_METHOD_NONE: + default: + gcd->auth_type = 0; + break; + } switch (ctx->proto) { case OFONO_GPRS_PROTO_IP: From babcc8c6df3af5494e87ac2bf4dcd2daddb100ad Mon Sep 17 00:00:00 2001 From: Sergei Golubtsov Date: Thu, 7 Jan 2021 23:40:15 +0300 Subject: [PATCH 289/320] gsmdial: adding support for selection of authentication method Selection capability for authentication method via a command line argument has been added --- ofono/gatchat/gsmdial.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ofono/gatchat/gsmdial.c b/ofono/gatchat/gsmdial.c index 60e4f2451..09dd85049 100644 --- a/ofono/gatchat/gsmdial.c +++ b/ofono/gatchat/gsmdial.c @@ -53,6 +53,7 @@ static gint option_cid = 0; static gchar *option_apn = NULL; static gint option_offmode = 0; static gboolean option_legacy = FALSE; +static gchar *option_auth_method; static gchar *option_username = NULL; static gchar *option_password = NULL; static gchar *option_pppdump = NULL; @@ -369,6 +370,11 @@ static void connect_cb(gboolean ok, GAtResult *result, gpointer user_data) } g_at_ppp_set_debug(ppp, gsmdial_debug, "PPP"); + if (option_auth_method && strcmp(option_auth_method, "PAP") == 0) + g_at_ppp_set_auth_method(ppp, G_AT_PPP_AUTH_METHOD_PAP); + else if (option_auth_method && strcmp(option_auth_method, "NONE") == 0) + g_at_ppp_set_auth_method(ppp, G_AT_PPP_AUTH_METHOD_NONE); + g_at_ppp_set_credentials(ppp, option_username, option_password); g_at_ppp_set_acfc_enabled(ppp, option_acfc); @@ -677,6 +683,10 @@ static GOptionEntry options[] = { "Use ATD*99***#" }, { "bluetooth", 'b', 0, G_OPTION_ARG_NONE, &option_bluetooth, "Use only ATD*99" }, + { "auth", 'A', 0, G_OPTION_ARG_STRING, &option_auth_method, + "Specify the authentication method for the PPP" + " connection: CHAP, PAP or NONE. CHAP is used" + " by default." }, { "username", 'u', 0, G_OPTION_ARG_STRING, &option_username, "Specify PPP username" }, { "password", 'w', 0, G_OPTION_ARG_STRING, &option_password, From b4b4431d32aa38435ea74b3496d5cd9949336162 Mon Sep 17 00:00:00 2001 From: Sergei Golubtsov Date: Thu, 7 Jan 2021 23:40:16 +0300 Subject: [PATCH 290/320] ppp: using RX ACCM = 0 by default Some modems such as Quectel EC200T do not honor the default value for the Async-Control-Character-Map (ACCM) configuration option defined in RFC 1548 6.2 as 0xffffffff. This patch suggests to use RX ACCM = 0 for Ofono by default as pppd does for instance. This will reduce PPP data overhead as well. --- ofono/gatchat/gatppp.c | 5 +++++ ofono/gatchat/gatppp.h | 1 + ofono/gatchat/ppp.h | 1 + ofono/gatchat/ppp_lcp.c | 15 ++++++++++++++- 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/ofono/gatchat/gatppp.c b/ofono/gatchat/gatppp.c index 141e27469..259e6d5cf 100644 --- a/ofono/gatchat/gatppp.c +++ b/ofono/gatchat/gatppp.c @@ -806,6 +806,11 @@ void g_at_ppp_set_server_info(GAtPPP *ppp, const char *remote, ipcp_set_server_info(ppp->ipcp, r, d1, d2); } +void g_at_ppp_set_accm(GAtPPP *ppp, guint32 accm) +{ + lcp_set_accm(ppp->lcp, accm); +} + void g_at_ppp_set_acfc_enabled(GAtPPP *ppp, gboolean enabled) { lcp_set_acfc_enabled(ppp->lcp, enabled); diff --git a/ofono/gatchat/gatppp.h b/ofono/gatchat/gatppp.h index dd203c28f..a12e42e31 100644 --- a/ofono/gatchat/gatppp.h +++ b/ofono/gatchat/gatppp.h @@ -88,6 +88,7 @@ void g_at_ppp_set_recording(GAtPPP *ppp, const char *filename); void g_at_ppp_set_server_info(GAtPPP *ppp, const char *remote_ip, const char *dns1, const char *dns2); +void g_at_ppp_set_accm(GAtPPP *ppp, guint32 accm); void g_at_ppp_set_acfc_enabled(GAtPPP *ppp, gboolean enabled); void g_at_ppp_set_pfc_enabled(GAtPPP *ppp, gboolean enabled); diff --git a/ofono/gatchat/ppp.h b/ofono/gatchat/ppp.h index ac1a7ef26..6c02b0539 100644 --- a/ofono/gatchat/ppp.h +++ b/ofono/gatchat/ppp.h @@ -90,6 +90,7 @@ static inline void __put_unaligned_short(void *p, guint16 val) struct pppcp_data *lcp_new(GAtPPP *ppp, gboolean dormant); void lcp_free(struct pppcp_data *lcp); void lcp_protocol_reject(struct pppcp_data *lcp, guint8 *packet, gsize len); +void lcp_set_accm(struct pppcp_data *pppcp, guint32 accm); void lcp_set_acfc_enabled(struct pppcp_data *pppcp, gboolean enabled); void lcp_set_pfc_enabled(struct pppcp_data *pppcp, gboolean enabled); diff --git a/ofono/gatchat/ppp_lcp.c b/ofono/gatchat/ppp_lcp.c index 3fe38217c..7c45a27f3 100644 --- a/ofono/gatchat/ppp_lcp.c +++ b/ofono/gatchat/ppp_lcp.c @@ -121,7 +121,9 @@ static void lcp_generate_config_options(struct lcp_data *lcp) static void lcp_reset_config_options(struct lcp_data *lcp) { - /* Using the default ACCM */ + /* Using RX ACCM = 0 instead of the default ACCM */ + lcp->accm = 0; + lcp->req_options |= REQ_OPTION_ACCM; lcp_generate_config_options(lcp); } @@ -398,6 +400,17 @@ struct pppcp_data *lcp_new(GAtPPP *ppp, gboolean is_server) return pppcp; } +void lcp_set_accm(struct pppcp_data *pppcp, guint32 accm) +{ + struct lcp_data *lcp = pppcp_get_data(pppcp); + + lcp->accm = accm; + lcp->req_options |= REQ_OPTION_ACCM; + + lcp_generate_config_options(lcp); + pppcp_set_local_options(pppcp, lcp->options, lcp->options_len); +} + void lcp_set_acfc_enabled(struct pppcp_data *pppcp, gboolean enabled) { struct lcp_data *lcp = pppcp_get_data(pppcp); From 3ced3c05966cbba3fc0f4f3b5ad0e98a8e24cef1 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Thu, 7 Jan 2021 23:21:09 -0600 Subject: [PATCH 291/320] AUTHORS: Mention Sergei's contributions --- ofono/AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/ofono/AUTHORS b/ofono/AUTHORS index b5cb0f793..f450d1f95 100644 --- a/ofono/AUTHORS +++ b/ofono/AUTHORS @@ -151,3 +151,4 @@ Jimmy Gysens Sergey Matyukevich Shweta Jain JongSeok Won +Sergei Golubtsov From 3b82c0030e419b366c7b1db9749970e1fc4336e3 Mon Sep 17 00:00:00 2001 From: Sergei Golubtsov Date: Thu, 7 Jan 2021 23:40:17 +0300 Subject: [PATCH 292/320] quectel: adding support for the Quectel EC200 USB modem series Support for the Quectel EC200 USB modem series has been added. The model identification AT command has been added as the first step in the communication with a Quectel USB modem. --- ofono/plugins/quectel.c | 128 +++++++++++++++++++++++++--------------- ofono/plugins/udevng.c | 6 +- 2 files changed, 85 insertions(+), 49 deletions(-) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index 2dff96847..c625a8d5a 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/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", - "EC21", NULL }; + "EC21", "EC200", NULL }; static const char *none_prefix[] = { NULL }; static const uint8_t gsm0710_terminate[] = { @@ -84,6 +84,7 @@ enum quectel_model { QUECTEL_M95, QUECTEL_MC60, QUECTEL_EC21, + QUECTEL_EC200, }; struct quectel_data { @@ -127,6 +128,15 @@ enum quectel_power_event { static const char dbus_hw_interface[] = OFONO_SERVICE ".quectel.Hardware"; +static ofono_bool_t has_serial_connection(struct ofono_modem *modem) +{ + + if (ofono_modem_get_string(modem, "Device")) + return TRUE; + + return FALSE; +} + static void quectel_debug(const char *str, void *user_data) { const char *prefix = user_data; @@ -545,6 +555,7 @@ static void dbus_hw_enable(struct ofono_modem *modem) switch (data->model) { case QUECTEL_UC15: case QUECTEL_EC21: + case QUECTEL_EC200: g_at_chat_register(data->aux, "+QIND", qind_notify, FALSE, hw, NULL); break; @@ -593,6 +604,13 @@ static void qinistat_cb(gboolean ok, GAtResult *result, gpointer user_data) /* UC15 uses a bitmap of 1 + 2 + 4 = 7 */ ready = 7; break; + case QUECTEL_EC200: + /* + * EC200T doesn't indicate that the Phonebook initialization + * is completed (==4) when AT+CFUN=4, that's why 1 + 2 = 3 + */ + ready = 3; + break; case QUECTEL_M95: case QUECTEL_MC60: /* M95 and MC60 uses a counter to 3 */ @@ -809,6 +827,9 @@ static void setup_aux(struct ofono_modem *modem) NULL, NULL, NULL); g_at_chat_send(data->aux, "AT+QURCCFG=\"urcport\",\"uart1\"", none_prefix, NULL, NULL, NULL); + } else if (data->model == QUECTEL_EC200) { + g_at_chat_send(data->aux, "ATE0; &C0; +CMEE=1", none_prefix, + NULL, NULL, NULL); } else g_at_chat_send(data->aux, "ATE0; &C0; +CMEE=1; +QIURC=0", none_prefix, NULL, NULL, NULL); @@ -817,6 +838,59 @@ static void setup_aux(struct ofono_modem *modem) NULL); } +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, "", &model)) { + 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_EC2X; + data->model = QUECTEL_EC21; + } else if (strstr(model, "EC200")) { + DBG("%p model %s", modem, model); + data->vendor = OFONO_VENDOR_QUECTEL_EC2X; + data->model = QUECTEL_EC200; + } else { + ofono_warn("%p unknown model: '%s'", modem, model); + data->vendor = OFONO_VENDOR_QUECTEL; + data->model = QUECTEL_UNKNOWN; + } + + setup_aux(modem); +} + +static void identify_model(struct ofono_modem *modem) +{ + struct quectel_data *data = ofono_modem_get_data(modem); + + DBG("%p", modem); + + g_at_chat_send(data->aux, "AT+CGMM", cgmm_prefix, cgmm_cb, modem, + NULL); +} + static int open_ttys(struct ofono_modem *modem) { struct quectel_data *data = ofono_modem_get_data(modem); @@ -836,7 +910,7 @@ static int open_ttys(struct ofono_modem *modem) return -EIO; } - setup_aux(modem); + identify_model(modem); return -EINPROGRESS; } @@ -900,7 +974,7 @@ static void cmux_gatmux(struct ofono_modem *modem) return; } - setup_aux(modem); + identify_model(modem); } static void mux_ready_cb(struct l_timeout *timeout, void *user_data) @@ -1033,46 +1107,6 @@ static void cmux_cb(gboolean ok, GAtResult *result, gpointer user_data) close_serial(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, "", &model)) { - 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_EC2X; - 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; @@ -1080,8 +1114,8 @@ static void ate_cb(int ok, GAtResult *result, void *user_data) DBG("%p", modem); - g_at_chat_send(data->uart, "AT+CGMM", cgmm_prefix, cgmm_cb, modem, - NULL); + g_at_chat_send(data->uart, "AT+CMUX=0,0,5,127,10,3,30,10,2", NULL, + cmux_cb, modem, NULL); } static void init_cmd_cb(gboolean ok, GAtResult *result, void *user_data) @@ -1213,7 +1247,7 @@ static int quectel_enable(struct ofono_modem *modem) { DBG("%p", modem); - if (ofono_modem_get_string(modem, "Device")) + if (has_serial_connection(modem)) return open_serial(modem); else return open_ttys(modem); @@ -1317,7 +1351,7 @@ 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 || data->model == QUECTEL_EC200) { ofono_ussd_create(modem, data->vendor, "atmodem", data->aux); ofono_lte_create(modem, data->vendor, "atmodem", data->aux); } diff --git a/ofono/plugins/udevng.c b/ofono/plugins/udevng.c index 2abb40820..5d2c07c14 100644 --- a/ofono/plugins/udevng.c +++ b/ofono/plugins/udevng.c @@ -941,10 +941,12 @@ static gboolean setup_quectel_serial(struct modem_info *modem) static gboolean setup_quectel(struct modem_info *modem) { - if (modem->serial) + if (modem->type == MODEM_TYPE_SERIAL) return setup_quectel_serial(modem); - else + else if (modem->type == MODEM_TYPE_USB) return setup_quectel_usb(modem); + else + return FALSE; } static gboolean setup_quectelqmi(struct modem_info *modem) From ebf84522a2c3ff21dda052061eba42084763ef75 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Fri, 15 Jan 2021 19:25:45 +0300 Subject: [PATCH 293/320] gemalto: add netmon driver Implement network monitoring driver for gemalto modems that are able to provide serving cell information and basic measurements using AT+CQS and AT^SMONI commands. --- ofono/Makefile.am | 3 +- ofono/drivers/gemaltomodem/gemaltomodem.c | 2 + ofono/drivers/gemaltomodem/gemaltomodem.h | 3 + ofono/drivers/gemaltomodem/netmon.c | 605 ++++++++++++++++++++++ 4 files changed, 612 insertions(+), 1 deletion(-) create mode 100644 ofono/drivers/gemaltomodem/netmon.c diff --git a/ofono/Makefile.am b/ofono/Makefile.am index 35655f35d..48d9f27f9 100644 --- a/ofono/Makefile.am +++ b/ofono/Makefile.am @@ -416,7 +416,8 @@ builtin_sources += drivers/atmodem/atutil.h \ drivers/gemaltomodem/gemaltomodem.c \ drivers/gemaltomodem/location-reporting.c \ drivers/gemaltomodem/voicecall.c \ - drivers/gemaltomodem/gprs-context.c + drivers/gemaltomodem/gprs-context.c \ + drivers/gemaltomodem/netmon.c builtin_modules += xmm7modem builtin_sources += drivers/atmodem/atutil.h \ diff --git a/ofono/drivers/gemaltomodem/gemaltomodem.c b/ofono/drivers/gemaltomodem/gemaltomodem.c index 4b20dd1b8..f7e4ff3ee 100644 --- a/ofono/drivers/gemaltomodem/gemaltomodem.c +++ b/ofono/drivers/gemaltomodem/gemaltomodem.c @@ -38,6 +38,7 @@ static int gemaltomodem_init(void) gemalto_location_reporting_init(); gemalto_gprs_context_init(); gemalto_voicecall_init(); + gemalto_netmon_init(); return 0; } @@ -47,6 +48,7 @@ static void gemaltomodem_exit(void) gemalto_location_reporting_exit(); gemalto_gprs_context_exit(); gemalto_voicecall_exit(); + gemalto_netmon_exit(); } OFONO_PLUGIN_DEFINE(gemaltomodem, "Gemalto modem driver", VERSION, diff --git a/ofono/drivers/gemaltomodem/gemaltomodem.h b/ofono/drivers/gemaltomodem/gemaltomodem.h index dc0d346bd..ae8f2141a 100644 --- a/ofono/drivers/gemaltomodem/gemaltomodem.h +++ b/ofono/drivers/gemaltomodem/gemaltomodem.h @@ -30,3 +30,6 @@ extern void gemalto_voicecall_exit(); extern void gemalto_gprs_context_init(); extern void gemalto_gprs_context_exit(); + +extern void gemalto_netmon_init(void); +extern void gemalto_netmon_exit(void); diff --git a/ofono/drivers/gemaltomodem/netmon.c b/ofono/drivers/gemaltomodem/netmon.c new file mode 100644 index 000000000..ddaebf1a3 --- /dev/null +++ b/ofono/drivers/gemaltomodem/netmon.c @@ -0,0 +1,605 @@ +/* + * + * oFono - Open Source Telephony + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "gatchat.h" +#include "gatresult.h" + +#include "common.h" +#include "gemaltomodem.h" +#include "drivers/atmodem/vendor.h" + +static const char *smoni_prefix[] = { "^SMONI:", NULL }; +static const char *csq_prefix[] = { "+CSQ:", NULL }; + +struct netmon_driver_data { + GAtChat *chat; +}; + +struct req_cb_data { + gint ref_count; /* Ref count */ + + struct ofono_netmon *netmon; + ofono_netmon_cb_t cb; + void *data; + + struct ofono_network_operator op; + + int rssi; /* CSQ: received signal strength indicator (RSSI) */ + + union { + struct { + int arfcn; /* SMONI: Absolute Radio Frequency Channel Number */ + int bcch; /* SMONI: Receiving level of the BCCH carrier in dBm */ + int lac; /* SMONI: Location Area Code */ + int ci; /* SMONI: Cell ID */ + } gsm; + struct { + int uarfcn; /* SMONI: UTRAN Absolute Radio Frequency Channel Number */ + int psc; /* SMONI: Primary Scrambling Code */ + int ecno; /* SMONI: Carrier to noise ratio in dB */ + int rscp; /* SMONI: Received Signal Code Power in dBm */ + int lac; /* SMONI: Location Area Code */ + int ci; /* SMONI: Cell ID */ + } umts; + struct { + int euarfcn; /* SMONI: E-UTRA Absolute Radio Frequency Channel Number */ + int rsrp; /* SMONI: Reference Signal Received Power */ + int rsrq; /* SMONI: Reference Signal Received Quality */ + } lte; + } t; +}; + +static inline struct req_cb_data *req_cb_data_new0(void *cb, void *data, + void *user) +{ + struct req_cb_data *ret = g_new0(struct req_cb_data, 1); + + ret->ref_count = 1; + ret->netmon = user; + ret->data = data; + ret->cb = cb; + + return ret; +} + +static inline struct req_cb_data *req_cb_data_ref(struct req_cb_data *cbd) +{ + if (cbd == NULL) + return NULL; + + g_atomic_int_inc(&cbd->ref_count); + + return cbd; +} + +static void req_cb_data_unref(gpointer user_data) +{ + struct req_cb_data *cbd = user_data; + gboolean is_zero; + + if (cbd == NULL) + return; + + is_zero = g_atomic_int_dec_and_test(&cbd->ref_count); + + if (is_zero == TRUE) + g_free(cbd); +} + +static gboolean gemalto_delayed_register(gpointer user_data) +{ + struct ofono_netmon *netmon = user_data; + + ofono_netmon_register(netmon); + + return FALSE; +} + +static int gemalto_parse_smoni_gsm(GAtResultIter *iter, + struct req_cb_data *cbd) +{ + /* + * ME is camping on a GSM (2G) cell: + * ^SMONI: ACT,ARFCN,BCCH,MCC,MNC,LAC,cell,C1,C2,NCC,BCC,GPRS,Conn_state + * ^SMONI: 2G,71,-61,262,02,0143,83BA,33,33,3,6,G,NOCONN + * + * ME is searching and could not (yet) find a suitable GSM (2G) cell: + * ^SMONI: ACT,ARFCN,BCCH,MCC,MNC,LAC,cell,C1,C2,NCC,BCC,GPRS,ARFCN,TS,timAdv,dBm,Q,ChMod + * ^SMONI: 2G,SEARCH,SEARCH + * + * ME is camping on a GSM cell but not registered to the network (only emergency call allowed): + * ^SMONI: ACT,ARFCN,BCCH,MCC,MNC,LAC,cell,C1,C2,NCC,BCC,GPRS,PWR,RXLev,ARFCN,TS,timAdv,dBm,Q,ChMod + * ^SMONI: 2G,673,-89,262,07,4EED,A500,16,16,7,4,G,5,-107,LIMSRV + * + * ME has a dedicated channel (for example call in progress): + * ^SMONI: ACT,ARFCN,BCCH,MCC,MNC,LAC,cell,C1,C2,NCC,BCC,GPRS,ARFCN,TS,timAdv,dBm,Q,ChMod + * ^SMONI: 2G,673,-80,262,07,4EED,A500,35,35,7,4,G,643,4,0,-80,0,S_FR + */ + + enum smoni_gsm_field { + SMONI_GSM_ARFCN, + SMONI_GSM_BCCH, + SMONI_GSM_MCC, + SMONI_GSM_MNC, + SMONI_GSM_LAC, + SMONI_GSM_CI, + SMONI_GSM_MAX, + }; + + const char *str; + int number; + int idx; + + cbd->t.gsm.arfcn = -1; + cbd->t.gsm.bcch = -1; + cbd->t.gsm.lac = -1; + cbd->t.gsm.ci = -1; + + for (idx = 0; idx < SMONI_GSM_MAX; idx++) { + switch (idx) { + case SMONI_GSM_ARFCN: + if (g_at_result_iter_next_number(iter, &number)) + cbd->t.gsm.arfcn = number; + break; + case SMONI_GSM_BCCH: + if (g_at_result_iter_next_unquoted_string(iter, &str)) { + if (sscanf(str, "%d", &number) == 1) + cbd->t.gsm.bcch = number; + } + break; + case SMONI_GSM_MCC: + if (g_at_result_iter_next_number(iter, &number)) + snprintf(cbd->op.mcc, 4, "%d", number); + break; + case SMONI_GSM_MNC: + if (g_at_result_iter_next_number(iter, &number)) + snprintf(cbd->op.mnc, 4, "%d", number); + break; + case SMONI_GSM_LAC: + if (g_at_result_iter_next_unquoted_string(iter, &str)) { + if (sscanf(str, "%x", &number) == 1) + cbd->t.gsm.lac = number; + } + break; + case SMONI_GSM_CI: + if (g_at_result_iter_next_unquoted_string(iter, &str)) { + if (sscanf(str, "%x", &number) == 1) + cbd->t.gsm.ci = number; + } + break; + default: + break; + } + } + + DBG(" %-15s %s", "GSM.MCC", cbd->op.mcc); + DBG(" %-15s %s", "GSM.MNC", cbd->op.mnc); + DBG(" %-15s %d", "GSM.ARFCN", cbd->t.gsm.arfcn); + DBG(" %-15s %d", "GSM.BCCH", cbd->t.gsm.bcch); + DBG(" %-15s %d", "GSM.LAC", cbd->t.gsm.lac); + DBG(" %-15s %d", "GSM.CELL", cbd->t.gsm.ci); + + return 0; +} + +static int gemalto_parse_smoni_umts(GAtResultIter *iter, + struct req_cb_data *cbd) +{ + /* + * ME is camping on a UMTS (3G) cell: + * ^SMONI: ACT,UARFCN,PSC,EC/n0,RSCP,MCC,MNC,LAC,cell,SQual,SRxLev,,Conn_state + * ^SMONI: 3G,10564,296,-7.5,-79,262,02,0143,00228FF,-92,-78,NOCONN + * + * ME is searching and could not (yet) find a suitable UMTS (3G) cell: + * ^SMONI: ACT,UARFCN,PSC,EC/n0,RSCP,MCC,MNC,LAC,cell,SQual,SRxLev,PhysCh, SF,Slot,EC/n0,RSCP,ComMod,HSUPA,HSDPA + * ^SMONI: 3G,SEARCH,SEARCH + * + * ME is camping on a UMTS cell but not registered to the network (only emergency call allowed): + * ^SMONI: ACT,UARFCN,PSC,EC/n0,RSCP,MCC,MNC,LAC,cell,SQual,SRxLev,PhysCh, SF,Slot,EC/n0,RSCP,ComMod,HSUPA,HSDPA + * ^SMONI: 3G,10564,96,-7.5,-79,262,02,0143,00228FF,-92,-78,LIMSRV + * + * ME has a dedicated channel (for example call in progress): + * ^SMONI: ACT,UARFCN,PSC,EC/n0,RSCP,MCC,MNC,LAC,cell,SQual,SRxLev,PhysCh, SF,Slot,EC/n0,RSCP,ComMod,HSUPA,HSDPA + * ^SMONI: 3G,10737,131,-5,-93,260,01,7D3D,C80BC9A,--,--,----,---,-,-5,-93,0,01,06 + */ + + enum smoni_umts_field { + SMONI_UMTS_UARFCN, + SMONI_UMTS_PSC, + SMONI_UMTS_ECN0, + SMONI_UMTS_RSCP, + SMONI_UMTS_MCC, + SMONI_UMTS_MNC, + SMONI_UMTS_LAC, + SMONI_UMTS_CI, + SMONI_UMTS_MAX, + }; + + const char *str; + float fnumber; + int number; + int idx; + + cbd->t.umts.uarfcn = -1; + cbd->t.umts.psc = -1; + cbd->t.umts.ecno = -1; + cbd->t.umts.rscp = -1; + cbd->t.umts.lac = -1; + cbd->t.umts.ci = -1; + + for (idx = 0; idx < SMONI_UMTS_MAX; idx++) { + switch (idx) { + case SMONI_UMTS_UARFCN: + if (g_at_result_iter_next_number(iter, &number)) + cbd->t.umts.uarfcn = number; + break; + case SMONI_UMTS_PSC: + if (g_at_result_iter_next_number(iter, &number)) + cbd->t.umts.psc = number; + break; + case SMONI_UMTS_ECN0: + if (g_at_result_iter_next_unquoted_string(iter, &str)) { + if (sscanf(str, "%f", &fnumber) == 1) + cbd->t.umts.ecno = (int)fnumber; + } + break; + case SMONI_UMTS_RSCP: + if (g_at_result_iter_next_unquoted_string(iter, &str)) { + if (sscanf(str, "%d", &number) == 1) + cbd->t.umts.rscp = number; + } + break; + case SMONI_UMTS_MCC: + if (g_at_result_iter_next_number(iter, &number)) + snprintf(cbd->op.mcc, 4, "%d", number); + break; + case SMONI_UMTS_MNC: + if (g_at_result_iter_next_number(iter, &number)) + snprintf(cbd->op.mnc, 4, "%d", number); + break; + case SMONI_UMTS_LAC: + if (g_at_result_iter_next_unquoted_string(iter, &str)) { + if (sscanf(str, "%x", &number) == 1) + cbd->t.umts.lac = number; + } + break; + case SMONI_UMTS_CI: + if (g_at_result_iter_next_unquoted_string(iter, &str)) { + if (sscanf(str, "%x", &number) == 1) + cbd->t.umts.ci = number; + } + break; + default: + break; + } + } + + DBG(" %-15s %s", "UMTS.MCC", cbd->op.mcc); + DBG(" %-15s %s", "UMTS.MNC", cbd->op.mnc); + DBG(" %-15s %d", "UMTS.UARFCN", cbd->t.umts.uarfcn); + DBG(" %-15s %d", "UMTS.PSC", cbd->t.umts.psc); + DBG(" %-15s %d", "UMTS.ECN0", cbd->t.umts.ecno); + DBG(" %-15s %d", "UMTS.RSCP", cbd->t.umts.rscp); + DBG(" %-15s %d", "UMTS.LAC", cbd->t.umts.lac); + DBG(" %-15s %d", "UMTS.CELL", cbd->t.umts.ci); + + return 0; +} + +static int gemalto_parse_smoni_lte(GAtResultIter *iter, + struct req_cb_data *cbd) +{ + /* + * ME is camping on a LTE (4G) cell: + * ^SMONI: ACT,EARFCN,Band,DL bandwidth,UL bandwidth,Mode,MCC,MNC,TAC,Global Cell ID,Phys-ical Cell ID,Srxlev,RSRP,RSRQ,Conn_state + * ^SMONI: 4G,6300,20,10,10,FDD,262,02,BF75,0345103,350,33,-94,-7,NOCONN + * + * ME is searching and could not (yet) find a suitable LTE (4G) cell: + * ^SMONI: ACT,EARFCN,Band,DL bandwidth,UL bandwidth,Mode,MCC,MNC,TAC,Global Cell ID,Phys-ical Cell ID,Srxlev,RSRP,RSRQ,Conn_state + * ^SMONI: 4G,SEARCH + * + * ME is camping on a LTE (4G) cell but not registered to the network (only emergency call allowed): + * ^SMONI: ACT,EARFCN,Band,DL bandwidth,UL bandwidth,Mode,MCC,MNC,TAC,Global Cell ID,Phys-ical Cell ID,Srxlev,RSRP,RSRQ,Conn_state + * ^SMONI: 4G,6300,20,10,10,FDD,262,02,BF75,0345103,350,33,-94,-7,LIMSRV + * + * ME has a dedicated channel (for example call in progress): + * ^SMONI: ACT,EARFCN,Band,DL bandwidth,UL bandwidth,Mode,MCC,MNC,TAC,Global Cell ID,Phys-ical Cell ID,TX_power,RSRP,RSRQ,Conn_state + * ^SMONI: 4G,6300,20,10,10,FDD,262,02,BF75,0345103,350,90,-94,-7,CONN + */ + + const char *str; + int number; + + cbd->t.lte.euarfcn = -1; + cbd->t.lte.rsrp = -1; + cbd->t.lte.rsrq = -1; + + if (g_at_result_iter_next_number(iter, &number)) + cbd->t.lte.euarfcn = number; + + g_at_result_iter_skip_next(iter); + g_at_result_iter_skip_next(iter); + g_at_result_iter_skip_next(iter); + g_at_result_iter_skip_next(iter); + + if (g_at_result_iter_next_number(iter, &number)) + snprintf(cbd->op.mcc, 4, "%d", number); + + if (g_at_result_iter_next_number(iter, &number)) + snprintf(cbd->op.mnc, 4, "%d", number); + + g_at_result_iter_skip_next(iter); + g_at_result_iter_skip_next(iter); + g_at_result_iter_skip_next(iter); + g_at_result_iter_skip_next(iter); + + if (g_at_result_iter_next_unquoted_string(iter, &str)) { + if (sscanf(str, "%d", &number) == 1) + cbd->t.lte.rsrp = number; + } + + if (g_at_result_iter_next_unquoted_string(iter, &str)) { + if (sscanf(str, "%d", &number) == 1) + cbd->t.lte.rsrq = number; + } + + DBG(" %-15s %s", "LTE.MCC", cbd->op.mcc); + DBG(" %-15s %s", "LTE.MNC", cbd->op.mnc); + DBG(" %-15s %d", "LTE.EUARFCN", cbd->t.lte.euarfcn); + DBG(" %-15s %d", "LTE.RSRP", cbd->t.lte.rsrp); + DBG(" %-15s %d", "LTE.RSRQ", cbd->t.lte.rsrq); + + return 0; +} + +static void gemalto_netmon_finish_success(struct req_cb_data *cbd) +{ + struct ofono_netmon *nm = cbd->netmon; + + switch (cbd->op.tech) { + case OFONO_NETMON_CELL_TYPE_LTE: + ofono_netmon_serving_cell_notify(nm, cbd->op.tech, + OFONO_NETMON_INFO_MCC, cbd->op.mcc, + OFONO_NETMON_INFO_MNC, cbd->op.mnc, + OFONO_NETMON_INFO_RSSI, cbd->rssi, + OFONO_NETMON_INFO_EARFCN, cbd->t.lte.euarfcn, + OFONO_NETMON_INFO_RSRP, cbd->t.lte.rsrp, + OFONO_NETMON_INFO_RSRQ, cbd->t.lte.rsrq, + OFONO_NETMON_INFO_INVALID); + break; + case OFONO_NETMON_CELL_TYPE_UMTS: + ofono_netmon_serving_cell_notify(nm, cbd->op.tech, + OFONO_NETMON_INFO_MCC, cbd->op.mcc, + OFONO_NETMON_INFO_MNC, cbd->op.mnc, + OFONO_NETMON_INFO_RSSI, cbd->rssi, + OFONO_NETMON_INFO_ARFCN, cbd->t.umts.uarfcn, + OFONO_NETMON_INFO_PSC, cbd->t.umts.psc, + OFONO_NETMON_INFO_ECN0, cbd->t.umts.ecno, + OFONO_NETMON_INFO_RSCP, cbd->t.umts.rscp, + OFONO_NETMON_INFO_LAC, cbd->t.umts.lac, + OFONO_NETMON_INFO_CI, cbd->t.umts.ci, + OFONO_NETMON_INFO_INVALID); + break; + case OFONO_NETMON_CELL_TYPE_GSM: + ofono_netmon_serving_cell_notify(nm, cbd->op.tech, + OFONO_NETMON_INFO_MCC, cbd->op.mcc, + OFONO_NETMON_INFO_MNC, cbd->op.mnc, + OFONO_NETMON_INFO_RSSI, cbd->rssi, + OFONO_NETMON_INFO_ARFCN, cbd->t.gsm.arfcn, + OFONO_NETMON_INFO_LAC, cbd->t.gsm.lac, + OFONO_NETMON_INFO_CI, cbd->t.gsm.ci, + OFONO_NETMON_INFO_INVALID); + break; + default: + break; + } + + CALLBACK_WITH_SUCCESS(cbd->cb, cbd->data); +} + +static void csq_cb(gboolean ok, GAtResult *result, gpointer user_data) +{ + struct req_cb_data *cbd = user_data; + struct ofono_error error; + GAtResultIter iter; + int rssi; + + DBG("ok %d", ok); + + decode_at_error(&error, g_at_result_final_response(result)); + + if (!ok) { + CALLBACK_WITH_FAILURE(cbd->cb, cbd->data); + return; + } + + g_at_result_iter_init(&iter, result); + + if (!g_at_result_iter_next(&iter, "+CSQ: ")) { + cbd->rssi = -1; + goto out; + } + + if (!g_at_result_iter_next_number(&iter, &rssi) || rssi == 99) + cbd->rssi = -1; + else + cbd->rssi = rssi; + + DBG(" RSSI %d ", cbd->rssi); + +out: + gemalto_netmon_finish_success(cbd); +} + +static void smoni_cb(gboolean ok, GAtResult *result, gpointer user_data) +{ + struct req_cb_data *cbd = user_data; + struct ofono_netmon *nm = cbd->netmon; + struct netmon_driver_data *nmd = ofono_netmon_get_data(nm); + struct ofono_error error; + const char *technology; + GAtResultIter iter; + int ret; + + DBG("ok %d", ok); + + decode_at_error(&error, g_at_result_final_response(result)); + + if (!ok) { + CALLBACK_WITH_FAILURE(cbd->cb, cbd->data); + return; + } + + g_at_result_iter_init(&iter, result); + + /* do not fail */ + + if (!g_at_result_iter_next(&iter, "^SMONI: ")) { + CALLBACK_WITH_SUCCESS(cbd->cb, cbd->data); + return; + } + + if (!g_at_result_iter_next_unquoted_string(&iter, &technology)) { + DBG("^SMONI: failed to parse technology"); + CALLBACK_WITH_SUCCESS(cbd->cb, cbd->data); + return; + } + + if (strcmp(technology, "2G") == 0) { + cbd->op.tech = OFONO_NETMON_CELL_TYPE_GSM; + } else if (strcmp(technology, "3G") == 0) { + cbd->op.tech = OFONO_NETMON_CELL_TYPE_UMTS; + } else if (strcmp(technology, "4G") == 0) { + cbd->op.tech = OFONO_NETMON_CELL_TYPE_LTE; + } else { + /* fall-back to GSM by default */ + DBG("^SMONI: unexpected technology: %s", technology); + cbd->op.tech = OFONO_NETMON_CELL_TYPE_GSM; + } + + switch (cbd->op.tech) { + case OFONO_NETMON_CELL_TYPE_LTE: + ret = gemalto_parse_smoni_lte(&iter, cbd); + break; + case OFONO_NETMON_CELL_TYPE_UMTS: + ret = gemalto_parse_smoni_umts(&iter, cbd); + break; + case OFONO_NETMON_CELL_TYPE_GSM: + ret = gemalto_parse_smoni_gsm(&iter, cbd); + break; + default: + break; + } + + if (ret) { + CALLBACK_WITH_SUCCESS(cbd->cb, cbd->data); + return; + } + + cbd = req_cb_data_ref(cbd); + if (g_at_chat_send(nmd->chat, "AT+CSQ", csq_prefix, + csq_cb, cbd, req_cb_data_unref)) + return; + + req_cb_data_unref(cbd); + CALLBACK_WITH_FAILURE(cbd->cb, cbd->data); +} + +static void gemalto_netmon_request_update(struct ofono_netmon *netmon, + ofono_netmon_cb_t cb, + void *data) +{ + struct netmon_driver_data *nmd = ofono_netmon_get_data(netmon); + struct req_cb_data *cbd; + + DBG("gemalto netmon request update"); + + cbd = req_cb_data_new0(cb, data, netmon); + + if (g_at_chat_send(nmd->chat, "AT^SMONI", smoni_prefix, + smoni_cb, cbd, req_cb_data_unref)) + return; + + req_cb_data_unref(cbd); + CALLBACK_WITH_FAILURE(cbd->cb, cbd->data); +} + +static int gemalto_netmon_probe(struct ofono_netmon *netmon, + unsigned int vendor, void *user) +{ + struct netmon_driver_data *nmd = g_new0(struct netmon_driver_data, 1); + GAtChat *chat = user; + + DBG("gemalto netmon probe"); + + nmd->chat = g_at_chat_clone(chat); + + ofono_netmon_set_data(netmon, nmd); + + g_idle_add(gemalto_delayed_register, netmon); + + return 0; +} + +static void gemalto_netmon_remove(struct ofono_netmon *netmon) +{ + struct netmon_driver_data *nmd = ofono_netmon_get_data(netmon); + + DBG("gemalto netmon remove"); + + g_at_chat_unref(nmd->chat); + + ofono_netmon_set_data(netmon, NULL); + + g_free(nmd); +} + +static const struct ofono_netmon_driver driver = { + .name = "gemaltomodem", + .probe = gemalto_netmon_probe, + .remove = gemalto_netmon_remove, + .request_update = gemalto_netmon_request_update, +}; + +void gemalto_netmon_init(void) +{ + ofono_netmon_driver_register(&driver); +} + +void gemalto_netmon_exit(void) +{ + ofono_netmon_driver_unregister(&driver); +} From 60643233f5505cabedad5aa75685f2b9e6c44c29 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Fri, 15 Jan 2021 19:25:46 +0300 Subject: [PATCH 294/320] plugin: gemalto: enable netmon Enable netmon functionality for Gemalto ELS81x modems. --- ofono/plugins/gemalto.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ofono/plugins/gemalto.c b/ofono/plugins/gemalto.c index 28ee3affa..135e2d267 100644 --- a/ofono/plugins/gemalto.c +++ b/ofono/plugins/gemalto.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -622,6 +623,7 @@ static void gemalto_post_sim(struct ofono_modem *modem) static void gemalto_post_online(struct ofono_modem *modem) { struct gemalto_data *data = ofono_modem_get_data(modem); + const char *model = ofono_modem_get_string(modem, "Model"); DBG("%p", modem); @@ -634,6 +636,10 @@ static void gemalto_post_online(struct ofono_modem *modem) ofono_call_settings_create(modem, 0, "atmodem", data->app); ofono_call_meter_create(modem, 0, "atmodem", data->app); ofono_call_barring_create(modem, 0, "atmodem", data->app); + + if (!g_strcmp0(model, GEMALTO_MODEL_ELS81x)) + ofono_netmon_create(modem, OFONO_VENDOR_GEMALTO, + "gemaltomodem", data->app); } static struct ofono_modem_driver gemalto_driver = { From 067a700960fd81594885178c6baab828d4f1635a Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Fri, 15 Jan 2021 19:25:47 +0300 Subject: [PATCH 295/320] gemalto: netmon measurements scaling Gemalto modem reports raw measurements in dBm. Reported values may include negative numbers. Meanwhile oFono follows ETSI TS 27.007, so negative numbers do not really exist at the API level. Modify gemalto netmon driver to report measurements according to 27.007. For this purpose re-scale from what Gemalto firmware reports into something that 27.007 recommends. --- ofono/drivers/gemaltomodem/netmon.c | 54 ++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/ofono/drivers/gemaltomodem/netmon.c b/ofono/drivers/gemaltomodem/netmon.c index ddaebf1a3..d7959daa4 100644 --- a/ofono/drivers/gemaltomodem/netmon.c +++ b/ofono/drivers/gemaltomodem/netmon.c @@ -128,6 +128,50 @@ static gboolean gemalto_delayed_register(gpointer user_data) return FALSE; } +static int gemalto_ecno_scale(int value) +{ + if (value < -24) + return 0; + + if (value > 0) + return 49; + + return 49 * (value + 24) / 24; +} + +static int gemalto_rscp_scale(int value) +{ + if (value < -120) + return 0; + + if (value > -24) + return 96; + + return value + 120; +} + +static int gemalto_rsrp_scale(int value) +{ + if (value < -140) + return 0; + + if (value > -43) + return 97; + + return value + 140; +} + +static int gemalto_rsrq_scale(int value) +{ + if (2 * value < -39) + return 0; + + if (2 * value > -5) + return 34; + + return 2 * value + 39; +} + static int gemalto_parse_smoni_gsm(GAtResultIter *iter, struct req_cb_data *cbd) { @@ -273,13 +317,15 @@ static int gemalto_parse_smoni_umts(GAtResultIter *iter, case SMONI_UMTS_ECN0: if (g_at_result_iter_next_unquoted_string(iter, &str)) { if (sscanf(str, "%f", &fnumber) == 1) - cbd->t.umts.ecno = (int)fnumber; + cbd->t.umts.ecno = + gemalto_ecno_scale((int)fnumber); } break; case SMONI_UMTS_RSCP: if (g_at_result_iter_next_unquoted_string(iter, &str)) { if (sscanf(str, "%d", &number) == 1) - cbd->t.umts.rscp = number; + cbd->t.umts.rscp = + gemalto_rscp_scale(number); } break; case SMONI_UMTS_MCC: @@ -368,12 +414,12 @@ static int gemalto_parse_smoni_lte(GAtResultIter *iter, if (g_at_result_iter_next_unquoted_string(iter, &str)) { if (sscanf(str, "%d", &number) == 1) - cbd->t.lte.rsrp = number; + cbd->t.lte.rsrp = gemalto_rsrp_scale(number); } if (g_at_result_iter_next_unquoted_string(iter, &str)) { if (sscanf(str, "%d", &number) == 1) - cbd->t.lte.rsrq = number; + cbd->t.lte.rsrq = gemalto_rsrq_scale(number); } DBG(" %-15s %s", "LTE.MCC", cbd->op.mcc); From 8e4adf01d1bdd9251ebdc3f1295992375ffa90d0 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Sat, 16 Jan 2021 22:21:05 +0300 Subject: [PATCH 296/320] simutil: add validate_utf8_tlv Add helper to validate if TLV value is a valid UTF8 string. Note that both null-terminated and non null-terminated UTF8 strings are considered valid. --- ofono/src/simutil.c | 14 ++++++++++++++ ofono/src/simutil.h | 1 + 2 files changed, 15 insertions(+) diff --git a/ofono/src/simutil.c b/ofono/src/simutil.c index a7bf1fae9..9e1291b93 100644 --- a/ofono/src/simutil.c +++ b/ofono/src/simutil.c @@ -765,6 +765,20 @@ unsigned char *comprehension_tlv_builder_get_data( return tlv + tag_size + len_size; } +gboolean validate_utf8_tlv(const unsigned char *tlv) +{ + int len = tlv[1]; + + if (len == 0) + return FALSE; + + /* support both null-terminated and non null-terminated TLV value */ + if (tlv[len + 1] == '\0') + len -= 1; + + return g_utf8_validate_len((const char *)tlv + 2, len, NULL); +} + static char *sim_network_name_parse(const unsigned char *buffer, int length, gboolean *add_ci) { diff --git a/ofono/src/simutil.h b/ofono/src/simutil.h index 69e5b1d7f..09dffd834 100644 --- a/ofono/src/simutil.h +++ b/ofono/src/simutil.h @@ -412,6 +412,7 @@ gboolean comprehension_tlv_builder_set_length( unsigned int len); unsigned char *comprehension_tlv_builder_get_data( struct comprehension_tlv_builder *builder); +gboolean validate_utf8_tlv(const unsigned char *data); void ber_tlv_iter_init(struct ber_tlv_iter *iter, const unsigned char *pdu, unsigned int len); From 092a9f47d8f1b3f102094b2622c54e4dc691e6eb Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Sat, 16 Jan 2021 22:21:06 +0300 Subject: [PATCH 297/320] sim: validate IMS private identity Make sure that IMS private identity is a valid UTF8 string before setting sim->impi field. Otherwise ofono may crash on dbus assert when SIM properties are reported via org.ofono.SimManager interface. --- ofono/src/sim.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ofono/src/sim.c b/ofono/src/sim.c index b3c7708a6..f9129b9bb 100644 --- a/ofono/src/sim.c +++ b/ofono/src/sim.c @@ -1782,7 +1782,8 @@ static void impi_read_cb(int ok, int total_length, int record, return; } - sim->impi = g_strndup((const char *)data + 2, data[1]); + if (validate_utf8_tlv(data)) + sim->impi = g_strndup((const char *)data + 2, data[1]); } static void discover_apps_cb(const struct ofono_error *error, From 80c80a41d421560aee1b79c02650076d65114e2c Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Sat, 16 Jan 2021 22:21:07 +0300 Subject: [PATCH 298/320] unit: add validate_utf8_tlv tests --- ofono/unit/test-simutil.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/ofono/unit/test-simutil.c b/ofono/unit/test-simutil.c index 4cb07b15b..c72ba07dd 100644 --- a/ofono/unit/test-simutil.c +++ b/ofono/unit/test-simutil.c @@ -86,6 +86,27 @@ static void test_ber_tlv_iter(void) test_buffer(valid_mms_params, sizeof(valid_mms_params)); } +static void test_validate_tlv(void) +{ + unsigned char impi_none[] = { 0x80, 0x0 }; + unsigned char impi_empty[] = { 0x80, 0x1, '\0' }; + unsigned char impi_term1[] = { 0x80, 0x3, 'F', 'O', 'O' }; + unsigned char impi_term2[] = { 0x80, 0x4, 'F', 'O', 'O', '\0' }; + unsigned char impi_term3[] = { 0x80, 0x3, 'F', 'O', 'O', 0xff, 0xff }; + unsigned char impi_term4[] = { 0x80, 0x4, 'F', 'O', 'O', '\0', 0xff }; + unsigned char impi_invalid1[] = { 0x80, 0x4, 'F', '\0', 'O', '\0' }; + unsigned char impi_invalid2[] = { 0x80, 0x4, 0xff, 0xff, 0xff, 0xff }; + + g_assert(validate_utf8_tlv(impi_none) == FALSE); + g_assert(validate_utf8_tlv(impi_empty) == TRUE); + g_assert(validate_utf8_tlv(impi_term1) == TRUE); + g_assert(validate_utf8_tlv(impi_term2) == TRUE); + g_assert(validate_utf8_tlv(impi_term3) == TRUE); + g_assert(validate_utf8_tlv(impi_term4) == TRUE); + g_assert(validate_utf8_tlv(impi_invalid1) == FALSE); + g_assert(validate_utf8_tlv(impi_invalid2) == FALSE); +} + static void test_ber_tlv_builder_mms(void) { struct ber_tlv_iter top_iter, nested_iter; @@ -708,6 +729,7 @@ int main(int argc, char **argv) g_test_init(&argc, &argv, NULL); g_test_add_func("/testsimutil/ber tlv iter", test_ber_tlv_iter); + g_test_add_func("/testsimutil/ber tlv validate utf8", test_validate_tlv); g_test_add_func("/testsimutil/ber tlv encode MMS", test_ber_tlv_builder_mms); g_test_add_func("/testsimutil/ber tlv encode EFpnn", From 035fe446859454fa15250b7cc604ff40bc1df82c Mon Sep 17 00:00:00 2001 From: Alexey Andreyev Date: Fri, 19 Feb 2021 15:47:42 +0300 Subject: [PATCH 299/320] qmimodem: Add USSD indication support Handle USSD QMI indication messages. Add support for UCS2 USS Data coding scheme. Check for User Action TLV type. --- ofono/drivers/qmimodem/ussd.c | 44 +++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/ofono/drivers/qmimodem/ussd.c b/ofono/drivers/qmimodem/ussd.c index 1e613032c..e5399b9d8 100644 --- a/ofono/drivers/qmimodem/ussd.c +++ b/ofono/drivers/qmimodem/ussd.c @@ -67,6 +67,12 @@ static int convert_qmi_dcs_gsm_dcs(int qmi_dcs, int *gsm_dcs) case QMI_USSD_DCS_ASCII: *gsm_dcs = USSD_DCS_8BIT; break; + case QMI_USSD_DCS_8BIT: + *gsm_dcs = USSD_DCS_8BIT; + break; + case QMI_USSD_DCS_UCS2: + *gsm_dcs = USSD_DCS_UCS2; + break; default: return 1; } @@ -74,6 +80,41 @@ static int convert_qmi_dcs_gsm_dcs(int qmi_dcs, int *gsm_dcs) return 0; } +static void async_ind(struct qmi_result *result, void *user_data) +{ + struct ofono_ussd *ussd = user_data; + const struct qmi_ussd_data *qmi_ussd; + uint8_t user_action_required = 0; + int notify_status = OFONO_USSD_STATUS_NOTIFY; + uint16_t len; + int gsm_dcs; + + DBG(""); + + qmi_ussd = qmi_result_get(result, QMI_VOICE_PARAM_USSD_IND_DATA, &len); + if (qmi_ussd == NULL) + return; + + if (validate_ussd_data(qmi_ussd, len)) + goto error; + + if (convert_qmi_dcs_gsm_dcs(qmi_ussd->dcs, &gsm_dcs)) + goto error; + + if (qmi_result_get_uint8(result, QMI_VOICE_PARAM_USSD_IND_USER_ACTION, + &user_action_required)) { + if (user_action_required == QMI_USSD_USER_ACTION_REQUIRED) + notify_status = OFONO_USSD_STATUS_ACTION_REQUIRED; + } + + ofono_ussd_notify(ussd, notify_status, gsm_dcs, + qmi_ussd->data, qmi_ussd->length); + return; + +error: + ofono_ussd_notify(ussd, OFONO_USSD_STATUS_TERMINATED, 0, NULL, 0); +} + static void async_orig_ind(struct qmi_result *result, void *user_data) { struct ofono_ussd *ussd = user_data; @@ -141,6 +182,9 @@ static void create_voice_cb(struct qmi_service *service, void *user_data) data->voice = qmi_service_ref(service); + qmi_service_register(data->voice, QMI_VOICE_USSD_IND, + async_ind, ussd, NULL); + qmi_service_register(data->voice, QMI_VOICE_ASYNC_ORIG_USSD, async_orig_ind, ussd, NULL); From ebfacdb553103f0b5a1c1d859e551ce3162e3496 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 22 Feb 2021 10:04:18 -0600 Subject: [PATCH 300/320] AUTHORS: Mention Alexey's contributions --- ofono/AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/ofono/AUTHORS b/ofono/AUTHORS index f450d1f95..643775ce1 100644 --- a/ofono/AUTHORS +++ b/ofono/AUTHORS @@ -152,3 +152,4 @@ Sergey Matyukevich Shweta Jain JongSeok Won Sergei Golubtsov +Alexey Andreyev From 6ae415cc24818e68fbf9aafadd7c77fbd586cd3f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 28 Apr 2021 16:38:55 +0200 Subject: [PATCH 301/320] mbimmodem: Remove usage of likely and unlikely --- ofono/drivers/mbimmodem/mbim-message.c | 58 +++++++++++++------------- ofono/drivers/mbimmodem/mbim.c | 33 +++++++-------- 2 files changed, 45 insertions(+), 46 deletions(-) diff --git a/ofono/drivers/mbimmodem/mbim-message.c b/ofono/drivers/mbimmodem/mbim-message.c index 25e998b37..ad2926d99 100644 --- a/ofono/drivers/mbimmodem/mbim-message.c +++ b/ofono/drivers/mbimmodem/mbim-message.c @@ -500,7 +500,7 @@ static bool message_iter_next_entry_valist(struct mbim_message_iter *orig, signature += 1; indent += 1; - if (unlikely(indent > MAX_NESTING)) + if (indent > MAX_NESTING) return false; if (!_iter_enter_struct(iter, &stack[indent - 1])) @@ -510,7 +510,7 @@ static bool message_iter_next_entry_valist(struct mbim_message_iter *orig, break; case ')': - if (unlikely(indent == 0)) + if (indent == 0) return false; signature += 1; @@ -561,7 +561,7 @@ bool mbim_message_iter_next_entry(struct mbim_message_iter *iter, ...) va_list args; bool result; - if (unlikely(!iter)) + if (!iter) return false; va_start(args, iter); @@ -674,7 +674,7 @@ struct mbim_message *mbim_message_new(const uint8_t *uuid, uint32_t cid, struct mbim_message *mbim_message_ref(struct mbim_message *msg) { - if (unlikely(!msg)) + if (!msg) return NULL; __sync_fetch_and_add(&msg->ref_count, 1); @@ -686,7 +686,7 @@ void mbim_message_unref(struct mbim_message *msg) { unsigned int i; - if (unlikely(!msg)) + if (!msg) return; if (__sync_sub_and_fetch(&msg->ref_count, 1)) @@ -759,10 +759,10 @@ uint32_t mbim_message_get_error(struct mbim_message *message) { struct mbim_message_header *hdr; - if (unlikely(!message)) + if (!message) return false; - if (unlikely(!message->sealed)) + if (!message->sealed) return false; hdr = (struct mbim_message_header *) message->header; @@ -775,7 +775,7 @@ uint32_t mbim_message_get_error(struct mbim_message *message) uint32_t mbim_message_get_cid(struct mbim_message *message) { - if (unlikely(!message)) + if (!message) return false; return message->cid; @@ -783,7 +783,7 @@ uint32_t mbim_message_get_cid(struct mbim_message *message) const uint8_t *mbim_message_get_uuid(struct mbim_message *message) { - if (unlikely(!message)) + if (!message) return false; return message->uuid; @@ -799,10 +799,10 @@ bool mbim_message_get_arguments(struct mbim_message *message, uint32_t type; size_t begin; - if (unlikely(!message)) + if (!message) return false; - if (unlikely(!message->sealed)) + if (!message->sealed) return false; hdr = (struct mbim_message_header *) message->header; @@ -833,10 +833,10 @@ static bool _mbim_message_get_data(struct mbim_message *message, size_t pos; uint32_t i; - if (unlikely(!message)) + if (!message) return false; - if (unlikely(!message->sealed)) + if (!message->sealed) return false; hdr = (struct mbim_message_header *) message->header; @@ -1007,7 +1007,7 @@ struct mbim_message_builder *mbim_message_builder_new(struct mbim_message *msg) uint32_t type; struct container *container; - if (unlikely(!msg)) + if (!msg) return NULL; if (msg->sealed) @@ -1032,7 +1032,7 @@ void mbim_message_builder_free(struct mbim_message_builder *builder) { uint32_t i; - if (unlikely(!builder)) + if (!builder) return; mbim_message_unref(builder->message); @@ -1059,10 +1059,10 @@ bool mbim_message_builder_append_basic(struct mbim_message_builder *builder, size_t len; uint16_t *utf16; - if (unlikely(!builder)) + if (!builder) return false; - if (unlikely(!strchr(simple_types, type))) + if (!strchr(simple_types, type)) return false; alignment = get_alignment(type); @@ -1167,16 +1167,16 @@ bool mbim_message_builder_append_bytes(struct mbim_message_builder *builder, struct container *container = &builder->stack[builder->index]; size_t start; - if (unlikely(!builder)) + if (!builder) return false; if (container->container_type == CONTAINER_TYPE_ARRAY) { struct container *array; - if (unlikely(container->sigindex != 0)) + if (container->sigindex != 0) return false; - if (unlikely(container->signature[container->sigindex] != 'y')) + if (container->signature[container->sigindex] != 'y') return false; array = container; @@ -1246,12 +1246,12 @@ bool mbim_message_builder_leave_struct(struct mbim_message_builder *builder) struct container *array = NULL; size_t start; - if (unlikely(builder->index == 0)) + if (builder->index == 0) return false; container = &builder->stack[builder->index]; - if (unlikely(container->container_type != CONTAINER_TYPE_STRUCT)) + if (container->container_type != CONTAINER_TYPE_STRUCT) return false; builder->index -= 1; @@ -1338,12 +1338,12 @@ bool mbim_message_builder_leave_array(struct mbim_message_builder *builder) { struct container *container; - if (unlikely(builder->index == 0)) + if (builder->index == 0) return false; container = &builder->stack[builder->index]; - if (unlikely(container->container_type != CONTAINER_TYPE_ARRAY)) + if (container->container_type != CONTAINER_TYPE_ARRAY) return false; builder->index -= 1; @@ -1380,12 +1380,12 @@ bool mbim_message_builder_leave_databuf(struct mbim_message_builder *builder) struct container *parent; size_t start; - if (unlikely(builder->index == 0)) + if (builder->index == 0) return false; container = &builder->stack[builder->index]; - if (unlikely(container->container_type != CONTAINER_TYPE_DATABUF)) + if (container->container_type != CONTAINER_TYPE_DATABUF) return false; builder->index -= 1; @@ -1414,7 +1414,7 @@ struct mbim_message *mbim_message_builder_finalize( struct container *root; struct mbim_message_header *hdr; - if (unlikely(!builder)) + if (!builder) return NULL; if (builder->index != 0) @@ -1700,10 +1700,10 @@ bool mbim_message_set_arguments(struct mbim_message *message, va_list args; bool result; - if (unlikely(!message)) + if (!message) return false; - if (unlikely(message->sealed)) + if (message->sealed) return false; if (!signature) diff --git a/ofono/drivers/mbimmodem/mbim.c b/ofono/drivers/mbimmodem/mbim.c index 54b18acfd..d48083cd3 100644 --- a/ofono/drivers/mbimmodem/mbim.c +++ b/ofono/drivers/mbimmodem/mbim.c @@ -183,8 +183,7 @@ static struct mbim_message *message_assembly_add( struct message_assembly_node *node; struct mbim_message *message; - if (unlikely(type != MBIM_COMMAND_DONE && - type != MBIM_INDICATE_STATUS_MSG)) + if (type != MBIM_COMMAND_DONE && type != MBIM_INDICATE_STATUS_MSG) return NULL; node = l_queue_find(assembly->transactions, @@ -894,7 +893,7 @@ struct mbim_device *mbim_device_new(int fd, uint32_t max_segment_size) { struct mbim_device *device; - if (unlikely(fd < 0)) + if (fd < 0) return NULL; device = l_new(struct mbim_device, 1); @@ -926,7 +925,7 @@ struct mbim_device *mbim_device_new(int fd, uint32_t max_segment_size) struct mbim_device *mbim_device_ref(struct mbim_device *device) { - if (unlikely(!device)) + if (!device) return NULL; __sync_fetch_and_add(&device->ref_count, 1); @@ -936,7 +935,7 @@ struct mbim_device *mbim_device_ref(struct mbim_device *device) void mbim_device_unref(struct mbim_device *device) { - if (unlikely(!device)) + if (!device) return; if (__sync_sub_and_fetch(&device->ref_count, 1)) @@ -966,7 +965,7 @@ void mbim_device_unref(struct mbim_device *device) bool mbim_device_shutdown(struct mbim_device *device) { - if (unlikely(!device)) + if (!device) return false; l_io_set_read_handler(device->io, close_read_handler, device, NULL); @@ -978,7 +977,7 @@ bool mbim_device_shutdown(struct mbim_device *device) bool mbim_device_set_max_outstanding(struct mbim_device *device, uint32_t max) { - if (unlikely(!device)) + if (!device) return false; device->max_outstanding = max; @@ -990,7 +989,7 @@ bool mbim_device_set_disconnect_handler(struct mbim_device *device, void *user_data, mbim_device_destroy_func_t destroy) { - if (unlikely(!device)) + if (!device) return false; if (device->disconnect_destroy) @@ -1007,7 +1006,7 @@ bool mbim_device_set_debug(struct mbim_device *device, mbim_device_debug_func_t func, void *user_data, mbim_device_destroy_func_t destroy) { - if (unlikely(!device)) + if (!device) return false; if (device->debug_destroy) @@ -1022,7 +1021,7 @@ bool mbim_device_set_debug(struct mbim_device *device, bool mbim_device_set_close_on_unref(struct mbim_device *device, bool do_close) { - if (unlikely(!device)) + if (!device) return false; if (!device->io) @@ -1037,7 +1036,7 @@ bool mbim_device_set_ready_handler(struct mbim_device *device, void *user_data, mbim_device_destroy_func_t destroy) { - if (unlikely(!device)) + if (!device) return false; if (device->ready_destroy) @@ -1058,7 +1057,7 @@ uint32_t mbim_device_send(struct mbim_device *device, uint32_t gid, { struct pending_command *pending; - if (unlikely(!device || !message)) + if (!device || !message) return 0; pending = l_new(struct pending_command, 1); @@ -1088,7 +1087,7 @@ bool mbim_device_cancel(struct mbim_device *device, uint32_t tid) { struct pending_command *pending; - if (unlikely(!device)) + if (!device) return false; pending = l_queue_remove_if(device->pending_commands, @@ -1112,7 +1111,7 @@ bool mbim_device_cancel(struct mbim_device *device, uint32_t tid) bool mbim_device_cancel_group(struct mbim_device *device, uint32_t gid) { - if (unlikely(!device)) + if (!device) return false; l_queue_foreach_remove(device->pending_commands, @@ -1135,7 +1134,7 @@ uint32_t mbim_device_register(struct mbim_device *device, uint32_t gid, struct notification *notification; uint32_t id; - if (unlikely(!device)) + if (!device) return 0; id = device->next_notification; @@ -1163,7 +1162,7 @@ bool mbim_device_unregister(struct mbim_device *device, uint32_t id) { struct notification *notification; - if (unlikely(!device)) + if (!device) return false; if (device->in_notify) { @@ -1192,7 +1191,7 @@ bool mbim_device_unregister_group(struct mbim_device *device, uint32_t gid) const struct l_queue_entry *entry; bool r; - if (unlikely(!device)) + if (!device) return false; if (!device->in_notify) From 3b2d4b8bedebe241fc736fdc1d97015ded9071d3 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 28 Apr 2021 16:39:46 +0200 Subject: [PATCH 302/320] treewide: Replace g_memdup with g_memdup2 --- ofono/drivers/hsomodem/gprs-context.c | 2 +- ofono/drivers/huaweimodem/gprs-context.c | 2 +- ofono/drivers/iceramodem/gprs-context.c | 2 +- ofono/drivers/mbmmodem/gprs-context.c | 2 +- ofono/drivers/stemodem/gprs-context.c | 2 +- ofono/drivers/swmodem/gprs-context.c | 2 +- ofono/gatchat/gatmux.c | 2 +- ofono/gatchat/ppp_ipcp.c | 2 +- ofono/gatchat/ppp_ipv6cp.c | 2 +- ofono/src/modem.c | 4 ++-- ofono/src/network.c | 2 +- ofono/src/sim.c | 10 +++++----- ofono/src/simfs.c | 2 +- ofono/src/smsutil.c | 6 +++--- ofono/src/voicecall.c | 2 +- ofono/tools/stktest.c | 4 ++-- 16 files changed, 24 insertions(+), 24 deletions(-) diff --git a/ofono/drivers/hsomodem/gprs-context.c b/ofono/drivers/hsomodem/gprs-context.c index ca622480c..44dc89aec 100644 --- a/ofono/drivers/hsomodem/gprs-context.c +++ b/ofono/drivers/hsomodem/gprs-context.c @@ -128,7 +128,7 @@ static void hso_cgdcont_cb(gboolean ok, GAtResult *result, gpointer user_data) return; } - ncbd = g_memdup(cbd, sizeof(struct cb_data)); + ncbd = g_memdup2(cbd, sizeof(struct cb_data)); snprintf(buf, sizeof(buf), "AT_OWANCALL=%u,1,1", gcd->active_context); diff --git a/ofono/drivers/huaweimodem/gprs-context.c b/ofono/drivers/huaweimodem/gprs-context.c index de07b055d..2a1a828c6 100644 --- a/ofono/drivers/huaweimodem/gprs-context.c +++ b/ofono/drivers/huaweimodem/gprs-context.c @@ -234,7 +234,7 @@ static void at_cgdcont_cb(gboolean ok, GAtResult *result, gpointer user_data) return; } - ncbd = g_memdup(cbd, sizeof(struct cb_data)); + ncbd = g_memdup2(cbd, sizeof(struct cb_data)); snprintf(buf, sizeof(buf), "AT^NDISDUP=%u,1", gcd->active_context); diff --git a/ofono/drivers/iceramodem/gprs-context.c b/ofono/drivers/iceramodem/gprs-context.c index 41d9d9bf5..21b748a0b 100644 --- a/ofono/drivers/iceramodem/gprs-context.c +++ b/ofono/drivers/iceramodem/gprs-context.c @@ -284,7 +284,7 @@ static void at_cgdcont_cb(gboolean ok, GAtResult *result, gpointer user_data) if (g_at_chat_send(gcd->chat, buf, none_prefix, NULL, NULL, NULL) == 0) goto error; - ncbd = g_memdup(cbd, sizeof(struct cb_data)); + ncbd = g_memdup2(cbd, sizeof(struct cb_data)); snprintf(buf, sizeof(buf), "AT%%IPDPACT=%u,1", gcd->active_context); diff --git a/ofono/drivers/mbmmodem/gprs-context.c b/ofono/drivers/mbmmodem/gprs-context.c index f873e2835..acfa2115f 100644 --- a/ofono/drivers/mbmmodem/gprs-context.c +++ b/ofono/drivers/mbmmodem/gprs-context.c @@ -345,7 +345,7 @@ static void mbm_cgdcont_cb(gboolean ok, GAtResult *result, gpointer user_data) return; } - ncbd = g_memdup(cbd, sizeof(struct cb_data)); + ncbd = g_memdup2(cbd, sizeof(struct cb_data)); snprintf(buf, sizeof(buf), "AT*ENAP=1,%u", gcd->active_context); diff --git a/ofono/drivers/stemodem/gprs-context.c b/ofono/drivers/stemodem/gprs-context.c index fb279c5a6..e7420c1ed 100644 --- a/ofono/drivers/stemodem/gprs-context.c +++ b/ofono/drivers/stemodem/gprs-context.c @@ -259,7 +259,7 @@ static void ste_cgdcont_cb(gboolean ok, GAtResult *result, gpointer user_data) snprintf(buf, sizeof(buf), "AT*EPPSD=1,%x,%u", gcd->channel_id, gcd->active_context); - ncbd = g_memdup(cbd, sizeof(struct cb_data)); + ncbd = g_memdup2(cbd, sizeof(struct cb_data)); if (g_at_chat_send(gcd->chat, buf, NULL, ste_eppsd_up_cb, ncbd, g_free) > 0) diff --git a/ofono/drivers/swmodem/gprs-context.c b/ofono/drivers/swmodem/gprs-context.c index 002053cf9..6532aa4b5 100644 --- a/ofono/drivers/swmodem/gprs-context.c +++ b/ofono/drivers/swmodem/gprs-context.c @@ -132,7 +132,7 @@ static void at_cgdcont_cb(gboolean ok, GAtResult *result, gpointer user_data) return; } - ncbd = g_memdup(cbd, sizeof(struct cb_data)); + ncbd = g_memdup2(cbd, sizeof(struct cb_data)); snprintf(buf, sizeof(buf), "AT!SCACT=1,%u", gcd->active_context); diff --git a/ofono/gatchat/gatmux.c b/ofono/gatchat/gatmux.c index 4d89f0398..2e4ce9fe3 100644 --- a/ofono/gatchat/gatmux.c +++ b/ofono/gatchat/gatmux.c @@ -908,7 +908,7 @@ static void mux_query_cb(gboolean ok, GAtResult *result, gpointer user_data) } else goto error; - nmsd = g_memdup(msd, sizeof(struct mux_setup_data)); + nmsd = g_memdup2(msd, sizeof(struct mux_setup_data)); g_at_chat_ref(nmsd->chat); if (speed < 0) diff --git a/ofono/gatchat/ppp_ipcp.c b/ofono/gatchat/ppp_ipcp.c index 125a54292..4d19e1b8c 100644 --- a/ofono/gatchat/ppp_ipcp.c +++ b/ofono/gatchat/ppp_ipcp.c @@ -371,7 +371,7 @@ static enum rcr_result ipcp_server_rcr(struct ipcp_data *ipcp, if (len > 0) { *new_len = len; - *new_options = g_memdup(nak_options, len); + *new_options = g_memdup2(nak_options, len); return RCR_NAK; } diff --git a/ofono/gatchat/ppp_ipv6cp.c b/ofono/gatchat/ppp_ipv6cp.c index 94feaccdc..ac2b75873 100644 --- a/ofono/gatchat/ppp_ipv6cp.c +++ b/ofono/gatchat/ppp_ipv6cp.c @@ -160,7 +160,7 @@ static enum rcr_result ipv6cp_server_rcr(struct ipv6cp_data *ipv6cp, if (len > 0) { *new_len = len; - *new_options = g_memdup(nak_options, len); + *new_options = g_memdup2(nak_options, len); return RCR_NAK; } diff --git a/ofono/src/modem.c b/ofono/src/modem.c index 55ab4168c..68a97e9ed 100644 --- a/ofono/src/modem.c +++ b/ofono/src/modem.c @@ -1782,10 +1782,10 @@ static int set_modem_property(struct ofono_modem *modem, const char *name, property->value = g_strdup((const char *) value); break; case PROPERTY_TYPE_INTEGER: - property->value = g_memdup(value, sizeof(int)); + property->value = g_memdup2(value, sizeof(int)); break; case PROPERTY_TYPE_BOOLEAN: - property->value = g_memdup(value, sizeof(ofono_bool_t)); + property->value = g_memdup2(value, sizeof(ofono_bool_t)); break; default: break; diff --git a/ofono/src/network.c b/ofono/src/network.c index 4d1775f60..7dd1b5172 100644 --- a/ofono/src/network.c +++ b/ofono/src/network.c @@ -729,7 +729,7 @@ static gboolean update_operator_list(struct ofono_netreg *netreg, int total, /* New operator */ struct network_operator_data *opd; - opd = g_memdup(copd, + opd = g_memdup2(copd, sizeof(struct network_operator_data)); if (!network_operator_dbus_register(netreg, opd)) { diff --git a/ofono/src/sim.c b/ofono/src/sim.c index f9129b9bb..5b7e8dbdd 100644 --- a/ofono/src/sim.c +++ b/ofono/src/sim.c @@ -1296,7 +1296,7 @@ static void sim_iidf_read_cb(int ok, int length, int record, clut_len = data[3] * 3; iidf_id = efimg[3] << 8 | efimg[4]; - sim->iidf_image = g_memdup(data, length); + sim->iidf_image = g_memdup2(data, length); /* The path it the same between 2G and 3G */ path_len = sim_ef_db_get_path_3g(SIM_EFIMG_FILEID, path); @@ -2059,7 +2059,7 @@ static void sim_efsst_read_cb(int ok, int length, int record, goto out; } - sim->efsst = g_memdup(data, length); + sim->efsst = g_memdup2(data, length); sim->efsst_length = length; /* @@ -2098,7 +2098,7 @@ static void sim_efest_read_cb(int ok, int length, int record, goto out; } - sim->efest = g_memdup(data, length); + sim->efest = g_memdup2(data, length); sim->efest_length = length; /* @@ -2142,7 +2142,7 @@ static void sim_efust_read_cb(int ok, int length, int record, goto out; } - sim->efust = g_memdup(data, length); + sim->efust = g_memdup2(data, length); sim->efust_length = length; /* @@ -2289,7 +2289,7 @@ static void sim_efli_read_cb(int ok, int length, int record, if (!ok) return; - sim->efli = g_memdup(data, length); + sim->efli = g_memdup2(data, length); sim->efli_length = length; } diff --git a/ofono/src/simfs.c b/ofono/src/simfs.c index 7a382c338..b15d679ce 100644 --- a/ofono/src/simfs.c +++ b/ofono/src/simfs.c @@ -1228,7 +1228,7 @@ int sim_fs_write(struct ofono_sim_context *context, int id, op->cb = cb; op->userdata = userdata; op->is_read = FALSE; - op->buffer = g_memdup(data, length); + op->buffer = g_memdup2(data, length); op->structure = structure; op->length = length; op->current = record; diff --git a/ofono/src/smsutil.c b/ofono/src/smsutil.c index 747429aea..b08351b8d 100644 --- a/ofono/src/smsutil.c +++ b/ofono/src/smsutil.c @@ -2810,7 +2810,7 @@ static void sr_assembly_load_backup(GHashTable *assembly_table, } /* Node ready, create key and add them to the table */ - id_table_key = g_memdup(msgid, SMS_MSGID_LEN); + id_table_key = g_memdup2(msgid, SMS_MSGID_LEN); g_hash_table_insert(id_table, id_table_key, node); } @@ -3125,7 +3125,7 @@ void status_report_assembly_add_fragment( /* Create node in the message id hashtable if required */ if (node == NULL) { - id_table_key = g_memdup(msgid, SMS_MSGID_LEN); + id_table_key = g_memdup2(msgid, SMS_MSGID_LEN); node = g_new0(struct id_table_node, 1); node->total_mrs = total_mrs; @@ -3236,7 +3236,7 @@ static GSList *sms_tx_load(const char *imsi, const struct dirent *dir) if (sms_deserialize_outgoing(buf, &s, r) == FALSE) goto free_pdu; - list = g_slist_prepend(list, g_memdup(&s, sizeof(s))); + list = g_slist_prepend(list, g_memdup2(&s, sizeof(s))); free_pdu: g_free(pdus[len]); diff --git a/ofono/src/voicecall.c b/ofono/src/voicecall.c index a49488ef9..cafe34a3c 100644 --- a/ofono/src/voicecall.c +++ b/ofono/src/voicecall.c @@ -2798,7 +2798,7 @@ void ofono_voicecall_notify(struct ofono_voicecall *vc, __ofono_modem_callid_hold(modem, call->id); - newcall = g_memdup(call, sizeof(struct ofono_call)); + newcall = g_memdup2(call, sizeof(struct ofono_call)); if (newcall == NULL) { ofono_error("Unable to allocate call"); goto error; diff --git a/ofono/tools/stktest.c b/ofono/tools/stktest.c index c83d48399..5863bc5e0 100644 --- a/ofono/tools/stktest.c +++ b/ofono/tools/stktest.c @@ -3375,9 +3375,9 @@ static void stktest_add_test(const char *name, const char *method, test->name = g_strdup(name); test->method = g_strdup(method); - test->req_pdu = g_memdup(req, req_len); + test->req_pdu = g_memdup2(req, req_len); test->req_len = req_len; - test->rsp_pdu = g_memdup(rsp, rsp_len); + test->rsp_pdu = g_memdup2(rsp, rsp_len); test->rsp_len = rsp_len; test->agent_func = agent_func; test->tr_func = tr_func; From 2bbdfe8565da5b3a1a2c725de9ece6c0e2164f7c Mon Sep 17 00:00:00 2001 From: JongSeok Won Date: Mon, 8 Mar 2021 18:33:14 +0900 Subject: [PATCH 303/320] build: require glib >= 2.60 g_utf8_validate_len() is support after glib 2.60 --- ofono/configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ofono/configure.ac b/ofono/configure.ac index 40c6004a6..a9532722c 100644 --- a/ofono/configure.ac +++ b/ofono/configure.ac @@ -64,8 +64,8 @@ AC_CHECK_FUNC(signalfd, dummy=yes, AC_CHECK_LIB(dl, dlopen, dummy=yes, AC_MSG_ERROR(dynamic linking loader is required)) -PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.32, dummy=yes, - AC_MSG_ERROR(GLib >= 2.32 is required)) +PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.60, dummy=yes, + AC_MSG_ERROR(GLib >= 2.60 is required)) AC_SUBST(GLIB_CFLAGS) AC_SUBST(GLIB_LIBS) From c55250687dae2836d3a344de8f8db887a8a7fe66 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 4 May 2021 15:38:59 +0200 Subject: [PATCH 304/320] build: check for glib >= 2.68 first before checking for glib >= 2.60 --- ofono/configure.ac | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ofono/configure.ac b/ofono/configure.ac index a9532722c..a2edf7fda 100644 --- a/ofono/configure.ac +++ b/ofono/configure.ac @@ -64,8 +64,10 @@ AC_CHECK_FUNC(signalfd, dummy=yes, AC_CHECK_LIB(dl, dlopen, dummy=yes, AC_MSG_ERROR(dynamic linking loader is required)) -PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.60, dummy=yes, +PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.68, dummy=yes, [ + PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.60, dummy=yes, AC_MSG_ERROR(GLib >= 2.60 is required)) +]) AC_SUBST(GLIB_CFLAGS) AC_SUBST(GLIB_LIBS) From 0654a31d9fa6a2ec8620c5f721d5bd3a26f9404e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 5 May 2021 10:31:54 +0200 Subject: [PATCH 305/320] treewide: Introduce support for missing g_memdup2 --- ofono/Makefile.am | 4 ++-- ofono/configure.ac | 5 ++++- ofono/drivers/hsomodem/gprs-context.c | 1 + ofono/drivers/huaweimodem/gprs-context.c | 1 + ofono/drivers/iceramodem/gprs-context.c | 1 + ofono/drivers/mbmmodem/gprs-context.c | 1 + ofono/drivers/stemodem/gprs-context.c | 1 + ofono/drivers/swmodem/gprs-context.c | 1 + ofono/gatchat/gatmux.c | 1 + ofono/gatchat/ppp_ipcp.c | 1 + ofono/gatchat/ppp_ipv6cp.c | 1 + ofono/src/missing.h | 24 ++++++++++++++++++++++++ ofono/src/modem.c | 2 +- ofono/src/network.c | 1 + ofono/src/sim.c | 1 + ofono/src/simfs.c | 1 + ofono/src/simutil.c | 1 + ofono/src/smsutil.c | 1 + ofono/src/voicecall.c | 1 + ofono/tools/stktest.c | 1 + 20 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 ofono/src/missing.h diff --git a/ofono/Makefile.am b/ofono/Makefile.am index 48d9f27f9..3c18a4e81 100644 --- a/ofono/Makefile.am +++ b/ofono/Makefile.am @@ -702,8 +702,8 @@ endif sbin_PROGRAMS = src/ofonod -src_ofonod_SOURCES = $(builtin_sources) $(gatchat_sources) \ - linux/gsmmux.h linux/gpio.h src/ofono.ver \ +src_ofonod_SOURCES = $(builtin_sources) $(gatchat_sources) src/ofono.ver \ + linux/gsmmux.h linux/gpio.h src/missing.h \ src/main.c src/ofono.h src/log.c src/plugin.c \ src/modem.c src/common.h src/common.c \ src/manager.c src/dbus.c src/util.h src/util.c \ diff --git a/ofono/configure.ac b/ofono/configure.ac index a2edf7fda..cec208ecd 100644 --- a/ofono/configure.ac +++ b/ofono/configure.ac @@ -64,7 +64,10 @@ AC_CHECK_FUNC(signalfd, dummy=yes, AC_CHECK_LIB(dl, dlopen, dummy=yes, AC_MSG_ERROR(dynamic linking loader is required)) -PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.68, dummy=yes, [ +PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.68, [ + AC_DEFINE_UNQUOTED(HAVE_G_MEMDUP2, 1, + [Define to 1 if you have the `g_memdup2' function.]) +], [ PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.60, dummy=yes, AC_MSG_ERROR(GLib >= 2.60 is required)) ]) diff --git a/ofono/drivers/hsomodem/gprs-context.c b/ofono/drivers/hsomodem/gprs-context.c index 44dc89aec..aafcaa0b7 100644 --- a/ofono/drivers/hsomodem/gprs-context.c +++ b/ofono/drivers/hsomodem/gprs-context.c @@ -37,6 +37,7 @@ #include "gatresult.h" #include "hsomodem.h" +#include "src/missing.h" #define HSO_DISCONNECTED 0 #define HSO_CONNECTED 1 diff --git a/ofono/drivers/huaweimodem/gprs-context.c b/ofono/drivers/huaweimodem/gprs-context.c index 2a1a828c6..edc01badd 100644 --- a/ofono/drivers/huaweimodem/gprs-context.c +++ b/ofono/drivers/huaweimodem/gprs-context.c @@ -39,6 +39,7 @@ #include "gattty.h" #include "huaweimodem.h" +#include "src/missing.h" static const char *none_prefix[] = { NULL }; static const char *dhcp_prefix[] = { "^DHCP:", NULL }; diff --git a/ofono/drivers/iceramodem/gprs-context.c b/ofono/drivers/iceramodem/gprs-context.c index 21b748a0b..fdc7f84ac 100644 --- a/ofono/drivers/iceramodem/gprs-context.c +++ b/ofono/drivers/iceramodem/gprs-context.c @@ -40,6 +40,7 @@ #include "gattty.h" #include "iceramodem.h" +#include "src/missing.h" #define ICERA_DISCONNECTED 0 #define ICERA_CONNECTED 1 diff --git a/ofono/drivers/mbmmodem/gprs-context.c b/ofono/drivers/mbmmodem/gprs-context.c index acfa2115f..d6c3a3ce8 100644 --- a/ofono/drivers/mbmmodem/gprs-context.c +++ b/ofono/drivers/mbmmodem/gprs-context.c @@ -38,6 +38,7 @@ #include "gatresult.h" #include "mbmmodem.h" +#include "src/missing.h" #define MBM_E2NAP_DISCONNECTED 0 #define MBM_E2NAP_CONNECTED 1 diff --git a/ofono/drivers/stemodem/gprs-context.c b/ofono/drivers/stemodem/gprs-context.c index e7420c1ed..ebaf3477c 100644 --- a/ofono/drivers/stemodem/gprs-context.c +++ b/ofono/drivers/stemodem/gprs-context.c @@ -48,6 +48,7 @@ #include "if_caif.h" #include "caif_rtnl.h" #include "common.h" +#include "src/missing.h" #define MAX_DNS 2 #define IP_ADDR_LEN 20 diff --git a/ofono/drivers/swmodem/gprs-context.c b/ofono/drivers/swmodem/gprs-context.c index 6532aa4b5..b63c8954f 100644 --- a/ofono/drivers/swmodem/gprs-context.c +++ b/ofono/drivers/swmodem/gprs-context.c @@ -40,6 +40,7 @@ #include "gattty.h" #include "swmodem.h" +#include "src/missing.h" static const char *none_prefix[] = { NULL }; diff --git a/ofono/gatchat/gatmux.c b/ofono/gatchat/gatmux.c index 2e4ce9fe3..95ffeb8db 100644 --- a/ofono/gatchat/gatmux.c +++ b/ofono/gatchat/gatmux.c @@ -38,6 +38,7 @@ #include "ringbuffer.h" #include "gatmux.h" #include "gsm0710.h" +#include "src/missing.h" static const char *cmux_prefix[] = { "+CMUX:", NULL }; static const char *none_prefix[] = { NULL }; diff --git a/ofono/gatchat/ppp_ipcp.c b/ofono/gatchat/ppp_ipcp.c index 4d19e1b8c..4d4dd372a 100644 --- a/ofono/gatchat/ppp_ipcp.c +++ b/ofono/gatchat/ppp_ipcp.c @@ -34,6 +34,7 @@ #include "gatutil.h" #include "gatppp.h" #include "ppp.h" +#include "src/missing.h" #define IPCP_SUPPORTED_CODES ((1 << PPPCP_CODE_TYPE_CONFIGURE_REQUEST) | \ (1 << PPPCP_CODE_TYPE_CONFIGURE_ACK) | \ diff --git a/ofono/gatchat/ppp_ipv6cp.c b/ofono/gatchat/ppp_ipv6cp.c index ac2b75873..cde402025 100644 --- a/ofono/gatchat/ppp_ipv6cp.c +++ b/ofono/gatchat/ppp_ipv6cp.c @@ -34,6 +34,7 @@ #include "gatppp.h" #include "ppp.h" +#include "missing.h" #define IPV6CP_SUPPORTED_CODES ((1 << PPPCP_CODE_TYPE_CONFIGURE_REQUEST) | \ (1 << PPPCP_CODE_TYPE_CONFIGURE_ACK) | \ diff --git a/ofono/src/missing.h b/ofono/src/missing.h new file mode 100644 index 000000000..aa96e274d --- /dev/null +++ b/ofono/src/missing.h @@ -0,0 +1,24 @@ +/* + * + * oFono - Open Source Telephony + * + * Copyright (C) 2008-2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef HAVE_G_MEMDUP2 +#define g_memdup2(mem, size) g_memdup((mem), (size)) +#endif diff --git a/ofono/src/modem.c b/ofono/src/modem.c index 68a97e9ed..3bef58b5f 100644 --- a/ofono/src/modem.c +++ b/ofono/src/modem.c @@ -32,8 +32,8 @@ #include #include "ofono.h" - #include "common.h" +#include "missing.h" #define DEFAULT_POWERED_TIMEOUT (20) diff --git a/ofono/src/network.c b/ofono/src/network.c index 7dd1b5172..e14e56f23 100644 --- a/ofono/src/network.c +++ b/ofono/src/network.c @@ -37,6 +37,7 @@ #include "util.h" #include "storage.h" #include "dbus-queue.h" +#include "missing.h" #define SETTINGS_STORE "netreg" #define SETTINGS_GROUP "Settings" diff --git a/ofono/src/sim.c b/ofono/src/sim.c index 5b7e8dbdd..631bbfb62 100644 --- a/ofono/src/sim.c +++ b/ofono/src/sim.c @@ -46,6 +46,7 @@ #include "storage.h" #include "simfs.h" #include "stkutil.h" +#include "missing.h" /* * A new session object will be created if a USim/ISim applications are diff --git a/ofono/src/simfs.c b/ofono/src/simfs.c index b15d679ce..ee48e48d3 100644 --- a/ofono/src/simfs.c +++ b/ofono/src/simfs.c @@ -40,6 +40,7 @@ #include "simfs.h" #include "simutil.h" #include "storage.h" +#include "missing.h" #define SIM_CACHE_MODE 0600 #define SIM_CACHE_BASEPATH STORAGEDIR "/%s-%i" diff --git a/ofono/src/simutil.c b/ofono/src/simutil.c index 9e1291b93..7e9c2d03b 100644 --- a/ofono/src/simutil.c +++ b/ofono/src/simutil.c @@ -33,6 +33,7 @@ #include "simutil.h" #include "util.h" #include "smsutil.h" +#include "missing.h" struct sim_eons { struct sim_eons_operator_info *pnn_list; diff --git a/ofono/src/smsutil.c b/ofono/src/smsutil.c index b08351b8d..88a8746c2 100644 --- a/ofono/src/smsutil.c +++ b/ofono/src/smsutil.c @@ -38,6 +38,7 @@ #include "util.h" #include "storage.h" #include "smsutil.h" +#include "missing.h" #include diff --git a/ofono/src/voicecall.c b/ofono/src/voicecall.c index cafe34a3c..9c0be2b2c 100644 --- a/ofono/src/voicecall.c +++ b/ofono/src/voicecall.c @@ -40,6 +40,7 @@ #include "smsutil.h" #include "storage.h" #include "voicecallagent.h" +#include "missing.h" #define MAX_VOICE_CALLS 16 diff --git a/ofono/tools/stktest.c b/ofono/tools/stktest.c index 5863bc5e0..80d277e3c 100644 --- a/ofono/tools/stktest.c +++ b/ofono/tools/stktest.c @@ -36,6 +36,7 @@ #include #include +#include "src/missing.h" #include "unit/stk-test-data.h" #define OFONO_SERVICE "org.ofono" From 25a588163c9d8578dad20cd979d7a41279f0eab6 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 5 May 2021 11:05:20 +0200 Subject: [PATCH 306/320] Release 1.32 --- ofono/ChangeLog | 6 ++++++ ofono/configure.ac | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ofono/ChangeLog b/ofono/ChangeLog index 0fc32a86d..3fc2ba026 100644 --- a/ofono/ChangeLog +++ b/ofono/ChangeLog @@ -1,3 +1,9 @@ +ver 1.32: + Fix issue with handling of IMS private identity validation. + Fix issue with handling of SIM EF structure bit processing. + Fix issue with handling removal of Huawai modems. + Add support for USSD indication with QMI modems. + ver 1.31: Fix issue with handling CID 0 context identifier. Fix issue with handling detach state and running LTE. diff --git a/ofono/configure.ac b/ofono/configure.ac index cec208ecd..05f2e0871 100644 --- a/ofono/configure.ac +++ b/ofono/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.60) -AC_INIT(ofono, 1.31) +AC_INIT(ofono, 1.32) AM_INIT_AUTOMAKE([foreign subdir-objects color-tests]) AC_CONFIG_HEADERS(config.h) From 98120f749b3d08ae735f83191746bd575edb3e49 Mon Sep 17 00:00:00 2001 From: Sean Nyekjaer Date: Mon, 31 May 2021 13:49:32 +0200 Subject: [PATCH 307/320] doc: radio-settings: adding UE dual mode operation property Added one new value for TechnologyPreference property as follows: "lte,gsm" Dual mode operation with LTE and GSM radio access whith preference for LTE. --- ofono/doc/radio-settings-api.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ofono/doc/radio-settings-api.txt b/ofono/doc/radio-settings-api.txt index 9663b07f9..ad4a14d87 100644 --- a/ofono/doc/radio-settings-api.txt +++ b/ofono/doc/radio-settings-api.txt @@ -50,6 +50,9 @@ Properties string TechnologyPreference [readwrite] "lte,umts" Dual mode operation with LTE and UMTS radio access with preference for LTE. + "lte,gsm" Dual mode operation with LTE + and GSM radio access with preference + for LTE. array{string} AvailableTechnologies [readonly, optional] From 0c45cfb97bf0bf0daab7aa152f0fce4075efe0d8 Mon Sep 17 00:00:00 2001 From: Sean Nyekjaer Date: Mon, 31 May 2021 13:49:31 +0200 Subject: [PATCH 308/320] radio-settings: Add handling of dual mode technology preference Allow setting of "lte,gsm" mode, for modems that doesn't support ANY mode. --- ofono/src/radio-settings.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ofono/src/radio-settings.c b/ofono/src/radio-settings.c index 6d4169a5a..cb9e9b370 100644 --- a/ofono/src/radio-settings.c +++ b/ofono/src/radio-settings.c @@ -94,6 +94,9 @@ const char *ofono_radio_access_mode_to_string(enum ofono_radio_access_mode m) if (m == (OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_UMTS)) return "lte,umts"; + if (m == (OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_GSM)) + return "lte,gsm"; + return NULL; } @@ -122,6 +125,9 @@ ofono_bool_t ofono_radio_access_mode_from_string(const char *str, } else if (g_str_equal(str, "lte,umts")) { *mode = OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_UMTS; return TRUE; + } else if (g_str_equal(str, "lte,gsm")) { + *mode = OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_GSM; + return TRUE; } return FALSE; From 21cf30535645d759119c51f339205da9a4bd502c Mon Sep 17 00:00:00 2001 From: Sean Nyekjaer Date: Mon, 31 May 2021 13:49:30 +0200 Subject: [PATCH 309/320] qmimodem: Add handling of dual mode technology preference Handled dual mode technology preference "lte,gsm" for Quectel BG96. Quectel BG96 doesn't support ANY mode. --- ofono/drivers/qmimodem/radio-settings.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ofono/drivers/qmimodem/radio-settings.c b/ofono/drivers/qmimodem/radio-settings.c index d6f911a15..abddc7e39 100644 --- a/ofono/drivers/qmimodem/radio-settings.c +++ b/ofono/drivers/qmimodem/radio-settings.c @@ -68,6 +68,9 @@ static void get_system_selection_pref_cb(struct qmi_result *result, case QMI_NAS_RAT_MODE_PREF_LTE: mode = OFONO_RADIO_ACCESS_MODE_LTE; break; + case QMI_NAS_RAT_MODE_PREF_GSM|QMI_NAS_RAT_MODE_PREF_LTE: + mode = OFONO_RADIO_ACCESS_MODE_GSM|OFONO_RADIO_ACCESS_MODE_LTE; + break; } CALLBACK_WITH_SUCCESS(cb, mode, cbd->data); @@ -131,6 +134,9 @@ static void qmi_set_rat_mode(struct ofono_radio_settings *rs, case OFONO_RADIO_ACCESS_MODE_LTE: pref = QMI_NAS_RAT_MODE_PREF_LTE; break; + case OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_GSM: + pref = QMI_NAS_RAT_MODE_PREF_LTE|QMI_NAS_RAT_MODE_PREF_GSM; + break; } param = qmi_param_new(); From 371ab0be4a18967294a6c16536e13a4bb1e2385d Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Tue, 1 Jun 2021 11:20:37 -0500 Subject: [PATCH 310/320] radio-settings: Do not use enum ofono_access_mode Originally the enum was only meant to signify a single radio access mode preference, but over time its meaning was overloaded to be a bitfield with multiple preferences. Switch away from using an enum value to using an unsigned int to make it clearer that the value is a bitfield. --- ofono/drivers/hsomodem/radio-settings.c | 4 ++-- ofono/drivers/huaweimodem/radio-settings.c | 10 ++++----- ofono/drivers/iceramodem/radio-settings.c | 4 ++-- ofono/drivers/ifxmodem/radio-settings.c | 5 ++--- ofono/drivers/isimodem/radio-settings.c | 7 +++---- ofono/drivers/nwmodem/radio-settings.c | 5 ++--- ofono/drivers/qmimodem/radio-settings.c | 5 ++--- ofono/drivers/rilmodem/radio-settings.c | 3 +-- ofono/drivers/stemodem/radio-settings.c | 9 ++++---- ofono/drivers/xmm7modem/radio-settings.c | 5 ++--- ofono/drivers/ztemodem/radio-settings.c | 5 ++--- ofono/include/radio-settings.h | 6 ++---- ofono/src/radio-settings.c | 24 +++++++++------------- 13 files changed, 39 insertions(+), 53 deletions(-) diff --git a/ofono/drivers/hsomodem/radio-settings.c b/ofono/drivers/hsomodem/radio-settings.c index 0a5e48fff..c074d8461 100644 --- a/ofono/drivers/hsomodem/radio-settings.c +++ b/ofono/drivers/hsomodem/radio-settings.c @@ -50,7 +50,7 @@ static void opsys_query_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct cb_data *cbd = user_data; ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb; - enum ofono_radio_access_mode mode; + unsigned int mode; struct ofono_error error; GAtResultIter iter; int value; @@ -120,7 +120,7 @@ static void opsys_modify_cb(gboolean ok, GAtResult *result, gpointer user_data) } static void hso_set_rat_mode(struct ofono_radio_settings *rs, - enum ofono_radio_access_mode mode, + unsigned int mode, ofono_radio_settings_rat_mode_set_cb_t cb, void *data) { diff --git a/ofono/drivers/huaweimodem/radio-settings.c b/ofono/drivers/huaweimodem/radio-settings.c index b3f31e56c..60a15bc99 100644 --- a/ofono/drivers/huaweimodem/radio-settings.c +++ b/ofono/drivers/huaweimodem/radio-settings.c @@ -134,7 +134,7 @@ static void syscfg_query_mode_cb(gboolean ok, GAtResult *result, { struct cb_data *cbd = user_data; ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb; - enum ofono_radio_access_mode mode; + unsigned int mode; struct ofono_error error; GAtResultIter iter; int value; @@ -182,7 +182,7 @@ static void syscfgex_query_mode_cb(gboolean ok, GAtResult *result, { struct cb_data *cbd = user_data; ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb; - enum ofono_radio_access_mode mode; + unsigned int mode; struct ofono_error error; GAtResultIter iter; const char *acqorder; @@ -262,7 +262,7 @@ static void syscfgxx_modify_mode_cb(gboolean ok, GAtResult *result, } static void syscfg_set_rat_mode(struct radio_settings_data *rsd, - enum ofono_radio_access_mode mode, + unsigned int mode, ofono_radio_settings_rat_mode_set_cb_t cb, void *data) { @@ -302,7 +302,7 @@ static void syscfg_set_rat_mode(struct radio_settings_data *rsd, } static void syscfgex_set_rat_mode(struct radio_settings_data *rsd, - enum ofono_radio_access_mode mode, + unsigned int mode, ofono_radio_settings_rat_mode_set_cb_t cb, void *data) { @@ -344,7 +344,7 @@ static void syscfgex_set_rat_mode(struct radio_settings_data *rsd, } static void huawei_set_rat_mode(struct ofono_radio_settings *rs, - enum ofono_radio_access_mode mode, + unsigned int mode, ofono_radio_settings_rat_mode_set_cb_t cb, void *data) { diff --git a/ofono/drivers/iceramodem/radio-settings.c b/ofono/drivers/iceramodem/radio-settings.c index defa43302..77498f37a 100644 --- a/ofono/drivers/iceramodem/radio-settings.c +++ b/ofono/drivers/iceramodem/radio-settings.c @@ -51,7 +51,7 @@ static void ipsys_query_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct cb_data *cbd = user_data; ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb; - enum ofono_radio_access_mode mode; + unsigned int mode; struct ofono_error error; GAtResultIter iter; int value; @@ -121,7 +121,7 @@ static void ipsys_modify_cb(gboolean ok, GAtResult *result, gpointer user_data) } static void icera_set_rat_mode(struct ofono_radio_settings *rs, - enum ofono_radio_access_mode mode, + unsigned int mode, ofono_radio_settings_rat_mode_set_cb_t cb, void *data) { diff --git a/ofono/drivers/ifxmodem/radio-settings.c b/ofono/drivers/ifxmodem/radio-settings.c index c132ba70a..ebc21e0ae 100644 --- a/ofono/drivers/ifxmodem/radio-settings.c +++ b/ofono/drivers/ifxmodem/radio-settings.c @@ -50,7 +50,7 @@ static void xrat_query_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct cb_data *cbd = user_data; ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb; - enum ofono_radio_access_mode mode; + unsigned int mode; struct ofono_error error; GAtResultIter iter; int value, preferred; @@ -120,8 +120,7 @@ static void xrat_modify_cb(gboolean ok, GAtResult *result, gpointer user_data) cb(&error, cbd->data); } -static void ifx_set_rat_mode(struct ofono_radio_settings *rs, - enum ofono_radio_access_mode mode, +static void ifx_set_rat_mode(struct ofono_radio_settings *rs, unsigned int mode, ofono_radio_settings_rat_mode_set_cb_t cb, void *data) { diff --git a/ofono/drivers/isimodem/radio-settings.c b/ofono/drivers/isimodem/radio-settings.c index fa5330054..f3f35e3ec 100644 --- a/ofono/drivers/isimodem/radio-settings.c +++ b/ofono/drivers/isimodem/radio-settings.c @@ -52,7 +52,7 @@ struct radio_data { uint16_t quick_release:1; }; -static enum ofono_radio_access_mode isi_mode_to_ofono_mode(guint8 mode) +static unsigned int isi_mode_to_ofono_mode(guint8 mode) { switch (mode) { case GSS_DUAL_RAT: @@ -66,7 +66,7 @@ static enum ofono_radio_access_mode isi_mode_to_ofono_mode(guint8 mode) } } -static int ofono_mode_to_isi_mode(enum ofono_radio_access_mode mode) +static int ofono_mode_to_isi_mode(unsigned int mode) { switch (mode) { case OFONO_RADIO_ACCESS_MODE_ANY: @@ -184,8 +184,7 @@ static void mode_write_resp_cb(const GIsiMessage *msg, void *opaque) return; } -static void isi_set_rat_mode(struct ofono_radio_settings *rs, - enum ofono_radio_access_mode mode, +static void isi_set_rat_mode(struct ofono_radio_settings *rs, unsigned int mode, ofono_radio_settings_rat_mode_set_cb_t cb, void *data) { diff --git a/ofono/drivers/nwmodem/radio-settings.c b/ofono/drivers/nwmodem/radio-settings.c index 13330e0b3..0a363f8f6 100644 --- a/ofono/drivers/nwmodem/radio-settings.c +++ b/ofono/drivers/nwmodem/radio-settings.c @@ -50,7 +50,7 @@ static void nwrat_query_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct cb_data *cbd = user_data; ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb; - enum ofono_radio_access_mode mode; + unsigned int mode; struct ofono_error error; GAtResultIter iter; int value; @@ -117,8 +117,7 @@ static void nwrat_modify_cb(gboolean ok, GAtResult *result, gpointer user_data) cb(&error, cbd->data); } -static void nw_set_rat_mode(struct ofono_radio_settings *rs, - enum ofono_radio_access_mode mode, +static void nw_set_rat_mode(struct ofono_radio_settings *rs, unsigned int mode, ofono_radio_settings_rat_mode_set_cb_t cb, void *data) { diff --git a/ofono/drivers/qmimodem/radio-settings.c b/ofono/drivers/qmimodem/radio-settings.c index abddc7e39..7ee952169 100644 --- a/ofono/drivers/qmimodem/radio-settings.c +++ b/ofono/drivers/qmimodem/radio-settings.c @@ -45,7 +45,7 @@ static void get_system_selection_pref_cb(struct qmi_result *result, { struct cb_data *cbd = user_data; ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb; - enum ofono_radio_access_mode mode = OFONO_RADIO_ACCESS_MODE_ANY; + unsigned int mode = OFONO_RADIO_ACCESS_MODE_ANY; uint16_t pref; DBG(""); @@ -109,8 +109,7 @@ static void set_system_selection_pref_cb(struct qmi_result *result, CALLBACK_WITH_SUCCESS(cb, cbd->data); } -static void qmi_set_rat_mode(struct ofono_radio_settings *rs, - enum ofono_radio_access_mode mode, +static void qmi_set_rat_mode(struct ofono_radio_settings *rs, unsigned int mode, ofono_radio_settings_rat_mode_set_cb_t cb, void *user_data) { diff --git a/ofono/drivers/rilmodem/radio-settings.c b/ofono/drivers/rilmodem/radio-settings.c index a2e25e0bf..446b97e13 100644 --- a/ofono/drivers/rilmodem/radio-settings.c +++ b/ofono/drivers/rilmodem/radio-settings.c @@ -102,8 +102,7 @@ static void ril_set_rat_cb(struct ril_msg *message, gpointer user_data) } } -static void ril_set_rat_mode(struct ofono_radio_settings *rs, - enum ofono_radio_access_mode mode, +static void ril_set_rat_mode(struct ofono_radio_settings *rs, unsigned int mode, ofono_radio_settings_rat_mode_set_cb_t cb, void *data) { diff --git a/ofono/drivers/stemodem/radio-settings.c b/ofono/drivers/stemodem/radio-settings.c index 5e726cd5b..d30acbc9a 100644 --- a/ofono/drivers/stemodem/radio-settings.c +++ b/ofono/drivers/stemodem/radio-settings.c @@ -56,7 +56,7 @@ enum ste_radio_mode { }; static gboolean ste_mode_to_ofono_mode(enum ste_radio_mode stemode, - enum ofono_radio_access_mode *mode) + unsigned int *mode) { switch (stemode) { case STE_RADIO_ON: @@ -76,7 +76,7 @@ static gboolean ste_mode_to_ofono_mode(enum ste_radio_mode stemode, return FALSE; } -static gboolean ofono_mode_to_ste_mode(enum ofono_radio_access_mode mode, +static gboolean ofono_mode_to_ste_mode(unsigned int mode, enum ste_radio_mode *stemode) { switch (mode) { @@ -100,7 +100,7 @@ static void rat_query_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct cb_data *cbd = user_data; ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb; - enum ofono_radio_access_mode mode; + unsigned int mode; struct ofono_error error; GAtResultIter iter; int value; @@ -161,8 +161,7 @@ static void rat_modify_cb(gboolean ok, GAtResult *result, gpointer user_data) CALLBACK_WITH_SUCCESS(cb, cbd->data); } -static void ste_set_rat_mode(struct ofono_radio_settings *rs, - enum ofono_radio_access_mode mode, +static void ste_set_rat_mode(struct ofono_radio_settings *rs, unsigned int mode, ofono_radio_settings_rat_mode_set_cb_t cb, void *data) { diff --git a/ofono/drivers/xmm7modem/radio-settings.c b/ofono/drivers/xmm7modem/radio-settings.c index c7c2ce0e8..19557bdc7 100644 --- a/ofono/drivers/xmm7modem/radio-settings.c +++ b/ofono/drivers/xmm7modem/radio-settings.c @@ -50,7 +50,7 @@ static void xact_query_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct cb_data *cbd = user_data; ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb; - enum ofono_radio_access_mode mode; + unsigned int mode; struct ofono_error error; GAtResultIter iter; int value, preferred; @@ -133,8 +133,7 @@ static void xact_modify_cb(gboolean ok, GAtResult *result, gpointer user_data) cb(&error, cbd->data); } -static void xmm_set_rat_mode(struct ofono_radio_settings *rs, - enum ofono_radio_access_mode mode, +static void xmm_set_rat_mode(struct ofono_radio_settings *rs, unsigned int mode, ofono_radio_settings_rat_mode_set_cb_t cb, void *data) { diff --git a/ofono/drivers/ztemodem/radio-settings.c b/ofono/drivers/ztemodem/radio-settings.c index 6a2b1fc15..e83f45506 100644 --- a/ofono/drivers/ztemodem/radio-settings.c +++ b/ofono/drivers/ztemodem/radio-settings.c @@ -50,7 +50,7 @@ static void zsnt_query_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct cb_data *cbd = user_data; ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb; - enum ofono_radio_access_mode mode; + unsigned int mode; struct ofono_error error; GAtResultIter iter; int value; @@ -117,8 +117,7 @@ static void zsnt_modify_cb(gboolean ok, GAtResult *result, gpointer user_data) cb(&error, cbd->data); } -static void zte_set_rat_mode(struct ofono_radio_settings *rs, - enum ofono_radio_access_mode mode, +static void zte_set_rat_mode(struct ofono_radio_settings *rs, unsigned int mode, ofono_radio_settings_rat_mode_set_cb_t cb, void *data) { diff --git a/ofono/include/radio-settings.h b/ofono/include/radio-settings.h index f994d1d8f..114c91d44 100644 --- a/ofono/include/radio-settings.h +++ b/ofono/include/radio-settings.h @@ -61,8 +61,7 @@ typedef void (*ofono_radio_settings_rat_mode_set_cb_t)( void *data); typedef void (*ofono_radio_settings_rat_mode_query_cb_t)( const struct ofono_error *error, - enum ofono_radio_access_mode mode, - void *data); + int mode, void *data); typedef void (*ofono_radio_settings_band_set_cb_t)( const struct ofono_error *error, @@ -94,8 +93,7 @@ struct ofono_radio_settings_driver { void (*query_rat_mode)(struct ofono_radio_settings *rs, ofono_radio_settings_rat_mode_query_cb_t cb, void *data); - void (*set_rat_mode)(struct ofono_radio_settings *rs, - enum ofono_radio_access_mode mode, + void (*set_rat_mode)(struct ofono_radio_settings *rs, unsigned int mode, ofono_radio_settings_rat_mode_set_cb_t cb, void *data); void (*query_band)(struct ofono_radio_settings *rs, diff --git a/ofono/src/radio-settings.c b/ofono/src/radio-settings.c index cb9e9b370..1ff9a40c2 100644 --- a/ofono/src/radio-settings.c +++ b/ofono/src/radio-settings.c @@ -46,11 +46,11 @@ static GSList *g_drivers = NULL; struct ofono_radio_settings { struct ofono_dbus_queue *q; int flags; - enum ofono_radio_access_mode mode; + unsigned int mode; enum ofono_radio_band_gsm band_gsm; enum ofono_radio_band_umts band_umts; ofono_bool_t fast_dormancy; - enum ofono_radio_access_mode pending_mode; + unsigned int pending_mode; enum ofono_radio_band_gsm pending_band_gsm; enum ofono_radio_band_umts pending_band_umts; ofono_bool_t fast_dormancy_pending; @@ -62,8 +62,8 @@ struct ofono_radio_settings { struct ofono_atom *atom; }; -enum ofono_radio_access_mode ofono_radio_access_max_mode( - enum ofono_radio_access_mode mask) +unsigned int ofono_radio_access_max_mode( + unsigned int mask) { return (mask & OFONO_RADIO_ACCESS_MODE_LTE) ? OFONO_RADIO_ACCESS_MODE_LTE : @@ -74,8 +74,7 @@ enum ofono_radio_access_mode ofono_radio_access_max_mode( OFONO_RADIO_ACCESS_MODE_ANY; } -#define radio_access_mode_to_string ofono_radio_access_mode_to_string -const char *ofono_radio_access_mode_to_string(enum ofono_radio_access_mode m) +static const char *radio_access_mode_to_string(unsigned int m) { switch (ofono_radio_access_max_mode(m)) { case OFONO_RADIO_ACCESS_MODE_ANY: @@ -100,10 +99,8 @@ const char *ofono_radio_access_mode_to_string(enum ofono_radio_access_mode m) return NULL; } -#define radio_access_mode_from_string ofono_radio_access_mode_from_string -ofono_bool_t ofono_radio_access_mode_from_string(const char *str, - enum ofono_radio_access_mode *mode) - +static gboolean radio_access_mode_from_string(const char *str, + unsigned int *mode) { if (!str) { return FALSE; @@ -391,7 +388,7 @@ static void radio_band_set_callback(const struct ofono_error *error, } static void radio_set_rat_mode(struct ofono_radio_settings *rs, - enum ofono_radio_access_mode mode) + unsigned int mode) { DBusConnection *conn = ofono_dbus_get_connection(); const char *path; @@ -536,8 +533,7 @@ static void radio_query_band(struct ofono_radio_settings *rs) } static void radio_rat_mode_query_callback(const struct ofono_error *error, - enum ofono_radio_access_mode mode, - void *data) + int mode, void *data) { struct ofono_radio_settings *rs = data; @@ -596,7 +592,7 @@ static DBusMessage *radio_set_property_handler(DBusMessage *msg, void *data) if (g_strcmp0(property, "TechnologyPreference") == 0) { const char *value; - enum ofono_radio_access_mode mode; + unsigned int mode; if (rs->driver->set_rat_mode == NULL) return __ofono_error_not_implemented(msg); From 8b83d9933c7a2573c8fec1e0e28bbf2d2a40905c Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Tue, 15 Jun 2021 09:24:07 -0500 Subject: [PATCH 311/320] README: Mention the new OFTC irc channel --- ofono/README | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ofono/README b/ofono/README index e42415732..3ffd05a83 100644 --- a/ofono/README +++ b/ofono/README @@ -34,5 +34,8 @@ Information Mailing list: ofono@ofono.org +IRC: + irc://irc.oftc.net/#ofono + For additional information about the project visit oFono web site: http://www.ofono.org From 7d5cbf81bf43ea78e94d2d7814d35dbfa1bcb824 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Sun, 4 Jul 2021 18:53:46 +0300 Subject: [PATCH 312/320] gemalto: add radio-settings driver Add support for Gemalto specific radio settings. --- ofono/Makefile.am | 1 + ofono/drivers/gemaltomodem/gemaltomodem.c | 2 + ofono/drivers/gemaltomodem/gemaltomodem.h | 3 + ofono/drivers/gemaltomodem/radio-settings.c | 267 ++++++++++++++++++++ 4 files changed, 273 insertions(+) create mode 100644 ofono/drivers/gemaltomodem/radio-settings.c diff --git a/ofono/Makefile.am b/ofono/Makefile.am index 3c18a4e81..088db525f 100644 --- a/ofono/Makefile.am +++ b/ofono/Makefile.am @@ -417,6 +417,7 @@ builtin_sources += drivers/atmodem/atutil.h \ drivers/gemaltomodem/location-reporting.c \ drivers/gemaltomodem/voicecall.c \ drivers/gemaltomodem/gprs-context.c \ + drivers/gemaltomodem/radio-settings.c \ drivers/gemaltomodem/netmon.c builtin_modules += xmm7modem diff --git a/ofono/drivers/gemaltomodem/gemaltomodem.c b/ofono/drivers/gemaltomodem/gemaltomodem.c index f7e4ff3ee..bcf37e5ef 100644 --- a/ofono/drivers/gemaltomodem/gemaltomodem.c +++ b/ofono/drivers/gemaltomodem/gemaltomodem.c @@ -36,6 +36,7 @@ static int gemaltomodem_init(void) { gemalto_location_reporting_init(); + gemalto_radio_settings_init(); gemalto_gprs_context_init(); gemalto_voicecall_init(); gemalto_netmon_init(); @@ -46,6 +47,7 @@ static int gemaltomodem_init(void) static void gemaltomodem_exit(void) { gemalto_location_reporting_exit(); + gemalto_radio_settings_exit(); gemalto_gprs_context_exit(); gemalto_voicecall_exit(); gemalto_netmon_exit(); diff --git a/ofono/drivers/gemaltomodem/gemaltomodem.h b/ofono/drivers/gemaltomodem/gemaltomodem.h index ae8f2141a..91a70baa0 100644 --- a/ofono/drivers/gemaltomodem/gemaltomodem.h +++ b/ofono/drivers/gemaltomodem/gemaltomodem.h @@ -33,3 +33,6 @@ extern void gemalto_gprs_context_exit(); extern void gemalto_netmon_init(void); extern void gemalto_netmon_exit(void); + +extern void gemalto_radio_settings_init(void); +extern void gemalto_radio_settings_exit(void); diff --git a/ofono/drivers/gemaltomodem/radio-settings.c b/ofono/drivers/gemaltomodem/radio-settings.c new file mode 100644 index 000000000..738a69087 --- /dev/null +++ b/ofono/drivers/gemaltomodem/radio-settings.c @@ -0,0 +1,267 @@ +/* + * + * oFono - Open Source Telephony + * + * Copyright (C) 2017 Intel Corporation. All rights reserved. + * Copyright (C) 2021 Sergey Matyukevich. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "gatchat.h" +#include "gatresult.h" + +#include "gemaltomodem.h" + +static const char *none_prefix[] = { NULL }; +static const char *sxrat_prefix[] = { "^SXRAT:", NULL }; + +struct radio_settings_data { + GAtChat *chat; +}; + +static void sxrat_query_cb(gboolean ok, GAtResult *result, gpointer user_data) +{ + struct cb_data *cbd = user_data; + ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb; + unsigned int mode; + struct ofono_error error; + int value, pref1, pref2; + GAtResultIter iter; + + DBG("ok %d", ok); + + decode_at_error(&error, g_at_result_final_response(result)); + + if (!ok) { + cb(&error, -1, cbd->data); + return; + } + + g_at_result_iter_init(&iter, result); + + if (!g_at_result_iter_next(&iter, "^SXRAT:")) + goto error; + + if (!g_at_result_iter_next_number(&iter, &value)) + goto error; + + g_at_result_iter_next_number_default(&iter, -1, &pref1); + g_at_result_iter_next_number_default(&iter, -1, &pref2); + + DBG("mode %d pref1 %d pref2 %d", value, pref1, pref2); + + switch (value) { + case 0: + mode = OFONO_RADIO_ACCESS_MODE_GSM; + break; + case 1: + mode = OFONO_RADIO_ACCESS_MODE_GSM | + OFONO_RADIO_ACCESS_MODE_UMTS; + break; + case 2: + mode = OFONO_RADIO_ACCESS_MODE_UMTS; + break; + case 3: + mode = OFONO_RADIO_ACCESS_MODE_LTE; + break; + case 4: + mode = OFONO_RADIO_ACCESS_MODE_UMTS | + OFONO_RADIO_ACCESS_MODE_LTE; + break; + case 5: + mode = OFONO_RADIO_ACCESS_MODE_GSM | + OFONO_RADIO_ACCESS_MODE_LTE; + break; + case 6: + mode = OFONO_RADIO_ACCESS_MODE_ANY; + break; + default: + CALLBACK_WITH_FAILURE(cb, -1, cbd->data); + return; + } + + cb(&error, mode, cbd->data); + + return; + +error: + CALLBACK_WITH_FAILURE(cb, -1, cbd->data); +} + +static void gemalto_query_rat_mode(struct ofono_radio_settings *rs, + ofono_radio_settings_rat_mode_query_cb_t cb, + void *data) +{ + struct radio_settings_data *rsd = ofono_radio_settings_get_data(rs); + struct cb_data *cbd = cb_data_new(cb, data); + + DBG(""); + + if (g_at_chat_send(rsd->chat, "AT^SXRAT?", sxrat_prefix, + sxrat_query_cb, cbd, g_free) == 0) { + CALLBACK_WITH_FAILURE(cb, -1, data); + g_free(cbd); + } +} + +static void sxrat_modify_cb(gboolean ok, GAtResult *result, gpointer user_data) +{ + struct cb_data *cbd = user_data; + ofono_radio_settings_rat_mode_set_cb_t cb = cbd->cb; + struct ofono_error error; + + DBG("ok %d", ok); + + decode_at_error(&error, g_at_result_final_response(result)); + cb(&error, cbd->data); +} + +static void gemalto_set_rat_mode(struct ofono_radio_settings *rs, + unsigned int m, + ofono_radio_settings_rat_mode_set_cb_t cb, + void *data) +{ + struct radio_settings_data *rsd = ofono_radio_settings_get_data(rs); + struct cb_data *cbd = cb_data_new(cb, data); + int val= 6, p1 = 3, p2 = 2; + char buf[20]; + + DBG("mode %d", m); + + switch (m) { + case OFONO_RADIO_ACCESS_MODE_ANY: + val = 6; + p1 = 3; + p2 = 2; + break; + case OFONO_RADIO_ACCESS_MODE_GSM: + val = 0; + break; + case OFONO_RADIO_ACCESS_MODE_UMTS: + val = 2; + break; + case OFONO_RADIO_ACCESS_MODE_LTE: + val = 3; + break; + } + + if (m == (OFONO_RADIO_ACCESS_MODE_UMTS|OFONO_RADIO_ACCESS_MODE_GSM)) { + val = 1; + p1 = 2; + } + + if (m == (OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_UMTS)) { + val = 4; + p1 = 3; + } + + if (m == (OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_GSM)) { + val = 5; + p1 = 3; + } + + if (val == 6) + snprintf(buf, sizeof(buf), "AT^SXRAT=%u,%u,%u", val, p1, p2); + else if (val == 1 || val == 4 || val == 5) + snprintf(buf, sizeof(buf), "AT^SXRAT=%u,%u", val, p1); + else + snprintf(buf, sizeof(buf), "AT^SXRAT=%u", val); + + if (g_at_chat_send(rsd->chat, buf, none_prefix, + sxrat_modify_cb, cbd, g_free) > 0) + return; + + CALLBACK_WITH_FAILURE(cb, data); + g_free(cbd); +} + +static void sxrat_support_cb(gboolean ok, GAtResult *result, gpointer user_data) +{ + struct ofono_radio_settings *rs = user_data; + + DBG("ok %d", ok); + + if (!ok) { + ofono_radio_settings_remove(rs); + return; + } + + ofono_radio_settings_register(rs); +} + +static int gemalto_radio_settings_probe(struct ofono_radio_settings *rs, + unsigned int vendor, void *data) +{ + GAtChat *chat = data; + struct radio_settings_data *rsd; + + DBG(""); + + rsd = g_new0(struct radio_settings_data, 1); + + rsd->chat = g_at_chat_clone(chat); + + ofono_radio_settings_set_data(rs, rsd); + + g_at_chat_send(rsd->chat, "AT^SXRAT=?", sxrat_prefix, + sxrat_support_cb, rs, NULL); + + return 0; +} + +static void gemalto_radio_settings_remove(struct ofono_radio_settings *rs) +{ + struct radio_settings_data *rsd = ofono_radio_settings_get_data(rs); + + DBG(""); + + ofono_radio_settings_set_data(rs, NULL); + g_at_chat_unref(rsd->chat); + g_free(rsd); +} + +static const struct ofono_radio_settings_driver driver = { + .name = "gemaltomodem", + .probe = gemalto_radio_settings_probe, + .remove = gemalto_radio_settings_remove, + .query_rat_mode = gemalto_query_rat_mode, + .set_rat_mode = gemalto_set_rat_mode +}; + +void gemalto_radio_settings_init(void) +{ + ofono_radio_settings_driver_register(&driver); +} + +void gemalto_radio_settings_exit(void) +{ + ofono_radio_settings_driver_unregister(&driver); +} From 049b59d43eae8d34b2a207ccc89ba5c4f2161376 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Sun, 4 Jul 2021 18:53:47 +0300 Subject: [PATCH 313/320] plugins: gemalto: add radio-settings atom Instantiate Gemalto radio-settings atom in post_sim. --- ofono/plugins/gemalto.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ofono/plugins/gemalto.c b/ofono/plugins/gemalto.c index 135e2d267..a2e8a39ce 100644 --- a/ofono/plugins/gemalto.c +++ b/ofono/plugins/gemalto.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -597,6 +598,7 @@ static void gemalto_post_sim(struct ofono_modem *modem) ofono_phonebook_create(modem, 0, "atmodem", data->app); ofono_sms_create(modem, OFONO_VENDOR_GEMALTO, "atmodem", data->app); + ofono_radio_settings_create(modem, 0, "gemaltomodem", data->app); gprs = ofono_gprs_create(modem, 0, "atmodem", data->app); From 24070010be959f86bfca731159850250f63274db Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Sun, 4 Jul 2021 18:53:48 +0300 Subject: [PATCH 314/320] plugins: gemalto: move ussd atom to post_online Gemalto modem does not allow to enable Supplementary Service during post_sim stage. So move ussd atom to post_online stage. --- ofono/plugins/gemalto.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ofono/plugins/gemalto.c b/ofono/plugins/gemalto.c index a2e8a39ce..d1962ab84 100644 --- a/ofono/plugins/gemalto.c +++ b/ofono/plugins/gemalto.c @@ -614,8 +614,6 @@ static void gemalto_post_sim(struct ofono_modem *modem) if (gprs && gc) ofono_gprs_add_context(gprs, gc); - ofono_ussd_create(modem, 0, "atmodem", data->app); - if (!g_strcmp0(model, GEMALTO_MODEL_ALS3_PLS8x) || !g_strcmp0(model, GEMALTO_MODEL_ELS81x)) ofono_lte_create(modem, OFONO_VENDOR_GEMALTO, @@ -639,6 +637,8 @@ static void gemalto_post_online(struct ofono_modem *modem) ofono_call_meter_create(modem, 0, "atmodem", data->app); ofono_call_barring_create(modem, 0, "atmodem", data->app); + ofono_ussd_create(modem, 0, "atmodem", data->app); + if (!g_strcmp0(model, GEMALTO_MODEL_ELS81x)) ofono_netmon_create(modem, OFONO_VENDOR_GEMALTO, "gemaltomodem", data->app); From f60cebdfd7d63e648cebe89572d16aa6a8f9808a Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Fri, 23 Jul 2021 20:00:01 +0300 Subject: [PATCH 315/320] gemalto: radio-settings: cleanup Enum ofono_radio_access_mode has been replaced by unsigned int. This change allows to move handling of all the modes into 'switch' in the function gemalto_set_rat_mode. --- ofono/drivers/gemaltomodem/radio-settings.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/ofono/drivers/gemaltomodem/radio-settings.c b/ofono/drivers/gemaltomodem/radio-settings.c index 738a69087..50764f83d 100644 --- a/ofono/drivers/gemaltomodem/radio-settings.c +++ b/ofono/drivers/gemaltomodem/radio-settings.c @@ -171,21 +171,18 @@ static void gemalto_set_rat_mode(struct ofono_radio_settings *rs, case OFONO_RADIO_ACCESS_MODE_LTE: val = 3; break; - } - - if (m == (OFONO_RADIO_ACCESS_MODE_UMTS|OFONO_RADIO_ACCESS_MODE_GSM)) { + case OFONO_RADIO_ACCESS_MODE_UMTS|OFONO_RADIO_ACCESS_MODE_GSM: val = 1; p1 = 2; - } - - if (m == (OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_UMTS)) { + break; + case OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_UMTS: val = 4; p1 = 3; - } - - if (m == (OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_GSM)) { + break; + case OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_GSM: val = 5; p1 = 3; + break; } if (val == 6) From 81d6bbb0be6c3c57e63ed66e74ff1921d685df35 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 15 Sep 2021 13:21:27 +0200 Subject: [PATCH 316/320] Release 1.33 --- ofono/ChangeLog | 5 +++++ ofono/configure.ac | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ofono/ChangeLog b/ofono/ChangeLog index 3fc2ba026..cea95b303 100644 --- a/ofono/ChangeLog +++ b/ofono/ChangeLog @@ -1,3 +1,8 @@ +ver 1.33: + Fix issue with filling unused part of AID with FFs. + Fix issue with reads beyond the first block of SIM filesystem. + Fix issue with parsing auth response according to TS 31.102. + ver 1.32: Fix issue with handling of IMS private identity validation. Fix issue with handling of SIM EF structure bit processing. diff --git a/ofono/configure.ac b/ofono/configure.ac index 05f2e0871..eea5c7372 100644 --- a/ofono/configure.ac +++ b/ofono/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.60) -AC_INIT(ofono, 1.32) +AC_INIT(ofono, 1.33) AM_INIT_AUTOMAKE([foreign subdir-objects color-tests]) AC_CONFIG_HEADERS(config.h) From ce9a30f8e7cddf13a22c66614135ca46aaa0f33f Mon Sep 17 00:00:00 2001 From: Sean Nyekjaer Date: Mon, 6 Dec 2021 10:50:12 +0100 Subject: [PATCH 317/320] quectel: get devinfo Quectel devices returns "Revision:" before the manufacture and revision. Via dbus: "Manufacturer" s "Revision: MTK 0828" "Revision" s "Revision: M95FAR02A08" --- ofono/plugins/quectel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ofono/plugins/quectel.c b/ofono/plugins/quectel.c index c625a8d5a..aecf81725 100644 --- a/ofono/plugins/quectel.c +++ b/ofono/plugins/quectel.c @@ -1322,6 +1322,8 @@ static void quectel_pre_sim(struct ofono_modem *modem) DBG("%p", modem); + ofono_devinfo_create(modem, data->vendor, "atmodem", data->aux); + ofono_voicecall_create(modem, data->vendor, "atmodem", data->aux); sim = ofono_sim_create(modem, data->vendor, "atmodem", data->aux); From 7022f77928047c52c2aaddf8f2d49f0d6f2ca0a2 Mon Sep 17 00:00:00 2001 From: Xiaoyi Chen Date: Mon, 13 Dec 2021 16:35:31 +0800 Subject: [PATCH 318/320] rilmodem: fix register of unsolicited notify --- ofono/drivers/rilmodem/stk.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ofono/drivers/rilmodem/stk.c b/ofono/drivers/rilmodem/stk.c index bfcbf1a0a..0b337e028 100644 --- a/ofono/drivers/rilmodem/stk.c +++ b/ofono/drivers/rilmodem/stk.c @@ -212,13 +212,13 @@ static int ril_stk_probe(struct ofono_stk *stk, unsigned int vendor, ofono_stk_set_data(stk, data); - g_ril_register(ril, RIL_UNSOL_STK_PROACTIVE_COMMAND, + g_ril_register(data->ril, RIL_UNSOL_STK_PROACTIVE_COMMAND, ril_stk_proactive_cmd_notify, stk); - g_ril_register(ril, RIL_UNSOL_STK_SESSION_END, + g_ril_register(data->ril, RIL_UNSOL_STK_SESSION_END, ril_stk_session_end_notify, stk); - g_ril_register(ril, RIL_UNSOL_STK_EVENT_NOTIFY, + g_ril_register(data->ril, RIL_UNSOL_STK_EVENT_NOTIFY, ril_stk_event_notify, stk); g_ril_send(data->ril, RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING, NULL, From 0c1951cf60c0c5c0dde199b5ba00b74afa0687e4 Mon Sep 17 00:00:00 2001 From: JongSeok Won Date: Thu, 16 Dec 2021 19:48:43 +0900 Subject: [PATCH 319/320] rilmodem: fix handling both of SUCCESS AND FAILURE --- ofono/drivers/rilmodem/netmon.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ofono/drivers/rilmodem/netmon.c b/ofono/drivers/rilmodem/netmon.c index 9f3a11914..d27928045 100644 --- a/ofono/drivers/rilmodem/netmon.c +++ b/ofono/drivers/rilmodem/netmon.c @@ -358,8 +358,10 @@ static void periodic_update_cb(struct ril_msg *message, gpointer user_data) struct cb_data *cbd = user_data; ofono_netmon_cb_t cb = cbd->cb; - if (message->error != RIL_E_SUCCESS) + if (message->error != RIL_E_SUCCESS) { CALLBACK_WITH_FAILURE(cb, cbd->data); + return; + } CALLBACK_WITH_SUCCESS(cb, cbd->data); } From e3d3db8575d70a5a8b8f02b870ceb7715fe20d02 Mon Sep 17 00:00:00 2001 From: Xiaoyi Chen Date: Thu, 16 Dec 2021 17:30:38 +0800 Subject: [PATCH 320/320] rilmodem: fix a problem that manager_dial_callback is never called This problem does not happen each time when dialing. It's only observed with some sim cards under certain network. The time sequence to reproduce the problem is: - send dial request - receive unsol event call state changed - send clcc poll request - clcc poll response (vd->cb is null here) - dial response - setup vd->cb (then it never gets called) --- ofono/drivers/rilmodem/voicecall.c | 12 +++++++++++- ofono/drivers/rilmodem/voicecall.h | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/ofono/drivers/rilmodem/voicecall.c b/ofono/drivers/rilmodem/voicecall.c index 6c1691665..1fce4a3a6 100644 --- a/ofono/drivers/rilmodem/voicecall.c +++ b/ofono/drivers/rilmodem/voicecall.c @@ -396,6 +396,8 @@ static void rild_cb(struct ril_msg *message, gpointer user_data) * DIAL_MODIFIED_TO_DIAL means redirection. The call we will see when * polling will have a different called number. */ + vd->suppress_clcc_poll = FALSE; + if (message->error == RIL_E_SUCCESS || (g_ril_vendor(vd->ril) == OFONO_RIL_VENDOR_AOSP && message->error == RIL_E_DIAL_MODIFIED_TO_DIAL)) { @@ -448,8 +450,10 @@ static void dial(struct ofono_voicecall *vc, /* Send request to RIL */ if (g_ril_send(vd->ril, RIL_REQUEST_DIAL, &rilp, - rild_cb, cbd, g_free) > 0) + rild_cb, cbd, g_free) > 0) { + vd->suppress_clcc_poll = TRUE; return; + } g_free(cbd); CALLBACK_WITH_FAILURE(cb, data); @@ -594,6 +598,11 @@ void ril_call_state_notify(struct ril_msg *message, gpointer user_data) g_ril_print_unsol_no_args(vd->ril, message); + if (vd->suppress_clcc_poll) { + DBG("suppress clcc poll!"); + return; + } + /* Just need to request the call list again */ ril_poll_clcc(vc); @@ -829,6 +838,7 @@ int ril_voicecall_probe(struct ofono_voicecall *vc, unsigned int vendor, vd->vendor = vendor; vd->cb = NULL; vd->data = NULL; + vd->suppress_clcc_poll = FALSE; clear_dtmf_queue(vd); diff --git a/ofono/drivers/rilmodem/voicecall.h b/ofono/drivers/rilmodem/voicecall.h index 31e120e32..beb251043 100644 --- a/ofono/drivers/rilmodem/voicecall.h +++ b/ofono/drivers/rilmodem/voicecall.h @@ -31,6 +31,7 @@ struct ril_voicecall_data { void *data; gchar *tone_queue; gboolean tone_pending; + gboolean suppress_clcc_poll; }; int ril_voicecall_probe(struct ofono_voicecall *vc, unsigned int vendor,