Compare commits

..

12 Commits

Author SHA1 Message Date
Slava Monich
08b3ea3d0f Merge branch 'last_fail' into 'master'
Handle fancy variant of LAST_CALL_FAIL_CAUSE response

Some RILs get creative and invent their own formats.
They must be very proud of it.

See merge request !106
2017-03-15 21:46:11 +00:00
Slava Monich
2978862417 [ril] Handle fancy variant of LAST_CALL_FAIL_CAUSE response. Fixes JB#38079
Some RILs get creative and invent their own formats.
2017-03-15 17:19:37 +02:00
Slava Monich
19228c9e67 Merge branch 'lastcause' into 'master'
Allow to configure custom hangup reasons

One can define localHangupReasons and remoteHangupReasons in
ril_subscription.conf which will be treated as normal local or
remote hangup reasons.

See merge request !104
2017-02-24 13:11:46 +00:00
Slava Monich
9be791d531 [ofono] Allow to conifigure custom hangup reasons. Fixes JB#37879
One can define localHangupReasons and remoteHangupReasons in
ril_subscription.conf which will be treated as normal local or
remote hangup reasons. The value is a comma-separated list of
numbers, e.g.

localHangupReasons=20,39
2017-02-24 12:07:57 +02:00
Slava Monich
6b9eb7bf8f Merge branch 'voicecall' into 'master'
Don't use internal voicecall data structures

Added ofono_voicecall_find_call API instead

See merge request !105
2017-02-24 10:06:39 +00:00
Slava Monich
01f8989aee [ril] Don't use internal voicecall data structures
Use newly added ofono_voicecall_find_call API instead
2017-02-24 00:28:50 +02:00
Slava Monich
2f5efaf591 [ofono] Added ofono_voicecall_find_call API
For use by plugins
2017-02-24 00:28:18 +02:00
Slava Monich
ca1d06c37a Merge branch 'disable' into 'master'
Disable some unnecessary and harmful functionality

See merge request !103
2017-01-12 15:17:23 +00:00
Slava Monich
5f45928a84 [ofono] Disable PhoNet/ISI and QMI modem support. MER#1734
This makes ARM executable smaller by 170 KB
2017-01-12 00:47:04 +02:00
Slava Monich
19f74e6c85 [ofono] Don't allow to add or remove connection context over D-Bus. Fixes MER#1733
Quite a few things in SailfishOS assume that each modem has exactly
one internet and one mms context. However, ofono's D-Bus API allows
any application to arbitrarily add and remove connection contexts
which can screw things up quite badly. Since this functionality is
not used by SailfishOS, it should be disabled.
2017-01-12 00:27:17 +02:00
Slava Monich
41d5cfcab2 Merge branch 'modem-error' into 'master'
Count rild crashes

See merge request !102
2017-01-11 11:58:42 +00:00
Slava Monich
357c5db580 [ril] Count rild crashes. Contributes to JB#35780
org.nemomobile.ofono.ModemManager.ModemError signal is emitted
when rild crash is detected. Also, the new GetModemErrors method
allows to query how many times which instance of rild has crashed
since ofono was (re)started.
2017-01-11 13:24:23 +02:00
14 changed files with 462 additions and 132 deletions

View File

@@ -183,6 +183,13 @@ if (test "${enable_jolla_rilmodem}" = "yes"); then
LIBS="$LIBS $GRILIO_LIBS $GLIBUTIL_LIBS $LIBMCE_LIBS" LIBS="$LIBS $GRILIO_LIBS $GLIBUTIL_LIBS $LIBMCE_LIBS"
fi fi
AC_ARG_ENABLE(add-remove-context, AC_HELP_STRING([--disable-add-remove-context],
[don't allow to add or remove connection context over D-Bus]), [
if (test "${enableval}" = "no"); then
CFLAGS="$CFLAGS -DDISABLE_ADD_REMOVE_CONTEXT"
fi
])
AC_ARG_ENABLE(qmimodem, AC_HELP_STRING([--disable-qmimodem], AC_ARG_ENABLE(qmimodem, AC_HELP_STRING([--disable-qmimodem],
[disable Qualcomm QMI modem support]), [disable Qualcomm QMI modem support]),
[enable_qmimodem=${enableval}]) [enable_qmimodem=${enableval}])

View File

@@ -1,7 +1,7 @@
/* /*
* oFono - Open Source Telephony - RIL-based devices * oFono - Open Source Telephony - RIL-based devices
* *
* Copyright (C) 2015-2016 Jolla Ltd. * Copyright (C) 2015-2017 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
@@ -15,6 +15,9 @@
#include "ril_config.h" #include "ril_config.h"
#include <gutil_intarray.h>
#include <gutil_ints.h>
/* Utilities for parsing ril_subscription.conf */ /* Utilities for parsing ril_subscription.conf */
char* ril_config_get_string(GKeyFile *file, const char *group, const char *key) char* ril_config_get_string(GKeyFile *file, const char *group, const char *key)
@@ -106,6 +109,51 @@ gboolean ril_config_get_flag(GKeyFile *file, const char *group,
} }
} }
GUtilInts *ril_config_get_ints(GKeyFile *file, const char *group,
const char *key)
{
char* value = ril_config_get_string(file, group, key);
if (value) {
char **values = g_strsplit(value, ",", -1);
char **ptr = values;
GUtilIntArray* array = gutil_int_array_new();
while (*ptr) {
const char *str = *ptr++;
char *end = NULL;
long ival = strtol(str, &end, 0);
if (str[0] && !end[0]) {
gutil_int_array_append(array, ival);
}
}
g_free(value);
g_strfreev(values);
return gutil_int_array_free_to_ints(array);
}
return NULL;
}
char *ril_config_ints_to_string(GUtilInts *ints, char separator)
{
if (ints) {
guint i, n;
const int *data = gutil_ints_get_data(ints, &n);
GString* buf = g_string_new(NULL);
for (i=0; i<n; i++) {
if (buf->len > 0) {
g_string_append_c(buf, separator);
}
g_string_append_printf(buf, "%d", data[i]);
}
return g_string_free(buf, FALSE);
}
return NULL;
}
/* /*
* Local Variables: * Local Variables:
* mode: C * mode: C

View File

@@ -1,7 +1,7 @@
/* /*
* oFono - Open Source Telephony - RIL-based devices * oFono - Open Source Telephony - RIL-based devices
* *
* Copyright (C) 2015-2016 Jolla Ltd. * Copyright (C) 2015-2017 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
@@ -22,13 +22,16 @@
#define RILCONF_SETTINGS_GROUP "Settings" #define RILCONF_SETTINGS_GROUP "Settings"
char* ril_config_get_string(GKeyFile *file, const char *group, const char *key); char *ril_config_get_string(GKeyFile *file, const char *group, const char *key);
gboolean ril_config_get_integer(GKeyFile *file, const char *group, gboolean ril_config_get_integer(GKeyFile *file, const char *group,
const char *key, int *value); const char *key, int *value);
gboolean ril_config_get_boolean(GKeyFile *file, const char *group, gboolean ril_config_get_boolean(GKeyFile *file, const char *group,
const char *key, gboolean *value); const char *key, gboolean *value);
gboolean ril_config_get_flag(GKeyFile *file, const char *group, gboolean ril_config_get_flag(GKeyFile *file, const char *group,
const char *key, int flag, int *flags); const char *key, int flag, int *flags);
GUtilInts *ril_config_get_ints(GKeyFile *file, const char *group,
const char *key);
char *ril_config_ints_to_string(GUtilInts *ints, char separator);
#endif /* RIL_CONFIG_H */ #endif /* RIL_CONFIG_H */

View File

