mirror of
https://github.com/sailfishos/ofono
synced 2025-11-26 20:31:06 +08:00
Compare commits
26 Commits
mer/1.20+g
...
mer/1.20+g
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
490a9c06f4 | ||
|
|
320b3f4605 | ||
|
|
e35dae17d9 | ||
|
|
f4522f4a00 | ||
|
|
ce85c94426 | ||
|
|
4027bdc04e | ||
|
|
c57f99bf01 | ||
|
|
54d610ce6a | ||
|
|
f7f9e32743 | ||
|
|
8c9e370486 | ||
|
|
19b80236f6 | ||
|
|
2ec6fc749d | ||
|
|
0a3bdd20f4 | ||
|
|
284919e76a | ||
|
|
ddcbb89fa1 | ||
|
|
5ec6b8e7ec | ||
|
|
f94681f6f6 | ||
|
|
de8edc84fa | ||
|
|
90faf1b3a5 | ||
|
|
2b139b6974 | ||
|
|
168f193efb | ||
|
|
32d8b5ccfc | ||
|
|
f400ceff80 | ||
|
|
2186c60630 | ||
|
|
d5fb195e2f | ||
|
|
cbb08079d2 |
2
ofono/.gitignore
vendored
2
ofono/.gitignore
vendored
@@ -48,8 +48,10 @@ unit/test-rilmodem-cs
|
||||
unit/test-rilmodem-gprs
|
||||
unit/test-rilmodem-sms
|
||||
unit/test-sailfish_cell_info
|
||||
unit/test-sailfish_cell_info_dbus
|
||||
unit/test-sailfish_manager
|
||||
unit/test-sailfish_sim_info
|
||||
unit/test-sailfish_sim_info_dbus
|
||||
unit/test-sms-filter
|
||||
unit/test-*.log
|
||||
unit/test-*.trs
|
||||
|
||||
@@ -166,8 +166,12 @@ builtin_sources += drivers/ril/ril_call_barring.c \
|
||||
drivers/ril/ril_stk.c \
|
||||
drivers/ril/ril_ussd.c \
|
||||
drivers/ril/ril_util.c \
|
||||
drivers/ril/ril_vendor.c \
|
||||
drivers/ril/ril_voicecall.c
|
||||
|
||||
# Vendor specific extensions
|
||||
builtin_sources += drivers/ril/ril_vendor_mtk.c
|
||||
|
||||
if DATAFILES
|
||||
dist_conf_DATA += drivers/ril/ril_subscription.conf
|
||||
endif
|
||||
@@ -912,11 +916,24 @@ if SAILFISH_MANAGER
|
||||
unit_test_sailfish_cell_info_SOURCES = unit/test-sailfish_cell_info.c \
|
||||
plugins/sailfish_manager/sailfish_cell_info.c
|
||||
unit_test_sailfish_cell_info_CFLAGS = $(AM_CFLAGS) $(COVERAGE_OPT) \
|
||||
-Iplugins/sailfish_cell_info
|
||||
-Iplugins/sailfish_manager
|
||||
unit_test_sailfish_cell_info_LDADD = @GLIB_LIBS@ -ldl
|
||||
unit_objects += $(unit_test_sailfish_cell_info_OBJECTS)
|
||||
unit_tests += unit/test-sailfish_cell_info
|
||||
|
||||
unit_test_sailfish_cell_info_dbus_SOURCES = unit/test-dbus.c \
|
||||
unit/test-sailfish_cell_info_dbus.c \
|
||||
unit/fake_sailfish_cell_info.c \
|
||||
plugins/sailfish_manager/sailfish_cell_info.c \
|
||||
plugins/sailfish_manager/sailfish_cell_info_dbus.c \
|
||||
gdbus/object.c \
|
||||
src/dbus.c src/log.c
|
||||
unit_test_sailfish_cell_info_dbus_CFLAGS = $(AM_CFLAGS) $(COVERAGE_OPT) \
|
||||
@DBUS_GLIB_CFLAGS@ -Iplugins/sailfish_manager
|
||||
unit_test_sailfish_cell_info_dbus_LDADD = @DBUS_GLIB_LIBS@ @GLIB_LIBS@ -ldl
|
||||
unit_objects += $(unit_test_sailfish_cell_info_dbus_OBJECTS)
|
||||
unit_tests += unit/test-sailfish_cell_info_dbus
|
||||
|
||||
unit_test_sailfish_sim_info_SOURCES = unit/test-sailfish_sim_info.c \
|
||||
unit/fake_sailfish_watch.c \
|
||||
plugins/sailfish_manager/sailfish_sim_info.c \
|
||||
@@ -927,6 +944,19 @@ unit_test_sailfish_sim_info_LDADD = @GLIB_LIBS@ -ldl
|
||||
unit_objects += $(unit_test_sailfish_sim_info_OBJECTS)
|
||||
unit_tests += unit/test-sailfish_sim_info
|
||||
|
||||
unit_test_sailfish_sim_info_dbus_SOURCES = unit/test-sailfish_sim_info_dbus.c \
|
||||
unit/test-dbus.c unit/fake_sailfish_watch.c \
|
||||
plugins/sailfish_manager/sailfish_sim_info.c \
|
||||
plugins/sailfish_manager/sailfish_sim_info_dbus.c \
|
||||
gdbus/object.c \
|
||||
src/dbus.c src/storage.c src/watch.c src/log.c
|
||||
unit_test_sailfish_sim_info_dbus_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS) \
|
||||
@DBUS_GLIB_CFLAGS@ -DSTORAGEDIR='"/tmp/ofono"' \
|
||||
-Iplugins/sailfish_manager
|
||||
unit_test_sailfish_sim_info_dbus_LDADD = @DBUS_GLIB_LIBS@ @GLIB_LIBS@ -ldl
|
||||
unit_objects += $(unit_test_sailfish_sim_info_dbus_OBJECTS)
|
||||
unit_tests += unit/test-sailfish_sim_info_dbus
|
||||
|
||||
unit_test_sailfish_manager_SOURCES = unit/test-sailfish_manager.c \
|
||||
unit/fake_sailfish_watch.c \
|
||||
plugins/sailfish_manager/sailfish_manager.c \
|
||||
|
||||
@@ -184,8 +184,8 @@ AC_ARG_ENABLE(sailfish-rilmodem, AC_HELP_STRING([--enable-sailfish-rilmodem],
|
||||
AM_CONDITIONAL(SAILFISH_RILMODEM, test "${enable_sailfish_rilmodem}" != "no")
|
||||
|
||||
if (test "${enable_sailfish_rilmodem}" = "yes"); then
|
||||
PKG_CHECK_MODULES(GRILIO, libgrilio >= 1.0.18, dummy=yes,
|
||||
AC_MSG_ERROR(libgrilio >= 1.0.18 is required))
|
||||
PKG_CHECK_MODULES(GRILIO, libgrilio >= 1.0.20, dummy=yes,
|
||||
AC_MSG_ERROR(libgrilio >= 1.0.20 is required))
|
||||
PKG_CHECK_MODULES(GLIBUTIL, libglibutil >= 1.0.23, dummy=yes,
|
||||
AC_MSG_ERROR(libglibutil >= 1.0.23 is required))
|
||||
PKG_CHECK_MODULES(LIBMCE, libmce-glib >= 1.0.5, dummy=yes,
|
||||
@@ -202,6 +202,13 @@ AC_ARG_ENABLE(sailfish-manager,
|
||||
[enable_sailfish_manager=${enableval}])
|
||||
AM_CONDITIONAL(SAILFISH_MANAGER, test "${enable_sailfish_manager}" = "yes")
|
||||
|
||||
if (test "${enable_sailfish_manager}" = "yes"); then
|
||||
PKG_CHECK_MODULES(DBUS_GLIB, dbus-glib-1, dummy=yes,
|
||||
AC_MSG_ERROR(dbus-glib is required by unit tests))
|
||||
AC_SUBST(DBUS_GLIB_CFLAGS)
|
||||
AC_SUBST(DBUS_GLIB_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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2016-2017 Jolla Ltd.
|
||||
* Copyright (C) 2016-2018 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
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#define DISPLAY_ON_UPDATE_RATE (1000) /* 1 sec */
|
||||
#define DISPLAY_OFF_UPDATE_RATE (60000) /* 1 min */
|
||||
#define MAX_RETRIES (5)
|
||||
|
||||
typedef GObjectClass RilCellInfoClass;
|
||||
typedef struct ril_cell_info RilCellInfo;
|
||||
@@ -296,8 +297,8 @@ static void ril_cell_info_list_cb(GRilIoChannel *io, int status,
|
||||
DBG_(self, "");
|
||||
GASSERT(self->query_id);
|
||||
self->query_id = 0;
|
||||
ril_cell_info_update_cells(self, ril_cell_info_parse_list
|
||||
(io->ril_version, data, len));
|
||||
ril_cell_info_update_cells(self, (status == RIL_E_SUCCESS) ?
|
||||
ril_cell_info_parse_list(io->ril_version, data, len) : NULL);
|
||||
}
|
||||
|
||||
static void ril_cell_info_set_rate_cb(GRilIoChannel *io, int status,
|
||||
@@ -314,7 +315,7 @@ static void ril_cell_info_query(struct ril_cell_info *self)
|
||||
{
|
||||
GRilIoRequest *req = grilio_request_new();
|
||||
|
||||
grilio_request_set_retry(req, RIL_RETRY_MS, -1);
|
||||
grilio_request_set_retry(req, RIL_RETRY_MS, MAX_RETRIES);
|
||||
grilio_channel_cancel_request(self->io, self->query_id, FALSE);
|
||||
self->query_id = grilio_channel_send_request_full(self->io, req,
|
||||
RIL_REQUEST_GET_CELL_INFO_LIST, ril_cell_info_list_cb,
|
||||
@@ -328,7 +329,7 @@ static void ril_cell_info_set_rate(struct ril_cell_info *self, int ms)
|
||||
|
||||
grilio_request_append_int32(req, 1);
|
||||
grilio_request_append_int32(req, ms);
|
||||
grilio_request_set_retry(req, RIL_RETRY_MS, -1);
|
||||
grilio_request_set_retry(req, RIL_RETRY_MS, MAX_RETRIES);
|
||||
grilio_channel_cancel_request(self->io, self->set_rate_id, FALSE);
|
||||
self->set_rate_id = grilio_channel_send_request_full(self->io, req,
|
||||
RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE,
|
||||
@@ -338,18 +339,16 @@ static void ril_cell_info_set_rate(struct ril_cell_info *self, int ms)
|
||||
|
||||
static void ril_cell_info_update_rate(struct ril_cell_info *self)
|
||||
{
|
||||
ril_cell_info_set_rate(self,
|
||||
(self->display->state == MCE_DISPLAY_STATE_OFF) ?
|
||||
DISPLAY_OFF_UPDATE_RATE : DISPLAY_ON_UPDATE_RATE);
|
||||
if (self->sim_card_ready) {
|
||||
ril_cell_info_set_rate(self,
|
||||
(self->display->state == MCE_DISPLAY_STATE_OFF) ?
|
||||
DISPLAY_OFF_UPDATE_RATE : DISPLAY_ON_UPDATE_RATE);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_cell_info_display_state_cb(MceDisplay *display, void *arg)
|
||||
{
|
||||
struct ril_cell_info *self = RIL_CELL_INFO(arg);
|
||||
|
||||
if (self->sim_card_ready) {
|
||||
ril_cell_info_update_rate(self);
|
||||
}
|
||||
ril_cell_info_update_rate(RIL_CELL_INFO(arg));
|
||||
}
|
||||
|
||||
static void ril_cell_info_refresh(struct ril_cell_info *self)
|
||||
@@ -373,16 +372,11 @@ static void ril_cell_info_radio_state_cb(struct ril_radio *radio, void *arg)
|
||||
static void ril_cell_info_sim_status_cb(struct ril_sim_card *sim, void *arg)
|
||||
{
|
||||
struct ril_cell_info *self = RIL_CELL_INFO(arg);
|
||||
const gboolean sim_card_was_ready = self->sim_card_ready;
|
||||
|
||||
DBG_(self, "%sready", ril_sim_card_ready(sim) ? "" : "not ");
|
||||
self->sim_card_ready = ril_sim_card_ready(sim);
|
||||
if (self->sim_card_ready != sim_card_was_ready) {
|
||||
ril_cell_info_refresh(self);
|
||||
if (self->sim_card_ready) {
|
||||
ril_cell_info_update_rate(self);
|
||||
}
|
||||
}
|
||||
DBG_(self, "%sready", self->sim_card_ready ? "" : "not ");
|
||||
ril_cell_info_refresh(self);
|
||||
ril_cell_info_update_rate(self);
|
||||
}
|
||||
|
||||
/* sailfish_cell_info interface callbacks */
|
||||
@@ -483,10 +477,8 @@ struct sailfish_cell_info *ril_cell_info_new(GRilIoChannel *io,
|
||||
ril_sim_card_add_status_changed_handler(self->sim_card,
|
||||
ril_cell_info_sim_status_cb, self);
|
||||
self->sim_card_ready = ril_sim_card_ready(sim_card);
|
||||
if (self->sim_card_ready) {
|
||||
ril_cell_info_query(self);
|
||||
ril_cell_info_update_rate(self);
|
||||
}
|
||||
ril_cell_info_refresh(self);
|
||||
ril_cell_info_update_rate(self);
|
||||
return &self->info;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "ril_network.h"
|
||||
#include "ril_sim_settings.h"
|
||||
#include "ril_util.h"
|
||||
#include "ril_vendor.h"
|
||||
#include "ril_log.h"
|
||||
|
||||
#include <gutil_strv.h>
|
||||
@@ -207,10 +208,15 @@ GRilIoRequest *ril_request_deactivate_data_call_new(int cid)
|
||||
* ril_data_call
|
||||
*==========================================================================*/
|
||||
|
||||
static struct ril_data_call *ril_data_call_new()
|
||||
{
|
||||
return g_new0(struct ril_data_call, 1);
|
||||
}
|
||||
|
||||
struct ril_data_call *ril_data_call_dup(const struct ril_data_call *call)
|
||||
{
|
||||
if (call) {
|
||||
struct ril_data_call *dc = g_new0(struct ril_data_call, 1);
|
||||
struct ril_data_call *dc = ril_data_call_new();
|
||||
dc->cid = call->cid;
|
||||
dc->status = call->status;
|
||||
dc->active = call->active;
|
||||
@@ -227,13 +233,18 @@ struct ril_data_call *ril_data_call_dup(const struct ril_data_call *call)
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_data_call_destroy(struct ril_data_call *call)
|
||||
{
|
||||
g_free(call->ifname);
|
||||
g_strfreev(call->dnses);
|
||||
g_strfreev(call->addresses);
|
||||
g_strfreev(call->gateways);
|
||||
}
|
||||
|
||||
void ril_data_call_free(struct ril_data_call *call)
|
||||
{
|
||||
if (call) {
|
||||
g_free(call->ifname);
|
||||
g_strfreev(call->dnses);
|
||||
g_strfreev(call->addresses);
|
||||
g_strfreev(call->gateways);
|
||||
ril_data_call_destroy(call);
|
||||
g_free(call);
|
||||
}
|
||||
}
|
||||
@@ -251,7 +262,7 @@ static void ril_data_call_list_free(struct ril_data_call_list *list)
|
||||
}
|
||||
}
|
||||
|
||||
static gint ril_data_call_parse_compare(gconstpointer a, gconstpointer b)
|
||||
static gint ril_data_call_compare(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
const struct ril_data_call *ca = a;
|
||||
const struct ril_data_call *cb = b;
|
||||
@@ -265,7 +276,7 @@ static gint ril_data_call_parse_compare(gconstpointer a, gconstpointer b)
|
||||
}
|
||||
}
|
||||
|
||||
static const char *ril_data_ofono_protocol_to_ril(enum ofono_gprs_proto proto)
|
||||
const char *ril_data_ofono_protocol_to_ril(enum ofono_gprs_proto proto)
|
||||
{
|
||||
switch (proto) {
|
||||
case OFONO_GPRS_PROTO_IPV6:
|
||||
@@ -279,7 +290,7 @@ static const char *ril_data_ofono_protocol_to_ril(enum ofono_gprs_proto proto)
|
||||
}
|
||||
}
|
||||
|
||||
static int ril_data_protocol_to_ofono(gchar *str)
|
||||
int ril_data_protocol_to_ofono(const gchar *str)
|
||||
{
|
||||
if (str) {
|
||||
if (!strcmp(str, PROTO_IPV6_STR)) {
|
||||
@@ -293,14 +304,13 @@ static int ril_data_protocol_to_ofono(gchar *str)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct ril_data_call *ril_data_call_parse(int version,
|
||||
GRilIoParser *rilp)
|
||||
static gboolean ril_data_call_parse_default(struct ril_data_call *call,
|
||||
int version, GRilIoParser *rilp)
|
||||
{
|
||||
int prot;
|
||||
char *prot_str;
|
||||
guint32 status = PDP_FAIL_ERROR_UNSPECIFIED;
|
||||
guint32 active = RIL_DATA_CALL_INACTIVE;
|
||||
struct ril_data_call *call = g_new0(struct ril_data_call, 1);
|
||||
|
||||
/* RIL_Data_Call_Response_v6 (see ril.h) */
|
||||
grilio_parser_get_uint32(rilp, &status);
|
||||
@@ -335,13 +345,48 @@ static struct ril_data_call *ril_data_call_parse(int version,
|
||||
}
|
||||
|
||||
g_free(prot_str);
|
||||
return call;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static struct ril_data_call *ril_data_call_parse(struct ril_vendor_hook *hook,
|
||||
int version, GRilIoParser *parser)
|
||||
{
|
||||
GRilIoParser copy = *parser;
|
||||
struct ril_data_call *call = ril_data_call_new();
|
||||
gboolean parsed = ril_vendor_hook_data_call_parse(hook, call,
|
||||
version, parser);
|
||||
|
||||
if (!parsed) {
|
||||
/* Try the default parser */
|
||||
ril_data_call_destroy(call);
|
||||
memset(call, 0, sizeof(*call));
|
||||
parsed = ril_data_call_parse_default(call, version, ©);
|
||||
}
|
||||
|
||||
if (parsed) {
|
||||
DBG("[status=%d,retry=%d,cid=%d,active=%d,type=%s,ifname=%s,"
|
||||
"mtu=%d,address=%s,dns=%s %s,gateways=%s]",
|
||||
call->status, call->retry_time,
|
||||
call->cid, call->active,
|
||||
ril_data_ofono_protocol_to_ril(call->prot),
|
||||
call->ifname, call->mtu,
|
||||
call->addresses ? call->addresses[0] : NULL,
|
||||
call->dnses ? call->dnses[0] : NULL,
|
||||
(call->dnses && call->dnses[0] &&
|
||||
call->dnses[1]) ? call->dnses[1] : "",
|
||||
call->gateways ? call->gateways[0] : NULL);
|
||||
return call;
|
||||
} else {
|
||||
ril_data_call_free(call);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static struct ril_data_call_list *ril_data_call_list_parse(const void *data,
|
||||
guint len, enum ril_data_call_format format)
|
||||
guint len, struct ril_vendor_hook *hook,
|
||||
enum ril_data_call_format format)
|
||||
{
|
||||
unsigned int version, n, i;
|
||||
guint32 version, n;
|
||||
GRilIoParser rilp;
|
||||
|
||||
grilio_parser_init(&rilp, data, len);
|
||||
@@ -358,26 +403,23 @@ static struct ril_data_call_list *ril_data_call_list_parse(const void *data,
|
||||
list->version = format;
|
||||
}
|
||||
|
||||
for (i = 0; i < n && !grilio_parser_at_end(&rilp); i++) {
|
||||
struct ril_data_call *call =
|
||||
ril_data_call_parse(list->version, &rilp);
|
||||
if (n > 0) {
|
||||
guint i, clen = grilio_parser_bytes_remaining(&rilp)/n;
|
||||
|
||||
DBG("[status=%d,retry=%d,cid=%d,"
|
||||
"active=%d,type=%s,ifname=%s,mtu=%d,"
|
||||
"address=%s, dns=%s %s,gateways=%s]",
|
||||
call->status, call->retry_time,
|
||||
call->cid, call->active,
|
||||
ril_data_ofono_protocol_to_ril(call->prot),
|
||||
call->ifname, call->mtu,
|
||||
call->addresses ? call->addresses[0] : NULL,
|
||||
call->dnses ? call->dnses[0] : NULL,
|
||||
(call->dnses && call->dnses[0] &&
|
||||
call->dnses[1]) ? call->dnses[1] : "",
|
||||
call->gateways ? call->gateways[0] : NULL);
|
||||
for (i = 0; i < n; i++) {
|
||||
GRilIoParser callp;
|
||||
struct ril_data_call *call;
|
||||
|
||||
list->num++;
|
||||
list->calls = g_slist_insert_sorted(list->calls, call,
|
||||
ril_data_call_parse_compare);
|
||||
grilio_parser_get_data(&rilp, &callp, clen);
|
||||
call = ril_data_call_parse(hook, list->version,
|
||||
&callp);
|
||||
if (call) {
|
||||
list->num++;
|
||||
list->calls = g_slist_insert_sorted
|
||||
(list->calls, call,
|
||||
ril_data_call_compare);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (list->calls) {
|
||||
@@ -471,7 +513,7 @@ static int ril_data_call_list_move_calls(struct ril_data_call_list *dest,
|
||||
dest->num++;
|
||||
src->calls = g_slist_delete_link(src->calls, l);
|
||||
dest->calls = g_slist_insert_sorted(dest->calls,
|
||||
call, ril_data_call_parse_compare);
|
||||
call, ril_data_call_compare);
|
||||
}
|
||||
|
||||
l = next;
|
||||
@@ -527,7 +569,7 @@ static void ril_data_call_list_changed_cb(GRilIoChannel *io, guint event,
|
||||
}
|
||||
|
||||
ril_data_set_calls(self, ril_data_call_list_parse(data, len,
|
||||
priv->options.data_call_format));
|
||||
priv->vendor_hook, priv->options.data_call_format));
|
||||
}
|
||||
|
||||
static void ril_data_query_data_calls_cb(GRilIoChannel *io, int ril_status,
|
||||
@@ -544,7 +586,7 @@ static void ril_data_query_data_calls_cb(GRilIoChannel *io, int ril_status,
|
||||
priv->query_id = 0;
|
||||
if (ril_status == RIL_E_SUCCESS) {
|
||||
ril_data_set_calls(self, ril_data_call_list_parse(data, len,
|
||||
priv->options.data_call_format));
|
||||
priv->vendor_hook, priv->options.data_call_format));
|
||||
} else {
|
||||
/* RADIO_NOT_AVAILABLE == no calls */
|
||||
ril_data_set_calls(self, NULL);
|
||||
@@ -750,7 +792,7 @@ static void ril_data_call_setup_cb(GRilIoChannel *io, int ril_status,
|
||||
|
||||
if (ril_status == RIL_E_SUCCESS) {
|
||||
list = ril_data_call_list_parse(data, len,
|
||||
priv->options.data_call_format);
|
||||
priv->vendor_hook, priv->options.data_call_format);
|
||||
}
|
||||
|
||||
if (list) {
|
||||
@@ -854,19 +896,23 @@ static gboolean ril_data_call_setup_submit(struct ril_data_request *req)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: add comments about tethering, other non-public
|
||||
* profiles...
|
||||
*/
|
||||
ioreq = grilio_request_new();
|
||||
grilio_request_append_int32(ioreq, 7 /* Parameter count */);
|
||||
grilio_request_append_format(ioreq, "%d", tech);
|
||||
grilio_request_append_utf8(ioreq, DATA_PROFILE_DEFAULT_STR);
|
||||
grilio_request_append_utf8(ioreq, setup->apn);
|
||||
grilio_request_append_utf8(ioreq, setup->username);
|
||||
grilio_request_append_utf8(ioreq, setup->password);
|
||||
grilio_request_append_format(ioreq, "%d", auth);
|
||||
grilio_request_append_utf8(ioreq, proto_str);
|
||||
/* Give vendor code a chance to build a vendor specific packet */
|
||||
ioreq = ril_vendor_hook_data_call_req(priv->vendor_hook, tech,
|
||||
DATA_PROFILE_DEFAULT_STR, setup->apn, setup->username,
|
||||
setup->password, auth, proto_str);
|
||||
|
||||
if (!ioreq) {
|
||||
/* The default one */
|
||||
ioreq = grilio_request_new();
|
||||
grilio_request_append_int32(ioreq, 7 /* Parameter count */);
|
||||
grilio_request_append_format(ioreq, "%d", tech);
|
||||
grilio_request_append_utf8(ioreq, DATA_PROFILE_DEFAULT_STR);
|
||||
grilio_request_append_utf8(ioreq, setup->apn);
|
||||
grilio_request_append_utf8(ioreq, setup->username);
|
||||
grilio_request_append_utf8(ioreq, setup->password);
|
||||
grilio_request_append_format(ioreq, "%d", auth);
|
||||
grilio_request_append_utf8(ioreq, proto_str);
|
||||
}
|
||||
|
||||
GASSERT(!req->pending_id);
|
||||
req->pending_id = grilio_queue_send_request_full(priv->q, ioreq,
|
||||
@@ -1114,7 +1160,8 @@ static gint ril_data_compare_cb(gconstpointer a, gconstpointer b)
|
||||
struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
|
||||
struct ril_radio *radio, struct ril_network *network,
|
||||
GRilIoChannel *io, const struct ril_data_options *options,
|
||||
const struct ril_slot_config *config)
|
||||
const struct ril_slot_config *config,
|
||||
struct ril_vendor_hook *vendor_hook)
|
||||
{
|
||||
GASSERT(dm);
|
||||
if (G_LIKELY(dm)) {
|
||||
@@ -1147,6 +1194,7 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
|
||||
priv->dm = ril_data_manager_ref(dm);
|
||||
priv->radio = ril_radio_ref(radio);
|
||||
priv->network = ril_network_ref(network);
|
||||
priv->vendor_hook = ril_vendor_hook_ref(vendor_hook);
|
||||
priv->io_event_id = grilio_channel_add_unsol_event_handler(io,
|
||||
ril_data_call_list_changed_cb,
|
||||
RIL_UNSOL_DATA_CALL_LIST_CHANGED, self);
|
||||
@@ -1457,6 +1505,7 @@ static void ril_data_finalize(GObject *object)
|
||||
ril_network_unref(priv->network);
|
||||
ril_data_manager_unref(priv->dm);
|
||||
ril_data_call_list_free(self->data_calls);
|
||||
ril_vendor_hook_unref(priv->vendor_hook);
|
||||
G_OBJECT_CLASS(ril_data_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,8 @@ typedef void (*ril_data_call_deactivate_cb_t)(struct ril_data *data,
|
||||
struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
|
||||
struct ril_radio *radio, struct ril_network *network,
|
||||
GRilIoChannel *io, const struct ril_data_options *options,
|
||||
const struct ril_slot_config *config);
|
||||
const struct ril_slot_config *config,
|
||||
struct ril_vendor_hook *vendor_hook);
|
||||
struct ril_data *ril_data_ref(struct ril_data *data);
|
||||
void ril_data_unref(struct ril_data *data);
|
||||
gboolean ril_data_allowed(struct ril_data *data);
|
||||
@@ -124,6 +125,9 @@ struct ril_data_call *ril_data_call_dup(const struct ril_data_call *call);
|
||||
struct ril_data_call *ril_data_call_find(struct ril_data_call_list *list,
|
||||
int cid);
|
||||
|
||||
const char *ril_data_ofono_protocol_to_ril(enum ofono_gprs_proto proto);
|
||||
int ril_data_protocol_to_ofono(const gchar *str);
|
||||
|
||||
/* Constructors of various kinds of RIL requests */
|
||||
GRilIoRequest *ril_request_allow_data_new(gboolean allow);
|
||||
GRilIoRequest *ril_request_deactivate_data_call_new(int cid);
|
||||
|
||||
@@ -58,8 +58,6 @@ struct ril_modem_data {
|
||||
char *imeisv;
|
||||
char *imei;
|
||||
char *ecclist_file;
|
||||
gboolean pre_sim_done;
|
||||
gboolean allow_data;
|
||||
gulong imsi_event_id;
|
||||
|
||||
guint online_check_id;
|
||||
@@ -249,7 +247,6 @@ static void ril_modem_pre_sim(struct ofono_modem *modem)
|
||||
struct ril_modem_data *md = ril_modem_data_from_ofono(modem);
|
||||
|
||||
DBG("%s", ofono_modem_get_path(modem));
|
||||
md->pre_sim_done = TRUE;
|
||||
ofono_devinfo_create(modem, 0, RILMODEM_DRIVER, md);
|
||||
ofono_sim_create(modem, 0, RILMODEM_DRIVER, md);
|
||||
if (md->modem.config.enable_voicecall) {
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "ril_radio_caps.h"
|
||||
#include "ril_data.h"
|
||||
#include "ril_util.h"
|
||||
#include "ril_vendor.h"
|
||||
#include "ril_log.h"
|
||||
|
||||
#include <sailfish_manager.h>
|
||||
@@ -102,6 +103,7 @@
|
||||
#define RILCONF_ALLOW_DATA_REQ "allowDataReq"
|
||||
#define RILCONF_EMPTY_PIN_QUERY "emptyPinQuery"
|
||||
#define RILCONF_DATA_CALL_FORMAT "dataCallFormat"
|
||||
#define RILCONF_VENDOR_DRIVER "vendorDriver"
|
||||
#define RILCONF_DATA_CALL_RETRY_LIMIT "dataCallRetryLimit"
|
||||
#define RILCONF_DATA_CALL_RETRY_DELAY "dataCallRetryDelay"
|
||||
#define RILCONF_LOCAL_HANGUP_REASONS "localHangupReasons"
|
||||
@@ -184,6 +186,8 @@ typedef struct sailfish_slot_impl {
|
||||
struct ril_sim_card *sim_card;
|
||||
struct ril_sim_settings *sim_settings;
|
||||
struct ril_oem_raw *oem_raw;
|
||||
const struct ril_vendor_driver *vendor;
|
||||
struct ril_vendor_hook *vendor_hook;
|
||||
struct ril_data *data;
|
||||
gboolean legacy_imei_query;
|
||||
guint start_timeout;
|
||||
@@ -397,6 +401,11 @@ static void ril_plugin_shutdown_slot(ril_slot *slot, gboolean kill_io)
|
||||
slot->received_sim_status = FALSE;
|
||||
}
|
||||
|
||||
if (slot->vendor_hook) {
|
||||
ril_vendor_hook_unref(slot->vendor_hook);
|
||||
slot->vendor_hook = NULL;
|
||||
}
|
||||
|
||||
if (slot->io) {
|
||||
int i;
|
||||
|
||||
@@ -715,10 +724,12 @@ static void ril_plugin_caps_switch_aborted(struct ril_radio_caps_manager *mgr,
|
||||
static void ril_plugin_trace(GRilIoChannel *io, GRILIO_PACKET_TYPE type,
|
||||
guint id, guint code, const void *data, guint data_len, void *user_data)
|
||||
{
|
||||
static const GLogModule *log_module = &ril_debug_trace_module;
|
||||
ril_slot *slot = user_data;
|
||||
struct ril_vendor_hook *hook = slot->vendor_hook;
|
||||
static const GLogModule* log_module = &ril_debug_trace_module;
|
||||
const char *prefix = io->name ? io->name : "";
|
||||
const char dir = (type == GRILIO_PACKET_REQ) ? '<' : '>';
|
||||
const char *scode;
|
||||
const char *scode = NULL;
|
||||
|
||||
switch (type) {
|
||||
case GRILIO_PACKET_REQ:
|
||||
@@ -726,7 +737,10 @@ static void ril_plugin_trace(GRilIoChannel *io, GRILIO_PACKET_TYPE type,
|
||||
code == RIL_REQUEST_V9_SET_UICC_SUBSCRIPTION) {
|
||||
scode = "V9_SET_UICC_SUBSCRIPTION";
|
||||
} else {
|
||||
scode = ril_request_to_string(code);
|
||||
scode = ril_vendor_hook_request_to_string(hook, code);
|
||||
if (!scode) {
|
||||
scode = ril_request_to_string(code);
|
||||
}
|
||||
}
|
||||
gutil_log(log_module, GLOG_LEVEL_VERBOSE, "%s%c [%08x] %s",
|
||||
prefix, dir, id, scode);
|
||||
@@ -742,8 +756,12 @@ static void ril_plugin_trace(GRilIoChannel *io, GRILIO_PACKET_TYPE type,
|
||||
break;
|
||||
case GRILIO_PACKET_UNSOL:
|
||||
case GRILIO_PACKET_UNSOL_ACK_EXP:
|
||||
scode = ril_vendor_hook_event_to_string(hook, code);
|
||||
if (!scode) {
|
||||
scode = ril_unsol_event_to_string(code);
|
||||
}
|
||||
gutil_log(log_module, GLOG_LEVEL_VERBOSE, "%s%c %s",
|
||||
prefix, dir, ril_unsol_event_to_string(code));
|
||||
prefix, dir, scode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -939,6 +957,10 @@ static void ril_plugin_slot_connected(ril_slot *slot)
|
||||
*/
|
||||
ril_plugin_start_imei_query(slot, TRUE, -1);
|
||||
|
||||
GASSERT(!slot->vendor_hook);
|
||||
slot->vendor_hook = ril_vendor_create_hook(slot->vendor, slot->io,
|
||||
slot->path, &slot->config);
|
||||
|
||||
GASSERT(!slot->radio);
|
||||
slot->radio = ril_radio_new(slot->io);
|
||||
|
||||
@@ -965,7 +987,7 @@ static void ril_plugin_slot_connected(ril_slot *slot)
|
||||
GASSERT(!slot->data);
|
||||
slot->data = ril_data_new(plugin->data_manager, log_prefix,
|
||||
slot->radio, slot->network, slot->io, &slot->data_opt,
|
||||
&slot->config);
|
||||
&slot->config, slot->vendor_hook);
|
||||
|
||||
GASSERT(!slot->cell_info);
|
||||
if (slot->io->ril_version >= 9) {
|
||||
@@ -1175,6 +1197,23 @@ static ril_slot *ril_plugin_slot_new_take(char *sockpath, char *path,
|
||||
return slot;
|
||||
}
|
||||
|
||||
static void ril_plugin_slot_apply_vendor_defaults(ril_slot *slot)
|
||||
{
|
||||
if (slot->vendor) {
|
||||
struct ril_slot_config *config = &slot->config;
|
||||
struct ril_vendor_defaults defaults;
|
||||
|
||||
/* Let the vendor extension to adjust (some) defaults */
|
||||
memset(&defaults, 0, sizeof(defaults));
|
||||
defaults.empty_pin_query = config->empty_pin_query;
|
||||
defaults.legacy_imei_query = slot->legacy_imei_query;
|
||||
|
||||
ril_vendor_get_defaults(slot->vendor, &defaults);
|
||||
config->empty_pin_query = defaults.empty_pin_query;
|
||||
slot->legacy_imei_query = defaults.legacy_imei_query;
|
||||
}
|
||||
}
|
||||
|
||||
static ril_slot *ril_plugin_slot_new(const char *sockpath, const char *path,
|
||||
const char *name, guint slot_index)
|
||||
{
|
||||
@@ -1244,6 +1283,25 @@ static ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
|
||||
DBG("%s: " RILCONF_SLOT " %u", group, config->slot);
|
||||
}
|
||||
|
||||
/* vendorDriver */
|
||||
sval = ril_config_get_string(file, group, RILCONF_VENDOR_DRIVER);
|
||||
if (sval) {
|
||||
const struct ril_vendor_driver *vendor;
|
||||
RIL_VENDOR_DRIVER_FOREACH(vendor) {
|
||||
if (!strcasecmp(vendor->name, sval)) {
|
||||
DBG("%s: " RILCONF_VENDOR_DRIVER " %s", group,
|
||||
sval);
|
||||
slot->vendor = vendor;
|
||||
ril_plugin_slot_apply_vendor_defaults(slot);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!slot->vendor) {
|
||||
ofono_warn("Unknown vendor '%s'", sval);
|
||||
}
|
||||
g_free(sval);
|
||||
}
|
||||
|
||||
/* startTimeout */
|
||||
if (ril_config_get_integer(file, group, RILCONF_START_TIMEOUT,
|
||||
&ival) && ival >= 0) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2015-2017 Jolla Ltd.
|
||||
* Copyright (C) 2015-2018 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,11 +18,15 @@
|
||||
#include "ril_util.h"
|
||||
#include "ril_log.h"
|
||||
|
||||
#include "sailfish_watch.h"
|
||||
#include "simutil.h"
|
||||
#include "util.h"
|
||||
#include "ofono.h"
|
||||
|
||||
#define SIM_STATE_CHANGE_TIMEOUT_SECS (5)
|
||||
#define FAC_LOCK_QUERY_TIMEOUT_SECS (10)
|
||||
#define FAC_LOCK_QUERY_RETRIES (1)
|
||||
#define SIM_IO_TIMEOUT_SECS (20)
|
||||
|
||||
#define EF_STATUS_INVALIDATED 0
|
||||
#define EF_STATUS_VALID 1
|
||||
@@ -75,13 +79,16 @@ struct ril_sim {
|
||||
int retries[OFONO_SIM_PASSWORD_INVALID];
|
||||
gboolean empty_pin_query_allowed;
|
||||
gboolean inserted;
|
||||
guint idle_id;
|
||||
guint idle_id; /* Used by register and SIM reset callbacks */
|
||||
gulong card_event_id[SIM_CARD_EVENT_COUNT];
|
||||
guint query_pin_retries_id;
|
||||
|
||||
const char *log_prefix;
|
||||
char *allocated_log_prefix;
|
||||
|
||||
struct sailfish_watch *watch;
|
||||
gulong sim_state_watch_id;
|
||||
|
||||
/* query_passwd_state context */
|
||||
ofono_sim_passwd_cb_t query_passwd_state_cb;
|
||||
void *query_passwd_state_cb_data;
|
||||
@@ -485,6 +492,7 @@ static void ril_sim_request_io(struct ril_sim *sd, guint cmd, int fileid,
|
||||
grilio_request_append_utf8(req, ril_sim_app_id(sd));
|
||||
|
||||
grilio_request_set_blocking(req, TRUE);
|
||||
grilio_request_set_timeout(req, SIM_IO_TIMEOUT_SECS * 1000);
|
||||
cbd->req_id = grilio_queue_send_request_full(sd->q, req,
|
||||
RIL_REQUEST_SIM_IO, cb, ril_sim_cbd_free, cbd);
|
||||
ril_sim_card_sim_io_started(sd->card, cbd->req_id);
|
||||
@@ -850,6 +858,34 @@ static void ril_sim_status_changed_cb(struct ril_sim_card *sc, void *user_data)
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean ril_sim_reinsert_cb(gpointer data)
|
||||
{
|
||||
struct ril_sim *sd = data;
|
||||
const enum ofono_sim_state state = ofono_sim_get_state(sd->watch->sim);
|
||||
|
||||
GASSERT(sd->idle_id);
|
||||
sd->idle_id = 0;
|
||||
|
||||
if (state == OFONO_SIM_STATE_RESETTING && sd->inserted) {
|
||||
DBG_(sd, "reinserting SIM");
|
||||
ofono_sim_inserted_notify(sd->sim, TRUE);
|
||||
}
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void ril_sim_state_changed_cb(struct sailfish_watch *watch, void *data)
|
||||
{
|
||||
struct ril_sim *sd = data;
|
||||
const enum ofono_sim_state state = ofono_sim_get_state(watch->sim);
|
||||
|
||||
DBG_(sd, "%d %d", state, sd->inserted);
|
||||
if (state == OFONO_SIM_STATE_RESETTING && sd->inserted &&
|
||||
!sd->idle_id) {
|
||||
sd->idle_id = g_idle_add(ril_sim_reinsert_cb, sd);
|
||||
}
|
||||
}
|
||||
|
||||
static int ril_sim_parse_retry_count(const void *data, guint len)
|
||||
{
|
||||
int retry_count = -1;
|
||||
@@ -864,10 +900,14 @@ static int ril_sim_parse_retry_count(const void *data, guint len)
|
||||
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) {
|
||||
if (sd->card->app) {
|
||||
/*
|
||||
* If there's no AID then so be it... Some
|
||||
* adaptations (namely, MTK) don't provide it
|
||||
* but don't seem to require it either.
|
||||
*/
|
||||
GRilIoRequest *req = grilio_request_array_utf8_new(2,
|
||||
pin, app_id);
|
||||
pin, sd->card->app->aid);
|
||||
|
||||
grilio_request_set_blocking(req, TRUE);
|
||||
return req;
|
||||
@@ -1356,6 +1396,13 @@ static void ril_sim_query_facility_lock_cb(GRilIoChannel *io, int status,
|
||||
cb(ril_error_failure(&error), FALSE, cbd->data);
|
||||
}
|
||||
|
||||
static gboolean ril_sim_query_facility_lock_retry(GRilIoRequest* req,
|
||||
int ril_status, const void* response_data,
|
||||
guint response_len, void* user_data)
|
||||
{
|
||||
return (ril_status == GRILIO_STATUS_TIMEOUT);
|
||||
}
|
||||
|
||||
static void ril_sim_query_facility_lock(struct ofono_sim *sim,
|
||||
enum ofono_sim_password_type type,
|
||||
ofono_query_facility_lock_cb_t cb, void *data)
|
||||
@@ -1366,6 +1413,11 @@ static void ril_sim_query_facility_lock(struct ofono_sim *sim,
|
||||
GRilIoRequest *req = grilio_request_array_utf8_new(4,
|
||||
type_str, "", "0" /* class */, ril_sim_app_id(sd));
|
||||
|
||||
/* Make sure that this request gets completed sooner or later */
|
||||
grilio_request_set_timeout(req, FAC_LOCK_QUERY_TIMEOUT_SECS * 1000);
|
||||
grilio_request_set_retry(req, RIL_RETRY_MS, FAC_LOCK_QUERY_RETRIES);
|
||||
grilio_request_set_retry_func(req, ril_sim_query_facility_lock_retry);
|
||||
|
||||
DBG_(sd, "%s", type_str);
|
||||
cbd->req_id = grilio_queue_send_request_full(sd->q, req,
|
||||
RIL_REQUEST_QUERY_FACILITY_LOCK, ril_sim_query_facility_lock_cb,
|
||||
@@ -1391,6 +1443,9 @@ static gboolean ril_sim_register(gpointer user)
|
||||
sd->card_event_id[SIM_CARD_APP_EVENT] =
|
||||
ril_sim_card_add_app_changed_handler(sd->card,
|
||||
ril_sim_app_changed_cb, sd);
|
||||
sd->sim_state_watch_id =
|
||||
sailfish_watch_add_sim_state_changed_handler(sd->watch,
|
||||
ril_sim_state_changed_cb, sd);
|
||||
|
||||
/* Check the current state */
|
||||
ril_sim_status_changed_cb(sd->card, sd);
|
||||
@@ -1409,6 +1464,7 @@ static int ril_sim_probe(struct ofono_sim *sim, unsigned int vendor,
|
||||
sd->io = grilio_channel_ref(ril_modem_io(modem));
|
||||
sd->card = ril_sim_card_ref(modem->sim_card);
|
||||
sd->q = grilio_queue_new(sd->io);
|
||||
sd->watch = sailfish_watch_new(ril_modem_get_path(modem));
|
||||
|
||||
if (modem->log_prefix && modem->log_prefix[0]) {
|
||||
sd->log_prefix = sd->allocated_log_prefix =
|
||||
@@ -1445,6 +1501,9 @@ static void ril_sim_remove(struct ofono_sim *sim)
|
||||
sd->query_passwd_state_sim_status_refresh_id);
|
||||
}
|
||||
|
||||
sailfish_watch_remove_handler(sd->watch, sd->sim_state_watch_id);
|
||||
sailfish_watch_unref(sd->watch);
|
||||
|
||||
ril_sim_card_remove_handlers(sd->card, sd->card_event_id,
|
||||
G_N_ELEMENTS(sd->card_event_id));
|
||||
ril_sim_card_unref(sd->card);
|
||||
|
||||
@@ -41,10 +41,12 @@ struct ofono_sim;
|
||||
#define RIL_RETRY_MS (RIL_RETRY_SECS*1000)
|
||||
|
||||
struct ril_data;
|
||||
struct ril_data_call;
|
||||
struct ril_modem;
|
||||
struct ril_radio;
|
||||
struct ril_network;
|
||||
struct ril_sim_card;
|
||||
struct ril_vendor_hook;
|
||||
|
||||
struct ril_slot_config {
|
||||
guint slot;
|
||||
|
||||
165
ofono/drivers/ril/ril_vendor.c
Normal file
165
ofono/drivers/ril/ril_vendor.c
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "ril_vendor.h"
|
||||
#include "ril_log.h"
|
||||
|
||||
struct ril_vendor_hook *ril_vendor_create_hook
|
||||
(const struct ril_vendor_driver *vendor, GRilIoChannel *io,
|
||||
const char *path, const struct ril_slot_config *config)
|
||||
{
|
||||
if (vendor) {
|
||||
const void *data = vendor->driver_data;
|
||||
|
||||
/*
|
||||
* NOTE: we are looking for the callback in the base but
|
||||
* keeping the original driver data.
|
||||
*/
|
||||
while (!vendor->create_hook && vendor->base) {
|
||||
vendor = vendor->base;
|
||||
}
|
||||
if (vendor->create_hook) {
|
||||
return vendor->create_hook(data, io, path, config);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct ril_vendor_hook *ril_vendor_hook_init(struct ril_vendor_hook *self,
|
||||
const struct ril_vendor_hook_proc *proc)
|
||||
{
|
||||
self->proc = proc;
|
||||
g_atomic_int_set(&self->ref_count, 1);
|
||||
return self;
|
||||
}
|
||||
|
||||
struct ril_vendor_hook *ril_vendor_hook_ref(struct ril_vendor_hook *self)
|
||||
{
|
||||
if (self) {
|
||||
GASSERT(self->ref_count > 0);
|
||||
g_atomic_int_inc(&self->ref_count);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
static void ril_vendor_hook_free(struct ril_vendor_hook *self)
|
||||
{
|
||||
const struct ril_vendor_hook_proc *proc = self->proc;
|
||||
|
||||
while (!proc->free && proc->base) {
|
||||
proc = proc->base;
|
||||
}
|
||||
if (proc->free) {
|
||||
proc->free(self);
|
||||
}
|
||||
}
|
||||
|
||||
void ril_vendor_hook_unref(struct ril_vendor_hook *self)
|
||||
{
|
||||
if (self) {
|
||||
GASSERT(self->ref_count > 0);
|
||||
if (g_atomic_int_dec_and_test(&self->ref_count)) {
|
||||
ril_vendor_hook_free(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ril_vendor_get_defaults(const struct ril_vendor_driver *vendor,
|
||||
struct ril_vendor_defaults *defaults)
|
||||
{
|
||||
if (vendor) {
|
||||
while (!vendor->get_defaults && vendor->base) {
|
||||
vendor = vendor->base;
|
||||
}
|
||||
if (vendor->get_defaults) {
|
||||
vendor->get_defaults(defaults);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *ril_vendor_hook_request_to_string(struct ril_vendor_hook *self,
|
||||
guint request)
|
||||
{
|
||||
if (self) {
|
||||
const struct ril_vendor_hook_proc *proc = self->proc;
|
||||
|
||||
while (!proc->request_to_string && proc->base) {
|
||||
proc = proc->base;
|
||||
}
|
||||
if (proc->request_to_string) {
|
||||
return proc->request_to_string(self, request);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *ril_vendor_hook_event_to_string(struct ril_vendor_hook *self,
|
||||
guint event)
|
||||
{
|
||||
if (self) {
|
||||
const struct ril_vendor_hook_proc *proc = self->proc;
|
||||
|
||||
while (!proc->event_to_string && proc->base) {
|
||||
proc = proc->base;
|
||||
}
|
||||
if (proc->event_to_string) {
|
||||
return proc->event_to_string(self, event);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GRilIoRequest *ril_vendor_hook_data_call_req(struct ril_vendor_hook *self,
|
||||
int tech, const char *profile, const char *apn,
|
||||
const char *username, const char *password,
|
||||
enum ril_auth auth, const char *proto)
|
||||
{
|
||||
if (self) {
|
||||
const struct ril_vendor_hook_proc *proc = self->proc;
|
||||
|
||||
while (!proc->data_call_req && proc->base) {
|
||||
proc = proc->base;
|
||||
}
|
||||
if (proc->data_call_req) {
|
||||
return proc->data_call_req(self, tech, profile, apn,
|
||||
username, password, auth, proto);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean ril_vendor_hook_data_call_parse(struct ril_vendor_hook *self,
|
||||
struct ril_data_call *call, int ver, GRilIoParser *rilp)
|
||||
{
|
||||
if (self) {
|
||||
const struct ril_vendor_hook_proc *proc = self->proc;
|
||||
|
||||
while (!proc->data_call_parse && proc->base) {
|
||||
proc = proc->base;
|
||||
}
|
||||
if (proc->data_call_parse) {
|
||||
return proc->data_call_parse(self, call, ver, rilp);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
97
ofono/drivers/ril/ril_vendor.h
Normal file
97
ofono/drivers/ril/ril_vendor.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef RIL_VENDOR_H
|
||||
#define RIL_VENDOR_H
|
||||
|
||||
#include "ril_types.h"
|
||||
|
||||
struct ril_vendor_defaults {
|
||||
gboolean empty_pin_query;
|
||||
gboolean legacy_imei_query;
|
||||
};
|
||||
|
||||
struct ril_vendor_driver {
|
||||
const char *name;
|
||||
const void *driver_data;
|
||||
const struct ril_vendor_driver *base;
|
||||
void (*get_defaults)(struct ril_vendor_defaults *defaults);
|
||||
struct ril_vendor_hook *(*create_hook)(const void *driver_data,
|
||||
GRilIoChannel *io, const char *path,
|
||||
const struct ril_slot_config *cfg);
|
||||
};
|
||||
|
||||
struct ril_vendor_hook_proc {
|
||||
const struct ril_vendor_hook_proc *base;
|
||||
void (*free)(struct ril_vendor_hook *hook);
|
||||
const char *(*request_to_string)(struct ril_vendor_hook *hook,
|
||||
guint request);
|
||||
const char *(*event_to_string)(struct ril_vendor_hook *hook,
|
||||
guint event);
|
||||
GRilIoRequest *(*data_call_req)(struct ril_vendor_hook *hook,
|
||||
int tech, const char *profile, const char *apn,
|
||||
const char *username, const char *password,
|
||||
enum ril_auth auth, const char *proto);
|
||||
gboolean (*data_call_parse)(struct ril_vendor_hook *hook,
|
||||
struct ril_data_call *call, int version,
|
||||
GRilIoParser *rilp);
|
||||
};
|
||||
|
||||
struct ril_vendor_hook {
|
||||
const struct ril_vendor_hook_proc *proc;
|
||||
gint ref_count;
|
||||
};
|
||||
|
||||
struct ril_vendor_hook *ril_vendor_create_hook
|
||||
(const struct ril_vendor_driver *vendor, GRilIoChannel *io,
|
||||
const char *path, const struct ril_slot_config *cfg);
|
||||
void ril_vendor_get_defaults(const struct ril_vendor_driver *vendor,
|
||||
struct ril_vendor_defaults *defaults);
|
||||
|
||||
struct ril_vendor_hook *ril_vendor_hook_init(struct ril_vendor_hook *hook,
|
||||
const struct ril_vendor_hook_proc *proc);
|
||||
struct ril_vendor_hook *ril_vendor_hook_ref(struct ril_vendor_hook *hook);
|
||||
void ril_vendor_hook_unref(struct ril_vendor_hook *hook);
|
||||
|
||||
const char *ril_vendor_hook_request_to_string(struct ril_vendor_hook *hook,
|
||||
guint request);
|
||||
const char *ril_vendor_hook_event_to_string(struct ril_vendor_hook *hook,
|
||||
guint event);
|
||||
GRilIoRequest *ril_vendor_hook_data_call_req(struct ril_vendor_hook *hook,
|
||||
int tech, const char *profile, const char *apn,
|
||||
const char *username, const char *password,
|
||||
enum ril_auth auth, const char *proto);
|
||||
gboolean ril_vendor_hook_data_call_parse(struct ril_vendor_hook *hook,
|
||||
struct ril_data_call *call, int version,
|
||||
GRilIoParser *rilp);
|
||||
|
||||
/* Put vendor driver descriptors to the "__vendor" section */
|
||||
#define RIL_VENDOR_DRIVER_DEFINE(name) \
|
||||
const struct ril_vendor_driver name \
|
||||
__attribute__((used, section("__vendor"))) =
|
||||
#define RIL_VENDOR_DRIVER_FOREACH(var) \
|
||||
for ((var) = __start___vendor; (var) < __stop___vendor; (var)++)
|
||||
extern const struct ril_vendor_driver __start___vendor[];
|
||||
extern const struct ril_vendor_driver __stop___vendor[];
|
||||
|
||||
#endif /* RIL_VENDOR_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
488
ofono/drivers/ril/ril_vendor_mtk.c
Normal file
488
ofono/drivers/ril/ril_vendor_mtk.c
Normal file
@@ -0,0 +1,488 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "ril_plugin.h"
|
||||
#include "ril_vendor.h"
|
||||
#include "ril_data.h"
|
||||
#include "ril_log.h"
|
||||
|
||||
#include "sailfish_watch.h"
|
||||
|
||||
#include <grilio_channel.h>
|
||||
#include <grilio_parser.h>
|
||||
#include <grilio_request.h>
|
||||
#include <grilio_queue.h>
|
||||
|
||||
#include <gutil_macros.h>
|
||||
|
||||
#include "ofono.h"
|
||||
|
||||
enum ril_mtk_watch_events {
|
||||
WATCH_EVENT_SIM_CHANGED,
|
||||
WATCH_EVENT_COUNT
|
||||
};
|
||||
|
||||
enum ril_mtk_events {
|
||||
MTK_EVENT_REGISTRATION_SUSPENDED,
|
||||
MTK_EVENT_SET_ATTACH_APN,
|
||||
MTK_EVENT_COUNT
|
||||
};
|
||||
|
||||
struct ril_vendor_hook_mtk {
|
||||
struct ril_vendor_hook hook;
|
||||
const struct ril_mtk_msg *msg;
|
||||
GRilIoQueue *q;
|
||||
GRilIoChannel *io;
|
||||
struct sailfish_watch *watch;
|
||||
gulong ril_event_id[MTK_EVENT_COUNT];
|
||||
guint slot;
|
||||
};
|
||||
|
||||
/* driver_data point this this: */
|
||||
struct ril_vendor_mtk_driver_data {
|
||||
const char *name;
|
||||
const struct ril_mtk_msg *msg;
|
||||
const struct ril_vendor_hook_proc *proc;
|
||||
};
|
||||
|
||||
/* MTK specific RIL messages (actual codes differ from model to model!) */
|
||||
struct ril_mtk_msg {
|
||||
guint request_resume_registration;
|
||||
guint unsol_network_info;
|
||||
guint unsol_ps_network_state_changed;
|
||||
guint unsol_registration_suspended;
|
||||
guint unsol_ims_registration_info;
|
||||
guint unsol_volte_eps_network_feature_support;
|
||||
guint unsol_emergency_bearer_support_notify;
|
||||
guint unsol_set_attach_apn;
|
||||
};
|
||||
|
||||
/* Fly FS522 Cirrus 14 */
|
||||
static const struct ril_mtk_msg mtk_msg_mt6737 = {
|
||||
.request_resume_registration = 2050,
|
||||
.unsol_network_info = 3001,
|
||||
.unsol_ps_network_state_changed = 3012,
|
||||
.unsol_registration_suspended = 3021,
|
||||
.unsol_ims_registration_info = 3029,
|
||||
.unsol_volte_eps_network_feature_support = 3042,
|
||||
.unsol_emergency_bearer_support_notify = 3052,
|
||||
.unsol_set_attach_apn = 3065
|
||||
};
|
||||
|
||||
/* MT8735 Tablet */
|
||||
static const struct ril_mtk_msg mtk_msg_mt8735 = {
|
||||
.request_resume_registration = 2065,
|
||||
.unsol_network_info = 3001,
|
||||
.unsol_ps_network_state_changed = 3015,
|
||||
.unsol_ims_registration_info = 3033,
|
||||
.unsol_volte_eps_network_feature_support = 3048,
|
||||
.unsol_emergency_bearer_support_notify = 3059,
|
||||
.unsol_registration_suspended = 3024
|
||||
};
|
||||
|
||||
static inline struct ril_vendor_hook_mtk *ril_vendor_hook_mtk_cast
|
||||
(struct ril_vendor_hook *hook)
|
||||
{
|
||||
return G_CAST(hook, struct ril_vendor_hook_mtk, hook);
|
||||
}
|
||||
|
||||
static const char *ril_vendor_mtk_request_to_string
|
||||
(struct ril_vendor_hook *hook, guint request)
|
||||
{
|
||||
struct ril_vendor_hook_mtk *self = ril_vendor_hook_mtk_cast(hook);
|
||||
const struct ril_mtk_msg *msg = self->msg;
|
||||
|
||||
if (request == msg->request_resume_registration) {
|
||||
return "MTK_RESUME_REGISTRATION";
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *ril_vendor_mtk_event_to_string(struct ril_vendor_hook *hook,
|
||||
guint event)
|
||||
{
|
||||
struct ril_vendor_hook_mtk *self = ril_vendor_hook_mtk_cast(hook);
|
||||
const struct ril_mtk_msg *msg = self->msg;
|
||||
|
||||
if (event == msg->unsol_network_info) {
|
||||
return "MTK_NETWORK_INFO";
|
||||
} else if (event == msg->unsol_ps_network_state_changed) {
|
||||
return "MTK_PS_NETWORK_STATE_CHANGED";
|
||||
} else if (event == msg->unsol_registration_suspended) {
|
||||
return "MTK_REGISTRATION_SUSPENDED";
|
||||
} else if (event == msg->unsol_ims_registration_info) {
|
||||
return "MTK_IMS_REGISTRATION_INFO";
|
||||
} else if (event == msg->unsol_volte_eps_network_feature_support) {
|
||||
return "MTK_VOLTE_EPS_NETWORK_FEATURE_SUPPORT";
|
||||
} else if (event == msg->unsol_emergency_bearer_support_notify) {
|
||||
return "MTK_EMERGENCY_BEARER_SUPPORT_NOTIFY";
|
||||
} else if (event == msg->unsol_set_attach_apn) {
|
||||
return "MTK_SET_ATTACH_APN";
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_vendor_mtk_registration_suspended(GRilIoChannel *io, guint id,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ril_vendor_hook_mtk *self = user_data;
|
||||
const struct ril_mtk_msg *msg = self->msg;
|
||||
GRilIoParser rilp;
|
||||
int session_id;
|
||||
|
||||
GASSERT(id == msg->unsol_registration_suspended);
|
||||
grilio_parser_init(&rilp, data, len);
|
||||
if (grilio_parser_get_int32(&rilp, NULL) &&
|
||||
grilio_parser_get_int32(&rilp, &session_id)) {
|
||||
GRilIoRequest* req = grilio_request_new();
|
||||
DBG("slot=%u,session_id=%d", self->slot, session_id);
|
||||
grilio_request_append_int32(req, 1);
|
||||
grilio_request_append_int32(req, session_id);
|
||||
grilio_queue_send_request(self->q, req,
|
||||
msg->request_resume_registration);
|
||||
grilio_request_unref(req);
|
||||
}
|
||||
}
|
||||
|
||||
static void ril_vendor_mtk_set_attach_apn(GRilIoChannel *io, guint id,
|
||||
const void *data, guint len, void *user_data)
|
||||
{
|
||||
struct ril_vendor_hook_mtk *self = user_data;
|
||||
struct sailfish_watch *watch = self->watch;
|
||||
struct ofono_atom * gprs_atom = __ofono_modem_find_atom(watch->modem,
|
||||
OFONO_ATOM_TYPE_GPRS);
|
||||
struct ofono_gprs *gprs = gprs_atom ?
|
||||
__ofono_atom_get_data(gprs_atom) : NULL;
|
||||
const struct ofono_gprs_primary_context *pc =
|
||||
(gprs && watch->imsi) ?
|
||||
__ofono_gprs_context_settings_by_type(gprs,
|
||||
OFONO_GPRS_CONTEXT_TYPE_INTERNET) : NULL;
|
||||
|
||||
/* authtype, username, password */
|
||||
if (pc) {
|
||||
GRilIoRequest *req = grilio_request_new();
|
||||
const char *proto = ril_data_ofono_protocol_to_ril(pc->proto);
|
||||
|
||||
DBG("%s",pc->apn);
|
||||
grilio_request_append_utf8(req, pc->apn); /* apn */
|
||||
grilio_request_append_utf8(req, proto); /* protocol */
|
||||
grilio_request_append_utf8(req, proto); /* roamingProtocol */
|
||||
|
||||
if (pc->username[0]) {
|
||||
int auth;
|
||||
|
||||
switch (pc->auth_method) {
|
||||
case OFONO_GPRS_AUTH_METHOD_ANY:
|
||||
auth = RIL_AUTH_BOTH;
|
||||
break;
|
||||
case OFONO_GPRS_AUTH_METHOD_NONE:
|
||||
auth = RIL_AUTH_NONE;
|
||||
break;
|
||||
case OFONO_GPRS_AUTH_METHOD_CHAP:
|
||||
auth = RIL_AUTH_CHAP;
|
||||
break;
|
||||
case OFONO_GPRS_AUTH_METHOD_PAP:
|
||||
auth = RIL_AUTH_PAP;
|
||||
break;
|
||||
default:
|
||||
auth = RIL_AUTH_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
grilio_request_append_int32(req, auth);
|
||||
grilio_request_append_utf8(req, pc->username);
|
||||
grilio_request_append_utf8(req, pc->password);
|
||||
} else {
|
||||
grilio_request_append_int32(req, RIL_AUTH_NONE);
|
||||
grilio_request_append_utf8(req, "");
|
||||
grilio_request_append_utf8(req, "");
|
||||
}
|
||||
|
||||
grilio_request_append_utf8(req, ""); /* operatorNumeric */
|
||||
grilio_request_append_int32(req, FALSE); /* canHandleIms */
|
||||
grilio_request_append_int32(req, 0); /* Some sort of count */
|
||||
grilio_queue_send_request(self->q, req,
|
||||
RIL_REQUEST_SET_INITIAL_ATTACH_APN);
|
||||
grilio_request_unref(req);
|
||||
}
|
||||
}
|
||||
|
||||
static GRilIoRequest* ril_vendor_mtk_data_call_req
|
||||
(struct ril_vendor_hook *hook, int tech, const char *profile,
|
||||
const char *apn, const char *username, const char *password,
|
||||
enum ril_auth auth, const char *proto)
|
||||
{
|
||||
struct ril_vendor_hook_mtk *self = ril_vendor_hook_mtk_cast(hook);
|
||||
GRilIoRequest *req = grilio_request_new();
|
||||
|
||||
grilio_request_append_int32(req, 8); /* Number of parameters */
|
||||
grilio_request_append_format(req, "%d", tech);
|
||||
grilio_request_append_utf8(req, profile);
|
||||
grilio_request_append_utf8(req, apn);
|
||||
grilio_request_append_utf8(req, username);
|
||||
grilio_request_append_utf8(req, password);
|
||||
grilio_request_append_format(req, "%d", auth);
|
||||
grilio_request_append_utf8(req, proto);
|
||||
grilio_request_append_format(req, "%d", self->slot+1);
|
||||
return req;
|
||||
}
|
||||
|
||||
static gboolean ril_vendor_mtk_data_call_parse_v6(struct ril_vendor_hook *hook,
|
||||
struct ril_data_call *call, int version,
|
||||
GRilIoParser *rilp)
|
||||
{
|
||||
if (version < 11) {
|
||||
int prot;
|
||||
char *prot_str;
|
||||
guint32 status = PDP_FAIL_ERROR_UNSPECIFIED;
|
||||
guint32 active = RIL_DATA_CALL_INACTIVE;
|
||||
|
||||
/* RIL_Data_Call_Response_v6 with MTK specific additions */
|
||||
grilio_parser_get_uint32(rilp, &status);
|
||||
grilio_parser_get_int32(rilp, &call->retry_time);
|
||||
grilio_parser_get_int32(rilp, &call->cid);
|
||||
grilio_parser_get_uint32(rilp, &active);
|
||||
grilio_parser_get_int32(rilp, &call->mtu); /* MTK specific */
|
||||
prot_str = grilio_parser_get_utf8(rilp);
|
||||
prot = ril_data_protocol_to_ofono(prot_str);
|
||||
g_free(prot_str);
|
||||
|
||||
if (prot >= 0) {
|
||||
call->ifname = grilio_parser_get_utf8(rilp);
|
||||
call->addresses = grilio_parser_split_utf8(rilp, " ");
|
||||
call->dnses = grilio_parser_split_utf8(rilp, " ");
|
||||
call->gateways = grilio_parser_split_utf8(rilp, " ");
|
||||
if (call->ifname && call->addresses) {
|
||||
call->prot = prot;
|
||||
call->status = status;
|
||||
call->active = active;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void ril_vendor_mtk_get_defaults(struct ril_vendor_defaults *defaults)
|
||||
{
|
||||
defaults->empty_pin_query = FALSE;
|
||||
defaults->legacy_imei_query = TRUE;
|
||||
}
|
||||
|
||||
static struct ril_vendor_hook *ril_vendor_mtk_create_hook_from_data
|
||||
(const void *driver_data, GRilIoChannel *io, const char *path,
|
||||
const struct ril_slot_config *config)
|
||||
{
|
||||
const struct ril_vendor_mtk_driver_data *mtk_driver_data = driver_data;
|
||||
const struct ril_mtk_msg *msg = mtk_driver_data->msg;
|
||||
struct ril_vendor_hook_mtk *self =
|
||||
g_new0(struct ril_vendor_hook_mtk, 1);
|
||||
|
||||
self->msg = msg;
|
||||
self->q = grilio_queue_new(io);
|
||||
self->io = grilio_channel_ref(io);
|
||||
self->watch = sailfish_watch_new(path);
|
||||
self->slot = config->slot;
|
||||
self->ril_event_id[MTK_EVENT_REGISTRATION_SUSPENDED] =
|
||||
grilio_channel_add_unsol_event_handler(self->io,
|
||||
ril_vendor_mtk_registration_suspended,
|
||||
msg->unsol_registration_suspended, self);
|
||||
if (msg->unsol_set_attach_apn) {
|
||||
self->ril_event_id[MTK_EVENT_SET_ATTACH_APN] =
|
||||
grilio_channel_add_unsol_event_handler(self->io,
|
||||
ril_vendor_mtk_set_attach_apn,
|
||||
msg->unsol_set_attach_apn, self);
|
||||
}
|
||||
DBG("%s slot %u", mtk_driver_data->name, self->slot);
|
||||
return ril_vendor_hook_init(&self->hook, mtk_driver_data->proc);
|
||||
}
|
||||
|
||||
static void ril_vendor_mtk_free(struct ril_vendor_hook *hook)
|
||||
{
|
||||
struct ril_vendor_hook_mtk *self = ril_vendor_hook_mtk_cast(hook);
|
||||
|
||||
DBG("slot %u", self->slot);
|
||||
grilio_queue_cancel_all(self->q, FALSE);
|
||||
grilio_channel_remove_all_handlers(self->io, self->ril_event_id);
|
||||
grilio_queue_unref(self->q);
|
||||
grilio_channel_unref(self->io);
|
||||
sailfish_watch_unref(self->watch);
|
||||
g_free(self);
|
||||
}
|
||||
|
||||
static const struct ril_vendor_hook_proc ril_vendor_mtk_hook_base_proc = {
|
||||
.free = ril_vendor_mtk_free,
|
||||
.request_to_string = ril_vendor_mtk_request_to_string,
|
||||
.event_to_string = ril_vendor_mtk_event_to_string,
|
||||
.data_call_req = ril_vendor_mtk_data_call_req
|
||||
};
|
||||
|
||||
static const struct ril_vendor_driver ril_vendor_mtk_base = {
|
||||
.get_defaults = ril_vendor_mtk_get_defaults,
|
||||
.create_hook = ril_vendor_mtk_create_hook_from_data
|
||||
};
|
||||
|
||||
static const struct ril_vendor_mtk_driver_data ril_vendor_mtk_mt6737_data = {
|
||||
.name = "MT6737",
|
||||
.msg = &mtk_msg_mt6737,
|
||||
.proc = &ril_vendor_mtk_hook_base_proc
|
||||
};
|
||||
|
||||
static struct ril_vendor_hook_proc ril_vendor_mtk_mt8735_proc = {
|
||||
.base = &ril_vendor_mtk_hook_base_proc,
|
||||
.data_call_parse = ril_vendor_mtk_data_call_parse_v6
|
||||
};
|
||||
|
||||
static const struct ril_vendor_mtk_driver_data ril_vendor_mtk_mt8735_data = {
|
||||
.name = "MT8735",
|
||||
.msg = &mtk_msg_mt8735,
|
||||
.proc = &ril_vendor_mtk_mt8735_proc
|
||||
};
|
||||
|
||||
RIL_VENDOR_DRIVER_DEFINE(ril_vendor_driver_mt6737) {
|
||||
.name = "mt6737t",
|
||||
.driver_data = &ril_vendor_mtk_mt6737_data,
|
||||
.base = &ril_vendor_mtk_base
|
||||
};
|
||||
|
||||
RIL_VENDOR_DRIVER_DEFINE(ril_vendor_driver_mt8735) {
|
||||
.name = "mt8735",
|
||||
.driver_data = &ril_vendor_mtk_mt8735_data,
|
||||
.base = &ril_vendor_mtk_base
|
||||
};
|
||||
|
||||
#define DEFAULT_MTK_DRIVER (&ril_vendor_driver_mt6737)
|
||||
|
||||
static const struct ril_vendor_driver *mtk_hw_drivers [] = {
|
||||
&ril_vendor_driver_mt6737,
|
||||
&ril_vendor_driver_mt8735
|
||||
};
|
||||
|
||||
/* Automatic driver selection based on /proc/cpuinfo */
|
||||
|
||||
static GString *ril_vendor_mtk_read_line(GString *buf, FILE *f)
|
||||
{
|
||||
int c = fgetc(f);
|
||||
|
||||
g_string_truncate(buf, 0);
|
||||
if (c != EOF) {
|
||||
/* Read the line char by char until we hit EOF or EOL */
|
||||
while (c != EOF && c != '\r' && c != '\n') {
|
||||
g_string_append_c(buf, c);
|
||||
c = fgetc(f);
|
||||
}
|
||||
/* Skip EOL characters */
|
||||
while (c != EOF && (c == '\r' || c == '\n')) {
|
||||
c = fgetc(f);
|
||||
}
|
||||
/* Unget the last char (the first char of the next line) */
|
||||
if (c != EOF) {
|
||||
ungetc(c, f);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *ril_vendor_mtk_hardware()
|
||||
{
|
||||
FILE *f = fopen("/proc/cpuinfo", "r");
|
||||
char *hardware = NULL;
|
||||
|
||||
if (f) {
|
||||
const char prefix[] = "Hardware\t:";
|
||||
const gsize prefix_len = sizeof(prefix) - 1;
|
||||
GString *buf = g_string_new("");
|
||||
|
||||
/* Find the "Hardware:" line */
|
||||
while (ril_vendor_mtk_read_line(buf, f) &&
|
||||
strncmp(buf->str, prefix, prefix_len));
|
||||
|
||||
if (buf->len > prefix_len) {
|
||||
/* Erase the prefix */
|
||||
g_string_erase(buf, 0, prefix_len);
|
||||
|
||||
/* Remove trailing whitespaces */
|
||||
while (buf->len > 0 &&
|
||||
g_ascii_isspace(buf->str[buf->len - 1])) {
|
||||
g_string_truncate(buf, buf->len - 1);
|
||||
}
|
||||
|
||||
/* Extract the last word */
|
||||
if (buf->len > 0) {
|
||||
gsize pos = buf->len;
|
||||
|
||||
while (pos > 0 &&
|
||||
!g_ascii_isspace(buf->str[pos - 1])) {
|
||||
pos--;
|
||||
}
|
||||
|
||||
if (buf->str[pos]) {
|
||||
hardware = g_strdup(buf->str + pos);
|
||||
DBG("Hardware: %s", hardware);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_string_free(buf, TRUE);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
return hardware;
|
||||
}
|
||||
|
||||
static const struct ril_vendor_driver *ril_vendor_mtk_detect()
|
||||
{
|
||||
const struct ril_vendor_driver *driver = DEFAULT_MTK_DRIVER;
|
||||
char *hw = ril_vendor_mtk_hardware();
|
||||
|
||||
if (hw) {
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS(mtk_hw_drivers); i++) {
|
||||
if (!strcasecmp(mtk_hw_drivers[i]->name, hw)) {
|
||||
driver = mtk_hw_drivers[i];
|
||||
DBG("Driver: %s", driver->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_free(hw);
|
||||
}
|
||||
return driver;
|
||||
}
|
||||
|
||||
static struct ril_vendor_hook *ril_vendor_mtk_create_hook_auto
|
||||
(const void *driver_data, GRilIoChannel *io, const char *path,
|
||||
const struct ril_slot_config *cfg)
|
||||
{
|
||||
return ril_vendor_create_hook(ril_vendor_mtk_detect(), io, path, cfg);
|
||||
}
|
||||
|
||||
RIL_VENDOR_DRIVER_DEFINE(ril_vendor_driver_mtk) {
|
||||
.name = "mtk",
|
||||
.get_defaults = ril_vendor_mtk_get_defaults,
|
||||
.create_hook = ril_vendor_mtk_create_hook_auto
|
||||
};
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
@@ -119,6 +119,13 @@ typedef void (*ofono_sms_filter_recv_datagram_cb_t)
|
||||
#define OFONO_SMS_FILTER_PRIORITY_DEFAULT (0)
|
||||
#define OFONO_SMS_FILTER_PRIORITY_HIGH (100)
|
||||
|
||||
/*
|
||||
* The api_version field makes it possible to keep using old plugins
|
||||
* even if struct ofono_sms_filter gets extended with new callbacks.
|
||||
*/
|
||||
|
||||
#define OFONO_SMS_FILTER_API_VERSION (0)
|
||||
|
||||
/*
|
||||
* The filter callbacks either invoke the completion callback directly
|
||||
* or return the id of the cancellable asynchronous operation (but never
|
||||
@@ -135,6 +142,7 @@ typedef void (*ofono_sms_filter_recv_datagram_cb_t)
|
||||
*/
|
||||
struct ofono_sms_filter {
|
||||
const char *name;
|
||||
int api_version; /* OFONO_SMS_FILTER_API_VERSION */
|
||||
int priority;
|
||||
unsigned int (*filter_send_text)(struct ofono_modem *modem,
|
||||
const struct ofono_sms_address *addr,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony - RIL-based devices
|
||||
*
|
||||
* Copyright (C) 2016-2017 Jolla Ltd.
|
||||
* Copyright (C) 2016-2018 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
|
||||
@@ -178,7 +178,7 @@ static void sailfish_cell_info_dbus_append_type(DBusMessageIter *it,
|
||||
static void sailfish_cell_info_dbus_append_registered(DBusMessageIter *it,
|
||||
const struct sailfish_cell_entry *entry)
|
||||
{
|
||||
dbus_bool_t registered = entry->cell.registered;
|
||||
const dbus_bool_t registered = (entry->cell.registered != FALSE);
|
||||
|
||||
dbus_message_iter_append_basic(it, DBUS_TYPE_BOOLEAN, ®istered);
|
||||
}
|
||||
@@ -279,8 +279,8 @@ static const GDBusSignalTable sailfish_cell_info_dbus_cell_signals[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct sailfish_cell_entry *sailfish_cell_info_dbus_find_id(
|
||||
struct sailfish_cell_info_dbus *dbus, guint id)
|
||||
static struct sailfish_cell_entry *sailfish_cell_info_dbus_find_id
|
||||
(struct sailfish_cell_info_dbus *dbus, guint id)
|
||||
{
|
||||
GSList *l;
|
||||
for (l = dbus->entries; l; l = l->next) {
|
||||
@@ -376,7 +376,7 @@ static void sailfish_cell_info_dbus_property_changed
|
||||
sailfish_cell_info_dbus_cell_properties(cell->type, &n);
|
||||
|
||||
if (mask & SAILFISH_CELL_PROPERTY_REGISTERED) {
|
||||
dbus_bool_t registered = cell->registered;
|
||||
const dbus_bool_t registered = (cell->registered != FALSE);
|
||||
g_dbus_emit_signal(dbus->conn, entry->path,
|
||||
CELL_DBUS_INTERFACE,
|
||||
CELL_DBUS_REGISTERED_CHANGED_SIGNAL,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2017 Jolla Ltd.
|
||||
* Copyright (C) 2017-2018 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
|
||||
@@ -795,9 +795,6 @@ void sailfish_manager_set_sim_state(struct sailfish_slot *s,
|
||||
slot->pub.sim_present = present;
|
||||
sailfish_manager_dbus_signal_sim(p->dbus,
|
||||
slot->index, present);
|
||||
if (!present) {
|
||||
sailfish_sim_info_invalidate(slot->siminfo);
|
||||
}
|
||||
sailfish_manager_update_modem_paths_full(p);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2017 Jolla Ltd.
|
||||
* Copyright (C) 2017-2018 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,7 @@ struct sailfish_sim_info_priv {
|
||||
guint netreg_status_watch_id;
|
||||
gboolean update_imsi_cache;
|
||||
gboolean update_iccid_map;
|
||||
int queued_signals;
|
||||
};
|
||||
|
||||
enum sailfish_sim_info_signal {
|
||||
@@ -94,12 +95,37 @@ G_DEFINE_TYPE(SailfishSimInfo, sailfish_sim_info, G_TYPE_OBJECT)
|
||||
/* Skip the leading slash from the modem path: */
|
||||
#define DBG_(obj,fmt,args...) DBG("%s " fmt, (obj)->path+1, ##args)
|
||||
|
||||
static int sailfish_sim_info_signal_bit(enum sailfish_sim_info_signal id)
|
||||
{
|
||||
return (1 << id);
|
||||
}
|
||||
|
||||
static void sailfish_sim_info_signal_emit(struct sailfish_sim_info *self,
|
||||
enum sailfish_sim_info_signal id)
|
||||
{
|
||||
self->priv->queued_signals &= ~sailfish_sim_info_signal_bit(id);
|
||||
g_signal_emit(self, sailfish_sim_info_signals[id], 0);
|
||||
}
|
||||
|
||||
static void sailfish_sim_info_signal_queue(struct sailfish_sim_info *self,
|
||||
enum sailfish_sim_info_signal id)
|
||||
{
|
||||
self->priv->queued_signals |= sailfish_sim_info_signal_bit(id);
|
||||
}
|
||||
|
||||
static void sailfish_sim_info_emit_queued_signals
|
||||
(struct sailfish_sim_info *self)
|
||||
{
|
||||
struct sailfish_sim_info_priv *priv = self->priv;
|
||||
int i;
|
||||
|
||||
for (i = 0; priv->queued_signals && i < SIGNAL_COUNT; i++) {
|
||||
if (priv->queued_signals & sailfish_sim_info_signal_bit(i)) {
|
||||
sailfish_sim_info_signal_emit(self, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void sailfish_sim_info_update_imsi_cache(struct sailfish_sim_info *self)
|
||||
{
|
||||
struct sailfish_sim_info_priv *priv = self->priv;
|
||||
@@ -178,8 +204,15 @@ static void sailfish_sim_info_update_public_spn(struct sailfish_sim_info *self)
|
||||
|
||||
if (g_strcmp0(priv->public_spn, spn)) {
|
||||
g_free(priv->public_spn);
|
||||
self->spn = priv->public_spn = g_strdup(spn);
|
||||
sailfish_sim_info_signal_emit(self, SIGNAL_SPN_CHANGED);
|
||||
if (spn && spn[0]) {
|
||||
DBG_(self, "public spn \"%s\"", spn);
|
||||
priv->public_spn = g_strdup(spn);
|
||||
} else {
|
||||
DBG_(self, "no public spn");
|
||||
priv->public_spn = NULL;
|
||||
}
|
||||
self->spn = priv->public_spn;
|
||||
sailfish_sim_info_signal_queue(self, SIGNAL_SPN_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,16 +221,13 @@ static void sailfish_sim_info_set_cached_spn(struct sailfish_sim_info *self,
|
||||
{
|
||||
struct sailfish_sim_info_priv *priv = self->priv;
|
||||
|
||||
GASSERT(spn);
|
||||
if (g_strcmp0(priv->cached_spn, spn)) {
|
||||
DBG_(self, "%s", spn);
|
||||
g_free(priv->cached_spn);
|
||||
if (spn) {
|
||||
DBG_(self, "cached spn \"%s\"", spn);
|
||||
priv->cached_spn = g_strdup(spn);
|
||||
priv->update_imsi_cache = TRUE;
|
||||
sailfish_sim_info_update_imsi_cache(self);
|
||||
} else {
|
||||
priv->cached_spn = NULL;
|
||||
}
|
||||
priv->cached_spn = g_strdup(spn);
|
||||
priv->update_imsi_cache = TRUE;
|
||||
sailfish_sim_info_update_imsi_cache(self);
|
||||
sailfish_sim_info_update_public_spn(self);
|
||||
}
|
||||
}
|
||||
@@ -207,6 +237,7 @@ static void sailfish_sim_info_set_spn(struct sailfish_sim_info *self,
|
||||
{
|
||||
struct sailfish_sim_info_priv *priv = self->priv;
|
||||
|
||||
GASSERT(spn);
|
||||
if (g_strcmp0(priv->sim_spn, spn)) {
|
||||
DBG_(self, "%s", spn);
|
||||
g_free(priv->sim_spn);
|
||||
@@ -254,29 +285,24 @@ static void sailfish_sim_info_update_default_spn(struct sailfish_sim_info *self)
|
||||
}
|
||||
}
|
||||
|
||||
static void sailfish_sim_info_set_imsi(struct sailfish_sim_info *self,
|
||||
const char *imsi)
|
||||
static void sailfish_sim_info_update_imsi(struct sailfish_sim_info *self)
|
||||
{
|
||||
struct sailfish_sim_info_priv *priv = self->priv;
|
||||
const char *imsi = priv->watch->imsi;
|
||||
|
||||
if (g_strcmp0(priv->imsi, imsi)) {
|
||||
/* IMSI only gets reset when ICCID disappears, ignore NULL IMSI here */
|
||||
if (imsi && imsi[0] && g_strcmp0(priv->imsi, imsi)) {
|
||||
DBG_(self, "%s", imsi);
|
||||
g_free(priv->imsi);
|
||||
self->imsi = priv->imsi = g_strdup(imsi);
|
||||
priv->update_iccid_map = TRUE;
|
||||
sailfish_sim_info_update_iccid_map(self);
|
||||
sailfish_sim_info_update_imsi_cache(self);
|
||||
sailfish_sim_info_signal_emit(self, SIGNAL_IMSI_CHANGED);
|
||||
sailfish_sim_info_signal_queue(self, SIGNAL_IMSI_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
static void sailfish_sim_info_update_imsi(struct sailfish_sim_info *self)
|
||||
{
|
||||
struct sailfish_watch *watch = self->priv->watch;
|
||||
|
||||
if (watch->imsi && watch->imsi[0]) {
|
||||
sailfish_sim_info_set_imsi(self, watch->imsi);
|
||||
}
|
||||
/* Check if MCC/MNC have changed */
|
||||
sailfish_sim_info_update_default_spn(self);
|
||||
}
|
||||
|
||||
static void sailfish_sim_info_network_check(struct sailfish_sim_info *self)
|
||||
@@ -333,7 +359,8 @@ static void sailfish_sim_info_load_cache(struct sailfish_sim_info *self)
|
||||
self->imsi = priv->imsi = imsi;
|
||||
DBG_(self, "imsi[%s] = %s", priv->iccid, imsi);
|
||||
sailfish_sim_info_update_iccid_map(self);
|
||||
sailfish_sim_info_signal_emit(self,
|
||||
sailfish_sim_info_update_default_spn(self);
|
||||
sailfish_sim_info_signal_queue(self,
|
||||
SIGNAL_IMSI_CHANGED);
|
||||
} else if (imsi) {
|
||||
g_free(imsi);
|
||||
@@ -378,38 +405,32 @@ static void sailfish_sim_info_set_iccid(struct sailfish_sim_info *self,
|
||||
if (g_strcmp0(priv->iccid, iccid)) {
|
||||
g_free(priv->iccid);
|
||||
self->iccid = priv->iccid = g_strdup(iccid);
|
||||
sailfish_sim_info_signal_emit(self, SIGNAL_ICCID_CHANGED);
|
||||
sailfish_sim_info_signal_queue(self, SIGNAL_ICCID_CHANGED);
|
||||
if (iccid) {
|
||||
sailfish_sim_info_load_cache(self);
|
||||
} else {
|
||||
DBG_(self, "no more iccid");
|
||||
if (priv->imsi) {
|
||||
g_free(priv->imsi);
|
||||
self->imsi = priv->imsi = NULL;
|
||||
sailfish_sim_info_signal_emit(self,
|
||||
sailfish_sim_info_signal_queue(self,
|
||||
SIGNAL_IMSI_CHANGED);
|
||||
}
|
||||
if (priv->sim_spn) {
|
||||
g_free(priv->sim_spn);
|
||||
priv->sim_spn = NULL;
|
||||
sailfish_sim_info_set_cached_spn(self, NULL);
|
||||
}
|
||||
if (priv->cached_spn) {
|
||||
g_free(priv->cached_spn);
|
||||
priv->cached_spn = NULL;
|
||||
}
|
||||
/* No more default SPN too */
|
||||
priv->default_spn[0] = 0;
|
||||
sailfish_sim_info_update_public_spn(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void sailfish_sim_info_sim_watch_cb(struct sailfish_watch *watch,
|
||||
void *data)
|
||||
{
|
||||
struct sailfish_sim_info *self = SAILFISH_SIMINFO(data);
|
||||
struct ofono_sim *sim = self->priv->watch->sim;
|
||||
|
||||
sailfish_sim_info_update_default_spn(self);
|
||||
if (ofono_sim_get_state(sim) == OFONO_SIM_STATE_NOT_PRESENT) {
|
||||
sailfish_sim_info_set_iccid(self, NULL);
|
||||
}
|
||||
sailfish_sim_info_network_check(self);
|
||||
}
|
||||
|
||||
static void sailfish_sim_info_iccid_watch_cb(struct sailfish_watch *watch,
|
||||
void *data)
|
||||
{
|
||||
@@ -417,24 +438,34 @@ static void sailfish_sim_info_iccid_watch_cb(struct sailfish_watch *watch,
|
||||
|
||||
DBG_(self, "%s", watch->iccid);
|
||||
sailfish_sim_info_set_iccid(self, watch->iccid);
|
||||
sailfish_sim_info_emit_queued_signals(self);
|
||||
}
|
||||
|
||||
static void sailfish_sim_info_imsi_watch_cb(struct sailfish_watch *watch,
|
||||
void *data)
|
||||
{
|
||||
sailfish_sim_info_update_imsi(SAILFISH_SIMINFO(data));
|
||||
struct sailfish_sim_info *self = SAILFISH_SIMINFO(data);
|
||||
|
||||
sailfish_sim_info_update_imsi(self);
|
||||
sailfish_sim_info_emit_queued_signals(self);
|
||||
}
|
||||
|
||||
static void sailfish_sim_info_spn_watch_cb(struct sailfish_watch *watch,
|
||||
void *data)
|
||||
{
|
||||
sailfish_sim_info_update_spn(SAILFISH_SIMINFO(data));
|
||||
struct sailfish_sim_info *self = SAILFISH_SIMINFO(data);
|
||||
|
||||
sailfish_sim_info_update_spn(self);
|
||||
sailfish_sim_info_emit_queued_signals(self);
|
||||
}
|
||||
|
||||
static void sailfish_sim_info_netreg_watch(int status, int lac, int ci,
|
||||
int tech, const char *mcc, const char *mnc, void *data)
|
||||
{
|
||||
sailfish_sim_info_network_check(SAILFISH_SIMINFO(data));
|
||||
struct sailfish_sim_info *self = SAILFISH_SIMINFO(data);
|
||||
|
||||
sailfish_sim_info_network_check(self);
|
||||
sailfish_sim_info_emit_queued_signals(self);
|
||||
}
|
||||
|
||||
static void sailfish_sim_info_netreg_watch_done(void *data)
|
||||
@@ -475,7 +506,10 @@ static void sailfish_sim_info_set_netreg(struct sailfish_sim_info *self,
|
||||
static void sailfish_sim_info_netreg_changed(struct sailfish_watch *watch,
|
||||
void *data)
|
||||
{
|
||||
sailfish_sim_info_set_netreg(SAILFISH_SIMINFO(data), watch->netreg);
|
||||
struct sailfish_sim_info *self = SAILFISH_SIMINFO(data);
|
||||
|
||||
sailfish_sim_info_set_netreg(self, watch->netreg);
|
||||
sailfish_sim_info_emit_queued_signals(self);
|
||||
}
|
||||
|
||||
struct sailfish_sim_info *sailfish_sim_info_new(const char *path)
|
||||
@@ -490,12 +524,6 @@ struct sailfish_sim_info *sailfish_sim_info_new(const char *path)
|
||||
priv = self->priv;
|
||||
priv->watch = watch;
|
||||
self->path = watch->path;
|
||||
priv->watch_event_id[WATCH_EVENT_SIM] =
|
||||
sailfish_watch_add_sim_changed_handler(watch,
|
||||
sailfish_sim_info_sim_watch_cb, self);
|
||||
priv->watch_event_id[WATCH_EVENT_SIM_STATE] =
|
||||
sailfish_watch_add_sim_state_changed_handler(watch,
|
||||
sailfish_sim_info_sim_watch_cb, self);
|
||||
priv->watch_event_id[WATCH_EVENT_ICCID] =
|
||||
sailfish_watch_add_iccid_changed_handler(watch,
|
||||
sailfish_sim_info_iccid_watch_cb, self);
|
||||
@@ -513,6 +541,9 @@ struct sailfish_sim_info *sailfish_sim_info_new(const char *path)
|
||||
sailfish_sim_info_update_imsi(self);
|
||||
sailfish_sim_info_update_spn(self);
|
||||
sailfish_sim_info_network_check(self);
|
||||
|
||||
/* Clear queued events, if any */
|
||||
priv->queued_signals = 0;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -534,13 +565,6 @@ void sailfish_sim_info_unref(struct sailfish_sim_info *self)
|
||||
}
|
||||
}
|
||||
|
||||
void sailfish_sim_info_invalidate(struct sailfish_sim_info *self)
|
||||
{
|
||||
if (self) {
|
||||
sailfish_sim_info_set_iccid(self, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
gulong sailfish_sim_info_add_iccid_changed_handler(struct sailfish_sim_info *s,
|
||||
sailfish_sim_info_cb_t cb, void *arg)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2017 Jolla Ltd.
|
||||
* Copyright (C) 2017-2018 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,7 +48,6 @@ typedef void (*sailfish_sim_info_cb_t)(struct sailfish_sim_info *si,
|
||||
struct sailfish_sim_info *sailfish_sim_info_new(const char *path);
|
||||
struct sailfish_sim_info *sailfish_sim_info_ref(struct sailfish_sim_info *si);
|
||||
void sailfish_sim_info_unref(struct sailfish_sim_info *si);
|
||||
void sailfish_sim_info_invalidate(struct sailfish_sim_info *si);
|
||||
gulong sailfish_sim_info_add_iccid_changed_handler(struct sailfish_sim_info *si,
|
||||
sailfish_sim_info_cb_t cb, void *user_data);
|
||||
gulong sailfish_sim_info_add_imsi_changed_handler(struct sailfish_sim_info *si,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2017 Jolla Ltd.
|
||||
* Copyright (C) 2017-2018 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
|
||||
@@ -126,24 +126,6 @@ static inline void sailfish_watch_resume_signals(struct sailfish_watch *self)
|
||||
sailfish_watch_emit_queued_signals(self);
|
||||
}
|
||||
|
||||
static void sailfish_watch_sim_state_notify(enum ofono_sim_state new_state,
|
||||
void *user_data)
|
||||
{
|
||||
struct sailfish_watch *self = SAILFISH_WATCH(user_data);
|
||||
|
||||
sailfish_watch_signal_queue(self, SIGNAL_SIM_STATE_CHANGED);
|
||||
sailfish_watch_emit_queued_signals(self);
|
||||
}
|
||||
|
||||
static void sailfish_watch_sim_state_destroy(void *user_data)
|
||||
{
|
||||
struct sailfish_watch *self = SAILFISH_WATCH(user_data);
|
||||
struct sailfish_watch_priv *priv = self->priv;
|
||||
|
||||
GASSERT(priv->sim_state_watch_id);
|
||||
priv->sim_state_watch_id = 0;
|
||||
}
|
||||
|
||||
static void sailfish_watch_iccid_update(struct sailfish_watch *self,
|
||||
const char *iccid)
|
||||
{
|
||||
@@ -238,6 +220,35 @@ static void sailfish_watch_imsi_destroy(void *user_data)
|
||||
priv->imsi_watch_id = 0;
|
||||
}
|
||||
|
||||
static void sailfish_watch_sim_state_notify(enum ofono_sim_state new_state,
|
||||
void *user_data)
|
||||
{
|
||||
struct sailfish_watch *self = SAILFISH_WATCH(user_data);
|
||||
|
||||
/*
|
||||
* ofono core doesn't notify SIM watches when SIM card gets removed.
|
||||
* So we have to reset things here based on the SIM state.
|
||||
*/
|
||||
if (new_state == OFONO_SIM_STATE_NOT_PRESENT) {
|
||||
sailfish_watch_iccid_update(self, NULL);
|
||||
}
|
||||
if (new_state != OFONO_SIM_STATE_READY) {
|
||||
sailfish_watch_imsi_update(self, NULL);
|
||||
sailfish_watch_spn_update(self, NULL);
|
||||
}
|
||||
sailfish_watch_signal_queue(self, SIGNAL_SIM_STATE_CHANGED);
|
||||
sailfish_watch_emit_queued_signals(self);
|
||||
}
|
||||
|
||||
static void sailfish_watch_sim_state_destroy(void *user_data)
|
||||
{
|
||||
struct sailfish_watch *self = SAILFISH_WATCH(user_data);
|
||||
struct sailfish_watch_priv *priv = self->priv;
|
||||
|
||||
GASSERT(priv->sim_state_watch_id);
|
||||
priv->sim_state_watch_id = 0;
|
||||
}
|
||||
|
||||
static void sailfish_watch_set_sim(struct sailfish_watch *self,
|
||||
struct ofono_sim *sim)
|
||||
{
|
||||
@@ -271,6 +282,11 @@ static void sailfish_watch_set_sim(struct sailfish_watch *self,
|
||||
self->sim = sim;
|
||||
sailfish_watch_signal_queue(self, SIGNAL_SIM_CHANGED);
|
||||
sailfish_watch_suspend_signals(self);
|
||||
|
||||
/* Reset the current state */
|
||||
sailfish_watch_iccid_update(self, NULL);
|
||||
sailfish_watch_imsi_update(self, NULL);
|
||||
sailfish_watch_spn_update(self, NULL);
|
||||
if (sim) {
|
||||
priv->sim_state_watch_id =
|
||||
ofono_sim_add_state_watch(sim,
|
||||
@@ -293,12 +309,6 @@ static void sailfish_watch_set_sim(struct sailfish_watch *self,
|
||||
ofono_sim_add_imsi_watch(self->sim,
|
||||
sailfish_watch_imsi_notify, self,
|
||||
sailfish_watch_imsi_destroy);
|
||||
} else {
|
||||
/* And these will just queue the signals
|
||||
* if necessary */
|
||||
sailfish_watch_iccid_update(self, NULL);
|
||||
sailfish_watch_imsi_update(self, NULL);
|
||||
sailfish_watch_spn_update(self, NULL);
|
||||
}
|
||||
|
||||
/* Emit the pending signals. */
|
||||
|
||||
@@ -3770,3 +3770,21 @@ gboolean __ofono_gprs_get_roaming_allowed(struct ofono_gprs *gprs)
|
||||
{
|
||||
return gprs->roaming_allowed;
|
||||
}
|
||||
|
||||
const struct ofono_gprs_primary_context *__ofono_gprs_context_settings_by_type
|
||||
(struct ofono_gprs *gprs, enum ofono_gprs_context_type type)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
if (!gprs)
|
||||
return NULL;
|
||||
|
||||
for (l = gprs->contexts; l; l = l->next) {
|
||||
struct pri_context *ctx = l->data;
|
||||
|
||||
if (type == OFONO_GPRS_CONTEXT_TYPE_ANY || type == ctx->type)
|
||||
return &ctx->context;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -277,6 +277,10 @@ gboolean __ofono_call_settings_is_busy(struct ofono_call_settings *cs);
|
||||
gboolean __ofono_gprs_get_roaming_allowed(struct ofono_gprs *gprs);
|
||||
|
||||
#include <ofono/gprs-context.h>
|
||||
|
||||
const struct ofono_gprs_primary_context *__ofono_gprs_context_settings_by_type
|
||||
(struct ofono_gprs *gprs, enum ofono_gprs_context_type type);
|
||||
|
||||
#include <ofono/radio-settings.h>
|
||||
#include <ofono/audio-settings.h>
|
||||
#include <ofono/ctm.h>
|
||||
|
||||
@@ -2207,6 +2207,9 @@ static void sim_efli_efpl_changed(int id, void *userdata)
|
||||
if (sim->efli != NULL) /* This shouldn't happen */
|
||||
return;
|
||||
|
||||
if (sim->language_prefs_update)
|
||||
return;
|
||||
|
||||
if (sim->language_prefs) {
|
||||
g_strfreev(sim->language_prefs);
|
||||
sim->language_prefs = NULL;
|
||||
|
||||
@@ -20,8 +20,10 @@ TESTS="\
|
||||
test-ril_util \
|
||||
test-sms-filter \
|
||||
test-sailfish_cell_info \
|
||||
test-sailfish_cell_info_dbus \
|
||||
test-sailfish_manager \
|
||||
test-sailfish_sim_info"
|
||||
test-sailfish_sim_info \
|
||||
test-sailfish_sim_info_dbus"
|
||||
|
||||
pushd `dirname $0` > /dev/null
|
||||
TEST_DIR="$PWD"
|
||||
|
||||
181
ofono/unit/fake_sailfish_cell_info.c
Normal file
181
ofono/unit/fake_sailfish_cell_info.c
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "fake_sailfish_cell_info.h"
|
||||
|
||||
#include <gutil_macros.h>
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
typedef GObjectClass FakeCellInfoClass;
|
||||
typedef struct fake_cell_info {
|
||||
GObject object;
|
||||
struct sailfish_cell_info info;
|
||||
} FakeCellInfo;
|
||||
|
||||
typedef struct fake_cell_info_signal_data {
|
||||
sailfish_cell_info_cb_t cb;
|
||||
void *arg;
|
||||
} FakeCellInfoSignalData;
|
||||
|
||||
enum fake_cell_info_signal {
|
||||
SIGNAL_CELLS_CHANGED,
|
||||
SIGNAL_COUNT
|
||||
};
|
||||
|
||||
static guint fake_cell_info_signals[SIGNAL_COUNT] = { 0 };
|
||||
|
||||
G_DEFINE_TYPE(FakeCellInfo, fake_cell_info, G_TYPE_OBJECT)
|
||||
#define FAKE_CELL_INFO_TYPE (fake_cell_info_get_type())
|
||||
#define FAKE_CELL_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
|
||||
FAKE_CELL_INFO_TYPE, FakeCellInfo))
|
||||
|
||||
#define SIGNAL_CELLS_CHANGED_NAME "fake-cell-info-cells-changed"
|
||||
|
||||
static FakeCellInfo *fake_cell_info_cast(struct sailfish_cell_info *info)
|
||||
{
|
||||
return G_CAST(info, FakeCellInfo, info);
|
||||
}
|
||||
|
||||
static void fake_cell_info_ref_proc(struct sailfish_cell_info *info)
|
||||
{
|
||||
g_object_ref(fake_cell_info_cast(info));
|
||||
}
|
||||
|
||||
static void fake_cell_info_unref_proc(struct sailfish_cell_info *info)
|
||||
{
|
||||
g_object_unref(fake_cell_info_cast(info));
|
||||
}
|
||||
|
||||
static void fake_cell_info_cells_changed_cb(FakeCellInfo *self, void *data)
|
||||
{
|
||||
FakeCellInfoSignalData *signal_data = data;
|
||||
|
||||
signal_data->cb(&self->info, signal_data->arg);
|
||||
}
|
||||
|
||||
static void fake_cell_info_cells_disconnect_notify(gpointer data,
|
||||
GClosure *closure)
|
||||
{
|
||||
g_free(data);
|
||||
}
|
||||
|
||||
static gulong fake_cell_info_add_cells_changed_handler_proc
|
||||
(struct sailfish_cell_info *info,
|
||||
sailfish_cell_info_cb_t cb, void *arg)
|
||||
{
|
||||
if (cb) {
|
||||
FakeCellInfoSignalData *data =
|
||||
g_new0(FakeCellInfoSignalData, 1);
|
||||
|
||||
data->cb = cb;
|
||||
data->arg = arg;
|
||||
return g_signal_connect_data(fake_cell_info_cast(info),
|
||||
SIGNAL_CELLS_CHANGED_NAME,
|
||||
G_CALLBACK(fake_cell_info_cells_changed_cb),
|
||||
data, fake_cell_info_cells_disconnect_notify,
|
||||
G_CONNECT_AFTER);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void fake_cell_info_remove_handler_proc(struct sailfish_cell_info *info,
|
||||
gulong id)
|
||||
{
|
||||
if (id) {
|
||||
g_signal_handler_disconnect(fake_cell_info_cast(info), id);
|
||||
}
|
||||
}
|
||||
|
||||
static void fake_cell_info_init(FakeCellInfo *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void fake_cell_info_finalize(GObject *object)
|
||||
{
|
||||
FakeCellInfo *self = FAKE_CELL_INFO(object);
|
||||
|
||||
fake_cell_info_remove_all_cells(&self->info);
|
||||
G_OBJECT_CLASS(fake_cell_info_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static void fake_cell_info_class_init(FakeCellInfoClass *klass)
|
||||
{
|
||||
G_OBJECT_CLASS(klass)->finalize = fake_cell_info_finalize;
|
||||
fake_cell_info_signals[SIGNAL_CELLS_CHANGED] =
|
||||
g_signal_new(SIGNAL_CELLS_CHANGED_NAME,
|
||||
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST,
|
||||
0, NULL, NULL, NULL, G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
struct sailfish_cell_info *fake_cell_info_new()
|
||||
{
|
||||
static const struct sailfish_cell_info_proc fake_cell_info_proc = {
|
||||
fake_cell_info_ref_proc,
|
||||
fake_cell_info_unref_proc,
|
||||
fake_cell_info_add_cells_changed_handler_proc,
|
||||
fake_cell_info_remove_handler_proc
|
||||
};
|
||||
|
||||
FakeCellInfo *self = g_object_new(FAKE_CELL_INFO_TYPE, 0);
|
||||
|
||||
self->info.proc = &fake_cell_info_proc;
|
||||
return &self->info;
|
||||
}
|
||||
|
||||
void fake_cell_info_add_cell(struct sailfish_cell_info *info,
|
||||
const struct sailfish_cell* cell)
|
||||
{
|
||||
info->cells = g_slist_append(info->cells,
|
||||
g_memdup(cell, sizeof(*cell)));
|
||||
}
|
||||
|
||||
gboolean fake_cell_info_remove_cell(struct sailfish_cell_info *info,
|
||||
const struct sailfish_cell* cell)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
for (l = info->cells; l; l = l->next) {
|
||||
struct sailfish_cell *known_cell = l->data;
|
||||
|
||||
if (!memcmp(cell, known_cell, sizeof(*cell))) {
|
||||
info->cells = g_slist_remove(info->cells, known_cell);
|
||||
g_free(known_cell);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void fake_cell_info_remove_all_cells(struct sailfish_cell_info *info)
|
||||
{
|
||||
g_slist_free_full(info->cells, g_free);
|
||||
info->cells = NULL;
|
||||
}
|
||||
|
||||
void fake_cell_info_cells_changed(struct sailfish_cell_info *info)
|
||||
{
|
||||
g_signal_emit(fake_cell_info_cast(info), fake_cell_info_signals
|
||||
[SIGNAL_CELLS_CHANGED], 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
37
ofono/unit/fake_sailfish_cell_info.h
Normal file
37
ofono/unit/fake_sailfish_cell_info.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2018 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef SAILFISH_FAKE_CELL_INFO_H
|
||||
#define SAILFISH_FAKE_CELL_INFO_H
|
||||
|
||||
#include "sailfish_cell_info.h"
|
||||
|
||||
struct sailfish_cell_info *fake_cell_info_new(void);
|
||||
void fake_cell_info_add_cell(struct sailfish_cell_info *info,
|
||||
const struct sailfish_cell* cell);
|
||||
gboolean fake_cell_info_remove_cell(struct sailfish_cell_info *info,
|
||||
const struct sailfish_cell* cell);
|
||||
void fake_cell_info_remove_all_cells(struct sailfish_cell_info *info);
|
||||
void fake_cell_info_cells_changed(struct sailfish_cell_info *info);
|
||||
|
||||
#endif /* FAKE_SAILFISH_CELL_INFO_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
357
ofono/unit/test-dbus.c
Normal file
357
ofono/unit/test-dbus.c
Normal file
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2018 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "test-dbus.h"
|
||||
#include "ofono.h"
|
||||
|
||||
#include <dbus/dbus-glib-lowlevel.h>
|
||||
|
||||
struct test_polkit_auth_check {
|
||||
void (*function)(dbus_bool_t authorized, void *user_data);
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
struct test_dbus_watch {
|
||||
struct test_dbus_watch *next;
|
||||
guint id;
|
||||
DBusConnection *connection;
|
||||
GDBusWatchFunction disconnect;
|
||||
GDBusDestroyFunction destroy;
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
struct test_dbus_watch *test_dbus_watch_list;
|
||||
static unsigned int test_last_id;
|
||||
|
||||
static gboolean polkit_check_authorization_cb(gpointer data)
|
||||
{
|
||||
struct test_polkit_auth_check *check = data;
|
||||
|
||||
check->function(TRUE, check->user_data);
|
||||
g_free(check);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
int polkit_check_authorization(DBusConnection *conn,
|
||||
const char *action, gboolean interaction,
|
||||
void (*function)(dbus_bool_t authorized, void *user_data),
|
||||
void *user_data, int timeout)
|
||||
{
|
||||
struct test_polkit_auth_check *check =
|
||||
g_new(struct test_polkit_auth_check, 1);
|
||||
|
||||
check->function = function;
|
||||
check->user_data = user_data;
|
||||
g_idle_add(polkit_check_authorization_cb, check);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static guint test_dbus_add_watch(DBusConnection *connection,
|
||||
GDBusWatchFunction disconnect, GDBusDestroyFunction destroy,
|
||||
void *user_data)
|
||||
{
|
||||
struct test_dbus_watch *watch = g_new0(struct test_dbus_watch, 1);
|
||||
|
||||
test_last_id++;
|
||||
watch->id = test_last_id;
|
||||
watch->connection = dbus_connection_ref(connection);
|
||||
watch->disconnect = disconnect;
|
||||
watch->destroy = destroy;
|
||||
watch->user_data = user_data;
|
||||
watch->next = test_dbus_watch_list;
|
||||
test_dbus_watch_list = watch;
|
||||
return test_last_id;
|
||||
}
|
||||
|
||||
static gboolean test_dbus_watch_disconnect_one(void)
|
||||
{
|
||||
struct test_dbus_watch *watch = test_dbus_watch_list;
|
||||
|
||||
while (watch) {
|
||||
if (watch->disconnect) {
|
||||
GDBusWatchFunction disconnect = watch->disconnect;
|
||||
|
||||
watch->disconnect = NULL;
|
||||
disconnect(watch->connection, watch->user_data);
|
||||
return TRUE;
|
||||
}
|
||||
watch = watch->next;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void test_dbus_watch_disconnect_all(void)
|
||||
{
|
||||
while (test_dbus_watch_disconnect_one());
|
||||
}
|
||||
|
||||
static void test_dbus_watch_free(struct test_dbus_watch *watch)
|
||||
{
|
||||
if (watch->destroy) {
|
||||
watch->destroy(watch->user_data);
|
||||
}
|
||||
dbus_connection_unref(watch->connection);
|
||||
g_free(watch);
|
||||
}
|
||||
|
||||
static gboolean test_dbus_watch_remove_one(void)
|
||||
{
|
||||
struct test_dbus_watch *watch = test_dbus_watch_list;
|
||||
|
||||
if (watch) {
|
||||
test_dbus_watch_list = watch->next;
|
||||
test_dbus_watch_free(watch);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void test_dbus_watch_remove_all(void)
|
||||
{
|
||||
while (test_dbus_watch_remove_one());
|
||||
}
|
||||
|
||||
guint g_dbus_add_signal_watch(DBusConnection *connection, const char *sender,
|
||||
const char *path, const char *interface, const char *member,
|
||||
GDBusSignalFunction function, void *user_data,
|
||||
GDBusDestroyFunction destroy)
|
||||
{
|
||||
return test_dbus_add_watch(connection, NULL, destroy, user_data);
|
||||
}
|
||||
|
||||
gboolean g_dbus_remove_watch(DBusConnection *connection, guint id)
|
||||
{
|
||||
struct test_dbus_watch *prev = NULL;
|
||||
struct test_dbus_watch *watch = test_dbus_watch_list;
|
||||
|
||||
while (watch) {
|
||||
if (watch->id == id) {
|
||||
if (prev) {
|
||||
prev->next = watch->next;
|
||||
} else {
|
||||
test_dbus_watch_list = watch->next;
|
||||
}
|
||||
test_dbus_watch_free(watch);
|
||||
return TRUE;
|
||||
}
|
||||
prev = watch;
|
||||
watch = watch->next;
|
||||
}
|
||||
ofono_warn("Unexpected id %u", id);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean test_dbus_loop_quit(gpointer data)
|
||||
{
|
||||
g_main_loop_quit(data);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void test_dbus_loop_quit_later(GMainLoop *loop)
|
||||
{
|
||||
g_idle_add(test_dbus_loop_quit, loop);
|
||||
}
|
||||
|
||||
DBusMessage *test_dbus_find_signal(struct test_dbus_context *test,
|
||||
const char *path, const char *iface, const char *member)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
for (l = test->client_signals; l; l = l->next) {
|
||||
DBusMessage *msg = l->data;
|
||||
|
||||
if (!g_strcmp0(dbus_message_get_interface(msg), iface) &&
|
||||
!g_strcmp0(dbus_message_get_member(msg), member) &&
|
||||
!g_strcmp0(dbus_message_get_path(msg), path)) {
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DBusMessage *test_dbus_take_signal(struct test_dbus_context *test,
|
||||
const char *path, const char *iface, const char *member)
|
||||
{
|
||||
DBusMessage *m = test_dbus_find_signal(test, path, iface, member);
|
||||
|
||||
if (m) {
|
||||
test->client_signals = g_slist_remove(test->client_signals, m);
|
||||
return m;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int test_dbus_get_int32(DBusMessageIter *it)
|
||||
{
|
||||
dbus_uint32_t value;
|
||||
|
||||
g_assert(dbus_message_iter_get_arg_type(it) == DBUS_TYPE_INT32);
|
||||
dbus_message_iter_get_basic(it, &value);
|
||||
dbus_message_iter_next(it);
|
||||
return value;
|
||||
}
|
||||
|
||||
gboolean test_dbus_get_bool(DBusMessageIter *it)
|
||||
{
|
||||
dbus_bool_t value;
|
||||
|
||||
g_assert(dbus_message_iter_get_arg_type(it) == DBUS_TYPE_BOOLEAN);
|
||||
dbus_message_iter_get_basic(it, &value);
|
||||
dbus_message_iter_next(it);
|
||||
return value;
|
||||
}
|
||||
|
||||
const char *test_dbus_get_string(DBusMessageIter *it)
|
||||
{
|
||||
const char *value;
|
||||
|
||||
g_assert(dbus_message_iter_get_arg_type(it) == DBUS_TYPE_STRING);
|
||||
dbus_message_iter_get_basic(it, &value);
|
||||
dbus_message_iter_next(it);
|
||||
return value;
|
||||
}
|
||||
|
||||
const char *test_dbus_get_object_path(DBusMessageIter *it)
|
||||
{
|
||||
const char *value;
|
||||
|
||||
g_assert(dbus_message_iter_get_arg_type(it) == DBUS_TYPE_OBJECT_PATH);
|
||||
dbus_message_iter_get_basic(it, &value);
|
||||
dbus_message_iter_next(it);
|
||||
return value;
|
||||
}
|
||||
|
||||
void test_dbus_expect_empty_reply(DBusPendingCall *call, void *data)
|
||||
{
|
||||
struct test_dbus_context *test = data;
|
||||
DBusMessage *reply = dbus_pending_call_steal_reply(call);
|
||||
DBusMessageIter it;
|
||||
|
||||
DBG("");
|
||||
g_assert(dbus_message_get_type(reply) ==
|
||||
DBUS_MESSAGE_TYPE_METHOD_RETURN);
|
||||
|
||||
dbus_message_iter_init(reply, &it);
|
||||
g_assert(dbus_message_iter_get_arg_type(&it) == DBUS_TYPE_INVALID);
|
||||
|
||||
dbus_message_unref(reply);
|
||||
dbus_pending_call_unref(call);
|
||||
test_dbus_loop_quit_later(test->loop);
|
||||
}
|
||||
|
||||
void test_dbus_check_string_reply(DBusPendingCall *call, const char *str)
|
||||
{
|
||||
DBusMessage *reply = dbus_pending_call_steal_reply(call);
|
||||
DBusMessageIter it;
|
||||
|
||||
DBG("");
|
||||
g_assert(dbus_message_get_type(reply) ==
|
||||
DBUS_MESSAGE_TYPE_METHOD_RETURN);
|
||||
|
||||
dbus_message_iter_init(reply, &it);
|
||||
g_assert(!g_strcmp0(test_dbus_get_string(&it), str));
|
||||
g_assert(dbus_message_iter_get_arg_type(&it) == DBUS_TYPE_INVALID);
|
||||
|
||||
dbus_message_unref(reply);
|
||||
}
|
||||
|
||||
void test_dbus_message_unref(gpointer data)
|
||||
{
|
||||
dbus_message_unref(data);
|
||||
}
|
||||
|
||||
static DBusHandlerResult test_dbus_client_message_cb(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
struct test_dbus_context *test = data;
|
||||
|
||||
if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_SIGNAL) {
|
||||
DBG("signal %s.%s \"%s\"", dbus_message_get_interface(msg),
|
||||
dbus_message_get_member(msg),
|
||||
dbus_message_get_path(msg));
|
||||
test->client_signals = g_slist_append(test->client_signals,
|
||||
dbus_message_ref(msg));
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
} else {
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
static void test_dbus_connection_cb(DBusServer *server, DBusConnection *conn,
|
||||
void *data)
|
||||
{
|
||||
struct test_dbus_context *test = data;
|
||||
|
||||
DBG("");
|
||||
g_assert(!test->server_connection);
|
||||
test->server_connection = dbus_connection_ref(conn);
|
||||
dbus_connection_setup_with_g_main(test->server_connection,
|
||||
g_main_loop_get_context(test->loop));
|
||||
|
||||
/* Start the test */
|
||||
__ofono_dbus_init(test->server_connection);
|
||||
test->start(test);
|
||||
}
|
||||
|
||||
void test_dbus_setup(struct test_dbus_context *test)
|
||||
{
|
||||
char *address;
|
||||
GMainContext *context;
|
||||
|
||||
test->loop = g_main_loop_new(NULL, TRUE);
|
||||
context = g_main_loop_get_context(test->loop);
|
||||
test->server = dbus_server_listen("unix:runtime=yes;unix:tmpdir=/tmp",
|
||||
NULL);
|
||||
g_assert(test->server);
|
||||
address = dbus_server_get_address(test->server);
|
||||
DBG("listening on %s", address);
|
||||
|
||||
dbus_server_setup_with_g_main(test->server, context);
|
||||
dbus_server_set_new_connection_function(test->server,
|
||||
test_dbus_connection_cb, test, NULL);
|
||||
|
||||
test->client_connection = dbus_connection_open_private(address, NULL);
|
||||
g_assert(test->client_connection);
|
||||
dbus_connection_setup_with_g_main(test->client_connection, context);
|
||||
g_assert(dbus_connection_add_filter(test->client_connection,
|
||||
test_dbus_client_message_cb, test, NULL));
|
||||
DBG("connected on %s", address);
|
||||
dbus_free(address);
|
||||
}
|
||||
|
||||
void test_dbus_shutdown(struct test_dbus_context *test)
|
||||
{
|
||||
test_dbus_watch_disconnect_all();
|
||||
test_dbus_watch_remove_all();
|
||||
__ofono_dbus_cleanup();
|
||||
if (test->server_connection) {
|
||||
dbus_connection_close(test->server_connection);
|
||||
dbus_connection_unref(test->server_connection);
|
||||
}
|
||||
dbus_connection_close(test->client_connection);
|
||||
dbus_connection_unref(test->client_connection);
|
||||
dbus_server_disconnect(test->server);
|
||||
dbus_server_unref(test->server);
|
||||
g_main_loop_unref(test->loop);
|
||||
g_slist_free_full(test->client_signals, test_dbus_message_unref);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
58
ofono/unit/test-dbus.h
Normal file
58
ofono/unit/test-dbus.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2018 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef TEST_DBUS_H
|
||||
#define TEST_DBUS_H
|
||||
|
||||
#include <ofono/gdbus.h>
|
||||
|
||||
struct test_dbus_context {
|
||||
GMainLoop *loop;
|
||||
DBusServer *server;
|
||||
DBusConnection *server_connection;
|
||||
DBusConnection *client_connection;
|
||||
GSList* client_signals;
|
||||
void (*start)(struct test_dbus_context *test);
|
||||
guint timeout_id;
|
||||
};
|
||||
|
||||
void test_dbus_setup(struct test_dbus_context *context);
|
||||
void test_dbus_shutdown(struct test_dbus_context *context);
|
||||
|
||||
void test_dbus_watch_disconnect_all(void);
|
||||
void test_dbus_watch_remove_all(void);
|
||||
|
||||
int test_dbus_get_int32(DBusMessageIter *it);
|
||||
gboolean test_dbus_get_bool(DBusMessageIter *it);
|
||||
const char *test_dbus_get_string(DBusMessageIter *it);
|
||||
const char *test_dbus_get_object_path(DBusMessageIter *it);
|
||||
|
||||
void test_dbus_check_string_reply(DBusPendingCall *call, const char *str);
|
||||
void test_dbus_expect_empty_reply(DBusPendingCall *call, void *data);
|
||||
|
||||
DBusMessage *test_dbus_find_signal(struct test_dbus_context *test,
|
||||
const char *path, const char *iface, const char *member);
|
||||
DBusMessage *test_dbus_take_signal(struct test_dbus_context *test,
|
||||
const char *path, const char *iface, const char *member);
|
||||
|
||||
#endif /* TEST_DBUS_H */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
@@ -35,9 +35,12 @@ static void test_alloc(void)
|
||||
idmap = idmap_new(2);
|
||||
|
||||
g_assert(idmap);
|
||||
g_assert(idmap_get_min(idmap) == 1);
|
||||
|
||||
bit = idmap_alloc(idmap);
|
||||
g_assert(bit == 1);
|
||||
g_assert(idmap_find(idmap, bit));
|
||||
g_assert(!idmap_find(idmap, idmap_get_max(idmap) + 1));
|
||||
|
||||
bit = idmap_alloc(idmap);
|
||||
g_assert(bit == 2);
|
||||
@@ -62,6 +65,12 @@ static void test_alloc(void)
|
||||
bit = idmap_alloc(idmap);
|
||||
g_assert(bit == 1);
|
||||
|
||||
idmap_put(idmap, 1);
|
||||
idmap_take(idmap, 1);
|
||||
idmap_take(idmap, 3);
|
||||
bit = idmap_alloc(idmap);
|
||||
g_assert(bit == 2);
|
||||
|
||||
idmap_free(idmap);
|
||||
}
|
||||
|
||||
@@ -80,9 +89,24 @@ static void test_alloc_next(void)
|
||||
bit = idmap_alloc_next(idmap, 255);
|
||||
g_assert(bit == 1);
|
||||
|
||||
while (idmap_alloc(idmap) < (sizeof(unsigned long) * 8) + 1);
|
||||
bit = idmap_alloc_next(idmap, 1);
|
||||
g_assert(bit == (sizeof(unsigned long) * 8) + 2);
|
||||
|
||||
idmap_free(idmap);
|
||||
|
||||
idmap = idmap_new(2);
|
||||
|
||||
g_assert(idmap);
|
||||
g_assert(idmap_alloc_next(idmap, 0) == 3);
|
||||
g_assert(idmap_alloc_next(idmap, 3) == 3);
|
||||
|
||||
bit = idmap_alloc_next(idmap, 1);
|
||||
g_assert(bit == 2);
|
||||
|
||||
bit = idmap_alloc_next(idmap, 2);
|
||||
g_assert(bit == 1);
|
||||
|
||||
idmap_free(idmap);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2017 Jolla Ltd.
|
||||
* Copyright (C) 2017-2018 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
|
||||
@@ -102,6 +102,20 @@ void test_parse_int(void)
|
||||
g_assert(!ril_parse_int("0xffffffff", 0, &value));
|
||||
}
|
||||
|
||||
void test_strings(void)
|
||||
{
|
||||
g_assert(!g_strcmp0(ril_error_to_string(RIL_E_SUCCESS), "OK"));
|
||||
g_assert(!g_strcmp0(ril_error_to_string(2147483647), "2147483647"));
|
||||
g_assert(!g_strcmp0(ril_request_to_string(RIL_RESPONSE_ACKNOWLEDGEMENT),
|
||||
"RESPONSE_ACK"));
|
||||
g_assert(!g_strcmp0(ril_request_to_string(2147483647),
|
||||
"RIL_REQUEST_2147483647"));
|
||||
g_assert(!g_strcmp0(ril_unsol_event_to_string(2147483647),
|
||||
"RIL_UNSOL_2147483647"));
|
||||
g_assert(!g_strcmp0(ril_radio_state_to_string(2147483647),
|
||||
"2147483647 (?)"));
|
||||
}
|
||||
|
||||
#define TEST_(name) "/ril_util/" name
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@@ -115,6 +129,7 @@ int main(int argc, char *argv[])
|
||||
g_test_add_func(TEST_("parse_tech"), test_parse_tech);
|
||||
g_test_add_func(TEST_("parse_mcc_mnc"), test_parse_mcc_mnc);
|
||||
g_test_add_func(TEST_("parse_int"), test_parse_int);
|
||||
g_test_add_func(TEST_("strings"), test_strings);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
|
||||
979
ofono/unit/test-sailfish_cell_info_dbus.c
Normal file
979
ofono/unit/test-sailfish_cell_info_dbus.c
Normal file
@@ -0,0 +1,979 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2018 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "test-dbus.h"
|
||||
|
||||
#include "sailfish_cell_info.h"
|
||||
#include "sailfish_cell_info_dbus.h"
|
||||
#include "fake_sailfish_cell_info.h"
|
||||
|
||||
#include <gutil_log.h>
|
||||
#include <gutil_macros.h>
|
||||
|
||||
#include "ofono.h"
|
||||
|
||||
#define TEST_TIMEOUT (10) /* seconds */
|
||||
#define TEST_MODEM_PATH "/test"
|
||||
#define TEST_SENDER ":1.0"
|
||||
|
||||
#define CELL_INFO_DBUS_INTERFACE "org.nemomobile.ofono.CellInfo"
|
||||
#define CELL_INFO_DBUS_CELLS_ADDED_SIGNAL "CellsAdded"
|
||||
#define CELL_INFO_DBUS_CELLS_REMOVED_SIGNAL "CellsRemoved"
|
||||
|
||||
#define CELL_DBUS_INTERFACE_VERSION (1)
|
||||
#define CELL_DBUS_INTERFACE "org.nemomobile.ofono.Cell"
|
||||
#define CELL_DBUS_REGISTERED_CHANGED_SIGNAL "RegisteredChanged"
|
||||
#define CELL_DBUS_PROPERTY_CHANGED_SIGNAL "PropertyChanged"
|
||||
#define CELL_DBUS_REMOVED_SIGNAL "Removed"
|
||||
|
||||
static gboolean test_debug;
|
||||
|
||||
/* Stubs (ofono) */
|
||||
|
||||
struct ofono_modem {
|
||||
const char *path;
|
||||
};
|
||||
|
||||
const char *ofono_modem_get_path(struct ofono_modem *modem)
|
||||
{
|
||||
return modem->path;
|
||||
}
|
||||
|
||||
void ofono_modem_add_interface(struct ofono_modem *modem, const char *iface)
|
||||
{
|
||||
DBG("%s %s", modem->path, iface);
|
||||
}
|
||||
|
||||
/* ==== common ==== */
|
||||
|
||||
static gboolean test_timeout(gpointer param)
|
||||
{
|
||||
g_assert(!"TIMEOUT");
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static guint test_setup_timeout(void)
|
||||
{
|
||||
if (!test_debug) {
|
||||
return 0;
|
||||
} else {
|
||||
return g_timeout_add_seconds(TEST_TIMEOUT, test_timeout, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean test_loop_quit(gpointer data)
|
||||
{
|
||||
g_main_loop_quit(data);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void test_loop_quit_later(GMainLoop *loop)
|
||||
{
|
||||
g_idle_add(test_loop_quit, loop);
|
||||
}
|
||||
|
||||
static DBusMessage *test_new_cell_info_call(const char *method)
|
||||
{
|
||||
DBusMessage *msg = dbus_message_new_method_call(NULL, TEST_MODEM_PATH,
|
||||
CELL_INFO_DBUS_INTERFACE, method);
|
||||
|
||||
g_assert(dbus_message_set_sender(msg, TEST_SENDER));
|
||||
return msg;
|
||||
}
|
||||
|
||||
static DBusMessage *test_new_cell_call(const char *path, const char *method)
|
||||
{
|
||||
DBusMessage *msg = dbus_message_new_method_call(NULL, path,
|
||||
CELL_DBUS_INTERFACE, method);
|
||||
|
||||
g_assert(dbus_message_set_sender(msg, TEST_SENDER));
|
||||
return msg;
|
||||
}
|
||||
|
||||
static void test_submit_get_all_call(DBusConnection* connection,
|
||||
const char *cell_path, DBusPendingCallNotifyFunction notify,
|
||||
void *data)
|
||||
{
|
||||
DBusMessage *msg;
|
||||
DBusPendingCall* call;
|
||||
|
||||
msg = test_new_cell_call(cell_path, "GetAll");
|
||||
g_assert(dbus_connection_send_with_reply(connection, msg, &call,
|
||||
DBUS_TIMEOUT_INFINITE));
|
||||
dbus_pending_call_set_notify(call, notify, data, NULL);
|
||||
dbus_message_unref(msg);
|
||||
}
|
||||
|
||||
static void test_check_object_path_array_va(DBusMessageIter *it,
|
||||
const char *path1, va_list va)
|
||||
{
|
||||
DBusMessageIter array;
|
||||
|
||||
g_assert(dbus_message_iter_get_arg_type(it) == DBUS_TYPE_ARRAY);
|
||||
dbus_message_iter_recurse(it, &array);
|
||||
dbus_message_iter_next(it);
|
||||
|
||||
if (path1) {
|
||||
const char *path;
|
||||
|
||||
g_assert(!g_strcmp0(test_dbus_get_object_path(&array), path1));
|
||||
while ((path = va_arg(va, char*)) != NULL) {
|
||||
g_assert(!g_strcmp0(test_dbus_get_object_path(&array),
|
||||
path));
|
||||
}
|
||||
}
|
||||
|
||||
g_assert(dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_INVALID);
|
||||
g_assert(dbus_message_iter_get_arg_type(it) == DBUS_TYPE_INVALID);
|
||||
}
|
||||
|
||||
static void test_check_object_path_array(DBusMessageIter *it,
|
||||
const char *path1, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, path1);
|
||||
test_check_object_path_array_va(it, path1, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
static void test_check_get_cells_reply(DBusPendingCall *call,
|
||||
const char *path1, ...)
|
||||
{
|
||||
DBusMessage *reply = dbus_pending_call_steal_reply(call);
|
||||
DBusMessageIter it;
|
||||
va_list va;
|
||||
|
||||
g_assert(dbus_message_get_type(reply) ==
|
||||
DBUS_MESSAGE_TYPE_METHOD_RETURN);
|
||||
dbus_message_iter_init(reply, &it);
|
||||
va_start(va, path1);
|
||||
test_check_object_path_array_va(&it, path1, va);
|
||||
va_end(va);
|
||||
|
||||
dbus_message_unref(reply);
|
||||
}
|
||||
|
||||
static void test_check_get_all_reply(DBusPendingCall *call,
|
||||
const struct sailfish_cell *cell, const char *type)
|
||||
{
|
||||
DBusMessage *reply = dbus_pending_call_steal_reply(call);
|
||||
DBusMessageIter it, array;
|
||||
|
||||
g_assert(dbus_message_get_type(reply) ==
|
||||
DBUS_MESSAGE_TYPE_METHOD_RETURN);
|
||||
dbus_message_iter_init(reply, &it);
|
||||
g_assert(test_dbus_get_int32(&it) == CELL_DBUS_INTERFACE_VERSION);
|
||||
g_assert(!g_strcmp0(test_dbus_get_string(&it), type));
|
||||
g_assert(test_dbus_get_bool(&it) == (cell->registered != FALSE));
|
||||
g_assert(dbus_message_iter_get_arg_type(&it) == DBUS_TYPE_ARRAY);
|
||||
dbus_message_iter_recurse(&it, &array);
|
||||
dbus_message_iter_next(&it);
|
||||
/* Validate the properties? */
|
||||
g_assert(dbus_message_iter_get_arg_type(&it) == DBUS_TYPE_INVALID);
|
||||
dbus_message_unref(reply);
|
||||
}
|
||||
|
||||
static struct sailfish_cell *test_cell_init_gsm1(struct sailfish_cell *cell)
|
||||
{
|
||||
struct sailfish_cell_info_gsm *gsm = &cell->info.gsm;
|
||||
|
||||
memset(cell, 0, sizeof(*cell));
|
||||
cell->type = SAILFISH_CELL_TYPE_GSM;
|
||||
cell->registered = TRUE;
|
||||
gsm->mcc = 244;
|
||||
gsm->mnc = 5;
|
||||
gsm->lac = 9007;
|
||||
gsm->cid = 42335;
|
||||
gsm->arfcn = INT_MAX;
|
||||
gsm->bsic = INT_MAX;
|
||||
gsm->signalStrength = 26;
|
||||
gsm->bitErrorRate = 99;
|
||||
gsm->timingAdvance = INT_MAX;
|
||||
return cell;
|
||||
}
|
||||
|
||||
static struct sailfish_cell *test_cell_init_gsm2(struct sailfish_cell *cell)
|
||||
{
|
||||
struct sailfish_cell_info_gsm *gsm = &cell->info.gsm;
|
||||
|
||||
memset(cell, 0, sizeof(*cell));
|
||||
cell->type = SAILFISH_CELL_TYPE_GSM;
|
||||
cell->registered = FALSE;
|
||||
gsm->mcc = 244;
|
||||
gsm->mnc = 5;
|
||||
gsm->lac = 9007;
|
||||
gsm->cid = 35600;
|
||||
gsm->arfcn = INT_MAX;
|
||||
gsm->bsic = INT_MAX;
|
||||
gsm->signalStrength = 8;
|
||||
gsm->bitErrorRate = 99;
|
||||
gsm->timingAdvance = INT_MAX;
|
||||
return cell;
|
||||
}
|
||||
|
||||
static struct sailfish_cell *test_cell_init_wcdma1(struct sailfish_cell *cell)
|
||||
{
|
||||
struct sailfish_cell_info_wcdma *wcdma = &cell->info.wcdma;
|
||||
|
||||
memset(cell, 0, sizeof(*cell));
|
||||
cell->type = SAILFISH_CELL_TYPE_WCDMA;
|
||||
cell->registered = TRUE;
|
||||
wcdma->mcc = 250;
|
||||
wcdma->mnc = 99;
|
||||
wcdma->lac = 14760;
|
||||
wcdma->cid = 149331616;
|
||||
wcdma->psc = 371;
|
||||
wcdma->uarfcn = INT_MAX;
|
||||
wcdma->signalStrength = 4;
|
||||
wcdma->bitErrorRate = 99;
|
||||
return cell;
|
||||
}
|
||||
|
||||
static struct sailfish_cell *test_cell_init_wcdma2(struct sailfish_cell *cell)
|
||||
{
|
||||
struct sailfish_cell_info_wcdma *wcdma = &cell->info.wcdma;
|
||||
|
||||
memset(cell, 0, sizeof(*cell));
|
||||
cell->type = SAILFISH_CELL_TYPE_WCDMA;
|
||||
cell->registered = FALSE;
|
||||
wcdma->mcc = INT_MAX;
|
||||
wcdma->mnc = INT_MAX;
|
||||
wcdma->lac = INT_MAX;
|
||||
wcdma->cid = INT_MAX;
|
||||
wcdma->psc = INT_MAX;
|
||||
wcdma->uarfcn = INT_MAX;
|
||||
wcdma->signalStrength = 5;
|
||||
wcdma->bitErrorRate = 99;
|
||||
return cell;
|
||||
}
|
||||
|
||||
static struct sailfish_cell *test_cell_init_lte(struct sailfish_cell *cell)
|
||||
{
|
||||
struct sailfish_cell_info_lte *lte = &cell->info.lte;
|
||||
|
||||
memset(cell, 0, sizeof(*cell));
|
||||
cell->type = SAILFISH_CELL_TYPE_LTE;
|
||||
cell->registered = TRUE;
|
||||
lte->mcc = 244;
|
||||
lte->mnc = 91;
|
||||
lte->ci = 36591883;
|
||||
lte->pci = 309;
|
||||
lte->tac = 4030;
|
||||
lte->earfcn = INT_MAX;
|
||||
lte->signalStrength = 17;
|
||||
lte->rsrp = 106;
|
||||
lte->rsrq = 6;
|
||||
lte->rssnr = INT_MAX;
|
||||
lte->cqi = INT_MAX;
|
||||
lte->timingAdvance = INT_MAX;
|
||||
return cell;
|
||||
}
|
||||
|
||||
/* ==== Misc ==== */
|
||||
|
||||
static void test_misc(void)
|
||||
{
|
||||
struct ofono_modem modem;
|
||||
|
||||
modem.path = TEST_MODEM_PATH;
|
||||
|
||||
/* NULL resistance */
|
||||
g_assert(!sailfish_cell_info_dbus_new(NULL, NULL));
|
||||
g_assert(!sailfish_cell_info_dbus_new(&modem, NULL));
|
||||
sailfish_cell_info_dbus_free(NULL);
|
||||
|
||||
/* Calling __ofono_dbus_cleanup() without __ofono_dbus_init() is ok */
|
||||
__ofono_dbus_cleanup();
|
||||
}
|
||||
|
||||
/* ==== GetCells ==== */
|
||||
|
||||
struct test_get_cells_data {
|
||||
struct ofono_modem modem;
|
||||
struct test_dbus_context context;
|
||||
struct sailfish_cell_info *info;
|
||||
struct sailfish_cell_info_dbus *dbus;
|
||||
};
|
||||
|
||||
static void test_get_cells_call(struct test_get_cells_data *test,
|
||||
DBusPendingCallNotifyFunction notify)
|
||||
{
|
||||
DBusPendingCall *call;
|
||||
DBusConnection *connection = test->context.client_connection;
|
||||
DBusMessage *msg = test_new_cell_info_call("GetCells");
|
||||
|
||||
g_assert(dbus_connection_send_with_reply(connection, msg, &call,
|
||||
DBUS_TIMEOUT_INFINITE));
|
||||
dbus_pending_call_set_notify(call, notify, test, NULL);
|
||||
dbus_message_unref(msg);
|
||||
}
|
||||
|
||||
static void test_get_cells_start_reply3(DBusPendingCall *call, void *data)
|
||||
{
|
||||
struct test_get_cells_data *test = data;
|
||||
DBusMessageIter it;
|
||||
DBusMessage *signal = test_dbus_take_signal(&test->context,
|
||||
test->modem.path, CELL_INFO_DBUS_INTERFACE,
|
||||
CELL_INFO_DBUS_CELLS_REMOVED_SIGNAL);
|
||||
|
||||
DBG("");
|
||||
test_check_get_cells_reply(call, "/test/cell_1", NULL);
|
||||
dbus_pending_call_unref(call);
|
||||
|
||||
/* Validate the signal */
|
||||
g_assert(signal);
|
||||
dbus_message_iter_init(signal, &it);
|
||||
test_check_object_path_array(&it, "/test/cell_0", NULL);
|
||||
dbus_message_unref(signal);
|
||||
|
||||
test_loop_quit_later(test->context.loop);
|
||||
}
|
||||
|
||||
static void test_get_cells_start_reply2(DBusPendingCall *call, void *data)
|
||||
{
|
||||
struct test_get_cells_data *test = data;
|
||||
const char *cell_added = "/test/cell_1";
|
||||
struct sailfish_cell cell;
|
||||
DBusMessageIter it;
|
||||
DBusMessage *signal = test_dbus_take_signal(&test->context,
|
||||
test->modem.path, CELL_INFO_DBUS_INTERFACE,
|
||||
CELL_INFO_DBUS_CELLS_ADDED_SIGNAL);
|
||||
|
||||
DBG("");
|
||||
test_check_get_cells_reply(call, "/test/cell_0", cell_added, NULL);
|
||||
dbus_pending_call_unref(call);
|
||||
|
||||
/* Validate the signal */
|
||||
g_assert(signal);
|
||||
dbus_message_iter_init(signal, &it);
|
||||
test_check_object_path_array(&it, cell_added, NULL);
|
||||
dbus_message_unref(signal);
|
||||
|
||||
/* Remove "/test/cell_0" */
|
||||
g_assert(fake_cell_info_remove_cell(test->info,
|
||||
test_cell_init_gsm1(&cell)));
|
||||
fake_cell_info_cells_changed(test->info);
|
||||
test_get_cells_call(test, test_get_cells_start_reply3);
|
||||
}
|
||||
|
||||
static void test_get_cells_start_reply1(DBusPendingCall *call, void *data)
|
||||
{
|
||||
struct test_get_cells_data *test = data;
|
||||
struct sailfish_cell cell;
|
||||
|
||||
DBG("");
|
||||
test_check_get_cells_reply(call, "/test/cell_0", NULL);
|
||||
dbus_pending_call_unref(call);
|
||||
|
||||
/* Add "/test/cell_1" */
|
||||
fake_cell_info_add_cell(test->info, test_cell_init_gsm2(&cell));
|
||||
fake_cell_info_cells_changed(test->info);
|
||||
test_get_cells_call(test, test_get_cells_start_reply2);
|
||||
}
|
||||
|
||||
static void test_get_cells_start(struct test_dbus_context *context)
|
||||
{
|
||||
struct sailfish_cell cell;
|
||||
struct test_get_cells_data *test =
|
||||
G_CAST(context, struct test_get_cells_data, context);
|
||||
|
||||
DBG("");
|
||||
test->info = fake_cell_info_new();
|
||||
fake_cell_info_add_cell(test->info, test_cell_init_gsm1(&cell));
|
||||
|
||||
test->dbus = sailfish_cell_info_dbus_new(&test->modem, test->info);
|
||||
g_assert(test->dbus);
|
||||
|
||||
test_get_cells_call(test, test_get_cells_start_reply1);
|
||||
}
|
||||
|
||||
static void test_get_cells(void)
|
||||
{
|
||||
struct test_get_cells_data test;
|
||||
guint timeout = test_setup_timeout();
|
||||
|
||||
memset(&test, 0, sizeof(test));
|
||||
test.modem.path = TEST_MODEM_PATH;
|
||||
test.context.start = test_get_cells_start;
|
||||
test_dbus_setup(&test.context);
|
||||
|
||||
g_main_loop_run(test.context.loop);
|
||||
|
||||
sailfish_cell_info_unref(test.info);
|
||||
sailfish_cell_info_dbus_free(test.dbus);
|
||||
test_dbus_shutdown(&test.context);
|
||||
if (timeout) {
|
||||
g_source_remove(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
/* ==== GetAll ==== */
|
||||
|
||||
struct test_get_all_data {
|
||||
struct ofono_modem modem;
|
||||
struct test_dbus_context context;
|
||||
struct sailfish_cell_info_dbus *dbus;
|
||||
struct sailfish_cell cell;
|
||||
const char *type;
|
||||
};
|
||||
|
||||
static void test_get_all_reply(DBusPendingCall *call, void *data)
|
||||
{
|
||||
struct test_get_all_data *test = data;
|
||||
|
||||
DBG("");
|
||||
test_check_get_all_reply(call, &test->cell, test->type);
|
||||
dbus_pending_call_unref(call);
|
||||
|
||||
test_loop_quit_later(test->context.loop);
|
||||
}
|
||||
|
||||
static void test_get_all_start(struct test_dbus_context *context)
|
||||
{
|
||||
struct sailfish_cell_info *info;
|
||||
struct test_get_all_data *test =
|
||||
G_CAST(context, struct test_get_all_data, context);
|
||||
|
||||
DBG("");
|
||||
info = fake_cell_info_new();
|
||||
fake_cell_info_add_cell(info, &test->cell);
|
||||
test->dbus = sailfish_cell_info_dbus_new(&test->modem, info);
|
||||
g_assert(test->dbus);
|
||||
sailfish_cell_info_unref(info);
|
||||
|
||||
test_submit_get_all_call(context->client_connection, "/test/cell_0",
|
||||
test_get_all_reply, test);
|
||||
}
|
||||
|
||||
static void test_get_all(const struct sailfish_cell *cell, const char *type)
|
||||
{
|
||||
struct test_get_all_data test;
|
||||
guint timeout = test_setup_timeout();
|
||||
|
||||
memset(&test, 0, sizeof(test));
|
||||
test.modem.path = TEST_MODEM_PATH;
|
||||
test.context.start = test_get_all_start;
|
||||
test.cell = *cell;
|
||||
test.type = type;
|
||||
test_dbus_setup(&test.context);
|
||||
|
||||
g_main_loop_run(test.context.loop);
|
||||
|
||||
sailfish_cell_info_dbus_free(test.dbus);
|
||||
test_dbus_shutdown(&test.context);
|
||||
if (timeout) {
|
||||
g_source_remove(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_get_all1(void)
|
||||
{
|
||||
struct sailfish_cell cell;
|
||||
|
||||
test_get_all(test_cell_init_gsm1(&cell), "gsm");
|
||||
}
|
||||
|
||||
static void test_get_all2(void)
|
||||
{
|
||||
struct sailfish_cell cell;
|
||||
|
||||
test_get_all(test_cell_init_wcdma2(&cell), "wcdma");
|
||||
}
|
||||
|
||||
static void test_get_all3(void)
|
||||
{
|
||||
struct sailfish_cell cell;
|
||||
|
||||
test_get_all(test_cell_init_lte(&cell), "lte");
|
||||
}
|
||||
|
||||
static void test_get_all4(void)
|
||||
{
|
||||
struct sailfish_cell cell;
|
||||
|
||||
/* Invalid cell */
|
||||
memset(&cell, 0xff, sizeof(cell));
|
||||
test_get_all(&cell, "unknown");
|
||||
}
|
||||
|
||||
/* ==== GetInterfaceVersion ==== */
|
||||
|
||||
struct test_get_version_data {
|
||||
struct ofono_modem modem;
|
||||
struct test_dbus_context context;
|
||||
struct sailfish_cell_info_dbus *dbus;
|
||||
};
|
||||
|
||||
static void test_get_version_reply(DBusPendingCall *call, void *data)
|
||||
{
|
||||
struct test_get_version_data *test = data;
|
||||
DBusMessage *reply = dbus_pending_call_steal_reply(call);
|
||||
dbus_int32_t version;
|
||||
|
||||
DBG("");
|
||||
g_assert(dbus_message_get_type(reply) ==
|
||||
DBUS_MESSAGE_TYPE_METHOD_RETURN);
|
||||
g_assert(dbus_message_get_args(reply, NULL,
|
||||
DBUS_TYPE_INT32, &version,
|
||||
DBUS_TYPE_INVALID));
|
||||
g_assert(version == CELL_DBUS_INTERFACE_VERSION);
|
||||
dbus_message_unref(reply);
|
||||
dbus_pending_call_unref(call);
|
||||
|
||||
test_loop_quit_later(test->context.loop);
|
||||
}
|
||||
|
||||
static void test_get_version_start(struct test_dbus_context *context)
|
||||
{
|
||||
DBusPendingCall *call;
|
||||
DBusMessage *msg;
|
||||
struct sailfish_cell cell;
|
||||
struct sailfish_cell_info *info;
|
||||
struct test_get_version_data *test =
|
||||
G_CAST(context, struct test_get_version_data, context);
|
||||
|
||||
DBG("");
|
||||
info = fake_cell_info_new();
|
||||
fake_cell_info_add_cell(info, test_cell_init_gsm1(&cell));
|
||||
test->dbus = sailfish_cell_info_dbus_new(&test->modem, info);
|
||||
g_assert(test->dbus);
|
||||
sailfish_cell_info_unref(info);
|
||||
|
||||
msg = test_new_cell_call("/test/cell_0", "GetInterfaceVersion");
|
||||
g_assert(dbus_connection_send_with_reply(context->client_connection,
|
||||
msg, &call, DBUS_TIMEOUT_INFINITE));
|
||||
dbus_pending_call_set_notify(call, test_get_version_reply, test, NULL);
|
||||
dbus_message_unref(msg);
|
||||
}
|
||||
|
||||
static void test_get_version(void)
|
||||
{
|
||||
struct test_get_version_data test;
|
||||
guint timeout = test_setup_timeout();
|
||||
|
||||
memset(&test, 0, sizeof(test));
|
||||
test.modem.path = TEST_MODEM_PATH;
|
||||
test.context.start = test_get_version_start;
|
||||
test_dbus_setup(&test.context);
|
||||
|
||||
g_main_loop_run(test.context.loop);
|
||||
|
||||
sailfish_cell_info_dbus_free(test.dbus);
|
||||
test_dbus_shutdown(&test.context);
|
||||
if (timeout) {
|
||||
g_source_remove(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
/* ==== GetType ==== */
|
||||
|
||||
struct test_get_type_data {
|
||||
struct ofono_modem modem;
|
||||
struct test_dbus_context context;
|
||||
struct sailfish_cell_info_dbus *dbus;
|
||||
};
|
||||
|
||||
static void test_get_type_reply(DBusPendingCall *call, void *data)
|
||||
{
|
||||
struct test_get_type_data *test = data;
|
||||
DBusMessage *reply = dbus_pending_call_steal_reply(call);
|
||||
DBusMessageIter it;
|
||||
|
||||
DBG("");
|
||||
g_assert(dbus_message_get_type(reply) ==
|
||||
DBUS_MESSAGE_TYPE_METHOD_RETURN);
|
||||
dbus_message_iter_init(reply, &it);
|
||||
g_assert(!g_strcmp0(test_dbus_get_string(&it), "wcdma"));
|
||||
g_assert(dbus_message_iter_get_arg_type(&it) == DBUS_TYPE_INVALID);
|
||||
dbus_message_unref(reply);
|
||||
dbus_pending_call_unref(call);
|
||||
|
||||
test_loop_quit_later(test->context.loop);
|
||||
}
|
||||
|
||||
static void test_get_type_start(struct test_dbus_context *context)
|
||||
{
|
||||
DBusPendingCall *call;
|
||||
DBusMessage *msg;
|
||||
struct sailfish_cell cell;
|
||||
struct sailfish_cell_info *info;
|
||||
struct test_get_type_data *test =
|
||||
G_CAST(context, struct test_get_type_data, context);
|
||||
|
||||
DBG("");
|
||||
info = fake_cell_info_new();
|
||||
fake_cell_info_add_cell(info, test_cell_init_wcdma1(&cell));
|
||||
test->dbus = sailfish_cell_info_dbus_new(&test->modem, info);
|
||||
g_assert(test->dbus);
|
||||
sailfish_cell_info_unref(info);
|
||||
|
||||
msg = test_new_cell_call("/test/cell_0", "GetType");
|
||||
g_assert(dbus_connection_send_with_reply(context->client_connection,
|
||||
msg, &call, DBUS_TIMEOUT_INFINITE));
|
||||
dbus_pending_call_set_notify(call, test_get_type_reply, test, NULL);
|
||||
dbus_message_unref(msg);
|
||||
}
|
||||
|
||||
static void test_get_type(void)
|
||||
{
|
||||
struct test_get_type_data test;
|
||||
guint timeout = test_setup_timeout();
|
||||
|
||||
memset(&test, 0, sizeof(test));
|
||||
test.modem.path = TEST_MODEM_PATH;
|
||||
test.context.start = test_get_type_start;
|
||||
test_dbus_setup(&test.context);
|
||||
|
||||
g_main_loop_run(test.context.loop);
|
||||
|
||||
sailfish_cell_info_dbus_free(test.dbus);
|
||||
test_dbus_shutdown(&test.context);
|
||||
if (timeout) {
|
||||
g_source_remove(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
/* ==== GetRegistered ==== */
|
||||
|
||||
struct test_get_registered_data {
|
||||
struct ofono_modem modem;
|
||||
struct test_dbus_context context;
|
||||
struct sailfish_cell_info_dbus *dbus;
|
||||
};
|
||||
|
||||
static void test_get_registered_reply(DBusPendingCall *call, void *data)
|
||||
{
|
||||
struct test_get_registered_data *test = data;
|
||||
DBusMessage *reply = dbus_pending_call_steal_reply(call);
|
||||
DBusMessageIter it;
|
||||
|
||||
DBG("");
|
||||
g_assert(dbus_message_get_type(reply) ==
|
||||
DBUS_MESSAGE_TYPE_METHOD_RETURN);
|
||||
dbus_message_iter_init(reply, &it);
|
||||
g_assert(test_dbus_get_bool(&it) == TRUE);
|
||||
g_assert(dbus_message_iter_get_arg_type(&it) == DBUS_TYPE_INVALID);
|
||||
dbus_message_unref(reply);
|
||||
dbus_pending_call_unref(call);
|
||||
|
||||
test_loop_quit_later(test->context.loop);
|
||||
}
|
||||
|
||||
static void test_get_registered_start(struct test_dbus_context *context)
|
||||
{
|
||||
DBusPendingCall *call;
|
||||
DBusMessage *msg;
|
||||
struct sailfish_cell cell;
|
||||
struct sailfish_cell_info *info;
|
||||
struct test_get_registered_data *test =
|
||||
G_CAST(context, struct test_get_registered_data, context);
|
||||
|
||||
DBG("");
|
||||
info = fake_cell_info_new();
|
||||
fake_cell_info_add_cell(info, test_cell_init_wcdma1(&cell));
|
||||
test->dbus = sailfish_cell_info_dbus_new(&test->modem, info);
|
||||
g_assert(test->dbus);
|
||||
sailfish_cell_info_unref(info);
|
||||
|
||||
msg = test_new_cell_call("/test/cell_0", "GetRegistered");
|
||||
g_assert(dbus_connection_send_with_reply(context->client_connection,
|
||||
msg, &call, DBUS_TIMEOUT_INFINITE));
|
||||
dbus_pending_call_set_notify(call, test_get_registered_reply, test,
|
||||
NULL);
|
||||
dbus_message_unref(msg);
|
||||
}
|
||||
|
||||
static void test_get_registered(void)
|
||||
{
|
||||
struct test_get_registered_data test;
|
||||
guint timeout = test_setup_timeout();
|
||||
|
||||
memset(&test, 0, sizeof(test));
|
||||
test.modem.path = TEST_MODEM_PATH;
|
||||
test.context.start = test_get_registered_start;
|
||||
test_dbus_setup(&test.context);
|
||||
|
||||
g_main_loop_run(test.context.loop);
|
||||
|
||||
sailfish_cell_info_dbus_free(test.dbus);
|
||||
test_dbus_shutdown(&test.context);
|
||||
if (timeout) {
|
||||
g_source_remove(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
/* ==== GetProperties ==== */
|
||||
|
||||
struct test_get_properties_data {
|
||||
struct ofono_modem modem;
|
||||
struct test_dbus_context context;
|
||||
struct sailfish_cell_info_dbus *dbus;
|
||||
};
|
||||
|
||||
static void test_get_properties_reply(DBusPendingCall *call, void *data)
|
||||
{
|
||||
struct test_get_properties_data *test = data;
|
||||
DBusMessage *reply = dbus_pending_call_steal_reply(call);
|
||||
DBusMessageIter it, array;
|
||||
|
||||
DBG("");
|
||||
g_assert(dbus_message_get_type(reply) ==
|
||||
DBUS_MESSAGE_TYPE_METHOD_RETURN);
|
||||
dbus_message_iter_init(reply, &it);
|
||||
g_assert(dbus_message_iter_get_arg_type(&it) == DBUS_TYPE_ARRAY);
|
||||
dbus_message_iter_recurse(&it, &array);
|
||||
dbus_message_iter_next(&it);
|
||||
/* Validate the properties? */
|
||||
g_assert(dbus_message_iter_get_arg_type(&it) == DBUS_TYPE_INVALID);
|
||||
dbus_message_unref(reply);
|
||||
dbus_pending_call_unref(call);
|
||||
|
||||
test_loop_quit_later(test->context.loop);
|
||||
}
|
||||
|
||||
static void test_get_properties_start(struct test_dbus_context *context)
|
||||
{
|
||||
DBusPendingCall *call;
|
||||
DBusMessage *msg;
|
||||
struct sailfish_cell cell;
|
||||
struct sailfish_cell_info *info;
|
||||
struct test_get_properties_data *test =
|
||||
G_CAST(context, struct test_get_properties_data, context);
|
||||
|
||||
DBG("");
|
||||
info = fake_cell_info_new();
|
||||
fake_cell_info_add_cell(info, test_cell_init_wcdma2(&cell));
|
||||
test->dbus = sailfish_cell_info_dbus_new(&test->modem, info);
|
||||
g_assert(test->dbus);
|
||||
sailfish_cell_info_unref(info);
|
||||
|
||||
msg = test_new_cell_call("/test/cell_0", "GetProperties");
|
||||
g_assert(dbus_connection_send_with_reply(context->client_connection,
|
||||
msg, &call, DBUS_TIMEOUT_INFINITE));
|
||||
dbus_pending_call_set_notify(call, test_get_properties_reply, test,
|
||||
NULL);
|
||||
dbus_message_unref(msg);
|
||||
}
|
||||
|
||||
static void test_get_properties(void)
|
||||
{
|
||||
struct test_get_properties_data test;
|
||||
guint timeout = test_setup_timeout();
|
||||
|
||||
memset(&test, 0, sizeof(test));
|
||||
test.modem.path = TEST_MODEM_PATH;
|
||||
test.context.start = test_get_properties_start;
|
||||
test_dbus_setup(&test.context);
|
||||
|
||||
g_main_loop_run(test.context.loop);
|
||||
|
||||
sailfish_cell_info_dbus_free(test.dbus);
|
||||
test_dbus_shutdown(&test.context);
|
||||
if (timeout) {
|
||||
g_source_remove(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
/* ==== RegisteredChanged ==== */
|
||||
|
||||
struct test_registered_changed_data {
|
||||
struct ofono_modem modem;
|
||||
struct test_dbus_context context;
|
||||
struct sailfish_cell_info *info;
|
||||
struct sailfish_cell_info_dbus *dbus;
|
||||
struct sailfish_cell cell;
|
||||
const char *type;
|
||||
const char *cell_path;
|
||||
};
|
||||
|
||||
static void test_registered_changed_reply(DBusPendingCall *call, void *data)
|
||||
{
|
||||
struct test_registered_changed_data *test = data;
|
||||
|
||||
DBG("");
|
||||
test_check_get_all_reply(call, &test->cell, test->type);
|
||||
dbus_pending_call_unref(call);
|
||||
|
||||
test_loop_quit_later(test->context.loop);
|
||||
}
|
||||
|
||||
static void test_registered_changed_start(struct test_dbus_context *context)
|
||||
{
|
||||
struct test_registered_changed_data *test =
|
||||
G_CAST(context, struct test_registered_changed_data, context);
|
||||
struct sailfish_cell *first_cell;
|
||||
|
||||
DBG("");
|
||||
test->info = fake_cell_info_new();
|
||||
fake_cell_info_add_cell(test->info, &test->cell);
|
||||
test->dbus = sailfish_cell_info_dbus_new(&test->modem, test->info);
|
||||
g_assert(test->dbus);
|
||||
|
||||
/* Trigger "RegisteredChanged" signal */
|
||||
first_cell = test->info->cells->data;
|
||||
test->cell.registered =
|
||||
first_cell->registered = !first_cell->registered;
|
||||
fake_cell_info_cells_changed(test->info);
|
||||
|
||||
test_submit_get_all_call(context->client_connection, test->cell_path,
|
||||
test_registered_changed_reply, test);
|
||||
}
|
||||
|
||||
static void test_registered_changed(void)
|
||||
{
|
||||
struct test_registered_changed_data test;
|
||||
guint timeout = test_setup_timeout();
|
||||
|
||||
memset(&test, 0, sizeof(test));
|
||||
test.modem.path = TEST_MODEM_PATH;
|
||||
test.context.start = test_registered_changed_start;
|
||||
test_cell_init_gsm1(&test.cell);
|
||||
test.type = "gsm";
|
||||
test.cell_path = "/test/cell_0";
|
||||
test_dbus_setup(&test.context);
|
||||
|
||||
g_main_loop_run(test.context.loop);
|
||||
|
||||
/* We must have received "RegisteredChanged" signal */
|
||||
g_assert(test_dbus_find_signal(&test.context, test.cell_path,
|
||||
CELL_DBUS_INTERFACE, CELL_DBUS_REGISTERED_CHANGED_SIGNAL));
|
||||
|
||||
sailfish_cell_info_unref(test.info);
|
||||
sailfish_cell_info_dbus_free(test.dbus);
|
||||
test_dbus_shutdown(&test.context);
|
||||
if (timeout) {
|
||||
g_source_remove(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
/* ==== PropertyChanged ==== */
|
||||
|
||||
struct test_property_changed_data {
|
||||
struct ofono_modem modem;
|
||||
struct test_dbus_context context;
|
||||
struct sailfish_cell_info *info;
|
||||
struct sailfish_cell_info_dbus *dbus;
|
||||
struct sailfish_cell cell;
|
||||
const char *type;
|
||||
const char *cell_path;
|
||||
};
|
||||
|
||||
static void test_property_changed_reply1(DBusPendingCall *call, void *data)
|
||||
{
|
||||
struct test_property_changed_data *test = data;
|
||||
|
||||
DBG("");
|
||||
test_check_get_all_reply(call, &test->cell, test->type);
|
||||
dbus_pending_call_unref(call);
|
||||
|
||||
test_loop_quit_later(test->context.loop);
|
||||
}
|
||||
|
||||
static void test_property_changed_start(struct test_dbus_context *context)
|
||||
{
|
||||
struct test_property_changed_data *test =
|
||||
G_CAST(context, struct test_property_changed_data, context);
|
||||
struct sailfish_cell *first_cell;
|
||||
|
||||
DBG("");
|
||||
test->info = fake_cell_info_new();
|
||||
fake_cell_info_add_cell(test->info, &test->cell);
|
||||
test->dbus = sailfish_cell_info_dbus_new(&test->modem, test->info);
|
||||
g_assert(test->dbus);
|
||||
|
||||
/* Trigger "PropertyChanged" signal */
|
||||
first_cell = test->info->cells->data;
|
||||
test->cell.info.gsm.signalStrength =
|
||||
(++(first_cell->info.gsm.signalStrength));
|
||||
fake_cell_info_cells_changed(test->info);
|
||||
|
||||
test_submit_get_all_call(context->client_connection, test->cell_path,
|
||||
test_property_changed_reply1, test);
|
||||
}
|
||||
|
||||
static void test_property_changed(void)
|
||||
{
|
||||
struct test_property_changed_data test;
|
||||
guint timeout = test_setup_timeout();
|
||||
|
||||
memset(&test, 0, sizeof(test));
|
||||
test.modem.path = TEST_MODEM_PATH;
|
||||
test.context.start = test_property_changed_start;
|
||||
test_cell_init_gsm1(&test.cell);
|
||||
test.type = "gsm";
|
||||
test.cell_path = "/test/cell_0";
|
||||
test_dbus_setup(&test.context);
|
||||
|
||||
g_main_loop_run(test.context.loop);
|
||||
|
||||
/* We must have received "PropertyChanged" signal */
|
||||
g_assert(test_dbus_find_signal(&test.context, test.cell_path,
|
||||
CELL_DBUS_INTERFACE, CELL_DBUS_PROPERTY_CHANGED_SIGNAL));
|
||||
|
||||
sailfish_cell_info_unref(test.info);
|
||||
sailfish_cell_info_dbus_free(test.dbus);
|
||||
test_dbus_shutdown(&test.context);
|
||||
if (timeout) {
|
||||
g_source_remove(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
#define TEST_(name) "/sailfish_cell_info_dbus/" name
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
for (i=1; i<argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
if (!strcmp(arg, "-d") || !strcmp(arg, "--debug")) {
|
||||
test_debug = TRUE;
|
||||
} else {
|
||||
GWARN("Unsupported command line option %s", arg);
|
||||
}
|
||||
}
|
||||
|
||||
gutil_log_timestamp = FALSE;
|
||||
gutil_log_default.level = g_test_verbose() ?
|
||||
GLOG_LEVEL_VERBOSE : GLOG_LEVEL_NONE;
|
||||
__ofono_log_init("test-sailfish_cell_info_dbus",
|
||||
g_test_verbose() ? "*" : NULL,
|
||||
FALSE, FALSE);
|
||||
|
||||
g_test_add_func(TEST_("Misc"), test_misc);
|
||||
g_test_add_func(TEST_("GetCells"), test_get_cells);
|
||||
g_test_add_func(TEST_("GetAll1"), test_get_all1);
|
||||
g_test_add_func(TEST_("GetAll2"), test_get_all2);
|
||||
g_test_add_func(TEST_("GetAll3"), test_get_all3);
|
||||
g_test_add_func(TEST_("GetAll4"), test_get_all4);
|
||||
g_test_add_func(TEST_("GetInterfaceVersion"), test_get_version);
|
||||
g_test_add_func(TEST_("GetType"), test_get_type);
|
||||
g_test_add_func(TEST_("GetRegistered"), test_get_registered);
|
||||
g_test_add_func(TEST_("GetProperties"), test_get_properties);
|
||||
g_test_add_func(TEST_("RegisteredChanged"), test_registered_changed);
|
||||
g_test_add_func(TEST_("PropertyChanged"), test_property_changed);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2017 Jolla Ltd.
|
||||
* Copyright (C) 2017-2018 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
|
||||
@@ -919,9 +919,11 @@ static gboolean test_voice_sim_done(gpointer user_data)
|
||||
g_assert(!g_strcmp0(m->default_voice_path, TEST_PATH));
|
||||
|
||||
/* Remove the SIM */
|
||||
fake_sailfish_watch_set_ofono_sim(w, NULL);
|
||||
fake_sailfish_watch_emit_queued_signals(w);
|
||||
fake_sailfish_watch_set_ofono_iccid(w, NULL);
|
||||
fake_sailfish_watch_set_ofono_imsi(w, NULL);
|
||||
fake_sailfish_watch_set_ofono_spn(w, NULL);
|
||||
sailfish_manager_set_sim_state(s->handle, SAILFISH_SIM_STATE_ABSENT);
|
||||
fake_sailfish_watch_emit_queued_signals(w);
|
||||
g_assert(!m->slots[0]->sim_present);
|
||||
g_assert(!g_strcmp0(m->default_voice_imsi, TEST_IMSI));
|
||||
g_assert(!m->default_voice_path);
|
||||
@@ -1240,6 +1242,24 @@ static gboolean test_multisim_done(gpointer user_data)
|
||||
g_assert(!m->default_data_imsi);
|
||||
g_assert(!m->default_data_path);
|
||||
|
||||
/* But there is automatic voice SIM selection */
|
||||
g_assert(!m->default_voice_imsi);
|
||||
g_assert(!g_strcmp0(m->default_voice_path, TEST_PATH));
|
||||
|
||||
/* Switch the voice SIM back and forth */
|
||||
fake_sailfish_manager_dbus.cb.set_default_voice_imsi(m, TEST_IMSI);
|
||||
g_assert(!g_strcmp0(m->default_voice_imsi, TEST_IMSI));
|
||||
g_assert(!g_strcmp0(m->default_voice_path, TEST_PATH));
|
||||
|
||||
fake_sailfish_manager_dbus.cb.set_default_voice_imsi(m, TEST_IMSI_1);
|
||||
g_assert(!g_strcmp0(m->default_voice_imsi, TEST_IMSI_1));
|
||||
g_assert(!g_strcmp0(m->default_voice_path, TEST_PATH_1));
|
||||
|
||||
/* test_1 remains the current voice slot */
|
||||
fake_sailfish_manager_dbus.cb.set_default_voice_imsi(m, NULL);
|
||||
g_assert(!m->default_voice_imsi);
|
||||
g_assert(!g_strcmp0(m->default_voice_path, TEST_PATH_1));
|
||||
|
||||
/* Reserve the first slot for data */
|
||||
fake_sailfish_manager_dbus.cb.set_default_data_imsi(m, TEST_IMSI);
|
||||
g_assert(s->data_role == SAILFISH_DATA_ROLE_INTERNET);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2017 Jolla Ltd.
|
||||
* Copyright (C) 2017-2018 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
|
||||
@@ -27,8 +27,10 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#define TEST_PATH "/test"
|
||||
#define TEST_ICCID "1111111111111111111"
|
||||
#define TEST_ICCID "0000000000000000000"
|
||||
#define TEST_IMSI "244120000000000"
|
||||
#define TEST_ICCID_1 "1111111111111111111"
|
||||
#define TEST_IMSI_1 "244120000000001"
|
||||
#define TEST_MCC "244"
|
||||
#define TEST_MNC "12"
|
||||
#define TEST_DEFAULT_SPN TEST_MCC TEST_MNC
|
||||
@@ -171,6 +173,18 @@ static void netreg_notify_status_watches(struct ofono_netreg *netreg)
|
||||
}
|
||||
}
|
||||
|
||||
static void test_remove_sim(struct ofono_sim* sim, struct sailfish_watch *watch)
|
||||
{
|
||||
sim->mcc = NULL;
|
||||
sim->mnc = NULL;
|
||||
sim->state = OFONO_SIM_STATE_NOT_PRESENT;
|
||||
fake_sailfish_watch_signal_queue(watch, WATCH_SIGNAL_IMSI_CHANGED);
|
||||
fake_sailfish_watch_signal_queue(watch, WATCH_SIGNAL_SIM_STATE_CHANGED);
|
||||
fake_sailfish_watch_set_ofono_iccid(watch, NULL);
|
||||
fake_sailfish_watch_set_ofono_imsi(watch, NULL);
|
||||
fake_sailfish_watch_set_ofono_spn(watch, NULL);
|
||||
fake_sailfish_watch_emit_queued_signals(watch);
|
||||
}
|
||||
|
||||
/* Test cases */
|
||||
|
||||
@@ -182,7 +196,6 @@ static void test_basic(void)
|
||||
g_assert(!sailfish_sim_info_new(NULL));
|
||||
g_assert(!sailfish_sim_info_ref(NULL));
|
||||
sailfish_sim_info_unref(NULL);
|
||||
sailfish_sim_info_invalidate(NULL);
|
||||
g_assert(!sailfish_sim_info_add_iccid_changed_handler(NULL,NULL,NULL));
|
||||
g_assert(!sailfish_sim_info_add_imsi_changed_handler(NULL,NULL,NULL));
|
||||
g_assert(!sailfish_sim_info_add_spn_changed_handler(NULL,NULL,NULL));
|
||||
@@ -192,7 +205,6 @@ static void test_basic(void)
|
||||
/* Very basic things (mostly to improve code coverage) */
|
||||
si = sailfish_sim_info_new("/test");
|
||||
g_assert(si);
|
||||
sailfish_sim_info_invalidate(si);
|
||||
g_assert(!sailfish_sim_info_add_iccid_changed_handler(si,NULL,NULL));
|
||||
g_assert(!sailfish_sim_info_add_imsi_changed_handler(si,NULL,NULL));
|
||||
g_assert(!sailfish_sim_info_add_spn_changed_handler(si,NULL,NULL));
|
||||
@@ -241,6 +253,9 @@ static void test_cache(void)
|
||||
g_assert(!count[SIM_INFO_SIGNAL_ICCID_CHANGED]);
|
||||
g_assert(!count[SIM_INFO_SIGNAL_IMSI_CHANGED]);
|
||||
g_assert(!count[SIM_INFO_SIGNAL_SPN_CHANGED]);
|
||||
g_assert(!si->iccid);
|
||||
g_assert(!si->imsi);
|
||||
g_assert(!si->spn);
|
||||
|
||||
fake_sailfish_watch_set_ofono_iccid(w, TEST_ICCID);
|
||||
fake_sailfish_watch_emit_queued_signals(w);
|
||||
@@ -258,7 +273,7 @@ static void test_cache(void)
|
||||
g_assert(!count[SIM_INFO_SIGNAL_SPN_CHANGED]);
|
||||
g_assert(count[SIM_INFO_SIGNAL_IMSI_CHANGED] == 1);
|
||||
count[SIM_INFO_SIGNAL_IMSI_CHANGED] = 0;
|
||||
/* ICCID mape appears */
|
||||
/* ICCID map appears */
|
||||
g_assert(stat(ICCID_MAP, &st) == 0);
|
||||
g_assert(S_ISREG(st.st_mode));
|
||||
/* But no cache yet */
|
||||
@@ -268,12 +283,46 @@ static void test_cache(void)
|
||||
sim.mcc = TEST_MCC;
|
||||
sim.mnc = TEST_MNC;
|
||||
sim.state = OFONO_SIM_STATE_READY;
|
||||
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_IMSI_CHANGED);
|
||||
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_SIM_STATE_CHANGED);
|
||||
fake_sailfish_watch_emit_queued_signals(w);
|
||||
g_assert(!g_strcmp0(si->spn, TEST_DEFAULT_SPN));
|
||||
g_assert(count[SIM_INFO_SIGNAL_SPN_CHANGED] == 1);
|
||||
count[SIM_INFO_SIGNAL_SPN_CHANGED] = 0;
|
||||
|
||||
/* Remove the SIM and insert it again */
|
||||
test_remove_sim(&sim, w);
|
||||
g_assert(count[SIM_INFO_SIGNAL_ICCID_CHANGED] == 1);
|
||||
g_assert(count[SIM_INFO_SIGNAL_IMSI_CHANGED] == 1);
|
||||
g_assert(count[SIM_INFO_SIGNAL_SPN_CHANGED] == 1);
|
||||
g_assert(!si->iccid);
|
||||
g_assert(!si->imsi);
|
||||
g_assert(!si->spn);
|
||||
memset(count, 0, sizeof(count));
|
||||
|
||||
sim.state = OFONO_SIM_STATE_INSERTED;
|
||||
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_SIM_STATE_CHANGED);
|
||||
fake_sailfish_watch_emit_queued_signals(w);
|
||||
g_assert(!count[SIM_INFO_SIGNAL_ICCID_CHANGED]);
|
||||
g_assert(!count[SIM_INFO_SIGNAL_IMSI_CHANGED]);
|
||||
g_assert(!count[SIM_INFO_SIGNAL_SPN_CHANGED]);
|
||||
|
||||
sim.mcc = TEST_MCC;
|
||||
sim.mnc = TEST_MNC;
|
||||
sim.state = OFONO_SIM_STATE_READY;
|
||||
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_SIM_STATE_CHANGED);
|
||||
fake_sailfish_watch_set_ofono_iccid(w, TEST_ICCID);
|
||||
fake_sailfish_watch_emit_queued_signals(w);
|
||||
|
||||
/* IMSI gets loaded from the cache file */
|
||||
g_assert(!g_strcmp0(si->iccid, TEST_ICCID));
|
||||
g_assert(!g_strcmp0(si->imsi, TEST_IMSI));
|
||||
g_assert(!g_strcmp0(si->spn, TEST_DEFAULT_SPN));
|
||||
g_assert(count[SIM_INFO_SIGNAL_ICCID_CHANGED] == 1);
|
||||
g_assert(count[SIM_INFO_SIGNAL_IMSI_CHANGED] == 1);
|
||||
g_assert(count[SIM_INFO_SIGNAL_SPN_CHANGED] == 1);
|
||||
memset(count, 0, sizeof(count));
|
||||
|
||||
/* Replace default SPN with the real one */
|
||||
fake_sailfish_watch_set_ofono_spn(w, TEST_SPN);
|
||||
fake_sailfish_watch_emit_queued_signals(w);
|
||||
@@ -286,24 +335,39 @@ static void test_cache(void)
|
||||
g_assert(stat(SIM_CACHE, &st) == 0);
|
||||
g_assert(S_ISREG(st.st_mode));
|
||||
|
||||
/* Reset the information */
|
||||
sim.mcc = NULL;
|
||||
sim.mnc = NULL;
|
||||
sim.state = OFONO_SIM_STATE_NOT_PRESENT;
|
||||
/* Stray events have no effect */
|
||||
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_SPN_CHANGED);
|
||||
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_IMSI_CHANGED);
|
||||
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_ICCID_CHANGED);
|
||||
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_SIM_STATE_CHANGED);
|
||||
fake_sailfish_watch_set_ofono_iccid(w, NULL);
|
||||
fake_sailfish_watch_set_ofono_imsi(w, NULL);
|
||||
fake_sailfish_watch_set_ofono_spn(w, NULL);
|
||||
fake_sailfish_watch_emit_queued_signals(w);
|
||||
g_assert(!count[SIM_INFO_SIGNAL_ICCID_CHANGED]);
|
||||
g_assert(!count[SIM_INFO_SIGNAL_IMSI_CHANGED]);
|
||||
g_assert(!count[SIM_INFO_SIGNAL_SPN_CHANGED]);
|
||||
|
||||
/* Empty SPN and IMSI are ignored too */
|
||||
fake_sailfish_watch_set_ofono_imsi(w, "");
|
||||
fake_sailfish_watch_set_ofono_spn(w, "");
|
||||
fake_sailfish_watch_emit_queued_signals(w);
|
||||
g_assert(!count[SIM_INFO_SIGNAL_ICCID_CHANGED]);
|
||||
g_assert(!count[SIM_INFO_SIGNAL_IMSI_CHANGED]);
|
||||
g_assert(!count[SIM_INFO_SIGNAL_SPN_CHANGED]);
|
||||
|
||||
/* Reset the information */
|
||||
test_remove_sim(&sim, w);
|
||||
g_assert(count[SIM_INFO_SIGNAL_ICCID_CHANGED] == 1);
|
||||
g_assert(count[SIM_INFO_SIGNAL_IMSI_CHANGED] == 1);
|
||||
g_assert(count[SIM_INFO_SIGNAL_SPN_CHANGED] == 1);
|
||||
g_assert(!si->iccid);
|
||||
g_assert(!si->imsi);
|
||||
g_assert(!si->spn);
|
||||
memset(count, 0, sizeof(count));
|
||||
|
||||
/* Set ICCID again, that will load the cached information */
|
||||
sim.mcc = NULL;
|
||||
sim.mnc = NULL;
|
||||
sim.state = OFONO_SIM_STATE_INSERTED;
|
||||
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_ICCID_CHANGED);
|
||||
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_SIM_STATE_CHANGED);
|
||||
fake_sailfish_watch_set_ofono_iccid(w, TEST_ICCID);
|
||||
fake_sailfish_watch_emit_queued_signals(w);
|
||||
@@ -315,12 +379,75 @@ static void test_cache(void)
|
||||
g_assert(count[SIM_INFO_SIGNAL_SPN_CHANGED] == 1);
|
||||
memset(count, 0, sizeof(count));
|
||||
|
||||
sailfish_sim_info_remove_handler(si, id[SIM_INFO_SIGNAL_SPN_CHANGED]);
|
||||
id[SIM_INFO_SIGNAL_SPN_CHANGED] = 0;
|
||||
sailfish_sim_info_invalidate(si);
|
||||
/* Replace the SIM with a different one */
|
||||
test_remove_sim(&sim, w);
|
||||
g_assert(count[SIM_INFO_SIGNAL_ICCID_CHANGED] == 1);
|
||||
g_assert(count[SIM_INFO_SIGNAL_IMSI_CHANGED] == 1);
|
||||
g_assert(count[SIM_INFO_SIGNAL_SPN_CHANGED] == 1);
|
||||
g_assert(!si->iccid);
|
||||
g_assert(!si->imsi);
|
||||
g_assert(!si->iccid);
|
||||
g_assert(!si->spn);
|
||||
memset(count, 0, sizeof(count));
|
||||
|
||||
sim.state = OFONO_SIM_STATE_INSERTED;
|
||||
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_SIM_STATE_CHANGED);
|
||||
fake_sailfish_watch_emit_queued_signals(w);
|
||||
g_assert(!count[SIM_INFO_SIGNAL_ICCID_CHANGED]);
|
||||
g_assert(!count[SIM_INFO_SIGNAL_IMSI_CHANGED]);
|
||||
g_assert(!count[SIM_INFO_SIGNAL_SPN_CHANGED]);
|
||||
|
||||
sim.mcc = TEST_MCC;
|
||||
sim.mnc = TEST_MNC;
|
||||
sim.state = OFONO_SIM_STATE_READY;
|
||||
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_SIM_STATE_CHANGED);
|
||||
fake_sailfish_watch_set_ofono_iccid(w, TEST_ICCID_1);
|
||||
fake_sailfish_watch_set_ofono_imsi(w, TEST_IMSI_1);
|
||||
|
||||
fake_sailfish_watch_emit_queued_signals(w);
|
||||
g_assert(!g_strcmp0(si->iccid, TEST_ICCID_1));
|
||||
g_assert(!g_strcmp0(si->imsi, TEST_IMSI_1));
|
||||
g_assert(!g_strcmp0(si->spn, TEST_DEFAULT_SPN));
|
||||
g_assert(count[SIM_INFO_SIGNAL_ICCID_CHANGED] == 1);
|
||||
g_assert(count[SIM_INFO_SIGNAL_IMSI_CHANGED] == 1);
|
||||
g_assert(count[SIM_INFO_SIGNAL_SPN_CHANGED] == 1);
|
||||
memset(count, 0, sizeof(count));
|
||||
|
||||
/* And then insert back the previous one */
|
||||
test_remove_sim(&sim, w);
|
||||
memset(count, 0, sizeof(count));
|
||||
|
||||
sim.state = OFONO_SIM_STATE_INSERTED;
|
||||
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_SIM_STATE_CHANGED);
|
||||
fake_sailfish_watch_emit_queued_signals(w);
|
||||
|
||||
sim.mcc = TEST_MCC;
|
||||
sim.mnc = TEST_MNC;
|
||||
sim.state = OFONO_SIM_STATE_READY;
|
||||
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_SIM_STATE_CHANGED);
|
||||
fake_sailfish_watch_set_ofono_iccid(w, TEST_ICCID);
|
||||
fake_sailfish_watch_set_ofono_imsi(w, TEST_IMSI);
|
||||
|
||||
fake_sailfish_watch_emit_queued_signals(w);
|
||||
g_assert(!g_strcmp0(si->iccid, TEST_ICCID));
|
||||
g_assert(!g_strcmp0(si->imsi, TEST_IMSI));
|
||||
g_assert(!g_strcmp0(si->spn, TEST_SPN));
|
||||
g_assert(count[SIM_INFO_SIGNAL_ICCID_CHANGED] == 1);
|
||||
g_assert(count[SIM_INFO_SIGNAL_IMSI_CHANGED] == 1);
|
||||
g_assert(count[SIM_INFO_SIGNAL_SPN_CHANGED] == 1);
|
||||
memset(count, 0, sizeof(count));
|
||||
|
||||
/* Make sure that removed handler doesn't get invoked */
|
||||
sailfish_sim_info_remove_handler(si, id[SIM_INFO_SIGNAL_SPN_CHANGED]);
|
||||
id[SIM_INFO_SIGNAL_SPN_CHANGED] = 0;
|
||||
sim.mcc = NULL;
|
||||
sim.mnc = NULL;
|
||||
sim.state = OFONO_SIM_STATE_NOT_PRESENT;
|
||||
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_IMSI_CHANGED);
|
||||
fake_sailfish_watch_signal_queue(w, WATCH_SIGNAL_SIM_STATE_CHANGED);
|
||||
fake_sailfish_watch_set_ofono_iccid(w, NULL);
|
||||
fake_sailfish_watch_set_ofono_imsi(w, NULL);
|
||||
fake_sailfish_watch_set_ofono_spn(w, NULL);
|
||||
fake_sailfish_watch_emit_queued_signals(w);
|
||||
g_assert(count[SIM_INFO_SIGNAL_ICCID_CHANGED] == 1);
|
||||
g_assert(count[SIM_INFO_SIGNAL_IMSI_CHANGED] == 1);
|
||||
g_assert(!count[SIM_INFO_SIGNAL_SPN_CHANGED]); /* removed ^ */
|
||||
|
||||
670
ofono/unit/test-sailfish_sim_info_dbus.c
Normal file
670
ofono/unit/test-sailfish_sim_info_dbus.c
Normal file
@@ -0,0 +1,670 @@
|
||||
/*
|
||||
* oFono - Open Source Telephony
|
||||
*
|
||||
* Copyright (C) 2018 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "test-dbus.h"
|
||||
#include "fake_sailfish_watch.h"
|
||||
|
||||
#include "sailfish_sim_info.h"
|
||||
|
||||
#include <gutil_log.h>
|
||||
#include <gutil_macros.h>
|
||||
|
||||
#include "ofono.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define TEST_TIMEOUT (10) /* seconds */
|
||||
#define TEST_MODEM_PATH "/test"
|
||||
#define TEST_ICCID "0000000000000000000"
|
||||
#define TEST_IMSI "244120000000000"
|
||||
#define TEST_MCC "244"
|
||||
#define TEST_MNC "12"
|
||||
#define TEST_DEFAULT_SPN TEST_MCC TEST_MNC
|
||||
#define TEST_SPN "Test"
|
||||
|
||||
#define SIM_INFO_DBUS_INTERFACE "org.nemomobile.ofono.SimInfo"
|
||||
#define SIM_INFO_DBUS_INTERFACE_VERSION (1)
|
||||
|
||||
#define SIM_INFO_DBUS_ICCID_CHANGED_SIGNAL "CardIdentifierChanged"
|
||||
#define SIM_INFO_DBUS_IMSI_CHANGED_SIGNAL "SubscriberIdentityChanged"
|
||||
#define SIM_INFO_DBUS_SPN_CHANGED_SIGNAL "ServiceProviderNameChanged"
|
||||
|
||||
static gboolean test_debug;
|
||||
|
||||
/* Fake ofono_sim */
|
||||
|
||||
struct ofono_sim {
|
||||
const char *mcc;
|
||||
const char *mnc;
|
||||
const char *spn;
|
||||
enum ofono_sim_state state;
|
||||
};
|
||||
|
||||
enum ofono_sim_state ofono_sim_get_state(struct ofono_sim *sim)
|
||||
{
|
||||
return sim ? sim->state : OFONO_SIM_STATE_NOT_PRESENT;
|
||||
}
|
||||
|
||||
const char *ofono_sim_get_mcc(struct ofono_sim *sim)
|
||||
{
|
||||
return sim ? sim->mcc : NULL;
|
||||
}
|
||||
|
||||
const char *ofono_sim_get_mnc(struct ofono_sim *sim)
|
||||
{
|
||||
return sim ? sim->mnc : NULL;
|
||||
}
|
||||
|
||||
/* Stubs (ofono) */
|
||||
|
||||
struct ofono_modem {
|
||||
const char *path;
|
||||
GSList *iflist;
|
||||
struct ofono_sim sim;
|
||||
};
|
||||
|
||||
const char *ofono_modem_get_path(struct ofono_modem *modem)
|
||||
{
|
||||
return modem->path;
|
||||
}
|
||||
|
||||
static gint test_strcmp(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
return g_strcmp0(a, b);
|
||||
}
|
||||
|
||||
static char *test_find_interface(struct ofono_modem *modem, const char *iface)
|
||||
{
|
||||
GSList *l = g_slist_find_custom(modem->iflist, iface, test_strcmp);
|
||||
return l ? l->data : NULL;
|
||||
}
|
||||
|
||||
void ofono_modem_add_interface(struct ofono_modem *modem, const char *iface)
|
||||
{
|
||||
if (iface && !test_find_interface(modem, iface)) {
|
||||
DBG("%s %s", modem->path, iface);
|
||||
modem->iflist = g_slist_append(modem->iflist, g_strdup(iface));
|
||||
}
|
||||
}
|
||||
|
||||
void ofono_modem_remove_interface(struct ofono_modem *modem, const char *iface)
|
||||
{
|
||||
char *found = test_find_interface(modem, iface);
|
||||
if (found) {
|
||||
DBG("%s %s", modem->path, iface);
|
||||
modem->iflist = g_slist_remove(modem->iflist, found);
|
||||
g_free(found);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fake ofono_netreg */
|
||||
|
||||
struct ofono_netreg {
|
||||
const char *mcc;
|
||||
const char *mnc;
|
||||
const char *name;
|
||||
int location;
|
||||
int cellid;
|
||||
enum ofono_radio_access_mode technology;
|
||||
int status;
|
||||
struct ofono_watchlist *status_watches;
|
||||
};
|
||||
|
||||
int ofono_netreg_get_status(struct ofono_netreg *netreg)
|
||||
{
|
||||
return netreg ? (int) netreg->status : -1;
|
||||
}
|
||||
|
||||
const char *ofono_netreg_get_mcc(struct ofono_netreg *netreg)
|
||||
{
|
||||
return netreg ? netreg->mcc : NULL;
|
||||
}
|
||||
|
||||
const char *ofono_netreg_get_mnc(struct ofono_netreg *netreg)
|
||||
{
|
||||
return netreg ? netreg->mnc : NULL;
|
||||
}
|
||||
|
||||
const char *ofono_netreg_get_name(struct ofono_netreg *netreg)
|
||||
{
|
||||
return netreg ? netreg->name : NULL;
|
||||
}
|
||||
|
||||
unsigned int __ofono_netreg_add_status_watch(struct ofono_netreg *netreg,
|
||||
ofono_netreg_status_notify_cb_t notify,
|
||||
void *data, ofono_destroy_func destroy)
|
||||
{
|
||||
struct ofono_watchlist_item *item =
|
||||
g_new0(struct ofono_watchlist_item, 1);
|
||||
|
||||
DBG("%p", netreg);
|
||||
g_assert(netreg);
|
||||
g_assert(notify);
|
||||
item->notify = notify;
|
||||
item->destroy = destroy;
|
||||
item->notify_data = data;
|
||||
return __ofono_watchlist_add_item(netreg->status_watches, item);
|
||||
}
|
||||
|
||||
gboolean __ofono_netreg_remove_status_watch(struct ofono_netreg *netreg,
|
||||
unsigned int id)
|
||||
{
|
||||
return __ofono_watchlist_remove_item(netreg->status_watches, id);
|
||||
}
|
||||
|
||||
/* Utilities */
|
||||
|
||||
static int rmdir_r(const char *path)
|
||||
{
|
||||
DIR *d = opendir(path);
|
||||
|
||||
if (d) {
|
||||
const struct dirent *p;
|
||||
int r = 0;
|
||||
|
||||
while (!r && (p = readdir(d))) {
|
||||
char *buf;
|
||||
struct stat st;
|
||||
|
||||
if (!strcmp(p->d_name, ".") ||
|
||||
!strcmp(p->d_name, "..")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
buf = g_strdup_printf("%s/%s", path, p->d_name);
|
||||
if (!stat(buf, &st)) {
|
||||
r = S_ISDIR(st.st_mode) ? rmdir_r(buf) :
|
||||
unlink(buf);
|
||||
}
|
||||
g_free(buf);
|
||||
}
|
||||
closedir(d);
|
||||
return r ? r : rmdir(path);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==== common ==== */
|
||||
|
||||
static gboolean test_timeout(gpointer param)
|
||||
{
|
||||
g_assert(!"TIMEOUT");
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static guint test_setup_timeout(void)
|
||||
{
|
||||
if (!test_debug) {
|
||||
return 0;
|
||||
} else {
|
||||
return g_timeout_add_seconds(TEST_TIMEOUT, test_timeout, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean test_loop_quit(gpointer data)
|
||||
{
|
||||
g_main_loop_quit(data);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void test_loop_quit_later(GMainLoop *loop)
|
||||
{
|
||||
g_idle_add(test_loop_quit, loop);
|
||||
}
|
||||
|
||||
/* ==== Misc ==== */
|
||||
|
||||
static void test_misc(void)
|
||||
{
|
||||
/* NULL resistance */
|
||||
g_assert(!sailfish_sim_info_dbus_new_path(NULL));
|
||||
sailfish_sim_info_dbus_free(NULL);
|
||||
}
|
||||
|
||||
/* ==== GetAll ==== */
|
||||
|
||||
struct test_get_all_data {
|
||||
struct ofono_modem modem;
|
||||
struct test_dbus_context context;
|
||||
struct sailfish_sim_info_dbus *dbus;
|
||||
struct sailfish_watch *watch;
|
||||
const char *iccid;
|
||||
};
|
||||
|
||||
static void test_submit_get_all_call(struct test_get_all_data *test,
|
||||
DBusPendingCallNotifyFunction notify)
|
||||
{
|
||||
DBusPendingCall *call;
|
||||
DBusConnection* connection = test->context.client_connection;
|
||||
DBusMessage *msg = dbus_message_new_method_call(NULL, test->modem.path,
|
||||
SIM_INFO_DBUS_INTERFACE, "GetAll");
|
||||
|
||||
g_assert(dbus_connection_send_with_reply(connection, msg, &call,
|
||||
DBUS_TIMEOUT_INFINITE));
|
||||
dbus_pending_call_set_notify(call, notify, test, NULL);
|
||||
dbus_message_unref(msg);
|
||||
}
|
||||
|
||||
static void test_check_get_all_reply(struct test_get_all_data *test,
|
||||
DBusPendingCall *call)
|
||||
{
|
||||
DBusMessage *reply = dbus_pending_call_steal_reply(call);
|
||||
DBusMessageIter it;
|
||||
|
||||
g_assert(dbus_message_get_type(reply) ==
|
||||
DBUS_MESSAGE_TYPE_METHOD_RETURN);
|
||||
dbus_message_iter_init(reply, &it);
|
||||
g_assert(test_dbus_get_int32(&it) == SIM_INFO_DBUS_INTERFACE_VERSION);
|
||||
g_assert(!g_strcmp0(test_dbus_get_string(&it), test->iccid));
|
||||
g_assert(!g_strcmp0(test_dbus_get_string(&it), ""));
|
||||
g_assert(!g_strcmp0(test_dbus_get_string(&it), ""));
|
||||
g_assert(dbus_message_iter_get_arg_type(&it) == DBUS_TYPE_INVALID);
|
||||
dbus_message_unref(reply);
|
||||
}
|
||||
|
||||
static void test_get_all_reply(DBusPendingCall *call, void *data)
|
||||
{
|
||||
struct test_get_all_data *test = data;
|
||||
|
||||
DBG("");
|
||||
test_check_get_all_reply(test, call);
|
||||
dbus_pending_call_unref(call);
|
||||
|
||||
test_loop_quit_later(test->context.loop);
|
||||
}
|
||||
|
||||
static void test_get_all1_start(struct test_dbus_context *context)
|
||||
{
|
||||
struct test_get_all_data *test =
|
||||
G_CAST(context, struct test_get_all_data, context);
|
||||
const char *path = test->modem.path;
|
||||
|
||||
DBG("");
|
||||
test->dbus = sailfish_sim_info_dbus_new_path(path);
|
||||
g_assert(test->dbus);
|
||||
|
||||
test_submit_get_all_call(test, test_get_all_reply);
|
||||
}
|
||||
|
||||
static void test_get_all1(void)
|
||||
{
|
||||
struct test_get_all_data test;
|
||||
guint timeout = test_setup_timeout();
|
||||
|
||||
rmdir_r(STORAGEDIR);
|
||||
memset(&test, 0, sizeof(test));
|
||||
test.modem.path = TEST_MODEM_PATH;
|
||||
test.context.start = test_get_all1_start;
|
||||
test.watch = sailfish_watch_new(test.modem.path);
|
||||
test.watch->modem = &test.modem;
|
||||
test.iccid = "";
|
||||
test_dbus_setup(&test.context);
|
||||
|
||||
g_main_loop_run(test.context.loop);
|
||||
|
||||
sailfish_watch_unref(test.watch);
|
||||
sailfish_sim_info_dbus_free(test.dbus);
|
||||
test_dbus_shutdown(&test.context);
|
||||
if (timeout) {
|
||||
g_source_remove(timeout);
|
||||
}
|
||||
rmdir_r(STORAGEDIR);
|
||||
}
|
||||
|
||||
/* ==== GetAll2 ==== */
|
||||
|
||||
static void test_get_all2_start(struct test_dbus_context *context)
|
||||
{
|
||||
struct test_get_all_data *test =
|
||||
G_CAST(context, struct test_get_all_data, context);
|
||||
const char *path = test->modem.path;
|
||||
struct sailfish_watch *watch = test->watch;
|
||||
|
||||
DBG("");
|
||||
test->dbus = sailfish_sim_info_dbus_new_path(path);
|
||||
g_assert(test->dbus);
|
||||
|
||||
/* Tell sailfish_watch that we have a modem */
|
||||
test->watch->modem = &test->modem;
|
||||
fake_sailfish_watch_set_ofono_sim(watch, &test->modem.sim);
|
||||
fake_sailfish_watch_set_ofono_iccid(watch, test->iccid);
|
||||
fake_sailfish_watch_signal_queue(watch, WATCH_SIGNAL_MODEM_CHANGED);
|
||||
fake_sailfish_watch_emit_queued_signals(watch);
|
||||
|
||||
test_submit_get_all_call(test, test_get_all_reply);
|
||||
}
|
||||
|
||||
static void test_get_all2(void)
|
||||
{
|
||||
struct test_get_all_data test;
|
||||
guint timeout = test_setup_timeout();
|
||||
|
||||
rmdir_r(STORAGEDIR);
|
||||
memset(&test, 0, sizeof(test));
|
||||
test.modem.path = TEST_MODEM_PATH;
|
||||
test.context.start = test_get_all2_start;
|
||||
test.watch = sailfish_watch_new(test.modem.path);
|
||||
test.iccid = TEST_ICCID;
|
||||
test_dbus_setup(&test.context);
|
||||
|
||||
g_main_loop_run(test.context.loop);
|
||||
|
||||
/* "CardIdentifierChanged" is expected */
|
||||
g_assert(test_dbus_find_signal(&test.context, test.modem.path,
|
||||
SIM_INFO_DBUS_INTERFACE, SIM_INFO_DBUS_ICCID_CHANGED_SIGNAL));
|
||||
|
||||
sailfish_watch_unref(test.watch);
|
||||
sailfish_sim_info_dbus_free(test.dbus);
|
||||
test_dbus_shutdown(&test.context);
|
||||
if (timeout) {
|
||||
g_source_remove(timeout);
|
||||
}
|
||||
rmdir_r(STORAGEDIR);
|
||||
}
|
||||
|
||||
/* ==== GetInterfaceVersion ==== */
|
||||
|
||||
struct test_get_version_data {
|
||||
struct ofono_modem modem;
|
||||
struct test_dbus_context context;
|
||||
struct sailfish_sim_info_dbus *dbus;
|
||||
};
|
||||
|
||||
static void test_get_version_reply(DBusPendingCall *call, void *data)
|
||||
{
|
||||
struct test_get_version_data *test = data;
|
||||
DBusMessage *reply = dbus_pending_call_steal_reply(call);
|
||||
DBusMessageIter it;
|
||||
|
||||
DBG("");
|
||||
g_assert(dbus_message_get_type(reply) ==
|
||||
DBUS_MESSAGE_TYPE_METHOD_RETURN);
|
||||
dbus_message_iter_init(reply, &it);
|
||||
g_assert(test_dbus_get_int32(&it) == SIM_INFO_DBUS_INTERFACE_VERSION);
|
||||
g_assert(dbus_message_iter_get_arg_type(&it) == DBUS_TYPE_INVALID);
|
||||
dbus_message_unref(reply);
|
||||
dbus_pending_call_unref(call);
|
||||
|
||||
test_loop_quit_later(test->context.loop);
|
||||
}
|
||||
|
||||
static void test_get_version_start(struct test_dbus_context *context)
|
||||
{
|
||||
DBusMessage *msg;
|
||||
DBusPendingCall *call;
|
||||
struct test_get_version_data *test =
|
||||
G_CAST(context, struct test_get_version_data, context);
|
||||
const char *path = test->modem.path;
|
||||
|
||||
DBG("");
|
||||
test->dbus = sailfish_sim_info_dbus_new_path(path);
|
||||
g_assert(test->dbus);
|
||||
|
||||
msg = dbus_message_new_method_call(NULL, test->modem.path,
|
||||
SIM_INFO_DBUS_INTERFACE, "GetInterfaceVersion");
|
||||
g_assert(dbus_connection_send_with_reply(context->client_connection,
|
||||
msg, &call, DBUS_TIMEOUT_INFINITE));
|
||||
dbus_pending_call_set_notify(call, test_get_version_reply, test, NULL);
|
||||
dbus_message_unref(msg);
|
||||
}
|
||||
|
||||
static void test_get_version(void)
|
||||
{
|
||||
struct test_get_version_data test;
|
||||
guint timeout = test_setup_timeout();
|
||||
|
||||
memset(&test, 0, sizeof(test));
|
||||
test.modem.path = TEST_MODEM_PATH;
|
||||
test.context.start = test_get_version_start;
|
||||
test_dbus_setup(&test.context);
|
||||
|
||||
g_main_loop_run(test.context.loop);
|
||||
|
||||
sailfish_sim_info_dbus_free(test.dbus);
|
||||
test_dbus_shutdown(&test.context);
|
||||
if (timeout) {
|
||||
g_source_remove(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
/* ==== GetCardIdentifier ==== */
|
||||
|
||||
struct test_get_iccid_data {
|
||||
struct ofono_modem modem;
|
||||
struct test_dbus_context context;
|
||||
struct sailfish_sim_info_dbus *dbus;
|
||||
struct sailfish_watch *watch;
|
||||
const char *iccid;
|
||||
const char *result;
|
||||
};
|
||||
|
||||
static void test_get_iccid_reply(DBusPendingCall *call, void *data)
|
||||
{
|
||||
struct test_get_iccid_data *test = data;
|
||||
|
||||
DBG("");
|
||||
test_dbus_check_string_reply(call, test->result);
|
||||
dbus_pending_call_unref(call);
|
||||
|
||||
test_loop_quit_later(test->context.loop);
|
||||
}
|
||||
|
||||
static void test_get_iccid_start(struct test_dbus_context *context)
|
||||
{
|
||||
DBusMessage *msg;
|
||||
DBusPendingCall *call;
|
||||
struct test_get_iccid_data *test =
|
||||
G_CAST(context, struct test_get_iccid_data, context);
|
||||
const char *path = test->modem.path;
|
||||
|
||||
DBG("");
|
||||
test->dbus = sailfish_sim_info_dbus_new_path(path);
|
||||
fake_sailfish_watch_set_ofono_iccid(test->watch, test->iccid);
|
||||
fake_sailfish_watch_emit_queued_signals(test->watch);
|
||||
g_assert(test->dbus);
|
||||
|
||||
msg = dbus_message_new_method_call(NULL, test->modem.path,
|
||||
SIM_INFO_DBUS_INTERFACE, "GetCardIdentifier");
|
||||
g_assert(dbus_connection_send_with_reply(context->client_connection,
|
||||
msg, &call, DBUS_TIMEOUT_INFINITE));
|
||||
dbus_pending_call_set_notify(call, test_get_iccid_reply, test, NULL);
|
||||
dbus_message_unref(msg);
|
||||
}
|
||||
|
||||
static void test_get_iccid(const char *init_iccid, const char *set_iccid,
|
||||
const char *result)
|
||||
{
|
||||
struct test_get_iccid_data test;
|
||||
guint timeout = test_setup_timeout();
|
||||
|
||||
memset(&test, 0, sizeof(test));
|
||||
test.iccid = set_iccid;
|
||||
test.result = result;
|
||||
test.modem.path = TEST_MODEM_PATH;
|
||||
test.context.start = test_get_iccid_start;
|
||||
test.watch = sailfish_watch_new(test.modem.path);
|
||||
test.watch->modem = &test.modem;
|
||||
fake_sailfish_watch_set_ofono_iccid(test.watch, init_iccid);
|
||||
fake_sailfish_watch_emit_queued_signals(test.watch);
|
||||
test_dbus_setup(&test.context);
|
||||
|
||||
g_main_loop_run(test.context.loop);
|
||||
|
||||
/* "CardIdentifierChanged" is expected */
|
||||
g_assert(test_dbus_find_signal(&test.context, test.modem.path,
|
||||
SIM_INFO_DBUS_INTERFACE, SIM_INFO_DBUS_ICCID_CHANGED_SIGNAL));
|
||||
|
||||
sailfish_watch_unref(test.watch);
|
||||
sailfish_sim_info_dbus_free(test.dbus);
|
||||
test_dbus_shutdown(&test.context);
|
||||
if (timeout) {
|
||||
g_source_remove(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_get_iccid1(void)
|
||||
{
|
||||
test_get_iccid(NULL, TEST_ICCID, TEST_ICCID);
|
||||
}
|
||||
|
||||
/* ==== GetCardIdentifier2 ==== */
|
||||
|
||||
static void test_get_iccid2(void)
|
||||
{
|
||||
test_get_iccid(TEST_ICCID, NULL, "");
|
||||
}
|
||||
|
||||
/* ==== GetSubscriberIdentity ==== */
|
||||
|
||||
struct test_get_string_data {
|
||||
struct ofono_modem modem;
|
||||
struct test_dbus_context context;
|
||||
struct sailfish_sim_info_dbus *dbus;
|
||||
struct sailfish_watch *watch;
|
||||
const char *method;
|
||||
const char *result;
|
||||
};
|
||||
|
||||
static void test_get_string_reply(DBusPendingCall *call, void *data)
|
||||
{
|
||||
struct test_get_string_data *test = data;
|
||||
|
||||
DBG("");
|
||||
test_dbus_check_string_reply(call, test->result);
|
||||
dbus_pending_call_unref(call);
|
||||
|
||||
test_loop_quit_later(test->context.loop);
|
||||
}
|
||||
|
||||
static void test_get_string_start(struct test_dbus_context *context)
|
||||
{
|
||||
DBusMessage *msg;
|
||||
DBusPendingCall *call;
|
||||
struct test_get_string_data *test =
|
||||
G_CAST(context, struct test_get_string_data, context);
|
||||
const char *path = test->modem.path;
|
||||
struct ofono_sim *sim = &test->modem.sim;
|
||||
struct sailfish_watch *watch = test->watch;
|
||||
|
||||
DBG("%s", test->method);
|
||||
test->dbus = sailfish_sim_info_dbus_new_path(path);
|
||||
sim->mcc = TEST_MCC;
|
||||
sim->mnc = TEST_MNC;
|
||||
sim->state = OFONO_SIM_STATE_READY;
|
||||
fake_sailfish_watch_signal_queue(watch, WATCH_SIGNAL_SIM_STATE_CHANGED);
|
||||
fake_sailfish_watch_set_ofono_imsi(watch, TEST_IMSI);
|
||||
fake_sailfish_watch_emit_queued_signals(watch);
|
||||
g_assert(test->dbus);
|
||||
|
||||
msg = dbus_message_new_method_call(NULL, test->modem.path,
|
||||
SIM_INFO_DBUS_INTERFACE, test->method);
|
||||
g_assert(dbus_connection_send_with_reply(context->client_connection,
|
||||
msg, &call, DBUS_TIMEOUT_INFINITE));
|
||||
dbus_pending_call_set_notify(call, test_get_string_reply, test, NULL);
|
||||
dbus_message_unref(msg);
|
||||
}
|
||||
|
||||
static void test_get_string(const char *method, const char *result)
|
||||
{
|
||||
struct test_get_string_data test;
|
||||
guint timeout = test_setup_timeout();
|
||||
|
||||
rmdir_r(STORAGEDIR);
|
||||
memset(&test, 0, sizeof(test));
|
||||
test.method = method;
|
||||
test.result = result;
|
||||
test.modem.path = TEST_MODEM_PATH;
|
||||
test.context.start = test_get_string_start;
|
||||
test.watch = sailfish_watch_new(test.modem.path);
|
||||
test.watch->modem = &test.modem;
|
||||
fake_sailfish_watch_set_ofono_iccid(test.watch, TEST_ICCID);
|
||||
fake_sailfish_watch_set_ofono_sim(test.watch, &test.modem.sim);
|
||||
fake_sailfish_watch_emit_queued_signals(test.watch);
|
||||
test_dbus_setup(&test.context);
|
||||
|
||||
g_main_loop_run(test.context.loop);
|
||||
|
||||
/* Verify signals */
|
||||
g_assert(test_dbus_find_signal(&test.context, test.modem.path,
|
||||
SIM_INFO_DBUS_INTERFACE, SIM_INFO_DBUS_IMSI_CHANGED_SIGNAL));
|
||||
g_assert(test_dbus_find_signal(&test.context, test.modem.path,
|
||||
SIM_INFO_DBUS_INTERFACE, SIM_INFO_DBUS_SPN_CHANGED_SIGNAL));
|
||||
|
||||
sailfish_watch_unref(test.watch);
|
||||
sailfish_sim_info_dbus_free(test.dbus);
|
||||
test_dbus_shutdown(&test.context);
|
||||
if (timeout) {
|
||||
g_source_remove(timeout);
|
||||
}
|
||||
rmdir_r(STORAGEDIR);
|
||||
}
|
||||
|
||||
static void test_get_imsi(void)
|
||||
{
|
||||
test_get_string("GetSubscriberIdentity", TEST_IMSI);
|
||||
}
|
||||
|
||||
/* ==== GetServiceProviderName ==== */
|
||||
|
||||
static void test_get_spn(void)
|
||||
{
|
||||
test_get_string("GetServiceProviderName", TEST_DEFAULT_SPN);
|
||||
}
|
||||
|
||||
#define TEST_(name) "/sailfish_sim_info_dbus/" name
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
for (i=1; i<argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
if (!strcmp(arg, "-d") || !strcmp(arg, "--debug")) {
|
||||
test_debug = TRUE;
|
||||
} else {
|
||||
GWARN("Unsupported command line option %s", arg);
|
||||
}
|
||||
}
|
||||
|
||||
gutil_log_timestamp = FALSE;
|
||||
gutil_log_default.level = g_test_verbose() ?
|
||||
GLOG_LEVEL_VERBOSE : GLOG_LEVEL_NONE;
|
||||
__ofono_log_init("test-sailfish_sim_info_dbus",
|
||||
g_test_verbose() ? "*" : NULL,
|
||||
FALSE, FALSE);
|
||||
|
||||
g_test_add_func(TEST_("Misc"), test_misc);
|
||||
g_test_add_func(TEST_("GetAll1"), test_get_all1);
|
||||
g_test_add_func(TEST_("GetAll2"), test_get_all2);
|
||||
g_test_add_func(TEST_("GetInterfaceVersion"), test_get_version);
|
||||
g_test_add_func(TEST_("GetCardIdentifier1"), test_get_iccid1);
|
||||
g_test_add_func(TEST_("GetCardIdentifier2"), test_get_iccid2);
|
||||
g_test_add_func(TEST_("GetSubscriberIdentity"), test_get_imsi);
|
||||
g_test_add_func(TEST_("GetServiceProviderName"), test_get_spn);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* c-basic-offset: 8
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
@@ -10,17 +10,18 @@ Source: %{name}-%{version}.tar.bz2
|
||||
Requires: dbus
|
||||
Requires: systemd
|
||||
Requires: ofono-configs
|
||||
Requires: libgrilio >= 1.0.16
|
||||
Requires: libgrilio >= 1.0.20
|
||||
Requires: libglibutil >= 1.0.23
|
||||
Requires: mobile-broadband-provider-info
|
||||
Requires(preun): systemd
|
||||
Requires(post): systemd
|
||||
Requires(postun): systemd
|
||||
BuildRequires: pkgconfig(dbus-1)
|
||||
BuildRequires: pkgconfig(dbus-glib-1)
|
||||
BuildRequires: pkgconfig(glib-2.0)
|
||||
BuildRequires: pkgconfig(libudev) >= 145
|
||||
BuildRequires: pkgconfig(libwspcodec) >= 2.0
|
||||
BuildRequires: pkgconfig(libgrilio) >= 1.0.18
|
||||
BuildRequires: pkgconfig(libgrilio) >= 1.0.20
|
||||
BuildRequires: pkgconfig(libglibutil) >= 1.0.23
|
||||
BuildRequires: pkgconfig(libdbuslogserver-dbus)
|
||||
BuildRequires: pkgconfig(libmce-glib) >= 1.0.5
|
||||
|
||||
Reference in New Issue
Block a user