mirror of
https://github.com/sailfishos/ofono
synced 2025-11-25 03:49:44 +08:00
Compare commits
34 Commits
mer/1.19+g
...
mer/1.19+g
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e1e4381105 | ||
|
|
cc3ca52e61 | ||
|
|
a71779ea2a | ||
|
|
a9d2849bbb | ||
|
|
ca29c8e538 | ||
|
|
85fe1b7174 | ||
|
|
56e0d9dffa | ||
|
|
6867ba65cb | ||
|
|
6199eaa4d8 | ||
|
|
fabdd6799c | ||
|
|
1219ab6a3f | ||
|
|
85a956d9eb | ||
|
|
c83d992a3b | ||
|
|
b22027017c | ||
|
|
1fa137b36d | ||
|
|
cfd837b1db | ||
|
|
735ad21e89 | ||
|
|
c9078404de | ||
|
|
e375195c92 | ||
|
|
ef5610f741 | ||
|
|
aef9bbd3e0 | ||
|
|
c6eb410f21 | ||
|
|
08b3ea3d0f | ||
|
|
2978862417 | ||
|
|
19228c9e67 | ||
|
|
9be791d531 | ||
|
|
6b9eb7bf8f | ||
|
|
01f8989aee | ||
|
|
2f5efaf591 | ||
|
|
ca1d06c37a | ||
|
|
5f45928a84 | ||
|
|
19f74e6c85 | ||
|
|
41d5cfcab2 | ||
|
|
357c5db580 |
@@ -575,6 +575,11 @@ builtin_sources += plugins/bluez5.c plugins/bluez5.h
|
||||
|
||||
builtin_modules += hfp_ag_bluez5
|
||||
builtin_sources += plugins/hfp_ag_bluez5.c plugins/bluez5.h
|
||||
|
||||
if SAILFISHFOS
|
||||
builtin_modules += sfos_bt
|
||||
builtin_sources += plugins/sfos_bt.c
|
||||
endif
|
||||
endif
|
||||
|
||||
if UPOWER
|
||||
|
||||
@@ -183,6 +183,13 @@ if (test "${enable_jolla_rilmodem}" = "yes"); then
|
||||
LIBS="$LIBS $GRILIO_LIBS $GLIBUTIL_LIBS $LIBMCE_LIBS"
|
||||
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],
|
||||
[disable Qualcomm QMI modem support]),
|
||||
[enable_qmimodem=${enableval}])
|
||||
@@ -206,6 +213,10 @@ fi
|
||||
AM_CONDITIONAL(BLUEZ4, test "${enable_bluetooth}" != "no" && test "${enable_bluez4}" = "yes")
|
||||
AM_CONDITIONAL(BLUETOOTH, test "${enable_bluetooth}" != "no")
|
||||
|
||||
AC_ARG_ENABLE(sailfishos, AC_HELP_STRING([--enable-sailfishos],
|
||||
[enable sailfishos plugin]), [enable_sailfishos=${enableval}])
|
||||
AM_CONDITIONAL(SAILFISHFOS, test "${enable_sailfishos}" = "yes")
|
||||
|
||||
AC_ARG_ENABLE(nettime, AC_HELP_STRING([--disable-nettime],
|
||||
[disable Nettime plugin]),
|
||||
[enable_nettime=${enableval}])
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -15,9 +15,12 @@
|
||||
|
||||
#include "ril_config.h"
|
||||
|
||||
#include <gutil_intarray.h>
|
||||
#include <gutil_ints.h>
|
||||
|
||||
/* 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)
|
||||
{
|
||||
char *val = g_key_file_get_string(file, group, key, NULL);
|
||||
|
||||
@@ -29,6 +32,31 @@ char* ril_config_get_string(GKeyFile *file, const char *group, const char *key)
|
||||
return val;
|
||||
}
|
||||
|
||||
char **ril_config_get_strings(GKeyFile *file, const char *group,
|
||||
const char *key, char delimiter)
|
||||
{
|
||||
char *str = ril_config_get_string(file, group, key);
|
||||
|
||||
if (str) {
|
||||
char **strv, **p;
|
||||
char delimiter_str[2];
|
||||
|
||||
delimiter_str[0] = delimiter;
|
||||
delimiter_str[1] = 0;
|
||||
strv = g_strsplit(str, delimiter_str, -1);
|
||||
|
||||
/* Strip whitespaces */
|
||||
for (p = strv; *p; p++) {
|
||||
*p = g_strstrip(*p);
|
||||
}
|
||||
|
||||
g_free(str);
|
||||
return strv;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean ril_config_get_integer(GKeyFile *file, const char *group,
|
||||
const char *key, int *out_value)
|
||||
{
|
||||
@@ -106,6 +134,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:
|
||||
* mode: C
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -22,13 +22,19 @@
|
||||
|
||||
#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);
|
||||
char **ril_config_get_strings(GKeyFile *file, const char *group,
|
||||
const char *key, char delimiter);
|
||||
gboolean ril_config_get_integer(GKeyFile *file, const char *group,
|
||||
const char *key, int *value);
|
||||
gboolean ril_config_get_boolean(GKeyFile *file, const char *group,
|
||||
const char *key, gboolean *value);
|
||||
gboolean ril_config_get_flag(GKeyFile *file, const char *group,
|
||||
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 */
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
/*
|
||||
*
|
||||
* RIL constants adopted from AOSP's header:
|
||||
*
|
||||
* /hardware/ril/reference_ril/ril.h
|
||||
*
|
||||
* 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
|
||||
* 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 */
|
||||
#define CALL_FAIL_UNOBTAINABLE_NUMBER 1
|
||||
#define CALL_FAIL_NORMAL 16
|
||||
#define CALL_FAIL_BUSY 17
|
||||
#define CALL_FAIL_CONGESTION 34
|
||||
#define CALL_FAIL_ACM_LIMIT_EXCEEDED 68
|
||||
#define CALL_FAIL_CALL_BARRED 240
|
||||
#define CALL_FAIL_FDN_BLOCKED 241
|
||||
#define CALL_FAIL_IMSI_UNKNOWN_IN_VLR 242
|
||||
#define CALL_FAIL_IMEI_NOT_ACCEPTED 243
|
||||
#define CALL_FAIL_DIAL_MODIFIED_TO_USSD 244
|
||||
#define CALL_FAIL_DIAL_MODIFIED_TO_SS 245
|
||||
#define CALL_FAIL_DIAL_MODIFIED_TO_DIAL 246
|
||||
#define CALL_FAIL_CDMA_LOCKED_UNTIL_POWER_CYCLE 1000
|
||||
#define CALL_FAIL_CDMA_DROP 1001
|
||||
#define CALL_FAIL_CDMA_INTERCEPT 1002
|
||||
#define CALL_FAIL_CDMA_REORDER 1003
|
||||
#define CALL_FAIL_CDMA_SO_REJECT 1004
|
||||
#define CALL_FAIL_CDMA_RETRY_ORDER 1005
|
||||
#define CALL_FAIL_CDMA_ACCESS_FAILURE 1006
|
||||
#define CALL_FAIL_CDMA_PREEMPTED 1007
|
||||
#define CALL_FAIL_CDMA_NOT_EMERGENCY 1008
|
||||
#define CALL_FAIL_CDMA_ACCESS_BLOCKED 1009
|
||||
#define CALL_FAIL_ERROR_UNSPECIFIED 0xffff
|
||||
enum ril_call_fail_cause {
|
||||
CALL_FAIL_UNOBTAINABLE_NUMBER = 1,
|
||||
CALL_FAIL_NO_ROUTE_TO_DESTINATION = 3,
|
||||
CALL_FAIL_CHANNEL_UNACCEPTABLE = 6,
|
||||
CALL_FAIL_OPERATOR_DETERMINED_BARRING = 8,
|
||||
CALL_FAIL_NORMAL = 16,
|
||||
CALL_FAIL_BUSY = 17,
|
||||
CALL_FAIL_NO_USER_RESPONDING = 18,
|
||||
CALL_FAIL_NO_ANSWER_FROM_USER = 19,
|
||||
CALL_FAIL_CALL_REJECTED = 21,
|
||||
CALL_FAIL_NUMBER_CHANGED = 22,
|
||||
CALL_FAIL_DESTINATION_OUT_OF_ORDER = 27,
|
||||
CALL_FAIL_INVALID_NUMBER_FORMAT = 28,
|
||||
CALL_FAIL_FACILITY_REJECTED = 29,
|
||||
CALL_FAIL_RESP_TO_STATUS_ENQUIRY = 30,
|
||||
CALL_FAIL_NORMAL_UNSPECIFIED = 31,
|
||||
CALL_FAIL_CONGESTION = 34,
|
||||
CALL_FAIL_NETWORK_OUT_OF_ORDER = 38,
|
||||
CALL_FAIL_TEMPORARY_FAILURE = 41,
|
||||
CALL_FAIL_SWITCHING_EQUIPMENT_CONGESTION = 42,
|
||||
CALL_FAIL_ACCESS_INFORMATION_DISCARDED = 43,
|
||||
CALL_FAIL_REQUESTED_CIRCUIT_OR_CHANNEL_NOT_AVAILABLE = 44,
|
||||
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
|
||||
* for call control. See 3GPP TS 24.008 Annex H. */
|
||||
#define CALL_FAIL_NO_ROUTE_TO_DESTINATION 3
|
||||
#define CALL_FAIL_CHANNEL_UNACCEPTABLE 6
|
||||
#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
|
||||
CALL_FAIL_ANONYMOUS_CALL_REJECTION = 24,
|
||||
CALL_FAIL_PRE_EMPTION = 25
|
||||
};
|
||||
|
||||
enum ril_data_call_fail_cause {
|
||||
PDP_FAIL_NONE = 0,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -17,16 +17,24 @@
|
||||
#include "ril_util.h"
|
||||
#include "ril_log.h"
|
||||
|
||||
#include <gutil_idlequeue.h>
|
||||
|
||||
/*
|
||||
* TODO: No public RIL api to query manufacturer or model.
|
||||
* Check where to get, could /system/build.prop be updated to have good values?
|
||||
*/
|
||||
|
||||
enum ril_devinfo_cb_tag {
|
||||
DEVINFO_QUERY_SERIAL = 1,
|
||||
DEVINFO_QUERY_SVN
|
||||
};
|
||||
|
||||
struct ril_devinfo {
|
||||
struct ofono_devinfo *info;
|
||||
GRilIoQueue *q;
|
||||
guint register_id;
|
||||
guint imei_id;
|
||||
GUtilIdleQueue *iq;
|
||||
char *log_prefix;
|
||||
char *imeisv;
|
||||
char *imei;
|
||||
};
|
||||
|
||||
@@ -36,6 +44,7 @@ struct ril_devinfo_cbd {
|
||||
gpointer data;
|
||||
};
|
||||
|
||||
#define DBG_(self,fmt,args...) DBG("%s" fmt, (self)->log_prefix, ##args)
|
||||
#define ril_devinfo_cbd_free g_free
|
||||
|
||||
static inline struct ril_devinfo *ril_devinfo_get_data(
|
||||
@@ -62,7 +71,7 @@ static void ril_devinfo_query_unsupported(struct ofono_devinfo *info,
|
||||
cb(ril_error_failure(&error), "", data);
|
||||
}
|
||||
|
||||
static void ril_devinfo_query_cb(GRilIoChannel *io, int status,
|
||||
static void ril_devinfo_query_revision_cb(GRilIoChannel *io, int status,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ofono_error error;
|
||||
@@ -73,7 +82,7 @@ static void ril_devinfo_query_cb(GRilIoChannel *io, int status,
|
||||
GRilIoParser rilp;
|
||||
grilio_parser_init(&rilp, data, len);
|
||||
res = grilio_parser_get_utf8(&rilp);
|
||||
DBG("%s", res);
|
||||
DBG_(cbd->di, "%s", res);
|
||||
cbd->cb(ril_error_ok(&error), res ? res : "", cbd->data);
|
||||
g_free(res);
|
||||
} else {
|
||||
@@ -86,23 +95,46 @@ static void ril_devinfo_query_revision(struct ofono_devinfo *info,
|
||||
{
|
||||
struct ril_devinfo *di = ril_devinfo_get_data(info);
|
||||
|
||||
DBG("");
|
||||
grilio_queue_send_request_full(di->q, NULL, RIL_REQUEST_BASEBAND_VERSION,
|
||||
ril_devinfo_query_cb, ril_devinfo_cbd_free,
|
||||
DBG_(di, "");
|
||||
grilio_queue_send_request_full(di->q, NULL,
|
||||
RIL_REQUEST_BASEBAND_VERSION,
|
||||
ril_devinfo_query_revision_cb,
|
||||
ril_devinfo_cbd_free,
|
||||
ril_devinfo_cbd_new(di, cb, data));
|
||||
}
|
||||
|
||||
static gboolean ril_devinfo_query_serial_cb(void *user_data)
|
||||
static void ril_devinfo_query_serial_cb(gpointer user_data)
|
||||
{
|
||||
struct ril_devinfo_cbd *cbd = user_data;
|
||||
struct ril_devinfo *di = cbd->di;
|
||||
struct ofono_error error;
|
||||
|
||||
GASSERT(di->imei_id);
|
||||
di->imei_id = 0;
|
||||
|
||||
DBG_(di, "%s", di->imei);
|
||||
cbd->cb(ril_error_ok(&error), di->imei, cbd->data);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void ril_devinfo_query_svn_cb(gpointer user_data)
|
||||
{
|
||||
struct ril_devinfo_cbd *cbd = user_data;
|
||||
struct ril_devinfo *di = cbd->di;
|
||||
struct ofono_error error;
|
||||
|
||||
DBG_(di, "%s", di->imeisv);
|
||||
if (di->imeisv && di->imeisv[0]) {
|
||||
cbd->cb(ril_error_ok(&error), di->imeisv, cbd->data);
|
||||
} else {
|
||||
cbd->cb(ril_error_failure(&error), "", cbd->data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_devinfo_query(struct ril_devinfo *di,
|
||||
enum ril_devinfo_cb_tag tag, GUtilIdleFunc fn,
|
||||
ofono_devinfo_query_cb_t cb, void *data)
|
||||
{
|
||||
GVERIFY_FALSE(gutil_idle_queue_cancel_tag(di->iq, tag));
|
||||
gutil_idle_queue_add_tag_full(di->iq, tag, fn,
|
||||
ril_devinfo_cbd_new(di, cb, data),
|
||||
ril_devinfo_cbd_free);
|
||||
}
|
||||
|
||||
static void ril_devinfo_query_serial(struct ofono_devinfo *info,
|
||||
@@ -111,29 +143,28 @@ static void ril_devinfo_query_serial(struct ofono_devinfo *info,
|
||||
{
|
||||
struct ril_devinfo *di = ril_devinfo_get_data(info);
|
||||
|
||||
GASSERT(!di->imei_id);
|
||||
if (di->imei_id) {
|
||||
g_source_remove(di->imei_id);
|
||||
di->imei_id = 0;
|
||||
}
|
||||
|
||||
DBG("%s", di->imei);
|
||||
di->imei_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
|
||||
ril_devinfo_query_serial_cb,
|
||||
ril_devinfo_cbd_new(di, cb, data),
|
||||
ril_devinfo_cbd_free);
|
||||
DBG_(di, "");
|
||||
ril_devinfo_query(di, DEVINFO_QUERY_SERIAL,
|
||||
ril_devinfo_query_serial_cb, cb, data);
|
||||
}
|
||||
|
||||
static gboolean ril_devinfo_register(gpointer user_data)
|
||||
static void ril_devinfo_query_svn(struct ofono_devinfo *info,
|
||||
ofono_devinfo_query_cb_t cb,
|
||||
void *data)
|
||||
{
|
||||
struct ril_devinfo *di = ril_devinfo_get_data(info);
|
||||
|
||||
DBG_(di, "");
|
||||
ril_devinfo_query(di, DEVINFO_QUERY_SVN,
|
||||
ril_devinfo_query_svn_cb, cb, data);
|
||||
}
|
||||
|
||||
static void ril_devinfo_register(gpointer user_data)
|
||||
{
|
||||
struct ril_devinfo *di = user_data;
|
||||
|
||||
DBG("");
|
||||
di->register_id = 0;
|
||||
DBG_(di, "");
|
||||
ofono_devinfo_register(di->info);
|
||||
|
||||
/* This makes the timeout a single-shot */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int ril_devinfo_probe(struct ofono_devinfo *info, unsigned int vendor,
|
||||
@@ -142,13 +173,18 @@ static int ril_devinfo_probe(struct ofono_devinfo *info, unsigned int vendor,
|
||||
struct ril_modem *modem = data;
|
||||
struct ril_devinfo *di = g_new0(struct ril_devinfo, 1);
|
||||
|
||||
DBG("%s %s %p", ril_modem_get_path(modem), modem->imei, di);
|
||||
di->log_prefix = (modem->log_prefix && modem->log_prefix[0]) ?
|
||||
g_strconcat(modem->log_prefix, " ", NULL) : g_strdup("");
|
||||
|
||||
DBG_(di, "%s", modem->imei);
|
||||
GASSERT(modem->imei);
|
||||
|
||||
di->q = grilio_queue_new(ril_modem_io(modem));
|
||||
di->info = info;
|
||||
di->imeisv = g_strdup(modem->imeisv);
|
||||
di->imei = g_strdup(modem->imei);
|
||||
|
||||
di->register_id = g_idle_add(ril_devinfo_register, di);
|
||||
di->iq = gutil_idle_queue_new();
|
||||
gutil_idle_queue_add(di->iq, ril_devinfo_register, di);
|
||||
ofono_devinfo_set_data(info, di);
|
||||
return 0;
|
||||
}
|
||||
@@ -157,19 +193,14 @@ static void ril_devinfo_remove(struct ofono_devinfo *info)
|
||||
{
|
||||
struct ril_devinfo *di = ril_devinfo_get_data(info);
|
||||
|
||||
DBG("%p", di);
|
||||
DBG_(di, "");
|
||||
ofono_devinfo_set_data(info, NULL);
|
||||
|
||||
if (di->register_id > 0) {
|
||||
g_source_remove(di->register_id);
|
||||
}
|
||||
|
||||
if (di->imei_id > 0) {
|
||||
g_source_remove(di->imei_id);
|
||||
}
|
||||
|
||||
gutil_idle_queue_cancel_all(di->iq);
|
||||
gutil_idle_queue_unref(di->iq);
|
||||
grilio_queue_cancel_all(di->q, FALSE);
|
||||
grilio_queue_unref(di->q);
|
||||
g_free(di->log_prefix);
|
||||
g_free(di->imeisv);
|
||||
g_free(di->imei);
|
||||
g_free(di);
|
||||
}
|
||||
@@ -178,10 +209,11 @@ const struct ofono_devinfo_driver ril_devinfo_driver = {
|
||||
.name = RILMODEM_DRIVER,
|
||||
.probe = ril_devinfo_probe,
|
||||
.remove = ril_devinfo_remove,
|
||||
.query_manufacturer = ril_devinfo_query_unsupported,
|
||||
/* query_revision won't be called if query_model is missing */
|
||||
.query_model = ril_devinfo_query_unsupported,
|
||||
.query_revision = ril_devinfo_query_revision,
|
||||
.query_serial = ril_devinfo_query_serial
|
||||
.query_serial = ril_devinfo_query_serial,
|
||||
.query_svn = ril_devinfo_query_svn
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -52,6 +52,7 @@ struct ril_modem_data {
|
||||
struct ril_modem modem;
|
||||
GRilIoQueue *q;
|
||||
char *log_prefix;
|
||||
char *imeisv;
|
||||
char *imei;
|
||||
char *ecclist_file;
|
||||
gboolean pre_sim_done;
|
||||
@@ -433,6 +434,7 @@ static void ril_modem_remove(struct ofono_modem *ofono)
|
||||
grilio_queue_unref(md->q);
|
||||
g_free(md->ecclist_file);
|
||||
g_free(md->log_prefix);
|
||||
g_free(md->imeisv);
|
||||
g_free(md->imei);
|
||||
g_free(md);
|
||||
}
|
||||
@@ -460,6 +462,7 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
|
||||
/* Copy config */
|
||||
modem->config = *slot->config;
|
||||
modem->imei = md->imei = g_strdup(slot->imei);
|
||||
modem->imeisv = md->imeisv = g_strdup(slot->imeisv);
|
||||
modem->log_prefix = log_prefix;
|
||||
modem->ecclist_file =
|
||||
md->ecclist_file = g_strdup(slot->ecclist_file);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -420,13 +420,16 @@ static int ril_network_mode_to_rat(struct ril_network *self,
|
||||
switch (mode) {
|
||||
case OFONO_RADIO_ACCESS_MODE_ANY:
|
||||
case OFONO_RADIO_ACCESS_MODE_LTE:
|
||||
if (self->settings->enable_4g) {
|
||||
if (self->settings->techs & OFONO_RADIO_ACCESS_MODE_LTE) {
|
||||
return PREF_NET_TYPE_LTE_GSM_WCDMA;
|
||||
}
|
||||
/* no break */
|
||||
default:
|
||||
case OFONO_RADIO_ACCESS_MODE_UMTS:
|
||||
return PREF_NET_TYPE_GSM_WCDMA_AUTO;
|
||||
if (self->settings->techs & OFONO_RADIO_ACCESS_MODE_UMTS) {
|
||||
return PREF_NET_TYPE_GSM_WCDMA_AUTO;
|
||||
}
|
||||
/* no break */
|
||||
case OFONO_RADIO_ACCESS_MODE_GSM:
|
||||
return PREF_NET_TYPE_GSM_ONLY;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "ril_log.h"
|
||||
|
||||
#include <gdbus.h>
|
||||
#include <gutil_ints.h>
|
||||
#include <gutil_strv.h>
|
||||
#include <gutil_misc.h>
|
||||
#include <mce_display.h>
|
||||
@@ -40,6 +41,12 @@
|
||||
#include "ofono.h"
|
||||
#include "storage.h"
|
||||
|
||||
#define OFONO_RADIO_ACCESS_MODE_ALL (OFONO_RADIO_ACCESS_MODE_GSM |\
|
||||
OFONO_RADIO_ACCESS_MODE_UMTS |\
|
||||
OFONO_RADIO_ACCESS_MODE_LTE)
|
||||
|
||||
#define RIL_DEVICE_IDENTITY_RETRIES_LAST 2
|
||||
|
||||
#define RADIO_GID 1001
|
||||
#define RADIO_UID 1001
|
||||
#define RIL_SUB_SIZE 4
|
||||
@@ -48,7 +55,7 @@
|
||||
#define RILMODEM_DEFAULT_SOCK "/dev/socket/rild"
|
||||
#define RILMODEM_DEFAULT_SOCK2 "/dev/socket/rild2"
|
||||
#define RILMODEM_DEFAULT_SUB "SUB1"
|
||||
#define RILMODEM_DEFAULT_4G TRUE /* 4G is on by default */
|
||||
#define RILMODEM_DEFAULT_TECHS OFONO_RADIO_ACCESS_MODE_ALL
|
||||
#define RILMODEM_DEFAULT_SLOT 0xffffffff
|
||||
#define RILMODEM_DEFAULT_TIMEOUT 0 /* No timeout */
|
||||
#define RILMODEM_DEFAULT_SIM_FLAGS RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND
|
||||
@@ -69,7 +76,8 @@
|
||||
#define RILCONF_SLOT "slot"
|
||||
#define RILCONF_SUB "sub"
|
||||
#define RILCONF_TIMEOUT "timeout"
|
||||
#define RILCONF_4G "enable4G"
|
||||
#define RILCONF_4G "enable4G" /* Deprecated */
|
||||
#define RILCONF_TECHS "technologies"
|
||||
#define RILCONF_UICC_WORKAROUND "uiccWorkaround"
|
||||
#define RILCONF_ECCLIST_FILE "ecclistFile"
|
||||
#define RILCONF_ALLOW_DATA_REQ "allowDataReq"
|
||||
@@ -77,6 +85,8 @@
|
||||
#define RILCONF_DATA_CALL_FORMAT "dataCallFormat"
|
||||
#define RILCONF_DATA_CALL_RETRY_LIMIT "dataCallRetryLimit"
|
||||
#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_GROUP "Settings"
|
||||
@@ -85,6 +95,12 @@
|
||||
#define RIL_STORE_DEFAULT_DATA_SIM "DefaultDataSim"
|
||||
#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 {
|
||||
IO_EVENT_CONNECTED,
|
||||
IO_EVENT_ERROR,
|
||||
@@ -121,6 +137,7 @@ struct ril_slot {
|
||||
struct ril_slot_info pub;
|
||||
char *path;
|
||||
char *imei;
|
||||
char *imeisv;
|
||||
char *name;
|
||||
char *sockpath;
|
||||
char *sub;
|
||||
@@ -148,6 +165,7 @@ struct ril_slot {
|
||||
gulong io_event_id[IO_EVENT_COUNT];
|
||||
gulong imei_req_id;
|
||||
gulong sim_card_state_event_id;
|
||||
gboolean received_sim_status;
|
||||
guint trace_id;
|
||||
guint dump_id;
|
||||
guint retry_id;
|
||||
@@ -166,6 +184,7 @@ static void ril_debug_grilio_notify(struct ofono_debug_desc *desc);
|
||||
static void ril_debug_mce_notify(struct ofono_debug_desc *desc);
|
||||
static void ril_plugin_debug_notify(struct ofono_debug_desc *desc);
|
||||
static void ril_plugin_retry_init_io(struct ril_slot *slot);
|
||||
static void ril_plugin_check_modem(struct ril_slot *slot);
|
||||
|
||||
GLOG_MODULE_DEFINE("rilmodem");
|
||||
|
||||
@@ -208,6 +227,12 @@ static struct ofono_debug_desc ril_plugin_debug OFONO_DEBUG_ATTR = {
|
||||
.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)
|
||||
{
|
||||
return G_CAST(pub, struct ril_plugin_priv, pub);
|
||||
@@ -232,7 +257,7 @@ static void ril_plugin_foreach_slot(struct ril_plugin_priv *plugin,
|
||||
|
||||
static void ril_plugin_send_screen_state(struct ril_slot *slot)
|
||||
{
|
||||
if (slot->io) {
|
||||
if (slot->io && slot->io->connected) {
|
||||
GRilIoRequest *req = grilio_request_sized_new(8);
|
||||
grilio_request_append_int32(req, 1); /* Number of params */
|
||||
grilio_request_append_int32(req, slot->plugin->display_on);
|
||||
@@ -338,6 +363,7 @@ static void ril_plugin_shutdown_slot(struct ril_slot *slot, gboolean kill_io)
|
||||
ril_sim_card_unref(slot->sim_card);
|
||||
slot->sim_card_state_event_id = 0;
|
||||
slot->sim_card = NULL;
|
||||
slot->received_sim_status = FALSE;
|
||||
}
|
||||
|
||||
if (slot->io) {
|
||||
@@ -469,14 +495,23 @@ static int ril_plugin_update_modem_paths(struct ril_plugin_priv *plugin)
|
||||
if (plugin->default_data_imsi) {
|
||||
slot = ril_plugin_find_slot_imsi(plugin->slots,
|
||||
plugin->default_data_imsi);
|
||||
} else if (plugin->data_slot) {
|
||||
/* Make sure that the slot is enabled and SIM is in */
|
||||
slot = ril_plugin_find_slot_imsi(plugin->slots,
|
||||
} else if (!ril_plugin_multisim(plugin)) {
|
||||
if (plugin->data_slot) {
|
||||
/* Make sure that the slot is enabled and SIM is in */
|
||||
slot = ril_plugin_find_slot_imsi(plugin->slots,
|
||||
plugin->data_slot->modem ?
|
||||
ofono_sim_get_imsi(plugin->data_slot->sim) :
|
||||
NULL);
|
||||
} else {
|
||||
/* Check if anything is available */
|
||||
slot = ril_plugin_find_slot_imsi(plugin->slots, NULL);
|
||||
}
|
||||
} else {
|
||||
slot = ril_plugin_find_slot_imsi(plugin->slots, NULL);
|
||||
/*
|
||||
* Should we automatically select the default data sim
|
||||
* on a multisim phone that has only one sim inserted?
|
||||
*/
|
||||
slot = NULL;
|
||||
}
|
||||
|
||||
if (slot && !slot->radio->online) {
|
||||
@@ -568,14 +603,79 @@ static void ril_plugin_update_ready(struct ril_plugin_priv *plugin)
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_plugin_device_identity_cb(GRilIoChannel *io, int status,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ril_slot *slot = user_data;
|
||||
char *imei = NULL;
|
||||
char *imeisv = NULL;
|
||||
|
||||
GASSERT(slot->imei_req_id);
|
||||
slot->imei_req_id = 0;
|
||||
|
||||
if (status == RIL_E_SUCCESS) {
|
||||
GRilIoParser rilp;
|
||||
guint32 n;
|
||||
|
||||
/*
|
||||
* RIL_REQUEST_DEVICE_IDENTITY
|
||||
*
|
||||
* "response" is const char **
|
||||
* ((const char **)response)[0] is IMEI (for GSM)
|
||||
* ((const char **)response)[1] is IMEISV (for GSM)
|
||||
* ((const char **)response)[2] is ESN (for CDMA)
|
||||
* ((const char **)response)[3] is MEID (for CDMA)
|
||||
*/
|
||||
grilio_parser_init(&rilp, data, len);
|
||||
if (grilio_parser_get_uint32(&rilp, &n) && n >= 2) {
|
||||
imei = grilio_parser_get_utf8(&rilp);
|
||||
imeisv = grilio_parser_get_utf8(&rilp);
|
||||
DBG("%s %s", imei, imeisv);
|
||||
} else {
|
||||
DBG("parsing failure!");
|
||||
}
|
||||
|
||||
/*
|
||||
* slot->imei should be either NULL (when we get connected
|
||||
* to rild the very first time) or match the already known
|
||||
* IMEI (if rild crashed and we have reconnected)
|
||||
*/
|
||||
if (slot->imei && imei && strcmp(slot->imei, imei)) {
|
||||
ofono_warn("IMEI has changed \"%s\" -> \"%s\"",
|
||||
slot->imei, imei);
|
||||
}
|
||||
} else {
|
||||
ofono_error("Slot %u IMEI query error: %s", slot->config.slot,
|
||||
ril_error_to_string(status));
|
||||
}
|
||||
|
||||
if (slot->imei) {
|
||||
/* We assume that IMEI never changes */
|
||||
g_free(imei);
|
||||
} else {
|
||||
slot->pub.imei =
|
||||
slot->imei = imei ? imei : g_strdup_printf("%d", slot->index);
|
||||
}
|
||||
|
||||
if (slot->imeisv) {
|
||||
g_free(imeisv);
|
||||
} else {
|
||||
slot->pub.imeisv =
|
||||
slot->imeisv = (imeisv ? imeisv : g_strdup(""));
|
||||
}
|
||||
|
||||
ril_plugin_check_modem(slot);
|
||||
ril_plugin_update_ready(slot->plugin);
|
||||
}
|
||||
|
||||
static void ril_plugin_sim_state_changed(struct ril_sim_card *card, void *data)
|
||||
{
|
||||
struct ril_slot *slot = data;
|
||||
struct ril_plugin_priv *plugin = slot->plugin;
|
||||
const struct ril_sim_card_status *status = card->status;
|
||||
gboolean present;
|
||||
|
||||
if (card && card->status &&
|
||||
card->status->card_state == RIL_CARDSTATE_PRESENT) {
|
||||
if (status && status->card_state == RIL_CARDSTATE_PRESENT) {
|
||||
DBG("SIM found in slot %u", slot->config.slot);
|
||||
present = TRUE;
|
||||
} else {
|
||||
@@ -583,6 +683,36 @@ static void ril_plugin_sim_state_changed(struct ril_sim_card *card, void *data)
|
||||
present = FALSE;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
if (!slot->received_sim_status && slot->imei_req_id) {
|
||||
/*
|
||||
* We have received the SIM status but haven't yet
|
||||
* got IMEI from the modem. Some RILs behave this
|
||||
* way if the modem doesn't have IMEI initialized
|
||||
* yet. Cancel the current request (with unlimited
|
||||
* number of retries) and give a few more tries
|
||||
* (this time, limited number).
|
||||
*
|
||||
* Some RILs fail RIL_REQUEST_DEVICE_IDENTITY until
|
||||
* the modem hasn't been properly initialized.
|
||||
*/
|
||||
GRilIoRequest* req = grilio_request_new();
|
||||
|
||||
DBG("Giving slot %u last chance", slot->config.slot);
|
||||
grilio_request_set_retry(req, RIL_RETRY_MS,
|
||||
RIL_DEVICE_IDENTITY_RETRIES_LAST);
|
||||
grilio_channel_cancel_request(slot->io,
|
||||
slot->imei_req_id, FALSE);
|
||||
slot->imei_req_id =
|
||||
grilio_channel_send_request_full(slot->io,
|
||||
req, RIL_REQUEST_DEVICE_IDENTITY,
|
||||
ril_plugin_device_identity_cb,
|
||||
NULL, slot);
|
||||
grilio_request_unref(req);
|
||||
}
|
||||
slot->received_sim_status = TRUE;
|
||||
}
|
||||
|
||||
if (slot->pub.sim_present != present) {
|
||||
slot->pub.sim_present = present;
|
||||
ril_plugin_dbus_signal_sim(plugin->dbus, slot->index, present);
|
||||
@@ -611,7 +741,7 @@ static void ril_plugin_sim_state_watch(enum ofono_sim_state new_state,
|
||||
struct ril_slot *slot = data;
|
||||
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;
|
||||
if (new_state == OFONO_SIM_STATE_READY) {
|
||||
struct ril_slot *voice_slot = plugin->voice_slot;
|
||||
@@ -667,10 +797,10 @@ static void ril_plugin_sim_watch(struct ofono_atom *atom,
|
||||
struct ril_slot *slot = data;
|
||||
|
||||
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));
|
||||
} 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;
|
||||
}
|
||||
|
||||
@@ -678,8 +808,35 @@ static void ril_plugin_sim_watch(struct ofono_atom *atom,
|
||||
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_update_modem_paths_full(slot->plugin);
|
||||
ril_plugin_retry_init_io(slot);
|
||||
@@ -688,12 +845,12 @@ static void ril_plugin_handle_error(struct ril_slot *slot)
|
||||
static void ril_plugin_slot_error(GRilIoChannel *io, const GError *error,
|
||||
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)
|
||||
{
|
||||
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,
|
||||
@@ -701,7 +858,7 @@ static void ril_plugin_modem_online(struct ril_modem *modem, gboolean online,
|
||||
{
|
||||
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 == modem);
|
||||
|
||||
@@ -813,14 +970,15 @@ static void ril_debug_trace_update(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)
|
||||
{
|
||||
struct ril_modem *modem;
|
||||
|
||||
DBG("%s", slot->path);
|
||||
DBG("%s", ril_slot_debug_prefix(slot));
|
||||
GASSERT(slot->io && slot->io->connected);
|
||||
GASSERT(!slot->modem);
|
||||
|
||||
@@ -869,42 +1027,6 @@ static void ril_plugin_check_modem(struct ril_slot *slot)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void ril_plugin_imei_cb(GRilIoChannel *io, int status,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ril_slot *slot = user_data;
|
||||
char *imei = NULL;
|
||||
|
||||
GASSERT(slot->imei_req_id);
|
||||
slot->imei_req_id = 0;
|
||||
|
||||
if (status == RIL_E_SUCCESS) {
|
||||
GRilIoParser rilp;
|
||||
|
||||
grilio_parser_init(&rilp, data, len);
|
||||
imei = grilio_parser_get_utf8(&rilp);
|
||||
|
||||
DBG("%s", imei);
|
||||
|
||||
/*
|
||||
* slot->imei should be either NULL (when we get connected
|
||||
* to rild the very first time) or match the already known
|
||||
* IMEI (if rild crashed and we have reconnected)
|
||||
*/
|
||||
GASSERT(!slot->imei || !g_strcmp0(slot->imei, imei));
|
||||
} else {
|
||||
ofono_error("Slot %u IMEI query error: %s", slot->config.slot,
|
||||
ril_error_to_string(status));
|
||||
}
|
||||
|
||||
g_free(slot->imei);
|
||||
slot->pub.imei = slot->imei = (imei ? imei : g_strdup("ERROR"));
|
||||
|
||||
ril_plugin_check_modem(slot);
|
||||
ril_plugin_update_ready(slot->plugin);
|
||||
}
|
||||
|
||||
/*
|
||||
* It seems to be necessary to kick (with RIL_REQUEST_RADIO_POWER) the
|
||||
* modems with power on after one of the modems has been powered off.
|
||||
@@ -940,17 +1062,19 @@ static void ril_plugin_slot_connected(struct ril_slot *slot)
|
||||
GASSERT(!slot->io_event_id[IO_EVENT_CONNECTED]);
|
||||
|
||||
/*
|
||||
* Modem will be registered after RIL_REQUEST_GET_IMEI successfully
|
||||
* completes. By the time ofono starts, rild may not be completely
|
||||
* functional. Waiting until it responds to RIL_REQUEST_GET_IMEI
|
||||
* (and retrying the request on failure) gives rild time to finish
|
||||
* whatever it's doing during initialization.
|
||||
* Modem will be registered after RIL_REQUEST_DEVICE_IDENTITY
|
||||
* successfully completes. By the time ofono starts, rild may
|
||||
* not be completely functional. Waiting until it responds to
|
||||
* RIL_REQUEST_DEVICE_IDENTITY (and retrying the request on
|
||||
* failure) gives rild time to finish whatever it's doing during
|
||||
* initialization.
|
||||
*/
|
||||
GASSERT(!slot->imei_req_id);
|
||||
req = grilio_request_new();
|
||||
grilio_request_set_retry(req, RIL_RETRY_MS, -1);
|
||||
slot->imei_req_id = grilio_channel_send_request_full(slot->io, req,
|
||||
RIL_REQUEST_GET_IMEI, ril_plugin_imei_cb, NULL, slot);
|
||||
slot->imei_req_id = grilio_channel_send_request_full(slot->io,
|
||||
req, RIL_REQUEST_DEVICE_IDENTITY,
|
||||
ril_plugin_device_identity_cb, NULL, slot);
|
||||
grilio_request_unref(req);
|
||||
|
||||
GASSERT(!slot->radio);
|
||||
@@ -967,6 +1091,10 @@ static void ril_plugin_slot_connected(struct ril_slot *slot)
|
||||
slot->sim_flags);
|
||||
slot->sim_card_state_event_id = ril_sim_card_add_state_changed_handler(
|
||||
slot->sim_card, ril_plugin_sim_state_changed, slot);
|
||||
/* ril_sim_card is expected to perform RIL_REQUEST_GET_SIM_STATUS
|
||||
* asynchronously and report back when request has completed: */
|
||||
GASSERT(!slot->sim_card->status);
|
||||
GASSERT(!slot->received_sim_status);
|
||||
|
||||
GASSERT(!slot->network);
|
||||
slot->network = ril_network_new(slot->io, log_prefix, slot->radio,
|
||||
@@ -1066,7 +1194,7 @@ static struct ril_slot *ril_plugin_slot_new(const char *sockpath,
|
||||
slot->path = g_strdup(path);
|
||||
slot->name = g_strdup(name);
|
||||
slot->config.slot = slot_index;
|
||||
slot->config.enable_4g = RILMODEM_DEFAULT_4G;
|
||||
slot->config.techs = RILMODEM_DEFAULT_TECHS;
|
||||
slot->config.empty_pin_query = RILMODEM_DEFAULT_EMPTY_PIN_QUERY;
|
||||
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
|
||||
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
|
||||
@@ -1076,6 +1204,7 @@ static struct ril_slot *ril_plugin_slot_new(const char *sockpath,
|
||||
RILMODEM_DEFAULT_DATA_CALL_RETRY_LIMIT;
|
||||
slot->data_opt.data_call_retry_delay_ms =
|
||||
RILMODEM_DEFAULT_DATA_CALL_RETRY_DELAY;
|
||||
slot->pub.errors = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
return slot;
|
||||
}
|
||||
|
||||
@@ -1115,7 +1244,8 @@ static struct ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
|
||||
char *sock = g_key_file_get_string(file, group, RILCONF_SOCKET, NULL);
|
||||
if (sock) {
|
||||
int value;
|
||||
char* strval;
|
||||
char *strval;
|
||||
char **strv;
|
||||
char *sub = ril_config_get_string(file, group, RILCONF_SUB);
|
||||
|
||||
slot = ril_plugin_slot_new(NULL, NULL, NULL,
|
||||
@@ -1143,9 +1273,52 @@ static struct ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
|
||||
DBG("%s: timeout %d", group, slot->timeout);
|
||||
}
|
||||
|
||||
ril_config_get_boolean(file, group, RILCONF_4G,
|
||||
&slot->config.enable_4g);
|
||||
DBG("%s: 4G %s", group, slot->config.enable_4g ? "on" : "off");
|
||||
strv = ril_config_get_strings(file, group, RILCONF_TECHS, ',');
|
||||
if (strv) {
|
||||
char **p;
|
||||
|
||||
slot->config.techs = 0;
|
||||
for (p = strv; *p; p++) {
|
||||
const char *s = *p;
|
||||
enum ofono_radio_access_mode m;
|
||||
|
||||
if (!s[0]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(s, "all")) {
|
||||
slot->config.techs =
|
||||
OFONO_RADIO_ACCESS_MODE_ALL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ofono_radio_access_mode_from_string(s,
|
||||
&m)) {
|
||||
ofono_warn("Unknown technology %s "
|
||||
"in [%s] section of %s", s,
|
||||
group, RILMODEM_CONF_FILE);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m == OFONO_RADIO_ACCESS_MODE_ANY) {
|
||||
slot->config.techs =
|
||||
OFONO_RADIO_ACCESS_MODE_ALL;
|
||||
break;
|
||||
}
|
||||
|
||||
slot->config.techs |= m;
|
||||
}
|
||||
g_strfreev(strv);
|
||||
}
|
||||
|
||||
/* "enable4G" is deprecated */
|
||||
value = slot->config.techs;
|
||||
if (ril_config_get_flag(file, group, RILCONF_4G,
|
||||
OFONO_RADIO_ACCESS_MODE_LTE, &value)) {
|
||||
slot->config.techs = value;
|
||||
}
|
||||
|
||||
DBG("%s: technologies 0x%02x", group, slot->config.techs);
|
||||
|
||||
if (ril_config_get_boolean(file, group, RILCONF_EMPTY_PIN_QUERY,
|
||||
&slot->config.empty_pin_query)) {
|
||||
@@ -1236,6 +1409,27 @@ static struct ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
|
||||
g_free(slot->ecclist_file);
|
||||
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 {
|
||||
DBG("no socket path in %s", group);
|
||||
}
|
||||
@@ -1248,8 +1442,12 @@ static void ril_plugin_delete_slot(struct ril_slot *slot)
|
||||
ril_plugin_shutdown_slot(slot, TRUE);
|
||||
ril_sim_info_unref(slot->sim_info);
|
||||
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->imei);
|
||||
g_free(slot->imeisv);
|
||||
g_free(slot->name);
|
||||
g_free(slot->sockpath);
|
||||
g_free(slot->sub);
|
||||
@@ -1403,7 +1601,7 @@ static void ril_plugin_switch_user()
|
||||
static void ril_plugin_update_enabled_slot(struct ril_slot *slot)
|
||||
{
|
||||
if (slot->pub.enabled) {
|
||||
DBG("%s enabled", slot->path + 1);
|
||||
DBG("%s enabled", ril_slot_debug_prefix(slot));
|
||||
ril_plugin_check_modem(slot);
|
||||
}
|
||||
}
|
||||
@@ -1411,7 +1609,7 @@ static void ril_plugin_update_enabled_slot(struct ril_slot *slot)
|
||||
static void ril_plugin_update_disabled_slot(struct ril_slot *slot)
|
||||
{
|
||||
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_update_modem_paths_full(slot->plugin);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -48,10 +48,12 @@ typedef struct ril_slot_info const *ril_slot_info_ptr;
|
||||
struct ril_slot_info {
|
||||
const char *path;
|
||||
const char *imei;
|
||||
const char *imeisv;
|
||||
const char *ecclist_file;
|
||||
gboolean enabled;
|
||||
gboolean sim_present;
|
||||
const struct ril_slot_config *config;
|
||||
GHashTable *errors;
|
||||
};
|
||||
|
||||
struct ril_plugin {
|
||||
@@ -68,6 +70,7 @@ struct ril_plugin {
|
||||
struct ril_modem {
|
||||
GRilIoChannel *io;
|
||||
const char *imei;
|
||||
const char *imeisv;
|
||||
const char *log_prefix;
|
||||
const char *ecclist_file;
|
||||
struct ofono_modem *ofono;
|
||||
@@ -123,6 +126,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_sim(struct ril_plugin_dbus *dbus, int index,
|
||||
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,
|
||||
const struct ril_slot_info *slot, struct ril_radio *radio,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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
|
||||
* 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_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_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_MODEM_CHANGED "MmsModemChanged"
|
||||
#define RIL_DBUS_SIGNAL_READY_CHANGED "ReadyChanged"
|
||||
#define RIL_DBUS_SIGNAL_MODEM_ERROR "ModemError"
|
||||
#define RIL_DBUS_IMSI_AUTO "auto"
|
||||
|
||||
#define RIL_DBUS_ERROR_SIGNATURE "si"
|
||||
|
||||
static gboolean ril_plugin_dbus_enabled(const struct ril_slot_info *slot)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
@@ -410,6 +475,13 @@ static DBusMessage *ril_plugin_dbus_get_all5(DBusConnection *conn,
|
||||
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,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
@@ -554,6 +626,13 @@ static DBusMessage *ril_plugin_dbus_get_ready(DBusConnection *conn,
|
||||
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,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
@@ -697,28 +776,44 @@ static DBusMessage *ril_plugin_dbus_set_mms_sim(DBusConnection *conn,
|
||||
* 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 \
|
||||
{"version", "i" }, \
|
||||
{"availableModems", "ao" }, \
|
||||
{"enabledModems", "ao" }, \
|
||||
{"defaultDataSim", "s" }, \
|
||||
{"defaultVoiceSim", "s" }, \
|
||||
{"defaultDataModem", "s" }, \
|
||||
{"defaultVoiceModem" , "s"}
|
||||
RIL_DBUS_VERSION_ARG, \
|
||||
RIL_DBUS_AVAILABLE_MODEMS_ARG, \
|
||||
RIL_DBUS_ENABLED_MODEMS_ARG, \
|
||||
RIL_DBUS_DEFAULT_DATA_SIM_ARG, \
|
||||
RIL_DBUS_DEFAULT_VOICE_SIM_ARG, \
|
||||
RIL_DBUS_DEFAULT_DATA_MODEM_ARG, \
|
||||
RIL_DBUS_DEFAULT_VOICE_MODEM_ARG
|
||||
#define RIL_DBUS_GET_ALL2_ARGS \
|
||||
RIL_DBUS_GET_ALL_ARGS, \
|
||||
{"presentSims" , "ab"}
|
||||
RIL_DBUS_PRESENT_SIMS_ARG
|
||||
#define RIL_DBUS_GET_ALL3_ARGS \
|
||||
RIL_DBUS_GET_ALL2_ARGS, \
|
||||
{"imei" , "as"}
|
||||
RIL_DBUS_IMEI_ARG
|
||||
#define RIL_DBUS_GET_ALL4_ARGS \
|
||||
RIL_DBUS_GET_ALL3_ARGS, \
|
||||
{"mmsSim", "s" }, \
|
||||
{"mmsModem" , "s"}
|
||||
RIL_DBUS_MMS_SIM_ARG, \
|
||||
RIL_DBUS_MMS_MODEM_ARG
|
||||
#define RIL_DBUS_GET_ALL5_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[] = {
|
||||
{ GDBUS_METHOD("GetAll",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL_ARGS),
|
||||
@@ -735,42 +830,48 @@ static const GDBusMethodTable ril_plugin_dbus_methods[] = {
|
||||
{ GDBUS_ASYNC_METHOD("GetAll5",
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL5_ARGS),
|
||||
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",
|
||||
NULL, GDBUS_ARGS({ "version", "i" }),
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_VERSION_ARG),
|
||||
ril_plugin_dbus_get_interface_version) },
|
||||
{ GDBUS_METHOD("GetAvailableModems",
|
||||
NULL, GDBUS_ARGS({ "modems", "ao" }),
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_AVAILABLE_MODEMS_ARG),
|
||||
ril_plugin_dbus_get_available_modems) },
|
||||
{ GDBUS_METHOD("GetEnabledModems",
|
||||
NULL, GDBUS_ARGS({ "modems", "ao" }),
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_ENABLED_MODEMS_ARG),
|
||||
ril_plugin_dbus_get_enabled_modems) },
|
||||
{ GDBUS_METHOD("GetPresentSims",
|
||||
NULL, GDBUS_ARGS({ "presentSims", "ab" }),
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_PRESENT_SIMS_ARG),
|
||||
ril_plugin_dbus_get_present_sims) },
|
||||
{ GDBUS_ASYNC_METHOD("GetIMEI",
|
||||
NULL, GDBUS_ARGS({ "imei", "as" }),
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_IMEI_ARG),
|
||||
ril_plugin_dbus_get_imei) },
|
||||
{ GDBUS_METHOD("GetDefaultDataSim",
|
||||
NULL, GDBUS_ARGS({ "imsi", "s" }),
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_DEFAULT_DATA_SIM_ARG),
|
||||
ril_plugin_dbus_get_default_data_sim) },
|
||||
{ GDBUS_METHOD("GetDefaultVoiceSim",
|
||||
NULL, GDBUS_ARGS({ "imsi", "s" }),
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_DEFAULT_VOICE_SIM_ARG),
|
||||
ril_plugin_dbus_get_default_voice_sim) },
|
||||
{ GDBUS_METHOD("GetMmsSim",
|
||||
NULL, GDBUS_ARGS({ "imsi", "s" }),
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_MMS_SIM_ARG),
|
||||
ril_plugin_dbus_get_mms_sim) },
|
||||
{ GDBUS_METHOD("GetDefaultDataModem",
|
||||
NULL, GDBUS_ARGS({ "path", "s" }),
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_DEFAULT_DATA_MODEM_ARG),
|
||||
ril_plugin_dbus_get_default_data_modem) },
|
||||
{ GDBUS_METHOD("GetDefaultVoiceModem",
|
||||
NULL, GDBUS_ARGS({ "path", "s" }),
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_DEFAULT_VOICE_MODEM_ARG),
|
||||
ril_plugin_dbus_get_default_voice_modem) },
|
||||
{ GDBUS_METHOD("GetMmsModem",
|
||||
NULL, GDBUS_ARGS({ "path", "s" }),
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_MMS_MODEM_ARG),
|
||||
ril_plugin_dbus_get_mms_modem) },
|
||||
{ GDBUS_METHOD("GetReady",
|
||||
NULL, GDBUS_ARGS({ "ready", "b" }),
|
||||
NULL, GDBUS_ARGS(RIL_DBUS_READY_ARG),
|
||||
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_ARGS({ "modems", "ao" }), NULL,
|
||||
ril_plugin_dbus_set_enabled_modems) },
|
||||
@@ -788,24 +889,28 @@ static const GDBusMethodTable ril_plugin_dbus_methods[] = {
|
||||
|
||||
static const GDBusSignalTable ril_plugin_dbus_signals[] = {
|
||||
{ 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_ARGS({"index", "i" },
|
||||
{"present" , "b"})) },
|
||||
{ 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_ARGS({ "imsi", "s" })) },
|
||||
GDBUS_ARGS(RIL_DBUS_DEFAULT_VOICE_SIM_ARG)) },
|
||||
{ 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_ARGS({ "path", "s" })) },
|
||||
GDBUS_ARGS(RIL_DBUS_DEFAULT_VOICE_MODEM_ARG)) },
|
||||
{ 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_ARGS({ "path", "s" })) },
|
||||
GDBUS_ARGS(RIL_DBUS_MMS_MODEM_ARG)) },
|
||||
{ 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"})) },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -113,15 +113,11 @@ static gboolean ril_radio_settings_query_available_rats_cb(gpointer data)
|
||||
struct ofono_error error;
|
||||
struct ril_radio_settings_cbd *cbd = data;
|
||||
struct ril_radio_settings *rsd = cbd->rsd;
|
||||
guint rats = OFONO_RADIO_ACCESS_MODE_GSM | OFONO_RADIO_ACCESS_MODE_UMTS;
|
||||
|
||||
if (cbd->rsd->settings->enable_4g) {
|
||||
rats |= OFONO_RADIO_ACCESS_MODE_LTE;
|
||||
}
|
||||
|
||||
GASSERT(cbd->rsd->source_id);
|
||||
GASSERT(rsd->source_id);
|
||||
rsd->source_id = 0;
|
||||
cbd->cb.available_rats(ril_error_ok(&error), rats, cbd->data);
|
||||
cbd->cb.available_rats(ril_error_ok(&error), rsd->settings->techs,
|
||||
cbd->data);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
@@ -132,8 +128,8 @@ static void ril_radio_settings_query_available_rats(
|
||||
struct ril_radio_settings *rsd = ril_radio_settings_get_data(rs);
|
||||
|
||||
DBG_(rsd, "");
|
||||
ril_radio_settings_later(rsd, ril_radio_settings_query_available_rats_cb,
|
||||
cb, data);
|
||||
ril_radio_settings_later(rsd,
|
||||
ril_radio_settings_query_available_rats_cb, cb, data);
|
||||
}
|
||||
|
||||
static gboolean ril_radio_settings_register(gpointer user_data)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -65,6 +65,13 @@
|
||||
*
|
||||
* The same applies to the app_type.
|
||||
*/
|
||||
|
||||
enum ril_sim_card_event {
|
||||
SIM_CARD_STATUS_EVENT,
|
||||
SIM_CARD_APP_EVENT,
|
||||
SIM_CARD_EVENT_COUNT
|
||||
};
|
||||
|
||||
struct ril_sim {
|
||||
GRilIoChannel *io;
|
||||
GRilIoQueue *q;
|
||||
@@ -76,7 +83,8 @@ struct ril_sim {
|
||||
gboolean empty_pin_query_allowed;
|
||||
gboolean inserted;
|
||||
guint idle_id;
|
||||
gulong card_status_id;
|
||||
gulong card_event_id[SIM_CARD_EVENT_COUNT];
|
||||
guint query_pin_retries_id;
|
||||
|
||||
const char *log_prefix;
|
||||
char *allocated_log_prefix;
|
||||
@@ -85,6 +93,7 @@ struct ril_sim {
|
||||
ofono_sim_passwd_cb_t query_passwd_state_cb;
|
||||
void *query_passwd_state_cb_data;
|
||||
guint query_passwd_state_timeout_id;
|
||||
gulong query_passwd_state_sim_status_refresh_id;
|
||||
};
|
||||
|
||||
struct ril_sim_io_response {
|
||||
@@ -100,7 +109,6 @@ struct ril_sim_cbd {
|
||||
ofono_sim_read_cb_t read;
|
||||
ofono_sim_write_cb_t write;
|
||||
ofono_sim_imsi_cb_t imsi;
|
||||
ofono_sim_pin_retries_cb_t retries;
|
||||
ofono_query_facility_lock_cb_t query_facility_lock;
|
||||
gpointer ptr;
|
||||
} cb;
|
||||
@@ -119,6 +127,49 @@ struct ril_sim_pin_cbd {
|
||||
gulong card_status_id;
|
||||
};
|
||||
|
||||
struct ril_sim_retry_query_cbd {
|
||||
struct ril_sim *sd;
|
||||
ofono_sim_pin_retries_cb_t cb;
|
||||
void *data;
|
||||
guint query_index;
|
||||
};
|
||||
|
||||
struct ril_sim_retry_query {
|
||||
const char *name;
|
||||
enum ofono_sim_password_type passwd_type;
|
||||
guint req_code;
|
||||
GRilIoRequest *(*new_req)(struct ril_sim *sd);
|
||||
};
|
||||
|
||||
static GRilIoRequest *ril_sim_empty_sim_pin_req(struct ril_sim *sd);
|
||||
static GRilIoRequest *ril_sim_empty_sim_puk_req(struct ril_sim *sd);
|
||||
static void ril_sim_query_retry_count_cb(GRilIoChannel *io, int status,
|
||||
const void *data, guint len, void *user_data);
|
||||
|
||||
static const struct ril_sim_retry_query ril_sim_retry_query_types[] = {
|
||||
{
|
||||
"pin",
|
||||
OFONO_SIM_PASSWORD_SIM_PIN,
|
||||
RIL_REQUEST_ENTER_SIM_PIN,
|
||||
ril_sim_empty_sim_pin_req
|
||||
},{
|
||||
"pin2",
|
||||
OFONO_SIM_PASSWORD_SIM_PIN2,
|
||||
RIL_REQUEST_ENTER_SIM_PIN2,
|
||||
ril_sim_empty_sim_pin_req
|
||||
},{
|
||||
"puk",
|
||||
OFONO_SIM_PASSWORD_SIM_PUK,
|
||||
RIL_REQUEST_ENTER_SIM_PUK,
|
||||
ril_sim_empty_sim_puk_req
|
||||
},{
|
||||
"puk2",
|
||||
OFONO_SIM_PASSWORD_SIM_PUK2,
|
||||
RIL_REQUEST_ENTER_SIM_PUK2,
|
||||
ril_sim_empty_sim_puk_req
|
||||
}
|
||||
};
|
||||
|
||||
#define DBG_(sd,fmt,args...) DBG("%s" fmt, (sd)->log_prefix, ##args)
|
||||
|
||||
#define ril_sim_cbd_free g_free
|
||||
@@ -691,6 +742,12 @@ static void ril_sim_finish_passwd_state_query(struct ril_sim *sd,
|
||||
sd->query_passwd_state_timeout_id = 0;
|
||||
}
|
||||
|
||||
if (sd->query_passwd_state_sim_status_refresh_id) {
|
||||
ril_sim_card_remove_handler(sd->card,
|
||||
sd->query_passwd_state_sim_status_refresh_id);
|
||||
sd->query_passwd_state_sim_status_refresh_id = 0;
|
||||
}
|
||||
|
||||
if (sd->query_passwd_state_cb) {
|
||||
ofono_sim_passwd_cb_t cb = sd->query_passwd_state_cb;
|
||||
void *data = sd->query_passwd_state_cb_data;
|
||||
@@ -709,6 +766,34 @@ static void ril_sim_finish_passwd_state_query(struct ril_sim *sd,
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_sim_check_perm_lock(struct ril_sim *sd)
|
||||
{
|
||||
struct ril_sim_card *sc = sd->card;
|
||||
|
||||
/*
|
||||
* Zero number of retries in the PUK state indicates to the ofono
|
||||
* client that the card is permanently locked. This is different
|
||||
* from the case when the number of retries is negative (which
|
||||
* means that PUK is required but the number of remaining attempts
|
||||
* is not available).
|
||||
*/
|
||||
if (sc->app && sc->app->app_state == RIL_APPSTATE_PUK &&
|
||||
sc->app->pin1_state == RIL_PINSTATE_ENABLED_PERM_BLOCKED) {
|
||||
|
||||
/*
|
||||
* It makes no sense for RIL to return non-zero number of
|
||||
* remaining attempts in PERM_LOCKED state. So when we get
|
||||
* here, the number of retries has to be negative (unknown)
|
||||
* or zero. Otherwise, something must be broken.
|
||||
*/
|
||||
GASSERT(sd->retries[OFONO_SIM_PASSWORD_SIM_PUK] <= 0);
|
||||
if (sd->retries[OFONO_SIM_PASSWORD_SIM_PUK] < 0) {
|
||||
sd->retries[OFONO_SIM_PASSWORD_SIM_PUK] = 0;
|
||||
DBG_(sd, "SIM card is locked");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_sim_invalidate_passwd_state(struct ril_sim *sd)
|
||||
{
|
||||
guint i;
|
||||
@@ -718,10 +803,16 @@ static void ril_sim_invalidate_passwd_state(struct ril_sim *sd)
|
||||
sd->retries[i] = -1;
|
||||
}
|
||||
|
||||
ril_sim_check_perm_lock(sd);
|
||||
ril_sim_finish_passwd_state_query(sd, OFONO_SIM_PASSWORD_INVALID);
|
||||
}
|
||||
|
||||
static void ril_sim_status_cb(struct ril_sim_card *sc, void *user_data)
|
||||
static void ril_sim_app_changed_cb(struct ril_sim_card *sc, void *user_data)
|
||||
{
|
||||
ril_sim_check_perm_lock((struct ril_sim *)user_data);
|
||||
}
|
||||
|
||||
static void ril_sim_status_changed_cb(struct ril_sim_card *sc, void *user_data)
|
||||
{
|
||||
struct ril_sim *sd = user_data;
|
||||
|
||||
@@ -730,6 +821,7 @@ static void ril_sim_status_cb(struct ril_sim_card *sc, void *user_data)
|
||||
if (sc->app) {
|
||||
enum ofono_sim_password_type ps;
|
||||
|
||||
ril_sim_check_perm_lock(sd);
|
||||
if (!sd->inserted) {
|
||||
sd->inserted = TRUE;
|
||||
ofono_info("SIM card OK");
|
||||
@@ -764,13 +856,29 @@ static int ril_sim_parse_retry_count(const void *data, guint len)
|
||||
return retry_count;
|
||||
}
|
||||
|
||||
static GRilIoRequest *ril_sim_enter_sim_req(struct ril_sim *sd, const char *pw)
|
||||
static GRilIoRequest *ril_sim_enter_sim_pin_req(struct ril_sim *sd,
|
||||
const char *pin)
|
||||
{
|
||||
const char *app_id = ril_sim_app_id(sd);
|
||||
if (app_id) {
|
||||
GRilIoRequest *req = grilio_request_new();
|
||||
grilio_request_append_int32(req, ENTER_SIM_PIN_PARAMS);
|
||||
grilio_request_append_utf8(req, pw);
|
||||
grilio_request_append_utf8(req, pin);
|
||||
grilio_request_append_utf8(req, app_id);
|
||||
return req;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GRilIoRequest *ril_sim_enter_sim_puk_req(struct ril_sim *sd,
|
||||
const char *puk, const char *pin)
|
||||
{
|
||||
const char *app_id = ril_sim_app_id(sd);
|
||||
if (app_id) {
|
||||
GRilIoRequest *req = grilio_request_new();
|
||||
grilio_request_append_int32(req, ENTER_SIM_PUK_PARAMS);
|
||||
grilio_request_append_utf8(req, puk);
|
||||
grilio_request_append_utf8(req, pin);
|
||||
grilio_request_append_utf8(req, app_id);
|
||||
return req;
|
||||
}
|
||||
@@ -781,63 +889,90 @@ static GRilIoRequest *ril_sim_enter_sim_req(struct ril_sim *sd, const char *pw)
|
||||
* Some RIL implementations allow to query the retry count
|
||||
* by sending the empty pin in any state.
|
||||
*/
|
||||
static void ril_sim_query_pin2_retries_cb(GRilIoChannel *io, int status,
|
||||
const void *data, guint len, void *user_data)
|
||||
|
||||
static GRilIoRequest *ril_sim_empty_sim_pin_req(struct ril_sim *sd)
|
||||
{
|
||||
struct ril_sim_cbd *cbd = user_data;
|
||||
struct ril_sim *sd = cbd->sd;
|
||||
ofono_sim_pin_retries_cb_t cb = cbd->cb.retries;
|
||||
struct ofono_error error;
|
||||
|
||||
if (status == RIL_E_SUCCESS) {
|
||||
const int retry_count = ril_sim_parse_retry_count(data, len);
|
||||
DBG_(sd, "pin2 retry_count=%d", retry_count);
|
||||
sd->retries[OFONO_SIM_PASSWORD_SIM_PIN2] = retry_count;
|
||||
} else {
|
||||
ofono_error("pin2 retry query is not supported");
|
||||
sd->empty_pin_query_allowed = FALSE;
|
||||
}
|
||||
|
||||
cb(ril_error_ok(&error), sd->retries, cbd->data);
|
||||
return ril_sim_enter_sim_pin_req(sd, "");
|
||||
}
|
||||
|
||||
static gboolean ril_sim_query_pin2_retry_count(struct ril_sim *sd,
|
||||
static GRilIoRequest *ril_sim_empty_sim_puk_req(struct ril_sim *sd)
|
||||
{
|
||||
return ril_sim_enter_sim_puk_req(sd, "", "");
|
||||
}
|
||||
|
||||
static struct ril_sim_retry_query_cbd *ril_sim_retry_query_cbd_new(
|
||||
struct ril_sim *sd, guint query_index,
|
||||
ofono_sim_pin_retries_cb_t cb, void *data)
|
||||
{
|
||||
if (sd->empty_pin_query_allowed &&
|
||||
sd->retries[OFONO_SIM_PASSWORD_SIM_PIN2] < 0) {
|
||||
GRilIoRequest *req = ril_sim_enter_sim_req(sd, "");
|
||||
if (req) {
|
||||
DBG_(sd, "querying pin2 retry count...");
|
||||
grilio_queue_send_request_full(sd->q, req,
|
||||
RIL_REQUEST_ENTER_SIM_PIN2,
|
||||
ril_sim_query_pin2_retries_cb,
|
||||
ril_sim_cbd_free,
|
||||
ril_sim_cbd_new(sd, cb, data));
|
||||
grilio_request_unref(req);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
struct ril_sim_retry_query_cbd *cbd =
|
||||
g_new(struct ril_sim_retry_query_cbd, 1);
|
||||
|
||||
cbd->sd = sd;
|
||||
cbd->cb = cb;
|
||||
cbd->data = data;
|
||||
cbd->query_index = query_index;
|
||||
return cbd;
|
||||
}
|
||||
|
||||
static void ril_sim_query_pin_retries_cb(GRilIoChannel *io, int status,
|
||||
static gboolean ril_sim_query_retry_count(struct ril_sim *sd,
|
||||
guint start_index, ofono_sim_pin_retries_cb_t cb, void *data)
|
||||
{
|
||||
guint id = 0;
|
||||
|
||||
if (sd->empty_pin_query_allowed) {
|
||||
guint i = start_index;
|
||||
|
||||
/* Find the first unknown retry count that we can query. */
|
||||
while (i < G_N_ELEMENTS(ril_sim_retry_query_types)) {
|
||||
const struct ril_sim_retry_query *query =
|
||||
ril_sim_retry_query_types + i;
|
||||
|
||||
if (sd->retries[query->passwd_type] < 0) {
|
||||
GRilIoRequest *req = query->new_req(sd);
|
||||
|
||||
if (req) {
|
||||
DBG_(sd, "querying %s retry count...",
|
||||
query->name);
|
||||
id = grilio_queue_send_request_full(
|
||||
sd->q, req, query->req_code,
|
||||
ril_sim_query_retry_count_cb,
|
||||
g_free,
|
||||
ril_sim_retry_query_cbd_new(
|
||||
sd, i, cb, data));
|
||||
grilio_request_unref(req);
|
||||
}
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
static void ril_sim_query_retry_count_cb(GRilIoChannel *io, int status,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ril_sim_cbd *cbd = user_data;
|
||||
struct ril_sim_retry_query_cbd *cbd = user_data;
|
||||
struct ril_sim *sd = cbd->sd;
|
||||
ofono_sim_pin_retries_cb_t cb = cbd->cb.retries;
|
||||
struct ofono_error error;
|
||||
|
||||
GASSERT(sd->query_pin_retries_id);
|
||||
sd->query_pin_retries_id = 0;
|
||||
|
||||
if (status == RIL_E_SUCCESS) {
|
||||
const int retry_count = ril_sim_parse_retry_count(data, len);
|
||||
DBG_(sd, "pin retry_count=%d", retry_count);
|
||||
sd->retries[OFONO_SIM_PASSWORD_SIM_PIN] = retry_count;
|
||||
if (ril_sim_query_pin2_retry_count(sd, cb, cbd->data)) {
|
||||
/*
|
||||
* ril_sim_query_pin2_retries_cb will invoke
|
||||
* the completion callback
|
||||
*/
|
||||
const struct ril_sim_retry_query *query =
|
||||
ril_sim_retry_query_types + cbd->query_index;
|
||||
|
||||
DBG_(sd, "%s retry_count=%d", query->name, retry_count);
|
||||
sd->retries[query->passwd_type] = retry_count;
|
||||
|
||||
/* Submit the next request */
|
||||
if ((sd->query_pin_retries_id =
|
||||
ril_sim_query_retry_count(sd, cbd->query_index + 1,
|
||||
cbd->cb, cbd->data)) != 0) {
|
||||
/* The next request is pending */
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -845,43 +980,32 @@ static void ril_sim_query_pin_retries_cb(GRilIoChannel *io, int status,
|
||||
sd->empty_pin_query_allowed = FALSE;
|
||||
}
|
||||
|
||||
cb(ril_error_ok(&error), sd->retries, cbd->data);
|
||||
}
|
||||
|
||||
static gboolean ril_sim_query_pin_retry_count(struct ril_sim *sd,
|
||||
ofono_sim_pin_retries_cb_t cb, void *data)
|
||||
{
|
||||
if (sd->empty_pin_query_allowed &&
|
||||
sd->retries[OFONO_SIM_PASSWORD_SIM_PIN] < 0) {
|
||||
GRilIoRequest *req = ril_sim_enter_sim_req(sd, "");
|
||||
if (req) {
|
||||
DBG_(sd, "querying pin retry count...");
|
||||
grilio_queue_send_request_full(sd->q, req,
|
||||
RIL_REQUEST_ENTER_SIM_PIN,
|
||||
ril_sim_query_pin_retries_cb,
|
||||
ril_sim_cbd_free,
|
||||
ril_sim_cbd_new(sd, cb, data));
|
||||
grilio_request_unref(req);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
cbd->cb(ril_error_ok(&error), sd->retries, cbd->data);
|
||||
}
|
||||
|
||||
static void ril_sim_query_pin_retries(struct ofono_sim *sim,
|
||||
ofono_sim_pin_retries_cb_t cb, void *data)
|
||||
{
|
||||
struct ofono_error error;
|
||||
struct ril_sim *sd = ril_sim_get_data(sim);
|
||||
|
||||
DBG_(sd, "");
|
||||
if (ril_sim_query_pin_retry_count(sd, cb, data) ||
|
||||
ril_sim_query_pin2_retry_count(sd, cb, data)) {
|
||||
/* Wait for completion of PIN and then PIN2 query */
|
||||
return;
|
||||
}
|
||||
grilio_queue_cancel_request(sd->q, sd->query_pin_retries_id, FALSE);
|
||||
sd->query_pin_retries_id = ril_sim_query_retry_count(sd, 0, cb, data);
|
||||
if (!sd->query_pin_retries_id) {
|
||||
struct ofono_error error;
|
||||
|
||||
cb(ril_error_ok(&error), sd->retries, data);
|
||||
/* Nothing to wait for */
|
||||
cb(ril_error_ok(&error), sd->retries, data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_sim_query_passwd_state_complete_cb(struct ril_sim_card *sc,
|
||||
void *user_data)
|
||||
{
|
||||
struct ril_sim *sd = user_data;
|
||||
|
||||
GASSERT(sd->query_passwd_state_sim_status_refresh_id);
|
||||
ril_sim_finish_passwd_state_query(sd, ril_sim_passwd_state(sd));
|
||||
}
|
||||
|
||||
static gboolean ril_sim_query_passwd_state_timeout_cb(gpointer user_data)
|
||||
@@ -899,29 +1023,41 @@ static void ril_sim_query_passwd_state(struct ofono_sim *sim,
|
||||
ofono_sim_passwd_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_sim *sd = ril_sim_get_data(sim);
|
||||
enum ofono_sim_password_type passwd_state = ril_sim_passwd_state(sd);
|
||||
struct ofono_error error;
|
||||
|
||||
if (sd->query_passwd_state_timeout_id) {
|
||||
g_source_remove(sd->query_passwd_state_timeout_id);
|
||||
sd->query_passwd_state_timeout_id = 0;
|
||||
}
|
||||
|
||||
if (passwd_state != OFONO_SIM_PASSWORD_INVALID) {
|
||||
DBG_(sd, "%d", passwd_state);
|
||||
sd->query_passwd_state_cb = NULL;
|
||||
sd->query_passwd_state_cb_data = NULL;
|
||||
sd->ofono_passwd_state = passwd_state;
|
||||
cb(ril_error_ok(&error), passwd_state, data);
|
||||
if (!sd->query_passwd_state_sim_status_refresh_id) {
|
||||
ril_sim_card_remove_handler(sd->card,
|
||||
sd->query_passwd_state_sim_status_refresh_id);
|
||||
sd->query_passwd_state_sim_status_refresh_id = 0;
|
||||
}
|
||||
|
||||
/* Always request fresh status, just in case. */
|
||||
ril_sim_card_request_status(sd->card);
|
||||
sd->query_passwd_state_cb = cb;
|
||||
sd->query_passwd_state_cb_data = data;
|
||||
|
||||
if (ril_sim_passwd_state(sd) != OFONO_SIM_PASSWORD_INVALID) {
|
||||
/* Just wait for GET_SIM_STATUS completion */
|
||||
DBG_(sd, "waiting for SIM status query to complete");
|
||||
sd->query_passwd_state_sim_status_refresh_id =
|
||||
ril_sim_card_add_status_received_handler(sd->card,
|
||||
ril_sim_query_passwd_state_complete_cb, sd);
|
||||
} else {
|
||||
/* Wait for the state to change */
|
||||
DBG_(sd, "waiting for the SIM state to change");
|
||||
sd->query_passwd_state_cb = cb;
|
||||
sd->query_passwd_state_cb_data = data;
|
||||
sd->query_passwd_state_timeout_id =
|
||||
g_timeout_add_seconds(SIM_STATE_CHANGE_TIMEOUT_SECS,
|
||||
ril_sim_query_passwd_state_timeout_cb, sd);
|
||||
}
|
||||
|
||||
/*
|
||||
* We still need to complete the request somehow, even if
|
||||
* GET_STATUS never completes or SIM status never changes.
|
||||
*/
|
||||
sd->query_passwd_state_timeout_id =
|
||||
g_timeout_add_seconds(SIM_STATE_CHANGE_TIMEOUT_SECS,
|
||||
ril_sim_query_passwd_state_timeout_cb, sd);
|
||||
}
|
||||
|
||||
static gboolean ril_sim_pin_change_state_timeout_cb(gpointer user_data)
|
||||
@@ -971,20 +1107,30 @@ static void ril_sim_pin_change_state_cb(GRilIoChannel *io, int ril_status,
|
||||
struct ril_sim_pin_cbd *cbd = user_data;
|
||||
struct ril_sim *sd = cbd->sd;
|
||||
const int retry_count = ril_sim_parse_retry_count(data, len);
|
||||
enum ofono_sim_password_type type = cbd->passwd_type;
|
||||
|
||||
DBG_(sd, "result=%d passwd_type=%d retry_count=%d",
|
||||
ril_status, cbd->passwd_type, retry_count);
|
||||
|
||||
if (ril_status == RIL_E_SUCCESS && retry_count == 0 &&
|
||||
sd->empty_pin_query_allowed &&
|
||||
(cbd->passwd_type == OFONO_SIM_PASSWORD_SIM_PIN ||
|
||||
cbd->passwd_type == OFONO_SIM_PASSWORD_SIM_PIN2)) {
|
||||
/* Will query it */
|
||||
sd->retries[cbd->passwd_type] = -1;
|
||||
if (ril_status == RIL_E_SUCCESS && retry_count == 0) {
|
||||
enum ofono_sim_password_type associated_pin =
|
||||
__ofono_sim_puk2pin(type);
|
||||
/*
|
||||
* If PIN/PUK request has succeeded, zero retry count
|
||||
* makes no sense, we have to assume that it's unknown.
|
||||
* If it can be queried, it will be queried later. If
|
||||
* it can't be queried it will remain unknown.
|
||||
*/
|
||||
sd->retries[type] = -1;
|
||||
if (associated_pin != OFONO_SIM_PASSWORD_INVALID) {
|
||||
/* Successful PUK requests affect PIN retry count */
|
||||
sd->retries[associated_pin] = -1;
|
||||
}
|
||||
} else {
|
||||
sd->retries[cbd->passwd_type] = retry_count;
|
||||
sd->retries[type] = retry_count;
|
||||
}
|
||||
|
||||
ril_sim_check_perm_lock(sd);
|
||||
cbd->ril_status = ril_status;
|
||||
if (cbd->card_status_id && (!cbd->state_event_count ||
|
||||
ril_sim_app_in_transient_state(sd))) {
|
||||
@@ -1014,6 +1160,13 @@ static void ril_sim_pin_change_state_cb(GRilIoChannel *io, int ril_status,
|
||||
} else {
|
||||
cbd->cb(ril_error_failure(&error), cbd->data);
|
||||
}
|
||||
|
||||
/* To avoid assert in ril_sim_pin_req_done: */
|
||||
if (cbd->card_status_id) {
|
||||
ril_sim_card_remove_handler(cbd->card,
|
||||
cbd->card_status_id);
|
||||
cbd->card_status_id = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1021,18 +1174,21 @@ static void ril_sim_pin_send(struct ofono_sim *sim, const char *passwd,
|
||||
ofono_sim_lock_unlock_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_sim *sd = ril_sim_get_data(sim);
|
||||
GRilIoRequest *req = grilio_request_new();
|
||||
GRilIoRequest *req = ril_sim_enter_sim_pin_req(sd, passwd);
|
||||
|
||||
grilio_request_append_int32(req, ENTER_SIM_PIN_PARAMS);
|
||||
grilio_request_append_utf8(req, passwd);
|
||||
grilio_request_append_utf8(req, ril_sim_app_id(sd));
|
||||
if (req) {
|
||||
DBG_(sd, "%s,aid=%s", passwd, ril_sim_app_id(sd));
|
||||
grilio_queue_send_request_full(sd->q, req,
|
||||
RIL_REQUEST_ENTER_SIM_PIN, ril_sim_pin_change_state_cb,
|
||||
ril_sim_pin_req_done, ril_sim_pin_cbd_new(sd,
|
||||
OFONO_SIM_PASSWORD_SIM_PIN, TRUE, cb, data));
|
||||
grilio_request_unref(req);
|
||||
} else {
|
||||
struct ofono_error error;
|
||||
|
||||
DBG_(sd, "%s,aid=%s", passwd, ril_sim_app_id(sd));
|
||||
grilio_queue_send_request_full(sd->q, req, RIL_REQUEST_ENTER_SIM_PIN,
|
||||
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
|
||||
ril_sim_pin_cbd_new(sd, OFONO_SIM_PASSWORD_SIM_PIN,
|
||||
TRUE, cb, data));
|
||||
grilio_request_unref(req);
|
||||
DBG_(sd, "sorry");
|
||||
cb(ril_error_failure(&error), data);
|
||||
}
|
||||
}
|
||||
|
||||
static guint ril_perso_change_state(struct ofono_sim *sim,
|
||||
@@ -1137,19 +1293,22 @@ static void ril_sim_pin_send_puk(struct ofono_sim *sim,
|
||||
ofono_sim_lock_unlock_cb_t cb, void *data)
|
||||
{
|
||||
struct ril_sim *sd = ril_sim_get_data(sim);
|
||||
GRilIoRequest *req = grilio_request_sized_new(60);
|
||||
GRilIoRequest *req = ril_sim_enter_sim_puk_req(sd, puk, passwd);
|
||||
|
||||
grilio_request_append_int32(req, ENTER_SIM_PUK_PARAMS);
|
||||
grilio_request_append_utf8(req, puk);
|
||||
grilio_request_append_utf8(req, passwd);
|
||||
grilio_request_append_utf8(req, ril_sim_app_id(sd));
|
||||
if (req) {
|
||||
DBG_(sd, "puk=%s,pin=%s,aid=%s", puk, passwd,
|
||||
ril_sim_app_id(sd));
|
||||
grilio_queue_send_request_full(sd->q, req,
|
||||
RIL_REQUEST_ENTER_SIM_PUK, ril_sim_pin_change_state_cb,
|
||||
ril_sim_pin_req_done, ril_sim_pin_cbd_new(sd,
|
||||
OFONO_SIM_PASSWORD_SIM_PUK, TRUE, cb, data));
|
||||
grilio_request_unref(req);
|
||||
} else {
|
||||
struct ofono_error error;
|
||||
|
||||
DBG_(sd, "puk=%s,pin=%s,aid=%s", puk, passwd, ril_sim_app_id(sd));
|
||||
grilio_queue_send_request_full(sd->q, req, RIL_REQUEST_ENTER_SIM_PUK,
|
||||
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
|
||||
ril_sim_pin_cbd_new(sd, OFONO_SIM_PASSWORD_SIM_PUK,
|
||||
TRUE, cb, data));
|
||||
grilio_request_unref(req);
|
||||
DBG_(sd, "sorry");
|
||||
cb(ril_error_failure(&error), data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_sim_change_passwd(struct ofono_sim *sim,
|
||||
@@ -1229,11 +1388,15 @@ static gboolean ril_sim_register(gpointer user)
|
||||
ofono_sim_register(sd->sim);
|
||||
|
||||
/* Register for change notifications */
|
||||
sd->card_status_id = ril_sim_card_add_status_changed_handler(sd->card,
|
||||
ril_sim_status_cb, sd);
|
||||
sd->card_event_id[SIM_CARD_STATUS_EVENT] =
|
||||
ril_sim_card_add_status_changed_handler(sd->card,
|
||||
ril_sim_status_changed_cb, sd);
|
||||
sd->card_event_id[SIM_CARD_APP_EVENT] =
|
||||
ril_sim_card_add_app_changed_handler(sd->card,
|
||||
ril_sim_app_changed_cb, sd);
|
||||
|
||||
/* Check the current state */
|
||||
ril_sim_status_cb(sd->card, sd);
|
||||
ril_sim_status_changed_cb(sd->card, sd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -1280,7 +1443,13 @@ static void ril_sim_remove(struct ofono_sim *sim)
|
||||
g_source_remove(sd->query_passwd_state_timeout_id);
|
||||
}
|
||||
|
||||
ril_sim_card_remove_handler(sd->card, sd->card_status_id);
|
||||
if (sd->query_passwd_state_sim_status_refresh_id) {
|
||||
ril_sim_card_remove_handler(sd->card,
|
||||
sd->query_passwd_state_sim_status_refresh_id);
|
||||
}
|
||||
|
||||
ril_sim_card_remove_handlers(sd->card, sd->card_event_id,
|
||||
G_N_ELEMENTS(sd->card_event_id));
|
||||
ril_sim_card_unref(sd->card);
|
||||
|
||||
grilio_channel_unref(sd->io);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -64,8 +64,6 @@ G_DEFINE_TYPE(RilSimCard, ril_sim_card, G_TYPE_OBJECT)
|
||||
#define RIL_SIMCARD_STATE_CHANGED (0x01)
|
||||
#define RIL_SIMCARD_STATUS_CHANGED (0x02)
|
||||
|
||||
static void ril_sim_card_request_status(struct ril_sim_card *self);
|
||||
|
||||
static gboolean ril_sim_card_app_equal(const struct ril_sim_card_app *a1,
|
||||
const struct ril_sim_card_app *a2)
|
||||
{
|
||||
@@ -338,6 +336,7 @@ static struct ril_sim_card_status *ril_sim_card_status_parse(const void *data,
|
||||
}
|
||||
|
||||
if (i == num_apps) {
|
||||
GASSERT(grilio_parser_at_end(&rilp));
|
||||
return status;
|
||||
} else {
|
||||
ril_sim_card_status_free(status);
|
||||
@@ -365,7 +364,7 @@ static void ril_sim_card_status_cb(GRilIoChannel *io, int ril_status,
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_sim_card_request_status(struct ril_sim_card *self)
|
||||
void ril_sim_card_request_status(struct ril_sim_card *self)
|
||||
{
|
||||
struct ril_sim_card_priv *priv = self->priv;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -55,6 +55,7 @@ typedef void (*ril_sim_card_cb_t)(struct ril_sim_card *sc, void *arg);
|
||||
struct ril_sim_card *ril_sim_card_new(GRilIoChannel *io, guint slot, int flags);
|
||||
struct ril_sim_card *ril_sim_card_ref(struct ril_sim_card *sc);
|
||||
void ril_sim_card_unref(struct ril_sim_card *sc);
|
||||
void ril_sim_card_request_status(struct ril_sim_card *self);
|
||||
gboolean ril_sim_card_ready(struct ril_sim_card *sc);
|
||||
gulong ril_sim_card_add_status_received_handler(struct ril_sim_card *sc,
|
||||
ril_sim_card_cb_t cb, void *arg);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2016 Jolla Ltd.
|
||||
* Copyright (C) 2016-2017 Jolla Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -17,6 +17,8 @@
|
||||
#include "ril_sim_info.h"
|
||||
#include "ril_log.h"
|
||||
|
||||
#include <gutil_misc.h>
|
||||
|
||||
#include <ofono/dbus.h>
|
||||
|
||||
#include <gdbus.h>
|
||||
@@ -32,7 +34,7 @@ enum sim_info_event_id {
|
||||
};
|
||||
|
||||
struct ril_sim_info_dbus {
|
||||
struct ril_modem *md;
|
||||
struct ril_modem *modem;
|
||||
struct ril_sim_info *info;
|
||||
DBusConnection *conn;
|
||||
char *path;
|
||||
@@ -113,35 +115,43 @@ static DBusMessage *ril_sim_info_dbus_get_spn(DBusConnection *conn,
|
||||
return ril_sim_info_dbus_reply_with_string(msg, dbus->info->spn);
|
||||
}
|
||||
|
||||
#define RIL_SIM_INFO_DBUS_VERSION_ARG {"version", "i"}
|
||||
#define RIL_SIM_INFO_DBUS_ICCID_ARG {"iccid", "s"}
|
||||
#define RIL_SIM_INFO_DBUS_IMSI_ARG {"imsi", "s"}
|
||||
#define RIL_SIM_INFO_DBUS_SPN_ARG {"spn" , "s"}
|
||||
|
||||
#define RIL_SIM_INFO_DBUS_GET_ALL_ARGS \
|
||||
RIL_SIM_INFO_DBUS_VERSION_ARG, \
|
||||
RIL_SIM_INFO_DBUS_ICCID_ARG, \
|
||||
RIL_SIM_INFO_DBUS_IMSI_ARG, \
|
||||
RIL_SIM_INFO_DBUS_SPN_ARG
|
||||
|
||||
static const GDBusMethodTable ril_sim_info_dbus_methods[] = {
|
||||
{ GDBUS_METHOD("GetAll",
|
||||
NULL, GDBUS_ARGS({"version", "i" },
|
||||
{"iccid", "s" },
|
||||
{"imsi", "s" },
|
||||
{"spn" , "s"}),
|
||||
NULL, GDBUS_ARGS(RIL_SIM_INFO_DBUS_GET_ALL_ARGS),
|
||||
ril_sim_info_dbus_get_all) },
|
||||
{ GDBUS_METHOD("GetInterfaceVersion",
|
||||
NULL, GDBUS_ARGS({ "version", "i" }),
|
||||
NULL, GDBUS_ARGS(RIL_SIM_INFO_DBUS_VERSION_ARG),
|
||||
ril_sim_info_dbus_get_version) },
|
||||
{ GDBUS_METHOD("GetCardIdentifier",
|
||||
NULL, GDBUS_ARGS({ "iccid", "s" }),
|
||||
NULL, GDBUS_ARGS(RIL_SIM_INFO_DBUS_ICCID_ARG),
|
||||
ril_sim_info_dbus_get_iccid) },
|
||||
{ GDBUS_METHOD("GetSubscriberIdentity",
|
||||
NULL, GDBUS_ARGS({ "imsi", "s" }),
|
||||
NULL, GDBUS_ARGS(RIL_SIM_INFO_DBUS_IMSI_ARG),
|
||||
ril_sim_info_dbus_get_imsi) },
|
||||
{ GDBUS_METHOD("GetServiceProviderName",
|
||||
NULL, GDBUS_ARGS({ "spn", "s" }),
|
||||
NULL, GDBUS_ARGS(RIL_SIM_INFO_DBUS_SPN_ARG),
|
||||
ril_sim_info_dbus_get_spn) },
|
||||
{ }
|
||||
};
|
||||
|
||||
static const GDBusSignalTable ril_sim_info_dbus_signals[] = {
|
||||
{ GDBUS_SIGNAL(RIL_SIM_INFO_DBUS_ICCID_CHANGED_SIGNAL,
|
||||
GDBUS_ARGS({ "iccid", "s" })) },
|
||||
GDBUS_ARGS(RIL_SIM_INFO_DBUS_ICCID_ARG)) },
|
||||
{ GDBUS_SIGNAL(RIL_SIM_INFO_DBUS_IMSI_CHANGED_SIGNAL,
|
||||
GDBUS_ARGS({ "imsi", "s" })) },
|
||||
GDBUS_ARGS(RIL_SIM_INFO_DBUS_IMSI_ARG)) },
|
||||
{ GDBUS_SIGNAL(RIL_SIM_INFO_DBUS_SPN_CHANGED_SIGNAL,
|
||||
GDBUS_ARGS({ "spn", "s" })) },
|
||||
GDBUS_ARGS(RIL_SIM_INFO_DBUS_SPN_ARG)) },
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -156,23 +166,20 @@ static void ril_sim_info_dbus_emit(struct ril_sim_info_dbus *dbus,
|
||||
|
||||
static void ril_sim_info_dbus_iccid_cb(struct ril_sim_info *info, void *arg)
|
||||
{
|
||||
struct ril_sim_info_dbus *dbus = arg;
|
||||
ril_sim_info_dbus_emit(dbus, RIL_SIM_INFO_DBUS_ICCID_CHANGED_SIGNAL,
|
||||
info->iccid);
|
||||
ril_sim_info_dbus_emit((struct ril_sim_info_dbus *)arg,
|
||||
RIL_SIM_INFO_DBUS_ICCID_CHANGED_SIGNAL, info->iccid);
|
||||
}
|
||||
|
||||
static void ril_sim_info_dbus_imsi_cb(struct ril_sim_info *info, void *arg)
|
||||
{
|
||||
struct ril_sim_info_dbus *dbus = arg;
|
||||
ril_sim_info_dbus_emit(dbus, RIL_SIM_INFO_DBUS_IMSI_CHANGED_SIGNAL,
|
||||
info->imsi);
|
||||
ril_sim_info_dbus_emit((struct ril_sim_info_dbus *)arg,
|
||||
RIL_SIM_INFO_DBUS_IMSI_CHANGED_SIGNAL, info->imsi);
|
||||
}
|
||||
|
||||
static void ril_sim_info_dbus_spn_cb(struct ril_sim_info *info, void *arg)
|
||||
{
|
||||
struct ril_sim_info_dbus *dbus = arg;
|
||||
ril_sim_info_dbus_emit(dbus, RIL_SIM_INFO_DBUS_SPN_CHANGED_SIGNAL,
|
||||
info->spn);
|
||||
ril_sim_info_dbus_emit((struct ril_sim_info_dbus *)arg,
|
||||
RIL_SIM_INFO_DBUS_SPN_CHANGED_SIGNAL, info->spn);
|
||||
}
|
||||
|
||||
struct ril_sim_info_dbus *ril_sim_info_dbus_new(struct ril_modem *md,
|
||||
@@ -181,7 +188,7 @@ struct ril_sim_info_dbus *ril_sim_info_dbus_new(struct ril_modem *md,
|
||||
struct ril_sim_info_dbus *dbus = g_new0(struct ril_sim_info_dbus, 1);
|
||||
|
||||
DBG("%s", ril_modem_get_path(md));
|
||||
dbus->md = md;
|
||||
dbus->modem = md;
|
||||
dbus->path = g_strdup(ril_modem_get_path(md));
|
||||
dbus->info = ril_sim_info_ref(info);
|
||||
dbus->conn = dbus_connection_ref(ofono_dbus_get_connection());
|
||||
@@ -205,7 +212,7 @@ struct ril_sim_info_dbus *ril_sim_info_dbus_new(struct ril_modem *md,
|
||||
|
||||
return dbus;
|
||||
} else {
|
||||
ofono_error("CellInfo D-Bus register failed");
|
||||
ofono_error("SimInfo D-Bus register failed");
|
||||
ril_sim_info_dbus_free(dbus);
|
||||
return NULL;
|
||||
}
|
||||
@@ -214,19 +221,15 @@ struct ril_sim_info_dbus *ril_sim_info_dbus_new(struct ril_modem *md,
|
||||
void ril_sim_info_dbus_free(struct ril_sim_info_dbus *dbus)
|
||||
{
|
||||
if (dbus) {
|
||||
unsigned int i;
|
||||
|
||||
DBG("%s", dbus->path);
|
||||
g_dbus_unregister_interface(dbus->conn, dbus->path,
|
||||
RIL_SIM_INFO_DBUS_INTERFACE);
|
||||
ofono_modem_remove_interface(dbus->md->ofono,
|
||||
ofono_modem_remove_interface(dbus->modem->ofono,
|
||||
RIL_SIM_INFO_DBUS_INTERFACE);
|
||||
dbus_connection_unref(dbus->conn);
|
||||
|
||||
for (i=0; i<G_N_ELEMENTS(dbus->handler_id); i++) {
|
||||
ril_sim_info_remove_handler(dbus->info,
|
||||
dbus->handler_id[i]);
|
||||
}
|
||||
gutil_disconnect_handlers(dbus->info, dbus->handler_id,
|
||||
G_N_ELEMENTS(dbus->handler_id));
|
||||
ril_sim_info_unref(dbus->info);
|
||||
|
||||
g_free(dbus->path);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2016 Jolla Ltd.
|
||||
* Copyright (C) 2016-2017 Jolla Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -26,8 +26,12 @@
|
||||
#define RIL_SIM_STORE_GROUP "Settings"
|
||||
#define RIL_SIM_STORE_PREF_MODE "TechnologyPreference"
|
||||
|
||||
#define RIL_SIM_STORE_PREF_MODE_DEFAULT(self) ((self)->enable_4g ? \
|
||||
OFONO_RADIO_ACCESS_MODE_LTE : OFONO_RADIO_ACCESS_MODE_UMTS)
|
||||
#define RIL_SIM_STORE_PREF_MODE_DEFAULT(self) (\
|
||||
((self)->techs & OFONO_RADIO_ACCESS_MODE_LTE) ? \
|
||||
OFONO_RADIO_ACCESS_MODE_LTE : \
|
||||
((self)->techs & OFONO_RADIO_ACCESS_MODE_UMTS) ? \
|
||||
OFONO_RADIO_ACCESS_MODE_UMTS : \
|
||||
OFONO_RADIO_ACCESS_MODE_GSM)
|
||||
|
||||
typedef GObjectClass RilSimSettingsClass;
|
||||
typedef struct ril_sim_settings RilSimSettings;
|
||||
@@ -84,8 +88,7 @@ static void ril_sim_settings_reload(struct ril_sim_settings *self)
|
||||
mode_str = g_key_file_get_string(priv->storage,
|
||||
RIL_SIM_STORE_GROUP, RIL_SIM_STORE_PREF_MODE, NULL);
|
||||
if (ofono_radio_access_mode_from_string(mode_str, &mode)) {
|
||||
if (!self->enable_4g &&
|
||||
mode == OFONO_RADIO_ACCESS_MODE_LTE) {
|
||||
if (!(self->techs & mode)) {
|
||||
mode = OFONO_RADIO_ACCESS_MODE_ANY;
|
||||
}
|
||||
} else {
|
||||
@@ -263,7 +266,7 @@ void ril_sim_settings_remove_handlers(struct ril_sim_settings *self,
|
||||
struct ril_sim_settings *ril_sim_settings_new(const struct ril_slot_config *sc)
|
||||
{
|
||||
struct ril_sim_settings *self = g_object_new(RIL_SIM_SETTINGS_TYPE, 0);
|
||||
self->enable_4g = sc->enable_4g;
|
||||
self->techs = sc->techs;
|
||||
self->slot = sc->slot;
|
||||
self->pref_mode = RIL_SIM_STORE_PREF_MODE_DEFAULT(self);
|
||||
return self;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2016 Jolla Ltd.
|
||||
* Copyright (C) 2016-2017 Jolla Ltd.
|
||||
*
|
||||
* 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
|
||||
@@ -18,16 +18,14 @@
|
||||
|
||||
#include "ril_types.h"
|
||||
|
||||
#include <ofono/radio-settings.h>
|
||||
|
||||
struct ril_sim_settings_priv;
|
||||
|
||||
struct ril_sim_settings {
|
||||
GObject object;
|
||||
struct ril_sim_settings_priv *priv;
|
||||
gboolean enable_4g;
|
||||
guint slot;
|
||||
const char *imsi;
|
||||
enum ofono_radio_access_mode techs;
|
||||
enum ofono_radio_access_mode pref_mode;
|
||||
};
|
||||
|
||||
|
||||
@@ -67,9 +67,15 @@ socket=/dev/socket/rild
|
||||
#
|
||||
#timeout=0
|
||||
|
||||
# Setting this one to false would disable 4G technology selection.
|
||||
# Comma-separated list of radio technologies supported by the modem.
|
||||
# Valid technologies are "gsm", "umts" and "lte". The special value
|
||||
# "all" means that all technologies are supported.
|
||||
#
|
||||
# By default 4G is enabled
|
||||
# The default is all
|
||||
#
|
||||
#technologies=all
|
||||
|
||||
# This one is deprecated, use the technologies entry instead (above).
|
||||
#
|
||||
#enable4G=true
|
||||
|
||||
@@ -142,3 +148,12 @@ socket=/dev/socket/rild
|
||||
# Default is 200 ms
|
||||
#
|
||||
#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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -23,11 +23,12 @@
|
||||
#include <grilio_types.h>
|
||||
#include <gutil_macros.h>
|
||||
|
||||
#include <ofono/types.h>
|
||||
|
||||
struct ofono_modem;
|
||||
struct ofono_sim;
|
||||
|
||||
#include <ofono/types.h>
|
||||
#include <ofono/radio-settings.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
@@ -51,8 +52,10 @@ struct ril_cell_info;
|
||||
|
||||
struct ril_slot_config {
|
||||
guint slot;
|
||||
gboolean enable_4g;
|
||||
enum ofono_radio_access_mode techs;
|
||||
gboolean empty_pin_query;
|
||||
GUtilInts *local_hangup_reasons;
|
||||
GUtilInts *remote_hangup_reasons;
|
||||
};
|
||||
|
||||
#endif /* RIL_TYPES_H */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <gutil_ints.h>
|
||||
#include <gutil_ring.h>
|
||||
|
||||
#define FLAG_NEED_CLIP 1
|
||||
@@ -43,7 +44,9 @@ struct ril_voicecall {
|
||||
ofono_voicecall_cb_t cb;
|
||||
void *data;
|
||||
guint timer_id;
|
||||
GUtilRing* dtmf_queue;
|
||||
GUtilRing *dtmf_queue;
|
||||
GUtilInts *local_hangup_reasons;
|
||||
GUtilInts *remote_hangup_reasons;
|
||||
guint send_dtmf_id;
|
||||
guint clcc_poll_id;
|
||||
gulong event_id[VOICECALL_EVENT_COUNT];
|
||||
@@ -60,28 +63,13 @@ struct ril_voicecall_change_state_req {
|
||||
};
|
||||
|
||||
struct lastcause_req {
|
||||
struct ofono_voicecall *vc;
|
||||
struct ril_voicecall *vd;
|
||||
int id;
|
||||
};
|
||||
|
||||
static void ril_voicecall_send_one_dtmf(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(
|
||||
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 */
|
||||
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 voicecall *v;
|
||||
struct ofono_call *call = ofono_voicecall_find_call(vc, id);
|
||||
|
||||
GASSERT(vc);
|
||||
return call ? call->status : -1;
|
||||
}
|
||||
|
||||
for (l = vc->call_list; l; l = l->next) {
|
||||
v = l->data;
|
||||
if (v->call->id == id) {
|
||||
return v->call->status;
|
||||
/* Tries to parse the payload as a uint followed by a string */
|
||||
static int ril_voicecall_parse_lastcause_1(const void *data, guint len)
|
||||
{
|
||||
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,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct lastcause_req *reqdata = user_data;
|
||||
struct ofono_voicecall *vc = reqdata->vc;
|
||||
int tmp;
|
||||
struct ril_voicecall *vd = reqdata->vd;
|
||||
struct ofono_voicecall *vc = vd->vc;
|
||||
int id = reqdata->id;
|
||||
int call_status;
|
||||
|
||||
enum ofono_disconnect_reason reason = OFONO_DISCONNECT_REASON_ERROR;
|
||||
int last_cause = CALL_FAIL_ERROR_UNSPECIFIED;
|
||||
GRilIoParser rilp;
|
||||
grilio_parser_init(&rilp, data, len);
|
||||
if (grilio_parser_get_int32(&rilp, &tmp) && tmp > 0) {
|
||||
grilio_parser_get_int32(&rilp, &last_cause);
|
||||
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;
|
||||
int num, code;
|
||||
|
||||
/* Default format described in ril.h */
|
||||
grilio_parser_init(&rilp, data, len);
|
||||
if (grilio_parser_get_int32(&rilp, &num) && num == 1 &&
|
||||
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,7 +234,14 @@ static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
|
||||
* CALL_FAIL_ERROR_UNSPECIFIED, and thus indistinguishable
|
||||
* from a network failure.
|
||||
*/
|
||||
switch (last_cause) {
|
||||
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) {
|
||||
case CALL_FAIL_UNOBTAINABLE_NUMBER:
|
||||
case CALL_FAIL_NORMAL:
|
||||
case CALL_FAIL_BUSY:
|
||||
@@ -216,19 +249,19 @@ static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
|
||||
case CALL_FAIL_CHANNEL_UNACCEPTABLE:
|
||||
case CALL_FAIL_OPERATOR_DETERMINED_BARRING:
|
||||
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_NUMBER_CHANGED:
|
||||
case CALL_FAIL_ANONYMOUS_CALL_REJECTION:
|
||||
case CALL_FAIL_PRE_EMPTION:
|
||||
case CALL_FAIL_DESTINATION_OUT_OF_ORDER:
|
||||
case CALL_FAIL_INCOMPLETE_NUMBER:
|
||||
case CALL_FAIL_INVALID_NUMBER_FORMAT:
|
||||
case CALL_FAIL_FACILITY_REJECTED:
|
||||
reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP;
|
||||
break;
|
||||
|
||||
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 ||
|
||||
call_status == CALL_STATUS_HELD ||
|
||||
call_status == CALL_STATUS_DIALING ||
|
||||
@@ -240,7 +273,7 @@ static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
|
||||
break;
|
||||
|
||||
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 ||
|
||||
call_status == CALL_STATUS_ALERTING) {
|
||||
reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP;
|
||||
@@ -250,6 +283,7 @@ static void ril_voicecall_lastcause_cb(GRilIoChannel *io, int status,
|
||||
default:
|
||||
reason = OFONO_DISCONNECT_REASON_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ofono_info("Call %d ended with RIL cause %d -> ofono reason %d",
|
||||
@@ -295,7 +329,7 @@ static void ril_voicecall_clcc_poll_cb(GRilIoChannel *io, int status,
|
||||
struct lastcause_req *reqdata =
|
||||
g_new0(struct lastcause_req, 1);
|
||||
|
||||
reqdata->vc = vd->vc;
|
||||
reqdata->vd = vd;
|
||||
reqdata->id = oc->id;
|
||||
grilio_queue_send_request_full(vd->q, NULL,
|
||||
RIL_REQUEST_LAST_CALL_FAIL_CAUSE,
|
||||
@@ -803,6 +837,7 @@ static int ril_voicecall_probe(struct ofono_voicecall *vc, unsigned int vendor,
|
||||
void *data)
|
||||
{
|
||||
struct ril_modem *modem = data;
|
||||
const struct ril_slot_config *cfg = &modem->config;
|
||||
struct ril_voicecall *vd;
|
||||
|
||||
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->q = grilio_queue_new(vd->io);
|
||||
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->timer_id = g_idle_add(ril_delayed_register, vd);
|
||||
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_unref(vd->q);
|
||||
gutil_ring_unref(vd->dtmf_queue);
|
||||
gutil_ints_unref(vd->local_hangup_reasons);
|
||||
gutil_ints_unref(vd->remote_hangup_reasons);
|
||||
g_free(vd);
|
||||
}
|
||||
|
||||
|
||||
@@ -172,6 +172,8 @@ void ofono_voicecall_ssn_mt_notify(struct ofono_voicecall *vc, unsigned int id,
|
||||
int code, int index,
|
||||
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,
|
||||
const ofono_bool_t playTone);
|
||||
|
||||
|
||||
362
ofono/plugins/sfos_bt.c
Normal file
362
ofono/plugins/sfos_bt.c
Normal file
@@ -0,0 +1,362 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2017 Jolla Ltd. 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <glib.h>
|
||||
#include <ofono.h>
|
||||
#include <gdbus.h>
|
||||
|
||||
#define OFONO_API_SUBJECT_TO_CHANGE
|
||||
#include <ofono/plugin.h>
|
||||
#include <ofono/log.h>
|
||||
|
||||
#define SFOS_BT_DBUS_CV_INTERFACE "org.nemomobile.ofono.bluetooth.CallVolume"
|
||||
#define HFP_CALL_VOLUME_MAX 15
|
||||
|
||||
struct sfos_bt {
|
||||
unsigned int emu_watch;
|
||||
struct ofono_modem *modem;
|
||||
struct ofono_emulator *em;
|
||||
unsigned char speaker_volume;
|
||||
unsigned char microphone_volume;
|
||||
};
|
||||
|
||||
static GSList *modems;
|
||||
static guint modemwatch_id;
|
||||
|
||||
static void set_hfp_microphone_volume(struct sfos_bt *sfos_bt,
|
||||
unsigned char gain)
|
||||
{
|
||||
char buf[64];
|
||||
|
||||
snprintf(buf, sizeof(buf), "+VGM:%d", (int) gain);
|
||||
ofono_emulator_send_unsolicited(sfos_bt->em, buf);
|
||||
}
|
||||
|
||||
static void set_hfp_speaker_volume(struct sfos_bt *sfos_bt,
|
||||
unsigned char gain)
|
||||
{
|
||||
char buf[64];
|
||||
|
||||
snprintf(buf, sizeof(buf), "+VGS:%d", (int) gain);
|
||||
ofono_emulator_send_unsolicited(sfos_bt->em, buf);
|
||||
}
|
||||
|
||||
static DBusMessage *cv_set_property(DBusConnection *conn, DBusMessage *msg,
|
||||
void *data)
|
||||
{
|
||||
struct sfos_bt *sfos_bt = data;
|
||||
DBusMessageIter iter;
|
||||
DBusMessageIter var;
|
||||
const char *property;
|
||||
|
||||
if (!dbus_message_iter_init(msg, &iter))
|
||||
return __ofono_error_invalid_args(msg);
|
||||
|
||||
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
|
||||
return __ofono_error_invalid_args(msg);
|
||||
|
||||
dbus_message_iter_get_basic(&iter, &property);
|
||||
dbus_message_iter_next(&iter);
|
||||
|
||||
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
|
||||
return __ofono_error_invalid_args(msg);
|
||||
|
||||
dbus_message_iter_recurse(&iter, &var);
|
||||
|
||||
if (g_str_equal(property, "SpeakerVolume") == TRUE) {
|
||||
unsigned char gain;
|
||||
|
||||
if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_BYTE)
|
||||
return __ofono_error_invalid_args(msg);
|
||||
|
||||
dbus_message_iter_get_basic(&var, &gain);
|
||||
|
||||
if (gain > HFP_CALL_VOLUME_MAX)
|
||||
return __ofono_error_invalid_format(msg);
|
||||
|
||||
if (gain == sfos_bt->speaker_volume)
|
||||
return dbus_message_new_method_return(msg);
|
||||
|
||||
DBG("SpeakerVolume:%d", gain);
|
||||
sfos_bt->speaker_volume = gain;
|
||||
set_hfp_speaker_volume(sfos_bt, gain);
|
||||
|
||||
return dbus_message_new_method_return(msg);
|
||||
|
||||
} else if (g_str_equal(property, "MicrophoneVolume") == TRUE) {
|
||||
unsigned char gain;
|
||||
|
||||
if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_BYTE)
|
||||
return __ofono_error_invalid_args(msg);
|
||||
|
||||
dbus_message_iter_get_basic(&var, &gain);
|
||||
|
||||
if (gain > HFP_CALL_VOLUME_MAX)
|
||||
return __ofono_error_invalid_format(msg);
|
||||
|
||||
if (gain == sfos_bt->microphone_volume)
|
||||
return dbus_message_new_method_return(msg);
|
||||
|
||||
DBG("MicrophoneVolume:%d", gain);
|
||||
sfos_bt->microphone_volume = gain;
|
||||
set_hfp_microphone_volume(sfos_bt, gain);
|
||||
|
||||
return dbus_message_new_method_return(msg);
|
||||
|
||||
} else if (g_str_equal(property, "Muted") == TRUE) {
|
||||
unsigned char gain;
|
||||
dbus_bool_t muted;
|
||||
|
||||
/*Remove when supported*/
|
||||
return __ofono_error_not_implemented(msg);
|
||||
|
||||
if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_BOOLEAN)
|
||||
return __ofono_error_invalid_args(msg);
|
||||
|
||||
dbus_message_iter_get_basic(&var, &muted);
|
||||
|
||||
if (muted)
|
||||
gain = 0;
|
||||
else
|
||||
gain = 7;/* rather gain = sfos->old_mic_vol */
|
||||
|
||||
if (gain == sfos_bt->microphone_volume)
|
||||
return dbus_message_new_method_return(msg);
|
||||
|
||||
sfos_bt->microphone_volume = gain;
|
||||
set_hfp_microphone_volume(sfos_bt, gain);
|
||||
|
||||
return dbus_message_new_method_return(msg);
|
||||
}
|
||||
|
||||
return __ofono_error_invalid_args(msg);
|
||||
}
|
||||
|
||||
static const GDBusMethodTable cv_methods[] = {
|
||||
{ GDBUS_METHOD("SetProperty",
|
||||
GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
|
||||
NULL, cv_set_property) },
|
||||
{ }
|
||||
};
|
||||
|
||||
static const GDBusSignalTable cv_signals[] = {
|
||||
{ GDBUS_SIGNAL("PropertyChanged",
|
||||
GDBUS_ARGS({ "property", "s" }, { "value", "v" })) },
|
||||
{ }
|
||||
};
|
||||
|
||||
int sfos_bt_call_volume_set(struct ofono_modem *modem, unsigned char volume,
|
||||
const char *gain)
|
||||
{
|
||||
DBusConnection *conn = ofono_dbus_get_connection();
|
||||
const char *path = ofono_modem_get_path(modem);
|
||||
|
||||
return ofono_dbus_signal_property_changed(conn, path,
|
||||
SFOS_BT_DBUS_CV_INTERFACE,
|
||||
gain,
|
||||
DBUS_TYPE_BYTE, &volume);
|
||||
}
|
||||
|
||||
static void set_gain(struct ofono_emulator *em,
|
||||
struct ofono_emulator_request *req,
|
||||
void *userdata, const char *gain)
|
||||
{
|
||||
struct sfos_bt *sfos_bt = userdata;
|
||||
struct ofono_modem *modem = sfos_bt->modem;
|
||||
struct ofono_error result;
|
||||
unsigned char volume;
|
||||
int val;
|
||||
result.error = 0;
|
||||
|
||||
switch (ofono_emulator_request_get_type(req)) {
|
||||
case OFONO_EMULATOR_REQUEST_TYPE_SET:
|
||||
if (ofono_emulator_request_next_number(req, &val) == FALSE)
|
||||
goto fail;
|
||||
|
||||
if (val < 0 || val > 0xffff || val > HFP_CALL_VOLUME_MAX)
|
||||
goto fail;
|
||||
|
||||
DBG("gain:%d", val);
|
||||
|
||||
volume = (unsigned char) val;
|
||||
if (sfos_bt_call_volume_set(modem, volume, gain)<= 0)
|
||||
goto fail;
|
||||
|
||||
if (!g_strcmp0(gain, "SpeakerVolume"))
|
||||
sfos_bt->speaker_volume = volume;
|
||||
else
|
||||
sfos_bt->microphone_volume = volume;
|
||||
|
||||
result.type = OFONO_ERROR_TYPE_NO_ERROR;
|
||||
ofono_emulator_send_final(em, &result);
|
||||
break;
|
||||
|
||||
default:
|
||||
fail:
|
||||
result.type = OFONO_ERROR_TYPE_FAILURE;
|
||||
ofono_emulator_send_final(em, &result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void sfos_bt_vgm_cb(struct ofono_emulator *em,
|
||||
struct ofono_emulator_request *req, void *userdata)
|
||||
{
|
||||
const char *gain = "MicrophoneVolume";
|
||||
set_gain(em, req, userdata, gain);
|
||||
}
|
||||
|
||||
static void sfos_bt_vgs_cb(struct ofono_emulator *em,
|
||||
struct ofono_emulator_request *req, void *userdata)
|
||||
{
|
||||
const char *gain = "SpeakerVolume";
|
||||
set_gain(em, req, userdata, gain);
|
||||
}
|
||||
|
||||
void sfos_bt_cv_dbus_new(struct sfos_bt *sfos_bt)
|
||||
{
|
||||
DBusConnection *conn = ofono_dbus_get_connection();
|
||||
struct ofono_modem *modem = sfos_bt->modem;
|
||||
const char *path = ofono_modem_get_path(modem);
|
||||
|
||||
if (g_dbus_register_interface(conn, path,
|
||||
SFOS_BT_DBUS_CV_INTERFACE, cv_methods,
|
||||
cv_signals, NULL, sfos_bt, NULL)){
|
||||
ofono_modem_add_interface(modem,SFOS_BT_DBUS_CV_INTERFACE);
|
||||
return;
|
||||
}
|
||||
|
||||
ofono_error("D-Bus register failed");
|
||||
}
|
||||
|
||||
static void sfos_bt_remove_handler(struct ofono_emulator *em)
|
||||
{
|
||||
ofono_emulator_remove_handler(em, "+VGS");
|
||||
ofono_emulator_remove_handler(em, "+VGM");
|
||||
}
|
||||
|
||||
void sfos_bt_cv_dbus_free(struct sfos_bt *sfos_bt)
|
||||
{
|
||||
DBusConnection *conn = ofono_dbus_get_connection();
|
||||
struct ofono_modem *modem = sfos_bt->modem;
|
||||
const char *path = ofono_modem_get_path(modem);
|
||||
ofono_modem_remove_interface(modem, SFOS_BT_DBUS_CV_INTERFACE);
|
||||
g_dbus_unregister_interface(conn, path,
|
||||
SFOS_BT_DBUS_CV_INTERFACE);
|
||||
}
|
||||
|
||||
static void sfos_bt_emu_watch_cb(struct ofono_atom *atom,
|
||||
enum ofono_atom_watch_condition cond,
|
||||
void *data)
|
||||
{
|
||||
struct sfos_bt *sfos_bt = data;
|
||||
|
||||
if (cond == OFONO_ATOM_WATCH_CONDITION_REGISTERED){
|
||||
sfos_bt->em = __ofono_atom_get_data(atom);
|
||||
sfos_bt_cv_dbus_new(sfos_bt);
|
||||
ofono_emulator_add_handler(sfos_bt->em, "+VGS",
|
||||
sfos_bt_vgs_cb, sfos_bt, NULL);
|
||||
ofono_emulator_add_handler(sfos_bt->em, "+VGM",
|
||||
sfos_bt_vgm_cb, sfos_bt, NULL);
|
||||
} else {
|
||||
sfos_bt_cv_dbus_free(sfos_bt);
|
||||
sfos_bt_remove_handler(sfos_bt->em);
|
||||
sfos_bt->em = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void sfos_bt_emu_watch_destroy(void *data)
|
||||
{
|
||||
struct sfos_bt *sfos_bt = data;
|
||||
|
||||
sfos_bt->emu_watch = 0;
|
||||
}
|
||||
|
||||
static void sfos_bt_free(void *data)
|
||||
{
|
||||
struct sfos_bt *sfos_bt = data;
|
||||
|
||||
if (sfos_bt->emu_watch)
|
||||
__ofono_modem_remove_atom_watch(sfos_bt->modem,
|
||||
sfos_bt->emu_watch);
|
||||
|
||||
if (sfos_bt->em) {
|
||||
sfos_bt_cv_dbus_free(sfos_bt);
|
||||
sfos_bt_remove_handler(sfos_bt->em);
|
||||
}
|
||||
|
||||
g_free(sfos_bt);
|
||||
}
|
||||
|
||||
static gint sfos_bt_find_modem(gconstpointer listdata, gconstpointer modem)
|
||||
{
|
||||
const struct sfos_bt *sfos_bt = listdata;
|
||||
|
||||
return (sfos_bt->modem != modem);
|
||||
}
|
||||
|
||||
static void modem_watch(struct ofono_modem *modem, gboolean added, void *user)
|
||||
{
|
||||
struct sfos_bt *sfos_bt;
|
||||
DBG("modem: %p, added: %d", modem, added);
|
||||
|
||||
if (added) {
|
||||
sfos_bt = g_new0(struct sfos_bt, 1);
|
||||
modems = g_slist_append(modems, sfos_bt);
|
||||
sfos_bt->emu_watch = __ofono_modem_add_atom_watch(modem,
|
||||
OFONO_ATOM_TYPE_EMULATOR_HFP, sfos_bt_emu_watch_cb,
|
||||
sfos_bt, sfos_bt_emu_watch_destroy);
|
||||
sfos_bt->modem = modem;
|
||||
} else {
|
||||
GSList *link = g_slist_find_custom(modems, modem,
|
||||
sfos_bt_find_modem);
|
||||
if (link) {
|
||||
sfos_bt_free(link->data);
|
||||
modems = g_slist_delete_link(modems, link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void call_modemwatch(struct ofono_modem *modem, void *user)
|
||||
{
|
||||
modem_watch(modem, TRUE, user);
|
||||
}
|
||||
|
||||
static int sfos_bt_init(void)
|
||||
{
|
||||
modemwatch_id = __ofono_modemwatch_add(modem_watch, NULL, NULL);
|
||||
__ofono_modem_foreach(call_modemwatch, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sfos_bt_exit(void)
|
||||
{
|
||||
DBG("");
|
||||
__ofono_modemwatch_remove(modemwatch_id);
|
||||
g_slist_free_full(modems, sfos_bt_free);
|
||||
}
|
||||
|
||||
OFONO_PLUGIN_DEFINE(sfos_bt, "Sailfish OS Bluetooth Plugin", VERSION,
|
||||
OFONO_PLUGIN_PRIORITY_DEFAULT,
|
||||
sfos_bt_init, sfos_bt_exit)
|
||||
@@ -2274,6 +2274,11 @@ static DBusMessage *gprs_add_context(DBusConnection *conn,
|
||||
const char *path;
|
||||
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,
|
||||
DBUS_TYPE_INVALID))
|
||||
return __ofono_error_invalid_args(msg);
|
||||
@@ -2355,6 +2360,11 @@ static DBusMessage *gprs_remove_context(DBusConnection *conn,
|
||||
const char *path;
|
||||
const char *atompath;
|
||||
|
||||
#ifdef DISABLE_ADD_REMOVE_CONTEXT
|
||||
ofono_error("RemoveContext not allowed");
|
||||
return __ofono_error_not_supported(msg);
|
||||
#endif
|
||||
|
||||
if (gprs->pending)
|
||||
return __ofono_error_busy(msg);
|
||||
|
||||
|
||||
@@ -386,6 +386,9 @@ void __ofono_sim_refresh(struct ofono_sim *sim, GSList *file_list,
|
||||
|
||||
void __ofono_sim_recheck_pin(struct ofono_sim *sim);
|
||||
|
||||
enum ofono_sim_password_type __ofono_sim_puk2pin(
|
||||
enum ofono_sim_password_type type);
|
||||
|
||||
#include <ofono/stk.h>
|
||||
|
||||
typedef void (*__ofono_sms_sim_download_cb_t)(ofono_bool_t ok,
|
||||
|
||||
@@ -197,7 +197,10 @@ static gboolean password_is_pin(enum ofono_sim_password_type type)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static enum ofono_sim_password_type puk2pin(enum ofono_sim_password_type type)
|
||||
#define puk2pin(type) __ofono_sim_puk2pin(type)
|
||||
|
||||
enum ofono_sim_password_type __ofono_sim_puk2pin(
|
||||
enum ofono_sim_password_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case OFONO_SIM_PASSWORD_SIM_PUK:
|
||||
|
||||
@@ -226,6 +226,9 @@ void sim_fs_notify_file_watches(struct sim_fs *fs, int id)
|
||||
struct ofono_sim_context *context = l->data;
|
||||
GSList *k;
|
||||
|
||||
if (context->file_watches == NULL)
|
||||
continue;
|
||||
|
||||
for (k = context->file_watches->items; k; k = k->next) {
|
||||
struct file_watch *w = k->data;
|
||||
ofono_sim_file_changed_cb_t notify = w->item.notify;
|
||||
|
||||
@@ -3748,6 +3748,15 @@ int ofono_voicecall_get_next_callid(struct ofono_voicecall *vc)
|
||||
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,
|
||||
enum ofono_voicecall_interaction type)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ Requires: dbus
|
||||
Requires: systemd
|
||||
Requires: ofono-configs
|
||||
Requires: libgrilio >= 1.0.10
|
||||
Requires: libglibutil >= 1.0.10
|
||||
Requires: libglibutil >= 1.0.22
|
||||
Requires(preun): systemd
|
||||
Requires(post): systemd
|
||||
Requires(postun): systemd
|
||||
@@ -21,7 +21,7 @@ BuildRequires: pkgconfig(libudev) >= 145
|
||||
BuildRequires: pkgconfig(mobile-broadband-provider-info)
|
||||
BuildRequires: pkgconfig(libwspcodec) >= 2.0
|
||||
BuildRequires: pkgconfig(libgrilio) >= 1.0.10
|
||||
BuildRequires: pkgconfig(libglibutil) >= 1.0.10
|
||||
BuildRequires: pkgconfig(libglibutil) >= 1.0.22
|
||||
BuildRequires: pkgconfig(libdbuslogserver-dbus)
|
||||
BuildRequires: pkgconfig(libmce-glib)
|
||||
BuildRequires: libtool
|
||||
@@ -71,9 +71,13 @@ autoreconf --force --install
|
||||
--enable-test \
|
||||
--enable-debuglog \
|
||||
--enable-jolla-rilmodem \
|
||||
--enable-sailfishos \
|
||||
--disable-add-remove-context \
|
||||
--disable-isimodem \
|
||||
--disable-qmimodem \
|
||||
--with-systemdunitdir="/%{_lib}/systemd/system"
|
||||
|
||||
make %{?jobs:-j%jobs}
|
||||
make %{_smp_mflags}
|
||||
|
||||
|
||||
%check
|
||||
|
||||
Reference in New Issue
Block a user