@@ -1,11 +1,10 @@
/* /*
*
* RIL constants adopted from AOSP's header: * RIL constants adopted from AOSP's header:
* *
* /hardware/ril/reference_ril/ril.h * /hardware/ril/reference_ril/ril.h
* *
* Copyright (C) 2013 Canonical Ltd. * Copyright (C) 2013 Canonical Ltd.
* Copyright (C) 2013-2016 Jolla Ltd. * Copyright (C) 2013-2017 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
@@ -118,45 +117,68 @@ enum ril_radio_tech {
}; };
/* See RIL_REQUEST_LAST_CALL_FAIL_CAUSE */ /* See RIL_REQUEST_LAST_CALL_FAIL_CAUSE */
#define CALL_FAIL_UNOBTAINABLE_NUMBER 1 enum ril_call_fail_cause {
#define CALL_FAIL_NORMAL 16 CALL_FAIL_UNOBTAINABLE_NUMBER = 1,
#define CALL_FAIL_BUSY 17 CALL_FAIL_NO_ROUTE_TO_DESTINATION = 3,
#define CALL_FAIL_CONGESTION 34 CALL_FAIL_CHANNEL_UNACCEPTABLE = 6,
#define CALL_FAIL_ACM_LIMIT_EXCEEDED 68 CALL_FAIL_OPERATOR_DETERMINED_BARRING = 8,
#define CALL_FAIL_CALL_BARRED 240 CALL_FAIL_NORMAL = 16,
#define CALL_FAIL_FDN_BLOCKED 241 CALL_FAIL_BUSY = 17,
#define CALL_FAIL_IMSI_UNKNOWN_IN_VLR 242 CALL_FAIL_NO_USER_RESPONDING = 18,
#define CALL_FAIL_IMEI_NOT_ACCEPTED 243 CALL_FAIL_NO_ANSWER_FROM_USER = 19,
#define CALL_FAIL_DIAL_MODIFIED_TO_USSD 244 CALL_FAIL_CALL_REJECTED = 21,
#define CALL_FAIL_DIAL_MODIFIED_TO_SS 245 CALL_FAIL_NUMBER_CHANGED = 22,
#define CALL_FAIL_DIAL_MODIFIED_TO_DIAL 246 CALL_FAIL_DESTINATION_OUT_OF_ORDER = 27,
#define CALL_FAIL_CDMA_LOCKED_UNTIL_POWER_CYCLE 1000 CALL_FAIL_INVALID_NUMBER_FORMAT = 28,
#define CALL_FAIL_CDMA_DROP 1001 CALL_FAIL_FACILITY_REJECTED = 29,
#define CALL_FAIL_CDMA_INTERCEPT 1002 CALL_FAIL_RESP_TO_STATUS_ENQUIRY = 30,
#define CALL_FAIL_CDMA_REORDER 1003 CALL_FAIL_NORMAL_UNSPECIFIED = 31,
#define CALL_FAIL_CDMA_SO_REJECT 1004 CALL_FAIL_CONGESTION = 34,
#define CALL_FAIL_CDMA_RETRY_ORDER 1005 CALL_FAIL_NETWORK_OUT_OF_ORDER = 38,
#define CALL_FAIL_CDMA_ACCESS_FAILURE 1006 CALL_FAIL_TEMPORARY_FAILURE = 41,
#define CALL_FAIL_CDMA_PREEMPTED 1007 CALL_FAIL_SWITCHING_EQUIPMENT_CONGESTION = 42,
#define CALL_FAIL_CDMA_NOT_EMERGENCY 1008 CALL_FAIL_ACCESS_INFORMATION_DISCARDED = 43,
#define CALL_FAIL_CDMA_ACCESS_BLOCKED 1009 CALL_FAIL_REQUESTED_CIRCUIT_OR_CHANNEL_NOT_AVAILABLE = 44,
#define CALL_FAIL_ERROR_UNSPECIFIED 0xffff CALL_FAIL_RESOURCES_UNAVAILABLE_OR_UNSPECIFIED = 47,
CALL_FAIL_QOS_UNAVAILABLE = 49,
CALL_FAIL_REQUESTED_FACILITY_NOT_SUBSCRIBED = 50,
CALL_FAIL_INCOMING_CALLS_BARRED_WITHIN_CUG = 55,
CALL_FAIL_BEARER_CAPABILITY_NOT_AUTHORIZED = 57,
CALL_FAIL_BEARER_CAPABILITY_UNAVAILABLE = 58,
CALL_FAIL_SERVICE_OPTION_NOT_AVAILABLE = 63,
CALL_FAIL_BEARER_SERVICE_NOT_IMPLEMENTED = 65,
CALL_FAIL_ACM_LIMIT_EXCEEDED = 68,
CALL_FAIL_REQUESTED_FACILITY_NOT_IMPLEMENTED = 69,
CALL_FAIL_ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE = 70,
CALL_FAIL_SERVICE_OR_OPTION_NOT_IMPLEMENTED = 79,
CALL_FAIL_INVALID_TRANSACTION_IDENTIFIER = 81,
CALL_FAIL_USER_NOT_MEMBER_OF_CUG = 87,
CALL_FAIL_INCOMPATIBLE_DESTINATION = 88,
CALL_FAIL_INVALID_TRANSIT_NW_SELECTION = 91,
CALL_FAIL_SEMANTICALLY_INCORRECT_MESSAGE = 95,
CALL_FAIL_INVALID_MANDATORY_INFORMATION = 96,
CALL_FAIL_MESSAGE_TYPE_NON_IMPLEMENTED = 97,
CALL_FAIL_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 98,
CALL_FAIL_INFORMATION_ELEMENT_NON_EXISTENT = 99,
CALL_FAIL_CONDITIONAL_IE_ERROR = 100,
CALL_FAIL_MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 101,
CALL_FAIL_RECOVERY_ON_TIMER_EXPIRED = 102,
CALL_FAIL_PROTOCOL_ERROR_UNSPECIFIED = 111,
CALL_FAIL_INTERWORKING_UNSPECIFIED = 127,
CALL_FAIL_CALL_BARRED = 240,
CALL_FAIL_FDN_BLOCKED = 241,
CALL_FAIL_IMSI_UNKNOWN_IN_VLR = 242,
CALL_FAIL_IMEI_NOT_ACCEPTED = 243,
CALL_FAIL_DIAL_MODIFIED_TO_USSD = 244,
CALL_FAIL_DIAL_MODIFIED_TO_SS = 245,
CALL_FAIL_DIAL_MODIFIED_TO_DIAL = 246,
CALL_FAIL_ERROR_UNSPECIFIED = 0xffff,
/* Not defined in ril.h but valid 3GPP specific cause values /* Not defined in ril.h but valid 3GPP specific cause values
* for call control. See 3GPP TS 24.008 Annex H. */ * for call control. See 3GPP TS 24.008 Annex H. */
#define CALL_FAIL_NO_ROUTE_TO_DESTINATION 3 CALL_FAIL_ANONYMOUS_CALL_REJECTION = 24,
#define CALL_FAIL_CHANNEL_UNACCEPTABLE 6 CALL_FAIL_PRE_EMPTION = 25
#define CALL_FAIL_OPERATOR_DETERMINED_BARRING 8 };
#define CALL_FAIL_NO_USER_RESPONDING 18
#define CALL_FAIL_USER_ALERTING_NO_ANSWER 19
#define CALL_FAIL_CALL_REJECTED 21
#define CALL_FAIL_NUMBER_CHANGED 22
#define CALL_FAIL_ANONYMOUS_CALL_REJECTION 24
#define CALL_FAIL_PRE_EMPTION 25
#define CALL_FAIL_DESTINATION_OUT_OF_ORDER 27
#define CALL_FAIL_INCOMPLETE_NUMBER 28
#define CALL_FAIL_FACILITY_REJECTED 29
#define CALL_FAIL_NORMAL_UNSPECIFIED 31
enum ril_data_call_fail_cause { enum ril_data_call_fail_cause {
PDP_FAIL_NONE = 0, PDP_FAIL_NONE = 0,

View File

@@ -1,7 +1,7 @@
/* /*
* oFono - Open Source Telephony - RIL-based devices * oFono - Open Source Telephony - RIL-based devices
* *
* Copyright (C) 2015-2016 Jolla Ltd. * Copyright (C) 2015-2017 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
@@ -26,6 +26,7 @@
#include "ril_log.h" #include "ril_log.h"
#include <gdbus.h> #include <gdbus.h>
#include <gutil_ints.h>
#include <gutil_strv.h> #include <gutil_strv.h>
#include <gutil_misc.h> #include <gutil_misc.h>
#include <mce_display.h> #include <mce_display.h>
@@ -77,6 +78,8 @@
#define RILCONF_DATA_CALL_FORMAT "dataCallFormat" #define RILCONF_DATA_CALL_FORMAT "dataCallFormat"
#define RILCONF_DATA_CALL_RETRY_LIMIT "dataCallRetryLimit" #define RILCONF_DATA_CALL_RETRY_LIMIT "dataCallRetryLimit"
#define RILCONF_DATA_CALL_RETRY_DELAY "dataCallRetryDelay" #define RILCONF_DATA_CALL_RETRY_DELAY "dataCallRetryDelay"
#define RILCONF_LOCAL_HANGUP_REASONS "localHangupReasons"
#define RILCONF_REMOTE_HANGUP_REASONS "remoteHangupReasons"
#define RIL_STORE "ril" #define RIL_STORE "ril"
#define RIL_STORE_GROUP "Settings" #define RIL_STORE_GROUP "Settings"
@@ -85,6 +88,12 @@
#define RIL_STORE_DEFAULT_DATA_SIM "DefaultDataSim" #define RIL_STORE_DEFAULT_DATA_SIM "DefaultDataSim"
#define RIL_STORE_SLOTS_SEP "," #define RIL_STORE_SLOTS_SEP ","
/* The file where error statistics is stored */
#define RIL_ERROR_STORAGE "rilerror"
/* Modem error ids, must be static strings (only one is defined for now) */
static const char RIL_ERROR_ID_RILD_RESTART[] = "rild-restart";
enum ril_plugin_io_events { enum ril_plugin_io_events {
IO_EVENT_CONNECTED, IO_EVENT_CONNECTED,
IO_EVENT_ERROR, IO_EVENT_ERROR,
@@ -208,6 +217,12 @@ static struct ofono_debug_desc ril_plugin_debug OFONO_DEBUG_ATTR = {
.notify = ril_plugin_debug_notify .notify = ril_plugin_debug_notify
}; };
static inline const char *ril_slot_debug_prefix(const struct ril_slot *slot)
{
/* slot->path always starts with a slash, skip it */
return slot->path + 1;
}
static struct ril_plugin_priv *ril_plugin_cast(struct ril_plugin *pub) static struct ril_plugin_priv *ril_plugin_cast(struct ril_plugin *pub)
{ {
return G_CAST(pub, struct ril_plugin_priv, pub); return G_CAST(pub, struct ril_plugin_priv, pub);
@@ -611,7 +626,7 @@ static void ril_plugin_sim_state_watch(enum ofono_sim_state new_state,
struct ril_slot *slot = data; struct ril_slot *slot = data;
struct ril_plugin_priv *plugin = slot->plugin; struct ril_plugin_priv *plugin = slot->plugin;
DBG("%s sim state %d", slot->path + 1, new_state); DBG("%s sim state %d", ril_slot_debug_prefix(slot), new_state);
slot->sim_state = new_state; slot->sim_state = new_state;
if (new_state == OFONO_SIM_STATE_READY) { if (new_state == OFONO_SIM_STATE_READY) {
struct ril_slot *voice_slot = plugin->voice_slot; struct ril_slot *voice_slot = plugin->voice_slot;
@@ -667,10 +682,10 @@ static void ril_plugin_sim_watch(struct ofono_atom *atom,
struct ril_slot *slot = data; struct ril_slot *slot = data;
if (cond == OFONO_ATOM_WATCH_CONDITION_REGISTERED) { if (cond == OFONO_ATOM_WATCH_CONDITION_REGISTERED) {
DBG("%s sim registered", slot->path + 1); DBG("%s sim registered", ril_slot_debug_prefix(slot));
ril_plugin_register_sim(slot, __ofono_atom_get_data(atom)); ril_plugin_register_sim(slot, __ofono_atom_get_data(atom));
} else if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) { } else if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
DBG("%s sim unregistered", slot->path + 1); DBG("%s sim unregistered", ril_slot_debug_prefix(slot));
slot->sim = NULL; slot->sim = NULL;
} }
@@ -678,8 +693,35 @@ static void ril_plugin_sim_watch(struct ofono_atom *atom,
ril_plugin_update_modem_paths_full(slot->plugin); ril_plugin_update_modem_paths_full(slot->plugin);
} }
static void ril_plugin_handle_error(struct ril_slot *slot) static void ril_plugin_count_error(struct ril_slot *slot, const char *key,
const char *message)
{ {
GHashTable *errors = slot->pub.errors;
GKeyFile *storage = storage_open(NULL, RIL_ERROR_STORAGE);
/* Update life-time statistics */
if (storage) {
/* slot->path always starts with a slash, skip it */
const char *group = slot->path + 1;
g_key_file_set_integer(storage, group, key,
g_key_file_get_integer(storage, group, key, NULL) + 1);
storage_close(NULL, RIL_ERROR_STORAGE, storage, TRUE);
}
/* Update run-time error counts. The key is the error id which
* is always a static string */
g_hash_table_insert(errors, (void*)key, GINT_TO_POINTER(
GPOINTER_TO_INT(g_hash_table_lookup(errors, key)) + 1));
/* Issue the D-Bus signal */
ril_plugin_dbus_signal_modem_error(slot->plugin->dbus,
slot->index, key, message);
}
static void ril_plugin_handle_error(struct ril_slot *slot, const char *msg)
{
ofono_error("%s %s", ril_slot_debug_prefix(slot), msg);
ril_plugin_count_error(slot, RIL_ERROR_ID_RILD_RESTART, msg);
ril_plugin_shutdown_slot(slot, TRUE); ril_plugin_shutdown_slot(slot, TRUE);
ril_plugin_update_modem_paths_full(slot->plugin); ril_plugin_update_modem_paths_full(slot->plugin);
ril_plugin_retry_init_io(slot); ril_plugin_retry_init_io(slot);
@@ -688,12 +730,12 @@ static void ril_plugin_handle_error(struct ril_slot *slot)
static void ril_plugin_slot_error(GRilIoChannel *io, const GError *error, static void ril_plugin_slot_error(GRilIoChannel *io, const GError *error,
void *data) void *data)
{ {
ril_plugin_handle_error((struct ril_slot *)data); ril_plugin_handle_error((struct ril_slot *)data, GERRMSG(error));
} }
static void ril_plugin_slot_disconnected(GRilIoChannel *io, void *data) static void ril_plugin_slot_disconnected(GRilIoChannel *io, void *data)
{ {
ril_plugin_handle_error((struct ril_slot *)data); ril_plugin_handle_error((struct ril_slot *)data, "disconnected");
} }
static void ril_plugin_modem_online(struct ril_modem *modem, gboolean online, static void ril_plugin_modem_online(struct ril_modem *modem, gboolean online,
@@ -701,7 +743,7 @@ static void ril_plugin_modem_online(struct ril_modem *modem, gboolean online,
{ {
struct ril_slot *slot = data; struct ril_slot *slot = data;
DBG("%s %d", slot->path + 1, online); DBG("%s %d", ril_slot_debug_prefix(slot), online);
GASSERT(slot->modem); GASSERT(slot->modem);
GASSERT(slot->modem == modem); GASSERT(slot->modem == modem);
@@ -813,14 +855,15 @@ static void ril_debug_trace_update(struct ril_slot *slot)
static const char *ril_plugin_log_prefix(struct ril_slot *slot) static const char *ril_plugin_log_prefix(struct ril_slot *slot)
{ {
return ril_plugin_multisim(slot->plugin) ? (slot->path + 1) : ""; return ril_plugin_multisim(slot->plugin) ?
ril_slot_debug_prefix(slot) : "";
} }
static void ril_plugin_create_modem(struct ril_slot *slot) static void ril_plugin_create_modem(struct ril_slot *slot)
{ {
struct ril_modem *modem; struct ril_modem *modem;
DBG("%s", slot->path); DBG("%s", ril_slot_debug_prefix(slot));
GASSERT(slot->io && slot->io->connected); GASSERT(slot->io && slot->io->connected);
GASSERT(!slot->modem); GASSERT(!slot->modem);
@@ -1076,6 +1119,7 @@ static struct ril_slot *ril_plugin_slot_new(const char *sockpath,
RILMODEM_DEFAULT_DATA_CALL_RETRY_LIMIT; RILMODEM_DEFAULT_DATA_CALL_RETRY_LIMIT;
slot->data_opt.data_call_retry_delay_ms = slot->data_opt.data_call_retry_delay_ms =
RILMODEM_DEFAULT_DATA_CALL_RETRY_DELAY; RILMODEM_DEFAULT_DATA_CALL_RETRY_DELAY;
slot->pub.errors = g_hash_table_new(g_str_hash, g_str_equal);
return slot; return slot;
} }
@@ -1236,6 +1280,27 @@ static struct ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
g_free(slot->ecclist_file); g_free(slot->ecclist_file);
slot->ecclist_file = NULL; slot->ecclist_file = NULL;
} }
slot->config.local_hangup_reasons = ril_config_get_ints(file,
group, RILCONF_LOCAL_HANGUP_REASONS);
strval = ril_config_ints_to_string(
slot->config.local_hangup_reasons, ',');
if (strval) {
DBG("%s: %s %s", group, RILCONF_LOCAL_HANGUP_REASONS,
strval);
g_free(strval);
}
slot->config.remote_hangup_reasons = ril_config_get_ints(file,
group, RILCONF_REMOTE_HANGUP_REASONS);
strval = ril_config_ints_to_string(
slot->config.remote_hangup_reasons, ',');
if (strval) {
DBG("%s: %s %s", group, RILCONF_REMOTE_HANGUP_REASONS,
strval);
g_free(strval);
}
} else { } else {
DBG("no socket path in %s", group); DBG("no socket path in %s", group);
} }
@@ -1248,6 +1313,9 @@ static void ril_plugin_delete_slot(struct ril_slot *slot)
ril_plugin_shutdown_slot(slot, TRUE); ril_plugin_shutdown_slot(slot, TRUE);
ril_sim_info_unref(slot->sim_info); ril_sim_info_unref(slot->sim_info);
ril_sim_settings_unref(slot->sim_settings); ril_sim_settings_unref(slot->sim_settings);
gutil_ints_unref(slot->config.local_hangup_reasons);
gutil_ints_unref(slot->config.remote_hangup_reasons);
g_hash_table_destroy(slot->pub.errors);
g_free(slot->path); g_free(slot->path);
g_free(slot->imei); g_free(slot->imei);
g_free(slot->name); g_free(slot->name);
@@ -1403,7 +1471,7 @@ static void ril_plugin_switch_user()
static void ril_plugin_update_enabled_slot(struct ril_slot *slot) static void ril_plugin_update_enabled_slot(struct ril_slot *slot)
{ {
if (slot->pub.enabled) { if (slot->pub.enabled) {
DBG("%s enabled", slot->path + 1); DBG("%s enabled", ril_slot_debug_prefix(slot));
ril_plugin_check_modem(slot); ril_plugin_check_modem(slot);
} }
} }
@@ -1411,7 +1479,7 @@ static void ril_plugin_update_enabled_slot(struct ril_slot *slot)
static void ril_plugin_update_disabled_slot(struct ril_slot *slot) static void ril_plugin_update_disabled_slot(struct ril_slot *slot)
{ {
if (!slot->pub.enabled) { if (!slot->pub.enabled) {
DBG("%s disabled", slot->path + 1); DBG("%s disabled", ril_slot_debug_prefix(slot));
ril_plugin_shutdown_slot(slot, FALSE); ril_plugin_shutdown_slot(slot, FALSE);
ril_plugin_update_modem_paths_full(slot->plugin); ril_plugin_update_modem_paths_full(slot->plugin);
} }

View File

@@ -1,7 +1,7 @@
/* /*
* oFono - Open Source Telephony - RIL-based devices * oFono - Open Source Telephony - RIL-based devices
* *
* Copyright (C) 2015-2016 Jolla Ltd. * Copyright (C) 2015-2017 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
@@ -52,6 +52,7 @@ struct ril_slot_info {
gboolean enabled; gboolean enabled;
gboolean sim_present; gboolean sim_present;
const struct ril_slot_config *config; const struct ril_slot_config *config;
GHashTable *errors;
}; };
struct ril_plugin { struct ril_plugin {
@@ -123,6 +124,8 @@ void ril_plugin_dbus_block_imei_requests(struct ril_plugin_dbus *dbus,
void ril_plugin_dbus_signal(struct ril_plugin_dbus *dbus, int mask); void ril_plugin_dbus_signal(struct ril_plugin_dbus *dbus, int mask);
void ril_plugin_dbus_signal_sim(struct ril_plugin_dbus *dbus, int index, void ril_plugin_dbus_signal_sim(struct ril_plugin_dbus *dbus, int index,
gboolean present); gboolean present);
void ril_plugin_dbus_signal_modem_error(struct ril_plugin_dbus *dbus,
int index, const char *id, const char *message);
struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix, struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
const struct ril_slot_info *slot, struct ril_radio *radio, const struct ril_slot_info *slot, struct ril_radio *radio,

View File

@@ -1,7 +1,7 @@
/* /*
* oFono - Open Source Telephony - RIL-based devices * oFono - Open Source Telephony - RIL-based devices
* *
* Copyright (C) 2015-2016 Jolla Ltd. * Copyright (C) 2015-2017 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
@@ -46,7 +46,7 @@ struct ril_plugin_dbus {
#define RIL_DBUS_PATH "/" #define RIL_DBUS_PATH "/"
#define RIL_DBUS_INTERFACE "org.nemomobile.ofono.ModemManager" #define RIL_DBUS_INTERFACE "org.nemomobile.ofono.ModemManager"
#define RIL_DBUS_INTERFACE_VERSION (5) #define RIL_DBUS_INTERFACE_VERSION (6)
#define RIL_DBUS_SIGNAL_ENABLED_MODEMS_CHANGED "EnabledModemsChanged" #define RIL_DBUS_SIGNAL_ENABLED_MODEMS_CHANGED "EnabledModemsChanged"
#define RIL_DBUS_SIGNAL_PRESENT_SIMS_CHANGED "PresentSimsChanged" #define RIL_DBUS_SIGNAL_PRESENT_SIMS_CHANGED "PresentSimsChanged"
@@ -57,8 +57,11 @@ struct ril_plugin_dbus {
#define RIL_DBUS_SIGNAL_MMS_SIM_CHANGED "MmsSimChanged" #define RIL_DBUS_SIGNAL_MMS_SIM_CHANGED "MmsSimChanged"
#define RIL_DBUS_SIGNAL_MMS_MODEM_CHANGED "MmsModemChanged" #define RIL_DBUS_SIGNAL_MMS_MODEM_CHANGED "MmsModemChanged"
#define RIL_DBUS_SIGNAL_READY_CHANGED "ReadyChanged" #define RIL_DBUS_SIGNAL_READY_CHANGED "ReadyChanged"
#define RIL_DBUS_SIGNAL_MODEM_ERROR "ModemError"
#define RIL_DBUS_IMSI_AUTO "auto" #define RIL_DBUS_IMSI_AUTO "auto"
#define RIL_DBUS_ERROR_SIGNATURE "si"
static gboolean ril_plugin_dbus_enabled(const struct ril_slot_info *slot) static gboolean ril_plugin_dbus_enabled(const struct ril_slot_info *slot)
{ {
return slot->enabled; return slot->enabled;
@@ -167,6 +170,48 @@ static void ril_plugin_dbus_message_append_path_array(DBusMessage *msg,
ril_plugin_dbus_append_path_array(&iter, dbus, fn); ril_plugin_dbus_append_path_array(&iter, dbus, fn);
} }
static void ril_plugin_dbus_append_modem_error(DBusMessageIter *it,
const char *id, dbus_uint32_t count)
{
DBusMessageIter sub;
dbus_message_iter_open_container(it, DBUS_TYPE_STRUCT, NULL, &sub);
dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &id);
dbus_message_iter_append_basic(&sub, DBUS_TYPE_INT32, &count);
dbus_message_iter_close_container(it, &sub);
}
static void ril_plugin_dbus_append_modem_errors(DBusMessageIter *it,
struct ril_plugin_dbus *dbus)
{
DBusMessageIter slots;
const struct ril_slot_info *const *ptr = dbus->plugin->slots;
dbus_message_iter_open_container(it, DBUS_TYPE_ARRAY,
"a(" RIL_DBUS_ERROR_SIGNATURE ")", &slots);
while (*ptr) {
const struct ril_slot_info *slot = *ptr++;
DBusMessageIter errors;
dbus_message_iter_open_container(&slots, DBUS_TYPE_ARRAY,
"(" RIL_DBUS_ERROR_SIGNATURE ")", &errors);
if (g_hash_table_size(slot->errors)) {
gpointer key, value;
GHashTableIter iter;
g_hash_table_iter_init(&iter, slot->errors);
while (g_hash_table_iter_next(&iter, &key, &value)) {
ril_plugin_dbus_append_modem_error(&errors,
key, GPOINTER_TO_INT(value));
}
}
dbus_message_iter_close_container(&slots, &errors);
}
dbus_message_iter_close_container(it, &slots);
}
static void ril_plugin_dbus_signal_path_array(struct ril_plugin_dbus *dbus, static void ril_plugin_dbus_signal_path_array(struct ril_plugin_dbus *dbus,
const char *name, ril_plugin_dbus_slot_select_fn fn) const char *name, ril_plugin_dbus_slot_select_fn fn)
{ {
@@ -257,6 +302,19 @@ void ril_plugin_dbus_signal_sim(struct ril_plugin_dbus *dbus, int index,
DBUS_TYPE_INVALID); DBUS_TYPE_INVALID);
} }
void ril_plugin_dbus_signal_modem_error(struct ril_plugin_dbus *dbus,
int index, const char *id, const char *message)
{
const char *path = dbus->plugin->slots[index]->path;
if (!message) message = "";
g_dbus_emit_signal(dbus->conn, RIL_DBUS_PATH, RIL_DBUS_INTERFACE,
RIL_DBUS_SIGNAL_MODEM_ERROR,
DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_STRING, &id,
DBUS_TYPE_STRING, &message,
DBUS_TYPE_INVALID);
}
static DBusMessage *ril_plugin_dbus_reply_with_path_array(DBusMessage *msg, static DBusMessage *ril_plugin_dbus_reply_with_path_array(DBusMessage *msg,
struct ril_plugin_dbus *dbus, ril_plugin_dbus_slot_select_fn fn) struct ril_plugin_dbus *dbus, ril_plugin_dbus_slot_select_fn fn)
{ {
@@ -375,6 +433,13 @@ static void ril_plugin_dbus_append_all5(DBusMessageIter *it,
ril_plugin_dbus_append_boolean(it, dbus->plugin->ready); ril_plugin_dbus_append_boolean(it, dbus->plugin->ready);
} }
static void ril_plugin_dbus_append_all6(DBusMessageIter *it,
struct ril_plugin_dbus *dbus)
{
ril_plugin_dbus_append_all5(it, dbus);
ril_plugin_dbus_append_modem_errors(it, dbus);
}
static DBusMessage *ril_plugin_dbus_get_all(DBusConnection *conn, static DBusMessage *ril_plugin_dbus_get_all(DBusConnection *conn,
DBusMessage *msg, void *data) DBusMessage *msg, void *data)
{ {
@@ -410,6 +475,13 @@ static DBusMessage *ril_plugin_dbus_get_all5(DBusConnection *conn,
ril_plugin_dbus_append_all5); ril_plugin_dbus_append_all5);
} }
static DBusMessage *ril_plugin_dbus_get_all6(DBusConnection *conn,
DBusMessage *msg, void *data)
{
return ril_plugin_dbus_imei_reply(msg, (struct ril_plugin_dbus *)data,
ril_plugin_dbus_append_all6);
}
static DBusMessage *ril_plugin_dbus_get_interface_version(DBusConnection *conn, static DBusMessage *ril_plugin_dbus_get_interface_version(DBusConnection *conn,
DBusMessage *msg, void *data) DBusMessage *msg, void *data)
{ {
@@ -554,6 +626,13 @@ static DBusMessage *ril_plugin_dbus_get_ready(DBusConnection *conn,
return reply; return reply;
} }
static DBusMessage *ril_plugin_dbus_get_modem_errors(DBusConnection *conn,
DBusMessage *msg, void *data)
{
return ril_plugin_dbus_reply(msg, (struct ril_plugin_dbus *)data,
ril_plugin_dbus_append_modem_errors);
}
static DBusMessage *ril_plugin_dbus_set_enabled_modems(DBusConnection *conn, static DBusMessage *ril_plugin_dbus_set_enabled_modems(DBusConnection *conn,
DBusMessage *msg, void *data) DBusMessage *msg, void *data)
{ {
@@ -697,28 +776,44 @@ static DBusMessage *ril_plugin_dbus_set_mms_sim(DBusConnection *conn,
* talking to. * talking to.
*/ */
#define RIL_DBUS_VERSION_ARG {"version", "i"}
#define RIL_DBUS_AVAILABLE_MODEMS_ARG {"availableModems", "ao"}
#define RIL_DBUS_ENABLED_MODEMS_ARG {"enabledModems", "ao" }
#define RIL_DBUS_DEFAULT_DATA_SIM_ARG {"defaultDataSim", "s" }
#define RIL_DBUS_DEFAULT_VOICE_SIM_ARG {"defaultVoiceSim", "s" }
#define RIL_DBUS_DEFAULT_DATA_MODEM_ARG {"defaultDataModem", "s" }
#define RIL_DBUS_DEFAULT_VOICE_MODEM_ARG {"defaultVoiceModem" , "s"}
#define RIL_DBUS_PRESENT_SIMS_ARG {"presentSims" , "ab"}
#define RIL_DBUS_IMEI_ARG {"imei" , "as"}
#define RIL_DBUS_MMS_SIM_ARG {"mmsSim", "s"}
#define RIL_DBUS_MMS_MODEM_ARG {"mmsModem" , "s"}
#define RIL_DBUS_READY_ARG {"ready" , "b"}
#define RIL_DBUS_MODEM_ERRORS_ARG {"errors" , \
"aa(" RIL_DBUS_ERROR_SIGNATURE ")"}
#define RIL_DBUS_GET_ALL_ARGS \ #define RIL_DBUS_GET_ALL_ARGS \
{"version", "i" }, \ RIL_DBUS_VERSION_ARG, \
{"availableModems", "ao" }, \ RIL_DBUS_AVAILABLE_MODEMS_ARG, \
{"enabledModems", "ao" }, \ RIL_DBUS_ENABLED_MODEMS_ARG, \
{"defaultDataSim", "s" }, \ RIL_DBUS_DEFAULT_DATA_SIM_ARG, \
{"defaultVoiceSim", "s" }, \ RIL_DBUS_DEFAULT_VOICE_SIM_ARG, \
{"defaultDataModem", "s" }, \ RIL_DBUS_DEFAULT_DATA_MODEM_ARG, \
{"defaultVoiceModem" , "s"} RIL_DBUS_DEFAULT_VOICE_MODEM_ARG
#define RIL_DBUS_GET_ALL2_ARGS \ #define RIL_DBUS_GET_ALL2_ARGS \
RIL_DBUS_GET_ALL_ARGS, \ RIL_DBUS_GET_ALL_ARGS, \
{"presentSims" , "ab"} RIL_DBUS_PRESENT_SIMS_ARG
#define RIL_DBUS_GET_ALL3_ARGS \ #define RIL_DBUS_GET_ALL3_ARGS \
RIL_DBUS_GET_ALL2_ARGS, \ RIL_DBUS_GET_ALL2_ARGS, \
{"imei" , "as"} RIL_DBUS_IMEI_ARG
#define RIL_DBUS_GET_ALL4_ARGS \ #define RIL_DBUS_GET_ALL4_ARGS \
RIL_DBUS_GET_ALL3_ARGS, \ RIL_DBUS_GET_ALL3_ARGS, \
{"mmsSim", "s" }, \ RIL_DBUS_MMS_SIM_ARG, \
{"mmsModem" , "s"} RIL_DBUS_MMS_MODEM_ARG
#define RIL_DBUS_GET_ALL5_ARGS \ #define RIL_DBUS_GET_ALL5_ARGS \
RIL_DBUS_GET_ALL4_ARGS, \ RIL_DBUS_GET_ALL4_ARGS, \
{"ready" , "b"} RIL_DBUS_READY_ARG
#define RIL_DBUS_GET_ALL6_ARGS \
RIL_DBUS_GET_ALL5_ARGS, \
RIL_DBUS_MODEM_ERRORS_ARG
static const GDBusMethodTable ril_plugin_dbus_methods[] = { static const GDBusMethodTable ril_plugin_dbus_methods[] = {
{ GDBUS_METHOD("GetAll", { GDBUS_METHOD("GetAll",
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL_ARGS), NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL_ARGS),
@@ -735,42 +830,48 @@ static const GDBusMethodTable ril_plugin_dbus_methods[] = {
{ GDBUS_ASYNC_METHOD("GetAll5", { GDBUS_ASYNC_METHOD("GetAll5",
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL5_ARGS), NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL5_ARGS),
ril_plugin_dbus_get_all5) }, ril_plugin_dbus_get_all5) },
{ GDBUS_ASYNC_METHOD("GetAll6",
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL6_ARGS),
ril_plugin_dbus_get_all6) },
{ GDBUS_METHOD("GetInterfaceVersion", { GDBUS_METHOD("GetInterfaceVersion",
NULL, GDBUS_ARGS({ "version", "i" }), NULL, GDBUS_ARGS(RIL_DBUS_VERSION_ARG),
ril_plugin_dbus_get_interface_version) }, ril_plugin_dbus_get_interface_version) },
{ GDBUS_METHOD("GetAvailableModems", { GDBUS_METHOD("GetAvailableModems",
NULL, GDBUS_ARGS({ "modems", "ao" }), NULL, GDBUS_ARGS(RIL_DBUS_AVAILABLE_MODEMS_ARG),
ril_plugin_dbus_get_available_modems) }, ril_plugin_dbus_get_available_modems) },
{ GDBUS_METHOD("GetEnabledModems", { GDBUS_METHOD("GetEnabledModems",
NULL, GDBUS_ARGS({ "modems", "ao" }), NULL, GDBUS_ARGS(RIL_DBUS_ENABLED_MODEMS_ARG),
ril_plugin_dbus_get_enabled_modems) }, ril_plugin_dbus_get_enabled_modems) },
{ GDBUS_METHOD("GetPresentSims", { GDBUS_METHOD("GetPresentSims",
NULL, GDBUS_ARGS({ "presentSims", "ab" }), NULL, GDBUS_ARGS(RIL_DBUS_PRESENT_SIMS_ARG),
ril_plugin_dbus_get_present_sims) }, ril_plugin_dbus_get_present_sims) },
{ GDBUS_ASYNC_METHOD("GetIMEI", { GDBUS_ASYNC_METHOD("GetIMEI",
NULL, GDBUS_ARGS({ "imei", "as" }), NULL, GDBUS_ARGS(RIL_DBUS_IMEI_ARG),
ril_plugin_dbus_get_imei) }, ril_plugin_dbus_get_imei) },
{ GDBUS_METHOD("GetDefaultDataSim", { GDBUS_METHOD("GetDefaultDataSim",
NULL, GDBUS_ARGS({ "imsi", "s" }), NULL, GDBUS_ARGS(RIL_DBUS_DEFAULT_DATA_SIM_ARG),
ril_plugin_dbus_get_default_data_sim) }, ril_plugin_dbus_get_default_data_sim) },
{ GDBUS_METHOD("GetDefaultVoiceSim", { GDBUS_METHOD("GetDefaultVoiceSim",
NULL, GDBUS_ARGS({ "imsi", "s" }), NULL, GDBUS_ARGS(RIL_DBUS_DEFAULT_VOICE_SIM_ARG),
ril_plugin_dbus_get_default_voice_sim) }, ril_plugin_dbus_get_default_voice_sim) },
{ GDBUS_METHOD("GetMmsSim", { GDBUS_METHOD("GetMmsSim",
NULL, GDBUS_ARGS({ "imsi", "s" }), NULL, GDBUS_ARGS(RIL_DBUS_MMS_SIM_ARG),
ril_plugin_dbus_get_mms_sim) }, ril_plugin_dbus_get_mms_sim) },
{ GDBUS_METHOD("GetDefaultDataModem", { GDBUS_METHOD("GetDefaultDataModem",
NULL, GDBUS_ARGS({ "path", "s" }), NULL, GDBUS_ARGS(RIL_DBUS_DEFAULT_DATA_MODEM_ARG),
ril_plugin_dbus_get_default_data_modem) }, ril_plugin_dbus_get_default_data_modem) },
{ GDBUS_METHOD("GetDefaultVoiceModem", { GDBUS_METHOD("GetDefaultVoiceModem",
NULL, GDBUS_ARGS({ "path", "s" }), NULL, GDBUS_ARGS(RIL_DBUS_DEFAULT_VOICE_MODEM_ARG),
ril_plugin_dbus_get_default_voice_modem) }, ril_plugin_dbus_get_default_voice_modem) },
{ GDBUS_METHOD("GetMmsModem", { GDBUS_METHOD("GetMmsModem",
NULL, GDBUS_ARGS({ "path", "s" }), NULL, GDBUS_ARGS(RIL_DBUS_MMS_MODEM_ARG),
ril_plugin_dbus_get_mms_modem) }, ril_plugin_dbus_get_mms_modem) },
{ GDBUS_METHOD("GetReady", { GDBUS_METHOD("GetReady",
NULL, GDBUS_ARGS({ "ready", "b" }), NULL, GDBUS_ARGS(RIL_DBUS_READY_ARG),
ril_plugin_dbus_get_ready) }, ril_plugin_dbus_get_ready) },
{ GDBUS_METHOD("GetModemErrors",
NULL, GDBUS_ARGS(RIL_DBUS_MODEM_ERRORS_ARG),
ril_plugin_dbus_get_modem_errors) },
{ GDBUS_METHOD("SetEnabledModems", { GDBUS_METHOD("SetEnabledModems",
GDBUS_ARGS({ "modems", "ao" }), NULL, GDBUS_ARGS({ "modems", "ao" }), NULL,
ril_plugin_dbus_set_enabled_modems) }, ril_plugin_dbus_set_enabled_modems) },
@@ -788,24 +889,28 @@ static const GDBusMethodTable ril_plugin_dbus_methods[] = {
static const GDBusSignalTable ril_plugin_dbus_signals[] = { static const GDBusSignalTable ril_plugin_dbus_signals[] = {
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_ENABLED_MODEMS_CHANGED, { GDBUS_SIGNAL(RIL_DBUS_SIGNAL_ENABLED_MODEMS_CHANGED,
GDBUS_ARGS({ "modems", "ao" })) }, GDBUS_ARGS(RIL_DBUS_ENABLED_MODEMS_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_PRESENT_SIMS_CHANGED, { GDBUS_SIGNAL(RIL_DBUS_SIGNAL_PRESENT_SIMS_CHANGED,
GDBUS_ARGS({"index", "i" }, GDBUS_ARGS({"index", "i" },
{"present" , "b"})) }, {"present" , "b"})) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_DATA_SIM_CHANGED, { GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_DATA_SIM_CHANGED,
GDBUS_ARGS({ "imsi", "s" })) }, GDBUS_ARGS(RIL_DBUS_DEFAULT_DATA_SIM_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_VOICE_SIM_CHANGED, { GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_VOICE_SIM_CHANGED,
GDBUS_ARGS({ "imsi", "s" })) }, GDBUS_ARGS(RIL_DBUS_DEFAULT_VOICE_SIM_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_DATA_MODEM_CHANGED, { GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_DATA_MODEM_CHANGED,
GDBUS_ARGS({ "path", "s" })) }, GDBUS_ARGS(RIL_DBUS_DEFAULT_DATA_MODEM_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_VOICE_MODEM_CHANGED, { GDBUS_SIGNAL(RIL_DBUS_SIGNAL_DEFAULT_VOICE_MODEM_CHANGED,
GDBUS_ARGS({ "path", "s" })) }, GDBUS_ARGS(RIL_DBUS_DEFAULT_VOICE_MODEM_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_MMS_SIM_CHANGED, { GDBUS_SIGNAL(RIL_DBUS_SIGNAL_MMS_SIM_CHANGED,
GDBUS_ARGS({ "imsi", "s" })) }, GDBUS_ARGS(RIL_DBUS_MMS_SIM_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_MMS_MODEM_CHANGED, { GDBUS_SIGNAL(RIL_DBUS_SIGNAL_MMS_MODEM_CHANGED,
GDBUS_ARGS({ "path", "s" })) }, GDBUS_ARGS(RIL_DBUS_MMS_MODEM_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_READY_CHANGED, { GDBUS_SIGNAL(RIL_DBUS_SIGNAL_READY_CHANGED,
GDBUS_ARGS({ "ready", "b" })) }, GDBUS_ARGS(RIL_DBUS_READY_ARG)) },
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_MODEM_ERROR,
GDBUS_ARGS({"path","o"},
{"error_id", "s"},
{"message", "s"})) },
{ } { }
}; };

View File

@@ -142,3 +142,12 @@ socket=/dev/socket/rild
# Default is 200 ms # Default is 200 ms
# #
#dataCallRetryDelay=200 #dataCallRetryDelay=200
# Additional local and remote hangup reasons. Remote reasons are checked
# first. Normally, RIL plugin figures it out automatically. You would only
# need to define these if your RIL does something unusual.
#
# No default
#
#remoteHangupReasons=20
#localHangupReasons=23

View File

@@ -1,7 +1,7 @@
/* /*
* oFono - Open Source Telephony - RIL-based devices * oFono - Open Source Telephony - RIL-based devices
* *
* Copyright (C) 2015-2016 Jolla Ltd. * Copyright (C) 2015-2017 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
@@ -53,6 +53,8 @@ struct ril_slot_config {
guint slot; guint slot;
gboolean enable_4g; gboolean enable_4g;
gboolean empty_pin_query; gboolean empty_pin_query;
GUtilInts *local_hangup_reasons;
GUtilInts *remote_hangup_reasons;
}; };
#endif /* RIL_TYPES_H */ #endif /* RIL_TYPES_H */

View File

@@ -1,7 +1,7 @@
/* /*
* oFono - Open Source Telephony - RIL-based devices * oFono - Open Source Telephony - RIL-based devices
* *
* Copyright (C) 2015-2016 Jolla Ltd. * Copyright (C) 2015-2017 Jolla Ltd.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
@@ -21,6 +21,7 @@
#include "common.h" #include "common.h"
#include <gutil_ints.h>
#include <gutil_ring.h> #include <gutil_ring.h>
#define FLAG_NEED_CLIP 1 #define FLAG_NEED_CLIP 1
@@ -43,7 +44,9 @@ struct ril_voicecall {
ofono_voicecall_cb_t cb; ofono_voicecall_cb_t cb;
void *data; void *data;
guint timer_id; guint timer_id;
GUtilRing* dtmf_queue; GUtilRing *dtmf_queue;
GUtilInts *local_hangup_reasons;
GUtilInts *remote_hangup_reasons;
guint send_dtmf_id; guint send_dtmf_id;
guint clcc_poll_id; guint clcc_poll_id;
gulong event_id[VOICECALL_EVENT_COUNT]; gulong event_id[VOICECALL_EVENT_COUNT];
@@ -60,28 +63,13 @@ struct ril_voicecall_change_state_req {
}; };
struct lastcause_req { struct lastcause_req {
struct ofono_voicecall *vc; struct ril_voicecall *vd;
int id; int id;
}; };
static void ril_voicecall_send_one_dtmf(struct ril_voicecall *vd); static void ril_voicecall_send_one_dtmf(struct ril_voicecall *vd);
static void ril_voicecall_clear_dtmf_queue(struct ril_voicecall *vd); static void ril_voicecall_clear_dtmf_queue(struct ril_voicecall *vd);
/*
* structs ofono_voicecall and voicecall are fully defined
* in src/voicecall.c; we need (read) access to the
* call objects, so partially redefine them here.
*/
struct ofono_voicecall {
GSList *call_list;
/* ... */
};
struct voicecall {
struct ofono_call *call;
/* ... */
};
static inline struct ril_voicecall *ril_voicecall_get_data( static inline struct ril_voicecall *ril_voicecall_get_data(
struct ofono_voicecall *vc) struct ofono_voicecall *vc)
{ {
@@ -166,38 +154,76 @@ static GSList *ril_voicecall_parse_clcc(const void *data, guint len)
} }
/* Valid call statuses have value >= 0 */ /* Valid call statuses have value >= 0 */
static int call_status_with_id(struct ofono_voicecall *vc, int id) static int ril_voicecall_status_with_id(struct ofono_voicecall *vc,
unsigned int id)
{ {
GSList *l; struct ofono_call *call = ofono_voicecall_find_call(vc, id);
struct voicecall *v;
GASSERT(vc); return call ? call->status : -1;
}
for (l = vc->call_list; l; l = l->next) { /* Tries to parse the payload as a uint followed by a string */
v = l->data; static int ril_voicecall_parse_lastcause_1(const void *data, guint len)
if (v->call->id == id) { {
return v->call->status; int result = -1;
if (len > 8) {
int code;
char *msg = NULL;
GRilIoParser rilp;
grilio_parser_init(&rilp, data, len);
if (grilio_parser_get_int32(&rilp, &code) && code >= 0 &&
(msg = grilio_parser_get_utf8(&rilp)) &&
grilio_parser_at_end(&rilp)) {
DBG("%d \"%s\"", code, msg);
result = code;
} }
g_free(msg);
} }
return -1; return result;
} }
static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status, static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data) const void *data, guint len, void *user_data)
{ {
struct lastcause_req *reqdata = user_data; struct lastcause_req *reqdata = user_data;
struct ofono_voicecall *vc = reqdata->vc; struct ril_voicecall *vd = reqdata->vd;
int tmp; struct ofono_voicecall *vc = vd->vc;
int id = reqdata->id; int id = reqdata->id;
int call_status; int call_status;
enum ofono_disconnect_reason reason = OFONO_DISCONNECT_REASON_ERROR; enum ofono_disconnect_reason reason = OFONO_DISCONNECT_REASON_ERROR;
int last_cause = CALL_FAIL_ERROR_UNSPECIFIED; int last_cause;
/*
* According to ril.h:
*
* "response" is a "int *"
* ((int *)response)[0] is RIL_LastCallFailCause. GSM failure
* reasons are mapped to cause codes defined in TS 24.008 Annex H
* where possible.
*
* However some RILs feel free to invent their own formats,
* try those first.
*/
last_cause = ril_voicecall_parse_lastcause_1(data, len);
if (last_cause < 0) {
GRilIoParser rilp; GRilIoParser rilp;
int num, code;
/* Default format described in ril.h */
grilio_parser_init(&rilp, data, len); grilio_parser_init(&rilp, data, len);
if (grilio_parser_get_int32(&rilp, &tmp) && tmp > 0) { if (grilio_parser_get_int32(&rilp, &num) && num == 1 &&
grilio_parser_get_int32(&rilp, &last_cause); grilio_parser_get_int32(&rilp, &code) &&
grilio_parser_at_end(&rilp)) {
last_cause = code;
} else {
ofono_warn("Unable to parse last call fail cause");
last_cause = CALL_FAIL_ERROR_UNSPECIFIED;
}
} }
/* /*
@@ -208,6 +234,13 @@ static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
* CALL_FAIL_ERROR_UNSPECIFIED, and thus indistinguishable * CALL_FAIL_ERROR_UNSPECIFIED, and thus indistinguishable
* from a network failure. * from a network failure.
*/ */
if (gutil_ints_contains(vd->remote_hangup_reasons, last_cause)) {
DBG("hangup cause %d => remote hangup", last_cause);
reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP;
} else if (gutil_ints_contains(vd->local_hangup_reasons, last_cause)) {
DBG("hangup cause %d => local hangup", last_cause);
reason = OFONO_DISCONNECT_REASON_LOCAL_HANGUP;
} else {
switch (last_cause) { switch (last_cause) {
case CALL_FAIL_UNOBTAINABLE_NUMBER: case CALL_FAIL_UNOBTAINABLE_NUMBER:
case CALL_FAIL_NORMAL: case CALL_FAIL_NORMAL:
@@ -216,19 +249,19 @@ static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
case CALL_FAIL_CHANNEL_UNACCEPTABLE: case CALL_FAIL_CHANNEL_UNACCEPTABLE:
case CALL_FAIL_OPERATOR_DETERMINED_BARRING: case CALL_FAIL_OPERATOR_DETERMINED_BARRING:
case CALL_FAIL_NO_USER_RESPONDING: case CALL_FAIL_NO_USER_RESPONDING:
case CALL_FAIL_USER_ALERTING_NO_ANSWER: case CALL_FAIL_NO_ANSWER_FROM_USER:
case CALL_FAIL_CALL_REJECTED: case CALL_FAIL_CALL_REJECTED:
case CALL_FAIL_NUMBER_CHANGED: case CALL_FAIL_NUMBER_CHANGED:
case CALL_FAIL_ANONYMOUS_CALL_REJECTION: case CALL_FAIL_ANONYMOUS_CALL_REJECTION:
case CALL_FAIL_PRE_EMPTION: case CALL_FAIL_PRE_EMPTION:
case CALL_FAIL_DESTINATION_OUT_OF_ORDER: case CALL_FAIL_DESTINATION_OUT_OF_ORDER:
case CALL_FAIL_INCOMPLETE_NUMBER: case CALL_FAIL_INVALID_NUMBER_FORMAT:
case CALL_FAIL_FACILITY_REJECTED: case CALL_FAIL_FACILITY_REJECTED:
reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP; reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP;
break; break;
case CALL_FAIL_NORMAL_UNSPECIFIED: case CALL_FAIL_NORMAL_UNSPECIFIED:
call_status = call_status_with_id(vc, id); call_status = ril_voicecall_status_with_id(vc, id);
if (call_status == CALL_STATUS_ACTIVE || if (call_status == CALL_STATUS_ACTIVE ||
call_status == CALL_STATUS_HELD || call_status == CALL_STATUS_HELD ||
call_status == CALL_STATUS_DIALING || call_status == CALL_STATUS_DIALING ||
@@ -240,7 +273,7 @@ static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
break; break;
case CALL_FAIL_ERROR_UNSPECIFIED: case CALL_FAIL_ERROR_UNSPECIFIED:
call_status = call_status_with_id(vc, id); call_status = ril_voicecall_status_with_id(vc, id);
if (call_status == CALL_STATUS_DIALING || if (call_status == CALL_STATUS_DIALING ||
call_status == CALL_STATUS_ALERTING) { call_status == CALL_STATUS_ALERTING) {
reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP; reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP;
@@ -251,6 +284,7 @@ static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
reason = OFONO_DISCONNECT_REASON_ERROR; reason = OFONO_DISCONNECT_REASON_ERROR;
break; break;
} }
}
ofono_info("Call %d ended with RIL cause %d -> ofono reason %d", ofono_info("Call %d ended with RIL cause %d -> ofono reason %d",
id, last_cause, reason); id, last_cause, reason);
@@ -295,7 +329,7 @@ static void ril_voicecall_clcc_poll_cb(GRilIoChannel *io, int status,
struct lastcause_req *reqdata = struct lastcause_req *reqdata =
g_new0(struct lastcause_req, 1); g_new0(struct lastcause_req, 1);
reqdata->vc = vd->vc; reqdata->vd = vd;
reqdata->id = oc->id; reqdata->id = oc->id;
grilio_queue_send_request_full(vd->q, NULL, grilio_queue_send_request_full(vd->q, NULL,
RIL_REQUEST_LAST_CALL_FAIL_CAUSE, RIL_REQUEST_LAST_CALL_FAIL_CAUSE,
@@ -803,6 +837,7 @@ static int ril_voicecall_probe(struct ofono_voicecall *vc, unsigned int vendor,
void *data) void *data)
{ {
struct ril_modem *modem = data; struct ril_modem *modem = data;
const struct ril_slot_config *cfg = &modem->config;
struct ril_voicecall *vd; struct ril_voicecall *vd;
DBG(""); DBG("");
@@ -810,6 +845,8 @@ static int ril_voicecall_probe(struct ofono_voicecall *vc, unsigned int vendor,
vd->io = grilio_channel_ref(ril_modem_io(modem)); vd->io = grilio_channel_ref(ril_modem_io(modem));
vd->q = grilio_queue_new(vd->io); vd->q = grilio_queue_new(vd->io);
vd->dtmf_queue = gutil_ring_new(); vd->dtmf_queue = gutil_ring_new();
vd->local_hangup_reasons = gutil_ints_ref(cfg->local_hangup_reasons);
vd->remote_hangup_reasons = gutil_ints_ref(cfg->remote_hangup_reasons);
vd->vc = vc; vd->vc = vc;
vd->timer_id = g_idle_add(ril_delayed_register, vd); vd->timer_id = g_idle_add(ril_delayed_register, vd);
if (modem->ecclist_file) { if (modem->ecclist_file) {
@@ -841,6 +878,8 @@ static void ril_voicecall_remove(struct ofono_voicecall *vc)
grilio_queue_cancel_all(vd->q, FALSE); grilio_queue_cancel_all(vd->q, FALSE);
grilio_queue_unref(vd->q); grilio_queue_unref(vd->q);
gutil_ring_unref(vd->dtmf_queue); gutil_ring_unref(vd->dtmf_queue);
gutil_ints_unref(vd->local_hangup_reasons);
gutil_ints_unref(vd->remote_hangup_reasons);
g_free(vd); g_free(vd);
} }

View File

@@ -172,6 +172,8 @@ void ofono_voicecall_ssn_mt_notify(struct ofono_voicecall *vc, unsigned int id,
int code, int index, int code, int index,
const struct ofono_phone_number *ph); const struct ofono_phone_number *ph);
struct ofono_call *ofono_voicecall_find_call(struct ofono_voicecall *vc,
unsigned int id);
void ofono_voicecall_ringback_tone_notify(struct ofono_voicecall *vc, void ofono_voicecall_ringback_tone_notify(struct ofono_voicecall *vc,
const ofono_bool_t playTone); const ofono_bool_t playTone);

View File

@@ -2274,6 +2274,11 @@ static DBusMessage *gprs_add_context(DBusConnection *conn,
const char *path; const char *path;
enum ofono_gprs_context_type type; enum ofono_gprs_context_type type;
#ifdef DISABLE_ADD_REMOVE_CONTEXT
ofono_error("AddContext not allowed");
return __ofono_error_not_supported(msg);
#endif
if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &typestr, if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &typestr,
DBUS_TYPE_INVALID)) DBUS_TYPE_INVALID))
return __ofono_error_invalid_args(msg); return __ofono_error_invalid_args(msg);
@@ -2355,6 +2360,11 @@ static DBusMessage *gprs_remove_context(DBusConnection *conn,
const char *path; const char *path;
const char *atompath; const char *atompath;
#ifdef DISABLE_ADD_REMOVE_CONTEXT
ofono_error("RemoveContext not allowed");
return __ofono_error_not_supported(msg);
#endif
if (gprs->pending) if (gprs->pending)
return __ofono_error_busy(msg); return __ofono_error_busy(msg);

View File

@@ -3748,6 +3748,15 @@ int ofono_voicecall_get_next_callid(struct ofono_voicecall *vc)
return __ofono_modem_callid_next(modem); return __ofono_modem_callid_next(modem);
} }
struct ofono_call *ofono_voicecall_find_call(struct ofono_voicecall *vc,
unsigned int id)
{
GSList *l = g_slist_find_custom(vc->call_list, GUINT_TO_POINTER(id),
call_compare_by_id);
return l ? ((struct voicecall *)l->data)->call : NULL;
}
ofono_bool_t __ofono_voicecall_is_busy(struct ofono_voicecall *vc, ofono_bool_t __ofono_voicecall_is_busy(struct ofono_voicecall *vc,
enum ofono_voicecall_interaction type) enum ofono_voicecall_interaction type)
{ {

View File

@@ -11,7 +11,7 @@ Requires: dbus
Requires: systemd Requires: systemd
Requires: ofono-configs Requires: ofono-configs
Requires: libgrilio >= 1.0.10 Requires: libgrilio >= 1.0.10
Requires: libglibutil >= 1.0.10 Requires: libglibutil >= 1.0.19
Requires(preun): systemd Requires(preun): systemd
Requires(post): systemd Requires(post): systemd
Requires(postun): systemd Requires(postun): systemd
@@ -21,7 +21,7 @@ BuildRequires: pkgconfig(libudev) >= 145
BuildRequires: pkgconfig(mobile-broadband-provider-info) BuildRequires: pkgconfig(mobile-broadband-provider-info)
BuildRequires: pkgconfig(libwspcodec) >= 2.0 BuildRequires: pkgconfig(libwspcodec) >= 2.0
BuildRequires: pkgconfig(libgrilio) >= 1.0.10 BuildRequires: pkgconfig(libgrilio) >= 1.0.10
BuildRequires: pkgconfig(libglibutil) >= 1.0.10 BuildRequires: pkgconfig(libglibutil) >= 1.0.19
BuildRequires: pkgconfig(libdbuslogserver-dbus) BuildRequires: pkgconfig(libdbuslogserver-dbus)
BuildRequires: pkgconfig(libmce-glib) BuildRequires: pkgconfig(libmce-glib)
BuildRequires: libtool BuildRequires: libtool
@@ -71,6 +71,9 @@ autoreconf --force --install
--enable-test \ --enable-test \
--enable-debuglog \ --enable-debuglog \
--enable-jolla-rilmodem \ --enable-jolla-rilmodem \
--disable-add-remove-context \
--disable-isimodem \
--disable-qmimodem \
--with-systemdunitdir="/%{_lib}/systemd/system" --with-systemdunitdir="/%{_lib}/systemd/system"
make %{?jobs:-j%jobs} make %{?jobs:-j%jobs}