forked from sailfishos/ofono
Compare commits
113 Commits
mer/1.17+g
...
upgrade-2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cbd32e5aaa | ||
|
|
baa4fe30e5 | ||
|
|
d0d0793ccb | ||
|
|
55dd461ce7 | ||
|
|
4da1a30290 | ||
|
|
303f527d79 | ||
|
|
27e8621c0b | ||
|
|
200237372a | ||
|
|
9cae262c80 | ||
|
|
5e23459b67 | ||
|
|
a88d7af6c8 | ||
|
|
290c3d2388 | ||
|
|
ee880398ad | ||
|
|
d65bbc3236 | ||
|
|
655544be45 | ||
|
|
50a544a191 | ||
|
|
9e7a4a4d72 | ||
|
|
c5b5e3109d | ||
|
|
deb106343a | ||
|
|
771e8becf2 | ||
|
|
a0b69f974a | ||
|
|
b3a4aaea95 | ||
|
|
137e504e10 | ||
|
|
2de3e445f0 | ||
|
|
1cd0d60768 | ||
|
|
d1f1f16355 | ||
|
|
4df72c9376 | ||
|
|
a35ca2bbd9 | ||
|
|
8376174c76 | ||
|
|
b6f5befcac | ||
|
|
403f29320c | ||
|
|
54209b39bd | ||
|
|
3ca442ad15 | ||
|
|
3a579dd7be | ||
|
|
a7266fc9c8 | ||
|
|
04dbd344b3 | ||
|
|
296534c2a8 | ||
|
|
6114482e2a | ||
|
|
8281885ba5 | ||
|
|
9cd3b84421 | ||
|
|
8d65aaefed | ||
|
|
ce15cfe48d | ||
|
|
3a1e37b498 | ||
|
|
ecef97dd83 | ||
|
|
a68f1e9c4d | ||
|
|
42808ed0f7 | ||
|
|
d896ebcb37 | ||
|
|
93c57284bd | ||
|
|
91436f9643 | ||
|
|
d0d2587b2a | ||
|
|
3e10878348 | ||
|
|
6de8c4aa85 | ||
|
|
a9da50f890 | ||
|
|
3ca5161a78 | ||
|
|
03b3ca7776 | ||
|
|
6e5316aba9 | ||
|
|
49b752f0ad | ||
|
|
268684eebf | ||
|
|
24db1db2b1 | ||
|
|
55977c1dac | ||
|
|
1025a6c6ed | ||
|
|
98a143233d | ||
|
|
88013ff63e | ||
|
|
efbe8b12c9 | ||
|
|
ba9cc0eb4a | ||
|
|
46b5f22464 | ||
|
|
a31332ebae | ||
|
|
b30141c3d3 | ||
|
|
e8ae8bba1c | ||
|
|
3ea25fb81f | ||
|
|
197df7141d | ||
|
|
eef6993391 | ||
|
|
f1a5941b35 | ||
|
|
5f6a258d0a | ||
|
|
9fa18f967b | ||
|
|
4d17a2e3b9 | ||
|
|
c34b3c39b2 | ||
|
|
df1824b2e2 | ||
|
|
b3a18326e1 | ||
|
|
93e564d5e5 | ||
|
|
42847e03b5 | ||
|
|
f0d6b69972 | ||
|
|
2100a8d975 | ||
|
|
c393e63e4e | ||
|
|
b24bc9761b | ||
|
|
06daa7cf21 | ||
|
|
49215d60b2 | ||
|
|
f3f3b73d6f | ||
|
|
113d9424b5 | ||
|
|
2a8489c4d9 | ||
|
|
c4f968b87a | ||
|
|
537c7ae8b4 | ||
|
|
b320fc7f59 | ||
|
|
edf49e6e99 | ||
|
|
b7985a1d67 | ||
|
|
bbb2c68a72 | ||
|
|
bd3f7f35eb | ||
|
|
65bf1a24fa | ||
|
|
0c37015145 | ||
|
|
a8551cdce7 | ||
|
|
5bd2b96240 | ||
|
|
3bf309b887 | ||
|
|
c14b9bbf93 | ||
|
|
568bd615cd | ||
|
|
4d55f94015 | ||
|
|
95d06963cd | ||
|
|
479458138a | ||
|
|
c221d677d1 | ||
|
|
a32da19192 | ||
|
|
a20da10621 | ||
|
|
64c754c3b9 | ||
|
|
d64fd7dca7 | ||
|
|
f608c0821a |
@@ -22,7 +22,7 @@ pkginclude_HEADERS = include/log.h include/plugin.h include/history.h \
|
|||||||
include/private-network.h include/cdma-netreg.h \
|
include/private-network.h include/cdma-netreg.h \
|
||||||
include/cdma-provision.h include/handsfree.h \
|
include/cdma-provision.h include/handsfree.h \
|
||||||
include/handsfree-audio.h \
|
include/handsfree-audio.h \
|
||||||
include/sim-mnclength.h include/oemraw.h \
|
include/sim-mnclength.h \
|
||||||
include/siri.h
|
include/siri.h
|
||||||
|
|
||||||
nodist_pkginclude_HEADERS = include/version.h
|
nodist_pkginclude_HEADERS = include/version.h
|
||||||
@@ -125,13 +125,18 @@ builtin_sources += drivers/ril/ril_call_barring.c \
|
|||||||
drivers/ril/ril_call_forward.c \
|
drivers/ril/ril_call_forward.c \
|
||||||
drivers/ril/ril_call_settings.c \
|
drivers/ril/ril_call_settings.c \
|
||||||
drivers/ril/ril_call_volume.c \
|
drivers/ril/ril_call_volume.c \
|
||||||
|
drivers/ril/ril_cell_info.c \
|
||||||
|
drivers/ril/ril_cell_info_dbus.c \
|
||||||
|
drivers/ril/ril_config.c \
|
||||||
drivers/ril/ril_cbs.c \
|
drivers/ril/ril_cbs.c \
|
||||||
drivers/ril/ril_data.c \
|
drivers/ril/ril_data.c \
|
||||||
drivers/ril/ril_devinfo.c \
|
drivers/ril/ril_devinfo.c \
|
||||||
|
drivers/ril/ril_ecclist.c \
|
||||||
drivers/ril/ril_gprs.c \
|
drivers/ril/ril_gprs.c \
|
||||||
drivers/ril/ril_gprs_context.c \
|
drivers/ril/ril_gprs_context.c \
|
||||||
drivers/ril/ril_mce.c \
|
drivers/ril/ril_mce.c \
|
||||||
drivers/ril/ril_modem.c \
|
drivers/ril/ril_modem.c \
|
||||||
|
drivers/ril/ril_mtu.c \
|
||||||
drivers/ril/ril_netreg.c \
|
drivers/ril/ril_netreg.c \
|
||||||
drivers/ril/ril_network.c \
|
drivers/ril/ril_network.c \
|
||||||
drivers/ril/ril_oem_raw.c \
|
drivers/ril/ril_oem_raw.c \
|
||||||
@@ -142,7 +147,9 @@ builtin_sources += drivers/ril/ril_call_barring.c \
|
|||||||
drivers/ril/ril_radio_settings.c \
|
drivers/ril/ril_radio_settings.c \
|
||||||
drivers/ril/ril_sim.c \
|
drivers/ril/ril_sim.c \
|
||||||
drivers/ril/ril_sim_card.c \
|
drivers/ril/ril_sim_card.c \
|
||||||
drivers/ril/ril_sim_dbus.c \
|
drivers/ril/ril_sim_info.c \
|
||||||
|
drivers/ril/ril_sim_info_dbus.c \
|
||||||
|
drivers/ril/ril_sim_settings.c \
|
||||||
drivers/ril/ril_sms.c \
|
drivers/ril/ril_sms.c \
|
||||||
drivers/ril/ril_stk.c \
|
drivers/ril/ril_stk.c \
|
||||||
drivers/ril/ril_ussd.c \
|
drivers/ril/ril_ussd.c \
|
||||||
@@ -612,7 +619,7 @@ builtin_cflags += @WSPCODEC_CFLAGS@
|
|||||||
builtin_libadd += @WSPCODEC_LIBS@
|
builtin_libadd += @WSPCODEC_LIBS@
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if LOGCONTROL
|
if DEBUGLOG
|
||||||
builtin_modules += debuglog
|
builtin_modules += debuglog
|
||||||
builtin_sources += plugins/debuglog.c
|
builtin_sources += plugins/debuglog.c
|
||||||
endif
|
endif
|
||||||
@@ -647,7 +654,7 @@ src_ofonod_SOURCES = $(builtin_sources) src/ofono.ver \
|
|||||||
src/cdma-sms.c src/private-network.c src/cdma-netreg.c \
|
src/cdma-sms.c src/private-network.c src/cdma-netreg.c \
|
||||||
src/cdma-provision.c src/handsfree.c \
|
src/cdma-provision.c src/handsfree.c \
|
||||||
src/handsfree-audio.c src/bluetooth.h \
|
src/handsfree-audio.c src/bluetooth.h \
|
||||||
src/sim-mnclength.c src/oemraw.c src/voicecallagent.c \
|
src/sim-mnclength.c src/voicecallagent.c \
|
||||||
src/hfp.h src/siri.c
|
src/hfp.h src/siri.c
|
||||||
|
|
||||||
src_ofonod_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
|
src_ofonod_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
|
||||||
|
|||||||
@@ -175,8 +175,8 @@ AM_CONDITIONAL(JOLLA_RILMODEM, test "${enable_jolla_rilmodem}" != "no")
|
|||||||
if (test "${enable_jolla_rilmodem}" = "yes"); then
|
if (test "${enable_jolla_rilmodem}" = "yes"); then
|
||||||
PKG_CHECK_MODULES(GRILIO, libgrilio >= 1.0.6, dummy=yes,
|
PKG_CHECK_MODULES(GRILIO, libgrilio >= 1.0.6, dummy=yes,
|
||||||
AC_MSG_ERROR(libgrilio >= 1.0.6 is required))
|
AC_MSG_ERROR(libgrilio >= 1.0.6 is required))
|
||||||
PKG_CHECK_MODULES(GLIBUTIL, libglibutil, dummy=yes,
|
PKG_CHECK_MODULES(GLIBUTIL, libglibutil >= 1.0.5, dummy=yes,
|
||||||
AC_MSG_ERROR(libglibutil is required))
|
AC_MSG_ERROR(libglibutil >= 1.0.5 is required))
|
||||||
CFLAGS="$CFLAGS $GRILIO_CFLAGS $GLIBUTIL_CFLAGS"
|
CFLAGS="$CFLAGS $GRILIO_CFLAGS $GLIBUTIL_CFLAGS"
|
||||||
LIBS="$LIBS $GRILIO_LIBS $GLIBUTIL_LIBS"
|
LIBS="$LIBS $GRILIO_LIBS $GLIBUTIL_LIBS"
|
||||||
fi
|
fi
|
||||||
@@ -252,10 +252,16 @@ if (test "${enable_pushforwarder}" != "no"); then
|
|||||||
AC_SUBST(WSPCODEC_LIBS)
|
AC_SUBST(WSPCODEC_LIBS)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_ARG_ENABLE(logcontrol,
|
AC_ARG_ENABLE(debuglog,
|
||||||
AC_HELP_STRING([--enable-logcontrol], [enable log control plugin]),
|
AC_HELP_STRING([--enable-debuglog], [enable log control plugin]),
|
||||||
[enable_logcontrol=${enableval}], [enable_logcontrol="no"])
|
[enable_debuglog=${enableval}], [enable_debuglog="no"])
|
||||||
AM_CONDITIONAL(LOGCONTROL, test "${enable_logcontrol}" != "no")
|
AM_CONDITIONAL(DEBUGLOG, test "${enable_debuglog}" != "no")
|
||||||
|
if (test "${enable_debuglog}" = "yes"); then
|
||||||
|
PKG_CHECK_MODULES(DBUSLOG, libdbuslogserver-dbus, dummy=yes,
|
||||||
|
AC_MSG_ERROR(libdbuslogserver-dbus is required))
|
||||||
|
CFLAGS="$CFLAGS $DBUSLOG_CFLAGS"
|
||||||
|
LIBS="$LIBS $DBUSLOG_LIBS"
|
||||||
|
fi
|
||||||
|
|
||||||
if (test "${prefix}" = "NONE"); then
|
if (test "${prefix}" = "NONE"); then
|
||||||
dnl no prefix and no localstatedir, so default to /var
|
dnl no prefix and no localstatedir, so default to /var
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
Debug log control
|
|
||||||
=================
|
|
||||||
|
|
||||||
Service org.ofono
|
|
||||||
Interface org.ofono.DebugLog
|
|
||||||
Object path /
|
|
||||||
|
|
||||||
Methods void Enable(string pattern)
|
|
||||||
|
|
||||||
Enables all logs that match the pattern.
|
|
||||||
|
|
||||||
void Disable(string pattern)
|
|
||||||
|
|
||||||
Disables all logs that match the pattern.
|
|
||||||
|
|
||||||
array(string,boolean) List()
|
|
||||||
|
|
||||||
Returns all available log names and their current
|
|
||||||
states.
|
|
||||||
|
|
||||||
In order for Enable or Disable call to have any
|
|
||||||
effect, the pattern must match one or more of
|
|
||||||
these strings.
|
|
||||||
|
|
||||||
Signals Changed(string name, boolean enabled)
|
|
||||||
|
|
||||||
This signal indicates a changed log status of the
|
|
||||||
given log module.
|
|
||||||
537
ofono/drivers/ril/ril_cell_info.c
Normal file
537
ofono/drivers/ril/ril_cell_info.c
Normal file
@@ -0,0 +1,537 @@
|
|||||||
|
/*
|
||||||
|
* oFono - Open Source Telephony - RIL-based devices
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 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_cell_info.h"
|
||||||
|
#include "ril_sim_card.h"
|
||||||
|
#include "ril_radio.h"
|
||||||
|
#include "ril_util.h"
|
||||||
|
#include "ril_mce.h"
|
||||||
|
#include "ril_log.h"
|
||||||
|
|
||||||
|
#include <grilio_channel.h>
|
||||||
|
#include <grilio_request.h>
|
||||||
|
#include <grilio_parser.h>
|
||||||
|
|
||||||
|
#define DISPLAY_ON_UPDATE_RATE (1000) /* 1 sec */
|
||||||
|
#define DISPLAY_OFF_UPDATE_RATE (60000) /* 1 min */
|
||||||
|
|
||||||
|
typedef GObjectClass RilCellInfoClass;
|
||||||
|
typedef struct ril_cell_info RilCellInfo;
|
||||||
|
|
||||||
|
struct ril_cell_info_priv {
|
||||||
|
GRilIoChannel *io;
|
||||||
|
struct ril_mce *mce;
|
||||||
|
struct ril_radio *radio;
|
||||||
|
struct ril_sim_card *sim_card;
|
||||||
|
gulong display_state_event_id;
|
||||||
|
gulong radio_state_event_id;
|
||||||
|
gulong sim_status_event_id;
|
||||||
|
gboolean sim_card_ready;
|
||||||
|
char *log_prefix;
|
||||||
|
gulong event_id;
|
||||||
|
guint query_id;
|
||||||
|
guint set_rate_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ril_cell_info_signal {
|
||||||
|
SIGNAL_CELLS_CHANGED,
|
||||||
|
SIGNAL_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SIGNAL_CELLS_CHANGED_NAME "ril-cell-info-cells-changed"
|
||||||
|
|
||||||
|
static guint ril_cell_info_signals[SIGNAL_COUNT] = { 0 };
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(RilCellInfo, ril_cell_info, G_TYPE_OBJECT)
|
||||||
|
#define RIL_CELL_INFO_TYPE (ril_cell_info_get_type())
|
||||||
|
#define RIL_CELL_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
|
||||||
|
RIL_CELL_INFO_TYPE, RilCellInfo))
|
||||||
|
|
||||||
|
#define DBG_(self,fmt,args...) DBG("%s" fmt, (self)->priv->log_prefix, ##args)
|
||||||
|
|
||||||
|
gint ril_cell_compare_location(const struct ril_cell *c1,
|
||||||
|
const struct ril_cell *c2)
|
||||||
|
{
|
||||||
|
if (c1 && c2) {
|
||||||
|
if (c1->type != c2->type) {
|
||||||
|
return c1->type - c2->type;
|
||||||
|
} else if (c1->type == RIL_CELL_INFO_TYPE_GSM) {
|
||||||
|
const struct ril_cell_info_gsm *g1 = &c1->info.gsm;
|
||||||
|
const struct ril_cell_info_gsm *g2 = &c2->info.gsm;
|
||||||
|
|
||||||
|
if (g1->lac != g2->lac) {
|
||||||
|
return g1->lac - g2->lac;
|
||||||
|
} else {
|
||||||
|
return g1->cid - g2->cid;
|
||||||
|
}
|
||||||
|
} else if (c2->type == RIL_CELL_INFO_TYPE_WCDMA) {
|
||||||
|
const struct ril_cell_info_wcdma *w1 = &c1->info.wcdma;
|
||||||
|
const struct ril_cell_info_wcdma *w2 = &c2->info.wcdma;
|
||||||
|
|
||||||
|
if (w1->lac != w2->lac) {
|
||||||
|
return w1->lac - w2->lac;
|
||||||
|
} else {
|
||||||
|
return w1->cid - w2->cid;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const struct ril_cell_info_lte *l1 = &c1->info.lte;
|
||||||
|
const struct ril_cell_info_lte *l2 = &c2->info.lte;
|
||||||
|
|
||||||
|
GASSERT(c1->type == RIL_CELL_INFO_TYPE_LTE);
|
||||||
|
if (l1->ci != l2->ci) {
|
||||||
|
return l1->ci - l2->ci;
|
||||||
|
} else if (l1->pci != l2->pci) {
|
||||||
|
return l1->pci - l2->pci;
|
||||||
|
} else {
|
||||||
|
return l1->tac - l2->tac;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (c1) {
|
||||||
|
return 1;
|
||||||
|
} else if (c2) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gint ril_cell_compare_func(gconstpointer v1, gconstpointer v2)
|
||||||
|
{
|
||||||
|
return ril_cell_compare_location(v1, v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean ril_cell_info_list_identical(GSList *l1, GSList *l2)
|
||||||
|
{
|
||||||
|
while (l1 && l2) {
|
||||||
|
if (memcmp(l1->data, l2->data, sizeof(struct ril_cell))) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
l1 = l1->next;
|
||||||
|
l2 = l2->next;
|
||||||
|
}
|
||||||
|
return !l1 && !l2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_update_cells(struct ril_cell_info *self, GSList *l)
|
||||||
|
{
|
||||||
|
if (!ril_cell_info_list_identical(self->cells, l)) {
|
||||||
|
g_slist_free_full(self->cells, g_free);
|
||||||
|
self->cells = l;
|
||||||
|
g_signal_emit(self, ril_cell_info_signals[
|
||||||
|
SIGNAL_CELLS_CHANGED], 0);
|
||||||
|
} else {
|
||||||
|
g_slist_free_full(l, g_free);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ril_cell *ril_cell_info_parse_cell_gsm(GRilIoParser *rilp,
|
||||||
|
gboolean registered)
|
||||||
|
{
|
||||||
|
struct ril_cell *cell = g_new0(struct ril_cell, 1);
|
||||||
|
struct ril_cell_info_gsm *gsm = &cell->info.gsm;
|
||||||
|
|
||||||
|
if (grilio_parser_get_int32(rilp, &gsm->mcc) &&
|
||||||
|
grilio_parser_get_int32(rilp, &gsm->mnc) &&
|
||||||
|
grilio_parser_get_int32(rilp, &gsm->lac) &&
|
||||||
|
grilio_parser_get_int32(rilp, &gsm->cid) &&
|
||||||
|
grilio_parser_get_int32(rilp, &gsm->signalStrength) &&
|
||||||
|
grilio_parser_get_int32(rilp, &gsm->bitErrorRate)) {
|
||||||
|
DBG("[gsm] reg=%d,mcc=%d,mnc=%d,lac=%d,cid=%d,"
|
||||||
|
"strength=%d,err=%d", registered, gsm->mcc, gsm->mnc,
|
||||||
|
gsm->lac, gsm->cid, gsm->signalStrength,
|
||||||
|
gsm->bitErrorRate);
|
||||||
|
cell->type = RIL_CELL_INFO_TYPE_GSM;
|
||||||
|
cell->registered = registered;
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
ofono_error("failed to parse GSM cell info");
|
||||||
|
g_free(cell);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ril_cell *ril_cell_info_parse_cell_wcdma(GRilIoParser *rilp,
|
||||||
|
gboolean registered)
|
||||||
|
{
|
||||||
|
struct ril_cell *cell = g_new0(struct ril_cell, 1);
|
||||||
|
struct ril_cell_info_wcdma *wcdma = &cell->info.wcdma;
|
||||||
|
|
||||||
|
if (grilio_parser_get_int32(rilp, &wcdma->mcc) &&
|
||||||
|
grilio_parser_get_int32(rilp, &wcdma->mnc) &&
|
||||||
|
grilio_parser_get_int32(rilp, &wcdma->lac) &&
|
||||||
|
grilio_parser_get_int32(rilp, &wcdma->cid) &&
|
||||||
|
grilio_parser_get_int32(rilp, &wcdma->psc) &&
|
||||||
|
grilio_parser_get_int32(rilp, &wcdma->signalStrength) &&
|
||||||
|
grilio_parser_get_int32(rilp, &wcdma->bitErrorRate)) {
|
||||||
|
DBG("[wcdma] reg=%d,mcc=%d,mnc=%d,lac=%d,cid=%d,psc=%d,"
|
||||||
|
"strength=%d,err=%d", registered, wcdma->mcc,
|
||||||
|
wcdma->mnc, wcdma->lac, wcdma->cid, wcdma->psc,
|
||||||
|
wcdma->signalStrength, wcdma->bitErrorRate);
|
||||||
|
cell->type = RIL_CELL_INFO_TYPE_WCDMA;
|
||||||
|
cell->registered = registered;
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
ofono_error("failed to parse WCDMA cell info");
|
||||||
|
g_free(cell);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ril_cell *ril_cell_info_parse_cell_lte(GRilIoParser *rilp,
|
||||||
|
gboolean registered)
|
||||||
|
{
|
||||||
|
struct ril_cell *cell = g_new0(struct ril_cell, 1);
|
||||||
|
struct ril_cell_info_lte *lte = &cell->info.lte;
|
||||||
|
|
||||||
|
if (grilio_parser_get_int32(rilp, <e->mcc) &&
|
||||||
|
grilio_parser_get_int32(rilp, <e->mnc) &&
|
||||||
|
grilio_parser_get_int32(rilp, <e->ci) &&
|
||||||
|
grilio_parser_get_int32(rilp, <e->pci) &&
|
||||||
|
grilio_parser_get_int32(rilp, <e->tac) &&
|
||||||
|
grilio_parser_get_int32(rilp, <e->signalStrength) &&
|
||||||
|
grilio_parser_get_int32(rilp, <e->rsrp) &&
|
||||||
|
grilio_parser_get_int32(rilp, <e->rsrq) &&
|
||||||
|
grilio_parser_get_int32(rilp, <e->rssnr) &&
|
||||||
|
grilio_parser_get_int32(rilp, <e->cqi) &&
|
||||||
|
grilio_parser_get_int32(rilp, <e->timingAdvance)) {
|
||||||
|
DBG("[lte] reg=%d,mcc=%d,mnc=%d,ci=%d,pci=%d,tac=%d,"
|
||||||
|
"strength=%d,rsrp=%d,rsrq=0x%x,rssnr=0x%x,cqi=%d,"
|
||||||
|
"t=0x%x", registered, lte->mcc, lte->mnc, lte->ci,
|
||||||
|
lte->pci, lte->tac, lte->signalStrength, lte->rsrp,
|
||||||
|
lte->rsrq, lte->rssnr, lte->cqi, lte->timingAdvance);
|
||||||
|
cell->type = RIL_CELL_INFO_TYPE_LTE;
|
||||||
|
cell->registered = registered;
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
ofono_error("failed to parse LTE cell info");
|
||||||
|
g_free(cell);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum ril_cell_info_type ril_cell_info_parse_cell(GRilIoParser *rilp,
|
||||||
|
struct ril_cell **cell_ptr)
|
||||||
|
{
|
||||||
|
int type, reg;
|
||||||
|
|
||||||
|
if (grilio_parser_get_int32(rilp, &type) &&
|
||||||
|
grilio_parser_get_int32(rilp, ®) &&
|
||||||
|
grilio_parser_get_int32_array(rilp, NULL, 3)) {
|
||||||
|
int skip = 0;
|
||||||
|
struct ril_cell *cell = NULL;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case RIL_CELL_INFO_TYPE_GSM:
|
||||||
|
cell = ril_cell_info_parse_cell_gsm(rilp, reg);
|
||||||
|
break;
|
||||||
|
case RIL_CELL_INFO_TYPE_WCDMA:
|
||||||
|
cell = ril_cell_info_parse_cell_wcdma(rilp, reg);
|
||||||
|
break;
|
||||||
|
case RIL_CELL_INFO_TYPE_LTE:
|
||||||
|
cell = ril_cell_info_parse_cell_lte(rilp, reg);
|
||||||
|
break;
|
||||||
|
case RIL_CELL_INFO_TYPE_CDMA:
|
||||||
|
skip = 10;
|
||||||
|
break;
|
||||||
|
case RIL_CELL_INFO_TYPE_TD_SCDMA:
|
||||||
|
skip = 6;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
skip = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cell) {
|
||||||
|
*cell_ptr = cell;
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skip && grilio_parser_get_int32_array(rilp, NULL, skip)) {
|
||||||
|
*cell_ptr = NULL;
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*cell_ptr = NULL;
|
||||||
|
return RIL_CELL_INFO_TYPE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GSList *ril_cell_info_parse_list(const void *data, guint len)
|
||||||
|
{
|
||||||
|
GSList *l = NULL;
|
||||||
|
GRilIoParser rilp;
|
||||||
|
int i, n;
|
||||||
|
|
||||||
|
grilio_parser_init(&rilp, data, len);
|
||||||
|
if (grilio_parser_get_int32(&rilp, &n) && n > 0) {
|
||||||
|
struct ril_cell *c;
|
||||||
|
|
||||||
|
DBG("%d cell(s):", n);
|
||||||
|
for (i=0; i<n && ril_cell_info_parse_cell(&rilp, &c); i++) {
|
||||||
|
if (c) {
|
||||||
|
l = g_slist_insert_sorted(l, c,
|
||||||
|
ril_cell_compare_func);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_list_changed_cb(GRilIoChannel *io, guint code,
|
||||||
|
const void *data, guint len, void *user_data)
|
||||||
|
{
|
||||||
|
struct ril_cell_info *self = RIL_CELL_INFO(user_data);
|
||||||
|
|
||||||
|
DBG_(self, "");
|
||||||
|
ril_cell_info_update_cells(self, ril_cell_info_parse_list(data, len));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_list_cb(GRilIoChannel *io, int status,
|
||||||
|
const void *data, guint len, void *user_data)
|
||||||
|
{
|
||||||
|
struct ril_cell_info *self = RIL_CELL_INFO(user_data);
|
||||||
|
struct ril_cell_info_priv *priv = self->priv;
|
||||||
|
|
||||||
|
DBG_(self, "");
|
||||||
|
GASSERT(priv->query_id);
|
||||||
|
priv->query_id = 0;
|
||||||
|
ril_cell_info_update_cells(self, ril_cell_info_parse_list(data, len));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_set_rate_cb(GRilIoChannel *io, int status,
|
||||||
|
const void *data, guint len, void *user_data)
|
||||||
|
{
|
||||||
|
struct ril_cell_info *self = RIL_CELL_INFO(user_data);
|
||||||
|
struct ril_cell_info_priv *priv = self->priv;
|
||||||
|
|
||||||
|
DBG_(self, "");
|
||||||
|
GASSERT(priv->set_rate_id);
|
||||||
|
priv->set_rate_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_query(struct ril_cell_info *self)
|
||||||
|
{
|
||||||
|
struct ril_cell_info_priv *priv = self->priv;
|
||||||
|
GRilIoRequest *req = grilio_request_new();
|
||||||
|
|
||||||
|
grilio_request_set_retry(req, RIL_RETRY_MS, -1);
|
||||||
|
grilio_channel_cancel_request(priv->io, priv->query_id, FALSE);
|
||||||
|
priv->query_id = grilio_channel_send_request_full(priv->io, req,
|
||||||
|
RIL_REQUEST_GET_CELL_INFO_LIST, ril_cell_info_list_cb,
|
||||||
|
NULL, self);
|
||||||
|
grilio_request_unref(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_set_rate(struct ril_cell_info *self, int ms)
|
||||||
|
{
|
||||||
|
struct ril_cell_info_priv *priv = self->priv;
|
||||||
|
GRilIoRequest *req = grilio_request_sized_new(8);
|
||||||
|
|
||||||
|
grilio_request_append_int32(req, 1);
|
||||||
|
grilio_request_append_int32(req, ms);
|
||||||
|
grilio_request_set_retry(req, RIL_RETRY_MS, -1);
|
||||||
|
grilio_channel_cancel_request(priv->io, priv->set_rate_id, FALSE);
|
||||||
|
priv->set_rate_id = grilio_channel_send_request_full(priv->io, req,
|
||||||
|
RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE,
|
||||||
|
ril_cell_info_set_rate_cb, NULL, self);
|
||||||
|
grilio_request_unref(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_update_rate(struct ril_cell_info *self)
|
||||||
|
{
|
||||||
|
struct ril_cell_info_priv *priv = self->priv;
|
||||||
|
|
||||||
|
ril_cell_info_set_rate(self,
|
||||||
|
(priv->mce->display_state == RIL_MCE_DISPLAY_OFF) ?
|
||||||
|
DISPLAY_OFF_UPDATE_RATE : DISPLAY_ON_UPDATE_RATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_display_state_cb(struct ril_mce *mce, void *arg)
|
||||||
|
{
|
||||||
|
struct ril_cell_info *self = RIL_CELL_INFO(arg);
|
||||||
|
struct ril_cell_info_priv *priv = self->priv;
|
||||||
|
|
||||||
|
if (priv->sim_card_ready) {
|
||||||
|
ril_cell_info_update_rate(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_refresh(struct ril_cell_info *self)
|
||||||
|
{
|
||||||
|
struct ril_cell_info_priv *priv = self->priv;
|
||||||
|
|
||||||
|
/* RIL_REQUEST_GET_CELL_INFO_LIST fails without SIM card */
|
||||||
|
if (priv->radio->state == RADIO_STATE_ON && priv->sim_card_ready) {
|
||||||
|
ril_cell_info_query(self);
|
||||||
|
} else {
|
||||||
|
ril_cell_info_update_cells(self, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_radio_state_cb(struct ril_radio *radio, void *arg)
|
||||||
|
{
|
||||||
|
struct ril_cell_info *self = RIL_CELL_INFO(arg);
|
||||||
|
|
||||||
|
DBG_(self, "%s", ril_radio_state_to_string(radio->state));
|
||||||
|
ril_cell_info_refresh(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_sim_status_cb(struct ril_sim_card *sim, void *arg)
|
||||||
|
{
|
||||||
|
struct ril_cell_info *self = RIL_CELL_INFO(arg);
|
||||||
|
struct ril_cell_info_priv *priv = self->priv;
|
||||||
|
const gboolean sim_card_was_ready = priv->sim_card_ready;
|
||||||
|
|
||||||
|
DBG_(self, "%sready", ril_sim_card_ready(sim) ? "" : "not ");
|
||||||
|
priv->sim_card_ready = ril_sim_card_ready(sim);
|
||||||
|
if (priv->sim_card_ready != sim_card_was_ready) {
|
||||||
|
ril_cell_info_refresh(self);
|
||||||
|
if (priv->sim_card_ready) {
|
||||||
|
ril_cell_info_update_rate(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gulong ril_cell_info_add_cells_changed_handler(struct ril_cell_info *self,
|
||||||
|
ril_cell_info_cb_t cb, void *arg)
|
||||||
|
{
|
||||||
|
return (G_LIKELY(self) && G_LIKELY(cb)) ? g_signal_connect(self,
|
||||||
|
SIGNAL_CELLS_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ril_cell_info_remove_handler(struct ril_cell_info *self, gulong id)
|
||||||
|
{
|
||||||
|
if (G_LIKELY(self) && G_LIKELY(id)) {
|
||||||
|
g_signal_handler_disconnect(self, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ril_cell_info *ril_cell_info_new(GRilIoChannel *io,
|
||||||
|
const char *log_prefix, struct ril_mce *mce,
|
||||||
|
struct ril_radio *radio, struct ril_sim_card *sim_card)
|
||||||
|
{
|
||||||
|
struct ril_cell_info *self = g_object_new(RIL_CELL_INFO_TYPE, 0);
|
||||||
|
struct ril_cell_info_priv *priv = self->priv;
|
||||||
|
|
||||||
|
priv->io = grilio_channel_ref(io);
|
||||||
|
priv->mce = ril_mce_ref(mce);
|
||||||
|
priv->radio = ril_radio_ref(radio);
|
||||||
|
priv->sim_card = ril_sim_card_ref(sim_card);
|
||||||
|
priv->log_prefix = (log_prefix && log_prefix[0]) ?
|
||||||
|
g_strconcat(log_prefix, " ", NULL) : g_strdup("");
|
||||||
|
DBG_(self, "");
|
||||||
|
priv->event_id = grilio_channel_add_unsol_event_handler(priv->io,
|
||||||
|
ril_cell_info_list_changed_cb, RIL_UNSOL_CELL_INFO_LIST, self);
|
||||||
|
priv->display_state_event_id =
|
||||||
|
ril_mce_add_display_state_changed_handler(mce,
|
||||||
|
ril_cell_info_display_state_cb, self);
|
||||||
|
priv->radio_state_event_id =
|
||||||
|
ril_radio_add_state_changed_handler(radio,
|
||||||
|
ril_cell_info_radio_state_cb, self);
|
||||||
|
priv->sim_status_event_id =
|
||||||
|
ril_sim_card_add_status_changed_handler(priv->sim_card,
|
||||||
|
ril_cell_info_sim_status_cb, self);
|
||||||
|
priv->sim_card_ready = ril_sim_card_ready(sim_card);
|
||||||
|
if (priv->sim_card_ready) {
|
||||||
|
ril_cell_info_query(self);
|
||||||
|
ril_cell_info_update_rate(self);
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ril_cell_info *ril_cell_info_ref(struct ril_cell_info *self)
|
||||||
|
{
|
||||||
|
if (G_LIKELY(self)) {
|
||||||
|
g_object_ref(RIL_CELL_INFO(self));
|
||||||
|
return self;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ril_cell_info_unref(struct ril_cell_info *self)
|
||||||
|
{
|
||||||
|
if (G_LIKELY(self)) {
|
||||||
|
g_object_unref(RIL_CELL_INFO(self));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_init(struct ril_cell_info *self)
|
||||||
|
{
|
||||||
|
self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self, RIL_CELL_INFO_TYPE,
|
||||||
|
struct ril_cell_info_priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_dispose(GObject *object)
|
||||||
|
{
|
||||||
|
struct ril_cell_info *self = RIL_CELL_INFO(object);
|
||||||
|
struct ril_cell_info_priv *priv = self->priv;
|
||||||
|
|
||||||
|
grilio_channel_remove_handlers(priv->io, &priv->event_id, 1);
|
||||||
|
if (priv->query_id) {
|
||||||
|
grilio_channel_cancel_request(priv->io, priv->query_id, FALSE);
|
||||||
|
priv->query_id = 0;
|
||||||
|
}
|
||||||
|
if (priv->set_rate_id) {
|
||||||
|
grilio_channel_cancel_request(priv->io, priv->set_rate_id,
|
||||||
|
FALSE);
|
||||||
|
priv->set_rate_id = 0;
|
||||||
|
}
|
||||||
|
if (priv->display_state_event_id) {
|
||||||
|
ril_mce_remove_handler(priv->mce, priv->display_state_event_id);
|
||||||
|
priv->display_state_event_id = 0;
|
||||||
|
}
|
||||||
|
ril_radio_remove_handlers(priv->radio, &priv->radio_state_event_id, 1);
|
||||||
|
ril_sim_card_remove_handlers(priv->sim_card,
|
||||||
|
&priv->sim_status_event_id, 1);
|
||||||
|
G_OBJECT_CLASS(ril_cell_info_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_finalize(GObject *object)
|
||||||
|
{
|
||||||
|
struct ril_cell_info *self = RIL_CELL_INFO(object);
|
||||||
|
struct ril_cell_info_priv *priv = self->priv;
|
||||||
|
|
||||||
|
DBG_(self, "");
|
||||||
|
g_free(priv->log_prefix);
|
||||||
|
grilio_channel_unref(priv->io);
|
||||||
|
ril_mce_unref(priv->mce);
|
||||||
|
ril_radio_unref(priv->radio);
|
||||||
|
ril_sim_card_unref(priv->sim_card);
|
||||||
|
g_slist_free_full(self->cells, g_free);
|
||||||
|
G_OBJECT_CLASS(ril_cell_info_parent_class)->finalize(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_class_init(RilCellInfoClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
||||||
|
|
||||||
|
object_class->dispose = ril_cell_info_dispose;
|
||||||
|
object_class->finalize = ril_cell_info_finalize;
|
||||||
|
g_type_class_add_private(klass, sizeof(struct ril_cell_info_priv));
|
||||||
|
ril_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local Variables:
|
||||||
|
* mode: C
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
63
ofono/drivers/ril/ril_cell_info.h
Normal file
63
ofono/drivers/ril/ril_cell_info.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* oFono - Open Source Telephony - RIL-based devices
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 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_CELL_INFO_H
|
||||||
|
#define RIL_CELL_INFO_H
|
||||||
|
|
||||||
|
#include "ril_types.h"
|
||||||
|
|
||||||
|
struct ril_cell {
|
||||||
|
enum ril_cell_info_type type;
|
||||||
|
gboolean registered;
|
||||||
|
union {
|
||||||
|
struct ril_cell_info_gsm gsm;
|
||||||
|
struct ril_cell_info_wcdma wcdma;
|
||||||
|
struct ril_cell_info_lte lte;
|
||||||
|
} info;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ril_cell_info_priv;
|
||||||
|
struct ril_cell_info {
|
||||||
|
GObject object;
|
||||||
|
struct ril_cell_info_priv *priv;
|
||||||
|
GSList *cells;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*ril_cell_info_cb_t)(struct ril_cell_info *info, void *arg);
|
||||||
|
|
||||||
|
gint ril_cell_compare_func(gconstpointer v1, gconstpointer v2);
|
||||||
|
gint ril_cell_compare_location(const struct ril_cell *c1,
|
||||||
|
const struct ril_cell *c2);
|
||||||
|
|
||||||
|
struct ril_cell_info *ril_cell_info_new(GRilIoChannel *io,
|
||||||
|
const char *log_prefix, struct ril_mce *mce,
|
||||||
|
struct ril_radio *radio, struct ril_sim_card *sim_card);
|
||||||
|
struct ril_cell_info *ril_cell_info_ref(struct ril_cell_info *info);
|
||||||
|
void ril_cell_info_unref(struct ril_cell_info *info);
|
||||||
|
struct ril_cell *ril_cell_find_cell(struct ril_cell_info *info,
|
||||||
|
const struct ril_cell *cell);
|
||||||
|
gulong ril_cell_info_add_cells_changed_handler(struct ril_cell_info *info,
|
||||||
|
ril_cell_info_cb_t cb, void *arg);
|
||||||
|
void ril_cell_info_remove_handler(struct ril_cell_info *info, gulong id);
|
||||||
|
|
||||||
|
#endif /* RIL_CELL_INFO_H */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local Variables:
|
||||||
|
* mode: C
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
586
ofono/drivers/ril/ril_cell_info_dbus.c
Normal file
586
ofono/drivers/ril/ril_cell_info_dbus.c
Normal file
@@ -0,0 +1,586 @@
|
|||||||
|
/*
|
||||||
|
* oFono - Open Source Telephony - RIL-based devices
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 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_cell_info.h"
|
||||||
|
#include "ril_log.h"
|
||||||
|
|
||||||
|
#include <ofono/dbus.h>
|
||||||
|
|
||||||
|
#include <gdbus.h>
|
||||||
|
|
||||||
|
struct ril_cell_entry {
|
||||||
|
guint cell_id;
|
||||||
|
char *path;
|
||||||
|
struct ril_cell cell;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ril_cell_info_dbus {
|
||||||
|
struct ril_modem *md;
|
||||||
|
struct ril_cell_info *info;
|
||||||
|
DBusConnection *conn;
|
||||||
|
char *path;
|
||||||
|
gulong handler_id;
|
||||||
|
guint next_cell_id;
|
||||||
|
GSList *entries;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define RIL_CELL_INFO_DBUS_INTERFACE "org.nemomobile.ofono.CellInfo"
|
||||||
|
#define RIL_CELL_INFO_DBUS_CELLS_ADDED_SIGNAL "CellsAdded"
|
||||||
|
#define RIL_CELL_INFO_DBUS_CELLS_REMOVED_SIGNAL "CellsRemoved"
|
||||||
|
|
||||||
|
#define RIL_CELL_DBUS_INTERFACE_VERSION (1)
|
||||||
|
#define RIL_CELL_DBUS_INTERFACE "org.nemomobile.ofono.Cell"
|
||||||
|
#define RIL_CELL_DBUS_REGISTERED_CHANGED_SIGNAL "RegisteredChanged"
|
||||||
|
#define RIL_CELL_DBUS_PROPERTY_CHANGED_SIGNAL "PropertyChanged"
|
||||||
|
#define RIL_CELL_DBUS_REMOVED_SIGNAL "Removed"
|
||||||
|
|
||||||
|
struct ril_cell_property {
|
||||||
|
const char *name;
|
||||||
|
glong off;
|
||||||
|
int flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define RIL_CELL_GSM_PROPERTY(value,name) \
|
||||||
|
{ #name, G_STRUCT_OFFSET(struct ril_cell_info_gsm,name), value }
|
||||||
|
#define RIL_CELL_WCDMA_PROPERTY(value,name) \
|
||||||
|
{ #name, G_STRUCT_OFFSET(struct ril_cell_info_wcdma,name), value }
|
||||||
|
#define RIL_CELL_LTE_PROPERTY(value,name) \
|
||||||
|
{ #name, G_STRUCT_OFFSET(struct ril_cell_info_lte,name), value }
|
||||||
|
|
||||||
|
static const struct ril_cell_property ril_cell_gsm_properties [] = {
|
||||||
|
RIL_CELL_GSM_PROPERTY(0x01,mcc),
|
||||||
|
RIL_CELL_GSM_PROPERTY(0x02,mnc),
|
||||||
|
RIL_CELL_GSM_PROPERTY(0x04,lac),
|
||||||
|
RIL_CELL_GSM_PROPERTY(0x08,cid),
|
||||||
|
RIL_CELL_GSM_PROPERTY(0x10,signalStrength),
|
||||||
|
RIL_CELL_GSM_PROPERTY(0x20,bitErrorRate)
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct ril_cell_property ril_cell_wcdma_properties [] = {
|
||||||
|
RIL_CELL_WCDMA_PROPERTY(0x01,mcc),
|
||||||
|
RIL_CELL_WCDMA_PROPERTY(0x02,mnc),
|
||||||
|
RIL_CELL_WCDMA_PROPERTY(0x04,lac),
|
||||||
|
RIL_CELL_WCDMA_PROPERTY(0x08,cid),
|
||||||
|
RIL_CELL_WCDMA_PROPERTY(0x10,psc),
|
||||||
|
RIL_CELL_WCDMA_PROPERTY(0x20,signalStrength),
|
||||||
|
RIL_CELL_WCDMA_PROPERTY(0x40,bitErrorRate)
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct ril_cell_property ril_cell_lte_properties [] = {
|
||||||
|
RIL_CELL_LTE_PROPERTY(0x001,mcc),
|
||||||
|
RIL_CELL_LTE_PROPERTY(0x002,mnc),
|
||||||
|
RIL_CELL_LTE_PROPERTY(0x004,ci),
|
||||||
|
RIL_CELL_LTE_PROPERTY(0x008,pci),
|
||||||
|
RIL_CELL_LTE_PROPERTY(0x010,tac),
|
||||||
|
RIL_CELL_LTE_PROPERTY(0x020,signalStrength),
|
||||||
|
RIL_CELL_LTE_PROPERTY(0x040,rsrp),
|
||||||
|
RIL_CELL_LTE_PROPERTY(0x080,rsrq),
|
||||||
|
RIL_CELL_LTE_PROPERTY(0x100,rssnr),
|
||||||
|
RIL_CELL_LTE_PROPERTY(0x200,cqi),
|
||||||
|
RIL_CELL_LTE_PROPERTY(0x400,timingAdvance)
|
||||||
|
};
|
||||||
|
|
||||||
|
#define RIL_CELL_PROPERTY_REGISTERED 0x1000
|
||||||
|
|
||||||
|
typedef void (*ril_cell_info_dbus_append_fn)(DBusMessageIter *it,
|
||||||
|
const struct ril_cell_entry *entry);
|
||||||
|
|
||||||
|
static const char *ril_cell_info_dbus_cell_type_str(enum ril_cell_info_type t)
|
||||||
|
{
|
||||||
|
switch (t) {
|
||||||
|
case RIL_CELL_INFO_TYPE_GSM:
|
||||||
|
return "gsm";
|
||||||
|
case RIL_CELL_INFO_TYPE_CDMA:
|
||||||
|
return "cdma";
|
||||||
|
case RIL_CELL_INFO_TYPE_LTE:
|
||||||
|
return "lte";
|
||||||
|
case RIL_CELL_INFO_TYPE_WCDMA:
|
||||||
|
return "wcdma";
|
||||||
|
case RIL_CELL_INFO_TYPE_TD_SCDMA:
|
||||||
|
return "tdscdma";
|
||||||
|
case RIL_CELL_INFO_TYPE_NONE:
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct ril_cell_property *ril_cell_info_dbus_cell_properties(
|
||||||
|
enum ril_cell_info_type type, int *count)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case RIL_CELL_INFO_TYPE_GSM:
|
||||||
|
*count = G_N_ELEMENTS(ril_cell_gsm_properties);
|
||||||
|
return ril_cell_gsm_properties;
|
||||||
|
case RIL_CELL_INFO_TYPE_WCDMA:
|
||||||
|
*count = G_N_ELEMENTS(ril_cell_wcdma_properties);
|
||||||
|
return ril_cell_wcdma_properties;
|
||||||
|
case RIL_CELL_INFO_TYPE_LTE:
|
||||||
|
*count = G_N_ELEMENTS(ril_cell_lte_properties);
|
||||||
|
return ril_cell_lte_properties;
|
||||||
|
default:
|
||||||
|
*count = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void ril_cell_info_destroy_entry(struct ril_cell_entry *entry)
|
||||||
|
{
|
||||||
|
if (entry) {
|
||||||
|
g_free(entry->path);
|
||||||
|
g_free(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static DBusMessage *ril_cell_info_dbus_reply(DBusMessage *msg,
|
||||||
|
const struct ril_cell_entry *entry,
|
||||||
|
ril_cell_info_dbus_append_fn append)
|
||||||
|
{
|
||||||
|
DBusMessage *reply = dbus_message_new_method_return(msg);
|
||||||
|
DBusMessageIter it;
|
||||||
|
|
||||||
|
dbus_message_iter_init_append(reply, &it);
|
||||||
|
append(&it, entry);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_dbus_append_version(DBusMessageIter *it,
|
||||||
|
const struct ril_cell_entry *entry)
|
||||||
|
{
|
||||||
|
dbus_int32_t version = RIL_CELL_DBUS_INTERFACE_VERSION;
|
||||||
|
|
||||||
|
dbus_message_iter_append_basic(it, DBUS_TYPE_INT32, &version);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_dbus_append_type(DBusMessageIter *it,
|
||||||
|
const struct ril_cell_entry *entry)
|
||||||
|
{
|
||||||
|
const char *type = ril_cell_info_dbus_cell_type_str(entry->cell.type);
|
||||||
|
|
||||||
|
dbus_message_iter_append_basic(it, DBUS_TYPE_STRING, &type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_dbus_append_registered(DBusMessageIter *it,
|
||||||
|
const struct ril_cell_entry *entry)
|
||||||
|
{
|
||||||
|
dbus_bool_t registered = entry->cell.registered;
|
||||||
|
|
||||||
|
dbus_message_iter_append_basic(it, DBUS_TYPE_BOOLEAN, ®istered);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_dbus_append_properties(DBusMessageIter *it,
|
||||||
|
const struct ril_cell_entry *entry)
|
||||||
|
{
|
||||||
|
int i, n;
|
||||||
|
DBusMessageIter dict;
|
||||||
|
const struct ril_cell *cell = &entry->cell;
|
||||||
|
const struct ril_cell_property *prop =
|
||||||
|
ril_cell_info_dbus_cell_properties(cell->type, &n);
|
||||||
|
|
||||||
|
dbus_message_iter_open_container(it, DBUS_TYPE_ARRAY, "{sv}", &dict);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
gint32 value = G_STRUCT_MEMBER(int, &cell->info, prop[i].off);
|
||||||
|
if (value != INT_MAX) {
|
||||||
|
ofono_dbus_dict_append(&dict, prop[i].name,
|
||||||
|
DBUS_TYPE_INT32, &value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dbus_message_iter_close_container(it, &dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_dbus_append_all(DBusMessageIter *it,
|
||||||
|
const struct ril_cell_entry *entry)
|
||||||
|
{
|
||||||
|
ril_cell_info_dbus_append_version(it, entry);
|
||||||
|
ril_cell_info_dbus_append_type(it, entry);
|
||||||
|
ril_cell_info_dbus_append_registered(it, entry);
|
||||||
|
ril_cell_info_dbus_append_properties(it, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DBusMessage *ril_cell_info_dbus_cell_get_all(DBusConnection *conn,
|
||||||
|
DBusMessage *msg, void *data)
|
||||||
|
{
|
||||||
|
return ril_cell_info_dbus_reply(msg, (struct ril_cell_entry*)data,
|
||||||
|
ril_cell_info_dbus_append_all);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DBusMessage *ril_cell_info_dbus_cell_get_version(DBusConnection *conn,
|
||||||
|
DBusMessage *msg, void *data)
|
||||||
|
{
|
||||||
|
return ril_cell_info_dbus_reply(msg, (struct ril_cell_entry*)data,
|
||||||
|
ril_cell_info_dbus_append_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DBusMessage *ril_cell_info_dbus_cell_get_type(DBusConnection *conn,
|
||||||
|
DBusMessage *msg, void *data)
|
||||||
|
{
|
||||||
|
return ril_cell_info_dbus_reply(msg, (struct ril_cell_entry*)data,
|
||||||
|
ril_cell_info_dbus_append_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DBusMessage *ril_cell_info_dbus_cell_get_registered(DBusConnection *conn,
|
||||||
|
DBusMessage *msg, void *data)
|
||||||
|
{
|
||||||
|
return ril_cell_info_dbus_reply(msg, (struct ril_cell_entry*)data,
|
||||||
|
ril_cell_info_dbus_append_registered);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DBusMessage *ril_cell_info_dbus_cell_get_properties(DBusConnection *conn,
|
||||||
|
DBusMessage *msg, void *data)
|
||||||
|
{
|
||||||
|
return ril_cell_info_dbus_reply(msg, (struct ril_cell_entry*)data,
|
||||||
|
ril_cell_info_dbus_append_properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const GDBusMethodTable ril_cell_info_dbus_cell_methods[] = {
|
||||||
|
{ GDBUS_METHOD("GetAll", NULL,
|
||||||
|
GDBUS_ARGS({ "version", "i" },
|
||||||
|
{ "type", "s" },
|
||||||
|
{ "registered", "b" },
|
||||||
|
{ "properties", "a{sv}" }),
|
||||||
|
ril_cell_info_dbus_cell_get_all) },
|
||||||
|
{ GDBUS_METHOD("GetInterfaceVersion", NULL,
|
||||||
|
GDBUS_ARGS({ "version", "i" }),
|
||||||
|
ril_cell_info_dbus_cell_get_version) },
|
||||||
|
{ GDBUS_METHOD("GetType", NULL,
|
||||||
|
GDBUS_ARGS({ "type", "s" }),
|
||||||
|
ril_cell_info_dbus_cell_get_type) },
|
||||||
|
{ GDBUS_METHOD("GetRegistered", NULL,
|
||||||
|
GDBUS_ARGS({ "registered", "b" }),
|
||||||
|
ril_cell_info_dbus_cell_get_registered) },
|
||||||
|
{ GDBUS_METHOD("GetProperties", NULL,
|
||||||
|
GDBUS_ARGS({ "properties", "a{sv}" }),
|
||||||
|
ril_cell_info_dbus_cell_get_properties) },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const GDBusSignalTable ril_cell_info_dbus_cell_signals[] = {
|
||||||
|
{ GDBUS_SIGNAL(RIL_CELL_DBUS_REGISTERED_CHANGED_SIGNAL,
|
||||||
|
GDBUS_ARGS({ "registered", "b" })) },
|
||||||
|
{ GDBUS_SIGNAL(RIL_CELL_DBUS_PROPERTY_CHANGED_SIGNAL,
|
||||||
|
GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
|
||||||
|
{ GDBUS_SIGNAL(RIL_CELL_DBUS_REMOVED_SIGNAL,
|
||||||
|
GDBUS_ARGS({})) },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct ril_cell_entry *ril_cell_info_dbus_find_id(
|
||||||
|
struct ril_cell_info_dbus *dbus, guint id)
|
||||||
|
{
|
||||||
|
GSList *l;
|
||||||
|
for (l = dbus->entries; l; l = l->next) {
|
||||||
|
struct ril_cell_entry *entry = l->data;
|
||||||
|
if (entry->cell_id == id) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static guint ril_cell_info_dbus_next_cell_id(struct ril_cell_info_dbus *dbus)
|
||||||
|
{
|
||||||
|
while (ril_cell_info_dbus_find_id(dbus, dbus->next_cell_id)) {
|
||||||
|
dbus->next_cell_id++;
|
||||||
|
}
|
||||||
|
return dbus->next_cell_id++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ril_cell_entry *ril_cell_info_dbus_find_cell(
|
||||||
|
struct ril_cell_info_dbus *dbus, const struct ril_cell *cell)
|
||||||
|
{
|
||||||
|
if (cell) {
|
||||||
|
GSList *l;
|
||||||
|
for (l = dbus->entries; l; l = l->next) {
|
||||||
|
struct ril_cell_entry *entry = l->data;
|
||||||
|
if (!ril_cell_compare_location(&entry->cell, cell)) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_dbus_emit_path_list(struct ril_cell_info_dbus *dbus,
|
||||||
|
const char *name, GPtrArray *list)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
DBusMessageIter it, array;
|
||||||
|
DBusMessage *signal = dbus_message_new_signal(dbus->path,
|
||||||
|
RIL_CELL_INFO_DBUS_INTERFACE, name);
|
||||||
|
|
||||||
|
dbus_message_iter_init_append(signal, &it);
|
||||||
|
dbus_message_iter_open_container(&it, DBUS_TYPE_ARRAY, "o", &array);
|
||||||
|
for (i = 0; i < list->len; i++) {
|
||||||
|
const char* path = list->pdata[i];
|
||||||
|
dbus_message_iter_append_basic(&array, DBUS_TYPE_OBJECT_PATH,
|
||||||
|
&path);
|
||||||
|
}
|
||||||
|
dbus_message_iter_close_container(&it, &array);
|
||||||
|
|
||||||
|
g_dbus_send_message(dbus->conn, signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ril_cell_info_dbus_compare(const struct ril_cell *c1,
|
||||||
|
const struct ril_cell *c2)
|
||||||
|
{
|
||||||
|
if (c1->type == c2->type) {
|
||||||
|
int i, n, mask = 0;
|
||||||
|
const struct ril_cell_property *prop =
|
||||||
|
ril_cell_info_dbus_cell_properties(c1->type, &n);
|
||||||
|
|
||||||
|
if (c1->registered != c2->registered) {
|
||||||
|
mask |= RIL_CELL_PROPERTY_REGISTERED;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
const glong offset = prop[i].off;
|
||||||
|
gint32 v1 = G_STRUCT_MEMBER(int, &c1->info, offset);
|
||||||
|
gint32 v2 = G_STRUCT_MEMBER(int, &c2->info, offset);
|
||||||
|
if (v1 != v2) {
|
||||||
|
mask |= prop[i].flag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mask;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_dbus_property_changed(struct ril_cell_info_dbus *dbus,
|
||||||
|
const struct ril_cell_entry *entry, int mask)
|
||||||
|
{
|
||||||
|
int i, n;
|
||||||
|
const struct ril_cell *cell = &entry->cell;
|
||||||
|
const struct ril_cell_property *prop =
|
||||||
|
ril_cell_info_dbus_cell_properties(cell->type, &n);
|
||||||
|
|
||||||
|
if (mask & RIL_CELL_PROPERTY_REGISTERED) {
|
||||||
|
dbus_bool_t registered = cell->registered;
|
||||||
|
g_dbus_emit_signal(dbus->conn, entry->path,
|
||||||
|
RIL_CELL_DBUS_INTERFACE,
|
||||||
|
RIL_CELL_DBUS_REGISTERED_CHANGED_SIGNAL,
|
||||||
|
DBUS_TYPE_BOOLEAN, ®istered, DBUS_TYPE_INVALID);
|
||||||
|
mask &= ~RIL_CELL_PROPERTY_REGISTERED;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n && mask; i++) {
|
||||||
|
if (mask & prop[i].flag) {
|
||||||
|
ofono_dbus_signal_property_changed(dbus->conn,
|
||||||
|
entry->path, RIL_CELL_DBUS_INTERFACE,
|
||||||
|
prop[i].name, DBUS_TYPE_INT32,
|
||||||
|
G_STRUCT_MEMBER_P(&cell->info, prop[i].off));
|
||||||
|
mask &= ~prop[i].flag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_dbus_update_entries(struct ril_cell_info_dbus *dbus,
|
||||||
|
gboolean emit_signals)
|
||||||
|
{
|
||||||
|
GSList *l;
|
||||||
|
GPtrArray* added = NULL;
|
||||||
|
GPtrArray* removed = NULL;
|
||||||
|
|
||||||
|
/* Remove non-existent cells */
|
||||||
|
l = dbus->entries;
|
||||||
|
while (l) {
|
||||||
|
GSList *next = l->next;
|
||||||
|
struct ril_cell_entry *entry = l->data;
|
||||||
|
if (!g_slist_find_custom(dbus->info->cells, &entry->cell,
|
||||||
|
ril_cell_compare_func)) {
|
||||||
|
DBG("%s removed", entry->path);
|
||||||
|
dbus->entries = g_slist_delete_link(dbus->entries, l);
|
||||||
|
g_dbus_emit_signal(dbus->conn, entry->path,
|
||||||
|
RIL_CELL_DBUS_INTERFACE,
|
||||||
|
RIL_CELL_DBUS_REMOVED_SIGNAL,
|
||||||
|
DBUS_TYPE_INVALID);
|
||||||
|
g_dbus_unregister_interface(dbus->conn, entry->path,
|
||||||
|
RIL_CELL_DBUS_INTERFACE);
|
||||||
|
if (emit_signals) {
|
||||||
|
if (!removed) {
|
||||||
|
removed =
|
||||||
|
g_ptr_array_new_with_free_func(
|
||||||
|
g_free);
|
||||||
|
}
|
||||||
|
/* Steal the path */
|
||||||
|
g_ptr_array_add(removed, entry->path);
|
||||||
|
entry->path = NULL;
|
||||||
|
}
|
||||||
|
ril_cell_info_destroy_entry(entry);
|
||||||
|
}
|
||||||
|
l = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add new cells */
|
||||||
|
for (l = dbus->info->cells; l; l = l->next) {
|
||||||
|
const struct ril_cell *cell = l->data;
|
||||||
|
struct ril_cell_entry *entry =
|
||||||
|
ril_cell_info_dbus_find_cell(dbus, cell);
|
||||||
|
|
||||||
|
if (entry) {
|
||||||
|
if (emit_signals) {
|
||||||
|
int diff = ril_cell_info_dbus_compare(cell,
|
||||||
|
&entry->cell);
|
||||||
|
entry->cell = *cell;
|
||||||
|
ril_cell_info_dbus_property_changed(dbus,
|
||||||
|
entry, diff);
|
||||||
|
} else {
|
||||||
|
entry->cell = *cell;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
entry = g_new0(struct ril_cell_entry, 1);
|
||||||
|
entry->cell = *cell;
|
||||||
|
entry->cell_id = ril_cell_info_dbus_next_cell_id(dbus);
|
||||||
|
entry->path = g_strdup_printf("%s/cell_%u", dbus->path,
|
||||||
|
entry->cell_id);
|
||||||
|
dbus->entries = g_slist_append(dbus->entries, entry);
|
||||||
|
DBG("%s added", entry->path);
|
||||||
|
g_dbus_register_interface(dbus->conn, entry->path,
|
||||||
|
RIL_CELL_DBUS_INTERFACE,
|
||||||
|
ril_cell_info_dbus_cell_methods,
|
||||||
|
ril_cell_info_dbus_cell_signals, NULL,
|
||||||
|
entry, NULL);
|
||||||
|
if (emit_signals) {
|
||||||
|
if (!added) {
|
||||||
|
added = g_ptr_array_new();
|
||||||
|
}
|
||||||
|
g_ptr_array_add(added, entry->path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removed) {
|
||||||
|
ril_cell_info_dbus_emit_path_list(dbus,
|
||||||
|
RIL_CELL_INFO_DBUS_CELLS_REMOVED_SIGNAL, removed);
|
||||||
|
g_ptr_array_free(removed, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (added) {
|
||||||
|
ril_cell_info_dbus_emit_path_list(dbus,
|
||||||
|
RIL_CELL_INFO_DBUS_CELLS_ADDED_SIGNAL, added);
|
||||||
|
g_ptr_array_free(added, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_cell_info_dbus_cells_changed_cb(struct ril_cell_info *info,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
DBG("");
|
||||||
|
ril_cell_info_dbus_update_entries((struct ril_cell_info_dbus *)arg,
|
||||||
|
TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DBusMessage *ril_cell_info_dbus_get_cells(DBusConnection *conn,
|
||||||
|
DBusMessage *msg, void *data)
|
||||||
|
{
|
||||||
|
struct ril_cell_info_dbus *dbus = data;
|
||||||
|
DBusMessage *reply = dbus_message_new_method_return(msg);
|
||||||
|
DBusMessageIter it, array;
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
dbus_message_iter_init_append(reply, &it);
|
||||||
|
dbus_message_iter_open_container(&it, DBUS_TYPE_ARRAY, "o", &array);
|
||||||
|
for (l = dbus->entries; l; l = l->next) {
|
||||||
|
const struct ril_cell_entry *entry = l->data;
|
||||||
|
dbus_message_iter_append_basic(&array, DBUS_TYPE_OBJECT_PATH,
|
||||||
|
&entry->path);
|
||||||
|
}
|
||||||
|
dbus_message_iter_close_container(&it, &array);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const GDBusMethodTable ril_cell_info_dbus_methods[] = {
|
||||||
|
{ GDBUS_METHOD("GetCells", NULL,
|
||||||
|
GDBUS_ARGS({ "paths", "ao" }),
|
||||||
|
ril_cell_info_dbus_get_cells) },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const GDBusSignalTable ril_cell_info_dbus_signals[] = {
|
||||||
|
{ GDBUS_SIGNAL(RIL_CELL_INFO_DBUS_CELLS_ADDED_SIGNAL,
|
||||||
|
GDBUS_ARGS({ "paths", "ao" })) },
|
||||||
|
{ GDBUS_SIGNAL(RIL_CELL_INFO_DBUS_CELLS_REMOVED_SIGNAL,
|
||||||
|
GDBUS_ARGS({ "paths", "ao" })) },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ril_cell_info_dbus *ril_cell_info_dbus_new(struct ril_modem *md,
|
||||||
|
struct ril_cell_info *info)
|
||||||
|
{
|
||||||
|
struct ril_cell_info_dbus *dbus = g_new0(struct ril_cell_info_dbus, 1);
|
||||||
|
|
||||||
|
DBG("%s", ril_modem_get_path(md));
|
||||||
|
dbus->md = md;
|
||||||
|
dbus->path = g_strdup(ril_modem_get_path(md));
|
||||||
|
dbus->conn = dbus_connection_ref(ofono_dbus_get_connection());
|
||||||
|
dbus->info = ril_cell_info_ref(info);
|
||||||
|
dbus->handler_id = ril_cell_info_add_cells_changed_handler(info,
|
||||||
|
ril_cell_info_dbus_cells_changed_cb, dbus);
|
||||||
|
|
||||||
|
/* Register D-Bus interface */
|
||||||
|
if (g_dbus_register_interface(dbus->conn, dbus->path,
|
||||||
|
RIL_CELL_INFO_DBUS_INTERFACE, ril_cell_info_dbus_methods,
|
||||||
|
ril_cell_info_dbus_signals, NULL, dbus, NULL)) {
|
||||||
|
ofono_modem_add_interface(md->ofono,
|
||||||
|
RIL_CELL_INFO_DBUS_INTERFACE);
|
||||||
|
ril_cell_info_dbus_update_entries(dbus, FALSE);
|
||||||
|
return dbus;
|
||||||
|
} else {
|
||||||
|
ofono_error("RIL D-Bus register failed");
|
||||||
|
ril_cell_info_dbus_free(dbus);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ril_cell_info_dbus_free(struct ril_cell_info_dbus *dbus)
|
||||||
|
{
|
||||||
|
if (dbus) {
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
DBG("%s", dbus->path);
|
||||||
|
g_dbus_unregister_interface(dbus->conn, dbus->path,
|
||||||
|
RIL_CELL_INFO_DBUS_INTERFACE);
|
||||||
|
ofono_modem_remove_interface(dbus->md->ofono,
|
||||||
|
RIL_CELL_INFO_DBUS_INTERFACE);
|
||||||
|
|
||||||
|
/* Unregister cells */
|
||||||
|
l = dbus->entries;
|
||||||
|
while (l) {
|
||||||
|
struct ril_cell_entry *entry = l->data;
|
||||||
|
g_dbus_unregister_interface(dbus->conn, entry->path,
|
||||||
|
RIL_CELL_DBUS_INTERFACE);
|
||||||
|
ril_cell_info_destroy_entry(entry);
|
||||||
|
l = l->next;
|
||||||
|
}
|
||||||
|
g_slist_free(dbus->entries);
|
||||||
|
|
||||||
|
dbus_connection_unref(dbus->conn);
|
||||||
|
|
||||||
|
ril_cell_info_remove_handler(dbus->info, dbus->handler_id);
|
||||||
|
ril_cell_info_unref(dbus->info);
|
||||||
|
|
||||||
|
g_free(dbus->path);
|
||||||
|
g_free(dbus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local Variables:
|
||||||
|
* mode: C
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
115
ofono/drivers/ril/ril_config.c
Normal file
115
ofono/drivers/ril/ril_config.c
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* oFono - Open Source Telephony - RIL-based devices
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015-2016 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_config.h"
|
||||||
|
|
||||||
|
/* Utilities for parsing ril_subscription.conf */
|
||||||
|
|
||||||
|
char* ril_config_get_string(GKeyFile *file, const char *group, const char *key)
|
||||||
|
{
|
||||||
|
char *val = g_key_file_get_string(file, group, key, NULL);
|
||||||
|
|
||||||
|
if (!val && strcmp(group, RILCONF_SETTINGS_GROUP)) {
|
||||||
|
/* Check the common section */
|
||||||
|
val = g_key_file_get_string(file, RILCONF_SETTINGS_GROUP, key,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean ril_config_get_integer(GKeyFile *file, const char *group,
|
||||||
|
const char *key, int *out_value)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
int value = g_key_file_get_integer(file, group, key, &error);
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
if (out_value) {
|
||||||
|
*out_value = value;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
} else {
|
||||||
|
g_error_free(error);
|
||||||
|
if (strcmp(group, RILCONF_SETTINGS_GROUP)) {
|
||||||
|
/* Check the common section */
|
||||||
|
error = NULL;
|
||||||
|
value = g_key_file_get_integer(file,
|
||||||
|
RILCONF_SETTINGS_GROUP, key, &error);
|
||||||
|
if (!error) {
|
||||||
|
if (out_value) {
|
||||||
|
*out_value = value;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
g_error_free(error);
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean ril_config_get_boolean(GKeyFile *file, const char *group,
|
||||||
|
const char *key, gboolean *out_value)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean value = g_key_file_get_boolean(file, group, key, &error);
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
if (out_value) {
|
||||||
|
*out_value = value;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
} else {
|
||||||
|
g_error_free(error);
|
||||||
|
if (strcmp(group, RILCONF_SETTINGS_GROUP)) {
|
||||||
|
/* Check the common section */
|
||||||
|
error = NULL;
|
||||||
|
value = g_key_file_get_boolean(file,
|
||||||
|
RILCONF_SETTINGS_GROUP, key, &error);
|
||||||
|
if (!error) {
|
||||||
|
if (out_value) {
|
||||||
|
*out_value = value;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
g_error_free(error);
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean ril_config_get_flag(GKeyFile *file, const char *group,
|
||||||
|
const char *key, int flag, int *flags)
|
||||||
|
{
|
||||||
|
gboolean value;
|
||||||
|
|
||||||
|
if (ril_config_get_boolean(file, group, key, &value)) {
|
||||||
|
if (value) {
|
||||||
|
*flags |= flag;
|
||||||
|
} else {
|
||||||
|
*flags &= ~flag;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
} else {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local Variables:
|
||||||
|
* mode: C
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
41
ofono/drivers/ril/ril_config.h
Normal file
41
ofono/drivers/ril/ril_config.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* oFono - Open Source Telephony - RIL-based devices
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015-2016 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_CONFIG_H
|
||||||
|
#define RIL_CONFIG_H
|
||||||
|
|
||||||
|
#include "ril_types.h"
|
||||||
|
|
||||||
|
/* Utilities for parsing ril_subscription.conf */
|
||||||
|
|
||||||
|
#define RILCONF_SETTINGS_GROUP "Settings"
|
||||||
|
|
||||||
|
char* ril_config_get_string(GKeyFile *file, const char *group, const char *key);
|
||||||
|
gboolean ril_config_get_integer(GKeyFile *file, const char *group,
|
||||||
|
const char *key, int *value);
|
||||||
|
gboolean ril_config_get_boolean(GKeyFile *file, const char *group,
|
||||||
|
const char *key, gboolean *value);
|
||||||
|
gboolean ril_config_get_flag(GKeyFile *file, const char *group,
|
||||||
|
const char *key, int flag, int *flags);
|
||||||
|
|
||||||
|
#endif /* RIL_CONFIG_H */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local Variables:
|
||||||
|
* mode: C
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
@@ -277,6 +277,49 @@ enum ril_app_type {
|
|||||||
RIL_APPTYPE_ISIM = 5
|
RIL_APPTYPE_ISIM = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Cell info */
|
||||||
|
enum ril_cell_info_type {
|
||||||
|
RIL_CELL_INFO_TYPE_NONE = 0,
|
||||||
|
RIL_CELL_INFO_TYPE_GSM = 1,
|
||||||
|
RIL_CELL_INFO_TYPE_CDMA = 2,
|
||||||
|
RIL_CELL_INFO_TYPE_LTE = 3,
|
||||||
|
RIL_CELL_INFO_TYPE_WCDMA = 4,
|
||||||
|
RIL_CELL_INFO_TYPE_TD_SCDMA = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ril_cell_info_gsm {
|
||||||
|
int mcc; /* Mobile Country Code (0..999) */
|
||||||
|
int mnc; /* Mobile Network Code (0..999) */
|
||||||
|
int lac; /* Location Area Code (0..65535) */
|
||||||
|
int cid; /* GSM Cell Identity (0..65535) TS 27.007 */
|
||||||
|
int signalStrength; /* (0-31, 99) TS 27.007 */
|
||||||
|
int bitErrorRate; /* (0-7, 99) TS 27.007 */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ril_cell_info_wcdma {
|
||||||
|
int mcc; /* Mobile Country Code (0..999) */
|
||||||
|
int mnc; /* Mobile Network Code (0..999) */
|
||||||
|
int lac; /* Location Area Code (0..65535) */
|
||||||
|
int cid; /* UMTS Cell Identity (0..268435455) TS 25.331 */
|
||||||
|
int psc; /* Primary Scrambling Code (0..511) TS 25.331) */
|
||||||
|
int signalStrength; /* (0-31, 99) TS 27.007 */
|
||||||
|
int bitErrorRate; /* (0-7, 99) TS 27.007 */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ril_cell_info_lte {
|
||||||
|
int mcc; /* Mobile Country Code (0..999) */
|
||||||
|
int mnc; /* Mobile Network Code (0..999) */
|
||||||
|
int ci; /* Cell Identity */
|
||||||
|
int pci; /* Physical cell id (0..503) */
|
||||||
|
int tac; /* Tracking area code */
|
||||||
|
int signalStrength; /* (0-31, 99) TS 27.007 8.5 */
|
||||||
|
int rsrp; /* Reference Signal Receive Power TS 36.133 */
|
||||||
|
int rsrq; /* Reference Signal Receive Quality TS 36.133 */
|
||||||
|
int rssnr; /* Reference Signal-to-Noise Ratio TS 36.101*/
|
||||||
|
int cqi; /* Channel Quality Indicator TS 36.101 */
|
||||||
|
int timingAdvance; /* (Distance = 300m/us) TS 36.321 */
|
||||||
|
};
|
||||||
|
|
||||||
/* RIL Request Messages */
|
/* RIL Request Messages */
|
||||||
#define RIL_REQUEST_GET_SIM_STATUS 1
|
#define RIL_REQUEST_GET_SIM_STATUS 1
|
||||||
#define RIL_REQUEST_ENTER_SIM_PIN 2
|
#define RIL_REQUEST_ENTER_SIM_PIN 2
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -50,8 +50,24 @@ struct ril_data {
|
|||||||
struct ril_data_call_list *data_calls;
|
struct ril_data_call_list *data_calls;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ril_data_manager_flags {
|
||||||
|
RIL_DATA_MANAGER_3GLTE_HANDOVER = 0x01
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ril_data_allow_data_opt {
|
||||||
|
RIL_ALLOW_DATA_AUTO,
|
||||||
|
RIL_ALLOW_DATA_ON,
|
||||||
|
RIL_ALLOW_DATA_OFF
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ril_data_role {
|
||||||
|
RIL_DATA_ROLE_NONE, /* Data not allowed */
|
||||||
|
RIL_DATA_ROLE_MMS, /* Data is allowed at any speed */
|
||||||
|
RIL_DATA_ROLE_INTERNET /* Data is allowed at full speed */
|
||||||
|
};
|
||||||
|
|
||||||
struct ril_data_manager;
|
struct ril_data_manager;
|
||||||
struct ril_data_manager *ril_data_manager_new(void);
|
struct ril_data_manager *ril_data_manager_new(enum ril_data_manager_flags flg);
|
||||||
struct ril_data_manager *ril_data_manager_ref(struct ril_data_manager *dm);
|
struct ril_data_manager *ril_data_manager_ref(struct ril_data_manager *dm);
|
||||||
void ril_data_manager_unref(struct ril_data_manager *dm);
|
void ril_data_manager_unref(struct ril_data_manager *dm);
|
||||||
|
|
||||||
@@ -62,12 +78,11 @@ typedef void (*ril_data_call_setup_cb_t)(struct ril_data *data,
|
|||||||
typedef void (*ril_data_call_deactivate_cb_t)(struct ril_data *data,
|
typedef void (*ril_data_call_deactivate_cb_t)(struct ril_data *data,
|
||||||
int ril_status, void *arg);
|
int ril_status, void *arg);
|
||||||
|
|
||||||
struct ril_data *ril_data_new(struct ril_data_manager *dm,
|
struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
|
||||||
struct ril_radio *radio, struct ril_network *network,
|
struct ril_radio *radio, struct ril_network *network,
|
||||||
GRilIoChannel *io);
|
GRilIoChannel *io, enum ril_data_allow_data_opt opt);
|
||||||
struct ril_data *ril_data_ref(struct ril_data *data);
|
struct ril_data *ril_data_ref(struct ril_data *data);
|
||||||
void ril_data_unref(struct ril_data *data);
|
void ril_data_unref(struct ril_data *data);
|
||||||
void ril_data_set_name(struct ril_data *data, const char *name);
|
|
||||||
gboolean ril_data_allowed(struct ril_data *data);
|
gboolean ril_data_allowed(struct ril_data *data);
|
||||||
|
|
||||||
gulong ril_data_add_allow_changed_handler(struct ril_data *data,
|
gulong ril_data_add_allow_changed_handler(struct ril_data *data,
|
||||||
@@ -76,16 +91,16 @@ gulong ril_data_add_calls_changed_handler(struct ril_data *data,
|
|||||||
ril_data_cb_t cb, void *arg);
|
ril_data_cb_t cb, void *arg);
|
||||||
void ril_data_remove_handler(struct ril_data *data, gulong id);
|
void ril_data_remove_handler(struct ril_data *data, gulong id);
|
||||||
|
|
||||||
void ril_data_allow(struct ril_data *data, gboolean allow);
|
void ril_data_allow(struct ril_data *data, enum ril_data_role role);
|
||||||
|
|
||||||
struct ril_data_call_request;
|
struct ril_data_request;
|
||||||
struct ril_data_call_request *ril_data_call_setup(struct ril_data *data,
|
struct ril_data_request *ril_data_call_setup(struct ril_data *data,
|
||||||
const struct ofono_gprs_primary_context *ctx,
|
const struct ofono_gprs_primary_context *ctx,
|
||||||
ril_data_call_setup_cb_t cb, void *arg);
|
ril_data_call_setup_cb_t cb, void *arg);
|
||||||
struct ril_data_call_request *ril_data_call_deactivate(struct ril_data *data,
|
struct ril_data_request *ril_data_call_deactivate(struct ril_data *data,
|
||||||
int cid, ril_data_call_deactivate_cb_t cb, void *arg);
|
int cid, ril_data_call_deactivate_cb_t cb, void *arg);
|
||||||
void ril_data_call_request_detach(struct ril_data_call_request *req);
|
void ril_data_request_detach(struct ril_data_request *req);
|
||||||
void ril_data_call_request_cancel(struct ril_data_call_request *req);
|
void ril_data_request_cancel(struct ril_data_request *req);
|
||||||
|
|
||||||
void ril_data_call_free(struct ril_data_call *call);
|
void ril_data_call_free(struct ril_data_call *call);
|
||||||
struct ril_data_call *ril_data_call_dup(const struct ril_data_call *call);
|
struct ril_data_call *ril_data_call_dup(const struct ril_data_call *call);
|
||||||
|
|||||||
258
ofono/drivers/ril/ril_ecclist.c
Normal file
258
ofono/drivers/ril/ril_ecclist.c
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
/*
|
||||||
|
* oFono - Open Source Telephony - RIL-based devices
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 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_ecclist.h"
|
||||||
|
#include "ril_log.h"
|
||||||
|
|
||||||
|
#include <gutil_strv.h>
|
||||||
|
#include <gutil_inotify.h>
|
||||||
|
|
||||||
|
#include <sys/inotify.h>
|
||||||
|
|
||||||
|
typedef GObjectClass RilEccListClass;
|
||||||
|
typedef struct ril_ecclist RilEccList;
|
||||||
|
|
||||||
|
struct ril_ecclist_priv {
|
||||||
|
struct ofono_sim *sim;
|
||||||
|
GUtilInotifyWatchCallback *dir_watch;
|
||||||
|
GUtilInotifyWatchCallback *file_watch;
|
||||||
|
char *dir;
|
||||||
|
char *path;
|
||||||
|
char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ril_ecclist_signal {
|
||||||
|
SIGNAL_LIST_CHANGED,
|
||||||
|
SIGNAL_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SIGNAL_LIST_CHANGED_NAME "ril-ecclist-changed"
|
||||||
|
|
||||||
|
static guint ril_ecclist_signals[SIGNAL_COUNT] = { 0 };
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(RilEccList, ril_ecclist, G_TYPE_OBJECT)
|
||||||
|
#define RIL_ECCLIST_TYPE (ril_ecclist_get_type())
|
||||||
|
#define RIL_ECCLIST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
|
||||||
|
RIL_ECCLIST_TYPE, RilEccList))
|
||||||
|
|
||||||
|
static char **ril_ecclist_read(struct ril_ecclist *self)
|
||||||
|
{
|
||||||
|
struct ril_ecclist_priv *priv = self->priv;
|
||||||
|
char **list = NULL;
|
||||||
|
|
||||||
|
if (g_file_test(priv->path, G_FILE_TEST_EXISTS)) {
|
||||||
|
gsize len = 0;
|
||||||
|
gchar *content = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
if (g_file_get_contents(priv->path, &content, &len, &error)) {
|
||||||
|
char **ptr;
|
||||||
|
|
||||||
|
DBG("%s = %s", priv->name, content);
|
||||||
|
list = g_strsplit(content, ",", 0);
|
||||||
|
for (ptr = list; *ptr; ptr++) {
|
||||||
|
*ptr = g_strstrip(*ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
gutil_strv_sort(list, TRUE);
|
||||||
|
} else if (error) {
|
||||||
|
DBG("%s: %s", priv->path, GERRMSG(error));
|
||||||
|
g_error_free(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (content);
|
||||||
|
} else {
|
||||||
|
DBG("%s doesn't exist", priv->path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_ecclist_update(struct ril_ecclist *self)
|
||||||
|
{
|
||||||
|
struct ril_ecclist_priv *priv = self->priv;
|
||||||
|
char **list = ril_ecclist_read(self);
|
||||||
|
|
||||||
|
if (!gutil_strv_equal(self->list, list)) {
|
||||||
|
DBG("%s changed", priv->name);
|
||||||
|
g_strfreev(self->list);
|
||||||
|
self->list = list;
|
||||||
|
g_signal_emit(self, ril_ecclist_signals[SIGNAL_LIST_CHANGED], 0);
|
||||||
|
} else {
|
||||||
|
g_strfreev(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_ecclist_changed(GUtilInotifyWatch *watch, guint mask,
|
||||||
|
guint cookie, const char *name, void *user_data)
|
||||||
|
{
|
||||||
|
struct ril_ecclist *self = RIL_ECCLIST(user_data);
|
||||||
|
struct ril_ecclist_priv *priv = self->priv;
|
||||||
|
|
||||||
|
ril_ecclist_update(self);
|
||||||
|
|
||||||
|
if (mask & IN_IGNORED) {
|
||||||
|
DBG("file %s is gone", priv->path);
|
||||||
|
gutil_inotify_watch_callback_free(priv->file_watch);
|
||||||
|
priv->file_watch = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_ecclist_dir_changed(GUtilInotifyWatch *watch, guint mask,
|
||||||
|
guint cookie, const char *name, void *user_data)
|
||||||
|
{
|
||||||
|
struct ril_ecclist *self = RIL_ECCLIST(user_data);
|
||||||
|
struct ril_ecclist_priv *priv = self->priv;
|
||||||
|
|
||||||
|
DBG("0x%04x %s", mask, name);
|
||||||
|
if (!priv->file_watch && !g_strcmp0(name, priv->name)) {
|
||||||
|
priv->file_watch = gutil_inotify_watch_callback_new(priv->path,
|
||||||
|
IN_MODIFY | IN_CLOSE_WRITE,
|
||||||
|
ril_ecclist_changed, self);
|
||||||
|
if (priv->file_watch) {
|
||||||
|
DBG("watching %s", priv->path);
|
||||||
|
ril_ecclist_update(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask & IN_IGNORED) {
|
||||||
|
DBG("%s is gone", priv->dir);
|
||||||
|
gutil_inotify_watch_callback_free(priv->dir_watch);
|
||||||
|
priv->dir_watch = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gulong ril_ecclist_add_list_changed_handler(struct ril_ecclist *self,
|
||||||
|
ril_ecclist_cb_t cb, void *arg)
|
||||||
|
{
|
||||||
|
return (G_LIKELY(self) && G_LIKELY(cb)) ? g_signal_connect(self,
|
||||||
|
SIGNAL_LIST_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ril_ecclist_remove_handler(struct ril_ecclist *self, gulong id)
|
||||||
|
{
|
||||||
|
if (G_LIKELY(self) && G_LIKELY(id)) {
|
||||||
|
g_signal_handler_disconnect(self, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ril_ecclist *ril_ecclist_new(const char *path)
|
||||||
|
{
|
||||||
|
if (path) {
|
||||||
|
struct ril_ecclist *self = g_object_new(RIL_ECCLIST_TYPE, 0);
|
||||||
|
struct ril_ecclist_priv *priv = self->priv;
|
||||||
|
|
||||||
|
DBG("%s", path);
|
||||||
|
priv->path = g_strdup(path);
|
||||||
|
priv->name = g_path_get_basename(path);
|
||||||
|
priv->dir = g_path_get_dirname(path);
|
||||||
|
priv->dir_watch = gutil_inotify_watch_callback_new(priv->dir,
|
||||||
|
IN_MODIFY|IN_MOVED_FROM|IN_MOVED_TO|IN_DELETE|
|
||||||
|
IN_CREATE|IN_DELETE_SELF|IN_CLOSE_WRITE,
|
||||||
|
ril_ecclist_dir_changed, self);
|
||||||
|
if (priv->dir_watch) {
|
||||||
|
DBG("watching %s", priv->dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
self->list = ril_ecclist_read(self);
|
||||||
|
priv->file_watch = gutil_inotify_watch_callback_new(priv->path,
|
||||||
|
IN_MODIFY | IN_CLOSE_WRITE,
|
||||||
|
ril_ecclist_changed, self);
|
||||||
|
if (priv->file_watch) {
|
||||||
|
DBG("watching %s", priv->path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ril_ecclist *ril_ecclist_ref(struct ril_ecclist *self)
|
||||||
|
{
|
||||||
|
if (G_LIKELY(self)) {
|
||||||
|
g_object_ref(RIL_ECCLIST(self));
|
||||||
|
return self;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ril_ecclist_unref(struct ril_ecclist *self)
|
||||||
|
{
|
||||||
|
if (G_LIKELY(self)) {
|
||||||
|
g_object_unref(RIL_ECCLIST(self));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_ecclist_init(struct ril_ecclist *self)
|
||||||
|
{
|
||||||
|
self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self, RIL_ECCLIST_TYPE,
|
||||||
|
struct ril_ecclist_priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_ecclist_dispose(GObject *object)
|
||||||
|
{
|
||||||
|
struct ril_ecclist *self = RIL_ECCLIST(object);
|
||||||
|
struct ril_ecclist_priv *priv = self->priv;
|
||||||
|
|
||||||
|
if (priv->dir_watch) {
|
||||||
|
gutil_inotify_watch_callback_free(priv->dir_watch);
|
||||||
|
priv->dir_watch = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->file_watch) {
|
||||||
|
gutil_inotify_watch_callback_free(priv->file_watch);
|
||||||
|
priv->file_watch = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
G_OBJECT_CLASS(ril_ecclist_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_ecclist_finalize(GObject *object)
|
||||||
|
{
|
||||||
|
struct ril_ecclist *self = RIL_ECCLIST(object);
|
||||||
|
struct ril_ecclist_priv *priv = self->priv;
|
||||||
|
|
||||||
|
GASSERT(!priv->dir_watch);
|
||||||
|
GASSERT(!priv->file_watch);
|
||||||
|
g_free(priv->dir);
|
||||||
|
g_free(priv->path);
|
||||||
|
g_free(priv->name);
|
||||||
|
g_strfreev(self->list);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS(ril_ecclist_parent_class)->finalize(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_ecclist_class_init(RilEccListClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
||||||
|
|
||||||
|
object_class->dispose = ril_ecclist_dispose;
|
||||||
|
object_class->finalize = ril_ecclist_finalize;
|
||||||
|
g_type_class_add_private(klass, sizeof(struct ril_ecclist_priv));
|
||||||
|
ril_ecclist_signals[SIGNAL_LIST_CHANGED] =
|
||||||
|
g_signal_new(SIGNAL_LIST_CHANGED_NAME,
|
||||||
|
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST,
|
||||||
|
0, NULL, NULL, NULL, G_TYPE_NONE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local Variables:
|
||||||
|
* mode: C
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
46
ofono/drivers/ril/ril_ecclist.h
Normal file
46
ofono/drivers/ril/ril_ecclist.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* oFono - Open Source Telephony - RIL-based devices
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 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_ECCLIST_H
|
||||||
|
#define RIL_ECCLIST_H
|
||||||
|
|
||||||
|
#include "ril_types.h"
|
||||||
|
|
||||||
|
struct ril_ecclist_priv;
|
||||||
|
|
||||||
|
struct ril_ecclist {
|
||||||
|
GObject object;
|
||||||
|
struct ril_ecclist_priv *priv;
|
||||||
|
char **list;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*ril_ecclist_cb_t)(struct ril_ecclist *ecc, void *arg);
|
||||||
|
|
||||||
|
struct ril_ecclist *ril_ecclist_new(const char *path);
|
||||||
|
struct ril_ecclist *ril_ecclist_ref(struct ril_ecclist *ecc);
|
||||||
|
void ril_ecclist_unref(struct ril_ecclist *ecc);
|
||||||
|
gulong ril_ecclist_add_list_changed_handler(struct ril_ecclist *ecc,
|
||||||
|
ril_ecclist_cb_t cb, void *arg);
|
||||||
|
void ril_ecclist_remove_handler(struct ril_ecclist *ecc, gulong id);
|
||||||
|
|
||||||
|
#endif /* RIL_ECCLIST_H */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local Variables:
|
||||||
|
* mode: C
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -17,20 +17,21 @@
|
|||||||
#include "ril_network.h"
|
#include "ril_network.h"
|
||||||
#include "ril_data.h"
|
#include "ril_data.h"
|
||||||
#include "ril_util.h"
|
#include "ril_util.h"
|
||||||
|
#include "ril_mtu.h"
|
||||||
#include "ril_log.h"
|
#include "ril_log.h"
|
||||||
|
|
||||||
#include <gutil_strv.h>
|
#include <gutil_strv.h>
|
||||||
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#define CTX_ID_NONE ((unsigned int)(-1))
|
#define CTX_ID_NONE ((unsigned int)(-1))
|
||||||
|
|
||||||
|
#define MAX_MTU 1280
|
||||||
|
|
||||||
struct ril_gprs_context_call {
|
struct ril_gprs_context_call {
|
||||||
struct ril_data_call_request *req;
|
struct ril_data_request *req;
|
||||||
ofono_gprs_context_cb_t cb;
|
ofono_gprs_context_cb_t cb;
|
||||||
gpointer data;
|
gpointer data;
|
||||||
};
|
};
|
||||||
@@ -42,6 +43,7 @@ struct ril_gprs_context {
|
|||||||
struct ril_data *data;
|
struct ril_data *data;
|
||||||
guint active_ctx_cid;
|
guint active_ctx_cid;
|
||||||
gulong calls_changed_event_id;
|
gulong calls_changed_event_id;
|
||||||
|
struct ril_mtu_watch *mtu_watch;
|
||||||
struct ril_data_call *active_call;
|
struct ril_data_call *active_call;
|
||||||
struct ril_gprs_context_call activate;
|
struct ril_gprs_context_call activate;
|
||||||
struct ril_gprs_context_call deactivate;
|
struct ril_gprs_context_call deactivate;
|
||||||
@@ -103,30 +105,35 @@ static void ril_gprs_context_set_ipv6(struct ofono_gprs_context *gc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_gprs_context_call_done(struct ril_gprs_context_call *call,
|
static void ril_gprs_context_free_active_call(struct ril_gprs_context *gcd)
|
||||||
gboolean ok)
|
|
||||||
{
|
{
|
||||||
ofono_gprs_context_cb_t cb = call->cb;
|
if (gcd->active_call) {
|
||||||
gpointer data = call->data;
|
ril_data_call_free(gcd->active_call);
|
||||||
|
gcd->active_call = NULL;
|
||||||
ril_data_call_request_cancel(call->req);
|
}
|
||||||
|
if (gcd->calls_changed_event_id) {
|
||||||
call->req = NULL;
|
ril_data_remove_handler(gcd->data, gcd->calls_changed_event_id);
|
||||||
call->cb = NULL;
|
gcd->calls_changed_event_id = 0;
|
||||||
call->data = NULL;
|
}
|
||||||
|
if (gcd->mtu_watch) {
|
||||||
if (cb) {
|
ril_mtu_watch_free(gcd->mtu_watch);
|
||||||
struct ofono_error error;
|
gcd->mtu_watch = NULL;
|
||||||
cb(ok ? ril_error_ok(&error) : ril_error_failure(&error), data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_gprs_context_free_active_call(struct ril_gprs_context *gcd)
|
static void ril_gprs_context_set_active_call(struct ril_gprs_context *gcd,
|
||||||
|
const struct ril_data_call *call)
|
||||||
{
|
{
|
||||||
ril_data_call_free(gcd->active_call);
|
if (call) {
|
||||||
gcd->active_call = NULL;
|
ril_data_call_free(gcd->active_call);
|
||||||
ril_data_remove_handler(gcd->data, gcd->calls_changed_event_id);
|
gcd->active_call = ril_data_call_dup(call);
|
||||||
gcd->calls_changed_event_id = 0;
|
if (!gcd->mtu_watch) {
|
||||||
|
gcd->mtu_watch = ril_mtu_watch_new(MAX_MTU);
|
||||||
|
}
|
||||||
|
ril_mtu_watch_set_ifname(gcd->mtu_watch, call->ifname);
|
||||||
|
} else {
|
||||||
|
ril_gprs_context_free_active_call(gcd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_gprs_context_set_disconnected(struct ril_gprs_context *gcd)
|
static void ril_gprs_context_set_disconnected(struct ril_gprs_context *gcd)
|
||||||
@@ -134,7 +141,29 @@ static void ril_gprs_context_set_disconnected(struct ril_gprs_context *gcd)
|
|||||||
if (gcd->active_call) {
|
if (gcd->active_call) {
|
||||||
ril_gprs_context_free_active_call(gcd);
|
ril_gprs_context_free_active_call(gcd);
|
||||||
if (gcd->deactivate.req) {
|
if (gcd->deactivate.req) {
|
||||||
ril_gprs_context_call_done(&gcd->deactivate, TRUE);
|
struct ril_gprs_context_call deact = gcd->deactivate;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Complete the deactivate request. We need to
|
||||||
|
* clear gcd->deactivate first because cancelling
|
||||||
|
* the deactivation request will probably result
|
||||||
|
* in ril_gprs_context_deactivate_primary_cb() being
|
||||||
|
* invoked with GRILIO_CANCELLED status. And we don't
|
||||||
|
* want to fail the disconnect request because this
|
||||||
|
* is a success (we wanted to disconnect the data
|
||||||
|
* call and it's gone).
|
||||||
|
*
|
||||||
|
* Additionally, we need to make sure that we don't
|
||||||
|
* complete the same request twice - that would crash
|
||||||
|
* the core.
|
||||||
|
*/
|
||||||
|
memset(&gcd->deactivate, 0, sizeof(gcd->deactivate));
|
||||||
|
ril_data_request_cancel(deact.req);
|
||||||
|
if (deact.cb) {
|
||||||
|
struct ofono_error error;
|
||||||
|
ofono_info("Deactivated data call");
|
||||||
|
deact.cb(ril_error_ok(&error), deact.data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (gcd->active_ctx_cid != CTX_ID_NONE) {
|
if (gcd->active_ctx_cid != CTX_ID_NONE) {
|
||||||
@@ -278,8 +307,13 @@ static void ril_gprs_context_call_list_changed(struct ril_data *data, void *arg)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Store the updated call data */
|
/*
|
||||||
gcd->active_call = ril_data_call_dup(call);
|
* prev_call points to the previous active call, and it will
|
||||||
|
* be deallocated at the end of the this function. Clear the
|
||||||
|
* gcd->active_call pointer so that we don't deallocate it twice.
|
||||||
|
*/
|
||||||
|
gcd->active_call = NULL;
|
||||||
|
ril_gprs_context_set_active_call(gcd, call);
|
||||||
|
|
||||||
if (call->status != PDP_FAIL_NONE) {
|
if (call->status != PDP_FAIL_NONE) {
|
||||||
ofono_info("data call status: %d", call->status);
|
ofono_info("data call status: %d", call->status);
|
||||||
@@ -400,8 +434,6 @@ static void ril_gprs_context_activate_primary_cb(struct ril_data *data,
|
|||||||
ofono_gprs_context_cb_t cb;
|
ofono_gprs_context_cb_t cb;
|
||||||
gpointer cb_data;
|
gpointer cb_data;
|
||||||
|
|
||||||
ofono_info("setting up data call");
|
|
||||||
|
|
||||||
ril_error_init_failure(&error);
|
ril_error_init_failure(&error);
|
||||||
if (ril_status != RIL_E_SUCCESS) {
|
if (ril_status != RIL_E_SUCCESS) {
|
||||||
ofono_error("GPRS context: Reply failure: %s",
|
ofono_error("GPRS context: Reply failure: %s",
|
||||||
@@ -422,6 +454,8 @@ static void ril_gprs_context_activate_primary_cb(struct ril_data *data,
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ofono_info("setting up data call");
|
||||||
|
|
||||||
/* Check the ip address */
|
/* Check the ip address */
|
||||||
ril_gprs_split_ip_by_protocol(call->addresses, &split_ip_addr,
|
ril_gprs_split_ip_by_protocol(call->addresses, &split_ip_addr,
|
||||||
&split_ipv6_addr);
|
&split_ipv6_addr);
|
||||||
@@ -431,8 +465,7 @@ static void ril_gprs_context_activate_primary_cb(struct ril_data *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ril_error_init_ok(&error);
|
ril_error_init_ok(&error);
|
||||||
ril_data_call_free(gcd->active_call);
|
ril_gprs_context_set_active_call(gcd, call);
|
||||||
gcd->active_call = ril_data_call_dup(call);
|
|
||||||
|
|
||||||
GASSERT(!gcd->calls_changed_event_id);
|
GASSERT(!gcd->calls_changed_event_id);
|
||||||
ril_data_remove_handler(gcd->data, gcd->calls_changed_event_id);
|
ril_data_remove_handler(gcd->data, gcd->calls_changed_event_id);
|
||||||
@@ -520,32 +553,37 @@ static void ril_gprs_context_deactivate_primary_cb(struct ril_data *data,
|
|||||||
int ril_status, void *user_data)
|
int ril_status, void *user_data)
|
||||||
{
|
{
|
||||||
struct ril_gprs_context *gcd = user_data;
|
struct ril_gprs_context *gcd = user_data;
|
||||||
struct ofono_error error;
|
|
||||||
ofono_gprs_context_cb_t cb;
|
|
||||||
gpointer cb_data;
|
|
||||||
|
|
||||||
if (ril_status == RIL_E_SUCCESS) {
|
/*
|
||||||
GASSERT(gcd->active_call);
|
* Data call list may change before the completion of the deactivate
|
||||||
ril_error_init_ok(&error);
|
* request, in that case ril_gprs_context_set_disconnected will be
|
||||||
ofono_info("Deactivated data call");
|
* invoked and gcd->deactivate.req will be NULL.
|
||||||
} else {
|
*/
|
||||||
ril_error_init_failure(&error);
|
if (gcd->deactivate.req) {
|
||||||
ofono_error("Deactivate failure: %s",
|
struct ofono_error error;
|
||||||
|
ofono_gprs_context_cb_t cb = gcd->deactivate.cb;
|
||||||
|
gpointer cb_data = gcd->deactivate.data;
|
||||||
|
|
||||||
|
if (ril_status == RIL_E_SUCCESS) {
|
||||||
|
GASSERT(gcd->active_call);
|
||||||
|
ril_error_init_ok(&error);
|
||||||
|
ofono_info("Deactivated data call");
|
||||||
|
} else {
|
||||||
|
ril_error_init_failure(&error);
|
||||||
|
ofono_error("Deactivate failure: %s",
|
||||||
ril_error_to_string(ril_status));
|
ril_error_to_string(ril_status));
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&gcd->deactivate, 0, sizeof(gcd->deactivate));
|
||||||
|
if (cb) {
|
||||||
|
ril_gprs_context_free_active_call(gcd);
|
||||||
|
cb(&error, cb_data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cb = gcd->deactivate.cb;
|
/* Make sure we are in the disconnected state */
|
||||||
cb_data = gcd->deactivate.data;
|
ril_gprs_context_set_disconnected(gcd);
|
||||||
GASSERT(gcd->deactivate.req);
|
|
||||||
memset(&gcd->deactivate, 0, sizeof(gcd->deactivate));
|
|
||||||
|
|
||||||
if (cb) {
|
|
||||||
ril_gprs_context_free_active_call(gcd);
|
|
||||||
cb(&error, cb_data);
|
|
||||||
} else {
|
|
||||||
/* Have to tell ofono that the call has been disconnected */
|
|
||||||
ril_gprs_context_set_disconnected(gcd);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_gprs_context_deactivate_primary(struct ofono_gprs_context *gc,
|
static void ril_gprs_context_deactivate_primary(struct ofono_gprs_context *gc,
|
||||||
@@ -598,11 +636,19 @@ static void ril_gprs_context_remove(struct ofono_gprs_context *gc)
|
|||||||
DBG("");
|
DBG("");
|
||||||
ofono_gprs_context_set_data(gc, NULL);
|
ofono_gprs_context_set_data(gc, NULL);
|
||||||
|
|
||||||
ril_data_call_request_cancel(gcd->activate.req);
|
if (gcd->activate.req) {
|
||||||
|
/*
|
||||||
|
* The core has already completed its pending D-Bus
|
||||||
|
* request, invoking the completion callback will
|
||||||
|
* cause libdbus to panic.
|
||||||
|
*/
|
||||||
|
ril_data_request_detach(gcd->activate.req);
|
||||||
|
ril_data_request_cancel(gcd->activate.req);
|
||||||
|
}
|
||||||
|
|
||||||
if (gcd->deactivate.req) {
|
if (gcd->deactivate.req) {
|
||||||
/* Let it complete but we won't be around to be notified. */
|
/* Let it complete but we won't be around to be notified. */
|
||||||
ril_data_call_request_detach(gcd->deactivate.req);
|
ril_data_request_detach(gcd->deactivate.req);
|
||||||
} else if (gcd->active_call) {
|
} else if (gcd->active_call) {
|
||||||
ril_data_call_deactivate(gcd->data, gcd->active_call->cid,
|
ril_data_call_deactivate(gcd->data, gcd->active_call->cid,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
@@ -612,6 +658,7 @@ static void ril_gprs_context_remove(struct ofono_gprs_context *gc)
|
|||||||
ril_data_unref(gcd->data);
|
ril_data_unref(gcd->data);
|
||||||
ril_network_unref(gcd->network);
|
ril_network_unref(gcd->network);
|
||||||
ril_data_call_free(gcd->active_call);
|
ril_data_call_free(gcd->active_call);
|
||||||
|
ril_mtu_watch_free(gcd->mtu_watch);
|
||||||
g_free(gcd);
|
g_free(gcd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* oFono - Open Source Telephony - RIL-based devices
|
* oFono - Open Source Telephony - RIL-based devices
|
||||||
*
|
*
|
||||||
* Copyright (C) 2015 Jolla Ltd.
|
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
@@ -14,118 +14,251 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ril_mce.h"
|
#include "ril_mce.h"
|
||||||
#include "ril_constants.h"
|
#include "ril_log.h"
|
||||||
|
|
||||||
#include <grilio_channel.h>
|
|
||||||
#include <grilio_request.h>
|
|
||||||
|
|
||||||
#include <ofono/log.h>
|
|
||||||
#include <ofono/dbus.h>
|
#include <ofono/dbus.h>
|
||||||
|
|
||||||
#include <gdbus.h>
|
#include <gdbus.h>
|
||||||
|
|
||||||
|
/* <mce/dbus-names.h> */
|
||||||
#define MCE_SERVICE "com.nokia.mce"
|
#define MCE_SERVICE "com.nokia.mce"
|
||||||
#define MCE_SIGNAL_IF "com.nokia.mce.signal"
|
#define MCE_SIGNAL_IF "com.nokia.mce.signal"
|
||||||
|
#define MCE_REQUEST_IF "com.nokia.mce.request"
|
||||||
|
#define MCE_REQUEST_PATH "/com/nokia/mce/request"
|
||||||
|
#define MCE_DISPLAY_STATUS_GET "get_display_status"
|
||||||
#define MCE_DISPLAY_SIG "display_status_ind"
|
#define MCE_DISPLAY_SIG "display_status_ind"
|
||||||
|
#define MCE_DISPLAY_DIM_STRING "dimmed"
|
||||||
|
#define MCE_DISPLAY_ON_STRING "on"
|
||||||
#define MCE_DISPLAY_OFF_STRING "off"
|
#define MCE_DISPLAY_OFF_STRING "off"
|
||||||
|
|
||||||
struct ril_mce {
|
typedef GObjectClass RilMceClass;
|
||||||
|
typedef struct ril_mce RilMce;
|
||||||
|
|
||||||
|
struct ril_mce_priv {
|
||||||
GRilIoChannel *io;
|
GRilIoChannel *io;
|
||||||
DBusConnection *conn;
|
DBusConnection *conn;
|
||||||
int screen_state;
|
DBusPendingCall *req;
|
||||||
guint daemon_watch;
|
guint daemon_watch;
|
||||||
guint signal_watch;
|
guint signal_watch;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void ril_mce_send_screen_state(struct ril_mce *mce, gboolean on)
|
enum ril_mce_signal {
|
||||||
|
SIGNAL_DISPLAY_STATE_CHANGED,
|
||||||
|
SIGNAL_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SIGNAL_DISPLAY_STATE_CHANGED_NAME "ril-mce-display-state-changed"
|
||||||
|
|
||||||
|
static guint ril_mce_signals[SIGNAL_COUNT] = { 0 };
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(RilMce, ril_mce, G_TYPE_OBJECT)
|
||||||
|
#define RIL_MCE_TYPE (ril_mce_get_type())
|
||||||
|
#define RIL_MCE(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj,RIL_MCE_TYPE,RilMce))
|
||||||
|
|
||||||
|
static const char *ril_mce_display_state_string(enum ril_mce_display_state ds)
|
||||||
{
|
{
|
||||||
GRilIoRequest *req = grilio_request_sized_new(8);
|
switch (ds) {
|
||||||
|
case RIL_MCE_DISPLAY_OFF:
|
||||||
|
return MCE_DISPLAY_OFF_STRING;
|
||||||
|
case RIL_MCE_DISPLAY_DIM:
|
||||||
|
return MCE_DISPLAY_DIM_STRING;
|
||||||
|
case RIL_MCE_DISPLAY_ON:
|
||||||
|
return MCE_DISPLAY_ON_STRING;
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
grilio_request_append_int32(req, 1); /* Number of params */
|
static enum ril_mce_display_state ril_mce_parse_display_state(DBusMessage *msg)
|
||||||
grilio_request_append_int32(req, on); /* screen on/off */
|
{
|
||||||
|
DBusMessageIter it;
|
||||||
|
|
||||||
grilio_channel_send_request(mce->io, req, RIL_REQUEST_SCREEN_STATE);
|
if (dbus_message_iter_init(msg, &it) &&
|
||||||
grilio_request_unref(req);
|
dbus_message_iter_get_arg_type(&it) == DBUS_TYPE_STRING) {
|
||||||
|
const char *value = NULL;
|
||||||
|
|
||||||
|
dbus_message_iter_get_basic(&it, &value);
|
||||||
|
if (!g_strcmp0(value, MCE_DISPLAY_OFF_STRING)) {
|
||||||
|
return RIL_MCE_DISPLAY_OFF;
|
||||||
|
} else if (!g_strcmp0(value, MCE_DISPLAY_DIM_STRING)) {
|
||||||
|
return RIL_MCE_DISPLAY_DIM;
|
||||||
|
} else {
|
||||||
|
GASSERT(!g_strcmp0(value, MCE_DISPLAY_ON_STRING));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RIL_MCE_DISPLAY_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_mce_update_display_state(struct ril_mce *self,
|
||||||
|
enum ril_mce_display_state state)
|
||||||
|
{
|
||||||
|
if (self->display_state != state) {
|
||||||
|
self->display_state = state;
|
||||||
|
g_signal_emit(self, ril_mce_signals[
|
||||||
|
SIGNAL_DISPLAY_STATE_CHANGED], 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean ril_mce_display_changed(DBusConnection *conn,
|
static gboolean ril_mce_display_changed(DBusConnection *conn,
|
||||||
DBusMessage *message, void *user_data)
|
DBusMessage *msg, void *user_data)
|
||||||
{
|
{
|
||||||
DBusMessageIter iter;
|
enum ril_mce_display_state state = ril_mce_parse_display_state(msg);
|
||||||
|
|
||||||
if (dbus_message_iter_init(message, &iter) &&
|
|
||||||
dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) {
|
|
||||||
struct ril_mce *mce = user_data;
|
|
||||||
const char *value = NULL;
|
|
||||||
int state;
|
|
||||||
|
|
||||||
dbus_message_iter_get_basic(&iter, &value);
|
|
||||||
DBG(" %s", value);
|
|
||||||
|
|
||||||
/* It is on if it's not off */
|
|
||||||
state = (g_strcmp0(value, MCE_DISPLAY_OFF_STRING) != 0);
|
|
||||||
if (mce->screen_state != state) {
|
|
||||||
mce->screen_state = state;
|
|
||||||
ril_mce_send_screen_state(mce, state);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DBG("");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
DBG("%s", ril_mce_display_state_string(state));
|
||||||
|
ril_mce_update_display_state(RIL_MCE(user_data), state);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ril_mce_display_status_reply(DBusPendingCall *call, void *user_data)
|
||||||
|
{
|
||||||
|
struct ril_mce *self = RIL_MCE(user_data);
|
||||||
|
struct ril_mce_priv *priv = self->priv;
|
||||||
|
DBusMessage *reply = dbus_pending_call_steal_reply(call);
|
||||||
|
enum ril_mce_display_state state = ril_mce_parse_display_state(reply);
|
||||||
|
|
||||||
|
GASSERT(priv->req);
|
||||||
|
dbus_message_unref(reply);
|
||||||
|
dbus_pending_call_unref(priv->req);
|
||||||
|
priv->req = NULL;
|
||||||
|
|
||||||
|
DBG("%s", ril_mce_display_state_string(state));
|
||||||
|
ril_mce_update_display_state(self, state);
|
||||||
|
}
|
||||||
|
|
||||||
static void ril_mce_connect(DBusConnection *conn, void *user_data)
|
static void ril_mce_connect(DBusConnection *conn, void *user_data)
|
||||||
{
|
{
|
||||||
struct ril_mce *mce = user_data;
|
struct ril_mce *self = RIL_MCE(user_data);
|
||||||
|
struct ril_mce_priv *priv = self->priv;
|
||||||
|
|
||||||
DBG("");
|
DBG("");
|
||||||
if (!mce->signal_watch) {
|
if (!priv->req) {
|
||||||
mce->signal_watch = g_dbus_add_signal_watch(conn,
|
DBusMessage *msg = dbus_message_new_method_call(MCE_SERVICE,
|
||||||
|
MCE_REQUEST_PATH, MCE_REQUEST_IF,
|
||||||
|
MCE_DISPLAY_STATUS_GET);
|
||||||
|
if (g_dbus_send_message_with_reply(conn, msg, &priv->req, -1)) {
|
||||||
|
dbus_pending_call_set_notify(priv->req,
|
||||||
|
ril_mce_display_status_reply,
|
||||||
|
self, NULL);
|
||||||
|
dbus_message_unref(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!priv->signal_watch) {
|
||||||
|
priv->signal_watch = g_dbus_add_signal_watch(conn,
|
||||||
MCE_SERVICE, NULL, MCE_SIGNAL_IF, MCE_DISPLAY_SIG,
|
MCE_SERVICE, NULL, MCE_SIGNAL_IF, MCE_DISPLAY_SIG,
|
||||||
ril_mce_display_changed, mce, NULL);
|
ril_mce_display_changed, self, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_mce_disconnect(DBusConnection *conn, void *user_data)
|
static void ril_mce_disconnect(DBusConnection *conn, void *user_data)
|
||||||
{
|
{
|
||||||
struct ril_mce *mce = user_data;
|
struct ril_mce *self = user_data;
|
||||||
|
struct ril_mce_priv *priv = self->priv;
|
||||||
|
|
||||||
DBG("");
|
DBG("");
|
||||||
if (mce->signal_watch) {
|
if (priv->signal_watch) {
|
||||||
g_dbus_remove_watch(conn, mce->signal_watch);
|
g_dbus_remove_watch(conn, priv->signal_watch);
|
||||||
mce->signal_watch = 0;
|
priv->signal_watch = 0;
|
||||||
|
}
|
||||||
|
if (priv->req) {
|
||||||
|
dbus_pending_call_cancel(priv->req);
|
||||||
|
dbus_pending_call_unref(priv->req);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ril_mce *ril_mce_new(GRilIoChannel *io)
|
struct ril_mce *ril_mce_new()
|
||||||
{
|
{
|
||||||
struct ril_mce *mce = g_new0(struct ril_mce, 1);
|
struct ril_mce *self = g_object_new(RIL_MCE_TYPE, NULL);
|
||||||
|
struct ril_mce_priv *priv = self->priv;
|
||||||
|
|
||||||
mce->conn = dbus_connection_ref(ofono_dbus_get_connection());
|
DBG("");
|
||||||
mce->io = grilio_channel_ref(io);
|
priv->daemon_watch = g_dbus_add_service_watch(priv->conn, MCE_SERVICE,
|
||||||
mce->screen_state = -1;
|
ril_mce_connect, ril_mce_disconnect, self, NULL);
|
||||||
mce->daemon_watch = g_dbus_add_service_watch(mce->conn, MCE_SERVICE,
|
return self;
|
||||||
ril_mce_connect, ril_mce_disconnect, mce, NULL);
|
|
||||||
|
|
||||||
return mce;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ril_mce_free(struct ril_mce *mce)
|
struct ril_mce *ril_mce_ref(struct ril_mce *self)
|
||||||
{
|
{
|
||||||
if (mce) {
|
if (G_LIKELY(self)) {
|
||||||
if (mce->signal_watch) {
|
g_object_ref(RIL_MCE(self));
|
||||||
g_dbus_remove_watch(mce->conn, mce->signal_watch);
|
return self;
|
||||||
}
|
} else {
|
||||||
if (mce->daemon_watch) {
|
return NULL;
|
||||||
g_dbus_remove_watch(mce->conn, mce->daemon_watch);
|
|
||||||
}
|
|
||||||
dbus_connection_unref(mce->conn);
|
|
||||||
grilio_channel_unref(mce->io);
|
|
||||||
g_free(mce);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ril_mce_unref(struct ril_mce *self)
|
||||||
|
{
|
||||||
|
if (G_LIKELY(self)) {
|
||||||
|
g_object_unref(RIL_MCE(self));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gulong ril_mce_add_display_state_changed_handler(struct ril_mce *self,
|
||||||
|
ril_mce_cb_t cb, void *arg)
|
||||||
|
{
|
||||||
|
return (G_LIKELY(self) && G_LIKELY(cb)) ? g_signal_connect(self,
|
||||||
|
SIGNAL_DISPLAY_STATE_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ril_mce_remove_handler(struct ril_mce *self, gulong id)
|
||||||
|
{
|
||||||
|
if (G_LIKELY(self) && G_LIKELY(id)) {
|
||||||
|
g_signal_handler_disconnect(self, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_mce_init(struct ril_mce *self)
|
||||||
|
{
|
||||||
|
struct ril_mce_priv *priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
|
||||||
|
RIL_MCE_TYPE, struct ril_mce_priv);
|
||||||
|
|
||||||
|
priv->conn = dbus_connection_ref(ofono_dbus_get_connection());
|
||||||
|
self->priv = priv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_mce_dispose(GObject *object)
|
||||||
|
{
|
||||||
|
struct ril_mce *self = RIL_MCE(object);
|
||||||
|
struct ril_mce_priv *priv = self->priv;
|
||||||
|
|
||||||
|
if (priv->signal_watch) {
|
||||||
|
g_dbus_remove_watch(priv->conn, priv->signal_watch);
|
||||||
|
priv->signal_watch = 0;
|
||||||
|
}
|
||||||
|
if (priv->daemon_watch) {
|
||||||
|
g_dbus_remove_watch(priv->conn, priv->daemon_watch);
|
||||||
|
priv->daemon_watch = 0;
|
||||||
|
}
|
||||||
|
if (priv->req) {
|
||||||
|
dbus_pending_call_cancel(priv->req);
|
||||||
|
dbus_pending_call_unref(priv->req);
|
||||||
|
}
|
||||||
|
G_OBJECT_CLASS(ril_mce_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_mce_finalize(GObject *object)
|
||||||
|
{
|
||||||
|
struct ril_mce *self = RIL_MCE(object);
|
||||||
|
struct ril_mce_priv *priv = self->priv;
|
||||||
|
|
||||||
|
dbus_connection_unref(priv->conn);
|
||||||
|
G_OBJECT_CLASS(ril_mce_parent_class)->finalize(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_mce_class_init(RilMceClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
||||||
|
|
||||||
|
object_class->dispose = ril_mce_dispose;
|
||||||
|
object_class->finalize = ril_mce_finalize;
|
||||||
|
g_type_class_add_private(klass, sizeof(struct ril_mce_priv));
|
||||||
|
ril_mce_signals[SIGNAL_DISPLAY_STATE_CHANGED] =
|
||||||
|
g_signal_new(SIGNAL_DISPLAY_STATE_CHANGED_NAME,
|
||||||
|
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST,
|
||||||
|
0, NULL, NULL, NULL, G_TYPE_NONE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local Variables:
|
* Local Variables:
|
||||||
* mode: C
|
* mode: C
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* oFono - Open Source Telephony - RIL-based devices
|
* oFono - Open Source Telephony - RIL-based devices
|
||||||
*
|
*
|
||||||
* Copyright (C) 2015 Jolla Ltd.
|
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
@@ -18,8 +18,27 @@
|
|||||||
|
|
||||||
#include "ril_types.h"
|
#include "ril_types.h"
|
||||||
|
|
||||||
struct ril_mce *ril_mce_new(GRilIoChannel *io);
|
enum ril_mce_display_state {
|
||||||
void ril_mce_free(struct ril_mce *mce);
|
RIL_MCE_DISPLAY_OFF,
|
||||||
|
RIL_MCE_DISPLAY_DIM,
|
||||||
|
RIL_MCE_DISPLAY_ON
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ril_mce_priv;
|
||||||
|
struct ril_mce {
|
||||||
|
GObject object;
|
||||||
|
struct ril_mce_priv *priv;
|
||||||
|
enum ril_mce_display_state display_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ril_mce *ril_mce_new(void);
|
||||||
|
struct ril_mce *ril_mce_ref(struct ril_mce *mce);
|
||||||
|
void ril_mce_unref(struct ril_mce *mce);
|
||||||
|
|
||||||
|
typedef void (*ril_mce_cb_t)(struct ril_mce *mce, void *arg);
|
||||||
|
gulong ril_mce_add_display_state_changed_handler(struct ril_mce *mce,
|
||||||
|
ril_mce_cb_t cb, void *arg);
|
||||||
|
void ril_mce_remove_handler(struct ril_mce *mce, gulong id);
|
||||||
|
|
||||||
#endif /* RIL_MCE_H */
|
#endif /* RIL_MCE_H */
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "ril_network.h"
|
#include "ril_network.h"
|
||||||
#include "ril_radio.h"
|
#include "ril_radio.h"
|
||||||
#include "ril_sim_card.h"
|
#include "ril_sim_card.h"
|
||||||
|
#include "ril_sim_settings.h"
|
||||||
#include "ril_data.h"
|
#include "ril_data.h"
|
||||||
#include "ril_util.h"
|
#include "ril_util.h"
|
||||||
#include "ril_log.h"
|
#include "ril_log.h"
|
||||||
@@ -50,10 +51,9 @@ struct ril_modem_data {
|
|||||||
struct ril_modem modem;
|
struct ril_modem modem;
|
||||||
GRilIoQueue *q;
|
GRilIoQueue *q;
|
||||||
struct ofono_radio_settings *radio_settings;
|
struct ofono_radio_settings *radio_settings;
|
||||||
char *default_name;
|
|
||||||
char *imei;
|
char *imei;
|
||||||
|
char *ecclist_file;
|
||||||
gboolean pre_sim_done;
|
gboolean pre_sim_done;
|
||||||
gboolean devinfo_created;
|
|
||||||
gboolean allow_data;
|
gboolean allow_data;
|
||||||
|
|
||||||
guint online_check_id;
|
guint online_check_id;
|
||||||
@@ -139,27 +139,6 @@ void ril_modem_set_online_cb(struct ril_modem *modem, ril_modem_online_cb_t cb,
|
|||||||
md->online_cb_data = data;
|
md->online_cb_data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_modem_check_devinfo(struct ril_modem_data *md)
|
|
||||||
{
|
|
||||||
/* devinfo driver assumes that IMEI is known */
|
|
||||||
if (md->imei && md->pre_sim_done && !md->devinfo_created &&
|
|
||||||
md->modem.ofono) {
|
|
||||||
md->devinfo_created = TRUE;
|
|
||||||
ofono_devinfo_create(md->modem.ofono, 0, RILMODEM_DRIVER, md);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ril_modem_set_imei(struct ril_modem *modem, const char *imei)
|
|
||||||
{
|
|
||||||
struct ril_modem_data *md = ril_modem_data_from_modem(modem);
|
|
||||||
|
|
||||||
if (md) {
|
|
||||||
g_free(md->imei);
|
|
||||||
modem->imei = md->imei = g_strdup(imei);
|
|
||||||
ril_modem_check_devinfo(md);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ril_modem_online_request_ok(struct ril_modem_online_request *req)
|
static void ril_modem_online_request_ok(struct ril_modem_online_request *req)
|
||||||
{
|
{
|
||||||
if (req->timeout_id) {
|
if (req->timeout_id) {
|
||||||
@@ -220,7 +199,8 @@ static gboolean ril_modem_online_request_timeout(gpointer data)
|
|||||||
req->data = NULL;
|
req->data = NULL;
|
||||||
cb(ril_error_failure(&error), cb_data);
|
cb(ril_error_failure(&error), cb_data);
|
||||||
ril_modem_update_online_state(req->md);
|
ril_modem_update_online_state(req->md);
|
||||||
return FALSE;
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean ril_modem_online_check(gpointer data)
|
static gboolean ril_modem_online_check(gpointer data)
|
||||||
@@ -263,7 +243,7 @@ static void ril_modem_radio_state_cb(struct ril_radio *radio, void *data)
|
|||||||
GASSERT(md->modem.radio == radio);
|
GASSERT(md->modem.radio == radio);
|
||||||
ril_modem_update_radio_settings(md);
|
ril_modem_update_radio_settings(md);
|
||||||
ril_modem_update_online_state(md);
|
ril_modem_update_online_state(md);
|
||||||
};
|
}
|
||||||
|
|
||||||
static void ril_modem_pre_sim(struct ofono_modem *modem)
|
static void ril_modem_pre_sim(struct ofono_modem *modem)
|
||||||
{
|
{
|
||||||
@@ -271,7 +251,7 @@ static void ril_modem_pre_sim(struct ofono_modem *modem)
|
|||||||
|
|
||||||
DBG("%s", ofono_modem_get_path(modem));
|
DBG("%s", ofono_modem_get_path(modem));
|
||||||
md->pre_sim_done = TRUE;
|
md->pre_sim_done = TRUE;
|
||||||
ril_modem_check_devinfo(md);
|
ofono_devinfo_create(modem, 0, RILMODEM_DRIVER, md);
|
||||||
ofono_sim_create(modem, 0, RILMODEM_DRIVER, md);
|
ofono_sim_create(modem, 0, RILMODEM_DRIVER, md);
|
||||||
ofono_voicecall_create(modem, 0, RILMODEM_DRIVER, md);
|
ofono_voicecall_create(modem, 0, RILMODEM_DRIVER, md);
|
||||||
ril_modem_update_radio_settings(md);
|
ril_modem_update_radio_settings(md);
|
||||||
@@ -320,7 +300,6 @@ static void ril_modem_post_online(struct ofono_modem *modem)
|
|||||||
ofono_netreg_create(modem, 0, RILMODEM_DRIVER, md);
|
ofono_netreg_create(modem, 0, RILMODEM_DRIVER, md);
|
||||||
ofono_ussd_create(modem, 0, RILMODEM_DRIVER, md);
|
ofono_ussd_create(modem, 0, RILMODEM_DRIVER, md);
|
||||||
ofono_call_settings_create(modem, 0, RILMODEM_DRIVER, md);
|
ofono_call_settings_create(modem, 0, RILMODEM_DRIVER, md);
|
||||||
ofono_oem_raw_create(modem, 0, RILMODEM_DRIVER, md);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_modem_set_online(struct ofono_modem *modem, ofono_bool_t online,
|
static void ril_modem_set_online(struct ofono_modem *modem, ofono_bool_t online,
|
||||||
@@ -418,19 +397,20 @@ static void ril_modem_remove(struct ofono_modem *ofono)
|
|||||||
|
|
||||||
ril_network_unref(modem->network);
|
ril_network_unref(modem->network);
|
||||||
ril_sim_card_unref(modem->sim_card);
|
ril_sim_card_unref(modem->sim_card);
|
||||||
|
ril_sim_settings_unref(modem->sim_settings);
|
||||||
ril_data_unref(modem->data);
|
ril_data_unref(modem->data);
|
||||||
grilio_channel_unref(modem->io);
|
grilio_channel_unref(modem->io);
|
||||||
grilio_queue_cancel_all(md->q, FALSE);
|
grilio_queue_cancel_all(md->q, FALSE);
|
||||||
grilio_queue_unref(md->q);
|
grilio_queue_unref(md->q);
|
||||||
g_free(md->default_name);
|
g_free(md->ecclist_file);
|
||||||
g_free(md->imei);
|
g_free(md->imei);
|
||||||
g_free(md);
|
g_free(md);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ril_modem *ril_modem_create(GRilIoChannel *io,
|
struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
|
||||||
const struct ril_slot_info *slot, struct ril_radio *radio,
|
const struct ril_slot_info *slot, struct ril_radio *radio,
|
||||||
struct ril_network *network, struct ril_sim_card *card,
|
struct ril_network *network, struct ril_sim_card *card,
|
||||||
struct ril_data *data)
|
struct ril_data *data, struct ril_sim_settings *settings)
|
||||||
{
|
{
|
||||||
/* Skip the slash from the path, it looks like "/ril_0" */
|
/* Skip the slash from the path, it looks like "/ril_0" */
|
||||||
struct ofono_modem *ofono = ofono_modem_create(slot->path + 1,
|
struct ofono_modem *ofono = ofono_modem_create(slot->path + 1,
|
||||||
@@ -440,22 +420,24 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io,
|
|||||||
struct ril_modem_data *md = g_new0(struct ril_modem_data, 1);
|
struct ril_modem_data *md = g_new0(struct ril_modem_data, 1);
|
||||||
struct ril_modem *modem = &md->modem;
|
struct ril_modem *modem = &md->modem;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ril_plugin.c must wait until IMEI becomes known before
|
||||||
|
* creating the modem
|
||||||
|
*/
|
||||||
|
GASSERT(slot->imei);
|
||||||
|
|
||||||
/* Copy config */
|
/* Copy config */
|
||||||
modem->config = *slot->config;
|
modem->config = *slot->config;
|
||||||
modem->imei = md->imei = g_strdup(slot->imei);
|
modem->imei = md->imei = g_strdup(slot->imei);
|
||||||
if (slot->config->default_name &&
|
modem->log_prefix = log_prefix;
|
||||||
slot->config->default_name[0]) {
|
modem->ecclist_file =
|
||||||
md->default_name = g_strdup(slot->config->default_name);
|
md->ecclist_file = g_strdup(slot->ecclist_file);
|
||||||
} else {
|
|
||||||
md->default_name = g_strdup_printf("SIM%u",
|
|
||||||
slot->config->slot + 1);
|
|
||||||
}
|
|
||||||
modem->config.default_name = md->default_name;
|
|
||||||
|
|
||||||
modem->ofono = ofono;
|
modem->ofono = ofono;
|
||||||
modem->radio = ril_radio_ref(radio);
|
modem->radio = ril_radio_ref(radio);
|
||||||
modem->network = ril_network_ref(network);
|
modem->network = ril_network_ref(network);
|
||||||
modem->sim_card = ril_sim_card_ref(card);
|
modem->sim_card = ril_sim_card_ref(card);
|
||||||
|
modem->sim_settings = ril_sim_settings_ref(settings);
|
||||||
modem->data = ril_data_ref(data);
|
modem->data = ril_data_ref(data);
|
||||||
modem->io = grilio_channel_ref(io);
|
modem->io = grilio_channel_ref(io);
|
||||||
md->q = grilio_queue_new(io);
|
md->q = grilio_queue_new(io);
|
||||||
@@ -465,7 +447,6 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io,
|
|||||||
err = ofono_modem_register(ofono);
|
err = ofono_modem_register(ofono);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
ril_radio_power_cycle(modem->radio);
|
ril_radio_power_cycle(modem->radio);
|
||||||
ril_radio_power_on(modem->radio, RADIO_POWER_TAG(md));
|
|
||||||
GASSERT(io->connected);
|
GASSERT(io->connected);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -475,6 +456,15 @@ struct ril_modem *ril_modem_create(GRilIoChannel *io,
|
|||||||
ofono_modem_set_powered(modem->ofono, FALSE);
|
ofono_modem_set_powered(modem->ofono, FALSE);
|
||||||
ofono_modem_set_powered(modem->ofono, TRUE);
|
ofono_modem_set_powered(modem->ofono, TRUE);
|
||||||
md->power_state = POWERED_ON;
|
md->power_state = POWERED_ON;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* With some RIL implementations, querying available
|
||||||
|
* band modes causes some magic Android properties to
|
||||||
|
* appear. Otherwise this request is pretty harmless
|
||||||
|
* and useless.
|
||||||
|
*/
|
||||||
|
grilio_queue_send_request(md->q, NULL,
|
||||||
|
RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE);
|
||||||
return modem;
|
return modem;
|
||||||
} else {
|
} else {
|
||||||
ofono_error("Error %d registering %s",
|
ofono_error("Error %d registering %s",
|
||||||
|
|||||||
223
ofono/drivers/ril/ril_mtu.c
Normal file
223
ofono/drivers/ril/ril_mtu.c
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
/*
|
||||||
|
* oFono - Open Source Telephony - RIL-based devices
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 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_mtu.h"
|
||||||
|
#include "ril_log.h"
|
||||||
|
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#include <linux/netlink.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
|
struct ril_mtu_watch {
|
||||||
|
int max_mtu;
|
||||||
|
char *ifname;
|
||||||
|
void *buf;
|
||||||
|
int bufsize;
|
||||||
|
GIOChannel *channel;
|
||||||
|
guint io_watch;
|
||||||
|
int fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void ril_mtu_watch_limit_mtu(struct ril_mtu_watch *self)
|
||||||
|
{
|
||||||
|
int fd = socket(PF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (fd >= 0) {
|
||||||
|
struct ifreq ifr;
|
||||||
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
|
strncpy(ifr.ifr_name, self->ifname, IFNAMSIZ);
|
||||||
|
if (ioctl(fd, SIOCGIFMTU, &ifr) < 0 ||
|
||||||
|
ifr.ifr_mtu > self->max_mtu) {
|
||||||
|
DBG("%s mtu %d => %d", self->ifname, ifr.ifr_mtu,
|
||||||
|
self->max_mtu);
|
||||||
|
ifr.ifr_mtu = self->max_mtu;
|
||||||
|
if (ioctl(fd, SIOCSIFMTU, &ifr) < 0) {
|
||||||
|
ofono_error("Failed to set MTU");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_mtu_watch_handle_rtattr(struct ril_mtu_watch *self,
|
||||||
|
const struct rtattr *rta, int len)
|
||||||
|
{
|
||||||
|
int mtu = 0;
|
||||||
|
const char *ifname = NULL;
|
||||||
|
while (len > 0 && RTA_OK(rta, len) && (!mtu || !ifname)) {
|
||||||
|
switch (rta->rta_type) {
|
||||||
|
case IFLA_IFNAME:
|
||||||
|
ifname = RTA_DATA(rta);
|
||||||
|
break;
|
||||||
|
case IFLA_MTU:
|
||||||
|
mtu = *((int*)RTA_DATA(rta));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rta = RTA_NEXT(rta, len);
|
||||||
|
}
|
||||||
|
if (mtu > self->max_mtu && !g_strcmp0(ifname, self->ifname)) {
|
||||||
|
DBG("%s %d", ifname, mtu);
|
||||||
|
ril_mtu_watch_limit_mtu(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_mtu_watch_handle_ifinfomsg(struct ril_mtu_watch *self,
|
||||||
|
const struct ifinfomsg *ifi, int len)
|
||||||
|
{
|
||||||
|
if (ifi->ifi_flags & IFF_UP) {
|
||||||
|
const struct rtattr *rta = IFLA_RTA(ifi);
|
||||||
|
ril_mtu_watch_handle_rtattr(self, rta,
|
||||||
|
len - ((char*)rta - (char*)ifi));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_mtu_watch_handle_nlmsg(struct ril_mtu_watch *self,
|
||||||
|
const struct nlmsghdr *hdr, int len)
|
||||||
|
{
|
||||||
|
while (len > 0 && NLMSG_OK(hdr, len)) {
|
||||||
|
if (hdr->nlmsg_type == RTM_NEWLINK) {
|
||||||
|
ril_mtu_watch_handle_ifinfomsg(self, NLMSG_DATA(hdr),
|
||||||
|
IFLA_PAYLOAD(hdr));
|
||||||
|
}
|
||||||
|
hdr = NLMSG_NEXT(hdr, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean ril_mtu_watch_event(GIOChannel *ch, GIOCondition cond,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
struct ril_mtu_watch *self = data;
|
||||||
|
struct sockaddr_nl addr;
|
||||||
|
socklen_t addrlen = sizeof(addr);
|
||||||
|
ssize_t result = recvfrom(self->fd, self->buf, self->bufsize, 0,
|
||||||
|
(struct sockaddr *)&addr, &addrlen);
|
||||||
|
if (result > 0) {
|
||||||
|
if (!addr.nl_pid) {
|
||||||
|
ril_mtu_watch_handle_nlmsg(self, self->buf, result);
|
||||||
|
}
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
} else if (result == 0 || errno == EINTR || errno == EAGAIN) {
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
} else {
|
||||||
|
DBG("%s error %d", self->ifname, errno);
|
||||||
|
self->io_watch = 0;
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean ril_mtu_watch_open_socket(struct ril_mtu_watch *self)
|
||||||
|
{
|
||||||
|
GASSERT(self->fd < 0);
|
||||||
|
self->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||||
|
if (self->fd >= 0) {
|
||||||
|
struct sockaddr_nl nl;
|
||||||
|
memset(&nl, 0, sizeof(nl));
|
||||||
|
nl.nl_pid = getpid();
|
||||||
|
nl.nl_family = AF_NETLINK;
|
||||||
|
nl.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE |
|
||||||
|
RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE |
|
||||||
|
RTMGRP_LINK;
|
||||||
|
|
||||||
|
if (bind(self->fd, (struct sockaddr*)&nl, sizeof(nl)) >= 0) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
close(self->fd);
|
||||||
|
self->fd = -1;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean ril_mtu_watch_start(struct ril_mtu_watch *self)
|
||||||
|
{
|
||||||
|
if (self->fd >= 0) {
|
||||||
|
return TRUE;
|
||||||
|
} else if (ril_mtu_watch_open_socket(self)) {
|
||||||
|
GASSERT(!self->channel);
|
||||||
|
GASSERT(!self->io_watch);
|
||||||
|
self->channel = g_io_channel_unix_new(self->fd);
|
||||||
|
if (self->channel) {
|
||||||
|
g_io_channel_set_encoding(self->channel, NULL, NULL);
|
||||||
|
g_io_channel_set_buffered(self->channel, FALSE);
|
||||||
|
self->io_watch = g_io_add_watch(self->channel,
|
||||||
|
G_IO_IN | G_IO_NVAL | G_IO_HUP,
|
||||||
|
ril_mtu_watch_event, self);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
close(self->fd);
|
||||||
|
self->fd = -1;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_mtu_watch_stop(struct ril_mtu_watch *self)
|
||||||
|
{
|
||||||
|
if (self->io_watch) {
|
||||||
|
g_source_remove(self->io_watch);
|
||||||
|
self->io_watch = 0;
|
||||||
|
}
|
||||||
|
if (self->channel) {
|
||||||
|
g_io_channel_shutdown(self->channel, TRUE, NULL);
|
||||||
|
g_io_channel_unref(self->channel);
|
||||||
|
self->channel = NULL;
|
||||||
|
}
|
||||||
|
if (self->fd >= 0) {
|
||||||
|
close(self->fd);
|
||||||
|
self->fd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ril_mtu_watch *ril_mtu_watch_new(int max_mtu)
|
||||||
|
{
|
||||||
|
struct ril_mtu_watch *self = g_new0(struct ril_mtu_watch, 1);
|
||||||
|
self->fd = -1;
|
||||||
|
self->max_mtu = max_mtu;
|
||||||
|
self->bufsize = 4096;
|
||||||
|
self->buf = g_malloc(self->bufsize);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ril_mtu_watch_free(struct ril_mtu_watch *self)
|
||||||
|
{
|
||||||
|
if (self) {
|
||||||
|
ril_mtu_watch_stop(self);
|
||||||
|
g_free(self->ifname);
|
||||||
|
g_free(self->buf);
|
||||||
|
g_free(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ril_mtu_watch_set_ifname(struct ril_mtu_watch *self, const char *ifname)
|
||||||
|
{
|
||||||
|
if (self && g_strcmp0(self->ifname, ifname)) {
|
||||||
|
g_free(self->ifname);
|
||||||
|
if (ifname) {
|
||||||
|
self->ifname = g_strdup(ifname);
|
||||||
|
ril_mtu_watch_limit_mtu(self);
|
||||||
|
ril_mtu_watch_start(self);
|
||||||
|
} else {
|
||||||
|
self->ifname = NULL;
|
||||||
|
ril_mtu_watch_stop(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local Variables:
|
||||||
|
* mode: C
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
33
ofono/drivers/ril/ril_mtu.h
Normal file
33
ofono/drivers/ril/ril_mtu.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* oFono - Open Source Telephony - RIL-based devices
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 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_MTU_H
|
||||||
|
#define RIL_MTU_H
|
||||||
|
|
||||||
|
#include "ril_types.h"
|
||||||
|
|
||||||
|
struct ril_mtu_watch *ril_mtu_watch_new(int max_mtu);
|
||||||
|
void ril_mtu_watch_free(struct ril_mtu_watch *mw);
|
||||||
|
void ril_mtu_watch_set_ifname(struct ril_mtu_watch *mw, const char *ifname);
|
||||||
|
|
||||||
|
#endif /* RIL_MTU_H */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local Variables:
|
||||||
|
* mode: C
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
@@ -164,7 +164,13 @@ static void ril_netreg_current_operator(struct ofono_netreg *netreg,
|
|||||||
{
|
{
|
||||||
struct ril_netreg *nd = ril_netreg_get_data(netreg);
|
struct ril_netreg *nd = ril_netreg_get_data(netreg);
|
||||||
|
|
||||||
GASSERT(!nd->current_operator_id);
|
/*
|
||||||
|
* Calling ofono_netreg_status_notify() may result in
|
||||||
|
* ril_netreg_current_operator() being invoked even if one
|
||||||
|
* is already pending. Since ofono core doesn't associate
|
||||||
|
* any context with individual calls, we can safely assume
|
||||||
|
* that such a call essentially cancels the previous one.
|
||||||
|
*/
|
||||||
if (nd->current_operator_id) {
|
if (nd->current_operator_id) {
|
||||||
g_source_remove(nd->current_operator_id);
|
g_source_remove(nd->current_operator_id);
|
||||||
}
|
}
|
||||||
@@ -397,10 +403,13 @@ static void ril_netreg_strength(struct ofono_netreg *netreg,
|
|||||||
ofono_netreg_strength_cb_t cb, void *data)
|
ofono_netreg_strength_cb_t cb, void *data)
|
||||||
{
|
{
|
||||||
struct ril_netreg *nd = ril_netreg_get_data(netreg);
|
struct ril_netreg *nd = ril_netreg_get_data(netreg);
|
||||||
|
GRilIoRequest* req = grilio_request_new();
|
||||||
|
|
||||||
grilio_queue_send_request_full(nd->q, NULL,
|
grilio_request_set_retry(req, RIL_RETRY_MS, -1);
|
||||||
|
grilio_queue_send_request_full(nd->q, req,
|
||||||
RIL_REQUEST_SIGNAL_STRENGTH, ril_netreg_strength_cb,
|
RIL_REQUEST_SIGNAL_STRENGTH, ril_netreg_strength_cb,
|
||||||
ril_netreg_cbd_free, ril_netreg_cbd_new(nd, cb, data));
|
ril_netreg_cbd_free, ril_netreg_cbd_new(nd, cb, data));
|
||||||
|
grilio_request_unref(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_netreg_nitz_notify(GRilIoChannel *io, guint ril_event,
|
static void ril_netreg_nitz_notify(GRilIoChannel *io, guint ril_event,
|
||||||
|
|||||||
@@ -9,12 +9,14 @@
|
|||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ril_network.h"
|
#include "ril_network.h"
|
||||||
#include "ril_radio.h"
|
#include "ril_radio.h"
|
||||||
|
#include "ril_sim_card.h"
|
||||||
|
#include "ril_sim_settings.h"
|
||||||
#include "ril_util.h"
|
#include "ril_util.h"
|
||||||
#include "ril_log.h"
|
#include "ril_log.h"
|
||||||
|
|
||||||
@@ -22,22 +24,47 @@
|
|||||||
#include <grilio_request.h>
|
#include <grilio_request.h>
|
||||||
#include <grilio_parser.h>
|
#include <grilio_parser.h>
|
||||||
|
|
||||||
|
#include <gutil_misc.h>
|
||||||
|
|
||||||
#include <ofono/netreg.h>
|
#include <ofono/netreg.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
#define SET_PREF_MODE_HOLDOFF_SEC RIL_RETRY_SECS
|
||||||
|
|
||||||
typedef GObjectClass RilNetworkClass;
|
typedef GObjectClass RilNetworkClass;
|
||||||
typedef struct ril_network RilNetwork;
|
typedef struct ril_network RilNetwork;
|
||||||
|
|
||||||
|
enum ril_network_timer {
|
||||||
|
TIMER_SET_RAT_HOLDOFF,
|
||||||
|
TIMER_FORCE_CHECK_PREF_MODE,
|
||||||
|
TIMER_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ril_network_radio_event {
|
||||||
|
RADIO_EVENT_STATE_CHANGED,
|
||||||
|
RADIO_EVENT_ONLINE_CHANGED,
|
||||||
|
RADIO_EVENT_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
struct ril_network_priv {
|
struct ril_network_priv {
|
||||||
GRilIoChannel *io;
|
GRilIoChannel *io;
|
||||||
GRilIoQueue *q;
|
GRilIoQueue *q;
|
||||||
struct ril_radio *radio;
|
struct ril_radio *radio;
|
||||||
|
struct ril_sim_card *sim_card;
|
||||||
|
enum ofono_radio_access_mode max_pref_mode;
|
||||||
|
int rat;
|
||||||
char *log_prefix;
|
char *log_prefix;
|
||||||
gulong event_id;
|
|
||||||
guint operator_poll_id;
|
guint operator_poll_id;
|
||||||
guint voice_poll_id;
|
guint voice_poll_id;
|
||||||
guint data_poll_id;
|
guint data_poll_id;
|
||||||
gulong radio_event_id;
|
guint timer[TIMER_COUNT];
|
||||||
|
gulong query_rat_id;
|
||||||
|
gulong set_rat_id;
|
||||||
|
gulong ril_event_id;
|
||||||
|
gulong settings_event_id;
|
||||||
|
gulong sim_status_event_id;
|
||||||
|
gulong radio_event_id[RADIO_EVENT_COUNT];
|
||||||
struct ofono_network_operator operator;
|
struct ofono_network_operator operator;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -45,12 +72,14 @@ enum ril_network_signal {
|
|||||||
SIGNAL_OPERATOR_CHANGED,
|
SIGNAL_OPERATOR_CHANGED,
|
||||||
SIGNAL_VOICE_STATE_CHANGED,
|
SIGNAL_VOICE_STATE_CHANGED,
|
||||||
SIGNAL_DATA_STATE_CHANGED,
|
SIGNAL_DATA_STATE_CHANGED,
|
||||||
|
SIGNAL_PREF_MODE_CHANGED,
|
||||||
SIGNAL_COUNT
|
SIGNAL_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SIGNAL_OPERATOR_CHANGED_NAME "ril-network-operator-changed"
|
#define SIGNAL_OPERATOR_CHANGED_NAME "ril-network-operator-changed"
|
||||||
#define SIGNAL_VOICE_STATE_CHANGED_NAME "ril-network-voice-state-changed"
|
#define SIGNAL_VOICE_STATE_CHANGED_NAME "ril-network-voice-state-changed"
|
||||||
#define SIGNAL_DATA_STATE_CHANGED_NAME "ril-network-data-state-changed"
|
#define SIGNAL_DATA_STATE_CHANGED_NAME "ril-network-data-state-changed"
|
||||||
|
#define SIGNAL_PREF_MODE_CHANGED_NAME "ril-network-pref-mode-changed"
|
||||||
|
|
||||||
static guint ril_network_signals[SIGNAL_COUNT] = { 0 };
|
static guint ril_network_signals[SIGNAL_COUNT] = { 0 };
|
||||||
|
|
||||||
@@ -59,6 +88,40 @@ G_DEFINE_TYPE(RilNetwork, ril_network, G_TYPE_OBJECT)
|
|||||||
#define RIL_NETWORK(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj,\
|
#define RIL_NETWORK(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj,\
|
||||||
RIL_NETWORK_TYPE,RilNetwork))
|
RIL_NETWORK_TYPE,RilNetwork))
|
||||||
|
|
||||||
|
#define RIL_NETWORK_SIGNAL(klass,name) \
|
||||||
|
ril_network_signals[SIGNAL_##name##_CHANGED] = \
|
||||||
|
g_signal_new(SIGNAL_##name##_CHANGED_NAME, \
|
||||||
|
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST, \
|
||||||
|
0, NULL, NULL, NULL, G_TYPE_NONE, 0)
|
||||||
|
|
||||||
|
#define DBG_(self,fmt,args...) DBG("%s" fmt, (self)->priv->log_prefix, ##args)
|
||||||
|
|
||||||
|
/* Some assumptions: */
|
||||||
|
G_STATIC_ASSERT(OFONO_RADIO_ACCESS_MODE_ANY == 0);
|
||||||
|
G_STATIC_ASSERT(OFONO_RADIO_ACCESS_MODE_GSM > OFONO_RADIO_ACCESS_MODE_ANY);
|
||||||
|
G_STATIC_ASSERT(OFONO_RADIO_ACCESS_MODE_UMTS > OFONO_RADIO_ACCESS_MODE_GSM);
|
||||||
|
G_STATIC_ASSERT(OFONO_RADIO_ACCESS_MODE_LTE > OFONO_RADIO_ACCESS_MODE_UMTS);
|
||||||
|
|
||||||
|
static void ril_network_query_pref_mode(struct ril_network *self);
|
||||||
|
static void ril_network_set_pref_mode(struct ril_network *self, int rat);
|
||||||
|
|
||||||
|
static void ril_network_emit(struct ril_network *self,
|
||||||
|
enum ril_network_signal sig)
|
||||||
|
{
|
||||||
|
g_signal_emit(self, ril_network_signals[sig], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_network_stop_timer(struct ril_network *self,
|
||||||
|
enum ril_network_timer tid)
|
||||||
|
{
|
||||||
|
struct ril_network_priv *priv = self->priv;
|
||||||
|
|
||||||
|
if (priv->timer[tid]) {
|
||||||
|
g_source_remove(priv->timer[tid]);
|
||||||
|
priv->timer[tid] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void ril_network_reset_state(struct ril_registration_state *reg)
|
static void ril_network_reset_state(struct ril_registration_state *reg)
|
||||||
{
|
{
|
||||||
memset(reg, 0, sizeof(*reg));
|
memset(reg, 0, sizeof(*reg));
|
||||||
@@ -72,7 +135,6 @@ static void ril_network_reset_state(struct ril_registration_state *reg)
|
|||||||
static gboolean ril_network_parse_response(struct ril_network *self,
|
static gboolean ril_network_parse_response(struct ril_network *self,
|
||||||
const void *data, guint len, struct ril_registration_state *reg)
|
const void *data, guint len, struct ril_registration_state *reg)
|
||||||
{
|
{
|
||||||
struct ril_network_priv *priv = self->priv;
|
|
||||||
int nparams, ril_status;
|
int nparams, ril_status;
|
||||||
gchar *sstatus = NULL, *slac = NULL, *sci = NULL;
|
gchar *sstatus = NULL, *slac = NULL, *sci = NULL;
|
||||||
gchar *stech = NULL, *sreason = NULL, *smax = NULL;
|
gchar *stech = NULL, *sreason = NULL, *smax = NULL;
|
||||||
@@ -83,13 +145,13 @@ static gboolean ril_network_parse_response(struct ril_network *self,
|
|||||||
/* Size of response string array. The minimum seen in the wild is 3 */
|
/* Size of response string array. The minimum seen in the wild is 3 */
|
||||||
grilio_parser_init(&rilp, data, len);
|
grilio_parser_init(&rilp, data, len);
|
||||||
if (!grilio_parser_get_int32(&rilp, &nparams) || nparams < 3) {
|
if (!grilio_parser_get_int32(&rilp, &nparams) || nparams < 3) {
|
||||||
DBG("%sbroken response", priv->log_prefix);
|
DBG_(self, "broken response");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
sstatus = grilio_parser_get_utf8(&rilp); /* response[0] */
|
sstatus = grilio_parser_get_utf8(&rilp); /* response[0] */
|
||||||
if (!sstatus) {
|
if (!sstatus) {
|
||||||
DBG("%sNo sstatus value returned!", priv->log_prefix);
|
DBG_(self, "No sstatus value returned!");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,7 +204,7 @@ static gboolean ril_network_parse_response(struct ril_network *self,
|
|||||||
reg->ci = sci ? strtol(sci, NULL, 16) : -1;
|
reg->ci = sci ? strtol(sci, NULL, 16) : -1;
|
||||||
reg->access_tech = ril_parse_tech(stech, ®->ril_tech);
|
reg->access_tech = ril_parse_tech(stech, ®->ril_tech);
|
||||||
|
|
||||||
DBG("%s%s,%s,%s,%d,%s,%s,%s", priv->log_prefix,
|
DBG_(self, "%s,%s,%s,%d,%s,%s,%s",
|
||||||
registration_status_to_string(reg->status),
|
registration_status_to_string(reg->status),
|
||||||
slac, sci, reg->ril_tech,
|
slac, sci, reg->ril_tech,
|
||||||
registration_tech_to_string(reg->access_tech),
|
registration_tech_to_string(reg->access_tech),
|
||||||
@@ -237,16 +299,15 @@ static void ril_network_poll_operator_cb(GRilIoChannel *io, int req_status,
|
|||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
if (self->operator) {
|
if (self->operator) {
|
||||||
DBG("%slalpha=%s, salpha=%s, numeric=%s, %s, "
|
DBG_(self, "lalpha=%s, salpha=%s, numeric=%s, "
|
||||||
"mcc=%s, mnc=%s, %s", priv->log_prefix,
|
"%s, mcc=%s, mnc=%s, %s",
|
||||||
lalpha, salpha, numeric,
|
lalpha, salpha, numeric,
|
||||||
op.name, op.mcc, op.mnc,
|
op.name, op.mcc, op.mnc,
|
||||||
registration_tech_to_string(op.tech));
|
registration_tech_to_string(op.tech));
|
||||||
} else {
|
} else {
|
||||||
DBG("%sno operator", priv->log_prefix);
|
DBG_(self, "no operator");
|
||||||
}
|
}
|
||||||
g_signal_emit(self, ril_network_signals[
|
ril_network_emit(self, SIGNAL_OPERATOR_CHANGED);
|
||||||
SIGNAL_OPERATOR_CHANGED], 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free(lalpha);
|
g_free(lalpha);
|
||||||
@@ -269,10 +330,9 @@ static void ril_network_poll_voice_state_cb(GRilIoChannel *io, int req_status,
|
|||||||
|
|
||||||
ril_network_parse_response(self, data, len, &state);
|
ril_network_parse_response(self, data, len, &state);
|
||||||
if (memcmp(&state, &self->voice, sizeof(state))) {
|
if (memcmp(&state, &self->voice, sizeof(state))) {
|
||||||
DBG("%svoice registration changed", priv->log_prefix);
|
DBG_(self, "voice registration changed");
|
||||||
self->voice = state;
|
self->voice = state;
|
||||||
g_signal_emit(self, ril_network_signals[
|
ril_network_emit(self, SIGNAL_VOICE_STATE_CHANGED);
|
||||||
SIGNAL_VOICE_STATE_CHANGED], 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -291,10 +351,9 @@ static void ril_network_poll_data_state_cb(GRilIoChannel *io, int req_status,
|
|||||||
|
|
||||||
ril_network_parse_response(self, data, len, &state);
|
ril_network_parse_response(self, data, len, &state);
|
||||||
if (memcmp(&state, &self->data, sizeof(state))) {
|
if (memcmp(&state, &self->data, sizeof(state))) {
|
||||||
DBG("%sdata registration changed", priv->log_prefix);
|
DBG_(self, "data registration changed");
|
||||||
self->data = state;
|
self->data = state;
|
||||||
g_signal_emit(self, ril_network_signals[
|
ril_network_emit(self, SIGNAL_DATA_STATE_CHANGED);
|
||||||
SIGNAL_DATA_STATE_CHANGED], 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -323,7 +382,7 @@ static void ril_network_poll_state(struct ril_network *self)
|
|||||||
{
|
{
|
||||||
struct ril_network_priv *priv = self->priv;
|
struct ril_network_priv *priv = self->priv;
|
||||||
|
|
||||||
DBG("%s", priv->log_prefix);
|
DBG_(self, "");
|
||||||
priv->operator_poll_id = ril_network_poll_and_retry(self,
|
priv->operator_poll_id = ril_network_poll_and_retry(self,
|
||||||
priv->operator_poll_id, RIL_REQUEST_OPERATOR,
|
priv->operator_poll_id, RIL_REQUEST_OPERATOR,
|
||||||
ril_network_poll_operator_cb);
|
ril_network_poll_operator_cb);
|
||||||
@@ -335,6 +394,221 @@ static void ril_network_poll_state(struct ril_network *self)
|
|||||||
ril_network_poll_data_state_cb);
|
ril_network_poll_data_state_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum ofono_radio_access_mode ril_network_rat_to_mode(int rat)
|
||||||
|
{
|
||||||
|
switch (rat) {
|
||||||
|
case PREF_NET_TYPE_LTE_CDMA_EVDO:
|
||||||
|
case PREF_NET_TYPE_LTE_GSM_WCDMA:
|
||||||
|
case PREF_NET_TYPE_LTE_CMDA_EVDO_GSM_WCDMA:
|
||||||
|
case PREF_NET_TYPE_LTE_ONLY:
|
||||||
|
case PREF_NET_TYPE_LTE_WCDMA:
|
||||||
|
return OFONO_RADIO_ACCESS_MODE_LTE;
|
||||||
|
case PREF_NET_TYPE_GSM_WCDMA_AUTO:
|
||||||
|
case PREF_NET_TYPE_WCDMA:
|
||||||
|
case PREF_NET_TYPE_GSM_WCDMA:
|
||||||
|
return OFONO_RADIO_ACCESS_MODE_UMTS;
|
||||||
|
default:
|
||||||
|
DBG("unexpected rat mode %d", rat);
|
||||||
|
case PREF_NET_TYPE_GSM_ONLY:
|
||||||
|
return OFONO_RADIO_ACCESS_MODE_GSM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ril_network_mode_to_rat(struct ril_network *self,
|
||||||
|
enum ofono_radio_access_mode mode)
|
||||||
|
{
|
||||||
|
switch (mode) {
|
||||||
|
case OFONO_RADIO_ACCESS_MODE_ANY:
|
||||||
|
case OFONO_RADIO_ACCESS_MODE_LTE:
|
||||||
|
if (self->settings->enable_4g) {
|
||||||
|
return PREF_NET_TYPE_LTE_GSM_WCDMA;
|
||||||
|
}
|
||||||
|
/* no break */
|
||||||
|
default:
|
||||||
|
case OFONO_RADIO_ACCESS_MODE_UMTS:
|
||||||
|
return PREF_NET_TYPE_GSM_WCDMA_AUTO;
|
||||||
|
case OFONO_RADIO_ACCESS_MODE_GSM:
|
||||||
|
return PREF_NET_TYPE_GSM_ONLY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ril_network_pref_mode_expected(struct ril_network *self)
|
||||||
|
{
|
||||||
|
struct ril_sim_settings *settings = self->settings;
|
||||||
|
struct ril_network_priv *priv = self->priv;
|
||||||
|
const enum ofono_radio_access_mode pref_mode = priv->max_pref_mode ?
|
||||||
|
MIN(settings->pref_mode, priv->max_pref_mode) :
|
||||||
|
settings->pref_mode;
|
||||||
|
return ril_network_mode_to_rat(self, pref_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean ril_network_can_set_pref_mode(struct ril_network *self)
|
||||||
|
{
|
||||||
|
struct ril_network_priv *priv = self->priv;
|
||||||
|
|
||||||
|
return priv->radio->online && ril_sim_card_ready(priv->sim_card);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean ril_network_set_rat_holdoff_cb(gpointer user_data)
|
||||||
|
{
|
||||||
|
struct ril_network *self = RIL_NETWORK(user_data);
|
||||||
|
struct ril_network_priv *priv = self->priv;
|
||||||
|
const int rat = ril_network_pref_mode_expected(self);
|
||||||
|
|
||||||
|
DBG_(self, "rat mode %d, expected %d", priv->rat, rat);
|
||||||
|
GASSERT(priv->timer[TIMER_SET_RAT_HOLDOFF]);
|
||||||
|
priv->timer[TIMER_SET_RAT_HOLDOFF] = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't retry the request if modem is offline or SIM card isn't
|
||||||
|
* ready, to avoid spamming system log with error messages. Radio
|
||||||
|
* and SIM card state change callbacks will schedule a new check
|
||||||
|
* when it's appropriate.
|
||||||
|
*/
|
||||||
|
if (priv->rat != rat) {
|
||||||
|
if (ril_network_can_set_pref_mode(self)) {
|
||||||
|
ril_network_set_pref_mode(self, rat);
|
||||||
|
} else {
|
||||||
|
DBG_(self, "giving up");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_network_set_pref_mode_cb(GRilIoChannel *io, int status,
|
||||||
|
const void *data, guint len, void *user_data)
|
||||||
|
{
|
||||||
|
struct ril_network *self = RIL_NETWORK(user_data);
|
||||||
|
struct ril_network_priv *priv = self->priv;
|
||||||
|
|
||||||
|
GASSERT(priv->set_rat_id);
|
||||||
|
priv->set_rat_id = 0;
|
||||||
|
if (status != RIL_E_SUCCESS) {
|
||||||
|
ofono_error("failed to set rat mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
ril_network_query_pref_mode(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_network_set_pref_mode(struct ril_network *self, int rat)
|
||||||
|
{
|
||||||
|
struct ril_network_priv *priv = self->priv;
|
||||||
|
GRilIoRequest *req = grilio_request_sized_new(8);
|
||||||
|
|
||||||
|
DBG_(self, "setting rat mode %d", rat);
|
||||||
|
grilio_request_append_int32(req, 1); /* Number of params */
|
||||||
|
grilio_request_append_int32(req, rat);
|
||||||
|
|
||||||
|
grilio_queue_cancel_request(priv->q, priv->set_rat_id, FALSE);
|
||||||
|
priv->set_rat_id = grilio_queue_send_request_full(priv->q, req,
|
||||||
|
RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE,
|
||||||
|
ril_network_set_pref_mode_cb, NULL, self);
|
||||||
|
grilio_request_unref(req);
|
||||||
|
|
||||||
|
/* Don't do it too often */
|
||||||
|
GASSERT(!priv->timer[TIMER_SET_RAT_HOLDOFF]);
|
||||||
|
priv->timer[TIMER_SET_RAT_HOLDOFF] =
|
||||||
|
g_timeout_add_seconds(SET_PREF_MODE_HOLDOFF_SEC,
|
||||||
|
ril_network_set_rat_holdoff_cb, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_network_check_pref_mode(struct ril_network *self,
|
||||||
|
gboolean force)
|
||||||
|
{
|
||||||
|
struct ril_network_priv *priv = self->priv;
|
||||||
|
const int rat = ril_network_pref_mode_expected(self);
|
||||||
|
|
||||||
|
if (priv->timer[TIMER_FORCE_CHECK_PREF_MODE]) {
|
||||||
|
ril_network_stop_timer(self, TIMER_FORCE_CHECK_PREF_MODE);
|
||||||
|
/*
|
||||||
|
* TIMER_FORCE_CHECK_PREF_MODE is scheduled by
|
||||||
|
* ril_network_pref_mode_changed_cb and is meant
|
||||||
|
* to force radio tech check right now.
|
||||||
|
*/
|
||||||
|
force = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->rat == rat || force) {
|
||||||
|
ril_network_stop_timer(self, TIMER_SET_RAT_HOLDOFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->rat != rat) {
|
||||||
|
/* Something isn't right, we need to fix it */
|
||||||
|
if (!priv->timer[TIMER_SET_RAT_HOLDOFF]) {
|
||||||
|
ril_network_set_pref_mode(self, rat);
|
||||||
|
} else {
|
||||||
|
/* OK, later */
|
||||||
|
DBG_(self, "need to set rat mode %d", rat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ril_network_parse_pref_resp(const void *data, guint len)
|
||||||
|
{
|
||||||
|
GRilIoParser rilp;
|
||||||
|
int pref = -1;
|
||||||
|
|
||||||
|
grilio_parser_init(&rilp, data, len);
|
||||||
|
grilio_parser_get_int32(&rilp, NULL);
|
||||||
|
grilio_parser_get_int32(&rilp, &pref);
|
||||||
|
return pref;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_network_query_pref_mode_cb(GRilIoChannel *io, int status,
|
||||||
|
const void *data, guint len, void *user_data)
|
||||||
|
{
|
||||||
|
struct ril_network *self = RIL_NETWORK(user_data);
|
||||||
|
struct ril_network_priv *priv = self->priv;
|
||||||
|
const enum ofono_radio_access_mode pref_mode = self->pref_mode;
|
||||||
|
|
||||||
|
/* This request never fails because in case of error it gets retried */
|
||||||
|
GASSERT(status == RIL_E_SUCCESS);
|
||||||
|
GASSERT(priv->query_rat_id);
|
||||||
|
|
||||||
|
priv->query_rat_id = 0;
|
||||||
|
priv->rat = ril_network_parse_pref_resp(data, len);
|
||||||
|
self->pref_mode = ril_network_rat_to_mode(priv->rat);
|
||||||
|
DBG_(self, "rat mode %d (%s)", priv->rat,
|
||||||
|
ofono_radio_access_mode_to_string(self->pref_mode));
|
||||||
|
|
||||||
|
if (self->pref_mode != pref_mode) {
|
||||||
|
ril_network_emit(self, SIGNAL_PREF_MODE_CHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ril_network_can_set_pref_mode(self)) {
|
||||||
|
ril_network_check_pref_mode(self, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_network_query_pref_mode(struct ril_network *self)
|
||||||
|
{
|
||||||
|
struct ril_network_priv *priv = self->priv;
|
||||||
|
GRilIoRequest *req = grilio_request_new();
|
||||||
|
|
||||||
|
grilio_request_set_retry(req, RIL_RETRY_SECS*1000, -1);
|
||||||
|
grilio_queue_cancel_request(priv->q, priv->query_rat_id, FALSE);
|
||||||
|
priv->query_rat_id = grilio_queue_send_request_full(priv->q, req,
|
||||||
|
RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE,
|
||||||
|
ril_network_query_pref_mode_cb, NULL, self);
|
||||||
|
grilio_request_unref(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ril_network_set_max_pref_mode(struct ril_network *self,
|
||||||
|
enum ofono_radio_access_mode max_mode,
|
||||||
|
gboolean force_check)
|
||||||
|
{
|
||||||
|
if (G_LIKELY(self)) {
|
||||||
|
struct ril_network_priv *priv = self->priv;
|
||||||
|
if (priv->max_pref_mode != max_mode || force_check) {
|
||||||
|
DBG_(self, "rat mode %d (%s)", max_mode,
|
||||||
|
ofono_radio_access_mode_to_string(max_mode));
|
||||||
|
priv->max_pref_mode = max_mode;
|
||||||
|
ril_network_check_pref_mode(self, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gulong ril_network_add_operator_changed_handler(struct ril_network *self,
|
gulong ril_network_add_operator_changed_handler(struct ril_network *self,
|
||||||
ril_network_cb_t cb, void *arg)
|
ril_network_cb_t cb, void *arg)
|
||||||
{
|
{
|
||||||
@@ -356,6 +630,13 @@ gulong ril_network_add_data_state_changed_handler(struct ril_network *self,
|
|||||||
SIGNAL_DATA_STATE_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
|
SIGNAL_DATA_STATE_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gulong ril_network_add_pref_mode_changed_handler(struct ril_network *self,
|
||||||
|
ril_network_cb_t cb, void *arg)
|
||||||
|
{
|
||||||
|
return (G_LIKELY(self) && G_LIKELY(cb)) ? g_signal_connect(self,
|
||||||
|
SIGNAL_PREF_MODE_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
void ril_network_remove_handler(struct ril_network *self, gulong id)
|
void ril_network_remove_handler(struct ril_network *self, gulong id)
|
||||||
{
|
{
|
||||||
if (G_LIKELY(self) && G_LIKELY(id)) {
|
if (G_LIKELY(self) && G_LIKELY(id)) {
|
||||||
@@ -363,43 +644,110 @@ void ril_network_remove_handler(struct ril_network *self, gulong id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ril_network_remove_handlers(struct ril_network *self, gulong *ids, int n)
|
||||||
|
{
|
||||||
|
gutil_disconnect_handlers(self, ids, n);
|
||||||
|
}
|
||||||
|
|
||||||
static void ril_network_voice_state_changed_cb(GRilIoChannel *io, guint code,
|
static void ril_network_voice_state_changed_cb(GRilIoChannel *io, guint code,
|
||||||
const void *data, guint len, void *user_data)
|
const void *data, guint len, void *user_data)
|
||||||
{
|
{
|
||||||
struct ril_network *self = RIL_NETWORK(user_data);
|
struct ril_network *self = RIL_NETWORK(user_data);
|
||||||
struct ril_network_priv *priv = self->priv;
|
|
||||||
|
|
||||||
DBG("%s", priv->log_prefix);
|
DBG_(self, "");
|
||||||
GASSERT(code == RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED);
|
GASSERT(code == RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED);
|
||||||
ril_network_poll_state(self);
|
ril_network_poll_state(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_network_radio_state_cb(struct ril_radio *radio, void *user_data)
|
static void ril_network_radio_state_cb(struct ril_radio *radio, void *data)
|
||||||
{
|
{
|
||||||
struct ril_network *self = RIL_NETWORK(user_data);
|
|
||||||
|
|
||||||
if (radio->state == RADIO_STATE_ON) {
|
if (radio->state == RADIO_STATE_ON) {
|
||||||
ril_network_poll_state(self);
|
ril_network_poll_state(RIL_NETWORK(data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ril_network *ril_network_new(GRilIoChannel *io, struct ril_radio *radio)
|
static void ril_network_radio_online_cb(struct ril_radio *radio, void *data)
|
||||||
|
{
|
||||||
|
struct ril_network *self = RIL_NETWORK(data);
|
||||||
|
|
||||||
|
if (ril_network_can_set_pref_mode(self)) {
|
||||||
|
ril_network_check_pref_mode(self, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean ril_network_check_pref_mode_cb(gpointer user_data)
|
||||||
|
{
|
||||||
|
struct ril_network *self = RIL_NETWORK(user_data);
|
||||||
|
struct ril_network_priv *priv = self->priv;
|
||||||
|
|
||||||
|
GASSERT(priv->timer[TIMER_FORCE_CHECK_PREF_MODE]);
|
||||||
|
priv->timer[TIMER_FORCE_CHECK_PREF_MODE] = 0;
|
||||||
|
|
||||||
|
DBG_(self, "checking pref mode");
|
||||||
|
ril_network_check_pref_mode(self, TRUE);
|
||||||
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_network_pref_mode_changed_cb(struct ril_sim_settings *settings,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct ril_network *self = RIL_NETWORK(user_data);
|
||||||
|
struct ril_network_priv *priv = self->priv;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Postpone ril_network_check_pref_mode because other pref_mode
|
||||||
|
* listeners (namely, ril_data) may want to tweak max_pref_mode
|
||||||
|
*/
|
||||||
|
if (!priv->timer[TIMER_FORCE_CHECK_PREF_MODE]) {
|
||||||
|
DBG_(self, "scheduling pref mode check");
|
||||||
|
priv->timer[TIMER_FORCE_CHECK_PREF_MODE] =
|
||||||
|
g_idle_add(ril_network_check_pref_mode_cb, self);
|
||||||
|
} else {
|
||||||
|
DBG_(self, "pref mode check already scheduled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_network_sim_status_changed_cb(struct ril_sim_card *sc,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct ril_network *self = RIL_NETWORK(user_data);
|
||||||
|
|
||||||
|
if (ril_network_can_set_pref_mode(self)) {
|
||||||
|
ril_network_check_pref_mode(self, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ril_network *ril_network_new(GRilIoChannel *io, const char *log_prefix,
|
||||||
|
struct ril_radio *radio, struct ril_sim_card *sim_card,
|
||||||
|
struct ril_sim_settings *settings)
|
||||||
{
|
{
|
||||||
struct ril_network *self = g_object_new(RIL_NETWORK_TYPE, NULL);
|
struct ril_network *self = g_object_new(RIL_NETWORK_TYPE, NULL);
|
||||||
struct ril_network_priv *priv = self->priv;
|
struct ril_network_priv *priv = self->priv;
|
||||||
|
|
||||||
|
self->settings = ril_sim_settings_ref(settings);
|
||||||
priv->io = grilio_channel_ref(io);
|
priv->io = grilio_channel_ref(io);
|
||||||
priv->q = grilio_queue_new(priv->io);
|
priv->q = grilio_queue_new(priv->io);
|
||||||
priv->radio = ril_radio_ref(radio);
|
priv->radio = ril_radio_ref(radio);
|
||||||
priv->log_prefix =
|
priv->sim_card = ril_sim_card_ref(sim_card);
|
||||||
(io && io->name && io->name[0] && strcmp(io->name, "RIL")) ?
|
priv->log_prefix = (log_prefix && log_prefix[0]) ?
|
||||||
g_strconcat(io->name, " ", NULL) : g_strdup("");
|
g_strconcat(log_prefix, " ", NULL) : g_strdup("");
|
||||||
DBG("%s", priv->log_prefix);
|
DBG_(self, "");
|
||||||
priv->event_id = grilio_channel_add_unsol_event_handler(priv->io,
|
priv->ril_event_id = grilio_channel_add_unsol_event_handler(priv->io,
|
||||||
ril_network_voice_state_changed_cb,
|
ril_network_voice_state_changed_cb,
|
||||||
RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, self);
|
RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, self);
|
||||||
priv->radio_event_id = ril_radio_add_state_changed_handler(priv->radio,
|
priv->radio_event_id[RADIO_EVENT_STATE_CHANGED] =
|
||||||
ril_network_radio_state_cb, self);
|
ril_radio_add_state_changed_handler(priv->radio,
|
||||||
|
ril_network_radio_state_cb, self);
|
||||||
|
priv->radio_event_id[RADIO_EVENT_ONLINE_CHANGED] =
|
||||||
|
ril_radio_add_online_changed_handler(priv->radio,
|
||||||
|
ril_network_radio_online_cb, self);
|
||||||
|
priv->settings_event_id =
|
||||||
|
ril_sim_settings_add_pref_mode_changed_handler(settings,
|
||||||
|
ril_network_pref_mode_changed_cb, self);
|
||||||
|
priv->sim_status_event_id =
|
||||||
|
ril_sim_card_add_status_changed_handler(priv->sim_card,
|
||||||
|
ril_network_sim_status_changed_cb, self);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Query the initial state. Querying network state before the radio
|
* Query the initial state. Querying network state before the radio
|
||||||
@@ -437,24 +785,31 @@ static void ril_network_init(struct ril_network *self)
|
|||||||
self->priv = priv;
|
self->priv = priv;
|
||||||
ril_network_reset_state(&self->voice);
|
ril_network_reset_state(&self->voice);
|
||||||
ril_network_reset_state(&self->data);
|
ril_network_reset_state(&self->data);
|
||||||
|
priv->rat = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_network_dispose(GObject *object)
|
static void ril_network_dispose(GObject *object)
|
||||||
{
|
{
|
||||||
struct ril_network *self = RIL_NETWORK(object);
|
struct ril_network *self = RIL_NETWORK(object);
|
||||||
struct ril_network_priv *priv = self->priv;
|
struct ril_network_priv *priv = self->priv;
|
||||||
|
enum ril_network_timer tid;
|
||||||
|
|
||||||
if (priv->event_id) {
|
grilio_channel_remove_handlers(priv->io, &priv->ril_event_id, 1);
|
||||||
grilio_channel_remove_handler(priv->io, priv->event_id);
|
ril_radio_remove_handlers(priv->radio, priv->radio_event_id,
|
||||||
priv->event_id = 0;
|
G_N_ELEMENTS(priv->radio_event_id));
|
||||||
}
|
ril_sim_settings_remove_handlers(self->settings,
|
||||||
|
&priv->settings_event_id, 1);
|
||||||
|
ril_sim_card_remove_handlers(priv->sim_card,
|
||||||
|
&priv->sim_status_event_id, 1);
|
||||||
|
|
||||||
if (priv->radio_event_id) {
|
for (tid=0; tid<TIMER_COUNT; tid++) {
|
||||||
ril_radio_remove_handler(priv->radio, priv->radio_event_id);
|
ril_network_stop_timer(self, tid);
|
||||||
priv->radio_event_id = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
grilio_queue_cancel_all(priv->q, FALSE);
|
grilio_queue_cancel_all(priv->q, FALSE);
|
||||||
|
priv->set_rat_id = 0;
|
||||||
|
priv->query_rat_id = 0;
|
||||||
|
|
||||||
G_OBJECT_CLASS(ril_network_parent_class)->dispose(object);
|
G_OBJECT_CLASS(ril_network_parent_class)->dispose(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -463,11 +818,13 @@ static void ril_network_finalize(GObject *object)
|
|||||||
struct ril_network *self = RIL_NETWORK(object);
|
struct ril_network *self = RIL_NETWORK(object);
|
||||||
struct ril_network_priv *priv = self->priv;
|
struct ril_network_priv *priv = self->priv;
|
||||||
|
|
||||||
DBG("%s", priv->log_prefix);
|
DBG_(self, "");
|
||||||
g_free(priv->log_prefix);
|
g_free(priv->log_prefix);
|
||||||
grilio_channel_unref(priv->io);
|
grilio_channel_unref(priv->io);
|
||||||
grilio_queue_unref(priv->q);
|
grilio_queue_unref(priv->q);
|
||||||
ril_radio_unref(priv->radio);
|
ril_radio_unref(priv->radio);
|
||||||
|
ril_sim_card_unref(priv->sim_card);
|
||||||
|
ril_sim_settings_unref(self->settings);
|
||||||
G_OBJECT_CLASS(ril_network_parent_class)->finalize(object);
|
G_OBJECT_CLASS(ril_network_parent_class)->finalize(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,18 +835,10 @@ static void ril_network_class_init(RilNetworkClass *klass)
|
|||||||
object_class->dispose = ril_network_dispose;
|
object_class->dispose = ril_network_dispose;
|
||||||
object_class->finalize = ril_network_finalize;
|
object_class->finalize = ril_network_finalize;
|
||||||
g_type_class_add_private(klass, sizeof(struct ril_network_priv));
|
g_type_class_add_private(klass, sizeof(struct ril_network_priv));
|
||||||
ril_network_signals[SIGNAL_OPERATOR_CHANGED] =
|
RIL_NETWORK_SIGNAL(klass, OPERATOR);
|
||||||
g_signal_new(SIGNAL_OPERATOR_CHANGED_NAME,
|
RIL_NETWORK_SIGNAL(klass, VOICE_STATE);
|
||||||
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST,
|
RIL_NETWORK_SIGNAL(klass, DATA_STATE);
|
||||||
0, NULL, NULL, NULL, G_TYPE_NONE, 0);
|
RIL_NETWORK_SIGNAL(klass, PREF_MODE);
|
||||||
ril_network_signals[SIGNAL_VOICE_STATE_CHANGED] =
|
|
||||||
g_signal_new(SIGNAL_VOICE_STATE_CHANGED_NAME,
|
|
||||||
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST,
|
|
||||||
0, NULL, NULL, NULL, G_TYPE_NONE, 0);
|
|
||||||
ril_network_signals[SIGNAL_DATA_STATE_CHANGED] =
|
|
||||||
g_signal_new(SIGNAL_DATA_STATE_CHANGED_NAME,
|
|
||||||
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST,
|
|
||||||
0, NULL, NULL, NULL, G_TYPE_NONE, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
#include "ril_types.h"
|
#include "ril_types.h"
|
||||||
|
|
||||||
|
#include <ofono/radio-settings.h>
|
||||||
|
|
||||||
struct ofono_network_operator;
|
struct ofono_network_operator;
|
||||||
|
|
||||||
struct ril_registration_state {
|
struct ril_registration_state {
|
||||||
@@ -35,21 +37,32 @@ struct ril_network {
|
|||||||
struct ril_registration_state voice;
|
struct ril_registration_state voice;
|
||||||
struct ril_registration_state data;
|
struct ril_registration_state data;
|
||||||
const struct ofono_network_operator *operator;
|
const struct ofono_network_operator *operator;
|
||||||
|
enum ofono_radio_access_mode pref_mode;
|
||||||
|
struct ril_sim_settings *settings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ofono_sim;
|
||||||
typedef void (*ril_network_cb_t)(struct ril_network *net, void *arg);
|
typedef void (*ril_network_cb_t)(struct ril_network *net, void *arg);
|
||||||
|
|
||||||
struct ril_network *ril_network_new(GRilIoChannel *io, struct ril_radio *radio);
|
struct ril_network *ril_network_new(GRilIoChannel *io, const char *log_prefix,
|
||||||
|
struct ril_radio *radio, struct ril_sim_card *sim_card,
|
||||||
|
struct ril_sim_settings *settings);
|
||||||
struct ril_network *ril_network_ref(struct ril_network *net);
|
struct ril_network *ril_network_ref(struct ril_network *net);
|
||||||
void ril_network_unref(struct ril_network *net);
|
void ril_network_unref(struct ril_network *net);
|
||||||
|
|
||||||
|
void ril_network_set_max_pref_mode(struct ril_network *net,
|
||||||
|
enum ofono_radio_access_mode max_pref_mode,
|
||||||
|
gboolean force_check);
|
||||||
gulong ril_network_add_operator_changed_handler(struct ril_network *net,
|
gulong ril_network_add_operator_changed_handler(struct ril_network *net,
|
||||||
ril_network_cb_t cb, void *arg);
|
ril_network_cb_t cb, void *arg);
|
||||||
gulong ril_network_add_voice_state_changed_handler(struct ril_network *net,
|
gulong ril_network_add_voice_state_changed_handler(struct ril_network *net,
|
||||||
ril_network_cb_t cb, void *arg);
|
ril_network_cb_t cb, void *arg);
|
||||||
gulong ril_network_add_data_state_changed_handler(struct ril_network *net,
|
gulong ril_network_add_data_state_changed_handler(struct ril_network *net,
|
||||||
ril_network_cb_t cb, void *arg);
|
ril_network_cb_t cb, void *arg);
|
||||||
|
gulong ril_network_add_pref_mode_changed_handler(struct ril_network *net,
|
||||||
|
ril_network_cb_t cb, void *arg);
|
||||||
void ril_network_remove_handler(struct ril_network *net, gulong id);
|
void ril_network_remove_handler(struct ril_network *net, gulong id);
|
||||||
|
void ril_network_remove_handlers(struct ril_network *net, gulong *ids, int n);
|
||||||
|
|
||||||
#endif /* RIL_NETWORK_H */
|
#endif /* RIL_NETWORK_H */
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* oFono - Open Source Telephony - RIL-based devices
|
* oFono - Open Source Telephony - RIL-based devices
|
||||||
*
|
*
|
||||||
* Copyright (C) 2015 Jolla Ltd.
|
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
@@ -16,118 +16,147 @@
|
|||||||
#include "ril_plugin.h"
|
#include "ril_plugin.h"
|
||||||
#include "ril_util.h"
|
#include "ril_util.h"
|
||||||
#include "ril_log.h"
|
#include "ril_log.h"
|
||||||
#include "ril_constants.h"
|
|
||||||
|
#include "gdbus.h"
|
||||||
|
#include "ofono.h"
|
||||||
|
|
||||||
|
#define RIL_OEM_RAW_INTERFACE "org.ofono.OemRaw"
|
||||||
|
#define RIL_OEM_RAW_TIMEOUT (60*1000) /* 60 sec */
|
||||||
|
|
||||||
struct ril_oem_raw {
|
struct ril_oem_raw {
|
||||||
|
struct ril_modem *modem;
|
||||||
GRilIoQueue *q;
|
GRilIoQueue *q;
|
||||||
guint timer_id;
|
DBusConnection *conn;
|
||||||
|
char *path;
|
||||||
|
char *log_prefix;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ril_oem_raw_cbd {
|
#define DBG_(oem,fmt,args...) DBG("%s" fmt, (oem)->log_prefix, ##args)
|
||||||
ofono_oem_raw_query_cb_t cb;
|
|
||||||
gpointer data;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define ril_oem_raw_cbd_free g_free
|
static void ril_oem_raw_send_cb(GRilIoChannel *io, int ril_status,
|
||||||
|
|
||||||
static inline struct ril_oem_raw *ril_oem_raw_get_data(
|
|
||||||
struct ofono_oem_raw *raw)
|
|
||||||
{
|
|
||||||
return ofono_oem_raw_get_data(raw);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct ril_oem_raw_cbd *ril_oem_raw_cbd_new(ofono_oem_raw_query_cb_t cb,
|
|
||||||
void *data)
|
|
||||||
{
|
|
||||||
struct ril_oem_raw_cbd *cbd = g_new0(struct ril_oem_raw_cbd, 1);
|
|
||||||
|
|
||||||
cbd->cb = cb;
|
|
||||||
cbd->data = data;
|
|
||||||
return cbd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ril_oem_raw_request_cb(GRilIoChannel *io, int status,
|
|
||||||
const void *data, guint len, void *user_data)
|
const void *data, guint len, void *user_data)
|
||||||
{
|
{
|
||||||
struct ofono_error error;
|
DBusMessage *msg = user_data;
|
||||||
struct ril_oem_raw_cbd *cbd = user_data;
|
DBusMessage *reply;
|
||||||
|
|
||||||
if (status == RIL_E_SUCCESS) {
|
if (ril_status == RIL_E_SUCCESS) {
|
||||||
struct ofono_oem_raw_results result;
|
DBusMessageIter it, array;
|
||||||
|
const guchar* bytes = data;
|
||||||
|
guint i;
|
||||||
|
|
||||||
result.data = (void *)data;
|
reply = dbus_message_new_method_return(msg);
|
||||||
result.length = len;
|
dbus_message_iter_init_append(reply, &it);
|
||||||
cbd->cb(ril_error_ok(&error), &result, cbd->data);
|
dbus_message_iter_open_container(&it, DBUS_TYPE_ARRAY,
|
||||||
|
DBUS_TYPE_BYTE_AS_STRING, &array);
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
guchar byte = bytes[i];
|
||||||
|
dbus_message_iter_append_basic(&array, DBUS_TYPE_BYTE,
|
||||||
|
&byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbus_message_iter_close_container(&it, &array);
|
||||||
|
} else if (ril_status == GRILIO_STATUS_TIMEOUT) {
|
||||||
|
DBG("Timed out");
|
||||||
|
reply = __ofono_error_timed_out(msg);
|
||||||
} else {
|
} else {
|
||||||
DBG("error:%d len:%d ", status, len);
|
DBG("Error %s", ril_error_to_string(ril_status));
|
||||||
cbd->cb(ril_error_failure(&error), NULL, cbd->data);
|
reply = __ofono_error_failed(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
__ofono_dbus_pending_reply(&msg, reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DBusMessage *ril_oem_raw_send(DBusConnection *conn, DBusMessage *msg,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
DBusMessageIter it;
|
||||||
|
struct ril_oem_raw *oem = user_data;
|
||||||
|
|
||||||
|
dbus_message_iter_init(msg, &it);
|
||||||
|
if (dbus_message_iter_get_arg_type(&it) == DBUS_TYPE_ARRAY &&
|
||||||
|
dbus_message_iter_get_element_type(&it) == DBUS_TYPE_BYTE) {
|
||||||
|
char *data;
|
||||||
|
int data_len;
|
||||||
|
DBusMessageIter array;
|
||||||
|
GRilIoRequest *req;
|
||||||
|
|
||||||
|
/* Fetch the data */
|
||||||
|
dbus_message_iter_recurse(&it, &array);
|
||||||
|
dbus_message_iter_get_fixed_array(&array, &data, &data_len);
|
||||||
|
DBG_(oem, "%d bytes", data_len);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* And forward it to rild. Set a timeout because rild may
|
||||||
|
* never respond to invalid requests.
|
||||||
|
*/
|
||||||
|
req = grilio_request_sized_new(data_len);
|
||||||
|
grilio_request_set_timeout(req, RIL_OEM_RAW_TIMEOUT);
|
||||||
|
grilio_request_append_bytes(req, data, data_len);
|
||||||
|
grilio_queue_send_request_full(oem->q, req,
|
||||||
|
RIL_REQUEST_OEM_HOOK_RAW, ril_oem_raw_send_cb,
|
||||||
|
NULL, dbus_message_ref(msg));
|
||||||
|
grilio_request_unref(req);
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
DBG_(oem, "Unexpected signature");
|
||||||
|
return __ofono_error_invalid_args(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_oem_raw_request(struct ofono_oem_raw *raw,
|
static const GDBusMethodTable ril_oem_raw_methods[] = {
|
||||||
const struct ofono_oem_raw_request *request,
|
{ GDBUS_ASYNC_METHOD("Send",
|
||||||
ofono_oem_raw_query_cb_t cb, void *data)
|
GDBUS_ARGS({ "request", "ay" }),
|
||||||
{
|
GDBUS_ARGS({ "response", "ay" }),
|
||||||
struct ril_oem_raw *od = ril_oem_raw_get_data(raw);
|
ril_oem_raw_send) },
|
||||||
GRilIoRequest *req = grilio_request_sized_new(request->length);
|
{ }
|
||||||
|
|
||||||
grilio_request_append_bytes(req, request->data, request->length);
|
|
||||||
grilio_queue_send_request_full(od->q, req, RIL_REQUEST_OEM_HOOK_RAW,
|
|
||||||
ril_oem_raw_request_cb, ril_oem_raw_cbd_free,
|
|
||||||
ril_oem_raw_cbd_new(cb, data));
|
|
||||||
grilio_request_unref(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean ril_oem_raw_register(gpointer user_data)
|
|
||||||
{
|
|
||||||
struct ofono_oem_raw *raw = user_data;
|
|
||||||
struct ril_oem_raw *od = ril_oem_raw_get_data(raw);
|
|
||||||
|
|
||||||
DBG("");
|
|
||||||
GASSERT(od->timer_id);
|
|
||||||
od->timer_id = 0;
|
|
||||||
ofono_oem_raw_dbus_register(raw);
|
|
||||||
|
|
||||||
/* Single-shot */
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ril_oem_raw_probe(struct ofono_oem_raw *raw, unsigned int vendor,
|
|
||||||
void *data)
|
|
||||||
{
|
|
||||||
struct ril_modem *modem = data;
|
|
||||||
struct ril_oem_raw *od = g_new0(struct ril_oem_raw, 1);
|
|
||||||
|
|
||||||
DBG("");
|
|
||||||
od->q = grilio_queue_new(ril_modem_io(modem));
|
|
||||||
od->timer_id = g_idle_add(ril_oem_raw_register, raw);
|
|
||||||
ofono_oem_raw_set_data(raw, od);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ril_oem_raw_remove(struct ofono_oem_raw *raw)
|
|
||||||
{
|
|
||||||
struct ril_oem_raw *od = ril_oem_raw_get_data(raw);
|
|
||||||
|
|
||||||
DBG("");
|
|
||||||
grilio_queue_cancel_all(od->q, TRUE);
|
|
||||||
ofono_oem_raw_set_data(raw, NULL);
|
|
||||||
|
|
||||||
if (od->timer_id) {
|
|
||||||
g_source_remove(od->timer_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
grilio_queue_unref(od->q);
|
|
||||||
g_free(od);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* const */ struct ofono_oem_raw_driver ril_oem_raw_driver = {
|
|
||||||
.name = RILMODEM_DRIVER,
|
|
||||||
.probe = ril_oem_raw_probe,
|
|
||||||
.remove = ril_oem_raw_remove,
|
|
||||||
.request = ril_oem_raw_request,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ril_oem_raw *ril_oem_raw_new(struct ril_modem *modem,
|
||||||
|
const char *log_prefix)
|
||||||
|
{
|
||||||
|
struct ril_oem_raw *oem = g_new0(struct ril_oem_raw, 1);
|
||||||
|
|
||||||
|
DBG("%s", ril_modem_get_path(modem));
|
||||||
|
oem->modem = modem;
|
||||||
|
oem->path = g_strdup(ril_modem_get_path(modem));
|
||||||
|
oem->conn = dbus_connection_ref(ofono_dbus_get_connection());
|
||||||
|
oem->q = grilio_queue_new(ril_modem_io(modem));
|
||||||
|
oem->log_prefix = (log_prefix && log_prefix[0]) ?
|
||||||
|
g_strconcat(log_prefix, " ", NULL) : g_strdup("");
|
||||||
|
|
||||||
|
/* Register D-Bus interface */
|
||||||
|
if (g_dbus_register_interface(oem->conn, oem->path,
|
||||||
|
RIL_OEM_RAW_INTERFACE, ril_oem_raw_methods,
|
||||||
|
NULL, NULL, oem, NULL)) {
|
||||||
|
ofono_modem_add_interface(modem->ofono, RIL_OEM_RAW_INTERFACE);
|
||||||
|
return oem;
|
||||||
|
} else {
|
||||||
|
ofono_error("OemRaw D-Bus register failed");
|
||||||
|
ril_oem_raw_free(oem);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ril_oem_raw_free(struct ril_oem_raw *oem)
|
||||||
|
{
|
||||||
|
if (oem) {
|
||||||
|
DBG("%s", oem->path);
|
||||||
|
g_dbus_unregister_interface(oem->conn, oem->path,
|
||||||
|
RIL_OEM_RAW_INTERFACE);
|
||||||
|
ofono_modem_remove_interface(oem->modem->ofono,
|
||||||
|
RIL_OEM_RAW_INTERFACE);
|
||||||
|
dbus_connection_unref(oem->conn);
|
||||||
|
|
||||||
|
grilio_queue_cancel_all(oem->q, TRUE);
|
||||||
|
grilio_queue_unref(oem->q);
|
||||||
|
|
||||||
|
g_free(oem->log_prefix);
|
||||||
|
g_free(oem->path);
|
||||||
|
g_free(oem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local Variables:
|
* Local Variables:
|
||||||
* mode: C
|
* mode: C
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -14,7 +14,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ril_plugin.h"
|
#include "ril_plugin.h"
|
||||||
|
#include "ril_config.h"
|
||||||
#include "ril_sim_card.h"
|
#include "ril_sim_card.h"
|
||||||
|
#include "ril_sim_info.h"
|
||||||
|
#include "ril_sim_settings.h"
|
||||||
|
#include "ril_cell_info.h"
|
||||||
#include "ril_network.h"
|
#include "ril_network.h"
|
||||||
#include "ril_radio.h"
|
#include "ril_radio.h"
|
||||||
#include "ril_data.h"
|
#include "ril_data.h"
|
||||||
@@ -46,6 +50,10 @@
|
|||||||
#define RILMODEM_DEFAULT_SLOT 0xffffffff
|
#define RILMODEM_DEFAULT_SLOT 0xffffffff
|
||||||
#define RILMODEM_DEFAULT_TIMEOUT 0 /* No timeout */
|
#define RILMODEM_DEFAULT_TIMEOUT 0 /* No timeout */
|
||||||
#define RILMODEM_DEFAULT_SIM_FLAGS RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND
|
#define RILMODEM_DEFAULT_SIM_FLAGS RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND
|
||||||
|
#define RILMODEM_DEFAULT_DATA_OPT RIL_ALLOW_DATA_AUTO
|
||||||
|
#define RILMODEM_DEFAULT_DM_FLAGS RIL_DATA_MANAGER_3GLTE_HANDOVER
|
||||||
|
|
||||||
|
#define RILCONF_SETTINGS_3GHANDOVER "3GLTEHandover"
|
||||||
|
|
||||||
#define RILCONF_DEV_PREFIX "ril_"
|
#define RILCONF_DEV_PREFIX "ril_"
|
||||||
#define RILCONF_PATH_PREFIX "/" RILCONF_DEV_PREFIX
|
#define RILCONF_PATH_PREFIX "/" RILCONF_DEV_PREFIX
|
||||||
@@ -56,6 +64,8 @@
|
|||||||
#define RILCONF_TIMEOUT "timeout"
|
#define RILCONF_TIMEOUT "timeout"
|
||||||
#define RILCONF_4G "enable4G"
|
#define RILCONF_4G "enable4G"
|
||||||
#define RILCONF_UICC_WORKAROUND "uiccWorkaround"
|
#define RILCONF_UICC_WORKAROUND "uiccWorkaround"
|
||||||
|
#define RILCONF_ECCLIST_FILE "ecclistFile"
|
||||||
|
#define RILCONF_ALLOW_DATA_REQ "allowDataReq"
|
||||||
|
|
||||||
#define RIL_STORE "ril"
|
#define RIL_STORE "ril"
|
||||||
#define RIL_STORE_GROUP "Settings"
|
#define RIL_STORE_GROUP "Settings"
|
||||||
@@ -76,6 +86,9 @@ struct ril_plugin_priv {
|
|||||||
struct ril_plugin pub;
|
struct ril_plugin pub;
|
||||||
struct ril_plugin_dbus *dbus;
|
struct ril_plugin_dbus *dbus;
|
||||||
struct ril_data_manager *data_manager;
|
struct ril_data_manager *data_manager;
|
||||||
|
struct ril_mce *mce;
|
||||||
|
gboolean display_on;
|
||||||
|
gulong display_state_change_id;
|
||||||
GSList *slots;
|
GSList *slots;
|
||||||
ril_slot_info_ptr *slots_info;
|
ril_slot_info_ptr *slots_info;
|
||||||
struct ril_slot *voice_slot;
|
struct ril_slot *voice_slot;
|
||||||
@@ -94,19 +107,25 @@ struct ril_slot {
|
|||||||
char *name;
|
char *name;
|
||||||
char *sockpath;
|
char *sockpath;
|
||||||
char *sub;
|
char *sub;
|
||||||
gint timeout; /* RIL timeout, in milliseconds */
|
char *ecclist_file;
|
||||||
|
int timeout; /* RIL timeout, in milliseconds */
|
||||||
int index;
|
int index;
|
||||||
int sim_flags;
|
int sim_flags;
|
||||||
gboolean online;
|
enum ril_data_allow_data_opt allow_data_opt;
|
||||||
struct ril_slot_config config;
|
struct ril_slot_config config;
|
||||||
struct ril_plugin_priv *plugin;
|
struct ril_plugin_priv *plugin;
|
||||||
struct ril_sim_dbus *sim_dbus;
|
|
||||||
struct ril_modem *modem;
|
struct ril_modem *modem;
|
||||||
struct ril_mce *mce;
|
struct ril_mce *mce;
|
||||||
struct ofono_sim *sim;
|
struct ofono_sim *sim;
|
||||||
struct ril_radio *radio;
|
struct ril_radio *radio;
|
||||||
struct ril_network *network;
|
struct ril_network *network;
|
||||||
struct ril_sim_card *sim_card;
|
struct ril_sim_card *sim_card;
|
||||||
|
struct ril_sim_info *sim_info;
|
||||||
|
struct ril_sim_info_dbus *sim_info_dbus;
|
||||||
|
struct ril_sim_settings *sim_settings;
|
||||||
|
struct ril_cell_info *cell_info;
|
||||||
|
struct ril_cell_info_dbus *cell_info_dbus;
|
||||||
|
struct ril_oem_raw *oem_raw;
|
||||||
struct ril_data *data;
|
struct ril_data *data;
|
||||||
GRilIoChannel *io;
|
GRilIoChannel *io;
|
||||||
gulong io_event_id[IO_EVENT_COUNT];
|
gulong io_event_id[IO_EVENT_COUNT];
|
||||||
@@ -120,22 +139,36 @@ struct ril_slot {
|
|||||||
enum ofono_sim_state sim_state;
|
enum ofono_sim_state sim_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ril_plugin_settings {
|
||||||
|
int dm_flags;
|
||||||
|
};
|
||||||
|
|
||||||
static void ril_debug_trace_notify(struct ofono_debug_desc *desc);
|
static void ril_debug_trace_notify(struct ofono_debug_desc *desc);
|
||||||
static void ril_debug_dump_notify(struct ofono_debug_desc *desc);
|
static void ril_debug_dump_notify(struct ofono_debug_desc *desc);
|
||||||
static void ril_debug_grilio_notify(struct ofono_debug_desc *desc);
|
static void ril_debug_grilio_notify(struct ofono_debug_desc *desc);
|
||||||
|
static void ril_plugin_debug_notify(struct ofono_debug_desc *desc);
|
||||||
static void ril_plugin_retry_init_io(struct ril_slot *slot);
|
static void ril_plugin_retry_init_io(struct ril_slot *slot);
|
||||||
|
|
||||||
GLOG_MODULE_DEFINE("rilmodem");
|
GLOG_MODULE_DEFINE("rilmodem");
|
||||||
|
|
||||||
|
static const char ril_debug_trace_name[] = "ril_trace";
|
||||||
|
|
||||||
|
static GLogModule ril_debug_trace_module = {
|
||||||
|
.name = ril_debug_trace_name,
|
||||||
|
.max_level = GLOG_LEVEL_VERBOSE,
|
||||||
|
.level = GLOG_LEVEL_VERBOSE,
|
||||||
|
.flags = GLOG_FLAG_HIDE_NAME
|
||||||
|
};
|
||||||
|
|
||||||
static struct ofono_debug_desc ril_debug_trace OFONO_DEBUG_ATTR = {
|
static struct ofono_debug_desc ril_debug_trace OFONO_DEBUG_ATTR = {
|
||||||
.name = "ril_trace",
|
.name = ril_debug_trace_name,
|
||||||
.flags = OFONO_DEBUG_FLAG_DEFAULT,
|
.flags = OFONO_DEBUG_FLAG_DEFAULT | OFONO_DEBUG_FLAG_HIDE_NAME,
|
||||||
.notify = ril_debug_trace_notify
|
.notify = ril_debug_trace_notify
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct ofono_debug_desc ril_debug_dump OFONO_DEBUG_ATTR = {
|
static struct ofono_debug_desc ril_debug_dump OFONO_DEBUG_ATTR = {
|
||||||
.name = "ril_dump",
|
.name = "ril_dump",
|
||||||
.flags = OFONO_DEBUG_FLAG_DEFAULT,
|
.flags = OFONO_DEBUG_FLAG_DEFAULT | OFONO_DEBUG_FLAG_HIDE_NAME,
|
||||||
.notify = ril_debug_dump_notify
|
.notify = ril_debug_dump_notify
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -145,6 +178,12 @@ static struct ofono_debug_desc grilio_debug OFONO_DEBUG_ATTR = {
|
|||||||
.notify = ril_debug_grilio_notify
|
.notify = ril_debug_grilio_notify
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct ofono_debug_desc ril_plugin_debug OFONO_DEBUG_ATTR = {
|
||||||
|
.name = "ril_plugin",
|
||||||
|
.flags = OFONO_DEBUG_FLAG_DEFAULT,
|
||||||
|
.notify = ril_plugin_debug_notify
|
||||||
|
};
|
||||||
|
|
||||||
static struct ril_plugin_priv *ril_plugin_cast(struct ril_plugin *pub)
|
static struct ril_plugin_priv *ril_plugin_cast(struct ril_plugin *pub)
|
||||||
{
|
{
|
||||||
return G_CAST(pub, struct ril_plugin_priv, pub);
|
return G_CAST(pub, struct ril_plugin_priv, pub);
|
||||||
@@ -167,6 +206,29 @@ static void ril_plugin_foreach_slot(struct ril_plugin_priv *plugin,
|
|||||||
g_slist_foreach(plugin->slots, ril_plugin_foreach_slot_proc, fn);
|
g_slist_foreach(plugin->slots, ril_plugin_foreach_slot_proc, fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ril_plugin_send_screen_state(struct ril_slot *slot)
|
||||||
|
{
|
||||||
|
if (slot->io) {
|
||||||
|
GRilIoRequest *req = grilio_request_sized_new(8);
|
||||||
|
grilio_request_append_int32(req, 1); /* Number of params */
|
||||||
|
grilio_request_append_int32(req, slot->plugin->display_on);
|
||||||
|
grilio_channel_send_request(slot->io, req,
|
||||||
|
RIL_REQUEST_SCREEN_STATE);
|
||||||
|
grilio_request_unref(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_plugin_display_state_cb(struct ril_mce *mce, void *user_data)
|
||||||
|
{
|
||||||
|
struct ril_plugin_priv *plugin = user_data;
|
||||||
|
const gboolean display_was_on = plugin->display_on;
|
||||||
|
|
||||||
|
plugin->display_on = (mce->display_state != RIL_MCE_DISPLAY_OFF);
|
||||||
|
if (plugin->display_on != display_was_on) {
|
||||||
|
ril_plugin_foreach_slot(plugin, ril_plugin_send_screen_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void ril_plugin_remove_slot_handler(struct ril_slot *slot, int id)
|
static void ril_plugin_remove_slot_handler(struct ril_slot *slot, int id)
|
||||||
{
|
{
|
||||||
GASSERT(id >= 0 && id<IO_EVENT_COUNT);
|
GASSERT(id >= 0 && id<IO_EVENT_COUNT);
|
||||||
@@ -176,14 +238,22 @@ static void ril_plugin_remove_slot_handler(struct ril_slot *slot, int id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ril_plugin_update_ofono_sim(struct ril_slot *slot)
|
||||||
|
{
|
||||||
|
ril_sim_settings_set_ofono_sim(slot->sim_settings, slot->sim);
|
||||||
|
ril_sim_info_set_ofono_sim(slot->sim_info, slot->sim);
|
||||||
|
}
|
||||||
|
|
||||||
static void ril_plugin_shutdown_slot(struct ril_slot *slot, gboolean kill_io)
|
static void ril_plugin_shutdown_slot(struct ril_slot *slot, gboolean kill_io)
|
||||||
{
|
{
|
||||||
if (slot->sim) {
|
if (slot->sim) {
|
||||||
if (slot->sim_state_watch_id) {
|
if (slot->sim_state_watch_id) {
|
||||||
ofono_sim_remove_state_watch(slot->sim,
|
ofono_sim_remove_state_watch(slot->sim,
|
||||||
slot->sim_state_watch_id);
|
slot->sim_state_watch_id);
|
||||||
|
GASSERT(!slot->sim_state_watch_id);
|
||||||
}
|
}
|
||||||
slot->sim = NULL;
|
slot->sim = NULL;
|
||||||
|
ril_plugin_update_ofono_sim(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slot->modem) {
|
if (slot->modem) {
|
||||||
@@ -205,18 +275,18 @@ static void ril_plugin_shutdown_slot(struct ril_slot *slot, gboolean kill_io)
|
|||||||
GASSERT(!slot->sim_watch_id);
|
GASSERT(!slot->sim_watch_id);
|
||||||
|
|
||||||
if (kill_io) {
|
if (kill_io) {
|
||||||
if (slot->mce) {
|
|
||||||
ril_mce_free(slot->mce);
|
|
||||||
slot->mce = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (slot->retry_id) {
|
if (slot->retry_id) {
|
||||||
g_source_remove(slot->retry_id);
|
g_source_remove(slot->retry_id);
|
||||||
slot->retry_id = 0;
|
slot->retry_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (slot->cell_info) {
|
||||||
|
ril_cell_info_unref(slot->cell_info);
|
||||||
|
slot->cell_info = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (slot->data) {
|
if (slot->data) {
|
||||||
ril_data_allow(slot->data, FALSE);
|
ril_data_allow(slot->data, RIL_DATA_ROLE_NONE);
|
||||||
ril_data_unref(slot->data);
|
ril_data_unref(slot->data);
|
||||||
slot->data = NULL;
|
slot->data = NULL;
|
||||||
}
|
}
|
||||||
@@ -227,6 +297,7 @@ static void ril_plugin_shutdown_slot(struct ril_slot *slot, gboolean kill_io)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (slot->network) {
|
if (slot->network) {
|
||||||
|
ril_sim_info_set_network(slot->sim_info, slot->network);
|
||||||
ril_network_unref(slot->network);
|
ril_network_unref(slot->network);
|
||||||
slot->network = NULL;
|
slot->network = NULL;
|
||||||
}
|
}
|
||||||
@@ -378,7 +449,7 @@ static int ril_plugin_update_modem_paths(struct ril_plugin_priv *plugin)
|
|||||||
slot = ril_plugin_find_slot_imsi(plugin->slots, NULL);
|
slot = ril_plugin_find_slot_imsi(plugin->slots, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slot && !slot->online) {
|
if (slot && !slot->radio->online) {
|
||||||
slot = NULL;
|
slot = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -426,10 +497,12 @@ static int ril_plugin_update_modem_paths(struct ril_plugin_priv *plugin)
|
|||||||
if (old_data_slot != new_data_slot) {
|
if (old_data_slot != new_data_slot) {
|
||||||
/* Yes we are switching data SIMs */
|
/* Yes we are switching data SIMs */
|
||||||
if (old_data_slot) {
|
if (old_data_slot) {
|
||||||
ril_data_allow(old_data_slot->data, FALSE);
|
ril_data_allow(old_data_slot->data, RIL_DATA_ROLE_NONE);
|
||||||
}
|
}
|
||||||
if (new_data_slot) {
|
if (new_data_slot) {
|
||||||
ril_data_allow(new_data_slot->data, TRUE);
|
ril_data_allow(new_data_slot->data,
|
||||||
|
(new_data_slot == plugin->data_slot) ?
|
||||||
|
RIL_DATA_ROLE_INTERNET : RIL_DATA_ROLE_MMS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,25 +516,32 @@ static void ril_plugin_update_modem_paths_full(struct ril_plugin_priv *plugin)
|
|||||||
ril_plugin_update_modem_paths(plugin));
|
ril_plugin_update_modem_paths(plugin));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_plugin_check_sim_state(struct ril_slot *slot)
|
static void ril_plugin_update_ready(struct ril_plugin_priv *plugin)
|
||||||
{
|
{
|
||||||
const char *slot_imsi = ofono_sim_get_imsi(slot->sim);
|
GSList *link;
|
||||||
const char *dbus_imsi = ril_sim_dbus_imsi(slot->sim_dbus);
|
gboolean ready = TRUE;
|
||||||
|
|
||||||
if (!slot_imsi) {
|
for (link = plugin->slots; link; link = link->next) {
|
||||||
if (slot->sim_dbus) {
|
struct ril_slot *slot = link->data;
|
||||||
ril_sim_dbus_free(slot->sim_dbus);
|
|
||||||
slot->sim_dbus = NULL;
|
if (!slot->imei || !slot->sim_card || !slot->sim_card->status) {
|
||||||
|
ready = FALSE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else if (g_strcmp0(slot_imsi, dbus_imsi)) {
|
}
|
||||||
ril_sim_dbus_free(slot->sim_dbus);
|
|
||||||
slot->sim_dbus = ril_sim_dbus_new(slot->modem);
|
if (plugin->pub.ready != ready) {
|
||||||
|
plugin->pub.ready = ready;
|
||||||
|
ril_plugin_dbus_block_imei_requests(plugin->dbus, !ready);
|
||||||
|
DBG("%sready", ready ? "" : "not ");
|
||||||
|
ril_plugin_dbus_signal(plugin->dbus, RIL_PLUGIN_SIGNAL_READY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_plugin_sim_state_changed(struct ril_sim_card *card, void *data)
|
static void ril_plugin_sim_state_changed(struct ril_sim_card *card, void *data)
|
||||||
{
|
{
|
||||||
struct ril_slot *slot = data;
|
struct ril_slot *slot = data;
|
||||||
|
struct ril_plugin_priv *plugin = slot->plugin;
|
||||||
gboolean present;
|
gboolean present;
|
||||||
|
|
||||||
if (card && card->status &&
|
if (card && card->status &&
|
||||||
@@ -475,9 +555,10 @@ static void ril_plugin_sim_state_changed(struct ril_sim_card *card, void *data)
|
|||||||
|
|
||||||
if (slot->pub.sim_present != present) {
|
if (slot->pub.sim_present != present) {
|
||||||
slot->pub.sim_present = present;
|
slot->pub.sim_present = present;
|
||||||
ril_plugin_dbus_signal_sim(slot->plugin->dbus,
|
ril_plugin_dbus_signal_sim(plugin->dbus, slot->index, present);
|
||||||
slot->index, present);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ril_plugin_update_ready(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_plugin_sim_watch_done(void *data)
|
static void ril_plugin_sim_watch_done(void *data)
|
||||||
@@ -498,11 +579,42 @@ static void ril_plugin_sim_state_watch(enum ofono_sim_state new_state,
|
|||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
struct ril_slot *slot = data;
|
struct ril_slot *slot = data;
|
||||||
|
struct ril_plugin_priv *plugin = slot->plugin;
|
||||||
|
|
||||||
DBG("%s sim state %d", slot->path + 1, new_state);
|
DBG("%s sim state %d", slot->path + 1, new_state);
|
||||||
slot->sim_state = new_state;
|
slot->sim_state = new_state;
|
||||||
ril_plugin_check_sim_state(slot);
|
if (new_state == OFONO_SIM_STATE_READY) {
|
||||||
ril_plugin_update_modem_paths_full(slot->plugin);
|
struct ril_slot *voice_slot = plugin->voice_slot;
|
||||||
|
struct ril_slot *data_slot = plugin->data_slot;
|
||||||
|
int signal_mask;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OFONO_SIM_STATE_READY means that pin code has been
|
||||||
|
* entered (if necessary) and IMSI has been obtained.
|
||||||
|
*
|
||||||
|
* We want the first slot to be selected by default.
|
||||||
|
* However, things may become available in pretty much
|
||||||
|
* any order, so reset the slot pointers to NULL and let
|
||||||
|
* ril_plugin_update_modem_paths() to pick them again.
|
||||||
|
*
|
||||||
|
* Only affects the very first boot and first boot after
|
||||||
|
* the default voice SIM has been removed.
|
||||||
|
*/
|
||||||
|
plugin->voice_slot = NULL;
|
||||||
|
plugin->data_slot = NULL;
|
||||||
|
signal_mask = ril_plugin_update_modem_paths(plugin);
|
||||||
|
if (voice_slot != plugin->voice_slot) {
|
||||||
|
DBG("Voice slot changed");
|
||||||
|
signal_mask |= RIL_PLUGIN_SIGNAL_VOICE_PATH;
|
||||||
|
}
|
||||||
|
if (data_slot != plugin->data_slot) {
|
||||||
|
DBG("Data slot changed");
|
||||||
|
signal_mask |= RIL_PLUGIN_SIGNAL_DATA_PATH;
|
||||||
|
}
|
||||||
|
ril_plugin_dbus_signal(plugin->dbus, signal_mask);
|
||||||
|
} else {
|
||||||
|
ril_plugin_update_modem_paths_full(plugin);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_plugin_register_sim(struct ril_slot *slot, struct ofono_sim *sim)
|
static void ril_plugin_register_sim(struct ril_slot *slot, struct ofono_sim *sim)
|
||||||
@@ -511,6 +623,7 @@ static void ril_plugin_register_sim(struct ril_slot *slot, struct ofono_sim *sim
|
|||||||
GASSERT(!slot->sim);
|
GASSERT(!slot->sim);
|
||||||
GASSERT(slot->sim_watch_id);
|
GASSERT(slot->sim_watch_id);
|
||||||
GASSERT(!slot->sim_state_watch_id);
|
GASSERT(!slot->sim_state_watch_id);
|
||||||
|
|
||||||
slot->sim = sim;
|
slot->sim = sim;
|
||||||
slot->sim_state = ofono_sim_get_state(sim);
|
slot->sim_state = ofono_sim_get_state(sim);
|
||||||
slot->sim_state_watch_id = ofono_sim_add_state_watch(sim,
|
slot->sim_state_watch_id = ofono_sim_add_state_watch(sim,
|
||||||
@@ -531,7 +644,7 @@ static void ril_plugin_sim_watch(struct ofono_atom *atom,
|
|||||||
slot->sim = NULL;
|
slot->sim = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ril_plugin_check_sim_state(slot);
|
ril_plugin_update_ofono_sim(slot);
|
||||||
ril_plugin_update_modem_paths_full(slot->plugin);
|
ril_plugin_update_modem_paths_full(slot->plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,7 +675,7 @@ static void ril_plugin_modem_online(struct ril_modem *modem, gboolean online,
|
|||||||
GASSERT(slot->modem);
|
GASSERT(slot->modem);
|
||||||
GASSERT(slot->modem == modem);
|
GASSERT(slot->modem == modem);
|
||||||
|
|
||||||
slot->online = online;
|
ril_radio_set_online(slot->radio, online);
|
||||||
ril_plugin_update_modem_paths_full(slot->plugin);
|
ril_plugin_update_modem_paths_full(slot->plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,22 +687,31 @@ static void ril_plugin_modem_removed(struct ril_modem *modem, void *data)
|
|||||||
GASSERT(slot->modem);
|
GASSERT(slot->modem);
|
||||||
GASSERT(slot->modem == modem);
|
GASSERT(slot->modem == modem);
|
||||||
|
|
||||||
if (slot->sim_dbus) {
|
if (slot->oem_raw) {
|
||||||
ril_sim_dbus_free(slot->sim_dbus);
|
ril_oem_raw_free(slot->oem_raw);
|
||||||
slot->sim_dbus = NULL;
|
slot->oem_raw = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slot->sim_info_dbus) {
|
||||||
|
ril_sim_info_dbus_free(slot->sim_info_dbus);
|
||||||
|
slot->sim_info_dbus = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slot->cell_info_dbus) {
|
||||||
|
ril_cell_info_dbus_free(slot->cell_info_dbus);
|
||||||
|
slot->cell_info_dbus = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
slot->modem = NULL;
|
slot->modem = NULL;
|
||||||
slot->online = FALSE;
|
ril_radio_set_online(slot->radio, FALSE);
|
||||||
ril_data_allow(slot->data, FALSE);
|
ril_data_allow(slot->data, RIL_DATA_ROLE_NONE);
|
||||||
ril_plugin_update_modem_paths_full(slot->plugin);
|
ril_plugin_update_modem_paths_full(slot->plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_plugin_trace(GRilIoChannel *io, GRILIO_PACKET_TYPE type,
|
static void ril_plugin_trace(GRilIoChannel *io, GRILIO_PACKET_TYPE type,
|
||||||
guint id, guint code, const void *data, guint data_len, void *user_data)
|
guint id, guint code, const void *data, guint data_len, void *user_data)
|
||||||
{
|
{
|
||||||
/* Use log sub-module to turn prefix off */
|
static const GLogModule* log_module = &ril_debug_trace_module;
|
||||||
static GLOG_MODULE_DEFINE2_(log_module, NULL, GLOG_MODULE_NAME);
|
|
||||||
const char *prefix = io->name ? io->name : "";
|
const char *prefix = io->name ? io->name : "";
|
||||||
const char dir = (type == GRILIO_PACKET_REQ) ? '<' : '>';
|
const char dir = (type == GRILIO_PACKET_REQ) ? '<' : '>';
|
||||||
const char *scode;
|
const char *scode;
|
||||||
@@ -602,28 +724,28 @@ static void ril_plugin_trace(GRilIoChannel *io, GRILIO_PACKET_TYPE type,
|
|||||||
} else {
|
} else {
|
||||||
scode = ril_request_to_string(code);
|
scode = ril_request_to_string(code);
|
||||||
}
|
}
|
||||||
gutil_log(&log_module, GLOG_LEVEL_INFO, "%s%c [%08x] %s",
|
gutil_log(log_module, GLOG_LEVEL_VERBOSE, "%s%c [%08x] %s",
|
||||||
prefix, dir, id, scode);
|
prefix, dir, id, scode);
|
||||||
break;
|
break;
|
||||||
case GRILIO_PACKET_RESP:
|
case GRILIO_PACKET_RESP:
|
||||||
gutil_log(&log_module, GLOG_LEVEL_INFO, "%s%c [%08x] %s",
|
gutil_log(log_module, GLOG_LEVEL_VERBOSE, "%s%c [%08x] %s",
|
||||||
prefix, dir, id, ril_error_to_string(code));
|
prefix, dir, id, ril_error_to_string(code));
|
||||||
break;
|
break;
|
||||||
case GRILIO_PACKET_UNSOL:
|
case GRILIO_PACKET_UNSOL:
|
||||||
gutil_log(&log_module, GLOG_LEVEL_INFO, "%s%c %s",
|
gutil_log(log_module, GLOG_LEVEL_VERBOSE, "%s%c %s",
|
||||||
prefix, dir, ril_unsol_event_to_string(code));
|
prefix, dir, ril_unsol_event_to_string(code));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_debug_dump_update_slot(struct ril_slot *slot)
|
static void ril_debug_dump_update(struct ril_slot *slot)
|
||||||
{
|
{
|
||||||
if (slot->io) {
|
if (slot->io) {
|
||||||
if (ril_debug_dump.flags & OFONO_DEBUG_FLAG_PRINT) {
|
if (ril_debug_dump.flags & OFONO_DEBUG_FLAG_PRINT) {
|
||||||
if (!slot->dump_id) {
|
if (!slot->dump_id) {
|
||||||
slot->dump_id =
|
slot->dump_id =
|
||||||
grilio_channel_add_default_logger(
|
grilio_channel_add_default_logger(
|
||||||
slot->io, GLOG_LEVEL_INFO);
|
slot->io, GLOG_LEVEL_VERBOSE);
|
||||||
}
|
}
|
||||||
} else if (slot->dump_id) {
|
} else if (slot->dump_id) {
|
||||||
grilio_channel_remove_logger(slot->io, slot->dump_id);
|
grilio_channel_remove_logger(slot->io, slot->dump_id);
|
||||||
@@ -632,7 +754,7 @@ static void ril_debug_dump_update_slot(struct ril_slot *slot)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_debug_trace_update_slot(struct ril_slot *slot)
|
static void ril_debug_trace_update(struct ril_slot *slot)
|
||||||
{
|
{
|
||||||
if (slot->io) {
|
if (slot->io) {
|
||||||
if (ril_debug_trace.flags & OFONO_DEBUG_FLAG_PRINT) {
|
if (ril_debug_trace.flags & OFONO_DEBUG_FLAG_PRINT) {
|
||||||
@@ -650,7 +772,7 @@ static void ril_debug_trace_update_slot(struct ril_slot *slot)
|
|||||||
slot->dump_id);
|
slot->dump_id);
|
||||||
slot->dump_id = 0;
|
slot->dump_id = 0;
|
||||||
}
|
}
|
||||||
ril_debug_dump_update_slot(slot);
|
ril_debug_dump_update(slot);
|
||||||
}
|
}
|
||||||
} else if (slot->trace_id) {
|
} else if (slot->trace_id) {
|
||||||
grilio_channel_remove_logger(slot->io, slot->trace_id);
|
grilio_channel_remove_logger(slot->io, slot->trace_id);
|
||||||
@@ -659,9 +781,9 @@ static void ril_debug_trace_update_slot(struct ril_slot *slot)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean ril_plugin_can_create_modem(struct ril_slot *slot)
|
static const char *ril_plugin_log_prefix(struct ril_slot *slot)
|
||||||
{
|
{
|
||||||
return slot->pub.enabled && slot->io && slot->io->connected;
|
return ril_plugin_multisim(slot->plugin) ? (slot->path + 1) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_plugin_create_modem(struct ril_slot *slot)
|
static void ril_plugin_create_modem(struct ril_slot *slot)
|
||||||
@@ -672,8 +794,9 @@ static void ril_plugin_create_modem(struct ril_slot *slot)
|
|||||||
GASSERT(slot->io && slot->io->connected);
|
GASSERT(slot->io && slot->io->connected);
|
||||||
GASSERT(!slot->modem);
|
GASSERT(!slot->modem);
|
||||||
|
|
||||||
modem = ril_modem_create(slot->io, &slot->pub, slot->radio,
|
modem = ril_modem_create(slot->io, ril_plugin_log_prefix(slot),
|
||||||
slot->network, slot->sim_card, slot->data);
|
&slot->pub, slot->radio, slot->network, slot->sim_card,
|
||||||
|
slot->data, slot->sim_settings);
|
||||||
|
|
||||||
if (modem) {
|
if (modem) {
|
||||||
struct ofono_sim *sim = ril_modem_ofono_sim(modem);
|
struct ofono_sim *sim = ril_modem_ofono_sim(modem);
|
||||||
@@ -684,8 +807,20 @@ static void ril_plugin_create_modem(struct ril_slot *slot)
|
|||||||
slot, ril_plugin_sim_watch_done);
|
slot, ril_plugin_sim_watch_done);
|
||||||
if (sim) {
|
if (sim) {
|
||||||
ril_plugin_register_sim(slot, sim);
|
ril_plugin_register_sim(slot, sim);
|
||||||
|
ril_plugin_update_ofono_sim(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slot->sim_info_dbus = ril_sim_info_dbus_new(slot->modem,
|
||||||
|
slot->sim_info);
|
||||||
|
if (slot->cell_info) {
|
||||||
|
slot->cell_info_dbus =
|
||||||
|
ril_cell_info_dbus_new(slot->modem,
|
||||||
|
slot->cell_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
slot->oem_raw = ril_oem_raw_new(slot->modem,
|
||||||
|
ril_plugin_log_prefix(slot));
|
||||||
|
|
||||||
ril_modem_set_removed_cb(modem, ril_plugin_modem_removed, slot);
|
ril_modem_set_removed_cb(modem, ril_plugin_modem_removed, slot);
|
||||||
ril_modem_set_online_cb(modem, ril_plugin_modem_online, slot);
|
ril_modem_set_online_cb(modem, ril_plugin_modem_online, slot);
|
||||||
} else {
|
} else {
|
||||||
@@ -695,41 +830,49 @@ static void ril_plugin_create_modem(struct ril_slot *slot)
|
|||||||
ril_plugin_update_modem_paths_full(slot->plugin);
|
ril_plugin_update_modem_paths_full(slot->plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ril_plugin_check_modem(struct ril_slot *slot)
|
||||||
|
{
|
||||||
|
if (!slot->modem && slot->pub.enabled &&
|
||||||
|
slot->io && slot->io->connected &&
|
||||||
|
!slot->imei_req_id && slot->imei) {
|
||||||
|
ril_plugin_create_modem(slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ril_plugin_imei_cb(GRilIoChannel *io, int status,
|
static void ril_plugin_imei_cb(GRilIoChannel *io, int status,
|
||||||
const void *data, guint len, void *user_data)
|
const void *data, guint len, void *user_data)
|
||||||
{
|
{
|
||||||
struct ril_slot *slot = user_data;
|
struct ril_slot *slot = user_data;
|
||||||
struct ril_plugin_priv *plugin = slot->plugin;
|
char *imei = NULL;
|
||||||
gboolean all_done = TRUE;
|
|
||||||
GSList *link;
|
|
||||||
|
|
||||||
GASSERT(!slot->imei);
|
|
||||||
GASSERT(slot->imei_req_id);
|
GASSERT(slot->imei_req_id);
|
||||||
slot->imei_req_id = 0;
|
slot->imei_req_id = 0;
|
||||||
|
|
||||||
if (status == RIL_E_SUCCESS) {
|
if (status == RIL_E_SUCCESS) {
|
||||||
GRilIoParser rilp;
|
GRilIoParser rilp;
|
||||||
|
|
||||||
grilio_parser_init(&rilp, data, len);
|
grilio_parser_init(&rilp, data, len);
|
||||||
slot->pub.imei = slot->imei = grilio_parser_get_utf8(&rilp);
|
imei = grilio_parser_get_utf8(&rilp);
|
||||||
DBG("%s", slot->imei);
|
|
||||||
if (slot->modem) {
|
DBG("%s", imei);
|
||||||
ril_modem_set_imei(slot->modem, slot->imei);
|
|
||||||
}
|
/*
|
||||||
|
* slot->imei should be either NULL (when we get connected
|
||||||
|
* to rild the very first time) or match the already known
|
||||||
|
* IMEI (if rild crashed and we have reconnected)
|
||||||
|
*/
|
||||||
|
GASSERT(!slot->imei || !g_strcmp0(slot->imei, imei));
|
||||||
} else {
|
} else {
|
||||||
ofono_error("Slot %u IMEI query error: %s", slot->config.slot,
|
ofono_error("Slot %u IMEI query error: %s", slot->config.slot,
|
||||||
ril_error_to_string(status));
|
ril_error_to_string(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (link = plugin->slots; link && all_done; link = link->next) {
|
g_free(slot->imei);
|
||||||
if (((struct ril_slot *)link->data)->imei_req_id) {
|
slot->pub.imei = slot->imei = (imei ? imei : g_strdup("ERROR"));
|
||||||
all_done = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (all_done) {
|
ril_plugin_check_modem(slot);
|
||||||
DBG("all done");
|
ril_plugin_update_ready(slot->plugin);
|
||||||
ril_plugin_dbus_block_imei_requests(plugin->dbus, FALSE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -756,22 +899,32 @@ static void ril_plugin_radio_state_changed(GRilIoChannel *io, guint code,
|
|||||||
|
|
||||||
static void ril_plugin_slot_connected(struct ril_slot *slot)
|
static void ril_plugin_slot_connected(struct ril_slot *slot)
|
||||||
{
|
{
|
||||||
|
struct ril_plugin_priv *plugin = slot->plugin;
|
||||||
|
const char *log_prefix = ril_plugin_log_prefix(slot);
|
||||||
|
GRilIoRequest* req;
|
||||||
|
|
||||||
ofono_debug("%s version %u", (slot->name && slot->name[0]) ?
|
ofono_debug("%s version %u", (slot->name && slot->name[0]) ?
|
||||||
slot->name : "RIL", slot->io->ril_version);
|
slot->name : "RIL", slot->io->ril_version);
|
||||||
|
|
||||||
GASSERT(slot->io->connected);
|
GASSERT(slot->io->connected);
|
||||||
GASSERT(!slot->io_event_id[IO_EVENT_CONNECTED]);
|
GASSERT(!slot->io_event_id[IO_EVENT_CONNECTED]);
|
||||||
|
|
||||||
GASSERT(!slot->mce);
|
/*
|
||||||
slot->mce = ril_mce_new(slot->io);
|
* Modem will be registered after RIL_REQUEST_GET_IMEI successfully
|
||||||
|
* completes. By the time ofono starts, rild may not be completely
|
||||||
|
* functional. Waiting until it responds to RIL_REQUEST_GET_IMEI
|
||||||
|
* (and retrying the request on failure) gives rild time to finish
|
||||||
|
* whatever it's doing during initialization.
|
||||||
|
*/
|
||||||
GASSERT(!slot->imei_req_id);
|
GASSERT(!slot->imei_req_id);
|
||||||
slot->imei_req_id = grilio_channel_send_request_full(slot->io, NULL,
|
req = grilio_request_new();
|
||||||
|
grilio_request_set_retry(req, RIL_RETRY_MS, -1);
|
||||||
|
slot->imei_req_id = grilio_channel_send_request_full(slot->io, req,
|
||||||
RIL_REQUEST_GET_IMEI, ril_plugin_imei_cb, NULL, slot);
|
RIL_REQUEST_GET_IMEI, ril_plugin_imei_cb, NULL, slot);
|
||||||
|
grilio_request_unref(req);
|
||||||
|
|
||||||
GASSERT(!slot->radio);
|
GASSERT(!slot->radio);
|
||||||
slot->radio = ril_radio_new(slot->io);
|
slot->radio = ril_radio_new(slot->io);
|
||||||
slot->network = ril_network_new(slot->io, slot->radio);
|
|
||||||
|
|
||||||
GASSERT(!slot->io_event_id[IO_EVENT_RADIO_STATE_CHANGED]);
|
GASSERT(!slot->io_event_id[IO_EVENT_RADIO_STATE_CHANGED]);
|
||||||
slot->io_event_id[IO_EVENT_RADIO_STATE_CHANGED] =
|
slot->io_event_id[IO_EVENT_RADIO_STATE_CHANGED] =
|
||||||
@@ -785,17 +938,24 @@ static void ril_plugin_slot_connected(struct ril_slot *slot)
|
|||||||
slot->sim_card_state_event_id = ril_sim_card_add_state_changed_handler(
|
slot->sim_card_state_event_id = ril_sim_card_add_state_changed_handler(
|
||||||
slot->sim_card, ril_plugin_sim_state_changed, slot);
|
slot->sim_card, ril_plugin_sim_state_changed, slot);
|
||||||
|
|
||||||
|
GASSERT(!slot->network);
|
||||||
|
slot->network = ril_network_new(slot->io, log_prefix, slot->radio,
|
||||||
|
slot->sim_card, slot->sim_settings);
|
||||||
|
ril_sim_info_set_network(slot->sim_info, slot->network);
|
||||||
|
|
||||||
GASSERT(!slot->data);
|
GASSERT(!slot->data);
|
||||||
slot->data = ril_data_new(slot->plugin->data_manager, slot->radio,
|
slot->data = ril_data_new(slot->plugin->data_manager, log_prefix,
|
||||||
slot->network, slot->io);
|
slot->radio, slot->network, slot->io, slot->allow_data_opt);
|
||||||
|
|
||||||
if (ril_plugin_multisim(slot->plugin)) {
|
GASSERT(!slot->cell_info);
|
||||||
ril_data_set_name(slot->data, slot->path + 1);
|
if (slot->io->ril_version > 8) {
|
||||||
|
slot->cell_info = ril_cell_info_new(slot->io, log_prefix,
|
||||||
|
plugin->mce, slot->radio, slot->sim_card);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ril_plugin_can_create_modem(slot) && !slot->modem) {
|
ril_plugin_send_screen_state(slot);
|
||||||
ril_plugin_create_modem(slot);
|
ril_plugin_check_modem(slot);
|
||||||
}
|
ril_plugin_update_ready(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_plugin_slot_connected_cb(GRilIoChannel *io, void *user_data)
|
static void ril_plugin_slot_connected_cb(GRilIoChannel *io, void *user_data)
|
||||||
@@ -812,8 +972,8 @@ static void ril_plugin_init_io(struct ril_slot *slot)
|
|||||||
DBG("%s %s", slot->sockpath, slot->sub);
|
DBG("%s %s", slot->sockpath, slot->sub);
|
||||||
slot->io = grilio_channel_new_socket(slot->sockpath, slot->sub);
|
slot->io = grilio_channel_new_socket(slot->sockpath, slot->sub);
|
||||||
if (slot->io) {
|
if (slot->io) {
|
||||||
ril_debug_trace_update_slot(slot);
|
ril_debug_trace_update(slot);
|
||||||
ril_debug_dump_update_slot(slot);
|
ril_debug_dump_update(slot);
|
||||||
|
|
||||||
if (slot->name) {
|
if (slot->name) {
|
||||||
grilio_channel_set_name(slot->io, slot->name);
|
grilio_channel_set_name(slot->io, slot->name);
|
||||||
@@ -851,7 +1011,8 @@ static gboolean ril_plugin_retry_init_io_cb(gpointer data)
|
|||||||
GASSERT(slot->retry_id);
|
GASSERT(slot->retry_id);
|
||||||
slot->retry_id = 0;
|
slot->retry_id = 0;
|
||||||
ril_plugin_init_io(slot);
|
ril_plugin_init_io(slot);
|
||||||
return FALSE;
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_plugin_retry_init_io(struct ril_slot *slot)
|
static void ril_plugin_retry_init_io(struct ril_slot *slot)
|
||||||
@@ -882,6 +1043,7 @@ static GSList *ril_plugin_create_default_config()
|
|||||||
slot->config.enable_4g = RILMODEM_DEFAULT_4G;
|
slot->config.enable_4g = RILMODEM_DEFAULT_4G;
|
||||||
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
|
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
|
||||||
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
|
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
|
||||||
|
slot->allow_data_opt = RILMODEM_DEFAULT_DATA_OPT;
|
||||||
list = g_slist_append(list, slot);
|
list = g_slist_append(list, slot);
|
||||||
|
|
||||||
slot = g_new0(struct ril_slot, 1);
|
slot = g_new0(struct ril_slot, 1);
|
||||||
@@ -891,6 +1053,7 @@ static GSList *ril_plugin_create_default_config()
|
|||||||
slot->config.enable_4g = RILMODEM_DEFAULT_4G;
|
slot->config.enable_4g = RILMODEM_DEFAULT_4G;
|
||||||
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
|
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
|
||||||
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
|
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
|
||||||
|
slot->allow_data_opt = RILMODEM_DEFAULT_DATA_OPT;
|
||||||
slot->config.slot = 1;
|
slot->config.slot = 1;
|
||||||
list = g_slist_append(list, slot);
|
list = g_slist_append(list, slot);
|
||||||
} else {
|
} else {
|
||||||
@@ -904,6 +1067,7 @@ static GSList *ril_plugin_create_default_config()
|
|||||||
slot->config.enable_4g = RILMODEM_DEFAULT_4G;
|
slot->config.enable_4g = RILMODEM_DEFAULT_4G;
|
||||||
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
|
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
|
||||||
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
|
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
|
||||||
|
slot->allow_data_opt = RILMODEM_DEFAULT_DATA_OPT;
|
||||||
list = g_slist_append(list, slot);
|
list = g_slist_append(list, slot);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -913,20 +1077,6 @@ static GSList *ril_plugin_create_default_config()
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_plugin_read_config_flag(GKeyFile *file, const char *group,
|
|
||||||
const char *key, int flag, int *flags)
|
|
||||||
{
|
|
||||||
GError *err = NULL;
|
|
||||||
|
|
||||||
if (g_key_file_get_boolean(file, group, key, &err)) {
|
|
||||||
*flags |= flag;
|
|
||||||
} else if (!err) {
|
|
||||||
*flags &= ~flag;
|
|
||||||
} else {
|
|
||||||
g_error_free(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
|
static struct ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
|
||||||
const char *group)
|
const char *group)
|
||||||
{
|
{
|
||||||
@@ -934,16 +1084,15 @@ static struct ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
|
|||||||
char *sock = g_key_file_get_string(file, group, RILCONF_SOCKET, NULL);
|
char *sock = g_key_file_get_string(file, group, RILCONF_SOCKET, NULL);
|
||||||
if (sock) {
|
if (sock) {
|
||||||
int value;
|
int value;
|
||||||
GError *err = NULL;
|
char* strval;
|
||||||
char *sub = g_key_file_get_string(file, group, RILCONF_SUB,
|
char *sub = ril_config_get_string(file, group, RILCONF_SUB);
|
||||||
NULL);
|
|
||||||
|
|
||||||
slot = g_new0(struct ril_slot, 1);
|
slot = g_new0(struct ril_slot, 1);
|
||||||
slot->sockpath = sock;
|
slot->sockpath = sock;
|
||||||
slot->path = g_strconcat("/", group, NULL);
|
slot->path = g_strconcat("/", group, NULL);
|
||||||
slot->name = g_key_file_get_string(file, group, RILCONF_NAME,
|
slot->name = ril_config_get_string(file, group, RILCONF_NAME);
|
||||||
NULL);
|
|
||||||
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
|
slot->sim_flags = RILMODEM_DEFAULT_SIM_FLAGS;
|
||||||
|
slot->allow_data_opt = RILMODEM_DEFAULT_DATA_OPT;
|
||||||
|
|
||||||
if (sub && strlen(sub) == RIL_SUB_SIZE) {
|
if (sub && strlen(sub) == RIL_SUB_SIZE) {
|
||||||
DBG("%s: %s:%s", group, sock, sub);
|
DBG("%s: %s:%s", group, sock, sub);
|
||||||
@@ -953,48 +1102,58 @@ static struct ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
|
|||||||
g_free(sub);
|
g_free(sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
value = g_key_file_get_integer(file, group, RILCONF_SLOT, &err);
|
if (ril_config_get_integer(file, group, RILCONF_SLOT, &value) &&
|
||||||
if (!err && value >= 0) {
|
value >= 0) {
|
||||||
slot->config.slot = value;
|
slot->config.slot = value;
|
||||||
DBG("%s: slot %u", group, slot->config.slot);
|
DBG("%s: slot %u", group, slot->config.slot);
|
||||||
} else {
|
} else {
|
||||||
slot->config.slot = RILMODEM_DEFAULT_SLOT;
|
slot->config.slot = RILMODEM_DEFAULT_SLOT;
|
||||||
if (err) {
|
|
||||||
g_error_free(err);
|
|
||||||
err = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
value = g_key_file_get_integer(file, group, RILCONF_TIMEOUT,
|
if (ril_config_get_integer(file, group, RILCONF_TIMEOUT,
|
||||||
&err);
|
&slot->timeout)) {
|
||||||
if (!err) {
|
|
||||||
slot->timeout = value;
|
|
||||||
DBG("%s: timeout %d", group, slot->timeout);
|
DBG("%s: timeout %d", group, slot->timeout);
|
||||||
} else {
|
} else {
|
||||||
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
|
slot->timeout = RILMODEM_DEFAULT_TIMEOUT;
|
||||||
if (err) {
|
|
||||||
g_error_free(err);
|
|
||||||
err = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
slot->config.enable_4g = g_key_file_get_boolean(file, group,
|
if (!ril_config_get_boolean(file, group, RILCONF_4G,
|
||||||
RILCONF_4G, &err);
|
&slot->config.enable_4g)) {
|
||||||
if (err) {
|
|
||||||
/* Set to default */
|
|
||||||
slot->config.enable_4g = RILMODEM_DEFAULT_4G;
|
slot->config.enable_4g = RILMODEM_DEFAULT_4G;
|
||||||
g_error_free(err);
|
|
||||||
err = NULL;
|
|
||||||
}
|
}
|
||||||
DBG("%s: 4G %s", group, slot->config.enable_4g ? "on" : "off");
|
DBG("%s: 4G %s", group, slot->config.enable_4g ? "on" : "off");
|
||||||
|
|
||||||
ril_plugin_read_config_flag(file, group,
|
ril_config_get_flag(file, group,
|
||||||
RILCONF_UICC_WORKAROUND,
|
RILCONF_UICC_WORKAROUND,
|
||||||
RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND,
|
RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND,
|
||||||
&slot->sim_flags);
|
&slot->sim_flags);
|
||||||
DBG("%s: UICC workaround %s", group, (slot->sim_flags &
|
DBG("%s: UICC workaround %s", group, (slot->sim_flags &
|
||||||
RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND) ?
|
RIL_SIM_CARD_V9_UICC_SUBSCRIPTION_WORKAROUND) ?
|
||||||
"on" : "off");
|
"on" : "off");
|
||||||
|
|
||||||
|
strval = ril_config_get_string(file, group,
|
||||||
|
RILCONF_ALLOW_DATA_REQ);
|
||||||
|
if (strval) {
|
||||||
|
slot->allow_data_opt =
|
||||||
|
!strcasecmp(strval, "on") ? RIL_ALLOW_DATA_ON :
|
||||||
|
!strcasecmp(strval, "off")? RIL_ALLOW_DATA_OFF :
|
||||||
|
RIL_ALLOW_DATA_AUTO;
|
||||||
|
g_free(strval);
|
||||||
|
}
|
||||||
|
DBG("%s: AllowDataReq %s", group,
|
||||||
|
(slot->allow_data_opt == RIL_ALLOW_DATA_ON) ? "on" :
|
||||||
|
(slot->allow_data_opt == RIL_ALLOW_DATA_OFF) ? "off" :
|
||||||
|
"auto");
|
||||||
|
|
||||||
|
slot->ecclist_file = ril_config_get_string(file, group,
|
||||||
|
RILCONF_ECCLIST_FILE);
|
||||||
|
if (slot->ecclist_file && slot->ecclist_file[0]) {
|
||||||
|
DBG("%s: ecclist file %s", group, slot->ecclist_file);
|
||||||
|
slot->pub.ecclist_file = slot->ecclist_file;
|
||||||
|
} else {
|
||||||
|
g_free(slot->ecclist_file);
|
||||||
|
slot->ecclist_file = NULL;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
DBG("no socket path in %s", group);
|
DBG("no socket path in %s", group);
|
||||||
}
|
}
|
||||||
@@ -1005,11 +1164,14 @@ static struct ril_slot *ril_plugin_parse_config_group(GKeyFile *file,
|
|||||||
static void ril_plugin_delete_slot(struct ril_slot *slot)
|
static void ril_plugin_delete_slot(struct ril_slot *slot)
|
||||||
{
|
{
|
||||||
ril_plugin_shutdown_slot(slot, TRUE);
|
ril_plugin_shutdown_slot(slot, TRUE);
|
||||||
|
ril_sim_info_unref(slot->sim_info);
|
||||||
|
ril_sim_settings_unref(slot->sim_settings);
|
||||||
g_free(slot->path);
|
g_free(slot->path);
|
||||||
g_free(slot->imei);
|
g_free(slot->imei);
|
||||||
g_free(slot->name);
|
g_free(slot->name);
|
||||||
g_free(slot->sockpath);
|
g_free(slot->sockpath);
|
||||||
g_free(slot->sub);
|
g_free(slot->sub);
|
||||||
|
g_free(slot->ecclist_file);
|
||||||
g_free(slot);
|
g_free(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1051,7 +1213,8 @@ static guint ril_plugin_find_unused_slot(GSList *slots)
|
|||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GSList *ril_plugin_parse_config_file(GKeyFile *file)
|
static GSList *ril_plugin_parse_config_file(GKeyFile *file,
|
||||||
|
struct ril_plugin_settings *ps)
|
||||||
{
|
{
|
||||||
GSList *list = NULL;
|
GSList *list = NULL;
|
||||||
GSList *link;
|
GSList *link;
|
||||||
@@ -1059,13 +1222,21 @@ static GSList *ril_plugin_parse_config_file(GKeyFile *file)
|
|||||||
gchar **groups = g_key_file_get_groups(file, &n);
|
gchar **groups = g_key_file_get_groups(file, &n);
|
||||||
|
|
||||||
for (i=0; i<n; i++) {
|
for (i=0; i<n; i++) {
|
||||||
if (g_str_has_prefix(groups[i], RILCONF_DEV_PREFIX)) {
|
const char *group = groups[i];
|
||||||
|
if (g_str_has_prefix(group, RILCONF_DEV_PREFIX)) {
|
||||||
|
/* Modem configuration */
|
||||||
struct ril_slot *slot =
|
struct ril_slot *slot =
|
||||||
ril_plugin_parse_config_group(file, groups[i]);
|
ril_plugin_parse_config_group(file, group);
|
||||||
|
|
||||||
if (slot) {
|
if (slot) {
|
||||||
list = ril_plugin_add_slot(list, slot);
|
list = ril_plugin_add_slot(list, slot);
|
||||||
}
|
}
|
||||||
|
} else if (!strcmp(group, RILCONF_SETTINGS_GROUP)) {
|
||||||
|
/* Plugin configuration */
|
||||||
|
ril_config_get_flag(file, group,
|
||||||
|
RILCONF_SETTINGS_3GHANDOVER,
|
||||||
|
RIL_DATA_MANAGER_3GLTE_HANDOVER,
|
||||||
|
&ps->dm_flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1083,7 +1254,8 @@ static GSList *ril_plugin_parse_config_file(GKeyFile *file)
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GSList *ril_plugin_load_config(const char *path)
|
static GSList *ril_plugin_load_config(const char *path,
|
||||||
|
struct ril_plugin_settings *ps)
|
||||||
{
|
{
|
||||||
GError *err = NULL;
|
GError *err = NULL;
|
||||||
GSList *list = NULL;
|
GSList *list = NULL;
|
||||||
@@ -1091,9 +1263,9 @@ static GSList *ril_plugin_load_config(const char *path)
|
|||||||
|
|
||||||
if (g_key_file_load_from_file(file, path, 0, &err)) {
|
if (g_key_file_load_from_file(file, path, 0, &err)) {
|
||||||
DBG("loading %s", path);
|
DBG("loading %s", path);
|
||||||
list = ril_plugin_parse_config_file(file);
|
list = ril_plugin_parse_config_file(file, ps);
|
||||||
} else {
|
} else {
|
||||||
DBG("conf load result: %s", err->message);
|
DBG("conf load error: %s", err->message);
|
||||||
g_error_free(err);
|
g_error_free(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1144,9 +1316,7 @@ static void ril_plugin_update_enabled_slot(struct ril_slot *slot)
|
|||||||
{
|
{
|
||||||
if (slot->pub.enabled) {
|
if (slot->pub.enabled) {
|
||||||
DBG("%s enabled", slot->path + 1);
|
DBG("%s enabled", slot->path + 1);
|
||||||
if (ril_plugin_can_create_modem(slot) && !slot->modem) {
|
ril_plugin_check_modem(slot);
|
||||||
ril_plugin_create_modem(slot);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1329,6 +1499,8 @@ static void ril_plugin_init_slots(struct ril_plugin_priv *plugin)
|
|||||||
slot->plugin = plugin;
|
slot->plugin = plugin;
|
||||||
slot->pub.path = slot->path;
|
slot->pub.path = slot->path;
|
||||||
slot->pub.config = &slot->config;
|
slot->pub.config = &slot->config;
|
||||||
|
slot->sim_info = ril_sim_info_new(ril_plugin_log_prefix(slot));
|
||||||
|
slot->sim_settings = ril_sim_settings_new(&slot->config);
|
||||||
}
|
}
|
||||||
|
|
||||||
*info = NULL;
|
*info = NULL;
|
||||||
@@ -1345,48 +1517,73 @@ static void ril_plugin_enable_slot(struct ril_slot *slot)
|
|||||||
slot->pub.enabled = TRUE;
|
slot->pub.enabled = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ril_plugin_priv *ril_plugin = NULL;
|
static struct ril_plugin_priv *ril_plugin = NULL;
|
||||||
|
|
||||||
static void ril_debug_trace_notify(struct ofono_debug_desc *desc)
|
static void ril_debug_trace_notify(struct ofono_debug_desc *desc)
|
||||||
{
|
{
|
||||||
if (ril_plugin) {
|
if (ril_plugin) {
|
||||||
ril_plugin_foreach_slot(ril_plugin, ril_debug_trace_update_slot);
|
ril_plugin_foreach_slot(ril_plugin, ril_debug_trace_update);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_debug_dump_notify(struct ofono_debug_desc *desc)
|
static void ril_debug_dump_notify(struct ofono_debug_desc *desc)
|
||||||
{
|
{
|
||||||
if (ril_plugin) {
|
if (ril_plugin) {
|
||||||
ril_plugin_foreach_slot(ril_plugin, ril_debug_dump_update_slot);
|
ril_plugin_foreach_slot(ril_plugin, ril_debug_dump_update);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_debug_grilio_notify(struct ofono_debug_desc *desc)
|
static void ril_debug_grilio_notify(struct ofono_debug_desc *desc)
|
||||||
{
|
{
|
||||||
if (desc->flags & OFONO_DEBUG_FLAG_PRINT) {
|
grilio_log.level = (desc->flags & OFONO_DEBUG_FLAG_PRINT) ?
|
||||||
grilio_log.level = GLOG_LEVEL_VERBOSE;
|
GLOG_LEVEL_VERBOSE : GLOG_LEVEL_INHERIT;
|
||||||
} else {
|
}
|
||||||
grilio_log.level = GLOG_LEVEL_INHERIT;
|
|
||||||
}
|
static void ril_plugin_debug_notify(struct ofono_debug_desc *desc)
|
||||||
|
{
|
||||||
|
GLOG_MODULE_NAME.level = (desc->flags & OFONO_DEBUG_FLAG_PRINT) ?
|
||||||
|
GLOG_LEVEL_VERBOSE : GLOG_LEVEL_INHERIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ril_plugin_init(void)
|
static int ril_plugin_init(void)
|
||||||
{
|
{
|
||||||
char *enabled_slots;
|
char *enabled_slots;
|
||||||
|
struct ril_plugin_settings ps;
|
||||||
|
|
||||||
|
/* Default settings */
|
||||||
|
ps.dm_flags = RILMODEM_DEFAULT_DM_FLAGS;
|
||||||
|
|
||||||
DBG("");
|
DBG("");
|
||||||
GASSERT(!ril_plugin);
|
GASSERT(!ril_plugin);
|
||||||
|
|
||||||
/* ofono core calls openlog() */
|
/*
|
||||||
|
* Log categories (accessible via D-Bus) are generated from
|
||||||
|
* ofono_debug_desc structures, while libglibutil based log
|
||||||
|
* functions receive the log module name. Those should match
|
||||||
|
* otherwise the client receiving the log won't get the category
|
||||||
|
* information.
|
||||||
|
*/
|
||||||
|
grilio_hexdump_log.name = ril_debug_dump.name;
|
||||||
|
grilio_log.name = grilio_debug.name;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Debug log plugin hooks gutil_log_func2 while we replace
|
||||||
|
* gutil_log_func, they don't interfere with each other.
|
||||||
|
*
|
||||||
|
* Note that ofono core calls openlog(), so we don't need to.
|
||||||
|
*/
|
||||||
gutil_log_func = gutil_log_syslog;
|
gutil_log_func = gutil_log_syslog;
|
||||||
|
|
||||||
ril_plugin_switch_user();
|
ril_plugin_switch_user();
|
||||||
|
|
||||||
ril_plugin = g_new0(struct ril_plugin_priv, 1);
|
ril_plugin = g_new0(struct ril_plugin_priv, 1);
|
||||||
ril_plugin->slots = ril_plugin_load_config(RILMODEM_CONF_FILE);
|
ril_plugin->slots = ril_plugin_load_config(RILMODEM_CONF_FILE, &ps);
|
||||||
ril_plugin_init_slots(ril_plugin);
|
ril_plugin_init_slots(ril_plugin);
|
||||||
ril_plugin->dbus = ril_plugin_dbus_new(&ril_plugin->pub);
|
ril_plugin->dbus = ril_plugin_dbus_new(&ril_plugin->pub);
|
||||||
ril_plugin->data_manager = ril_data_manager_new();
|
ril_plugin->data_manager = ril_data_manager_new(ps.dm_flags);
|
||||||
|
ril_plugin->mce = ril_mce_new();
|
||||||
|
ril_plugin->display_on =
|
||||||
|
(ril_plugin->mce->display_state != RIL_MCE_DISPLAY_OFF);
|
||||||
|
|
||||||
if (ril_plugin->slots) {
|
if (ril_plugin->slots) {
|
||||||
/*
|
/*
|
||||||
@@ -1443,7 +1640,6 @@ static int ril_plugin_init(void)
|
|||||||
ofono_phonebook_driver_register(&ril_phonebook_driver);
|
ofono_phonebook_driver_register(&ril_phonebook_driver);
|
||||||
ofono_ussd_driver_register(&ril_ussd_driver);
|
ofono_ussd_driver_register(&ril_ussd_driver);
|
||||||
ofono_cbs_driver_register(&ril_cbs_driver);
|
ofono_cbs_driver_register(&ril_cbs_driver);
|
||||||
ofono_oem_raw_driver_register(&ril_oem_raw_driver);
|
|
||||||
ofono_stk_driver_register(&ril_stk_driver);
|
ofono_stk_driver_register(&ril_stk_driver);
|
||||||
|
|
||||||
/* This will create the modems (those that are enabled) */
|
/* This will create the modems (those that are enabled) */
|
||||||
@@ -1454,6 +1650,15 @@ static int ril_plugin_init(void)
|
|||||||
* SIM insertion/removal notifications
|
* SIM insertion/removal notifications
|
||||||
*/
|
*/
|
||||||
ril_plugin_foreach_slot(ril_plugin, ril_plugin_init_io);
|
ril_plugin_foreach_slot(ril_plugin, ril_plugin_init_io);
|
||||||
|
|
||||||
|
/* Set initial screen state and register for updates */
|
||||||
|
ril_plugin_foreach_slot(ril_plugin, ril_plugin_send_screen_state);
|
||||||
|
ril_plugin->display_state_change_id =
|
||||||
|
ril_mce_add_display_state_changed_handler(ril_plugin->mce,
|
||||||
|
ril_plugin_display_state_cb, ril_plugin);
|
||||||
|
|
||||||
|
/* This will set 'ready' flag if we have no modems at all */
|
||||||
|
ril_plugin_update_ready(ril_plugin);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1478,13 +1683,15 @@ static void ril_plugin_exit(void)
|
|||||||
ofono_phonebook_driver_unregister(&ril_phonebook_driver);
|
ofono_phonebook_driver_unregister(&ril_phonebook_driver);
|
||||||
ofono_ussd_driver_unregister(&ril_ussd_driver);
|
ofono_ussd_driver_unregister(&ril_ussd_driver);
|
||||||
ofono_cbs_driver_unregister(&ril_cbs_driver);
|
ofono_cbs_driver_unregister(&ril_cbs_driver);
|
||||||
ofono_oem_raw_driver_unregister(&ril_oem_raw_driver);
|
|
||||||
ofono_stk_driver_unregister(&ril_stk_driver);
|
ofono_stk_driver_unregister(&ril_stk_driver);
|
||||||
|
|
||||||
if (ril_plugin) {
|
if (ril_plugin) {
|
||||||
g_slist_free_full(ril_plugin->slots, ril_plugin_destroy_slot);
|
g_slist_free_full(ril_plugin->slots, ril_plugin_destroy_slot);
|
||||||
ril_plugin_dbus_free(ril_plugin->dbus);
|
ril_plugin_dbus_free(ril_plugin->dbus);
|
||||||
ril_data_manager_unref(ril_plugin->data_manager);
|
ril_data_manager_unref(ril_plugin->data_manager);
|
||||||
|
ril_mce_remove_handler(ril_plugin->mce,
|
||||||
|
ril_plugin->display_state_change_id);
|
||||||
|
ril_mce_unref(ril_plugin->mce);
|
||||||
g_key_file_free(ril_plugin->storage);
|
g_key_file_free(ril_plugin->storage);
|
||||||
g_free(ril_plugin->slots_info);
|
g_free(ril_plugin->slots_info);
|
||||||
g_free(ril_plugin->default_voice_imsi);
|
g_free(ril_plugin->default_voice_imsi);
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
#include <ofono/gprs-context.h>
|
#include <ofono/gprs-context.h>
|
||||||
#include <ofono/gprs.h>
|
#include <ofono/gprs.h>
|
||||||
#include <ofono/netreg.h>
|
#include <ofono/netreg.h>
|
||||||
#include <ofono/oemraw.h>
|
|
||||||
#include <ofono/phonebook.h>
|
#include <ofono/phonebook.h>
|
||||||
#include <ofono/radio-settings.h>
|
#include <ofono/radio-settings.h>
|
||||||
#include <ofono/sim.h>
|
#include <ofono/sim.h>
|
||||||
@@ -45,15 +44,10 @@
|
|||||||
|
|
||||||
typedef struct ril_slot_info const *ril_slot_info_ptr;
|
typedef struct ril_slot_info const *ril_slot_info_ptr;
|
||||||
|
|
||||||
struct ril_slot_config {
|
|
||||||
guint slot;
|
|
||||||
gboolean enable_4g;
|
|
||||||
const char *default_name;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ril_slot_info {
|
struct ril_slot_info {
|
||||||
const char *path;
|
const char *path;
|
||||||
const char *imei;
|
const char *imei;
|
||||||
|
const char *ecclist_file;
|
||||||
gboolean enabled;
|
gboolean enabled;
|
||||||
gboolean sim_present;
|
gboolean sim_present;
|
||||||
const struct ril_slot_config *config;
|
const struct ril_slot_config *config;
|
||||||
@@ -67,16 +61,20 @@ struct ril_plugin {
|
|||||||
const char *default_voice_path;
|
const char *default_voice_path;
|
||||||
const char *default_data_path;
|
const char *default_data_path;
|
||||||
const ril_slot_info_ptr *slots;
|
const ril_slot_info_ptr *slots;
|
||||||
|
gboolean ready;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ril_modem {
|
struct ril_modem {
|
||||||
GRilIoChannel *io;
|
GRilIoChannel *io;
|
||||||
const char *imei;
|
const char *imei;
|
||||||
|
const char *log_prefix;
|
||||||
|
const char *ecclist_file;
|
||||||
struct ofono_modem *ofono;
|
struct ofono_modem *ofono;
|
||||||
struct ril_radio *radio;
|
struct ril_radio *radio;
|
||||||
struct ril_data *data;
|
struct ril_data *data;
|
||||||
struct ril_network *network;
|
struct ril_network *network;
|
||||||
struct ril_sim_card *sim_card;
|
struct ril_sim_card *sim_card;
|
||||||
|
struct ril_sim_settings *sim_settings;
|
||||||
struct ril_slot_config config;
|
struct ril_slot_config config;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -87,6 +85,7 @@ struct ril_modem {
|
|||||||
#define RIL_PLUGIN_SIGNAL_ENABLED_SLOTS (0x10)
|
#define RIL_PLUGIN_SIGNAL_ENABLED_SLOTS (0x10)
|
||||||
#define RIL_PLUGIN_SIGNAL_MMS_IMSI (0x20)
|
#define RIL_PLUGIN_SIGNAL_MMS_IMSI (0x20)
|
||||||
#define RIL_PLUGIN_SIGNAL_MMS_PATH (0x40)
|
#define RIL_PLUGIN_SIGNAL_MMS_PATH (0x40)
|
||||||
|
#define RIL_PLUGIN_SIGNAL_READY (0x80)
|
||||||
|
|
||||||
typedef void (*ril_modem_cb_t)(struct ril_modem *modem, void *data);
|
typedef void (*ril_modem_cb_t)(struct ril_modem *modem, void *data);
|
||||||
typedef void (*ril_modem_online_cb_t)(struct ril_modem *modem, gboolean online,
|
typedef void (*ril_modem_online_cb_t)(struct ril_modem *modem, gboolean online,
|
||||||
@@ -99,10 +98,22 @@ void ril_plugin_set_default_voice_imsi(struct ril_plugin *plugin,
|
|||||||
void ril_plugin_set_default_data_imsi(struct ril_plugin *plugin,
|
void ril_plugin_set_default_data_imsi(struct ril_plugin *plugin,
|
||||||
const char *imsi);
|
const char *imsi);
|
||||||
|
|
||||||
struct ril_sim_dbus *ril_sim_dbus_new(struct ril_modem *modem);
|
struct ril_oem_raw;
|
||||||
const char *ril_sim_dbus_imsi(struct ril_sim_dbus *dbus);
|
struct ril_oem_raw *ril_oem_raw_new(struct ril_modem *md,
|
||||||
void ril_sim_dbus_free(struct ril_sim_dbus *dbus);
|
const char *log_prefix);
|
||||||
|
void ril_oem_raw_free(struct ril_oem_raw *raw);
|
||||||
|
|
||||||
|
struct ril_sim_info_dbus;
|
||||||
|
struct ril_sim_info_dbus *ril_sim_info_dbus_new(struct ril_modem *md,
|
||||||
|
struct ril_sim_info *info);
|
||||||
|
void ril_sim_info_dbus_free(struct ril_sim_info_dbus *dbus);
|
||||||
|
|
||||||
|
struct ril_cell_info_dbus;
|
||||||
|
struct ril_cell_info_dbus *ril_cell_info_dbus_new(struct ril_modem *md,
|
||||||
|
struct ril_cell_info *info);
|
||||||
|
void ril_cell_info_dbus_free(struct ril_cell_info_dbus *dbus);
|
||||||
|
|
||||||
|
struct ril_plugin_dbus;
|
||||||
struct ril_plugin_dbus *ril_plugin_dbus_new(struct ril_plugin *plugin);
|
struct ril_plugin_dbus *ril_plugin_dbus_new(struct ril_plugin *plugin);
|
||||||
void ril_plugin_dbus_free(struct ril_plugin_dbus *dbus);
|
void ril_plugin_dbus_free(struct ril_plugin_dbus *dbus);
|
||||||
void ril_plugin_dbus_block_imei_requests(struct ril_plugin_dbus *dbus,
|
void ril_plugin_dbus_block_imei_requests(struct ril_plugin_dbus *dbus,
|
||||||
@@ -111,12 +122,11 @@ void ril_plugin_dbus_signal(struct ril_plugin_dbus *dbus, int mask);
|
|||||||
void ril_plugin_dbus_signal_sim(struct ril_plugin_dbus *dbus, int index,
|
void ril_plugin_dbus_signal_sim(struct ril_plugin_dbus *dbus, int index,
|
||||||
gboolean present);
|
gboolean present);
|
||||||
|
|
||||||
struct ril_modem *ril_modem_create(GRilIoChannel *io,
|
struct ril_modem *ril_modem_create(GRilIoChannel *io, const char *log_prefix,
|
||||||
const struct ril_slot_info *slot, struct ril_radio *radio,
|
const struct ril_slot_info *slot, struct ril_radio *radio,
|
||||||
struct ril_network *network, struct ril_sim_card *card,
|
struct ril_network *network, struct ril_sim_card *card,
|
||||||
struct ril_data *data);
|
struct ril_data *data, struct ril_sim_settings *settings);
|
||||||
void ril_modem_delete(struct ril_modem *modem);
|
void ril_modem_delete(struct ril_modem *modem);
|
||||||
void ril_modem_set_imei(struct ril_modem *modem, const char *imei);
|
|
||||||
struct ofono_sim *ril_modem_ofono_sim(struct ril_modem *modem);
|
struct ofono_sim *ril_modem_ofono_sim(struct ril_modem *modem);
|
||||||
struct ofono_gprs *ril_modem_ofono_gprs(struct ril_modem *modem);
|
struct ofono_gprs *ril_modem_ofono_gprs(struct ril_modem *modem);
|
||||||
struct ofono_netreg *ril_modem_ofono_netreg(struct ril_modem *modem);
|
struct ofono_netreg *ril_modem_ofono_netreg(struct ril_modem *modem);
|
||||||
@@ -130,19 +140,6 @@ void ril_modem_set_online_cb(struct ril_modem *modem, ril_modem_online_cb_t cb,
|
|||||||
#define ril_modem_slot(modem) ((modem)->config.slot)
|
#define ril_modem_slot(modem) ((modem)->config.slot)
|
||||||
#define ril_modem_io(modem) ((modem)->io)
|
#define ril_modem_io(modem) ((modem)->io)
|
||||||
|
|
||||||
void ril_sim_read_file_linear(struct ofono_sim *sim, int fileid,
|
|
||||||
int record, int length, const unsigned char *path,
|
|
||||||
unsigned int path_len, ofono_sim_read_cb_t cb, void *data);
|
|
||||||
void ril_sim_read_file_cyclic(struct ofono_sim *sim, int fileid,
|
|
||||||
int record, int length, const unsigned char *path,
|
|
||||||
unsigned int path_len, ofono_sim_read_cb_t cb, void *data);
|
|
||||||
void ril_sim_read_file_transparent(struct ofono_sim *sim, int fileid,
|
|
||||||
int start, int length, const unsigned char *path,
|
|
||||||
unsigned int path_len, ofono_sim_read_cb_t cb, void *data);
|
|
||||||
void ril_sim_read_file_info(struct ofono_sim *sim, int fileid,
|
|
||||||
const unsigned char *path, unsigned int path_len,
|
|
||||||
ofono_sim_file_info_cb_t cb, void *data);
|
|
||||||
|
|
||||||
int ril_sim_app_type(struct ofono_sim *sim);
|
int ril_sim_app_type(struct ofono_sim *sim);
|
||||||
int ril_netreg_check_if_really_roaming(struct ofono_netreg *netreg, gint status);
|
int ril_netreg_check_if_really_roaming(struct ofono_netreg *netreg, gint status);
|
||||||
|
|
||||||
@@ -156,7 +153,6 @@ extern const struct ofono_gprs_context_driver ril_gprs_context_driver;
|
|||||||
extern const struct ofono_gprs_driver ril_gprs_driver;
|
extern const struct ofono_gprs_driver ril_gprs_driver;
|
||||||
extern const struct ofono_modem_driver ril_modem_driver;
|
extern const struct ofono_modem_driver ril_modem_driver;
|
||||||
extern const struct ofono_netreg_driver ril_netreg_driver;
|
extern const struct ofono_netreg_driver ril_netreg_driver;
|
||||||
extern /* const */ struct ofono_oem_raw_driver ril_oem_raw_driver;
|
|
||||||
extern const struct ofono_phonebook_driver ril_phonebook_driver;
|
extern const struct ofono_phonebook_driver ril_phonebook_driver;
|
||||||
extern const struct ofono_radio_settings_driver ril_radio_settings_driver;
|
extern const struct ofono_radio_settings_driver ril_radio_settings_driver;
|
||||||
extern const struct ofono_sim_driver ril_sim_driver;
|
extern const struct ofono_sim_driver ril_sim_driver;
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ struct ril_plugin_dbus {
|
|||||||
|
|
||||||
#define RIL_DBUS_PATH "/"
|
#define RIL_DBUS_PATH "/"
|
||||||
#define RIL_DBUS_INTERFACE "org.nemomobile.ofono.ModemManager"
|
#define RIL_DBUS_INTERFACE "org.nemomobile.ofono.ModemManager"
|
||||||
#define RIL_DBUS_INTERFACE_VERSION (4)
|
#define RIL_DBUS_INTERFACE_VERSION (5)
|
||||||
|
|
||||||
#define RIL_DBUS_SIGNAL_ENABLED_MODEMS_CHANGED "EnabledModemsChanged"
|
#define RIL_DBUS_SIGNAL_ENABLED_MODEMS_CHANGED "EnabledModemsChanged"
|
||||||
#define RIL_DBUS_SIGNAL_PRESENT_SIMS_CHANGED "PresentSimsChanged"
|
#define RIL_DBUS_SIGNAL_PRESENT_SIMS_CHANGED "PresentSimsChanged"
|
||||||
@@ -56,6 +56,7 @@ struct ril_plugin_dbus {
|
|||||||
#define RIL_DBUS_SIGNAL_DEFAULT_DATA_MODEM_CHANGED "DefaultDataModemChanged"
|
#define RIL_DBUS_SIGNAL_DEFAULT_DATA_MODEM_CHANGED "DefaultDataModemChanged"
|
||||||
#define RIL_DBUS_SIGNAL_MMS_SIM_CHANGED "MmsSimChanged"
|
#define RIL_DBUS_SIGNAL_MMS_SIM_CHANGED "MmsSimChanged"
|
||||||
#define RIL_DBUS_SIGNAL_MMS_MODEM_CHANGED "MmsModemChanged"
|
#define RIL_DBUS_SIGNAL_MMS_MODEM_CHANGED "MmsModemChanged"
|
||||||
|
#define RIL_DBUS_SIGNAL_READY_CHANGED "ReadyChanged"
|
||||||
#define RIL_DBUS_IMSI_AUTO "auto"
|
#define RIL_DBUS_IMSI_AUTO "auto"
|
||||||
|
|
||||||
static gboolean ril_plugin_dbus_enabled(const struct ril_slot_info *slot)
|
static gboolean ril_plugin_dbus_enabled(const struct ril_slot_info *slot)
|
||||||
@@ -133,6 +134,11 @@ static void ril_plugin_dbus_append_boolean_array(DBusMessageIter *it,
|
|||||||
dbus_message_iter_close_container(it, &array);
|
dbus_message_iter_close_container(it, &array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ril_plugin_dbus_append_boolean(DBusMessageIter *it, dbus_bool_t b)
|
||||||
|
{
|
||||||
|
dbus_message_iter_append_basic(it, DBUS_TYPE_BOOLEAN, &b);
|
||||||
|
}
|
||||||
|
|
||||||
static void ril_plugin_dbus_append_string(DBusMessageIter *it, const char *str)
|
static void ril_plugin_dbus_append_string(DBusMessageIter *it, const char *str)
|
||||||
{
|
{
|
||||||
if (!str) str = "";
|
if (!str) str = "";
|
||||||
@@ -179,12 +185,19 @@ static inline void ril_plugin_dbus_signal_imsi(struct ril_plugin_dbus *dbus,
|
|||||||
name, DBUS_TYPE_STRING, &imsi, DBUS_TYPE_INVALID);
|
name, DBUS_TYPE_STRING, &imsi, DBUS_TYPE_INVALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ril_plugin_dbus_signal_path(struct ril_plugin_dbus *dbus,
|
static inline void ril_plugin_dbus_signal_string(struct ril_plugin_dbus *dbus,
|
||||||
const char *name, const char *path)
|
const char *name, const char *str)
|
||||||
{
|
{
|
||||||
if (!path) path = "";
|
if (!str) str = "";
|
||||||
g_dbus_emit_signal(dbus->conn, RIL_DBUS_PATH, RIL_DBUS_INTERFACE,
|
g_dbus_emit_signal(dbus->conn, RIL_DBUS_PATH, RIL_DBUS_INTERFACE,
|
||||||
name, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID);
|
name, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ril_plugin_dbus_signal_boolean(struct ril_plugin_dbus *dbus,
|
||||||
|
const char *name, dbus_bool_t value)
|
||||||
|
{
|
||||||
|
g_dbus_emit_signal(dbus->conn, RIL_DBUS_PATH, RIL_DBUS_INTERFACE,
|
||||||
|
name, DBUS_TYPE_BOOLEAN, &value, DBUS_TYPE_INVALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ril_plugin_dbus_signal(struct ril_plugin_dbus *dbus, int mask)
|
void ril_plugin_dbus_signal(struct ril_plugin_dbus *dbus, int mask)
|
||||||
@@ -201,11 +214,9 @@ void ril_plugin_dbus_signal(struct ril_plugin_dbus *dbus, int mask)
|
|||||||
dbus->plugin->default_data_imsi);
|
dbus->plugin->default_data_imsi);
|
||||||
}
|
}
|
||||||
if (mask & RIL_PLUGIN_SIGNAL_MMS_IMSI) {
|
if (mask & RIL_PLUGIN_SIGNAL_MMS_IMSI) {
|
||||||
g_dbus_emit_signal(dbus->conn, RIL_DBUS_PATH,
|
ril_plugin_dbus_signal_string(dbus,
|
||||||
RIL_DBUS_INTERFACE,
|
|
||||||
RIL_DBUS_SIGNAL_MMS_SIM_CHANGED,
|
RIL_DBUS_SIGNAL_MMS_SIM_CHANGED,
|
||||||
DBUS_TYPE_STRING, &dbus->plugin->mms_imsi,
|
dbus->plugin->mms_imsi);
|
||||||
DBUS_TYPE_INVALID);
|
|
||||||
}
|
}
|
||||||
if (mask & RIL_PLUGIN_SIGNAL_ENABLED_SLOTS) {
|
if (mask & RIL_PLUGIN_SIGNAL_ENABLED_SLOTS) {
|
||||||
ril_plugin_dbus_signal_path_array(dbus,
|
ril_plugin_dbus_signal_path_array(dbus,
|
||||||
@@ -213,20 +224,25 @@ void ril_plugin_dbus_signal(struct ril_plugin_dbus *dbus, int mask)
|
|||||||
ril_plugin_dbus_enabled);
|
ril_plugin_dbus_enabled);
|
||||||
}
|
}
|
||||||
if (mask & RIL_PLUGIN_SIGNAL_VOICE_PATH) {
|
if (mask & RIL_PLUGIN_SIGNAL_VOICE_PATH) {
|
||||||
ril_plugin_dbus_signal_path(dbus,
|
ril_plugin_dbus_signal_string(dbus,
|
||||||
RIL_DBUS_SIGNAL_DEFAULT_VOICE_MODEM_CHANGED,
|
RIL_DBUS_SIGNAL_DEFAULT_VOICE_MODEM_CHANGED,
|
||||||
dbus->plugin->default_voice_path);
|
dbus->plugin->default_voice_path);
|
||||||
}
|
}
|
||||||
if (mask & RIL_PLUGIN_SIGNAL_DATA_PATH) {
|
if (mask & RIL_PLUGIN_SIGNAL_DATA_PATH) {
|
||||||
ril_plugin_dbus_signal_path(dbus,
|
ril_plugin_dbus_signal_string(dbus,
|
||||||
RIL_DBUS_SIGNAL_DEFAULT_DATA_MODEM_CHANGED,
|
RIL_DBUS_SIGNAL_DEFAULT_DATA_MODEM_CHANGED,
|
||||||
dbus->plugin->default_data_path);
|
dbus->plugin->default_data_path);
|
||||||
}
|
}
|
||||||
if (mask & RIL_PLUGIN_SIGNAL_MMS_PATH) {
|
if (mask & RIL_PLUGIN_SIGNAL_MMS_PATH) {
|
||||||
ril_plugin_dbus_signal_path(dbus,
|
ril_plugin_dbus_signal_string(dbus,
|
||||||
RIL_DBUS_SIGNAL_MMS_MODEM_CHANGED,
|
RIL_DBUS_SIGNAL_MMS_MODEM_CHANGED,
|
||||||
dbus->plugin->mms_path);
|
dbus->plugin->mms_path);
|
||||||
}
|
}
|
||||||
|
if (mask & RIL_PLUGIN_SIGNAL_READY) {
|
||||||
|
ril_plugin_dbus_signal_boolean(dbus,
|
||||||
|
RIL_DBUS_SIGNAL_READY_CHANGED,
|
||||||
|
dbus->plugin->ready);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,6 +368,13 @@ static void ril_plugin_dbus_append_all4(DBusMessageIter *it,
|
|||||||
ril_plugin_dbus_append_path(it, dbus->plugin->mms_path);
|
ril_plugin_dbus_append_path(it, dbus->plugin->mms_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ril_plugin_dbus_append_all5(DBusMessageIter *it,
|
||||||
|
struct ril_plugin_dbus *dbus)
|
||||||
|
{
|
||||||
|
ril_plugin_dbus_append_all4(it, dbus);
|
||||||
|
ril_plugin_dbus_append_boolean(it, dbus->plugin->ready);
|
||||||
|
}
|
||||||
|
|
||||||
static DBusMessage *ril_plugin_dbus_get_all(DBusConnection *conn,
|
static DBusMessage *ril_plugin_dbus_get_all(DBusConnection *conn,
|
||||||
DBusMessage *msg, void *data)
|
DBusMessage *msg, void *data)
|
||||||
{
|
{
|
||||||
@@ -380,6 +403,13 @@ static DBusMessage *ril_plugin_dbus_get_all4(DBusConnection *conn,
|
|||||||
ril_plugin_dbus_append_all4);
|
ril_plugin_dbus_append_all4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DBusMessage *ril_plugin_dbus_get_all5(DBusConnection *conn,
|
||||||
|
DBusMessage *msg, void *data)
|
||||||
|
{
|
||||||
|
return ril_plugin_dbus_imei_reply(msg, (struct ril_plugin_dbus *)data,
|
||||||
|
ril_plugin_dbus_append_all5);
|
||||||
|
}
|
||||||
|
|
||||||
static DBusMessage *ril_plugin_dbus_get_interface_version(DBusConnection *conn,
|
static DBusMessage *ril_plugin_dbus_get_interface_version(DBusConnection *conn,
|
||||||
DBusMessage *msg, void *data)
|
DBusMessage *msg, void *data)
|
||||||
{
|
{
|
||||||
@@ -512,6 +542,18 @@ static DBusMessage *ril_plugin_dbus_get_mms_modem(DBusConnection *conn,
|
|||||||
return ril_plugin_dbus_reply_with_path(msg, dbus->plugin->mms_path);
|
return ril_plugin_dbus_reply_with_path(msg, dbus->plugin->mms_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DBusMessage *ril_plugin_dbus_get_ready(DBusConnection *conn,
|
||||||
|
DBusMessage *msg, void *data)
|
||||||
|
{
|
||||||
|
struct ril_plugin_dbus *dbus = data;
|
||||||
|
DBusMessage *reply = dbus_message_new_method_return(msg);
|
||||||
|
DBusMessageIter it;
|
||||||
|
|
||||||
|
dbus_message_iter_init_append(reply, &it);
|
||||||
|
ril_plugin_dbus_append_boolean(&it, dbus->plugin->ready);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
static DBusMessage *ril_plugin_dbus_set_enabled_modems(DBusConnection *conn,
|
static DBusMessage *ril_plugin_dbus_set_enabled_modems(DBusConnection *conn,
|
||||||
DBusMessage *msg, void *data)
|
DBusMessage *msg, void *data)
|
||||||
{
|
{
|
||||||
@@ -673,6 +715,9 @@ static DBusMessage *ril_plugin_dbus_set_mms_sim(DBusConnection *conn,
|
|||||||
RIL_DBUS_GET_ALL3_ARGS, \
|
RIL_DBUS_GET_ALL3_ARGS, \
|
||||||
{"mmsSim", "s" }, \
|
{"mmsSim", "s" }, \
|
||||||
{"mmsModem" , "s"}
|
{"mmsModem" , "s"}
|
||||||
|
#define RIL_DBUS_GET_ALL5_ARGS \
|
||||||
|
RIL_DBUS_GET_ALL4_ARGS, \
|
||||||
|
{"ready" , "b"}
|
||||||
|
|
||||||
static const GDBusMethodTable ril_plugin_dbus_methods[] = {
|
static const GDBusMethodTable ril_plugin_dbus_methods[] = {
|
||||||
{ GDBUS_METHOD("GetAll",
|
{ GDBUS_METHOD("GetAll",
|
||||||
@@ -687,6 +732,9 @@ static const GDBusMethodTable ril_plugin_dbus_methods[] = {
|
|||||||
{ GDBUS_ASYNC_METHOD("GetAll4",
|
{ GDBUS_ASYNC_METHOD("GetAll4",
|
||||||
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL4_ARGS),
|
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL4_ARGS),
|
||||||
ril_plugin_dbus_get_all4) },
|
ril_plugin_dbus_get_all4) },
|
||||||
|
{ GDBUS_ASYNC_METHOD("GetAll5",
|
||||||
|
NULL, GDBUS_ARGS(RIL_DBUS_GET_ALL5_ARGS),
|
||||||
|
ril_plugin_dbus_get_all5) },
|
||||||
{ GDBUS_METHOD("GetInterfaceVersion",
|
{ GDBUS_METHOD("GetInterfaceVersion",
|
||||||
NULL, GDBUS_ARGS({ "version", "i" }),
|
NULL, GDBUS_ARGS({ "version", "i" }),
|
||||||
ril_plugin_dbus_get_interface_version) },
|
ril_plugin_dbus_get_interface_version) },
|
||||||
@@ -720,6 +768,9 @@ static const GDBusMethodTable ril_plugin_dbus_methods[] = {
|
|||||||
{ GDBUS_METHOD("GetMmsModem",
|
{ GDBUS_METHOD("GetMmsModem",
|
||||||
NULL, GDBUS_ARGS({ "path", "s" }),
|
NULL, GDBUS_ARGS({ "path", "s" }),
|
||||||
ril_plugin_dbus_get_mms_modem) },
|
ril_plugin_dbus_get_mms_modem) },
|
||||||
|
{ GDBUS_METHOD("GetReady",
|
||||||
|
NULL, GDBUS_ARGS({ "ready", "b" }),
|
||||||
|
ril_plugin_dbus_get_ready) },
|
||||||
{ GDBUS_METHOD("SetEnabledModems",
|
{ GDBUS_METHOD("SetEnabledModems",
|
||||||
GDBUS_ARGS({ "modems", "ao" }), NULL,
|
GDBUS_ARGS({ "modems", "ao" }), NULL,
|
||||||
ril_plugin_dbus_set_enabled_modems) },
|
ril_plugin_dbus_set_enabled_modems) },
|
||||||
@@ -753,6 +804,8 @@ static const GDBusSignalTable ril_plugin_dbus_signals[] = {
|
|||||||
GDBUS_ARGS({ "imsi", "s" })) },
|
GDBUS_ARGS({ "imsi", "s" })) },
|
||||||
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_MMS_MODEM_CHANGED,
|
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_MMS_MODEM_CHANGED,
|
||||||
GDBUS_ARGS({ "path", "s" })) },
|
GDBUS_ARGS({ "path", "s" })) },
|
||||||
|
{ GDBUS_SIGNAL(RIL_DBUS_SIGNAL_READY_CHANGED,
|
||||||
|
GDBUS_ARGS({ "ready", "b" })) },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -21,6 +21,8 @@
|
|||||||
#include <grilio_request.h>
|
#include <grilio_request.h>
|
||||||
#include <grilio_parser.h>
|
#include <grilio_parser.h>
|
||||||
|
|
||||||
|
#include <gutil_misc.h>
|
||||||
|
|
||||||
typedef GObjectClass RilRadioClass;
|
typedef GObjectClass RilRadioClass;
|
||||||
typedef struct ril_radio RilRadio;
|
typedef struct ril_radio RilRadio;
|
||||||
|
|
||||||
@@ -48,38 +50,53 @@ struct ril_radio_priv {
|
|||||||
|
|
||||||
enum ril_radio_signal {
|
enum ril_radio_signal {
|
||||||
SIGNAL_STATE_CHANGED,
|
SIGNAL_STATE_CHANGED,
|
||||||
|
SIGNAL_ONLINE_CHANGED,
|
||||||
SIGNAL_COUNT
|
SIGNAL_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
#define POWER_RETRY_SECS (1)
|
#define POWER_RETRY_SECS (1)
|
||||||
|
|
||||||
#define SIGNAL_STATE_CHANGED_NAME "ril-radio-state-changed"
|
#define SIGNAL_STATE_CHANGED_NAME "ril-radio-state-changed"
|
||||||
|
#define SIGNAL_ONLINE_CHANGED_NAME "ril-radio-online-changed"
|
||||||
|
|
||||||
static guint ril_radio_signals[SIGNAL_COUNT] = { 0 };
|
static guint ril_radio_signals[SIGNAL_COUNT] = { 0 };
|
||||||
|
|
||||||
|
#define NEW_SIGNAL(klass,name) \
|
||||||
|
ril_radio_signals[SIGNAL_##name##_CHANGED] = \
|
||||||
|
g_signal_new(SIGNAL_##name##_CHANGED_NAME, \
|
||||||
|
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST, \
|
||||||
|
0, NULL, NULL, NULL, G_TYPE_NONE, 0)
|
||||||
|
|
||||||
G_DEFINE_TYPE(RilRadio, ril_radio, G_TYPE_OBJECT)
|
G_DEFINE_TYPE(RilRadio, ril_radio, G_TYPE_OBJECT)
|
||||||
#define RIL_RADIO_TYPE (ril_radio_get_type())
|
#define RIL_RADIO_TYPE (ril_radio_get_type())
|
||||||
#define RIL_RADIO(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj,RIL_RADIO_TYPE,RilRadio))
|
#define RIL_RADIO(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj,RIL_RADIO_TYPE,RilRadio))
|
||||||
|
|
||||||
static void ril_radio_submit_power_request(struct ril_radio *self, gboolean on);
|
static void ril_radio_submit_power_request(struct ril_radio *self, gboolean on);
|
||||||
|
|
||||||
G_INLINE_FUNC gboolean ril_radio_power_should_be_on(struct ril_radio *self)
|
static inline gboolean ril_radio_power_should_be_on(struct ril_radio *self)
|
||||||
{
|
{
|
||||||
struct ril_radio_priv *priv = self->priv;
|
struct ril_radio_priv *priv = self->priv;
|
||||||
|
|
||||||
return g_hash_table_size(priv->req_table) && !priv->power_cycle;
|
return self->online && !priv->power_cycle &&
|
||||||
|
g_hash_table_size(priv->req_table) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
G_INLINE_FUNC gboolean ril_radio_state_off(enum ril_radio_state radio_state)
|
static inline gboolean ril_radio_state_off(enum ril_radio_state radio_state)
|
||||||
{
|
{
|
||||||
return radio_state == RADIO_STATE_OFF;
|
return radio_state == RADIO_STATE_OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
G_INLINE_FUNC gboolean ril_radio_state_on(enum ril_radio_state radio_state)
|
static inline gboolean ril_radio_state_on(enum ril_radio_state radio_state)
|
||||||
{
|
{
|
||||||
return !ril_radio_state_off(radio_state);
|
return !ril_radio_state_off(radio_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void ril_radio_emit_signal(struct ril_radio *self,
|
||||||
|
enum ril_radio_signal id)
|
||||||
|
{
|
||||||
|
g_signal_emit(self, ril_radio_signals[id], 0);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean ril_radio_power_request_retry_cb(gpointer user_data)
|
static gboolean ril_radio_power_request_retry_cb(gpointer user_data)
|
||||||
{
|
{
|
||||||
struct ril_radio *self = user_data;
|
struct ril_radio *self = user_data;
|
||||||
@@ -89,7 +106,8 @@ static gboolean ril_radio_power_request_retry_cb(gpointer user_data)
|
|||||||
GASSERT(priv->retry_id);
|
GASSERT(priv->retry_id);
|
||||||
priv->retry_id = 0;
|
priv->retry_id = 0;
|
||||||
ril_radio_submit_power_request(self, ril_radio_power_should_be_on(self));
|
ril_radio_submit_power_request(self, ril_radio_power_should_be_on(self));
|
||||||
return FALSE;
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_radio_cancel_retry(struct ril_radio *self)
|
static void ril_radio_cancel_retry(struct ril_radio *self)
|
||||||
@@ -132,7 +150,7 @@ static void ril_radio_check_state(struct ril_radio *self)
|
|||||||
ril_radio_state_to_string(self->state),
|
ril_radio_state_to_string(self->state),
|
||||||
ril_radio_state_to_string(priv->last_known_state));
|
ril_radio_state_to_string(priv->last_known_state));
|
||||||
self->state = priv->last_known_state;
|
self->state = priv->last_known_state;
|
||||||
g_signal_emit(self, ril_radio_signals[SIGNAL_STATE_CHANGED], 0);
|
ril_radio_emit_signal(self, SIGNAL_STATE_CHANGED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,7 +252,7 @@ void ril_radio_power_on(struct ril_radio *self, gpointer tag)
|
|||||||
|
|
||||||
DBG("%s%p", priv->log_prefix, tag);
|
DBG("%s%p", priv->log_prefix, tag);
|
||||||
g_hash_table_insert(priv->req_table, tag, tag);
|
g_hash_table_insert(priv->req_table, tag, tag);
|
||||||
if (!was_on) {
|
if (!was_on && ril_radio_power_should_be_on(self)) {
|
||||||
ril_radio_power_request(self, TRUE, FALSE);
|
ril_radio_power_request(self, TRUE, FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -256,6 +274,19 @@ void ril_radio_power_off(struct ril_radio *self, gpointer tag)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ril_radio_set_online(struct ril_radio *self, gboolean online)
|
||||||
|
{
|
||||||
|
if (G_LIKELY(self) && self->online != online) {
|
||||||
|
gboolean on, was_on = ril_radio_power_should_be_on(self);
|
||||||
|
self->online = online;
|
||||||
|
on = ril_radio_power_should_be_on(self);
|
||||||
|
if (was_on != on) {
|
||||||
|
ril_radio_power_request(self, on, FALSE);
|
||||||
|
}
|
||||||
|
ril_radio_emit_signal(self, SIGNAL_ONLINE_CHANGED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gulong ril_radio_add_state_changed_handler(struct ril_radio *self,
|
gulong ril_radio_add_state_changed_handler(struct ril_radio *self,
|
||||||
ril_radio_cb_t cb, void *arg)
|
ril_radio_cb_t cb, void *arg)
|
||||||
{
|
{
|
||||||
@@ -263,6 +294,13 @@ gulong ril_radio_add_state_changed_handler(struct ril_radio *self,
|
|||||||
SIGNAL_STATE_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
|
SIGNAL_STATE_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gulong ril_radio_add_online_changed_handler(struct ril_radio *self,
|
||||||
|
ril_radio_cb_t cb, void *arg)
|
||||||
|
{
|
||||||
|
return (G_LIKELY(self) && G_LIKELY(cb)) ? g_signal_connect(self,
|
||||||
|
SIGNAL_ONLINE_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
void ril_radio_remove_handler(struct ril_radio *self, gulong id)
|
void ril_radio_remove_handler(struct ril_radio *self, gulong id)
|
||||||
{
|
{
|
||||||
if (G_LIKELY(self) && G_LIKELY(id)) {
|
if (G_LIKELY(self) && G_LIKELY(id)) {
|
||||||
@@ -270,6 +308,11 @@ void ril_radio_remove_handler(struct ril_radio *self, gulong id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ril_radio_remove_handlers(struct ril_radio *self, gulong *ids, int count)
|
||||||
|
{
|
||||||
|
gutil_disconnect_handlers(self, ids, count);
|
||||||
|
}
|
||||||
|
|
||||||
enum ril_radio_state ril_radio_state_parse(const void *data, guint len)
|
enum ril_radio_state ril_radio_state_parse(const void *data, guint len)
|
||||||
{
|
{
|
||||||
GRilIoParser rilp;
|
GRilIoParser rilp;
|
||||||
@@ -394,10 +437,8 @@ static void ril_radio_class_init(RilRadioClass *klass)
|
|||||||
object_class->dispose = ril_radio_dispose;
|
object_class->dispose = ril_radio_dispose;
|
||||||
object_class->finalize = ril_radio_finalize;
|
object_class->finalize = ril_radio_finalize;
|
||||||
g_type_class_add_private(klass, sizeof(struct ril_radio_priv));
|
g_type_class_add_private(klass, sizeof(struct ril_radio_priv));
|
||||||
ril_radio_signals[SIGNAL_STATE_CHANGED] =
|
NEW_SIGNAL(klass, STATE);
|
||||||
g_signal_new(SIGNAL_STATE_CHANGED_NAME,
|
NEW_SIGNAL(klass, ONLINE);
|
||||||
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST,
|
|
||||||
0, NULL, NULL, NULL, G_TYPE_NONE, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -22,6 +22,7 @@ struct ril_radio {
|
|||||||
GObject object;
|
GObject object;
|
||||||
struct ril_radio_priv *priv;
|
struct ril_radio_priv *priv;
|
||||||
enum ril_radio_state state;
|
enum ril_radio_state state;
|
||||||
|
gboolean online;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*ril_radio_cb_t)(struct ril_radio *radio, void *arg);
|
typedef void (*ril_radio_cb_t)(struct ril_radio *radio, void *arg);
|
||||||
@@ -32,11 +33,15 @@ void ril_radio_unref(struct ril_radio *radio);
|
|||||||
|
|
||||||
void ril_radio_power_on(struct ril_radio *radio, gpointer tag);
|
void ril_radio_power_on(struct ril_radio *radio, gpointer tag);
|
||||||
void ril_radio_power_off(struct ril_radio *radio, gpointer tag);
|
void ril_radio_power_off(struct ril_radio *radio, gpointer tag);
|
||||||
void ril_radio_confirm_power_on(struct ril_radio *radio);
|
|
||||||
void ril_radio_power_cycle(struct ril_radio *radio);
|
void ril_radio_power_cycle(struct ril_radio *radio);
|
||||||
|
void ril_radio_confirm_power_on(struct ril_radio *radio);
|
||||||
|
void ril_radio_set_online(struct ril_radio *radio, gboolean online);
|
||||||
gulong ril_radio_add_state_changed_handler(struct ril_radio *radio,
|
gulong ril_radio_add_state_changed_handler(struct ril_radio *radio,
|
||||||
ril_radio_cb_t cb, void *arg);
|
ril_radio_cb_t cb, void *arg);
|
||||||
|
gulong ril_radio_add_online_changed_handler(struct ril_radio *radio,
|
||||||
|
ril_radio_cb_t cb, void *arg);
|
||||||
void ril_radio_remove_handler(struct ril_radio *radio, gulong id);
|
void ril_radio_remove_handler(struct ril_radio *radio, gulong id);
|
||||||
|
void ril_radio_remove_handlers(struct ril_radio *radio, gulong *ids, int n);
|
||||||
enum ril_radio_state ril_radio_state_parse(const void *data, guint len);
|
enum ril_radio_state ril_radio_state_parse(const void *data, guint len);
|
||||||
|
|
||||||
#endif /* RIL_RADIO_H */
|
#endif /* RIL_RADIO_H */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* oFono - Open Source Telephony - RIL-based devices
|
* oFono - Open Source Telephony - RIL-based devices
|
||||||
*
|
*
|
||||||
* Copyright (C) 2015 Jolla Ltd.
|
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
@@ -14,17 +14,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ril_plugin.h"
|
#include "ril_plugin.h"
|
||||||
|
#include "ril_sim_settings.h"
|
||||||
#include "ril_util.h"
|
#include "ril_util.h"
|
||||||
#include "ril_log.h"
|
#include "ril_log.h"
|
||||||
#include "ril_constants.h"
|
#include "ril_constants.h"
|
||||||
|
|
||||||
struct ril_radio_settings {
|
struct ril_radio_settings {
|
||||||
GRilIoQueue *q;
|
|
||||||
struct ofono_radio_settings *rs;
|
struct ofono_radio_settings *rs;
|
||||||
enum ofono_radio_access_mode access_mode;
|
struct ril_sim_settings *settings;
|
||||||
gboolean enable_4g;
|
const char *log_prefix;
|
||||||
int ratmode;
|
char *allocated_log_prefix;
|
||||||
guint query_rats_id;
|
guint source_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ril_radio_settings_cbd {
|
struct ril_radio_settings_cbd {
|
||||||
@@ -38,7 +38,7 @@ struct ril_radio_settings_cbd {
|
|||||||
gpointer data;
|
gpointer data;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ril_radio_settings_cbd_free g_free
|
#define DBG_(rsd,fmt,args...) DBG("%s" fmt, (rsd)->log_prefix, ##args)
|
||||||
|
|
||||||
static inline struct ril_radio_settings *ril_radio_settings_get_data(
|
static inline struct ril_radio_settings *ril_radio_settings_get_data(
|
||||||
struct ofono_radio_settings *rs)
|
struct ofono_radio_settings *rs)
|
||||||
@@ -46,8 +46,8 @@ static inline struct ril_radio_settings *ril_radio_settings_get_data(
|
|||||||
return ofono_radio_settings_get_data(rs);
|
return ofono_radio_settings_get_data(rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ril_radio_settings_cbd *ril_radio_settings_cbd_new(
|
static void ril_radio_settings_later(struct ril_radio_settings *rsd,
|
||||||
struct ril_radio_settings *rsd, void *cb, void *data)
|
GSourceFunc fn, void *cb, void *data)
|
||||||
{
|
{
|
||||||
struct ril_radio_settings_cbd *cbd;
|
struct ril_radio_settings_cbd *cbd;
|
||||||
|
|
||||||
@@ -55,89 +55,22 @@ static struct ril_radio_settings_cbd *ril_radio_settings_cbd_new(
|
|||||||
cbd->rsd = rsd;
|
cbd->rsd = rsd;
|
||||||
cbd->cb.ptr = cb;
|
cbd->cb.ptr = cb;
|
||||||
cbd->data = data;
|
cbd->data = data;
|
||||||
return cbd;
|
|
||||||
|
GASSERT(!rsd->source_id);
|
||||||
|
rsd->source_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
|
||||||
|
fn, cbd, g_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum ofono_radio_access_mode ril_radio_settings_pref_to_mode(int pref)
|
static gboolean ril_radio_settings_set_rat_mode_cb(gpointer user_data)
|
||||||
{
|
|
||||||
switch (pref) {
|
|
||||||
case PREF_NET_TYPE_LTE_CDMA_EVDO:
|
|
||||||
case PREF_NET_TYPE_LTE_GSM_WCDMA:
|
|
||||||
case PREF_NET_TYPE_LTE_CMDA_EVDO_GSM_WCDMA:
|
|
||||||
case PREF_NET_TYPE_LTE_ONLY:
|
|
||||||
case PREF_NET_TYPE_LTE_WCDMA:
|
|
||||||
return OFONO_RADIO_ACCESS_MODE_LTE;
|
|
||||||
case PREF_NET_TYPE_GSM_ONLY:
|
|
||||||
return OFONO_RADIO_ACCESS_MODE_GSM;
|
|
||||||
case PREF_NET_TYPE_GSM_WCDMA_AUTO:
|
|
||||||
case PREF_NET_TYPE_WCDMA:
|
|
||||||
case PREF_NET_TYPE_GSM_WCDMA:
|
|
||||||
return OFONO_RADIO_ACCESS_MODE_UMTS;
|
|
||||||
default:
|
|
||||||
return OFONO_RADIO_ACCESS_MODE_ANY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ril_radio_settings_mode_to_pref(struct ril_radio_settings *rsd,
|
|
||||||
enum ofono_radio_access_mode mode)
|
|
||||||
{
|
|
||||||
switch (mode) {
|
|
||||||
case OFONO_RADIO_ACCESS_MODE_ANY:
|
|
||||||
case OFONO_RADIO_ACCESS_MODE_LTE:
|
|
||||||
if (rsd->enable_4g) {
|
|
||||||
return PREF_NET_TYPE_LTE_WCDMA;
|
|
||||||
}
|
|
||||||
/* no break */
|
|
||||||
case OFONO_RADIO_ACCESS_MODE_UMTS:
|
|
||||||
return PREF_NET_TYPE_GSM_WCDMA_AUTO;
|
|
||||||
case OFONO_RADIO_ACCESS_MODE_GSM:
|
|
||||||
return PREF_NET_TYPE_GSM_ONLY;
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ril_radio_settings_submit_request(struct ril_radio_settings *rsd,
|
|
||||||
GRilIoRequest* req, guint code, GRilIoChannelResponseFunc response,
|
|
||||||
void *cb, void *data)
|
|
||||||
{
|
|
||||||
grilio_queue_send_request_full(rsd->q, req, code, response,
|
|
||||||
ril_radio_settings_cbd_free,
|
|
||||||
ril_radio_settings_cbd_new(rsd, cb, data));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ril_radio_settings_set_rat_mode_cb(GRilIoChannel *io, int status,
|
|
||||||
const void *data, guint len, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct ofono_error error;
|
struct ofono_error error;
|
||||||
struct ril_radio_settings_cbd *cbd = user_data;
|
struct ril_radio_settings_cbd *cbd = user_data;
|
||||||
ofono_radio_settings_rat_mode_set_cb_t cb = cbd->cb.rat_mode_set;
|
struct ril_radio_settings *rsd = cbd->rsd;
|
||||||
|
|
||||||
if (status == RIL_E_SUCCESS) {
|
GASSERT(rsd->source_id);
|
||||||
cb(ril_error_ok(&error), cbd->data);
|
rsd->source_id = 0;
|
||||||
} else {
|
cbd->cb.rat_mode_set(ril_error_ok(&error), cbd->data);
|
||||||
ofono_error("failed to set rat mode");
|
return G_SOURCE_REMOVE;
|
||||||
cb(ril_error_failure(&error), cbd->data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static GRilIoRequest *ril_radio_settings_set_pref_req(int pref)
|
|
||||||
{
|
|
||||||
GRilIoRequest *req = grilio_request_sized_new(8);
|
|
||||||
grilio_request_append_int32(req, 1); /* Number of params */
|
|
||||||
grilio_request_append_int32(req, pref);
|
|
||||||
return req;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ril_radio_settings_parse_pref_resp(const void *data, guint len)
|
|
||||||
{
|
|
||||||
GRilIoParser rilp;
|
|
||||||
int pref = -1;
|
|
||||||
|
|
||||||
grilio_parser_init(&rilp, data, len);
|
|
||||||
grilio_parser_get_int32(&rilp, NULL);
|
|
||||||
grilio_parser_get_int32(&rilp, &pref);
|
|
||||||
return pref;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_radio_settings_set_rat_mode(struct ofono_radio_settings *rs,
|
static void ril_radio_settings_set_rat_mode(struct ofono_radio_settings *rs,
|
||||||
@@ -145,45 +78,24 @@ static void ril_radio_settings_set_rat_mode(struct ofono_radio_settings *rs,
|
|||||||
ofono_radio_settings_rat_mode_set_cb_t cb, void *data)
|
ofono_radio_settings_rat_mode_set_cb_t cb, void *data)
|
||||||
{
|
{
|
||||||
struct ril_radio_settings *rsd = ril_radio_settings_get_data(rs);
|
struct ril_radio_settings *rsd = ril_radio_settings_get_data(rs);
|
||||||
int pref = ril_radio_settings_mode_to_pref(rsd, mode);
|
DBG_(rsd, "%s", ofono_radio_access_mode_to_string(mode));
|
||||||
GRilIoRequest *req;
|
ril_sim_settings_set_pref_mode(rsd->settings, mode);
|
||||||
|
ril_radio_settings_later(rsd, ril_radio_settings_set_rat_mode_cb,
|
||||||
if (pref < 0) pref = rsd->ratmode;
|
cb, data);
|
||||||
DBG("rat mode set %d (ril %d)", mode, pref);
|
|
||||||
req = ril_radio_settings_set_pref_req(pref);
|
|
||||||
ril_radio_settings_submit_request(rsd, req,
|
|
||||||
RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE,
|
|
||||||
ril_radio_settings_set_rat_mode_cb, cb, data);
|
|
||||||
grilio_request_unref(req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_radio_settings_query_rat_mode_cb(GRilIoChannel *io, int status,
|
static gboolean ril_radio_settings_query_rat_mode_cb(gpointer user_data)
|
||||||
const void *data, guint len, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct ofono_error error;
|
|
||||||
struct ril_radio_settings_cbd *cbd = user_data;
|
struct ril_radio_settings_cbd *cbd = user_data;
|
||||||
struct ril_radio_settings *rsd = cbd->rsd;
|
struct ril_radio_settings *rsd = cbd->rsd;
|
||||||
ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb.rat_mode_query;
|
enum ofono_radio_access_mode mode = rsd->settings->pref_mode;
|
||||||
|
struct ofono_error error;
|
||||||
|
|
||||||
if (status == RIL_E_SUCCESS) {
|
DBG_(rsd, "rat mode %s", ofono_radio_access_mode_to_string(mode));
|
||||||
rsd->ratmode = ril_radio_settings_parse_pref_resp(data, len);
|
GASSERT(rsd->source_id);
|
||||||
DBG("rat mode %d (ril %d)",
|
rsd->source_id = 0;
|
||||||
ril_radio_settings_pref_to_mode(rsd->ratmode),
|
cbd->cb.rat_mode_query(ril_error_ok(&error), mode, cbd->data);
|
||||||
rsd->ratmode);
|
return G_SOURCE_REMOVE;
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* With certain versions of RIL, preferred network type
|
|
||||||
* queries don't work even though setting preferred network
|
|
||||||
* type does actually work. In this case, assume that our
|
|
||||||
* cached network type is the right one.
|
|
||||||
*/
|
|
||||||
ofono_error("rat mode query failed, assuming %d (ril %d)",
|
|
||||||
ril_radio_settings_pref_to_mode(rsd->ratmode),
|
|
||||||
rsd->ratmode);
|
|
||||||
}
|
|
||||||
|
|
||||||
cb(ril_error_ok(&error), ril_radio_settings_pref_to_mode(rsd->ratmode),
|
|
||||||
cbd->data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_radio_settings_query_rat_mode(struct ofono_radio_settings *rs,
|
static void ril_radio_settings_query_rat_mode(struct ofono_radio_settings *rs,
|
||||||
@@ -191,26 +103,26 @@ static void ril_radio_settings_query_rat_mode(struct ofono_radio_settings *rs,
|
|||||||
{
|
{
|
||||||
struct ril_radio_settings *rsd = ril_radio_settings_get_data(rs);
|
struct ril_radio_settings *rsd = ril_radio_settings_get_data(rs);
|
||||||
|
|
||||||
DBG("rat mode query");
|
DBG_(rsd, "");
|
||||||
ril_radio_settings_submit_request(rsd, NULL,
|
ril_radio_settings_later(rsd, ril_radio_settings_query_rat_mode_cb,
|
||||||
RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE,
|
cb, data);
|
||||||
ril_radio_settings_query_rat_mode_cb, cb, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean ril_radio_settings_query_available_rats_cb(gpointer data)
|
static gboolean ril_radio_settings_query_available_rats_cb(gpointer data)
|
||||||
{
|
{
|
||||||
struct ofono_error error;
|
struct ofono_error error;
|
||||||
struct ril_radio_settings_cbd *cbd = data;
|
struct ril_radio_settings_cbd *cbd = data;
|
||||||
|
struct ril_radio_settings *rsd = cbd->rsd;
|
||||||
guint rats = OFONO_RADIO_ACCESS_MODE_GSM | OFONO_RADIO_ACCESS_MODE_UMTS;
|
guint rats = OFONO_RADIO_ACCESS_MODE_GSM | OFONO_RADIO_ACCESS_MODE_UMTS;
|
||||||
|
|
||||||
if (cbd->rsd->enable_4g) {
|
if (cbd->rsd->settings->enable_4g) {
|
||||||
rats |= OFONO_RADIO_ACCESS_MODE_LTE;
|
rats |= OFONO_RADIO_ACCESS_MODE_LTE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GASSERT(cbd->rsd->query_rats_id);
|
GASSERT(cbd->rsd->source_id);
|
||||||
cbd->rsd->query_rats_id = 0;
|
rsd->source_id = 0;
|
||||||
cbd->cb.available_rats(ril_error_ok(&error), rats, cbd->data);
|
cbd->cb.available_rats(ril_error_ok(&error), rats, cbd->data);
|
||||||
return FALSE;
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_radio_settings_query_available_rats(
|
static void ril_radio_settings_query_available_rats(
|
||||||
@@ -219,50 +131,18 @@ static void ril_radio_settings_query_available_rats(
|
|||||||
{
|
{
|
||||||
struct ril_radio_settings *rsd = ril_radio_settings_get_data(rs);
|
struct ril_radio_settings *rsd = ril_radio_settings_get_data(rs);
|
||||||
|
|
||||||
DBG("");
|
DBG_(rsd, "");
|
||||||
GASSERT(!rsd->query_rats_id);
|
ril_radio_settings_later(rsd, ril_radio_settings_query_available_rats_cb,
|
||||||
rsd->query_rats_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
|
cb, data);
|
||||||
ril_radio_settings_query_available_rats_cb,
|
|
||||||
ril_radio_settings_cbd_new(rsd, cb, data),
|
|
||||||
ril_radio_settings_cbd_free);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_radio_settings_init_query_cb(GRilIoChannel *io, int status,
|
static gboolean ril_radio_settings_register(gpointer user_data)
|
||||||
const void *data, guint len, void *user_data)
|
|
||||||
{
|
{
|
||||||
int pref;
|
|
||||||
struct ril_radio_settings *rsd = user_data;
|
struct ril_radio_settings *rsd = user_data;
|
||||||
enum ofono_radio_access_mode mode;
|
GASSERT(rsd->source_id);
|
||||||
|
rsd->source_id = 0;
|
||||||
if (status == RIL_E_SUCCESS) {
|
|
||||||
pref = ril_radio_settings_parse_pref_resp(data, len);
|
|
||||||
DBG("rat mode %d", pref);
|
|
||||||
} else {
|
|
||||||
ofono_error("initial rat mode query failed");
|
|
||||||
pref = ril_radio_settings_mode_to_pref(rsd,
|
|
||||||
OFONO_RADIO_ACCESS_MODE_ANY);
|
|
||||||
}
|
|
||||||
|
|
||||||
mode = ril_radio_settings_pref_to_mode(pref);
|
|
||||||
|
|
||||||
if (!rsd->enable_4g && mode == OFONO_RADIO_ACCESS_MODE_LTE) {
|
|
||||||
rsd->ratmode = ril_radio_settings_mode_to_pref(rsd,
|
|
||||||
OFONO_RADIO_ACCESS_MODE_UMTS);
|
|
||||||
} else {
|
|
||||||
rsd->ratmode = pref;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rsd->ratmode != pref || status != RIL_E_SUCCESS) {
|
|
||||||
GRilIoRequest *req;
|
|
||||||
|
|
||||||
DBG("forcing rat mode %d", rsd->ratmode);
|
|
||||||
req = ril_radio_settings_set_pref_req(rsd->ratmode);
|
|
||||||
grilio_queue_send_request(rsd->q, req,
|
|
||||||
RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE);
|
|
||||||
grilio_request_unref(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
ofono_radio_settings_register(rsd->rs);
|
ofono_radio_settings_register(rsd->rs);
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ril_radio_settings_probe(struct ofono_radio_settings *rs,
|
static int ril_radio_settings_probe(struct ofono_radio_settings *rs,
|
||||||
@@ -271,13 +151,17 @@ static int ril_radio_settings_probe(struct ofono_radio_settings *rs,
|
|||||||
struct ril_modem *modem = data;
|
struct ril_modem *modem = data;
|
||||||
struct ril_radio_settings *rsd = g_new0(struct ril_radio_settings, 1);
|
struct ril_radio_settings *rsd = g_new0(struct ril_radio_settings, 1);
|
||||||
|
|
||||||
DBG("");
|
DBG("%s", modem->log_prefix);
|
||||||
rsd->rs = rs;
|
rsd->rs = rs;
|
||||||
rsd->q = grilio_queue_new(ril_modem_io(modem));
|
rsd->settings = ril_sim_settings_ref(modem->sim_settings);
|
||||||
rsd->enable_4g = ril_modem_4g_enabled(modem);
|
rsd->source_id = g_idle_add(ril_radio_settings_register, rsd);
|
||||||
grilio_queue_send_request_full(rsd->q, NULL,
|
|
||||||
RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE,
|
if (modem->log_prefix && modem->log_prefix[0]) {
|
||||||
ril_radio_settings_init_query_cb, NULL, rsd);
|
rsd->log_prefix = rsd->allocated_log_prefix =
|
||||||
|
g_strconcat(modem->log_prefix, " ", NULL);
|
||||||
|
} else {
|
||||||
|
rsd->log_prefix = "";
|
||||||
|
}
|
||||||
|
|
||||||
ofono_radio_settings_set_data(rs, rsd);
|
ofono_radio_settings_set_data(rs, rsd);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -287,14 +171,13 @@ static void ril_radio_settings_remove(struct ofono_radio_settings *rs)
|
|||||||
{
|
{
|
||||||
struct ril_radio_settings *rsd = ril_radio_settings_get_data(rs);
|
struct ril_radio_settings *rsd = ril_radio_settings_get_data(rs);
|
||||||
|
|
||||||
DBG("");
|
DBG_(rsd, "");
|
||||||
ofono_radio_settings_set_data(rs, NULL);
|
ofono_radio_settings_set_data(rs, NULL);
|
||||||
if (rsd->query_rats_id > 0) {
|
if (rsd->source_id) {
|
||||||
g_source_remove(rsd->query_rats_id);
|
g_source_remove(rsd->source_id);
|
||||||
}
|
}
|
||||||
|
ril_sim_settings_unref(rsd->settings);
|
||||||
grilio_queue_cancel_all(rsd->q, FALSE);
|
g_free(rsd->allocated_log_prefix);
|
||||||
grilio_queue_unref(rsd->q);
|
|
||||||
g_free(rsd);
|
g_free(rsd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ril_plugin.h"
|
#include "ril_plugin.h"
|
||||||
#include "ril_radio.h"
|
|
||||||
#include "ril_sim_card.h"
|
#include "ril_sim_card.h"
|
||||||
#include "ril_util.h"
|
#include "ril_util.h"
|
||||||
#include "ril_log.h"
|
#include "ril_log.h"
|
||||||
@@ -68,18 +67,15 @@
|
|||||||
struct ril_sim {
|
struct ril_sim {
|
||||||
GRilIoChannel *io;
|
GRilIoChannel *io;
|
||||||
GRilIoQueue *q;
|
GRilIoQueue *q;
|
||||||
GRilIoQueue *q2;
|
|
||||||
GList *pin_cbd_list;
|
GList *pin_cbd_list;
|
||||||
struct ofono_sim *sim;
|
struct ofono_sim *sim;
|
||||||
struct ril_sim_card *card;
|
struct ril_sim_card *card;
|
||||||
struct ril_radio *radio;
|
|
||||||
enum ofono_sim_password_type ofono_passwd_state;
|
enum ofono_sim_password_type ofono_passwd_state;
|
||||||
int retries[OFONO_SIM_PASSWORD_INVALID];
|
int retries[OFONO_SIM_PASSWORD_INVALID];
|
||||||
guint slot;
|
guint slot;
|
||||||
gboolean inserted;
|
gboolean inserted;
|
||||||
guint idle_id;
|
guint idle_id;
|
||||||
gulong card_status_id;
|
gulong card_status_id;
|
||||||
gulong radio_state_id;
|
|
||||||
|
|
||||||
/* query_passwd_state context */
|
/* query_passwd_state context */
|
||||||
ofono_sim_passwd_cb_t query_passwd_state_cb;
|
ofono_sim_passwd_cb_t query_passwd_state_cb;
|
||||||
@@ -141,6 +137,7 @@ static void ril_sim_pin_cbd_state_event_count_cb(struct ril_sim_card *sc,
|
|||||||
|
|
||||||
static struct ril_sim_pin_cbd *ril_sim_pin_cbd_new(struct ril_sim *sd,
|
static struct ril_sim_pin_cbd *ril_sim_pin_cbd_new(struct ril_sim *sd,
|
||||||
enum ofono_sim_password_type passwd_type,
|
enum ofono_sim_password_type passwd_type,
|
||||||
|
gboolean state_change_expected,
|
||||||
ofono_sim_lock_unlock_cb_t cb, void *data)
|
ofono_sim_lock_unlock_cb_t cb, void *data)
|
||||||
{
|
{
|
||||||
struct ril_sim_pin_cbd *cbd = g_new0(struct ril_sim_pin_cbd, 1);
|
struct ril_sim_pin_cbd *cbd = g_new0(struct ril_sim_pin_cbd, 1);
|
||||||
@@ -150,8 +147,11 @@ static struct ril_sim_pin_cbd *ril_sim_pin_cbd_new(struct ril_sim *sd,
|
|||||||
cbd->data = data;
|
cbd->data = data;
|
||||||
cbd->passwd_type = passwd_type;
|
cbd->passwd_type = passwd_type;
|
||||||
cbd->card = ril_sim_card_ref(sd->card);
|
cbd->card = ril_sim_card_ref(sd->card);
|
||||||
cbd->card_status_id = ril_sim_card_add_status_received_handler(sd->card,
|
if (state_change_expected) {
|
||||||
|
cbd->card_status_id =
|
||||||
|
ril_sim_card_add_status_received_handler(sd->card,
|
||||||
ril_sim_pin_cbd_state_event_count_cb, cbd);
|
ril_sim_pin_cbd_state_event_count_cb, cbd);
|
||||||
|
}
|
||||||
return cbd;
|
return cbd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,36 +385,19 @@ static guint ril_sim_request_io(struct ril_sim *sd, GRilIoQueue *q, int fileid,
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_sim_internal_read_file_info(struct ril_sim *sd, GRilIoQueue *q,
|
|
||||||
int fileid, const unsigned char *path, unsigned int path_len,
|
|
||||||
ofono_sim_file_info_cb_t cb, void *data)
|
|
||||||
{
|
|
||||||
if (!sd || !ril_sim_request_io(sd, q, fileid, CMD_GET_RESPONSE,
|
|
||||||
0, 0, 15, path, path_len, ril_sim_file_info_cb,
|
|
||||||
ril_sim_cbd_new(sd, cb, data))) {
|
|
||||||
struct ofono_error error;
|
|
||||||
cb(ril_error_failure(&error), -1, -1, -1, NULL,
|
|
||||||
EF_STATUS_INVALIDATED, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ril_sim_ofono_read_file_info(struct ofono_sim *sim, int fileid,
|
static void ril_sim_ofono_read_file_info(struct ofono_sim *sim, int fileid,
|
||||||
const unsigned char *path, unsigned int len,
|
const unsigned char *path, unsigned int len,
|
||||||
ofono_sim_file_info_cb_t cb, void *data)
|
ofono_sim_file_info_cb_t cb, void *data)
|
||||||
{
|
{
|
||||||
struct ril_sim *sd = ril_sim_get_data(sim);
|
struct ril_sim *sd = ril_sim_get_data(sim);
|
||||||
|
|
||||||
ril_sim_internal_read_file_info(sd, sd->q, fileid, path, len, cb, data);
|
if (!sd || !ril_sim_request_io(sd, sd->q, fileid, CMD_GET_RESPONSE,
|
||||||
}
|
0, 0, 15, path, len, ril_sim_file_info_cb,
|
||||||
|
ril_sim_cbd_new(sd, cb, data))) {
|
||||||
void ril_sim_read_file_info(struct ofono_sim *sim, int fileid,
|
struct ofono_error error;
|
||||||
const unsigned char *path, unsigned int path_len,
|
cb(ril_error_failure(&error), -1, -1, -1, NULL,
|
||||||
ofono_sim_file_info_cb_t cb, void *data)
|
EF_STATUS_INVALIDATED, data);
|
||||||
{
|
}
|
||||||
struct ril_sim *sd = ril_sim_get_data(sim);
|
|
||||||
|
|
||||||
ril_sim_internal_read_file_info(sd, sd->q2, fileid, path, path_len,
|
|
||||||
cb, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_sim_read_cb(GRilIoChannel *io, int status,
|
static void ril_sim_read_cb(GRilIoChannel *io, int status,
|
||||||
@@ -457,42 +440,14 @@ static void ril_sim_read(struct ril_sim *sd, GRilIoQueue *q, int fileid,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ril_sim_internal_read_file_transparent(struct ril_sim *sd,
|
|
||||||
GRilIoQueue *q, int fileid, int start, int length,
|
|
||||||
const unsigned char *path, unsigned int path_len,
|
|
||||||
ofono_sim_read_cb_t cb, void *data)
|
|
||||||
{
|
|
||||||
ril_sim_read(sd, q, fileid, CMD_READ_BINARY, (start >> 8),
|
|
||||||
(start & 0xff), length, path, path_len, cb, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ril_sim_ofono_read_file_transparent(struct ofono_sim *sim,
|
static void ril_sim_ofono_read_file_transparent(struct ofono_sim *sim,
|
||||||
int fileid, int start, int length, const unsigned char *path,
|
int fileid, int start, int length, const unsigned char *path,
|
||||||
unsigned int path_len, ofono_sim_read_cb_t cb, void *data)
|
unsigned int path_len, ofono_sim_read_cb_t cb, void *data)
|
||||||
{
|
{
|
||||||
struct ril_sim *sd = ril_sim_get_data(sim);
|
struct ril_sim *sd = ril_sim_get_data(sim);
|
||||||
|
|
||||||
ril_sim_internal_read_file_transparent(sd, sd->q, fileid, start, length,
|
ril_sim_read(sd, sd->q, fileid, CMD_READ_BINARY, (start >> 8),
|
||||||
path, path_len, cb, data);
|
(start & 0xff), length, path, path_len, cb, data);
|
||||||
}
|
|
||||||
|
|
||||||
void ril_sim_read_file_transparent(struct ofono_sim *sim, int fileid,
|
|
||||||
int start, int length, const unsigned char *path,
|
|
||||||
unsigned int path_len, ofono_sim_read_cb_t cb, void *data)
|
|
||||||
{
|
|
||||||
struct ril_sim *sd = ril_sim_get_data(sim);
|
|
||||||
|
|
||||||
ril_sim_internal_read_file_transparent(sd, sd->q2, fileid, start,
|
|
||||||
length, path, path_len, cb, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ril_sim_internal_read_file_linear(struct ril_sim *sd,
|
|
||||||
GRilIoQueue *q, int fileid, int record, int length,
|
|
||||||
const unsigned char *path, unsigned int path_len,
|
|
||||||
ofono_sim_read_cb_t cb, void *data)
|
|
||||||
{
|
|
||||||
ril_sim_read(sd, q, fileid, CMD_READ_RECORD, record, 4, length,
|
|
||||||
path, path_len, cb, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_sim_ofono_read_file_linear(struct ofono_sim *sim, int fileid,
|
static void ril_sim_ofono_read_file_linear(struct ofono_sim *sim, int fileid,
|
||||||
@@ -501,29 +456,10 @@ static void ril_sim_ofono_read_file_linear(struct ofono_sim *sim, int fileid,
|
|||||||
{
|
{
|
||||||
struct ril_sim *sd = ril_sim_get_data(sim);
|
struct ril_sim *sd = ril_sim_get_data(sim);
|
||||||
|
|
||||||
ril_sim_internal_read_file_linear(sd, sd->q, fileid, record, length,
|
ril_sim_read(sd, sd->q, fileid, CMD_READ_RECORD, record, 4, length,
|
||||||
path, path_len, cb, data);
|
path, path_len, cb, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ril_sim_read_file_linear(struct ofono_sim *sim, int fileid,
|
|
||||||
int record, int length, const unsigned char *path,
|
|
||||||
unsigned int path_len, ofono_sim_read_cb_t cb, void *data)
|
|
||||||
{
|
|
||||||
struct ril_sim *sd = ril_sim_get_data(sim);
|
|
||||||
|
|
||||||
ril_sim_internal_read_file_linear(sd, sd->q2, fileid, record, length,
|
|
||||||
path, path_len, cb, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ril_sim_read_file_cyclic(struct ofono_sim *sim, int fileid,
|
|
||||||
int rec, int length, const unsigned char *path,
|
|
||||||
unsigned int path_len, ofono_sim_read_cb_t cb, void *data)
|
|
||||||
{
|
|
||||||
/* Hmmm... Is this right? */
|
|
||||||
ril_sim_read_file_linear(sim, fileid, rec, length, path, path_len,
|
|
||||||
cb, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ril_sim_ofono_read_file_cyclic(struct ofono_sim *sim, int fileid,
|
static void ril_sim_ofono_read_file_cyclic(struct ofono_sim *sim, int fileid,
|
||||||
int rec, int length, const unsigned char *path,
|
int rec, int length, const unsigned char *path,
|
||||||
unsigned int path_len, ofono_sim_read_cb_t cb, void *data)
|
unsigned int path_len, ofono_sim_read_cb_t cb, void *data)
|
||||||
@@ -569,6 +505,13 @@ static void ril_sim_read_imsi(struct ofono_sim *sim, ofono_sim_imsi_cb_t cb,
|
|||||||
DBG("%s", ril_sim_app_id(sd));
|
DBG("%s", ril_sim_app_id(sd));
|
||||||
grilio_request_append_int32(req, GET_IMSI_NUM_PARAMS);
|
grilio_request_append_int32(req, GET_IMSI_NUM_PARAMS);
|
||||||
grilio_request_append_utf8(req, ril_sim_app_id(sd));
|
grilio_request_append_utf8(req, ril_sim_app_id(sd));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we fail the .read_imsi call, ofono gets into "Unable to
|
||||||
|
* read IMSI, emergency calls only" state. Retry the request
|
||||||
|
* on failure.
|
||||||
|
*/
|
||||||
|
grilio_request_set_retry(req, RIL_RETRY_MS, -1);
|
||||||
grilio_queue_send_request_full(sd->q, req, RIL_REQUEST_GET_IMSI,
|
grilio_queue_send_request_full(sd->q, req, RIL_REQUEST_GET_IMSI,
|
||||||
ril_sim_get_imsi_cb, ril_sim_cbd_free,
|
ril_sim_get_imsi_cb, ril_sim_cbd_free,
|
||||||
ril_sim_cbd_new(sd, cb, data));
|
ril_sim_cbd_new(sd, cb, data));
|
||||||
@@ -644,24 +587,6 @@ static gboolean ril_sim_app_in_transient_state(struct ril_sim *sd)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_sim_insert_check(struct ril_sim *sd)
|
|
||||||
{
|
|
||||||
if (!sd->inserted &&
|
|
||||||
ril_sim_passwd_state(sd) != OFONO_SIM_PASSWORD_INVALID) {
|
|
||||||
switch (sd->radio->state) {
|
|
||||||
case RADIO_STATE_SIM_READY:
|
|
||||||
case RADIO_STATE_RUIM_READY:
|
|
||||||
case RADIO_STATE_ON:
|
|
||||||
sd->inserted = TRUE;
|
|
||||||
ofono_info("SIM card OK");
|
|
||||||
ofono_sim_inserted_notify(sd->sim, TRUE);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ril_sim_finish_passwd_state_query(struct ril_sim *sd,
|
static void ril_sim_finish_passwd_state_query(struct ril_sim *sd,
|
||||||
enum ofono_sim_password_type state)
|
enum ofono_sim_password_type state)
|
||||||
{
|
{
|
||||||
@@ -709,7 +634,12 @@ static void ril_sim_status_cb(struct ril_sim_card *sc, void *user_data)
|
|||||||
if (sc->app) {
|
if (sc->app) {
|
||||||
enum ofono_sim_password_type ps;
|
enum ofono_sim_password_type ps;
|
||||||
|
|
||||||
ril_sim_insert_check(sd);
|
if (!sd->inserted) {
|
||||||
|
sd->inserted = TRUE;
|
||||||
|
ofono_info("SIM card OK");
|
||||||
|
ofono_sim_inserted_notify(sd->sim, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
ps = ril_sim_passwd_state(sd);
|
ps = ril_sim_passwd_state(sd);
|
||||||
if (ps != OFONO_SIM_PASSWORD_INVALID) {
|
if (ps != OFONO_SIM_PASSWORD_INVALID) {
|
||||||
ril_sim_finish_passwd_state_query(sd, ps);
|
ril_sim_finish_passwd_state_query(sd, ps);
|
||||||
@@ -727,13 +657,6 @@ static void ril_sim_status_cb(struct ril_sim_card *sc, void *user_data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_sim_radio_state_cb(struct ril_radio *radio, void *user_data)
|
|
||||||
{
|
|
||||||
struct ril_sim *sd = user_data;
|
|
||||||
|
|
||||||
ril_sim_insert_check(sd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ril_sim_query_pin_retries(struct ofono_sim *sim,
|
static void ril_sim_query_pin_retries(struct ofono_sim *sim,
|
||||||
ofono_sim_pin_retries_cb_t cb, void *data)
|
ofono_sim_pin_retries_cb_t cb, void *data)
|
||||||
{
|
{
|
||||||
@@ -752,7 +675,8 @@ static gboolean ril_sim_query_passwd_state_timeout_cb(gpointer user_data)
|
|||||||
GASSERT(sd->query_passwd_state_cb);
|
GASSERT(sd->query_passwd_state_cb);
|
||||||
sd->query_passwd_state_timeout_id = 0;
|
sd->query_passwd_state_timeout_id = 0;
|
||||||
ril_sim_finish_passwd_state_query(sd, OFONO_SIM_PASSWORD_INVALID);
|
ril_sim_finish_passwd_state_query(sd, OFONO_SIM_PASSWORD_INVALID);
|
||||||
return FALSE;
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_sim_query_passwd_state(struct ofono_sim *sim,
|
static void ril_sim_query_passwd_state(struct ofono_sim *sim,
|
||||||
@@ -795,7 +719,8 @@ static gboolean ril_sim_pin_change_state_timeout_cb(gpointer user_data)
|
|||||||
sd->pin_cbd_list = g_list_remove(sd->pin_cbd_list, cbd);
|
sd->pin_cbd_list = g_list_remove(sd->pin_cbd_list, cbd);
|
||||||
cbd->cb(ril_error_failure(&error), cbd->data);
|
cbd->cb(ril_error_failure(&error), cbd->data);
|
||||||
ril_sim_pin_cbd_free(cbd);
|
ril_sim_pin_cbd_free(cbd);
|
||||||
return FALSE;
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_sim_pin_change_state_status_cb(struct ril_sim_card *sc,
|
static void ril_sim_pin_change_state_status_cb(struct ril_sim_card *sc,
|
||||||
@@ -841,7 +766,8 @@ static void ril_sim_pin_change_state_cb(GRilIoChannel *io, int ril_status,
|
|||||||
ril_status, cbd->passwd_type, retry_count);
|
ril_status, cbd->passwd_type, retry_count);
|
||||||
|
|
||||||
cbd->ril_status = ril_status;
|
cbd->ril_status = ril_status;
|
||||||
if (!cbd->state_event_count || ril_sim_app_in_transient_state(sd)) {
|
if (cbd->card_status_id && (!cbd->state_event_count ||
|
||||||
|
ril_sim_app_in_transient_state(sd))) {
|
||||||
|
|
||||||
GASSERT(!g_list_find(sd->pin_cbd_list, cbd));
|
GASSERT(!g_list_find(sd->pin_cbd_list, cbd));
|
||||||
GASSERT(!cbd->timeout_id);
|
GASSERT(!cbd->timeout_id);
|
||||||
@@ -862,7 +788,7 @@ static void ril_sim_pin_change_state_cb(GRilIoChannel *io, int ril_status,
|
|||||||
} else {
|
} else {
|
||||||
struct ofono_error error;
|
struct ofono_error error;
|
||||||
|
|
||||||
/* Looks like the state has already changed */
|
/* It's either already changed or not expected at all */
|
||||||
if (ril_status == RIL_E_SUCCESS) {
|
if (ril_status == RIL_E_SUCCESS) {
|
||||||
cbd->cb(ril_error_ok(&error), cbd->data);
|
cbd->cb(ril_error_ok(&error), cbd->data);
|
||||||
} else {
|
} else {
|
||||||
@@ -884,7 +810,8 @@ static void ril_sim_pin_send(struct ofono_sim *sim, const char *passwd,
|
|||||||
DBG("%s,aid=%s", passwd, ril_sim_app_id(sd));
|
DBG("%s,aid=%s", passwd, ril_sim_app_id(sd));
|
||||||
grilio_queue_send_request_full(sd->q, req, RIL_REQUEST_ENTER_SIM_PIN,
|
grilio_queue_send_request_full(sd->q, req, RIL_REQUEST_ENTER_SIM_PIN,
|
||||||
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
|
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
|
||||||
ril_sim_pin_cbd_new(sd, OFONO_SIM_PASSWORD_SIM_PIN, cb, data));
|
ril_sim_pin_cbd_new(sd, OFONO_SIM_PASSWORD_SIM_PIN,
|
||||||
|
TRUE, cb, data));
|
||||||
grilio_request_unref(req);
|
grilio_request_unref(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -917,7 +844,7 @@ static guint ril_perso_change_state(struct ofono_sim *sim,
|
|||||||
if (req) {
|
if (req) {
|
||||||
id = grilio_queue_send_request_full(sd->q, req, code,
|
id = grilio_queue_send_request_full(sd->q, req, code,
|
||||||
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
|
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
|
||||||
ril_sim_pin_cbd_new(sd, passwd_type, cb, data));
|
ril_sim_pin_cbd_new(sd, passwd_type, TRUE, cb, data));
|
||||||
grilio_request_unref(req);
|
grilio_request_unref(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -979,7 +906,7 @@ static void ril_sim_pin_change_state(struct ofono_sim *sim,
|
|||||||
id = grilio_queue_send_request_full(sd->q, req,
|
id = grilio_queue_send_request_full(sd->q, req,
|
||||||
RIL_REQUEST_SET_FACILITY_LOCK,
|
RIL_REQUEST_SET_FACILITY_LOCK,
|
||||||
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
|
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
|
||||||
ril_sim_pin_cbd_new(sd, passwd_type, cb, data));
|
ril_sim_pin_cbd_new(sd, passwd_type, TRUE, cb, data));
|
||||||
grilio_request_unref(req);
|
grilio_request_unref(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1003,7 +930,8 @@ static void ril_sim_pin_send_puk(struct ofono_sim *sim,
|
|||||||
DBG("puk=%s,pin=%s,aid=%s", puk, passwd, ril_sim_app_id(sd));
|
DBG("puk=%s,pin=%s,aid=%s", puk, passwd, ril_sim_app_id(sd));
|
||||||
grilio_queue_send_request_full(sd->q, req, RIL_REQUEST_ENTER_SIM_PUK,
|
grilio_queue_send_request_full(sd->q, req, RIL_REQUEST_ENTER_SIM_PUK,
|
||||||
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
|
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
|
||||||
ril_sim_pin_cbd_new(sd, OFONO_SIM_PASSWORD_SIM_PUK, cb, data));
|
ril_sim_pin_cbd_new(sd, OFONO_SIM_PASSWORD_SIM_PUK,
|
||||||
|
TRUE, cb, data));
|
||||||
grilio_request_unref(req);
|
grilio_request_unref(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1025,7 +953,8 @@ static void ril_sim_change_passwd(struct ofono_sim *sim,
|
|||||||
(passwd_type == OFONO_SIM_PASSWORD_SIM_PIN2) ?
|
(passwd_type == OFONO_SIM_PASSWORD_SIM_PIN2) ?
|
||||||
RIL_REQUEST_CHANGE_SIM_PIN2 : RIL_REQUEST_CHANGE_SIM_PIN,
|
RIL_REQUEST_CHANGE_SIM_PIN2 : RIL_REQUEST_CHANGE_SIM_PIN,
|
||||||
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
|
ril_sim_pin_change_state_cb, ril_sim_pin_req_done,
|
||||||
ril_sim_pin_cbd_new(sd, passwd_type, cb, data));
|
ril_sim_pin_cbd_new(sd, passwd_type, FALSE, cb, data));
|
||||||
|
grilio_request_unref(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean ril_sim_register(gpointer user)
|
static gboolean ril_sim_register(gpointer user)
|
||||||
@@ -1039,8 +968,6 @@ static gboolean ril_sim_register(gpointer user)
|
|||||||
ofono_sim_register(sd->sim);
|
ofono_sim_register(sd->sim);
|
||||||
|
|
||||||
/* Register for change notifications */
|
/* Register for change notifications */
|
||||||
sd->radio_state_id = ril_radio_add_state_changed_handler(sd->radio,
|
|
||||||
ril_sim_radio_state_cb, sd);
|
|
||||||
sd->card_status_id = ril_sim_card_add_status_changed_handler(sd->card,
|
sd->card_status_id = ril_sim_card_add_status_changed_handler(sd->card,
|
||||||
ril_sim_status_cb, sd);
|
ril_sim_status_cb, sd);
|
||||||
|
|
||||||
@@ -1060,19 +987,7 @@ static int ril_sim_probe(struct ofono_sim *sim, unsigned int vendor,
|
|||||||
sd->slot = ril_modem_slot(modem);
|
sd->slot = ril_modem_slot(modem);
|
||||||
sd->io = grilio_channel_ref(ril_modem_io(modem));
|
sd->io = grilio_channel_ref(ril_modem_io(modem));
|
||||||
sd->card = ril_sim_card_ref(modem->sim_card);
|
sd->card = ril_sim_card_ref(modem->sim_card);
|
||||||
sd->radio = ril_radio_ref(modem->radio);
|
|
||||||
|
|
||||||
/* NB: One queue is used for the requests originated from the ofono
|
|
||||||
* core, and the second one if for the requests initiated internally
|
|
||||||
* by the RIL code.
|
|
||||||
*
|
|
||||||
* The difference is that when SIM card is removed, ofono requests
|
|
||||||
* are cancelled without invoking the completion callbacks (otherwise
|
|
||||||
* ofono would crash) while our completion callbacks have to be
|
|
||||||
* notified in this case (otherwise we would leak memory)
|
|
||||||
*/
|
|
||||||
sd->q = grilio_queue_new(sd->io);
|
sd->q = grilio_queue_new(sd->io);
|
||||||
sd->q2 = grilio_queue_new(sd->io);
|
|
||||||
|
|
||||||
DBG("[%u]", sd->slot);
|
DBG("[%u]", sd->slot);
|
||||||
|
|
||||||
@@ -1093,7 +1008,6 @@ static void ril_sim_remove(struct ofono_sim *sim)
|
|||||||
DBG("[%u]", sd->slot);
|
DBG("[%u]", sd->slot);
|
||||||
g_list_free_full(sd->pin_cbd_list, ril_sim_pin_cbd_list_free_cb);
|
g_list_free_full(sd->pin_cbd_list, ril_sim_pin_cbd_list_free_cb);
|
||||||
grilio_queue_cancel_all(sd->q, FALSE);
|
grilio_queue_cancel_all(sd->q, FALSE);
|
||||||
grilio_queue_cancel_all(sd->q2, TRUE);
|
|
||||||
ofono_sim_set_data(sim, NULL);
|
ofono_sim_set_data(sim, NULL);
|
||||||
|
|
||||||
if (sd->idle_id) {
|
if (sd->idle_id) {
|
||||||
@@ -1104,15 +1018,11 @@ static void ril_sim_remove(struct ofono_sim *sim)
|
|||||||
g_source_remove(sd->query_passwd_state_timeout_id);
|
g_source_remove(sd->query_passwd_state_timeout_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
ril_radio_remove_handler(sd->radio, sd->radio_state_id);
|
|
||||||
ril_radio_unref(sd->radio);
|
|
||||||
|
|
||||||
ril_sim_card_remove_handler(sd->card, sd->card_status_id);
|
ril_sim_card_remove_handler(sd->card, sd->card_status_id);
|
||||||
ril_sim_card_unref(sd->card);
|
ril_sim_card_unref(sd->card);
|
||||||
|
|
||||||
grilio_channel_unref(sd->io);
|
grilio_channel_unref(sd->io);
|
||||||
grilio_queue_unref(sd->q);
|
grilio_queue_unref(sd->q);
|
||||||
grilio_queue_unref(sd->q2);
|
|
||||||
g_free(sd);
|
g_free(sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,8 @@
|
|||||||
#include <grilio_request.h>
|
#include <grilio_request.h>
|
||||||
#include <grilio_parser.h>
|
#include <grilio_parser.h>
|
||||||
|
|
||||||
|
#include <gutil_misc.h>
|
||||||
|
|
||||||
typedef GObjectClass RilSimCardClass;
|
typedef GObjectClass RilSimCardClass;
|
||||||
typedef struct ril_sim_card RilSimCard;
|
typedef struct ril_sim_card RilSimCard;
|
||||||
|
|
||||||
@@ -436,6 +438,14 @@ void ril_sim_card_unref(struct ril_sim_card *self)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean ril_sim_card_ready(struct ril_sim_card *self)
|
||||||
|
{
|
||||||
|
return self && self->app &&
|
||||||
|
((self->app->app_state == RIL_APPSTATE_READY) ||
|
||||||
|
(self->app->app_state == RIL_APPSTATE_SUBSCRIPTION_PERSO &&
|
||||||
|
self->app->perso_substate == RIL_PERSOSUBSTATE_READY));
|
||||||
|
}
|
||||||
|
|
||||||
gulong ril_sim_card_add_status_received_handler(struct ril_sim_card *self,
|
gulong ril_sim_card_add_status_received_handler(struct ril_sim_card *self,
|
||||||
ril_sim_card_cb_t cb, void *arg)
|
ril_sim_card_cb_t cb, void *arg)
|
||||||
{
|
{
|
||||||
@@ -471,6 +481,11 @@ void ril_sim_card_remove_handler(struct ril_sim_card *self, gulong id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ril_sim_card_remove_handlers(struct ril_sim_card *self, gulong *ids, int n)
|
||||||
|
{
|
||||||
|
gutil_disconnect_handlers(self, ids, n);
|
||||||
|
}
|
||||||
|
|
||||||
static void ril_sim_card_init(struct ril_sim_card *self)
|
static void ril_sim_card_init(struct ril_sim_card *self)
|
||||||
{
|
{
|
||||||
self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self, RIL_SIMCARD_TYPE,
|
self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self, RIL_SIMCARD_TYPE,
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ typedef void (*ril_sim_card_cb_t)(struct ril_sim_card *sc, void *arg);
|
|||||||
struct ril_sim_card *ril_sim_card_new(GRilIoChannel *io, guint slot, int flags);
|
struct ril_sim_card *ril_sim_card_new(GRilIoChannel *io, guint slot, int flags);
|
||||||
struct ril_sim_card *ril_sim_card_ref(struct ril_sim_card *sc);
|
struct ril_sim_card *ril_sim_card_ref(struct ril_sim_card *sc);
|
||||||
void ril_sim_card_unref(struct ril_sim_card *sc);
|
void ril_sim_card_unref(struct ril_sim_card *sc);
|
||||||
|
gboolean ril_sim_card_ready(struct ril_sim_card *sc);
|
||||||
gulong ril_sim_card_add_status_received_handler(struct ril_sim_card *sc,
|
gulong ril_sim_card_add_status_received_handler(struct ril_sim_card *sc,
|
||||||
ril_sim_card_cb_t cb, void *arg);
|
ril_sim_card_cb_t cb, void *arg);
|
||||||
gulong ril_sim_card_add_status_changed_handler(struct ril_sim_card *sc,
|
gulong ril_sim_card_add_status_changed_handler(struct ril_sim_card *sc,
|
||||||
@@ -64,9 +65,10 @@ gulong ril_sim_card_add_state_changed_handler(struct ril_sim_card *sc,
|
|||||||
gulong ril_sim_card_add_app_changed_handler(struct ril_sim_card *sc,
|
gulong ril_sim_card_add_app_changed_handler(struct ril_sim_card *sc,
|
||||||
ril_sim_card_cb_t cb, void *arg);
|
ril_sim_card_cb_t cb, void *arg);
|
||||||
void ril_sim_card_remove_handler(struct ril_sim_card *sc, gulong id);
|
void ril_sim_card_remove_handler(struct ril_sim_card *sc, gulong id);
|
||||||
|
void ril_sim_card_remove_handlers(struct ril_sim_card *sc, gulong *ids, int n);
|
||||||
|
|
||||||
/* Inline wrappers */
|
/* Inline wrappers */
|
||||||
G_INLINE_FUNC enum ril_app_type
|
static inline enum ril_app_type
|
||||||
ril_sim_card_app_type(struct ril_sim_card *sc)
|
ril_sim_card_app_type(struct ril_sim_card *sc)
|
||||||
{ return (sc && sc->app) ? sc->app->app_type : RIL_APPTYPE_UNKNOWN; }
|
{ return (sc && sc->app) ? sc->app->app_type : RIL_APPTYPE_UNKNOWN; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,242 +0,0 @@
|
|||||||
/*
|
|
||||||
* oFono - Open Source Telephony - RIL-based devices
|
|
||||||
*
|
|
||||||
* Copyright (C) 2015-2016 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_log.h"
|
|
||||||
|
|
||||||
#include <ofono/dbus.h>
|
|
||||||
|
|
||||||
#include <gdbus.h>
|
|
||||||
|
|
||||||
#include "ofono.h"
|
|
||||||
#include "storage.h"
|
|
||||||
|
|
||||||
struct ril_sim_dbus {
|
|
||||||
char *path;
|
|
||||||
char *imsi;
|
|
||||||
char *name;
|
|
||||||
char *default_name;
|
|
||||||
gboolean enable_4g;
|
|
||||||
GKeyFile *storage;
|
|
||||||
DBusConnection *conn;
|
|
||||||
struct ril_modem *md;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define RIL_SIM_STORE "ril"
|
|
||||||
#define RIL_SIM_STORE_GROUP "Settings"
|
|
||||||
#define RIL_SIM_STORE_ENABLE_4G "Enable4G"
|
|
||||||
#define RIL_SIM_STORE_DISPLAY_NAME "DisplayName"
|
|
||||||
|
|
||||||
#define RIL_SIM_DBUS_INTERFACE "org.nemomobile.ofono.SimSettings"
|
|
||||||
#define RIL_SIM_DBUS_INTERFACE_VERSION (1)
|
|
||||||
|
|
||||||
#define RIL_SIM_DBUS_DISPLAY_NAME_CHANGED_SIGNAL "DisplayNameChanged"
|
|
||||||
#define RIL_SIM_DBUS_ENABLE_4G_CHANGED_SIGNAL "Enable4GChanged"
|
|
||||||
|
|
||||||
static DBusMessage *ril_sim_dbus_get_all(DBusConnection *conn,
|
|
||||||
DBusMessage *msg, void *data)
|
|
||||||
{
|
|
||||||
struct ril_sim_dbus *dbus = data;
|
|
||||||
DBusMessage *reply = dbus_message_new_method_return(msg);
|
|
||||||
dbus_int32_t version = RIL_SIM_DBUS_INTERFACE_VERSION;
|
|
||||||
dbus_bool_t enable_4g = dbus->enable_4g;
|
|
||||||
DBusMessageIter iter;
|
|
||||||
|
|
||||||
dbus_message_iter_init_append(reply, &iter);
|
|
||||||
dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &version);
|
|
||||||
dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &enable_4g);
|
|
||||||
dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &dbus->name);
|
|
||||||
return reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
static DBusMessage *ril_sim_dbus_get_interface_version(DBusConnection *conn,
|
|
||||||
DBusMessage *msg, void *data)
|
|
||||||
{
|
|
||||||
DBusMessage *reply = dbus_message_new_method_return(msg);
|
|
||||||
dbus_int32_t version = RIL_SIM_DBUS_INTERFACE_VERSION;
|
|
||||||
DBusMessageIter iter;
|
|
||||||
|
|
||||||
dbus_message_iter_init_append(reply, &iter);
|
|
||||||
dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &version);
|
|
||||||
return reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
static DBusMessage *ril_sim_dbus_get_enable_4g(DBusConnection *conn,
|
|
||||||
DBusMessage *msg, void *data)
|
|
||||||
{
|
|
||||||
struct ril_sim_dbus *dbus = data;
|
|
||||||
DBusMessage *reply = dbus_message_new_method_return(msg);
|
|
||||||
dbus_bool_t enable_4g = dbus->enable_4g;
|
|
||||||
DBusMessageIter iter;
|
|
||||||
|
|
||||||
dbus_message_iter_init_append(reply, &iter);
|
|
||||||
dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &enable_4g);
|
|
||||||
return reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
static DBusMessage *ril_sim_dbus_get_display_name(DBusConnection *conn,
|
|
||||||
DBusMessage *msg, void *data)
|
|
||||||
{
|
|
||||||
struct ril_sim_dbus *dbus = data;
|
|
||||||
DBusMessage *reply = dbus_message_new_method_return(msg);
|
|
||||||
DBusMessageIter iter;
|
|
||||||
|
|
||||||
dbus_message_iter_init_append(reply, &iter);
|
|
||||||
dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &dbus->name);
|
|
||||||
return reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ril_sim_dbus_update_display_name(struct ril_sim_dbus *dbus,
|
|
||||||
const char *name)
|
|
||||||
{
|
|
||||||
if (g_strcmp0(dbus->name, name)) {
|
|
||||||
g_free(dbus->name);
|
|
||||||
dbus->name = g_strdup(name);
|
|
||||||
g_key_file_set_string(dbus->storage, RIL_SIM_STORE_GROUP,
|
|
||||||
RIL_SIM_STORE_DISPLAY_NAME, name);
|
|
||||||
storage_sync(dbus->imsi, RIL_SIM_STORE, dbus->storage);
|
|
||||||
g_dbus_emit_signal(dbus->conn, dbus->path,
|
|
||||||
RIL_SIM_DBUS_INTERFACE,
|
|
||||||
RIL_SIM_DBUS_DISPLAY_NAME_CHANGED_SIGNAL,
|
|
||||||
DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static DBusMessage *ril_sim_dbus_set_display_name(DBusConnection *conn,
|
|
||||||
DBusMessage *msg, void *data)
|
|
||||||
{
|
|
||||||
DBusMessageIter iter;
|
|
||||||
|
|
||||||
dbus_message_iter_init(msg, &iter);
|
|
||||||
if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) {
|
|
||||||
struct ril_sim_dbus *dbus = data;
|
|
||||||
DBusBasicValue value;
|
|
||||||
const char *name;
|
|
||||||
|
|
||||||
dbus_message_iter_get_basic(&iter, &value);
|
|
||||||
name = value.str;
|
|
||||||
if (!name || !name[0]) name = dbus->default_name;
|
|
||||||
ril_sim_dbus_update_display_name(dbus, name);
|
|
||||||
return dbus_message_new_method_return(msg);
|
|
||||||
} else {
|
|
||||||
return __ofono_error_invalid_args(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const GDBusMethodTable ril_sim_dbus_methods[] = {
|
|
||||||
{ GDBUS_METHOD("GetAll",
|
|
||||||
NULL, GDBUS_ARGS({ "settings", "ibs" }),
|
|
||||||
ril_sim_dbus_get_all) },
|
|
||||||
{ GDBUS_METHOD("GetInterfaceVersion",
|
|
||||||
NULL, GDBUS_ARGS({ "version", "i" }),
|
|
||||||
ril_sim_dbus_get_interface_version) },
|
|
||||||
{ GDBUS_METHOD("GetEnable4G",
|
|
||||||
NULL, GDBUS_ARGS({ "enable", "b" }),
|
|
||||||
ril_sim_dbus_get_enable_4g) },
|
|
||||||
{ GDBUS_METHOD("GetDisplayName",
|
|
||||||
NULL, GDBUS_ARGS({ "name", "s" }),
|
|
||||||
ril_sim_dbus_get_display_name) },
|
|
||||||
{ GDBUS_METHOD("SetDisplayName",
|
|
||||||
GDBUS_ARGS({ "name", "s" }), NULL,
|
|
||||||
ril_sim_dbus_set_display_name) },
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
static const GDBusSignalTable ril_sim_dbus_signals[] = {
|
|
||||||
{ GDBUS_SIGNAL(RIL_SIM_DBUS_DISPLAY_NAME_CHANGED_SIGNAL,
|
|
||||||
GDBUS_ARGS({ "name", "s" })) },
|
|
||||||
{ GDBUS_SIGNAL(RIL_SIM_DBUS_ENABLE_4G_CHANGED_SIGNAL,
|
|
||||||
GDBUS_ARGS({ "enabled", "b" })) },
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *ril_sim_dbus_imsi(struct ril_sim_dbus *dbus)
|
|
||||||
{
|
|
||||||
return dbus ? dbus->imsi : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ril_sim_dbus *ril_sim_dbus_new(struct ril_modem *md)
|
|
||||||
{
|
|
||||||
const char *imsi = ofono_sim_get_imsi(ril_modem_ofono_sim(md));
|
|
||||||
|
|
||||||
if (imsi) {
|
|
||||||
GError *error = NULL;
|
|
||||||
const struct ril_slot_config *config = &md->config;
|
|
||||||
struct ril_sim_dbus *dbus = g_new0(struct ril_sim_dbus, 1);
|
|
||||||
|
|
||||||
DBG("%s", ril_modem_get_path(md));
|
|
||||||
dbus->md = md;
|
|
||||||
dbus->conn = dbus_connection_ref(ofono_dbus_get_connection());
|
|
||||||
dbus->path = g_strdup(ril_modem_get_path(md));
|
|
||||||
dbus->imsi = g_strdup(imsi);
|
|
||||||
dbus->default_name = g_strdup(config->default_name);
|
|
||||||
|
|
||||||
/* Load settings */
|
|
||||||
dbus->storage = storage_open(imsi, RIL_SIM_STORE);
|
|
||||||
dbus->enable_4g = g_key_file_get_boolean(dbus->storage,
|
|
||||||
RIL_SIM_STORE_GROUP, RIL_SIM_STORE_ENABLE_4G, &error);
|
|
||||||
if (error) {
|
|
||||||
dbus->enable_4g = config->enable_4g;
|
|
||||||
g_error_free(error);
|
|
||||||
error = NULL;
|
|
||||||
}
|
|
||||||
dbus->name = g_key_file_get_string(dbus->storage,
|
|
||||||
RIL_SIM_STORE_GROUP, RIL_SIM_STORE_DISPLAY_NAME, NULL);
|
|
||||||
if (!dbus->name) {
|
|
||||||
dbus->name = g_strdup(config->default_name);
|
|
||||||
GASSERT(dbus->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Register D-Bus interface */
|
|
||||||
if (g_dbus_register_interface(dbus->conn, dbus->path,
|
|
||||||
RIL_SIM_DBUS_INTERFACE, ril_sim_dbus_methods,
|
|
||||||
ril_sim_dbus_signals, NULL, dbus, NULL)) {
|
|
||||||
ofono_modem_add_interface(md->ofono,
|
|
||||||
RIL_SIM_DBUS_INTERFACE);
|
|
||||||
return dbus;
|
|
||||||
} else {
|
|
||||||
ofono_error("RIL D-Bus register failed");
|
|
||||||
ril_sim_dbus_free(dbus);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ril_sim_dbus_free(struct ril_sim_dbus *dbus)
|
|
||||||
{
|
|
||||||
if (dbus) {
|
|
||||||
DBG("%s", dbus->path);
|
|
||||||
g_dbus_unregister_interface(dbus->conn, dbus->path,
|
|
||||||
RIL_SIM_DBUS_INTERFACE);
|
|
||||||
ofono_modem_remove_interface(dbus->md->ofono,
|
|
||||||
RIL_SIM_DBUS_INTERFACE);
|
|
||||||
dbus_connection_unref(dbus->conn);
|
|
||||||
g_key_file_free(dbus->storage);
|
|
||||||
g_free(dbus->path);
|
|
||||||
g_free(dbus->imsi);
|
|
||||||
g_free(dbus->name);
|
|
||||||
g_free(dbus->default_name);
|
|
||||||
g_free(dbus);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Local Variables:
|
|
||||||
* mode: C
|
|
||||||
* c-basic-offset: 8
|
|
||||||
* indent-tabs-mode: t
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
653
ofono/drivers/ril/ril_sim_info.c
Normal file
653
ofono/drivers/ril/ril_sim_info.c
Normal file
@@ -0,0 +1,653 @@
|
|||||||
|
/*
|
||||||
|
* oFono - Open Source Telephony - RIL-based devices
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 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_sim_info.h"
|
||||||
|
#include "ril_network.h"
|
||||||
|
#include "ril_log.h"
|
||||||
|
|
||||||
|
#include <ofono/sim.h>
|
||||||
|
|
||||||
|
#include "ofono.h"
|
||||||
|
#include "storage.h"
|
||||||
|
|
||||||
|
#define RIL_SIM_INFO_STORE "cache"
|
||||||
|
#define RIL_SIM_INFO_STORE_GROUP "sim"
|
||||||
|
#define RIL_SIM_INFO_STORE_SPN "spn"
|
||||||
|
|
||||||
|
/* ICCID -> IMSI map */
|
||||||
|
#define RIL_SIM_ICCID_MAP "iccidmap"
|
||||||
|
#define RIL_SIM_ICCID_MAP_IMSI "imsi"
|
||||||
|
|
||||||
|
#define RIL_SIM_DEFAULT_SPN_BUFSIZE 8
|
||||||
|
G_STATIC_ASSERT(RIL_SIM_DEFAULT_SPN_BUFSIZE >= \
|
||||||
|
OFONO_MAX_MCC_LENGTH + OFONO_MAX_MNC_LENGTH + 1);
|
||||||
|
|
||||||
|
typedef GObjectClass RilSimInfoClass;
|
||||||
|
typedef struct ril_sim_info RilSimInfo;
|
||||||
|
|
||||||
|
typedef void (*ril_sim_info_remove_cb_t)(struct ofono_sim *sim,
|
||||||
|
unsigned int id);
|
||||||
|
typedef void (*ril_sim_info_set_value_cb_t)(struct ril_sim_info *info,
|
||||||
|
const char *value);
|
||||||
|
|
||||||
|
struct ril_sim_info_watch {
|
||||||
|
ril_sim_info_set_value_cb_t set_value;
|
||||||
|
ril_sim_info_remove_cb_t remove;
|
||||||
|
struct ril_sim_info *info;
|
||||||
|
unsigned int id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ril_sim_info_priv {
|
||||||
|
char *log_prefix;
|
||||||
|
char *iccid;
|
||||||
|
char *imsi;
|
||||||
|
char *cached_spn;
|
||||||
|
char *sim_spn;
|
||||||
|
char *public_spn;
|
||||||
|
char default_spn[RIL_SIM_DEFAULT_SPN_BUFSIZE];
|
||||||
|
struct ofono_sim *sim;
|
||||||
|
struct ril_sim_info_watch state_watch;
|
||||||
|
struct ril_sim_info_watch iccid_watch;
|
||||||
|
struct ril_sim_info_watch imsi_watch;
|
||||||
|
struct ril_sim_info_watch spn_watch;
|
||||||
|
struct ril_network *network;
|
||||||
|
gulong network_operator_changed_id;
|
||||||
|
gboolean update_imsi_cache;
|
||||||
|
gboolean update_iccid_map;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ril_sim_info_signal {
|
||||||
|
SIGNAL_ICCID_CHANGED,
|
||||||
|
SIGNAL_IMSI_CHANGED,
|
||||||
|
SIGNAL_SPN_CHANGED,
|
||||||
|
SIGNAL_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SIGNAL_ICCID_CHANGED_NAME "ril-sim-info-iccid-changed"
|
||||||
|
#define SIGNAL_IMSI_CHANGED_NAME "ril-sim-info-imsi-changed"
|
||||||
|
#define SIGNAL_SPN_CHANGED_NAME "ril-sim-info-spn-changed"
|
||||||
|
|
||||||
|
static guint ril_sim_info_signals[SIGNAL_COUNT] = { 0 };
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(RilSimInfo, ril_sim_info, G_TYPE_OBJECT)
|
||||||
|
#define RIL_SIMINFO_TYPE (ril_sim_info_get_type())
|
||||||
|
#define RIL_SIMINFO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
|
||||||
|
RIL_SIMINFO_TYPE, RilSimInfo))
|
||||||
|
|
||||||
|
#define NEW_SIGNAL(klass,name) \
|
||||||
|
ril_sim_info_signals[SIGNAL_##name##_CHANGED] = \
|
||||||
|
g_signal_new(SIGNAL_##name##_CHANGED_NAME, \
|
||||||
|
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST, \
|
||||||
|
0, NULL, NULL, NULL, G_TYPE_NONE, 0)
|
||||||
|
|
||||||
|
#define DBG_(info,fmt,args...) DBG("%s" fmt, (info)->priv->log_prefix, ##args)
|
||||||
|
|
||||||
|
static void ril_sim_info_signal_emit(struct ril_sim_info *self,
|
||||||
|
enum ril_sim_info_signal id)
|
||||||
|
{
|
||||||
|
g_signal_emit(self, ril_sim_info_signals[id], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_watch_remove(struct ril_sim_info_watch *watch)
|
||||||
|
{
|
||||||
|
if (watch->id) {
|
||||||
|
struct ril_sim_info_priv *priv = watch->info->priv;
|
||||||
|
|
||||||
|
GASSERT(priv->sim);
|
||||||
|
if (priv->sim) {
|
||||||
|
watch->remove(priv->sim, watch->id);
|
||||||
|
GASSERT(!watch->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
watch->id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (watch->set_value) {
|
||||||
|
watch->set_value(watch->info, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_remove_spn_watch(struct ofono_sim *sim,
|
||||||
|
unsigned int id)
|
||||||
|
{
|
||||||
|
ofono_sim_remove_spn_watch(sim, &id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_update_imsi_cache(struct ril_sim_info *self)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_priv *priv = self->priv;
|
||||||
|
|
||||||
|
if (priv->update_imsi_cache && priv->imsi && priv->imsi[0] &&
|
||||||
|
priv->cached_spn && priv->cached_spn[0]) {
|
||||||
|
gboolean save = FALSE;
|
||||||
|
const char *store = RIL_SIM_INFO_STORE;
|
||||||
|
GKeyFile *cache = storage_open(priv->imsi, store);
|
||||||
|
char *spn = g_key_file_get_string(cache,
|
||||||
|
RIL_SIM_INFO_STORE_GROUP,
|
||||||
|
RIL_SIM_INFO_STORE_SPN, NULL);
|
||||||
|
|
||||||
|
if (g_strcmp0(priv->cached_spn, spn)) {
|
||||||
|
save = TRUE;
|
||||||
|
g_key_file_set_string(cache, RIL_SIM_INFO_STORE_GROUP,
|
||||||
|
RIL_SIM_INFO_STORE_SPN, priv->cached_spn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since we are most likely running on flash which
|
||||||
|
* supports a limited number of writes, don't overwrite
|
||||||
|
* the file unless something has actually changed.
|
||||||
|
*/
|
||||||
|
if (save) {
|
||||||
|
DBG_(self, "updating " STORAGEDIR "/%s/%s",
|
||||||
|
priv->imsi, store);
|
||||||
|
storage_close(priv->imsi, store, cache, TRUE);
|
||||||
|
} else {
|
||||||
|
g_key_file_free(cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(spn);
|
||||||
|
priv->update_imsi_cache = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_update_iccid_map(struct ril_sim_info *self)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_priv *priv = self->priv;
|
||||||
|
|
||||||
|
if (priv->update_iccid_map && priv->iccid && priv->iccid[0] &&
|
||||||
|
priv->imsi && priv->imsi[0]) {
|
||||||
|
const char *store = RIL_SIM_ICCID_MAP;
|
||||||
|
GKeyFile *map = storage_open(NULL, store);
|
||||||
|
char *imsi = g_key_file_get_string(map, RIL_SIM_ICCID_MAP_IMSI,
|
||||||
|
priv->iccid, NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since we are most likely running on flash which
|
||||||
|
* supports a limited number of writes, don't overwrite
|
||||||
|
* the file unless something has actually changed.
|
||||||
|
*/
|
||||||
|
if (g_strcmp0(imsi, priv->imsi)) {
|
||||||
|
DBG_(self, "updating " STORAGEDIR "/%s", store);
|
||||||
|
g_key_file_set_string(map, RIL_SIM_ICCID_MAP_IMSI,
|
||||||
|
priv->iccid, priv->imsi);
|
||||||
|
storage_close(NULL, store, map, TRUE);
|
||||||
|
} else {
|
||||||
|
g_key_file_free(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(imsi);
|
||||||
|
priv->update_iccid_map = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_set_imsi(struct ril_sim_info *self, const char *imsi)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_priv *priv = self->priv;
|
||||||
|
|
||||||
|
if (g_strcmp0(priv->imsi, imsi)) {
|
||||||
|
g_free(priv->imsi);
|
||||||
|
self->imsi = priv->imsi = g_strdup(imsi);
|
||||||
|
priv->update_iccid_map = TRUE;
|
||||||
|
ril_sim_info_update_iccid_map(self);
|
||||||
|
ril_sim_info_update_imsi_cache(self);
|
||||||
|
ril_sim_info_signal_emit(self, SIGNAL_IMSI_CHANGED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_update_public_spn(struct ril_sim_info *self)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_priv *priv = self->priv;
|
||||||
|
const char *spn = priv->sim_spn ? priv->sim_spn :
|
||||||
|
priv->cached_spn ? priv->cached_spn :
|
||||||
|
priv->default_spn;
|
||||||
|
|
||||||
|
if (g_strcmp0(priv->public_spn, spn)) {
|
||||||
|
g_free(priv->public_spn);
|
||||||
|
self->spn = priv->public_spn = g_strdup(spn);
|
||||||
|
ril_sim_info_signal_emit(self, SIGNAL_SPN_CHANGED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_set_cached_spn(struct ril_sim_info *self,
|
||||||
|
const char *spn)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_priv *priv = self->priv;
|
||||||
|
|
||||||
|
if (g_strcmp0(priv->cached_spn, spn)) {
|
||||||
|
DBG_(self, "cached spn \"%s\"", spn);
|
||||||
|
g_free(priv->cached_spn);
|
||||||
|
priv->cached_spn = g_strdup(spn);
|
||||||
|
priv->update_imsi_cache = TRUE;
|
||||||
|
ril_sim_info_update_imsi_cache(self);
|
||||||
|
ril_sim_info_update_public_spn(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_set_sim_spn(struct ril_sim_info *self,
|
||||||
|
const char *spn)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_priv *priv = self->priv;
|
||||||
|
|
||||||
|
if (g_strcmp0(priv->sim_spn, spn)) {
|
||||||
|
g_free(priv->sim_spn);
|
||||||
|
priv->sim_spn = g_strdup(spn);
|
||||||
|
priv->update_imsi_cache = TRUE;
|
||||||
|
ril_sim_info_set_cached_spn(self, spn);
|
||||||
|
ril_sim_info_update_imsi_cache(self);
|
||||||
|
ril_sim_info_update_public_spn(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_update_default_spn(struct ril_sim_info *self)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_priv *priv = self->priv;
|
||||||
|
char buf[RIL_SIM_DEFAULT_SPN_BUFSIZE];
|
||||||
|
const char *mcc = NULL;
|
||||||
|
const char *mnc = NULL;
|
||||||
|
|
||||||
|
if (priv->sim &&
|
||||||
|
ofono_sim_get_state(priv->sim) == OFONO_SIM_STATE_READY) {
|
||||||
|
mcc = ofono_sim_get_mcc(priv->sim);
|
||||||
|
mnc = ofono_sim_get_mnc(priv->sim);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mcc && mnc) {
|
||||||
|
snprintf(buf, RIL_SIM_DEFAULT_SPN_BUFSIZE, "%s%s", mcc, mnc);
|
||||||
|
buf[RIL_SIM_DEFAULT_SPN_BUFSIZE - 1] = 0;
|
||||||
|
} else {
|
||||||
|
buf[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(buf, priv->default_spn)) {
|
||||||
|
strncpy(priv->default_spn, buf, RIL_SIM_DEFAULT_SPN_BUFSIZE);
|
||||||
|
DBG_(self, "default spn \"%s\"", priv->default_spn);
|
||||||
|
ril_sim_info_update_public_spn(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_network_check(struct ril_sim_info *self)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_priv *priv = self->priv;
|
||||||
|
|
||||||
|
if (priv->network && priv->network->operator && priv->sim &&
|
||||||
|
ofono_sim_get_state(priv->sim) == OFONO_SIM_STATE_READY) {
|
||||||
|
const char *mcc = ofono_sim_get_mcc(priv->sim);
|
||||||
|
const char *mnc = ofono_sim_get_mnc(priv->sim);
|
||||||
|
const struct ofono_network_operator *op =
|
||||||
|
priv->network->operator;
|
||||||
|
|
||||||
|
if (mcc && mcc[0] && !strcmp(mcc, op->mcc) &&
|
||||||
|
mnc && mnc[0] && !strcmp(mnc, op->mnc)) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If EFspn is present then sim_spn should be set
|
||||||
|
* before we get registered with the network.
|
||||||
|
*/
|
||||||
|
DBG_(self, "home network \"%s\"", op->name);
|
||||||
|
if (!priv->sim_spn) {
|
||||||
|
ril_sim_info_set_cached_spn(self, op->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_network_operator_changed(struct ril_network *network,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct ril_sim_info *self = RIL_SIMINFO(user_data);
|
||||||
|
|
||||||
|
DBG_(self, "");
|
||||||
|
ril_sim_info_network_check(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_load_cache(struct ril_sim_info *self)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_priv *priv = self->priv;
|
||||||
|
|
||||||
|
if (priv->iccid && priv->iccid[0]) {
|
||||||
|
GKeyFile *map = storage_open(NULL, RIL_SIM_ICCID_MAP);
|
||||||
|
char *imsi = g_key_file_get_string(map, RIL_SIM_ICCID_MAP_IMSI,
|
||||||
|
priv->iccid, NULL);
|
||||||
|
g_key_file_free(map);
|
||||||
|
|
||||||
|
if (imsi && imsi[0] && g_strcmp0(priv->imsi, imsi)) {
|
||||||
|
if (priv->imsi && priv->imsi[0]) {
|
||||||
|
/* Need to update ICCID -> IMSI map */
|
||||||
|
DBG_(self, "IMSI changed %s -> %s",
|
||||||
|
priv->imsi, imsi);
|
||||||
|
priv->update_imsi_cache = TRUE;
|
||||||
|
}
|
||||||
|
g_free(priv->imsi);
|
||||||
|
self->imsi = priv->imsi = imsi;
|
||||||
|
DBG_(self, "imsi[%s] = %s", priv->iccid, imsi);
|
||||||
|
ril_sim_info_update_iccid_map(self);
|
||||||
|
ril_sim_info_signal_emit(self, SIGNAL_IMSI_CHANGED);
|
||||||
|
} else if (imsi) {
|
||||||
|
g_free(imsi);
|
||||||
|
} else {
|
||||||
|
DBG_(self, "no imsi for iccid %s", priv->iccid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->imsi && priv->imsi[0]) {
|
||||||
|
GKeyFile *cache = storage_open(priv->imsi, RIL_SIM_INFO_STORE);
|
||||||
|
char *spn = g_key_file_get_string(cache,
|
||||||
|
RIL_SIM_INFO_STORE_GROUP,
|
||||||
|
RIL_SIM_INFO_STORE_SPN, NULL);
|
||||||
|
g_key_file_free(cache);
|
||||||
|
|
||||||
|
if (spn && spn[0] && g_strcmp0(priv->cached_spn, spn)) {
|
||||||
|
if (priv->cached_spn && priv->cached_spn[0]) {
|
||||||
|
/* Need to update the cache file */
|
||||||
|
DBG_(self, "spn changing %s -> %s",
|
||||||
|
priv->cached_spn, spn);
|
||||||
|
priv->update_imsi_cache = TRUE;
|
||||||
|
}
|
||||||
|
g_free(priv->cached_spn);
|
||||||
|
priv->cached_spn = spn;
|
||||||
|
DBG_(self, "spn[%s] = \"%s\"", priv->imsi, spn);
|
||||||
|
ril_sim_info_update_imsi_cache(self);
|
||||||
|
ril_sim_info_update_public_spn(self);
|
||||||
|
} else if (spn) {
|
||||||
|
g_free(spn);
|
||||||
|
} else {
|
||||||
|
DBG_(self, "no spn for imsi %s", priv->imsi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_set_iccid(struct ril_sim_info *self, const char *iccid)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_priv *priv = self->priv;
|
||||||
|
|
||||||
|
if (g_strcmp0(priv->iccid, iccid)) {
|
||||||
|
g_free(priv->iccid);
|
||||||
|
self->iccid = priv->iccid = g_strdup(iccid);
|
||||||
|
ril_sim_info_signal_emit(self, SIGNAL_ICCID_CHANGED);
|
||||||
|
if (iccid) {
|
||||||
|
ril_sim_info_load_cache(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_imsi_watch_cb(const char *imsi, void *data)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_watch *watch = data;
|
||||||
|
|
||||||
|
DBG_(watch->info, "%s", imsi);
|
||||||
|
ril_sim_info_set_imsi(watch->info, imsi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_spn_watch_cb(const char *spn, const char *dc,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_watch *watch = data;
|
||||||
|
|
||||||
|
DBG_(watch->info, "%s", spn);
|
||||||
|
ril_sim_info_set_sim_spn(watch->info, spn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_iccid_watch_cb(const char *iccid, void *data)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_watch *watch = data;
|
||||||
|
|
||||||
|
DBG_(watch->info, "%s", iccid);
|
||||||
|
ril_sim_info_set_iccid(watch->info, iccid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_watch_done(void *data)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_watch *watch = data;
|
||||||
|
|
||||||
|
GASSERT(watch->id);
|
||||||
|
watch->id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_handle_sim_state(struct ril_sim_info *self,
|
||||||
|
enum ofono_sim_state state)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_priv *priv = self->priv;
|
||||||
|
struct ril_sim_info_watch *watch;
|
||||||
|
|
||||||
|
DBG_(self, "%d", state);
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case OFONO_SIM_STATE_READY:
|
||||||
|
/* SPN */
|
||||||
|
watch = &priv->spn_watch;
|
||||||
|
if (!watch->id) {
|
||||||
|
ofono_sim_add_spn_watch(priv->sim, &watch->id,
|
||||||
|
ril_sim_info_spn_watch_cb, watch,
|
||||||
|
ril_sim_info_watch_done);
|
||||||
|
GASSERT(priv->spn_watch.id);
|
||||||
|
}
|
||||||
|
/* IMSI */
|
||||||
|
watch = &priv->imsi_watch;
|
||||||
|
if (!watch->id) {
|
||||||
|
watch->id = ofono_sim_add_imsi_watch(priv->sim,
|
||||||
|
ril_sim_info_imsi_watch_cb, watch,
|
||||||
|
ril_sim_info_watch_done);
|
||||||
|
GASSERT(watch->id);
|
||||||
|
}
|
||||||
|
/* no break */
|
||||||
|
case OFONO_SIM_STATE_INSERTED:
|
||||||
|
case OFONO_SIM_STATE_LOCKED_OUT:
|
||||||
|
/* ICCID */
|
||||||
|
watch = &priv->iccid_watch;
|
||||||
|
if (!watch->id) {
|
||||||
|
watch->id = ofono_sim_add_iccid_watch(priv->sim,
|
||||||
|
ril_sim_info_iccid_watch_cb, watch,
|
||||||
|
ril_sim_info_watch_done);
|
||||||
|
GASSERT(watch->id);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OFONO_SIM_STATE_NOT_PRESENT:
|
||||||
|
case OFONO_SIM_STATE_RESETTING:
|
||||||
|
ril_sim_info_watch_remove(&priv->spn_watch);
|
||||||
|
ril_sim_info_watch_remove(&priv->imsi_watch);
|
||||||
|
ril_sim_info_watch_remove(&priv->iccid_watch);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ril_sim_info_update_default_spn(self);
|
||||||
|
ril_sim_info_network_check(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_state_watch_cb(enum ofono_sim_state new_state,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_watch *watch = data;
|
||||||
|
ril_sim_info_handle_sim_state(watch->info, new_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ril_sim_info *ril_sim_info_new(const char *log_prefix)
|
||||||
|
{
|
||||||
|
struct ril_sim_info *self = g_object_new(RIL_SIMINFO_TYPE, NULL);
|
||||||
|
|
||||||
|
self->priv->log_prefix = (log_prefix && log_prefix[0]) ?
|
||||||
|
g_strconcat(log_prefix, " ", NULL) : g_strdup("");
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ril_sim_info *ril_sim_info_ref(struct ril_sim_info *self)
|
||||||
|
{
|
||||||
|
if (G_LIKELY(self)) {
|
||||||
|
g_object_ref(RIL_SIMINFO(self));
|
||||||
|
return self;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ril_sim_info_unref(struct ril_sim_info *self)
|
||||||
|
{
|
||||||
|
if (G_LIKELY(self)) {
|
||||||
|
g_object_unref(RIL_SIMINFO(self));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ril_sim_info_set_ofono_sim(struct ril_sim_info *self,
|
||||||
|
struct ofono_sim *sim)
|
||||||
|
{
|
||||||
|
if (G_LIKELY(self)) {
|
||||||
|
struct ril_sim_info_priv *priv = self->priv;
|
||||||
|
|
||||||
|
if (priv->sim != sim) {
|
||||||
|
ril_sim_info_watch_remove(&priv->state_watch);
|
||||||
|
ril_sim_info_watch_remove(&priv->iccid_watch);
|
||||||
|
ril_sim_info_watch_remove(&priv->imsi_watch);
|
||||||
|
ril_sim_info_watch_remove(&priv->spn_watch);
|
||||||
|
|
||||||
|
priv->update_imsi_cache = FALSE;
|
||||||
|
priv->update_iccid_map = FALSE;
|
||||||
|
priv->sim = sim;
|
||||||
|
|
||||||
|
if (sim) {
|
||||||
|
priv->state_watch.id =
|
||||||
|
ofono_sim_add_state_watch(sim,
|
||||||
|
ril_sim_info_state_watch_cb,
|
||||||
|
&priv->state_watch,
|
||||||
|
ril_sim_info_watch_done);
|
||||||
|
GASSERT(priv->state_watch.id);
|
||||||
|
DBG_(self, "attached to sim");
|
||||||
|
ril_sim_info_handle_sim_state(self,
|
||||||
|
ofono_sim_get_state(sim));
|
||||||
|
}
|
||||||
|
|
||||||
|
ril_sim_info_network_check(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ril_sim_info_set_network(struct ril_sim_info *self,
|
||||||
|
struct ril_network *network)
|
||||||
|
{
|
||||||
|
if (G_LIKELY(self) && self->priv->network != network) {
|
||||||
|
struct ril_sim_info_priv *priv = self->priv;
|
||||||
|
|
||||||
|
if (priv->network) {
|
||||||
|
ril_network_remove_handlers(priv->network,
|
||||||
|
&priv->network_operator_changed_id, 1);
|
||||||
|
ril_network_unref(priv->network);
|
||||||
|
}
|
||||||
|
if (network) {
|
||||||
|
priv->network_operator_changed_id =
|
||||||
|
ril_network_add_operator_changed_handler(network,
|
||||||
|
ril_sim_info_network_operator_changed,
|
||||||
|
self);
|
||||||
|
priv->network = ril_network_ref(network);
|
||||||
|
ril_sim_info_network_check(self);
|
||||||
|
} else {
|
||||||
|
priv->network = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gulong ril_sim_info_add_iccid_changed_handler(struct ril_sim_info *self,
|
||||||
|
ril_sim_info_cb_t cb, void *arg)
|
||||||
|
{
|
||||||
|
return (G_LIKELY(self) && G_LIKELY(cb)) ? g_signal_connect(self,
|
||||||
|
SIGNAL_ICCID_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gulong ril_sim_info_add_imsi_changed_handler(struct ril_sim_info *self,
|
||||||
|
ril_sim_info_cb_t cb, void *arg)
|
||||||
|
{
|
||||||
|
return (G_LIKELY(self) && G_LIKELY(cb)) ? g_signal_connect(self,
|
||||||
|
SIGNAL_IMSI_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gulong ril_sim_info_add_spn_changed_handler(struct ril_sim_info *self,
|
||||||
|
ril_sim_info_cb_t cb, void *arg)
|
||||||
|
{
|
||||||
|
return (G_LIKELY(self) && G_LIKELY(cb)) ? g_signal_connect(self,
|
||||||
|
SIGNAL_SPN_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ril_sim_info_remove_handler(struct ril_sim_info *self, gulong id)
|
||||||
|
{
|
||||||
|
if (G_LIKELY(self) && G_LIKELY(id)) {
|
||||||
|
g_signal_handler_disconnect(self, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_watch_init(struct ril_sim_info *self,
|
||||||
|
struct ril_sim_info_watch *watch,
|
||||||
|
ril_sim_info_set_value_cb_t set_value,
|
||||||
|
ril_sim_info_remove_cb_t remove)
|
||||||
|
{
|
||||||
|
watch->info = self;
|
||||||
|
watch->set_value = set_value;
|
||||||
|
watch->remove = remove;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_init(struct ril_sim_info *self)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_priv *priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
|
||||||
|
RIL_SIMINFO_TYPE, struct ril_sim_info_priv);
|
||||||
|
|
||||||
|
self->priv = priv;
|
||||||
|
ril_sim_info_watch_init(self, &priv->state_watch,
|
||||||
|
NULL, ofono_sim_remove_state_watch);
|
||||||
|
ril_sim_info_watch_init(self, &priv->iccid_watch,
|
||||||
|
ril_sim_info_set_iccid, ofono_sim_remove_iccid_watch);
|
||||||
|
ril_sim_info_watch_init(self, &priv->imsi_watch,
|
||||||
|
ril_sim_info_set_imsi, ofono_sim_remove_imsi_watch);
|
||||||
|
ril_sim_info_watch_init(self, &priv->spn_watch,
|
||||||
|
ril_sim_info_set_sim_spn, ril_sim_info_remove_spn_watch);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_dispose(GObject *object)
|
||||||
|
{
|
||||||
|
struct ril_sim_info *self = RIL_SIMINFO(object);
|
||||||
|
|
||||||
|
ril_sim_info_set_ofono_sim(self, NULL);
|
||||||
|
ril_sim_info_set_network(self, NULL);
|
||||||
|
G_OBJECT_CLASS(ril_sim_info_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_finalize(GObject *object)
|
||||||
|
{
|
||||||
|
struct ril_sim_info *self = RIL_SIMINFO(object);
|
||||||
|
struct ril_sim_info_priv *priv = self->priv;
|
||||||
|
|
||||||
|
g_free(priv->log_prefix);
|
||||||
|
g_free(priv->cached_spn);
|
||||||
|
g_free(priv->public_spn);
|
||||||
|
GASSERT(!priv->iccid);
|
||||||
|
GASSERT(!priv->imsi);
|
||||||
|
GASSERT(!priv->sim_spn);
|
||||||
|
G_OBJECT_CLASS(ril_sim_info_parent_class)->finalize(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_class_init(RilSimInfoClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
||||||
|
|
||||||
|
object_class->dispose = ril_sim_info_dispose;
|
||||||
|
object_class->finalize = ril_sim_info_finalize;
|
||||||
|
g_type_class_add_private(klass, sizeof(struct ril_sim_info_priv));
|
||||||
|
NEW_SIGNAL(klass, ICCID);
|
||||||
|
NEW_SIGNAL(klass, IMSI);
|
||||||
|
NEW_SIGNAL(klass, SPN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local Variables:
|
||||||
|
* mode: C
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
53
ofono/drivers/ril/ril_sim_info.h
Normal file
53
ofono/drivers/ril/ril_sim_info.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* oFono - Open Source Telephony - RIL-based devices
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 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_SIM_INFO_H
|
||||||
|
#define RIL_SIM_INFO_H
|
||||||
|
|
||||||
|
#include "ril_types.h"
|
||||||
|
|
||||||
|
struct ril_sim_info {
|
||||||
|
GObject object;
|
||||||
|
struct ril_sim_info_priv *priv;
|
||||||
|
const char *iccid;
|
||||||
|
const char *imsi;
|
||||||
|
const char *spn;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ofono_sim;
|
||||||
|
typedef void (*ril_sim_info_cb_t)(struct ril_sim_info *info, void *arg);
|
||||||
|
|
||||||
|
struct ril_sim_info *ril_sim_info_new(const char *log_prefix);
|
||||||
|
struct ril_sim_info *ril_sim_info_ref(struct ril_sim_info *info);
|
||||||
|
void ril_sim_info_unref(struct ril_sim_info *si);
|
||||||
|
void ril_sim_info_set_ofono_sim(struct ril_sim_info *si, struct ofono_sim *sim);
|
||||||
|
void ril_sim_info_set_network(struct ril_sim_info *si, struct ril_network *net);
|
||||||
|
gulong ril_sim_info_add_iccid_changed_handler(struct ril_sim_info *si,
|
||||||
|
ril_sim_info_cb_t cb, void *arg);
|
||||||
|
gulong ril_sim_info_add_imsi_changed_handler(struct ril_sim_info *si,
|
||||||
|
ril_sim_info_cb_t cb, void *arg);
|
||||||
|
gulong ril_sim_info_add_spn_changed_handler(struct ril_sim_info *si,
|
||||||
|
ril_sim_info_cb_t cb, void *arg);
|
||||||
|
void ril_sim_info_remove_handler(struct ril_sim_info *si, gulong id);
|
||||||
|
|
||||||
|
#endif /* RIL_SIM_INFO_H */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local Variables:
|
||||||
|
* mode: C
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
243
ofono/drivers/ril/ril_sim_info_dbus.c
Normal file
243
ofono/drivers/ril/ril_sim_info_dbus.c
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
/*
|
||||||
|
* oFono - Open Source Telephony - RIL-based devices
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 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_sim_info.h"
|
||||||
|
#include "ril_log.h"
|
||||||
|
|
||||||
|
#include <ofono/dbus.h>
|
||||||
|
|
||||||
|
#include <gdbus.h>
|
||||||
|
|
||||||
|
#include "ofono.h"
|
||||||
|
#include "storage.h"
|
||||||
|
|
||||||
|
enum sim_info_event_id {
|
||||||
|
SIM_INFO_EVENT_ICCID,
|
||||||
|
SIM_INFO_EVENT_IMSI,
|
||||||
|
SIM_INFO_EVENT_SPN,
|
||||||
|
SIM_INFO_EVENT_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ril_sim_info_dbus {
|
||||||
|
struct ril_modem *md;
|
||||||
|
struct ril_sim_info *info;
|
||||||
|
DBusConnection *conn;
|
||||||
|
char *path;
|
||||||
|
gulong handler_id[SIM_INFO_EVENT_COUNT];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define RIL_SIM_INFO_DBUS_INTERFACE "org.nemomobile.ofono.SimInfo"
|
||||||
|
#define RIL_SIM_INFO_DBUS_INTERFACE_VERSION (1)
|
||||||
|
|
||||||
|
#define RIL_SIM_INFO_DBUS_ICCID_CHANGED_SIGNAL "CardIdentifierChanged"
|
||||||
|
#define RIL_SIM_INFO_DBUS_IMSI_CHANGED_SIGNAL "SubscriberIdentityChanged"
|
||||||
|
#define RIL_SIM_INFO_DBUS_SPN_CHANGED_SIGNAL "ServiceProviderNameChanged"
|
||||||
|
|
||||||
|
static void ril_sim_info_dbus_append_string(DBusMessageIter *it, const char *s)
|
||||||
|
{
|
||||||
|
if (!s) s = "";
|
||||||
|
dbus_message_iter_append_basic(it, DBUS_TYPE_STRING, &s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DBusMessage *ril_sim_info_dbus_reply_with_string(DBusMessage *msg,
|
||||||
|
const char *str)
|
||||||
|
{
|
||||||
|
DBusMessage *reply = dbus_message_new_method_return(msg);
|
||||||
|
DBusMessageIter iter;
|
||||||
|
|
||||||
|
dbus_message_iter_init_append(reply, &iter);
|
||||||
|
ril_sim_info_dbus_append_string(&iter, str);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DBusMessage *ril_sim_info_dbus_get_all(DBusConnection *conn,
|
||||||
|
DBusMessage *msg, void *data)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_dbus *dbus = data;
|
||||||
|
struct ril_sim_info *info = dbus->info;
|
||||||
|
DBusMessage *reply = dbus_message_new_method_return(msg);
|
||||||
|
const dbus_int32_t version = RIL_SIM_INFO_DBUS_INTERFACE_VERSION;
|
||||||
|
DBusMessageIter iter;
|
||||||
|
|
||||||
|
dbus_message_iter_init_append(reply, &iter);
|
||||||
|
dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &version);
|
||||||
|
ril_sim_info_dbus_append_string(&iter, info->iccid);
|
||||||
|
ril_sim_info_dbus_append_string(&iter, info->imsi);
|
||||||
|
ril_sim_info_dbus_append_string(&iter, info->spn);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DBusMessage *ril_sim_info_dbus_get_version(DBusConnection *dc,
|
||||||
|
DBusMessage *msg, void *data)
|
||||||
|
{
|
||||||
|
DBusMessage *reply = dbus_message_new_method_return(msg);
|
||||||
|
dbus_int32_t version = RIL_SIM_INFO_DBUS_INTERFACE_VERSION;
|
||||||
|
DBusMessageIter iter;
|
||||||
|
|
||||||
|
dbus_message_iter_init_append(reply, &iter);
|
||||||
|
dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &version);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DBusMessage *ril_sim_info_dbus_get_iccid(DBusConnection *conn,
|
||||||
|
DBusMessage *msg, void *data)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_dbus *dbus = data;
|
||||||
|
return ril_sim_info_dbus_reply_with_string(msg, dbus->info->iccid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DBusMessage *ril_sim_info_dbus_get_imsi(DBusConnection *conn,
|
||||||
|
DBusMessage *msg, void *data)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_dbus *dbus = data;
|
||||||
|
return ril_sim_info_dbus_reply_with_string(msg, dbus->info->imsi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DBusMessage *ril_sim_info_dbus_get_spn(DBusConnection *conn,
|
||||||
|
DBusMessage *msg, void *data)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_dbus *dbus = data;
|
||||||
|
return ril_sim_info_dbus_reply_with_string(msg, dbus->info->spn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const GDBusMethodTable ril_sim_info_dbus_methods[] = {
|
||||||
|
{ GDBUS_METHOD("GetAll",
|
||||||
|
NULL, GDBUS_ARGS({"version", "i" },
|
||||||
|
{"iccid", "s" },
|
||||||
|
{"imsi", "s" },
|
||||||
|
{"spn" , "s"}),
|
||||||
|
ril_sim_info_dbus_get_all) },
|
||||||
|
{ GDBUS_METHOD("GetInterfaceVersion",
|
||||||
|
NULL, GDBUS_ARGS({ "version", "i" }),
|
||||||
|
ril_sim_info_dbus_get_version) },
|
||||||
|
{ GDBUS_METHOD("GetCardIdentifier",
|
||||||
|
NULL, GDBUS_ARGS({ "iccid", "s" }),
|
||||||
|
ril_sim_info_dbus_get_iccid) },
|
||||||
|
{ GDBUS_METHOD("GetSubscriberIdentity",
|
||||||
|
NULL, GDBUS_ARGS({ "imsi", "s" }),
|
||||||
|
ril_sim_info_dbus_get_imsi) },
|
||||||
|
{ GDBUS_METHOD("GetServiceProviderName",
|
||||||
|
NULL, GDBUS_ARGS({ "spn", "s" }),
|
||||||
|
ril_sim_info_dbus_get_spn) },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const GDBusSignalTable ril_sim_info_dbus_signals[] = {
|
||||||
|
{ GDBUS_SIGNAL(RIL_SIM_INFO_DBUS_ICCID_CHANGED_SIGNAL,
|
||||||
|
GDBUS_ARGS({ "iccid", "s" })) },
|
||||||
|
{ GDBUS_SIGNAL(RIL_SIM_INFO_DBUS_IMSI_CHANGED_SIGNAL,
|
||||||
|
GDBUS_ARGS({ "imsi", "s" })) },
|
||||||
|
{ GDBUS_SIGNAL(RIL_SIM_INFO_DBUS_SPN_CHANGED_SIGNAL,
|
||||||
|
GDBUS_ARGS({ "spn", "s" })) },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static void ril_sim_info_dbus_emit(struct ril_sim_info_dbus *dbus,
|
||||||
|
const char *signal, const char *value)
|
||||||
|
{
|
||||||
|
const char *arg = value;
|
||||||
|
if (!arg) arg = "";
|
||||||
|
g_dbus_emit_signal(dbus->conn, dbus->path, RIL_SIM_INFO_DBUS_INTERFACE,
|
||||||
|
signal, DBUS_TYPE_STRING, &arg, DBUS_TYPE_INVALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_dbus_iccid_cb(struct ril_sim_info *info, void *arg)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_dbus *dbus = arg;
|
||||||
|
ril_sim_info_dbus_emit(dbus, RIL_SIM_INFO_DBUS_ICCID_CHANGED_SIGNAL,
|
||||||
|
info->iccid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_dbus_imsi_cb(struct ril_sim_info *info, void *arg)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_dbus *dbus = arg;
|
||||||
|
ril_sim_info_dbus_emit(dbus, RIL_SIM_INFO_DBUS_IMSI_CHANGED_SIGNAL,
|
||||||
|
info->imsi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_info_dbus_spn_cb(struct ril_sim_info *info, void *arg)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_dbus *dbus = arg;
|
||||||
|
ril_sim_info_dbus_emit(dbus, RIL_SIM_INFO_DBUS_SPN_CHANGED_SIGNAL,
|
||||||
|
info->spn);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ril_sim_info_dbus *ril_sim_info_dbus_new(struct ril_modem *md,
|
||||||
|
struct ril_sim_info *info)
|
||||||
|
{
|
||||||
|
struct ril_sim_info_dbus *dbus = g_new0(struct ril_sim_info_dbus, 1);
|
||||||
|
|
||||||
|
DBG("%s", ril_modem_get_path(md));
|
||||||
|
dbus->md = md;
|
||||||
|
dbus->path = g_strdup(ril_modem_get_path(md));
|
||||||
|
dbus->info = ril_sim_info_ref(info);
|
||||||
|
dbus->conn = dbus_connection_ref(ofono_dbus_get_connection());
|
||||||
|
|
||||||
|
/* Register D-Bus interface */
|
||||||
|
if (g_dbus_register_interface(dbus->conn, dbus->path,
|
||||||
|
RIL_SIM_INFO_DBUS_INTERFACE, ril_sim_info_dbus_methods,
|
||||||
|
ril_sim_info_dbus_signals, NULL, dbus, NULL)) {
|
||||||
|
ofono_modem_add_interface(md->ofono,
|
||||||
|
RIL_SIM_INFO_DBUS_INTERFACE);
|
||||||
|
|
||||||
|
dbus->handler_id[SIM_INFO_EVENT_ICCID] =
|
||||||
|
ril_sim_info_add_iccid_changed_handler(info,
|
||||||
|
ril_sim_info_dbus_iccid_cb, dbus);
|
||||||
|
dbus->handler_id[SIM_INFO_EVENT_IMSI] =
|
||||||
|
ril_sim_info_add_imsi_changed_handler(info,
|
||||||
|
ril_sim_info_dbus_imsi_cb, dbus);
|
||||||
|
dbus->handler_id[SIM_INFO_EVENT_SPN] =
|
||||||
|
ril_sim_info_add_spn_changed_handler(info,
|
||||||
|
ril_sim_info_dbus_spn_cb, dbus);
|
||||||
|
|
||||||
|
return dbus;
|
||||||
|
} else {
|
||||||
|
ofono_error("CellInfo D-Bus register failed");
|
||||||
|
ril_sim_info_dbus_free(dbus);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ril_sim_info_dbus_free(struct ril_sim_info_dbus *dbus)
|
||||||
|
{
|
||||||
|
if (dbus) {
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
DBG("%s", dbus->path);
|
||||||
|
g_dbus_unregister_interface(dbus->conn, dbus->path,
|
||||||
|
RIL_SIM_INFO_DBUS_INTERFACE);
|
||||||
|
ofono_modem_remove_interface(dbus->md->ofono,
|
||||||
|
RIL_SIM_INFO_DBUS_INTERFACE);
|
||||||
|
dbus_connection_unref(dbus->conn);
|
||||||
|
|
||||||
|
for (i=0; i<G_N_ELEMENTS(dbus->handler_id); i++) {
|
||||||
|
ril_sim_info_remove_handler(dbus->info,
|
||||||
|
dbus->handler_id[i]);
|
||||||
|
}
|
||||||
|
ril_sim_info_unref(dbus->info);
|
||||||
|
|
||||||
|
g_free(dbus->path);
|
||||||
|
g_free(dbus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local Variables:
|
||||||
|
* mode: C
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
305
ofono/drivers/ril/ril_sim_settings.c
Normal file
305
ofono/drivers/ril/ril_sim_settings.c
Normal file
@@ -0,0 +1,305 @@
|
|||||||
|
/*
|
||||||
|
* oFono - Open Source Telephony - RIL-based devices
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 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_sim_settings.h"
|
||||||
|
#include "ril_log.h"
|
||||||
|
|
||||||
|
#include <gutil_misc.h>
|
||||||
|
|
||||||
|
#include <ofono/sim.h>
|
||||||
|
|
||||||
|
#include "storage.h"
|
||||||
|
|
||||||
|
#define RIL_SIM_STORE "ril"
|
||||||
|
#define RIL_SIM_STORE_GROUP "Settings"
|
||||||
|
#define RIL_SIM_STORE_PREF_MODE "TechnologyPreference"
|
||||||
|
|
||||||
|
#define RIL_SIM_STORE_PREF_MODE_DEFAULT(self) ((self)->enable_4g ? \
|
||||||
|
OFONO_RADIO_ACCESS_MODE_LTE : OFONO_RADIO_ACCESS_MODE_UMTS)
|
||||||
|
|
||||||
|
typedef GObjectClass RilSimSettingsClass;
|
||||||
|
typedef struct ril_sim_settings RilSimSettings;
|
||||||
|
|
||||||
|
struct ril_sim_settings_priv {
|
||||||
|
struct ofono_sim *sim;
|
||||||
|
guint imsi_watch_id;
|
||||||
|
guint state_watch_id;
|
||||||
|
GKeyFile *storage;
|
||||||
|
char *imsi;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ril_sim_settings_signal {
|
||||||
|
SIGNAL_IMSI_CHANGED,
|
||||||
|
SIGNAL_PREF_MODE_CHANGED,
|
||||||
|
SIGNAL_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SIGNAL_IMSI_CHANGED_NAME "ril-sim-settings-imsi-changed"
|
||||||
|
#define SIGNAL_PREF_MODE_CHANGED_NAME "ril-sim-settings-pref-mode-changed"
|
||||||
|
|
||||||
|
static guint ril_sim_settings_signals[SIGNAL_COUNT] = { 0 };
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(RilSimSettings, ril_sim_settings, G_TYPE_OBJECT)
|
||||||
|
#define RIL_SIM_SETTINGS_TYPE (ril_sim_settings_get_type())
|
||||||
|
#define RIL_SIM_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
|
||||||
|
RIL_SIM_SETTINGS_TYPE, RilSimSettings))
|
||||||
|
|
||||||
|
#define NEW_SIGNAL(klass,name) \
|
||||||
|
ril_sim_settings_signals[SIGNAL_##name##_CHANGED] = \
|
||||||
|
g_signal_new(SIGNAL_##name##_CHANGED_NAME, \
|
||||||
|
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST, \
|
||||||
|
0, NULL, NULL, NULL, G_TYPE_NONE, 0)
|
||||||
|
|
||||||
|
static void ril_sim_settings_signal_emit(struct ril_sim_settings *self,
|
||||||
|
enum ril_sim_settings_signal id)
|
||||||
|
{
|
||||||
|
g_signal_emit(self, ril_sim_settings_signals[id], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_settings_reload(struct ril_sim_settings *self)
|
||||||
|
{
|
||||||
|
struct ril_sim_settings_priv *priv = self->priv;
|
||||||
|
|
||||||
|
if (priv->storage) {
|
||||||
|
g_key_file_free(priv->storage);
|
||||||
|
priv->storage = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->imsi) {
|
||||||
|
char *mode_str;
|
||||||
|
enum ofono_radio_access_mode mode;
|
||||||
|
priv->storage = storage_open(priv->imsi, RIL_SIM_STORE);
|
||||||
|
mode_str = g_key_file_get_string(priv->storage,
|
||||||
|
RIL_SIM_STORE_GROUP, RIL_SIM_STORE_PREF_MODE, NULL);
|
||||||
|
if (ofono_radio_access_mode_from_string(mode_str, &mode)) {
|
||||||
|
if (!self->enable_4g &&
|
||||||
|
mode == OFONO_RADIO_ACCESS_MODE_LTE) {
|
||||||
|
mode = OFONO_RADIO_ACCESS_MODE_ANY;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mode = OFONO_RADIO_ACCESS_MODE_ANY;
|
||||||
|
}
|
||||||
|
if (mode == OFONO_RADIO_ACCESS_MODE_ANY) {
|
||||||
|
self->pref_mode = RIL_SIM_STORE_PREF_MODE_DEFAULT(self);
|
||||||
|
} else {
|
||||||
|
self->pref_mode = mode;
|
||||||
|
}
|
||||||
|
g_free(mode_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ril_sim_settings_set_pref_mode(struct ril_sim_settings *self,
|
||||||
|
enum ofono_radio_access_mode mode)
|
||||||
|
{
|
||||||
|
if (G_LIKELY(self) && self->pref_mode != mode) {
|
||||||
|
struct ril_sim_settings_priv *priv = self->priv;
|
||||||
|
const char *mode_str = ofono_radio_access_mode_to_string(mode);
|
||||||
|
|
||||||
|
GASSERT(priv->storage);
|
||||||
|
if (mode_str) {
|
||||||
|
if (priv->storage) {
|
||||||
|
g_key_file_set_string(priv->storage,
|
||||||
|
RIL_SIM_STORE_GROUP,
|
||||||
|
RIL_SIM_STORE_PREF_MODE, mode_str);
|
||||||
|
storage_sync(self->imsi, RIL_SIM_STORE,
|
||||||
|
priv->storage);
|
||||||
|
}
|
||||||
|
self->pref_mode = mode;
|
||||||
|
ril_sim_settings_signal_emit(self,
|
||||||
|
SIGNAL_PREF_MODE_CHANGED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_settings_set_imsi(struct ril_sim_settings *self,
|
||||||
|
const char *imsi)
|
||||||
|
{
|
||||||
|
struct ril_sim_settings_priv *priv = self->priv;
|
||||||
|
if (g_strcmp0(priv->imsi, imsi)) {
|
||||||
|
enum ofono_radio_access_mode prev_mode = self->pref_mode;
|
||||||
|
g_free(priv->imsi);
|
||||||
|
self->imsi = priv->imsi = g_strdup(imsi);
|
||||||
|
ril_sim_settings_reload(self);
|
||||||
|
ril_sim_settings_signal_emit(self, SIGNAL_IMSI_CHANGED);
|
||||||
|
if (prev_mode != self->pref_mode) {
|
||||||
|
ril_sim_settings_signal_emit(self,
|
||||||
|
SIGNAL_PREF_MODE_CHANGED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_settings_imsi_watch_cb(const char *imsi, void *user_data)
|
||||||
|
{
|
||||||
|
ril_sim_settings_set_imsi(RIL_SIM_SETTINGS(user_data), imsi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_settings_imsi_watch_done(void *user_data)
|
||||||
|
{
|
||||||
|
struct ril_sim_settings *self = RIL_SIM_SETTINGS(user_data);
|
||||||
|
struct ril_sim_settings_priv *priv = self->priv;
|
||||||
|
|
||||||
|
GASSERT(priv->imsi_watch_id);
|
||||||
|
priv->imsi_watch_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_settings_ready(struct ril_sim_settings *self)
|
||||||
|
{
|
||||||
|
struct ril_sim_settings_priv *priv = self->priv;
|
||||||
|
|
||||||
|
GASSERT(!priv->imsi_watch_id);
|
||||||
|
priv->imsi_watch_id = ofono_sim_add_imsi_watch(priv->sim,
|
||||||
|
ril_sim_settings_imsi_watch_cb, self,
|
||||||
|
ril_sim_settings_imsi_watch_done);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_settings_state_watch(enum ofono_sim_state new_state,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
if (new_state == OFONO_SIM_STATE_READY) {
|
||||||
|
ril_sim_settings_ready(RIL_SIM_SETTINGS(user_data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_settings_state_watch_done(void *user_data)
|
||||||
|
{
|
||||||
|
struct ril_sim_settings *self = RIL_SIM_SETTINGS(user_data);
|
||||||
|
struct ril_sim_settings_priv *priv = self->priv;
|
||||||
|
|
||||||
|
GASSERT(priv->state_watch_id);
|
||||||
|
priv->state_watch_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ril_sim_settings_set_ofono_sim(struct ril_sim_settings *self,
|
||||||
|
struct ofono_sim *sim)
|
||||||
|
{
|
||||||
|
if (G_LIKELY(self)) {
|
||||||
|
struct ril_sim_settings_priv *priv = self->priv;
|
||||||
|
if (priv->sim != sim) {
|
||||||
|
GASSERT(priv->sim || !priv->imsi_watch_id);
|
||||||
|
if (priv->imsi_watch_id) {
|
||||||
|
ofono_sim_remove_imsi_watch(priv->sim,
|
||||||
|
priv->imsi_watch_id);
|
||||||
|
/* ril_sim_settings_imsi_watch_done clears it */
|
||||||
|
GASSERT(!priv->imsi_watch_id);
|
||||||
|
}
|
||||||
|
if (priv->state_watch_id) {
|
||||||
|
ofono_sim_remove_state_watch(priv->sim,
|
||||||
|
priv->state_watch_id);
|
||||||
|
/* ril_sim_settings_state_watch_done clears it */
|
||||||
|
GASSERT(!priv->state_watch_id);
|
||||||
|
}
|
||||||
|
priv->sim = sim;
|
||||||
|
if (sim) {
|
||||||
|
priv->state_watch_id =
|
||||||
|
ofono_sim_add_state_watch(sim,
|
||||||
|
ril_sim_settings_state_watch, self,
|
||||||
|
ril_sim_settings_state_watch_done);
|
||||||
|
GASSERT(priv->state_watch_id);
|
||||||
|
if (ofono_sim_get_state(sim) ==
|
||||||
|
OFONO_SIM_STATE_READY) {
|
||||||
|
ril_sim_settings_ready(self);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ril_sim_settings_set_imsi(self, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gulong ril_sim_settings_add_imsi_changed_handler(struct ril_sim_settings *self,
|
||||||
|
ril_sim_settings_cb_t cb, void *arg)
|
||||||
|
{
|
||||||
|
return (G_LIKELY(self) && G_LIKELY(cb)) ? g_signal_connect(self,
|
||||||
|
SIGNAL_IMSI_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gulong ril_sim_settings_add_pref_mode_changed_handler(
|
||||||
|
struct ril_sim_settings *self,
|
||||||
|
ril_sim_settings_cb_t cb, void *arg)
|
||||||
|
{
|
||||||
|
return (G_LIKELY(self) && G_LIKELY(cb)) ? g_signal_connect(self,
|
||||||
|
SIGNAL_PREF_MODE_CHANGED_NAME, G_CALLBACK(cb), arg) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ril_sim_settings_remove_handler(struct ril_sim_settings *self, gulong id)
|
||||||
|
{
|
||||||
|
if (G_LIKELY(self) && G_LIKELY(id)) {
|
||||||
|
g_signal_handler_disconnect(self, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ril_sim_settings_remove_handlers(struct ril_sim_settings *self,
|
||||||
|
gulong *ids, int count)
|
||||||
|
{
|
||||||
|
gutil_disconnect_handlers(self, ids, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ril_sim_settings *ril_sim_settings_new(const struct ril_slot_config *sc)
|
||||||
|
{
|
||||||
|
struct ril_sim_settings *self = g_object_new(RIL_SIM_SETTINGS_TYPE, 0);
|
||||||
|
self->enable_4g = sc->enable_4g;
|
||||||
|
self->slot = sc->slot;
|
||||||
|
self->pref_mode = RIL_SIM_STORE_PREF_MODE_DEFAULT(self);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ril_sim_settings *ril_sim_settings_ref(struct ril_sim_settings *self)
|
||||||
|
{
|
||||||
|
if (G_LIKELY(self)) {
|
||||||
|
g_object_ref(RIL_SIM_SETTINGS(self));
|
||||||
|
return self;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ril_sim_settings_unref(struct ril_sim_settings *self)
|
||||||
|
{
|
||||||
|
if (G_LIKELY(self)) {
|
||||||
|
g_object_unref(RIL_SIM_SETTINGS(self));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_settings_init(struct ril_sim_settings *self)
|
||||||
|
{
|
||||||
|
self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self, RIL_SIM_SETTINGS_TYPE,
|
||||||
|
struct ril_sim_settings_priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_settings_dispose(GObject *object)
|
||||||
|
{
|
||||||
|
struct ril_sim_settings *self = RIL_SIM_SETTINGS(object);
|
||||||
|
|
||||||
|
ril_sim_settings_set_ofono_sim(self, NULL);
|
||||||
|
G_OBJECT_CLASS(ril_sim_settings_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ril_sim_settings_class_init(RilSimSettingsClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
||||||
|
|
||||||
|
object_class->dispose = ril_sim_settings_dispose;
|
||||||
|
g_type_class_add_private(klass, sizeof(struct ril_sim_settings_priv));
|
||||||
|
NEW_SIGNAL(klass, IMSI);
|
||||||
|
NEW_SIGNAL(klass, PREF_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local Variables:
|
||||||
|
* mode: C
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
59
ofono/drivers/ril/ril_sim_settings.h
Normal file
59
ofono/drivers/ril/ril_sim_settings.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* oFono - Open Source Telephony - RIL-based devices
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 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_SIM_SETTINGS_H
|
||||||
|
#define RIL_SIM_SETTINGS_H
|
||||||
|
|
||||||
|
#include "ril_types.h"
|
||||||
|
|
||||||
|
#include <ofono/radio-settings.h>
|
||||||
|
|
||||||
|
struct ril_sim_settings_priv;
|
||||||
|
|
||||||
|
struct ril_sim_settings {
|
||||||
|
GObject object;
|
||||||
|
struct ril_sim_settings_priv *priv;
|
||||||
|
gboolean enable_4g;
|
||||||
|
guint slot;
|
||||||
|
const char *imsi;
|
||||||
|
enum ofono_radio_access_mode pref_mode;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*ril_sim_settings_cb_t)(struct ril_sim_settings *s, void *arg);
|
||||||
|
|
||||||
|
struct ril_sim_settings *ril_sim_settings_new(const struct ril_slot_config *sc);
|
||||||
|
struct ril_sim_settings *ril_sim_settings_ref(struct ril_sim_settings *s);
|
||||||
|
void ril_sim_settings_unref(struct ril_sim_settings *s);
|
||||||
|
void ril_sim_settings_set_ofono_sim(struct ril_sim_settings *s,
|
||||||
|
struct ofono_sim *sim);
|
||||||
|
void ril_sim_settings_set_pref_mode(struct ril_sim_settings *s,
|
||||||
|
enum ofono_radio_access_mode mode);
|
||||||
|
gulong ril_sim_settings_add_imsi_changed_handler(struct ril_sim_settings *s,
|
||||||
|
ril_sim_settings_cb_t cb, void *arg);
|
||||||
|
gulong ril_sim_settings_add_pref_mode_changed_handler(struct ril_sim_settings *s,
|
||||||
|
ril_sim_settings_cb_t cb, void *arg);
|
||||||
|
void ril_sim_settings_remove_handler(struct ril_sim_settings *s, gulong id);
|
||||||
|
void ril_sim_settings_remove_handlers(struct ril_sim_settings *s, gulong *ids,
|
||||||
|
int count);
|
||||||
|
|
||||||
|
#endif /* RIL_SIM_SETTINGS_H */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local Variables:
|
||||||
|
* mode: C
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* oFono - Open Source Telephony - RIL-based devices
|
* oFono - Open Source Telephony - RIL-based devices
|
||||||
*
|
*
|
||||||
* Copyright (C) 2015 Jolla Ltd.
|
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
@@ -22,13 +22,16 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "simutil.h"
|
#include "simutil.h"
|
||||||
|
|
||||||
|
#define RIL_SMS_ACK_RETRY_MS 1000
|
||||||
|
#define RIL_SMS_ACK_RETRY_COUNT 10
|
||||||
|
|
||||||
#define SIM_EFSMS_FILEID 0x6F3C
|
#define SIM_EFSMS_FILEID 0x6F3C
|
||||||
#define EFSMS_LENGTH 176
|
#define EFSMS_LENGTH 176
|
||||||
|
|
||||||
#define TYPE_LOCAL 129
|
#define TYPE_LOCAL 129
|
||||||
#define TYPE_INTERNATIONAL 145
|
#define TYPE_INTERNATIONAL 145
|
||||||
|
|
||||||
static unsigned char path[4] = {0x3F, 0x00, 0x7F, 0x10};
|
static unsigned char sim_path[4] = {0x3F, 0x00, 0x7F, 0x10};
|
||||||
|
|
||||||
enum ril_sms_events {
|
enum ril_sms_events {
|
||||||
SMS_EVENT_NEW_SMS,
|
SMS_EVENT_NEW_SMS,
|
||||||
@@ -42,6 +45,7 @@ struct ril_sms {
|
|||||||
GRilIoQueue *q;
|
GRilIoQueue *q;
|
||||||
struct ril_modem *modem;
|
struct ril_modem *modem;
|
||||||
struct ofono_sms *sms;
|
struct ofono_sms *sms;
|
||||||
|
struct ofono_sim_context *sim_context;
|
||||||
gulong event_id[SMS_EVENT_COUNT];
|
gulong event_id[SMS_EVENT_COUNT];
|
||||||
guint timer_id;
|
guint timer_id;
|
||||||
};
|
};
|
||||||
@@ -277,6 +281,8 @@ static void ril_ack_delivery(struct ril_sms *sd, gboolean error)
|
|||||||
grilio_request_append_int32(req, code); /* error code */
|
grilio_request_append_int32(req, code); /* error code */
|
||||||
|
|
||||||
/* ACK the incoming NEW_SMS */
|
/* ACK the incoming NEW_SMS */
|
||||||
|
grilio_request_set_retry(req, RIL_SMS_ACK_RETRY_MS,
|
||||||
|
RIL_SMS_ACK_RETRY_COUNT);
|
||||||
grilio_queue_send_request_full(sd->q, req,
|
grilio_queue_send_request_full(sd->q, req,
|
||||||
RIL_REQUEST_SMS_ACKNOWLEDGE, ril_ack_delivery_cb, NULL, NULL);
|
RIL_REQUEST_SMS_ACKNOWLEDGE, ril_ack_delivery_cb, NULL, NULL);
|
||||||
grilio_request_unref(req);
|
grilio_request_unref(req);
|
||||||
@@ -366,11 +372,10 @@ static void ril_request_delete_sms_om_sim(struct ril_sms *sd, int record)
|
|||||||
grilio_request_unref(req);
|
grilio_request_unref(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_sms_on_sim_cb(const struct ofono_error *error,
|
static void ril_sms_on_sim_cb(int ok, int total_length, int record,
|
||||||
const unsigned char *sdata,
|
const unsigned char *sdata, int length, void *userdata)
|
||||||
int length, void *data)
|
|
||||||
{
|
{
|
||||||
struct ril_sms_on_sim_req *cbd = data;
|
struct ril_sms_on_sim_req *cbd = userdata;
|
||||||
struct ril_sms *sd = cbd->sd;
|
struct ril_sms *sd = cbd->sd;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -383,7 +388,7 @@ static void ril_sms_on_sim_cb(const struct ofono_error *error,
|
|||||||
* the read length to take into account this read octet in order
|
* the read length to take into account this read octet in order
|
||||||
* to calculate the proper tpdu length.
|
* to calculate the proper tpdu length.
|
||||||
*/
|
*/
|
||||||
if (error->type == OFONO_ERROR_TYPE_NO_ERROR) {
|
if (ok) {
|
||||||
unsigned int smsc_len = sdata[1] + 1;
|
unsigned int smsc_len = sdata[1] + 1;
|
||||||
ofono_sms_deliver_notify(sd->sms, sdata + 1, length - 1,
|
ofono_sms_deliver_notify(sd->sms, sdata + 1, length - 1,
|
||||||
length - smsc_len - 1);
|
length - smsc_len - 1);
|
||||||
@@ -409,10 +414,15 @@ static void ril_sms_on_sim(GRilIoChannel *io, guint ril_event,
|
|||||||
grilio_parser_get_int32(&rilp, &data_len) && data_len > 0 &&
|
grilio_parser_get_int32(&rilp, &data_len) && data_len > 0 &&
|
||||||
grilio_parser_get_int32(&rilp, &rec)) {
|
grilio_parser_get_int32(&rilp, &rec)) {
|
||||||
DBG("rec %d", rec);
|
DBG("rec %d", rec);
|
||||||
ril_sim_read_file_linear(sim, SIM_EFSMS_FILEID, rec,
|
if (sd->sim_context) {
|
||||||
EFSMS_LENGTH, path, sizeof(path),
|
ofono_sim_read_record(sd->sim_context,
|
||||||
ril_sms_on_sim_cb,
|
SIM_EFSMS_FILEID,
|
||||||
ril_sms_on_sim_req_new(sd,rec));
|
OFONO_SIM_FILE_STRUCTURE_FIXED,
|
||||||
|
rec, EFSMS_LENGTH,
|
||||||
|
sim_path, sizeof(sim_path),
|
||||||
|
ril_sms_on_sim_cb,
|
||||||
|
ril_sms_on_sim_req_new(sd,rec));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,14 +454,18 @@ static int ril_sms_probe(struct ofono_sms *sms, unsigned int vendor,
|
|||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
struct ril_modem *modem = data;
|
struct ril_modem *modem = data;
|
||||||
|
struct ofono_sim *sim = ril_modem_ofono_sim(modem);
|
||||||
struct ril_sms *sd = g_new0(struct ril_sms, 1);
|
struct ril_sms *sd = g_new0(struct ril_sms, 1);
|
||||||
|
|
||||||
sd->modem = modem;
|
sd->modem = modem;
|
||||||
sd->sms = sms;
|
sd->sms = sms;
|
||||||
sd->io = grilio_channel_ref(ril_modem_io(modem));
|
sd->io = grilio_channel_ref(ril_modem_io(modem));
|
||||||
|
sd->sim_context = ofono_sim_context_create(sim);
|
||||||
sd->q = grilio_queue_new(sd->io);
|
sd->q = grilio_queue_new(sd->io);
|
||||||
sd->timer_id = g_idle_add(ril_sms_register, sd);
|
sd->timer_id = g_idle_add(ril_sms_register, sd);
|
||||||
ofono_sms_set_data(sms, sd);
|
ofono_sms_set_data(sms, sd);
|
||||||
|
|
||||||
|
GASSERT(sd->sim_context);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -463,6 +477,10 @@ static void ril_sms_remove(struct ofono_sms *sms)
|
|||||||
DBG("");
|
DBG("");
|
||||||
ofono_sms_set_data(sms, NULL);
|
ofono_sms_set_data(sms, NULL);
|
||||||
|
|
||||||
|
if (sd->sim_context) {
|
||||||
|
ofono_sim_context_free(sd->sim_context);
|
||||||
|
}
|
||||||
|
|
||||||
for (i=0; i<G_N_ELEMENTS(sd->event_id); i++) {
|
for (i=0; i<G_N_ELEMENTS(sd->event_id); i++) {
|
||||||
grilio_channel_remove_handler(sd->io, sd->event_id[i]);
|
grilio_channel_remove_handler(sd->io, sd->event_id[i]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,31 @@
|
|||||||
# This is a sample configuration file for the ril driver
|
# This is a sample configuration file for Jolla ril driver
|
||||||
#
|
#
|
||||||
# This file is expected to be installed in /etc/ofono
|
# This file is expected to be installed in /etc/ofono
|
||||||
#
|
#
|
||||||
# Configuration for each modem is defined in its own [ril_x] section.
|
# Configuration for each modem is defined in its own [ril_x] section,
|
||||||
# Only the sections that start with the "ril_" prefix define the modems,
|
# common settings are in the [Settings] section, all other sections
|
||||||
# other sections are currently ignored.
|
# are ignored.
|
||||||
#
|
#
|
||||||
|
# If any value from [ril_x] section (except "socket") is defined
|
||||||
|
# in the [Settings] section, it becomes the default for all modems.
|
||||||
|
# Default values can still be redefined at [ril_x] level.
|
||||||
|
#
|
||||||
|
|
||||||
|
[Settings]
|
||||||
|
|
||||||
|
# If the phone has more than one SIM slot, the 3G/LTE module may be
|
||||||
|
# shared by all modems, meaning that only one of the slots can use
|
||||||
|
# 3G/LTE. In order to "hand 4G over" to the other slot, the modem
|
||||||
|
# currently using 3G/LTE has to drop to GSM, release 3G/LTE module
|
||||||
|
# and only then 3G/LTE can be used by the other modem. This setting
|
||||||
|
# allows to disable this behaviour (say, if your phone has independent
|
||||||
|
# 3G/LTE modules for each slot or you don't need 4G for both slots).
|
||||||
|
# Obviously, it only has any effect if you have more than one SIM.
|
||||||
|
#
|
||||||
|
# Default is true (switch the current data modem to 2G when changing
|
||||||
|
# the data modems)
|
||||||
|
#
|
||||||
|
#3GLTEHandover=true
|
||||||
|
|
||||||
[ril_0]
|
[ril_0]
|
||||||
|
|
||||||
@@ -53,3 +73,25 @@ socket=/dev/socket/rild
|
|||||||
# Default is true (select SET_UICC_SUBSCRIPTION based on the RIL version)
|
# Default is true (select SET_UICC_SUBSCRIPTION based on the RIL version)
|
||||||
#
|
#
|
||||||
#uiccWorkaround=true
|
#uiccWorkaround=true
|
||||||
|
|
||||||
|
# Points to the file containing comma-separated ECC (Emergency List Codes)
|
||||||
|
# list, e.g. 911,112,*911,#911. The file is tracked by ofono and when its
|
||||||
|
# contents changes, it's reflected in the EmergencyNumbers property of
|
||||||
|
# org.ofono.VoiceCallManager.
|
||||||
|
#
|
||||||
|
# If necessary, the contents of the file can be synchronized with the
|
||||||
|
# Android system property by adding something like this to /init.rc:
|
||||||
|
#
|
||||||
|
# on property:ril.ecclist=*
|
||||||
|
# write /var/lib/ofono/ril.ecclist ${ril.ecclist}
|
||||||
|
# chmod 0644 /var/lib/ofono/ril.ecclist
|
||||||
|
#
|
||||||
|
#ecclistFile=/var/lib/ofono/ril.ecclist
|
||||||
|
|
||||||
|
# RIL_REQUEST_ALLOW_DATA may or may not be supported by your RIL.
|
||||||
|
# This option allows you to forcibly enable or disable use of this request.
|
||||||
|
# Possible values are auto, on and off
|
||||||
|
#
|
||||||
|
# Default is auto (usage based on the RIL version)
|
||||||
|
#
|
||||||
|
#allowDataReq=auto
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <ofono/types.h>
|
#include <ofono/types.h>
|
||||||
|
|
||||||
struct ofono_modem;
|
struct ofono_modem;
|
||||||
|
struct ofono_sim;
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@@ -38,12 +39,20 @@ struct ofono_modem;
|
|||||||
#define RIL_RETRY_SECS (2)
|
#define RIL_RETRY_SECS (2)
|
||||||
#define RIL_RETRY_MS (RIL_RETRY_SECS*1000)
|
#define RIL_RETRY_MS (RIL_RETRY_SECS*1000)
|
||||||
|
|
||||||
|
struct ril_mce;
|
||||||
struct ril_data;
|
struct ril_data;
|
||||||
struct ril_modem;
|
struct ril_modem;
|
||||||
struct ril_radio;
|
struct ril_radio;
|
||||||
struct ril_network;
|
struct ril_network;
|
||||||
struct ril_sim_card;
|
struct ril_sim_card;
|
||||||
struct ril_plugin_dbus;
|
struct ril_sim_info;
|
||||||
|
struct ril_sim_settings;
|
||||||
|
struct ril_cell_info;
|
||||||
|
|
||||||
|
struct ril_slot_config {
|
||||||
|
guint slot;
|
||||||
|
gboolean enable_4g;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* RIL_TYPES_H */
|
#endif /* RIL_TYPES_H */
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* oFono - Open Source Telephony - RIL-based devices
|
* oFono - Open Source Telephony - RIL-based devices
|
||||||
*
|
*
|
||||||
* Copyright (C) 2015 Jolla Ltd.
|
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -101,11 +101,10 @@ static void ril_ussd_request(struct ofono_ussd *ussd, int dcs,
|
|||||||
}
|
}
|
||||||
grilio_request_append_utf8_chars(req, (char*)
|
grilio_request_append_utf8_chars(req, (char*)
|
||||||
unpacked_buf, length);
|
unpacked_buf, length);
|
||||||
grilio_queue_send_request_full(ud->q, req,
|
grilio_queue_send_request(ud->q, req,
|
||||||
RIL_REQUEST_SEND_USSD, ril_ussd_cb,
|
RIL_REQUEST_SEND_USSD);
|
||||||
ril_ussd_cbd_free,
|
|
||||||
ril_ussd_cbd_new(cb, data));
|
|
||||||
grilio_request_unref(req);
|
grilio_request_unref(req);
|
||||||
|
cb(ril_error_ok(&error), data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,14 +15,15 @@
|
|||||||
|
|
||||||
#include "ril_plugin.h"
|
#include "ril_plugin.h"
|
||||||
#include "ril_constants.h"
|
#include "ril_constants.h"
|
||||||
|
#include "ril_ecclist.h"
|
||||||
#include "ril_util.h"
|
#include "ril_util.h"
|
||||||
#include "ril_log.h"
|
#include "ril_log.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
/* Amount of ms we wait between CLCC calls */
|
#include <gutil_ring.h>
|
||||||
|
|
||||||
#define FLAG_NEED_CLIP 1
|
#define FLAG_NEED_CLIP 1
|
||||||
#define MAX_DTMF_BUFFER 32
|
|
||||||
|
|
||||||
enum ril_voicecall_events {
|
enum ril_voicecall_events {
|
||||||
VOICECALL_EVENT_CALL_STATE_CHANGED,
|
VOICECALL_EVENT_CALL_STATE_CHANGED,
|
||||||
@@ -36,24 +37,19 @@ struct ril_voicecall {
|
|||||||
GRilIoChannel *io;
|
GRilIoChannel *io;
|
||||||
GRilIoQueue *q;
|
GRilIoQueue *q;
|
||||||
struct ofono_voicecall *vc;
|
struct ofono_voicecall *vc;
|
||||||
|
struct ril_ecclist *ecclist;
|
||||||
unsigned int local_release;
|
unsigned int local_release;
|
||||||
unsigned char flags;
|
unsigned char flags;
|
||||||
ofono_voicecall_cb_t cb;
|
ofono_voicecall_cb_t cb;
|
||||||
void *data;
|
void *data;
|
||||||
guint timer_id;
|
guint timer_id;
|
||||||
gchar *tone_queue;
|
GUtilRing* dtmf_queue;
|
||||||
guint send_dtmf_id;
|
guint send_dtmf_id;
|
||||||
guint clcc_poll_id;
|
guint clcc_poll_id;
|
||||||
gulong event_id[VOICECALL_EVENT_COUNT];
|
gulong event_id[VOICECALL_EVENT_COUNT];
|
||||||
gulong supp_svc_notification_id;
|
gulong supp_svc_notification_id;
|
||||||
gulong ringback_tone_event_id;
|
gulong ringback_tone_event_id;
|
||||||
};
|
gulong ecclist_change_id;
|
||||||
|
|
||||||
struct release_id_req {
|
|
||||||
struct ofono_voicecall *vc;
|
|
||||||
ofono_voicecall_cb_t cb;
|
|
||||||
gpointer data;
|
|
||||||
int id;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ril_voicecall_change_state_req {
|
struct ril_voicecall_change_state_req {
|
||||||
@@ -68,12 +64,6 @@ struct lastcause_req {
|
|||||||
int id;
|
int id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ril_voicecall_req {
|
|
||||||
struct ofono_voicecall *vc;
|
|
||||||
ofono_voicecall_cb_t cb;
|
|
||||||
gpointer data;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void ril_voicecall_send_one_dtmf(struct ril_voicecall *vd);
|
static void ril_voicecall_send_one_dtmf(struct ril_voicecall *vd);
|
||||||
static void ril_voicecall_clear_dtmf_queue(struct ril_voicecall *vd);
|
static void ril_voicecall_clear_dtmf_queue(struct ril_voicecall *vd);
|
||||||
|
|
||||||
@@ -322,9 +312,10 @@ static void ril_voicecall_clcc_poll_cb(GRilIoChannel *io, int status,
|
|||||||
ofono_voicecall_notify(vd->vc, nc);
|
ofono_voicecall_notify(vd->vc, nc);
|
||||||
if (vd->cb) {
|
if (vd->cb) {
|
||||||
ofono_voicecall_cb_t cb = vd->cb;
|
ofono_voicecall_cb_t cb = vd->cb;
|
||||||
cb(ril_error_ok(&error), vd->data);
|
void *cbdata = vd->data;
|
||||||
vd->cb = NULL;
|
vd->cb = NULL;
|
||||||
vd->data = NULL;
|
vd->data = NULL;
|
||||||
|
cb(ril_error_ok(&error), cbdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,9 +374,12 @@ static void ril_voicecall_clcc_poll(struct ril_voicecall *vd)
|
|||||||
{
|
{
|
||||||
GASSERT(vd);
|
GASSERT(vd);
|
||||||
if (!vd->clcc_poll_id) {
|
if (!vd->clcc_poll_id) {
|
||||||
|
GRilIoRequest* req = grilio_request_new();
|
||||||
|
grilio_request_set_retry(req, RIL_RETRY_MS, -1);
|
||||||
vd->clcc_poll_id = grilio_queue_send_request_full(vd->q,
|
vd->clcc_poll_id = grilio_queue_send_request_full(vd->q,
|
||||||
NULL, RIL_REQUEST_GET_CURRENT_CALLS,
|
req, RIL_REQUEST_GET_CURRENT_CALLS,
|
||||||
ril_voicecall_clcc_poll_cb, NULL, vd);
|
ril_voicecall_clcc_poll_cb, NULL, vd);
|
||||||
|
grilio_request_unref(req);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,9 +437,7 @@ static void ril_voicecall_request(const guint rreq, struct ofono_voicecall *vc,
|
|||||||
static void ril_voicecall_dial_cb(GRilIoChannel *io, int status,
|
static void ril_voicecall_dial_cb(GRilIoChannel *io, int status,
|
||||||
const void *data, guint len, void *user_data)
|
const void *data, guint len, void *user_data)
|
||||||
{
|
{
|
||||||
struct ril_voicecall_req *cbd = user_data;
|
struct ril_voicecall *vd = user_data;
|
||||||
struct ofono_voicecall *vc = cbd->vc;
|
|
||||||
struct ril_voicecall *vd = ril_voicecall_get_data(vc);
|
|
||||||
|
|
||||||
if (status == RIL_E_SUCCESS) {
|
if (status == RIL_E_SUCCESS) {
|
||||||
if (vd->cb) {
|
if (vd->cb) {
|
||||||
@@ -454,11 +446,21 @@ static void ril_voicecall_dial_cb(GRilIoChannel *io, int status,
|
|||||||
ril_voicecall_clcc_poll(vd);
|
ril_voicecall_clcc_poll(vd);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
struct ofono_error error;
|
|
||||||
ofono_error("call failed.");
|
ofono_error("call failed.");
|
||||||
vd->cb = cbd->cb;
|
|
||||||
vd->data = cbd->data;
|
/*
|
||||||
cbd->cb(ril_error_failure(&error), cbd->data);
|
* Even though this dial request may have already been
|
||||||
|
* completed (successfully) by ril_voicecall_clcc_poll_cb,
|
||||||
|
* RIL_REQUEST_DIAL may still fail.
|
||||||
|
*/
|
||||||
|
if (vd->cb) {
|
||||||
|
struct ofono_error error;
|
||||||
|
ofono_voicecall_cb_t cb = vd->cb;
|
||||||
|
void *cbdata = vd->data;
|
||||||
|
vd->cb = NULL;
|
||||||
|
vd->data = NULL;
|
||||||
|
cb(ril_error_failure(&error), cbdata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,27 +470,22 @@ static void ril_voicecall_dial(struct ofono_voicecall *vc,
|
|||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
struct ril_voicecall *vd = ril_voicecall_get_data(vc);
|
struct ril_voicecall *vd = ril_voicecall_get_data(vc);
|
||||||
struct ril_voicecall_req *cbd = g_new(struct ril_voicecall_req, 1);
|
|
||||||
const char *phstr = phone_number_to_string(ph);
|
const char *phstr = phone_number_to_string(ph);
|
||||||
GRilIoRequest *req = grilio_request_new();
|
GRilIoRequest *req = grilio_request_new();
|
||||||
|
|
||||||
ofono_info("dialing \"%s\"", phstr);
|
ofono_info("dialing \"%s\"", phstr);
|
||||||
|
|
||||||
DBG("%s,%d,0", phstr, clir);
|
DBG("%s,%d,0", phstr, clir);
|
||||||
cbd->vc = vc;
|
|
||||||
cbd->cb = cb;
|
|
||||||
cbd->data = data;
|
|
||||||
|
|
||||||
GASSERT(!vd->cb);
|
GASSERT(!vd->cb);
|
||||||
vd->cb = cbd->cb;
|
vd->cb = cb;
|
||||||
vd->data = cbd->data;
|
vd->data = data;
|
||||||
|
|
||||||
grilio_request_append_utf8(req, phstr); /* Number to dial */
|
grilio_request_append_utf8(req, phstr); /* Number to dial */
|
||||||
grilio_request_append_int32(req, clir); /* CLIR mode */
|
grilio_request_append_int32(req, clir); /* CLIR mode */
|
||||||
grilio_request_append_int32(req, 0); /* UUS information (absent) */
|
grilio_request_append_int32(req, 0); /* UUS information (absent) */
|
||||||
|
|
||||||
grilio_queue_send_request_full(vd->q, req, RIL_REQUEST_DIAL,
|
grilio_queue_send_request_full(vd->q, req, RIL_REQUEST_DIAL,
|
||||||
ril_voicecall_dial_cb, g_free, cbd);
|
ril_voicecall_dial_cb, NULL, vd);
|
||||||
grilio_request_unref(req);
|
grilio_request_unref(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,11 +596,6 @@ static void ril_voicecall_send_dtmf_cb(GRilIoChannel *io, int status,
|
|||||||
vd->send_dtmf_id = 0;
|
vd->send_dtmf_id = 0;
|
||||||
|
|
||||||
if (status == RIL_E_SUCCESS) {
|
if (status == RIL_E_SUCCESS) {
|
||||||
/* Remove sent DTMF character from queue */
|
|
||||||
gchar *tmp = g_strdup(vd->tone_queue + 1);
|
|
||||||
g_free(vd->tone_queue);
|
|
||||||
vd->tone_queue = tmp;
|
|
||||||
|
|
||||||
/* Send the next one */
|
/* Send the next one */
|
||||||
ril_voicecall_send_one_dtmf(vd);
|
ril_voicecall_send_one_dtmf(vd);
|
||||||
} else {
|
} else {
|
||||||
@@ -614,12 +606,15 @@ static void ril_voicecall_send_dtmf_cb(GRilIoChannel *io, int status,
|
|||||||
|
|
||||||
static void ril_voicecall_send_one_dtmf(struct ril_voicecall *vd)
|
static void ril_voicecall_send_one_dtmf(struct ril_voicecall *vd)
|
||||||
{
|
{
|
||||||
if (!vd->send_dtmf_id && vd->tone_queue && vd->tone_queue[0]) {
|
if (!vd->send_dtmf_id && gutil_ring_size(vd->dtmf_queue) > 0) {
|
||||||
GRilIoRequest *req = grilio_request_sized_new(4);
|
GRilIoRequest *req = grilio_request_sized_new(4);
|
||||||
|
const char dtmf_char = (char)
|
||||||
|
GPOINTER_TO_UINT(gutil_ring_get(vd->dtmf_queue));
|
||||||
|
|
||||||
/* RIL wants just one character */
|
/* RIL wants just one character */
|
||||||
DBG("%c", vd->tone_queue[0]);
|
GASSERT(dtmf_char);
|
||||||
grilio_request_append_utf8_chars(req, vd->tone_queue, 1);
|
DBG("%c", dtmf_char);
|
||||||
|
grilio_request_append_utf8_chars(req, &dtmf_char, 1);
|
||||||
vd->send_dtmf_id = grilio_queue_send_request_full(vd->q, req,
|
vd->send_dtmf_id = grilio_queue_send_request_full(vd->q, req,
|
||||||
RIL_REQUEST_DTMF, ril_voicecall_send_dtmf_cb, NULL, vd);
|
RIL_REQUEST_DTMF, ril_voicecall_send_dtmf_cb, NULL, vd);
|
||||||
grilio_request_unref(req);
|
grilio_request_unref(req);
|
||||||
@@ -632,23 +627,23 @@ static void ril_voicecall_send_dtmf(struct ofono_voicecall *vc,
|
|||||||
struct ril_voicecall *vd = ril_voicecall_get_data(vc);
|
struct ril_voicecall *vd = ril_voicecall_get_data(vc);
|
||||||
struct ofono_error error;
|
struct ofono_error error;
|
||||||
|
|
||||||
DBG("Queue '%s'",dtmf);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Queue any incoming DTMF (up to MAX_DTMF_BUFFER characters),
|
* Queue any incoming DTMF, send them to RIL one-by-one,
|
||||||
* send them to RIL one-by-one, immediately call back
|
* immediately call back core with no error
|
||||||
* core with no error
|
|
||||||
*/
|
*/
|
||||||
g_strlcat(vd->tone_queue, dtmf, MAX_DTMF_BUFFER);
|
DBG("Queue '%s'", dtmf);
|
||||||
ril_voicecall_send_one_dtmf(vd);
|
while (*dtmf) {
|
||||||
|
gutil_ring_put(vd->dtmf_queue, GUINT_TO_POINTER(*dtmf));
|
||||||
|
dtmf++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ril_voicecall_send_one_dtmf(vd);
|
||||||
cb(ril_error_ok(&error), data);
|
cb(ril_error_ok(&error), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ril_voicecall_clear_dtmf_queue(struct ril_voicecall *vd)
|
static void ril_voicecall_clear_dtmf_queue(struct ril_voicecall *vd)
|
||||||
{
|
{
|
||||||
g_free(vd->tone_queue);
|
gutil_ring_clear(vd->dtmf_queue);
|
||||||
vd->tone_queue = g_strnfill(MAX_DTMF_BUFFER + 1, '\0');
|
|
||||||
if (vd->send_dtmf_id) {
|
if (vd->send_dtmf_id) {
|
||||||
grilio_channel_cancel_request(vd->io, vd->send_dtmf_id, FALSE);
|
grilio_channel_cancel_request(vd->io, vd->send_dtmf_id, FALSE);
|
||||||
vd->send_dtmf_id = 0;
|
vd->send_dtmf_id = 0;
|
||||||
@@ -759,6 +754,13 @@ static void ril_voicecall_ringback_tone_event(GRilIoChannel *io,
|
|||||||
ofono_voicecall_ringback_tone_notify(vd->vc, playTone);
|
ofono_voicecall_ringback_tone_notify(vd->vc, playTone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ril_voicecall_ecclist_changed(struct ril_ecclist *list, void *data)
|
||||||
|
{
|
||||||
|
struct ril_voicecall *vd = data;
|
||||||
|
|
||||||
|
ofono_voicecall_en_list_notify(vd->vc, vd->ecclist->list);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean ril_delayed_register(gpointer user_data)
|
static gboolean ril_delayed_register(gpointer user_data)
|
||||||
{
|
{
|
||||||
struct ril_voicecall *vd = user_data;
|
struct ril_voicecall *vd = user_data;
|
||||||
@@ -767,6 +769,14 @@ static gboolean ril_delayed_register(gpointer user_data)
|
|||||||
vd->timer_id = 0;
|
vd->timer_id = 0;
|
||||||
ofono_voicecall_register(vd->vc);
|
ofono_voicecall_register(vd->vc);
|
||||||
|
|
||||||
|
/* Emergency Call Codes */
|
||||||
|
if (vd->ecclist) {
|
||||||
|
ofono_voicecall_en_list_notify(vd->vc, vd->ecclist->list);
|
||||||
|
vd->ecclist_change_id =
|
||||||
|
ril_ecclist_add_list_changed_handler(vd->ecclist,
|
||||||
|
ril_voicecall_ecclist_changed, vd);
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize call list */
|
/* Initialize call list */
|
||||||
ril_voicecall_clcc_poll(vd);
|
ril_voicecall_clcc_poll(vd);
|
||||||
|
|
||||||
@@ -805,8 +815,12 @@ static int ril_voicecall_probe(struct ofono_voicecall *vc, unsigned int vendor,
|
|||||||
vd = g_new0(struct ril_voicecall, 1);
|
vd = g_new0(struct ril_voicecall, 1);
|
||||||
vd->io = grilio_channel_ref(ril_modem_io(modem));
|
vd->io = grilio_channel_ref(ril_modem_io(modem));
|
||||||
vd->q = grilio_queue_new(vd->io);
|
vd->q = grilio_queue_new(vd->io);
|
||||||
|
vd->dtmf_queue = gutil_ring_new();
|
||||||
vd->vc = vc;
|
vd->vc = vc;
|
||||||
vd->timer_id = g_idle_add(ril_delayed_register, vd);
|
vd->timer_id = g_idle_add(ril_delayed_register, vd);
|
||||||
|
if (modem->ecclist_file) {
|
||||||
|
vd->ecclist = ril_ecclist_new(modem->ecclist_file);
|
||||||
|
}
|
||||||
ril_voicecall_clear_dtmf_queue(vd);
|
ril_voicecall_clear_dtmf_queue(vd);
|
||||||
ofono_voicecall_set_data(vc, vd);
|
ofono_voicecall_set_data(vc, vd);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -814,26 +828,25 @@ static int ril_voicecall_probe(struct ofono_voicecall *vc, unsigned int vendor,
|
|||||||
|
|
||||||
static void ril_voicecall_remove(struct ofono_voicecall *vc)
|
static void ril_voicecall_remove(struct ofono_voicecall *vc)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
struct ril_voicecall *vd = ril_voicecall_get_data(vc);
|
struct ril_voicecall *vd = ril_voicecall_get_data(vc);
|
||||||
|
|
||||||
DBG("");
|
DBG("");
|
||||||
ofono_voicecall_set_data(vc, NULL);
|
ofono_voicecall_set_data(vc, NULL);
|
||||||
g_slist_foreach(vd->calls, (GFunc) g_free, NULL);
|
g_slist_free_full(vd->calls, g_free);
|
||||||
g_slist_free(vd->calls);
|
|
||||||
|
|
||||||
for (i=0; i<G_N_ELEMENTS(vd->event_id); i++) {
|
|
||||||
grilio_channel_remove_handler(vd->io, vd->event_id[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vd->timer_id > 0) {
|
if (vd->timer_id > 0) {
|
||||||
g_source_remove(vd->timer_id);
|
g_source_remove(vd->timer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ril_ecclist_remove_handler(vd->ecclist, vd->ecclist_change_id);
|
||||||
|
ril_ecclist_unref(vd->ecclist);
|
||||||
|
|
||||||
|
grilio_channel_remove_handlers(vd->io, vd->event_id,
|
||||||
|
G_N_ELEMENTS(vd->event_id));
|
||||||
grilio_channel_unref(vd->io);
|
grilio_channel_unref(vd->io);
|
||||||
grilio_queue_cancel_all(vd->q, FALSE);
|
grilio_queue_cancel_all(vd->q, FALSE);
|
||||||
grilio_queue_unref(vd->q);
|
grilio_queue_unref(vd->q);
|
||||||
g_free(vd->tone_queue);
|
gutil_ring_unref(vd->dtmf_queue);
|
||||||
g_free(vd);
|
g_free(vd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,14 +58,6 @@ struct netreg_data {
|
|||||||
int corestatus; /* Registration status previously reported to core */
|
int corestatus; /* Registration status previously reported to core */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 27.007 Section 7.3 <stat> */
|
|
||||||
enum operator_status {
|
|
||||||
OPERATOR_STATUS_UNKNOWN = 0,
|
|
||||||
OPERATOR_STATUS_AVAILABLE = 1,
|
|
||||||
OPERATOR_STATUS_CURRENT = 2,
|
|
||||||
OPERATOR_STATUS_FORBIDDEN = 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ofono_netreg *current_netreg;
|
struct ofono_netreg *current_netreg;
|
||||||
|
|
||||||
static void extract_mcc_mnc(const char *str, char *mcc, char *mnc)
|
static void extract_mcc_mnc(const char *str, char *mcc, char *mnc)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* oFono - Open Telephony stack for Linux
|
* oFono - Open Telephony stack for Linux
|
||||||
*
|
*
|
||||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||||
* Copyright (C) 2013 Jolla Ltd.
|
* Copyright (C) 2013-2016 Jolla Ltd.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
@@ -61,7 +61,6 @@ extern "C" {
|
|||||||
#define OFONO_GNSS_POSR_AGENT_INTERFACE "org.ofono.PositioningRequestAgent"
|
#define OFONO_GNSS_POSR_AGENT_INTERFACE "org.ofono.PositioningRequestAgent"
|
||||||
#define OFONO_HANDSFREE_INTERFACE OFONO_SERVICE ".Handsfree"
|
#define OFONO_HANDSFREE_INTERFACE OFONO_SERVICE ".Handsfree"
|
||||||
#define OFONO_NETWORK_TIME_INTERFACE OFONO_SERVICE ".NetworkTime"
|
#define OFONO_NETWORK_TIME_INTERFACE OFONO_SERVICE ".NetworkTime"
|
||||||
#define OFONO_OEM_RAW_INTERFACE "org.ofono.OemRaw"
|
|
||||||
#define OFONO_SIRI_INTERFACE OFONO_SERVICE ".Siri"
|
#define OFONO_SIRI_INTERFACE OFONO_SERVICE ".Siri"
|
||||||
|
|
||||||
/* CDMA Interfaces */
|
/* CDMA Interfaces */
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
* oFono - Open Telephony stack for Linux
|
* oFono - Open Telephony stack for Linux
|
||||||
*
|
*
|
||||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||||
|
* Copyright (C) 2013-2016 Jolla Ltd.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
@@ -22,6 +23,8 @@
|
|||||||
#ifndef __OFONO_LOG_H
|
#ifndef __OFONO_LOG_H
|
||||||
#define __OFONO_LOG_H
|
#define __OFONO_LOG_H
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@@ -50,6 +53,7 @@ struct ofono_debug_desc {
|
|||||||
const char *file;
|
const char *file;
|
||||||
#define OFONO_DEBUG_FLAG_DEFAULT (0)
|
#define OFONO_DEBUG_FLAG_DEFAULT (0)
|
||||||
#define OFONO_DEBUG_FLAG_PRINT (1 << 0)
|
#define OFONO_DEBUG_FLAG_PRINT (1 << 0)
|
||||||
|
#define OFONO_DEBUG_FLAG_HIDE_NAME (1 << 1)
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
void (*notify)(struct ofono_debug_desc* desc);
|
void (*notify)(struct ofono_debug_desc* desc);
|
||||||
} __attribute__((aligned(OFONO_DEBUG_ALIGN)));
|
} __attribute__((aligned(OFONO_DEBUG_ALIGN)));
|
||||||
@@ -67,10 +71,20 @@ struct ofono_debug_desc {
|
|||||||
.file = __FILE__, .flags = OFONO_DEBUG_FLAG_DEFAULT, \
|
.file = __FILE__, .flags = OFONO_DEBUG_FLAG_DEFAULT, \
|
||||||
}; \
|
}; \
|
||||||
if (__ofono_debug_desc.flags & OFONO_DEBUG_FLAG_PRINT) \
|
if (__ofono_debug_desc.flags & OFONO_DEBUG_FLAG_PRINT) \
|
||||||
ofono_debug("%s:%s() " fmt, \
|
__ofono_dbg(&__ofono_debug_desc, "%s() " fmt, \
|
||||||
__FILE__, __FUNCTION__ , ## arg); \
|
__FUNCTION__ , ## arg); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
void __ofono_dbg(const struct ofono_debug_desc *desc, const char *format, ...)
|
||||||
|
__attribute__((format(printf, 2, 3)));
|
||||||
|
|
||||||
|
typedef void (*ofono_log_hook_cb_t)(const struct ofono_debug_desc *desc,
|
||||||
|
int priority, const char *format, va_list va);
|
||||||
|
|
||||||
|
extern ofono_log_hook_cb_t ofono_log_hook;
|
||||||
|
extern struct ofono_debug_desc __start___debug[];
|
||||||
|
extern struct ofono_debug_desc __stop___debug[];
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* oFono - Open Source Telephony
|
|
||||||
*
|
|
||||||
* Copyright (C) 2013 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.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef __OFONO_OEM_RAW_H
|
|
||||||
#define __OFONO_OEM_RAW_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <dbus/dbus.h>
|
|
||||||
#include <ofono/types.h>
|
|
||||||
|
|
||||||
struct ofono_oem_raw;
|
|
||||||
|
|
||||||
/* Request response from driver to core */
|
|
||||||
struct ofono_oem_raw_results {
|
|
||||||
char *data;
|
|
||||||
int length;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Request details from core to driver */
|
|
||||||
struct ofono_oem_raw_request {
|
|
||||||
char *data;
|
|
||||||
int length; /* Number of bytes in data */
|
|
||||||
DBusMessage *pending;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef void (*ofono_oem_raw_query_cb_t)(const struct ofono_error *error,
|
|
||||||
const struct ofono_oem_raw_results *results, void *data);
|
|
||||||
|
|
||||||
struct ofono_oem_raw_driver {
|
|
||||||
const char *name;
|
|
||||||
int (*probe)(struct ofono_oem_raw *raw,
|
|
||||||
unsigned int vendor,
|
|
||||||
void *data);
|
|
||||||
void (*remove)(struct ofono_oem_raw *raw);
|
|
||||||
void (*request)(struct ofono_oem_raw *raw,
|
|
||||||
const struct ofono_oem_raw_request *request,
|
|
||||||
ofono_oem_raw_query_cb_t cb,
|
|
||||||
void *data);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ofono_oem_raw *ofono_oem_raw_create(struct ofono_modem *modem,
|
|
||||||
unsigned int vendor,
|
|
||||||
const char *driver,
|
|
||||||
void *data);
|
|
||||||
void ofono_oem_raw_dbus_register(struct ofono_oem_raw *raw);
|
|
||||||
void ofono_oem_raw_remove(struct ofono_oem_raw *raw);
|
|
||||||
int ofono_oem_raw_driver_register(struct ofono_oem_raw_driver *driver);
|
|
||||||
void ofono_oem_raw_driver_unregister(struct ofono_oem_raw_driver *driver);
|
|
||||||
void *ofono_oem_raw_get_data(struct ofono_oem_raw *raw);
|
|
||||||
void ofono_oem_raw_set_data(struct ofono_oem_raw *raw, void *cid);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __OFONO_OEM_RAW_H */
|
|
||||||
@@ -136,6 +136,10 @@ void *ofono_radio_settings_get_data(struct ofono_radio_settings *rs);
|
|||||||
struct ofono_modem *ofono_radio_settings_get_modem(
|
struct ofono_modem *ofono_radio_settings_get_modem(
|
||||||
struct ofono_radio_settings *rs);
|
struct ofono_radio_settings *rs);
|
||||||
|
|
||||||
|
const char *ofono_radio_access_mode_to_string(enum ofono_radio_access_mode m);
|
||||||
|
ofono_bool_t ofono_radio_access_mode_from_string(const char *str,
|
||||||
|
enum ofono_radio_access_mode *mode);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -104,6 +104,11 @@ typedef void (*ofono_sim_state_event_cb_t)(enum ofono_sim_state new_state,
|
|||||||
typedef void (*ofono_sim_file_read_cb_t)(int ok, int total_length, int record,
|
typedef void (*ofono_sim_file_read_cb_t)(int ok, int total_length, int record,
|
||||||
const unsigned char *data,
|
const unsigned char *data,
|
||||||
int record_length, void *userdata);
|
int record_length, void *userdata);
|
||||||
|
|
||||||
|
typedef void (*ofono_sim_read_info_cb_t)(int ok, unsigned char file_status,
|
||||||
|
int total_length, int record_length,
|
||||||
|
void *userdata);
|
||||||
|
|
||||||
typedef void (*ofono_sim_file_changed_cb_t)(int id, void *userdata);
|
typedef void (*ofono_sim_file_changed_cb_t)(int id, void *userdata);
|
||||||
|
|
||||||
typedef void (*ofono_sim_file_write_cb_t)(int ok, void *userdata);
|
typedef void (*ofono_sim_file_write_cb_t)(int ok, void *userdata);
|
||||||
@@ -215,6 +220,22 @@ ofono_bool_t ofono_sim_add_spn_watch(struct ofono_sim *sim, unsigned int *id,
|
|||||||
|
|
||||||
ofono_bool_t ofono_sim_remove_spn_watch(struct ofono_sim *sim, unsigned int *id);
|
ofono_bool_t ofono_sim_remove_spn_watch(struct ofono_sim *sim, unsigned int *id);
|
||||||
|
|
||||||
|
typedef void (*ofono_sim_iccid_event_cb_t)(const char *iccid, void *data);
|
||||||
|
|
||||||
|
unsigned int ofono_sim_add_iccid_watch(struct ofono_sim *sim,
|
||||||
|
ofono_sim_iccid_event_cb_t cb, void *data,
|
||||||
|
ofono_destroy_func destroy);
|
||||||
|
|
||||||
|
void ofono_sim_remove_iccid_watch(struct ofono_sim *sim, unsigned int id);
|
||||||
|
|
||||||
|
typedef void (*ofono_sim_imsi_event_cb_t)(const char *imsi, void *data);
|
||||||
|
|
||||||
|
unsigned int ofono_sim_add_imsi_watch(struct ofono_sim *sim,
|
||||||
|
ofono_sim_imsi_event_cb_t cb, void *data,
|
||||||
|
ofono_destroy_func destroy);
|
||||||
|
|
||||||
|
void ofono_sim_remove_imsi_watch(struct ofono_sim *sim, unsigned int id);
|
||||||
|
|
||||||
void ofono_sim_inserted_notify(struct ofono_sim *sim, ofono_bool_t inserted);
|
void ofono_sim_inserted_notify(struct ofono_sim *sim, ofono_bool_t inserted);
|
||||||
|
|
||||||
struct ofono_sim_context *ofono_sim_context_create(struct ofono_sim *sim);
|
struct ofono_sim_context *ofono_sim_context_create(struct ofono_sim *sim);
|
||||||
@@ -231,6 +252,22 @@ int ofono_sim_read(struct ofono_sim_context *context, int id,
|
|||||||
enum ofono_sim_file_structure expected,
|
enum ofono_sim_file_structure expected,
|
||||||
ofono_sim_file_read_cb_t cb, void *data);
|
ofono_sim_file_read_cb_t cb, void *data);
|
||||||
|
|
||||||
|
int ofono_sim_read_path(struct ofono_sim_context *context, int id,
|
||||||
|
enum ofono_sim_file_structure expected_type,
|
||||||
|
const unsigned char *path, unsigned int path_len,
|
||||||
|
ofono_sim_file_read_cb_t cb, void *data);
|
||||||
|
|
||||||
|
int ofono_sim_read_info(struct ofono_sim_context *context, int id,
|
||||||
|
enum ofono_sim_file_structure expected_type,
|
||||||
|
const unsigned char *path, unsigned int pth_len,
|
||||||
|
ofono_sim_read_info_cb_t cb, void *data);
|
||||||
|
|
||||||
|
int ofono_sim_read_record(struct ofono_sim_context *context, int id,
|
||||||
|
enum ofono_sim_file_structure expected_type,
|
||||||
|
int record, int record_length,
|
||||||
|
const unsigned char *path, unsigned int pth_len,
|
||||||
|
ofono_sim_file_read_cb_t cb, void *data);
|
||||||
|
|
||||||
int ofono_sim_write(struct ofono_sim_context *context, int id,
|
int ofono_sim_write(struct ofono_sim_context *context, int id,
|
||||||
ofono_sim_file_write_cb_t cb,
|
ofono_sim_file_write_cb_t cb,
|
||||||
enum ofono_sim_file_structure structure, int record,
|
enum ofono_sim_file_structure structure, int record,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* oFono - Open Source Telephony
|
* oFono - Open Source Telephony
|
||||||
*
|
*
|
||||||
* Copyright (C) 2015 Jolla Ltd. All rights reserved.
|
* Copyright (C) 2015-2016 Jolla Ltd.
|
||||||
* Contact: Slava Monich <slava.monich@jolla.com>
|
* Contact: Slava Monich <slava.monich@jolla.com>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -13,49 +13,148 @@
|
|||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <gdbus.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#define OFONO_API_SUBJECT_TO_CHANGE
|
#define OFONO_API_SUBJECT_TO_CHANGE
|
||||||
#include <ofono/plugin.h>
|
#include <ofono/plugin.h>
|
||||||
|
#include <ofono/dbus.h>
|
||||||
#include <ofono/log.h>
|
#include <ofono/log.h>
|
||||||
#include <ofono.h>
|
|
||||||
|
|
||||||
#define DEBUGLOG_INTERFACE OFONO_SERVICE ".DebugLog"
|
#include <dbuslog_server_dbus.h>
|
||||||
#define DEBUGLOG_PATH "/"
|
#include <gutil_log.h>
|
||||||
#define DEBUGLOG_CHANGED_SIGNAL "Changed"
|
|
||||||
|
|
||||||
static DBusConnection *connection = NULL;
|
#include <string.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
|
||||||
extern struct ofono_debug_desc __start___debug[];
|
#define DEBUGLOG_PATH "/"
|
||||||
extern struct ofono_debug_desc __stop___debug[];
|
|
||||||
|
|
||||||
static void debuglog_signal(DBusConnection *conn, const char *name,
|
enum _debug_server_event {
|
||||||
guint flags)
|
DEBUG_EVENT_CATEGORY_ENABLED,
|
||||||
|
DEBUG_EVENT_CATEGORY_DISABLED,
|
||||||
|
DEBUG_EVENT_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
static DBusLogServer *debuglog_server;
|
||||||
|
static GLogProc2 debuglog_default_log_proc;
|
||||||
|
static gulong debuglog_event_id[DEBUG_EVENT_COUNT];
|
||||||
|
|
||||||
|
static void debuglog_ofono_log_hook(const struct ofono_debug_desc *desc,
|
||||||
|
int priority, const char *format, va_list va)
|
||||||
{
|
{
|
||||||
DBusMessage *signal = dbus_message_new_signal(DEBUGLOG_PATH,
|
DBUSLOG_LEVEL dbuslevel;
|
||||||
DEBUGLOG_INTERFACE, DEBUGLOG_CHANGED_SIGNAL);
|
const char *category;
|
||||||
|
|
||||||
if (signal) {
|
if (desc) {
|
||||||
DBusMessageIter iter;
|
category = desc->name ? desc->name : desc->file;
|
||||||
const dbus_bool_t on = (flags & OFONO_DEBUG_FLAG_PRINT) != 0;
|
} else {
|
||||||
|
category = NULL;
|
||||||
dbus_message_iter_init_append(signal, &iter);
|
|
||||||
dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
|
|
||||||
dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &on);
|
|
||||||
g_dbus_send_message(conn, signal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ofono is only using these four priorities: */
|
||||||
|
switch (priority) {
|
||||||
|
case LOG_ERR:
|
||||||
|
dbuslevel = DBUSLOG_LEVEL_ERROR;
|
||||||
|
break;
|
||||||
|
case LOG_WARNING:
|
||||||
|
dbuslevel = DBUSLOG_LEVEL_WARNING;
|
||||||
|
break;
|
||||||
|
case LOG_INFO:
|
||||||
|
dbuslevel = DBUSLOG_LEVEL_INFO;
|
||||||
|
break;
|
||||||
|
case LOG_DEBUG:
|
||||||
|
dbuslevel = DBUSLOG_LEVEL_DEBUG;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dbuslevel = DBUSLOG_LEVEL_UNDEFINED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbus_log_server_logv(debuglog_server, dbuslevel, category, format, va);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debuglog_gutil_log_func(const GLogModule* log, int level,
|
||||||
|
const char* format, va_list va)
|
||||||
|
{
|
||||||
|
DBUSLOG_LEVEL loglevel;
|
||||||
|
|
||||||
|
switch (level) {
|
||||||
|
case GLOG_LEVEL_ERR:
|
||||||
|
loglevel = DBUSLOG_LEVEL_ERROR;
|
||||||
|
break;
|
||||||
|
case GLOG_LEVEL_WARN:
|
||||||
|
loglevel = DBUSLOG_LEVEL_WARNING;
|
||||||
|
break;
|
||||||
|
case GLOG_LEVEL_INFO:
|
||||||
|
loglevel = DBUSLOG_LEVEL_INFO;
|
||||||
|
break;
|
||||||
|
case GLOG_LEVEL_DEBUG:
|
||||||
|
loglevel = DBUSLOG_LEVEL_DEBUG;
|
||||||
|
break;
|
||||||
|
case GLOG_LEVEL_VERBOSE:
|
||||||
|
loglevel = DBUSLOG_LEVEL_VERBOSE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
loglevel = DBUSLOG_LEVEL_UNDEFINED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbus_log_server_logv(debuglog_server, loglevel, log->name, format, va);
|
||||||
|
if (debuglog_default_log_proc) {
|
||||||
|
debuglog_default_log_proc(log, level, format, va);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean debuglog_match(const char* s1, const char* s2)
|
||||||
|
{
|
||||||
|
return s1 && s2 && !strcmp(s1, s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debuglog_update_flags(const char* name, guint set, guint clear)
|
||||||
|
{
|
||||||
|
const guint flags = set | clear;
|
||||||
|
struct ofono_debug_desc *start = __start___debug;
|
||||||
|
struct ofono_debug_desc *stop = __stop___debug;
|
||||||
|
|
||||||
|
if (start && stop) {
|
||||||
|
struct ofono_debug_desc *desc;
|
||||||
|
|
||||||
|
for (desc = start; desc < stop; desc++) {
|
||||||
|
const char *matched = NULL;
|
||||||
|
|
||||||
|
if (debuglog_match(desc->file, name)) {
|
||||||
|
matched = desc->file;
|
||||||
|
} else if (debuglog_match(desc->name, name)) {
|
||||||
|
matched = desc->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matched) {
|
||||||
|
const guint old_flags = (desc->flags & flags);
|
||||||
|
desc->flags |= set;
|
||||||
|
desc->flags &= ~clear;
|
||||||
|
if ((desc->flags & flags) != old_flags &&
|
||||||
|
desc->notify) {
|
||||||
|
desc->notify(desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debuglog_category_enabled(DBusLogServer* server,
|
||||||
|
const char* category, gpointer user_data)
|
||||||
|
{
|
||||||
|
debuglog_update_flags(category, OFONO_DEBUG_FLAG_PRINT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debuglog_category_disabled(DBusLogServer* server,
|
||||||
|
const char* category, gpointer user_data)
|
||||||
|
{
|
||||||
|
debuglog_update_flags(category, 0, OFONO_DEBUG_FLAG_PRINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GHashTable *debuglog_update_flags_hash(GHashTable *hash,
|
static GHashTable *debuglog_update_flags_hash(GHashTable *hash,
|
||||||
@@ -77,197 +176,80 @@ static GHashTable *debuglog_update_flags_hash(GHashTable *hash,
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean debuglog_match(const char* name, const char* pattern)
|
static guint debuglog_translate_flags(unsigned int ofono_flags)
|
||||||
{
|
{
|
||||||
return name && g_pattern_match_simple(pattern, name);
|
guint flags = 0;
|
||||||
|
|
||||||
|
if (ofono_flags & OFONO_DEBUG_FLAG_PRINT)
|
||||||
|
flags |= DBUSLOG_CATEGORY_FLAG_ENABLED;
|
||||||
|
|
||||||
|
if (ofono_flags & OFONO_DEBUG_FLAG_HIDE_NAME)
|
||||||
|
flags |= DBUSLOG_CATEGORY_FLAG_HIDE_NAME;
|
||||||
|
|
||||||
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void debuglog_update(DBusConnection *conn, const char* pattern,
|
|
||||||
guint set_flags, guint clear_flags)
|
|
||||||
{
|
|
||||||
const guint flags = set_flags | clear_flags;
|
|
||||||
struct ofono_debug_desc *start = __start___debug;
|
|
||||||
struct ofono_debug_desc *stop = __stop___debug;
|
|
||||||
struct ofono_debug_desc *desc;
|
|
||||||
GHashTable *hash = NULL;
|
|
||||||
|
|
||||||
if (!start || !stop)
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
|
||||||
for (desc = start; desc < stop; desc++) {
|
|
||||||
const char *matched = NULL;
|
|
||||||
|
|
||||||
if (debuglog_match(desc->file, pattern)) {
|
|
||||||
matched = desc->file;
|
|
||||||
} else if (debuglog_match(desc->name, pattern)) {
|
|
||||||
matched = desc->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matched) {
|
|
||||||
const guint old_flags = (desc->flags & flags);
|
|
||||||
desc->flags |= set_flags;
|
|
||||||
desc->flags &= ~clear_flags;
|
|
||||||
if ((desc->flags & flags) != old_flags) {
|
|
||||||
hash = debuglog_update_flags_hash(hash,
|
|
||||||
matched, desc->flags);
|
|
||||||
if (desc->notify) {
|
|
||||||
desc->notify(desc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hash) {
|
|
||||||
GList *entry, *names = g_hash_table_get_keys(hash);
|
|
||||||
|
|
||||||
for (entry = names; entry; entry = entry->next) {
|
|
||||||
debuglog_signal(conn, entry->data,
|
|
||||||
GPOINTER_TO_INT(g_hash_table_lookup(
|
|
||||||
hash, entry->data)));
|
|
||||||
}
|
|
||||||
|
|
||||||
g_list_free(names);
|
|
||||||
g_hash_table_destroy(hash);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static DBusMessage *debuglog_handle(DBusConnection *conn, DBusMessage *msg,
|
|
||||||
guint set_flags, guint clear_flags)
|
|
||||||
{
|
|
||||||
const char *pattern;
|
|
||||||
|
|
||||||
if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
|
|
||||||
DBUS_TYPE_INVALID)) {
|
|
||||||
debuglog_update(conn, pattern, set_flags, clear_flags);
|
|
||||||
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
|
|
||||||
} else {
|
|
||||||
return __ofono_error_invalid_args(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static DBusMessage *debuglog_enable(DBusConnection *conn,
|
|
||||||
DBusMessage *msg, void *data)
|
|
||||||
{
|
|
||||||
return debuglog_handle(conn, msg, OFONO_DEBUG_FLAG_PRINT, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static DBusMessage *debuglog_disable(DBusConnection *conn,
|
|
||||||
DBusMessage *msg, void *data)
|
|
||||||
{
|
|
||||||
return debuglog_handle(conn, msg, 0, OFONO_DEBUG_FLAG_PRINT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gint debuglog_list_compare(gconstpointer a, gconstpointer b)
|
|
||||||
{
|
|
||||||
return strcmp(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void debuglog_list_append(DBusMessageIter *iter, const char *name,
|
|
||||||
guint flags)
|
|
||||||
{
|
|
||||||
DBusMessageIter entry;
|
|
||||||
dbus_bool_t enabled = (flags & OFONO_DEBUG_FLAG_PRINT) != 0;
|
|
||||||
|
|
||||||
dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &entry);
|
|
||||||
dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &name);
|
|
||||||
dbus_message_iter_append_basic(&entry, DBUS_TYPE_BOOLEAN, &enabled);
|
|
||||||
dbus_message_iter_close_container(iter, &entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
static DBusMessage *debuglog_list(DBusConnection *conn,
|
|
||||||
DBusMessage *msg, void *data)
|
|
||||||
{
|
|
||||||
DBusMessage *reply = dbus_message_new_method_return(msg);
|
|
||||||
|
|
||||||
if (reply) {
|
|
||||||
struct ofono_debug_desc *start = __start___debug;
|
|
||||||
struct ofono_debug_desc *stop = __stop___debug;
|
|
||||||
DBusMessageIter iter, array;
|
|
||||||
|
|
||||||
dbus_message_iter_init_append(reply, &iter);
|
|
||||||
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
|
|
||||||
"(sb)", &array);
|
|
||||||
|
|
||||||
if (start && stop) {
|
|
||||||
struct ofono_debug_desc *desc;
|
|
||||||
GList *names, *entry;
|
|
||||||
GHashTable *hash = g_hash_table_new_full(g_str_hash,
|
|
||||||
g_str_equal, NULL, NULL);
|
|
||||||
|
|
||||||
for (desc = start; desc < stop; desc++) {
|
|
||||||
debuglog_update_flags_hash(hash, desc->file,
|
|
||||||
desc->flags);
|
|
||||||
debuglog_update_flags_hash(hash, desc->name,
|
|
||||||
desc->flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
names = g_list_sort(g_hash_table_get_keys(hash),
|
|
||||||
debuglog_list_compare);
|
|
||||||
for (entry = names; entry; entry = entry->next) {
|
|
||||||
const char *name = entry->data;
|
|
||||||
debuglog_list_append(&array, name,
|
|
||||||
GPOINTER_TO_INT(g_hash_table_lookup(
|
|
||||||
hash, name)));
|
|
||||||
}
|
|
||||||
|
|
||||||
g_list_free(names);
|
|
||||||
g_hash_table_destroy(hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
dbus_message_iter_close_container(&iter, &array);
|
|
||||||
}
|
|
||||||
|
|
||||||
return reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const GDBusMethodTable debuglog_methods[] = {
|
|
||||||
{ GDBUS_METHOD("Enable", GDBUS_ARGS({ "pattern", "s" }), NULL,
|
|
||||||
debuglog_enable) },
|
|
||||||
{ GDBUS_METHOD("Disable", GDBUS_ARGS({ "pattern", "s" }), NULL,
|
|
||||||
debuglog_disable) },
|
|
||||||
{ GDBUS_METHOD("List", NULL, GDBUS_ARGS({ "list", "a(sb)" }),
|
|
||||||
debuglog_list) },
|
|
||||||
{ },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const GDBusSignalTable debuglog_signals[] = {
|
|
||||||
{ GDBUS_SIGNAL(DEBUGLOG_CHANGED_SIGNAL,
|
|
||||||
GDBUS_ARGS({ "name", "s" }, { "enabled", "b" })) },
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
static int debuglog_init(void)
|
static int debuglog_init(void)
|
||||||
{
|
{
|
||||||
DBG("");
|
const struct ofono_debug_desc *start = __start___debug;
|
||||||
|
const struct ofono_debug_desc *stop = __stop___debug;
|
||||||
|
|
||||||
connection = ofono_dbus_get_connection();
|
debuglog_server = dbus_log_server_new(ofono_dbus_get_connection(),
|
||||||
if (!connection)
|
DEBUGLOG_PATH);
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (!g_dbus_register_interface(connection, DEBUGLOG_PATH,
|
if (start && stop) {
|
||||||
DEBUGLOG_INTERFACE, debuglog_methods, debuglog_signals,
|
const struct ofono_debug_desc *desc;
|
||||||
NULL, NULL, NULL)) {
|
GHashTable *hash = NULL;
|
||||||
ofono_error("debuglog: failed to register "
|
|
||||||
DEBUGLOG_INTERFACE);
|
for (desc = start; desc < stop; desc++) {
|
||||||
return -1;
|
const guint f = debuglog_translate_flags(desc->flags);
|
||||||
|
hash = debuglog_update_flags_hash(hash, desc->file, f);
|
||||||
|
hash = debuglog_update_flags_hash(hash, desc->name, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hash) {
|
||||||
|
gpointer key, value;
|
||||||
|
GHashTableIter it;
|
||||||
|
|
||||||
|
g_hash_table_iter_init(&it, hash);
|
||||||
|
|
||||||
|
while (g_hash_table_iter_next(&it, &key, &value)) {
|
||||||
|
dbus_log_server_add_category(debuglog_server,
|
||||||
|
key, DBUSLOG_LEVEL_UNDEFINED,
|
||||||
|
GPOINTER_TO_INT(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_destroy(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
debuglog_event_id[DEBUG_EVENT_CATEGORY_ENABLED] =
|
||||||
|
dbus_log_server_add_category_enabled_handler(
|
||||||
|
debuglog_server, debuglog_category_enabled,
|
||||||
|
NULL);
|
||||||
|
debuglog_event_id[DEBUG_EVENT_CATEGORY_DISABLED] =
|
||||||
|
dbus_log_server_add_category_disabled_handler(
|
||||||
|
debuglog_server, debuglog_category_disabled,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debuglog_default_log_proc = gutil_log_func2;
|
||||||
|
gutil_log_func2 = debuglog_gutil_log_func;
|
||||||
|
ofono_log_hook = debuglog_ofono_log_hook;
|
||||||
|
|
||||||
|
dbus_log_server_set_default_level(debuglog_server, DBUSLOG_LEVEL_DEBUG);
|
||||||
|
dbus_log_server_start(debuglog_server);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void debuglog_exit(void)
|
static void debuglog_exit(void)
|
||||||
{
|
{
|
||||||
DBG("");
|
gutil_log_func2 = debuglog_default_log_proc;
|
||||||
|
dbus_log_server_remove_handlers(debuglog_server, debuglog_event_id,
|
||||||
if (connection) {
|
G_N_ELEMENTS(debuglog_event_id));
|
||||||
g_dbus_unregister_interface(connection, DEBUGLOG_PATH,
|
dbus_log_server_unref(debuglog_server);
|
||||||
DEBUGLOG_INTERFACE);
|
debuglog_server = NULL;
|
||||||
dbus_connection_unref(connection);
|
|
||||||
connection = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OFONO_PLUGIN_DEFINE(debuglog, "Debug log control interface",
|
OFONO_PLUGIN_DEFINE(debuglog, "Debug log interface",
|
||||||
VERSION, OFONO_PLUGIN_PRIORITY_DEFAULT,
|
VERSION, OFONO_PLUGIN_PRIORITY_DEFAULT,
|
||||||
debuglog_init, debuglog_exit)
|
debuglog_init, debuglog_exit)
|
||||||
|
|||||||
@@ -44,6 +44,16 @@
|
|||||||
|
|
||||||
#include "mbpi.h"
|
#include "mbpi.h"
|
||||||
|
|
||||||
|
const char *mbpi_database = MBPI_DATABASE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use IPv4 for MMS contexts because gprs.c assumes that MMS proxy
|
||||||
|
* address is IPv4.
|
||||||
|
*/
|
||||||
|
enum ofono_gprs_proto mbpi_default_internet_proto = OFONO_GPRS_PROTO_IPV4V6;
|
||||||
|
enum ofono_gprs_proto mbpi_default_mms_proto = OFONO_GPRS_PROTO_IP;
|
||||||
|
enum ofono_gprs_proto mbpi_default_proto = OFONO_GPRS_PROTO_IP;
|
||||||
|
|
||||||
#define _(x) case x: return (#x)
|
#define _(x) case x: return (#x)
|
||||||
|
|
||||||
enum MBPI_ERROR {
|
enum MBPI_ERROR {
|
||||||
@@ -111,7 +121,7 @@ static void mbpi_g_set_error(GMarkupParseContext *context, GError **error,
|
|||||||
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
g_prefix_error(error, "%s:%d ", MBPI_DATABASE, line_number);
|
g_prefix_error(error, "%s:%d ", mbpi_database, line_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void text_handler(GMarkupParseContext *context,
|
static void text_handler(GMarkupParseContext *context,
|
||||||
@@ -120,7 +130,7 @@ static void text_handler(GMarkupParseContext *context,
|
|||||||
{
|
{
|
||||||
char **string = userdata;
|
char **string = userdata;
|
||||||
|
|
||||||
g_free(*string);
|
g_free(*string);
|
||||||
*string = g_strndup(text, text_len);
|
*string = g_strndup(text, text_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +176,7 @@ static void authentication_start(GMarkupParseContext *context,
|
|||||||
static void usage_start(GMarkupParseContext *context,
|
static void usage_start(GMarkupParseContext *context,
|
||||||
const gchar **attribute_names,
|
const gchar **attribute_names,
|
||||||
const gchar **attribute_values,
|
const gchar **attribute_values,
|
||||||
enum ofono_gprs_context_type *type, GError **error)
|
struct ofono_gprs_provision_data *apn, GError **error)
|
||||||
{
|
{
|
||||||
const char *text = NULL;
|
const char *text = NULL;
|
||||||
int i;
|
int i;
|
||||||
@@ -182,12 +192,14 @@ static void usage_start(GMarkupParseContext *context,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(text, "internet") == 0)
|
if (strcmp(text, "internet") == 0) {
|
||||||
*type = OFONO_GPRS_CONTEXT_TYPE_INTERNET;
|
apn->type = OFONO_GPRS_CONTEXT_TYPE_INTERNET;
|
||||||
else if (strcmp(text, "mms") == 0)
|
apn->proto = mbpi_default_internet_proto;
|
||||||
*type = OFONO_GPRS_CONTEXT_TYPE_MMS;
|
} else if (strcmp(text, "mms") == 0) {
|
||||||
else if (strcmp(text, "wap") == 0)
|
apn->type = OFONO_GPRS_CONTEXT_TYPE_MMS;
|
||||||
*type = OFONO_GPRS_CONTEXT_TYPE_WAP;
|
apn->proto = mbpi_default_mms_proto;
|
||||||
|
} else if (strcmp(text, "wap") == 0)
|
||||||
|
apn->type = OFONO_GPRS_CONTEXT_TYPE_WAP;
|
||||||
else
|
else
|
||||||
mbpi_g_set_error(context, error, G_MARKUP_ERROR,
|
mbpi_g_set_error(context, error, G_MARKUP_ERROR,
|
||||||
G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
|
G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
|
||||||
@@ -220,7 +232,7 @@ static void apn_start(GMarkupParseContext *context, const gchar *element_name,
|
|||||||
&apn->message_proxy);
|
&apn->message_proxy);
|
||||||
else if (g_str_equal(element_name, "usage"))
|
else if (g_str_equal(element_name, "usage"))
|
||||||
usage_start(context, attribute_names, attribute_values,
|
usage_start(context, attribute_names, attribute_values,
|
||||||
&apn->type, error);
|
apn, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void apn_end(GMarkupParseContext *context, const gchar *element_name,
|
static void apn_end(GMarkupParseContext *context, const gchar *element_name,
|
||||||
@@ -331,7 +343,7 @@ static void apn_handler(GMarkupParseContext *context, struct gsm_data *gsm,
|
|||||||
|
|
||||||
ap->apn = g_strdup(apn);
|
ap->apn = g_strdup(apn);
|
||||||
ap->type = OFONO_GPRS_CONTEXT_TYPE_INTERNET;
|
ap->type = OFONO_GPRS_CONTEXT_TYPE_INTERNET;
|
||||||
ap->proto = OFONO_GPRS_PROTO_IP;
|
ap->proto = mbpi_default_proto;
|
||||||
ap->auth_method = OFONO_GPRS_AUTH_METHOD_CHAP;
|
ap->auth_method = OFONO_GPRS_AUTH_METHOD_CHAP;
|
||||||
|
|
||||||
g_markup_parse_context_push(context, &apn_parser, ap);
|
g_markup_parse_context_push(context, &apn_parser, ap);
|
||||||
@@ -611,11 +623,11 @@ static gboolean mbpi_parse(const GMarkupParser *parser, gpointer userdata,
|
|||||||
GMarkupParseContext *context;
|
GMarkupParseContext *context;
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
|
|
||||||
fd = open(MBPI_DATABASE, O_RDONLY);
|
fd = open(mbpi_database, O_RDONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
g_set_error(error, G_FILE_ERROR,
|
g_set_error(error, G_FILE_ERROR,
|
||||||
g_file_error_from_errno(errno),
|
g_file_error_from_errno(errno),
|
||||||
"open(%s) failed: %s", MBPI_DATABASE,
|
"open(%s) failed: %s", mbpi_database,
|
||||||
g_strerror(errno));
|
g_strerror(errno));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -624,7 +636,7 @@ static gboolean mbpi_parse(const GMarkupParser *parser, gpointer userdata,
|
|||||||
close(fd);
|
close(fd);
|
||||||
g_set_error(error, G_FILE_ERROR,
|
g_set_error(error, G_FILE_ERROR,
|
||||||
g_file_error_from_errno(errno),
|
g_file_error_from_errno(errno),
|
||||||
"fstat(%s) failed: %s", MBPI_DATABASE,
|
"fstat(%s) failed: %s", mbpi_database,
|
||||||
g_strerror(errno));
|
g_strerror(errno));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -634,7 +646,7 @@ static gboolean mbpi_parse(const GMarkupParser *parser, gpointer userdata,
|
|||||||
close(fd);
|
close(fd);
|
||||||
g_set_error(error, G_FILE_ERROR,
|
g_set_error(error, G_FILE_ERROR,
|
||||||
g_file_error_from_errno(errno),
|
g_file_error_from_errno(errno),
|
||||||
"mmap(%s) failed: %s", MBPI_DATABASE,
|
"mmap(%s) failed: %s", mbpi_database,
|
||||||
g_strerror(errno));
|
g_strerror(errno));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,11 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
extern const char *mbpi_database;
|
||||||
|
extern enum ofono_gprs_proto mbpi_default_internet_proto;
|
||||||
|
extern enum ofono_gprs_proto mbpi_default_mms_proto;
|
||||||
|
extern enum ofono_gprs_proto mbpi_default_proto;
|
||||||
|
|
||||||
const char *mbpi_ap_type(enum ofono_gprs_context_type type);
|
const char *mbpi_ap_type(enum ofono_gprs_context_type type);
|
||||||
|
|
||||||
void mbpi_ap_free(struct ofono_gprs_provision_data *data);
|
void mbpi_ap_free(struct ofono_gprs_provision_data *data);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* oFono - Open Source Telephony
|
* oFono - Open Source Telephony
|
||||||
*
|
*
|
||||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||||
* Copyright (C) 2013 Jolla Ltd.
|
* Copyright (C) 2013-2016 Jolla Ltd.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
@@ -86,6 +86,7 @@ static gint provision_compare_ap(gconstpointer a, gconstpointer b, gpointer data
|
|||||||
|
|
||||||
/* Picks best ap, deletes the rest. Creates one if necessary */
|
/* Picks best ap, deletes the rest. Creates one if necessary */
|
||||||
static GSList *provision_pick_best_ap(GSList *list, const char* spn,
|
static GSList *provision_pick_best_ap(GSList *list, const char* spn,
|
||||||
|
const enum ofono_gprs_proto default_proto,
|
||||||
const struct provision_ap_defaults *defaults)
|
const struct provision_ap_defaults *defaults)
|
||||||
{
|
{
|
||||||
/* Sort the list */
|
/* Sort the list */
|
||||||
@@ -101,6 +102,7 @@ static GSList *provision_pick_best_ap(GSList *list, const char* spn,
|
|||||||
struct ofono_gprs_provision_data *ap =
|
struct ofono_gprs_provision_data *ap =
|
||||||
g_new0(struct ofono_gprs_provision_data, 1);
|
g_new0(struct ofono_gprs_provision_data, 1);
|
||||||
|
|
||||||
|
ap->proto = default_proto;
|
||||||
ap->type = defaults->type;
|
ap->type = defaults->type;
|
||||||
ap->name = g_strdup(defaults->name);
|
ap->name = g_strdup(defaults->name);
|
||||||
ap->apn = g_strdup(defaults->apn);
|
ap->apn = g_strdup(defaults->apn);
|
||||||
@@ -136,8 +138,10 @@ static GSList *provision_normalize_apn_list(GSList *apns, const char* spn)
|
|||||||
|
|
||||||
/* Pick the best ap of each type and concatenate them */
|
/* Pick the best ap of each type and concatenate them */
|
||||||
return g_slist_concat(
|
return g_slist_concat(
|
||||||
provision_pick_best_ap(internet_apns, spn, &internet_defaults),
|
provision_pick_best_ap(internet_apns, spn,
|
||||||
provision_pick_best_ap(mms_apns, spn, &mms_defaults));
|
mbpi_default_internet_proto, &internet_defaults),
|
||||||
|
provision_pick_best_ap(mms_apns, spn,
|
||||||
|
mbpi_default_mms_proto, &mms_defaults));
|
||||||
}
|
}
|
||||||
|
|
||||||
int provision_get_settings(const char *mcc, const char *mnc,
|
int provision_get_settings(const char *mcc, const char *mnc,
|
||||||
|
|||||||
@@ -57,8 +57,6 @@
|
|||||||
#define MAX_MESSAGE_CENTER_LENGTH 255
|
#define MAX_MESSAGE_CENTER_LENGTH 255
|
||||||
#define MAX_CONTEXTS 256
|
#define MAX_CONTEXTS 256
|
||||||
#define SUSPEND_TIMEOUT 8
|
#define SUSPEND_TIMEOUT 8
|
||||||
#define MAX_MMS_MTU 1280
|
|
||||||
#define MAX_GPRS_MTU 1280
|
|
||||||
|
|
||||||
struct ofono_gprs {
|
struct ofono_gprs {
|
||||||
GSList *contexts;
|
GSList *contexts;
|
||||||
@@ -790,31 +788,6 @@ static void pri_reset_context_settings(struct pri_context *ctx)
|
|||||||
g_free(interface);
|
g_free(interface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pri_limit_mtu(const char *interface, int max_mtu)
|
|
||||||
{
|
|
||||||
struct ifreq ifr;
|
|
||||||
int sk;
|
|
||||||
|
|
||||||
if (interface == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sk = socket(PF_INET, SOCK_DGRAM, 0);
|
|
||||||
if (sk < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
memset(&ifr, 0, sizeof(ifr));
|
|
||||||
strncpy(ifr.ifr_name, interface, IFNAMSIZ);
|
|
||||||
|
|
||||||
if (ioctl(sk, SIOCGIFMTU, &ifr) < 0 || ifr.ifr_mtu > max_mtu) {
|
|
||||||
ifr.ifr_mtu = max_mtu;
|
|
||||||
|
|
||||||
if (ioctl(sk, SIOCSIFMTU, &ifr) < 0)
|
|
||||||
ofono_error("Failed to set MTU");
|
|
||||||
}
|
|
||||||
|
|
||||||
close(sk);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pri_update_mms_context_settings(struct pri_context *ctx)
|
static void pri_update_mms_context_settings(struct pri_context *ctx)
|
||||||
{
|
{
|
||||||
struct ofono_gprs_context *gc = ctx->context_driver;
|
struct ofono_gprs_context *gc = ctx->context_driver;
|
||||||
@@ -832,8 +805,6 @@ static void pri_update_mms_context_settings(struct pri_context *ctx)
|
|||||||
|
|
||||||
if (ctx->proxy_host)
|
if (ctx->proxy_host)
|
||||||
pri_setproxy(settings->interface, ctx->proxy_host);
|
pri_setproxy(settings->interface, ctx->proxy_host);
|
||||||
|
|
||||||
pri_limit_mtu(settings->interface, MAX_MMS_MTU);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean pri_str_changed(const char *val, const char *newval)
|
static gboolean pri_str_changed(const char *val, const char *newval)
|
||||||
@@ -1130,9 +1101,6 @@ static void pri_activate_callback(const struct ofono_error *error, void *data)
|
|||||||
|
|
||||||
pri_context_signal_settings(ctx, gc->settings->ipv4 != NULL,
|
pri_context_signal_settings(ctx, gc->settings->ipv4 != NULL,
|
||||||
gc->settings->ipv6 != NULL);
|
gc->settings->ipv6 != NULL);
|
||||||
|
|
||||||
if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_INTERNET)
|
|
||||||
pri_limit_mtu(gc->settings->interface, MAX_GPRS_MTU);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
value = ctx->active;
|
value = ctx->active;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
* oFono - Open Source Telephony
|
* oFono - Open Source Telephony
|
||||||
*
|
*
|
||||||
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
|
||||||
|
* Copyright (C) 2013-2016 Jolla Ltd.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
@@ -37,6 +38,9 @@
|
|||||||
|
|
||||||
#include "ofono.h"
|
#include "ofono.h"
|
||||||
|
|
||||||
|
ofono_log_hook_cb_t ofono_log_hook;
|
||||||
|
static GString *ofono_debug_str;
|
||||||
|
|
||||||
static const char *program_exec;
|
static const char *program_exec;
|
||||||
static const char *program_path;
|
static const char *program_path;
|
||||||
|
|
||||||
@@ -56,6 +60,12 @@ void ofono_info(const char *format, ...)
|
|||||||
vsyslog(LOG_INFO, format, ap);
|
vsyslog(LOG_INFO, format, ap);
|
||||||
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
|
if (ofono_log_hook) {
|
||||||
|
va_start(ap, format);
|
||||||
|
ofono_log_hook(NULL, LOG_INFO, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,6 +84,12 @@ void ofono_warn(const char *format, ...)
|
|||||||
vsyslog(LOG_WARNING, format, ap);
|
vsyslog(LOG_WARNING, format, ap);
|
||||||
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
|
if (ofono_log_hook) {
|
||||||
|
va_start(ap, format);
|
||||||
|
ofono_log_hook(NULL, LOG_WARNING, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,6 +108,12 @@ void ofono_error(const char *format, ...)
|
|||||||
vsyslog(LOG_ERR, format, ap);
|
vsyslog(LOG_ERR, format, ap);
|
||||||
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
|
if (ofono_log_hook) {
|
||||||
|
va_start(ap, format);
|
||||||
|
ofono_log_hook(NULL, LOG_ERR, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -113,6 +135,37 @@ void ofono_debug(const char *format, ...)
|
|||||||
vsyslog(LOG_DEBUG, format, ap);
|
vsyslog(LOG_DEBUG, format, ap);
|
||||||
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
|
if (ofono_log_hook) {
|
||||||
|
va_start(ap, format);
|
||||||
|
ofono_log_hook(NULL, LOG_DEBUG, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __ofono_dbg(const struct ofono_debug_desc *desc, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
if (!(desc->flags & OFONO_DEBUG_FLAG_PRINT))
|
||||||
|
return;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
|
||||||
|
if (ofono_debug_str) {
|
||||||
|
g_string_vprintf(ofono_debug_str, format, ap);
|
||||||
|
syslog(LOG_DEBUG, "%s:%s", desc->file, ofono_debug_str->str);
|
||||||
|
} else {
|
||||||
|
vsyslog(LOG_DEBUG, format, ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
if (ofono_log_hook) {
|
||||||
|
va_start(ap, format);
|
||||||
|
ofono_log_hook(desc, LOG_DEBUG, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __GLIBC__
|
#ifdef __GLIBC__
|
||||||
@@ -306,6 +359,7 @@ int __ofono_log_init(const char *program, const char *debug,
|
|||||||
|
|
||||||
program_exec = program;
|
program_exec = program;
|
||||||
program_path = getcwd(path, sizeof(path));
|
program_path = getcwd(path, sizeof(path));
|
||||||
|
ofono_debug_str = g_string_sized_new(127);
|
||||||
|
|
||||||
if (debug != NULL)
|
if (debug != NULL)
|
||||||
enabled = g_strsplit_set(debug, ":, ", 0);
|
enabled = g_strsplit_set(debug, ":, ", 0);
|
||||||
@@ -339,4 +393,6 @@ void __ofono_log_cleanup(ofono_bool_t backtrace)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
g_strfreev(enabled);
|
g_strfreev(enabled);
|
||||||
|
g_string_free(ofono_debug_str, TRUE);
|
||||||
|
ofono_debug_str = NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1326,7 +1326,7 @@ void ofono_modem_remove_interface(struct ofono_modem *modem,
|
|||||||
found = g_slist_find_custom(modem->interface_list, interface,
|
found = g_slist_find_custom(modem->interface_list, interface,
|
||||||
(GCompareFunc) strcmp);
|
(GCompareFunc) strcmp);
|
||||||
if (found == NULL) {
|
if (found == NULL) {
|
||||||
ofono_error("Interface %s not found on the interface_list",
|
DBG("Interface %s not found on the interface_list",
|
||||||
interface);
|
interface);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ struct ofono_netreg {
|
|||||||
struct ofono_network_registration_ops *ops;
|
struct ofono_network_registration_ops *ops;
|
||||||
int flags;
|
int flags;
|
||||||
DBusMessage *pending;
|
DBusMessage *pending;
|
||||||
|
GSList *pending_auto;
|
||||||
|
GSList *pending_list;
|
||||||
int signal_strength;
|
int signal_strength;
|
||||||
struct sim_spdi *spdi;
|
struct sim_spdi *spdi;
|
||||||
struct sim_eons *eons;
|
struct sim_eons *eons;
|
||||||
@@ -599,7 +601,7 @@ static DBusMessage *network_operator_register(DBusConnection *conn,
|
|||||||
if (netreg->mode == NETWORK_REGISTRATION_MODE_AUTO_ONLY)
|
if (netreg->mode == NETWORK_REGISTRATION_MODE_AUTO_ONLY)
|
||||||
return __ofono_error_access_denied(msg);
|
return __ofono_error_access_denied(msg);
|
||||||
|
|
||||||
if (netreg->pending)
|
if (netreg->pending || netreg->pending_auto || netreg->pending_list)
|
||||||
return __ofono_error_busy(msg);
|
return __ofono_error_busy(msg);
|
||||||
|
|
||||||
if (netreg->driver->register_manual == NULL)
|
if (netreg->driver->register_manual == NULL)
|
||||||
@@ -854,6 +856,44 @@ static DBusMessage *network_get_properties(DBusConnection *conn,
|
|||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void network_reply_ok(gpointer data)
|
||||||
|
{
|
||||||
|
DBusMessage *msg = data;
|
||||||
|
|
||||||
|
__ofono_dbus_pending_reply(&msg, dbus_message_new_method_return(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void network_reply_failed(gpointer data)
|
||||||
|
{
|
||||||
|
DBusMessage *msg = data;
|
||||||
|
|
||||||
|
__ofono_dbus_pending_reply(&msg, __ofono_error_failed(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void network_reply_canceled(gpointer data)
|
||||||
|
{
|
||||||
|
DBusMessage *msg = data;
|
||||||
|
|
||||||
|
__ofono_dbus_pending_reply(&msg, __ofono_error_canceled(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void register_auto_callback(const struct ofono_error *error, void *data)
|
||||||
|
{
|
||||||
|
struct ofono_netreg *netreg = data;
|
||||||
|
|
||||||
|
if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
|
||||||
|
g_slist_free_full(netreg->pending_auto, network_reply_ok);
|
||||||
|
else
|
||||||
|
g_slist_free_full(netreg->pending_auto, network_reply_failed);
|
||||||
|
|
||||||
|
netreg->pending_auto = NULL;
|
||||||
|
|
||||||
|
if (netreg->driver->registration_status)
|
||||||
|
netreg->driver->registration_status(netreg,
|
||||||
|
registration_status_callback,
|
||||||
|
netreg);
|
||||||
|
}
|
||||||
|
|
||||||
static DBusMessage *network_register(DBusConnection *conn,
|
static DBusMessage *network_register(DBusConnection *conn,
|
||||||
DBusMessage *msg, void *data)
|
DBusMessage *msg, void *data)
|
||||||
{
|
{
|
||||||
@@ -862,17 +902,19 @@ static DBusMessage *network_register(DBusConnection *conn,
|
|||||||
if (netreg->mode == NETWORK_REGISTRATION_MODE_AUTO_ONLY)
|
if (netreg->mode == NETWORK_REGISTRATION_MODE_AUTO_ONLY)
|
||||||
return __ofono_error_access_denied(msg);
|
return __ofono_error_access_denied(msg);
|
||||||
|
|
||||||
if (netreg->pending)
|
if (netreg->pending || netreg->pending_list)
|
||||||
return __ofono_error_busy(msg);
|
return __ofono_error_busy(msg);
|
||||||
|
|
||||||
if (netreg->driver->register_auto == NULL)
|
if (netreg->driver->register_auto == NULL)
|
||||||
return __ofono_error_not_implemented(msg);
|
return __ofono_error_not_implemented(msg);
|
||||||
|
|
||||||
netreg->pending = dbus_message_ref(msg);
|
netreg->pending_auto = g_slist_append(netreg->pending_auto,
|
||||||
|
dbus_message_ref(msg));
|
||||||
netreg->driver->register_auto(netreg, register_callback, netreg);
|
if (!netreg->pending_auto->next) {
|
||||||
|
netreg->driver->register_auto(netreg, register_auto_callback,
|
||||||
set_registration_mode(netreg, NETWORK_REGISTRATION_MODE_AUTO);
|
netreg);
|
||||||
|
set_registration_mode(netreg, NETWORK_REGISTRATION_MODE_AUTO);
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -972,26 +1014,15 @@ static void network_signal_operators_changed(struct ofono_netreg *netreg)
|
|||||||
g_dbus_send_message(conn, signal);
|
g_dbus_send_message(conn, signal);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void operator_list_callback(const struct ofono_error *error, int total,
|
static void operator_list_reply(gpointer data, gpointer user_data)
|
||||||
const struct ofono_network_operator *list,
|
|
||||||
void *data)
|
|
||||||
{
|
{
|
||||||
struct ofono_netreg *netreg = data;
|
struct ofono_netreg *netreg = user_data;
|
||||||
|
DBusMessage *msg = data;
|
||||||
DBusMessage *reply;
|
DBusMessage *reply;
|
||||||
DBusMessageIter iter;
|
DBusMessageIter iter;
|
||||||
DBusMessageIter array;
|
DBusMessageIter array;
|
||||||
gboolean changed;
|
|
||||||
|
|
||||||
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
|
reply = dbus_message_new_method_return(msg);
|
||||||
DBG("Error occurred during operator list");
|
|
||||||
__ofono_dbus_pending_reply(&netreg->pending,
|
|
||||||
__ofono_error_failed(netreg->pending));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
changed = update_operator_list(netreg, total, list);
|
|
||||||
|
|
||||||
reply = dbus_message_new_method_return(netreg->pending);
|
|
||||||
|
|
||||||
dbus_message_iter_init_append(reply, &iter);
|
dbus_message_iter_init_append(reply, &iter);
|
||||||
|
|
||||||
@@ -1008,12 +1039,31 @@ static void operator_list_callback(const struct ofono_error *error, int total,
|
|||||||
append_operator_struct_list(netreg, &array);
|
append_operator_struct_list(netreg, &array);
|
||||||
dbus_message_iter_close_container(&iter, &array);
|
dbus_message_iter_close_container(&iter, &array);
|
||||||
|
|
||||||
__ofono_dbus_pending_reply(&netreg->pending, reply);
|
__ofono_dbus_pending_reply(&msg, reply);
|
||||||
|
}
|
||||||
|
|
||||||
DBG("operator list %schanged", changed ? "" : "not ");
|
static void operator_list_callback(const struct ofono_error *error, int total,
|
||||||
|
const struct ofono_network_operator *list,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct ofono_netreg *netreg = data;
|
||||||
|
|
||||||
if (changed)
|
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
|
||||||
network_signal_operators_changed(netreg);
|
DBG("Error occurred during operator list");
|
||||||
|
g_slist_free_full(netreg->pending_list, network_reply_failed);
|
||||||
|
} else {
|
||||||
|
gboolean changed = update_operator_list(netreg, total, list);
|
||||||
|
|
||||||
|
g_slist_foreach(netreg->pending_list, operator_list_reply,
|
||||||
|
netreg);
|
||||||
|
g_slist_free(netreg->pending_list);
|
||||||
|
|
||||||
|
DBG("operator list %schanged", changed ? "" : "not ");
|
||||||
|
if (changed)
|
||||||
|
network_signal_operators_changed(netreg);
|
||||||
|
}
|
||||||
|
|
||||||
|
netreg->pending_list = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DBusMessage *network_scan(DBusConnection *conn,
|
static DBusMessage *network_scan(DBusConnection *conn,
|
||||||
@@ -1024,16 +1074,17 @@ static DBusMessage *network_scan(DBusConnection *conn,
|
|||||||
if (netreg->mode == NETWORK_REGISTRATION_MODE_AUTO_ONLY)
|
if (netreg->mode == NETWORK_REGISTRATION_MODE_AUTO_ONLY)
|
||||||
return __ofono_error_access_denied(msg);
|
return __ofono_error_access_denied(msg);
|
||||||
|
|
||||||
if (netreg->pending)
|
if (netreg->pending || netreg->pending_auto)
|
||||||
return __ofono_error_busy(msg);
|
return __ofono_error_busy(msg);
|
||||||
|
|
||||||
if (netreg->driver->list_operators == NULL)
|
if (netreg->driver->list_operators == NULL)
|
||||||
return __ofono_error_not_implemented(msg);
|
return __ofono_error_not_implemented(msg);
|
||||||
|
|
||||||
netreg->pending = dbus_message_ref(msg);
|
netreg->pending_list = g_slist_append(netreg->pending_list,
|
||||||
|
dbus_message_ref(msg));
|
||||||
netreg->driver->list_operators(netreg, operator_list_callback, netreg);
|
if (!netreg->pending_list->next)
|
||||||
|
netreg->driver->list_operators(netreg, operator_list_callback,
|
||||||
|
netreg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1898,6 +1949,15 @@ static void netreg_remove(struct ofono_atom *atom)
|
|||||||
if (netreg->driver != NULL && netreg->driver->remove != NULL)
|
if (netreg->driver != NULL && netreg->driver->remove != NULL)
|
||||||
netreg->driver->remove(netreg);
|
netreg->driver->remove(netreg);
|
||||||
|
|
||||||
|
if (netreg->pending) {
|
||||||
|
__ofono_dbus_pending_reply(&netreg->pending,
|
||||||
|
__ofono_error_canceled(netreg->pending));
|
||||||
|
} else if (netreg->pending_auto) {
|
||||||
|
g_slist_free_full(netreg->pending_auto, network_reply_canceled);
|
||||||
|
} else if (netreg->pending_list) {
|
||||||
|
g_slist_free_full(netreg->pending_list, network_reply_canceled);
|
||||||
|
}
|
||||||
|
|
||||||
sim_eons_free(netreg->eons);
|
sim_eons_free(netreg->eons);
|
||||||
sim_spdi_free(netreg->spdi);
|
sim_spdi_free(netreg->spdi);
|
||||||
|
|
||||||
|
|||||||
@@ -1,265 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* oFono - Open Source Telephony
|
|
||||||
*
|
|
||||||
* Copyright (C) 2013 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.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <glib.h>
|
|
||||||
#include <gdbus.h>
|
|
||||||
#include <dbus/dbus.h>
|
|
||||||
#include "ofono.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "ofono/oemraw.h"
|
|
||||||
|
|
||||||
static GSList *g_drivers;
|
|
||||||
|
|
||||||
struct ofono_oem_raw {
|
|
||||||
struct ofono_atom *atom;
|
|
||||||
const struct ofono_oem_raw_driver *driver;
|
|
||||||
void *driver_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void ofono_oem_raw_query_cb(const struct ofono_error *error,
|
|
||||||
const struct ofono_oem_raw_results *res, void *data)
|
|
||||||
{
|
|
||||||
char *ptr;
|
|
||||||
char byte;
|
|
||||||
int i;
|
|
||||||
DBusMessage *reply;
|
|
||||||
DBusMessageIter iter;
|
|
||||||
DBusMessageIter subiter;
|
|
||||||
struct ofono_oem_raw_request *req = data;
|
|
||||||
|
|
||||||
if (error && error->type == OFONO_ERROR_TYPE_NO_ERROR) {
|
|
||||||
reply = dbus_message_new_method_return(req->pending);
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* Log error messages in driver when completing a request,
|
|
||||||
* logging here provides no extra information.
|
|
||||||
*/
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
dbus_message_iter_init_append(reply, &iter);
|
|
||||||
|
|
||||||
if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
|
|
||||||
"y", &subiter)) {
|
|
||||||
DBG("Failed to open a dbus iterator");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr = (char *)res->data;
|
|
||||||
|
|
||||||
for (i = 0; i < res->length; i++) {
|
|
||||||
byte = ptr[i];
|
|
||||||
dbus_message_iter_append_basic(&subiter, DBUS_TYPE_BYTE,
|
|
||||||
&byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
dbus_message_iter_close_container(&iter, &subiter);
|
|
||||||
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
error:
|
|
||||||
reply = __ofono_error_failed(req->pending);
|
|
||||||
|
|
||||||
end:
|
|
||||||
__ofono_dbus_pending_reply(&req->pending, reply);
|
|
||||||
g_free(req);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static DBusMessage *oem_raw_make_request(DBusConnection *conn,
|
|
||||||
DBusMessage *msg, void *data)
|
|
||||||
{
|
|
||||||
char *array; /* Byte array containing client request*/
|
|
||||||
int array_len; /* Length of request byte array */
|
|
||||||
DBusMessageIter iter;
|
|
||||||
DBusMessageIter subiter;
|
|
||||||
struct ofono_oem_raw_request *req;
|
|
||||||
struct ofono_oem_raw *raw;
|
|
||||||
raw = data;
|
|
||||||
req = 0;
|
|
||||||
|
|
||||||
if (raw && raw->driver->request == NULL)
|
|
||||||
return __ofono_error_not_implemented(msg);
|
|
||||||
|
|
||||||
dbus_message_iter_init(msg, &iter);
|
|
||||||
|
|
||||||
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
|
|
||||||
goto error_arg;
|
|
||||||
|
|
||||||
if (dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE) {
|
|
||||||
DBG("Ignoring request because dbus request element type=%c",
|
|
||||||
dbus_message_iter_get_element_type(&iter));
|
|
||||||
goto error_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
dbus_message_iter_recurse(&iter, &subiter);
|
|
||||||
|
|
||||||
dbus_message_iter_get_fixed_array(&subiter, &array, &array_len);
|
|
||||||
|
|
||||||
req = g_new0(struct ofono_oem_raw_request, 1);
|
|
||||||
req->data = array;
|
|
||||||
req->length = array_len;
|
|
||||||
/* Store msg to request struct to allow multiple parallel requests */
|
|
||||||
req->pending = dbus_message_ref(msg);
|
|
||||||
raw->driver->request(raw, req, ofono_oem_raw_query_cb, req);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
error_arg:
|
|
||||||
DBG("DBus arg type=%c, msg signature: %s",
|
|
||||||
dbus_message_iter_get_arg_type(&iter),
|
|
||||||
dbus_message_get_signature(msg));
|
|
||||||
return __ofono_error_invalid_args(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const GDBusMethodTable oem_raw_methods[] = {
|
|
||||||
{ GDBUS_ASYNC_METHOD("Send",
|
|
||||||
GDBUS_ARGS({ "req", "ay" }),
|
|
||||||
GDBUS_ARGS({ "response", "ay"}),
|
|
||||||
oem_raw_make_request) },
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
static const GDBusSignalTable oem_raw_signals[] = {
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
static void oem_raw_dbus_unregister(struct ofono_atom *atom)
|
|
||||||
{
|
|
||||||
DBG("");
|
|
||||||
struct ofono_oem_raw *oemraw = __ofono_atom_get_data(atom);
|
|
||||||
const char *path = __ofono_atom_get_path(oemraw->atom);
|
|
||||||
DBusConnection *conn = ofono_dbus_get_connection();
|
|
||||||
struct ofono_modem *modem = __ofono_atom_get_modem(oemraw->atom);
|
|
||||||
|
|
||||||
ofono_modem_remove_interface(modem, OFONO_OEM_RAW_INTERFACE);
|
|
||||||
|
|
||||||
if (!g_dbus_unregister_interface(conn, path, OFONO_OEM_RAW_INTERFACE))
|
|
||||||
ofono_error("Failed to unregister interface %s",
|
|
||||||
OFONO_OEM_RAW_INTERFACE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ofono_oem_raw_dbus_register(struct ofono_oem_raw *oemraw)
|
|
||||||
{
|
|
||||||
DBusConnection *conn;
|
|
||||||
DBG("");
|
|
||||||
conn = ofono_dbus_get_connection();
|
|
||||||
struct ofono_modem *modem = __ofono_atom_get_modem(oemraw->atom);
|
|
||||||
const char *path = __ofono_atom_get_path(oemraw->atom);
|
|
||||||
|
|
||||||
if (!g_dbus_register_interface(conn, path,
|
|
||||||
OFONO_OEM_RAW_INTERFACE,
|
|
||||||
oem_raw_methods,
|
|
||||||
oem_raw_signals,
|
|
||||||
NULL, oemraw, NULL)) {
|
|
||||||
ofono_error("Could not create interface %s",
|
|
||||||
OFONO_OEM_RAW_INTERFACE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ofono_modem_add_interface(modem, OFONO_OEM_RAW_INTERFACE);
|
|
||||||
__ofono_atom_register(oemraw->atom, oem_raw_dbus_unregister);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ofono_oem_raw_driver_register(struct ofono_oem_raw_driver *driver)
|
|
||||||
{
|
|
||||||
if (driver->probe == NULL)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
g_drivers = g_slist_prepend(g_drivers, (void *) driver);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ofono_oem_raw_driver_unregister(struct ofono_oem_raw_driver *driver)
|
|
||||||
{
|
|
||||||
g_drivers = g_slist_remove(g_drivers, (void *) driver);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ofono_oem_raw_remove(struct ofono_oem_raw *oemraw)
|
|
||||||
{
|
|
||||||
__ofono_atom_free(oemraw->atom);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *ofono_oem_raw_get_data(struct ofono_oem_raw *raw)
|
|
||||||
{
|
|
||||||
return raw->driver_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ofono_oem_raw_set_data(struct ofono_oem_raw *raw, void *cid)
|
|
||||||
{
|
|
||||||
raw->driver_data = cid;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void oem_raw_remove(struct ofono_atom *atom)
|
|
||||||
{
|
|
||||||
struct ofono_oem_raw *oemraw = __ofono_atom_get_data(atom);
|
|
||||||
|
|
||||||
if (oemraw == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (oemraw->driver && oemraw->driver->remove)
|
|
||||||
oemraw->driver->remove(oemraw);
|
|
||||||
|
|
||||||
g_free(oemraw);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ofono_oem_raw *ofono_oem_raw_create(struct ofono_modem *modem,
|
|
||||||
unsigned int vendor,
|
|
||||||
const char *driver,
|
|
||||||
void *data)
|
|
||||||
{
|
|
||||||
struct ofono_oem_raw *oemraw = 0;
|
|
||||||
GSList *l;
|
|
||||||
|
|
||||||
if (driver == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
oemraw = g_try_new0(struct ofono_oem_raw, 1);
|
|
||||||
if (oemraw == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
oemraw->atom = __ofono_modem_add_atom(modem,
|
|
||||||
OFONO_ATOM_TYPE_OEM_RAW,
|
|
||||||
oem_raw_remove, oemraw);
|
|
||||||
|
|
||||||
for (l = g_drivers; l; l = l->next) {
|
|
||||||
const struct ofono_oem_raw_driver *drv = l->data;
|
|
||||||
|
|
||||||
if (g_strcmp0(drv->name, driver))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (drv->probe(oemraw, vendor, data) < 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
oemraw->driver = drv;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return oemraw;
|
|
||||||
}
|
|
||||||
@@ -152,7 +152,6 @@ enum ofono_atom_type {
|
|||||||
OFONO_ATOM_TYPE_CDMA_SMS,
|
OFONO_ATOM_TYPE_CDMA_SMS,
|
||||||
OFONO_ATOM_TYPE_CDMA_NETREG,
|
OFONO_ATOM_TYPE_CDMA_NETREG,
|
||||||
OFONO_ATOM_TYPE_HANDSFREE,
|
OFONO_ATOM_TYPE_HANDSFREE,
|
||||||
OFONO_ATOM_TYPE_OEM_RAW,
|
|
||||||
OFONO_ATOM_TYPE_SIRI,
|
OFONO_ATOM_TYPE_SIRI,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ enum phonebook_number_type {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ofono_phonebook {
|
struct ofono_phonebook {
|
||||||
DBusMessage *pending;
|
GSList *pending;
|
||||||
int storage_index; /* go through all supported storage */
|
int storage_index; /* go through all supported storage */
|
||||||
int flags;
|
int flags;
|
||||||
GString *vcards; /* entries with vcard 3.0 format */
|
GString *vcards; /* entries with vcard 3.0 format */
|
||||||
@@ -431,9 +431,24 @@ static void export_phonebook_cb(const struct ofono_error *error, void *data)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void phonebook_reply(gpointer data, gpointer user_data)
|
||||||
|
{
|
||||||
|
DBusMessage *msg = data;
|
||||||
|
struct ofono_phonebook *phonebook = user_data;
|
||||||
|
DBusMessage *reply = generate_export_entries_reply(phonebook, msg);
|
||||||
|
|
||||||
|
__ofono_dbus_pending_reply(&msg, reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void phonebook_cancel(gpointer data)
|
||||||
|
{
|
||||||
|
DBusMessage *msg = data;
|
||||||
|
|
||||||
|
__ofono_dbus_pending_reply(&msg, __ofono_error_canceled(msg));
|
||||||
|
}
|
||||||
|
|
||||||
static void export_phonebook(struct ofono_phonebook *phonebook)
|
static void export_phonebook(struct ofono_phonebook *phonebook)
|
||||||
{
|
{
|
||||||
DBusMessage *reply;
|
|
||||||
const char *pb = storage_support[phonebook->storage_index];
|
const char *pb = storage_support[phonebook->storage_index];
|
||||||
|
|
||||||
if (pb) {
|
if (pb) {
|
||||||
@@ -442,13 +457,9 @@ static void export_phonebook(struct ofono_phonebook *phonebook)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
reply = generate_export_entries_reply(phonebook, phonebook->pending);
|
g_slist_foreach(phonebook->pending, phonebook_reply, phonebook);
|
||||||
if (reply == NULL) {
|
g_slist_free(phonebook->pending);
|
||||||
dbus_message_unref(phonebook->pending);
|
phonebook->pending = NULL;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
__ofono_dbus_pending_reply(&phonebook->pending, reply);
|
|
||||||
phonebook->flags |= PHONEBOOK_FLAG_CACHED;
|
phonebook->flags |= PHONEBOOK_FLAG_CACHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,23 +469,22 @@ static DBusMessage *import_entries(DBusConnection *conn, DBusMessage *msg,
|
|||||||
struct ofono_phonebook *phonebook = data;
|
struct ofono_phonebook *phonebook = data;
|
||||||
DBusMessage *reply;
|
DBusMessage *reply;
|
||||||
|
|
||||||
if (phonebook->pending) {
|
|
||||||
reply = __ofono_error_busy(phonebook->pending);
|
|
||||||
g_dbus_send_message(conn, reply);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (phonebook->flags & PHONEBOOK_FLAG_CACHED) {
|
if (phonebook->flags & PHONEBOOK_FLAG_CACHED) {
|
||||||
reply = generate_export_entries_reply(phonebook, msg);
|
reply = generate_export_entries_reply(phonebook, msg);
|
||||||
g_dbus_send_message(conn, reply);
|
g_dbus_send_message(conn, reply);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_string_set_size(phonebook->vcards, 0);
|
if (phonebook->pending) {
|
||||||
phonebook->storage_index = 0;
|
phonebook->pending = g_slist_append(phonebook->pending,
|
||||||
|
dbus_message_ref(msg));
|
||||||
phonebook->pending = dbus_message_ref(msg);
|
} else {
|
||||||
export_phonebook(phonebook);
|
phonebook->pending = g_slist_append(NULL,
|
||||||
|
dbus_message_ref(msg));
|
||||||
|
g_string_set_size(phonebook->vcards, 0);
|
||||||
|
phonebook->storage_index = 0;
|
||||||
|
export_phonebook(phonebook);
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -516,6 +526,11 @@ static void phonebook_unregister(struct ofono_atom *atom)
|
|||||||
DBusConnection *conn = ofono_dbus_get_connection();
|
DBusConnection *conn = ofono_dbus_get_connection();
|
||||||
struct ofono_modem *modem = __ofono_atom_get_modem(pb->atom);
|
struct ofono_modem *modem = __ofono_atom_get_modem(pb->atom);
|
||||||
|
|
||||||
|
if (pb->pending) {
|
||||||
|
g_slist_free_full(pb->pending, phonebook_cancel);
|
||||||
|
pb->pending = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ofono_modem_remove_interface(modem, OFONO_PHONEBOOK_INTERFACE);
|
ofono_modem_remove_interface(modem, OFONO_PHONEBOOK_INTERFACE);
|
||||||
g_dbus_unregister_interface(conn, path, OFONO_PHONEBOOK_INTERFACE);
|
g_dbus_unregister_interface(conn, path, OFONO_PHONEBOOK_INTERFACE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ struct ofono_radio_settings {
|
|||||||
struct ofono_atom *atom;
|
struct ofono_atom *atom;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *radio_access_mode_to_string(enum ofono_radio_access_mode m)
|
const char *ofono_radio_access_mode_to_string(enum ofono_radio_access_mode m)
|
||||||
{
|
{
|
||||||
switch (m) {
|
switch (m) {
|
||||||
case OFONO_RADIO_ACCESS_MODE_ANY:
|
case OFONO_RADIO_ACCESS_MODE_ANY:
|
||||||
@@ -72,11 +72,13 @@ static const char *radio_access_mode_to_string(enum ofono_radio_access_mode m)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean radio_access_mode_from_string(const char *str,
|
ofono_bool_t ofono_radio_access_mode_from_string(const char *str,
|
||||||
enum ofono_radio_access_mode *mode)
|
enum ofono_radio_access_mode *mode)
|
||||||
|
|
||||||
{
|
{
|
||||||
if (g_str_equal(str, "any")) {
|
if (!str) {
|
||||||
|
return FALSE;
|
||||||
|
} else if (g_str_equal(str, "any")) {
|
||||||
*mode = OFONO_RADIO_ACCESS_MODE_ANY;
|
*mode = OFONO_RADIO_ACCESS_MODE_ANY;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} else if (g_str_equal(str, "gsm")) {
|
} else if (g_str_equal(str, "gsm")) {
|
||||||
@@ -192,7 +194,7 @@ static DBusMessage *radio_get_properties_reply(DBusMessage *msg,
|
|||||||
DBusMessageIter iter;
|
DBusMessageIter iter;
|
||||||
DBusMessageIter dict;
|
DBusMessageIter dict;
|
||||||
|
|
||||||
const char *mode = radio_access_mode_to_string(rs->mode);
|
const char *mode = ofono_radio_access_mode_to_string(rs->mode);
|
||||||
|
|
||||||
reply = dbus_message_new_method_return(msg);
|
reply = dbus_message_new_method_return(msg);
|
||||||
if (reply == NULL)
|
if (reply == NULL)
|
||||||
@@ -237,7 +239,7 @@ static DBusMessage *radio_get_properties_reply(DBusMessage *msg,
|
|||||||
if (!(rs->available_rats & tech))
|
if (!(rs->available_rats & tech))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rats[n++] = radio_access_mode_to_string(tech);
|
rats[n++] = ofono_radio_access_mode_to_string(tech);
|
||||||
}
|
}
|
||||||
|
|
||||||
rats[n] = NULL;
|
rats[n] = NULL;
|
||||||
@@ -358,7 +360,7 @@ static void radio_set_rat_mode(struct ofono_radio_settings *rs,
|
|||||||
rs->mode = mode;
|
rs->mode = mode;
|
||||||
|
|
||||||
path = __ofono_atom_get_path(rs->atom);
|
path = __ofono_atom_get_path(rs->atom);
|
||||||
str_mode = radio_access_mode_to_string(rs->mode);
|
str_mode = ofono_radio_access_mode_to_string(rs->mode);
|
||||||
|
|
||||||
ofono_dbus_signal_property_changed(conn, path,
|
ofono_dbus_signal_property_changed(conn, path,
|
||||||
OFONO_RADIO_SETTINGS_INTERFACE,
|
OFONO_RADIO_SETTINGS_INTERFACE,
|
||||||
@@ -580,7 +582,7 @@ static DBusMessage *radio_set_property(DBusConnection *conn, DBusMessage *msg,
|
|||||||
return __ofono_error_invalid_args(msg);
|
return __ofono_error_invalid_args(msg);
|
||||||
|
|
||||||
dbus_message_iter_get_basic(&var, &value);
|
dbus_message_iter_get_basic(&var, &value);
|
||||||
if (radio_access_mode_from_string(value, &mode) == FALSE)
|
if (ofono_radio_access_mode_from_string(value, &mode) == FALSE)
|
||||||
return __ofono_error_invalid_args(msg);
|
return __ofono_error_invalid_args(msg);
|
||||||
|
|
||||||
if (rs->mode == mode)
|
if (rs->mode == mode)
|
||||||
|
|||||||
134
ofono/src/sim.c
134
ofono/src/sim.c
@@ -53,6 +53,7 @@ struct ofono_sim {
|
|||||||
|
|
||||||
/* Contents of the SIM file system, in rough initialization order */
|
/* Contents of the SIM file system, in rough initialization order */
|
||||||
char *iccid;
|
char *iccid;
|
||||||
|
struct ofono_watchlist *iccid_watches;
|
||||||
|
|
||||||
char **language_prefs;
|
char **language_prefs;
|
||||||
unsigned char *efli;
|
unsigned char *efli;
|
||||||
@@ -80,6 +81,7 @@ struct ofono_sim {
|
|||||||
char *imsi;
|
char *imsi;
|
||||||
char mcc[OFONO_MAX_MCC_LENGTH + 1];
|
char mcc[OFONO_MAX_MCC_LENGTH + 1];
|
||||||
char mnc[OFONO_MAX_MNC_LENGTH + 1];
|
char mnc[OFONO_MAX_MNC_LENGTH + 1];
|
||||||
|
struct ofono_watchlist *imsi_watches;
|
||||||
|
|
||||||
GSList *own_numbers;
|
GSList *own_numbers;
|
||||||
GSList *new_numbers;
|
GSList *new_numbers;
|
||||||
@@ -340,6 +342,94 @@ static void call_state_watches(struct ofono_sim *sim)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int add_watch_item(struct ofono_watchlist *watchlist,
|
||||||
|
void *notify, void *notify_data,
|
||||||
|
ofono_destroy_func destroy)
|
||||||
|
{
|
||||||
|
struct ofono_watchlist_item *item;
|
||||||
|
|
||||||
|
item = g_new0(struct ofono_watchlist_item, 1);
|
||||||
|
item->notify = notify;
|
||||||
|
item->notify_data = notify_data;
|
||||||
|
item->destroy = destroy;
|
||||||
|
|
||||||
|
return __ofono_watchlist_add_item(watchlist, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void iccid_watch_cb(gpointer data, gpointer user_data)
|
||||||
|
{
|
||||||
|
struct ofono_watchlist_item *item = data;
|
||||||
|
struct ofono_sim *sim = user_data;
|
||||||
|
ofono_sim_iccid_event_cb_t cb = item->notify;
|
||||||
|
|
||||||
|
cb(sim->iccid, item->notify_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void iccid_watches_notify(struct ofono_sim *sim)
|
||||||
|
{
|
||||||
|
g_slist_foreach(sim->iccid_watches->items, iccid_watch_cb, sim);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int ofono_sim_add_iccid_watch(struct ofono_sim *sim,
|
||||||
|
ofono_sim_iccid_event_cb_t cb, void *data,
|
||||||
|
ofono_destroy_func destroy)
|
||||||
|
{
|
||||||
|
unsigned int watch_id;
|
||||||
|
|
||||||
|
DBG("%p", sim);
|
||||||
|
if (sim == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
watch_id = add_watch_item(sim->iccid_watches, cb, data, destroy);
|
||||||
|
|
||||||
|
if (sim->iccid)
|
||||||
|
cb(sim->iccid, data);
|
||||||
|
|
||||||
|
return watch_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ofono_sim_remove_iccid_watch(struct ofono_sim *sim, unsigned int id)
|
||||||
|
{
|
||||||
|
__ofono_watchlist_remove_item(sim->iccid_watches, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void imsi_watch_cb(gpointer data, gpointer user_data)
|
||||||
|
{
|
||||||
|
struct ofono_watchlist_item *item = data;
|
||||||
|
struct ofono_sim *sim = user_data;
|
||||||
|
ofono_sim_imsi_event_cb_t cb = item->notify;
|
||||||
|
|
||||||
|
cb(sim->imsi, item->notify_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void imsi_watches_notify(struct ofono_sim *sim)
|
||||||
|
{
|
||||||
|
g_slist_foreach(sim->imsi_watches->items, imsi_watch_cb, sim);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int ofono_sim_add_imsi_watch(struct ofono_sim *sim,
|
||||||
|
ofono_sim_imsi_event_cb_t cb, void *data,
|
||||||
|
ofono_destroy_func destroy)
|
||||||
|
{
|
||||||
|
unsigned int watch_id;
|
||||||
|
|
||||||
|
DBG("%p", sim);
|
||||||
|
if (sim == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
watch_id = add_watch_item(sim->imsi_watches, cb, data, destroy);
|
||||||
|
|
||||||
|
if (sim->imsi)
|
||||||
|
cb(sim->imsi, data);
|
||||||
|
|
||||||
|
return watch_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ofono_sim_remove_imsi_watch(struct ofono_sim *sim, unsigned int id)
|
||||||
|
{
|
||||||
|
__ofono_watchlist_remove_item(sim->imsi_watches, id);
|
||||||
|
}
|
||||||
|
|
||||||
static DBusMessage *sim_get_properties(DBusConnection *conn,
|
static DBusMessage *sim_get_properties(DBusConnection *conn,
|
||||||
DBusMessage *msg, void *data)
|
DBusMessage *msg, void *data)
|
||||||
{
|
{
|
||||||
@@ -1487,6 +1577,7 @@ static void sim_imsi_obtained(struct ofono_sim *sim, const char *imsi)
|
|||||||
DBUS_TYPE_STRING, &str);
|
DBUS_TYPE_STRING, &str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
imsi_watches_notify(sim);
|
||||||
sim_set_ready(sim);
|
sim_set_ready(sim);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1619,7 +1710,7 @@ static gboolean check_bdn_status(struct ofono_sim *sim)
|
|||||||
if (sim_sst_is_active(sim->efsst, sim->efsst_length,
|
if (sim_sst_is_active(sim->efsst, sim->efsst_length,
|
||||||
SIM_SST_SERVICE_BDN)) {
|
SIM_SST_SERVICE_BDN)) {
|
||||||
sim_fs_read_info(sim->context, SIM_EFBDN_FILEID,
|
sim_fs_read_info(sim->context, SIM_EFBDN_FILEID,
|
||||||
OFONO_SIM_FILE_STRUCTURE_FIXED,
|
OFONO_SIM_FILE_STRUCTURE_FIXED, NULL, 0,
|
||||||
sim_efbdn_info_read_cb, sim);
|
sim_efbdn_info_read_cb, sim);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -1673,7 +1764,7 @@ static void sim_efsst_read_cb(int ok, int length, int record,
|
|||||||
if (sim_sst_is_active(sim->efsst, sim->efsst_length,
|
if (sim_sst_is_active(sim->efsst, sim->efsst_length,
|
||||||
SIM_SST_SERVICE_FDN)) {
|
SIM_SST_SERVICE_FDN)) {
|
||||||
sim_fs_read_info(sim->context, SIM_EFADN_FILEID,
|
sim_fs_read_info(sim->context, SIM_EFADN_FILEID,
|
||||||
OFONO_SIM_FILE_STRUCTURE_FIXED,
|
OFONO_SIM_FILE_STRUCTURE_FIXED, NULL, 0,
|
||||||
sim_efadn_info_read_cb, sim);
|
sim_efadn_info_read_cb, sim);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1860,6 +1951,7 @@ static void sim_initialize_after_pin(struct ofono_sim *sim)
|
|||||||
{
|
{
|
||||||
sim->context = ofono_sim_context_create(sim);
|
sim->context = ofono_sim_context_create(sim);
|
||||||
sim->spn_watches = __ofono_watchlist_new(g_free);
|
sim->spn_watches = __ofono_watchlist_new(g_free);
|
||||||
|
sim->imsi_watches = __ofono_watchlist_new(g_free);
|
||||||
|
|
||||||
ofono_sim_read(sim->context, SIM_EFPHASE_FILEID,
|
ofono_sim_read(sim->context, SIM_EFPHASE_FILEID,
|
||||||
OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
|
OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
|
||||||
@@ -2089,6 +2181,7 @@ static void sim_iccid_read_cb(int ok, int length, int record,
|
|||||||
"CardIdentifier",
|
"CardIdentifier",
|
||||||
DBUS_TYPE_STRING,
|
DBUS_TYPE_STRING,
|
||||||
&sim->iccid);
|
&sim->iccid);
|
||||||
|
iccid_watches_notify(sim);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sim_iccid_changed(int id, void *userdata)
|
static void sim_iccid_changed(int id, void *userdata)
|
||||||
@@ -2221,6 +2314,34 @@ int ofono_sim_read(struct ofono_sim_context *context, int id,
|
|||||||
return sim_fs_read(context, id, expected_type, 0, 0, NULL, 0, cb, data);
|
return sim_fs_read(context, id, expected_type, 0, 0, NULL, 0, cb, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ofono_sim_read_path(struct ofono_sim_context *context, int id,
|
||||||
|
enum ofono_sim_file_structure expected_type,
|
||||||
|
const unsigned char *path, unsigned int path_len,
|
||||||
|
ofono_sim_file_read_cb_t cb, void *data)
|
||||||
|
{
|
||||||
|
return sim_fs_read(context, id, expected_type, 0, 0,
|
||||||
|
path, path_len, cb, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ofono_sim_read_info(struct ofono_sim_context *context, int id,
|
||||||
|
enum ofono_sim_file_structure expected_type,
|
||||||
|
const unsigned char *path, unsigned int pth_len,
|
||||||
|
ofono_sim_read_info_cb_t cb, void *data)
|
||||||
|
{
|
||||||
|
return sim_fs_read_info(context, id, expected_type, path, pth_len,
|
||||||
|
cb, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ofono_sim_read_record(struct ofono_sim_context *context, int id,
|
||||||
|
enum ofono_sim_file_structure expected_type,
|
||||||
|
int record, int record_length,
|
||||||
|
const unsigned char *path, unsigned int pth_len,
|
||||||
|
ofono_sim_file_read_cb_t cb, void *data)
|
||||||
|
{
|
||||||
|
return sim_fs_read_record(context, id, expected_type, record,
|
||||||
|
record_length, path, pth_len, cb, data);
|
||||||
|
}
|
||||||
|
|
||||||
int ofono_sim_write(struct ofono_sim_context *context, int id,
|
int ofono_sim_write(struct ofono_sim_context *context, int id,
|
||||||
ofono_sim_file_write_cb_t cb,
|
ofono_sim_file_write_cb_t cb,
|
||||||
enum ofono_sim_file_structure structure, int record,
|
enum ofono_sim_file_structure structure, int record,
|
||||||
@@ -2471,6 +2592,11 @@ static void sim_free_main_state(struct ofono_sim *sim)
|
|||||||
|
|
||||||
sim_spn_close(sim);
|
sim_spn_close(sim);
|
||||||
|
|
||||||
|
if (sim->imsi_watches) {
|
||||||
|
__ofono_watchlist_free(sim->imsi_watches);
|
||||||
|
sim->imsi_watches = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (sim->context) {
|
if (sim->context) {
|
||||||
ofono_sim_context_free(sim->context);
|
ofono_sim_context_free(sim->context);
|
||||||
sim->context = NULL;
|
sim->context = NULL;
|
||||||
@@ -2898,6 +3024,9 @@ static void sim_unregister(struct ofono_atom *atom)
|
|||||||
|
|
||||||
__ofono_modem_remove_atom_watch(modem, sim->hfp_watch);
|
__ofono_modem_remove_atom_watch(modem, sim->hfp_watch);
|
||||||
|
|
||||||
|
__ofono_watchlist_free(sim->iccid_watches);
|
||||||
|
sim->iccid_watches = NULL;
|
||||||
|
|
||||||
__ofono_watchlist_free(sim->state_watches);
|
__ofono_watchlist_free(sim->state_watches);
|
||||||
sim->state_watches = NULL;
|
sim->state_watches = NULL;
|
||||||
|
|
||||||
@@ -3030,6 +3159,7 @@ void ofono_sim_register(struct ofono_sim *sim)
|
|||||||
|
|
||||||
ofono_modem_add_interface(modem, OFONO_SIM_MANAGER_INTERFACE);
|
ofono_modem_add_interface(modem, OFONO_SIM_MANAGER_INTERFACE);
|
||||||
sim->state_watches = __ofono_watchlist_new(g_free);
|
sim->state_watches = __ofono_watchlist_new(g_free);
|
||||||
|
sim->iccid_watches = __ofono_watchlist_new(g_free);
|
||||||
sim->simfs = sim_fs_new(sim, sim->driver);
|
sim->simfs = sim_fs_new(sim, sim->driver);
|
||||||
|
|
||||||
__ofono_atom_register(sim->atom, sim_unregister);
|
__ofono_atom_register(sim->atom, sim_unregister);
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ static void sim_fs_op_error(struct sim_fs *fs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (op->info_only == TRUE)
|
if (op->info_only == TRUE)
|
||||||
((sim_fs_read_info_cb_t) op->cb)
|
((ofono_sim_read_info_cb_t) op->cb)
|
||||||
(0, 0, 0, 0, op->userdata);
|
(0, 0, 0, 0, op->userdata);
|
||||||
else if (op->is_read == TRUE)
|
else if (op->is_read == TRUE)
|
||||||
((ofono_sim_file_read_cb_t) op->cb)
|
((ofono_sim_file_read_cb_t) op->cb)
|
||||||
@@ -335,6 +335,27 @@ static void sim_fs_op_write_cb(const struct ofono_error *error, void *data)
|
|||||||
sim_fs_end_current(fs);
|
sim_fs_end_current(fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sim_fs_op_read_record_cb(const struct ofono_error *error,
|
||||||
|
const unsigned char *sdata, int length,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct sim_fs *fs = data;
|
||||||
|
struct sim_fs_op *op = g_queue_peek_head(fs->op_q);
|
||||||
|
ofono_sim_file_read_cb_t cb = op->cb;
|
||||||
|
|
||||||
|
if (cb == NULL) {
|
||||||
|
sim_fs_end_current(fs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
|
||||||
|
cb(1, -1, op->current, sdata, length, op->userdata);
|
||||||
|
else
|
||||||
|
cb(0, -1, op->current, NULL, 0, op->userdata);
|
||||||
|
|
||||||
|
sim_fs_end_current(fs);
|
||||||
|
}
|
||||||
|
|
||||||
static void sim_fs_op_read_block_cb(const struct ofono_error *error,
|
static void sim_fs_op_read_block_cb(const struct ofono_error *error,
|
||||||
const unsigned char *data, int len,
|
const unsigned char *data, int len,
|
||||||
void *user)
|
void *user)
|
||||||
@@ -565,7 +586,8 @@ static gboolean sim_fs_op_read_record(gpointer user)
|
|||||||
|
|
||||||
driver->read_file_linear(fs->sim, op->id, op->current,
|
driver->read_file_linear(fs->sim, op->id, op->current,
|
||||||
op->record_length,
|
op->record_length,
|
||||||
NULL, 0,
|
op->path_len ? op->path : NULL,
|
||||||
|
op->path_len,
|
||||||
sim_fs_op_retrieve_cb, fs);
|
sim_fs_op_retrieve_cb, fs);
|
||||||
break;
|
break;
|
||||||
case OFONO_SIM_FILE_STRUCTURE_CYCLIC:
|
case OFONO_SIM_FILE_STRUCTURE_CYCLIC:
|
||||||
@@ -576,7 +598,8 @@ static gboolean sim_fs_op_read_record(gpointer user)
|
|||||||
|
|
||||||
driver->read_file_cyclic(fs->sim, op->id, op->current,
|
driver->read_file_cyclic(fs->sim, op->id, op->current,
|
||||||
op->record_length,
|
op->record_length,
|
||||||
NULL, 0,
|
op->path_len ? op->path : NULL,
|
||||||
|
op->path_len,
|
||||||
sim_fs_op_retrieve_cb, fs);
|
sim_fs_op_retrieve_cb, fs);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -700,7 +723,7 @@ static void sim_fs_op_info_cb(const struct ofono_error *error, int length,
|
|||||||
* It's an info-only request, so there is no need to request
|
* It's an info-only request, so there is no need to request
|
||||||
* actual contents of the EF. Just return the EF-info.
|
* actual contents of the EF. Just return the EF-info.
|
||||||
*/
|
*/
|
||||||
sim_fs_read_info_cb_t cb = op->cb;
|
ofono_sim_read_info_cb_t cb = op->cb;
|
||||||
|
|
||||||
cb(1, file_status, op->length,
|
cb(1, file_status, op->length,
|
||||||
op->record_length, op->userdata);
|
op->record_length, op->userdata);
|
||||||
@@ -778,7 +801,7 @@ static gboolean sim_fs_op_check_cached(struct sim_fs *fs)
|
|||||||
* It's an info-only request, so there is no need to request
|
* It's an info-only request, so there is no need to request
|
||||||
* actual contents of the EF. Just return the EF-info.
|
* actual contents of the EF. Just return the EF-info.
|
||||||
*/
|
*/
|
||||||
sim_fs_read_info_cb_t cb = op->cb;
|
ofono_sim_read_info_cb_t cb = op->cb;
|
||||||
|
|
||||||
cb(1, file_status, op->length,
|
cb(1, file_status, op->length,
|
||||||
op->record_length, op->userdata);
|
op->record_length, op->userdata);
|
||||||
@@ -820,7 +843,28 @@ static gboolean sim_fs_op_next(gpointer user_data)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op->is_read == TRUE) {
|
if (op->is_read == TRUE && op->current > 0) {
|
||||||
|
switch (op->structure) {
|
||||||
|
case OFONO_SIM_FILE_STRUCTURE_FIXED:
|
||||||
|
driver->read_file_linear(fs->sim, op->id,
|
||||||
|
op->current, op->record_length,
|
||||||
|
op->path_len ? op->path : NULL,
|
||||||
|
op->path_len,
|
||||||
|
sim_fs_op_read_record_cb, fs);
|
||||||
|
break;
|
||||||
|
case OFONO_SIM_FILE_STRUCTURE_CYCLIC:
|
||||||
|
driver->read_file_cyclic(fs->sim, op->id,
|
||||||
|
op->current, op->record_length,
|
||||||
|
op->path_len ? op->path : NULL,
|
||||||
|
op->path_len,
|
||||||
|
sim_fs_op_read_record_cb, fs);
|
||||||
|
break;
|
||||||
|
case OFONO_SIM_FILE_STRUCTURE_TRANSPARENT:
|
||||||
|
default:
|
||||||
|
ofono_error("Wrong file structure for reading record");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (op->is_read == TRUE) {
|
||||||
if (sim_fs_op_check_cached(fs))
|
if (sim_fs_op_check_cached(fs))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@@ -859,7 +903,8 @@ static gboolean sim_fs_op_next(gpointer user_data)
|
|||||||
|
|
||||||
int sim_fs_read_info(struct ofono_sim_context *context, int id,
|
int sim_fs_read_info(struct ofono_sim_context *context, int id,
|
||||||
enum ofono_sim_file_structure expected_type,
|
enum ofono_sim_file_structure expected_type,
|
||||||
sim_fs_read_info_cb_t cb, void *data)
|
const unsigned char *path, unsigned int pth_len,
|
||||||
|
ofono_sim_read_info_cb_t cb, void *data)
|
||||||
{
|
{
|
||||||
struct sim_fs *fs = context->fs;
|
struct sim_fs *fs = context->fs;
|
||||||
struct sim_fs_op *op;
|
struct sim_fs_op *op;
|
||||||
@@ -887,6 +932,8 @@ int sim_fs_read_info(struct ofono_sim_context *context, int id,
|
|||||||
op->is_read = TRUE;
|
op->is_read = TRUE;
|
||||||
op->info_only = TRUE;
|
op->info_only = TRUE;
|
||||||
op->context = context;
|
op->context = context;
|
||||||
|
memcpy(op->path, path, pth_len);
|
||||||
|
op->path_len = pth_len;
|
||||||
|
|
||||||
g_queue_push_tail(fs->op_q, op);
|
g_queue_push_tail(fs->op_q, op);
|
||||||
|
|
||||||
@@ -943,6 +990,59 @@ int sim_fs_read(struct ofono_sim_context *context, int id,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sim_fs_read_record(struct ofono_sim_context *context, int id,
|
||||||
|
enum ofono_sim_file_structure expected_type,
|
||||||
|
int record, int record_length,
|
||||||
|
const unsigned char *path, unsigned int path_len,
|
||||||
|
ofono_sim_file_read_cb_t cb, void *data)
|
||||||
|
{
|
||||||
|
struct sim_fs *fs = context->fs;
|
||||||
|
struct sim_fs_op *op;
|
||||||
|
|
||||||
|
if (cb == NULL)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (fs->driver == NULL)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (record < 1)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if ((expected_type == OFONO_SIM_FILE_STRUCTURE_FIXED &&
|
||||||
|
fs->driver->read_file_linear == NULL) ||
|
||||||
|
(expected_type == OFONO_SIM_FILE_STRUCTURE_CYCLIC &&
|
||||||
|
fs->driver->read_file_cyclic == NULL)) {
|
||||||
|
cb(0, 0, 0, NULL, 0, data);
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fs->op_q == NULL)
|
||||||
|
fs->op_q = g_queue_new();
|
||||||
|
|
||||||
|
op = g_try_new0(struct sim_fs_op, 1);
|
||||||
|
if (op == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
op->id = id;
|
||||||
|
op->structure = expected_type;
|
||||||
|
op->cb = cb;
|
||||||
|
op->userdata = data;
|
||||||
|
op->is_read = TRUE;
|
||||||
|
op->info_only = FALSE;
|
||||||
|
op->context = context;
|
||||||
|
op->record_length = record_length;
|
||||||
|
op->current = record;
|
||||||
|
memcpy(op->path, path, path_len);
|
||||||
|
op->path_len = path_len;
|
||||||
|
|
||||||
|
g_queue_push_tail(fs->op_q, op);
|
||||||
|
|
||||||
|
if (g_queue_get_length(fs->op_q) == 1)
|
||||||
|
fs->op_source = g_idle_add(sim_fs_op_next, fs);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int sim_fs_write(struct ofono_sim_context *context, int id,
|
int sim_fs_write(struct ofono_sim_context *context, int id,
|
||||||
ofono_sim_file_write_cb_t cb,
|
ofono_sim_file_write_cb_t cb,
|
||||||
enum ofono_sim_file_structure structure, int record,
|
enum ofono_sim_file_structure structure, int record,
|
||||||
|
|||||||
@@ -21,10 +21,6 @@
|
|||||||
|
|
||||||
struct sim_fs;
|
struct sim_fs;
|
||||||
|
|
||||||
typedef void (*sim_fs_read_info_cb_t)(int ok, unsigned char file_status,
|
|
||||||
int total_length, int record_length,
|
|
||||||
void *userdata);
|
|
||||||
|
|
||||||
struct sim_fs *sim_fs_new(struct ofono_sim *sim,
|
struct sim_fs *sim_fs_new(struct ofono_sim *sim,
|
||||||
const struct ofono_sim_driver *driver);
|
const struct ofono_sim_driver *driver);
|
||||||
struct ofono_sim_context *sim_fs_context_new(struct sim_fs *fs);
|
struct ofono_sim_context *sim_fs_context_new(struct sim_fs *fs);
|
||||||
@@ -45,9 +41,16 @@ int sim_fs_read(struct ofono_sim_context *context, int id,
|
|||||||
const unsigned char *path, unsigned int len,
|
const unsigned char *path, unsigned int len,
|
||||||
ofono_sim_file_read_cb_t cb, void *data);
|
ofono_sim_file_read_cb_t cb, void *data);
|
||||||
|
|
||||||
|
int sim_fs_read_record(struct ofono_sim_context *context, int id,
|
||||||
|
enum ofono_sim_file_structure expected_type,
|
||||||
|
int record, int record_length,
|
||||||
|
const unsigned char *path, unsigned int len,
|
||||||
|
ofono_sim_file_read_cb_t cb, void *data);
|
||||||
|
|
||||||
int sim_fs_read_info(struct ofono_sim_context *context, int id,
|
int sim_fs_read_info(struct ofono_sim_context *context, int id,
|
||||||
enum ofono_sim_file_structure expected_type,
|
enum ofono_sim_file_structure expected_type,
|
||||||
sim_fs_read_info_cb_t cb, void *data);
|
const unsigned char *path, unsigned int pth_len,
|
||||||
|
ofono_sim_read_info_cb_t cb, void *data);
|
||||||
|
|
||||||
void sim_fs_check_version(struct sim_fs *fs);
|
void sim_fs_check_version(struct sim_fs *fs);
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ unsigned int __ofono_watchlist_add_item(struct ofono_watchlist *watchlist,
|
|||||||
{
|
{
|
||||||
item->id = ++watchlist->next_id;
|
item->id = ++watchlist->next_id;
|
||||||
|
|
||||||
|
if (item->id == 0)
|
||||||
|
item->id = ++watchlist->next_id;
|
||||||
|
|
||||||
watchlist->items = g_slist_prepend(watchlist->items, item);
|
watchlist->items = g_slist_prepend(watchlist->items, item);
|
||||||
|
|
||||||
return item->id;
|
return item->id;
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
Name: ofono
|
Name: ofono
|
||||||
|
|
||||||
Summary: Open Source Telephony
|
Summary: Open Source Telephony
|
||||||
Version: 1.16
|
Version: 1.17
|
||||||
Release: 1
|
Release: 1
|
||||||
Group: Communications/Connectivity Adaptation
|
Group: Communications/Connectivity Adaptation
|
||||||
License: GPLv2
|
License: GPLv2
|
||||||
URL: http://ofono.org
|
URL: https://git.merproject.org/mer-core/ofono
|
||||||
Source0: http://www.kernel.org/pub/linux/network/ofono/ofono-%{version}.tar.xz
|
Source: %{name}-%{version}.tar.bz2
|
||||||
Requires: dbus
|
Requires: dbus
|
||||||
Requires: systemd
|
Requires: systemd
|
||||||
Requires: ofono-configs
|
Requires: ofono-configs
|
||||||
Requires: libgrilio >= 1.0.6
|
Requires: libgrilio >= 1.0.10
|
||||||
|
Requires: libglibutil >= 1.0.10
|
||||||
Requires(preun): systemd
|
Requires(preun): systemd
|
||||||
Requires(post): systemd
|
Requires(post): systemd
|
||||||
Requires(postun): systemd
|
Requires(postun): systemd
|
||||||
@@ -20,8 +21,9 @@ BuildRequires: pkgconfig(libudev) >= 145
|
|||||||
BuildRequires: pkgconfig(bluez) >= 4.85
|
BuildRequires: pkgconfig(bluez) >= 4.85
|
||||||
BuildRequires: pkgconfig(mobile-broadband-provider-info)
|
BuildRequires: pkgconfig(mobile-broadband-provider-info)
|
||||||
BuildRequires: pkgconfig(libwspcodec) >= 2.0
|
BuildRequires: pkgconfig(libwspcodec) >= 2.0
|
||||||
BuildRequires: pkgconfig(libglibutil)
|
BuildRequires: pkgconfig(libgrilio) >= 1.0.10
|
||||||
BuildRequires: pkgconfig(libgrilio) >= 1.0.6
|
BuildRequires: pkgconfig(libglibutil) >= 1.0.10
|
||||||
|
BuildRequires: pkgconfig(libdbuslogserver-dbus)
|
||||||
BuildRequires: libtool
|
BuildRequires: libtool
|
||||||
BuildRequires: automake
|
BuildRequires: automake
|
||||||
BuildRequires: autoconf
|
BuildRequires: autoconf
|
||||||
@@ -68,7 +70,7 @@ autoreconf --force --install
|
|||||||
|
|
||||||
%configure --disable-static \
|
%configure --disable-static \
|
||||||
--enable-test \
|
--enable-test \
|
||||||
--enable-logcontrol \
|
--enable-debuglog \
|
||||||
--enable-jolla-rilmodem \
|
--enable-jolla-rilmodem \
|
||||||
--with-systemdunitdir="/%{_lib}/systemd/system"
|
--with-systemdunitdir="/%{_lib}/systemd/system"
|
||||||
|
|
||||||
@@ -85,6 +87,7 @@ rm -rf %{buildroot}
|
|||||||
|
|
||||||
mkdir -p %{buildroot}/%{_sysconfdir}/ofono/push_forwarder.d
|
mkdir -p %{buildroot}/%{_sysconfdir}/ofono/push_forwarder.d
|
||||||
mkdir -p %{buildroot}/%{_lib}/systemd/system/network.target.wants
|
mkdir -p %{buildroot}/%{_lib}/systemd/system/network.target.wants
|
||||||
|
mkdir -p %{buildroot}/var/lib/ofono
|
||||||
ln -s ../ofono.service %{buildroot}/%{_lib}/systemd/system/network.target.wants/ofono.service
|
ln -s ../ofono.service %{buildroot}/%{_lib}/systemd/system/network.target.wants/ofono.service
|
||||||
|
|
||||||
%preun
|
%preun
|
||||||
|
|||||||
Reference in New Issue
Block a user